해당 바이너리와 같은 경우 핵스레이가 안되서 gdb로 디버깅하면서 코드 분석을 했다.


먼저 objudmp로 대충 봐보면 섹션이 하나밖에 없고 크기가 작아서 분석하는데 어려움은 없었다.


0000000000400080 <.text>:

  400080: eb 50                 jmp    0x4000d2

  400082: 48 31 c0              xor    rax,rax 

  400085: fe c0                 inc    al

  400087: 48 31 ff              xor    rdi,rdi

  40008a: 48 ff c7              inc    rdi

  40008d: 5e                    pop    rsi

  40008e: b2 2e                 mov    dl,0x2e

  400090: 0f 05                 syscall 

  400092: 2c 2e                 sub    al,0x2e

  400094: ff cf                 dec    edi

  400096: 0f 05                 syscall 

  400098: 48 0f b6 7e 01        movzx  rdi,BYTE PTR [rsi+0x1] 

  40009d: 48 31 3e              xor    QWORD PTR [rsi],rdi

  4000a0: 48 ff c6              inc    rsi

  4000a3: 48 ff ca              dec    rdx

  4000a6: 75 f0                 jne    0x400098 ; 반복문 end

  4000a8: 83 e1 2e              and    ecx,0x2e

  4000ab: 80 c1 26              add    cl,0x26

  4000ae: 48 8d 7e 07           lea    rdi,[rsi+0x7]

  4000b2: 48 8d 77 cb           lea    rsi,[rdi-0x35]

  4000b6: f3 a6                 repz cmps BYTE PTR ds:[rsi],BYTE PTR es:[rdi]

  4000b8: 48 85 c9              test   rcx,rcx

  4000bb: 75 49                 jne    0x400106

  4000bd: 34 2f                 xor    al,0x2f

  4000bf: 68 59 61 79 21        push   0x21796159

  4000c4: 48 89 e6              mov    rsi,rsp

  4000c7: b2 04                 mov    dl,0x4

  4000c9: bf 01 00 00 00        mov    edi,0x1

  4000ce: 0f 05                 syscall 

  4000d0: eb 34                 jmp    0x400106

  4000d2: e8 ab ff ff ff        call   0x400082 

  4000d7: 57                    push   rdi

  4000d8: 65 6c                 gs ins BYTE PTR es:[rdi],dx

  4000da: 63 6f 6d              movsxd ebp,DWORD PTR [rdi+0x6d]

  4000dd: 65 20 74 6f 20        and    BYTE PTR gs:[rdi+rbp*2+0x20],dh

  4000e2: 74 68                 je     0x40014c

  4000e4: 69 73 20 43 68 61 6c  imul   esi,DWORD PTR [rbx+0x20],0x6c616843

  4000eb: 6c                    ins    BYTE PTR es:[rdi],dx

  4000ec: 21 20                 and    DWORD PTR [rax],esp

  4000ee: 0a 45 6e              or     al,BYTE PTR [rbp+0x6e]

  4000f1: 74 65                 je     0x400158

  4000f3: 72 20                 jb     0x400115

  4000f5: 74 68                 je     0x40015f

  4000f7: 65 20 4b 65           and    BYTE PTR gs:[rbx+0x65],cl

  4000fb: 79 20                 jns    0x40011d

  4000fd: 74 6f                 je     0x40016e

  4000ff: 20 77 69              and    BYTE PTR [rdi+0x69],dh

  400102: 6e                    outs   dx,BYTE PTR ds:[rsi]

  400103: 3a 20                 cmp    ah,BYTE PTR [rax]

  400105: 00 31                 add    BYTE PTR [rcx],dh

  400107: c0                    (bad)  

  400108: b0 3c                 mov    al,0x3c

  40010a: 0f 05                 syscall 

  40010c: 0a 0d 06 1c 22 38     or     cl,BYTE PTR [rip+0x38221c06]        # 0x38621d18

  400112: 18 26                 sbb    BYTE PTR [rsi],ah

  400114: 36 0f 39              ss (bad) 

  400117: 2b 1c 59              sub    ebx,DWORD PTR [rcx+rbx*2]

  40011a: 42 2c 36              rex.X sub al,0x36

  40011d: 1a 2c 26              sbb    ch,BYTE PTR [rsi+riz*1]

  400120: 1c 17                 sbb    al,0x17

  400122: 2d 39 57 43 01        sub    eax,0x1435739

  400127: 07                    (bad)  

  400128: 2b 38                 sub    edi,DWORD PTR [rax]

  40012a: 09 07                 or     DWORD PTR [rdi],eax

  40012c: 1a 01                 sbb    al,BYTE PTR [rcx]

  40012e: 17                    (bad)  

  40012f: 13 13                 adc    edx,DWORD PTR [rbx]

  400131: 17                    (bad)  

  400132: 2d 39 0a 0d 06        sub    eax,0x60d0a39

  400137: 46 5c                 rex.RX pop rsp

  400139: 7d                    .byte 0x7d



전체적인 흐름은 syscall을 통해 입력 값을 받고 input[i]^input[i+1] 연산을 총 46회 반복한다.


이 값이 특정영역의 값과 같으면 되는데 특정영역의 값은  repz cmps BYTE PTR ds:[rsi],BYTE PTR es:[rdi] 요 명령어 실행 시 rdi 레지스터에 존재하는 주소에서 46 byte 값을 써주면 된다.


로직이 간단해서 코드 짜는건 간단했고 z3로 돌려주니 flag가 나왔다.


from z3 import *


result = [0x0a,0x0d,0x06,0x1c,0x22,0x38,0x18,0x26,0x36,0x0f,0x39,0x2b,0x1c,0x59,0x42,0x2c,0x36,0x1a,0x2c,0x26,0x1c,0x17,0x2d,0x39,0x57,0x43,0x01,0x07,0x2b,0x38,0x09,0x07,0x1a,0x01,0x17,0x13,0x13,0x17,0x2d,0x39,0x0a,0x0d,0x06,0x46,0x5c,0x7d,0x00]

a = []

s = Solver()


for i in range(0,47):

    a.append(BitVec('a['+str(i)+']',8))


for i in range(0,46):

    s.add( (a[i]^a[i+1])==result[i])


flag = ""

while s.check() == z3.sat:

    flag = ""

    m = s.model()

    for i in range(0, 47):

        flag += chr(int(str(m[a[i]])))

    if "flag" in flag:

        print flag

    for i in range(0,47):

        s.add(m[a[i]]!=a[i])



Flag = flag{Yay_if_th1s_is_yer_f1rst_gnisrever_flag!} 







'CTF > Writeup' 카테고리의 다른 글

BSides Delhi CTF 2018 auth3ntication  (0) 2018.10.29
BSides Delhi CTF 2018 Old School SQL  (0) 2018.10.29
InCTF 2018 TorPy  (0) 2018.10.08
InCTF 2018 WildCat  (0) 2018.10.08
InCTF 2018 S3cur3 Bank  (0) 2018.10.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,