Anroid逆向学习从编写so到静动态调试分析arm的一次总结

#Anroid逆向学习从编写so到静动态调试分析arm的一次总结 ##1、前言 最近跟着教我兄弟学逆向这篇教程学习Android逆向,在第七课后做业反复折腾了好几天,正好在折腾的时候对前面的学习总结一波,动态分析一下arm汇编(静态看arm感受跟看天书没什么区别。。。),涉及到的东西都很简单基础,大神就不要浪费时间了!!!java


##2、所使用到的工具android

  • Android studio v3.3
  • IDA v7.0
  • AndroidKiller
  • ApkToolBox v1.6.4

##3、编写所须要用到的so和apk文件 关于怎么编写Android应用和so文件,网上一大堆超详细的教程,这里就再也不细说了,只简单说一下so文件的编写过程。
一、新建一个java类,使用System.loadLibrary("so_name");来加载so文件,在建立native层函数,我这里建立的一个名为add,形参为两个整数,返回值为一个整数的native函数 建立java类 二、在Android Studio的终端使用javac java_name.java命令编译刚才添加的类 编译java文件 三、跳转到java目录,生成.h文件,生成命令格式为javah -jni Android项目包名.类名 生成.h文件 四、在main文件夹下面新建jni文件夹,而后将上一步在java文件夹下面生成好的.h文件复制到刚新建好的jni文件夹下面,并在相应函数下面编写逻辑代码(我这里比较简单,只实现了两个整数相加并返回结果),而后新建一个util.c的空文件(不加上这个文件会报错。。。) 新建jni文件夹 编写函数逻辑代码 五、在build.gradle文件中添加相应配置,而且在src目录下创建CMakeLists.txt文件 添加ndk配置 [代码]shell

ndk{
            moduleName "myjni"
        }
        externalNativeBuild{
            cmake {
                cppFlags ""
                abiFilters "arm64-v8a","armeabi-v7a","x86","x86_64"
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

[CMakeLists文件内容]app

\# Sets the minimum version of CMake required to build the native
\# library. You should either keep the default value or only pass a
\# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

\# Creates and names a library, sets it as either STATIC
\# or SHARED, and provides the relative paths to its source code.
\# You can define multiple libraries, and CMake builds it for you.
\# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.AndroidStudio开始支持Cmake了,ndk感受挺费劲的,这个是否是好玩点,,这里是要生成的库的文件名 libtest.so
             \#这里是liuxin
             myjni  \#so文件名字
             \# Sets the library as a shared library.
             SHARED

             \# Provides a relative path to your source file(s).
             \# Associated headers in the same location as their source
             \# file are automatically included.对应的C文件的目录位置
             src/main/jni/main.c)

\# Searches for a specified prebuilt library and stores the path as a
\# variable. Because system libraries are included in the search path by
\# default, you only need to specify the name of the public NDK library
\# you want to add. CMake verifies that the library exists before
\# completing its build.

find_library( \# Sets the name of the path variable.
              log-lib

              \# Specifies the name of the NDK library that
              \# you want CMake to locate.
              log )

\# Specifies libraries CMake should link to your target library. You
\# can link multiple libraries, such as libraries you define in the
\# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.指定依赖库
                      \#这里是liuxin
                       myjni  \#so文件名字

                       \# Links the target library to the log library
                       \# included in the NDK.关联日志记录库文件,在ndk目录中
                       ${log-lib} )

六、在Build->Rebuild Project编译好so文件,so文件位置存放在build->intermediates->cmake->debug->obj目录下,选取相应的so文件在main的JniLibs目录下(该目录须要本身创建),而后编译好apk便可 编译sotcp


##4、破解该apk,将结果变为调用该so中该函数时不管参数输入多少,返回结果恒等于0 一、将apk拖进夜神中,观察一波(这里结果为52,参入参数为22和30) 夜神结果 传入参数ide

二、将该apk拖进AndroidKiller中反编译,在jd中查看java代码(这里就再也不分析smali代码了,直接看java),能够看到在关键函数中调用myTest类的add函数,在jd中双击该类跟进,发现加载了so文件,而且定义了native函数int add(int,int),因此通过上面分析要修改返回值须要修改so文件(也能够在smali层直接修改,但这篇文章主要讲so,若是有兴趣的能够去smali层修改) 1 2 3函数

