MiniLctf2022
题目质量很高,我也是真的菜
¶题目和WP
https://github.com/XDSEC/miniLCTF_2022
¶Twin
¶考点:TLS_CallBack函数、SMC、XXTEA+XXTEA魔改、反调试、花指令
¶前置知识
¶TLS_CALLBACK函数
TLS设计的本意,是为了解决多线程程序中变量同步的问题,是Thread Local Storage的缩写,意为线程本地存储。线程本身有独立于其他线程的栈空间,因此线程中的局部变量不用考虑同步问题。多线程同步问题在于对全局变量的访问,TLS在操作系统的支持下,通过把全局变量打包到一个特殊的节,当每次创建线程时把这个节中的数据当做副本,拷贝到进程空闲的地址空间中。以后线程可以像访问局部变量一样访问该异于其他线程的全局变量的副本,而不用加同步控制。
TLS回调函数常用于反调试
每当创建或终止进程的线程时会自动调用执行的函数。当然,创建进程的主线程的时候也会自动调用回调函数,且其执行先于EP代码。反调试技术就是利用的TLS回调函数的这一特征。它是各线程独立的数据存储空间,可修改进程的全局/静态数据
而它可以注册多个TLS_CALLBACK函数
¶进程通信-共享内存CreateFileMapping+MapViewOfFile
https://www.cnblogs.com/endenvor/p/9753135.html
把文件映像到内存,首先必须调用CreateFileMapping()函数,然后再调用MapViewOfFile函数,把文件视映像到进程地址空间上。这样多个子进程都可以访问该内存
¶分析
这道题所有的字符串都进行了异或加密
在main函数中逆出来得到的是fake_flag,然后去Export发现了TLS函数
https://blog.csdn.net/CSNN2019/article/details/113094488
点进去发现里面什么代码都没有,很奇怪,查看汇编
这里加了一处花指令导致ida无法正常分析
这段花指令就是将返回地址(call后压入栈的值)加上插入字符串的长度,以跳过这段无用代码
直接改为jmp到原本指令的地址
然后F5
要注意的是这里面还有一处花指令很坑
去除之后,这里就是将我们的函数注册为TLS_CALLBACK函数
¶将文件映射到内存中
继续往下,这里的reason是TLS_CALLBACK函数的第二个参数,因为还处于主线程,所以是1,所以不会进入这里的if
先在注册的TLS_CALLBACK第二个函数下断点,然后F9
¶Hook掉WriteFile
可以看到这里是遍历,然后只要地址等于WriteFile就将final函数的地址赋值过去,实现Hook
Hook之后ExitProcess
所以不会进入到main函数中
¶第二次进入TLS_CALLBACK函数
此时第二个参数变成了0,进入第二段
加载资源文件
加载EXERES文件,然后xor_0x5F后创建tmp文件
注意这里的WriteFile已经被Hook成我们的函数
修改值为6,其他正常写入,我们手动去文件修改
下面这个函数是将取消Hook,也就是将WriteFile函数恢复
在Resources Hacker也可以找到资源文件
CreateProcessA创建新进程,这个新进程运行指定的可执行文件tmp文件,也就是创建子进程
https://baike.baidu.com/item/CreateProcess/11050419
这里的3代表的是新进程会被当做被调试的进程。系统把被调试程序发生的所有调试事件通知给调试器。
此时也可以通过工具查看
¶DEBUG模式
等待调试
¶子进程
去tmp文件查看
注册一个异常处理函数
当出现地址访问异常时,EIP+2
但是这里要注意因为子进程是DEBUG模式,所以优先让调试器也就是父进程处理
因为子进程是调试状态,所以这里要执行,也就是xxtea的常量进行异或,key[1]改为0x90
¶异常地址
此时再去父进程看
而EAX的值恰好是XXTEA的常量经过处理
¶子进程通过文件映射通信
¶xxtea
最后就是xxtea,不过要注意这里的>>5都改成了>>6,也就是前面WirteFile时候改的数值
脚本
1 |
|
剩下的一部分也是xxtea,没魔改就不说了
¶What assembly
¶考点:WASM逆向
https://www.52pojie.cn/thread-962068-1-1.html
https://github.com/WebAssembly/wabt
http://www.dwenzhao.cn/profession/netbuild/webassemblyfunc.html
wasm动态调试
利用python3在与.html
、.js
、.wasm
文件同目录下开启http服务。
1 | python -m http.server 8888 |
然后在浏览器输入http://127.0.0.1:8888/MiniLctf-2022.html
下断点动态调试
¶过程
1 | ./wasm2c flag.wasm -o flag.c |
生成flag.c和flag.h
将之前反编译出来的wasm.c,wasm.h,以及wabt项目内的wasm-rt.h,wasm-rt-impl.c,wasm-rt-impl.h三个文件放到同一个文件夹。
1 | gcc -c flag.c -o final.o |
生成.o文件, 因为很多wasm的函数没有具体的实现,我们不需要编译链接生成elf文件
因为wasm是基于栈的,编译后的C的结构也模拟对栈的操作,所以可以模拟栈进行分析
¶基础指令
https://juejin.cn/post/6844904069186715656
1 | load(memory,a2)//出栈指令 |
¶分析
就一步一步分析
得出最终的加密过程
1 |
|
可以知道第一轮先把key赋值给s的前八个,将flag的前八个字符赋值给s数组,然后进行42轮的加密
求解时只需要逆着进行,每次取出密文的16个字符,因为异或过程就只有异或,但是有先后的关系,比如s[12]已经被重新赋值,再次被使用时就会出错,所以要逆着来
¶脚本
1 |
|
¶NotRC4
¶考点:RISV架构
使用readelf可以知道是RISV架构
¶过程
ida无法反编译,jeb可以反编译但是效果不太好,最好的还是Ghidra
就是一个VM题
分析完大概就是这样
1 |
|
脚本
1 | for (int i = 0; i < 4; i += 2) |