From 5ed95764fc95c4d16f9e6037820da0edd99e2401 Mon Sep 17 00:00:00 2001 From: gastontoth Date: Thu, 23 May 2024 16:27:37 -0300 Subject: [PATCH] Adding functionalities: 'update' and 'remove' item from ios keychain. (#584) --- agent/src/ios/keychain.ts | 33 ++++++++++++++++++++++++ agent/src/ios/lib/libobjc.ts | 7 +++++ agent/src/rpc/ios.ts | 3 +++ objection/commands/ios/keychain.py | 41 ++++++++++++++++++++++++++++++ objection/console/commands.py | 10 ++++++++ 5 files changed, 94 insertions(+) diff --git a/agent/src/ios/keychain.ts b/agent/src/ios/keychain.ts index 32f509c3..b05edbaf 100644 --- a/agent/src/ios/keychain.ts +++ b/agent/src/ios/keychain.ts @@ -170,6 +170,39 @@ export const empty = (): void => { }); }; + // remove matching itemms from the keychain + export const remove = (account: string, service: string): void => { + const searchDictionary: NSMutableDictionaryType = ObjC.classes.NSMutableDictionary.alloc().init(); + searchDictionary.setObject_forKey_(kSec.kSecAttrSynchronizableAny, kSec.kSecAttrSynchronizable); + itemClasses.forEach((clazz) => { + // set the class-type we are querying for now & delete + searchDictionary.setObject_forKey_(clazz, kSec.kSecClass); + searchDictionary.setObject_forKey_(account, kSec.kSecAttrAccount); + searchDictionary.setObject_forKey_(service, kSec.kSecAttrService); + libObjc.SecItemDelete(searchDictionary); + }); + }; + + // update matching item from the keychain + export const update = (account: string, service: string, newData: string): void => { + + const searchDictionary: NSMutableDictionaryType = ObjC.classes.NSMutableDictionary.alloc().init(); + searchDictionary.setObject_forKey_(kSec.kSecAttrSynchronizableAny, kSec.kSecAttrSynchronizable); + + // set the class-type we are querying for now & update + searchDictionary.setObject_forKey_(kSec.kSecClassGenericPassword, kSec.kSecClass); + searchDictionary.setObject_forKey_(account, kSec.kSecAttrAccount); + searchDictionary.setObject_forKey_(service, kSec.kSecAttrService); + + // set the dictionary with new value + const itemDict: NSMutableDictionaryType = ObjC.classes.NSMutableDictionary.alloc().init(); + const v: NSStringType = ObjC.classes.NSString.stringWithString_(newData).dataUsingEncoding_(NSUTF8StringEncoding); + itemDict.setObject_forKey_(account, kSec.kSecAttrAccount); + itemDict.setObject_forKey_(v, kSec.kSecValueData); + libObjc.SecItemUpdate(searchDictionary, itemDict); + + }; + // add a string entry to the keychain export const add = (account: string, service: string, data: string): boolean => { diff --git a/agent/src/ios/lib/libobjc.ts b/agent/src/ios/lib/libobjc.ts index 0d36f06e..a31928e4 100644 --- a/agent/src/ios/lib/libobjc.ts +++ b/agent/src/ios/lib/libobjc.ts @@ -24,6 +24,12 @@ const nativeExports: any = { moduleName: "Security", retType: "pointer", }, + SecItemUpdate: { + argTypes: ["pointer", "pointer"], + exportName: "SecItemUpdate", + moduleName: "Security", + retType: "pointer", + }, // SSL pinning methods SSLCreateContext: { @@ -86,6 +92,7 @@ const api: any = { SecAccessControlGetConstraints: null, SecItemAdd: null, SecItemCopyMatching: null, + SecItemUpdate: null, SecItemDelete: null, SSLCreateContext: null, diff --git a/agent/src/rpc/ios.ts b/agent/src/rpc/ios.ts index 7b5cfbc8..f590e385 100644 --- a/agent/src/rpc/ios.ts +++ b/agent/src/rpc/ios.ts @@ -96,6 +96,9 @@ export const ios = { // ios keychain iosKeychainAdd: (account: string, service: string, data: string): boolean => ioskeychain.add(account, service, data), + iosKeychainRemove: (account: string, service: string): void => ioskeychain.remove(account, service), + iosKeychainUpdate: (account: string, service: string, newData: string): void => + ioskeychain.update(account, service, newData), iosKeychainEmpty: (): void => ioskeychain.empty(), iosKeychainList: (smartDecode): IKeychainItem[] => ioskeychain.list(smartDecode), iosKeychainListRaw: (): void => ioskeychain.listRaw(), diff --git a/objection/commands/ios/keychain.py b/objection/commands/ios/keychain.py index fa87e5c9..5f11941a 100644 --- a/objection/commands/ios/keychain.py +++ b/objection/commands/ios/keychain.py @@ -138,6 +138,47 @@ def clear(args: list = None) -> None: click.secho('Keychain cleared', fg='green') +def remove(args: list) -> None: + """ + Remove matching keychain entries from the keychain + + :param args: + :return: + """ + + account = _get_flag_value(args, '--account') + service = _get_flag_value(args, '--service') + + click.secho('Removing entry from the iOS keychain...', dim=True) + click.secho('Account: {0}'.format(account), dim=True) + click.secho('Service: {0}'.format(service), dim=True) + + api = state_connection.get_api() + api.ios_keychain_remove(account, service); + click.secho('Successfully removed matching keychain items', fg='green') + + +def update(args: list) -> None: + """ + Update matching keychain entry from the keychain + + :param args: + :return: + """ + + account = _get_flag_value(args, '--account') + service = _get_flag_value(args, '--service') + newData = _get_flag_value(args, '--newData') + + click.secho('Updating entries from the iOS keychain...', dim=True) + click.secho('Account: {0}'.format(account), dim=True) + click.secho('Service: {0}'.format(service), dim=True) + click.secho('New Data: {0}'.format(newData), dim=True) + + api = state_connection.get_api() + api.ios_keychain_update(account, service, newData); + click.secho('Successfully updated matching keychain item', fg='green') + def add(args: list) -> None: """ Adds a new kSecClassGenericPassword keychain entry to the keychain diff --git a/objection/console/commands.py b/objection/console/commands.py index 1326bd85..1688eac4 100644 --- a/objection/console/commands.py +++ b/objection/console/commands.py @@ -527,6 +527,16 @@ 'meta': 'Delete all keychain entries for the current app\'s entitlement group', 'exec': keychain.clear }, + 'remove': { + 'meta': 'Remove an entry from the iOS keychain', + 'flags': ['--account', '--service'], + 'exec': keychain.remove + }, + 'update': { + 'meta': 'Update an entry from the iOS keychain', + 'flags': ['--account', '--service', '--newData'], + 'exec': keychain.update + }, 'add': { 'meta': 'Add an entry to the iOS keychain', 'flags': ['--account', '--service', '--data'],