首页
社区
课程
招聘
[原创]某app c++层3处魔改md5详解
发表于: 2023-11-17 23:55 8229

[原创]某app c++层3处魔改md5详解

2023-11-17 23:55
8229

hello everybody,本期是安卓逆向so层魔改md5教学,干货满满,可以细细品味,重点介绍的是so层魔改md5的处理.

常见的魔改md5有:

        1:明文加密前处理 2:改初始化魔数 3:改k表中的值 4:改循环左移的次数  本期遇到的是124.且循环左移的次数是动态的,需要前面的加密结果处理生成

目录

首先介绍md5的实现

说明:

登陆抓包:

sign的加密

总结:


1首先对明文16进制编码,比如我的名字 杨如画 会被编码成 e6 9d a8 e5 a6 82 e7 94 bb

2把明文填充到448bit(比如e6是两个16进制字符,也就是一个字节,8bit),填充方式是先填充一个80,接着一直填充00 00 00直到448bit,

填充成这样e6 9d a8 e5 a6 82 e7 94 bb 80 00 00 00...(56个字节,448bit)

3附加消息长度,需要填充8个字节,也就是e6 9d a8 e5 a6 82 e7 94 bb的长度9个字节,72位,长度就是72,转成16进制就是48,理论上填充的长度为48 也就是

00 00 00 00 00 00 00 48,但是md5处理的时候需要把这8个字节转为小端序,什么是小端续呢?你可以上网查,我简单说一下这里的小端序就是把这8个字节,注意是以字节为单位把最后一个放到第二个,倒数第二个放到第二个,以此类推,最终结果是48 00 00 00 00 00 00 00.  md5的输入长度是无限长的,如果64bit位放不下,也就是长度大于2的64次方的话,会取低64bit,也是按照小端序来取的.  此外sha3算法也是明文无限长,其他hash算法不是.

4最终明文处理成e6 9d a8 e5 a6 82 e7 94 bb 80 00 00 00...48 00 00 00 00 00 00 00,一共512bit,如果输入的数据刚好为448bit,那么就需要填充512bit,再加上附加消息长度64bit,一共1024bit,因为md5的分组长度为512bit,所以需要进行分组处理

至于k表和初始化魔数和循环左移我们待会再说,先对md5的明文处理有一个概念,注意这很重要,后续需要用到.

概念介绍完了,我们来实战吧

设备: pixel4 XL android10

抓包:charles配合socksdroid

下载地址:aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzMwNjM5OS9oaXN0b3J5X3YzNjA=

frida版本:16.0.1

此版本是旧版本,新版本算法并没有改,流程也大致差不多,复杂的话可以frida trace,后续也会介绍到,事实上这也是我为了逆这个算法现学的,介绍一下背景,我是学了frida rpc接触到了这个app,当时逆登陆的时候有个sign,当时用的是rpc,因为rpc需要开着手机,我想着能不能逆向出完整的算法呢?这期间遇到了非常大的挑战,因为很多frida的api我也不太熟悉,我也是现学现用,后续会一一介绍,整个魔改md5耗时3天.

1 查询参数没什么特别的,重点看表单,username是手机号,密码加密了,还有一个用作验签的sign,这个sign的作用我之前说过很多次了,他是用来验签的,通常是把查询参数或者表单中的参数除sign之外的其他值拼接起来加密,防止数据包被恶意篡改,当然也不是不能篡改,把这个sign逆了不就行了吗

2 password的我就不说了,在java层,我直接给出代码吧  定位可以搜字符串,hook java层系统函数等等

3 定位我也不说了,搜字符串,hook什么hashmap,hashset,stringbuilder之类的你都试试吧,总能找到的,我就贴下面了

4 hook encrypt_data这个native函数,返回的就是sign,直接右键复制为frida片段

5 有java的api 要包在Java.perform里 

6 配合着抓包,点击一下登陆,发现加密的结果与抓包中一样,那铁定是这里了

