安全风险 - 检测设备是否为模拟器
在很多安全机构的检测中,关于模拟器的运行环境一般也会做监听处理,有的可能允许执行但是会提示用户,有的可能直接禁止在模拟器上运行我方APP
如何判断当前 app 是运行在Android真机,还是运行在模拟器? 可能做 Framework 的朋友思维会更开阔一些,不过现在也可以跟我这门外汉一起来稍微了解下
- 攻略过程
- 基础思考
- 进阶思考
- easyprotector 框架解析
- 剥离 easyprotector框架 模拟器检测功能
- CommandUtil (公共、基础)
- EmulatorCheckUtil (核心)
- EmulatorCheckCallback (配置)
- CheckResult(配置)
- 调用方式
攻略过程
其实我已经很久没有用过模拟器了,不过可以肯定的是模拟器与真机的本质区别大概率在于运行载体
Android 有非常多的模拟器,我已知的有官方自带的 Genymotion 模拟器,三方平台的夜神模拟器、天天模拟器等,所以想要完全鉴别出设备的运行环境,其实应该是存在一定问题的,我们只能说尽可能保证一定的容错率(我有想过很多应用平台提供的云机,但好像大多提供的都是真机,所以此项不在考虑范围之内)
基础思考
以下的一些思考主要结合了 如何判断是否是模拟器还是真机、全面检测设备是否模拟器、一行代码帮你检测Android模拟器、安卓逆向环境检测–模拟器 等多篇新旧文章
- IMEI 设备识别码:用于唯一标识移动设备(
放弃)
模拟器的 IMEI 可以修改,早期平板可能没有IMEI,但是随着时代发展很多平板设备已拥有了属于自己的IMEI
- MAC地址:物理地址,硬件地址,也称局域网地址,由网络设备制造商生产时烧录在网卡(
放弃)
模拟器的MAC地址是固定的几种,但是这些固定的地址随着模拟器类型递增,没有找到合适的,同时mac地址现在可以被模拟…
- 通过调用公开或者隐藏的系统API判断(
放弃)
因为调用结果可以轻易被修改,比如直接修改Android的源代码或者借助 Xposed Framework 进行修改(这种场景我虽未参与,但是应该可以参考Java的反射机制)
- 功能验证:初期模拟器功能并不完善,可以采用类似
打电话、发短信等方式进行功能测试,但是后续随着模拟器升级已补全对应功能 (放弃)
public boolean isSimulator1() {String url = "tel:" + "10086";Intent intent = new Intent();intent.setData(Uri.parse(url));intent.setAction(Intent.ACTION_DIAL);// 是否可以处理跳转到拨号的 Intentboolean canResolveIntent = intent.resolveActivity(mContext.getPackageManager()) != null;return !canResolveIntent;
}
- 设备IDS、特有文件验证(
放弃)
涉及到敏感权限时需要申请权限,根据授权结果容易出现误判,同时影响用户体验
private static String[]known_numbers = {"15555215554","15555215556","15555215558","15555215560","15555215562","15555215564","15555215566","15555215568","15555215570","15555215572","15555215574","15555215576","15555215578","15555215580","15555215582","15555215584",};public static Boolean CheckPhoneNumber(Context context){TelephonyManager telephonyManager =(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);String phonenumber =telephonyManager.getLine1Number();for(String number :known_numbers){if(number.equalsIgnoreCase(phonenumber)){Log.v("Result:","Find PhoneNumber!");return true;}}Log.v("Result:","Not Find PhoneNumber!");return false;}
特有文件检测 - 权限要求

设备IDS检测 - 权限要求

