前言
这些是从其他软件逆向出来的四种检测手段,能不能用暂时没试过,但是逆向之前是能用的。
正文
- Xposed检测(XposedDetect)
检测到Xposed环境就强制闪退
public static boolean XposedDetect(){
if (checkXpFormMap()) {
System.exit(1);
}
if (isHookByStack()) {
System.exit(1);
}
return false;
}
private static boolean isHookByStack() {
boolean isHook = false;
try {
throw new Exception("blah");
} catch (Exception e) {
int zygoteInitCallCount = 0;
StackTraceElement[] stackTrace = e.getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if (stackTraceElement.getClassName().equals("com.android.internal.os.ZygoteInit") && (zygoteInitCallCount = zygoteInitCallCount + 1) == 2) {
isHook = true;
}
if (stackTraceElement.getClassName().equals("com.saurik.substrate.MS$2") && stackTraceElement.getMethodName().equals("invoked")) {
isHook = true;
}
if (stackTraceElement.getClassName().equals("de.robv.android.xposed.XposedBridge") && stackTraceElement.getMethodName().equals("main")) {
isHook = true;
}
if (stackTraceElement.getClassName().equals("de.robv.android.xposed.XposedBridge") && stackTraceElement.getMethodName().equals("handleHookedMethod")) {
isHook = true;
}
}
return isHook;
}
}
private static boolean checkXpFormMap() {
File maps;
String readLine;
int Pid = Process.myPid();
if (Pid < 0) {
maps = new File("/proc/self/maps");
} else {
maps = new File("/proc/" + Pid + "/maps");
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(maps)));
do {
readLine = reader.readLine();
if (readLine == null) {
return false;
}
if (readLine.contains("libdexposed") || readLine.contains("libsubstrate.so") || readLine.contains("libepic.so")) {
return true;
}
} while (!readLine.contains("libxposed"));
return true;
} catch (Exception e) {
e.printStackTrace();
return true;
}
}
- 断网检测(NetworkDetect)
无网络就强制闪退
public static boolean NetworkDetect(Context context){
if (!isNetworkStatus((Context) Objects.requireNonNull(context))) {
System.exit(0);
}
if (!isNetworkConnected((Context) Objects.requireNonNull(context))) {
System.exit(0);
}
return false;
}
private static boolean isNetworkConnected(Context context) {
NetworkInfo activeNetworkInfo = ((ConnectivityManager) context.getSystemService("connectivity")).getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();
}
private static boolean isNetworkStatus(Context context) {
NetworkInfo activeNetworkInfo;
if (context == null || (activeNetworkInfo = ((ConnectivityManager) context.getSystemService("connectivity")).getActiveNetworkInfo()) == null) {
return false;
}
return activeNetworkInfo.isAvailable();
}
- 模拟器检测(SimulatorDetect)
检测当前是否运行在安卓模拟器环境
public static boolean SimulatorDetect(Context context){
if (isEmulator(context)) {
System.exit(1);
throw new RuntimeException();
} else if (!isEmulatorAbsoluly(context)) {
return false;
} else {
System.exit(1);
throw new RuntimeException();
}
}
private static int rating = -1;
private static boolean isEmulatorAbsoluly(Context context) {
if (!mayOnEmulatorViaQEMU(context) && !Build.PRODUCT.contains("sdk") && !Build.PRODUCT.contains("sdk_x86") && !Build.PRODUCT.contains("sdk_google") && !Build.PRODUCT.contains("Andy") && !Build.PRODUCT.contains("Droid4X") && !Build.PRODUCT.contains("nox") && !Build.PRODUCT.contains("vbox86p") && !Build.PRODUCT.contains("aries") && !Build.MANUFACTURER.equals("Genymotion") && !Build.MANUFACTURER.contains("Andy") && !Build.MANUFACTURER.contains("nox") && !Build.MANUFACTURER.contains("TiantianVM") && !Build.BRAND.contains("Andy") && !Build.DEVICE.contains("Andy") && !Build.DEVICE.contains("Droid4X") && !Build.DEVICE.contains("nox") && !Build.DEVICE.contains("vbox86p") && !Build.DEVICE.contains("aries") && !Build.MODEL.contains("Emulator") && !Build.MODEL.equals("google_sdk") && !Build.MODEL.contains("Droid4X") && !Build.MODEL.contains("TiantianVM") && !Build.MODEL.contains("Andy") && !Build.MODEL.equals("Android SDK built for x86_64") && !Build.MODEL.equals("Android SDK built for x86") && !Build.HARDWARE.equals("vbox86") && !Build.HARDWARE.contains("nox") && !Build.HARDWARE.contains("ttVM_x86") && !Build.FINGERPRINT.contains("generic/sdk/generic") && !Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") && !Build.FINGERPRINT.contains("Andy") && !Build.FINGERPRINT.contains("ttVM_Hdragon") && !Build.FINGERPRINT.contains("generic/google_sdk/generic") && !Build.FINGERPRINT.contains("vbox86p") && !Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {
return false;
}
return true;
}
private static boolean isEmulator(Context context) {
if (isEmulatorAbsoluly(context)) {
return true;
}
int newRating = 0;
if (rating < 0) {
if (Build.PRODUCT.contains("sdk") || Build.PRODUCT.contains("Andy") || Build.PRODUCT.contains("ttVM_Hdragon") || Build.PRODUCT.contains("google_sdk") || Build.PRODUCT.contains("Droid4X") || Build.PRODUCT.contains("nox") || Build.PRODUCT.contains("sdk_x86") || Build.PRODUCT.contains("sdk_google") || Build.PRODUCT.contains("vbox86p") || Build.PRODUCT.contains("aries")) {
newRating = 0 + 1;
}
if (Build.MANUFACTURER.equals("unknown") || Build.MANUFACTURER.equals("Genymotion") || Build.MANUFACTURER.contains("Andy") || Build.MANUFACTURER.contains("MIT") || Build.MANUFACTURER.contains("nox") || Build.MANUFACTURER.contains("TiantianVM")) {
newRating++;
}
if (Build.BRAND.equals("generic") || Build.BRAND.equals("generic_x86") || Build.BRAND.equals("TTVM") || Build.BRAND.contains("Andy")) {
newRating++;
}
if (Build.DEVICE.contains("generic") || Build.DEVICE.contains("generic_x86") || Build.DEVICE.contains("Andy") || Build.DEVICE.contains("ttVM_Hdragon") || Build.DEVICE.contains("Droid4X") || Build.DEVICE.contains("nox") || Build.DEVICE.contains("generic_x86_64") || Build.DEVICE.contains("vbox86p") || Build.DEVICE.contains("aries")) {
newRating++;
}
if (Build.MODEL.equals("sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.equals("google_sdk") || Build.MODEL.contains("Droid4X") || Build.MODEL.contains("TiantianVM") || Build.MODEL.contains("Andy") || Build.MODEL.equals("Android SDK built for x86_64") || Build.MODEL.equals("Android SDK built for x86")) {
newRating++;
}
if (Build.HARDWARE.equals("goldfish") || Build.HARDWARE.equals("vbox86") || Build.HARDWARE.contains("nox") || Build.HARDWARE.contains("ttVM_x86")) {
newRating++;
}
if (Build.FINGERPRINT.contains("generic/sdk/generic") || Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") || Build.FINGERPRINT.contains("Andy") || Build.FINGERPRINT.contains("ttVM_Hdragon") || Build.FINGERPRINT.contains("generic_x86_64") || Build.FINGERPRINT.contains("generic/google_sdk/generic") || Build.FINGERPRINT.contains("vbox86p") || Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {
newRating++;
}
try {
String opengl = GLES20.glGetString(7937);
if (opengl != null && (opengl.contains("Bluestacks") || opengl.contains("Translator"))) {
newRating += 10;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (new File(Environment.getExternalStorageDirectory().toString() + File.separatorChar + "windows" + File.separatorChar + "BstSharedFolder").exists()) {
newRating += 10;
}
} catch (Exception e2) {
e2.printStackTrace();
}
rating = newRating;
}
if (rating <= 3) {
return false;
}
return true;
}
private static boolean mayOnEmulatorViaQEMU(Context context) {
return "1".equals(getProp(context));
}
@SuppressLint({"PrivateApi"})
private static String getProp(Context context) {
try {
Class<?> SystemProperties = context.getClassLoader().loadClass("android.os.SystemProperties");
return (String) SystemProperties.getMethod("get", String.class).invoke(SystemProperties, "ro.kernel.qemu");
} catch (Exception e) {
return null;
}
}
- VPN代理抓包检测(VpnDetect)
检测是否开启VPN代理或者HttpCanary抓包
public static boolean VpnDetect(Context context){
if (isVpnConnected() || isWifiProxy(context)) {
System.exit(0);
}
return false;
}
private static boolean isWifiProxy(Context mContext) {
String proxyAddress;
int proxyPort;
if (Build.VERSION.SDK_INT >= 14) {
proxyAddress = System.getProperty("http.proxyHost");
String portStr = System.getProperty("http.proxyPort");
if (portStr == null) {
portStr = "-1";
}
proxyPort = Integer.parseInt(portStr);
} else {
proxyAddress = Proxy.getHost(mContext);
proxyPort = Proxy.getPort(mContext);
}
if (TextUtils.isEmpty(proxyAddress) || proxyPort == -1) {
return false;
}
return true;
}
private static boolean isVpnConnected() {
try {
Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
if (niList == null) {
return false;
}
Iterator<NetworkInterface> it = Collections.list(niList).iterator();
while (it.hasNext()) {
NetworkInterface intf = it.next();
if (intf.isUp() && intf.getInterfaceAddresses().size() != 0) {
if ("tun0".equals(intf.getName()) || "ppp0".equals(intf.getName())) {
return true;
}
}
}
return false;
} catch (Throwable e) {
e.printStackTrace();
return false;
}
}
别忘了权限。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
最后来整合一下
DetectUtils.java
import java.io.File;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.net.NetworkInterface;
import java.util.Iterator;
import java.util.Collections;
import android.os.Process;
import android.content.Context;
import android.net.NetworkInfo;
import android.net.ConnectivityManager;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Environment;
import android.opengl.GLES20;
import android.net.Proxy;
import android.text.TextUtils;
import java.util.Objects;
public class DetectUtils {
public static boolean XposedDetect(){
if (checkXpFormMap()) {
System.exit(1);
}
if (isHookByStack()) {
System.exit(1);
}
return false;
}
private static boolean isHookByStack() {
boolean isHook = false;
try {
throw new Exception("blah");
} catch (Exception e) {
int zygoteInitCallCount = 0;
StackTraceElement[] stackTrace = e.getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if (stackTraceElement.getClassName().equals("com.android.internal.os.ZygoteInit") && (zygoteInitCallCount = zygoteInitCallCount + 1) == 2) {
isHook = true;
}
if (stackTraceElement.getClassName().equals("com.saurik.substrate.MS$2") && stackTraceElement.getMethodName().equals("invoked")) {
isHook = true;
}
if (stackTraceElement.getClassName().equals("de.robv.android.xposed.XposedBridge") && stackTraceElement.getMethodName().equals("main")) {
isHook = true;
}
if (stackTraceElement.getClassName().equals("de.robv.android.xposed.XposedBridge") && stackTraceElement.getMethodName().equals("handleHookedMethod")) {
isHook = true;
}
}
return isHook;
}
}
private static boolean checkXpFormMap() {
File maps;
String readLine;
int Pid = Process.myPid();
if (Pid < 0) {
maps = new File("/proc/self/maps");
} else {
maps = new File("/proc/" + Pid + "/maps");
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(maps)));
do {
readLine = reader.readLine();
if (readLine == null) {
return false;
}
if (readLine.contains("libdexposed") || readLine.contains("libsubstrate.so") || readLine.contains("libepic.so")) {
return true;
}
} while (!readLine.contains("libxposed"));
return true;
} catch (Exception e) {
e.printStackTrace();
return true;
}
}
public static boolean NetworkDetect(Context context){
if (!isNetworkStatus((Context) Objects.requireNonNull(context))) {
System.exit(0);
}
if (!isNetworkConnected((Context) Objects.requireNonNull(context))) {
System.exit(0);
}
return false;
}
private static boolean isNetworkConnected(Context context) {
NetworkInfo activeNetworkInfo = ((ConnectivityManager) context.getSystemService("connectivity")).getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();
}
private static boolean isNetworkStatus(Context context) {
NetworkInfo activeNetworkInfo;
if (context == null || (activeNetworkInfo = ((ConnectivityManager) context.getSystemService("connectivity")).getActiveNetworkInfo()) == null) {
return false;
}
return activeNetworkInfo.isAvailable();
}
public static boolean SimulatorDetect(Context context){
if (isEmulator(context)) {
System.exit(1);
throw new RuntimeException();
} else if (!isEmulatorAbsoluly(context)) {
return false;
} else {
System.exit(1);
throw new RuntimeException();
}
}
private static int rating = -1;
private static boolean isEmulatorAbsoluly(Context context) {
if (!mayOnEmulatorViaQEMU(context) && !Build.PRODUCT.contains("sdk") && !Build.PRODUCT.contains("sdk_x86") && !Build.PRODUCT.contains("sdk_google") && !Build.PRODUCT.contains("Andy") && !Build.PRODUCT.contains("Droid4X") && !Build.PRODUCT.contains("nox") && !Build.PRODUCT.contains("vbox86p") && !Build.PRODUCT.contains("aries") && !Build.MANUFACTURER.equals("Genymotion") && !Build.MANUFACTURER.contains("Andy") && !Build.MANUFACTURER.contains("nox") && !Build.MANUFACTURER.contains("TiantianVM") && !Build.BRAND.contains("Andy") && !Build.DEVICE.contains("Andy") && !Build.DEVICE.contains("Droid4X") && !Build.DEVICE.contains("nox") && !Build.DEVICE.contains("vbox86p") && !Build.DEVICE.contains("aries") && !Build.MODEL.contains("Emulator") && !Build.MODEL.equals("google_sdk") && !Build.MODEL.contains("Droid4X") && !Build.MODEL.contains("TiantianVM") && !Build.MODEL.contains("Andy") && !Build.MODEL.equals("Android SDK built for x86_64") && !Build.MODEL.equals("Android SDK built for x86") && !Build.HARDWARE.equals("vbox86") && !Build.HARDWARE.contains("nox") && !Build.HARDWARE.contains("ttVM_x86") && !Build.FINGERPRINT.contains("generic/sdk/generic") && !Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") && !Build.FINGERPRINT.contains("Andy") && !Build.FINGERPRINT.contains("ttVM_Hdragon") && !Build.FINGERPRINT.contains("generic/google_sdk/generic") && !Build.FINGERPRINT.contains("vbox86p") && !Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {
return false;
}
return true;
}
private static boolean isEmulator(Context context) {
if (isEmulatorAbsoluly(context)) {
return true;
}
int newRating = 0;
if (rating < 0) {
if (Build.PRODUCT.contains("sdk") || Build.PRODUCT.contains("Andy") || Build.PRODUCT.contains("ttVM_Hdragon") || Build.PRODUCT.contains("google_sdk") || Build.PRODUCT.contains("Droid4X") || Build.PRODUCT.contains("nox") || Build.PRODUCT.contains("sdk_x86") || Build.PRODUCT.contains("sdk_google") || Build.PRODUCT.contains("vbox86p") || Build.PRODUCT.contains("aries")) {
newRating = 0 + 1;
}
if (Build.MANUFACTURER.equals("unknown") || Build.MANUFACTURER.equals("Genymotion") || Build.MANUFACTURER.contains("Andy") || Build.MANUFACTURER.contains("MIT") || Build.MANUFACTURER.contains("nox") || Build.MANUFACTURER.contains("TiantianVM")) {
newRating++;
}
if (Build.BRAND.equals("generic") || Build.BRAND.equals("generic_x86") || Build.BRAND.equals("TTVM") || Build.BRAND.contains("Andy")) {
newRating++;
}
if (Build.DEVICE.contains("generic") || Build.DEVICE.contains("generic_x86") || Build.DEVICE.contains("Andy") || Build.DEVICE.contains("ttVM_Hdragon") || Build.DEVICE.contains("Droid4X") || Build.DEVICE.contains("nox") || Build.DEVICE.contains("generic_x86_64") || Build.DEVICE.contains("vbox86p") || Build.DEVICE.contains("aries")) {
newRating++;
}
if (Build.MODEL.equals("sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.equals("google_sdk") || Build.MODEL.contains("Droid4X") || Build.MODEL.contains("TiantianVM") || Build.MODEL.contains("Andy") || Build.MODEL.equals("Android SDK built for x86_64") || Build.MODEL.equals("Android SDK built for x86")) {
newRating++;
}
if (Build.HARDWARE.equals("goldfish") || Build.HARDWARE.equals("vbox86") || Build.HARDWARE.contains("nox") || Build.HARDWARE.contains("ttVM_x86")) {
newRating++;
}
if (Build.FINGERPRINT.contains("generic/sdk/generic") || Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") || Build.FINGERPRINT.contains("Andy") || Build.FINGERPRINT.contains("ttVM_Hdragon") || Build.FINGERPRINT.contains("generic_x86_64") || Build.FINGERPRINT.contains("generic/google_sdk/generic") || Build.FINGERPRINT.contains("vbox86p") || Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) {
newRating++;
}
try {
String opengl = GLES20.glGetString(7937);
if (opengl != null && (opengl.contains("Bluestacks") || opengl.contains("Translator"))) {
newRating += 10;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (new File(Environment.getExternalStorageDirectory().toString() + File.separatorChar + "windows" + File.separatorChar + "BstSharedFolder").exists()) {
newRating += 10;
}
} catch (Exception e2) {
e2.printStackTrace();
}
rating = newRating;
}
if (rating <= 3) {
return false;
}
return true;
}
private static boolean mayOnEmulatorViaQEMU(Context context) {
return "1".equals(getProp(context));
}
@SuppressLint({"PrivateApi"})
private static String getProp(Context context) {
try {
Class<?> SystemProperties = context.getClassLoader().loadClass("android.os.SystemProperties");
return (String) SystemProperties.getMethod("get", String.class).invoke(SystemProperties, "ro.kernel.qemu");
} catch (Exception e) {
return null;
}
}
public static boolean VpnDetect(Context context){
if (isVpnConnected() || isWifiProxy(context)) {
System.exit(0);
}
return false;
}
private static boolean isWifiProxy(Context mContext) {
String proxyAddress;
int proxyPort;
if (Build.VERSION.SDK_INT >= 14) {
proxyAddress = System.getProperty("http.proxyHost");
String portStr = System.getProperty("http.proxyPort");
if (portStr == null) {
portStr = "-1";
}
proxyPort = Integer.parseInt(portStr);
} else {
proxyAddress = Proxy.getHost(mContext);
proxyPort = Proxy.getPort(mContext);
}
if (TextUtils.isEmpty(proxyAddress) || proxyPort == -1) {
return false;
}
return true;
}
private static boolean isVpnConnected() {
try {
Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
if (niList == null) {
return false;
}
Iterator<NetworkInterface> it = Collections.list(niList).iterator();
while (it.hasNext()) {
NetworkInterface intf = it.next();
if (intf.isUp() && intf.getInterfaceAddresses().size() != 0) {
if ("tun0".equals(intf.getName()) || "ppp0".equals(intf.getName())) {
return true;
}
}
}
return false;
} catch (Throwable e) {
e.printStackTrace();
return false;
}
}
}
来个彩蛋,防截屏 防止软件被截屏 NoPhotograph.java
import android.app.Activity;
import android.app.Application;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import java.util.Objects;
public class NoPhotograph extends ContentProvider implements Application.ActivityLifecycleCallbacks {
public int delete(Uri uri, String str, String[] strArr) {
return 0;
}
public String getType(Uri uri) {
return null;
}
public Uri insert(Uri uri, ContentValues contentValues) {
return null;
}
public void onActivityCreated(Activity activity, Bundle bundle) {
activity.getWindow().setFlags(8192, 8192);
}
public void onActivityDestroyed(Activity activity) {
}
public void onActivityPaused(Activity activity) {
}
public void onActivityResumed(Activity activity) {
}
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
public void onActivityStarted(Activity activity) {
activity.getWindow().setFlags(8192, 8192);
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public boolean onCreate() {
((Application) ((Context) Objects.requireNonNull(getContext())).getApplicationContext()).registerActivityLifecycleCallbacks(this);
return false;
}
@Override
public Cursor query(Uri uri, String[] strArr, String str, String[] strArr2, String str2) {
return null;
}
@Override
public int update(Uri uri, ContentValues contentValues, String str, String[] strArr) {
return 0;
}
}
下面这个添加到application
<provider
android:name="com.software.protect.NoPhotograph"
android:exported="false"
android:authorities="防截屏"
android:initOrder="19999999" />
结尾
好了,本次分享就到此结束了,如果满意的话请记得点赞,谢谢。
|