分析样例下载:链接: https://pan.baidu.com/s/1qxkYqMovR8Fe6sO-Zr-8ow 密码: dh7g

第一题algorithmbase_32

直接ida打开找到encodeFromJni_32函数。然后F5后。发现是ollvm混淆的。然后大概的分析一下。我的分析思路是。首先是大概的翻一下参数较多的那些函数,看看是否有什么比较眼熟的函数。果然很快锁定了一个函数sub_1D920。下面贴上交为眼熟的部分

image-20210109220431469

我圈出来的这几个特征和我们之前分析过的md5的特征高度的相似。v10的那些明显就是MD5的那个key。而下面是拼接的三段固定数据再加上我们的输入值。所以我们先看看那三段数据分别是什么

image-20210109220926171

点开后发现字符串被加密了。所以我们用之前研究的解ollvm字符串混淆的工具unidbg或者是AndroidNativeEmu来生成一个解密的so跑一下。下面贴上解完之后的结果

image-20210109221223706

然后点进去看看字符串。

image-20210109221252596

知道是什么值拼接的之后。然后就简单了。先看看输出和输出的值。

1
rRZrALoUFxTqxDCJHjT -> ea8caf7e47b8404d81de797995d6c3cc

然后我们拼接kanxue+imyang+ollvm_md5+输入数据来MD5看看是否一致

image-20210109222044810

结果和上面的一致。第一题搞定

=======================================================================================================

第二题algorithmbase_32_2

直接ida开始分析。找到encodeFromJni_32函数。由于上一个例子翻到了关键函数。直接找类似的函数。定位到了sub_1D48C。

image-20210109222513629

看着和之前的差不多的。然后看看前面固定拼接了些什么

image-20210109222606117

发现也是字符串混淆加密的。老办法。上unidbg或者是AndroidNativeEmu来生成一个解密的so。

image-20210109222824334

解密后看到依然还是这几个值。我们跑的测试一下看是否计算的值一致了。先获取一个手机上的输入和输出

1
cPKpWAMuRxJVSJORW -> ec184c0980693ef670486feb407b6031

看下面的图。发现结果不是一致的

image-20210109224758535

所以我们还得检查。key是否发生了变化。静态分析上面看。是没有什么变化。我们需要动态调试的情况下看看拼接完数据后。最后调用sub_1CDFC函数的时候v11的值是否已经变了。为了方便调试。我先用unidbg成功把这个函数跑通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

public class lianxi32 {
public static void main(String[] args) {
lianxi32 lianxi = new lianxi32();
lianxi.Call_EncodeFromJni_32();
}
private final AndroidEmulator emulator;
private final VM vm;
private DvmClass Clazz;
private lianxi32() {
emulator = new AndroidARM64Emulator();
Memory memory = emulator.getMemory();
LibraryResolver resolver = new AndroidResolver(23);
memory.setLibraryResolver(resolver);
vm = emulator.createDalvikVM(null);
vm.setVerbose(false);
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/lianxi32_2/libnative-lib.so"), false);
dm.callJNI_OnLoad(emulator);
Clazz = vm.resolveClass("com/kanxue/algorithmbase/MainActivity");
Debugger dbg = emulator.attach();
dbg.addBreakPoint(dm.getModule(), 0x1D63C);
dbg.debug();
}
public void Call_EncodeFromJni_32(){
String res=Clazz.callStaticJniMethodObject(emulator,"encodeFromJni_132(Ljava/lang/String;)Ljava/lang/String;","cPKpWAMuRxJVSJORW").toString();
System.out.print(res);
}
}

断点的位置是函数调用的点。所以要查v11参数。直接打印X1的内存数据就可以了

1
2
0000: 01 23 45 67 00 00 00 00 89 AB CD EF 00 00 00 00    .#Eg............
0010: FE DC BA 98 00 00 00 00 76 54 32 10 00 00 00 00 ........vT2.....

接着我再把上一个案例也跑一下。对比上一个案例的标准

1
2
0000: 01 23 45 67 00 00 00 00 89 AB CD EF 00 00 00 00    .#Eg............
0010: FE DC BA 98 00 00 00 00 76 54 32 10 00 00 00 00 ........vT2.....

结果发现key没有啥区别。猜测可能是MD5的那个table表发生了变化又或者这不是一个MD5。先trace一份分析一下.下面的KingTrace使用了我自己封装的。贴一下相关的代码连接https://github.com/dqzg12300/unidbg.git

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

