文章目录
  1. 1. 方法一
  2. 2. 方法二

原本的想法是想实操绕过反调试的,刚好以前这道移动安全挑战赛的第二题是有反调试的,于是拿来练手,过程中也对动态调试有了更深的一些理解。

方法一

1.反编译apk可以看到securityCheck是校验的函数,但是在so里

2.用ida打开so文件,分析securityCheck方法,主要实现的逻辑是比较字符串

找到一个字符串wojiushidaan,输入但是不正确,于是打算动态调试。如果直接在该函数下断点,然后进行调试,应用会直接退出,说明在这个函数之前可能存在着反调试的工作。

通常反调试可能在JNI_Onload或.init段的位置,因此我们在JNI_Onload下断点,进行调试。

3.开始动态调试,绕过反调试。调试的步骤如同上一篇文章的方法二所写。
(0)在JNI_Onload下断点
(1)启动android_server
(2)转发端口23946
(3)以调试模式启动应用,adb shell am start -D -n com.yaotong.crackme/.MainActivity
(4)ida挂载,process option,attach process
(5)启动ddms,jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
注:如果这里ddms上没有显示该进程,那么说明可能应用没有允许调试,可以修改Androidmanifest文件中的application标签,添加android:debuggable=”true”,重编译签名,重新安装应用。
(6)ida按运行,跳到JNI_Onload的地方了

(7)F8单步跟踪,直到PC走到C58这个位置,出现了警告,并且应用也退出了调试模式

(8)根据上述的反馈,可以判断BLX跳进去的这个地方可能有问题,于是我们重新挂载调试一遍。到R7这里,我们F7进入该函数,看到这里开了个线程,是做了检测反调试的工作

(9)再一次重新挂载动态调试,在单步跟踪到C58之前,nop掉C58这个地方。按F2(或右键->edit)修改为0000A0E1,在按一次F2应用修改。这一次平安无事地过了C58.

(10)按运行,然后在应用的输入框内输入,点击按钮。就跳到了securityCheck方法

(11)继续F8.根据之前静态分析的结果,可以定位这个地方。R0地址存的是我们输入的值,R2地址就是我们想要的flag.

(12)其中,过反调试的方法除了nop掉反调试检测的地方。网上还有大神提出使用Kill调试技巧。

该技巧是QEver 在《MSC的伪解题报告》中提到的。利用kill我们可以让程序挂起,然后用ida挂载上去,获取有用的信息,然后可以再用kill将程序恢复运行。我们还是拿自毁程序密码这个应用举例,具体实行方法如下:
1 首先用ps获取运行的app的pid。

2 然后用kill -19 [pid] 就可以将这个app挂起了。

3 随后我们用ida attach上这个app。因为整个进程都挂起了,所以这次ida挂载后app并没有闪退。然后就可以在内存中找到答案了。

4 如果想要恢复app的运行,需要将ida退出,然后再使用kill -18 [pid]即可。

方法二

在分析securityCheck方法时候,我们发现有一个android_log_print的方法,该方法会打印一些调试信息,那么我们尝试通过该log方法将flag的值输出来。具体方法如下:

  • 将从0x1284到0x129C处都用NOP改写(NOP为空操作)
  • 在0x12AC处调用android_log_print函数
  • 为了不影响R1的值,把0x12A0处的R1改成R3
  • 将0x12A4处的R1改成R3
  • 将0x12A8处指令改成MOV R0,#4
    因为so为二进制文件,所以我们修改的也是二进制。
  • NOP对应的二进制值为00 00 A0 E1
  • android_log_print对应的二进制值为88 FF FF EB
  • 0x12A0处的值应改为60 30 9F E5
  • 0x12A4处的值应改为07 20 93 E7
  • MOV R0,#4的值为04 00 A0 E3

在ida上直接修改只是会保存到相应的数据库中,而我们实际修改要通常十六进制编辑器直接对so文件进行修改。修改完后,重打包apk,运行,观察log信息。

文章目录
  1. 1. 方法一
  2. 2. 方法二