7 接下来为了避免一直手点登陆,可以进行java层主动调用

8 我建议你采用我这个主动调用,这样最终加密出来的结果会和我的一样,方便你调试

9 接下来我们把libCrypt.so拖到ida32中反编译,Crypt名字在上面的java代码中出现了,只有32位的所以拖到ida32中

10 反编译后搜一下java发现是静态注册,这里名字叫encrypt_1data是因为进行了符号修饰

11 这里直接点进去看内部逻辑

12 转换一下JNIEnv对象,ida7.5以后可以不用导头文件,直接改类型

13 看到NewStringUTF,第一个参数是JNIEnv,第二个参数是CString,这里是把CString转为JString再返回给java层,所以最终加密的结果就是v12

14 这里可以hook 1B88这个函数,这种没有名字的通常后面就是偏移量,不放心的话可以点进去看看,加上so基值就可以得到函数内存地址了,这是arm指令的,如果是thubm指令的就得+1,如果你不会看arm还是thumb指令就看so是32还是64,32的一般是thumb,64的一般是arm指令

15 接下来hook sub_1B88这个函数,这是修改过后的,一开始你不知道哪些是地址就把所有参数打印一遍,是地址再dump,因为你dump数字的话是会报错的

16这里开着两个hook脚本,java层主动调用,分析so的结果,后面这张图我就不贴了,就是java层的主动调用

17 我们可以看到结果在arg6中,也就是第7个参数,证明结果确实来自v12

18 而arg2就是我们从java层传进的第二个明文参数,只有这个是重要的,其他不重要的就不要输出,影响判断 

19 接下来我们从1B88点进去看看,点进去后发现这里面调用了很多函数,我是把这些函数都hook了一般,但是感觉很乱,有好几个函数被调用了好几次,有的函数内部有if判断还有嵌套函数,极大影响我们的思路,这里可以使用frida trace工具来帮我们分析调用流程

20 frida trace是github上的一个工具,可以自行去下载解压后放到ida的plugis目录下,重启ida 

21 这里还有几个好用的ida插件signsrch,findhash,可以识别一些加密特征来判断是什么加密. 这里直接点一下traceNatives会生成一条命令,终端执行一下 

22 接下来主动调用一下java层的函数,它会给我们打印函数调用流程,这样就清晰多了,这里的函数地址默认都加了1,因为这个so是thumb指令的

23 我们上面分析到1B88,后面的函数你可以一一hook,到这里我感觉写的内容有点多了,我怕你们没耐心看完,所以就不带你们一个一个函数hook了

24 这个sub1105就是魔改的md5算法 

25 最终会加密3次md5,每一次md5都是魔改的,共同的魔改是这里传进去的都是md5 update的字节,而且这个字节你实现的话必须要魔改原本的md5算法.除此以外,第一次还魔改了循环左移,第二次还魔改了初始化魔数和循环左移,并且初始化魔数并不是固定的,而是由第一次加密的md5结果处理生成的,第三次加密的字节需要由第二次加密的结果提供,也就是说,最终的加密结果需要依靠前两次加密的

26 说完了这些我们直接开始hook,下面的代码是简化后的,略去了无效的输出,方便阅读

27 这里我结合ida中的代码分析a1和a2,a3是什么

28 选中a1,发现它一直在被32减去它的一个值并赋值给另一个值,而复制的值参与了64轮加密


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (3)
雪    币: 2564
活跃值: (1661)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
2023-11-18 00:01
2
雪    币: 313
活跃值: (2362)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很详细,收藏有朝一日再看
2023-11-20 09:48
1
雪    币: 2564
活跃值: (1661)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
执念成狂 很详细,收藏有朝一日再看
csdn看会更清晰一点,复制过来压缩了
https://blog.csdn.net/xmx_000/article/details/134466398
2023-11-28 14:21
0
游客
登录 | 注册 方可回帖
返回
//