0% found this document useful (0 votes)
25 views

base

The document provides an analysis of the loading process for shared object (SO) files, detailing the use of dlopen and JNI_OnLoad functions. It includes code snippets for function replacement and memory dumping using Frida, as well as techniques for hooking and tracing function calls. Additionally, it discusses the use of SoFixer for repairing SO files and mentions challenges with Java layer hooks being detected.

Uploaded by

王强
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views

base

The document provides an analysis of the loading process for shared object (SO) files, detailing the use of dlopen and JNI_OnLoad functions. It includes code snippets for function replacement and memory dumping using Frida, as well as techniques for hooking and tracing function calls. Additionally, it discusses the use of SoFixer for repairing SO files and mentions challenges with Java layer hooks being detected.

Uploaded by

王强
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

最新版某banban加固分析

so的加载流程

https://zhuanlan.zhihu.com/p/22652847

so流程分析

dlopen加载

dlopen

整个so就已经被加载进入内存了

-> .init_array会执行这个部分

dlopen函数结束

system.load

dlopen

整个so就已经被加载进入内存了

-> .init_array会执行这个部分

dlopen函数结束

JNI_OnLoad

马上退出去的

检测没有使用到线程

等一会才退出去
开一个线程
pthread_create -> 杀线程

函数替换

function create_pthread_create() {
const pthread_create_addr =
Module.findExportByName(null, "pthread_create")
const pthread_create = new
NativeFunction(pthread_create_addr, "int", ["pointer",
"pointer", "pointer", "pointer"]);
return new NativeCallback((parg0, parg1, parg2, parg3)
=> {
const module = Process.findModuleByAddress(parg2);
const so_name = module.name;
const baseAddr = module.base
console.log("pthread_create", so_name, "0x" +
parg2.sub(baseAddr).toString(16), "0x" +
parg3.toString(16))
// 成功的返回值是0
return pthread_create(parg0, parg1, parg2, parg3)
}, "int", ["pointer", "pointer", "pointer",
"pointer"])
}

// 或者
function replace_thread() {
var new_pthread_create = create_pthread_create()
var pthread_create_addr =
Module.findExportByName(null, "pthread_create")
// 函数替换
Interceptor.replace(pthread_create_addr,
new_pthread_create);
}

replace_thread()
进行函数替换马上退出

在某一个地方,进行了inline hook检测

dlopen顺利结束,JNI_OnLoad

dump so

import frida

js_script = """
function dump_so(so_name) {
console.log("开始dump")
const module = Process.findModuleByName(so_name);
const module_size = module.size;
Memory.protect(ptr(module.base), module_size, 'rwx');
const soMemory = Memory.readByteArray(module.base,
module_size);
send({name: so_name, base: module.base, size:
module_size}, soMemory);
}

dump_so("libDexHelper.so")
"""

def on_message(message, data):


if message['type'] == 'send':
payload = message['payload']
so_name = payload['name']
base_address = payload['base']
size = payload['size']

print(f"Dumping {so_name} (Base: {base_address},


Size: {size})")

# 保存dump的.so文件
with open(so_name, "wb") as f:
f.write(data)
print(f"{so_name} dumped successfully!")
else:
print(f"Error: {message}")

def main():
# 附加到目标进程
device = frida.get_usb_device()
session = device.attach(18819)
# 加载Frida脚本
script = session.create_script(js_script)
# 设置消息处理函数
script.on("message", on_message)
# 加载并执行脚本
script.load()

if __name__ == "__main__":
main()

SoFixer修复so

.\SoFixer-Windows-64.exe -s .\libDexHelper.so -o
.\libDexHelper_xf.so

frida stalker

https://zhuanlan.zhihu.com/p/344222341

mov x1 x2

mov x1 x2
log
因为我们在JNI_OnLoad里面退出的,所以在stalker里面分析JNI_OnLoad这
个部分。

退出

svc退出

跳转不可执行的地方,也是可以退出的

最后代码

function nopFunc(parg2) {
// 修改内存保护,使其可写
Memory.protect(parg2, 4, 'rwx');
// 使用 Arm64Writer 写入 'ret' 指令
var writer = new Arm64Writer(parg2);
writer.putRet();
writer.flush();
writer.dispose();
console.log("nop " + parg2 + " success");
}

function create_pthread_create() {
const pthread_create_addr =
Module.findExportByName(null, "pthread_create")
const pthread_create = new
NativeFunction(pthread_create_addr, "int", ["pointer",
"pointer", "pointer", "pointer"]);
return new NativeCallback((parg0, parg1, parg2, parg3)
=> {
const module = Process.findModuleByAddress(parg2);
const so_name = module.name;
const baseAddr = module.base;
if (so_name.indexOf("libDexHelper.so") !== -1) {
console.log("pthread_create", so_name, "0x" +
parg2.sub(baseAddr).toString(16), "0x" +
parg3.toString(16))
return 0;
}
// 成功的返回值是0
return pthread_create(parg0, parg1, parg2, parg3)
}, "int", ["pointer", "pointer", "pointer",
"pointer"])
}

// 或者
function replace_thread() {
var new_pthread_create = create_pthread_create()
var pthread_create_addr =
Module.findExportByName(null, "pthread_create")
// 函数替换
Interceptor.replace(pthread_create_addr,
new_pthread_create);
}

replace_thread()

function hook_dlopen(so_name) {
Interceptor.attach(Module.findExportByName(null,
"android_dlopen_ext"), {
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null)
{
var path = ptr(pathptr).readCString();
console.log(path)
if (path.indexOf(so_name) !== -1) {
this.match = true
}
}
},
onLeave: function (retval) {
if (this.match) {
var module =
Process.findModuleByName("libDexHelper.so");
nopFunc(module.base.add(0x4B014));
if (module) {
var JNI_OnLoad =
module.findExportByName("JNI_OnLoad")
Interceptor.attach(JNI_OnLoad, {
onEnter: function (args) {
var curTid =
Process.getCurrentThreadId();
const startAddress =
module.base.add(0x31C60);
const size = 0x3755C -
0x31C60;
//开始trace
Stalker.follow(curTid, {
events: {
call: true
},
transform: function
(iterator) {
let instruction =
iterator.next();
const baseFirstAddress
= instruction.address;
const module =
Process.findModuleByAddress(baseFirstAddress);
const isModuleCode =
baseFirstAddress.compare(startAddress) >= 0 &&

baseFirstAddress.compare(startAddress.add(size)) < 0;
if (isModuleCode) {
if (module) {
const name =
module.name;
const offset =
baseFirstAddress.sub(module.base);
const base =
module.base;
console.log(`[transform] start: ${baseFirstAddress}
name:${name} offset: ${offset} base: ${base}`);
} else {

console.log(`[transform] start: ${baseFirstAddress}`);


}
}
do {
const curRealAddr
= instruction.address;
const curOffset =
curRealAddr.sub(baseFirstAddress);
const curOffsetInt
= curOffset.toInt32();
const
instructionStr = instruction.toString();
if (isModuleCode)
{

console.log("\t" + curRealAddr + " <+" + curOffsetInt +


">: " + instructionStr);
}
iterator.keep();
} while ((instruction
= iterator.next()) !== null);
if (isModuleCode) {
console.log()
}
}
})
},
onLeave: function () {
Stalker.unfollow();
Stalker.garbageCollect();
}
})
}
}
}
});
}

hook_dlopen("libDexHelper.so")

toda

java层的hook有问题
似乎还是被检测到了

You might also like