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 。

Anroid逆向学习从编写so到静动态调试分析arm的一次总结的更多相关文章

  1. CobaltStrike逆向学习系列(12):RDI 任务发布流程分析

    这是[信安成长计划]的第 12 篇文章 0x00 目录 0x01 任务构建 0x02 结果处理 0x03 功能 DLL 分析 之前的分析都是针对整个 CS 的框架来进行的,但是功能也是整个 C2 中相 ...

  2. CobaltStrike逆向学习系列(13):RDI 任务执行流程分析

    这是[信安成长计划]的第 13 篇文章 0x00 目录 0x01 任务号 0x02 功能执行 0x03 结果接收 在上一篇文章中已经讲明了 RDI 类型的任务在发布时候的流程,接下来就是执行了,文中不 ...

  3. CobaltStrike逆向学习系列(8):Beacon 结果回传流程分析

    这是[信安成长计划]的第 8 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 Beacon 接收与处理 0x02 结果回传 Beacon 在接受完命令并执行后,会将数据加密回传给 T ...

  4. CobaltStrike逆向学习系列(7):Controller 任务发布流程分析

    这是[信安成长计划]的第 7 篇文章 关注微信公众号[信安成长计划] 0x00 目录 0x01 Controller->TeamServer 0x02 TeamServer->Beacon ...

  5. CobaltStrike逆向学习系列(2):Stageless Beacon 生成流程分析

    这是[信安成长计划]的第 2 篇文章 关注微信公众号 [信安成长计划] 0x00 目录 0x01 Patch Beacon 0x02 Patch Loader 0x03 文件对比 0x04 流程图 C ...

  6. CobaltStrike逆向学习系列(1):CS 登陆通信流程分析

    这是[信安成长计划]的第 1 篇文章 关注微信公众号[信安成长计划][SecSource] 0x00 目录 0x01 密码校验 0x02 aggressor.authenticate 0x03 agg ...

  7. 【转】安卓逆向实践5——IDA动态调试so源码

    之前的安卓逆向都是在Java层上面的,但是当前大多数App,为了安全或者效率问题,会把一些重要功能放到native层,所以这里通过例子记录一下使用IDA对so文件进行调试的过程并对要点进行总结. 一. ...

  8. android逆向学习小结--CrackMe_1

    断断续续的总算的把android开发和逆向的这两本书看完了,虽然没有java,和android开发的基础,但总体感觉起来还是比较能接收的,毕竟都是触类旁通的.当然要深入的话还需要对这门语言的细节特性和 ...

  9. 从0开始的Python学习013编写一个Python脚本

    通过之前的学习我们已经了解了Python的很多基础运用了,现在我们尝试着做一个有使用价值的小脚本. 问题 需求: 我想要一个可以给我备份重要文件的程序. 需求分析: 首先文件是有存储路径,文件的路径和 ...

随机推荐

  1. MYSQL--表与表之间的关系、修改表的相关操作

    表与表之间的操作: 如果所有信息都在一张表中: 1.表的结构不清晰 2.浪费硬盘空间 3.表的扩展性变得极差(致命的缺点) 确立表与表之间的关系.一定要换位思考(必须在两者考虑清楚之后才能得出结论) ...

  2. Docker跨服务器通信Overlay解决方案(上) Consul单实例

    场景 公司微服务快上线了,微服务都是用Docker容器进行部署的,在同一台主机下,把服务都部署上,注册到Nacos的IP与PORT都是内网的IP与Dockerfile中定义的端口号,看起来好像也没什么 ...

  3. 10.源码分析---SOFARPC内置链路追踪SOFATRACER是怎么做的?

    SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...

  4. unity_UGUI养成之路02

    1.技能的冷确效果 2.背包的分页效果 1创建背包的总面板,并添加ToggleGroup组件 2.物品面板的实现 3.背包分页的实现 注意:添加了Toggle组件的游戏对象不能再添加button组件. ...

  5. JSP学习笔记(1)——Jsp指令、动作元素和内置对象

    简单来说,javaweb技术就是让服务器端能够执行Java代码,之后返回数据给客户端(浏览器)让客户端显示数据 jsp页面中可以嵌套java代码(java小脚本)和嵌套Web前端(html,css,j ...

  6. Angular Material 的设计之美

    前言 Angular Material 作为 Angular 的官方组件库,无论是设计交互还是易用性都有着极高的质量.正如官方所说其目的就是构建基于 Angular 和 Typescript 的高质量 ...

  7. Jedis操作Redis--List类型

    /** * List(列表) * BLPOP,BRPOP,BRPOPLPUSH,LINDEX,LINSERT,LLEN,LPOP,LPUSH,LPUSHX,LRANGE,LREM,LSET,LTRIM ...

  8. 堆、栈、内存分配、==、equals、hashcode详解(转载)

    问题的引入: 问题一:String str1 = "abc";String str2 = "abc";System.out.println(str1==str2 ...

  9. hdu 1007 Quoit Design(分治)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给出n个点求最短的两点间距离除以2. 题解:简单的分治. 其实分治就和二分很像二分的写df ...

  10. 牛客OI测试赛 C 序列 思维

    链接:https://www.nowcoder.com/acm/contest/181/C来源:牛客网 题目描述 小a有n个数,他想把他们划分为连续的权值相等的k段,但他不知道这是否可行. 每个数都必 ...