文章目录
- 0x00 序言
- 0x01 启动 IDA Server
- 选择android_server版本
- 指定端口运行android_server
- 0x02 开始调试
- 载入目标so(先dump再载入)
- Attach目标进程
0x00 序言
本文主要作为脑残的我记录一下IDA调试so的各种命令,因为老是忘记!没有任何干货,大家可以撤了!毫无技术含量!
0x01 启动 IDA Server
选择android_server版本
1. 在真机调试so中,根据应用程序的运行情况选择android_server 或 android_server64
2. 借助frida查看APP安装在多少位
32位:
64位:
3. 指定APP安装在多少位
adb install --abi armeabi-v7a <包名> //指定安装在32位
adb install --abi arm64-v8a <包名> //指定安装在64位
指定端口运行android_server
1. android_server在push到手机之后,需要给server文件加上执行权限
2. 修改ida的调试server文件名,比如我改成as7,运行时进程名会变,反调小技巧+1
3. 指定监听端口运行ida的调试server:
./as7 -p23445 //注意-p选项后面接端口号,不要加空格
反调小技巧+1
4. 端口转发
将我们监听的23445端口转发出来给PC:
adb forward tcp:23445 tcp:23445
0x02 开始调试
载入目标so(先dump再载入)
1. 载入目标so,有的大聪明给so做了加固,对抗静态反编译,那我们就需要dump一下
2. 我们利用frida去dump目标so,工具有现成的,来自yang神的dump_so: https://github.com/lasting-yang/frida_dump
rpc.exports = {
findmodule: function(so_name) {
var libso = Process.findModuleByName(so_name);
return libso;
},
dumpmodule: function(so_name) {
var libso = Process.findModuleByName(so_name);
if (libso == null) {
return -1;
}
Memory.protect(ptr(libso.base), libso.size, 'rwx');
var libso_buffer = ptr(libso.base).readByteArray(libso.size);
libso.buffer = libso_buffer;
return libso_buffer;
},
allmodule: function() {
return Process.enumerateModules()
},
arch: function() {
return Process.arch;
}
}
3. dump完成之后还是使用yang神的dump_so修复一下elf文件结构:
import sys
import frida
import sys
import os
def fix_so(arch, origin_so_name, so_name, base, size):
if arch == "arm":
os.system("adb push android/SoFixer32 /data/local/tmp/SoFixer")
elif arch == "arm64":
os.system("adb push android/SoFixer64 /data/local/tmp/SoFixer")
os.system("adb shell chmod +x /data/local/tmp/SoFixer")
os.system("adb push " + so_name + " /data/local/tmp/" + so_name)
print("adb shell /data/local/tmp/SoFixer -m " + base + " -s /data/local/tmp/" + so_name + " -o /data/local/tmp/" + so_name + ".fix.so")
os.system("adb shell /data/local/tmp/SoFixer -m " + base + " -s /data/local/tmp/" + so_name + " -o /data/local/tmp/" + so_name + ".fix.so")
os.system("adb pull /data/local/tmp/" + so_name + ".fix.so " + origin_so_name + "_" + base + "_" + str(size) + "_fix.so")
os.system("adb shell rm /data/local/tmp/" + so_name)
os.system("adb shell rm /data/local/tmp/" + so_name + ".fix.so")
os.system("adb shell rm /data/local/tmp/SoFixer")
return origin_so_name + "_" + base + "_" + str(size) + "_fix.so"
def read_frida_js_source():
with open("dump_so.js", "r") as f:
return f.read()
def on_message(message, data):
pass
if __name__ == "__main__":
device: frida.core.Device = frida.get_usb_device()
pid = device.get_frontmost_application().pid
session: frida.core.Session = device.attach(pid)
script = session.create_script(read_frida_js_source())
script.on('message', on_message)
script.load()
if len(sys.argv) < 2:
allmodule = script.exports.allmodule()
for module in allmodule:
print(module["name"])
else:
origin_so_name = sys.argv[1]
module_info = script.exports.findmodule(origin_so_name)
print(module_info)
base = module_info["base"]
size = module_info["size"]
module_buffer = script.exports.dumpmodule(origin_so_name)
if module_buffer != -1:
dump_so_name = origin_so_name + ".dump.so"
with open(dump_so_name, "wb") as f:
f.write(module_buffer)
f.close()
arch = script.exports.arch()
fix_so_name = fix_so(arch, origin_so_name, dump_so_name, base, size)
print(fix_so_name)
os.remove(dump_so_name)
4. 当然也可以使用F8LEFT大佬的SoFixer: https://github.com/F8LEFT/SoFixer
各平台下载对应版本release即可使用,使用命令也很简单
sofixer -s soruce.so -o fix.so
-s 待修复的so
-o 修复后的so输出位置
-d 输出debug信息,可选
5. 一切准备好之后,丢进IDA里就可以了,开心+1
Attach目标进程
1. 设置调试器参数:
(1)打开调试器设置选项
(2)设置端口
绿色这坨不用动,因为前面转发了端口,所以监听localhost:23445
2. 一切准备就绪,开始Attach
ctrl+f打开搜索框,搜索目标进程,点击OK,开始附加,完事,开心+1
注意:
调试时,使用冰神教的定制rom过反调,不要着急attach,先准备好到这里,然后脚本监听到目标函数,再点OK,去attach
反调大技巧 + 100
开心 + 100对于多线程APP过反调,把其他线程挂起,再attach主线程就OK的啦,反调小技巧 + 1 , 开心 + 1