diff --git a/examples/example_ios_ali_vmp_sign.py b/examples/example_ios_ali_vmp_sign.py index e676aeb..5a8915d 100644 --- a/examples/example_ios_ali_vmp_sign.py +++ b/examples/example_ios_ali_vmp_sign.py @@ -5,6 +5,7 @@ from chomper import Chomper from chomper.const import ARCH_ARM64, OS_IOS from chomper.objc import ObjC +from chomper.utils import pyobj2nsobj base_path = os.path.abspath(os.path.dirname(__file__)) @@ -28,53 +29,24 @@ def decorator(uc, address, size, user_data): return decorator -def hook_ns_bundle(emu, objc): - bundle_identifier = objc.msg_send("NSString", "stringWithUTF8String:", "com.ceair.b2m") +def hook_ns_bundle(emu): + executable_path = f"/var/containers/Bundle/Application/{uuid.uuid4()}/com.ceair.b2m/ceair_iOS_branch" - executable_path = objc.msg_send( - "NSString", - "stringWithUTF8String:", - f"/var/containers/Bundle/Application/{uuid.uuid4()}/com.ceair.b2m/ceair_iOS_branch", - ) - - bundle_info_directory = objc.msg_send( - "NSMutableDictionary", - "dictionaryWithObject:forKey:", - objc.msg_send("NSString", "stringWithUTF8String:", "9.4.7"), - objc.msg_send("NSString", "stringWithUTF8String:", "CFBundleShortVersionString"), - ) - - objc.msg_send( - bundle_info_directory, - "addObject:forKey:", - executable_path, - objc.msg_send("NSString", "stringWithUTF8String:", "CFBundleExecutable"), - ) + bundle_info = { + "CFBundleShortVersionString": "9.4.7", + "CFBundleExecutable": executable_path, + } emu.add_interceptor("-[NSBundle initWithPath:]", hook_skip) - emu.add_interceptor("-[NSBundle bundleIdentifier]", hook_retval(bundle_identifier)) - emu.add_interceptor("-[NSBundle executablePath]", hook_retval(executable_path)) - emu.add_interceptor("-[NSBundle infoDictionary]", hook_retval(bundle_info_directory)) - - -def hook_ns_locale(emu, objc): - preferred_languages = objc.msg_send( - "NSArray", - "arrayWithObject:", - objc.msg_send("NSString", "stringWithUTF8String:", "zh-cn") - ) - - emu.add_interceptor("+[NSLocale preferredLanguages]", hook_retval(preferred_languages)) + emu.add_interceptor("-[NSBundle bundleIdentifier]", hook_retval(pyobj2nsobj(emu, "com.ceair.b2m"))) + emu.add_interceptor("-[NSBundle executablePath]", hook_retval(pyobj2nsobj(emu, executable_path))) + emu.add_interceptor("-[NSBundle infoDictionary]", hook_retval(pyobj2nsobj(emu, bundle_info))) -def hook_ui_device(emu, objc): - system_version = objc.msg_send("NSString", "stringWithUTF8String:", "14.4.0") - device_name = objc.msg_send("NSString", "stringWithUTF8String:", "iPhone") - device_model = objc.msg_send("NSString", "stringWithUTF8String:", "iPhone13,1") - - emu.add_interceptor("-[UIDevice systemVersion]", hook_retval(system_version)) - emu.add_interceptor("-[UIDevice name]", hook_retval(device_name)) - emu.add_interceptor("-[UIDevice model]", hook_retval(device_model)) +def hook_ui_device(emu): + emu.add_interceptor("-[UIDevice systemVersion]", hook_retval(pyobj2nsobj(emu, "14.4.0"))) + emu.add_interceptor("-[UIDevice name]", hook_retval(pyobj2nsobj(emu, "iPhone"))) + emu.add_interceptor("-[UIDevice model]", hook_retval(pyobj2nsobj(emu, "iPhone13,1"))) def main(): @@ -88,9 +60,8 @@ def main(): objc = ObjC(emu) - hook_ns_bundle(emu, objc) - hook_ns_locale(emu, objc) - hook_ui_device(emu, objc) + hook_ns_bundle(emu) + hook_ui_device(emu) # Skip a file operation emu.add_interceptor("_fopen", hook_retval(0)) @@ -99,16 +70,11 @@ def main(): ali_tiger_tally_instance = objc.msg_send("AliTigerTally", "sharedInstance") - app_key = objc.msg_send( - "NSString", - "stringWithUTF8String:", - "xPEj7uv0KuziQnXUyPIBNUjnDvvHuW09VOYFuLYBcY-jV6fgqmfy5B1y75_iSuRM5U2zNq7MRoR9N1F-UthTEgv-QBWk68gr95BrAySzWuDzt08FrkeBZWQCGyZ0iAybalYLOJEF7nkKBtmDGLewcw==", - ) - - objc.msg_send(ali_tiger_tally_instance, "initialize:", app_key) + app_key = "xPEj7uv0KuziQnXUyPIBNUjnDvvHuW09VOYFuLYBcY-jV6fgqmfy5B1y75_iSuRM5U2zNq7MRoR9N1F-UthTEgv-QBWk68gr95BrAySzWuDzt08FrkeBZWQCGyZ0iAybalYLOJEF7nkKBtmDGLewcw==" + objc.msg_send(ali_tiger_tally_instance, "initialize:", pyobj2nsobj(emu, app_key)) - encrypt_str = objc.msg_send("NSString", "stringWithUTF8String:", '{"biClassId":["2","3","4"]}') - encrypt_bytes = objc.msg_send(encrypt_str, "dataUsingEncoding:", 1) + encrypt_str = '{"biClassId":["2","3","4"]}' + encrypt_bytes = objc.msg_send(pyobj2nsobj(emu, encrypt_str), "dataUsingEncoding:", 1) vmp_sign = objc.msg_send(ali_tiger_tally_instance, "vmpSign:", encrypt_bytes) logger.info("vmp sign: %s", emu.read_string(objc.msg_send(vmp_sign, "cStringUsingEncoding:", 4))) diff --git a/examples/example_ios_bangbang.py b/examples/example_ios_bangbang.py index b4823e0..d6a5ae4 100644 --- a/examples/example_ios_bangbang.py +++ b/examples/example_ios_bangbang.py @@ -4,6 +4,7 @@ from chomper import Chomper from chomper.const import ARCH_ARM64, OS_IOS from chomper.objc import ObjC +from chomper.utils import pyobj2nsobj base_path = os.path.abspath(os.path.dirname(__file__)) @@ -29,21 +30,10 @@ def hook_sec_item(emu): emu.add_interceptor("_CFRelease", hook_retval(0)) -def hook_ns_user_defaults(emu, objc): - bangcle_debug_log_key = objc.msg_send("NSString", "stringWithUTF8String:", "N") - - emu.add_interceptor("+[NSUserDefaults(NSUserDefaults) standardUserDefaults]", hook_retval(0)) - emu.add_interceptor("-[NSUserDefaults(NSUserDefaults) objectForKey:]", hook_retval(bangcle_debug_log_key)) - - -def hook_ui_device(emu, objc): - system_version = objc.msg_send("NSString", "stringWithUTF8String:", "14.4.0") - device_name = objc.msg_send("NSString", "stringWithUTF8String:", "iPhone") - device_model = objc.msg_send("NSString", "stringWithUTF8String:", "iPhone13,1") - - emu.add_interceptor("-[UIDevice systemVersion]", hook_retval(system_version)) - emu.add_interceptor("-[UIDevice name]", hook_retval(device_name)) - emu.add_interceptor("-[UIDevice model]", hook_retval(device_model)) +def hook_ui_device(emu): + emu.add_interceptor("-[UIDevice systemVersion]", hook_retval(pyobj2nsobj(emu, "14.4.0"))) + emu.add_interceptor("-[UIDevice name]", hook_retval(pyobj2nsobj(emu, "iPhone"))) + emu.add_interceptor("-[UIDevice model]", hook_retval(pyobj2nsobj(emu, "iPhone13,1"))) def main(): @@ -58,23 +48,20 @@ def main(): objc = ObjC(emu) hook_sec_item(emu) - hook_ns_user_defaults(emu, objc) - hook_ui_device(emu, objc) + hook_ui_device(emu) emu.load_module(os.path.join(base_path, "ios/apps/com.ceair.b2m/ceair_iOS_branch")) # Call encryption - encrypt_data = 'S{"osVersion":"14.2.1","os":"iOS","deviceModel":"iPhone","channelNo":"APPSTORE"}' - encrypt_input = objc.msg_send("NSString", "stringWithUTF8String:", encrypt_data) + encrypt_str = 'S{"osVersion":"14.2.1","os":"iOS","deviceModel":"iPhone","channelNo":"APPSTORE"}' + encrypt_result = objc.msg_send("BangSafeSDK", "checkcode:dataStyle:", pyobj2nsobj(emu, encrypt_str), 2) - encrypt_result = objc.msg_send("BangSafeSDK", "checkcode:dataStyle:", encrypt_input, 2) logger.info("encrypt_result: %s", emu.read_string(objc.msg_send(encrypt_result, "cStringUsingEncoding:", 4))) # Call decryption - decrypt_data = "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" - decrypt_input = objc.msg_send("NSString", "stringWithUTF8String:", decrypt_data) + decrypt_str = "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" + decrypt_result = objc.msg_send("BangSafeSDK", "decheckcode:", pyobj2nsobj(emu, decrypt_str)) - decrypt_result = objc.msg_send("BangSafeSDK", "decheckcode:", decrypt_input) logger.info("decrypt_result: %s", emu.read_string(objc.msg_send(decrypt_result, "cStringUsingEncoding:", 4))) diff --git a/examples/example_ios_ijm.py b/examples/example_ios_ijm.py index be2035f..8cf06e5 100644 --- a/examples/example_ios_ijm.py +++ b/examples/example_ios_ijm.py @@ -4,6 +4,7 @@ from chomper import Chomper from chomper.const import ARCH_ARM64, OS_IOS from chomper.objc import ObjC +from chomper.utils import pyobj2nsobj base_path = os.path.abspath(os.path.dirname(__file__)) @@ -42,16 +43,15 @@ def main(): emu.add_interceptor(czair.base + 0x1038F0004, hook_retval(1)) # Call encryption - encrypt_input = objc.msg_send("NSString", "stringWithUTF8String:", '{"biClassId":["2","3","4"]}') + encrypt_str = '{"biClassId":["2","3","4"]}' + encrypt_result = objc.msg_send("JMBox125", "JMBox167:JMBox501:", pyobj2nsobj(emu, encrypt_str), 1) - encrypt_result = objc.msg_send("JMBox125", "JMBox167:JMBox501:", encrypt_input, 1) logger.info("encrypt_result: %s", emu.read_string(objc.msg_send(encrypt_result, "cStringUsingEncoding:", 4))) # Call decryption - decrypt_data = "XKQYFMCP9Eb0IUzrQ9KaRRvTeFcYYyLcInrS/IWp6be1+VZa14GanCrzeb3DR45HW+XH0xiZLA5WUjUcXnlpM+CC6EtauUDUxCLap3QPWRyewLUosCB/ESHE7341DQca6lx5KFcP0XCkBpGlEKpACR5v7TwNBxc62auNBDvmEY422LTAUEEBrC8FDE+Y4DS2IJTLN6h9f7hdmQ4zUnY4cwyZXwgdIoH+bVuNy6TSw1JjQaFF/fLLHVZOQovrMcjtTpMZGr8xOSoW/+msiZzKwET3" - decrypt_input = objc.msg_send("NSString", "stringWithUTF8String:", decrypt_data) + decrypt_str = "XKQYFMCP9Eb0IUzrQ9KaRRvTeFcYYyLcInrS/IWp6be1+VZa14GanCrzeb3DR45HW+XH0xiZLA5WUjUcXnlpM+CC6EtauUDUxCLap3QPWRyewLUosCB/ESHE7341DQca6lx5KFcP0XCkBpGlEKpACR5v7TwNBxc62auNBDvmEY422LTAUEEBrC8FDE+Y4DS2IJTLN6h9f7hdmQ4zUnY4cwyZXwgdIoH+bVuNy6TSw1JjQaFF/fLLHVZOQovrMcjtTpMZGr8xOSoW/+msiZzKwET3" + decrypt_result = objc.msg_send("JMBox125", "JMBox167:JMBox501:", pyobj2nsobj(emu, decrypt_str), 1) - decrypt_result = objc.msg_send("JMBox125", "JMBox167:JMBox501:", decrypt_input, 1) logger.info("decrypt_result: %s", emu.read_string(objc.msg_send(decrypt_result, "cStringUsingEncoding:", 4))) diff --git a/src/chomper/core.py b/src/chomper/core.py index ceed99a..e723d86 100644 --- a/src/chomper/core.py +++ b/src/chomper/core.py @@ -190,10 +190,10 @@ def _setup_emulator(self, enable_vfp: bool = True): if self.arch == arm_arch and enable_vfp: self._enable_vfp() - def _start_emulate(self, address: int, *args: int): + def _start_emulate(self, address: int, *args: int) -> int: """Start emulate at the specified address.""" + context = self.uc.context_save() stop_addr = self.create_buffer(8) - # stop_addr = 0 for index, value in enumerate(args): self.set_arg(index, value) @@ -208,12 +208,18 @@ def _start_emulate(self, address: int, *args: int): self.logger.info(f"Start emulate at {self.debug_symbol(address)}") self.uc.emu_start(address, stop_addr) + return self.get_retval() + except UcError as e: self.crash("Unknown reason", from_exc=e) finally: + self.uc.context_restore(context) self.free(stop_addr) + # Pass type hints + return 0 + def find_module(self, name_or_addr: Union[str, int]) -> Optional[Module]: """Find module by name or address.""" for module in self.modules: @@ -739,12 +745,8 @@ def call_symbol(self, symbol_name: str, *args: int) -> int: symbol = self.find_symbol(symbol_name) address = symbol.address - self._start_emulate(address, *args) - - return self.get_retval() + return self._start_emulate(address, *args) def call_address(self, address: int, *args: int) -> int: """Call function at the address.""" - self._start_emulate(address, *args) - - return self.get_retval() + return self._start_emulate(address, *args) diff --git a/src/chomper/objc.py b/src/chomper/objc.py index a658f87..18478bc 100644 --- a/src/chomper/objc.py +++ b/src/chomper/objc.py @@ -7,32 +7,25 @@ class ObjC: def __init__(self, emu): self.emu = emu - self._class_cache = {} - self._sel_cache = {} - def get_class(self, class_name: str) -> int: """Get class by name.""" - if class_name in self._class_cache: - return self._class_cache[class_name] - - class_name_ptr = self.emu.create_string(class_name) + name_ptr = self.emu.create_string(class_name) - cls = self.emu.call_symbol("_objc_getClass", class_name_ptr) - self._class_cache[class_name] = cls + try: + return self.emu.call_symbol("_objc_getClass", name_ptr) - return cls + finally: + self.emu.free(name_ptr) def get_sel(self, sel_name: str) -> int: """Get selector by name.""" - if sel_name in self._sel_cache: - return self._sel_cache[sel_name] + name_ptr = self.emu.create_string(sel_name) - sel_name_ptr = self.emu.create_string(sel_name) - - sel = self.emu.call_symbol("_sel_registerName", sel_name_ptr) - self._sel_cache[sel_name] = sel + try: + return self.emu.call_symbol("_sel_registerName", name_ptr) - return sel + finally: + self.emu.free(name_ptr) def msg_send(self, receiver: Union[int, str], sel: Union[int, str], *args) -> int: """Send message to Objective-C runtime. @@ -47,25 +40,25 @@ def msg_send(self, receiver: Union[int, str], sel: Union[int, str], *args) -> in receiver = self.get_class(receiver) if isinstance(receiver, str) else receiver sel = self.get_sel(sel) if isinstance(sel, str) else sel - c_strs = [] - args_ = [] + str_ptrs = [] + new_args = [] for arg in args: if isinstance(arg, str): - c_str = self.emu.create_string(arg) + str_ptr = self.emu.create_string(arg) - c_strs.append(c_str) - args_.append(c_str) + str_ptrs.append(str_ptr) + new_args.append(str_ptr) else: - args_.append(arg) + new_args.append(arg) try: - return self.emu.call_symbol("_objc_msgSend", receiver, sel, *args_) + return self.emu.call_symbol("_objc_msgSend", receiver, sel, *new_args) finally: - for c_str in c_strs: - self.emu.free(c_str) + for str_ptr in str_ptrs: + self.emu.free(str_ptr) def release(self, obj: int): """Release object.""" diff --git a/src/chomper/os/ios/fixup.py b/src/chomper/os/ios/fixup.py index eb7b121..b0567d8 100644 --- a/src/chomper/os/ios/fixup.py +++ b/src/chomper/os/ios/fixup.py @@ -276,9 +276,11 @@ def fixup_cfstring_section(self, binary: lief.MachO.Binary, module_base: int): offset = 0 while offset < section.size: - address = module_base + start + offset + 0x10 - self.relocate_pointer(module_base, address) self.add_refs_relocation(start + offset) + + str_ptr = module_base + start + offset + 0x10 + self.relocate_pointer(module_base, str_ptr) + offset += step def fixup_cf_uni_char_string(self, binary: lief.MachO.Binary): diff --git a/src/chomper/os/ios/hooks.py b/src/chomper/os/ios/hooks.py index 6e6fc47..9ef0228 100644 --- a/src/chomper/os/ios/hooks.py +++ b/src/chomper/os/ios/hooks.py @@ -7,6 +7,8 @@ from unicorn.unicorn import UC_HOOK_CODE_TYPE +from chomper.utils import pyobj2nsobj + hooks: Dict[str, UC_HOOK_CODE_TYPE] = {} @@ -379,11 +381,95 @@ def hook_dispatch_async(uc, address, size, user_data): return 0 +@register_hook("_uloc_getLanguage") +def hook_uloc_get_language(uc, address, size, user_data): + return 0 + + +@register_hook("_uloc_getScript") +def hook_uloc_get_script(uc, address, size, user_data): + return 0 + + +@register_hook("_uloc_getCountry") +def hook_uloc_get_country(uc, address, size, user_data): + return 0 + + +@register_hook("_uloc_getVariant") +def hook_uloc_get_variant(uc, address, size, user_data): + return 0 + + +@register_hook("_uloc_openKeywords") +def hook_uloc_open_keywords(uc, address, size, user_data): + return 0 + + +@register_hook("_uloc_getDisplayName") +def hook_uloc_get_display_name(uc, address, size, user_data): + return 0 + + +@register_hook("_uloc_getDisplayLanguage") +def hook_uloc_get_display_language(uc, address, size, user_data): + return 0 + + +@register_hook("_uenum_next") +def hook_uenum_next(uc, address, size, user_data): + return 0 + + +@register_hook("_uenum_close") +def hook_uenum_close(uc, address, size, user_data): + return 0 + + +@register_hook("_os_log_type_enabled") +def hook_os_log_type_enabled(uc, address, size, user_data): + return 0 + + +@register_hook("__CFPreferencesCopyAppValueWithContainerAndConfiguration") +def hook_cf_preferences_copy_app_value_with_container_and_configuration( + uc, address, size, user_data +): + emu = user_data["emu"] + + str_ptr = emu.read_pointer(emu.get_arg(0) + 0x10) + key = emu.read_string(str_ptr) + + if key in emu.os.preferences: + return pyobj2nsobj(emu, emu.os.preferences[key]) + + return 0 + + @register_hook("__CFBundleCreateInfoDictFromMainExecutable") def hook_cf_bundle_create_info_dict_from_main_executable(uc, address, size, user_data): return 0 +@register_hook("___CFXPreferencesCopyCurrentApplicationStateWithDeadlockAvoidance") +def hook_cf_x_preferences_copy_current_application_state_with_deadlock_avoidance( + uc, address, size, user_data +): + emu = user_data["emu"] + + return pyobj2nsobj(emu, emu.os.preferences) + + +@register_hook("_CFNotificationCenterGetLocalCenter") +def hook_cf_notification_center_get_local_center(uc, address, size, user_data): + return 0 + + +@register_hook("__CFPrefsClientLog") +def hook_cf_prefs_client_log(uc, address, size, user_data): + return 0 + + @register_hook("_NSLog") def hook_ns_log(uc, address, size, user_data): return 0 diff --git a/src/chomper/os/ios/os.py b/src/chomper/os/ios/os.py index 56eeb37..188d683 100644 --- a/src/chomper/os/ios/os.py +++ b/src/chomper/os/ios/os.py @@ -21,6 +21,23 @@ def __init__(self, emu, **kwargs): self.loader = MachoLoader(emu) + # By hooking functions: + # `__CFPreferencesCopyAppValueWithContainerAndConfiguration`, + # `___CFXPreferencesCopyCurrentApplicationStateWithDeadlockAvoidance`, + # enable the program to obtain preferences. + self.preferences = self._default_preferences.copy() + + @property + def _default_preferences(self) -> dict: + """Define default preferences.""" + return { + "AppleLanguages": [ + "zh-Hans", + "en", + ], + "AppleLocale": "zh-Hans", + } + def _setup_hooks(self): """Initialize the hooks.""" self.emu.hooks.update(get_hooks()) @@ -29,12 +46,12 @@ def _setup_syscall_handlers(self): """Initialize the system call handlers.""" self.emu.syscall_handlers.update(get_syscall_handlers()) - def _init_special_flag(self): - """Set a flag meaning the arch type, which will be read by functions + def _init_magic_vars(self): + """Set flags meaning the arch type and others, which will be read by functions such as `_os_unfair_recursive_lock_lock_with_options`.""" self.emu.uc.mem_map(0xFFFFFC000, 1024) - # arch flag + # arch type self.emu.write_u64(0xFFFFFC023, 2) self.emu.write_u64(0xFFFFFC104, 0x100) @@ -126,7 +143,7 @@ def init_objc(self, module: Module): initialized = self.emu.find_symbol("__ZZ10_objc_initE11initialized") if not self.emu.read_u8(initialized.address): # As the initialization timing before program execution - self._init_special_flag() + self._init_magic_vars() self._init_program_vars() self._init_dyld_vars() self._init_objc_vars() diff --git a/src/chomper/utils.py b/src/chomper/utils.py index b9d170f..7b4a8f5 100644 --- a/src/chomper/utils.py +++ b/src/chomper/utils.py @@ -1,5 +1,7 @@ from ctypes import addressof, create_string_buffer, sizeof, memmove, Structure +from .objc import ObjC + def aligned(x: int, n: int) -> int: """Align `x` based on `n`.""" @@ -11,3 +13,36 @@ def struct2bytes(st: Structure) -> bytes: buffer = create_string_buffer(sizeof(st)) memmove(buffer, addressof(st), sizeof(st)) return buffer.raw + + +def pyobj2nsobj(emu, obj: object) -> int: + """Convert Python object to NS object. + + Raises: + TypeError: If the object type is not supported. + """ + objc = ObjC(emu) + + if isinstance(obj, dict): + ns_obj = objc.msg_send("NSMutableDictionary", "dictionary") + + for key, value in obj.items(): + ns_key = pyobj2nsobj(emu, key) + ns_value = pyobj2nsobj(emu, value) + + objc.msg_send(ns_obj, "setObject:forKey:", ns_value, ns_key) + + elif isinstance(obj, list): + ns_obj = objc.msg_send("NSMutableArray", "array") + + for item in obj: + ns_item = pyobj2nsobj(emu, item) + objc.msg_send(ns_obj, "addObject:", ns_item) + + elif isinstance(obj, str): + ns_obj = objc.msg_send("NSString", "stringWithUTF8String:", obj) + + else: + raise TypeError(f"Unsupported type: {type(obj)}") + + return ns_obj