- CPU检测方法:现在的模拟器基本可以做到模拟手机号码,手机品牌,cpu信息等,比如逍遥/夜神模拟器读取
ro.product.board进行了处理,能得到预先设置的cpu信息(放弃)
public static boolean checkIsNotRealPhone() {String cpuInfo = readCpuInfo();if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {return true;}return false;
}
public static String readCpuInfo() {String result = "";try {String[] args = {"/system/bin/cat", "/proc/cpuinfo"};ProcessBuilder cmd = new ProcessBuilder(args);Process process = cmd.start();StringBuffer sb = new StringBuffer();String readLine = "";BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));while ((readLine = responseReader.readLine()) != null) {sb.append(readLine);}responseReader.close();result = sb.toString().toLowerCase();} catch (IOException ex) {}return result;
}
进阶思考
在一篇Blog内有看到这样一副图,值得借鉴,因为我最后使用的 easyprotector 框架就做了硬件信息检测

Tip:有兴趣的可以参考以下方法扩展 easyprotector 框架内的模拟器检测部分
模拟器框架文件
UNEXPORT void AntiEmulator::check_file() {char *(path[]) = {"/system/bin/androVM-prop", //检测androidVM"/system/bin/microvirt-prop", //检测逍遥模拟器--新版本找不到特征"/system/lib/libdroid4x.so", //检测海马模拟器"/system/bin/windroyed", //检测文卓爷模拟器"/system/bin/nox-prop", //检测夜神模拟器--某些版本找不到特征"/system/lib/libnoxspeedup.so",//检测夜神模拟器"/system/bin/ttVM-prop", //检测天天模拟器"/data/.bluestacks.prop", //检测bluestacks模拟器 51模拟器"/system/bin/duosconfig", //检测AMIDuOS模拟器"/system/etc/xxzs_prop.sh", //检测星星模拟器"/system/etc/mumu-configs/device-prop-configs/mumu.config", //网易MuMu模拟器"/system/priv-app/ldAppStore", //雷电模拟器"/system/bin/ldinit", //雷电模拟器"/system/bin/ldmountsf", //雷电模拟器"/system/app/AntStore", //小蚁模拟器"/system/app/AntLauncher", //小蚁模拟器"vmos.prop", //vmos虚拟机"fstab.titan", //光速虚拟机"init.titan.rc", //光速虚拟机"x8.prop", //x8沙箱和51虚拟机"/system/lib/libc_malloc_debug_qemu.so", //AVD QEMU"/system/bin/microvirtd","/dev/socket/qemud","/dev/qemu_pipe"};for (int i = 0; i < sizeof(path) / sizeof(char*); i++){if (Syscall::check_file_or_dir_exists(path[i])){LOGI("check_file %s file existing", path[i]);// TODO 风险}}
}
easyprotector 框架解析
关于
easyprotector框架文档可以参考 一行代码帮你检测Android模拟器(更新至1.1.0) 会更详细一些
我之所以在 github 选这个框架,主要有几点原因
- 模拟器检测框架有限
- 该框架star高
- 检测方面考虑全面(检测渠道、设备型号、硬件制造商、主板名称、基带信息、第三方应用数量、传感器数量、是否支持蓝牙、是否支持相机、是否支持闪光灯等)
- 能力之内可以适当扩展检测项
- 为了避免误判设备类型,内部加入条件判断,只有满足3项模拟器特征才会判定为模拟器
直接通过框架源码,查看下模拟器检测的执行过程
- 调用了
EasyProtectorLib.checkIsRunningInEmulator方法

- 在
EasyProtectorLib中找到了checkIsRunningInEmulator实际调用了EmulatorCheckUtil

- 查看
EmulatorCheckUtil-readSysProperty源码即可
源码中
ro.build、ro.product、gsm.version含义,做Framework朋友可能比较了解,主要用于检测一些系统级信息

之前有提到功能扩展和延伸,大家可自行在该类源码中进行扩展,不过最好另起方法,有自信的话改原方法也行

剥离 easyprotector框架 模拟器检测功能
因为 easyprotector框架 中涉及的功能比较多,我习惯性只抽出了我所需要的部分
CommandUtil (公共、基础)
简单来看主要是通过反射机制获取一些系统的公共资源信息
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;/*** Project Name:EasyProtector* Package Name:com.lahm.library* Created by lahm on 2018/6/8 16:23 .*/
public class CommandUtil {private CommandUtil() {}private static class SingletonHolder {private static final CommandUtil INSTANCE = new CommandUtil();}public static final CommandUtil getSingleInstance() {return SingletonHolder.INSTANCE;}public String getProperty(String propName) {String value = null;Object roSecureObj;try {roSecureObj = Class.forName("android.os.SystemProperties").getMethod("get", String.class).invoke(null, propName);if (roSecureObj != null) value = (String) roSecureObj;} catch (Exception e) {value = null;} finally {return value;}}public String exec(String command) {BufferedOutputStream bufferedOutputStream = null;BufferedInputStream bufferedInputStream = null;Process process = null;try {process = Runtime.getRuntime().exec("sh");bufferedOutputStream = new BufferedOutputStream(process.getOutputStream());bufferedInputStream = new BufferedInputStream(process.getInputStream());bufferedOutputStream.write(command.getBytes());bufferedOutputStream.write('\n');bufferedOutputStream.flush();bufferedOutputStream.close();process.waitFor();String outputStr = getStrFromBufferInputSteam(bufferedInputStream);return outputStr;} catch (Exception e) {return null;} finally {if (bufferedOutputStream != null) {try {bufferedOutputStream.close();} catch (IOException e) {e.printStackTrace();}}if (bufferedInputStream != null) {try {bufferedInputStream.close();} catch (IOException e) {e.printStackTrace();}}if (process != null) {process.destroy();}}}private static String getStrFromBufferInputSteam(BufferedInputStream bufferedInputStream) {if (null == bufferedInputStream) {return "";}int BUFFER_SIZE = 512;byte[] buffer = new byte[BUFFER_SIZE];StringBuilder result = new StringBuilder();try {while (true) {int read = bufferedInputStream.read(buffer);if (read > 0) {result.append(new String(buffer, 0, read));}if (read < BUFFER_SIZE) {break;}}} catch (Exception e) {e.printStackTrace();}return result.toString();}
}
EmulatorCheckUtil (核心)
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.text.TextUtils;import static android.content.Context.SENSOR_SERVICE;
import static cn.com.huaan.fund.acts.base.safe.CheckResult.RESULT_EMULATOR;
import static cn.com.huaan.fund.acts.base.safe.CheckResult.RESULT_MAYBE_EMULATOR;
import static cn.com.huaan.fund.acts.base.safe.CheckResult.RESULT_UNKNOWN;/*** Project Name:EasyProtector* Package Name:com.lahm.library* Created by lahm on 2018/6/8 15:01 .*/
public class EmulatorCheckUtil {private EmulatorCheckUtil() {}private static class SingletonHolder {private static final EmulatorCheckUtil INSTANCE = new EmulatorCheckUtil();}public static final EmulatorCheckUtil getSingleInstance() {return SingletonHolder.INSTANCE;}public boolean readSysProperty(Context context, EmulatorCheckCallback callback) {if (context == null)throw new IllegalArgumentException("context must not be null");int suspectCount = 0;//检测硬件名称CheckResult hardwareResult = checkFeaturesByHardware();switch (hardwareResult.result) {case RESULT_MAYBE_EMULATOR:++suspectCount;break;case RESULT_EMULATOR:if (callback != null) callback.findEmulator("hardware = " + hardwareResult.value);return true;}//检测渠道CheckResult flavorResult = checkFeaturesByFlavor();switch (flavorResult.result) {case RESULT_MAYBE_EMULATOR:++suspectCount;break;case RESULT_EMULATOR:if (callback != null) callback.findEmulator("flavor = " + flavorResult.value);return true;}//检测设备型号CheckResult modelResult = checkFeaturesByModel();switch (modelResult.result) {case RESULT_MAYBE_EMULATOR:++suspectCount;break;case RESULT_EMULATOR:if (callback != null) callback.findEmulator("model = " + modelResult.value);return true;}//检测硬件制造商CheckResult manufacturerResult = checkFeaturesByManufacturer();switch (manufacturerResult.result) {case RESULT_MAYBE_EMULATOR:++suspectCount;break;case RESULT_EMULATOR:if (callback != null)callback.findEmulator("manufacturer = " + manufacturerResult.value);return true;}//检测主板名称CheckResult boardResult = checkFeaturesByBoard();switch (boardResult.result) {case RESULT_MAYBE_EMULATOR:++suspectCount;break;case RESULT_EMULATOR:if (callback != null) callback.findEmulator("board = " + boardResult.value);return true;}//检测主板平台CheckResult platformResult = checkFeaturesByPlatform();switch (platformResult.result) {case RESULT_MAYBE_EMULATOR:++suspectCount;break;case RESULT_EMULATOR:if (callback != null) callback.findEmulator("platform = " + platformResult.value);return true;}//检测基带信息CheckResult baseBandResult = checkFeaturesByBaseBand();switch (baseBandResult.result) {case RESULT_MAYBE_EMULATOR:suspectCount += 2;//模拟器基带信息为null的情况概率相当大break;case RESULT_EMULATOR:if (callback != null) callback.findEmulator("baseBand = " + baseBandResult.value);return true;}//检测传感器数量int sensorNumber = getSensorNumber(context);if (sensorNumber <= 7) ++suspectCount;//检测已安装第三方应用数量int userAppNumber = getUserAppNumber();if (userAppNumber <= 5) ++suspectCount;//检测是否支持闪光灯boolean supportCameraFlash = supportCameraFlash(context);if (!supportCameraFlash) ++suspectCount;//检测是否支持相机boolean supportCamera = supportCamera(context);if (!supportCamera) ++suspectCount;//检测是否支持蓝牙boolean supportBluetooth = supportBluetooth(context);if (!supportBluetooth) ++suspectCount;//检测光线传感器boolean hasLightSensor = hasLightSensor(context);if (!hasLightSensor) ++suspectCount;//检测进程组信息CheckResult cgroupResult = checkFeaturesByCgroup();if (cgroupResult.result == RESULT_MAYBE_EMULATOR) ++suspectCount;if (callback != null) {StringBuffer stringBuffer = new StringBuffer("Test start").append("\r\n").append("hardware = ").append(hardwareResult.value).append("\r\n").append("flavor = ").append(flavorResult.value).append("\r\n").append("model = ").append(modelResult.value).append("\r\n").append("manufacturer = ").append(manufacturerResult.value).append("\r\n").append("board = ").append(boardResult.value).append("\r\n").append("platform = ").append(platformResult.value).append("\r\n").append("baseBand = ").append(baseBandResult.value).append("\r\n").append("sensorNumber = ").append(sensorNumber).append("\r\n").append("userAppNumber = ").append(userAppNumber).append("\r\n").append("supportCamera = ").append(supportCamera).append("\r\n").append("supportCameraFlash = ").append(supportCameraFlash).append("\r\n").append("supportBluetooth = ").append(supportBluetooth).append("\r\n").append("hasLightSensor = ").append(hasLightSensor).append("\r\n").append("cgroupResult = ").append(cgroupResult.value).append("\r\n").append("suspectCount = ").append(suspectCount);callback.findEmulator(stringBuffer.toString());}//嫌疑值大于3,认为是模拟器return suspectCount > 3;}private int getUserAppNum(String userApps) {if (TextUtils.isEmpty(userApps)) return 0;String[] result = userApps.split("package:");return result.length;}private String getProperty(String propName) {String property = CommandUtil.getSingleInstance().getProperty(propName);return TextUtils.isEmpty(property) ? null : property;}/*** 特征参数-硬件名称** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByHardware() {String hardware = getProperty("ro.hardware");if (null == hardware) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;String tempValue = hardware.toLowerCase();switch (tempValue) {case "ttvm"://天天模拟器case "nox"://夜神模拟器case "cancro"://网易MUMU模拟器case "intel"://逍遥模拟器case "vbox":case "vbox86"://腾讯手游助手case "android_x86"://雷电模拟器result = RESULT_EMULATOR;break;default:result = RESULT_UNKNOWN;break;}return new CheckResult(result, hardware);}/*** 特征参数-渠道** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByFlavor() {String flavor = getProperty("ro.build.flavor");if (null == flavor) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;String tempValue = flavor.toLowerCase();if (tempValue.contains("vbox")) result = RESULT_EMULATOR;else if (tempValue.contains("sdk_gphone")) result = RESULT_EMULATOR;else result = RESULT_UNKNOWN;return new CheckResult(result, flavor);}/*** 特征参数-设备型号** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByModel() {String model = getProperty("ro.product.model");if (null == model) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;String tempValue = model.toLowerCase();if (tempValue.contains("google_sdk")) result = RESULT_EMULATOR;else if (tempValue.contains("emulator")) result = RESULT_EMULATOR;else if (tempValue.contains("android sdk built for x86")) result = RESULT_EMULATOR;else result = RESULT_UNKNOWN;return new CheckResult(result, model);}/*** 特征参数-硬件制造商** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByManufacturer() {String manufacturer = getProperty("ro.product.manufacturer");if (null == manufacturer) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;String tempValue = manufacturer.toLowerCase();if (tempValue.contains("genymotion")) result = RESULT_EMULATOR;else if (tempValue.contains("netease")) result = RESULT_EMULATOR;//网易MUMU模拟器else result = RESULT_UNKNOWN;return new CheckResult(result, manufacturer);}/*** 特征参数-主板名称** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByBoard() {String board = getProperty("ro.product.board");if (null == board) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;String tempValue = board.toLowerCase();if (tempValue.contains("android")) result = RESULT_EMULATOR;else if (tempValue.contains("goldfish")) result = RESULT_EMULATOR;else result = RESULT_UNKNOWN;return new CheckResult(result, board);}/*** 特征参数-主板平台** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByPlatform() {String platform = getProperty("ro.board.platform");if (null == platform) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;String tempValue = platform.toLowerCase();if (tempValue.contains("android")) result = RESULT_EMULATOR;else result = RESULT_UNKNOWN;return new CheckResult(result, platform);}/*** 特征参数-基带信息** @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机*/private CheckResult checkFeaturesByBaseBand() {String baseBandVersion = getProperty("gsm.version.baseband");if (null == baseBandVersion) return new CheckResult(RESULT_MAYBE_EMULATOR, null);int result;if (baseBandVersion.contains("1.0.0.0")) result = RESULT_EMULATOR;else result = RESULT_UNKNOWN;return new CheckResult(result, baseBandVersion);}/*** 获取传感器数量*/private int getSensorNumber(Context context) {SensorManager sm = (SensorManager) context.getSystemService(SENSOR_SERVICE);return sm.getSensorList(Sensor.TYPE_ALL).size();}/*** 获取已安装第三方应用数量*/private int getUserAppNumber() {String userApps = CommandUtil.getSingleInstance().exec("pm list package -3");return getUserAppNum(userApps);}/*** 是否支持相机*/private boolean supportCamera(Context context) {return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);}/*** 是否支持闪光灯*/private boolean supportCameraFlash(Context context) {return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);}/*** 是否支持蓝牙*/private boolean supportBluetooth(Context context) {return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);}/*** 判断是否存在光传感器来判断是否为模拟器* 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。** @return false为模拟器*/private boolean hasLightSensor(Context context) {SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光线传感器if (null == sensor) return false;else return true;}/*** 特征参数-进程组信息*/private CheckResult checkFeaturesByCgroup() {String filter = CommandUtil.getSingleInstance().exec("cat /proc/self/cgroup");if (null == filter) return new CheckResult(RESULT_MAYBE_EMULATOR, null);return new CheckResult(RESULT_UNKNOWN, filter);}
}
EmulatorCheckCallback (配置)
回调监听,可以获取到具体检测结果
public interface EmulatorCheckCallback {void findEmulator(String emulatorInfo);
}
CheckResult(配置)
对检测结果进行类别划分,方便管理
public class CheckResult {public static final int RESULT_MAYBE_EMULATOR = 0;//可能是模拟器public static final int RESULT_EMULATOR = 1;//模拟器public static final int RESULT_UNKNOWN = 2;//可能是真机public int result;public String value;public CheckResult(int result, String value) {this.result = result;this.value = value;}
}
调用方式
val readSysProperty = EmulatorCheckUtil.getSingleInstance().readSysProperty(context, null)if (readSysProperty) {//根据需要进行风险提示等相关业务ToastUtils.showToast("您当前可能运行在模拟器设备,请谨防安全风险!")}
相关文章:
安全风险 - 检测设备是否为模拟器
在很多安全机构的检测中,关于模拟器的运行环境一般也会做监听处理,有的可能允许执行但是会提示用户,有的可能直接禁止在模拟器上运行我方APP 如何判断当前 app 是运行在Android真机,还是运行在模拟器? 可能做 Framework 的朋友思…...
maven的下载以及配置的详细教程(附网盘下载地址)
文章目录 下载配置IDEA内部使用配置 下载 1.百度网盘下载 链接: https://pan.baidu.com/s/1LD9wOMFalLL49XUscU4qnQ?pwd1234 提取码: 1234 2.解压即可 配置 1.打开安装文件下conf下的settings.xml文件,我的如下 2.修改配置信息(目的是为了修改本地…...
Unity3D 主城角色动画控制与消息触发详解
前言 在游戏开发中,角色动画控制和消息触发是非常重要的一部分,它可以让游戏更加生动和互动。本文将详细介绍如何在Unity3D中实现主城角色动画控制与消息触发。 对惹,这里有一个游戏开发交流小组,大家可以点击进来一起交流一下开…...
【Endnote】如何在word界面加载Endnote
如何在word界面加载Endnote 方法1:方法2:从word入手方法3:从CWYW入手参考 已下载EndNote,但Word中没有显示EndNote,应如何加载显示呢? 方法1: 使用EndNote的Configure EndNote.exe 。 具体步骤为&#x…...
优化CPU占用率及内存占用2
在标准化无线通信板时,关注过程序占用ram的问题,当时 发现每一个线程都会分配8M栈空间,这次换rk3568后,偶尔看了下RAM占用,吓了一跳,不但每个线程有8M栈空间,几乎每个线程都占用了64MB的一个RAM…...
C语言(字符和字符串函数)2
Hi~!这里是奋斗的小羊,很荣幸各位能阅读我的文章,诚请评论指点,欢迎欢迎~~ 💥个人主页:小羊在奋斗 💥所属专栏:C语言 本系列文章为个人学习笔记,在这里撰写成文一…...
【数据结构与算法 | 栈篇】力扣20,150
1. 力扣20 : 有效的符号 (1). 题 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个…...
node依赖安装的bug汇总
1.npm仓库 首先要获取npm仓库的地址: registryhttp://11.11.111.1:1111/abcdefg/adsfadsf 类似这种的地址 然后设置npm仓库: npm config set registryhttp://11.11.111.1:1111/abcdefg/adsfadsf (地址要带等号) 接着安装依赖: npm i…...
Python中的 Lambda 函数
大家好,在 Python 编程的世界里,有一种功能强大却不常被提及的工具,它就是 Lambda 函数。这种匿名函数在 Python 中拥有着令人惊叹的灵活性和简洁性,却常常被许多开发者忽视或者只是将其当作一种附加功能。Lambda 函数的引入&…...
服务器遭遇黑洞后如何快速恢复与防范
在互联网世界中,“黑洞"一词常用于描述一种网络安全措施,即当服务器遭遇大规模DDoS攻击,为了保护网络基础设施和其他用户免受影响,网络服务商会暂时将受到攻击的IP地址流量导向一个"空洞”,使其不再响应任何…...
GPT-4o有点坑
GPT-4o有点坑 0. 前言1. GPT-4o简介2. GPT-4o带来的好处2.1 可以上传图片和文件2.2 更丰富的功能以及插件 3. "坑"的地方3.1 使用时间短3.2 GPT-4o变懒了 4. 总结 0. 前言 原本不想对GPT-4o的内容来进行评论的,但是看了相关的评论一直在说:技…...
【机器学习】探索未来科技的前沿:人工智能、机器学习与大模型
文章目录 引言一、人工智能:从概念到现实1.1 人工智能的定义1.2 人工智能的发展历史1.3 人工智能的分类1.4 人工智能的应用 二、机器学习:人工智能的核心技术2.1 机器学习的定义2.2 机器学习的分类2.3 机器学习的实现原理2.4 机器学习的应用2.5 机器学习…...
OceanBase 4.3.0 列存引擎解读:OLAP场景的入门券
近期,OceanBase 发布了4.3.0版本,该版本成功实现了行存与列存存储的一体化,并同时推出了基于列存的全新向量化引擎和代价评估模型。通过强化这些能力,OceanBase V4.3.0 显著提高了处理宽表的效率,增强了在AP࿰…...
算法每日一题(python,2024.05.25) day.7
题目来源(力扣. - 力扣(LeetCode),简单) 解题思路: 难点:加一时可能出现9使得位数进一,而当特殊情况,即全部为9时,数组所在长度会变长一。 从末尾开始判断&…...
【正在线上召开】2024机器智能与数字化应用国际会议(MIDA2024),免费参会
【ACM出版】2024机器智能与数字化应用国际会议(MIDA2024) 2024 International Conference on Machine Intelligence and Digital Applications 【支持单位】 宁波财经学院 法国上阿尔萨斯大学 【大会主席】 Ljiljana Trajkovic 加拿大西蒙菲莎大…...
景源畅信:抖音的爆款视频怎么选?
在短视频风起云涌的今天,抖音作为其中的佼佼者,每天都有无数视频在这里诞生。但如何在内容海洋中脱颖而出,成为人们茶余饭后谈论的焦点,是许多创作者和品牌思考的问题。选择爆款视频,不仅需要对平台规则有深刻理解&…...
开源大模型源代码
开源大模型的源代码可以在多个平台上找到,以下是一些知名的开源大模型及其源代码的获取方式: 1. **艾伦人工智能研究所的开放大语言模型(Open Language Model,OLMo)**: - 提供了完整的模型权重、训练代…...
算法思想总结:哈希表
一、哈希表剖析 1、哈希表底层:通过对C的学习,我们知道STL中哈希表底层是用的链地址法封装的开散列。 2、哈希表作用:存储数据的容器,插入、删除、搜索的时间复杂度都是O(1),无序。 3、什么时…...
基于Docker搭建属于你的CC++集成编译环境
常常,我会幻想着拥有一个随时可以携带、随时可以使用的开发环境,那该是多么美好的事情。 在工作中,编译环境的复杂性常常让我头疼不已。稍有不慎,删除了一些关键文件,整个编译链就会瞬间崩溃。更糟糕的是,…...
如何限制上网行为?上网行为管控软件有什么功能?
上网行为的管理与限制对于保障企业安全、提高员工工作效率以及保护孩子健康成长都显得尤为重要。 上网行为管控软件作为一种专业的工具,在这方面发挥着不可替代的作用。 本文将探讨如何限制上网行为,并介绍上网行为管控软件的主要功能。 一、如何限制上…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
