当前位置: 首页 > news >正文

【APK安全】Android 权限校验核心风险与防御指南

文章目录

    • 前言
    • 一、Android 权限校验的核心风险场景
      • 1. 风险 1:AndroidManifest 滥用 uid=1000(系统 UID 提权与兼容性崩溃)
        • 风险本质(uid=1000 的特殊性)
        • 典型案例 1:普通 APP 误配置系统 UID 导致安装失败
        • 典型案例 2:恶意 APP 伪造系统 UID 试图提权
      • 2. 风险 2:权限校验依赖不安全方法
        • 风险本质(不安全校验方法的共性问题)
        • 典型案例:依赖 getCallingPackage () 判断可信 APP 导致权限绕过
      • 3. 风险 3:checkCallingUriPermission 使用不当(URI 权限校验失效)
        • 风险本质(URI 权限校验的核心逻辑)
        • 典型案例:未指定 Uri 类型导致私有数据被非法访问
    • 二、权限校验安全防御方案
      • 1. uid=1000 的安全管控:禁止普通 APP 配置 + 系统 APP 权限收敛
        • 核心措施
        • 安全实现代码(检测系统 UID 与权限校验)
      • 2. 规范使用 checkCallingPermission:跨进程权限校验的唯一可靠方案
        • 核心措施
        • 合规代码示例(跨进程服务权限校验)
      • 3. checkCallingUriPermission 正确用法:明确 Uri 与权限类型
        • 核心措施
        • 代码示例(ContentProvider URI 权限校验)
      • 4. 禁用不安全的校验方法:替代方案与风险规避
        • 核心措施(不安全方法清单与替代方案)
        • 代码示例(替代不安全的包名判断)
    • 三、权限校验安全测试方法
      • 1. 静态测试(配置与代码审核)
      • 2. 动态测试(权限绕过模拟)
    • 四、总结:权限校验的核心原则

⚠️本博文所涉安全渗透测试技术、方法及案例,仅用于网络安全技术研究与合规性交流,旨在提升读者的安全防护意识与技术能力。任何个人或组织在使用相关内容前,必须获得目标网络 / 系统所有者的明确且书面授权,严禁用于未经授权的网络探测、漏洞利用、数据获取等非法行为。

前言

Android 权限机制是保障 APP 与系统安全的 “第一道闸门”—— 通过 AndroidManifest 声明权限、运行时校验权限,限制 APP 仅能访问其 “必要功能” 对应的资源(如相机、位置、跨进程数据)。但权限校验的安全性依赖两大关键:配置的合法性(uid=1000 的系统 UID 不可滥用)与校验方法的正确性(如必须使用 checkCallingPermission 而非包名判断)。

实际开发中,开发者常因对 “uid=1000 的特殊性” 认知不足、误用不安全的校验方法(如仅通过包名判断可信来源),导致权限绕过漏洞 —— 攻击者可伪造系统 UID、伪装可信 APP 包名,非法获取高权限(如读取系统数据)或访问私有资源(如用户隐私文件)。

本文将拆解三大核心权限风险,提供规范的校验方案与测试方法。

一、Android 权限校验的核心风险场景

Android 权限校验的风险本质是 “权限边界失控”—— 要么配置突破系统限制(如普通 APP 试图使用系统 UID),要么校验方法无法抵御伪造(如仅判断包名),最终导致权限机制失效。以下结合实际案例解析:

1. 风险 1:AndroidManifest 滥用 uid=1000(系统 UID 提权与兼容性崩溃)

风险本质(uid=1000 的特殊性)

Android 系统中,每个 APP 安装后会被分配唯一的 “用户 ID(UID)”,用于隔离不同 APP 的资源访问权限:

  • 普通 APP 的 UID:默认从 10000 开始(如 com.example.app 的 UID 可能为 10045),仅拥有自身私有目录与声明的普通权限;

  • 系统 UID(uid=1000):仅系统进程(如 SystemUI、Settings)、带系统签名的 APP 可使用,拥有 “访问系统核心资源” 的高权限(如修改系统设置、读取所有 APP 数据);

  • 配置方式:需在 AndroidManifest 中声明<manifest android:sharedUserId="android.uid.system">,且必须使用系统签名编译,否则无法安装。

