对于逆向同学而言,用android killer打开、分析、修改源代码、重新编译apk是很方便的一件事,所以大部分人都是按照这个流程逆向搞APK的;对于大部分APK而言这么做也是ok的,但是对于少数APK,用android killer打开的时候就会报错,比如前面提到的这款国民级app:
android killer反编译时不管三七二之一,会反编译所有的文件,不仅仅是源代码。其实对于逆向而言,核心需求就是改代码,至于资源、配置文件一般都是不关心的,但是这种报错(有些apk也可能不报错)直接影响了apk的二次编译,比如重新编译时报错如下:
明明一行代码也没改,二次编译的时候居然还是爆各种错误,逆向同学感觉“很受伤”!遇到这种情况怎么办了?难道就没办法改apk的smail源码了?这个时候就要借助MT管理器了;打开MT,在data/app目录下选中这款app,单击base.apk后选中功能,弹窗如下:这是MT管理器的核心功能了,非常强大!
返回后点击查看,能看到apk目录的所有文件;这里主要演示修改smail代码,所以选中一个dex,在弹出的窗口中选择dex编辑器:
然后继续选择需要更改代码的部分,比如类列表->方法列表->方法,这里只是做测试,随便选择一个init初始化方法,增加几个空格,如下:然后保存;会弹窗提示保存成功!
再一路返回,选择“保存并退出”!这里选中自动签名,并确定!然后MT会自动打包apk!
改过的dex会变绿:
退回上一级,base.apk也会变绿:
这时在点击base.apk重新安装:签名状态显示的是v1+v2:
然后一路点击安装按钮,就能重新安装我们更改后的apk了!
=============================分割线==============================================
Java层的代码用MT管理器修改,so层了?当然可以用010Editor、IDA等修改,但是app有可能会做MD5检测,是完全能检查出so被更改的!这时只能在刚加载so时去更改代码了(防止动态检测反调试),核心js代码如下:先通过linker找到call_funtion的地址,然后hook该函数,看看第三个参数、也就是so的path是不是自己想要更改的so;如果是,就可以直接在内存改so的代码了!
function dis(address, number) { for (var i = 0; i < number; i++) { var ins = Instruction.parse(address); console.log("address:" + address + "--dis:" + ins.toString()); address = ins.next; } } //libc->strstr() 从linker里面找到call_function的地址 function hook() { //call_function("DT_INIT", init_func_, get_realpath()); var linkermodule = Process.getModuleByName("linker"); var call_function_addr = null; var symbols = linkermodule.enumerateSymbols(); for (var i = 0; i < symbols.length; i++) { var symbol = symbols[i]; //LogPrint(linkername + "->" + symbol.name + "---" + symbol.address); if (symbol.name.indexOf("__dl__ZL13call_functionPKcPFviPPcS2_ES0_") != -1) { call_function_addr = symbol.address; //LogPrint("linker->" + symbol.name + "---" + symbol.address) } } Interceptor.attach(call_function_addr, { onEnter: function (args) { var type = ptr(args[0]).readUtf8String(); var address = args[1]; var sopath = ptr(args[2]).readUtf8String(); console.log("loadso:" + sopath + "--addr:" + address + "--type:" + type); if (sopath.indexOf("libnative-lib.so") != -1) { var libnativemodule = Process.getModuleByName("libnative-lib.so");//call_function正在加载目标so,这时就拦截下来 var base = libnativemodule.base; dis(base.add(0x8D8E).add(1), 10); var patchaddr = base.add(0x8d96);//改so的机器码,避免待会完全加载后运行时就错过时机了! Memory.patchCode(patchaddr, 4, patchaddr => { var cw = new ThumbWriter(patchaddr); cw.putNop(); cw = new ThumbWriter(patchaddr.add(0x2)); cw.putNop(); cw.flush(); }); /* Memory.protect(base.add(0x8d96),4,'rwx'); base.add(0x8d96).writeByteArray([0x00,0xbf,0x00,0xbf]);*/ console.log("+++++++++++++++++++++++") dis(base.add(0x8D8E).add(1), 10); console.log("----------------------") dis(base.add(0x8E6E).add(1), 10); Memory.protect(base.add(0x8E78), 4, 'rwx'); base.add(0x8E78).writeByteArray([0x00, 0xbf, 0x00, 0xbf]); console.log("+++++++++++++++++++++++") dis(base.add(0x8E6E).add(1), 10); } } }) } function main() { hook(); } setImmediate(main);
1、https://space.bilibili.com/10015124 MT管理器介绍
2、https://space.bilibili.com/377614938 MT管理器介绍