Android反调试

admin 2022年1月14日08:02:11移动安全评论18 views3685字阅读12分17秒阅读模式
Android反调试

点击上方蓝字关注我们


Android反调试


Android反调试

     主要是用来防止IDA进行附加的,主要的方法思路就是,判断自身是否有父进程,判断是否端口被监听,然后通过调用so文件中的线程进行监视,这个线程开启一般JNI_OnLoad中进行开启的。过反调试的话呢,就要把相关的函数进行NOP掉,直接将这几个字节改为00就可以了。

示例

首先反编译一下:

Android反调试    发现自带不可以调试,我们给他增加上:android:debuggable="true"application的节点中,然后进行编译,签名,安装。然后打开IDA进行附加:

    1. 常规的运行服务器,转发端口

    2. 然后使用调试模式进行运行:

    adb shell am start -D -n com.yaotong.crackme/.MainActivity

    Android反调试

    3. 运行之后,使用IDA进行附加,附加的时候正常操作,但是进去之后我们需要选择一下:在调试器的调试器选项中设置: 

    Android反调试

     我们勾选上在载入动态库的时候断下。

    4. 然后点击运行,之后就会不动,这个时候我们用jdb绑定端口(ddms需要打开的情况下使用8700端口),使用命令:

     jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700

    然后程序就会断下,因为在加载so文件。

    5. 然后我们一次运行就查看是否是我们的so被载入,我们的so文件名是:libcrackme.so

    6. 当被载入的时候,我们就选择在JNI_OnLoad中进行下段。                             Android反调试 

    7. 然后我们慢慢运行,直到我们运行至BXL R7的时候,IDA自己就掉了,所以我们可以推断,这个BLX跳转是反调试我们的IDA,这个时候我们就可以使用十六进制修改器修改我们的程序,将这个BLX R7改为00000000           Android反调试

    8. 转到十六进制视图,找到这个语句:37 FF 2F E1这四个字节我们就可以在十六进制修改器中修改为00 00 00 00. Android反调试

    9. 然后重新编译。

    这个时候我们重新安装运行,我们还是用调试模式运行:adb shell am start -D -n com.yaotong.crackme/.MainActivity,应该也不需要了,因为反调试让我们给nop掉了,我们这个时候运行,发现程序正常被IDA附加了。

java分析

反编译的java伪代码如下:

public class MainActivity extends Activity public Button btn_submit; public EditText inputCode; static { System.loadLibrary("crackme"); } protected void onCreate(Bundle paramBundle) super.onCreate(paramBundle); setContentView(2130903040); getWindow().setBackgroundDrawableResource(2130837504); this.inputCode = ((EditText)findViewById(2131099648)); this.btn_submit = ((Button)findViewById(2131099649)); this.btn_submit.setOnClickListener(new View.OnClickListener() { public void onClick(View paramAnonymousView) { paramAnonymousView = MainActivity.this.inputCode.getText().toString(); if (MainActivity.this.securityCheck(paramAnonymousView)) { paramAnonymousView = new Intent(MainActivity.this, ResultActivity.class); MainActivity.this.startActivity(paramAnonymousView); return; } Toast.makeText(MainActivity.this.getApplicationContext(), "验证码校验失败"0).show(); } }); } public native boolean securityCheck(String paramString); }

    载入时候的,发现按钮被点击之后,调用了securityCheck这个方法,这是个本地函数,我们在IDA中进行寻找:                                    

看一下IDA给我们的伪代码:

signed int __fastcall Java_com_yaotong_crackme_MainActivity_securityCheck(int a1, int a2, int a3) { int v3; // r5 int v4; // r4 unsigned __int8 *v5; // r0 char *v6; // r2 int v7; // r3 signed int v8; // r1 v3 = a1; v4 = a3; if ( !byte_B3DF5359 ) { ((void (__fastcall *)(void *, signed int, void *, void *, signed int, signed int))unk_B3DF1494)( &unk_B3DF5304, 8, &unk_B3DF346B, &unk_B3DF3468, 2, 7); byte_B3DF5359 = 1; } if ( !byte_B3DF535A ) { ((void (__fastcall *)(void *, signed int, void *, void *, signed int, signed int))unk_B3DF14F4)( &unk_B3DF536C, 25, &unk_B3DF3530, &unk_B3DF3474, 3, 117); byte_B3DF535A = 1; } ((void (__fastcall *)(signed int, void *, void *))unk_B3DF00D4)(4, &unk_B3DF5304, &unk_B3DF536C); v5 = (unsigned __int8 *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)v3 + 676))(v3, v4, 0); v6 = off_B3DF528C; while ( 1 ) { v7 = (unsigned __int8)*v6; if ( v7 != *v5 ) break; ++v6; ++v5; v8 = 1; if ( !v7 ) return v8; } return 0; }

    很直观,和流程图中的差不多,前面几个是if语句,可能在操作一些加密之类的东西,不是很重要,但是我们发现最后返回的是根据V8和V0进行判断的,在java层我们也分析道我们要的就是返回值,看最后的循环语句,可以清楚的发现,其实就是就是一个类似于strcmp的一个函数,每一个字符进行比较,如果有一处不一样,就跳出循环,否则都一样的话呢,返回v8,这个是1,这下就好看了,我们有两种方法,获取到v5的值,这个就是注册码,或者是将这个返回修改一下也是可以的。

1.获取注册码:我们在这个循环判断之前下断:Android反调试

    发现其实就是每次取出一个字符,然后进行判断,这个R2中的或者R0中的就是我们的注册码,动态调试一下:Android反调试    这个不是我们输入的,我输入的是123,这个不一样,所以基本可以判定是注册码,发现真是!

2.修改跳转 Android反调试      第一个BNE的跳转发现,如果满足,就回到下面的一个分支,而不满足就到另外一个分支,而下面的分支中又有一个BNE,这个BNE会往上进行跳转,这个是不是就是很容易理解了,所以这个就是我们while循环,并且进一步分析,发现我们第一个BNE的不进入循环的分支就是返回,也就是返回假,而进入循环一直循环的结束分支也就是左边的那个,应该就是返回真的,所以我们在so层的话呢,我们最好的办法就是直接将这两个BNE给NOP掉,这样子的话呢我们就可以顺序执行,最终只循环一次就可以实现返回真!

    我们将第一个BNE:05 00 00 1A修改为00 00 00 00 我们将第一个BNE:F6 FF FF 1A修改为00 00 00 00

    尝试修改编译之后发现,确实是实现了!

    并且其实在java层的修改其实也是可以实现我们的一个程序破解的!



往期推荐



MSF常用命令梳理

ARP欺骗

【Cheetah语言】缓冲区溢出


Android反调试

点个在看你最好看


本文始发于微信公众号(云剑侠心):Android反调试

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月14日08:02:11
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Android反调试 http://cn-sec.com/archives/479550.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: