Android动态代码注入调试
Android手机软件进程代码注入攻击与防御研究

Android手机软件进程代码注入攻击与防御研究作者:周凡来源:《科教导刊·电子版》2018年第19期摘要在Android手机广泛普及的今天,其被恶意程序攻击、病毒感染、信息复制等事件频频发生。
Android应用安全问题自然也引起人们的更多关注。
结合Android体系架构的特点,本文主要是通过ptrace注入的方式对Android手机软件进程代码注入攻击与防御进行研究,从而提高Android应用的安全性。
关键词 Android系统 ptrace注入现在Android手机应用已有案例遭到代码注入攻击:由于应用是通常运行在Dalvik虚拟机上的,其底层依然是C和C++环境。
攻击者进程通常伪装成gdb调试器对指定进程进行调试,然后远程调用dlopen使指定进程加载预先写好的恶意SO代码,从而窃取相关关键信息。
1 ptrace原理程序员的任务就是写程序,写完程序就是调程序,估计没人敢说自己写程序不用调试的,尤其是程序规模庞大了之后更是如此,第一个实现调试器的是一个伟大的人,个人见解:ptrace就是为gdb而生的,ptrace应该算是gdb的核心了。
2 Android下的ptrace注入ptrace让调试变得方便,也让程序变得不安全。
对于每一个Android应用,都对应一个Dalvik虚拟机,其上层是JAVA实现,下层又有支持C、C++的JNI环境,按照上述ptrace原理,可以在JNI环境下使用ptrace通过注入的方式使一个Android应用执行我们自己写的JAR包。
由于是执行在指定Android应用的进程空间中,我们的JAR包可以很方便的修改、获取该应用中的数据。
2.1时序图原理时序图的基本流程如下:(1)通过Shell指令执行Inject,Aseck在执行时必须拥有root权限。
(2)可执行文件Inject的流程非常通用,arm平台上无需更改。
(3)加载的libJavaLoader.so文件流程也是通用的,无需更改。
frida使用方式

