首页 > 其他分享 >Pwn 乱刷合集

Pwn 乱刷合集

时间:2024-11-25 23:44:33浏览次数:5  
标签:函数 乱刷 程序 pop 地址 ret Pwn 合集 我们

3※ [SHCTF 2024] No stack overflow2

  • 题目附件:

  • 考点:ret2libclibc 库查询整数溢出

  • 在 linux 下使用 checksec 查看该程序开启的保护,发现 Archamd64-64-little,这说明这是一个 64位 的程序,并且采用了 小端 存储,即低位对应低地址,高位对应高地址。

  • 下方的 RELRO ,这是一种通过设置 重定位相关表 的权限为 只读 来防止其被修改的安全机制,我们只关注其对 got 表的影响。Partial RELRO指的是部分开启,此时 got 表被设置为:每个表项只有在未解析过该函数地址前是可写,载入地址后改为只读:

  • 不过我们暂时不关心,把 vuln 文件拖进 IDA64 打开,点击左侧 main,按 F5 反编译,发现程序主要功能是先读入一个长度,接着检测长度小于等于 256 时再读入最多这么长的字节:

  • 我们看 IDA64 提示的存储地址,发现 nbytes_4 长度也是 0x100 即 256 个字节,难道无法溢出吗:

  • 我们发现关键在于传入参数时,将长度转为了 unsigned int 无符号整数,这就使得首位的符号位被当做了数据,那么如果原先输入长度为 -1,二进制对应的 0xFFFFFFFF,那么转为无符号整数后就变为了 2147483647,就可以绕过上方的长度检测了:

  • 那么接下来就是要构造我们的 payload1 了,但是一个个查看左侧函数发现没有 system 相关的,按 Shift+F12 也没有发现 /bin/sh 字符串。

  • 但是发现左侧有 puts 函数,那么我们可以考虑使用和上一题相同的方法:将 puts函数的 got 表地址泄露出来,然后查询其在动态库中的位置,二者相减得到偏移量。 接着就可以先查询动态库中的 system 函数和字符串 /bin/sh的位置,来计算出它们在程序中的位置,然后便可以构造 payload 模拟执行 system("/bin/sh")了。

  • 那么我们先打开 ELF 文件,查询puts函数 plt 表,got表所在的地址,以及 puts 结束后返回的 main 函数的地址:

  • 这里的 process('./vuln') 指的是先不连接服务器,而是用本地文件来模拟,方便我们调试:

  • 然后在第一处输入 -1 绕过长度检测:

  • 但是我们忽然发现一个问题,本题与上一题不同的是,上一题是 32位 程序,所有参数均通过栈来传递,我们只需要将函数的传参压入栈中即可模拟函数执行。但是这题是 64位 程序,函数的前 6个 参数是依次通过 6个 寄存器来传递:rdirsirdxrcxr8r9,之后的更多的参数才用栈来传递。这样使得程序运行的速度提升了不少,但是对于我们栈溢出攻击就不能直接通过栈来传参了,需要修改寄存器的值。


  • 我们可以想到,pop rdi 指令可以将栈内写入的内容传给 rdi这样就可以修改它了,那么如果我们将 pop rdi指令所在的地址,放在函数返回的 ret处,就可以修改 rip下一条指令执行 pop rdi 了!

  • 可是仅仅是这样,rip 跳转之后就回不来了,程序流程整个被打乱,所以我们需要找一个后面紧跟着 ret 指令的 pop rdi,这样下一句还会执行 ret,将此时 rsp 自加过后的栈顶的内容给 rip,不就仍然等同于继续进行栈溢出攻击了吗。

  • 同理,如果想要修改 rsirdx,也需要在程序中找到 pop rsi 随后 ret 的代码片段的地址,以此来传递参数模拟函数执行。这个过程就是所谓的构造 ROP 链。


  • 我们可以通过使用 ropper 工具或是 ROPgadget 工具,在 linux 下快速查找一个文件中出现指定字符串的位置,我们通过使用管道符来查找所有pop 开头到 ret 结尾的字符串,再要求其中含有 rdi,写出以下命令查询:ropper --file vuln --search "pop|ret" | grep "rdi",发现成功找到一个:

  • 记录下这段程序所在的地址 pop_rdi_ret = 0x401223,接下来就可以使用了。由于 puts 函数只需要一个参数,即输出的字符串的地址,我们只需要 rdi 来传参,所以现在可以开始构造 payload1 了:

  • 先填充 0x100即 256个字节 给 nbytes_4,然后因为这是 64位 程序,要填充 8个字节 给 srbp,接下来在 r 处填入我们的 pop rdi;ret 程序的地址:p64(pop_rdi_ret),然后填入要修改的 rid 数据,即 puts 的传参,也就是要输出的字符串的地址:puts_got

  • 然后填充 pop rdi;ret 返回回来后要执行的程序的地址,我们要输出 puts 函数的 got 表里的内容,所以这里填调用的输出函数 puts 的地址:puts_plt

  • 最后填充 puts函数输出完返回回来后要执行的下一个程序的地址,由于我们需要再次利用这里的栈溢出来执行 system("/bin/sh"),所以填 main 函数的首地址。

    image

  • 可以看到此时已经将地址输出出来了,不过都是 \x开头的 16 进制 bytes 数据。由于 64位 程序的地址都是以 \x7f 开头的,并且由于这是个 小端程序,字符串地位置存储在低位置,所以输出出来是倒序的,所以我们可以用 .recvuntil(b'\x7f') 读到 \x7f 为止。

  • 又由于虽然我们是 64位 程序虽然应该有 8 位,但使用时的编码都是以 \x7f 开头的 6位 编码地址,所以我们只要读进来的最后 6个字节:

    image

  • 然后我们要对这个 16进制 的 bytes 数据用 u64() 进行解包,但是如果直接使用的话程序会报错:

    image

  • 这是因为 u64() 每次解包需要输入 \(8个字节\),而刚才的地址不足 8位,我们需要在左侧用.ljust(8,b'\x00')\x00 将其补满 8位:

    image

  • 此时再输出发现就是正确的一个整数地址了:

    image

  • 那么拿到了一个 puts 函数的 got 表的所在地址,接下来我们就可以通过查询动态库中 puts 函数的地址然后计算出偏移量啦。

  • 不过这道题题目并没有把动态库文件直接给我们,我们需要根据泄露出来的 puts 函数的 got 表的所在地址来查询到系统所使用的动态库版本。


  • 我们可以下载使用 LibcSearcher 这个 python 库来打开对应的动态库,只需要提供某个已知函数的具体地址即可:

    image

  • 接下来就和上一题一样了,查询 puts 函数在动态库的地址,计算出偏移量,然后查询 system 函数和 /bin/sh 字符串在动态库的地址,计算出在程序内的地址。不过要注意的是此时使用 LibcSearcher 指令,需要用 .dump("xxx") 来查询某个函数的地址,用 .dump("str_bin_sh") 来查询字符串 /bin/sh 的位置:

    image

  • 此时运行时我们会发现,查找到多个匹配的动态库,程序询问我们要使用哪一个版本的,这是因为先前我们用的是 process('./vuln') 在本地调试。而如果连接到服务器上的时候就不需要我们进行选择了。

  • 不过现在我们需要根据自己的 ubuntu 版本来选择对应的动态库,我们可以先按 Ctrl+C 退出程序,在 linux 中输入 ldd --version 来查询版本:

    image

  • 可以看到第二行,我的是 2.39-0ubuntu8.3,那么再次运行程序,这次就选择这个版本的动态库,填入程序提示的版本前方的编号 0 按回车,可以看到下方有一句该版本 be choosed就成功选择了:

    image

  • 那么完事具备,我们现在已经执行到第二次 main 函数要求我们输入长度的位置了,再次输入 -1,然后开始构造我们第二次的 payload2:

  • 先填充前面 0x108 个字符到 r 处与 payload1 一样,然后通过 pop di;ret 来传递 system 的参数:bin_sh_addr

  • 然后填充要执行的 system 函数的地址: system_addr

  • 最后的返回地址在哪里都无所谓,因为马上要得到系统权限进入交互模式了,并不会返回回来用上,直接不填。

    image

  • 但是!此时运行会发现并没有得到系统权限,反而报错退出了。这是因为这是采用了新的高版本的 gcc 编译器的 64位 系统,其在调用动态库中的 system 函数时,对 rsp 有额外的要求:

  • 在准备进入 system 函数时,会对此时的 rsp 也就是栈顶进行一次检验,要求此时指向的地址必须能被 16 整除,也就是必须以 0 结尾,否则报错退出不予调用。

  • 我们进入 IDA64 的 main 函数,点击 nbytes_4 查看栈空间,发现我们填充到 r 的位置以 8 结尾:

    image

  • 所以此时放在 r 中的 pop rdi;ret 的地址以 8 结尾,接下来 /bin/sh 字符串的地址以 0 结尾,而 system函数的地址以 8 结尾,就无法通过高版本的 rsp 检验。

  • 那么我们需要再调用 system 函数之前额外填充一个 某段程序的地址,这样在执行 system 函数时 rsp就以 0 结尾了。

  • 最简单的就是找一个只有一句 ret 指令的地址,rip 执行原先函数的ret 跳转到这里后,下一句还是将执行 ret,没有区别,但是此时 rsp 已经自加了一次。

  • 所以我们用 ropper 指令寻找一个只有一句 ret 的程序,在 linux 下输入 ropper --file vuln --search "ret" 查找:

    image

  • 记录下程序的位置 ret = 0x40101a,接下来只需要在调用 system 之前多填充一个 ret 的地址即可:

    image

  • 此时运行完程序,在选择动态库版本输入 0 后,我们发现已经进入了交互模式,输入 ls 可以看到当前目录下的文件,大功告成:

    image

  • 最后调整为远程连接服务器,ls 一下发现有 flagcat flag 获取 flag:

    image

  • 最后放上完整 exp(调整了一下顺序):

    image

  • 除了使用 LibcSearcher 在线查询动态库之外,我们还可以使用一个在线网站将服务器所使用的动态库下载下来:https://libc.rip/,使用的时候只需要输入,泄露的函数的名称,和泄露出来的函数的地址的后三位(16进制)即可:

    image

  • 当然,如果用 puts 函数查不到对应的版本的话,可以试着用别的函数查询,网站的内容有时候明没有更新到最新(这里就是,我换成了 read函数 ):

    image

  • 然后可以下载下来,本地进行调试(当然我们不知道服务器用的是哪一个,这只限于本地调试代码用的下载)。