public class lianxi32 {
public static void main(String[] args) {
lianxi32 lianxi = new lianxi32();
lianxi.Call_EncodeFromJni_32();
}
private final AndroidEmulator emulator;
private final VM vm;
private DvmClass Clazz;
private lianxi32() {
emulator = new AndroidARM64Emulator();
Memory memory = emulator.getMemory();
LibraryResolver resolver = new AndroidResolver(23);
memory.setLibraryResolver(resolver);
vm = emulator.createDalvikVM(null);
vm.setVerbose(false);
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/lianxi32_2/libnative-lib.so"), false);
dm.callJNI_OnLoad(emulator);
Clazz = vm.resolveClass("com/kanxue/algorithmbase/MainActivity");
KingTrace trace=new KingTrace(emulator);
long start=0x400196c8; //0x196c8 0x3bb4
long end=0x400196c8+0x3bb4;
trace.initialize(start,end,null);
emulator.getBackend().hook_add_new(trace,start,end,emulator);
}
public void Call_EncodeFromJni_32(){
String res=Clazz.callStaticJniMethodObject(emulator,"encodeFromJni_132(Ljava/lang/String;)Ljava/lang/String;","cPKpWAMuRxJVSJORW").toString();
System.out.print(res);
}
}

然后我们看一下我们之前github上拿的MD5项目的table表是有哪些数据。然后只保留table的值。去掉其他代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
0xd76aa478
0xe8c7b756
0x242070db
0xc1bdceee
0xf57c0faf
0x4787c62a
0xa8304613
0xfd469501
0x698098d8
0x8b44f7af
0xffff5bb1
0x895cd7be
0x6b901122
0xfd987193
0xa679438e
0x49b40821
0xf61e2562
0xc040b340
0x265e5a51
0xe9b6c7aa
0xd62f105d
0x2441453
0xd8a1e681
0xe7d3fbc8
0x21e1cde6
0xc33707d6
0xf4d50d87
0x455a14ed
0xa9e3e905
0xfcefa3f8
0x676f02d9
0x8d2a4c8a
0xfffa3942
0x8771f681
0x6d9d6122
0xfde5380c
0xa4beea44
0x4bdecfa9
0xf6bb4b60
0xbebfbc70
0x289b7ec6
0xeaa127fa
0xd4ef3085
0x4881d05
0xd9d4d039
0xe6db99e5
0x1fa27cf8
0xc4ac5665
0xf4292244
0x432aff97
0xab9423a7
0xfc93a039
0x655b59c3
0x8f0ccc92
0xffeff47d
0x85845dd1
0x6fa87e4f
0xfe2ce6e0
0xa3014314
0x4e0811a1
0xf7537e82
0xbd3af235
0x2ad7d2bb
0xeb86d391

在trace记录里面查询一下。能够找的值的索引说明没有被修改。

1
2
"[libnative-lib.so] [0x19fa8] [ 40 ed ba 72 ] 0x40019fa8: movk w0, #0xd76a, lsl #16-----w0=0xa478        //w0=0xd76aa478"
"[libnative-lib.so] [0x19fc4] [ e0 18 bd 72 ] 0x40019fc4: movk w0, #0xe8c7, lsl #16-----w0=0xb756 //w0=0xe8c7b756"

写个简单的脚本检查一下trace中缺少了哪一个table的值

1
2
3
4
5
6
7
8
9
10
if __name__ == '__main__':
with open("./traces.log", "r+") as tracefile:
traces=tracefile.read()
with open("./md5table.txt","r+") as md5file:
table= md5file.read()
tableSp=table.split("\n")
for i in range(len(tableSp)):
if tableSp[i] in traces:
continue
print(tableSp[i])

最后打印出下面的两个值。这两个被改动了。然后看看这两个的索引位置分别在9和26的位置。

1
2
0x698098d8
0xc33707d6

