(lldb) thread step-out

Find resources of an app (on jailbroken device)

An app from AppStore has following places where its stuff can be found:

  1. App bundle with executable, resources and extensions/var/containers/Bundle/Application
  2. App working directory/var/mobile/Containers/Data/Application
  3. App Extensions working directory/var/mobile/Containers/Data/PluginKitPlugin
  4. App Groups working directory/var/mobile/Containers/Shared/AppGroup
First one is signed by developer during upload to AppStore, so no one can modify it's contents without re-signing the binary (or breaking codesisning validations). The others are directories for data generated during app lifetime. Each of the directories above has and UUID-named subfolders, where UUID is randomly generated during app installation.
How does the system know which directory belongs to which app then? System service called LaunchServicesdoes.

Caveman methods (1, 2, 3, 4)

Easiest way - run process explorer # ps ax | grep <NAME> on iOS side while the app in interest is launched, which will show binary's localtion per process - whether the process is one of app or of app extension.

List of app groups the app participates in can be found by reading binary's entitlements:# ldid -e <PATH-TO-BINARY>

Each of UUID'd folders contains hidden .com.apple.mobile_container_manager.metadata.plist file which contains either bundle ID or app group ID in MCMMetadataIdentifier field. So a brave reader can enumerate 1-4 directories and every one of subfolders in them, and search for those with bundleID/appGroupID of interest in the hidden plist.

Another way for desperate researcher would be to look for LaunchServices database located in a temporary folder under one of /private/var/containers/Data/System subfolders with a filename similar to com.apple.LaunchServices-231-v2.csstore. Altho I did not find any way to conveniently read contents of that file apart from running LSDTrip which is capable of talking to a responsible lsd launch services daemon on device itself.

Objection and Frida (1, 2)

Task is fully automated by objection framerwork for Frida:

LSDTrip (1, 2, 3, 4)