3※ [SHCTF2024] No stack overflow2 pro

  • 考点:libc 静态链接

  • 这题题目首先提示了,使用了静态链接,也就是将动态链接直接写入了程序中,这样就没有 plt 表和 got 表供我们使用了。

  • 首先在 linux 下用 checksec vuln 查看文件保护情况:

    image

  • 发现是 64位 小端程序,开了 Partial RELRO,开了 NX 保护,这个就是不允许执行存放在数据段的代码,也就是为什么我们之前,都要费尽心思往栈里面写别的程序的地址的原因:代码直接放在栈里面不允许执行。

  • 接着是 Stack:Canary found ,这是指开启了 Canary保护:在进入函数前生成一个校验码压入栈中,在函数返回时检测校验码是否被修改,若被修改则判断栈发生了改变收到了溢出攻击,自动结束程序。这是对栈溢出攻击的防护。

  • 那么接下来我们拖入 IDA64 中,发现左边乱七八糟一大堆,这正是因为静态链接引起的,将所有动态库里的函数全写进来了,如果查看过这个文件的大小的话,会发现它远远大于我们之前使用动态库连接技术的文件的大小:

    image

  • 我们找到加黑了的 main,点击进入,F5 反编译,发现和上一题的代码一模一样,都是输入一个长度,然后转化为有符号的 int来进行判断大小,接着往 v9 中存入不超过先前读入的长度的字节。很明显这里存在着和前几题一样的栈溢出:

    image

  • 那么我们记得先前有提到 Canary保护,点开 v9 查看栈结构找找 校验值 存在哪里,但是发现 v9 下面直接就是 sr 了,并没有找到 Canary保护的校验值存储的位置,那么就不需要理会了,直接正常溢出即可执行我们想执行的程序,也就是所谓的劫持程序。

  • 我们需要模拟 system("/bin/sh") ,这在动态库里本质是输入指令syscall,所以我们就需要一个写着 syscall指令的地址,用 ropper --file vuln --search "syscall" 进行查找:

  • 发现很多个,我们随便选哪个地址都可以,因为执行完 syscall 指令后我们会获得系统权限进入交互模式,就不用管 syscall指令之后还有什么了,可以选最后一个 syscall_addr = 0x41cbf6

  • 接下来我们要找字符串 /bin/sh,按 Shift+F12,按 alt+T 查找字符串 /bin/sh,发现并没有跳转,不存在现成的字符串:

    image

  • 所以我们只能自己找一个地址,往里面写入字符串 /bin/sh。首先我们需要找一个有读和写权限的段,因为既要写进去也要读出来使用。我们按 Shift+F7 打开段视图,一般使用 .bss 段,BSS 段通常是指用来存放程序中 未初始化 的或者 \(初始化为0\) 的 全局变量 和 静态变量 也就是说,只要初始值为 0 的类型,都会先放在这里,等到再次赋值时才会被取出。所以写在这里面可以全局使用。

  • 我们点开 .bss 段,随便复制一个起始位置,bss_addr = 0x4E72C0

  • 那么接下来我们要往里面写数据,可以调用 read 函数,在左侧下方输入 read 查找函数位置:

  • 点进去,复制函数入口位置,read_addr = 0x44FD90

  • 我们发现 read 函数需要三个参数,由于这是 64位 程序通过寄存器传参,所以和上一题一样我们要去寻找 pop rdi;retpop rsi;retpop rdx;ret 的程序的存放位置,来改变寄存器的值为 read函数传参:

  • 在 linux 下用 ropper --file vuln --search "pop|ret" | grep "rdi" 来找与 rdi 相关的指令,在一大堆结果中找到紧挨着 ret 的程序,pop_rdi_ret = 0x4022bf

  • 在 linux 下用 ropper --file vuln --search "pop|ret" | grep "rsi" 来找与 rsi 相关的指令,同理找紧挨着 ret的程序,pop_rsi_ret = 0x40a32e

  • 在 linux 下用 ropper --file vuln --search "pop|ret" | grep "rdx" 来找与 rsi 相关的指令时,发现没有紧挨着 ret的程序,我们找一个离 ret最近的程序,中间仍然多了一个 pop rbx,不过也可以用,每次多传一个 0 给 rbx 即可,pop_rdx_rbx_ret = 0x49D06B

  • 最后在程序内找到 main的起始地址,因为第一次溢出后我们输入字符串 /bin/sh 还需要第二次溢出来执行 system("/bin/sh")main_addr = 0x401B7A

  • 那么我们可以开始构造第一次溢出的 payload1 了,需要注意的是,这一个程序输入长度的时候用 (unsigned int) 输入,判断的时候转为 (int) 判断,所以我们需要输入 2147483679,对应的二进制转化为 (int) 就是 -1:

  • 然后构造 payload1,先用 0x100 + 0x08 个字节填充到 r 处,然后用寄存器为 read 函数传参:

  • 第一个参数表示读取的文件,为 0 表示从控制台读入,我们 pop_rdi_ret 后传 0

  • 第二个参数为存放的地址,我们 pop_rsi_ret 后传 bss_addr

  • 第三个参数为最大的写入长度,可以大一点,我们 pop_rdx_rbx_ret 后传 0x100,然后传 0 给多的 pop rbx

  • 最后填充函数结束后返回的地址 main_addr

  • 且慢,这是 64 程序,需要检验一下调用 main 函数之前,rsp 是否指向的地址末尾为 0,可以简单数一下 main 函数是第 9 条指令,第一条指令以 8 结尾,此时 main 也以 8 结尾,无法通过检验。我们需要再填充一条指令进去,这就是所谓的平衡栈操作。

  • 同上一题,我们再用 ropper --file vuln --search "ret" 找一下 ret 指令的位置,取单独的指令,ret = 0x454257

  • 那么我们此时在进入 main之前加一个 ret 指令的地址来平衡栈,构造出 payload1:

  • 运行可以看到此时程序成功执行了 read 函数,在输入一串字符后重新开始执行 main 函数了:

    image

  • 接下来我们可以往这个 .bss 段里面写入 /bin/sh 字符串了,需要注意的是字符串需要一个结束标识符 \x00,所以我们往里面写的应该是 b'/bin/sh\x00'

  • 接着重新再来一遍 main 函数,还是先输入 2147483649 绕过长度判断,然后开始构造 payload2 来执行我们的 system("/bin/sh")


  • syscall 的本质是系统通过调用这条指令时 rax 里面的值,来执行不同的函数,我们执行 system("/bin/sh")时需要令 rax = 0x3b 来执行 execve语句。(在 32位 系统中,是用 int 80h 代替 syscall,同时令 eax = 0x0b),所以我们需要找到修改 rax 寄存器的代码段 pop rax;ret,和之前的那些一样,都是所谓的 gadget。

  • 在 linux 中用 ropper --file vuln --search "pop|ret" | grep "rax" 来查找,pop_rax_ret = 0x4507f7

  • 那么接下来就可以继续构造我们的 payload2 了,先填充 0x108 个字符到 r,然后在 pop_rax_ret 后传 0x3b 修改 rax

  • 接着为 syscall 传参数,一共有三个参数:

    第一个参数是字符串地址,pop_rdi_ret 后传 bss_addr

    第二和第三个参数涉及系统内核取参方式,系统空间与用户空间之间的协议,都设为 0 默认即可。

  • pop_rsi_ret 后传 0,pop_rdx_rbx_ret 后传 0 ,再传 0 给 rbx

  • 最后填入 syscall_addr 的地址,来调用系统的 syscall 功能。

  • 此时算一下是否栈平衡,我们数一下 syscall的地址为第 10 个指令,此时 rsp 末位为 0,无需调整。

  • 运行成功获得系统权限,进入交互模式,输入 ls 成功输出当前目录下的内容:

  • 转为远程连接服务器再次运行,输入 cat flag 获得 flag:

  • 最后附上完整 exp(调整了下顺序):

