条件竞争
介绍
参考文章:ctf.wiki
条件竞争是指一个系统的运行结果依赖于不受控制的事件的先后顺序。当这些不受控制的事件并没有按照开发者想要的方式运行时,就可能会出现 bug。这个术语最初来自于两个电信号互相竞争来影响输出结果。
简单来说就是当一个资源被两个进程同时调用,那么就会出错。
通常,条件竞争出现下面三种情况
:
- 并发,即至少存在两个并发执行流。这里的执行流包括线程,进程,任务等级别的执行流。
- 共享对象,即多个并发流会访问同一对象。常见的共享对象有共享内存,文件系统,信号。一般来说,这些共享对象是用来使得多个程序执行流相互交流。此外,我们称访问共享对象的代码为临界区。在正常写代码时,这部分应该加锁。
- 改变对象,即至少有一个控制流会改变竞争对象的状态。因为如果程序只是对对象进行读操作,那么并不会产生条件竞争。
例子
1 | // 代码摘自ctf.wiki |
- 这个程序使用 POSIX 线程(
pthread
)库创建了 10 个线程,并让每个线程执行IncreaseCounter
函数。代码的目的是通过线程来增加一个共享变量counter
的值并打印每个线程的 ID 及counter
的当前值。 - 我们预期的输出应该是每个线程
conunter+1
,即:
1 | Thread .. has counter value 1 |
- 但是实际的输出却不尽如人意:
- 为什么会出现这样的输出呢?
counter
作为一个全局变量,但是却在多个线程之间+1,这样会导致条件竞争,使得多个线程在没有同步的情况下对counter
进行读写,从而导致counter
出错。
更加详细的参考开头的文章
例题
2024buildCTF-message
参考文章:stone神
ida查看
主要部分
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
- 在init函数里面的
clear_file
1 | int clear_file() |
add_message
1 | FILE *__fastcall add_message(FILE **a1) |
edit_message
1 | int __fastcall edit_message(FILE **a1) |
view_message
- 两秒检查一次
1 | int __fastcall view_message(FILE **a1) |
ftell
ftell
用于获取文件指针在文件中的当前位置,以字节为单位返回位置。>>>文件指针距离文件开头的距离
fseek
fseek
用于在文件中移动文件指针,允许从文件的指定位置开始读取或写入数据。
1
2 int fseek(FILE *stream, long int offset, int whence);
>>> fseek(*a1, 0LL, 2);// 表示移动到结尾
- 主要用到的就上面几个模块
分析
漏洞点就出现在edit_message
之中,2秒之后才会执行clear_file,在这之间我们可以开启两个线程,第一个随便写,第二个进程写入ROP,ROP的执行点就在view_message
之中,由于我们两次进程写入同一个共享资源message.txt
中,虽然每次只规定写0x50,但是两个进程可以写入0x100,会造成view_message
中栈溢出
可以第一个进程写入0x50的垃圾数据,然后第二个进程再补0x28的垃圾数据,然后就是正常的ret2libc了
EXP
1 | from pwn import * |
- 标题: 条件竞争
- 作者: D0wnBe@t
- 创建于 : 2024-11-05 22:15:52
- 更新于 : 2024-11-06 22:07:55
- 链接: http://downbeat.top/2024/11/05/条件竞争/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论