SBCTF2024
Last updated on February 5, 2024 am
SBCTF2024 Reverse wp
Week1
babymath
z3一把梭
1 |
|
simple
简单的字节码阅读,是个经典的TEA算法加密,不过需要注意的是这里的运算都是有符号的
1 |
|
1 |
|
babysmc
ESP定律脱壳,然后简单SMC,下断点在函数处,然后使用p
让IDA重新分析为函数
1 |
|
babyhash
题目先要求输入6个key,并要求为小写字符
![](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.29.10.png)
然后与字符串12345
进行拼接操作
![](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.33.08.png)
然后进行一系列操作,每个函数都有很多个调用,直接从最后面的比较看起
![截屏2024-01-19 02.35.43](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.35.43.png)
跟入sub_7FF618207E04
,然后一直跟入到sub_7FF6182175F0
![截屏2024-01-19 02.38.50](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.38.50.png)
其中函数sub_7FF6182061FD
最终只是调用memcmp
函数进行比较,因此这里就是输入的key和正确的key进行比较的地方,查看比较的两个参数
a1 是输入的密文 6d6eaa76a827ebae246617c27107c8dd
a3 是真正的密文 f27d71f53ae17679fb352baa5ea326db
这两个看起来很像是hash后的值,结合题目信息,用一些md5进行尝试计算
![截屏2024-01-19 02.44.02](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.44.02.png)
发现真正用来md5的是12345aaaaaa67890
,也就是输入的六位key会和12345
以及67890
进行拼接,那么直接进行爆破得到真正的key
1 |
|
在得到key后继续往后审计
![截屏2024-01-19 02.47.07](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.47.07.png)
关键只有两处,sub_7FF618208C4B
这个函数对输入进行加密,72行处的if语句对输入进行判断
查看加密函数,发现就是普通的RC4加密,密钥则是12345maikei67890
![截屏2024-01-19 02.48.45](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.48.45.png)
直接解密即可
![截屏2024-01-19 02.50.19](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2002.50.19.png)
babydecode
题目用到两个反调试手段
第一个是在函数sub_401F7B
中调用Ptrace
函数进行反调试,许多调试器的功能都是基于ptrace
这一个强大的系统调用实现,但是一个进程在同一时间只能被另外一个进程调试,那么这个程序就可以调用ptrace
函数来调试自己,如果失败,说明有进程在调试自己。这一个教程是十分清晰的解释了这个函数使用。
- ptrace PTRACE_ATTACH可以附加到目标进程上,对其进行调试。
- 反调试的方式
跟踪自己:因为,一个进程在同一时间只能被一个进程跟踪。如果进程在启动时,就调用ptrace PTRACE_TRACEME跟踪了自己。那么这个进程将无法被其他进程附加
将两个if条件patch一下就可以绕过
![截屏2024-01-19 16.03.52](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2016.03.52.png)
还有一处反调试是使用sys_alram
这一函数,通过字符串查找很容易到相关地方。
![截屏2024-01-19 16.12.46](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2016.12.46.png)
这里绕过方式也很多,可以修改时间,或者直接nop掉函数。
完成patch后就可以正常调试。
整体加密流程也很简单,先是正常TEA算法加密,然后进行一个BASE64的变表处理,然后用所得Base64加密后在一个新表里面找索引,最终的索引为密文
![截屏2024-01-19 16.15.06](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2016.15.06.png)
现在中间变量都可以通过调试正常正确拿到
得到Base加密
1 |
|
得到TEA加密
![截屏2024-01-19 16.17.54](https://yring-me.oss-cn-beijing.aliyuncs.com/test/%E6%88%AA%E5%B1%8F2024-01-19%2016.17.54.png)
最终解密
1 |
|
Week2
start_main
程序逻辑很简单,输入36位的flag然后经过一个变表的base64解码,然后再经过一个RC4解密,通过调试可以拿到变表RSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQ
和RC4密钥lFaUmVp=
,其中用变表可以解RC4密钥为SBCTF
不过奇怪的是并没有看到密文比较的地方,先运行看看
是有错误的输出提示的,但是直接搜这个字符串却搜不到,看来是做了一点加密。不过这也告诉我们一个东西,即在main函数运行完后还有函数在运行,这实际上就是fini_array
了。
简单说main
函数并不是第一个运行的函数,第一个运行的函数应该是start
,然后调用_libc_start_main
,_libc_start_main
再调用main
函数,并且在main
函数开始前运行init_array
里面的函数,main
函数结束后运行fini_array
里面的函数。
因此只需转过去看看fini_array
有函数即可,在IDA中按shift+F7
即可打开段窗口,在里面就有fini_array
地址
发现一个函数sub_55934E697E47
,跟过去看看
这就是很明显的比较流程了,这里俩函数就是解密失败成功字符串的。至此整题的流程就清楚了,当然init_array
也有一个函数,那个函数就是起到一个变表的作用。除了这种方式找之外,也可以直接搜索输入的引用,同样能够找到这个地方
最后的base解码就是猜测了,因为输入的字符会进行一个解码,那么猜测输入的字符串也应该是经过base加密的。
ez_ptrace
程序逻辑也很简单
函数sub_124D
写了一个文件son
,然后子进程使用调用excel
执行这个文件,父进程收到消息然后发出信号,父子进程函数也很简单。
父进程:
子进程:
具体流程如下
- sub_124d 写文件
- fork一个子进程
- 父进程执行
wait
函数等待子进程信号- 子进程执行
ptrace()
函数,参数为PTRACE_TRACEME
,表示希望得到调试,然后调用execl
函数,将刚刚的写好的son
文件进行运行,并替换当前的进程,这个操作回向父进程发送信号- 父进程收到信号,使用
ptrace
函数修改子进程内存中的一个值,然后向子进程发送继续运行信号- 父进程等待子进程退出
所以这里面的关键就是找到这个son
文件,有挺多方法可以得到这个son
文件。
第一个思路是既然父进程中写了文件,但是程序运行起来却看不到这个文件,说明调用了文件删除函数,这个函数需要一个文件路径的参数,那么把文件名字改一下,让文件删除函数无法删除即可
比如修改写文件的名字,或者找一下子进程里面的字符串,也比较好找。
第二个思路就是对程序下断点,先不让子进程运行excel
函数,或者在父进程发送继续运行处下断点。
第三个思路就是手动提取,这里简单用个idapython脚本即可
1 |
|
总之现在得到了son
文件,打开看看
函数流程也很简单,输入32位flag,然后sub_6000131
对输入进行4位一组的合并,变成一个32位的整型,然后丢进sub_600011ED
进行加密
这个加密算法的逆运算也很好搓,但这个时候还有一个地方需要注意,父进程调用了ptrace
函数修改了一个值,我们需要找到这个地方,修改地址是dword_4c64
而dword_4c64
是6000404c
,这个是RVA,还需要转换为FOA,即文件偏移,这里应该就是404c
在子文件中找到这个地方,发现是把密钥最后一个给改了
1 |
|
happydebug
用了很多IsDebugpresent
来进行反调试,逐一patch掉,其中还有一个TLS函数,TLS会先于main
函数运行
然后在主函数下断点调试,发现断不下来,而且会有错误输出,那么就肯定还有反调试手段。继续找,发现第二个TLS函数
发现这里的逻辑与主函数基本相同,不过对一些字符串进行了加密,防止直接搜索,看来这里才是真正程序逻辑的地方,通过搜索字符串找的函数是虚假的,即使通过手撕也无法解出flag。
加密很简单,前面的for循环都是对密钥做处理,与输入无关直接跳到sub_7FF79c22112c
,这个函数就是个简单的TEA加密
1 |
|
Week3
babymath
pyinstaller打包,解包然后pycdc反编译
1 |
|
简单迷宫题
1 |
|
八色三月七
题目逻辑倒很简单,不过挺烦这个中文编码的(这题中文编码是 GB21312)
输入字符串然后进行Base编码,再输出编码后结果
容易找到码表是这个东西,转化为中文就是一二三四五六七八
编码过程跟base64差不多,同样按照3个字节24bit为一个加密组,然后在24位里面再分6bit
一组,由于码表只有8个汉字,于是6bit
再分高3个bit和低3个bit来进行索引。这里面D4C2
是月
的中文编码,没有起到什么作用,解密直接丢掉就好。所以一个组输入24bit会被加密成8个汉字,每3个bit对应一个汉字
1 |
|
中文也差不多
so many flowers
如题目所言,确实有很多花指令,不再简单局限于jz jnz
了,需要稍微分析下
main函数第一处花指令,先push
了eax
的值然后清零eax
,那么这个jz
跳转就一定会实现,前面push
后面也应该会有相应的pop
patch后如下,那么这两个push
和pop
也一起patch
掉
这一组花指令最终是这样
main
函数第二组花指令在下面不远处,这里是用了call $+5
,即跳到当前指令下一条指令执行。这里需要对call
和retn
熟悉,call
指令在会把下一条指令地址压栈,然后jmp
去相应地址执行,
简单分析下就知道这三条指令没有任何用处,全部nop
掉即可
main函数最后一处花指令在下面的jmp
处,也很明显,patch掉
最后main
函数反汇编如下
显然sub_411203
比较关键,不断跟进去
与前面的花指令差不多,不过稍微绕了一点点,简单分析下。先把eax
压栈,然后给eax
赋值为4,再eax = eax * eax
,然后与0x100
比较,然后返回,这时会返回去mul eax
处,再eax = eax * eax
现在下面那条jz
指令就会执行,因此patch
如下
反汇编如下
发现就是个把输入4字节一组转为32位整形的操作,加密应该还在后面,接着往下看
不断跟入sub_41126c
一进去就有明显的爆红,因此查看下sub_4113d9
继续跟,关健在这三条汇编,这实际上就是把返回地址给+1了
patch如下,会多出一个字节,按c
让IDA重新识别为代码,然后按p
分析为函数即可
简单的XXTEA而已
1 |
|