首页
论坛
课程
招聘
[原创]记一次历史悠久的dymas算法的还原过程
2020-4-17 15:19 3976

[原创]记一次历史悠久的dymas算法的还原过程

2020-4-17 15:19
3976

libcms.so中查找Jni_OnLoad函数,


查看off_70004地址,函数的关键注册位置.


用frida打印byte_70086的字符串,最后得到e([B)[B的地址为0x208c9, 点进去,并按f5


这部分是mas算法的初始化步骤,大概流程如下, 传入的as数组扩充5位, 假设ptr = 0x7A218492 那么mas[0] = 0x1, mas [1] = 0x92 mas [2]=84  mas [3]=0x20 as[4] = 0x02, 仔细观察 sub_ 208c9函数,发现并没有加密逻辑,可以确定是在别的函数进行加密, 经过查找,确定了关键位置为sub_2087E,


具体流程如下:

1、_rbit mas[1]-mas[16], 然后把结果进行反序存放到mas中

2、调用sub_1EB64函数对16为字符进行加密,还原的代码如下:

uint data_i[4];
for(int i = 0; i < 4; i++){
    data_i[i] = encrypt_3(mas + 1 + i * 4);
}
// case 3
for(int i = 0; i < 32; i++){
    data_i[i % 4] = sub_20224(data_i[(i + 1) % 4] ^ data_i[(i + 2) % 4] ^ key[i] ^ data_i[(i + 3) % 4]) ^ data_i[i % 4];
}

sub_1EB64 经过了ollvm, 可以在关键块下断点,把结果记录下来,然后根据结果推导出算法,断点的关键块如下:


3:把2的结果,经过case4进行加密,具体算法如下:

uint test(uint r0){
    uint r1 = 0xAAAAAAAA;
    uint r2 = 0x55555555;
    r1 = r1 & (r0 << 1);
    r0 = r2 & (r0 >> 1);
    r0 = r0 | r1;
    r1 = 0xCCCCCCCC;
    r2 = 0x33333333;
    r1 = r1 & (r0 << 2);
    r0 = r2 & (r0 >> 2);
    r0 |= r1;
    r1 = 0xF0F0F0F0;
    r2 = 0x0F0F0F0F;
    r1 = r1 & (r0 << 4);
    r0 = r2 & (r0 >> 4);
    return r0 | r1;
}

4: 把2的结果使用sub_1f6b0函数进行加密, sub_1f6f0算法也是根据动态调试在关键快下断记录过程,然后推到出算法。 其中算法实现为:

uint sub_1F6B0(uint i){
    //0xF02962CF
    // 0:0x00000000 + 0xcf = 0x000000cf << 4 = 0x00000cf0
    // 1:0x00000cf0 + 0x62 = 0x00000d52 << 4 = 0x0000d520
    // 2:0x0000d520 + 0x29 = 0x0000D549? << 4 = 0x00xD5490
    // 3:0x000D5490 + 0xf0 = 0x000D5580
    uchar *c_arr = (uchar *)&i;
    uint temp = c_arr[0];
    for(int i = 1; i < 4; i++){
        temp = (temp << 4) + c_arr[i];
    }
    return temp;
}
5:同3
6:把2的结果经过sub_1F4D0加密
uint sub_1F4D0(uint i){
//    0x4E781CDB
//
//    0x00000000 << 0x00000007 = 0x00000000
//    0x00000000 ^  0x000000db = 0x000000db
//    0x00000000 >> 0x00000003 = 0x00000000
//    0x000000db ^  0x00000000 = 0x000000db
//    0x00000000 ^  0x000000db = 0x000000db
//
//    0x000000db << 0x0000000B = 0x0006D800
//    0x0006D800 ^  0x0000001c = 0x0006D81C
//    0x000000db >> 0x00000005 = 0x00000006
//    0x0006D81C ^  0x00000006 = 0x0006D81A
//    0x0006D81A  ^ 0xFFFFFFFF = 0xFFF927E5
//    0x000000DB ^  0xFFF927E5 = 0xFFF9273E
//
//    0xFFF9273E << 0x00000007 = 0xFC939F00
//    0xFC939F00  ^ 0x00000078 = 0xFC939F78
//    0xFFF9273E >> 0x00000003 = 0x1FFF24E7
//    0xFC939F78  ^ 0x1FFF24E7 = 0xE36CBB9F
//    0xFFF9273E  ^ 0xE36CBB9F = 0x1C959CA1
//
//    0x1C959CA1 << 0x0000000B = 0xACE50800
//    0xACE50800  ^ 0x0000004E = 0xACE5084E
//    0x1C959CA1 >> 0x00000005 = 0x00E4ACE5
//    0xACE5084E  ^ 0x00E4ACE5 = 0xAC01A4AB
//    0xAC01A4AB  ^ 0xFFFFFFFF = 0x53FE5B54
//    0x1C959CA1  ^ 0x53FE5B54 = 0x4F6BC7F5


    uchar *c_arr = (uchar *)&i;
    uint temp = 0;
    uint v1, v2, v3, v4, v5;
    for(int i = 0; i < 4; i++){
        switch (i & 1){
            case 0:
                v1 = temp << 7;
                v2 = c_arr[i] ^ v1;
                v3 = temp >> 3;
                v4 = v2 ^ v3;
                temp = temp ^ v4;
                break;
            case 1:
                v1 = temp << 0xb;
                v2 = v1 ^ c_arr[i];
                v3 = temp >> 5;
                v4 = v2 ^ v3;
                v5 = v4 ^ 0xffffffff;
                temp = temp ^ v5;
                break;
        }
    }
    return temp & 0x7fffffff;
}
7:同3
8:把2的结果进行sub_1F2E4加密。
uint sub_1F2E4(uint i){
    //0x4E67C6A7 << 0x00000005 = 0xCCF8D4E0
    //0xCCF8D4E0 +  0x000000i[index] = 0xCCF8D522
    //0x4E67C6A7 >> 0x00000002 = 0x1399F1A9
    //0xCCF8D522 +  0x1399F1A9 = 0xE092C6CB
    //0x4E67C6A7 ^  0xE092C6CB = 0xAEF5006C
    //
    //0xAEF5006C << 0x00000005 = xxxxxxxxxx
    //0xC51E9B60
    uchar *c_arr = (uchar *)&i;
    uint temp = 0x4E67C6A7;
    for(int i = 0; i < 4; i++){
        uint v1 = temp << 5;
        uint v2 = v1 + c_arr[i];
        uint v3 = temp >> 2;
        uint v4 = v2 + v3;
        temp ^= v4;
    }
    return temp;
}
9:同3

10:对3、5、7、9的结果进行异或。

11:3-9进行循环


最后对生成的字符串与as的日志相比较, 就能总结出算法。


后记: 入坑android 逆向差不多一年了吧, 这篇笔记是很久以前根据https://bbs.pediy.com/thread-246360.htm 这位大佬的心得所写的,考虑到mas算法现在已经没用,把它分享出来给需要的人学习吧,文档写的拉闸望各位大佬轻喷,不甚感激。


【公告】 [2022大礼包]《看雪论坛精华22期》发布!收录近1000余篇精华优秀文章!

最后于 2020-4-18 12:59 被hczhong编辑 ,原因: 重新上传图片
收藏
点赞0
打赏
分享
最新回复 (5)
雪    币: 4863
活跃值: 活跃值 (982)
能力值: (RANK:30 )
在线值:
发帖
回帖
粉丝
CCkicker 活跃值 2020-4-17 16:18
2
0
图片没过来,lz重新再上传一下图片啊
雪    币: 11576
活跃值: 活跃值 (2922)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
LowRebSwrd 活跃值 4 2020-4-18 09:15
3
0
图片看不到
雪    币: 1470
活跃值: 活跃值 (2289)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
hczhong 活跃值 2020-4-18 12:59
4
0
重新上传了
雪    币: 198
活跃值: 活跃值 (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lwykj 活跃值 2020-4-21 01:45
5
0
不错的分享,
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
拒绝平凡8 活跃值 2020-4-21 09:31
6
0
学习了。
游客
登录 | 注册 方可回帖
返回