dex调试_调试dex - CSDN
精华内容
参与话题
  • 代码动态调试: 代码动态调试技术,一般是通过观察程序在运行过程中的状态,如寄存器内容,函数执行结果,内存使用情况等等,分析函数功能,明确代码逻辑,查找可能存在的漏洞 工具:IDA 条件:AndroidManifest....

    代码动态调试:

    代码动态调试技术,一般是通过观察程序在运行过程中的状态,如寄存器内容,函数执行结果,内存使用情况等等,分析函数功能,明确代码逻辑,查找可能存在的漏洞

    工具:IDA

    条件:AndroidManifest.xml里的Android:debuggable="true"

    步骤:

    1)如果AndroidManifest.xml里的Android:debuggable="false",尝试修改为true,再使用Apktool重新签名,安装,如果成功就可以进行调试了;

    2)安装android_server(在ida安卓包中),然后端口转发adb forward tcp:23946 tcp:23496

    3)使用ida打开apk文件中的dex文件

    4)选择Debugger-Debugger options-set spectific options进行调试

     具体步骤:

    动态调试:

    启动android_server并且转发端口:

     

     

     

    打开dex文件:

     

     

     

    然后点击debugger选项中的debugger options,选择set specific options

     

     

     

    设置完上面的以后,点击debugger选项下的attach to process:

     

     

    弹出的对话框点击ok就可以来到调试页面了:

     

     

    如果你看不懂smali代码,这里也可以加载java代码来进行调试(这里需要先把class.dex文件反编译成java代码):

    还是在debugger选项下,选择open source file

     

     

     

     

     

    接下来就是下断点了,可以在java代码中下断点,也可以直接在smali中下断点,这里用smali

    Ctrl+P查找onclick

     

     

    双击onClick,进入到该函数:

     

     

     

     

    F2下断点,F8单步调试:

     

     

     

    利用java调试步骤是一样的,就不演示了。

     

    转载于:https://www.cnblogs.com/xiaoqiyue/p/10485168.html

    展开全文
  • 第一篇:如何使用Eclipse动态调试smali源码 第二篇:如何使用IDA动态调试SO文件 现在要说的就是最后一篇了,如何应对Android中一些加固apk安全防护,在之前的两篇破解文章中,我们可以看到一个是针对于Java层的...

    一、前言

    今天总算迎来了破解系列的最后一篇文章了,之前的两篇文章分别为:

    第一篇:如何使用Eclipse动态调试smali源码 

    第二篇:如何使用IDA动态调试SO文件

    现在要说的就是最后一篇了,如何应对Android中一些加固apk安全防护,在之前的两篇破解文章中,我们可以看到一个是针对于Java层的破解,一个是针对于native层的破解,还没有涉及到apk的加固,那么今天就要来介绍一下如何应对现在市场中一些加固的apk的破解之道,现在市场中加固apk的方式一般就是两种:一种是对源apk整体做一个加固,放到指定位置,运行的时候在解密动态加载,还有一种是对so进行加固,在so加载内存的时候进行解密释放。我们今天主要看第一种加固方式,就是对apk整体进行加固。

     

    二、案例分析

    按照国际惯例,咋们还是得用一个案例来分析讲解,这次依然采用的是阿里的CTF比赛的第三题:

    题目是:要求输入一个网页的url,然后会跳转到这个页面,但是必须要求弹出指定内容的Toast提示,这个内容是:祥龙!

    了解到题目,我们就来简单分析一下,这里大致的逻辑应该是,输入的url会传递给一个WebView控件,进行展示网页,如果按照题目的逻辑的话,应该是网页中的Js会调用本地的一个Java方法,然后弹出相应的提示,那么这里我们就来开始操作了。

     

    按照我们之前的破解步骤:

    第一步:肯定是先用解压软件搞出来他的classes.dex文件,然后使用dex2jar+jd-gui进行查看java代码

    擦,这里我们看到这里只有一个Application类,从这里我们可以看到,这个apk可能被加固了,为什么这么说呢?因为我们知道一个apk加固,外面肯定得套一个壳,这个壳必须是自定义的Application类,因为他需要做一些初始化操作,那么一般现在加固的apk的壳的Application类都喜欢叫StubApplication。而且,这里我们可以看到,除了一个Application类,没有其他任何类了,包括我们的如可Activity类都没有了,那么这时候会发现,很蛋疼,无处下手了。

     

    第二步:我们会使用apktool工具进行apk的反编译,得到apk的AndroidManifest.xml和资源内容

     

    反编译之后,看到程序会有一个入口的Activity就是MainActivity类,我们记住一点就是,不管最后的apk如何加固,即使我们看不到代码中的四大组件的定义,但是肯定会在AndroidManifest.xml中声明的,因为如果不声明的话,运行是会报错的。那么这里我们也分析完了该分析的内容,还是没发现我们的入口Activity类,而且我们知道他肯定是放在本地的一个地方,因为需要解密动态加载,所以不可能是放在网上的,肯定是本地,所以这里就有一些技巧了:

    当我们发现apk中主要的类都没有了,肯定是apk被加固了,加固的源程序肯定是在本地,一般会有这么几个地方需要注意的:

    1、应用程序的asset目录,我们知道这个目录是不参与apk的资源编译过程的,所以很多加固的应用喜欢把加密之后的源apk放到这里

    2、把源apk加密放到壳的dex文件的尾部,这个肯定不是我们这里的案例,但是也有这样的加固方式,这种加固方式会发现使用dex2jar工具解析dex是失败的,我们这时候就知道了,肯定对dex做了手脚

    3、把源apk加密放到so文件中,这个就比较难了,一般都是把源apk进行拆分,存到so文件中,分析难度会加大的。

    一般都是这三个地方,其实我们知道记住一点:就是不管源apk被拆分,被加密了,被放到哪了,只要是在本地,我们都有办法得到他的。

     

    好了,按照这上面的三个思路我们来分析一下,这个apk中加固的源apk放在哪了?通过刚刚的dex文件分析,发现第二种方式肯定不可能了,那么会放在asset目录中吗?我们查看asset目录:

    看到asset目录中的确有两个jar文件,而且我们第一反应是使用jd-gui来查看jar,可惜的是打开失败,所以猜想这个jar是经过处理了,应该是加密,所以这里很有可能是存放源apk的地方。但是我们上面也说了还有第三种方式,我们去看看libs目录中的so文件:

    擦,这里有三个so文件,而我们上面的Application中加载的只有一个so文件:libmobisec.so,那么其他的两个so文件很有可能是拆分的apk文件的藏身之处。

     

    通过上面的分析之后,我们大致知道了两个地方很有可能是源apk的藏身地方,一个是asset目录,一个是libs目录,那么分析完了之后,我们发现现在面临两个问题:

    第一个问题:asset目录中的jar文件被处理了,打不开,也不知道处理逻辑

    第二个问题:libs目录中的三个so文件,唯一加载了libmobisec.so文件了

    那么这里现在的唯一入口就是这个libmobisec.so文件了,因为上层的代码没有,没法分析,下面来看一下so文件:

    擦,发现蛋疼的是,这里没有特殊的方法,比如Java_开头的什么,所以猜测这里应该是自己注册了native方法,混淆了native方法名称,那么到这里,我们会发现我们遇到的问题用现阶段的技术是没法解决了。

     

    三、获取正确的dex内容

    分析完上面的破解流程之后,发现现在首要的任务是先得到源apk程序,通过分析知道,处理的源apk程序很难找到和分析,所以这里就要引出今天说的内容了,使用动态调试,给libdvm.so中的函数:dvmDexFileOpenPartial 下断点,然后得到dex文件在内存中的起始地址和大小,然后dump处dex数据即可。

    那么这里就有几个问题了:

    第一个问题:为何要给dvmDexFileOpenPartial 这个函数下断点?

    因为我们知道,不管之前的源程序如何加固,放到哪了,最终都是需要被加载到内存中,然后运行的,而且是没有加密的内容,那么我们只要找到这的dex的内存位置,把这部分数据搞出来就可以了,管他之前是如何加固的,我们并不关心。那么问题就变成了,如何获取加载到内存中的dex的地址和大小,这个就要用到这个函数了:dvmDexFileOpenPartial 因为这个函数是最终分析dex文件,加载到内存中的函数:

    int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);

    第一个参数就是dex内存起始地址,第二个参数就是dex大小。

     

    第二个问题:如何使用IDA给这个函数下断点

    我们在之前的一篇文章中说到了,在动态调试so,下断点的时候,必须知道一个函数在内存中的绝对地址,而函数的绝对地址是:这个函数在so文件中的相对地址+so文件映射到内存中的基地址,这里我们知道这个函数肯定是存在libdvm.so文件中的,因为一般涉及到dvm有关的函数功能都是存在这个so文件中的,那么我们可以从这个so文件中找到这个函数的相对地址,运行程序之后,在找到libdvm.so的基地址,相加即可,那么我们如何获取到这个libdvm.so文件呢?这个文件是存放在设备的/system/lib目录下的:

    那么我们只需要使用adb pull 把这个so文件搞出来就可以了。

     

    好了,解决了这两个问题,下面就开始操作了:

    第一步:运行设备中的android_server命令,使用adb forward进行端口转发

    这里的android_server工具可以去ida安装目录中dbgsrv文件夹中找到

     

    第二步:使用命令以debug模式启动apk

    adb shell am start -D -n com.ali.tg.testapp/.MainActivity

    因为我们需要给libdvm.so下断点,这个库是系统库,所以加载时间很早,所以我们需要像之前给JNI_OnLoad函数下断点一样,采用debugger模式运行程序,这里我们通过上面的AndroidManifest.xml中,得到应用的包名和入口Activity:

    而且这里的android:debuggable=true,可以进行debug调试的。

     

    第三步:双开IDA,一个用于静态分析libdvm.so,一个用于动态调试libdvm.so

    通过IDA的Debugger菜单,进行进程附加操作:

     

    第四步:使用jdb命令启动连接attach调试器

    jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700

    但是这里可能会出现这样的错误:

    这个是因为,我们的8700端口没有指定,这时候我们可以通过Eclipse的DDMS进行端口的查看:

    看到了,这里是8600端口,但是基本端口8700不在,所以这里我们有两种处理方式,一种是把上面的命令的端口改成8600,还有一种是选中这个应用,使其具有8700端口:

    点击这个条目即可,这时候我们在运行上面的jdb命令:

    处于等待状态。

     

    第四步:给dvmDexFileOpenPartial函数下断点

    使用一个IDA静态分析得到这个函数的相对地址:43308

    在动态调试的IDA解密,使用Ctrl+S键找到libdvm.so的在内存中的基地址:41579000

    然后将两者相加得到绝对地址:43308+41579000=415BC308,使用G键,跳转:

    跳转到dvmDexFileOpenPartial函数处,下断点:

     

    第五步:点击运行按钮或者F9运行程序

    之前的jdb命令就连接上了:

    IDA出现如下界面,不要理会,一路点击取消按钮即可

    运行到了dvmDexFileOpenPartial函数处:

    使用F8进行单步调试,但是这里需要注意的是,只要运行过了PUSH命令就可以了,记得不要越过下面的BL命令,因为我们没必要走到那里,当执行了PUSH命令之后,我们就是使用脚本来dump处内存中的dex数据了,这里有一个知识点,就是R0~R4寄存器一般是用来存放一个函数的参数值的,那么我们知道dvmDexFileOpenPartial函数的第一个参数就是dex内存起始地址,第二个参数就是dex大小:

    那么这里就可以使用这样的脚本进行dump即可:

    static main(void)
    {
        auto fp, dex_addr, end_addr;
        fp = fopen(“F:\\dump.dex”, “wb”);
        end_addr = r0 + r1;
        for ( dex_addr = r0; dex_addr < end_addr; dex_addr ++ )
            fputc(Byte(dex_addr), fp);
    }

    脚本不解释了,非常简单,而且这个是固定的格式,以后dump内存中的dex都是这段代码,我们将dump出来的dex保存到F盘中。

    然后这时候,我们使用:Shirt+F2 调出IDA的脚本运行界面:

    点击运行,这里可能需要等一会,运行成功之后,我们去F盘得到dump.dex文件,其实这里我们的IDA使命就完成了,因为我们得到了内存的dex文件了,下面开始就简单了,只要分析dex文件即可

     

    四、分析正确的dex文件内容

    我们拿到dump.dex之后,使用dex2jar工具进行反编译:

    可惜的是,报错了,反编译失败,主要是有一个类导致的,开始我以为是dump出来的dex文件有问题,最后我用baksmali工具得到smali文件是可以的,所以不是dump出来的问题,我最后用baksmali工具将dex转化成smali源码:

    java -jar baksmali-2.0.3.jar -o C:\classout/ dump.dex

    得到的smali源码目录classout在C盘中:

    我们得到了指定的smali源码了。

     

    那么下面我们就可以使用静态方式分析smali即可了:

    首先找到入口的MainActivity源码:

    这里不解释了,肯定是找按钮的点击事件代码处,这里是一个btn_listener变量,看这个变量的定义:

    是MainActivity$1内部类定义,查看这个类的smali源码,直接查看他的onClick方法:

    这里可以看到,把EditText中的内容,用Intent传递给WebViewActivity中,但是这里的intent数据的key是加密的。

    下面继续看WebViewActivity这个类:

    我们直接查找onCreate方法即可,看到这里是初始化WebView,然后进行一些设置,这里我们看到一个@JavascriptInterface

    这个注解,我们在使用WebView的时候都知道,他是用于Js中能够访问的设置了这个注解的方法,没有这个注解的方法Js是访问不了的

     

    注意:

    我们知道这个注解是在SDK17加上的,也就是Android4.2版本中,那么在之前的版本中没有这个注解,任何public的方法都可以在JS代码中访问,而Java对象继承关系会导致很多public的方法都可以在JS中访问,其中一个重要的方法就是  getClass()。然后JS可以通过反射来访问其他一些内容。那么这里就有这个问题了:比如下面的一段JS代码:

    <script>
    function findobj(){
    for (var obj in window) { 
    if ("getClass" in window[obj]) { 
    return window[obj] 


    }
    </script> 

    看到了,这段js代码很危险的,使用getClass方法,得到这个对象(java中的每个对象都有这个方法的),用这个方法可以得到一个java对象,然后我们就可以调用这个对象中的方法了。这个也算是WebView的一个漏洞了。

    所以通过引入 @JavascriptInterface注解,则在JS中只能访问 @JavascriptInterface注解的函数。这样就可以增强安全性。

     

    回归到正题,我们上面分析了smali源码,看到了WebView的一些设置信息,我们可以继续往下面看:

    这里的我们看到了一些重要的方法,一个是addJavascriptInterface,一个是loadUrl方法。

    我们知道addjavaascriptInterface方法一般的用法:

    mWebView.addJavascriptInterface(new JavaScriptObject(this), "jiangwei");

    第一个参数是本地的Java对象,第二个参数是给Js中使用的对象的名称。然后js得到这个对象的名称就可以调用本地的Java对象中的方法了。

    看了这里的addjavaascriptInterface方法代码,可以看到,这里用

    ListViewAutoScrollHelpern;->decrypt_native(Ljava/lang/String;I)Ljava/lang/String;

    将js中的名称进行混淆加密了,这个也是为了防止恶意的网站来拦截url,然后调用我们本地的Java中的方法。

     

    注意:

    这里又存在一个关于WebView的安全问题,就是这里的js访问的对象的名称问题,比如现在我的程序中有一个Js交互的类,类中有一个获取设备重要信息的方法,比如这里获取设备的imei方法,如果我们的程序没有做这样名称的混淆的话,破解者得到这个js名称和方法名,然后就伪造一个恶意url,来调用我们程序中的这个方法,比如这样一个例子:

    然后在设置js名称:

    我们就可以伪造一个恶意的url页面来访问这个方法,比如这个恶意的页面代码如下:

    运行程序:

    看到了,这里恶意的页面就成功的调用了程序中的一个重要方法。

    所以,我们可以看到,对Js交互中的对象名称做混淆是必要的,特别是本地一些重要的方法。

     

    回归到正题,我们分析完了WebView的一些初始化和设置代码,而且我们知道如果要被Js访问的方法,那么必须要有@JavascriptInterface注解 因为在Java中注解也是一个类,所以我们去注解类的源码看看那个被Js调用的方法:

    这里看到了有一个showToast方法,展示的内容:\u7965\u9f99\uff01 ,我们在线转化一下:

    擦,这里就是题目要求展示的内容。

     

    好了,到这里我们就分析完了apk的逻辑了,下面我们来整理一下:

    1、在MainActivity中输入一个页面的url,跳转到WebViewActivity进行展示

    2、WebViewActivity有Js交互,需要调用本地Java对象中的showToast方法展示消息

    问题:

    因为这里的js对象名称进行了加密,所以这里我们自己编写一个网页,但是不知道这个js对象名称,无法完成showToast方法的调用

     

    五、破解的方法

    下面我们就来分析一下如何解决上面的问题,其实解决这个问题,我们现有的方法太多了

    第一种方法:修改smali源码,把上面的那个js对象名称改成我们自己想要的,比如:jiangwei,然后在自己编写的页面中直接调用:jiangwei.showToast方法即可,不过这里需要修改smali源码,在使用smali工具回编译成dex文件,在弄到apk中,在运行。方法是可行的,但是感觉太复杂,这里不采用

    第二种方法:利用Android4.2中的WebView的漏洞,直接使用如下Js代码即可

    这里根本不需要任何js对象的名称,只需要方法名就可以完成调用,所以这里可以看到这个漏洞还是很危险的。

    第三种方法:我们看到了那个加密方法,我们自己写一个程序,来调用这个方法,尽然得到正确的js对象名称,这里我们就采用这种方式,因为这个方式有一个新的技能,所以这里我就讲解一下了。

    那么如果用第三种方法的话,就需要再去分析那个加密方法逻辑了:

    android.support.v4.widget.ListViewAutoScrollHelpern在这个类中,我们再去查找这个smali源码:

    这个类加载了libtranslate.so库,而且加密方法是native层的,那么我们用IDA查看libtranslate.so库:

    我们搜一下Java开头的函数,发现并没有和decrypt_native方法对应的native函数,说明这里做了native方法的注册混淆,我们直接看JNI_OnLoad函数:

    这里果然是自己注册了native函数,但是分析到这里,我就不往下分析了,为什么呢?因为我们其实没必要搞清楚native层的函数功能,我们知道了Java层的native方法定义,那么我们可以自己定义一个这么个native方法来调用libtranslate.so中的加密函数功能:

    我们新建一个Demo工程,仿造一个ListViewAutoScrollHelpern类,内部在定义一个native方法:

    然后我们在MainActivity中加载libtranslate.so:

    然后调用那个native方法,打印结果:

    这里的方法的参数可以查看smali源码中的那个方法参数:

    点击运行,发现有崩溃的,我们查看log信息:

    0?wx_fmt=pnguploading.4e448015.gif转存失败重新上传取消

    是libtranslate.so中有一个PagerTitleStripIcsn类找不到,这个类应该也有一个native方法,我们在构造这个类:

    再次运行,还是报错,原因差不多,还需要在构造一个类:TaskStackBuilderJellybeann

    好了,再次点击运行:

    OK了,成功了,从这个log信息可以看出来了,解密之后的js对象名称是:SmokeyBear,那么下面就简单了,我们在构造一个url页面,直接调用:SmokeyBear.showToast即可。

     

    注意:

    这里我们看到,如果知道了Java层的native方法的定义,那么我们就可以调用这个native方法来获取native层的函数功能了,这个还是很不安全的,但是我们如何防止自己的so被别人调用呢?可以在so中的native函数做一个应用的签名校验,只有属于自己的签名应用才能调用,否则直接退出。

     

    六,开始测试

    上面已经知道了js的对象名称,下面我们就来构造这个页面了:

    那么这里又有一个问题了,这个页面构造好了?放哪呢?有的同学说我有服务器,放到服务器上,然后输入url地址就可以了,的确这个方法是可以的,但是有的同学没有服务器怎么办呢?这个也是有方法的,我们知道WebView的loadUrl方法是可以加载本地的页面的,所以我们可以把这个页面保存到本地,但是需要注意的是,这里不能存到SD卡中,因为这个应用没有读取SD的权限,我们可以查看他的AndroidManifest.xml文件:

    我们在不重新打包的情况下,是没办法做到的,那么放哪呢?其实很简单了,放在这个应用的/data/data/com.ali.tg.testapp/目录下即可,因为除了SD卡位置,这个位置是最好的了,那么我们知道WebView的loadUrl方法在加载本地的页面的格式是:

    file:///data/data/com.ali.tg.testapp/crack.html

    那么我们直接输入即可

     

    注意:

    这里在说一个小技巧:就是我们在一个文本框中输入这么多内容,是不是有点蛋疼,我们其实可以借助于命令来实现输入的,就是使用:adb shell input text ”我们需要输入的内容“。

    具体用法很简单,打开我们需要输入内容的EditText,点击调出系统的输入法界面,然后执行上面的命令即可:

    不过这里有一个小问题,就是他不识别分号:

    不过我们直接修改成分号点击进入:

    运行成功,看到了toast的展示。

    http://download.csdn.net/detail/jiangwei0910410003/9543445


    七、内容整理

    到这里我们就破解成功了,下面来看看整理一下我们的破解步骤:

    1、破解的常规套路

    我们按照破解惯例,首先解压出classses.dex文件,使用dex2jar工具查看java代码,但是发现只有一个Application类,所以猜测apk被加壳了,然后用apktool来反编译apk,得到他的资源文件和AndroidManifest.xml内容,找到了包名和入口的Activity类。

    2、加固apk的源程序一般存放的位置

    知道是加固apk了,那么我们就分析,这个加固的apk肯定是存放在本地的一个地方,一般是三个地方:

    1》应用的asset目录中

    2》应用的libs中的so文件中

    3》应用的dex文件的末尾

    我们分析了一下之后,发现asset目录中的确有两个jar文件,但是打不开,猜测是被经过处理了,所以我们得分析处理逻辑,但是这时候我们也没有代码,怎么分析呢?所以这时候就需要借助于dump内存dex技术了:

    不管最后的源apk放在哪里,最后都是需要经历解密动态加载到内存中的,所以分析底层加载dex源码,知道有一个函数:dvmDexFileOpenPartial 这个函数有两个重要参数,一个是dex的其实地址,一个是dex的大小,而且知道这个函数是在libdvm.so中的。所以我们可以使用IDA进行动态调试获取信息

    3、双开IDA开始获取内存中的dex内容

    双开IDA,走之前的动态破解so方式来给dvmDexFileOpenPartial函数下断点,获取两个参数的值,然后使用一段脚本,将内存中的dex数据保存到本地磁盘中。

    4、分析获取到的dex内容

    得到了内存中的dex之后,我们在使用dex2jar工具去查看源码,但是发现保存,以为是dump出来的dex格式有问题,但是最后使用baksmali工具进行处理,得到smali源码是可以的,然后我们就开始分析smali源码。

    5、分析源码了解破解思路

    通过分析源码得知在WebViewActivity页面中会加载一个页面,然后那个页面中的js会调用本地的Java对象中的一个方法来展示toast信息,但是这里我们遇到了个问题:Js的Java对象名称被混淆加密了,所以这时候我们需要去分析那个加密函数,但是这个加密函数是native的,然后我们就是用IDA去静态分析了这个native函数,但是没有分析完成,因为我们不需要,其实很简单,我们只需要结果,不需要过程,现在解密的内容我们知道了,native方法的定义也知道了,那么我们就去写一个简单的demo去调用这个so的native方法即可,结果成功了,我们得到了正确的Js对象名称。

    6、了解WebView的安全性

    WebView的早期版本的一个漏洞信息,在Android4.2之前的版本WebView有一个漏洞,就是可以执行Java对象中所有的public方法,那么在js中就可以这么处理了,先获取geClass方法获取这个对象,然后在调用这个对象中的一些特定方法即可,因为Java中所有的对象都有一个getClass方法,而这个方法是public的,同时能够返回当前对象。所以在Android4.2之后有了一个注解:@JavascriptInterface ,只有这个注解标识的方法才能被Js中调用。

    7、获取输入的新技能

    验证结果的过程中我们发现了一个技巧,就是我们在输入很长的文本的时候,比较繁琐,可以借助adb shell input text命令来实现。

     

    八、技术点概要

    1、通过dump出内存中的dex数据,可以佛挡杀佛了,不管apk如何加固,最终都是需要加载到内存中的。

    2、了解到了WebView的安全性的相关知识,比如我们在WebView中js对象名称做一次混淆还是有必要的,防止被恶意网站调用我们的本地隐私方法。

    3、可以尝试调用so中的native方法,在知道了这个方法的定义之后

    4、adb shell input text 命令来辅助我们的输入

     

    本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者没关系,本文涉及到的代码项目可以去编码美丽小密圈自取,欢迎加入小密圈一起学习探讨技术

     

    九、总结

    这里就介绍了Android中如何dump出那些加固的apk程序,其实核心就一个:不管上层怎么加固,最终加载到内存的dex肯定不是加固的,所以这个dex就是我们想要的,这里使用了IDA来动态调试libdvm.so中的dvmDexFileOpenPartial函数来获取内存中的dex内容,同时还可以使用gdb+gdbserver来获取,这个感兴趣的同学自行搜索吧。结合了之前的两篇文章,就算善始善终,介绍了Android中大体的破解方式,当然这三种方式不是万能的,因为加固和破解是相生相克的,没有哪个有绝对的优势,只是两者相互进步罢了,当然还有很多其他的破解方式,后面如果遇到的话,会在详细说明。

     

    《Android应用安全防护和逆向分析》

    点击立即购买:京东  天猫  

    更多内容:点击这里

    关注微信公众号,最新技术干货实时推送

    展开全文
  • 产生这个问题的主因是dex文件格式的限制.一个DEX文件中method个数采用使用原生类型short来索引文件中的方法,也就是4个字节共计最多表达65536个method,field/class的个数也均有此限制。对于DEX文件,则是将工程所需...

    很多大厂的Android App因为业务量大,引用库多导致其apk包的中的类于方法剧增.这样就有可能出现因为方法数过多导致编译失败的情况.产生这个问题的主因是dex文件格式的限制.一个DEX文件中method个数采用使用原生类型short来索引文件中的方法,也就是4个字节共计最多表达65536个method,field/class的个数也均有此限制。对于DEX文件,则是将工程所需全部class文件合并且压缩到一个DEX文件期间,也就是Android打包的DEX过程中,单个DEX文件可被引用的方法总数被限制为65536.

    为解决这个问题,谷歌推出了Multidex技术,简单来说就是将一个apk中的dex文件拆分成多个分主次先后加载,当然在这之前业界已经开始使用插件化来弱化此类问题.现在市面上也有很多Multidex和插件化两种方案都使用的app.

    Multidex会给逆向工程师带来如下麻烦:

    1.常见工具静态分析的类和方法不全
    
    2.静态分析工具因为交叉引用的问题导致反编译失败或崩溃
    
    3.动态调试中无法下断点
    
    4.hook的时候找不到制定的类和方法
    

    0x01 merge multidex

    在这里插入图片描述

    在逆向apk中经常会遇到一些类丢失,反编译崩溃的情况.如果这时候去观察apk压缩包会发现其中有超过一个dex,上图中就有两个dex.那么这个app分析起来就不会很轻松了,因为这个叫dex分包的技术直接意味着你要面对超过65536个java方法.而这篇文章主要就是讲解笔者在遇到这种情况的时候一些应对手法.

    如果你的dex2jar版本为v2.1之前的版本,那么dex2jar就会默认转化第一个dex文件而忽略其他dex文件. 52f26c6 2.1版本开始支持multidex,直接执行

    d2j-dex2jar.sh the-apk-witch-mutidex.apk
    

    就可以转化所有dex文件到一个jar包中.

    在dex2jar更新v2.1之前笔者是用的一个比较”耿直”的方法解决这个问题,因为dex的method数量有限但是jar包对method是没有特别限制的,所以我写了一个脚本将apk中多个dex先转化为jar文件之后解压缩最后合并打包压缩,同样可以得到完全的反编译文件.

    Android逆向中出镜率较高的jeb在早期版本v1.x也同样有类似尴尬的问题,只默认反编译第一个dex文件.但是到v2.2也开始支持multidex采用merge的方式解决多个dex的反编译问题.也就是在jeb2.2之后就可以无障碍的在multidex中使用交叉引用功能了.

    在这里插入图片描述

    在很长一段时间使用jeb1.5的时候解决这个问题的办法同样也也merge多个dex的smali代码,因为要回编译至dex所以就无法突然65K方法数的限制,那么就要想办法对multidex进行瘦身.大数据情况下我们只关心其自有代码,对其依赖库往往是带过的(大多数情况是和配置文件中application或者入口Activity同路径的代码).这里就需要选择一个较小的dex去识别去除一些依赖库和第三方sdk比如android support / google gson,然后抽取另外的dex的主包smali代码合并到较小的dex中.最后回编译至dex拖入jeb1.5中就可以正常分析了.

    0x02 attach multidex

    在multidex的测试过程中还会出现一种情况,就是使用xposed hook其方法的时候,如果方法位于默认dex中是可以的正常hook,但是如果方法位于dex分包中xposed就会报错提示所要hook的方法所在类无法找到.

    要分析这个问题的原因以及解决办法,就要先了解multidex的载入过程以及xposed的hook时机.

    dex分包加载大致流程如下,可以得出分包是滞后主包不少时间加载的:

    1.检测是否有分包需要安装,系统是否支持multidex
    
    2.从apk中解压出分包
    
    3.通过反射将分包注入到当前classloader
    

    在这里插入图片描述

    而xposed为了能让module及时载入执行所以得尽快调用handleLoadPackage(),所以此时获取的context的classloader中只要默认dex主的包的类.

    因此我们得想法得到完整的上下文context,比较明显的获取完整context的hook时机有如下两处:

    MultiDex.install()
    MultiDexApplication.attachBaseContext()

    在这里插入图片描述

    而xposed的作者建议是选择android.app.Application.attach(),因为attachBaseContext是有概率被重写的不稳定.所以选择方法内调用了attachBaseContext的Application.attach().

    在这里插入图片描述

    示例代码如下

    在这里插入图片描述

    分析到这里就可以想到一些加壳后的app无法正常hook也可能是类似原因可以用同样的方法解决(这里前提当然是能脱壳看到代码且壳没对hook做对抗,如果有对抗还是脱了之后回打包比较稳妥.).下图这个壳同样也佐证了attachBaseContext被重写的可能,直接hook被重写的attachBaseContext也是可行的.
    在这里插入图片描述

    展开全文
  • 1.调试的过程。 2.查看和跟踪流程内存值. 3.遇到的问题(类型转换的问题) 3.修改某个寄存器的值

    0x01.调试的过程。

    1、首先AndroidManifest.xml里面Android:debuggable="true"。

    2、将classes.dex拖入IDA中。

    3、选择Debugger->Debugger options->Set specific options,在Package Name和Activity中填入主Activity的包名和类名。
    4、选择Debugger->Process options,将Port改为8700。
    5、下断点,在相应需要调试的函数的位置下断点。
     6、手机端开启android_server
    具体方法,
    C:\>adb shell push android_server /data/local/tmp/ (android_server需到IDA安装目录./dbgsrv下拷贝
    C:\>adb shell
    #su //获取root权限
    #chmod /data/local/tmp/android_server //给android_server添加可执行权限
    #/data/local/tmp/android_server //启动android_server
    7、端口转发
    C:\>adb forward tcp:23946 tcp:23946 //把手机上的端口转发到pc上
    8、打开要调试的Activity
    C:\>adb shell am start -D -a 包名/入口 //以调试的方式期待调试的程序
    9、选择Debugger->attach to process,attch到应用,选择包名单击即可。  接下来,出现的界面全部Cancel。程序运行到断点处。

    0x02.查看和跟踪流程内存值.

    F9运行

    F8单步调试

    F7进入函数


    1.debugger->debugger windows->locals
    查看变量的值

    0x03.遇到的问题(类型转换的问题)

    1.遇到IDA寄存器中的值bad type 
    使用 IDA 调试 APK 时经常遇到变量无法识别的情况,需要在WatchView里面手动加入类型转换,如下图

    然后在弹出的窗口中自己为变量添加一个类型,类似这样:
    (Object*)v0
    (String)v0
    (char*)v0
    (int)v0
    (int*)v0

    0x04.修改某个寄存器的值

    修改内存中的程序和值

    修改程序一般都是IDA的修改方式

    定位地址,edit修改对应的值后apply进行修改。


    修改内存中的值,在lcoals中直接修改即可


    0x05 dump内存中的dex脚本

    展开全文
  • 安卓逆向助手反编译dex进行打包(建议:把编译后文件夹改为src再新建一个文件夹 为apk名/工程名 再把src拖入文件夹) as导入 文件夹,下断 (配置:run->EditConfig...->+->Remote Name:smali Host:...
  • IDA动态调试Android的DEX文件

    千次阅读 2015-10-19 16:14:17
    Android程序的dex文件的动态调试确实是个大问题,网上也有一些教程但是不是特别的详细,今天用到了IDA动态调试Android的DEX文件,特此记录一下。   IDA 6.6新添加了对dex文件的调试支持,但是功能还是很弱的说,...
  • 使用ida调试dex文件

    千次阅读 2015-12-24 00:56:04
    ## 反编译apk文件 <!-- more--> ## dex文件拖入ida,等待分析完毕 ## 设置调试选�
  • 一次完整的IDA动态调试dex过程

    万次阅读 2017-05-10 22:18:07
    使用到的工具 IDA6.8,adb,apktool,auto-sign 原料:Crackme.apk文件 阶段一——反编译重打包重签名: 使用apktool反编译Crackme.apk 用法 apktool.bat d 查看一下AndroidManifest.xml文件,确认一下是否是...
  • 使用IDA进行DEX调试

    2020-08-10 01:17:13
    将apk(release)拖入ida,选择classes.dex 打开debugger option 可以选择点击以下的从AXML填充,也可以自己填写 二 选择Process option 选择端口,端口默认是23946,这里端口号可以设置为8700,但避免端口被...
  • APK程序Dex文件无源码调试方法讨论

    千次阅读 2015-10-22 09:52:34
    IDA pro6.6之后加入了dex动态调试功能,一时间普天同庆、喜大普奔。兴奋之后你才会发现IDA这东西在动态调试方面真的是很挫,就算他是静态反编译之王,我也不得不说他的动态调试功能还非常需要加强。先说说使用ida...
  • Android Studio动态调试

    2020-01-19 22:39:53
    https://blog.csdn.net/yusakul/article/details/81203174
  • 在APK改之理里双击打开AndroidManifest.xml,为了让APP可调试,需要在application 标签里添加一句android:debuggable=”true” 保存,然后回编译成apk,安装到模拟器或者真机中 二、调试配置 1.将APP包里的classes...
  • From:https://www.52pojie.cn/forum.php?mod=viewthread&tid=742250 jeb 动态调试 smali 代码:https://www.bilibili.com/video/BV1UE411A7rW?p=39 一....1.反编译apk,dex 2.包名树状图 3.查...
  • 利用IDA6.6进行apk dex代码动态调试

    千次阅读 2016-03-07 16:12:20
    根据android的官方文档,如果要调试一个apk里面的dex代码,必须满足以下两个条件中的任何一个: 1.apk中的AndroidManifest.xml文件中的Application标签包含属性android:debuggable=”true” 2./default
  • 现在要说的就是最后一篇了,如何应对Android中一些加固apk安全防护,在之前的两篇破解文章中,我们可以看到一个是针对于Java层的破解,一个是针对于native层的破解,还没有涉及到apk的加固,那么今天就要来介绍一下...
  • 【原创】IDA调试dex代码初体验

    千次阅读 2014-06-10 21:42:05
    IDA 6.6新添加了对dex文件的调试支持,由于工作原因,我第一时间拿到了这个版本,下面就是针对这个功能的一些简单体验。 IDA对这个新功能提供了一个PDF文档进行说明,按照教程一步步来就可以完成对例子程序的调试...
  • Android Dex文件格式解析

    千次阅读 2016-12-12 17:11:28
    Dex文件是Android虚拟机下的可执行文件,包含了应用程序所用到所有操作指令和运行时数据。在程序编译过程中,java源文件先被编译成class文件,然后通过dx工具将多个class文件整合为一个dex文件。这样的文件结构使得...
  • 1.用于动态加载的dex可以放在sdcard中进行加载,但是为了安全起见还是觉得放在asset中, 加载之前把dex复制到app的data空间中更好。 String copyDex(String dexName) { AssetManager as = getAssets(); String ...
1 2 3 4 5 ... 20
收藏数 10,912
精华内容 4,364
关键字:

dex调试