Analyzing the mtop Device Risk-Control SDK - Jailbreak Detection, a VMP Layer, and Multi-Stage Encryption

About the author. I’m Colin Xiao — an independent reverse engineer, mostly working solo on contract jobs. I dig into compiled code of every kind, including but not limited to: Android and iOS apps, x86/x64/ARM native binaries, packers and obfuscators, DRM and license checks, network protocols and APIs, crypto and signature algorithms, malware, game binaries, and embedded/IoT firmware. I also handle large-scale data collection and vulnerability research. If you have any project in mind, I’d be glad to take it on — whatever it is, as long as it’s within my wheelhouse. Just reach out. You can reach me on X at @colinxiao_lab or on Telegram at https://t.me/ColinXiao666.

This research is published for educational and defensive purposes. The target sample is anonymized throughout.

mtop is the device risk-control SDK that sits as a gateway between a major Chinese e-commerce app’s mobile client and its backend, shielding a huge surface of APIs — product listings, ordering, payment, and so on. Reverse engineering it is worthwhile on three fronts:

  • Anti-protocol-cracking and anti-device-spoofing. Understanding how the risk-control layer collects device data, encrypts it, and signs requests is the core of the analysis. Knowing the crypto and the parameter-generation logic shows you how the anti-tamper / anti-spoofing / “legal request construction” mechanisms work.
  • Anti-scraping and anti-automation. Studying the mtop request flow reveals how the app throttles automated data collection and order generation.
  • Anti-bypass. Picking apart the risk-control logic exposes the conditions that trigger risk flags, and in doing so surfaces both potential bypass paths and the corresponding defensive lessons.

Tools and environment

Frida, Charles, IDA Pro 9.0. Mac mini running macOS 14.6.1, iPhone X on iOS 14.8.

Device-side execution flow

3.0 Capture

First, capture the request parameters:

On first launch the risk-control layer makes three requests; the first returns risk features plus a device id (eeid):

The returned data JSON carries dt — risk features plus the logic instructions that control algorithm changes — and the device id (eeid), among other fields:

{
        "cdnScriptUrl": "http://[redacted]/u6vr/g9m6/1gkepoi",
        "cfg": {
                "trust": {
                        "modifiedtime": 1606735713,
                        "v": 174084,
                        "type1": "{\"en\":0}"
                },
                "e1002": {
                        "modifiedtime": 1719282753,
                        "v": 400052,
                        "type1": "{\"e1002\":{\"p\":1,\"s\":true,\"c\":[{\"s\":\"9a85\",\"k\":\"47b0\"},{\"s\":\"82a0\",\"k\":\"51b6\"}],\"z\":1},\"e1011\":{\"p\":1,\"s\":true,\"c\":[{\"s\":\"c99e\",\"k\":\"9a1d\"},{\"s\":\"4337\"},{\"s\":\"f983\"},{\"s\":\"5f0d\"},{\"s\":\"9a66\"},{\"s\":\"9a85\",\"k\":\"47b0\"},{\"s\":\"75f8\",\"k\":\"d54f\"},{\"s\":\"7e2d\",\"k\":\"14ee\"},{\"s\":\"82a0\",\"k\":\"51b6\"}],\"z\":7}}"
                },
                "e1011": {
                        "modifiedtime": 1700535253,
                        "v": 400011,
                        "type1": "{\"e1011\":{\"p\":1,\"z\":7,\"s\":true,\"c\":[{\"k\":\"9a1d\",\"s\":\"c99e\"},{\"k\":null,\"s\":\"4337\"},{\"k\":null,\"s\":\"f983\"},{\"k\":null,\"s\":\"5f0d\"},{\"k\":null,\"s\":\"9a66\"},{\"k\":\"da1a\",\"s\":\"c7b1\"}]}}"
                },
                "e1000": {
                        "modifiedtime": 1719282754,
                        "v": 400107,
                        "type1": "{\"e1000\":{\"p\":0,\"s\":true,\"z\":1},\"e1011\":{\"p\":1,\"s\":true,\"c\":[{\"s\":\"c99e\",\"k\":\"9a1d\"},{\"s\":\"4337\"},{\"s\":\"f983\"},{\"s\":\"9a85\",\"k\":\"47b0\"},{\"s\":\"75f8\",\"k\":\"d54f\"},{\"s\":\"7e2d\",\"k\":\"14ee\"}],\"z\":7}}"
                },
                "ocrt": {
                        "modifiedtime": 1635995243,
                        "v": 400001,
                        "type1": "14.0"
                },
                "applist": {
                        "modifiedtime": 1583808665,
                        "v": 116009,
                        "type1": "com.360buy.jdmobile,com.xunmeng.pinduoduo,com.vipshop.iphone,com.tencent.mqq,com.tencent.ww,com.tencent.xin,com.baidu.map,com.tencent.sosomap,ctrip.com,com.tuniu.app,com.qunar.iphoneclient8,com.qiyi.iphone,com.tencent.live4iphone,com.ss.iphone.ugc.Aweme,com.wuba.zhuanzhuan,com.ss.iphone.article.News,com.meituan.itakeaway,com.dianping.dpscope,com.meituan.imeituan,com.mmp.mmp040608"
                },
                "sgpt": {
                        "modifiedtime": 1727261154,
                        "v": 400090,
                        "type1": "{\"o\":\"QgIAA3b7uxQAcDYAB6vaNgE/ABk2Aj8aHjYDPx9oNgQ/KTI4BT8zPDYGPz1GNgc/R1A2CD9RWjYJP1tkNgo/Zf82CxMBCJk2DBMCDZk2DRMDnJk2DhMECJk2DxMFnJk2EBMG3Jk2ERMHDZk2EhMIfZk2ExMJ3Jk2FBMKCJk2FRMLjjYWEwyONhcTDY42GBMOjjYZEw+ONhoTEI42GxMRjjYcExKONh0TE442HhMUjjYfExUTFhMXExgTGRMaExsTHBMdEx42IDQENiETHyETIDYiEyHumTYjNAQTIDQEEyLPBMAUBz4TAAdJB4gH8we7EyPAGA==\",\"s\":\"QgEAA3j7uwAANgAHSQeIB/MHuwc+NgI0AjYDc2MFc6gFc6oFc2UFc/Urc7EFc6QFNgQdAJ0HJygN+QQLVb8OEwPLNgUTBP4FDRMDNgYTBSETAjYHB6sTAhMGzwTAFBMAEwfAGA==\"}"
                },
                "bp": {
                        "modifiedtime": 1675837757,
                        "v": 400004,
                        "type1": "[{\"b\":0,\"o\":59607428}]"
                },
                "e1004": {
                        "modifiedtime": 1726738032,
                        "v": 400104,
                        "type1": "{\"e1011\":{\"p\":1,\"s\":true,\"c\":[{\"s\":\"4337\"},{\"s\":\"f53f\",\"k\":\"ea2f\"},{\"s\":\"2109\",\"k\":\"b9de\"},{\"s\":\"5f0d\"},{\"s\":\"9a66\",\"k\":\"0eb2\"},{\"s\":\"9a85\",\"k\":\"47b0\"},{\"s\":\"75f8\",\"k\":\"d54f\"},{\"s\":\"7e2d\",\"k\":\"14ee\"},{\"s\":\"82a0\",\"k\":\"51b6\"}],\"z\":7},\"e1004\":{\"p\":1,\"s\":true,\"c\":[{\"s\":\"f983\"},{\"s\":\"c99e\",\"k\":\"9a1d\"},{\"s\":\"4337\"},{\"s\":\"ad62\",\"k\":\"0141\"},{\"s\":\"7e2d\",\"k\":\"14ee\"},{\"s\":\"5f0d\"},{\"s\":\"9a66\",\"k\":\"0eb2\"},{\"s\":\"9a85\",\"k\":\"47b0\"},{\"s\":\"82a0\",\"k\":\"51b6\"}],\"z\":7}}"
                },
                "RConfig": {
                        "modifiedtime": 1728641375,
                        "v": 400262,
                        "type1": "{\"gtaop\":0,\"hevent\":2,\"switch\":{\"r_64_0\":0,\"rc\":0,\"mach2\":1,\"ihook\":1,\"r_61_0\":0,\"ulib\":0,\"ier\":1,\"lnk\":0,\"its\":1,\"ist\":0}}"
                },
                "RList": {
                        "modifiedtime": 1595903663,
                        "v": 135019,
                        "type1": "{\"v\":1,\"sp\":{\"AWZ.dylib\":1,\"NZT.dylib\":1,\"ALS.dylib\":1,\"rstweak.dylib\":1,\"YOY.dylib\":1,\"iGrimace.dylib\":1,\"hdfaker.dylib\":1,\"NewDevice.dylib\":1,\"HookDevice.dylib\":1,\"zzhardChange.dylib\":1,\"deviceInfoChange.dylib\":1,\"FakeTweak.dylib\":1,\"setmobile.dylib\":1,\"amg.dylib\":1,\"TEMain.dylib\":2,\"TweakEx.dylib\":2,\"tweaktest.dylib\":2,\"MAServiceEnEx.dylib\":2,\"SimulateTouch.dylib\":2,\"TSTweak.dylib\":2,\"XXScreenShot.dylib\":2,\"GPSCheat.dylib\":2,\"GPSTravellerTweakProX.dylib\":2,\"LocationChanger.dylib\":4,\"TEGPS.dylib\":4,\"txytweak.dylib\":4,\"txyfakegps.dylib\":4,\"OTRLocation.dylib\":4,\"altweak.dylib\":4},\"so\":{\"v\":1,\"l\":[[\"/Applications/Cydia.app\",\"/usr/sbin/frida-server\",\"/usr/lib/libjailbreak.dylib\",\"/jb/libjailbreak.dylib\"],[\"/Applications/iGrimace.app\",\"/Applications/NZT.app\",\"/Applications/hdFaker.app\"],[\"/Applications/TouchElf.app\",\"/Applications/AutoTouch.app\",\"/Applications/TouchSprite.app\",\"/Applications/handjingling.app\"],[\"/Applications/tianxiayou.app\",\"/Applications/TianXiaYou.app\",\"/Applications/anylocation.app\",\"/Applications/OTRLocation.app\"]]}}"
                },
                "dmtop": {
                        "modifiedtime": 1689046187,
                        "v": 400017,
                        "type1": "1"
                },
                "crpt": {
                        "modifiedtime": 1727261147,
                        "v": 400021,
                        "type1": "QgIAA3b7uxQAcDYAB6vaNgE/ABk2Aj8aHjYDPx9oNgQ/KTI2BT8zPDYGPz1GNgfsd/R1A2CD9RWjYJP1tkNgo/Zf82CxMBCJk2DBMCDZk2DRMDnJk2DhMECJk2DxMFnJk2EBMG3Jk2ERMHDZk2EhMIfZk2ExMJ3Jk2FBMKCJk2FRMLjjYWEwyONhcTDY42GBMOjjYZEw+ONhoTEI42GxMRjjYcExKONh0TE442HhMUjjYfExUTFhMXExgTGRMaExsTHBMdEx42IDQENiETHyETIDYiEyHumTYjNAQTIDQEEyLPBMAUBz4TAAdJB4gH8we7EyPAGA=="
                },
                "hash": {
                        "modifiedtime": 1583809627,
                        "v": 118007,
                        "type1": "{\"p\":0,\"z\":1,\"s\":true,\"c\":[{\"k\":\"f471\",\"s\":\"5a7a\"},{\"k\":\"0174\",\"s\":\"5a7a\"},{\"k\":\"c07a\",\"s\":\"6932\"},{\"k\":\"d79b\",\"s\":\"5a7a\"},{\"k\":\"db95\",\"s\":\"8c64\"}]}"
                },
                "bcud": {
                        "modifiedtime": 1669186615,
                        "v": 400007,
                        "type1": "1"
                }
        },
        "cmd": 1011,
        "eeid": "[redacted]",
        "rmdata": "[redacted]",
        "token": "[redacted]"
}

3.1 Risk detection

All three requests scan the device for risk features, named r_<digits>_<digits> (e.g. r_1_0). Collection is done primarily through svc syscalls:

__uvm_call_registry_llc_do_syscall_sub_1026F4850
__text:00000001048898DC                         svc_sub_1026CD8DC
__text:00000001048898DC
__text:00000001048898DC                         arg_0=  0
__text:00000001048898DC
__text:00000001048898DC F0 03 40 F9             LDR             X16, [SP,#arg_0]
__text:00000001048898E0 01 00 00 D4             SVC             0
__text:00000001048898E4 43 00 00 54             B.CC            locret_1048898EC
__text:00000001048898E8 7A 9B 00 14             B               sub_1048B06D0

Jailbreak risk features:

MEMORY:0000000124F46652 2F 4C 69 62 72 61 72 79…aLibraryMobiles_1 DCB "/Library/MobileSubstrate",0
MEMORY:0000000124F4666B 2F 41 70 70 6C 69 63 61…aApplicationsCy_0 DCB "/Applications/Cydia.app",0
MEMORY:0000000124F46683 2F 41 70 70 6C 69 63 61…aApplicationsSi DCB "/Applications/Sileo.app",0
MEMORY:0000000124F4669B 2F 76 61 72 2F 6A 62 2F…aVarJbApplicati DCB "/var/jb/Applications/Sileo-Nightly.app",0
MEMORY:0000000124F466C2 2F 76 61 72 2F 6A 62 2F…aVarJbApplicati_0 DCB "/var/jb/Applications/Sileo-Beta.app",0
MEMORY:0000000124F466E6 2F 76 61 72 2F 6A 62 2F…aVarJbApplicati_1 DCB "/var/jb/Applications/Cydia.app",0
MEMORY:0000000124F46705 2F 76 61 72 2F 6A 62 2F…aVarJbApplicati_2 DCB "/var/jb/Applications/Sileo.app",0
MEMORY:0000000124F46724 2F 41 70 70 6C 69 63 61…aApplicationsZe DCB "/Applications/Zebra.app",0
MEMORY:0000000124F4673C 2F 75 73 72 2F 6C 69 62…aUsrLibexecCydi DCB "/usr/libexec/cydia",0
MEMORY:0000000124F4674F 2F 75 73 72 2F 6C 69 62…aUsrLibexecZebr DCB "/usr/libexec/zebra",0
MEMORY:0000000124F46762 2F 75 73 72 2F 6C 69 62…aUsrLibexecFilz DCB "/usr/libexec/filza",0
MEMORY:0000000124F46775 2F 75 73 72 2F 6C 69 62…aUsrLibexecSubs DCB "/usr/libexec/substrated",0
MEMORY:0000000124F4678D 2F 75 73 72 2F 6C 69 62…aUsrLibexecSubs_0 DCB "/usr/libexec/substituted",0
MEMORY:0000000124F467A6 2F 65 74 63 2F 61 70 74…aEtcApt_1 DCB "/etc/apt",0
MEMORY:0000000124F467AF 2F 65 74 63 2F 64 70 6B…aEtcDpkg DCB "/etc/dpkg",0
MEMORY:0000000124F467B9 2F 65 74 63 2F 73 73 68…aEtcSsh DCB "/etc/ssh",0
MEMORY:0000000124F467C2 2F 4C 69 62 72 61 72 79…aLibraryTweakin DCB "/Library/TweakInject",0
MEMORY:0000000124F467D7 2F 75 73 72 2F 62 69 6E…aUsrBinCycript DCB "/usr/bin/cycript",0
MEMORY:0000000124F467E8 2F 75 73 72 2F 6C 69 62…aUsrLibLibjailb DCB "/usr/lib/libjailbreak.dylib",0
MEMORY:0000000124F46804 2F 75 73 72 2F 6C 69 62…aUsrLibLibhooke DCB "/usr/lib/libhooker.dylib",0
MEMORY:0000000124F4681D 2F 75 73 72 2F 6C 69 62…aUsrLibLibsubst DCB "/usr/lib/libsubstitute.dylib",0
MEMORY:0000000124F4683A 2F 75 73 72 2F 6C 69 62…aUsrLibTweakinj DCB "/usr/lib/TweakInject",0
MEMORY:0000000124F4684F 2F 75 73 72 2F 62 69 6E…aUsrBinDebugser DCB "/usr/bin/debugserver",0
MEMORY:0000000124F46864 2F 75 73 72 2F 6C 69 62…aUsrLibexecAfc2 DCB "/usr/libexec/afc2d",0
MEMORY:0000000124F46877 2F 75 73 72 2F 62 69 6E…aUsrBinSsh DCB "/usr/bin/ssh",0
MEMORY:0000000124F46884 2F 75 73 72 2F 62 69 6E…aUsrBinDpkg DCB "/usr/bin/dpkg",0
MEMORY:0000000124F46892 2F 75 73 72 2F 62 69 6E…aUsrBinAptKey DCB "/usr/bin/apt-key",0
MEMORY:0000000124F468A3 2F 75 73 72 2F 62 69 6E…aUsrBinCynject DCB "/usr/bin/cynject",0
MEMORY:0000000124F468B4 2F 75 73 72 2F 6C 6F 63…aUsrLocalBinDro DCB "/usr/local/bin/dropbear",0
MEMORY:0000000124F468CC 2F 65 6C 65 63 74 72 61…aElectraInjectC DCB "/electra/inject_criticald",0
MEMORY:0000000124F468E6 2F 76 61 72 2F 62 69 6E…aVarBinpackLoad DCB "/var/binpack/loaderd_hook",0
MEMORY:0000000124F46900 2F 4C 69 62 72 61 72 79…aLibraryPrefere DCB "/Library/PreferenceBundles/LibertyPref.bundle",0
MEMORY:0000000124F4692E 2F 4C 69 62 72 61 72 79…aLibraryPrefere_0 DCB "/Library/PreferenceBundles/ShadowPreferences.bundle",0
MEMORY:0000000124F46962 2F 4C 69 62 72 61 72 79…aLibraryPrefere_1 DCB "/Library/PreferenceBundles/ABypassPrefs.bundle",0
MEMORY:0000000124F46991 2F 4C 69 62 72 61 72 79…aLibraryPrefere_2 DCB "/Library/PreferenceBundles/FlyJBPrefs.bundle",0
MEMORY:0000000124F469BE 2F 4C 69 62 72 61 72 79…aLibraryPrefere_3 DCB "/Library/PreferenceBundles/HestiaPrefs.bundle",0
MEMORY:0000000124F469EC 2F 4C 69 62 72 61 72 79…aLibraryPrefere_4 DCB "/Library/PreferenceBundles/KernBypassPrefs.bundle",0
MEMORY:0000000124F46A1E 2F 4C 69 62 72 61 72 79…aLibraryPrefere_5 DCB "/Library/PreferenceBundles/Avatar.bundle",0
MEMORY:0000000124F46A47 2F 65 74 63 2F 70 72 6F…aEtcProfileDCor DCB "/etc/profile.d/coreutils.sh",0
MEMORY:0000000124F46A63 2F 2E 69 6E 73 74 61 6C…aInstalledUnc0v DCB "/.installed_unc0ver",0
MEMORY:0000000124F46A77 2F 70 72 69 76 61 74 65…aPrivateVarMobi DCB "/private/var/mobile/staged_system_apps",0
MEMORY:0000000124F46A9E 2F 70 72 69 76 61 74 65…aPrivateVarMobi_0 DCB "/private/var/mobile/mobile",0
MEMORY:0000000124F46AB9 2F 64 65 76 2F 66 61 6B…aDevFakevar DCB "/dev/fakevar",0
MEMORY:0000000124F46AC6 2F 74 6D 70 2F 76 6E 6F…aTmpVnodememTxt DCB "/tmp/vnodeMem.txt",0
MEMORY:0000000124F46AD8 2F 75 73 72 2F 6C 69 62…aUsrLibEllekitM DCB "/usr/lib/ellekit/MobileSafety.dylib",0
MEMORY:0000000124F46AFC 2F 76 61 72 2F 6A 62 2F…aVarJbUsrLibTwe DCB "/var/jb/usr/lib/TweakInject",0
MEMORY:0000000124F46B18 2F 76 61 72 2F 6A 62 2F…aVarJbUsrLibEll DCB "/var/jb/usr/lib/ellekit/MobileSafety.dylib",0
MEMORY:0000000124F46B43 2F 76 61 72 2F 6A 62 2F…aVarJbLibraryMo DCB "/var/jb/Library/MobileSubstrate/DynamicLibraries",0
MEMORY:0000000124F46B74 2F 76 61 72 2F 6A 62 2F…aVarJbInstalled DCB "/var/jb/.installed_dopamine",0
MEMORY:0000000124F46B90 2F 76 61 72 2F 6A 62 2F…aVarJbBasebinJb DCB "/var/jb/basebin/jbctl",0
MEMORY:0000000124F46BA6 2F 76 61 72 2F 6A 62 2F…aVarJbUsrLibTwe_0 DCB "/var/jb/usr/lib/TweakLoader.dylib",0
MEMORY:0000000124F46BC8 2F 76 61 72 2F 6A 62 2F…aVarJbPrepBoots DCB "/var/jb/prep_bootstrap.sh",0
MEMORY:0000000124F46BE2 2F 65 74 63 2F 72 63 2E…aEtcRcDLibhooke DCB "/etc/rc.d/libhooker",0
MEMORY:0000000124F46BF6 2F 76 61 72 2F 6A 62 2F…aVarJbEtcRcDLib DCB "/var/jb/etc/rc.d/libhooker",0
MEMORY:0000000124F46C11 2F 41 70 70 6C 69 63 61…aApplications DCB "/Applications",0
MEMORY:0000000124F46C1F 2F 4C 69 62 72 61 72 79…aLibraryRington DCB "/Library/Ringtones",0
MEMORY:0000000124F46C32 2F 4C 69 62 72 61 72 79…aLibraryWallpap DCB "/Library/Wallpaper",0
MEMORY:0000000124F46C45 5F 4D 53 53 61 66 65 4D…aMssafemode DCB "_MSSafeMode",0
MEMORY:0000000124F46C51 73 75 62 73 74 69 74 75…aSubstitute DCB "substitute",0
MEMORY:0000000124F46C5C 4A 42 52 4F 4F 54 00    aJbroot DCB "JBROOT",0
MEMORY:0000000124F46C63 4A 42 52 41 4E 44 00    aJbrand DCB "JBRAND",0
MEMORY:0000000124F46C6A 4A 42 5F 52 4F 4F 54 5F…aJbRootPath DCB "JB_ROOT_PATH",0
MEMORY:0000000124F46C77 4A 42 5F 53 41 4E 44 42…aJbSandboxExten DCB "JB_SANDBOX_EXTENSIONS",0
MEMORY:0000000124F46C8D 63 79 64 69 61 3A 2F 2F…aCydiaInstalled DCB "cydia://installed",0
MEMORY:0000000124F46C9F 73 69 6C 65 6F 3A 2F 2F…aSileo DCB "sileo://",0
MEMORY:0000000124F46CA8 7A 62 72 61 3A 2F 2F 00 aZbra DCB "zbra://",0
MEMORY:0000000124F46CB0 66 69 6C 7A 61 3A 2F 2F…aFilza DCB "filza://",0
MEMORY:0000000124F46CB9 61 63 74 69 76 61 74 6F…aActivator DCB "activator://",0

Frida / device-spoofing detection:

MEMORY:000000012779091A aApplicationsIg DCB "/Applications/iGrimace.app",0
MEMORY:0000000127790935 aApplicationsNz DCB "/Applications/NZT.app",0
MEMORY:000000012779094B aApplicationsHd DCB "/Applications/hdFaker.app",0
MEMORY:0000000127790965 aApplicationsMo DCB "/Applications/MobileAnjian.app",0
MEMORY:0000000127790984 aApplicationsTo DCB "/Applications/TouchElf.app",0
MEMORY:000000012779099F aApplicationsAu DCB "/Applications/AutoTouch.app",0
MEMORY:00000001277909BB aApplicationsTo_0 DCB "/Applications/TouchSprite.app",0
MEMORY:00000001277909D9 aApplicationsTo_1 DCB "/Applications/TouchSpritePe.app",0
MEMORY:00000001277909F9 aApplicationsHa DCB "/Applications/handjingling.app",0
MEMORY:0000000127790A18 aApplicationsTi DCB "/Applications/tianxiayou.app",0
MEMORY:0000000127790A35 aApplicationsTi_0 DCB "/Applications/TianXiaYou.app",0
MEMORY:0000000127790A52 aApplicationsAn DCB "/Applications/anylocation.app",0
MEMORY:0000000127790A70 aApplicationsOt DCB "/Applications/OTRLocation.app",0
MEMORY:00000002822B0480 aApplicationsCy_1 DCB "/Applications/Cydia.app",0
MEMORY:00000002822B04A0 aUsrSbinFridaSe DCB "/usr/sbin/frida-server",0
MEMORY:0000000283671170 aLibraryMobiles_2 DCB "/Library/MobileSubstrate/MobileSubstrate.dylib",0
"/Library/LaunchDaemons/re.frida.server.plist"

There’s more besides — dump detection, re-signing, injection, frida, hooking, and so on. The three ways the SDK collects device information:

3.2 Device collection

Objective-C method collection:

UTDevice
ONI_FindClass
utdid
ONI_GetStaticMethodID
ONI_CallStaticObjectMethod
ONI_GetStringUTFcString

C function collection:

open、read、opendir readdir, etc.

Custom-method collection (via svc syscalls):

llc_do_syscall  0x0000000000000152   SYS_stat64
__text:00000001048898DC                         svc_sub_1026CD8DC
__text:00000001048898DC
__text:00000001048898DC                         arg_0=  0
__text:00000001048898DC
__text:00000001048898DC F0 03 40 F9             LDR             X16, [SP,#arg_0]
__text:00000001048898E0 01 00 00 D4             SVC             0
__text:00000001048898E4 43 00 00 54             B.CC            locret_1048898EC
__text:00000001048898E8 7A 9B 00 14             B               sub_1048B06D0

MEMORY:000000011553502C 2F 76 61 72 2F 6D 6F 62+aVarMobileMedia DCB "/var/mobile/Media/DCIM/100APPLE",0
MEMORY:000000011553504C 2F 53 79 73 74 65 6D 2F+aSystemLibraryP DCB "/System/Library/Pearl/ReferenceFrames/reference-sparse.plist",0
MEMORY:0000000115535089 2F 53 79 73 74 65 6D 2F+aSystemLibraryP_0 DCB "/System/Library/Pearl/ReferenceFrames/reference-dense.plist",0
MEMORY:00000001155350C5 2F 53 79 73 74 65 6D 2F+aSystemLibraryP_1 DCB "/System/Library/Pearl/ReferenceFrames/reference-sparseLP.plist",0

// format string for collected content
%ld%c %ld.%ld%c

3.3 VMP, briefly

a. VM entry:

__text:000000010732D1D0                 STP             X29, X30, [SP,#-0x10+var_s0]!
__text:000000010732D1D4                 MOV             X29, SP
__text:000000010732D1D8                 SUB             SP, SP, #0x100
__text:000000010732D1DC                 STP             X20, X19, [SP,#0x100+var_70]
__text:000000010732D1E0                 STP             X22, X21, [SP,#0x100+var_80]
__text:000000010732D1E4                 STP             X24, X23, [SP,#0x100+var_90]
__text:000000010732D1E8                 STP             X26, X25, [SP,#0x100+var_A0]
__text:000000010732D1EC                 STP             X28, X27, [SP,#0x100+var_B0]
__text:000000010732D1F0                 STP             X15, X14, [SP,#0x100+var_C0]
__text:000000010732D1F4                 STP             X13, X12, [SP,#0x100+var_D0]
__text:000000010732D1F8                 STP             X11, X10, [SP,#0x100+var_E0]
__text:000000010732D1FC                 STP             X9, X8, [SP,#0x100+var_F0]
__text:000000010732D200                 MOV             X26, X0
__text:000000010732D204                 MOV             X28, X1
__text:000000010732D208                 MOV             X19, X2
__text:000000010732D20C                 MOV             X27, X19
__text:000000010732D210                 MOV             X24, X4
__text:000000010732D214                 MOV             X20, X5
__text:000000010732D218                 MOV             X25, X6
__text:000000010732D21C                 ADD             X21, X24, #0x100
__text:000000010732D220                 MOV             X22, #0
__text:000000010732D224                 MOV             X23, #0
__text:000000010732D228                 MOV             X23, X27
__text:000000010732D22C                 ADD             X27, X27, X3,LSL#4
__text:000000010732D230                 LDR             W8, [X27]
__text:000000010732D234                 LDR             X8, [X20,X8,LSL#3]
__text:000000010732D238                 STR             X27, [X28,#8]
__text:000000010732D23C                 BR              X8

b. VM exit:

_text:000000010732D328                 LDR             X11, [X24,#0xF0]
__text:000000010732D32C                 LDP             X9, X10, [X24,#0xC0]
__text:000000010732D330                 STP             X9, X10, [X24,#0x40]
__text:000000010732D334                 LDP             X9, X10, [X24,#0xD0]
__text:000000010732D338                 STP             X9, X10, [X24,#0x50]
__text:000000010732D33C                 LDP             X9, X10, [X24,#0xE0]
__text:000000010732D340                 STP             X9, X10, [X24,#0x60]
__text:000000010732D344                 LDR             X9, [X24,#0xF8]
__text:000000010732D348                 STR             X9, [X24,#0x78]
__text:000000010732D34C                 MOV             X23, X22
__text:000000010732D350                 LDP             X9, X10, [X11]
__text:000000010732D354                 STP             X9, X10, [X24,#0x80]
__text:000000010732D358                 LDP             X9, X10, [X11,#0x10]
__text:000000010732D35C                 STP             X9, X10, [X24,#0x90]
__text:000000010732D360                 LDP             X9, X10, [X11,#0x20]
__text:000000010732D364                 STP             X9, X10, [X24,#0xA0]
__text:000000010732D368                 LDP             X9, X10, [X11,#0x30]
__text:000000010732D36C                 STP             X9, X10, [X24,#0xB0]
__text:000000010732D370                 LDP             X9, X10, [X11,#0x40]
__text:000000010732D374                 STP             X9, X10, [X24,#0xC0]
__text:000000010732D378                 LDP             X9, X10, [X11,#0x50]
__text:000000010732D37C                 STP             X9, X10, [X24,#0xD0]
__text:000000010732D380                 LDP             X9, X10, [X11,#0x60]
__text:000000010732D384                 STP             X9, X10, [X24,#0x70]
__text:000000010732D388                 LDP             X9, X10, [X11,#0x70]
__text:000000010732D38C                 STP             X9, X10, [X24,#0xF0]
__text:000000010732D390                 LDP             X9, X10, [X11,#0x80]
__text:000000010732D394                 STP             X9, X10, [X24,#0x30]
__text:000000010732D398                 LDR             X22, [X11,#0x78]
__text:000000010732D39C                 STR             X11, [X24,#0x70]
__text:000000010732D3A0                 LDR             X9, [X24,#0x78]
__text:000000010732D3A4                 ADD             X27, X9, #0x10
__text:000000010732D3A8                 LDR             W8, [X27]
__text:000000010732D3AC                 LDR             X8, [X20,X8,LSL#3]
__text:000000010732D3B0                 STR             X27, [X28,#8]
__text:000000010732D3B4                 BR              X8

c. Handlers.

There are about 70 handlers; most basic instructions are emulated. The handlers themselves aren’t obfuscated, so it’s fairly easy to see which instruction each one simulates:

__text:000000010732D908 EOR_sub_1026C9908
__text:000000010732D908                 LDRB            W1, [X27,#5]
__text:000000010732D90C                 LDRB            W2, [X27,#6] ; load vm register indices
__text:000000010732D910                 LDR             X1, [X24,X1,LSL#3]
__text:000000010732D914                 LDR             X2, [X24,X2,LSL#3]
__text:000000010732D918                 LDRB            W0, [X27,#7]
__text:000000010732D91C                 EOR             X1, X1, X2 ; eor
__text:000000010732D920                 AND             X1, X1, #0xFFFFFFFF
__text:000000010732D924                 STR             X1, [X24,X0,LSL#3]
__text:000000010732D928                 LDR             W8, [X27,#0x10]!
__text:000000010732D92C                 LDR             X8, [X20,X8,LSL#3]
__text:000000010732D930                 STR             X27, [X28,#8]
__text:000000010732D934                 BR              X8


__text:000000010697AA30                               ; r9, r25, r27
__text:000000010697AA30
__text:000000010697AA30                               _ADD_sub_10B2CAA30
__text:000000010697AA30 61 17 40 39                   LDRB            W1, [X27,#5]
__text:000000010697AA34 62 1B 40 39                   LDRB            W2, [X27,#6]  ; load vm register indices
__text:000000010697AA38 01 7B 61 F8                   LDR             X1, [X24,X1,LSL#3]
__text:000000010697AA3C 02 7B 62 F8                   LDR             X2, [X24,X2,LSL#3]
__text:000000010697AA40 60 1F 40 39                   LDRB            W0, [X27,#7]
__text:000000010697AA44 21 00 02 8B                   ADD             X1, X1, X2
__text:000000010697AA48 01 7B 20 F8                   STR             X1, [X24,X0,LSL#3]
__text:000000010697AA4C 68 0F 41 B8                   LDR             W8, [X27,#0x10]! ; handle index
__text:000000010697AA50 88 7A 68 F8                   LDR             X8, [X20,X8,LSL#3]
__text:000000010697AA54 9B 07 00 F9                   STR             X27, [X28,#8]
__text:000000010697AA58 00 01 1F D6                   BR              X8            ; index
__text:000000010697AA58

3.4 Encryption flow

After device data is collected, it’s encrypted for upload. The flow is complex: single-field encryption, per-segment encryption, and whole-payload encryption — and each segment uses a different algorithm. I’ll outline the flow; the details are an exercise.

Take MAC address collection as an example. The raw data:

00000002817806A0  37 38 3A 39 31 3A 32 33  3A 34 35 3A 36 33 3A 34  78:91:23:45:63:4
00000002817806B0  35

First layer

a. Generate a random number as the key:

00000319

b. First-layer encryption, byte-by-byte:

key "00000319" index 5 -> 0000000000000033
000000000000003A ADD 0000000000000033 = 000000000000006D
000000000000006D ADD FFFFFFFFFFFFFFC0 = 000000000000002D
000000000000002D ADD 0000000000000020 = 000000000000004D  (encrypted)

Second layer

a. Fixed key:

02 00 00 00 00 00 00 00

b. Encryption:

length 000000000000000B AND 0000000000000003 = 0000000000000003
02 00 00 00 00 00 00 00 // index into the key (0x3) -> 0000000000000000
0000000000000000 EOR 0000000000000040 = 0000000000000040 // xor
// combined with a fixed field-key name
35 33 66 62 34 39 33 32  59 3C 5E 40 00 00 00 00  53fb4932Y<^@....

c. All fields are then combined and concatenated together.

Third layer

a. The combined device data is split into groups for encryption:

// combined device data xor
00000000536D7261 XOR 000000000AAE8E7A = 0000000059C3FC1B
000000000017473D ORR 0000000005400000 = 000000000557473D
000000000000074F XOR 0000000005574072 = 000000000557473D
00000000000BA39E ORR 0000000082A00000 = 0000000082ABA39E
00000000596D5721 XOR 0000000082ABA39E = 00000000DBC6F4BF
000000000015D1CF ORR 0000000041400000 = 000000004155D1CF
0000000000000011 XOR 000000004155D1CF = 000000004155D1DE
00000000000AE8E7 ORR 00000000A0A00000 = 00000000A0AAE8E7
0000000064656362 XOR 00000000A0AAE8E7 = 00000000C4CF8B85
00000000C4CF8B85 LSR 000000000000000A = 00000000003133E2
0000000005574072 LSL 0000000000000016 = 000000001C800000
00000000003133E2 ORR 000000001C800000 = 000000001CB133E2
0000000059C3FC1B LSR 000000000000000A = 00000000001670FF
00000000DBC6F4BF LSL 0000000000000016 = 000000002FC00000
000000002FC00000 ORR 00000000001670FF = 000000002FD670FF
0000000005574072 LSR 000000000000000A = 00000000000155D0
000000004155D1DE LSL 0000000000000016 = 0000000077800000
0000000077800000 ORR 00000000000155D0 = 00000000778155D0
00000000DBC6F4BF LSR 000000000000000A = 000000000036F1BD
00000000C4CF8B85 LSL 0000000000000016 = 00000000E1400000
00000000E1400000 ORR 000000000036F1BD = 00000000E176F1BD

b. Segments are typed differently:

0x16、0x17、0x18、0x15、0x14

Each type encrypts slightly differently.

c. After each segment is encrypted, they’re combined and XORed with a random number.

d. Base64-encoded, then combined with a fixed string (v0001ipx234001).

Fourth layer

a. Wrap the encrypted data into JSON:

String es = v0001ipx234001 + Base64.encodeToString(encBytes);
JsonObject jsonet = new JsonObject();
jsonet.addProperty("es", es);

b. Compress the combined JSON.

c. AES-encrypt the compressed data.

d. Base64-encode the AES output and send it as the request body.

Wrap-up

All told, the mtop risk-control SDK has strong code protection. The signing algorithm and the local encryption pipeline are complex, the cost of protocol recovery is high, and the algorithm logic is dynamically pushed from the server. From an attacker’s perspective, a device-spoofing approach is probably the cheaper route.

Still, there are solid defensive takeaways worth stealing:

a. Common libc string functions (strlen, strcpy, memset, etc.) are re-implemented inside the VMP.

b. The SDK manages its own memory structures.

c. The VM flow is obfuscated, with junk operations unrelated to the real logic mixed in.

d. Internal methods are called dynamically; their addresses are stored encrypted and decrypted at call time.

e. Collected fields are split into 10 groups, each encrypted with a different algorithm whose variation is controlled server-side.

f. The encryption is white-box and computed inside the VMP layer.

Colin Xiao — I take on contract reverse-engineering work, and writeups like this are how I show what I can do. If you need help with anything in this space — including but not limited to the areas I cover above — I’m available. No project is too big or too small — if it’s reverse engineering and I can do it, I’ll take it. DM me on X (@colinxiao_lab) or Telegram (@ColinXiao666).

Get in touch