Kilkat

공주대학교 리버싱문제(중) KingKEY 본문

Security/reverse engineering

공주대학교 리버싱문제(중) KingKEY

KimKwangWoon 2018. 8. 4. 14:51

목표: strncmp 취약점을 이용해 flag값을 가져오기


사용 프로그램: vmware 64bit (kali linux 64bit), peda

문제: 공주대학교 영재교육원CTF 문제

컴퓨터 환경: kali linux(64bit)


문제풀이


우선 되게 재밌었던 문제였다. 리눅스로 풀어야 하는 리버싱 문제여서 되게 재밌게 풀은것 같다. 우선 문제가 어떻게 작동하는지 알기 위해서 kali linux에 옮겨서 실행을 시켜봅니다.

그럼 이렇게 ?????를 출력을 하고 그다음에 Pass code를 입력하는 창이 나오게 됩니다. 우선 Pass code를 모르는 상황이기 때문에 아무값이나 넣어 봤습니다.

그러니 바로 Who are U.라고 너 누구냐 라는 값을 출력하는데... 이제 저 값이 flag로 바뀌게끔 만들어보죠 gdb로 열어보겠습니다.

Dump of assembler code for function main:

   0x00000000004006ed <+0>: push   rbp

   0x00000000004006ee <+1>: mov    rbp,rsp

   0x00000000004006f1 <+4>: push   rbx

   0x00000000004006f2 <+5>: sub    rsp,0x98

   0x00000000004006f9 <+12>: mov    rax,QWORD PTR fs:0x28

   0x0000000000400702 <+21>: mov    QWORD PTR [rbp-0x18],rax

   0x0000000000400706 <+25>: xor    eax,eax

   0x0000000000400708 <+27>: movabs rax,0x6d624e70646d6a48

   0x0000000000400712 <+37>: mov    QWORD PTR [rbp-0x90],rax

   0x0000000000400719 <+44>: mov    WORD PTR [rbp-0x88],0x33

   0x0000000000400722 <+53>: movabs rax,0x5d676f32416e6755

   0x000000000040072c <+63>: mov    QWORD PTR [rbp-0x60],rax

   0x0000000000400730 <+67>: movabs rax,0x4f425d71656c6b49

   0x000000000040073a <+77>: mov    QWORD PTR [rbp-0x58],rax

   0x000000000040073e <+81>: movabs rax,0x7067606f67

   0x0000000000400748 <+91>: mov    QWORD PTR [rbp-0x50],rax

   0x000000000040074c <+95>: mov    DWORD PTR [rbp-0x48],0x0

   0x0000000000400753 <+102>: mov    WORD PTR [rbp-0x44],0x0

   0x0000000000400759 <+108>: mov    edi,0x400924

   0x000000000040075e <+113>: call   0x4005a0 <puts@plt>

   0x0000000000400763 <+118>: mov    edi,0x400924

   0x0000000000400768 <+123>: call   0x4005a0 <puts@plt>

   0x000000000040076d <+128>: mov    edi,0x400924

   0x0000000000400772 <+133>: call   0x4005a0 <puts@plt>

   0x0000000000400777 <+138>: mov    edi,0x400924

   0x000000000040077c <+143>: call   0x4005a0 <puts@plt>

   0x0000000000400781 <+148>: mov    edi,0x40092c

   0x0000000000400786 <+153>: mov    eax,0x0

   0x000000000040078b <+158>: call   0x4005c0 <printf@plt>

   0x0000000000400790 <+163>: mov    DWORD PTR [rbp-0x94],0x0

   0x000000000040079a <+173>: jmp    0x4007c4 <main+215>

   0x000000000040079c <+175>: mov    eax,DWORD PTR [rbp-0x94]

   0x00000000004007a2 <+181>: cdqe   

   0x00000000004007a4 <+183>: movzx  eax,BYTE PTR [rbp+rax*1-0x90]

   0x00000000004007ac <+191>: xor    eax,0x3

   0x00000000004007af <+194>: mov    edx,eax

   0x00000000004007b1 <+196>: mov    eax,DWORD PTR [rbp-0x94]

   0x00000000004007b7 <+202>: cdqe   

   0x00000000004007b9 <+204>: mov    BYTE PTR [rbp+rax*1-0x70],dl

   0x00000000004007bd <+208>: add    DWORD PTR [rbp-0x94],0x1

   0x00000000004007c4 <+215>: cmp    DWORD PTR [rbp-0x94],0x9

   0x00000000004007cb <+222>: jle    0x40079c <main+175>

   0x00000000004007cd <+224>: lea    rax,[rbp-0x80]

   0x00000000004007d1 <+228>: mov    rsi,rax

   0x00000000004007d4 <+231>: mov    edi,0x400937

   0x00000000004007d9 <+236>: mov    eax,0x0

   0x00000000004007de <+241>: call   0x4005f0 <__isoc99_scanf@plt>

   0x00000000004007e3 <+246>: lea    rcx,[rbp-0x80]

   0x00000000004007e7 <+250>: lea    rax,[rbp-0x70]

   0x00000000004007eb <+254>: mov    edx,0x9

   0x00000000004007f0 <+259>: mov    rsi,rcx

   0x00000000004007f3 <+262>: mov    rdi,rax

   0x00000000004007f6 <+265>: call   0x400590 <strncmp@plt>

   0x00000000004007fb <+270>: test   eax,eax

   0x00000000004007fd <+272>: jne    0x400870 <main+387>

   0x00000000004007ff <+274>: mov    edi,0x40093a

   0x0000000000400804 <+279>: call   0x4005a0 <puts@plt>

   0x0000000000400809 <+284>: mov    edi,0x400950

   0x000000000040080e <+289>: call   0x4005a0 <puts@plt>

   0x0000000000400813 <+294>: mov    DWORD PTR [rbp-0x94],0x0

   0x000000000040081d <+304>: jmp    0x40085b <main+366>

   0x000000000040081f <+306>: mov    eax,DWORD PTR [rbp-0x94]

   0x0000000000400825 <+312>: cdqe   

   0x0000000000400827 <+314>: movzx  eax,BYTE PTR [rbp+rax*1-0x60]

   0x000000000040082c <+319>: xor    eax,0x2

   0x000000000040082f <+322>: mov    edx,eax

   0x0000000000400831 <+324>: mov    eax,DWORD PTR [rbp-0x94]

   0x0000000000400837 <+330>: cdqe   

   0x0000000000400839 <+332>: mov    BYTE PTR [rbp+rax*1-0x40],dl

   0x000000000040083d <+336>: mov    eax,DWORD PTR [rbp-0x94]

   0x0000000000400843 <+342>: cdqe   

   0x0000000000400845 <+344>: movzx  eax,BYTE PTR [rbp+rax*1-0x40]

   0x000000000040084a <+349>: movsx  eax,al

   0x000000000040084d <+352>: mov    edi,eax

   0x000000000040084f <+354>: call   0x400580 <putchar@plt>

   0x0000000000400854 <+359>: add    DWORD PTR [rbp-0x94],0x1

   0x000000000040085b <+366>: cmp    DWORD PTR [rbp-0x94],0x14

   0x0000000000400862 <+373>: jle    0x40081f <main+306>

   0x0000000000400864 <+375>: mov    edi,0xa

   0x0000000000400869 <+380>: call   0x400580 <putchar@plt>

   0x000000000040086e <+385>: jmp    0x40087a <main+397>

   0x0000000000400870 <+387>: mov    edi,0x400962

   0x0000000000400875 <+392>: call   0x4005a0 <puts@plt>

   0x000000000040087a <+397>: mov    eax,0x0

   0x000000000040087f <+402>: mov    rbx,QWORD PTR [rbp-0x18]

   0x0000000000400883 <+406>: xor    rbx,QWORD PTR fs:0x28

   0x000000000040088c <+415>: je     0x400893 <main+422>

   0x000000000040088e <+417>: call   0x4005b0 <__stack_chk_fail@plt>

   0x0000000000400893 <+422>: add    rsp,0x98

   0x000000000040089a <+429>: pop    rbx

   0x000000000040089b <+430>: pop    rbp

   0x000000000040089c <+431>: ret    