三、使用ida静态分析myjni这个so文件。在AndroidKiller中找到该so文件,右键打开文件路径,而后拖进ida中,在export窗口(提供给外界调用的函数名集合的一个窗口)中找到add函数,双击进入该函数,能够看到汇编指令就这两条ADDS R0, R3, R2
BX LR (由于个人函数功能过于简单因此就2条汇编指令,做为学习只有就不要纠结那么多了),第一条意思很简单就是将r3和r2寄存器的值相加复制给r0寄存器,第二条指令意思是跳转到lr寄存器中所指地址中去执行下面的指令(lr是链路寄存器,用于保存函数返回地址,就是至关于存储了函数返回后下一条指令的地址)
4 5 6 7 arm 四、动态调试。静态其实看着仍是挺懵逼的,做为一个arm汇编的初学者,真的是搞不清楚调用函数过程当中参数传到那个寄存器中去了,返回值跑哪里去了(暂时只关注这两点),因此那就动态调试so吧(记住必定要用真机调试,反正我用夜神模拟器调试就木有成功过,网上有大佬分析说的是模拟器底层仍是x86的汇编,不是arm,因此有各类各样的奇葩错误没法解决)(并且要root)。
(1)、将手机链接好,并进入调试模式,将ida的dbgsrv->android_server拷贝到手机的/data/local/tmp目录下面(打开cmd,输入adb push ida路径/dbgsrv/android_serevr /data/local/tmp拷贝文件至手机),而后输入adb shell进入调试模式下,执行su获取root权限,cd /data/local/tmp进入android_server所在目录下面,chmod 777 android_server赋予android_server文件777(可读可写可执行)权限,./android_server执行android_server文件,最后另外打开一个cmd窗口,执行adb forward tcp:23946 tcp:23946进行端口转发(23946是ida的默认端口,由于木有反调试因此懒得改了)。 20 21 (2)、在手机上点击要调试的app启动,而后打开ida,在弹出的初始界面中,选择go这个选项,直接进入ida,而后选择Debugger->Attach->Remote ARMLinux/Android Debugger选项,在弹出的窗口中点击Debug Options选项,勾选下图所示三个选项(这三个选项名字太长了,麻烦看一下图吧),而后点击ok,在点击ok,弹出选择进程的界面,找到要调试的进程(可使用serarch搜索进程),点击,而后点击ok,而后ida会附加到要调试的进程,在ida右侧的module哪里显示了全部加载的so文件,能够左键点击而后Ctrl+F搜索so文件(我这里so文件名为libmyJni.so,因此我搜索my就好了),找到对应的so文件后,双击便可弹出so文件对应的函数框(我这里是add函数),而后双击对应的函数,ida会跳转到这个函数中去(我这儿就是跳转到了add函数中)。工具

22 23 24 25 26 27 29 28 30 三、通过上一步的配置,咱们以及成功进入到要调试的函数中了,如今差开始调试了,在ADDS R0, R3, R2处下一个断点(鼠标左键点击这行汇编代码,而后按F2便可下断点),而后按F9运行,在手机上点击按钮,便可看到程序停在了这行代码处,而后按F8单步调试,在右边寄存器处能够看到相关寄存器的16进制值,这里咱们能够看到r0寄存器的16进制值为34(10进制为52),可见函数返回结果所用的寄存器为r0,r2寄存器16进制值为16(10进制值为22),对应了咱们传进去的第一个参数22,r3寄存器的16进制值为1E(10进制为30),对应了咱们传进去的第二个参数30。学习

31 32 四、通过上面的动态分析,咱们已经很清楚的知道该函数汇编运行过程--将一个参数值传入寄存器R2,第二个参数值传入寄存器R3,相加结果返回值送入寄存器R0。如今咱们须要将结果很等于0,那么咱们只需将R0复值为0返回便可。具体思路是将ADDS R0,R2,R3这行汇编代码改成MOV R0,#0便可。如今咱们打开ida导入so文件,找到ADDS R0,R2,R3,咱们能够点击ida的菜单栏的Options->General,在弹出的窗口中,将bytes改成4,便可显示处汇编指令对应的机器码,如今咱们只须要将对应的机器码修改成mov R0,#0对应的机器码便可(能够用ApkToolBox这个工具的arm起色器码这个功能查看汇编对应的机器码)。咱们可使用patch来修改对应的机器码,首先,鼠标左键点击要修改的那行汇编代码,而后咱们点击菜单栏的Edit->Patch program->Change bytes,在弹出的窗口修改对应的机器码(由于是Thumb模式,因此修改两个字节便可,这里对应的修改成的机器码为00 20),而后点击菜单栏的Edit->Patch program->Apple patches to input file...便可保存修改。gradle

37 38 3 33 34 35 五、再将获得修改的so文件复制,在AndroidKiller中替换lib目录下全部so文件,而后从新编译便可,在将获得的apk文件安装好便可看到点击按钮显示结果为0。

36 1


##5、结束语 相关附件连接:连接:https://pan.baidu.com/s/12a_l4JcuJj4i6nJty0xXXQ 提取码:licr 。

相关文章
相关标签/搜索