Xiangxiang's Personal Site

Machine Learning & Security Engineer
生命不息,折腾不止,留下一点活着的记录.

View on GitHub
21 February 2025

TrollFools

by xiangxiang

iOS injection without JB

0x00 Exploit Needed for JB

kernel r/w

userspace -> kernel space

Integrity bypass


+-------+   ---->  Trust Cache  ---->  Core Trust  ----> amfid
| fork/ |             |                                    |
| exec  |             |                                    |
+-------+             +---------------         --------->  +------> a.out
              

0x01 TrollStore

1.1 Code signature

Inside Code Signing series

1.2 Exploits in TrollStore1

1.3 CVE-2023-41991

1.4 TrollStore2

0x02 TrollFools

otool -l machO to verify

2.1 list apps that can be injected

// Frameworks Directory exists
func checkIsEligibleAppBundle(_ target: URL) -> Bool {
    guard checkIsBundle(target) else {
        return false
    }

    let frameworksURL = target.appendingPathComponent("Frameworks")
    return !((try? FileManager.default.contentsOfDirectory(at: frameworksURL, includingPropertiesForKeys: nil).isEmpty) ?? true)
}

2.2 TrollFools/InjectorV3+Inject.swift

func inject(_ assetURLs: [URL]) throws {
    let preparedAssetURLs = try preprocessAssets(assetURLs)

    precondition(!preparedAssetURLs.isEmpty, "No asset to inject.")
    terminateApp()

    try injectBundles(preparedAssetURLs
        .filter { $0.pathExtension.lowercased() == "bundle" })

    try injectDylibsAndFrameworks(preparedAssetURLs
        .filter { $0.pathExtension.lowercased() == "dylib" || $0.pathExtension.lowercased() == "framework" })
}
ct_bypass -r -i /var/mobile/Library/Caches/wiki.qaq.TrollFools/InjectorV3/56A6617A-FB1C-4DED-A452-01609990B354/demo.dylib -t ZMX4C3B995

chown 33:33 /var/mobile/Library/Caches/wiki.qaq.TrollFools/InjectorV3/56A6617A-FB1C-4DED-A452-01609990B354/demo.dylib

cp-15 -rfp /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy.troll-fools.bak

rm -rf /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/demo.dylib

cp-15 --reflink=auto -rfp /var/mobile/Library/Caches/wiki.qaq.TrollFools/InjectorV3/56A6617A-FB1C-4DED-A452-01609990B354/demo.dylib /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/demo.dylib

chown 33:33 /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/demo.dylib

# @executable_path/Frameworks already in rpath
## install_name_tool -add_rpath @executable_path/Frameworks /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy 


insert_dylib @rpath/demo.dylib /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy --inplace --overwrite --no-strip-codesig --all-yes --weak
# Added LC_LOAD_WEAK_DYLIB to /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

ldid -S /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

install_name_tool -change @rpath/demo.dylib @rpath/demo.dylib /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

ct_bypass -r -i /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy -t ZMX4C3B995

chown 33:33 /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

2.3 TrollFools/InjectorV3+Eject.swift

func eject(_ assetURLs: [URL]) throws {
    precondition(!assetURLs.isEmpty, "No asset to eject.")
    terminateApp()

    try ejectBundles(assetURLs
        .filter { $0.pathExtension.lowercased() == "bundle" })

    try ejectDylibsAndFrameworks(assetURLs
        .filter { $0.pathExtension.lowercased() == "dylib" || $0.pathExtension.lowercased() == "framework" })
}
optool uninstall -p @rpath/demo.dylib -t /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy
# Successfully removed all entries for @rpath/demo.dylib

# Writing executable to /var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy...
rm -f /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/demo.dylib
ct_bypass -r -i /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy -t ZMX4C3B995

chown 33:33 /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

rm -rf /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

mv-15 -f /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy.troll-fools.bak /private/var/containers/Bundle/Application/B21CD6F2-5D73-4EC1-B5FE-745688DEE9CB/EMBS.app/Frameworks/AIPIFlyMSCDy.framework/AIPIFlyMSCDy

0x03 TODO: opainject

0x04 More

tags: iOS security