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

一、前言

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


二、所使用到的工具

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

三、编写所需要用到的so和apk文件

关于怎么编写Android应用和so文件,网上一大堆超详细的教程,这里就不再细说了,只简单说一下so文件的编写过程。

1、新建一个java类,使用System.loadLibrary("so_name");来加载so文件,在创建native层函数,我这里创建的一个名为add,形参为两个整数,返回值为一个整数的native函数



2、在Android Studio的终端使用javac java_name.java命令编译刚才添加的类



3、跳转到java目录,生成.h文件,生成命令格式为javah -jni Android项目包名.类名



4、在main文件夹下面新建jni文件夹,然后将上一步在java文件夹下面生成好的.h文件复制到刚新建好的jni文件夹下面,并在相应函数下面编写逻辑代码(我这里比较简单,只实现了两个整数相加并返回结果),然后新建一个util.c的空文件(不加上这个文件会报错。。。)





5、在build.gradle文件中添加相应配置,并且在src目录下建立CMakeLists.txt文件



[代码]

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

[CMakeLists文件内容]

\# 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} )

6、在Build->Rebuild Project编译好so文件,so文件位置存放在build->intermediates->cmake->debug->obj目录下,选取相应的so文件在main的JniLibs目录下(该目录需要自己建立),然后编译好apk即可


四、破解该apk,将结果变为调用该so中该函数时无论参数输入多少,返回结果恒等于0

1、将apk拖进夜神中,观察一波(这里结果为52,参入参数为22和30)



2、将该apk拖进AndroidKiller中反编译,在jd中查看java代码(这里就不再分析smali代码了,直接看java),可以看到在关键函数中调用myTest类的add函数,在jd中双击该类跟进,发现加载了so文件,并且定义了native函数int add(int,int),所以经过上面分析要修改返回值需要修改so文件(也可以在smali层直接修改,但这篇文章主要讲so,如果有兴趣的可以去smali层修改)





3、使用ida静态分析myjni这个so文件。在AndroidKiller中找到该so文件,右键打开文件路径,然后拖进ida中,在export窗口(提供给外界调用的函数名集合的一个窗口)中找到add函数,双击进入该函数,可以看到汇编指令就这两条ADDS R0, R3, R2

BX LR (因为我的函数功能过于简单所以就2条汇编指令,作为学习只有就不要纠结那么多了),第一条意思很简单就是将r3和r2寄存器的值相加复制给r0寄存器,第二条指令意思是跳转到lr寄存器中所指地址中去执行下面的指令(lr是链路寄存器,用于保存函数返回地址,就是相当于存储了函数返回后下一条指令的地址)












4、动态调试。静态其实看着还是挺懵逼的,作为一个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的默认端口,因为木有反调试所以懒得改了)。





(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函数中)。



















3、经过上一步的配置,我们以及成功进入到要调试的函数中了,现在差开始调试了,在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。





4、经过上面的动态分析,我们已经很清楚的知道该函数汇编运行过程--将一个参数值传入寄存器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...即可保存修改。













5、再将得到修改的so文件复制,在AndroidKiller中替换lib目录下所有so文件,然后重新编译即可,在将得到的apk文件安装好即可看到点击按钮显示结果为0。




五、结束语

相关附件链接:链接:https://pan.baidu.com/s/12a_l4JcuJj4i6nJty0xXXQ 提取码:licr 。

最新文章

  1. 【代码笔记】iOS-UILable电子表显示
  2. PHP字符串处理
  3. UVA 11827 Maximum GCD
  4. p4 是否能自动merge
  5. 推荐mysql优化的21条经验
  6. Solr数据库连接之多表关联
  7. 有关ListBox
  8. Linux下mysql的安装和使用(C语言)
  9. asp.net用Zxing库实现条形码输出的具体实现
  10. CentOS 6.2 二进制安装apache2.4.3出现configure: error: APR-util not found. Please read the documentation的解决方
  11. Database Connection Pool Library | Libzdb
  12. 【C疯狂的教材】(四)C语言分支语句
  13. 【DataStructure】Some useful methods for arrays
  14. go单元测试进阶篇
  15. 201521123035 《Java程序设计》第九周学习总结
  16. 别人的Linux私房菜(17)进程管理与SELinux初探
  17. karaf 控制台 常用linux指令(1)
  18. spring中IOC和AOP原理
  19. css 样式 记录
  20. Java 多线程 interrupt方法

热门文章

  1. Feign详细构建过程及自定义扩展
  2. 基于模糊聚类和最小割的层次化三维网格分割算法(Hierarchical Mesh Decomposition)
  3. python 31 升级版解决粘包现象
  4. Python+Selenium - Web自动化测试(二):元素定位
  5. ConcurrentLinkedQueue 源码解读
  6. 使用JDBC驱动程序处理元数据
  7. Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)
  8. 2019icpc南京网络赛_F_Greedy Sequence
  9. Keras 实例 MNIST
  10. SCRUM MASTER检查单