逆向能力提升,so解密与修复
标题:so解密与修复
使用工具
win11
frida
cygwin
realmeGT neo3(已root)
ida pro 7.7
010 editor
本文涉及到so的解密与修复,对观看者的逆向基础要求较高,请酌情观看
我认为这篇文章已经将这个目标app加密以及如何解密的过程讲解的很清楚了,但是如何查看ooxx函数的偏移和大小,作者没有说明他所使用的工具,我也是找了很久,才找到这个工具:readelf,linux系统可以直接使用,windows需要借助cygwin使用。
这篇文章也挺不错,但是最后的解密脚本是错误的
- def patchBytes(addr,length):
- for i in range(0,length):
- byte=get_bytes(addr + i,1)
- byte = ord(byte) ^ (i%0xff)
- patch_byte(addr+i,byte)
- patchBytes(0x8e00,0x8fd0-0x8e00)
作者没有考虑到i>=255的情况
正确的解密脚本
- def patchBytes(addr, length):
- for i in range(length):
- if i < 255:
- byte = get_bytes(addr + i,1)
- byte = ord(byte) ^ (i % 0xff)
- patch_byte(addr + i, byte)
- elif i == 255:
- byte = get_bytes(addr + i,1)
- byte = ord(byte) ^ 0xff
- patch_byte(addr + i, byte)
- else:
- byte = get_bytes(addr + i,1)
- byte = ord(byte) ^ ((i – 1) % 0xff)
- patch_byte(addr + i, byte)
- patchBytes(0x8e00, 0x8fd0 – 0x8e00)
以上2篇文章主要是从解密的角度分析,第3篇则是直接dump解密后的so.
function main(){
- var module_base = Module.findBaseAddress(“libnative-lib.so”);
- var mprotect_add = Module.findExportByName(“libc.so”, “cacheflush”);
- Interceptor.attach(mprotect_add,{
- onEnter: function(args){
- if(args[0] > module_base && args[0] < module_base.add(0x100000)){
- console.log(“\nargs :”, args[0], args[1], args[2]);
- console.log(args[0].sub(1).readByteArray(args[1] – args[0]));
- console.log(“called cacheflush”);
- }
- },
- onLeave: function(){}
- })
- }
- setImmediate(main)
原作者的脚本是将内存中解密后的ooxx函数给打印下来,再对比原so,一个字节一个字节修复,这样太麻烦了,我们直接把解密后的ooxx函数全dump到一个文件中,再对比修复,则是更方便简单一些。
改进后的脚本
- function main() {
- var module_base = Module.findBaseAddress(“libnative-lib.so”);
- var mprotect_add = Module.findExportByName(“libc.so”, “cacheflush”);
- var currentApplication = Java.use(“android.app.ActivityThread”).currentApplication();
- var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
- var keyso_path = dir + “/” + “keyso” + “_” + mprotect_add;
- Interceptor.attach(mprotect_add, {
- onEnter: function (args) {
- if (args[0] > module_base && args[0] < module_base.add(0x100000)) {
- console.log(“\nargs :”, args[0], args[1], args[2]);
- const data = args[0].sub(1).readByteArray(args[1] – args[0]);
- var file_handle = new File(keyso_path, “wb”);
- if (file_handle && file_handle != null) {
- Memory.protect(mprotect_add, Number(args[1] – args[0]), ‘r’);
- file_handle.write(data);
- file_handle.flush();
- file_handle.close();
- console.log(“[keyso]: “, keyso_path);
- }
- console.log(“called cacheflush”);
- }
- },
- onLeave: function () { }
- });
- }
- setImmediate(main);
- //frida -U -l 2.js “Test”
这样就可以把解密的函数直接从内存中dump下来,方便我们待会修复。
使用010 editor 修复so文件
先加载libnative-lib.so
再点击tools compare files
再把我们dump出的文件拉进来对比,对比肯定找不到相似之处,但是不要着急。
在libnative-lib.so 按crtl F,搜索f0 b5 03 af 89 b0,也就是dump文件的前5个字节,定位到8DC0偏移这一行
再看看dump文件有0240h(注意,h代表hex,也就是16进制),算一下8DC0+0240等于多少,应该没谁这么叼,口算16进制吧,所以我们windows的程序猿计算器算出结果,可以看到是9000h
也就是说我们要替换的字节大致在8DC0~9000之间,之后的估计大家都能清楚判断出要替换哪些字节了,我就不多说了。
最后一步,直接复制dump出的所有字节替换libnative-lib.so对应的字节,这样就完成解密了,是不是很简单?
发表评论