分析样例下载:链接: https://pan.baidu.com/s/1qxkYqMovR8Fe6sO-Zr-8ow 密码: dh7g
第一题algorithmbase_32
直接ida打开找到encodeFromJni_32函数。然后F5后。发现是ollvm混淆的。然后大概的分析一下。我的分析思路是。首先是大概的翻一下参数较多的那些函数,看看是否有什么比较眼熟的函数。果然很快锁定了一个函数sub_1D920。下面贴上交为眼熟的部分
我圈出来的这几个特征和我们之前分析过的md5的特征高度的相似。v10的那些明显就是MD5的那个key。而下面是拼接的三段固定数据再加上我们的输入值。所以我们先看看那三段数据分别是什么
点开后发现字符串被加密了。所以我们用之前研究的解ollvm字符串混淆的工具unidbg或者是AndroidNativeEmu来生成一个解密的so跑一下。下面贴上解完之后的结果
然后点进去看看字符串。
知道是什么值拼接的之后。然后就简单了。先看看输出和输出的值。
1 rRZrALoUFxTqxDCJHjT -> ea8caf7e47b8404d81de797995d6c3cc
然后我们拼接kanxue+imyang+ollvm_md5+输入数据来MD5看看是否一致
结果和上面的一致。第一题搞定
=======================================================================================================
第二题algorithmbase_32_2
直接ida开始分析。找到encodeFromJni_32函数。由于上一个例子翻到了关键函数。直接找类似的函数。定位到了sub_1D48C。
看着和之前的差不多的。然后看看前面固定拼接了些什么
发现也是字符串混淆加密的。老办法。上unidbg或者是AndroidNativeEmu来生成一个解密的so。
解密后看到依然还是这几个值。我们跑的测试一下看是否计算的值一致了。先获取一个手机上的输入和输出
1 cPKpWAMuRxJVSJORW -> ec184c0980693ef670486feb407b6031
看下面的图。发现结果不是一致的
所以我们还得检查。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 ; 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的位置。
接下来把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