easy_firmware
描述:世界上最简单的固件逆向
0x00 Daily Shell Check
喜闻乐见的stm32,关于IDA怎么加载不再赘述,arm32小端序,根据开始几个函数地址判断基地址是 0x8000000,然后全选分析即可
0x01 Find data
首先可以通过字符串比较容易的分析整个加密,只是对我们的输入进行了AES加密
那么,密钥和密文呢…当时做这题的估计所有人都卡这个步骤了,这个内存 0x20000024 到底是什么数值,毕竟又运行不起来,因为qemu只对stm32的部分板子支持,所以该怎么拿到这个值呢?
于是就整个文件乱翻,在结尾处找到神秘数据,就是这段了,可以从上图可知密钥和密文在内存中连续的,那么也可以得知肯定又哪个函数调用了这些数据,把他们加载到了内存,于是尝试对所有数据进行交叉引用,发现是引用不到的,因为ida没把一个关键函数分析出来,我们可以搜索整个文件看哪里引用了这个地址
1 | start = 0x8000000 |
于是可以找到这个真正的main函数?在这里初始化了这些数据到内存,然后跳到了可以从字符串分析的sub_80000F4函数
然后可以稍微审计一下就可以知道是怎么加载数据的了
当然还有一个好用的插件,不过用unicorn来模拟一样,不过这个插件挺方便的
于是得到我们所需的内存数据
0x02 GetFlag
于是数据有了,就是我们喜闻乐见的解密环节,然后AES ECB解密失败,因为魔改了,然后掏出祖传AES解密脚本
而这次魔改的点其实就一处也很明显,但最恶心的就是用了强制转换成了 int 类型,这里用bn更好看
注意这里的加密我本来以为只是个循环右移,但这里用了 int 类型,于是变得奇怪了起来,总结来说
就是需要注意 (arg1 >> 0x1f),这里进行算数右移31了一个int32的数据,于是只会出现两个值
- 如果是正数:即最高位为0,右移31位也是0
- 如果是负数:即最高位1,右移31位后就是-1,十六进制为 0xFFFFFFFF
也就是这样
1 | int32_t num = 0xF2345678; |
那么搞清楚这个,就比较容易的写处逆向脚本
1 | static void InvCipher(state_t* state, const uint8_t* RoundKey) |
Get Flag!
Keygen
0x00 Daily Shell Check
apk逆向,无shell
0x01 Native Time
Java层什么东西没有,就是把我们输入的调用到了so层,烂活,套了个魔改ollvm直接分析就行
而且界面的文本框没有按钮,根本不知道check怎么触发
如果要调试so要注意,用MT管理器或者修改重新打包把AndroidManifest.xml中的android:extractNativeLibs改成true,如果是false,则它从自身的base.apk加载so,所以在ida中调试不会出现你想要的so
当然也可以审计分析流程
- Java_com_qwctf_keygen_MainActivity_start(pthread_create起了个线程函数sub_4D8C来处理我们的输入)
- sub_4D8C函数把输入分成了三部分,第一部分是flag{ 第二三个部分是输入的两个部分 第四个部分是}
- 同时明文全都给加密了, sub_185C解密了我们所需要的数据第一个参数是key,第二个参数是key的长度,三四就是密文和长度
- sub_55E4和另一个函数分别加密了我们明文的两个部分,不过都一样,无魔改RC4和无魔改AES,直接解密即可,拿到密钥直接加密即可
至此整个流程分析完毕,其实这题就是个非常常见的加密流程,运行解密字符串,进行验证然后再把字符串解密回去,但由于ollvm不想分析加上出题人不知道怎么写的界面导致无法触发check函数,于是做的很慢,最后还是硬分析完了
0x02 GetFlag
1 | key1: 0x21, 0xCF, 0xCC, 0x68, 0xEA, 0xC5, 0x0A, 0x87, 0xFA, 0x60, 0xDB, 0x52, 0x99, 0xD4, 0xDC, 0x1B |
1 | from Crypto.Cipher import AES |
Get Flag!
About this Post
This post is written by P.Z, licensed under CC BY-NC 4.0.