风险点在于:

  • 普通 APP 误配置:未了解 uid=1000 的系统属性,盲目添加sharedUserId=“android.uid.system”,导致 APP 因无系统签名而安装失败;

  • 恶意 APP 试图提权:通过伪造系统签名、修改 AndroidManifest,试图获取 uid=1000 权限,若系统存在签名漏洞,可能成功提权并窃取系统数据。

典型案例 1:普通 APP 误配置系统 UID 导致安装失败

某工具类 APP 开发者为 “获取系统级文件访问权限”,在 AndroidManifest 中误配置系统 UID:

<!-- 风险配置:普通APP声明系统UID,无系统签名 -->
<manifestxmlns:android="http://schemas.android.com/apk/res/android"package="com.example.toolapp"android:sharedUserId="android.uid.system"> <!-- 错误配置:普通APP使用系统UID --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!-- 其他配置... -->
</manifest>

后果:

  1. APP 编译后无系统签名(普通开发者无法获取厂商系统签名);

  2. 安装时系统校验发现 “声明系统 UID 但无系统签名”,直接拒绝安装,提示 “安装失败:应用未获得系统授权”;

  3. 即使通过 root 设备强制推送 APK,启动时系统也会因 UID 权限不匹配,触发SecurityException导致 APP 崩溃。

典型案例 2:恶意 APP 伪造系统 UID 试图提权

某恶意 APP 利用 Android 7.0 以下的签名校验漏洞,伪造系统签名并配置 uid=1000:

<!-- 恶意配置:伪造系统UID与签名 -->
<manifestpackage="com.example.malicious"android:sharedUserId="android.uid.system"><uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!-- 系统级权限 -->
</manifest>

攻击流程:

  1. 利用系统签名漏洞(如旧版本signapk.jar工具缺陷),生成伪造的系统签名文件;

  2. 用伪造签名编译恶意 APP,安装到 Android 7.0 以下设备;

  3. 因系统漏洞,APP 成功获取 uid=1000,拥有系统级权限;

  4. 调用Settings.System.putInt()修改系统设置(如禁用 WiFi、篡改屏幕亮度),或读取/data/system/users/0/settings_ssaid.xml获取所有 APP 的 SSAID(设备唯一标识)。

2. 风险 2:权限校验依赖不安全方法

风险本质(不安全校验方法的共性问题)

Android 跨进程调用(如 Service、ContentProvider)时,需校验调用者是否拥有合法权限。系统推荐的唯一可靠方法是checkCallingPermission(String permission),但部分开发者会使用 “看似可行” 的替代方法,这些方法存在 “可伪造性” 缺陷:

  • 不安全方法 1:getCallingPackage()判断包名 —— 调用者可通过动态代理、Hook 等手段伪造包名(如将恶意 APP 包名伪装成 “com.example.trusted”);

  • 不安全方法 2:getCallingUid()判断 UID 范围 —— 普通 APP 的 UID 可通过修改系统配置(root 设备)篡改,且无法区分 “合法 APP” 与 “恶意 APP” 的同范围 UID;

  • 不安全方法 3:忽略校验直接执行 —— 跨进程接口未做任何权限校验,任何 APP 均可调用。

这些方法的核心问题是 “未依赖系统权限机制的底层校验”,仅通过上层可篡改的标识(包名、UID)判断,易被攻击者绕过。

典型案例:依赖 getCallingPackage () 判断可信 APP 导致权限绕过

某金融 APP 的跨进程服务(PaymentService),通过判断调用者包名是否为 “com.example.official” 来允许支付操作,未使用 checkCallingPermission

// 风险代码:依赖包名判断可信来源,无权限校验
public class PaymentService extends Service {private static final String TRUSTED_PACKAGE = "com.example.official";@Overridepublic IBinder onBind(Intent intent) {return new PaymentBinder();}public class PaymentBinder extends IPaymentService.Stub {@Overridepublic void submitPayment(String orderId, String password) throws RemoteException {// 不安全校验:仅判断调用者包名String callingPackage = getCallingPackage();if (TRUSTED_PACKAGE.equals(callingPackage)) {// 无权限校验,直接执行支付操作executePayment(orderId, password);} else {throw new SecurityException("非法调用者:" + callingPackage);}}}
}

攻击者通过伪造包名绕过校验:

