0x01 mole 很棒,但是他只支持 mac 。我想要让我的 claude code 或者 codex 去帮我整理 iPhone 的相册,优化下存储空间,顺便也做个备份。 所以我做了一个 iPhone 版本的 mole ,命名为: iMole 。 0x02 iMole 的使用非常简单,把你的 iPhone 连接上你的电脑(最好是 mac 电脑),然后让 agent 自己使用 iMole 帮你检测优化。 直接把 github 地址 https://github.com/chenhg5/imole 丢给你的 agent 去安装执行。 比如:你可以告诉你的 agent ,帮我把去年在日本的照片备份下网盘吧,然后他就会帮你开始操作了。 使用示例: # 查看存储占用 imole scan --summary # 找出最大的视频文件 imole scan --top 20 --only videos # 备份 90 天前的视频 imole backup --to ~/iphone-backup --only videos --older-than 90d --dry-run imole backup --to ~/iphone-backup --only videos --older-than 90d # 删除已备份的文件 imole clean --manifest ~/iphone-backup/manifest.json --yes 查看空间统计: imole scan --summary Scanning media… Querying app storage… iMole Storage Summary Media: 28.9GiB · 9960 files Photos: 10.3GiB · 6579 files Videos: 18.6GiB · 3261 files Top video: IMG_7523.MOV · 327.7MiB Device: 2.0GiB free · 0.9% free Apps: 35.9GiB · 49 apps App code: 13.9GiB App data: 22.0GiB Top app: 网易云音乐 · 3.2GiB Recommended next steps: imole scan --top 30 --only videos imole scan apps --top 20 查看占用最多的图片或视频: imole scan --top 10 --only videos Scanning device… (may take ~15 s for USB) Device ready: imagecapture:山哥本山 Top 30 Videos 1. IMG_7523.MOV 327.7MiB 2025-07-30 2. IMG_7510.MOV 306.8MiB 2025-07-29 3. IMG_4109.MOV 270.8MiB 2024-09-15 4. IMG_9441.MOV 267.3MiB 2026-04-06 5. VRQA7650.MP4 260.3MiB 2025-07-20 6. XCGC7110.MP4 172.9MiB 2025-07-18 7. IMG_4113.MOV 151.7MiB 2024-09-15 8. AYXW6719.MP4 143.3MiB 2025-07-18 9. IMG_5865.MOV 142.3MiB 2025-01-11 10. IMG_7036.MOV 141.8MiB 2025-06-15 0x03 开源不易,如果感兴趣或者能帮助到你,欢迎点赞转发! 地址: https://github.com/chenhg5/imole 加入 telegram 群一起交流: https://t.me/+ZpgBu1dlmCszODBl
0x0 样本: play.google.com Lost Sword - Google Play 上的应用 波涛胸涌&华丽冒险传说!好胸的冒... Free 正主: largosoft.co.kr 라르고소프트|LARGOSOFT 라르고소프트는 게임 보안 솔루션 개발에 특화된 기업으로, 게임 환경에서 발생하는 다양한 보안 위협을 효과적으로 방어하는 기술을 제공합니다. 非常非常简单的反作弊,很适合新手入门,完全没任何难度 0x1 整体流程 base.apk 里面的 Dalvik字节码 拉起 libATG_D.so libATG_D.so 解密 e8Hk2vi4CH 为正常的 Dalvik字节码,然后注入进去,后续执行的是注入进去的 Dalvik字节码 解密后的 e8Hk2vi4CH Dalvik字节码 拉起正常的Unity进程,同时拉起 libATG_L.so libATG_L.so 根据架构解密拉起 ATG_E 来进行环境检测,日志上报等等 0x2 libATG_D.so com/bishopsoft/Presto/SDK/Loader.java 载入 libATG_D.so public class Loader extends Application // class@00018b from classes.dex { private String mAppName; private Application mDelegate; private boolean mIsBindReal; private static ByteBuffer[] Buffers; private static Context mContext; static { System.loadLibrary("ATG_D"); } System.loadLibrary 会调用 libATG_D.so 的 JNI_OnLoad ,随后调用 JNI_OnLoad.54 JNI_OnLoad.54 开头有些垃圾代码狙击IDA的反编译 缓存运行环境信息 找到 Java 类 注册两个 native 方法 Loader.InitBuffer signature: (Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Landroid/content/res/AssetManager;)Ljava/lang/Object; native: 0x79004 -> real body 0x75660 Loader.native_InitLib signature: (Landroid/content/Context;Landroid/content/res/AssetManager;Z)I native: 0x77594 -> real body 0x740f8 JNI_OnLoad 返回到 Java,调用 InitBuffer 解密 Dalvik字节码 public native Object InitBuffer(Context p0,String p1,String p2,AssetManager p3); public void attachBaseContext(Context paramContext){ try{ super.attachBaseContext(paramContext); AssetManager assets = paramContext.getAssets(); this.native_InitLib(paramContext, assets, false); Loader.Buffers = this.InitBuffer(paramContext, paramContext.getApplicationInfo().dataDir, paramContext.getApplicationInfo().nativeLibraryDir, assets); if (Loader.Buffers != null) { this.loadDex(paramContext); } }catch(java.lang.NoSuchFieldException e1){ e1.printStackTrace(); }catch(java.lang.IllegalAccessException e1){ e1.printStackTrace(); }catch(java.lang.NoSuchMethodException e1){ e1.printStackTrace(); }catch(java.lang.reflect.InvocationTargetException e1){ e1.printStackTrace(); } return; } 开头依旧狙击IDA反编译 取 e8Hk2vi4CH 的路径 派生密钥 用派生出来的密钥跑AES解密 e8Hk2vi4CH 扫描 embedded Dalvik字节码 生成 + 返回 解密后的buffer 0x3 libATG_L.so java/stage2/code/com/bishopsoft/Presto/SDK/Presto.java 载入 libATG_L.so public class Presto extends Application // class@0000ff from classes2.dex { private static String EGdataPath; public static String SDK_version = "2025091801"; static CallBackReLogin callback; private static int checked_emul = 0; private static Context mContext; public static String packageList = ""; private static Presto presto; public static String rootPath = ""; private static String sData = ""; static boolean scanning = true; static { Presto.presto = new Presto(); System.loadLibrary("ATG_L"); } 开头依旧狙击IDA反编译 依旧注册函数查询CPU架构 fork/ptrace 保护+反调试 JNI_OnLoad 返回到 Java 开始 init,最终调用 WorkThread public void Presto_Init(Context context){ Presto.mContext = context; Presto.scanning = true; if (Presto.EGdataPath == null) { Presto.EGdataPath = Utils.getCPUABI(Presto.mContext); } Presto.rootPath = Utils.execByRuntime("pm path "+Presto.mContext.getPackageName()); if (Presto.rootPath != null && !Presto.rootPath.isEmpty()) { Presto.rootPath = Presto.rootPath.replace("package:", ""); } Presto.packageList = Utils.execByRuntime("pm list package"); if (Presto.packageList != null && !Presto.packageList.isEmpty()) { Presto.packageList = Presto.packageList.replaceAll("\npackage:", ","); } Log.i("Presto", "SDK_Ver = "+Presto.SDK_version); Integer[] integerArray = new Integer[0]; new ThreadScan(Presto.mContext, 0).execute(integerArray); return; } public class ThreadScan extends AsyncTask // class@000102 from classes2.dex { private Context mContext; private int option; private String result; public static String ResultScan = ""; static { } public void ThreadScan(Context context,int _option){ super(); this.mContext = context; this.option = _option; } protected Object doInBackground(Object[] p0){ return this.doInBackground(p0); } protected String doInBackground(Integer[] arg0){ int recovery = 1; this.result = Presto.WorkThread(this.mContext, recovery); return this.result; } } 根据CPU架构选择模块 CpuFamily = android_getCpuFamily(); if ( CpuFamily == ANDROID_CPU_FAMILY_X86_64 ) { strcpy(&filename[strlen(filename)], "/ATG_E_x86_64.sec"); } else { if ( CpuFamily == ANDROID_CPU_FAMILY_ARM64 ) { v25 = strlen(filename); v26 = "/ATG_E_x64.sec"; } else { if ( CpuFamily != ANDROID_CPU_FAMILY_X86 ) { strcpy(&filename[strlen(filename)], "/ATG_E.sec"); goto LABEL_64; } v25 = strlen(filename); v26 = "/ATG_E_x86.sec"; } v27 = &filename[v25]; v28 = *v26; v29 = *(v26 + 7); *v27 = v28; *(v27 + 7) = v29; } 解出临时 ._ATG_B.sec strcpy(file, g_dataPath); qmemcpy(v206, "FF8F2A6CDD9B3DB72CD301FB87035E34", sizeof(v206)); strcpy(szHex, "2CD301FB87035E34FF8F2A6CDD9B3DB7"); v30 = strlen(szHex); v31 = v30; if ( v30 >= 1 && (v30 & 0xF) == 0 && v30 >= 2 ) { v32 = v30 >> 1; v33 = operator new(v32); memset(v33, 0, v31 >> 1); v34 = 0; v35 = szHex; v36 = v33; while ( Hex2Char(v35, &s) ) { v37 = 0xFFFFFFFE - v34 - (~v34 | 0xFFFFFFFE); v35 += 2; v34 = (v37 ^ (v34 + 1)) + (v34 | 1) + 2 * (v37 & (v34 + 1)); *v36++ = s.erk[0]; if ( v34 >= v32 ) { v38 = operator new(v31 >> 1); memset(v38, 0, v31 >> 1); *name = WzrBpTHKGekFnEGBsJVCCbpW(char *,int)::iv_key; aes_set_key(&s, "e38d99fb4434d3d485794c6b34cd5d1fB3B4801D0A7AC103B2BC08C10BC017E6", 0x100); v39 = 0; do { v40 = &v33[v39]; aes_decrypt(&s, v40, &v38[v39]); v41 = 0; do { v42 = name[v41]; v43 = ((v41 + v39) ^ -(v41 | v39)) + (v41 | v39) + 2 * ((v41 + v39) & -(v41 | v39)); v44 = v38[v43]; v45 = v44 | v42; v46 = -(((v44 + v42) ^ -v45) + 2 * ((v44 + v42) & -v45)); v47 = 0xFFFFFFFE - v41 - (~v41 | 0xFFFFFFFE); v41 = (v47 ^ (v41 + 1)) + (v41 | 1) + 2 * (v47 & (v41 + 1)); v38[v43] = (v46 ^ v45) + 2 * (v46 & v45); } while ( v41 < 0x10 ); v39 = (v39 | 0x10) + ~v39 + (v39 | 1) + (v39 & 1) + ((0xFFFFFFEF - v39 - (~v39 | 0xFFFFFFEF)) ^ (v39 + 0x10)) + 2 * ((0xFFFFFFEF - v39 - (~v39 | 0xFFFFFFEF)) & (v39 + 0x10)); *name = *v40; } while ( v39 < v32 ); memset(&szHex[v32], 0, v31 - v32); memcpy(szHex, v38, v31 >> 1); memset(v33, 0, v31 >> 1); operator delete(v38); break; } } operator delete(v33); } strcat(file, szHex); v48 = fopen(filename, "rb"); v49 = fopen(file, "wb"); if ( v48 ) { v50 = v49; fseek(v48, 0xFFFFFFFFFFFFFFFCLL, 2); v51 = ftell(v48); fread(&ptr, 1u, 8u, v48); v52 = ptr; v53 = v51 - v52 + ((v52 - 1) | ~v51); v54 = ((v53 + 1) ^ (v52 - v51 + (v51 | -v52))) + 2 * (((v53 + 1) & (v52 - v51 + (v51 | -v52))) + (v53 ^ ~(v51 - ptr)) + 2 * ((v51 - ptr) & ~v53)); v55 = calloc(v54, 1u); v56 = calloc(v51, 1u); if ( v55 ) { v57 = v56; if ( v56 ) { fseek(v48, 0, 0); fread(v57, 1u, v51, v48); fseek(v48, v52, 0); fread(v55, 1u, v54, v48); fclose(v48); if ( v54 >= 1 ) { v58 = 0; for ( i = 0; i < v54; v58 = i ) { v60 = v55[v58]; v61 = v57[v58]; v62 = v61 | v60; v63 = -(((v61 + v60) ^ -v62) + 2 * ((v61 + v60) & -v62)); v64 = 0xFFFFFFFE - i - (~i | 0xFFFFFFFE); i = (v64 ^ (i + 1)) + (i | 1) + 2 * (v64 & (i + 1)); v55[v58] = (v63 ^ v62) + 2 * (v63 & v62); } } fwrite(v55, 1u, v54, v50); fclose(v50); free(v55); free(v57); } } } 完整性检查 v277 = 0; v276 = 0u; v275 = 0u; v274 = 0u; v273 = 0u; v272 = 0u; v271 = 0u; v270 = 0u; v269 = 0u; v268 = 0u; v267 = 0u; v266 = 0u; v265 = 0u; v264 = 0u; v263 = 0u; *v262 = 0u; *filename = 0u; memcpy(name, "B3B4801D0A7AC103B2BC08C10BC017E6", 0x104u); strcpy(file, g_dataPath); szHex[0x20] = 0; memset(v243, 0, sizeof(v243)); v242 = 0u; v241 = 0u; v240 = 0u; v239 = 0u; v238 = 0u; v237 = 0u; v236 = 0u; v235 = 0u; v234 = 0u; v233 = 0u; v232 = 0u; v231 = 0u; v230 = 0u; *szHex = v206[1]; *&szHex[0x10] = v206[0]; v65 = strlen(szHex); v66 = v65; v67 = v209; if ( v65 >= 1 && (v65 & 0xF) == 0 && v65 >= 2 ) { v68 = v65 >> 1; v69 = operator new(v68); memset(v69, 0, v66 >> 1); v70 = 0; v71 = szHex; v72 = v69; while ( Hex2Char(v71, &s) ) { v73 = 0xFFFFFFFE - v70 - (~v70 | 0xFFFFFFFE); v71 += 2; v70 = (v73 ^ (v70 + 1)) + (v70 | 1) + 2 * (v73 & (v70 + 1)); *v72++ = s.erk[0]; if ( v70 >= v68 ) { v74 = operator new(v66 >> 1); memset(v74, 0, v66 >> 1); ptr = WzrBpTHKGekFnEGBsJVCCbpW(char *,int)::iv_key; aes_set_key(&s, "e38d99fb4434d3d485794c6b34cd5d1fB3B4801D0A7AC103B2BC08C10BC017E6", 0x100); v75 = 0; do { v76 = &v69[v75]; aes_decrypt(&s, v76, &v74[v75]); v77 = 0; do { v78 = *(&ptr + v77); v79 = ((v77 + v75) ^ -(v77 | v75)) + (v77 | v75) + 2 * ((v77 + v75) & -(v77 | v75)); v80 = v74[v79]; v81 = v80 | v78; v82 = -(((v80 + v78) ^ -v81) + 2 * ((v80 + v78) & -v81)); v83 = 0xFFFFFFFE - v77 - (~v77 | 0xFFFFFFFE); v77 = (v83 ^ (v77 + 1)) + (v77 | 1) + 2 * (v83 & (v77 + 1)); v74[v79] = (v82 ^ v81) + 2 * (v82 & v81); } while ( v77 < 0x10 ); v75 = (v75 | 0x10) + ~v75 + (v75 | 1) + (v75 & 1) + ((0xFFFFFFEF - v75 - (~v75 | 0xFFFFFFEF)) ^ (v75 + 0x10)) + 2 * ((0xFFFFFFEF - v75 - (~v75 | 0xFFFFFFEF)) & (v75 + 0x10)); ptr = *v76; } while ( v75 < v68 ); memset(&szHex[v68], 0, v66 - v68); memcpy(szHex, v74, v66 >> 1); memset(v69, 0, v66 >> 1); operator delete(v74); break; } } operator delete(v69); } strcat(file, szHex); v84 = dlopen(file, 1); v85 = obja; if ( v84 ) { v86 = v84; v87 = strlen(name); v88 = v87; if ( v87 >= 1 && (v87 & 0xF) == 0 && v87 >= 2 ) { v89 = v87 >> 1; v90 = operator new(v89); memset(v90, 0, v88 >> 1); v91 = 0; v92 = name; v93 = v90; while ( Hex2Char(v92, &s) ) { v94 = 0xFFFFFFFE - v91 - (~v91 | 0xFFFFFFFE); v92 += 2; v91 = (v94 ^ (v91 + 1)) + (v91 | 1) + 2 * (v94 & (v91 + 1)); *v93++ = s.erk[0]; if ( v91 >= v89 ) { v95 = operator new(v88 >> 1); memset(v95, 0, v88 >> 1); ptr = WzrBpTHKGekFnEGBsJVCCbpW(char *,int)::iv_key; aes_set_key(&s, "e38d99fb4434d3d485794c6b34cd5d1fB3B4801D0A7AC103B2BC08C10BC017E6", 0x100); v96 = 0; do { v97 = &v90[v96]; aes_decrypt(&s, v97, &v95[v96]); v98 = 0; do { v99 = *(&ptr + v98); v100 = ((v98 + v96) ^ -(v98 | v96)) + (v98 | v96) + 2 * ((v98 + v96) & -(v98 | v96)); v101 = v95[v100]; v102 = v101 | v99; v103 = -(((v101 + v99) ^ -v102) + 2 * ((v101 + v99) & -v102)); v104 = 0xFFFFFFFE - v98 - (~v98 | 0xFFFFFFFE); v98 = (v104 ^ (v98 + 1)) + (v98 | 1) + 2 * (v104 & (v98 + 1)); v95[v100] = (v103 ^ v102) + 2 * (v103 & v102); } while ( v98 < 0x10 ); v96 = (v96 | 0x10) + ~v96 + (v96 | 1) + (v96 & 1) + ((0xFFFFFFEF - v96 - (~v96 | 0xFFFFFFEF)) ^ (v96 + 0x10)) + 2 * ((0xFFFFFFEF - v96 - (~v96 | 0xFFFFFFEF)) & (v96 + 0x10)); ptr = *v97; } while ( v96 < v89 ); memset(&name[v89], 0, v88 - v89); memcpy(name, v95, v88 >> 1); memset(v90, 0, v88 >> 1); operator delete(v95); v67 = v209; break; } } operator delete(v90); v85 = obja; } 启动模块 LABEL_249: g_result[0] = 0; memset(&s, 0, 0x104); if ( p_result ) { free(p_result); p_result = nullptr; } strcpy(&s, g_dataPath); *(s.erk + strlen(&s)) = 0x2F; if ( family == ANDROID_CPU_FAMILY_X86_64 ) { strcpy(&s + strlen(&s), "ATG_E_x86_64.sec"); } else { if ( family == ANDROID_CPU_FAMILY_ARM64 ) { v152 = strlen(&s); v153 = "ATG_E_x64.sec"; } else { if ( family != ANDROID_CPU_FAMILY_X86 ) { strcpy(&s + strlen(&s), "ATG_E.sec"); goto LABEL_259; } v152 = strlen(&s); v153 = "ATG_E_x86.sec"; } v154 = (s.erk + v152); v155 = *v153; v156 = *(v153 + 6); *v154 = v155; *(v154 + 6) = v156; } LABEL_259: if ( g_Ehandle || (g_Ehandle = dlopen(&s, 1)) != nullptr ) { unlink(&s); if ( g_isScanning ) return v67->functions->NewStringUTF(v67, g_result); v157 = dlsym(g_Ehandle, "WorkThread"); if ( v157 ) { g_isScanning = 1; m_infect_cnt = v157(v67, v85, m_option); if ( (m_infect_cnt & 0x80000000) == 0 ) return v67->functions->NewStringUTF(v67, g_result); memset(&s, 0, 0x104); v158 = operator new(0xF0u); v262[0] = v158; 虚拟机检测(非常全的特征,可以抄过来用 ) Build.BRAND == “generic” Build.BRAND == “sdk” Build.BRAND == “Microvirt” Build.BRAND == “AMIDuOS” Build.BRAND == “TTVM” Build.MODEL == “AMIDuOS” Build.MODEL == “Memu” Build.MODEL == “TiantianVM” Build.MODEL == “Droid4X” Build.MODEL == “vmos” Build.HARDWARE == “andy” Build.HARDWARE == “vbox86” Build.HARDWARE == “nox” Build.HARDWARE == “windroye” Build.HARDWARE == “goldfish” Build.HARDWARE == “ttVM_x86” Build.HARDWARE == “android_x86” Build.HARDWARE == “android_x86_64” Build.BOOTLOADER == “nox” 文件存在 /system/bin/droid4x 文件存在 /system/bin/droid4x-prop 文件存在 /system/bin/androVM-prop 文件存在 /system/bin/androVM-vbox-sf 文件存在 /fstab.intel 文件存在 /fstab.vbox86 文件存在 /fstab.vbox64 文件存在 /fstab.android_x86 文件存在 /fstab.android_x86_64 文件存在 /system/app/EmuCoreService/EmuCoreService.apk 文件存在 /system/app/EmuInputService/EmuInputService.apk 文件存在 /system/app/gpLogin/gpLogin.apk 文件存在 /system/app/gpLogin/gpLogin_new.apk 文件存在 /system/app/Helper/helper.apk 文件存在 /system/app/Helper/NoxHelp_en.apk 文件存在 /system/app/Helper/NoxHelp_en_new.apk 文件存在 /bin/nox-vbox-sf 文件存在 /bin/noxd 文件存在 /data/app/com.android.ld.appstore-1/base.apk 文件存在 /data/app/com.android.ld.appstore-2/base.apk 文件存在 /system/app/Launcher3/Launcher3.apk 文件存在 /system/priv-app/LDAppStore/LDAppStore.apk 文件存在 /data/user_de/0/com.android.flysilkworm 文件存在 /data/misc/profiles/ref/com.android.flysilkworm 目录可打开 /mnt/windows/BstSharedFolder 文件存在 system/app/IME/IME.apk 上一条 APK 的包名等于 com.microvirt.memuime 文件存在 /system/app/MuMuAudio/MuMuAudio.apk 文件存在 /system/app/com.mumu.store/com.mumu.store.apk 文件存在 /system/priv-app/MuMuAudio/MuMuAudio.apk 文件存在 /system/priv-app/com.mumu.store_overseas/com.mumu.store_overseas.apk 文件存在 /system/app/KiwiIntentSink/KiwiIntentSink.apk 0x3 libATG_E.so WorkThread 入口塞了一坨特征码 然后启动了两个线程 iCEcaaLIRKlGfNDwLLDLVlwO 还是做虚拟机检测,增加了下面的特征: com.gspace.android com.excean.gspace com.excean.splay com.excean.parallelspace io.va.exposed parallel.space com.ludashi.dualspace com.ludashi.superboost com.app.hider.master.dual.app com.app.hider.master.pro com.hidespps.apphider com.app.calculator.vault.hider com.excelliance.multiaccount multi.parallel.dualspace.cloner do.multiple.cloner com.lulu.luluboxpro com.cloneapp.parallelspace.dualspace com.pan.parallelspace com.dualspace.multispace.android com.pengyou.cloneapp 做crc32校验 初始化 libData.so ,解出来是作弊工具的名称 AlphaGameBooster CheatEngine Freedom Freedom Freedom Freedom Freedom Freedom Freedom Freedom Freedom GameCheater GameCheater GameCIH GameGuardian GameGuardian GameGuardian GameGuardian GameGuardian GameGuardian GameHackerSpeed GameHackerSpeed GameHacker GameHacker GameHacker GameHacker GameHacker GameHacker GameHacker GameKiller GameKiller GameKiller GameKiller GameKiller GameKiller GameMaster2 GameMaster2 GameMaster GameMaster_opda GameMaster_opda GameMaster_opda GameMaster_opda GGAssistant HoistMan HoistMan HoistMan HoistMan Huang Huang Huang Huang igamecool igamecool LuckyPatcher MemSpector MemSpector MuzhiwanGamehelper MuzhiwanGamehelper PacketSniffer PacketSniffer RootCloakPlus RootCloakPlus RootCloak RootCloak RootCloak RootCloak SlashGameBuster SlashGameBuster SlashGameBuster TcgameGamecheater Touch18 Touch18 WoodPecker Xiaojianjian Xiaojianjian xxAssistant xxAssistant xxAssistant xxAssistant Youxia Youxia Zhangkongapp Zhangkongapp Zhangkongapp Zhangkongapp SHBUoTIkyKmlbYGMbbWeIYeB 只负责轮询配置 0x4 global-metadata.dat 读进内存变换一下文件头,做一下xor完事 0xF 反作弊力度和LIAPP坐一桌,CrackProof比这玩意稍强 libunity.so 和 libil2cpp.so 不加壳,没有云下发,甚至安全模块包含完整的DWARF 2 个帖子 - 2 位参与者 阅读完整话题
0x01 不知道大家用过 mole 吗,很棒的一款终端软件可以帮你清理和优化 mac 电脑的存储空间。但是他只支持 mac ,而我主要困惑是手机,而对于我们这种 iPhone 手机常年处于存储满了,iCloud 也早就满了,不想花钱拼车或换手机改硬盘,老是得删东西才能下新的应用的人来说,太难受了,而且这么多年了,没有什么好用的免费的软件可以帮忙。 所以我就想做一个 iPhone 版本的 mole ,我把他命名为: iMole 。 0x02 他的使用非常简单,把你的 iPhone 连接上你的电脑(最好是 mac 电脑),然后让 agent 自己使用 iMole 帮你检测优化,或者你自己去执行都可以。 直接把 github 地址丢给你的 agent 去安装,或者执行: npm install -g @getimole/imole 然后,你可以开始使用了。 使用示例: # 查看存储占用 imole scan --summary # 找出最大的视频文件 imole scan --top 20 --only videos # 备份 90 天前的视频 imole backup --to ~/iphone-backup --only videos --older-than 90d --dry-run imole backup --to ~/iphone-backup --only videos --older-than 90d # 删除已备份的文件 imole clean --manifest ~/iphone-backup/manifest.json --yes 查看空间统计: imole scan --summary Scanning media… Querying app storage… iMole Storage Summary Media: 28.9GiB · 9960 files Photos: 10.3GiB · 6579 files Videos: 18.6GiB · 3261 files Top video: IMG_7523.MOV · 327.7MiB Device: ███████████████░ 99.2% 1.9GiB free Apps: 35.9GiB · 49 apps App code: 13.9GiB App data: 22.0GiB Top app: 网易云音乐 · 3.2GiB Recommended next steps: imole scan --top 30 --only videos imole scan apps --top 20 查看占用最多的图片或视频: imole scan --top 10 --only videos Scanning device… (may take ~15 s for USB) Device ready: imagecapture:山哥本山 Top 30 Videos 1. IMG_7523.MOV 327.7MiB 2025-07-30 2. IMG_7510.MOV 306.8MiB 2025-07-29 3. IMG_4109.MOV 270.8MiB 2024-09-15 4. IMG_9441.MOV 267.3MiB 2026-04-06 5. VRQA7650.MP4 260.3MiB 2025-07-20 6. XCGC7110.MP4 172.9MiB 2025-07-18 7. IMG_4113.MOV 151.7MiB 2024-09-15 8. AYXW6719.MP4 143.3MiB 2025-07-18 9. IMG_5865.MOV 142.3MiB 2025-01-11 10. IMG_7036.MOV 141.8MiB 2025-06-15 0x03 开源不易,如果感兴趣或者能帮助到你,欢迎点赞转发! 地址: https://github.com/chenhg5/imole 加入 telegram 群一起交流: https://t.me/+ZpgBu1dlmCszODBl
0x01 不知道大家用过 mole 吗,很棒的一款终端软件可以帮你清理和优化 mac 电脑的存储空间。但是他只支持 mac 。而我主要的困扰是 iPhone, 对于我们这种 iPhone 手机常年处于存储满了,iCloud 也早就满了,老是得删东西才能下新的应用的人来说,太难受了。而且这么多年了,没有什么好用的免费的软件可以帮忙。 所以我就想做一个 iPhone 版本的 mole ,我把他命名为: iMole 。 0x02 他的使用非常简单,把你的 iPhone 连接上你的电脑(最好是 mac 电脑),然后让 agent 自己使用 iMole 帮你检测优化,或者你自己去执行都可以。 直接把 github 地址( https://github.com/chenhg5/imole )丢给你的 agent 去安装,或者执行: npm install -g @getimole/imole 然后,你可以开始使用了。 使用示例: # 查看存储占用 imole scan --summary # 找出最大的视频文件 imole scan --top 20 --only videos # 备份 90 天前的视频 imole backup --to ~/iphone-backup --only videos --older-than 90d --dry-run imole backup --to ~/iphone-backup --only videos --older-than 90d # 删除已备份的文件 imole clean --manifest ~/iphone-backup/manifest.json --yes 查看空间统计: imole scan --summary Scanning media… Querying app storage… iMole Storage Summary Media: 28.9GiB · 9960 files Photos: 10.3GiB · 6579 files Videos: 18.6GiB · 3261 files Top video: IMG_7523.MOV · 327.7MiB Device: ███████████████░ 99.2% 1.9GiB free Apps: 35.9GiB · 49 apps App code: 13.9GiB App data: 22.0GiB Top app: 网易云音乐 · 3.2GiB Recommended next steps: imole scan --top 30 --only videos imole scan apps --top 20 查看占用最多的图片或视频: imole scan --top 10 --only videos Scanning device… (may take ~15 s for USB) Device ready: imagecapture:山哥本山 Top 30 Videos 1. IMG_7523.MOV 327.7MiB 2025-07-30 2. IMG_7510.MOV 306.8MiB 2025-07-29 3. IMG_4109.MOV 270.8MiB 2024-09-15 4. IMG_9441.MOV 267.3MiB 2026-04-06 5. VRQA7650.MP4 260.3MiB 2025-07-20 6. XCGC7110.MP4 172.9MiB 2025-07-18 7. IMG_4113.MOV 151.7MiB 2024-09-15 8. AYXW6719.MP4 143.3MiB 2025-07-18 9. IMG_5865.MOV 142.3MiB 2025-01-11 10. IMG_7036.MOV 141.8MiB 2025-06-15 0x03 开源不易,如果感兴趣或者能帮助到你,欢迎点赞转发! 地址: https://github.com/chenhg5/imole 欢迎加入 telegram 群一起交流: https://t.me/+ZpgBu1dlmCszODBl
0x01 不知道大家用过 mole 吗,很棒的一款终端软件可以帮你清理和优化 mac 电脑的存储空间。但是他只支持 mac 。而我主要的困扰是 iPhone, 对于我们这种 iPhone 手机常年处于存储满了,iCloud 也早就满了,老是得删东西才能下新的应用的人来说,太难受了。而且这么多年了,没有什么好用的免费的软件可以帮忙。 所以我就想做一个 iPhone 版本的 mole ,我把他命名为: iMole 。 0x02 他的使用非常简单,把你的 iPhone 连接上你的电脑(最好是 mac 电脑),然后让 agent 自己使用 iMole 帮你检测优化,或者你自己去执行都可以。 直接把 github 地址( https://github.com/chenhg5/imole )丢给你的 agent 去安装,或者执行: npm install -g @getimole/imole 然后,你可以开始使用了。 使用示例: # 查看存储占用 imole scan --summary # 找出最大的视频文件 imole scan --top 20 --only videos # 备份 90 天前的视频 imole backup --to ~/iphone-backup --only videos --older-than 90d --dry-run imole backup --to ~/iphone-backup --only videos --older-than 90d # 删除已备份的文件 imole clean --manifest ~/iphone-backup/manifest.json --yes 查看空间统计: imole scan --summary Scanning media… Querying app storage… iMole Storage Summary Media: 28.9GiB · 9960 files Photos: 10.3GiB · 6579 files Videos: 18.6GiB · 3261 files Top video: IMG_7523.MOV · 327.7MiB Device: ███████████████░ 99.2% 1.9GiB free Apps: 35.9GiB · 49 apps App code: 13.9GiB App data: 22.0GiB Top app: 网易云音乐 · 3.2GiB Recommended next steps: imole scan --top 30 --only videos imole scan apps --top 20 查看占用最多的图片或视频: imole scan --top 10 --only videos Scanning device… (may take ~15 s for USB) Device ready: imagecapture:山哥本山 Top 30 Videos 1. IMG_7523.MOV 327.7MiB 2025-07-30 2. IMG_7510.MOV 306.8MiB 2025-07-29 3. IMG_4109.MOV 270.8MiB 2024-09-15 4. IMG_9441.MOV 267.3MiB 2026-04-06 5. VRQA7650.MP4 260.3MiB 2025-07-20 6. XCGC7110.MP4 172.9MiB 2025-07-18 7. IMG_4113.MOV 151.7MiB 2024-09-15 8. AYXW6719.MP4 143.3MiB 2025-07-18 9. IMG_5865.MOV 142.3MiB 2025-01-11 10. IMG_7036.MOV 141.8MiB 2025-06-15 0x03 开源不易,如果感兴趣或者能帮助到你,欢迎点赞转发! 地址: https://github.com/chenhg5/imole 欢迎加入 telegram 群一起交流: https://t.me/+ZpgBu1dlmCszODBl
0x01 不知道大家用过 mole 吗,很棒的一款终端软件可以帮你清理和优化 mac 电脑的存储空间。但是他只支持 mac 。而我主要的困扰是 iPhone, 对于我们这种 iPhone 手机常年处于存储满了,iCloud 也早就满了,老是得删东西才能下新的应用的人来说,太难受了。而且这么多年了,没有什么好用的免费的软件可以帮忙。 所以我就想做一个 iPhone 版本的 mole ,我把他命名为: iMole 。 0x02 他的使用非常简单,把你的 iPhone 连接上你的电脑(最好是 mac 电脑),然后让 agent 自己使用 iMole 帮你检测优化,或者你自己去执行都可以。 直接把 github 地址( https://github.com/chenhg5/imole )丢给你的 agent 去安装,或者执行: npm install -g @getimole/imole 然后,你可以开始使用了。 使用示例: # 查看存储占用 imole scan --summary # 找出最大的视频文件 imole scan --top 20 --only videos # 备份 90 天前的视频 imole backup --to ~/iphone-backup --only videos --older-than 90d --dry-run imole backup --to ~/iphone-backup --only videos --older-than 90d # 删除已备份的文件 imole clean --manifest ~/iphone-backup/manifest.json --yes 查看空间统计: imole scan --summary Scanning media… Querying app storage… iMole Storage Summary Media: 28.9GiB · 9960 files Photos: 10.3GiB · 6579 files Videos: 18.6GiB · 3261 files Top video: IMG_7523.MOV · 327.7MiB Device: ███████████████░ 99.2% 1.9GiB free Apps: 35.9GiB · 49 apps App code: 13.9GiB App data: 22.0GiB Top app: 网易云音乐 · 3.2GiB Recommended next steps: imole scan --top 30 --only videos imole scan apps --top 20 查看占用最多的图片或视频: imole scan --top 10 --only videos Scanning device… (may take ~15 s for USB) Device ready: imagecapture:山哥本山 Top 30 Videos 1. IMG_7523.MOV 327.7MiB 2025-07-30 2. IMG_7510.MOV 306.8MiB 2025-07-29 3. IMG_4109.MOV 270.8MiB 2024-09-15 4. IMG_9441.MOV 267.3MiB 2026-04-06 5. VRQA7650.MP4 260.3MiB 2025-07-20 6. XCGC7110.MP4 172.9MiB 2025-07-18 7. IMG_4113.MOV 151.7MiB 2024-09-15 8. AYXW6719.MP4 143.3MiB 2025-07-18 9. IMG_5865.MOV 142.3MiB 2025-01-11 10. IMG_7036.MOV 141.8MiB 2025-06-15 0x03 开源不易,如果感兴趣或者能帮助到你,欢迎点赞转发! 地址: https://github.com/chenhg5/imole 欢迎加入 telegram 群一起交流: https://t.me/+ZpgBu1dlmCszODBl
产品形态没问题 实现太有问题了 我实在没想到还能套个lobechat 很卡体验很差 单产品形态确实没问题 有老友知道他们偷偷发了多少财吗 2 个帖子 - 1 位参与者 阅读完整话题
0x00 开始 openbee 是一款让 Agents 成为你的数字员工的解决方案。 0x01 demo 下面是我基于 openbee 今天早上发布 v0.0.32 版本的流程: 0x02 思考 通过在飞书对话让 Agents ( claude/codex/kimi/pi ) 完成任务。针对 openbee 我是这样思考: agent + skill 使得大模型能够完成一些比较稳定的较为复杂的任务,这打下了 agent 成为数字员工的基础。 少即是多,囿于大模型的上下文限制,agent 应当尽量去做可以 100%稳定完成的事情,这就要求一件较为复杂的事情需要做拆分成更小的任务去分别完成从而保证稳定性,这就引入了数字员工的概念,每个员工只负责一件事情。 基于上述规则,每位数字员工只负责一件事情的话则如果落地到企业业务实践的话那么肯定会有很多数字员工,这个时候就需要一个调度层去理解用户的需求然后调度员工完成任务,这就是 openbee 的基础架构:IM <-> 调度层 <-> 数字员工层( Agents )。 0x03 介绍 openbee 现在支持飞书、钉钉、企业微信、微信、Telegram 五个 IM 平台。目前支持 Claude Code / codex / pi / kimi 四个 agent 。可以通过 openbee 完成任何原先你可以通过 claude code 完成的任务。还有一些功能点: 员工部门管理 全局、调度器、部门、员工四个维度的 env 管理,可以按需分配 全局、调度器、员工三个维度的 args 管理,可以通过此参数配置 agent 底层的驱动模型,思考深度等,如: --model opus --effort high 定时任务、倒计时任务 项目地址: https://github.com/theopenbee/openbee 提供 npm install -g @theopenbee/cli 一键安装。 0x04 使用数据 从 3 月 19 日开始我就已经基于 openbee + 飞书实现了使用 openbee 开发 openbee 的自举。下面是我的一些使用数据: 从文章开头的软件截图可以看到: token 消耗 4B 发送了超过 1w+ 的消息 目前 20 位数字员工 累计工作时长 158h
0x00 开始 openbee 是一款让 Agents 成为你的数字员工的解决方案。 0x01 demo 下面是我基于 openbee 今天早上发布 v0.0.32 版本的流程: 0x02 思考 通过在飞书对话让 Agents ( claude/codex/kimi/pi ) 完成任务。针对 openbee 我是这样思考: agent + skill 使得大模型能够完成一些比较稳定的较为复杂的任务,这打下了 agent 成为数字员工的基础。 少即是多,囿于大模型的上下文限制,agent 应当尽量去做可以 100%稳定完成的事情,这就要求一件较为复杂的事情需要做拆分成更小的任务去分别完成从而保证稳定性,这就引入了数字员工的概念,每个员工只负责一件事情。 基于上述规则,每位数字员工只负责一件事情的话则如果落地到企业业务实践的话那么肯定会有很多数字员工,这个时候就需要一个调度层去理解用户的需求然后调度员工完成任务,这就是 openbee 的基础架构:IM <-> 调度层 <-> 数字员工层( Agents )。 0x03 介绍 openbee 现在支持飞书、钉钉、企业微信、微信、Telegram 五个 IM 平台。目前支持 Claude Code / codex / pi / kimi 四个 agent 。可以通过 openbee 完成任何原先你可以通过 claude code 完成的任务。还有一些功能点: 员工部门管理 全局、调度器、部门、员工四个维度的 env 管理,可以按需分配 全局、调度器、员工三个维度的 args 管理,可以通过此参数配置 agent 底层的驱动模型,思考深度等,如: --model opus --effort high 定时任务、倒计时任务 项目地址: https://github.com/theopenbee/openbee 提供 npm install -g @theopenbee/cli 一键安装。 0x04 使用数据 从 3 月 19 日开始我就已经基于 openbee + 飞书实现了使用 openbee 开发 openbee 的自举。下面是我的一些使用数据: 从文章开头的软件截图可以看到: token 消耗 4B 发送了超过 1w+ 的消息 目前 20 位数字员工 累计工作时长 158h
0x0 把市面上的非冷门二游全部肘击了一遍,各种加密方法应该是了解的差不多了 0x1 il2cpp 最经典的肯定是往 il2cpp::vm::MetadataLoader::LoadMetadataFile 加料了,拿到fileBuffer以后进行一些额外的解密操作,比如xor,解压,AES解密等等 global-metadata.dat 自己也可以藏某个文件里面,比如藏PE的资源段里面,或者藏 mscorlib.dll-resources.dat 尾部,方法挺多的 更进一步的话可以把文件头魔术字抹掉,版本号乱写一个,把全部的Size写0,运行时不依赖这些东西,global-metadata.dat字符串也能加密混淆一下 Il2CppGlobalMetadataHeader 也可以打乱顺序,建议打乱 Il2CppGlobalMetadataHeader 结构体后往里面塞入垃圾数据干扰分析,数据段也需要打乱顺序 正常的长这样 打乱 Il2CppGlobalMetadataHeader +打乱数据段顺序长这样 打乱 Il2CppMetadataRegistration , Il2CppCodeRegistration , Il2CppCodeGenModule 的结构体,改一下还是能狠狠恶心一下逆向的,AI不太能正确恢复出来 在二进制层面看大概长这样, FieldInfo , PropertyInfo , EventInfo , Il2CppClass 等等也可以打乱顺序,有些字段运行时完全不依赖,但是静态dump需要用到 C#函数的命名也可以用Bee尽可能混淆以后再编译成native 0x2 il2cpp API 如果买了Unity的源代码,可以直接把launcher,UnityPlayer,Gameassembly全部静态链接成一个主程序,直接解决il2cppAPI暴露的问题 或者参考某三字厂商的方法: 这是原版Unity调用Gameassembly内il2cpp函数的流程,UnityPlayer加载Gameassembly以后用 LookupSymbol 从导入表里面取到每个il2cppapi的地址,然后放入UnityPlayer内的全局变量里面以供使用 加密il2cpp可以这样加密, Gameassembly 的导入表只暴露 il2cpp_get_table 函数,该函数会返回一个固定长度的数组,里面有些是真的il2cppapi地址,有些则是完全没用的垃圾地址, LoadIl2cpp 函数不再通过 LookupSymbol 一个一个解析il2cppapi,而是改成解析 il2cpp_get_table 传过来的数组,然后逐个填充到对应的全局变量里面(垃圾地址也要填充到全局变量里面,但是这些全局变量没有任何函数会使用它) 0x3 InitializeRuntimeMetadata metadataPointer可以进行一下额外的解密操作, GetStringLiteralFromIndex 整个函数里面可以加点xor等额外解密,然后用vmp全部vm掉 混淆过的差不多长这样 0x4 AssetBundle 最基础的玩法肯定是先把ab包读进来,然后进行解密操作,最后用 LoadFromStream 或者 LoadFromStreamAsync 把解密好的ab包交给UnityPlayer 如果有源代码,可以根据下面的图进行魔改,解压缩部分可以增加一个魔改过的lz4或者zstd, ReadHeader 部分可以把文件头打乱一下顺序,随机xor一些字段等等(我这没源代码,只能从二进制层面提供建议) 甚至可以完全丢掉AssetBundle,自己造个VFS,例如一个文件存index,一个文件存data。取对应的文件先对VFS内的路径名称计算hash,然后根据算出来的hash取index里面取到offset和size,然后再去data内拿到需要的部分,这样VFS里面完全没有任何可读的文件名,只有hash 自定义VFS的处理解密可以用Unity插件搞一个dll去处理,也可以写UnityPlayer里面,通过icall调用 0x5 lua字节码/js/hybridCLR Unity基本上用的是藤子的Xlua 可以改字节码proto的结构顺序 opcode的顺序也可以进行打乱 vm解释器部分也可以加点料 js好像没见到有人编译成jsc的,这里不讨论 hybridCLR可以往 TransformBodyImpl 里面加点料,给il字节码xor一下阻止ilspy的反编译 0x6 网络 proto可以用flatbuffers,flatbuffers的二进制文件内完全没有类型定义,不像protobuf能猜定义,然后可以把flatc生成出来的代码混淆一下 通信也可以魔改KCP,请求也加上ssl pinning 这部分研究的不算多 0xF 感觉加密的玩法也就那几种,以前没AI/AI性能不行的时候,简单的加密一下还是有用的,现在怕是不太行了( 2 个帖子 - 2 位参与者 阅读完整话题
0x01 前言 之前学习逆向的时候碰到了一大堆问题,然后逆向在网络上资源复杂,有些问题太简单可能根本没人提起,写这篇文章是为了记录使用IDA PRO的时候遇到的问题,方便自己及他人排查错误,由于新手入门,秉持着能用就行,所以解释不一定正确,如有错误,请各位大佬指正。(以及不知道wiki编辑怎么搞,有知道的大佬可以告诉我,将这个转成wiki编辑贴,供大家填坑,修改格式等) 0x02 TIPS: IDA PRO可以用32bit版本,和64bit版本进行调试,用32bit版本调试时需要使用android_server开启服务,使用64bit版本进行调试时需要使用android_server64开启服务。 0x03: android_server版本问题 问题详情 : 在调试APK过程中中如果出现以下错误: (1)Can’t assign to Segment Register at D640CB20 (t=0001). Tring to recover-> OK 这个错误会不停弹窗,然后如果忽略继续下一步后,会发现程序无法调试,窗口中显示的都为%1,且程序正常运行后也在module窗口也看不到我们app的dex以及so文件。(如下图1、图2) (2)Module XXXXXXXXX.so has no names 即加载so文件后,双击模块找不到里面的函数(如下图3),且使用ctrl+s发现segment中为空(如下图4) 错误截图 : 解决办法 : 更换手机中的android_server版本,将android_server替换为android_server64,然后使用IDA PRO(64bit)进行调试。(如果使用32bit进行调试,可能会造成找不到函数以及segment为空的情况) 1 个帖子 - 1 位参与者 阅读完整话题
0x01 前言 一直想学习一下IDA PRO的动态调试,这样在逆向APP的时候,如果遇到突然的中断就可以一步一步调试,发现问题所在。但苦于模拟器坑太多,网上大多调试都只到jdb联通,至于后面的怎样定位到关键点,如何下断点,以及如何修改内存keypatch,大多都是零零散散的,写这篇文章也是首次进行动态调试SO成功,到关键点下断点,并修改相关内存指令得到想要的结果后的记录。笔者是小白入门,若本文有不正确的地方,欢迎大佬指正。 0x02 环境准备 Pixel 2 真机一部(需要root后的真机,如果不是真机,则使用jdb的时候可能会报jdb错误) IDA PRO (逆向软件) Android Studio (需要使用到里面的monitor做转发,当然也可以自己转发) java 8 (java8 自带jdb,最新版本java没有jdb了,所以如果找不到jdb可以手动进行安装) Native开发的APP一个 (逆向对象) 0x03 IDA PRO连接调试应用 (1)在IDA Pro的安装路径dbgsrv目录下找到android_server (android_server需要用ida.exe连接,用于调试32位程序,android_server64需要用ida64.exe链接,用于调试64位程序,笔者的程序so需要用64位的ida调试,所以下面的将用ida64.exe和android_server64用作演示) (2)将android_server64放入真机的/data/local/tmp路径下并赋权,以root身份运行,运行命令即截图如下 adb push android_server /data/local/tmp su cd /data/local/tmp chmod 755 android_server64 ./android_server64 (3)转发端口 adb forward tcp:23946 tcp:23946 (4)启动monitor,启动要调试的应用(被调试应用的Androidmanifest.xml文件中需要有debuggable=“true”,或者手机的ro.debuggable=1即所有应用可调试,否则无法进入调试模式),输入命令后可以看到monitor中对应app的包名旁边有个红色的小虫子,而且手机商进入了等待调试界面。 adb shell am start -D -n com.example.nativeapp/com.example.nativeapp.MainActivity (5)代开IDA PRO 32bit,进行附加进程 上一步点击ok后会弹出附加进程选择的框,里面有很多进程,可以用快捷键ctrl+F 进行搜索,然后选择自己要调试的进程,点击ok即可 出现以下界面表示IDA PRO已经连接上了,但是此时还无法调试,需要用jdb让程序继续运行 (6)打开DDMS查看端口号 (7)使用jdb进行附加,附加成功后可以看到ddms上的小虫会变成绿色 jdb -connect com.sun.jdi.SocketAttach:port=8600,hostname=localhost 如果报无法附加到VM,如下图,多半是用了模拟器,可以尝试下用真机。 至此IDA PRO已经成功连接到调试应用了,可以开始进行应用的调试了。 0x04 IDA PRO动态调试SO IDA连接上被调试应用后就可以开始调试了,可以按上方工具栏中的绿色按钮,或者快捷键F9,让程序继续执行,让APP继续运行起来。然后关注下方output窗口的输出,可以查看自己需要调试的SO是否被加载 比如运行到这儿,可以看到加载了我们app的so文件,如果我们需要在它运行前进行修改(例如绕过一些反调试,否则等函数运行起来后会自动终端我们的调试),那么此时就可以进入so,开始下断点,然后步调试。但是我们此次只需要修改程序运行时的返回结果,完全可以等他加载完后慢慢分析,所以我们可以不停的F9,直至程序全部加载完。 当上方的按钮变为灰色时候,表示程序已经完全加载了,可以看到手机界面,app的主界面也被加载出来。 现在我们可以边调试边运行程序了,比如我现在需要输入sn,点击提交,可以看到程序运行,返回failed。(在输入sn的时候,点击屏幕可能会没反应,这个时候可以回到ida界面看看运行按钮是否变为绿色,表示有程序运行,按下F9继续运行即可,然后就可以正常输入了) 由于提交的逻辑写在SO里,所以我们要查看SO,并修改SO的逻辑,使得我们输入错误的SN也能返回SO。可以在IDA右边的侧边栏Moudles窗口找到进行搜索,找到我们需要分析的so 双击SO,会弹出该函数的函数列表,可在函数列表中找到对应 逻辑的函数checkSN,双击后左侧会跳至对应的so文件部分 可使用F5查看伪代码,原本这儿可以修改a1的类型为 JNIEnv* ,函数可以更加直观,动态调试的时候没法,可以再开一个窗口静态分析SO,梳理逻辑,此处由于篇幅,就不作详细说明了。根据分析逻辑后,可以判断出,该函数的校验逻辑为判断输入的值是否等于123456,因此我们修改的点可以在判断这儿。 光标点击 == 符号,然后按Tab键跳转到汇编语言,在CSET处用快捷键F2下断点,然后继续运行程序,程序会到断点处停住,此时可以F8单步调试,通过网上查询发现CSET的功能为: CSET W0, EQ ; if (cond == true) W0 = 1, else W0 = 0。(操作符如下:相等(EQ)、不等(NE)、小于(LT)、大于(GT)、小于或等于(LE)、大于或等于(GE)) 我们要将错误的返回为正确的,所以此处需要把相等,改为不等,点击下方HEX View窗口,右键把PC窗口的16进制同步过来准备修改 同步后可以看到 CSET W0, EQ对应的16进制为E0179F1A,现在我们需要把它修改为 CSET W0, NE 通过在线网页arm转化可查询到 CSET W0, NE的16进制码为E0079F1A 我们只需要修改第二组数17为07即可,单击Hex View窗口中对应的16进制数,按F2进入编辑模式,将17改为07后,按F2进行保存,即可看到对应的命令变为CSET W0, NE 继续运行程序,即可看到,应用成功返回success 0x05 结语 IDA PRO动态调试还有很多内容,目前只是很简单的一部分,还在挖掘中… 2 个帖子 - 2 位参与者 阅读完整话题
0x01 前言 当前网上对OpenWrt安装EasyTier的教程比较少,踩了很多坑,摸索了一天好歹是成功部署上了,使用起来十分的简单,因此记录一下,以便后续查找。 0x02 环境准备 路由器型号:Xiaomi Redmi Router AX6000 (aarch64_cortex-a53) 路由器操作系统:ImmortalWrt 21.02-SNAPSHOT 0x03 EasyTier包下载 (1)查看Openwrt的架构:进入终端,进行如下操作 cat /etc/os-release | grep ARCH # 输入后回显实例如下: # OPENWRT_ARCH="aarch64_cortex-a53" (2)下载EasyTier的Openwrt插件:luci-app-easytier,此插件需要自己Fork官网插件用github的actions进行编译(也可以直接用我编译好的: https://github.com/Devil-Ryu/luci-app-easytier/releases/tag/v2.3.2 ),流程如下: Fork后直接找到actions,然后run workflow就行 编译完成后,点击上面列表中的 Build-OpenWrt-EasyTier ,然后在列表里根据第一步查到的架构,直接选择对应的包下载就行(其中SNAPSHOT后缀的是apk安装包,openwrt-22.03的是ipk安装包) 下载的包里面有三个文件: luci-i18n-easytier-zh-cn_git-25.182.85440-d9d1c03_all.ipk (easytier中文插件,需要安装) luci-app-easytier_2.3.2_all.ipk (easytier openwrt插件,需要安装) easytier_2.3.2_aarch64_cortex-a53.ipk (二进制包,在软件包里安装,这个和下面的二进制文件二选一就行) (3)下载EasyTier二进制文件zip[和上面二进制文件ipk二选一] 进入 官网 根据自己的硬件架构,选择对应zip包,比如我的是aarch64,下载下来的包就是: easytier-linux-aarch64-v2.3.2.zip 0x04 OpenWrt安装EasyTier 进入OpenWrt,分别上传 luci-app-easytier_2.3.2_all.ipk , luci-i18n-easytier-zh-cn_git-25.182.85440-d9d1c03_all.ipk (文件名不需要完全一样,前面差不多就行,后面是版本号,每个版本有差异) 上传完软件包后,刷新页面,即可看到EasyTier 然后进入EasyTier,上传二进制文件: easytier-linux-aarch64-v2.3.2.zip 至此,EasyTier插件已经完整的安装到了OpenWrt上 0x05 EasyTier的配置 (1)EasyTier基础配置 此处,我选择用GUI界面管理EasyTier,因此我配置中 启动方式 选择了 Web配置 ,并且需要启用下面的 自建Web服务 ,如不用GUI界面,也可选择其他选项。 配置完后,点击右下方的保存并应用,使得EasyTier启用 (2)本地注册EasyTier账号 启用后,点击 Web控制台 进入EasyTier的GUI界面,进行配置,先点Register进行注册,用户名,需要和 EasyTier配置-Web服务地址 中连接上的用户名保持一致,否则进入后将无法看到EasyTier节点。 注意,如果开启了EasyTier的自建Web服务,那么每次重启EasyTier的时候,EasyTier会自动在防火墙新开几个端口,其中Web页面的11211端口也会对外开放,如果你的路由器有公网IP,建议将这两个取消,然后保存,这样就只有本地才能访问到自建的Web服务,也就是上述登陆的页面。 (3)创建网络 使用刚刚创建的账号密码登录后,即可进入设备列表,点击右边的齿轮,进行网络创建 此处我是有公网IP,且该设备不用加入其余客户端的子网,因此在网络方式中选择 独立 ,若没有公网IP,可选择 公共服务器(默认使用官网节点) ,若有其他服务器,也可选择 手动 按照上述创建后,用其他客户端就能用10.0.0.1(或者你自己设置的其他虚拟IP来访问这台机器了) (4)开启子网访问功能 [可选] 要想其他设备加入该设备后,能访问该设备下的子网,需要在刚刚创建的网络中,展开下面的高级设置,选择系统转发,并添加子网网段 (5)开启WireGuard连接功能 [可选] 如需启用WireGuard连接,现在高级设置里,开启VPN Portal,然后输入随便一个网段,和端口然后运行服务 如需从外网访问,还需去防火墙新增一个通信规则,放开此端口 0x05 客户端加入子网 (1)使用EasyTier加入子网 全平台的GUI客户端都差不多长一个样,这边以macos的客户端为例 建议在高级设置中手动输入设备名称,方便查看加入的设备 然后点击运行即可加入到OpenWrt的网络中 此时可以用服务器上设置的虚拟IP访问到OpenWrt了,也可以通过子网IP如192.168.x.x 访问OpenWrt以及对应的内网服务 (2)使用WireGuard加入子网 前提:对端(即服务端)已经开启了WireGuard连接功能,可参考 0x05 EasyTier的配置->开启WireGuard连接功能 首先到服务端上查看WireGuard配置: 复制WireGuard配置并修改对应值 例如我复制到WireGuard配置如下 然后也能正常访问到内网 PS:WireGuard配置完后,很多时候立即连接会连不上服务器,不知道是怎么回事,等一会儿,或者重启一下客户端可能就好了,比如我写这个文章的时候也半天连不上,然后过了不断停用启用,过了一会就能连上了。。。。。 (创作不易,如果觉得对你有帮助的话点个关注或者赞吧~) 1 个帖子 - 1 位参与者 阅读完整话题
Easytier异地组网,内网相互访问 0x01 前言 之前给家里的路由器(Openwrt)部署了Easytier,使得其余设备在外面很方便就能连上内网,本来一直说组一个异地组网,让异地的内网进行互通,一直没进行实践,正好最近兄弟有需求,就研究了一下,由于非专业人士,所有中间还是遇到一些小坑,记录一下,方便以后查找。 0x02 异地组网拓扑图 Easytier官网其实是有说明如何异地组网的,原文链接可查看 网对网 ,原文拓扑图如下,可参考 完成网对网配置后,双方子网中的设备,可不用单独安装Easytier客户端就能访问到对方子网中的设备。 0x03 组网必要条件 公共或者私有Easytier节点(重点!!!,两个节点的Easytier,必须使用公共或者私有节点进行加入才能成功) 节点A部署Easytier,并代理自己子网 节点B部署Easytier,并代理自己子网 0x04 组网流程 (1)创建私有节点网络 [可选] 如果你有公网IP,不想使用公共节点,可以在其中一个Easytier上创建一个私有节点网络(需要通过公网IP能够访问到该节点的端口,否则其余节点无法加入),此处假设在节点A处创建一个私有的节点网络,直接进入Easytier配置页面,点击新建网络,其配置如下(主要是将网络方式选择为独立,然后设置一个强一点网络名称和密码,防止其他人加入该节点): 创建网络后记得点运行!!! (2)节点A配置 注意,如果你是在某个节点部署两个Easytier网络,启用了两个监听服务,对于多出来的那个监听服务,需要你单独去开一下防火墙开一下策略,否则互联网无法访问,以及创建网络后记得点运行!!! (3)节点B配置 基本配置和节点A一样,如果是私有节点,注意一下节点端口就行 创建网络后记得点运行!!! (4)访问内网 配置完后,就可以快乐地访问兄弟的内网了~ 1 个帖子 - 1 位参与者 阅读完整话题
[!Error] 本贴仅研究壳子本身,不涉及游戏内容,请勿在游戏内进行作弊行为! 0x0 《内核级反作弊》 《请输入文本》 0x1 日志 参考了别的佬的文档 gist.github.com https://gist.github.com/WitherOrNot/0c2974be82393265aa5fb8f82be1f0a1 htpec.md # Notes These are very disorganized because I wrote these as I reversed various bits and pieces. If I'm wrong about something, please let me know so I can forget to update this. ## Logging For me this was the Achilles' heel, Crackproof creates a debug log if a certain folder in `%temp%` is present. The folder name is 12 hex characters long, and different between executables. The easiest way to find it is to break on/hook `CreateFileW`. Once you create it, any Crackproofed modules will spit out logs as they unpack. Lines contain status codes, indicating roughly what the unpacker is doing at a given time (see below). Lines with additional debug information are also included, sometimes they can be very handy. 此文件已被截断。 显示原始文件 对kernelbase.CreateFileW下断不难发现壳子在检查存放日志的文件夹是否存在,并且还会检查文件夹创建时间是否超过2天,否则不保存日志 创建文件夹以后正常启动一次游戏可以抓出以下的日志: C:\priconner\sample\PrincessConnectReDive.exe -CF -C2 -E2 -CC -T12 -RC3 -GWH -DA -DD -PP2 -EDD -I -EL5 -CK2 -CD1 -CD2 -CD3 -CD4 -CD5 -EVS -DE -DEP1 -DC -PD -NCP -NCP2 -NC -NE -NCC2 -NRC -NDA3 -NDDE -NEL -NEL2 -NEL3 -NEL4 -NELA -NERR -NWEB -NGMD 2026/04/18 23:56:10.197 00000001`40000000 200 000 00001000 00000000 ._ 410 510 520 540 560 2026/04/18 23:56:12.083 561 C00 001 01A06658 01A037AB C01 001 0003 0003 0000 0000 C02 001 Htsysm1B4001 002 1 2 PrincessConnectRedive64_.sys C03 002 BCAB405E 36950000 03E8 003 PrincessConnectRedive64_.sys 004 0F000 C04 005 000005A0 000005E8 000005E0 003 03 00007FFC`21A9F7D0 ntdll.dll!LdrLoadDll A09 A0F A08 009 1 A07 002 01 00 5D0 552 570 00C 005F 00D 0000 0004 0000 0002 0002 0000 0000 010 00000001`400AB760 590 5B0 5B1 598 5A0 A06 5C0 5E1 5E2 610 640 655 6E1 800 001 00000001`400BB000 810 820 840 002 00000001`40052010 00000001`400B8D50 00000001`400B8C20 001 04F0 6E2 E20 014 003D20 1000 00000000`00000000 E40 00A 00000001`400C6800 000001A0 00B 0004 0002 0002 0001 0001 0000 0000 E52 E53 E54 E55 E59 660 280 2026/04/18 23:56:13.295 000-000-000 日志 解释 00000001`40000000 主exe的imagebase 200 壳子流程开始 000 00001000 00000000 ._ 映射外置的_RDATA段 410 开始反调试 510 检查某块内存的CRC32 520 检查NtQueryInformationProcess 540 检查是否存在VMWare后面 560 代码段解密初始化 561 选择加载子模块(新版本似乎已弃用 C00 检查Windows版本 001 01A06658 01A037AB 0x01A0+26200 = 01A06658,代表 Windows 11 25H2;0x01A0+14251 = 01A037AB,代表 Windows 10 Insider Preview Build 14251;也就是至少Windows 10才能运行 C01 检查 BCD 启动参数 001 0003 0003 0000 0000 意义不明 日志 解释 C02 安装驱动服务 001 Htsysm1B4001 驱动设备名称 002 1 2 PrincessConnectRedive64_.sys 1代表SERVICE_KERNEL_DRIVER,2代表SERVICE_AUTO_START,最后是驱动名称,在C:\Windows\System32文件夹下面 日志 解释 C03 NtLoadDriver 002 BCAB405E 36950000 03E8 意义不明 意义不明 驱动IOCTL返回值 003 PrincessConnectRedive64_.sys 驱动文件名 004 0F000 SizeOfImage 日志 解释 C04 安装hook(? 005 000005A0 000005E8 000005E0 意义不明 意义不明 意义不明 003 PrincessConnectRedive64_.sys 驱动文件名 03 03 00007FFC`21A9F7D0 ntdll.dll!LdrLoadDll LdrLoadDll所在地址 日志 解释 A09 反虚拟机,检测注册表路径里面是否以下面的字符串开头:Virtual,VMware,Bochs,VBOX,VRTUAL,Microsoft Hyper-V,Parallels(PD都检测是何意味) A0F 检查dll注入:AppInit_DLLs,User32.dll,apphelp.dll,ShimEng.dll(不检查dxgi,winhttp,version?????) A08 从磁盘拷贝干净的 ntdll/kernel32 代码到内存(hyperdbg:人尔女子) A07 杀注入线程 注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SystemInformation\SystemProductName HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\BIOS\SystemProductName HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\SystemBiosVersion 日志 解释 5D0 解密前置流程,handler为0x14005B694 552 解密前置流程,handler为0x140059AB5 570 解密前置流程,handler为0x14005A122 590 解密前置流程,handler为0x14005A5DC 5B0 解密前置流程,handler为0x14005A3E4 5B1 解密前置流程,handler为0x14005A728 598 解密前置流程,handler为0x14005AA0E 5A0 解密前置流程,handler为0x14005AAB3 A06 意义不明 5C0 运行时恢复模块的入口点(? 5E1 解密前置流程,handler为0x14005B483 5E2 解密前置流程,handler为0x14005B523 610 解密PE头 640 解密各个段 655 PE重定位 6E1 疑似收尾工作,似乎在重新加密部分text段 E55 检测openark驱动的设备名,检测到就自杀 E91 检测CE驱动的设备名,检测到就自杀 日志 解释 046-019-01F 内核驱动回调被禁用 048-012-002 检测到hyper-v虚拟机 601-000-008 检测到CE 0x2 动态解密 这部分仅针对公主连结Re:Dive DMM,Cygames就喜欢搞这种看似有用实际上完全没用的东西(笑 别的exe上面的crackproof没有这个功能,例如学园偶像大师DMM的内存就是正常的 以 00007FFA5E889000 为例,CE可以看到这里的内存属性为PAGE_NOACCESS 当CPU试图执行里面的指令就会触发异常 EXCEPTION_DEBUG_INFO: dwFirstChance: 1 ExceptionCode: C0000005 (EXCEPTION_ACCESS_VIOLATION) ExceptionFlags: 00000000 ExceptionAddress: gameassembly.00007FFA5E889000 NumberParameters: 2 ExceptionInformation[00]: 0000000000000008 DEP Violation ExceptionInformation[01]: gameassembly.00007FFA5E889000 Inaccessible Address 这里会调用 ntdll.KiUserExceptionDispatcher 处理异常 → ntdll.KiUserExceptionDispatcher 被壳 inline hook 00007FFB685E5AE0 E9 2B051000 jmp 00007FFB686E6010 跳到 ntdll .reloc 里面: 00007FFB686E6010 FF25 F2FFFFFF jmp qword ptr [00007FFB686E6008] [7FFB686E6008] 再跳到壳里面 → 7FF6AD977C00: ntdll.KiUserExceptionDispatcher hook dispatcher 7FF6AD977C00 8B0D 72210000 mov ecx, dword ptr [7FF6AD979D78] // 栈偏移 7FF6AD977C06 48 03 CC add rcx, rsp // rcx = rsp + offset 得到一个与当前异常恢复相关的结构指针,后续按 EXCEPTION_RECORD 布局读取。 7FF6AD977C09 48 83 EC 20 sub rsp, 20h 7FF6AD977C0D E8 AEDEFFFF call 7FF6AD975AC0 // 从异常记录里取 fault address 7FF6AD977C12 85 C0 test eax, eax 7FF6AD977C14 74 15 jz 7FF6AD977C2B 7FF6AD977C16 E8 F5DFFFFF call 7FF6AD975C10 // 处理异常 7FF6AD977C1B 85 C0 test eax, eax 7FF6AD977C1D 74 0B jz 7FF6AD977C2A 7FF6AD977C1F 48 83 C4 20 add rsp, 20h 7FF6AD977C23 48 8B CC mov rcx, rsp 7FF6AD977C26 33 D2 xor edx, edx 7FF6AD977C28 FF D0 call rax // 返回KiUserExceptionDispatcher 7FF6AD977C2A CC int3 7FF6AD977C2B E8 B0DFFFFF call 7FF6AD975BE0 7FF6AD977C30 48 83 C4 20 add rsp, 20h 7FF6AD977C34 FF E0 jmp rax // 返回KiUserExceptionDispatcher → 7FF6AD975AC0:从异常记录取 ExceptionAddress / ExceptionInformation[1] 7FF6AD975B0C 48 8B 77 28 mov rsi, qword ptr [rdi+28h] 7FF6AD975B10 48 8B 7F 10 mov rdi, qword ptr [rdi+10h] ... 7FF6AD975B41 8B CE mov ecx, esi 7FF6AD975B43 E8 98FDFFFF call 7FF6AD9758E0 ... 7FF6AD975BA4 48 8B D7 mov rdx, rdi 7FF6AD975BA7 48 8B CE mov rcx, rsi 7FF6AD975BAA E8 D1FEFFFF call 7FF6AD975A80 对应 EXCEPTION_RECORD 布局 ExceptionRecord + 0x10 = ExceptionAddress ExceptionRecord + 0x28 = ExceptionInformation[1] → 7FF6AD975A80:7FF6AD975910的wapper → 7FF6AD975910:定位 fault address 所属保护区域和页 7FF6AD975942 48 8D 44 24 30 lea rax, [rsp+30h] 7FF6AD975947 4C 8D 4C 24 68 lea r9, [rsp+68h] 7FF6AD97594C 4C 8D 44 24 60 lea r8, [rsp+60h] 7FF6AD975951 49 8B D4 mov rdx, r12 7FF6AD975954 48 8B CF mov rcx, rdi 7FF6AD975957 48 89 44 24 20 mov [rsp+20h], rax 7FF6AD97595C C7 44 24 60 0... mov dword ptr [rsp+60h], 0 7FF6AD975964 C7 44 24 68 0... mov dword ptr [rsp+68h], 0 7FF6AD97596C C7 44 24 30 0... mov dword ptr [rsp+30h], 0 7FF6AD975974 E8 F7F6FFFF call 7FF6AD975070 // 查找 fault address 属于哪个受保护区域 7FF6AD975979 48 8B 0D ... mov rcx, qword ptr [7FF6AD979D60] 7FF6AD975980 0F BA 69 04 1B bt dword ptr [rcx+4], 1Bh // 打印日志的开关 7FF6AD975985 48 8B D8 mov rbx, rax 7FF6AD975988 73 4F jnb 7FF6AD9759D9 7FF6AD9759D9 48 85 DB test rbx, rbx // 匹配到的区域描述符 7FF6AD9759DC 74 4B jz 7FF6AD975A29 7FF6AD9759DE 83 7C 24 60 00 cmp dword ptr [rsp+60h], 0 // 是是否需要解密 7FF6AD9759E3 74 44 jz 7FF6AD975A29 7FF6AD9759E5 FF15 ... call qword ptr [<&GetTickCount>] 7FF6AD9759EB 8905 ... mov dword ptr [7FF6AD979D50], eax ... 7FF6AD975A19 2B 7B 08 sub edi, dword ptr [rbx+8] 7FF6AD975A1C 48 8B CB mov rcx, rbx 7FF6AD975A1F C1 EF 0C shr edi, 0Ch 7FF6AD975A22 8B D7 mov edx, edi // edi = (fault_address - region_base) >> 12 得到 page index 7FF6AD975A24 E8 67F1FFFF call 7FF6AD974B90 // page handler → 7FF6AD975070:查找区域和页描述符 7FF6AD9750AA 44 8B 1D ... mov r11d, dword ptr [7FF6AD979D6C] // region count 7FF6AD9750C6 48 8D 0D ... lea rcx, [7FF6AD978D50] // region table loop: 7FF6AD9750D0 48 8B 11 mov rdx, qword ptr [rcx] 7FF6AD9750D3 4C 8B 42 08 mov r8, qword ptr [rdx+8] // region base 7FF6AD9750D7 49 3B D8 cmp rbx, r8 // fault < base? 7FF6AD9750DA 72 0C jb next 7FF6AD9750DC 48 63 42 10 movsxd rax, dword ptr [rdx+10h] // region size 7FF6AD9750E0 49 03 C0 add rax, r8 7FF6AD9750E3 48 3B D8 cmp rbx, rax // fault < base+size? 7FF6AD9750E6 72 39 jb found 找到所属区域后: 7FF6AD97514D 2B 5A 08 sub ebx, dword ptr [rdx+8] 7FF6AD975150 C1 EB 0C shr ebx, 0Ch // page index 7FF6AD975153 3B 5A 24 cmp ebx, dword ptr [rdx+24h] // page count 7FF6AD975158 48 63 42 20 movsxd rax, dword ptr [rdx+20h] // page table offset 7FF6AD97515C 8B CB mov ecx, ebx 7FF6AD97515E 48 C1 E1 04 shl rcx, 4 // page_desc size = 0x10 7FF6AD975162 48 03 C8 add rcx, rax 7FF6AD975165 48 03 4A 08 add rcx, qword ptr [rdx+8] // page_desc VA 7FF6AD975169 8B 01 mov eax, dword ptr [rcx] 7FF6AD97516B 0F BA E0 18 bt eax, 18h 7FF6AD975171 C1 E8 10 shr eax, 10h 7FF6AD975174 83 E0 01 and eax, 1 7FF6AD975177 89 45 00 mov dword ptr [rbp], eax 推断结构体: struct region_desc { uint32_t flags; // +0x04 也有全局/区域标志 uint64_t base; // +0x08 uint32_t size; // +0x10 ... uint32_t page_off; // +0x20 uint32_t page_count; // +0x24 HANDLE mapping; // +0x28 uint32_t decrypt_cnt; // +0x34 }; struct page_desc { uint32_t flags; // +0x00 uint32_t key_part; // +0x04 uint32_t last_tick; // +0x08 uint16_t hit_count; // +0x0C uint16_t checksum; // +0x0E }; → 7FF6AD974B90: 解密准备工作 7FF6AD974BC1 BF 00000100 mov edi, 10000h ... 7FF6AD974BEE 48 8B 4B 28 mov rcx, qword ptr [rbx+28h] 7FF6AD974BF2 41 8D 50 06 lea edx, [r8+6] 7FF6AD974BF6 FF15 ... call qword ptr [<&MapViewOfFile>] 7FF6AD974BFC 48 63 7B 20 movsxd rdi, dword ptr [rbx+20h] ... 7FF6AD974C08 49 8B E8 mov r12, rax // mapped view 通过 MapViewOfFile 映射待处理页的数据,保存在r12 7FF6AD974C0F 48 C1 E1 04 shl rcx, 4 7FF6AD974C13 48 03 F9 add rdi, rcx 7FF6AD974C16 48 03 7B 08 add rdi, qword ptr [rbx+8] page_desc = region_base + page_table_offset + page_index * 0x10 7FF6AD974C22 8B05 ... mov eax, dword ptr [7FF6AD979D50] 7FF6AD974C28 81 27 FFFF FEFF and dword ptr [rdi], 0FFFEFFFFh 7FF6AD974C2E 66 83 47 0C 01 add word ptr [rdi+0Ch], 1 7FF6AD974C33 89 47 08 mov dword ptr [rdi+8], eax 7FF6AD974C36 83 43 34 01 add dword ptr [rbx+34h], 1 意义不明 7FF6AD974C3A 8B C5 mov eax, ebp 7FF6AD974C3C 41 2B C6 sub eax, r14d 7FF6AD974C3F BA 00100000 mov edx, 1000h 7FF6AD974C44 48 63 F0 movsxd rsi, eax 7FF6AD974C47 8B 43 08 mov eax, dword ptr [rbx+8] 7FF6AD974C4A 44 8D 44 05 00 lea r8d, [rbp+rax] 7FF6AD974C4F 49 03 F4 add rsi, r12 7FF6AD974C52 44 33 47 04 xor r8d, dword ptr [rdi+4] 7FF6AD974C56 48 8B CE mov rcx, rsi 7FF6AD974C59 E8 52FBFFFF call 7FF6AD9747B0 key = (page_va_related_value + region_base_low32) ^ page_desc->key_part 7FF6AD974C96 0F BA 27 14 bt dword ptr [rdi], 14h 7FF6AD974C9A 73 48 jnb 7FF6AD974CE4 7FF6AD974C9C 45 8B C5 mov r8d, r13d 7FF6AD974C9F BA 00100000 mov edx, 1000h 7FF6AD974CA4 48 8B CE mov rcx, rsi 7FF6AD974CA7 E8 84FBFFFF call 7FF6AD974830 二次解密(? 7FF6AD974CE4 48 63 CD movsxd rcx, ebp 7FF6AD974CE7 4C 8D 4C 24 68 lea r9, [rsp+68h] 7FF6AD974CEC BA 00100000 mov edx, 1000h 7FF6AD974CF1 48 03 4B 08 add rcx, qword ptr [rbx+8] 7FF6AD974CF5 41 B8 20000000 mov r8d, 20h 7FF6AD974CFB C7 44 24 68 0... mov dword ptr [rsp+68h], 0 7FF6AD974D03 FF15 ... call qword ptr [<&VirtualProtect>] 把page权限改成可执行,然后清理现场 VirtualProtect(region_base + page_index_or_offset, 0x1000, PAGE_EXECUTE_READ, &oldProtect) → 7FF6AD9747B0: 主解密函数 7FF6AD9747BF 44 8B D8 mov ebx, r8d 7FF6AD9747C2 8B F2 mov esi, edx 7FF6AD9747C4 48 8B F9 mov rdi, rcx ... 7FF6AD9747DC C1 EE 02 shr esi, 2 7FF6AD9747DF 41 C1 E0 10 shl r8d, 10h 7FF6AD9747E3 33 D2 xor edx, edx 7FF6AD9747E5 44 33 C3 xor r8d, ebx 7FF6AD9747EA 45 8B C8 mov r9d, r8d loop: 7FF6AD9747F0 8B 0F mov ecx, dword ptr [rdi] 7FF6AD9747F2 44 03 C2 add r8d, edx 7FF6AD9747F5 83 C2 01 add edx, 1 7FF6AD9747F8 41 C1 C0 03 rol r8d, 3 7FF6AD9747FC 8B C1 mov eax, ecx 7FF6AD9747FE 48 83 C7 04 add rdi, 4 7FF6AD974802 41 33 C1 xor eax, r9d 7FF6AD974805 44 8B C9 mov r9d, ecx 7FF6AD974808 41 33 C0 xor eax, r8d 7FF6AD97480B 3B D6 cmp edx, esi 7FF6AD97480D 89 47 FC mov dword ptr [rdi-4], eax 7FF6AD974810 7C DE jl loop void decrypt(uint32_t *buf, uint32_t size, uint32_t key) { uint32_t count = size >> 2; uint32_t state = (key << 16) ^ key; uint32_t prev = state; for (uint32_t i = 0; i < count; i++) { uint32_t enc = buf[i]; state = rol32(state + i, 3); buf[i] = enc ^ prev ^ state; prev = enc; } } 0x3 过保护 停用 ProcessObCallback PRE 和 ProcessObCallback POST 内核回调就能随意attach/inject/dump了,想干啥就干啥(笑 0x4 前置解密就不研究了,隔着在里面block套block,解密出来一个block跳进去跑,再解密一个block出来再跳进去跑,还会把上一个block加密回去,各种间接跳转用的飞起,trace日志随随便便就1GB了,给我逆红温了,压力codex这货也看不明白 0xF 总结 非常垃圾的内核反作弊,完全过时的技术,只能看到吃老本的技术,看不到一点创新: 不检查PatchGuard,不检查Driver Signature Enforcement,不检查dll劫持,不检查堆栈回调,不过滤日志,混淆力度约等于0,隔壁ACE都在VT猛猛发力了,这玩意还在ring3吃老本 大名鼎鼎的 capcom.sys ( Htsysm72FB )驱动任意读写内核也是crackproof的《杰作》,允许任何进程运行带有未认证IOCTL的内核模式shellcode,内核里面还敢这样玩也是无敌了 1 个帖子 - 1 位参与者 阅读完整话题