很多病毒都很先检测检测运行环境。如果不是沙箱环境就释放恶意代码。 我们来总结他检测了哪些模拟器的特性
检测一些系统特定属性,如检测当前设备手机号,设备DeviceId,dev下是否存在socket/qemud和qemu_pipe两个文件,以及build.prop下的一些属性
/**固件信息
/system/libc_malloc_debg_qem.so //在cm,魔趣等基于aosp改版的系统上会存在libc_malloc_debug_qemu.so这个文件
/sys/qemu_trace
/system/bin/qemu-props
/dev/socket/genyd
/dev/socket/baseband_genyd
/dev/socket/qemud
/dev/qemu_pipe
**/
我这里的代码列出来几个
private static String[] known_pipes={
"/dev/socket/qemud",
"/dev/qemu_pipe"
};
/**
* 检测“/dev/socket/qemud”,“/dev/qemu_pipe”这两个通道
*读取文件内容,然后检查已知QEmu的驱动程序的列表
* @param context The context of the application package.
* @return launcher activity name of this application. From the
* "android:name" attribute.
*/
public static boolean checkPipes(){
for(int i = 0; i < known_pipes.length; i++){
String pipes = known_pipes[i];
File qemu_socket = new File(pipes);
if(qemu_socket.exists()){
Log.v("Result:", "Find pipes!");
return true;
}
}
Log.i("Result:", "Not Find pipes!");
return false;
}
目前市面上流行的Android模拟器主要有
Genymotion,天天模拟器,夜神模拟器,海马玩模拟器,畅玩模拟器,itools模拟器,逍遥模拟器,文卓爷模拟器,原生Android模拟器,BlueStacks,我们都知道除了原生模拟器之外,大部分Android模拟器都是基于VirtualBox的,这是重要的检测点之一,其次相比于手机,模拟器上少了一些重要特征,如蓝牙功能,温度传感器等等,这些都是可以用来检测模拟器的依据,同时,每种定制版本的模拟器上,都会有一些它特有的可执行文件,如下是我在测试多种模拟器时收集的特征文件:
/**其他模拟器特性
/system/usr/idc/androVM_Virtual_Input.idc
/system/usr/keylayout/androVM_Virtual_Input.kl
/system/xbin/mount.vboxsf
/ueventd.android_x86.rc //基于VirtualBox的模拟器都会存在该属性
/ueventd.vbox86.rc //基于VirtualBox的模拟器都会存在该属性
**/
检测一些特殊信息,如当前设备cpu温度时,搜集了一些资料,提供了一个adb方式去获取,/sys/class/thermal/thermal_zoneX/temp(其中X是核心数量),但发现模拟器上没有thermal_zoneX目录,只有两个cooling_deviceX目录,因而有了一个新的判断依据,如下:
int checkTemp() {
DIR *dirptr = NULL; //当前手机的温度检测,手机下均有thermal_zone文件
int i = 0;
struct dirent *entry;
if ((dirptr = opendir("/sys/class/thermal/")) != NULL) {
while (entry = readdir(dirptr)) {
// LOGE("%s \n", entry->d_name);
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
continue;
}
char *tmp = entry->d_name;
if (strstr(tmp, "thermal_zone") != NULL) {
i++;
}
}
closedir(dirptr);
} else {
LOGE("open thermal fail");
}
return i;
}
使用opendir函数去访问thermal目录,遍历该目录下所有目录,当不存在thermal_zone目录时,则判断当前设备为模拟器
还有病毒使用的一种基于行走步数来判断是否是模拟器。
https://blog.trendmicro.com/trendlabs-security-intelligence/google-play-apps-drop-anubis-banking-malware-use-motion-based-evasion-tactics/
1,IMEI和IMSI
IMEI 移动设备国际身份码。
IMSI IMSI国际移动用户识别码,储存在SIfinal TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId();
String imsi = tm.getSubscriberId();:354273055927169 / null(无卡)
设备2:862966024243759 / 460011040618938
模拟器:000000000000000 / 310260000000000
2,SerialString serial = android.os.Build.SERIAL;:4df78680771b117b
设备2:OBAI5HDQZPDIRCQG
模拟器:unknown
3,androidString android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);和模拟器都有,16位。
4,Mac地址
WifiManager wifimanage=(WifiManager)getSystemService(Context.WIFI_SERVICE); WifiInfo wifiinfo= wifimanage.getConnectionInfo();
设备1:88:32:9b:1e:49:20
设备2:f8:a4:5f:fd:56:17
/**
* 检测手机上的一些硬件信息
*
* @param context The context of the application package.
* @return launcher activity name of this application. From the
* "android:name" attribute.
*/
public static Boolean CheckEmulatorBuild(Context context){
String BOARD = android.os.Build.BOARD;
String BOOTLOADER = android.os.Build.BOOTLOADER;
String BRAND = android.os.Build.BRAND;
String DEVICE = android.os.Build.DEVICE;
String HARDWARE = android.os.Build.HARDWARE;
String MODEL = android.os.Build.MODEL;
String PRODUCT = android.os.Build.PRODUCT;
if (BOARD == "unknown" || BOOTLOADER == "unknown"
|| BRAND == "generic" || DEVICE == "generic"
|| MODEL == "sdk" || PRODUCT == "sdk"
|| HARDWARE == "goldfish")
{
Log.v("Result:", "Find Emulator by EmulatorBuild!");
return true;
}
Log.v("Result:", "Not Find Emulator by EmulatorBuild!");
return false;
}
这种方式可以通过root后hook来绕过
一,native方式。
通过c代码读取设备中的配置和硬件相关信息。
1,diskstats
获取闪存的分区状态信息。
int fd = open(“/proc/diskstats”, O_RDONLY);
bytes = read(fd, buf, bytes);
区别:真机下都有mmcblk0分区,但是模拟器没有分区信息。
2,mac地址。
通过socket和ioctl读取mac地址。
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(sockfd, SIOCGIFCONF, (char*)&ifc);
ioctl(sockfd, SIOCGIFADDR, &ifr[i])
ioctl(sockfd, SIOCGIFHWADDR, (char*)&ifr[i])
区别:真机可以获取wlan0的ip和mac地址,模拟器只能获取eth0的ip和mac地址;
3,有用的prop信息。
__system_property_get(key, buf);
区别: 模拟器没有ro.boot.serialno和ro.serialno属性,真机中为机器序列号。
模拟器 ro.hardware属性为goldfish,真机为各自的型号。
4,cpu信息。
int fd = open(“/proc/cpuinfo”, O_RDONLY);
bytes = read(fd, buf, bytes);
区别:模拟器中cpuinfo的硬件为Goldfish。
5,drivers
int fd = open(“/proc/tty/drivers”, O_RDONLY);
区别:模拟器中包含goldfish的驱动
反模拟器代码:https://github.com/ThomasKing2014/anti-emulator/blob/master/AntiEmulator/src/diff/strazzere/anti/MainActivity.java
改机伪装代码:https://github.com/bingghost/HideAndroidEmulator
这篇也比较全:https://bbs.pediy.com/thread-225717.htm
https://yq.aliyun.com/ziliao/152739
https://github.com/l123456789jy/Lazy/blob/master/lazylibrary/src/main/java/com/github/lazylibrary/util/AntiEmulatorUtiles.java
https://github.com/ysrc/Anti-Emulator/blob/master/app/src/main/AndroidManifest.xml