前段时间我写了一篇 android gdb 调试实例演示(有源代码篇)见下面的链接
http://sunzeduo.blog.51cto.com/2758509/1388555
主要是总结一下开发人员调试ndk编译出来的so来用的,对于破解人员,可能就不会有源代码,也不会有带符号表的so库文件了,这个时候破解人员要找到so中的关键函数,并且动态的调试,就需要一些手段了。
下面,还就着上面的一篇博文的例子展开,描述一下没有源代码的时候如何调试so
一 前置条件:
1 ida工具 主要用于静态分析
2 android版本的 gdbserver(同前一篇)
3 android版本的 gdb (同前一篇)
二 开始分析:
因为本身这篇博文主要描述调试过程,而不是描述破解的思路,所以假定我们已经找到例子代码中的关心的so库文件 libsocketclient.so
并且是关心的
Java_com_example_socketcomm_JniSocketClient_cliensocket
这个jni函数,想知道通过socket返回的数据是神马。
2.1 找到 libsocketclient.so 这个库在进程中的映射地址
shell@android:/ # cat /proc/30646/maps | busybox grep libsocketclient 58ead000-58eb0000 r-xp 00000000 103:04 627350 /data/data/com.example.socketcomm/lib/libsocketclient.so 58eb0000-58eb1000 r--p 00002000 103:04 627350 /data/data/com.example.socketcomm/lib/libsocketclient.so 58eb1000-58eb2000 rw-p 00003000 103:04 627350 /data/data/com.example.socketcomm/lib/libsocketclient.so
这个库可执行段映射的地址是 0x58ead000
2.2 通过ida静态分析,找到关心函数的地址
通过ida发现这个函数在 libsocketclient.so 中的开始地址是 ea0
而我们关心的数据的在这个函数的地址如下图,标记的红圈
0x1040 这个是接收到 socket数据的地址,所以我们应该在这个地方打上断点,然后动态调试。
我们实际应该打断点的地址应该是
58ead000 + 1040 = 58eae040
2.2 利用gdb调试,找到关心的值
0x4008aa40 in ?? () (gdb) b *0x58eae040 Breakpoint 1 at 0x58eae040 (gdb) c Continuing. [New Thread 30769] [Switching to Thread 30769] Breakpoint 1, 0x58eae040 in ?? ()
设置断点以后,再点击发送数据 ok ,进程停止到了设置断点的地方了
(gdb) info reg r0 0x12 18 r1 0x5ef8e85c 1593370716 r2 0x0 0 r3 0x0 0 r4 0x58eaf690 1491793552 r5 0x0 0 r6 0x31 49 r7 0x5c051db8 1543839160 r8 0x400cda4c 1074584140 r9 0x5ef8ec60 1593371744 r10 0x5c06bec0 1543945920 r11 0x5ef8ec94 1593371796 r12 0x5ef8e830 1593370672 sp 0x5ef8e840 0x5ef8e840 lr 0x40096ec9 1074360009 pc 0x58eae040 0x58eae040 cpsr 0x10 16 (gdb) print (char*)0x5ef8e85c $1 = 0x5ef8e85c "server back buff 5" (gdb) c Continuing.
查看寄存器的值,然后打印寄存器的值的数据,ok 我们想要的值已经获取。
三 小结
本篇博文主要是描述无源码的gdb调试方法,所以不针对so的静态分析的过程,其实调试方法只是找到最终答案的一个重要步骤,而通过对系统的熟悉,拨开层层迷雾,找到关键的库,找到关键的函数,才是整个逆向分析中最重要的一步。
注:附件和开头列出的链接地址的博文附件相同,就不添加了。
本文出自 “leeleell” 博客,请务必保留此出处http://sunzeduo.blog.51cto.com/2758509/1393012