作者:郭孝星
微博:郭孝星的新浪微博
邮箱:[email protected]
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWell
【Android应用保护技术探索之路系列】章节目录
【Android应用保护技术探索之路系列】之一:Android应用保护技术开篇
【Android应用保护技术探索之路系列】之二:对抗反编译
【Android应用保护技术探索之路系列】之三:对抗静态分析
【Android应用保护技术探索之路系列】之四:对抗动态调试
【Android应用保护技术探索之路系列】之五:对抗重编译
对抗动态调试常用的有两种方式:检测调试器和检测模拟器。
一 检测调试器
动态调试器使用调试器来挂钩应用,获取应用运行时的数据。我们可以在应用中加入检测调试器的代码,如果检测到调试器则终止应用的运行。
在AndroidManifest.xml的Application标签中加入:
android:debuggable = "false"
来让应用不可调试。
我们可以在应用运行时检测这个标志是否被修改,如果被修改则终止程序运行,如下所示:
package com.droider.antidebug;import android.os.Bundle;import android.app.Activity;import android.content.pm.ApplicationInfo;import android.util.Log;import android.view.Menu;import android.widget.Toast;public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("反调试演示程序"); if ((getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0){ Log.e("com.droider.antidebug", "程序被修改为可调试状态"); android.os.Process.killProcess(android.os.Process.myPid()); } if (android.os.Debug.isDebuggerConnected()) { //检测调试器 Log.e("com.droider.antidebug", "检测到测试器"); android.os.Process.killProcess(android.os.Process.myPid()); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; }}
二 检测模拟器
应用发布后是给用户安装到手机中运行的,如果发现应用运行在模拟器中,这显然不是正常的情况,说明可能有人想分析它,这个时候我们应予以阻止。
模拟器和真实设备有着诸多差异,比如:
- ro.product.model:该值在模拟器中是sdk,在真实设备中是手机的型号。
- ro.build.tags:该值在模拟器中是test-keys,在真实设备中是realease-keys。
- ro.lernel.qemu:该值在模拟器中是1,在真实设备中没有该属性。
下面以ro.lernel.qemu属性为例,检测代码如下:
package com.droider.checkqemu;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.InputStreamReader;import java.lang.reflect.Method;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.graphics.Color;import android.util.Log;import android.view.Menu;import android.widget.TextView;public class MainActivity extends Activity { private TextView text_info; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("模拟器检测演示程序"); text_info = (TextView) findViewById(R.id.textView1); if (isRunningInEmualtor()) { //检测模拟器 text_info.setTextColor(Color.RED); text_info.setText("程序运行在模拟器中!"); } else { text_info.setTextColor(Color.GREEN); text_info.setText("程序运行在真实设备中!"); } } boolean isRunningInEmualtor() { boolean qemuKernel = false; Process process = null; DataOutputStream os = null; try{ process = Runtime.getRuntime().exec("getprop ro.kernel.qemu"); os = new DataOutputStream(process.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK")); os.writeBytes("exit\n"); os.flush(); process.waitFor(); qemuKernel = (Integer.valueOf(in.readLine()) == 1); Log.d("com.droider.checkqemu", "检测到模拟器:" + qemuKernel); } catch (Exception e){ qemuKernel = false; Log.d("com.droider.checkqemu", "run failed" + e.getMessage()); } finally { try{ if (os != null) { os.close(); } process.destroy(); } catch (Exception e) { } Log.d("com.droider.checkqemu", "run finally"); } return qemuKernel; } public static String getProp(Context context, String property) { try { ClassLoader cl = context.getClassLoader(); Class SystemProperties = cl.loadClass("android.os.SystemProperties"); Method method = SystemProperties.getMethod("get", String.class); Object[] params = new Object[1]; params[0] = new String(property); return (String)method.invoke(SystemProperties, params); } catch (Exception e) { return null; } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; }}
版权声明:本文为博主原创文章,未经博主允许不得转载。