Android逆向中的常用调试方法和使用代码总结

0x01 smail语言的调式方法

a.动态分析法,利用log日志输入或者toast输出。

利用Toast进行调试
java代码
Toast.makeText(this, "Toast text", 1).show(); 
smail代码
const-string v0, "Toast text"
const/4 v1, 0x1
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V

利用Log日志输出
java代码
Log.v("android_log","test")
smail代码
const-string v0, "test" 
const-string v3, "android_log"  
invoke-static {v3,v0}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I

整数转字符串代码
 invoke-static {v5}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
 move-result-object v5

log日志查看方式
DDMS自动logcat
AndroidKiller集成的log工具
adb命令查看:adb logcat -s android_log:v

b.栈跟踪法,原理输出运行时的栈的跟踪信息。然后查看栈上的函数调用序列来理解方法的执行流程。
java代码
new Exception("print trace").printStackTrace();
smail代码
new-instance v0, Ljava/lang/Exception;
const-string v1, "print trace"
invoke-direct {v0,v1}, Ljava/lang/Exception;-><init>(Ljava/lang/String;)V
invoke-virtual {v0}, Ljava/lang/Exception;->printStackTrace()V
查看方式
利用log日志输出信息
c.Method Profiling同栈分析法,显示处各个函数的调用信息。
Method Profiling方法
java 代码
android.os.Debug.startMethodTracing("123")
func():
android.os.Debug.stopMethodTracing():
smai代码
可以插入OnCreate()方法中
const-string v0,  "123"
invoke-static {v0}, Landroid/os/Debug;->startMethodTracing(Ljava/lang/String;)V

插入OnStop()方法
invoke-static {}, Landroid/os/Debug;->stopMethodTracing()V
注入需要加sd写入权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

查看方式
利用adb导出trace文件
adb pull  /mnt/sdcard/123.trace
在sdk下的tools目录下利用traceview查看
traceview 123.trace

0x02.arm语言的修改与调式
静态调式
arm指令的修改,很多工具在对arm汇编指令修改成相应的十六进制码的过程中容易出现错误,一般需要我们手动分析进行修改。
首先我们看一下mov指令arm编码指令的一般格式

下面我们详细解释各个区段的含义:
28-31段cond: 指令执行的条件编码,下面是常见的cond条件和对应二进制码。

26-27段:一般是00
25段:如果我们的源操作数是立即数,该位置是1,如果是寄存器,改位置为0.
21-24段:表示的是opcode位

20段:是否带S标志位,如果不带该位为0,指令带S标志位为1

16-19段:保留位,一般都设置为0000

12-15段:指令中目的寄存器,根据R0-R15对应0-15比如r1对应为0001,R0对应0000

0-11段:指令的操作数,如果为立即数有十进制转换为二进制代码即可,如果是寄存器,同R0-R15对应0-15


例如下面两个指令

指令一  mov r1, #107

对应机器码

1110  00  1  1101  0  0000  0001  000001101011

对应十六进制

E3 A0 10 6B

对应十六进制编辑器中的值

6B 10 A0 E3


指令二 mov r2,r1

对应机器码

1110  00  0  1 101  0   0000   0010   000000000001

对应十六进制

E1 A0 20 01

对应十六进制编辑器中的值

01 20 A0 E1

下面是arm指令的标准格式如下:


常用的跳转指令B和机器码直接的转换


28-31段cond: 指令执行的条件编码

25-27段:一般是101
24段:是否带link跳转,0不带链接,1带链接跳转
0-23段:存放的是要跳转的相对地址
地址的机器码计算方式x=((目的地址-源地址)-8)/4

pediy上的一个例子:

.text:00637C80 E5 34 42 EB       BL      __mulsf3
.text:016C501C                   EXPORT __mulsf3

BL __mulsf3的机器码为((0x16C501C-0x637C80)-8)/4=4234E5

BL为带连接无条件跳转机器码为1110 1011 对应16进制为EB故BL __mulsf3对应的机器码为EB4234E5,在十六进制编辑器中显示的情况就是E5 34 42 EB。也就是第一条之类中间的机器码相同。


动态调试

利用IDA动态调试方法(来自:Android软件安全与逆向分析)

调试原生程序

1.动态调试一般的Android原生程序
实例程序:debugnativeapp
在Android设备中添加、配置android_server程序
先将IDA目录下的./dbgsrv/android_server程序拷贝到Android设备下:
adb push ./dbgsrv/android_server /data/local/tmp/
配置文件权限属性,使其为可执行文件:
adb shell chmod 755/data/local/tmp/android_server
2将实例程序添加到Android设备
adb push debugnativeapp/data/local/tmp/
adb shell chmod 755/data/local/tmp/debugnativeapp
3启动调试服务
adb shell/data/local/tmp/android_server
4进行端口转发,使PC端口与Android端口可进行交互
adb forward tcp:23946tcp:23946
5启动IDA,进行程序调试
启动IDA的32bit程序,点击:Debugger-Run-RemoteArmLinux/Android debugger,打开调试程序的设置对话框:
Application:对应调试程序所在的路径
Directory:对应调试程序所在的目录路径
HostName:输入localhost,Port:PC端口

调式动态链接库

实例:debugjniso.apk
1.将apk安装在设备中,运行后界面如下,点击“设置标题”按钮,便会调用动态链接库libdebugjniso.so中的jniString()方法返回一个修改标题栏的字符串。在分析加壳程序的壳时,应以调试方式来启动调试程序(adb shell am start-D -n packagename/activityname)
2.启动调试服务,进行端口转发
adb shell /data/local/tmp/android_server
adb forward tcp:23946 tcp:23946
3.启动IDA进行程序调试
点击Debugger-Attach-RemoteArmLinux/Android debugger,打开设置框
HostName:输入localhost,Port:对应PC端口
点击OK,便会弹出附加Android进程的对话框,选中进程com.droider.debugjniso
4.使用jdb来连接上apk的java层
jdb -connectcom.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8601
5.确定jniString()方法当前的基地址
回到调试的IDA,使用Ctrl+S快捷键打开段选择对话框,可查找到libdebugjniso.so当前的基地址为:4B1F2000(随加载改变)
6.定位到jniString()方法的程序位置
由内存地址=基地址+偏移地址(4b1f2000:00000c38),可得当前jniString()方法的内存地址为:0x4b1f2c38,使用快捷键G打开地址跳转框,输入内存地址
7.设定断点,进行调试
跳转在jniString()方法的程序位置,在0x4b1f2c38行设置断点(F2)


猜你喜欢

转载自blog.csdn.net/nextdoor6/article/details/54286718
今日推荐