End of assembler dump.


그럼 이렇게 뭔가 주르륵 나오게 되는데 여기서 주목해야 할 부분은 strncmp 즉 입력받은 값을 검사해 주는 부분을 주목해야 한다. 빨간색으로 색칠되어 있는 부분을 주목해야 한다고 방금 언급을 했는데 해석을 해보자면 mov명령어로 rcx에 들어가있는 값을 rsi부분으로 옮겨주고 그 다음 mov명령어에서 rax에 들어가있는 값을 rdi로 옮겨주는 것을 알수 있다. 그 다음은 입력받은 값을 서로 비교해서 검사하는 부분인데 여기서 문제에 대한 느낌이 온게 rsi에 입력된 값과 rdi에 입력된 값을 서로 비교해서 일치하면 flag를 출력시킬 것이라고 확신이 들었다. 그래서 서로 입력값을 비교하는 곳인 strncmp 부분에 breakpoint를 걸어서 확인해 봤다.

확인해보니 아까 예측이 정확하게 적중을 했다.

좀더 눈에 잘 보이도록 빨간색 박스를 쳐서 확인을 해보면 RSI부분에서 Passcode에서 입력받은 값을 저장하고 RDI부분에서 원래 Passcode값인 KingsMan0\003값을 가지고와서 RIP에서 strncmp로 서로 비교를 한다. 그러므로 여기서 우리가 Passcode에 넣어야 하는 값은 KingsMan0\003라는 것을 알수 있다. 실제 프로그램을 실행시켜 확인을 해보면

flag값을 출력하게 된다. 이로써 리버싱 (중)단계 문제인 KingKEY문제를 clear했다.




Comments