  1. 开发恶意 APP,使用动态代理 Hook getCallingPackage()方法,使其返回 “com.example.official”;
  2. 绑定金融 APP 的 PaymentService,调用submitPayment(“hacker_order”, “fake_pwd”);
  3. 服务的getCallingPackage()被 Hook 返回可信包名,跳过校验;
  4. 服务执行支付操作,将伪造的 “hacker_order” 标记为 “已支付”,导致金融 APP 财务对账异常。

3. 风险 3:checkCallingUriPermission 使用不当(URI 权限校验失效)

风险本质(URI 权限校验的核心逻辑)

checkCallingUriPermission(Uri uri, int modeFlags)用于校验 “调用者是否拥有访问特定 URI 资源的权限”,常见于 ContentProvider 场景(如 APP 通过 ContentProvider 向其他 APP 共享数据)。风险点在于:

  • 未指定具体 Uri:校验时使用Uri.parse("content://*")(通配符 URI),导致调用者可访问所有 URI 资源;

  • 错误设置 modeFlags:modeFlags(如Intent.FLAG_GRANT_READ_URI_PERMISSION)与实际所需权限不匹配(如需要读权限却校验写权限);

  • 忽略返回值判断:未检查checkCallingUriPermission的返回值(PackageManager.PERMISSION_GRANTED/DENIED),直接允许访问。

这些问题会导致 “URI 权限隔离失效”,调用者可访问未授权的私有数据(如用户通讯录、短信)。

典型案例:未指定 Uri 类型导致私有数据被非法访问

某社交 APP 的 ContentProvider(UserProvider),用于共享用户资料,但 checkCallingUriPermission 使用通配符 URI:

// 风险代码:URI权限校验使用通配符,未指定具体Uri
public class UserProvider extends ContentProvider {private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);static {// 注册合法URI:content://com.example.social/user/profile(用户资料)URI_MATCHER.addURI("com.example.social", "user/profile", 1);// 注册敏感URI:content://com.example.social/user/message(用户私信)URI_MATCHER.addURI("com.example.social", "user/message", 2);}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {// 风险1:使用通配符URI校验,而非当前请求的uriint permission = checkCallingUriPermission(Uri.parse("content://*"), // 通配符:允许访问所有URIIntent.FLAG_GRANT_READ_URI_PERMISSION);// 风险2:未判断permission返回值,直接执行查询int match = URI_MATCHER.match(uri);if (match == 1) {return queryUserProfile(); // 合法:查询用户资料} else if (match == 2) {return queryUserMessage(); // 敏感:查询用户私信}return null;}
}

攻击者通过访问敏感 URI 窃取私信:

  1. 恶意 APP 获取 “访问用户资料” 的 URI 权限(社交 APP 通过grantUriPermission授予);
  2. 恶意 APP 构造敏感 URI:content://com.example.social/user/message,调用 UserProvider 的 query 方法;
  3. 因 ContentProvider 使用通配符 URI 校验,checkCallingUriPermission返回PERMISSION_GRANTED;
  4. 恶意 APP 成功查询到用户私信内容,导致隐私泄露。

二、权限校验安全防御方案

针对上述风险,需围绕 “配置合法、校验可靠、权限最小” 三大原则,结合 Android 系统权限机制的底层逻辑,制定防御方案:

1. uid=1000 的安全管控:禁止普通 APP 配置 + 系统 APP 权限收敛

核心措施
  • 普通 APP:严禁在 AndroidManifest 中声明android:sharedUserId=“android.uid.system”,若需访问系统资源,通过系统提供的公开 API(如Settings.Secure)而非提权;

  • 系统 APP(需系统签名):配置 uid=1000 后,仅申请必要的系统权限,避免过度授权;

  • 运行时检测:系统 APP 启动时,通过Process.myUid()确认当前 UID 为 1000,避免被篡改;

