ISCC2021 LOCKK题解
程序运行
输入ISCC{123},点击ENCRYPT实现加密
点击DERYPT,发现得到一个假flag:
静态分析
JEB静态分析APK
JEB打开APK,onClick函数运行时,框内默认为空,点击解密按钮就会出现x函数中的fakeflag,点击加密按钮则会显示y函数中的加密结果。
观察SecureUtil函数,发现是先调用native层的encryptdata函数,再Base64加密。
通过翻看Assets文件夹可以猜测,flag的加密结果放在了log文件中,为:
j9lXGz/eWs4iODrHgTbQZdtXl1RjO82FQhSADajx1vRNnw2NIASP/2mySb2Dqmgh
IDA静态分析so
寻找encryptData函数
将armeabi-v7a文件夹(另一个文件夹下的so文件IDA反编译结果会和下图示例不同)下的so库拖入IDA中反编译,因为在函数导出列表中并没有找到encryptData函数,说明采用了动态注册的方法,因此找到JNI_OnLoad函数,其包含了简易的反调试信息:
JNI_OnLoad函数中最下面的部分与native注册函数RegisterNatives(env, class, method, numMethods)的格式类似,注意到off_1D004:
双击进入,里面的sub_4B8C就是要找的函数encryptData。
encryptData函数
进入sub_4B8C函数后,第一步是修复函数参数。native函数的前两个参数都为JNIEnv *, jclass,原encryptData的参数类型为context和byte[]对应到jni中应该为jobject和jbyteArray类型,返回值也为jbyteArray类型。
更改参数类型前:
更改参数类型:选中第一行,右击鼠标后,选择Set item type,打开修改框修改 。
jbyteArray __fastcall sub_4B8C(JNIEnv * env, jclass thiz, jobject context, jbyteArray input)
函数参数修复完成后,开始分析程序,可以看出最主要的关键函数为sub_4C3C、sub_5134和sub_5038:
后面主要涉及到的函数,浅蓝色为相比于原始AES的被修改部分:
包签名检查函数sub_4C3C
sub_4C3C中简单修复函数参数、修改变量名称后:
检查部分签名:
检查包名是否为com.iscclockk
初始key生成函数sub_5134
函数输出可以通过动态调试直接得到,可以识别出append函数和md5函数
append函数
可以看到有basic_string::append的信息
md5函数
可发现md5的初始变量魔数
主要的处理函数sub_5038
可以识别sub_5880处为主要加密函数
这里也初始化了16位的iv,基本上这里就可以初步判断出来加密方法。iv为0xDE, 0xAD, 0xBE, 0xEF, 0xCD, 0xDE, 0xAD, 0xBE, 0xEF, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xAA
加密函数sub_5880
key扩展函数sub_558C
首先关注key扩展函数sub_558C:
AES基础知识:https://www.davidwong.fr/blockbreakers/aes.html
一般来说应该Rotword函数实现的功能为将00 01 02 03转换为01 02 03 00,也就是:
0 | 1 | 2 | 3 |
---|---|---|---|
1 | 2 | 3 | 0 |
但是该函数的实现却是:
0 | 1 | 2 | 3 |
---|---|---|---|
0 | 3 | 2 | 1 |
接下来的部分,则是在获取S盒内容,S盒内容采用数论的方法生成:
S盒sub_5970
在sub_5970函数中,可以根据魔数0x63进一步确定该部分可以生成S盒;在函数的最后用到了传入的参数a1,可以通过动态调试来确定v2就是标准的S盒:
轮计算函数sub_56AC
进入sub_56AC函数中,可以看到前面获取S盒内容进行字节替换:
后半部分则是行移位,这里行移位与标准的AES也有不同:
对于原始数据:
0 | 1 | 2 | 3 |
---|---|---|---|
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
标准AES移位后:
0 | 5 | 10 | 15 |
---|---|---|---|
4 | 9 | 14 | 3 |
8 | 13 | 2 | 7 |
12 | 1 | 6 | 11 |
题目中移位后:
0 | 13 | 10 | 7 |
---|---|---|---|
4 | 1 | 14 | 11 |
8 | 5 | 2 | 15 |
12 | 9 | 6 | 3 |
之后根据Rotword和ShiftRows步骤的修改,相应改变AES解密代码,可得到结果。
动态分析
IDA pro attach进程
步骤可参考博客:https://blog.csdn.net/LJFYYJ/article/details/1259768502
在右侧的Modules模块中可以找到加载后的libLibs.so库。
双击进入后,可以方便的查看到我们想看的函数。但是因为我们最关心的函数不是导出函数,没法在这里直接看到,所以需要计算偏移地址才能找到。
调试得到所有subkeys
首先在IDA静态分析窗口继续分析:
- 初始key生成函数sub_5134,先生成初始密钥
- 初始密钥由key扩展函数sub_558C,生成每轮的密钥
- 每轮的密钥在轮计算函数sub_56AC中用到
在sub_56AC中可以看出所有的轮密钥存储在byte_1D0AC中:
为了看某行的偏移地址,可以按下图所示使几个窗口同步,这样在Pseudocode-B窗口选择的某行地址会在IDA View-A窗口中自动高亮。