某视频平台关键 so vm 解释器还原
将 metasec_xx.so 拖入 ida,ida 很自信的帮我们把 so 分析完毕,查看区段信息,ok,没有压缩或加密,可以直接静态分析了(ida server 总是断,用 unidbg 调试没有 ida 直观,lldb/gdb 又太古老了,不如使用 idapython 调 unicorn),找到入口,开始分析。
0x01 开始分析
跟踪关键算法从 java 层调用到 native 层之后,最终会调用一个很大的函数
F5 状态下
可以确定该函数是 vm 的入口,并且有混淆,使 ida 反编译失败,看看汇编
ok,不是 ollvm 的混淆。
0x02 混淆及去混淆
分析一下这段混淆的含义
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 |
|
可以看到在写地址前,和比较前的一些运算完全没用,关键的只是后面地址和判断条件,那么去混淆的时候只要保存这块就行。
先手动去混淆
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 |
|
再看看后面是不是都是这样的
可以确定,该类混淆是通过在跳转指令中将跳转地址转为计算值,比较后写入到寄存器中实现跳转,ida 默认没有自动给你分析这个结果,导致反编译失败(中间的多余计算也是一个干扰)。
根据正确的跳转方式,保留关键的寄存器,其他和跳转无关的全部 nop(全是无意义的指令(ps:其实有些也不是))
写去混淆脚本
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
|
去混淆后,ida 再次反编译查看
可以正常解析了,接下来我们要做的就简单了只需要对这个函数进行逐 byte 解析并记录其过程即可。
0x03 VM 解释流程
前面说过,该函数是一个 VM 解释的函数,VM 里执行的二进制代码我把他统称为 vm_opcode,这个 vm 里的 vm_opcode 大概长这样
前面去混淆的代码就是在对这段数据进行一个翻译执行。动静态执行分析一下,解释流程大概是这样的
关于如何分析 vm 和 vm 的结构可以看看看雪的月板第一的文章 https://bbs.kanxue.com/thread-282300.htm
0x04 还原成 C 代码
在上面的文章中,大佬已将伪代码一一列出,最后的做法是在这个基础上纯看代码静态分析,在他的基础上做了点改进
将伪代码用函数表示,并用真实的堆栈和真实的c语句将其打印,对于跳转的指令在前面加上c的跳转指示表,然后通过gcc编译,将编译的结果放入到ida中进行反编译,这样做的目的是在编译时会对编译语句进行编译优化,去除一下冗余和重复计算,这样之后再用ida的反编译优化,再进行了一次的优化,使得其读起来没那么复杂
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 |
|
大概样子
这样之后就比纯看来的好多了
0x05 四神算法还原
暂时没做,只做了 vm 解释器的还原,后面看看有没有需求,然后做做看。