메뉴 닫기

HackTM CTF 후기

예선은 코로나 본격적으로 터지기 전 2월 달에 했다.

원래 루마니아 갈줄 알고 c2w2m2, howdays stan, 나 이렇게 딱 4명에서 해서 예선 7등 했었다.

루마니아 놀러갈 생각으로 열심히 했었는데 코로나때문에 온라인 본선으로 바뀌었다.

근데 상금이 이렇게 걸려있어서, 아 이거 애들 이랑 같이 하고 상금 받으면 고기먹으면 되겠다 싶어서 아는 동생들 + 동욱땅 불러서 했다.

1st place: 1597€

2nd place: 987€

3rd place: 610€

 

결과적으로 2등해서 130만원 가량 획득했다.

원래는 응원단장만 하려고 했으나 갖은 구박에 이기지 못해 몇문제 풀었다.

아래는 내가 손 좀 많이 댔던 문제들 write-up

 

# ransom does not pay (forensic)

rdp 패킷과 인증서를 주는 문제이다.

인증서 비밀번호는 mimikatz로 약간 게싱이 필요하다.

아무튼 이 인증서를 이용해 패킷을 복호화 하고, 와이어샤크에서 Export PDU 어쩌구 한 패킷을 pyrdp에다 넣어주면 키보드 입력을 볼 수 있다.

https://pastebin.com/raw/MncD2YLw 를 입력했는데, 파워쉘 스크립트다.

슥삭 하고 보면 VerySecurePassword! 를 기본비밀번호로 사용해 csv파일을 암호화 한다.

복호화 해주고 extra_info 칼럼만 뽑아주면 플래그가 나온다.

HackTM{cd51fbc9b3082ae80dfbb78b970a2b8badb1aa99b9074697940e4ad504d2e868}

 

# the man the myth the legend (osint)

오신트 문제다.

사진파일 하나 달랑 주는데, stegsolve로 잘 비벼보면 주소가 나온다.

요 주소에 접속하면 유명한 아저씨 얼굴이 나온다.
 

난 누군지 몰랐는데, 검색해보니 참 이름이 많다.

Vlad / Tapes / Dracula / Bran 를 넣어주면 메인 페이지가 나오고, 거기에 51명의 얼굴과 CNP Hash라는게 있다.

검색해보니 한국 주민등록번호 비슷한 번호 인것 같은데, 전부 긁어서 hashcat 돌리니까 크랙되는게 딱 1개 있었다.

사진 파일 다운로드 받아서 보면 플래그가 적혀있다.

 

predator-time (forensic + rev)

volatility3 에서 pslist –dump 로 notepad.exe 하면 notepad.exe가 깔끔하게 뽑힌다.

이름만 notepad.exe지 사실은 gl로 만들어진 이상한 프로그램이다.

디펜던시인 glbinding.dll 과 SDL2.dll은 인터넷에서 구하고, 실행시켜보면…

이상한 문자열이 뜬다.

디버깅하다보면 glShaderSource / glCompileShader 가 있는데 이 때, 아래와 같은 코드를 뽑을 수 있다.

 

#version 450
#extension GL_EXT_gpu_shader4 : enable
layout(location=10)uniform int s;
out vec4 R;
int[]Z=int[](40,13,2,53,8,9,19,34,11,35,55,22,22,7,8,44,28,3,47,60,44,21,23,20,61,14,38,36,6,31,46,52);
void main()
{
    vec2 U=gl_FragCoord.xy/vec2(1280,720);
    int M[32],A=s,B,i,C,D,E,F,G,H,I,J,K;
    float c=0.,x,y;
    for(i=0; i<8; i++)
    {
        for(int _=0; _<100; _++)A=(A<<1)^(A>>23&1)^(A>>22&1)^(A>>21&1)^(A>>6&1)^1;
        for(B=0; B<4; B++)M[8*B+i]=Z[8*B+i]^A>>(6*B)&63;
    }
    for(i=0; i<32; i++)
    {
        x=30.*(U.x-.1-.05*float(i%16)),y=10.*(U.y-.45+.15*float(i/16));
        if(x<.0||x>1.||y<.0||y>1.)continue;
        A=int(y<.05);
        B=int(y<.25);
        C=int(y>.25&&y<.5),D=int(y>.48&&y<.52),E=int(y>.5&&y<.75),F=int(y>.75),G=int(y>.95),H=int(x<.1),I=int(x>.0&&x<.5),J=int(x>.5&&x<1.),K=int(x>.9);
        x=x+2.*y;
        y=x-4.*y;
        if(((int[](439128,557602,3222040,1327377,559780,429127,414808,557603,418200,428696,974848,1397824,2238464,2796032,1127424,70728,2671360,611392,557570,295426,208896,1118272,983040,618496,417792,78848,2514944,79872,278784,1119296,954368,430080,61440,24960,1359872,2394112,2237578,1329425,630360,3757397,397400,3773013,3218503,72775,956504,630372,557600,2785824,611684,3215428,627648,643812,430680,70997,2527832,611669,1346634,69703,3773028,430692,62052,614820,541092,3222819))[M[i]]&((A&J)<<21|(A&I)<<20|(B&K)<<19|int(abs(y-.5)<.05)<<18|int(abs(x-.5)<.05)<<17|(B&H)<<16|(C&K)<<15|int(abs(x-1.5)<.05&&C==1)<<14|int(abs(y+.5)<.05&&C==1)<<13|(C&H)<<12|(D&J)<<11|(D&I)<<10|(E&K)<<9|int(abs(y+.5)<.05&&E==1)<<8|int(abs(x-1.5)<.05&&E==1)<<7|(E&H)<<6|(K&F)<<5|int(abs(x-2.5)<.05)<<4|int(abs(y+1.5)<.05)<<3|(H&F)<<2|(G&J)<<1|(G&I)))!=0)
        {
            c=1.;
            break;
        }
    }
    R=vec4(((M[0]*M[1]==450&&M[1]*M[2]==120&&M[2]*M[3]==240&&M[3]*M[4]==1140&&M[4]*M[5]==2850&&M[5]*M[6]==1800&&M[0]+M[6]==81)?vec3(.3,.9,.3):vec3(.6,.1,.1))*c,0);
}