标签:函数,乱刷,程序,pop,地址,ret,Pwn,合集,我们
From: https://www.cnblogs.com/ShallowDream7933/p/18568528

相关文章

  • Crypto 攻防世界合集
    古典密码1※base64考点:base64加密得到一段字符串,有各种可见字符,考虑是否为base64加密:放到Cyberchef里面用base64解密,得到flag:1※Railfence考点:栅栏密码得到一串编码后的字符串,观察到存在明文{和},但是位置不对,考虑栅栏密码:题目中提示了喂......
  • (2024最新毕设合集)基于SpringBoot的校园共享厨房信息系统-72647|可做计算机毕业设计JAV
    目 录摘要第一章 绪论1.1选题背景与意义1.2研究现状1.3论文结构与章节安排第二章系统分析2.1可行性分析2.1.1技术可行性分析2.1.2 经济可行性分析2.1.3操作可行性分析2.2系统功能分析2.2.1功能性分析2.2.2非功能性分析2.3 系统用例分......
  • 开箱即用的JAVA AI平台AI合集包含旦不仅限于(人脸识别、车牌识别、安全帽识别、开门关
    开箱即用的JAVAAI平台AI合集包含旦不仅限于(人脸识别、车牌识别、安全帽识别、开门关门、常用类物识别等)图片和视频识别前景我在写摄像头识别AI内容的时候被一些api需要付费所感觉到恶心自此自己开发离线化版本AI识别、chatgpt简介1.AI合集包含旦不仅限于(人脸识别、车牌......
  • 51c大模型~合集78
    我自己的原文哦~  https://blog.51cto.com/whaosoft/12642335#LTX-VideoRTX4090可跑、完全开源,最快视频生成模型问世,实测一言难尽开源AI视频社区又一个重量级选手下场。这个周末,押注开源人工智能视频的初创公司Lightricks,有了重大动作。该公司推出了最快的视频......
  • 51c~TensorRT~合集1
    我自己的原文哦~  https://blog.51cto.com/whaosoft/11744302一、TensorRT-LLM~最佳部署实践TensorRT-LLM(LargeLanguageModel)部署实践的详细介绍TRT-LLM简单再介绍TensorRT-LLM的介绍前几篇中已提到,就不过多赘述了。这里列一个TensorRT-LLM的功能和定位:trt-llm功......
  • 51c~CUDA~合集2
     我自己的原文哦~  https://blog.51cto.com/whaosoft/12403901一、如何优雅地测量GPUCUDAKernel耗时?​背景Rainlin:如何优雅地测量GPUCUDAKernel耗时?(一)中介绍了常用的测量gpu耗时方法,而实际应用中,还会遇到其他的问题,比如:为什么同样的输入,测量的耗时存在较大差距?怎样......
  • JavaWeb合集17-拦截器(Interceptor)和过滤器(Filter)
    十七、拦截器和过滤器在JavaWeb开发中,拦截器(Interceptor)和过滤器(Filter)都是用于在请求处理前后执行某些操作的机制。虽然它们的功能相似,但在实现方式、使用场景和灵活性方面有一些重要的区别。1、拦截器和过滤器的区别及选择1.1拦截器定义:拦截器是Spring框架提供......
  • 【2024/10/22】ChatGPT国内中文版镜像网站整理合集
    一、GPT中文镜像站 yixiaai.com 支持GPT4、4o以及o1,支持MJ绘画1.什么是镜像站镜像站(MirrorSite)是指通过复制原始网站内容和结构,创建的备用网站。其主要目的是在原始网站无法访问时,提供相同或类似的服务和信息。2. ChatGPT镜像站的用途绕过访问限制 :在某些地区,访问O......
  • 大模型~合集12
    我自己的原文哦~ https://blog.51cto.com/whaosoft/12286764#DISC-FinLLM复旦大学团队发布中文智慧金融系统,采用多专家微调框架金融领域为自然语言处理(NLP)模型带来了独特的挑战和机遇。当前,金融文本和数据的信息量和复杂性呈现爆炸式增长,一个强大、可靠的智慧金融系统可以......
  • 顶会论文下载合集(ECCV 2024全)
    2024CV2024综述(持续更新中)链接:https://pan.baidu.com/s/16yglfB7YtkDDWFQPC3u9xQ提取码:52CVECCV2024论文全链接:https://pan.baidu.com/s/1YUVUqmIP3Y_DIxg4w1OYwg提取码:52CVCVPR2024论文全链接:https://pan.baidu.com/s/15-RZjmXoTxZtyS7NMxV4CQ提取......