zoukankan      html  css  js  c++  java
  • 【转】Android逆向之动态调试总结

    一、在SO中关键函数上下断点


    刚学逆向调试时。大多都满足于在SO中某关键函数上下断点。然后通过操作应用程序,去触发这个断点,然后进行调试

    详细的步骤可以参见非虫大大的《Android软件安全与逆向分析》

    简单说:在libsyclover.so文件中有一个函数jnicall1。每次单击按钮的时候,便会调用此函数。


    1.静态载入此so文件,找到函数的偏移地址为:0x132C

    <ignore_js_op> 
    2.执行android_server3.端口转发

    adb forward tcp:23946 tcp:23946

    4.运行程序

    5.IDA附加

    <ignore_js_op> 
    然后会弹出
    <ignore_js_op> 
    点击OK之后,在弹出的列表框中选择需要附加的进程即可

    6.下断点


    附加完成之后,会停在libc.so这个模块中。此时按下Ctrl + S,弹出模块列表框,搜索so文件名。
    <ignore_js_op> 
    记录下基地址:0×76072000 (RX权限)
    和静态分析时得到的偏移地址0x132C相加得到0x7607332C
    G跳转到此位置

    <ignore_js_op> 
    F2下好断点!

    7.触发断点


    下好断点,便F9执行,此时状态是runing
    此时,去应用中单击按钮,程序便会断在刚刚下好的断点处~

    <ignore_js_op> 
    ok~ 这种调试方法局限性很大,适合于比较初级的调试。这种调试手法在现在已经满足不了需求了。


    二、在JNI_OnLoad函数上下断点

    JNI_OnLoad函数大概功能就是在程序加载so的时候,会执行JNI_OnLoad函数,做一系列的准备工作。
    很多时候,程序猿们会将一些重要信息放在此函数中,而不是通过某种事件来重复触发。包括说将反调试函数放置在此函数中。因此,调试手段发生了改变,上述调试方法基本上被淘汰。

    1.静态分析,找到JNI_OnLoad函数的偏移:0×1504

    <ignore_js_op> 

    2.执行android_server3.端口转发

    adb forward tcp:23946 tcp:23946

    4.以调试模式启动程序

    adb shell am start -D -n com.example.mytestcm/.MainActivity
    此时,手机界面会出现Waiting For Debugger页面


    5.打开ddms或者Eclipse (必要,为了使用jdb命令)

    6.IDA附加

    7.设置调试选项

    Debugger — Debugger Options
    <ignore_js_op> 

    8.F9运行程序

    IDA中,F9运行程序,此时是runing状态。
    在命令行中执行:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700其中port=8700是从ddms中看到的。

    <ignore_js_op> 
    此时程序会断下来
    <ignore_js_op> 

    9.下断点

    Ctrl + S 然后搜索到so文件名
    <ignore_js_op> 
    记录下基地址是:0×76118000
    加上JNI_OnLoad函数的偏移地址0×1504为0×76119504
    G跳转到0×76119504,下断点

    <ignore_js_op> 

    A.触发断点

    下好断点之后,直接F9运行吧,就能断在JNI_OnLoad函数处~
    <ignore_js_op> 
    当这种调试手法出现之后,将特殊函数,或者反调试函数放在JNI_OnLoad中也不是那么的安全了。此时,程序猿们通过分析系统对SO文件的加载链接过程发现,JNI_OnLoad函数并不是最开始执行的。在JNI_OnLoad函数执行之前,还会执行init段和init_array中的一系列函数。
    因此,现在的调试方法,都是将断点下在init_array中~
    至于下断点的方法,可以类比于在JNI_OnLoad中下断点的方法,在init_array的函数中下断点。还有一种方法便是通过在linker模块中,通过对其中函数下断点,然后也能单步到init_array中
    下面便详细介绍下如何给任意系统函数下断点

    三、给任意系统函数下断点

    1.需要准备的有:
    与你调试环境一致的系统源码,这个也可以在http://androidxref.com/网站上在线查阅。
    root之后的手机,方便将系统的一些so文件dump至本地,静态获取到系统函数的偏移地址


    2.流程
    执行android_server
    端口转发 adb forward tcp:23946 tcp:23946
    调试模式启动程序 adb shell am start -D -n 包名/类名
    IDA附加
    静态找到目标函数对应所在模块的偏移地址
    Ctrl+S找到对应模块的基地址,两个地址相加得到最终地址
    G跳转至地址,然后下断
    F9运行
    执行jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
    断下,进行调试


    四、在dvmDexFileOpenPartial函数下断点,dump出明文dex


    发展至今,从去年到现在,apk的加解密发展非常迅速。国内出现了很多针对apk的加壳保护方案。主要也体现在对dex的保护和对so的保护!
    针对dex的保护,很长一段时间,都能通过对dvmDexFileOpenPartial函数下断点,从而dump出明文dex文件。

    以这次alictf的第三题为例子,展示下如何对dvmDexFileOpenPartial函数下断点!
    其他步骤都是一样的,这儿主要说下如何找到dvmDexFileOpenPartial函数位置
    1.查看源码


    dvmDexFileOpenPartial函数在rewriteDex这个函数中被调用。
    <ignore_js_op> 
    可以看到关键字符串信息是:Unable to create DexFile
    此时,从手机的/system/lib目录下得到libdvm.so


    2. 载入IDA,搜索字符串:Unable to create DexFile


    <ignore_js_op> 
    得到偏移地址是:0x0005AE8A

    3.下断点


    搜索模块libdvm.so
    <ignore_js_op> 
    基地址是0×41492000
    加上偏移地址为0x414ECE8A
    G跳转至此位置,下好断点,即可


    4.dump明文dex文件


    下好断点之后,F9运行,执行jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
    程序断下

    <ignore_js_op> 
    此时,看到寄存器窗口中的值为:
    <ignore_js_op> 
    R0保存dex的起始地址,R1便是dex的长度
    <ignore_js_op> 
    直接dump即可!

    5.后续


    dump出来的dex就可以进行反编。
    效果如下:

    <ignore_js_op> 


    五、写在最后


    随着现在技术的发展,对apk的保护是越来越好!大大增加了逆向分析人员的分析难度。同时,在整个攻防的过程中,对攻防两端的人都带来了非常棒体验。双方都取得了长足的进步!
    也促使了整个加固方向水平的提升!
    其中,动态调试手法在整个过程中是必不可少的。

  • 相关阅读:
    POJ 2923 Relocation (状态压缩,01背包)
    HDU 2126 Buy the souvenirs (01背包,输出方案数)
    hdu 2639 Bone Collector II (01背包,求第k优解)
    UVA 562 Dividing coins (01背包)
    POJ 3437 Tree Grafting
    Light OJ 1095 Arrange the Numbers(容斥)
    BZOJ 1560 火星藏宝图(DP)
    POJ 3675 Telescope
    POJ 2986 A Triangle and a Circle
    BZOJ 1040 骑士
  • 原文地址:https://www.cnblogs.com/dependence/p/4482393.html
Copyright © 2011-2022 走看看