s값이 v26 % 0x1000001 형태로 들어가기 때문에, 0x1000001 미만의 s 값 중 주어진 코드의 마지막 삼항연산자 식을 맞출만한 값을 찾아주면 5609537 이다.

이 값을 디버깅 하면서 glUniform1i 함수에 넣어주고 실행시켜주면…

vibrations (rev)

go언어로 만들어진 바이너리다.

되게 복잡해서 디버깅하는데 시간을 좀 썼는데, 그냥 해시맵으로 구현된 무언가였다.

main_bb 에서 해시맵을 초기화 한다.

이때 함수 인자를 파싱해주면…

[[1, ‘C’], [2, ‘F’], [3, ‘F’], [4, ‘G’], [5, ‘F’], [6, ‘E’], [7, ‘D’], [8, ‘D’], [9, ‘D’], [10, ‘G’], [11, ‘G’], [12, ‘A’], [13, ‘G’], [14, ‘F’], [15, ‘E’], [16, ‘C’], [17, ‘C’], [18, ‘A’], [19, ‘A’], [20, ‘B’], [21, ‘A’], [22, ‘G’], [23, ‘F’], [24, ‘D’], [25, ‘C’], [26, ‘C’], [27, ‘D’], [28, ‘G’], [29, ‘E’], [30, ‘F’], [31, ‘C’], [32, ‘F’], [33, ‘F’], [34, ‘G’], [35, ‘F’], [36, ‘E’], [37, ‘D’], [38, ‘D’], [39, ‘D’], [40, ‘G’], [41, ‘G’], [42, ‘A’], [43, ‘G’], [44, ‘F’], [45, ‘E’], [46, ‘C’], [47, ‘C’], [48, ‘A’], [49, ‘A’], [50, ‘B’], [51, ‘A’], [52, ‘G’], [53, ‘F’], [54, ‘D’], [55, ‘C’], [56, ‘C’], [57, ‘D’], [58, ‘G’], [59, ‘E’], [60, ‘F’], [61, ‘C’], [62, ‘F’], [63, ‘F’], [64, ‘F’], [65, ‘E’], [66, ‘E’], [67, ‘F’], [68, ‘E’], [69, ‘D’], [70, ‘C’], [71, ‘G’], [72, ‘A’], [73, ‘G’], [74, ‘F’], [75, ‘C’], [76, ‘C’], [77, ‘C’], [78, ‘C’], [79, ‘D’], [80, ‘G’], [81, ‘E’], [82, ‘F’], [83, ‘C’], [84, ‘F’], [85, ‘F’], [86, ‘G’], [87, ‘F’], [88, ‘E’], [89, ‘D’], [90, ‘D’], [91, ‘D’], [92, ‘G’], [93, ‘G’], [94, ‘A’], [95, ‘G’], [96, ‘F’], [97, ‘E’], [98, ‘C’], [99, ‘C’], [100, ‘A’], [101, ‘A’], [102, ‘B’], [103, ‘A’], [104, ‘G’], [105, ‘F’], [106, ‘D’], [107, ‘C’], [108, ‘C’], [109, ‘D’], [110, ‘G’], [111, ‘E’], [112, ‘F’], [113, ‘C’], [114, ‘F’], [115, ‘F’], [116, ‘F’], [117, ‘E’], [118, ‘E’], [119, ‘F’], [120, ‘E’], [121, ‘D’], [122, ‘C’], [123, ‘G’], [124, ‘A’], [125, ‘G’], [126, ‘F’], [127, ‘C’], [128, ‘C’], [129, ‘C’], [130, ‘C’], [131, ‘D’], [132, ‘G’], [133, ‘E’], [134, ‘F’]]
 

CFFGFEDDDGGAGFECCAABAGFDCCDGEFCFFGFEDDDGGAGFECCAABAGFDCCDGEFCFFFEEFEDCGAGFCCCCDGEFCFFGFEDDDGGAGFECCAABAGFDCCDGEFCFFFEEFEDCGAGFCCCCDGEF

입력을 요렇게 넣으면 프로그램이 뭔가 터지는데, 터지기 전에 분기를 아래에 있는 aes 복호화 해주는게 포함된 어떤 함수로 넘겨주면,

HackTM{m3rry_xm4s_and_4_b3tt3r_2021} 플래그가 짠 하고 나온다.

 

후기

오랜만에 ctf했다.

웹문제가 약간 게싱느낌이 났지만, 웹 특성상 어쩔수 없는거라 불만은 없다.

demoscene는 문제 출제진이 손으로 인증해줬다. 플래그를 거의 맞게 구했는데 끝나기 10분전부터 2~3바이트 정도를 계속 틀리고 있었다.

정확하게 비교하는 식이 있는 형태가 아니라, OK! 모양이 나와야 하는 형태이고, 출제진이 안쓰러웠는지 직접 인증해줬다.

문제 퀄리티 다들 괜찮았고 재밋었다 gg;

 

아 팀이름 ROK YoungBloods 는 내가 지었다. 작명센스좀 괜찮은듯 ㅋㅋ;

 

 

 

 

2 Comments

답글 남기기

이메일 주소를 발행하지 않을 것입니다.