frida使用方式Frida是一款强大的动态分析工具,其技术基于Google的V8 JavaScript引擎。
它是一种用于移动设备和桌面设备上进行逆向工程和安全测试的强大工具。
与其他调试工具相比,它在进行反调试时有着更为出色的效果。
本篇文章旨在介绍Frida的使用方式和相关工具。
第一步:安装Frida首先你需要安装Frida,它支持多个操作系统,包括Windows、macOS、Linux以及多个移动设备操作系统,例如iOS和Android。
安装方法可以参考官方文档。
第二步:选择合适的工具Frida提供了多个独特的工具,您可以根据自己的需求选择并使用它们。
1. Frida-traceFrida-trace用于动态追踪某个进程或者某个方法的执行,输出函数调用路径。
我们可以使用以下命令行执行:frida-trace -U -i "pthread_*" com.example.app这个命令将会追踪‘com.example.app’应用程序,并过滤出所有线程函数。
Frida-repl提供了一个交互式的console来执行JavaScript代码。
使用以下命令将会打开一个JavaScript console:Frida-inject被用于动态注入JavaScript代码到目标进程,以便我们动态修改应用程序的逻辑。
使用以下命令将会启动注入的流程:这个命令将会启动一个JavaScript脚本(script.js)并注入到‘com.example.app’应用程序中。
有了Frida和工具的基础知识,下面我们就来使用一些Frida的核心功能:1. 动态计算哈希值import fridadef on_message(message, data):print("[+] {}".format(message))device = frida.get_usb_device()pid = device.spawn(["com.example.app"])process = device.attach(pid)script = process.create_script("""Java.perform(function() {var MessageDigest = e('java.security.MessageDigest');var Arrays = e('java.util.Arrays');在检查上述代码之后,使用 adb shell ps命令会显示出‘com.example.app’应用程序的PID。
[转]Android逆向之动态调试总结 神乎
![[转]Android逆向之动态调试总结 神乎](https://img.taocdn.com/s3/m/8c8b9a1d0740be1e650e9aaf.png)
[转]Android逆向之动态调试总结神乎一、在SO中关键函数上下断点刚学逆向调试时。
大多都满足于在SO中某关键函数上下断点。
然后通过操作应用程序,去触发这个断点,然后进行调试详细的步骤可以参见非虫大大的《Android软件安全与逆向分析》简单说:在libsyclover.so文件中有一个函数jnicall1。
每次单击按钮的时候,便会调用此函数。
1.静态载入此so文件,找到函数的偏移地址为:0x132C2.执行android_server3.端口转发adb forward tcp:23946 tcp:239464.运行程序5.IDA附加然后会弹出点击OK之后,在弹出的列表框中选择需要附加的进程即可6.下断点附加完成之后,会停在libc.so这个模块中。
此时按下Ctrl + S,弹出模块列表框,搜索so文件名。
记录下基地址:0×76072000 (RX权限)和静态分析时得到的偏移地址0x132C相加得到0x7607332CG跳转到此位置F2下好断点!7.触发断点下好断点,便F9执行,此时状态是runing此时,去应用中单击按钮,程序便会断在刚刚下好的断点处~ok~ 这种调试方法局限性很大,适合于比较初级的调试。
这种调试手法在现在已经满足不了需求了。
二、在JNI_OnLoad函数上下断点JNI_OnLoad函数大概功能就是在程序加载so的时候,会执行JNI_OnLoad函数,做一系列的准备工作。
很多时候,程序猿们会将一些重要信息放在此函数中,而不是通过某种事件来重复触发。
包括说将反调试函数放置在此函数中。
因此,调试手段发生了改变,上述调试方法基本上被淘汰。
1.静态分析,找到JNI_OnLoad函数的偏移:0×15042.执行android_server3.端口转发adb forward tcp:23946 tcp:239464.以调试模式启动程序adb shell am start -D -ncom.example.mytestcm/.MainActivity此时,手机界面会出现Waiting For Debugger页面5.打开ddms或者Eclipse (必要,为了使用jdb命令)6.IDA附加7.设置调试选项Debugger — Debugger Options8.F9运行程序IDA中,F9运行程序,此时是runing状态。
android下如何调试程序(详解)

如何启动 DDMS
DDMS 工具存放在 SDK – tools/路径下,启动 DDMS 方法如下:
1. 直接双击 ddms.bat 运行; 2. 在 Eclipes 调试程序的过程中启动 DDMS,在 Eclipes 中的界面如下:
选择“Other”,界面如下:
mo-Android 感受 Android 带给我们的新体验
总结说明
以上是在工作中总结的代码调试的方法,并结合 Android 应用程序开发,为将来深入开发 Android 应用程序打好坚实的基础。
相关文章
• • • • •
android.test.InstrumentationTestRunner 解析 android.app.instrumentation 解析 Android、JUnit 深入浅出(三)——JUnit 深入解析(上) Android、JUnit 深入浅出(二)——JUnit 例子分析 Android、JUnit 深入浅出(一)——JUnit 初步解析
mo-Android 感受 Android 带给我们的新体验
以上就将 TestSample 增加到”TestSuite Test”中,将来在选择测试用例的过程中只要选择了 TestSuite Test,TestSample 就将加 入当前测试中。如果将来 SampleCalculator 增加了其他功能,只需要在 TestSample 增加相应的 测试,就可以对 TestSample 进行完 整单元测试。 看到这里对上面 4 个问题,应该都有了大致的了解。最后需要说明的:对 TestCase 的管理,是完全界面化的,只需要按照 JUnit 的要 求实现会自动产生 UI 界面,这个不必担心,还需要下载 JUint packeage,根据需求选择自己需要的。大胆尝试下,你会发现编程真 的可以如此“美好”。
进击的Android注入术

进击的Android注入术《二》分类我们平时所说的代码注入,主要静态和动态两种方式∙静态注入,针对是可执行文件,比如平时我们修改ELF,DEX文件等等,相关的辅助工具也很多,比如IDA、JEB、ApkTool等等;∙动态注入,针对是进程,比如修改进程的寄存器、内存值等等;动态跟静态最大的区别是,动态不需要改动源文件,但需要高权限(通常是root权限),而且所需的技术含量更高。
本质动态注入技术,本质上就是一种调度技术。
想想平时我们调试一个进程时,可以做哪些功能?一般有下列几项:∙查看变量值∙修改变量值∙跟踪进程跳转∙查看进程调用堆栈∙等等动态注入相比于普通的调试,最大的区别就是动态注入是一个”自动化调试并达到加载自定义动态链接库“的过程。
所谓自动化,其实就是通过代码实现,在Linux上通过Ptrace就可以完成上面所有功能,当然Ptrace功能是比较原始的,平时调试中的功能还需要很多高层逻辑封装才可以实现。
在阅读下面章节之前,强烈建议阅读一下man文档,见这里。
目的一般而言,我们要对一个进程进行注入,主要有以下几方面目的:∙增强目标进程的功能;∙修复目标进程缺陷;∙劫持目标进程函数;∙窃取目标进程数据;∙篡改目标进程数据;过程如上图所示,进程A注入到进程B后,通过修改寄存器和内存,让进程B加载自定义的动态库a,当a被加载后,a会尝试加载其他模块,比如加载dex文件等等,具体的注入过程如下:∙ATTATCH,指定目标进程,开始调试;∙GETREGS,获取目标进程的寄存器,保存现场;∙SETREGS,修改PC等相关寄存器,使其指向mmap;∙POPETEXT,把so path写入mmap申请的地址空间;∙SETRESG,修改PC等相关寄存器,使其指向dlopen;∙SETREGS,恢复现场;∙DETACH,解除调试,使其恢复;上述是一个简化的过程,整个注入的代码,我已经上传到github,地址https:///boyliang/Poison当so被dlopen加载到目标进程后,我们需要让so中的逻辑被执行,比较复杂的做法是同样使用ptrace修改寄存器的办法,让目标进程调用dlsym找到我们函数的地址。
Android动态调试

上一期中,我们介绍了如何用JDB调试Java应用,本期中我们将来学习如何用JDB来调试Android应用,如果某个Android应用是可以被调试的,我们就能在该应用的进程中注入并运行我们自己的代码。
背景介绍未使本文更加有意思,我开发了一个简单的演示应用,只有一个按钮和一个输入框。
下载:/cf3RVN5fRRC73(提取码:8734)运行截图如下:点击按钮,应用提示”Try Again”。
现在我们的目标就是在不修改程序的情况下,把提示结果改成”Hacked”。
为此,我们需要在程序运行是来改变提示的内容。
用到的工具l模拟器ladb - Android调试桥ljdb - Java调试器为了简单点,我会使用Android Tamer,其中包含了所以上面提到的工具相关主题:u检查漏洞u相关设置u运行时代码注入好了,开始。
漏洞检查这是本文最简单的部分1、使用APKTOOL反编译AndroidManifest.xml文件,命令如下#apktool d <vulnerableapp>.apk2、检查AndroidManifest.xml文件是否有如下内容:Android:debuggable=”true”如果你在其中发现了这样的内容,就所以该应用是可以被调试的。
提示:我们只用到了APKTOOL来检查应用是否可调试,但我们没有修改应用的代码。
设置准备:这一步中,我们会为在进程中注入代码做一些准备。
上一期中说了,我们会用远程调试的方法。
1、启动模拟器2、安装测试应用3、打开终端,输入以下命令,查看Dalvik虚拟机监听在模拟器的哪一个端口。
#adb jdwp这条命令会显示所有可以连接并调试的端口,如下图:提示:JDWP就是Java Debug Wire Protocol(Java调试线协议),如果一个应用可被调试,该应用的虚拟机会打开一个唯一端口以便JDB 连接调试。
Android的Dalvik虚拟机也支持该协议。
frida java层hook原理

frida java层hook原理Frida Java层Hook原理Frida是一款强大的动态分析工具,可以用于对Android应用进行逆向分析和应用程序的动态修改。
在Android开发中,Java层是应用程序的核心,在Java层进行Hook可以实现对应用程序的修改和控制。
本文将介绍Frida在Java层进行Hook的原理和实现方法。
一、Hook的基本概念和原理Hook是指在应用程序中拦截和修改函数调用的过程。
在Android 应用程序中,通过Hook可以截获应用程序的函数调用,修改其参数或返回值,甚至可以替换原有的函数实现。
Hook技术可以用于实现诸如函数跟踪、代码注入、动态调试等功能。
Frida是一款基于动态注入的Hook工具,它通过在目标进程中注入自己的代码来实现对应用程序的Hook。
Frida支持多种操作系统和架构,包括Android、iOS、Windows和macOS等。
在Android平台上,Frida主要通过Java层和Native层两种方式进行Hook。
二、Frida在Java层进行Hook的原理Frida在Java层进行Hook的原理主要有两个步骤:寻找目标函数和替换目标函数。
1. 寻找目标函数在Java层进行Hook时,首先需要确定目标函数的位置。
Frida提供了一些API来辅助寻找目标函数,比如通过类名和方法名来查找目标函数。
通过调用Frida提供的Java API,可以获取到目标函数的Method对象,进而获取到目标函数的地址。
2. 替换目标函数在找到目标函数之后,就可以通过Frida的Java API来替换目标函数了。
Frida提供了一些函数来实现Hook,比如intercept、replace等。
通过调用这些函数,可以将自定义的函数替换目标函数,实现对目标函数的修改和控制。
三、Frida在Java层进行Hook的实现方法在Frida中,可以使用JavaScript来编写Hook的代码。
frida dump so 原理

frida dump so 原理Frida Dump So是一款非常流行的二进制代码工具,它可以为Android系统上的应用程序进行动态的目标代码注入,并且注入代码可以在应用程序运行时进行调用,并且可以动态分析用户化应用程序。
在这篇文档中,我们将主要关注Frida Dump So原理的工作流程。
我们将涵盖Frida Dump So的相关核心技术,以及它提供的其他重要功能。
我们还将讨论如何使用Frida Dump So来执行目标代码和应用程序的动态注入、调试和POC测试。
Frida Dump So工作原理Frida Dump So的工作原理基于二进制文件注入技术,它能够在运行时将注入代码注入到目标应用程序的进程中。
这种方式可以使开发人员,在实时运行应用程序时对其进行操作,调试和修复。
以此来看可看到其与IDA Pro 民间版本运行原理相近。
如果要对Frida Dump So的工作原理进行进一步的简化,则可以将其分为以下几个步骤:1. 首先,我们需要准备一个目标应用程序并确定其PID。
这个PID可以通过Frida自带的进程管理器获得,它提供了一个完整的工具套件,支持在整个应用程序的生命周期中进行操作。
2. 接下来,我们需要编写一个JavaScript脚本,来进行注入代码。
在Frida中,我们可以使用JavaScript和Python等高级语言来编写注入和执行代码,以此来方便开发人员进行二进制代码操作。
这是在Frida Dump So的工作中最核心的步骤之一,因为它可以为我们提供强大的注入能力,以便我们对目标应用程序进行调试和优化操作。
3. 在这个阶段,我们将执行JavaScript代码,并向进程注入所需的库。
在Frida中,我们可以使用两种不同的注入方法,分别是:Agent-Based Injection和Process-Based Injection。
在Agent-Based Injection 中,注入的代码在目标进程中分配一些内存,并将JavaScript解释器加载到该内存中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录一、动态代码注入技术 (1)二、动态分析工具jdb介绍 (2)四、jdb动态分析Android实例应用程序 (10)五、jdb动态分析第三方文件管理器应用程序 (17)六、动态注入动态链接库 (20)一、动态代码注入技术Android动态代码注入即是不修改源程序只修改进程的寄存器、内存值等就能控制程序实现既定目标的一种方法。
动态代码注入技术本质上就是一种调度技术,动态代码注入相比于普通的调试,最大的区别就是动态代码注入是一个“自动化调试并达到加载自定义动态链接库”的过程。
所谓自动化,其实就是通过代码实现,在Linux上通过Ptrace就可以完成查看变量值、修改变量值、跟踪进程跳转、查看进程调试堆栈等待所有功能,当然,Ptrace功能是比较原始的,平时调试中的功能还需要很多高层逻辑封装才可以实现。
一般而言,我们要对一个进程进行动态注入,主要有以下几个方便目的:增强目标进程的功能、修复目标进程缺陷、劫持目标进程函数、窃取目标进程数据、篡改目标进程数据。
如上图所示,进程A注入到进程B后,通过司改寄存器和内存,让进程B加载自定义的动态链接库a,当a被加载后,a会尝试加载其他模块,比如加载dex文件等等,具体的注入过程如下:∙ATTATCH,指定目标进程,开始调试;∙GETREGS,获取目标进程的寄存器,保存现场;∙SETREGS,修改PC等相关寄存器,使其指向mmap;∙POPETEXT,把so path写入mmap申请的地址空间;∙SETRESG,修改PC等相关寄存器,使其指向dlopen;∙SETREGS,恢复现场;∙DETACH,解除调试,使其恢复;下面就介绍一些简单的进程注入方法:二、动态分析工具jdb介绍JDB是一个简单的Java命令行调试器,包含在JDK中。
使用JDB命令可以分析简单的Java程序。
三、jdb动态分析java应用程序以下是作示例的代码:文件名:Debug.java编译生成的Class文件:Debug.classpublic class Debug{public static void passCheck(String secret){String password = secret;System.out.println("JDBDemoTest-Incoming Password is:"+password);}public static void test(){System.out.println("JDBDemoTest-We are in test method");System.out.println("JDBDemoTest-We are in test method");}public static void main(String args[]){System.out.println("JDBDemoTest-We are in main method");test();passCheck("srini0x00");}}这段代码片段中,Debug类的main方法调用了该类中的其他两个方法,使用-g命令编译后执行,会产生以下输出,如下图:运行JDB要调试Java程序,需要一条JDB到JVM的通信信道,因为Java 程序实际上是运行在JVM(java虚拟机)中的,如下所示,有两种连接JDB和JVM的方法。
方法1:直接使用JDB来加载类文件,JDB会自动创建一个JAVA 虚拟机,并建立连接。
图中的Debug代表编译后生成的类文件。
方法2:使用“java -Xdebug -Xrunjdwp:transport=dt_socket, server=y,address=54321 Debug”命令启动一个Java虚拟机,Java虚拟机会监听54321端口。
然后使用“jdb -attach 54321”命令启动JDB连接到JVM。
开始调试现在开始用第一种方法来调试示例程序,执行一条run命令来让JDB启动Java虚拟机,如下图:图中显示,启动了Java虚拟机后,程序立刻执行完成并退出了。
为了中断程序执行以便手工单步调试,需要在程序运行之前设置断点。
用“stop in”命令在方法开始的地方设置断点,如下图:使用run命令运行程序来触发断点。
触发断点后,JDB会自动显示将要执行的下一行代码:System.out.println(“JDBDenoTest-We are in main method”);可以使用“list“命令来查看当前的上下文代码。
使用“clear“命令查看设置的所有断点:使用”threadgroups”命令查看所有的线程组。
使用“threads”查看所有线程:如上图,当前的system线程组中有三个线程,而main线程组中有一线程,这就是将要调试的线程。
使用“classes”命令查看当前Java虚拟机所加载的类的信息:上图中显示了当前Java虚拟机所加载的全部类中的部分类,要查看特定类的更加详细的信息,可以使用“class<classname>”命令,下图显示了Debug类的详细信息:同样,也能查看其它类的详细信息,例如下图就显示了java.io.FileInputStream类的详细信息:使用“methods <classname>”命令查看所加载的方法:以上介绍了JDB调试的常用命令,现在将深入程序的执行流程,体验怎样用JDB来帮助调试程序。
可以使用“next”命令执行下一行代码:执行完当前代码后,JDB会自动显示下一行代码:调用test方法。
这里,再执行“next”命令后,会执行完test方法并中断到下一行代码:passCheck方法。
想进入passCheck方法进行调试,就使用“step”命令。
在test方法处输入step命令:输入“next”命令继续运行下一条代码:如果想直接离开该方法,而不是运行余下的代码,可以使用“step up”命令。
当前代码已经离开test方法,回到main方法,等待执行下一条。
“where”命令会打印显示当前的调用栈:当前程序正在main方法中,现在使用“step”命令进入方法,并检查调用栈:如上图,程序当前正在”Debug.passCheck”中运行,而“Debug. passCheck”又是被“Debug.main”调用的。
假如想查看passChe ck方法的局部变量信息,可以使用“locals”命令查看所有的局部变量。
如图显示,该方法接收了一个main方法传入的密码变量,因为参数还没有被赋值给局部变量,所只显示了参数而没有局部变量,先执行下一行代码再查看局部变量“password”。
可以使用“pri nt”命令打印出指定变量的内容:四、jdb动态分析Android实例应用程序使用jdb分析Android应用程序的步骤为:1、启动模拟器启动模拟器之前首先使用Android list targets命令查看SDK支持的API 等级。
然后使用“android create avd -n Android411 -t 2”创建模拟器。
创建模拟器完成后使用“android list avd”命令查看创建后的模拟器。
使用“emulator -avd Android411”命令启动模拟器。
2、安装测试应用等到模拟器启动成功后使用“adb install”命令安装应用程序到模拟器。
3、打开终端,输入“adb jdwp”命令,查看Dalvik虚拟机监听在模拟器的哪一个端口。
这条命令会显示所有可以连接并调试的端口,如下图:4、现在打开刚安装的测试应用,再使用“adb jdwp”命令查看应用监听的端口,如图:比较两次命令执行的结果,发现运行测试应用后多出了554端口,这就是测试应用对应的端口,需要用JDB去连接该端口。
5、在连接之前,需要使用adb来转发端口。
6、现在就可以用JDB连接调试android应用了。
远程代码注入下面就实现在应用运行时通过远程代码注入的方式改变变量值达到测试远程代码注入方法的目的。
为此,需要设置断点来控制程序的执行流程。
但之前并不知道该应用所使用的类和方法。
可以使用“classes”命令来查看类和方法。
现在用“methods com.example.debug.MainActivity$1”命令查看 MainActivity$1类中的方法。
在MainActivity$1.onClick方法中设置断点“stop in com.exam ple.debug.MainActivity$1.onClick(android.view.View)”为了触发这个断点,需要手动点击应用的按钮,如下图,点击后断点被触发:使用“locals”命令查看局部变量:使用“next”命令执行下一行代码:再使用“locals”命令查看本地变量,看上一行代码做了什么:如上图,TextView已经被加载并赋值给了tv参数,对应代码中与TextView的代码已经被执行。
使用“next”命令执行下一行,并检查局部变量:上图中列出了所有的局部变量,其中secret的字符串变量的值“Try Again”就是原程序点击按钮后显示的信息。
在源程序中setText方法被用来设置值“Try Again”。
使用”step”命令进入“setText”方法动态修改界面空间中将要显示的值。
使用“locals”命令查看该方法中的局部变量:使用“set”命令将“text”变量的值从“Try Again”改为“Test Android Project By JDB”。
然后再次点击按钮会发现界面中控件显示的内容改变了,而这种改变是在不修改原程序代码的前提下改变的,这就是Android系统中的动态代码注入技术:即不修改源代码,只是在程序运行期间动态修改源程序内容的方法。
按钮被点击之前显示的值是“Crack Me”按钮被点击之后显示的值是“Try Again”动态注入代码后再次点击按钮会显示新注入的内容五、jdb动态分析第三方文件管理器应用程序安装apk文件到模拟器JDB连接模拟器使用“methods”命令进入FileViewInteractionHub类,查看类中的所有方法。
找到要分析的方法“onOperationSetting”在“onOperationSetting”方法中设置断点。
使用“next”命令继续执行程序,使用“step”命令进入方法,使用“locals”命令查看方法中的变量,查看到text控件中原本将要显示的值是“Setting Soft Value”,使用“set”命令修改这个变量值为“Test Android FileExplorer Settings By JDB Command”,使用“run”命令继续运行程序。