Utility called LSDTrip by Jonathan Levin gives more complete output. It is open source, but installation instructions in [2] are a little bit outdated - as of iOS 12 entitlements should be as follows:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.launchservices.clearadvertisingid</key>
<true/>
<key>com.apple.lsapplicationproxy.deviceidentifierforvendor</key>
<true/>
<key>com.apple.private.coreservices.canmaplsdatabase</key>
<true/>
</dict>
</plist>
view raw ls.ent hosted with ❤ by GitHub
and a little bit verbose output of # ./lsdtrip.arm64 dump will contain appContainer, dataContainer, groups
BundleClass: kLSBundleClassApplication
Container mount state: mounted
bundle id: 104
Mach-O UUIDs: E569466D-D64A-7DFD-3C74-F48539D4DFD1
Device Familie 1, 2
Counterpart ID ph.telegra.Telegraph.watchkitapp
sequenceNum: 104
itemID: 686449807
FamilyID: 0
PurchaserID: 1365520763
DownloaderID: 0
installType: 0
appContainer: /private/var/containers/Bundle/Application/BCE48FC7-017F-47E2-A7CE-881CFCEA0069
dataContainer: /private/var/mobile/Containers/Data/Application/2A53ECA8-80CB-4C0F-9073-C0C52ADEEC36
path: /private/var/containers/Bundle/Application/BCE48FC7-017F-47E2-A7CE-881CFCEA0069/Telegram.app
name: Telegram
displayName: Telegram
itemName: Telegram Messenger
teamID: C67CF9S4VU
staticSize: 86806528
storeFront: 143469
versionID: 834223507
sourceAppID: (null)
ratingLabel: 17+
ratingRank: 600
genre:: Социальные сети
genreID: 6005
identifier: ph.telegra.Telegraph (0x80000a08)
canonical id: ph.telegra.telegraph (0x80000a07)
vendor: Telegram LLC
type: User
version: 16435.0 (<00000000 00cc0001>)
versionString: 16435
displayVersion 5.13.1
codeInfoID: ph.telegra.Telegraph
signerOrg: Apple Inc.
mod date: 1/6/20, 6:25 PM
reg date: 1/13/20, 8:14 PM
type code: 'APPL'
creator code: '????'
bundle flags: has-display-name requires-iphone-os is-deletable name-is-localized (0020014000001002)
plist flags: has-uibackgroundmodes has-required-device-capabilities has-cohort-metadata (0000000000016200)
Icon flags: supports-asset-catalog supports-alternate-icons (000000000000000c)
arch flags: arm64 (0000000000000040)
item flags: container package application extension-hidden native-app (000000000010008e)
App Nap: capable (0000000000000001)
iconName: AppIconLLC
iconDict: {
CFBundleAlternateIcons = {
Black = {
CFBundleIconFiles = (
BlackIcon,
BlackNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlackClassic = {
CFBundleIconFiles = (
BlackClassicIcon,
BlackClassicNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlackFilled = {
CFBundleIconFiles = (
BlackFilledIcon
);
UIPrerenderedIcon = 1;
};
Blue = {
CFBundleIconFiles = (
BlueIcon,
BlueNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlueClassic = {
CFBundleIconFiles = (
BlueClassicIcon,
BlueClassicNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlueFilled = {
CFBundleIconFiles = (
BlueFilledIcon
);
UIPrerenderedIcon = 1;
};
WhiteFilled = {
CFBundleIconFiles = (
WhiteFilledIcon
);
UIPrerenderedIcon = 1;
};
};
CFBundlePrimaryIcon = {
CFBundleIconFiles = (
AppIconLLC20x20,
AppIconLLC29x29,
AppIconLLC40x40,
AppIconLLC60x60
);
CFBundleIconName = AppIconLLC;
UIPrerenderedIcon = 1;
};
}
executable: Telegram
inode: 61518214
exec inode: 61518221
container id: 8
min version: 12.2 (<00004000 00300000>)
execSDK ver: 13.2 (<00004000 00340000>)
AppStoreToolv: 11C29
properties: {
UIBackgroundModes = (
audio,
fetch,
location,
"remote-notification",
voip
);
UIRequiredDeviceCapabilities = (
armv7
);
storeCohort = "8|date=1391752398000&amp;sf=143469";
}
plistCommon: {
CFBundleAllowMixedLocalizations = 1;
CFBundleDevelopmentRegion = en;
CFBundleDisplayName = Telegram;
CFBundleExecutable = Telegram;
CFBundleIcons = {
CFBundleAlternateIcons = {
Black = {
CFBundleIconFiles = (
BlackIcon,
BlackNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlackClassic = {
CFBundleIconFiles = (
BlackClassicIcon,
BlackClassicNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlackFilled = {
CFBundleIconFiles = (
BlackFilledIcon
);
UIPrerenderedIcon = 1;
};
Blue = {
CFBundleIconFiles = (
BlueIcon,
BlueNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlueClassic = {
CFBundleIconFiles = (
BlueClassicIcon,
BlueClassicNotificationIcon
);
UIPrerenderedIcon = 1;
};
BlueFilled = {
CFBundleIconFiles = (
BlueFilledIcon
);
UIPrerenderedIcon = 1;
};
WhiteFilled = {
CFBundleIconFiles = (
WhiteFilledIcon
);
UIPrerenderedIcon = 1;
};
};
CFBundlePrimaryIcon = {
CFBundleIconFiles = (
AppIconLLC20x20,
AppIconLLC29x29,
AppIconLLC40x40,
AppIconLLC60x60
);
CFBundleIconName = AppIconLLC;
UIPrerenderedIcon = 1;
};
};
CFBundleIdentifier = "ph.telegra.Telegraph";
CFBundleInfoDictionaryVersion = "6.0";
CFBundleName = Telegram;
CFBundleNumericVersion = 0;
CFBundlePackageType = APPL;
CFBundleShortVersionString = "5.13.1";
CFBundleSignature = "????";
CFBundleSupportedPlatforms = (
iPhoneOS
);
CFBundleURLTypes = (
{
CFBundleTypeRole = Viewer;
CFBundleURLName = "ph.telegra.Telegraph";
CFBundleURLSchemes = (
telegram
);
},
{
CFBundleTypeRole = Viewer;
CFBundleURLName = "ph.telegra.Telegraph.compatibility";
CFBundleURLSchemes = (
tg,
tgapp
);
},
{
CFBundleTypeRole = Viewer;
CFBundleURLName = "ph.telegra.Telegraph.ton";
CFBundleURLSchemes = (
ton
);
}
);
CFBundleVersion = 16435;
NSAppTransportSecurity = {
NSAllowsArbitraryLoads = 1;
};
NSCameraUsageDescription = "We need this so that you can take and share photos and videos.";
NSContactsUsageDescription = "Telegram stores your contacts heavily encrypted in the cloud to let you connect with your friends across all your devices.";
NSFaceIDUsageDescription = "You can use Face ID to unlock the app.";
NSLocationAlwaysUsageDescription = "When you send your location to your friends, Telegram needs access to show them a map. You also need this to send locations from an Apple Watch.";
NSLocationWhenInUseUsageDescription = "When you send your location to your friends, Telegram needs access to show them a map.";
NSMicrophoneUsageDescription = "We need this so that you can record and share voice messages and videos with sound.";
NSMotionUsageDescription = "When you send your location to your friends, Telegram needs access to show them a map.";
NSPhotoLibraryAddUsageDescription = "We need this so that you can share photos and videos from your photo library.";
NSPhotoLibraryUsageDescription = "We need this so that you can share photos and videos from your photo library.";
NSSiriUsageDescription = "You can use Siri to send messages.";
NSUserActivityTypes = (
INSendMessageIntent,
RemindAboutChatIntent
);
UIAppFonts = (
"SFCompactRounded-Semibold.otf"
);
UIBackgroundModes = (
audio,
fetch,
location,
"remote-notification",
voip
);
UIDeviceFamily = (
1,
2
);
UIFileSharingEnabled = 0;
UILaunchStoryboardName = LaunchScreen;
UIRequiredDeviceCapabilities = (
armv7
);
UIRequiresPersistentWiFi = 1;
UIStatusBarStyle = UIStatusBarStyleDefault;
UISupportedDevices = (
"iPhone10,2",
"iPhone10,3",
"iPhone10,5",
"iPhone10,6",
"iPhone11,2",
"iPhone11,4",
"iPhone11,6",
"iPhone7,1",
"iPhone8,2",
"iPhone9,2",
"iPhone9,4"
);
UISupportedInterfaceOrientations = (
UIInterfaceOrientationPortrait,
UIInterfaceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRight
);
UIViewControllerBasedStatusBarAppearance = 0;
UIViewEdgeAntialiasing = 0;
UIViewGroupOpacity = 0;
}
library: (null)
schemesList: waze, ddgquicklink, uber, comgooglemaps, vimeo, lyft, moovit, dolphin, comgooglemaps-x-callback, telegram, citymapper, googlechrome, onionhttp, dgis, twitter, foursquare, firefox-focus, tg, ton, ucbrowser, firefox, brave, youtube, alook, yandexbrowser-open-url, microsoft-edge-http, instagram, vine, yandexnavi, opera-http, vk, touch-http, coub, yandexmaps, here-location, tgapp
activityTypes: ua-b172f1a860a663, INSendMessageIntent, C67CF9S4VU:RemindAboutChatIntent, ua-a5cd25b1fe2bc0, pv-d2c0f8ca2da084, NOTIFICATION#C67CF9S4VU:ph.telegra.Telegraph
entitlements: 14 entitlements
entitlements: {
"application-identifier" = "C67CF9S4VU.ph.telegra.Telegraph";
"aps-environment" = production;
"com.apple.developer.associated-domains" = (
"applinks:telegram.me",
"applinks:t.me"
);
"com.apple.developer.carplay-messaging" = 1;
"com.apple.developer.icloud-container-environment" = (
Production
);
"com.apple.developer.icloud-container-identifiers" = (
"iCloud.ph.telegra.Telegraph"
);
"com.apple.developer.icloud-services" = (
CloudDocuments,
CloudKit
);
"com.apple.developer.in-app-payments" = (
"merchant.privatbank.test.telergramios",
"merchant.privatbank.prod.telergram",
"merchant.sberbank.ph.telegra.Telegraph",
"merchant.yandex.ph.telegra.Telegraph",
"merchant.sberbank.test.ph.telegra.Telegraph",
"merchant.ph.telegra.Telegraph"
);
"com.apple.developer.pushkit.unrestricted-voip" = 1;
"com.apple.developer.siri" = 1;
"com.apple.developer.team-identifier" = C67CF9S4VU;
"com.apple.developer.ubiquity-container-identifiers" = (
"iCloud.ph.telegra.Telegraph"
);
"com.apple.security.application-groups" = (
"group.ph.telegra.Telegraph"
);
"keychain-access-groups" = (
"C67CF9S4VU.*"
);
}
group ctrs: 1 group containers
groups: {
"group.ph.telegra.Telegraph" = "/private/var/mobile/Containers/Shared/AppGroup/821859E8-53E6-4494-85A8-37FCA9571F4F";
}
environment: 3 environment variables
--------------------------------------------------------
type id: 2740
uti: org.telegram.telegram-ios.theme
description: Telegram iOS Color Theme File
flags: imported active trusted
icon: BlueIcon@3x.png
conforms to: public.data
tags: .tgios-theme
--------------------------------------------------------
claim id: 236
name: ph.telegra.Telegraph
rank: Default
roles: Viewer
flags: url-type
icon:
bindings: telegram:
--------------------------------------------------------
claim id: 240
name: ph.telegra.Telegraph.compatibility
rank: Default
roles: Viewer
flags: url-type
icon:
bindings: tg:, tgapp:
--------------------------------------------------------
claim id: 244
name: ph.telegra.Telegraph.ton
rank: Default
roles: Viewer
flags: url-type
icon:
bindings: ton:
--------------------------------------------------------
plugin Identif ph.telegra.Telegraph.NotificationContent
--------------------------------------------------------
plugin Identif ph.telegra.Telegraph.Widget
--------------------------------------------------------
plugin Identif ph.telegra.Telegraph.SiriIntents
--------------------------------------------------------
plugin Identif ph.telegra.Telegraph.NotificationService
--------------------------------------------------------
plugin Identif ph.telegra.Telegraph.Share
--------------------------------------------------------------------------------
and a list of plugin Identifiers, each of which has it's own place in the output down below:
Container mount state: mounted
plugin id: 160
isSystemManage
Mach-O UUIDs: 62E4F957-5851-5ABB-26EA-66B729F411A9
identifier: ph.telegra.Telegraph.Share
bundleID: ph.telegra.Telegraph.Share
name: Share
displayName: Telegram
parent: 104
path: /private/var/containers/Bundle/Application/BCE48FC7-017F-47E2-A7CE-881CFCEA0069/Telegram.app/PlugIns/ShareExtension.appex
dataContainer: /private/var/mobile/Containers/Data/PluginKitPlugin/D0F4B4E8-3BA6-47A3-ADC4-986AADD71909
EPID: com.apple.share-services
EPName: com.apple.share-services
version: 5.13.1
sdkVersion: 13.2
UUID: 67E3FEC1-84B5-46C9-8379-D430DED9EAE8
CodeInfoID: ph.telegra.Telegraph.Share
signerOrg: Apple Inc.
flags:
reg date: 1/13/20, 8:14 PM
directory: other
entitlements: {
"application-identifier" = "C67CF9S4VU.ph.telegra.Telegraph.Share";
"com.apple.developer.carplay-messaging" = 1;
"com.apple.developer.pushkit.unrestricted-voip" = 1;
"com.apple.developer.team-identifier" = C67CF9S4VU;
"com.apple.security.application-groups" = (
"group.ph.telegra.Telegraph"
);
"keychain-access-groups" = (
"C67CF9S4VU.*"
);
}
grpContainers: {
"group.ph.telegra.Telegraph" = "/private/var/mobile/Containers/Shared/AppGroup/821859E8-53E6-4494-85A8-37FCA9571F4F";
}
PKDict: {
CFBundleDevelopmentRegion = en;
CFBundleDisplayName = Telegram;
CFBundleExecutable = ShareExtension;
CFBundleIdentifier = "ph.telegra.Telegraph.Share";
CFBundleInfoDictionaryVersion = "6.0";
CFBundleName = Share;
CFBundleNumericVersion = 0;
CFBundlePackageType = "XPC!";
CFBundleShortVersionString = "5.13.1";
CFBundleSupportedPlatforms = (
iPhoneOS
);
CFBundleVersion = 16435;
LSExecutableFormat = LSExecutableMachOFormat;
LSExecutablePlatformKey = 2;
LSExecutableSDKVersion = "13.2";
LSRequiresIPhoneOS = 1;
MachOUUIDs = (
"62E4F957-5851-5ABB-26EA-66B729F411A9"
);
MinimumOSVersion = "9.0";
NSExtension = {
NSExtensionAttributes = {
IntentsSupported = (
INSendMessageIntent
);
NSExtensionActivationRule = "SUBQUERY (\n extensionItems,\n $extensionItem,\n SUBQUERY (\n $extensionItem.attachments,\n $attachment,\n ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.file-url\" ||\n ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.movie\" ||\n ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.image\" ||\n\t\tANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.url\" ||\n\t\tANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.text\" ||\n\t\tANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.audio\" ||\n ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.data\" ||\n ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"public.vcard\" ||\n ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO \"com.apple.pkpass\"\n ).@count == $extensionItem.attachments.@count\n).@count > 0";
NSExtensionVersion = "5.13.1";
};
NSExtensionPointIdentifier = "com.apple.share-services";
NSExtensionPrincipalClass = ShareRootController;
};
Path = "/private/var/containers/Bundle/Application/BCE48FC7-017F-47E2-A7CE-881CFCEA0069/Telegram.app/PlugIns/ShareExtension.appex";
"_LSArchitecturesAvailable" = (
arm64
);
"_LSExecutablePath" = ShareExtension;
"_LSSiriActionDefinitionURLs" = {
};
}
SDKData: {
CFBundlePackageType = "XPC!";
NSExtension = {
NSExtensionAttributes = {
NSExtensionPointName = "com.apple.share-services";
NSExtensionPointVersion = "1.0";
};
NSExtensionPointIdentifier = "com.apple.share-services";
NSExtensionViewControllerHostClass = SLRemoteComposeViewController;
};
XPCService = {
RunLoopType = "_UIApplicationMain";
ServiceType = Application;
"_AdditionalSubServices" = {
"apple-extension-service" = 1;
viewservice = 1;
};
};
}


Sources

[1] OWASP Mobile Security Testing Guide

[2] LSDTrip - Take a ride down the LaunchServices.framework rabbithole by Jonathan Levin


Jan 2020, iOS 12.4