发表日期: 2021-04-30 09:59:15 浏览次数:133
偃师企业微信公众号小程序开发公司、偃师企业网页设计方案、偃师做网站开发价格、偃师微信公众号制作运营报价明细表、偃师网站设计公司费用、偃师网站推广大概需要多少钱
偃师区,隶属于河南省洛阳市,位于河南省西部,总面积668.58平方千米 [1] 。截至2019年末,偃师区总人口63.2万人 [3] ,截至2020年6月,偃师区下辖4个街道、9个镇 [2] ,偃师区人民政府驻槐新街道民主路27号。 [24]
周,设偃师县。1993年,偃师撤县设市。 [4] 2021年3月,撤销县级偃师市,设立洛阳市偃师区 [25] 。偃师区是河南省制造业高质量发展综合评价试点市 [5] 、革命文物保护利用片区分县 [6] 、国家卫生城市(区)。 [18]
2019年,偃师区实现地区生产总值443.6亿元,固定资产投资193.8亿元,一般公共预算收入24.6亿元,社会消费品零售总额222.6亿元。 [7]
入手一个apk,我们该如何从头开始分析它那,讲apk分析的博客写的不少,但是很多都是大神写的,把关键点摘出来,让我们分享胜利的果实,但是那。。。。。。。。哎,可能是我更喜欢思路吧,更想问问大神是如何做到的,如何想的。
得了,废话删了。
下面说下目标,最近面试又被刷了,所以手撕一个apk找找感觉,手工硬调试,配置frida写动态脚本辅助分析
测试
你没看错,第一个就是测试。 测试要尽可能的全面,详细,尽可能一对一的找原因和结果
root测试
magisk测试,隐藏非隐藏,magisk报名
ida 和frida 开启,测试
ro.debuggable测试,java附加测试
说一下测试结果,上面这些一个不能开,root蹦,magisk非隐藏蹦(检查magisk的root),maigsk 不换包名蹦,java 附加,直接断开,ida 也蹦。单卡frida做不到,因为,必须root不蹦才行。感觉遇到了个大麻烦,一个坑一个坑的趟。
收集资料
想要分析加固,必有反调试啊,别人写的反调试来一份,了解原理,记录所有反调试点
反root,magisk,怎么怎么弄的找一找资料,寻找关键点,记录下来,可以挨个试
不写了,反正就是尽可能多了解这个加固的资料。
我们主要是要调试他,肯定要过反调试的,root权限,magisk什么的也想过了试试。测试的结果是,检查到root就崩溃,
如果我们想用frida分析,首先可能就要通过脚本分析找到检测的点,过掉root检查,和magisk检查,以及frida检测
如果我们直接附加调试,需要过掉反调试,root,magisk ,不必处理frida
但是我都没有,首先我分析了java代码,看了一下他主要的so加载点,然后用frida脚本hook root检测可能的点,magisk 更换包名安转(最新版的的可能有点问题,有的手机更换包名不让用,可以用supersu,或者把包名卸载),肯定还有frida检测,所以我们要尽可能让apk死在frida检测的位置,而不是root检测的位置
Thread id是我后面发现很多线程后单独加上的
从这里可以看到su文件检测的位置,通过修改这个函数的返回值,发现日志确实跑的比以前多一点了。
然后是过frida检测,网上很多种凡是,什么检测maps,循环检测内存,read函数读文件,等等,实在太多了,frida脚本跑出了很多frida的关键字,但是感觉都有点问题,也不好修改。于是就放弃了使用脚本继续分析下去,改用动态调试找到frida检测的点,过掉,然后再用脚本辅助进行分析。
主要思维就是通过hook,分析加固逻辑,得出关键的点,然后利用动态调试,调试这些关键位置,这样循环推进,一环一环的解。
这就是理想很丰满,现实很骨感吗,ida f5大发完全失效,不是无法反汇编,就是反汇编过来我都觉得不对劲,入口函数看到一个init_proc函数,init_arry没找到,so载入的时候报错了,肯定做了特殊处理了(看到init_proc,我开始以为不会有init_arry了,实际上有)。
动态调试,init_proc函数调着调着崩了,关键是,只调用了svc
<font size=6>写到这我必须要吐槽一下ida7.5,调试别的我没试过,但是armv7,坑也太多了,我给列下</font>:
无故指令报错,arm 和thumb切换的时候,经常在libc库就崩了,关键是还崩在我下断点的位置不远,感觉这是往我心脏上插刀子啊。
就是上面svc 2w+ 哪个,经常崩,好像没有不崩的时候
python3脚本不好用,一跑自动化脚本,就卡死,救不了
开的时间长了,或者调试的时间长了,反正也不知道怎么回事,就在跑分析了,动也不动,关键是,时间也太长了,我跑了一晚上第二天一看,还没跑完,调也调不了,只能重开
用ida7.0 能好一些,指令报错很少了,自动化脚本,也会好一些,
整个崩溃的代码,从头到尾,基本都分析过了,但是没有发现什么反调试的痕迹,关键是还是,错误的位置还是动态的。
断点反调试
后续接着调试,这个so是有init_array 的,我开始没发觉,ida只点了,so库加载的断点,这个so,做了特殊处理,估计是节头表删了,某些位置做了加密,怎么跑都跑不过去,我觉得,这个so的init执行玩肯定要执行下一个so的init啊,结果怎么跑也不行。后来我无意间在ptarce下了个断点试试,结果一直崩溃,ida7.5有bug。反正就是过不去了,不知道哪里有问题。
调试过不去,于是我找脚本试试运气,看看脚本是否跑过了这一块
找到这这些函数以后,发现中间还有函数没有hook,jni_onload(这个后面写)
通过frida,精准的定位到调用位置的偏移地址,然后在便宜位置下断点,调试就可以了
当然,即使这样最后,手工调试,依然没有完全的跑过去,frida的脚本,经过改善,最后跑到应用层,过掉了加固的检测,但是被应用本身的root检测被杀了,这个应用有两个地方进行root检测。反调试,最后调试到了多线程的位置,但是可能有线程同步的问题,直接睡眠没过去。看了hook脚本,后续可能没什么了,就当失败了吧。当然,后续还会有下文的,埋个伏笔。
init_proc入口的技术
开始通过 init_proc函数,前面的几个存储好的内存数据,计算好要操作的数据
申请内存的地址+53E4C,就是跳转到申请内存函数的第一个地址( 跑了几次,结果相同53E4C )
两边的内容是完全相同的,在so文件偏移 0x61FC4,这个地址,可以通过偏移和源文件对比,而且这个位置,刚好在init_proc跑的时候,跑了前半部分,这一部分没有跑。
还有copy函数,以及地址和数据大小问题,上面的copy次数可以看出来,其实主要大小就是第二次,而后三次,应该是用来反断点调试的,确保你调试这段copy过去的函数的时候,能刚好在copy过去要执行的代码上。
通过mmap 将源地址内容清空 ,清空的内容是 base + E000 ,然后将复制到malloc中的内容,在复制回去,解密
解密数据 eor 0x50 (310第一个数据开始对比)
下面这个函数是copy函数,我在这个位置下了断点,结果在copy过去的时候,断点错位,指令无法解析
init_array系列函数
init_array函数应该有两次的 fopen /proc/self/status ,检测TracerPid。
这两个ptrace,我是直接在open函数下断点,然后硬调试出来的,而且,最后我发现他调用fgets函数来获取结果,这个fgets函数在这个加固中很关键,许多位置都是直接调用fgets返回的,像frida内存maps检测的时候。而且,我还发现他特别喜欢调用时间函数,我hook的是 gettimeofday 这函数,然后每次这个函数一出来,都是关键位置,直接找到相关代码了。
特征检测
这部分代码在哪里找到的我忘了,但是fgets是我的幸运函数(我想以后可能不会有人用了),我hook open函数以后,如果打开关键文件,我就hook fgets,果然,我看他打开了maps文件,然后就跟我下去,发现了这个汇编写的比较函数:
多线程与反调试创建线程的代码
在第一个线程创建完了以后有一个java debug检测
然后有一次/proc/getpid()/status ,检查TracerPid。
之后在后几个线程里,有检测,我尝试过睡眠过几个线程,但是效果不好全部卡死了,怀疑可能有线程同步部分,最后这一部分没有好好分析。
wchan反调试,是无意间发现的,我当时hook的popen ,我以为他会用 mount 来检查magisk,是我菜了,然后无意间发现了这个, proc/self/wchan 这个文件会有个字符串,attach以及调试的时候是不同的,可以通过读取这个文件做反调试。
还有一个线程,循环检测TracerPid
可能还有linker 反调试什么的,但是后学没有接着调试了。
目前就发现了这些
5.jni jni_onload
函数dlopen libdvm.so好像还有libmthook.so库(这个,我后续的frida分析日志,打印的日志不太匹配,不太确定了)
然后会调用attachbaseContext的这个位置的函数
这个 l 是个native
public static native boolean l(Application application, String str);
就到这里了,后续没有在分析了,frida已经跑过去了,硬分析没什么意义了。
frida so文件检测
大部分都是通过maps文件检测,另外还有内存扫射frida的,端口检测的这个不说了
这里我提供一种隐藏maps文件检测的方法,这个方法的来自Riru 的 hide self maps
大致原理就是就这一段内存mmap一下,不过这个代码,必须放到一个so库中,通过获取符号调用,不能隐藏它本身
magisk检测
可能是我这个有点老,没有只有包名和so,这里我提供一种git上找到的,原理不讲了,有时间magisk单开一个
如何预防idf反汇编,只谈论armv7
不知道为什么好像没有人写过这个问题
下面这个函数,就是其中一个例子。
ARM 汇编和 c函数调用是有标准的,ARM调用标准(ATPC)与函数参数传递,我就写一点,剩下网上查吧
而ida这个反编译,完全是基于这个规则来处理的,在这个so中,完全改变了参数使用的寄存器,所以反编译失败。
另外我们还可以基于llvm 后端编译器函数的编译特征来让ida无法自动识别函数长度(这个算是个人猜测,毕竟没用完全看过llvm arm编译器后端 函数编译的生产代码)。
大致是,函数开栈的时候,有几个固定的栈操作,闭栈的时候也一样,而我们完全可以自己用汇编随意写,最后只要保证栈平衡就好。甚至我们可以用闭栈用到的指令去开栈,开栈的指令闭栈,以前学x86的时候,x86编译出来的函数也有这种特征,所以。。。。。。。。。。
就到这里吧,不是闲的蛋疼的人,不要调试了,找到frdia检测的地方过掉,然后直接ptrace就好。

偃师企业微信公众号小程序开发公司、偃师企业网页设计方案、偃师做网站开发价格、偃师微信公众号制作运营报价明细表、偃师网站设计公司费用、偃师网站推广大概需要多少钱