学习笔记-hook和主动调用

用户代码 native hook

  1. 静态注册函数参数,返回值打印和替换
  2. 调用栈
  3. 主动调动
  4. 符号hook == 偏移hook
  5. 枚举并保存结果

0x01 修改返回值以及参数和主动调用

  1. 修改返回值
    修改的原则本质上还是根据开发的套路去走,利用jni开发api去做,这里也是有文档可以进行查询的,https://github.com/frida/frida-java-bridge/blob/master/lib/env.js, 这里就可以直接搜索,ctrl+f直接搜就完事了,当然前提得先获取env,还是上次课的app,主要是修改返回值,上次那个函数的返回值是jstring,那么我们也需要去构造一个jstring对象出来,然后进行一波返回
    js代码:

function hook_nativelib()
{
var native_lib_addr=Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr ->",native_lib_addr);
var myfirstjniJNI=Module.findExportByName("libnative-lib.so","Java_com_example_demoso1_MainActivity_myfirstjniJNI");
console.log("myfirstjiniJNI addr ->",myfirstjniJNI);
Interceptor.attach(myfirstjniJNI,{
onEnter:function(args){
console.log("Interceptor.attach myfirstjniJNI args:",args[0],args[1],args[2]);
console.log("jstring is",Java.vm.getEnv().getStringUtfChars(args[2],null).readCString());
},onLeave:function(retval){
//console.log("Interceptor.attach myfirstjniJNI retval",reval);
var newRetval=Java.vm.getEnv().newStringUtf("YenKoc fucking crazy");
retval.replace(newRetval);
}
})
}
function main1()
{
hook_nativelib();
}
setImmediate(main1);

  1. 修改参数值 没啥好说了,和上面差不多,用jni开发的角度去想

function hook_nativelib()
{
var native_lib_addr=Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr ->",native_lib_addr);
var myfirstjniJNI=Module.findExportByName("libnative-lib.so","Java_com_example_demoso1_MainActivity_myfirstjniJNI");
console.log("myfirstjiniJNI addr ->",myfirstjniJNI);
Interceptor.attach(myfirstjniJNI,{
onEnter:function(args){
console.log("Interceptor.attach myfirstjniJNI args:",args[0],args[1],args[2]);
console.log("jstring is",Java.vm.getEnv().getStringUtfChars(args[2],null).readCString());
var newArgs2=Java.vm.getEnv().newStringUtf("I'm new Args");
args[2]=newArgs2;
},onLeave:function(retval){
//console.log("Interceptor.attach myfirstjniJNI retval",reval);
var newRetval=Java.vm.getEnv().newStringUtf("YenKoc fucking crazy");
retval.replace(newRetval);
}
})
}
function main1()
{
hook_nativelib();
}
setImmediate(main1);