  • 签名校验:系统 APP 在跨进程调用时,额外校验调用者的签名是否为系统签名,双重保障。

安全实现代码(检测系统 UID 与权限校验)
// 系统APP的安全检测逻辑
public class SystemAppSecurityUtils {// 系统签名的SHA-256哈希值(预存,从系统证书提取)private static final String SYSTEM_SIGN_HASH = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2";/*** 系统APP启动时检测UID是否合法(防止被篡改)*/public static boolean checkSystemUidValid(Context context) {int currentUid = Process.myUid();// 校验当前UID是否为系统UID(1000)if (currentUid != 1000) {Log.e("SystemSecurity", "非法UID:" + currentUid + ",系统APP需为1000");return false;}// 额外校验APP签名是否为系统签名(防止伪造系统APP)return checkAppSignature(context, SYSTEM_SIGN_HASH);}/*** 校验APP签名是否匹配目标哈希值*/private static boolean checkAppSignature(Context context, String targetHash) {try {PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);Signature[] signatures = packageInfo.signatures;if (signatures == null || signatures.length == 0) {return false;}// 计算签名的SHA-256哈希值MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[] signatureBytes = signatures[0].toByteArray();digest.update(signatureBytes);String appSignHash = bytesToHex(digest.digest());// 比对哈希值(忽略大小写)return targetHash.equalsIgnoreCase(appSignHash);} catch (Exception e) {Log.e("SystemSecurity", "签名校验异常", e);return false;}}private static String bytesToHex(byte[] bytes) {StringBuilder sb = new StringBuilder();for (byte b : bytes) {sb.append(String.format("%02x", b));}return sb.toString();}
}// 系统APP启动页调用检测
public class SystemAppSplashActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 启动时检测UID与签名合法性if (!SystemAppSecurityUtils.checkSystemUidValid(this)) {finish(); // 非法则退出APPreturn;}// 合法则进入主页面startActivity(new Intent(this, SystemAppMainActivity.class));finish();}
}

2. 规范使用 checkCallingPermission:跨进程权限校验的唯一可靠方案

核心措施
  • 跨进程场景必用:Service、ContentProvider、BroadcastReceiver 的跨进程调用,必须使用checkCallingPermission校验调用者是否拥有指定权限;

  • 校验时机前置:在执行核心逻辑(如支付、数据查询)前先校验,避免执行部分逻辑后因权限不足中断;

  • 处理返回值:严格判断返回值是否为PackageManager.PERMISSION_GRANTED,非授权则抛出SecurityException;

  • 动态权限适配:Android 6.0(API 23)后,需确保调用者已获取 “危险权限” 的运行时授权,checkCallingPermission会自动判断动态权限状态。

合规代码示例(跨进程服务权限校验)
// 安全的支付服务:使用checkCallingPermission校验权限
public class SecurePaymentService extends Service {// 自定义高风险权限(需在AndroidManifest中声明)private static final String PERMISSION_SUBMIT_PAYMENT = "com.example.permission.SUBMIT_PAYMENT";@Overridepublic IBinder onBind(Intent intent) {return new SecurePaymentBinder();}public class SecurePaymentBinder extends IPaymentService.Stub {@Overridepublic void submitPayment(String orderId, String password) throws RemoteException {// 前置权限校验:使用checkCallingPermissionint permission = checkCallingPermission(PERMISSION_SUBMIT_PAYMENT);if (permission != PackageManager.PERMISSION_GRANTED) {throw new SecurityException("调用者无支付权限,需申请" + PERMISSION_SUBMIT_PAYMENT);}// (可选)双重校验:结合签名判断(针对高敏感操作)String callingPackage = getCallingPackage();if (!checkCallingPackageSignature(callingPackage)) {throw new SecurityException("调用者签名非法");}// 执行支付逻辑executePayment(orderId, password);}}// 校验调用者包名的签名(额外保障,避免权限被非法授予)private boolean checkCallingPackageSignature(String packageName) {// 逻辑同前文SystemAppSecurityUtils.checkAppSignature,校验包名对应的签名是否为可信签名// (此处省略具体实现,需预存可信APP的签名哈希值)return true;}
}
// AndroidManifest中声明自定义权限(高风险,签名权限)
<permissionandroid:name="com.example.permission.SUBMIT_PAYMENT"android:protectionLevel="signature" /> <!-- 仅同签名APP可获取该权限 -->
<uses-permission android:name="com.example.permission.SUBMIT_PAYMENT" />

3. checkCallingUriPermission 正确用法:明确 Uri 与权限类型

核心措施
  • 使用请求的具体 Uri:校验时传入当前调用的uri参数,而非通配符或固定 Uri;

