欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]X加密-反调试-DumpDex-修复指令-重打包

[原创]X加密-反调试-DumpDex-修复指令-重打包

1.简介

如果有描述不准确的地方,还请各位大佬指正

某加密的最近的版本,网上资料比较少,是比较早的,没有混淆的,以及没有指令抽取的

这里分析的实例,是某加密直接把壳代码写到了原始dex里面去



    1)反调试     网上的大部分资料都是些基础的反调试,而且SO是没有经过ollvm混淆的,所以都是些比较直观的能看到代码

                      而现在大部分是ollvm混淆过,另外加UPX压缩壳,以及SO自解密等

    2)dump dex,另一种找到dex.035的地址

    3) 修复被抽取指令,找到codeitem的insns指针,取出指令,填充到被nop的dex里面去 

    4) 重打包APK 应该是做了对抗dex2smali,无法转回去,不过有办法

2. 调试

先看看Application

// 各家的壳都类似, attach和onCreate做初始化工作

  protected void attachBaseContext(Context arg6) {

        // some code 

         调用2个native方法初始化壳,以及hook相关还原函数

        N.l(((Application)this), "com.dmy.jiagushell");

        N.r(((Application)this), "android.app.Application");

   }

    public void onCreate() {

     // some code

      调用真正apk的Application

       N.ra(((Application)this), "android.app.Application");

            if(S.n != null) {

                S.n.onCreate();

            }

    }

这个样本解压开虽然直接能看到dex,但是还是通过调试dump了一次,这样可以了解一下反调试


SO被ollvm混淆了,看起来很费力,所以都是从一些关键点下断点去调试和绕过


1-反调试

关于反调试,有文章介绍了17中反调试,可以参考一下,现有资料博客能搜到的反调试,就这几种

      时间检测,  检测status,检测ida端口,以及java层的反调试

但是现在的壳已经不止这几种了,多而杂,现在常见的信号反调试,以及断点检测就比较麻烦


可以参考   IDA技巧 这位大神的方法,定位到initarray段的入口,和进入jni_onload的地址,


1.1  信号反调试,常识性的反调试,可以在bad_signal下断

 信号函数通常是      signal(SIGN_NO, antidebug_func)



跟进去看看 0xB388D391所在的函数内容,这个函数要在解密后才可以看到,就是获取pid,杀死



信号1,2,3的定义是

       

SIGHUP     终止进程     终端线路挂断
SIGINT     终止进程     中断进程
SIGQUIT   建立CORE文件终止进程,并且生成core文件      

绕过方法就是,signal注册信号函数的时候,吧函数地址改为0,让他注册失败


1.2

进入到initarray段的时候,会有很多个函数,我的做法是通常跳过,如果某一次跳过崩了,就进去找反调试

,就是这里的BLX R4,是循环进入initarray段内的函数



fget断点后看到status检测,修改为0即可,后面还会遇到检测,应该是检测了多次,可以用hook过掉,或者IDA直接手动改掉端口号


然后转换为数字 ,这个比较简单直接改掉字符串就行。


1.3 时间反调试,通常就是检测代码运行时间,暴力一点,R0保存的传入的参数,tm所以直接写0

 

struct timeval tm;

gettimeofday(&tm, NULL);




时间反调试是status检测是在同一函数内,这个结构看起来比较费力,而且比较多的是无效的if语句,还是找找汇编的关键点来的快


1.4 在application的几个native函数

找前面提到的java函数注册为native函数的地址 



看R2指针数据 是结构体,也就是0xBEE221E0

typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;


对应结构体,BEE221C8地址处就是函数名称,bee22198就是方法签名,可以看下面2张图

  也就是在java层的attachBaseContext中的第一个 


则be867090就是壳的第一个执行java层native函数



到第二个函数,这个点不像其他的  status是检测端口,时间是检测运行是否过长,以及信号注册函数

猜测可能是一个全局变量,存在这里,然后有我还没有发现的检测点,然后后面在判断这个全局变量(不知道这个解释是否合理)

如下图是运行到N.r这个里面进去

 

 就是这里的N.r这是个native函数,又一次检测,通过计算在调试的时候 上一步的地方 ,也就是0xB38ABC38  看出是在比较这个地址的值,不明白是什么检测方式,反正到这里下一句被崩,所以改了下寄存器先绕过吧


这里的反调试可能在检测一个全局变量


反调试可能还有检测断点的,偶尔会崩掉,这里请教下各位大佬,怎么快速定位检测断点的反调试


2.1  关于dumpdex,其实可以dump的点很多,我选择defineclass位于classlinker里面

是以为他的第三个参数是java类对应的签名就是哪个  env->FindClass的那个参数

由此可以判断此时加载的这个类是位于北加固的dex里面的,顺着这个地方可以找到DEX



根据这个参数可以找到dex


接下来, 看源码可以知道,第5个参数是dex引用,多余的参数在栈里,计算好地址 + 4 进去就是dex引用地址,然后这里比较奇怪的是dex的这个地址要加上4就能找到dex.035字符了,反正是加固前的DEX找到了,这里还要再琢磨下

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功