能力值:
( LV5,RANK:70 )
2 楼
typedef int (*dlopen_tp)(const char* __filename, int __flag); dlopen_tp my_dlopen = (dlopen_tp)dlopen; func_dlopen = base + 0x2F00+1; func_dlsym = base + 0x2FB8+1; LOGD("DLOPEN = %p ? %p %p",my_dlopen,func_dlopen,func_dlsym); 解决了上面的问题 这样会得到一个和dlopen地址(my_dlopen)
能力值:
( LV2,RANK:10 )
在线值:
3 楼
以前做了一个一键生成so、dll劫持源码的小工具,对这种可以说非常有用。 缺点就是 有的so自带JNI_OnLoad时 一键链接Java层所有的native函数,这个部分支持依然有点问题,需要用hook去直接hook register native,然后一个一个 链接到自己的函数上,偷懒没做。
能力值:
( LV12,RANK:219 )
4 楼
感谢分享 之前用inject感觉也挺方便的
能力值:
( LV2,RANK:10 )
5 楼
“我们使用inlinehook编译一个so并把名称改为他原来的so的名称,把他原来的so改个名字,由我们编译的so来加载.” 不重新打包,你怎么替换/data/app/com.xxx/lib/目录下的so?难道在root下使用copy来替换?
能力值:
( LV2,RANK:10 )
6 楼
都root了还用inlineHook实乃不明智之举。
能力值:
( LV5,RANK:70 )
7 楼
tDasm
“我们使用inlinehook编译一个so并把名称改为他原来的so的名称,把他原来的so改个名字,由我们编译的so来加载.”
不重新打包,你怎么替换/data/app/com.xxx/lib/目录下 ... adb push xxx.so /data/app/com.xxx/lib/arm/
最后于 2020-9-7 16:15
被唱过阡陌编辑
,原因:
能力值:
( LV2,RANK:10 )
8 楼
唱过阡陌
tDasm
“我们使用inlinehook编译一个so并把名称改为他原来的so的名称,把他原来的so改个名字,由我们编译的so来加载.”
不重新打包,你怎么替换 ...
root下使用copy来替换,猜对了
能力值:
( LV2,RANK:10 )
在线值:
9 楼
牛皮牛皮
能力值:
( LV3,RANK:20 )
在线值:
10 楼
dlopen地址自动获取其实有更高明的手段,比如vapp里用的那玩意 或者我之前写的方式http://www.52pojie.cn/thread-1226153-1-1.html
能力值:
( LV3,RANK:20 )
在线值:
11 楼
知道windos有dll代理,也想了想应该linux的也能代理吧,但是确实没想到原来替换个handle就可以用了
12 楼
这边试了下,没成功,有两个疑问: 1、"手动加载 原so 后,触发一下原so的Jni_onload()",这个没太明白 程序启动,应该是runtime 先dloepn libmarsxlog.so,在进入JNI_OnLoad函数,此时在JNI_OnLoad函数中dlopen libmarsxlogcp.so,只是获取了libmarsxlogcp.so的handle System.loadLibrary(libName) ->JavaVMExt.loadNativieLibrary: ->dlopen ->JNI_OnLoad 2、下面的代码仅仅打印下吗 //手动调用原so的JNI_OnLoad() void *p2 = dlsym(p1, "JNI_OnLoad"); LOGD("called dlsym JNI_OnLoad 0x%p",p2);
能力值:
( LV5,RANK:70 )
13 楼
wx_havenow
这边试了下,没成功,有两个疑问:
1、"手动加载 原so 后,触发一下原so的Jni_onload()",这个没太明白
程序启动,应该是runtime 先dloepn libm ...
第一个问题:
LoadNativeLibrary调用了android_dlopen_ext()和dlsym(),并由dlsym()调用了JNI_Onload(),所以我们手动dlopen打开一个so得手动去调用dlsym(),来触发他的JNI_Onload(),具体可以参见另一篇文章:(https://www.jianshu.com/p/5252b62aa9d2 )
第二个问题:
void *p2 = dlsym(p1, "JNI_OnLoad"); //就是上述我们说的要手动调用他的JNI_Onload()
LOGD("called dlsym JNI_OnLoad 0x%p",p2); //这里只是打印看一下调用情况
补充:
至于试了没有成功,可能不是这个问题,举例说的话,这种方式调用不是什么情况下都能成功的,比如Unity游戏中libil2cpp.so,具体也没研究(欢迎大佬来补充),但是众所周知这个so哪怕是改了一个字节他都会报错的,so里面做了其他处理吧,一般情况替换工具so是没问题的,建议动态用frida先跑通了在尝试inlinehook
14 楼
感觉这个方法确实不是什么情况下都能成功,我这边失败的原因暂时没找到。 我看了下打印的日志,我这边的app,老so的部分jni方法确实是有被dlsym,老so的jni方法为什么会被dlsym,而且只是部分被dlsym,具体的原因还有待验证,有可能是反射机制,java层调用的时候才会去dlsym 作者说的 “所以我们手动dlopen打开一个so得手动去调用dlsym(),来触发他的JNI_Onload()”,个人觉得是有问题的: libdl.cpp --->dlsym() //加载jni_onload() 对于这个一个流程的个人觉得应该是在libdl.cpp中先dlysm了jni_onload在去调用jni_onload 本身dlsym仅仅是获取jni_onload这个这个函数的handle 如果要调用,应该是 p2(vm, reserved);
15 楼
这边搜索了下代码 JavaVMExt::LoadNativeLibrary,楼主写的 “所以我们手动dlopen打开一个so得手动去调用dlsym(),来触发他的JNI_Onload()” 应该是有问题的 JavaVMExt::LoadNativeLibrary { void* sym; sym = library->FindSymbol("JNI_OnLoad", nullptr); if (sym == nullptr) { VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]"; was_successful = true; } else { // Call JNI_OnLoad. We have to override the current class // loader, which will always be "null" since the stuff at the // top of the stack is around Runtime.loadLibrary(). (See // the comments in the JNI FindClass function.) ScopedLocalRef<jobject> old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride())); self->SetClassLoaderOverride(class_loader); VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]"; typedef int (*JNI_OnLoadFn)(JavaVM*, void*); JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym); int version = (*jni_on_load)(this, nullptr); } 注意关键点: sym = library->FindSymbol("JNI_OnLoad", nullptr); //这里应该是dlsym JNI_OnLoad函数 JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym); int version = (*jni_on_load)(this, nullptr); //这里是根据函数地址做函数调用,这个调用就会进入so的JNI_OnLoad
16 楼
猜测失败的原因: 老的so里面函数dlsym应该是都会成功的,但是调用可以会有问题 vm是唯一的,但是env是线程相关的,如果JNI_OnLoad函数里面用到了env,可能会出问题
最后于 2020-9-20 21:38
被wx_havenow编辑
,原因:
能力值:
( LV5,RANK:70 )
17 楼
wx_havenow
猜测失败的原因:1、老的so里面部分函数dlsym失败;不确定用registerNative注册的函数和直接用Java_com_xxxx映射的函数 dlsym有没有区别2、vm是唯一的,但是env是线 ...
大佬指出的是,我刚才重新看了一下源码,文章这里确实是写错了 ,压根就没有调用jni_onload /xk
是在调用FindSymbol()拿到JNI_Onload地址之后,做了一次函数的调用
```
JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
int version = (*jni_on_load)(this, nullptr);
```
实际操作中不管是动态注册还是静态注册的函数dlsym只会调用一次
这里的this,都是一个同一个javaVM,但是函数里用到的env确实可能拿到不一样的env导致出问题
要真是线程相关的问题还不好处理
可以附一下报错嘛,大家一起找问题
能力值:
( LV5,RANK:70 )
18 楼
还有一个小问题,在自己写的小demo里面,java层的点击事件触发一个静态注册的native函数,hook dlsym的时候发现其实注册函数只是被调用了一次,即使后面再点击按钮不会再出发dlsym获取函数地址,可能是某种缓存机制?就是说要想hook到注册函数的调用时机得早,在他调用之后你再去改返回值其实也就不生效了,反正他也不会调用了
19 楼
我这边确认过了: java端调用System.loadLibrary()后, 1、dlopen so 2、dlsym so中的JNI_OnLoad函数,并且调用JNI_OnLoad函数 3、如果JNI_OnLoad函数中有registerNatives,对本地方法进行注册,这里是不会调用dlsym的,因为是将函数指针保存起来了 4、如果有Java_com.xxxx_fun的jni函数,在调用jni函数时,vm会dlysm jni函数,获取到jni函数地址,在调用jni函数,只会dlsym一次, 因为获取到jni函数的地址后会存起来,就不用在dlsym了 你做hook,肯定是要在so load结束,才能hook成功 比如你的System.loadLibrary不是在static块里面,用一个按钮去触发,app启动了,hook jni函数肯定是失败的
20 楼
13030-13057/? E/inlinehook: new_func_dlsym from 0x7a45cdaf, glSamplerParameteriv 13030-13057/? D/inlinehook: 0x0 = __loader_dlsym('0x7a45cdaf','glSamplerParameteriv') 13030-13057/? E/inlinehook: new_func_dlsym from 0xc68f21d3, glSamplerParameteriv 13030-13057/? D/inlinehook: 0xe5ce11a0 = __loader_dlsym('0xc68f21d3','glSamplerParameteriv') 13030-13077/? I/Process: Sending signal. PID: 13030 SIG: 9 1635-3586/? D/ActivityManager: report kill process: killerPid is:13030, killedPid is:13030 只能可看到 Sending signal. PID: 13030 SIG: 9
能力值:
( LV3,RANK:30 )
21 楼
还是 lief 比较香
`pip install lief`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import
lief
libm
=
lief.parse(
"/usr/lib/libm.so.6"
)
hook
=
lief.parse(
"hook"
)
cos_symbol
=
libm.get_symbol(
"cos"
)
hook_symbol
=
hook.get_symbol(
"hook"
)
code_segment
=
hook.segment_from_virtual_address(hook_symbol.value)
segment_added
=
libm.add(code_segment)
print
(
"Hook inserted at VA: 0x{:06x}"
.
format
(segment_added.virtual_address))
hook_offset
=
hook_symbol.value
-
code_segment.virtual_address
new_addr
=
segment_added.virtual_address
+
hook_offset
print
(f
"Change {cos_symbol.name}!{cos_symbol.value:x} -> {cos_symbol.name}!{new_addr:x}"
)
cos_symbol.value
=
new_addr
libm.write(
"libm.so.6"
)
能力值:
( LV2,RANK:10 )
22 楼
tql
能力值:
( LV1,RANK:0 )
23 楼
这个根本不必要这样搞啊,直接hook system.loadlibrary,然后先注入自己的inlinehook,再加载原有lib就可以了
能力值:
( LV5,RANK:70 )
24 楼
huangbof
这个根本不必要这样搞啊,直接hook system.loadlibrary,然后先注入自己的inlinehook,再加载原有lib就可以了
1.这篇文章是在不修改smali代码的情况下完成的,当你遇到指令抽取的时候可以绕过修改smali
2.发文就是想给大家分享思路,大家各抒己见就行,但是既然看到这篇文章,如果觉得思路有意思,咋不妨就去谈论一下这种思路的可行性,可能遇到的问题,听大佬的发言一起完善它,这才能有进步嘛
能力值:
( LV5,RANK:70 )
25 楼
发现一个python的工具lief(https://github.com/lief-project/LIEF) 这玩意修改一下依赖,添加上我们的inject.so就完事,这更简单