├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bin └── keychain_cat ├── bundle_ids.mm ├── control ├── ent.xml ├── keychain_cat.mm ├── scripts └── dump_NSUserDefaults.py └── wifi_passwords.mm /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .theos 4 | theos/ 5 | obj/ 6 | *.deb 7 | _/ 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Hao Zhou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:8.1 2 | ARCHS := armv7 armv7s arm64 3 | 4 | include theos/makefiles/common.mk 5 | 6 | TOOL_NAME = wifi_passwords keychain_cat #bundle_ids 7 | 8 | bundle_ids_FILES = bundle_ids.mm 9 | bundle_ids_LIBRARIES = applist 10 | 11 | wifi_passwords_FILES = wifi_passwords.mm 12 | wifi_passwords_FRAMEWORKS = Security 13 | 14 | keychain_cat_FILES = keychain_cat.mm 15 | keychain_cat_FRAMEWORKS = Security Foundation 16 | keychain_cat_LIBRARIES = sqlite3 17 | 18 | include $(THEOS_MAKE_PATH)/tool.mk 19 | 20 | after-all:: 21 | export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate 22 | ldid -Sent.xml obj/wifi_passwords 23 | ldid -Sent.xml obj/keychain_cat 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # My iDevice Tools 2 | ###### A set of console tools for iOS devices, build with [Theos](http://iphonedevwiki.net/index.php/Theos/Setup). 3 | 4 | ## Tools 5 | 6 | ### bundle_ids 7 | List bundle identifier for installed applications. (depend on **AppList**) 8 | 9 | ~~~sh 10 | # ./bundle_ids 11 | com.apple.AppStore : App Store 12 | com.apple.AskPermissionUI : AskPermissionUI 13 | com.apple.datadetectors.DDActionsService : DDActionsService 14 | com.apple.DemoApp : DemoApp 15 | com.apple.Diagnostics : Diagnostics 16 | com.apple.FacebookAccountMigrationDialog : FacebookAccountMigrationDialog 17 | com.apple.facetime : FaceTime 18 | ... 19 | ~~~ 20 | 21 | ### wifi_passwords 22 | Retrieve a saved WiFi password from keychain. See more: [自己动手从iOS Keychain中恢复保存的Wifi密码](http://blog.imaou.com/theos/2014/11/12/retrieve_wifi_password_from_keychain.html) 23 | 24 | ~~~sh 25 | # ./wifi_passwords 26 | Magdalene: Retrieve Wifi password. 27 | iPhone: 123456 28 | ~~~ 29 | 30 | 31 | ### keychain_cat 32 | Dump / modify and delete keychain v_Data. See more: [keychain_cat - 查看/修改keychain2数据的工具](http://blog.imaou.com/theos/2014/12/26/keychain_cat_tool.html) 33 | 34 | ~~~sh 35 | # ./keychain_cat -d 36 | >> keychain-access-groups: 37 | 6WX5RKLG95.com.supercell.reef 38 | 88L2Q4487U.com.tencent.mttlite 39 | apple 40 | com.apple.ProtectedCloudStorage 41 | com.apple.PublicCloudStorage 42 | com.apple.apsd 43 | com.apple.assistant 44 | com.apple.cloudd 45 | com.apple.ind 46 | com.apple.security.sos 47 | 48 | # ./keychain_cat -g 6WX5RKLG95.com.supercell.reef -s com.supercell 49 | 50 | { 51 | accc = ""; 52 | acct = appRated; 53 | agrp = "6WX5RKLG95.com.supercell.reef"; 54 | cdat = "2014-11-11 23:33:33 +0000"; 55 | class = genp; 56 | invi = 1; 57 | labl = Supercell; 58 | mdat = "2014-11-11 23:33:33 +0000"; 59 | pdmn = ak; 60 | svce = "com.supercell"; 61 | sync = 0; 62 | tomb = 0; 63 | "v_Data" = TRUE; 64 | } 65 | ... 66 | 67 | # ./keychain_cat -g 6WX5RKLG95.com.supercell.reef -s com.supercell -a THLevel -v 99 -U 68 | Origin: { 69 | accc = ""; 70 | acct = THLevel; 71 | agrp = "6WX5RKLG95.com.supercell.reef"; 72 | cdat = "2014-11-11 23:33:33 +0000"; 73 | invi = 1; 74 | labl = Supercell; 75 | mdat = "2014-11-11 23:33:33 +0000"; 76 | pdmn = ak; 77 | svce = "com.supercell"; 78 | sync = 0; 79 | tomb = 0; 80 | "v_Data" = <3133>; 81 | } 82 | >> Update v_Data to: <3939> 83 | ~~~ 84 | 85 | --------- 86 | 87 | ## Compiling 88 | 89 | ```shell 90 | git clone https://github.com/upbit/My-iDevice-Tools.git 91 | cd My-iDevice-Tools 92 | ln -s /opt/theos ./ 93 | make 94 | ``` 95 | 96 | ## Requirements 97 | 98 | * [Theos](http://iphonedevwiki.net/index.php/Theos/Setup) 99 | * [AppList](http://iphonedevwiki.net/index.php/AppList) on iOS (only **bundle_ids**) 100 | -------------------------------------------------------------------------------- /bin/keychain_cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upbit/My-iDevice-Tools/1e91c1feb0b16278c8738ad106f79d5ed13f1f76/bin/keychain_cat -------------------------------------------------------------------------------- /bundle_ids.mm: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, char **argv, char **envp) 4 | { 5 | // list all the apps 6 | ALApplicationList *apps = [ALApplicationList sharedApplicationList]; 7 | 8 | // sort the apps by display name. displayIdentifiers is an autoreleased object. 9 | NSArray *displayIdentifiers = [[apps.applications allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 10 | return [obj1 caseInsensitiveCompare:obj2]; 11 | }]; 12 | 13 | NSMutableString *outputs = [NSMutableString new]; 14 | 15 | for (NSString *key in displayIdentifiers) { 16 | NSString *name = [apps.applications objectForKey:key]; 17 | [outputs appendString:[NSString stringWithFormat:@"%-48s: %@\n", [key cStringUsingEncoding:NSUTF8StringEncoding], name]]; 18 | } 19 | 20 | printf("%s\n", [outputs cStringUsingEncoding:NSUTF8StringEncoding]); 21 | [outputs release]; 22 | return 0; 23 | } 24 | 25 | // vim:ft=objc 26 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.zzz.my-idevice-tools 2 | Name: my-idevice-tools 3 | Depends: 4 | Version: 0.1 5 | Architecture: iphoneos-arm, applist (>= 1.4.1) 6 | Description: A set of console tools for iOS devices 7 | Maintainer: Zhou Hao 8 | Author: Zhou Hao 9 | Section: System 10 | Tag: role::hacker 11 | -------------------------------------------------------------------------------- /ent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | application-identifier 6 | com.zzz.my-idevice-tools 7 | get-task-allow 8 | 9 | keychain-access-groups 10 | 11 | * 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /keychain_cat.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #include 6 | 7 | typedef enum { 8 | KCCMD_NONE = 0, 9 | KCCMD_LIST, 10 | KCCMD_UPDATE, 11 | KCCMD_DELETE, 12 | } KC_CommandType; 13 | 14 | void printToStdOut(NSString *format, ...) { 15 | va_list args; 16 | va_start(args, format); 17 | NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:args]; 18 | va_end(args); 19 | [[NSFileHandle fileHandleWithStandardOutput] writeData:[formattedString dataUsingEncoding:NSNEXTSTEPStringEncoding]]; 20 | } 21 | 22 | void printUsage(char* cmd_line) 23 | { 24 | printf("usage: %s [options]\n", cmd_line); 25 | printf(" -d --dump Dump Keychain AccessGroups\n"); 26 | printf(" -U --update UPDATE v_Data with specified value <-g> <-s> <-a> <-v>\n"); 27 | printf(" -D --delete DELETE keychain with <-g> (-s) (-a)\n"); 28 | printf(" -g --group kSecAttrAccessGroup\n"); 29 | printf(" -s --service kSecAttrService\n"); 30 | printf(" -a --account kSecAttrAccount\n"); 31 | printf(" -v --value (UPDATE only) kSecValueData\n"); 32 | printf("\n"); 33 | printf(" \n"); 34 | printf(" -G --generic-password kSecClassGenericPassword\n"); 35 | printf(" -N --internet-password kSecClassInternetPassword\n"); 36 | printf(" -I --identity kSecClassIdentity\n"); 37 | printf(" -C --certificate kSecClassCertificate\n"); 38 | printf(" -K --classKey kSecClassKey\n"); 39 | printf("\n"); 40 | printf(" -h --help Show this help\n"); 41 | } 42 | 43 | // modify form https://github.com/upbit/Keychain-Dumper/blob/master/main.m#L56, dumpKeychainEntitlements() 44 | void dumpKeychainAccessGroups() 45 | { 46 | NSString *databasePath = @"/var/Keychains/keychain-2.db"; 47 | const char *dbpath = [databasePath UTF8String]; 48 | sqlite3 *keychainDB; 49 | sqlite3_stmt *statement; 50 | 51 | printToStdOut(@">> keychain-access-groups:\n"); 52 | 53 | if (sqlite3_open(dbpath, &keychainDB) == SQLITE_OK) { 54 | const char *query_stmt = "SELECT DISTINCT agrp FROM genp UNION SELECT DISTINCT agrp FROM inet"; 55 | if (sqlite3_prepare_v2(keychainDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) { 56 | while(sqlite3_step(statement) == SQLITE_ROW) { 57 | NSString *group = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)]; 58 | printToStdOut(@" %@\n", group); 59 | } 60 | sqlite3_finalize(statement); 61 | } else { 62 | printf("[ERROR] Query keychain failed.\n"); 63 | } 64 | sqlite3_close(keychainDB); 65 | } else { 66 | printf("[ERROR] Open keychain failed.\n"); 67 | } 68 | } 69 | 70 | void keychain_list_entry(CFTypeRef kSecClassType, NSString *access_group, NSString *service, NSString *account) 71 | { 72 | NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 73 | [query setObject:(id)kSecClassType forKey:(id)kSecClass]; 74 | [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit]; 75 | if (access_group) 76 | [query setObject:(id)access_group forKey:(id)kSecAttrAccessGroup]; 77 | if ((service) && (kSecClassType == kSecClassGenericPassword)) 78 | [query setObject:(id)service forKey:(id)kSecAttrService]; 79 | if ((account) && (kSecClassType == kSecClassGenericPassword)) 80 | [query setObject:(id)account forKey:(id)kSecAttrAccount]; 81 | 82 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 83 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef]; 84 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 85 | 86 | CFTypeRef result = NULL; 87 | OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, &result); 88 | if (status != errSecSuccess) { 89 | if (status == errSecItemNotFound) return; 90 | printf("[ERROR] SecItemCopyMatching() failed! error = %d\n", (int)status); 91 | return; 92 | } 93 | 94 | NSArray *keychain_entrys = (NSArray *)result; 95 | for (int i = 0; i < keychain_entrys.count; i++) { 96 | NSDictionary *entry = (NSDictionary*)keychain_entrys[i]; 97 | NSMutableDictionary *mutable_entry = [NSMutableDictionary dictionaryWithDictionary:entry]; 98 | 99 | if ((kSecClassType == kSecClassGenericPassword) || (kSecClassType == kSecClassInternetPassword)) { 100 | NSData *password_data = [mutable_entry objectForKey:(id)kSecValueData]; 101 | NSString *password_string = [[NSString alloc] initWithData:password_data encoding:NSUTF8StringEncoding]; 102 | if (password_string) 103 | [mutable_entry setObject:password_string forKey:(id)kSecValueData]; 104 | } 105 | 106 | printToStdOut(@"\n", [mutable_entry objectForKey:(id)kSecAttrAccessGroup], [mutable_entry objectForKey:(id)kSecAttrService], [mutable_entry objectForKey:(id)kSecAttrAccount]); 107 | printToStdOut(@"%@\n", mutable_entry); 108 | } 109 | 110 | if (result != NULL) 111 | CFRelease(result); 112 | } 113 | 114 | void keychain_update_entry(CFTypeRef kSecClassType, NSString *access_group, NSString *service, NSString *account, NSString *value) 115 | { 116 | NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 117 | [query setObject:(id)kSecClassType forKey:(id)kSecClass]; 118 | [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit]; 119 | if (!access_group) { 120 | printf("[ERROR] --group kSecAttrAccessGroup missed.\n"); 121 | return; 122 | } else { 123 | [query setObject:(id)access_group forKey:(id)kSecAttrAccessGroup]; 124 | } 125 | if ((!service) || (kSecClassType != kSecClassGenericPassword)) { 126 | printf("[ERROR] --service kSecAttrService missed or SecClass!=kSecClassGenericPassword\n"); 127 | return; 128 | } else { 129 | [query setObject:(id)service forKey:(id)kSecAttrService]; 130 | } 131 | if ((!account) || (kSecClassType != kSecClassGenericPassword)) { 132 | printf("[ERROR] --account kSecAttrAccount missed or SecClass!=kSecClassGenericPassword\n"); 133 | return; 134 | } else { 135 | [query setObject:(id)account forKey:(id)kSecAttrAccount]; 136 | } 137 | 138 | if (!value) { 139 | printf("[ERROR] --value missed.\n"); 140 | return; 141 | } 142 | 143 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 144 | //[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef]; 145 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 146 | 147 | CFTypeRef result = NULL; 148 | OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, &result); 149 | if (status != errSecSuccess) { 150 | if (status == errSecItemNotFound) return; 151 | printf("[ERROR] SecItemCopyMatching() failed! error = %d\n", (int)status); 152 | return; 153 | } 154 | 155 | NSArray *keychain_entrys = (NSArray *)result; 156 | for (int i = 0; i < keychain_entrys.count; i++) { 157 | NSDictionary *entry = (NSDictionary*)keychain_entrys[i]; 158 | NSMutableDictionary *mutable_entry = [NSMutableDictionary dictionaryWithDictionary:entry]; 159 | NSMutableDictionary *update_item = [NSMutableDictionary dictionaryWithDictionary:entry]; 160 | [mutable_entry setObject:(id)kSecClassType forKey:(id)kSecClass]; 161 | 162 | printToStdOut(@" Origin: %@\n", update_item); 163 | 164 | [update_item removeObjectForKey:@"accc"]; 165 | [update_item removeObjectForKey:(id)kSecAttrAccessGroup]; 166 | 167 | [update_item setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; 168 | 169 | OSStatus status = SecItemUpdate((CFDictionaryRef)mutable_entry, (CFDictionaryRef)update_item); 170 | if (status != errSecSuccess) { 171 | if (status == errSecItemNotFound) return; 172 | printf("[ERROR] SecItemUpdate() failed! error = %d\n", (int)status); 173 | printToStdOut(@" error entry: %@\n", update_item); 174 | return; 175 | } 176 | 177 | printToStdOut(@">> Update v_Data to: %@\n", [value dataUsingEncoding:NSUTF8StringEncoding]); 178 | } 179 | 180 | if (result != NULL) 181 | CFRelease(result); 182 | } 183 | 184 | void keychain_delete_entry(CFTypeRef kSecClassType, NSString *access_group, NSString *service, NSString *account) 185 | { 186 | NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 187 | [query setObject:(id)kSecClassType forKey:(id)kSecClass]; 188 | [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit]; 189 | if (!access_group) { 190 | printf("[ERROR] --group kSecAttrAccessGroup missed.\n"); 191 | return; 192 | } else { 193 | [query setObject:(id)access_group forKey:(id)kSecAttrAccessGroup]; 194 | } 195 | if ((service) && (kSecClassType == kSecClassGenericPassword)) 196 | [query setObject:(id)service forKey:(id)kSecAttrService]; 197 | if ((account) && (kSecClassType == kSecClassGenericPassword)) 198 | [query setObject:(id)account forKey:(id)kSecAttrAccount]; 199 | 200 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 201 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef]; 202 | [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 203 | 204 | CFTypeRef result = NULL; 205 | OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, &result); 206 | if (status != errSecSuccess) { 207 | if (status == errSecItemNotFound) return; 208 | printf("[ERROR] SecItemCopyMatching() failed! error = %d\n", (int)status); 209 | return; 210 | } 211 | 212 | NSArray *keychain_entrys = (NSArray *)result; 213 | for (int i = 0; i < keychain_entrys.count; i++) { 214 | CFDictionaryRef dictionary = (CFDictionaryRef)keychain_entrys[i]; 215 | 216 | OSStatus status = SecItemDelete((CFDictionaryRef)dictionary); 217 | if (status != errSecSuccess) { 218 | printf("[ERROR] SecItemDelete() failed! error = %d\n", (int)status); 219 | return; 220 | } 221 | 222 | printToStdOut(@">> deleted: %@\n", (NSDictionary*)keychain_entrys[i]); 223 | } 224 | 225 | if (result != NULL) 226 | CFRelease(result); 227 | } 228 | 229 | int main(int argc, char **argv, char **envp) 230 | { 231 | id pool = [NSAutoreleasePool new]; 232 | 233 | int cmd = KCCMD_LIST; 234 | NSMutableArray *arraySecClass = [[NSMutableArray alloc] init]; 235 | 236 | NSString *access_group = nil; 237 | NSString *service_name = nil; 238 | NSString *account_name = nil; 239 | NSString *value_data = nil; 240 | 241 | int opt; 242 | const char *shortopts = "dg:s:a:v:GNICKUDh"; 243 | const struct option longopts[] = { 244 | // dump keychain groups 245 | {"dump", 0, NULL, 'd'}, 246 | {"group", 1, NULL, 'g'}, 247 | {"service", 1, NULL, 's'}, 248 | {"account", 1, NULL, 'a'}, 249 | {"value", 1, NULL, 'v'}, 250 | 251 | // SecClass selector 252 | {"generic-password", 0, NULL, 'G'}, // kSecClassGenericPassword 253 | {"internet-password", 0, NULL, 'N'}, // kSecClassInternetPassword 254 | {"identity", 0, NULL, 'I'}, // kSecClassIdentity 255 | {"certificate", 0, NULL, 'C'}, // kSecClassCertificate 256 | {"classKey", 0, NULL, 'K'}, // kSecClassKey 257 | 258 | // options 259 | {"update", 0, NULL, 'U'}, 260 | {"delete", 0, NULL, 'D'}, 261 | 262 | {"help", 0, NULL, 'h'}, 263 | {NULL, 0, NULL, 0} 264 | }; 265 | 266 | while((opt = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { 267 | switch (opt) { 268 | case 'd': 269 | dumpKeychainAccessGroups(); 270 | return 0; 271 | 272 | case 'g': 273 | access_group = [NSString stringWithUTF8String:optarg]; 274 | break; 275 | case 's': 276 | service_name = [NSString stringWithUTF8String:optarg]; 277 | break; 278 | case 'a': 279 | account_name = [NSString stringWithUTF8String:optarg]; 280 | break; 281 | case 'v': 282 | value_data = [NSString stringWithUTF8String:optarg]; 283 | break; 284 | 285 | case 'G': 286 | [arraySecClass addObject:(id)kSecClassGenericPassword]; 287 | break; 288 | case 'N': 289 | [arraySecClass addObject:(id)kSecClassInternetPassword]; 290 | break; 291 | case 'I': 292 | [arraySecClass addObject:(id)kSecClassIdentity]; 293 | break; 294 | case 'C': 295 | [arraySecClass addObject:(id)kSecClassCertificate]; 296 | break; 297 | case 'K': 298 | [arraySecClass addObject:(id)kSecClassKey]; 299 | break; 300 | 301 | case 'U': 302 | cmd = KCCMD_UPDATE; 303 | break; 304 | case 'D': 305 | cmd = KCCMD_DELETE; 306 | break; 307 | 308 | case 'h': 309 | printUsage(argv[0]); 310 | return 0; 311 | case '?': 312 | printf("Usage: %s [options]\ntype \"%s -h\" for more help.\n", argv[0], argv[0]); 313 | return 0; 314 | } 315 | } 316 | 317 | if (arraySecClass.count == 0) { 318 | [arraySecClass addObject:(id)kSecClassGenericPassword]; // genp 319 | /*if (cmd == KCCMD_LIST) { 320 | [arraySecClass addObject:(id)kSecClassInternetPassword]; // inet 321 | [arraySecClass addObject:(id)kSecClassIdentity]; // idnt 322 | [arraySecClass addObject:(id)kSecClassCertificate]; // cert 323 | [arraySecClass addObject:(id)kSecClassKey]; // keys 324 | }*/ 325 | } 326 | 327 | for (id kSecClassType in (NSArray *)arraySecClass) { 328 | //printToStdOut(@">>> SecClass(%@):\n", kSecClassType); 329 | switch (cmd) { 330 | case KCCMD_UPDATE: 331 | keychain_update_entry(kSecClassType, access_group, service_name, account_name, value_data); 332 | break; 333 | case KCCMD_DELETE: 334 | keychain_delete_entry(kSecClassType, access_group, service_name, account_name); 335 | break; 336 | 337 | case KCCMD_LIST: 338 | default: 339 | keychain_list_entry(kSecClassType, access_group, service_name, account_name); 340 | break; 341 | } 342 | } 343 | 344 | [pool drain]; 345 | return 0; 346 | } 347 | 348 | // vim:ft=objc -------------------------------------------------------------------------------- /scripts/dump_NSUserDefaults.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | import os 6 | import re 7 | 8 | def is_guid(dir_name): 9 | return re.match(r"[\da-fA-F]+-[\da-fA-F]+-[\da-fA-F]+-[\da-fA-F]+-[\da-fA-F]+", dir_name) 10 | 11 | def is_apple_plist(file_name): 12 | return re.match(r"com.apple.[^.]+.plist", file_name) 13 | 14 | def main(): 15 | # iOS7: /var/mobile/Applications//Library/Preferences/.plist 16 | # iOS8: /var/mobile/Containers/Data/Application//Library/Preferences/.plist 17 | AppRoot = "/var/mobile/Applications/" 18 | if (not os.path.isdir(AppRoot)): 19 | AppRoot = "/var/mobile/Containers/Data/Application/" 20 | 21 | for d in os.listdir(AppRoot): 22 | if (os.path.isdir(AppRoot+d) and is_guid(d)): 23 | path = "%s%s/Library/Preferences/" % (AppRoot, d) 24 | for f in os.listdir(path): 25 | if (not is_apple_plist(f)): 26 | filename = "%s%s" % (path, f) 27 | print ">>> %s" % f 28 | os.system("plutil %s" % (filename)) 29 | print " " 30 | 31 | 32 | main() 33 | -------------------------------------------------------------------------------- /wifi_passwords.mm: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #define KEYCHAIN_SVCE_AIRPORT "AirPort" 4 | #define KEYCHAIN_ACCT_NAME "acct" 5 | 6 | void keychain_wifi_passwords() 7 | { 8 | NSMutableArray *acct_name = [NSMutableArray array]; 9 | 10 | // form KeyChain get AirPort.acct (Wifi Name) 11 | { 12 | NSMutableDictionary *query = [NSMutableDictionary dictionary]; 13 | 14 | [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; 15 | [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; 16 | [query setObject:(__bridge id)@KEYCHAIN_SVCE_AIRPORT forKey:(__bridge id)kSecAttrService]; 17 | [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes]; 18 | 19 | CFTypeRef result = NULL; 20 | OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); 21 | if (status != errSecSuccess) { 22 | printf("[ERROR] SecItemCopyMatching() failed! error = %d\n", (int)status); 23 | return; 24 | } 25 | 26 | NSArray *wifi_list = (NSArray *)result; 27 | for (int i = 0; i < wifi_list.count; i++) { 28 | NSDictionary *wifi = (NSDictionary*)wifi_list[i]; 29 | // get wifi name 30 | [acct_name addObject:wifi[@KEYCHAIN_ACCT_NAME]]; 31 | } 32 | 33 | if (result != NULL) { 34 | CFRelease(result); 35 | } 36 | } 37 | 38 | // get password for each AirPort.acct 39 | { 40 | for (NSString *acct in acct_name) { 41 | NSMutableDictionary *query = [NSMutableDictionary dictionary]; 42 | 43 | [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; 44 | [query setObject:(__bridge id)@KEYCHAIN_SVCE_AIRPORT forKey:(__bridge id)kSecAttrService]; 45 | [query setObject:acct forKey:(__bridge id)kSecAttrAccount]; 46 | [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; 47 | 48 | CFTypeRef result = NULL; 49 | OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); 50 | if (status != errSecSuccess) { 51 | printf("[ERROR] SecItemCopyMatching() failed! error = %d\n", (int)status); 52 | return; 53 | } 54 | 55 | NSData *password = (NSData *)result; 56 | NSString *output = [[NSString alloc] initWithData:password encoding:NSASCIIStringEncoding]; 57 | printf("%s: %s\n", [acct cStringUsingEncoding:NSUTF8StringEncoding], [output cStringUsingEncoding:NSUTF8StringEncoding]); 58 | 59 | if (result != NULL) { 60 | CFRelease(result); 61 | } 62 | } 63 | } 64 | } 65 | 66 | int main(int argc, char **argv, char **envp) 67 | { 68 | keychain_wifi_passwords(); 69 | return 0; 70 | } 71 | 72 | // vim:ft=objc 73 | --------------------------------------------------------------------------------