动态调试攻击风险解决
application 设置debugable=“false”
另参考:
安卓应用加固之反动态调试技术总结
Android 动态加载(防止逆向编译)技术
App动态调试
代码未混淆风险
Android Studio 代码混淆(包教包会)
Android Studio 代码混淆(你真的会混淆吗)
Android studio开启代码混淆,让你的代码更安全
android studio 代码混淆如何忽略第三方jar包
界面劫持风险
Broadcast Receiver组件导出风险
AndroidManifest.xml中的
export=“true->false”
参考:移动APP安全测试
拒绝服务攻击漏洞
其他参考
移动APP安全测试
深入浅出 App 端安全漏洞之任意调试漏洞、中间人劫持漏洞及加密算法漏洞
我使用的代码
在Application中调用 securityCheck()
,注册ActivityLifecycleCallbacks,在onAcitivityResumed() 和 onActivityPause() 中做反劫持,就不用在BaseActivity中使用了。
private void securityCheck() {
// 防止动态调试攻击风险
DebuggerUtils.checkDebuggableInNotDebugModel(this);
// 反劫持
registerActivityLifecycleCallbacks(mSecurityLifecycleCallbacks);
}
ActivityLifecycleCallbacks mSecurityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
AntiHijackingUtils.getInstance().onResume();
}
@Override
public void onActivityPaused(Activity activity) {
AntiHijackingUtils.getInstance().onPause(activity);
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
};
AntiHijackingUtils 反劫持工具类
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
/**
* Title: AntiHijackingUtils<br/>
* Description: 反界面劫持工具类<br/>
* refer: [Android 防界面劫持方案,无视Android系统版本限制,无需操作栈] (https://blog.csdn.net/Prince_WenZheng/article/details/54630259?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare)
*/
public class AntiHijackingUtils {
/**
* 用于执行定时任务
*/
private Timer timer = null;
/**
* 用于保存当前任务
*/
private List<MyTimerTask> tasks = null;
/**
* 唯一实例
*/
private static AntiHijackingUtils antiHijackingUtils;
private AntiHijackingUtils() {
// 初始化
tasks = new ArrayList<MyTimerTask>();
timer = new Timer();
}
/**
* 获取唯一实例
*
* @return 唯一实例
*/
public static AntiHijackingUtils getInstance() {
if (antiHijackingUtils == null) {
antiHijackingUtils = new AntiHijackingUtils();
}
return antiHijackingUtils;
}
/**
* 在activity的onPause()方法中调用
*
* @param activity
*/
public void onPause(final Activity activity) {
MyTimerTask task = new MyTimerTask(activity);
tasks.add(task);
timer.schedule(task, 1000);
}
/**
* 在activity的onResume()方法中调用
*/
public void onResume() {
if (tasks.size() > 0) {
tasks.get(tasks.size() - 1).setCanRun(false);
tasks.remove(tasks.size() - 1);
}
}
/**
* 自定义TimerTask类
*/
class MyTimerTask extends TimerTask {
/**
* 任务是否有效
*/
private boolean canRun = true;
private Activity activity;
public void setCanRun(boolean canRun) {
this.canRun = canRun;
}
public MyTimerTask(Activity activity) {
this.activity = activity;
}
@Override
public void run() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (canRun) {
// 程序退到后台,进行风险警告
ToastUtil.popupMessage(activity, "程序切换至后台运行,请注意观察运行环境是否安全!");
tasks.remove(MyTimerTask.this);
}
}
});
}
}
}
防止动态调试工具类 DebuggerUtils
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Debug;
import android.support.v4.BuildConfig;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Locale;
/**
* 动态调试工具类
* · 检查是否被动态调试,如果是,则强制退出应用。
*
* refer: [Android防止被动态调试的解决方法] (https://blog.csdn.net/qq_43278826/article/details/106055838?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-2-106055838.nonecase)
*/
public class DebuggerUtils {
/**
* 判断当前应用是否是debug状态
*/
public static boolean isDebuggable(Context context) {
try {
ApplicationInfo info = context.getApplicationInfo();
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
} catch (Exception e) {
return false;
}
}
/**
* 检测是否在非Debug编译模式下,进行了调试操作,以防动态调试
*
* @param context
* @return
*/
public static void checkDebuggableInNotDebugModel(Context context) {
//非Debug 编译,反调试检测
if (!BuildConfig.DEBUG) {
if (isDebuggable(context)) {
System.exit(0);
}
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
//每隔300ms检测一次
Thread.sleep(300);
//判断是否有调试器连接,是就退出
if (Debug.isDebuggerConnected()) {
System.exit(0);
}
//判断是否被其他进程跟踪,是就退出
if (isUnderTraced()) {
System.exit(0);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "SafeGuardThread");
t.start();
}
if (isUnderTraced()) {
System.exit(0);
}
}
/**
* 当我们使用Ptrace方式跟踪一个进程时,目标进程会记录自己被谁跟踪,可以查看/proc/pid/status看到这个信息,而没有被调试的时候TracerPid为0
*
* @return
*/
private static boolean isUnderTraced() {
String processStatusFilePath = String.format(Locale.US, "/proc/%d/status", android.os.Process.myPid());
File procInfoFile = new File(processStatusFilePath);
try {
BufferedReader b = new BufferedReader(new FileReader(procInfoFile));
String readLine;
while ((readLine = b.readLine()) != null) {
if (readLine.contains("TracerPid")) {
String[] arrays = readLine.split(":");
if (arrays.length == 2) {
int tracerPid = Integer.parseInt(arrays[1].trim());
if (tracerPid != 0) {
return true;
}
}
}
}
b.close();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}