Skip to content

Commit

Permalink
Adding functionalities: 'update' and 'remove' item from ios keychain. (
Browse files Browse the repository at this point in the history
  • Loading branch information
gastontoth authored May 23, 2024
1 parent 6c55d7e commit 5ed9576
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 0 deletions.
33 changes: 33 additions & 0 deletions agent/src/ios/keychain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {

Expand Down
7 changes: 7 additions & 0 deletions agent/src/ios/lib/libobjc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -86,6 +92,7 @@ const api: any = {
SecAccessControlGetConstraints: null,
SecItemAdd: null,
SecItemCopyMatching: null,
SecItemUpdate: null,
SecItemDelete: null,

SSLCreateContext: null,
Expand Down
3 changes: 3 additions & 0 deletions agent/src/rpc/ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
41 changes: 41 additions & 0 deletions objection/commands/ios/keychain.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions objection/console/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
Expand Down

0 comments on commit 5ed9576

Please sign in to comment.