  • 匹配 modeFlags 与权限需求:需要读权限则使用Intent.FLAG_GRANT_READ_URI_PERMISSION,写权限使用Intent.FLAG_GRANT_WRITE_URI_PERMISSION;

  • 强制判断返回值:仅当返回PackageManager.PERMISSION_GRANTED时允许访问,否则拒绝;

  • 结合 URI 匹配器:使用UriMatcher限制合法 URI,避免非预期 URI 的访问。

代码示例(ContentProvider URI 权限校验)
// 安全的用户ContentProvider:正确使用checkCallingUriPermission
public class SecureUserProvider extends ContentProvider {private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);// 仅注册合法URI,拒绝敏感URI的外部访问static {URI_MATCHER.addURI("com.example.social", "user/profile", 1); // 合法:用户资料(允许外部访问)// 敏感URI(用户私信)不注册外部访问,仅内部使用}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {// 先校验URI是否在合法列表中int match = URI_MATCHER.match(uri);if (match != 1) {throw new SecurityException("非法URI:" + uri);}// 正确使用checkCallingUriPermission:传入当前uri+读权限flagint permission = checkCallingUriPermission(uri, // 传入当前请求的具体URI,非通配符Intent.FLAG_GRANT_READ_URI_PERMISSION // 匹配读权限需求);// 严格判断返回值,非授权则拒绝if (permission != PackageManager.PERMISSION_GRANTED) {throw new SecurityException("无访问" + uri + "的权限");}// 权限合法,执行查询(仅返回用户资料,无敏感数据)return queryUserProfile(projection, selection, selectionArgs, sortOrder);}// 仅查询用户公开资料(如昵称、头像,无私信、手机号)private Cursor queryUserProfile(String[] projection, String selection, String[] selectionArgs, String sortOrder) {// 具体查询逻辑...return null;}
}

4. 禁用不安全的校验方法:替代方案与风险规避

核心措施(不安全方法清单与替代方案)
不安全校验方法风险点替代方案(安全方法)
getCallingPackage()判断包名包名可通过 Hook、动态代理伪造1. checkCallingPermission校验权限;2. 结合checkAppSignature校验签名(双重保障)
getCallingUid()判断 UID 范围UID 可通过 root 设备篡改,无法区分可信性1. checkCallingPermission校验权限;2. 系统 APP 可结合Process.myUid() == 1000判断
忽略校验直接执行任何 APP 均可调用,无权限限制强制使用checkCallingPermission/checkCallingUriPermission校验
checkSelfPermission()跨进程校验仅校验自身权限,不校验调用者权限跨进程场景必须使用checkCallingPermission(而非checkSelfPermission)
代码示例(替代不安全的包名判断)
// 替代getCallingPackage()的安全逻辑
private void secureCheckCallingSource() {// 优先校验权限(核心保障)int permission = checkCallingPermission("com.example.permission.TRUSTED_ACCESS");if (permission != PackageManager.PERMISSION_GRANTED) {throw new SecurityException("无可信访问权限");}// (可选)额外校验签名(针对高敏感场景)String callingPackage = getCallingPackage();if (callingPackage == null) {throw new SecurityException("无法获取调用者包名");}// 预存可信APP的包名与签名哈希映射Map<String, String> trustedApps = new HashMap<>();trustedApps.put("com.example.official", "trusted_sign_hash_123");if (!trustedApps.containsKey(callingPackage)) {throw new SecurityException("调用者包名不在可信列表");}// 校验调用者签名是否匹配预存哈希if (!checkAppSignature(getContext(), callingPackage, trustedApps.get(callingPackage))) {throw new SecurityException("调用者签名不匹配");}
}// 校验指定包名的APP签名
private boolean checkAppSignature(Context context, String packageName, String targetHash) {// 逻辑同前文,计算packageName对应的签名哈希并比对// (此处省略具体实现)return true;
}

三、权限校验安全测试方法

权限校验的测试需覆盖 “配置合法性” 与 “校验可靠性”,结合静态审核与动态绕过模拟,确保无漏洞:

1. 静态测试(配置与代码审核)