接下来把traces拿出来搜索一下movk w。过滤后然后在里面搜索到table中的索引8的值0xfd469501在哪里。然后把往后的30条记录全部拿出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"[libnative-lib.so] [0x1a4ac] [ ca a8 bf 72 ] 0x4001a4ac: movk w10, #0xfd46, lsl #16-----w10=0x9501        //w10=0xfd469501"
"[libnative-lib.so] [0x1a584] [ 0a 33 ad 72 ] 0x4001a584: movk w10, #0x6998, lsl #16-----w10=0x80d8 //w10=0x699880d8"
"[libnative-lib.so] [0x1a670] [ 8e 68 b1 72 ] 0x4001a670: movk w14, #0x8b44, lsl #16-----w14=0xf7af //w14=0x8b44f7af"
"[libnative-lib.so] [0x1a6f8] [ fe 87 b3 72 ] 0x4001a6f8: movk w30, #0x9c3f, lsl #16-----w30=0x4e9d //w30=0x9c3f4e9d"
"[libnative-lib.so] [0x1a6fc] [ a6 23 b1 72 ] 0x4001a6fc: movk w6, #0x891d, lsl #16-----w6=0xdfce //w6=0x891ddfce"
"[libnative-lib.so] [0x1a700] [ e3 54 bb 72 ] 0x4001a700: movk w3, #0xdaa7, lsl #16-----w3=0xe993 //w3=0xdaa7e993"
"[libnative-lib.so] [0x1a704] [ 59 8c b1 72 ] 0x4001a704: movk w25, #0x8c62, lsl #16-----w25=0x3405 //w25=0x8c623405"
"[libnative-lib.so] [0x1a708] [ 82 8e be 72 ] 0x4001a708: movk w2, #0xf474, lsl #16-----w2=0x1363 //w2=0xf4741363"
"[libnative-lib.so] [0x1a70c] [ 89 8e be 72 ] 0x4001a70c: movk w9, #0xf474, lsl #16-----w9=0x1363 //w9=0xf4741363"
"[libnative-lib.so] [0x1aa84] [ 0a b3 bf 72 ] 0x4001aa84: movk w10, #0xfd98, lsl #16-----w10=0x7193 //w10=0xfd987193"
"[libnative-lib.so] [0x1aa9c] [ 8a 2b b1 72 ] 0x4001aa9c: movk w10, #0x895c, lsl #16-----w10=0xd7be //w10=0x895cd7be"
"[libnative-lib.so] [0x1aae4] [ 0a 72 ad 72 ] 0x4001aae4: movk w10, #0x6b90, lsl #16-----w10=0x1122 //w10=0x6b901122"
"[libnative-lib.so] [0x1ab9c] [ 2a cf b4 72 ] 0x4001ab9c: movk w10, #0xa679, lsl #16-----w10=0x438e //w10=0xa679438e"
"[libnative-lib.so] [0x1ac10] [ 89 36 a9 72 ] 0x4001ac10: movk w9, #0x49b4, lsl #16-----w9=0x821 //w9=0x49b40821"
"[libnative-lib.so] [0x1ad04] [ c3 c3 be 72 ] 0x4001ad04: movk w3, #0xf61e, lsl #16-----w3=0x2562 //w3=0xf61e2562"
"[libnative-lib.so] [0x1ae44] [ c0 cb a4 72 ] 0x4001ae44: movk w0, #0x265e, lsl #16-----w0=0x5a51 //w0=0x265e5a51"
"[libnative-lib.so] [0x1ae58] [ 06 08 b8 72 ] 0x4001ae58: movk w6, #0xc040, lsl #16-----w6=0xb340 //w6=0xc040b340"
"[libnative-lib.so] [0x1b02c] [ e0 c5 ba 72 ] 0x4001b02c: movk w0, #0xd62f, lsl #16-----w0=0x105d //w0=0xd62f105d"
"[libnative-lib.so] [0x1b0e8] [ c0 36 bd 72 ] 0x4001b0e8: movk w0, #0xe9b6, lsl #16-----w0=0xc7aa //w0=0xe9b6c7aa"
"[libnative-lib.so] [0x1b1b8] [ 2f 14 bb 72 ] 0x4001b1b8: movk w15, #0xd8a1, lsl #16-----w15=0xe681 //w15=0xd8a1e681"
"[libnative-lib.so] [0x1b264] [ 8f 48 a0 72 ] 0x4001b264: movk w15, #0x244, lsl #16-----w15=0x1453 //w15=0x2441453"
"[libnative-lib.so] [0x1b400] [ 6a fa bc 72 ] 0x4001b400: movk w10, #0xe7d3, lsl #16-----w10=0xfbc8 //w10=0xe7d3fbc8"
"[libnative-lib.so] [0x1b440] [ ef 60 b8 72 ] 0x4001b440: movk w15, #0xc307, lsl #16-----w15=0x37d6 //w15=0xc30737d6"
"[libnative-lib.so] [0x1b454] [ 2f 3c a4 72 ] 0x4001b454: movk w15, #0x21e1, lsl #16-----w15=0xcde6 //w15=0x21e1cde6"
"[libnative-lib.so] [0x1b544] [ a8 9a be 72 ] 0x4001b544: movk w8, #0xf4d5, lsl #16-----w8=0xd87 //w8=0xf4d50d87"
"[libnative-lib.so] [0x1b6f8] [ 4a ab a8 72 ] 0x4001b6f8: movk w10, #0x455a, lsl #16-----w10=0x14ed //w10=0x455a14ed"
"[libnative-lib.so] [0x1b828] [ 6a 3c b5 72 ] 0x4001b828: movk w10, #0xa9e3, lsl #16-----w10=0xe905 //w10=0xa9e3e905"
"[libnative-lib.so] [0x1b8f4] [ ea 9d bf 72 ] 0x4001b8f4: movk w10, #0xfcef, lsl #16-----w10=0xa3f8 //w10=0xfcefa3f8"
"[libnative-lib.so] [0x1ba48] [ ef ed ac 72 ] 0x4001ba48: movk w15, #0x676f, lsl #16-----w15=0x2d9 //w15=0x676f02d9"
"[libnative-lib.so] [0x1bb30] [ 4a a5 b1 72 ] 0x4001bb30: movk w10, #0x8d2a, lsl #16-----w10=0x4c8a //w10=0x8d2a4c8a"
"[libnative-lib.so] [0x1bc58] [ 4a ff bf 72 ] 0x4001bc58: movk w10, #0xfffa, lsl #16-----w10=0x3942 //w10=0xfffa3942"