不知道为什么一hook参数就crash了,lj app(吐槽
3. 主动调用 - 核心思想就是先在so中找到对应的地址,这是关键,没有地址一切都是扯淡,这里暂时还没用到偏移,都是通过objection的找到so的导出函数被符号修饰后的符号名,直接通过frida api得到的结果。至于手法就直接记住就好了

function hookandinvoke_add()
{
var native_lib_addr=Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr ->",native_lib_addr);
var r0add_addr=Module.findExportByName("libnative-lib.so","_Z5r0addii");
console.log("r0add addr ->",r0add_addr);
Interceptor.attach(r0add_addr,{
onEnter:function(args){
console.log("x->",args[0],"y->",args[1]);
},onLeave:function(retval)
{
console.log("retval is ->",retval);
}
})
var r0add=new NativeFunction(r0add_addr,"int",["int","int"]);
var r0add_result=r0add(50,2);
console.log("invoke result is",r0add_result);
}
function main1()
{
//hook_nativelib();
hookandinvoke_add();
}
setImmediate(main1);

  • hook native函数
    这里的参数发现都是jstring等等的,这些其实都是指针,我们如果需要主动调用的话,也需要像jni开发一样构造出jstring指针,就像上文做的一样,不过这里有点骚的就是在hook native函数时,将本来传入的参数,再传入主动调用的函数,这样就不需要这么麻烦了

unction hook_nativelib()
{
var native_lib_addr=Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr ->",native_lib_addr);
var myfirstjniJNI=Module.findExportByName("libnative-lib.so","Java_com_example_demoso1_MainActivity_myfirstjniJNI");
console.log("myfirstjiniJNI addr ->",myfirstjniJNI);
var myfirstjniJNI_invoke=new NativeFunction(myfirstjniJNI,"pointer",["pointer","pointer","pointer"]);
Interceptor.attach(myfirstjniJNI,{
onEnter:function(args){
console.log("Interceptor.attach myfirstjniJNI args:",args[0],args[1],args[2]);
console.log("jstring is",Java.vm.getEnv().getStringUtfChars(args[2],null).readCString());
//var newArgs2=Java.vm.getEnv().newStringUtf("I'm new Args");
//args[2]=newArgs2;
console.log("myfirstjniJNI_invoke result:",myfirstjniJNI_invoke(args[0],args[1],args[2]));
},onLeave:function(retval){
//console.log("Interceptor.attach myfirstjniJNI retval",reval);
var newRetval=Java.vm.getEnv().newStringUtf("YenKoc fucking crazy");
retval.replace(newRetval);
}
})
}
function hookandinvoke_add()
{
var native_lib_addr=Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr ->",native_lib_addr);
var r0add_addr=Module.findExportByName("libnative-lib.so","_Z5r0addii");
console.log("r0add addr ->",r0add_addr);
Interceptor.attach(r0add_addr,{
onEnter:function(args){
console.log("x->",args[0],"y->",args[1]);
},onLeave:function(retval)
{
console.log("retval is ->",retval);
}
})
var r0add=new NativeFunction(r0add_addr,"int",["int","int"]);
var r0add_result=r0add(50,2);
console.log("invoke result is",r0add_result);
}
function main1()
{
hook_nativelib();
//hookandinvoke_add();
}
setImmediate(main1);

0x02 调用栈

console.log("CCCryptoCreate called from:\n"+Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n")+'\n');

这行代码加入到hook的代码中去,就可以打印出调用栈 # 0x03 replace 这玩意其实就相当于java层中的hook,上面那个主动调用的话,其实就是this.xx的形式

function hook_replace()
{
var native_lib_addr=Module.findBaseAddress("libnative-lib.so");
console.log("native_lib_addr ->",native_lib_addr);
var myfirstjniJNI=Module.findExportByName("libnative-lib.so","Java_com_example_demoso1_MainActivity_myfirstjniJNI");
console.log("myfirstjiniJNI addr ->",myfirstjniJNI);
var myfirstjniJNI_invoke=new NativeFunction(myfirstjniJNI,"pointer",["pointer","pointer","pointer"]);
Interceptor.replace(myfirstjniJNI,new NativeCallback(function(args0,args1,args2){
console.log("Interceptor.attach myfirstjniJNI args:",args0,args1,args2);
return Java.vm.getEnv().newStringUtf("new Retval from frida");
},"pointer",["pointer","pointer","pointer"]));
}

肉丝说不常用,但是我感觉改返回值啥的,还可以把 # 0x04 枚举出所有模块的所有导出符号(静态注册的才行)

function EnumerateAllExports()
{
var modules=Process.enumerateModules();
//print all modules
//console.log("Process.enumerateModules->",JSON.stringify(modules));
for(var i=0;i<modules.length;i++)
{
var module=modules[i];
var module_name=modules[i].name;
var exports=module.enumerateExports();
console.log("module.enumerateeExports",JSON.stringify(exports))
}
}

点击关注,共同学习!
[安全狗的自我修养](https://mp.weixin.qq.com/s/E6Kp0fd7_I3VY5dOGtlD4w)


[github haidragon](https://github.com/haidragon)


https://github.com/haidragon

x64进程远程hook,x64_远程调用函数,源码更新V1.8.2:2021/4/12 源码为下方连接帖子后续更新内容: 浅谈64位进程远程hook技术: https://bbs.125.la/forum.php?mod=viewthreadtid=14666356extra= 不管您是转载还是使用请保留版权,源码在精益论坛免费发布本人未获利,请不要用于非法途径。 --------------------------------------------------------------- 2021/4/12 模块源码 v1.8.2更新 1:修复 x64_远调用函数()在 易语言 主线程调用时造成消息无法回调,导致易语言主线程窗口卡死的问题。      感谢楼下易友发现的BUG,已经第一时间更新 2021/4/12 模块源码 v1.8.1更新 1:修复 hook全部卸载时的流程写法的一个错误,由于句柄的提前关闭导致多个hook点卸载不干净的问题 2:改写了消息回调时线程传参的代码优化,优化了其他一些小问题 3:  鉴于很多朋友需要,改写了模块自带实列,对TCP,UDP的两组封包函数做了hook实列写法 4:列子中同样增加对x64_远调用函数()的应用写了几个列子,如使用套接字取得本地或远端IP端口API调用的的应用实列 5:本hook模块不支持非模块内存区hook,如申请的动态分配页等,不是不能支持,只是觉得没有任何意义,对这方面有需求的,自行改写模块源码使用 提醒:hook回调函数中尽量减少耗时代码,时间越长返回越慢,回调中谨慎操作控件,如必须要用到可参考源码中实列写法采用线程操作 历史更新 --------------------------------------------------------------- 2021/3/1   模块源码v1.6更新: 1:修复  x64_远程调用函数()命令,在没有提供 寄存器 参数时,没有返回值的BUG。 --------------------------------------------------------------- 2021/2/28 模块源码v1.5更新: 一:修复win7 64位系统下枚举模块 出现部分模块长度出现负数的问题,从而导致部分win7用户不能使用 二:强化 远程hook64指令_安装 的稳定性:        1,穿插代码中增加对标志位的保护,避免hook位置长度下一条指令为跳转时产生跳转错乱的问题,强化了hook任意位置的定位        2,因为穿插代码中会调用API函数,而64位汇编必须遵守栈指针16字节对齐,故对穿插代码进行栈指针16字节对齐,增强稳定性        3,hook指令安装支持长度由6-127字节 变动 为 6-119字节,原因么没必要说了,代码优化造成的,稍微少了一点无所谓了        4,对模块回调进行了适当优化处理,增强稳定性 三:应支持的朋友需要故增加 x64_远程调用函数()命令,易语言可以直接远call64进程,且无需写汇编代码或机器码指令,支持15个参数,支持返回值,支持16个通用寄存器全部取得返回值       该功能调用即16字节栈对齐,不要用户管堆栈,代码内部构成,远线程执行,你只需要知道call有几个参数,需要什么寄存器,对应提供即可。 四:有朋友说原模块x64英文看了烦,那好吧就给改成了中文标识,弄得我自己也不习惯 五:源码内列子改了改,可以自己看,需要注意的是模块注释的很详细,使用前最好看一看,尤其是hook回调接口的写法和安装的写法最好按照模块列子中的写法来,除非你能把64hook模块组看懂一遍,对于一些对本模块一知半解的朋友请不要乱改乱发,这个模块我会继续增强的,只是工作原因时间有限,只能一点一点来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C-haidragon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值