  • uid=1000 配置检测
  1. 检查 AndroidManifest 是否存在android:sharedUserId=“android.uid.system”,普通 APP 若有则标记为高风险;
  2. 系统 APP 需确认是否有checkSystemUidValid等 UID 与签名检测逻辑;
  • 权限校验方法检测
  1. 搜索跨进程场景(Service、ContentProvider)的代码,确认是否使用checkCallingPermission/checkCallingUriPermission
  2. 若存在getCallingPackage()/getCallingUid()单独判断,标记为不安全,需替换为系统推荐方法;
  3. 检查checkCallingUriPermission是否使用具体 Uri,而非通配符;
  • 权限声明检测
  1. 确认自定义权限的protectionLevel是否合理(高风险权限设为signature,普通权限设为normal)。

2. 动态测试(权限绕过模拟)

  • uid=1000 提权测试
  1. 对普通 APP,尝试添加sharedUserId="android.uid.system"并编译,验证是否安装失败;
  2. 在 root 设备上,使用pm install -t -r --uid 1000 malicious.apk强制安装恶意 APP,验证系统是否拦截。
  • 权限绕过测试
  1. 开发测试 APP,通过 Hook getCallingPackage()伪造可信包名,调用目标 APP 的跨进程接口,验证是否被checkCallingPermission拦截;
  2. 对 ContentProvider,构造未授权的 URI(如敏感数据 URI),调用 query 方法,验证是否被checkCallingUriPermission拒绝;

四、总结:权限校验的核心原则

Android 权限校验的安全防御,需紧扣 “依赖系统、最小权限、双重保障” 三大核心原则,避免因配置失误或方法误用导致权限机制失效:

  1. 依赖系统底层校验:跨进程权限校验必须使用checkCallingPermission/checkCallingUriPermission,禁用包名、UID 等上层可伪造的标识判断 —— 系统方法基于底层权限机制,可抵御大部分伪造攻击;
  2. uid=1000 严格管控:普通 APP 严禁配置系统 UID,系统 APP 需通过 UID + 签名双重检测,避免提权漏洞;
  3. 权限最小化:仅申请业务必需的权限,自定义权限按风险等级设置protectionLevel(高风险用signature),减少权限泄露面;
  4. 校验前置且严格:核心逻辑执行前必须完成权限校验,严格判断返回值,不遗漏任何非授权场景。
http://www.dtcms.com/a/437998.html

相关文章:

  • 单调队列与单调栈
  • 设计与优化Java API:构建高效、可维护的接口
  • Locality Sensitive Hashing (LSH) 详解:高效检测语言语句重复的利器
  • 阿里云网站开发零起步如何做设计师
  • 后端开发基础概念MVC以及Entity,DAO,DO,DTO,VO等概念
  • 七大排序算法的基本原理
  • Gateway-过滤器
  • 科普:Python 中,字典的“动态创建键”特性
  • Java 21 或 JavaFX 打包 exe 之 GraalVM Native Image 方案
  • 1.2.3 MCP(Model Context Protocol)
  • dede网站栏目管理网络科技是做什么的
  • 《Gdb 调试实战指南:不同风格于VS下的一种调试模式》
  • lua虚拟机的垃圾回收机制
  • 网站建设需要的材料wordpress自带的404
  • MPAndroidChart 用法解析和性能优化 - Kotlin Java 双版本
  • Qt中使用日志---Log4Qt
  • linux centos 7 解决终端提示符出现-bash-4.2的问题
  • MCP模型上下文协议实战:个人应用项目如何集成MCP?
  • Vue--Vue基础(一)
  • 外贸网站推广如何做郑佩佩 最新消息
  • 用VScode和msys2配置C/C++和wxWidgets
  • 【升级安卓9教程】华为Q21_Q21A_Q21C_Q21AQ_Q21AE_hi3798mv200线刷烧录包带adb权限
  • vite vue 打包后运行,路由首页加载不出来
  • 《C++ STL:vector类(下)》:攻克 C++ Vector 的迭代器失效陷阱:从源码层面详解原理与解决方案
  • 微软Agent框架深度解析:重新定义AI应用开发的革命性架构
  • 微信看视频打赏网站建设项目立项流程图
  • 爬虫与自动化技术深度解析:从数据采集到智能运维的完整实战指南
  • [工作流节点8] 更新记录节点应用案例 —— 业务自动化的关键一环
  • MySQL表的内连和外连
  • go 基础