接下来对比我们代码中的8 9 10索引的值和trace中的8 9 10的值

1
2
3
4
5
6
7
8
//MD5代码中的
0xfd469501
0x698098d8
0x8b44f7af
//trace记录中的
"[libnative-lib.so] [0x1a4ac] [ ca a8 bf 72 ] 0x4001a4ac: movk w10, #0xfd46, lsl #16-----w10=0x9501 //w10=0xfd469501"
"[libnative-lib.so] [0x1a584] [ 0a 33 ad 72 ] 0x4001a584: movk w10, #0x6998, lsl #16-----w10=0x80d8 //w10=0x699880d8"
"[libnative-lib.so] [0x1a670] [ 8e 68 b1 72 ] 0x4001a670: movk w14, #0x8b44, lsl #16-----w14=0xf7af //w14=0x8b44f7af"

对比出0x698098d8修改成了0x699880d8

继续再对比24 25 26 27 28和trace中的24 25 26 27 28

1
2
3
4
5
6
7
8
9
10
11
12
//MD5代码中的
0xe7d3fbc8
0x21e1cde6
0xc33707d6
0xf4d50d87
0x455a14ed
//trace记录中的
"[libnative-lib.so] [0x1b400] [ 6a fa bc 72 ] 0x4001b400: movk w10, #0xe7d3, lsl #16-----w10=0xfbc8 //w10=0xe7d3fbc8"
"[libnative-lib.so] [0x1b440] [ ef 60 b8 72 ] 0x4001b440: movk w15, #0xc307, lsl #16-----w15=0x37d6 //w15=0xc30737d6"
"[libnative-lib.so] [0x1b454] [ 2f 3c a4 72 ] 0x4001b454: movk w15, #0x21e1, lsl #16-----w15=0xcde6 //w15=0x21e1cde6"
"[libnative-lib.so] [0x1b544] [ a8 9a be 72 ] 0x4001b544: movk w8, #0xf4d5, lsl #16-----w8=0xd87 //w8=0xf4d50d87"
"[libnative-lib.so] [0x1b6f8] [ 4a ab a8 72 ] 0x4001b6f8: movk w10, #0x455a, lsl #16-----w10=0x14ed //w10=0x455a14ed"

对比发现26应该是修改成了0xc30737d6。或者是25变成0xc30737d6,26变成原来的25值。剩下两种可能。我们测试一下看看结果

接下来修改MD5里面table的第9条为0x699880d8 第26条为0xc30737d6测试一下

1
2
FF (a, b, c, d, x[ 8], s11, 0x699880d8);
GG (d, a, b, c, x[14], s22, 0xc30737d6);

测试结果正确。第二题搞定

1
md5("kanxueimyangollvm_md5cPKpWAMuRxJVSJORW") = ec184c0980693ef670486feb407b6031