-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix crash on Android 11 #133
Conversation
@lianglixin 你也是谜语人:有更好的解决方法。 |
💴 |
@lianglixin 在人家开源项目底下说钱,真有你的呢 |
@yujincheng08 把ClassLinker::ShouldUseInterpreterEntrypoint 这个函数inline hook掉,对于被hook过的方法让其返回false就能解决debug不生效的问题;另,yahfa作者明确表示过不想再引入一套完整的native inline hook框架,所以我没发pr。 |
@canyie 这个其实edxp有个接口只是没实现。我个人不是很喜欢这种native hook的方法。 |
看起来我遇到的并不是这个问题;我试了下直接拿yahfa的示例app在debug build的系统跑是没问题的,但是edxp在hook了这个函数后,甚至没有遇到过被hook的method检查 |
if (SDKVersion >= __ANDROID_API_Q__) { | ||
// On API 29 whether to use the fast path or not is cached in the ART method structure | ||
access_flags &= ~kAccFastInterpreterToInterpreterInvoke; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个是不是把Q漏了
某谜语壬测试下来,发现有个问题,不知道是谜语壬的问题,还是你的问题,、会调到java层的backup里。 2020-09-26 19:29:34.779 9988-9988/lab.galaxy.yahfa E/yahfa: this is cannot delete, come in is error!!! |
hook的目标 |
2020-09-28 11:28:25.546 28866-28866/lab.galaxy.yahfa.demoApp I/YAHFA-Native: replace entry point from 0x791f808fa0 to 0x7bb37b93a0
2020-09-28 11:28:25.546 28866-28866/lab.galaxy.yahfa.demoApp I/YAHFA-Native: change access flags from 0x12080009 to 0x12080009
2020-09-28 11:28:25.546 28866-28866/lab.galaxy.yahfa.demoApp I/YAHFA-Native: replace method from 0x71233098 to 0x790472a1d8
2020-09-28 11:28:25.546 28866-28866/lab.galaxy.yahfa.demoApp I/YAHFA-Native: replace entry point from 0x791f808fa0 to 0x7bb37b93c0
2020-09-28 11:28:25.546 28866-28866/lab.galaxy.yahfa.demoApp I/YAHFA-Native: change access flags from 0x12080001 to 0x12080001 这里是 access_flags &= ~kAccFastInterpreterToInterpreterInvoke; 但执行前后access_flags是一样
2020-09-28 11:28:25.546 28866-28866/lab.galaxy.yahfa.demoApp I/YAHFA-Native: hook and backup done
2020-09-28 11:28:25.641 28866-28866/lab.galaxy.yahfa.demoApp E/origin: call Log.e() 这里永远都是调用原函数,不会进hook函数
大佬还是亲测一下吧
…------------------ 原始邮件 ------------------
发件人: "Ruikai Liu"<notifications@github.com>;
发送时间: 2020年11月25日(星期三) 中午11:20
收件人: "PAGalaxyLab/YAHFA"<YAHFA@noreply.github.com>;
抄送: "1281579248"<1281579248@qq.com>; "Comment"<comment@noreply.github.com>;
主题: Re: [PAGalaxyLab/YAHFA] Fix crash on Android 11 (#133)
hook的目标target方法原本的入口是什么?backup的trampoline会最终调用target原本的入口(如果是要解析的话可能就会根据native access flag错误解析到jni?)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
@rk700 没记错的话是backup解析成了JNI。的确我这边用edxposed的话会因为没有quick_code所以走解释,但是用YAHFA应用是有quick_code的,可能是跟系统是debug build有关系。 |
我这里debug或者release都是一样的情况。好吧,那我也说下自己的解决方案吧,我使用了Handler.sendMessageAtFrontOfQueue完美修复11.0闪退问题(完美不闪退,包括一加8),但是这样会导致hook时机会偏慢一点点,后面我开了一个线程去等待,可以解决时机问题,但是现在在一加8,上会发现部分游戏有崩溃现象,也是那个队列的问题(但是是因为这个线程引起的)。另外建议作者可以测试时候直接在hook完马上调用dowork(),不要放在button里去测试。这样即使测试正常,真正使用还是会发现有很多问题
…------------------ 原始邮件 ------------------
发件人: "双草酸酯"<notifications@github.com>;
发送时间: 2020年11月25日(星期三) 中午1:55
收件人: "PAGalaxyLab/YAHFA"<YAHFA@noreply.github.com>;
抄送: "1281579248"<1281579248@qq.com>; "Comment"<comment@noreply.github.com>;
主题: Re: [PAGalaxyLab/YAHFA] Fix crash on Android 11 (#133)
@rk700 没记错的话是backup解析成了JNI。的确我这边用edxposed的话会因为没有quick_code所以走解释,但是用YAHFA应用是有quick_code的,可能是跟系统是debug build有关系。
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
跟native这个flag没关系,而且R系统也是必须加这个flag。 |
native flag记得是很早之前引入的,主要为了防止hook不生效 现在好像是backup添加native flag,解析会变成jni stub?这几个方法的原本entry都是什么?R我只有模拟器显示几个方法的entry都是interp bridge,所以没有复现出来jni的情况 |
R系统在AS上的模拟器是正常的,并且以前做反射在AS上的模拟器都不需要pass,,所以作者,不要在模拟器上测试,会浪费时间还得不到准确答案。 |
Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 14181 (.bigbull.tdsgtw), pid 14181 (.bigbull.tdsgtw),我是觉得跟队列有关系,SI_QUEUE,所以我用我的方案是成功修复,不会闪退,只是一个时机问题。开一个线程等待就可以解决,然而跟libil2cpp会有冲突,需要attach(domain)那个 |
没有R真机 #130 的trace里面,确实有art_quick_generic_jni_trampoline,这个是有问题,不知道是怎么根据native flag解析到jni trampoline的 |
可以参考下sandhook这个 |
是在link阶段,应该不影响后面的运行时吧。这里的检查 |
我提交的更改已经提示比较明显了,其实并不是所属什么Native Flag问题。Debug下实际表现跟安卓10之前一样,问题实际在GC,目前不通过钩子无法较好解决这个问题。具体在ArtMethod的invoke函数里面,走到执行分支,进入汇编函数闪退。汇编函数检测异常,进入处理异常流程,根本原因是Moving GC。 |
目前有个比较复杂的解决办法,在 汇编shellcode处 加入结构体成员信息恢复流程,每次调用都恢复backup的成员信息,但是这样做影响性能。另一个方案不支持某些函数,兼容性不好,实现更复杂,容易引起崩溃,其实是更改hook框架的全部成员属性。 |
你提交的更改=检测到debug就直接崩掉 |
你仔细看看看就会知道实际上他崩的原因是 |
确实,LinkCode发生得比hook早,我之前改AOSP打了下log,那个方法被LinkCode的时候的确是没有quick_code的,不过既然这么说的话当时这里应该是走interpreter的。 |
好了查明白了
这里 |
程序员都是这么晚睡的吗。头发都还好吗 ------------------ 原始邮件 ------------------
发件人: "双草酸酯"<notifications@github.com>
发送时间: 2020年11月26日(星期四) 凌晨2:21
收件人: "PAGalaxyLab/YAHFA"<YAHFA@noreply.github.com>;
抄送: "shuajinanhai"<1281579248@qq.com>;"Comment"<comment@noreply.github.com>;
主题: Re: [PAGalaxyLab/YAHFA] Fix crash on Android 11 (#133)
|
@google-mirror 其实你连epic的备注也没看
|
是的, 我就看了这个issue, 我错了, 大佬 |
我们把 target 的 entry 替换成 hookTrampoline 了,从这个新的 entry 直接往前计算偏移得到 这个所谓的 那么我们是否可以在 hookTrampoline 前构造一个假的 |
@rk700 我也是这个思路。在trampoline前面多放allocate一点空间,使得 |
其实可以构造一个 |
|
我意思是,这样就可以在不炸掉程序的前提下获得几个字节的0,可以让 |
我觉得不如entrypoint前面多放几个0,这样还能保证 |
嗯,感觉可以试下,好像前面就只有2个uint32,放8个0应该就可以? |
@rk700 可以多放个,因为他还有 |
建议把整个class PACKED(4) OatQuickMethodHeader结构抄过来 |
@google-mirror 我就是这么做的。抄谷歌代码反算entrypoint的实际offset,保证最小的allocate |
这个会有跨系统版本的问题,过两年你就要准备一大堆struct在代码里
Deleted user <notifications@github.com> 于 2020年12月18日周五 18:05写道:
… 建议把整个class PACKED(4) OatQuickMethodHeader结构抄过来
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#133 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEGYNSNEGEY7M76IBAOMPLDSVMSPVANCNFSM4T54C2JA>
.
|
其实我感觉放9个0,然后抄个 |
首先, 我没细看, 只是抛个问题, 假设带上了字段, 返回了真正的OatQuickMethodHeader, 在DoGetCalleeSaveMethodCaller里可能会调用NativeQuickPcOffset(caller_pc), 不是照样崩溃么 |
@google-mirror |
@yujincheng08 current_code是真实的header, 不一定为false |
@google-mirror current_code是我们自己造的
|
@yujincheng08
按上面的说法, GetOatQuickMethodHeader返回的难道不是原始的header? |
static OatQuickMethodHeader* FromCodePointer(const void* code_ptr) {
uintptr_t code = reinterpret_cast<uintptr_t>(code_ptr);
uintptr_t header = code - OFFSETOF_MEMBER(OatQuickMethodHeader, code_);
return reinterpret_cast<OatQuickMethodHeader*>(header);
} |
其实又想了一下,即使把
|
这个报错信息是说没有找到匹配的method index? 是否有测试例子? |
按理来讲是任意oat的系统库里面丢异常就可以复现,但是我写了几个test case测复现不来。比较容易复现貌似的是氢OS的一加8P。 |
我看它是从method的declaring class里遍历方法对比的,method的declaring class应该是没有修改的 |
他是用栈顶的方法去拿art_method指针的,所以调用backup时候会拿到target方法的art_method,然后用它的entrypoint去拿header,但是target的entrypoint变成了trampoline,自然会崩。 |
我这里有一台android 9的一加6,是否可以用于复现? |
可以尝试: hook一个系统函数,然后使得系统函数抛出异常,不catch,看看dump出来的stack有没有问题。 实际上edxp最近修复之后,已经比较稳定了,只有一个用户报问题( ElderDrivers/EdXposed#740 (comment) ),而且是非hook函数下出问题,头大。 |
可能是因为我catch了所以才没复现。 |
大佬 请教一下为什么会死锁呢。 我这边在MEIZU 18 Android 11 机型上必现。 "main" prio=5 tid=1 Native |
Fix #132 #130 (probably)
鉴于某谜语壬宁愿在issue里面讲故事也不发PR,那我自己研究下好了
Since someone figured out but won't send a PR, I'll do it.
From the crash trace, it tries to call
artQuickGenericJniTrampoline
andart_quick_generic_jni_trampoline
, which will readdata_
fromArtMethod
instead ofentry_point_from_quick_compiled_code_
, which will get null pointer and it won't properly throw a Exception. But according to the Changelog, it might cause hook fail on Android O+, but it seems working for me with even debug build.Credits: @yujincheng08