|
| 1 | +import logging |
| 2 | +import os |
| 3 | +import uuid |
| 4 | + |
| 5 | +from chomper.core import Chomper |
| 6 | +from chomper.const import OS_IOS |
| 7 | +from chomper.os.ios.options import IosOptions |
| 8 | + |
| 9 | +base_path = os.path.abspath(os.path.dirname(__file__)) |
| 10 | + |
| 11 | +log_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s" |
| 12 | +logging.basicConfig( |
| 13 | + format=log_format, |
| 14 | + level=logging.INFO, |
| 15 | +) |
| 16 | + |
| 17 | +logger = logging.getLogger(__name__) |
| 18 | + |
| 19 | + |
| 20 | +def create_emulator(): |
| 21 | + options = IosOptions(enable_objc=True, enable_ui_kit=True) |
| 22 | + emu = Chomper( |
| 23 | + os_type=OS_IOS, |
| 24 | + logger=logger, |
| 25 | + rootfs_path=os.path.join(base_path, "ios/rootfs"), |
| 26 | + os_options=options, |
| 27 | + ) |
| 28 | + return emu |
| 29 | + |
| 30 | + |
| 31 | +def objc_get_class(emu, class_name): |
| 32 | + return emu.call_symbol("_objc_getClass", emu.create_string(class_name)) |
| 33 | + |
| 34 | + |
| 35 | +def objc_sel_register_name(emu, sel_name): |
| 36 | + return emu.call_symbol("_sel_registerName", emu.create_string(sel_name)) |
| 37 | + |
| 38 | + |
| 39 | +def create_ns_string(emu, s): |
| 40 | + ns_string_class = objc_get_class(emu, "NSString") |
| 41 | + string_with_utf8_string_sel = objc_sel_register_name(emu, "stringWithUTF8String:") |
| 42 | + obj = emu.call_symbol( |
| 43 | + "_objc_msgSend", |
| 44 | + ns_string_class, |
| 45 | + string_with_utf8_string_sel, |
| 46 | + emu.create_string(s), |
| 47 | + ) |
| 48 | + return obj |
| 49 | + |
| 50 | + |
| 51 | +def read_ns_string(emu, obj): |
| 52 | + c_string_using_encoding_sel = objc_sel_register_name(emu, "cStringUsingEncoding:") |
| 53 | + ptr = emu.call_symbol("_objc_msgSend", obj, c_string_using_encoding_sel, 4) |
| 54 | + return emu.read_string(ptr) |
| 55 | + |
| 56 | + |
| 57 | +def hook_pass(uc, address, size, user_data): |
| 58 | + pass |
| 59 | + |
| 60 | + |
| 61 | +def hook_retval(retval): |
| 62 | + def decorator(uc, address, size, user_data): |
| 63 | + return retval |
| 64 | + |
| 65 | + return decorator |
| 66 | + |
| 67 | + |
| 68 | +def hook_ns_bundle(emu): |
| 69 | + ns_mutable_dictionary_cls = objc_get_class(emu, "NSMutableDictionary") |
| 70 | + dictionary_with_object_for_key_sel = objc_sel_register_name(emu, "dictionaryWithObject:forKey:") |
| 71 | + add_object_for_key_sel = objc_sel_register_name(emu, "addObject:forKey:") |
| 72 | + |
| 73 | + bundle_identifier = create_ns_string(emu, "com.ceair.b2m") |
| 74 | + executable_path = create_ns_string(emu, f"/var/containers/Bundle/Application" |
| 75 | + f"/{uuid.uuid4()}/com.ceair.b2m/ceair_iOS_branch") |
| 76 | + |
| 77 | + bundle_info_directory = emu.call_symbol( |
| 78 | + "_objc_msgSend", |
| 79 | + ns_mutable_dictionary_cls, |
| 80 | + dictionary_with_object_for_key_sel, |
| 81 | + create_ns_string(emu, "9.4.7"), |
| 82 | + create_ns_string(emu, "CFBundleShortVersionString"), |
| 83 | + ) |
| 84 | + |
| 85 | + emu.call_symbol( |
| 86 | + "_objc_msgSend", |
| 87 | + bundle_info_directory, |
| 88 | + add_object_for_key_sel, |
| 89 | + executable_path, |
| 90 | + create_ns_string(emu, "CFBundleExecutable"), |
| 91 | + ) |
| 92 | + |
| 93 | + emu.add_interceptor("-[NSBundle initWithPath:]", hook_pass) |
| 94 | + emu.add_interceptor("-[NSBundle bundleIdentifier]", hook_retval(bundle_identifier)) |
| 95 | + emu.add_interceptor("-[NSBundle executablePath]", hook_retval(executable_path)) |
| 96 | + emu.add_interceptor("-[NSBundle infoDictionary]", hook_retval(bundle_info_directory)) |
| 97 | + |
| 98 | + |
| 99 | +def hook_ns_locale(emu): |
| 100 | + ns_array_cls = objc_get_class(emu, "NSArray") |
| 101 | + array_with_object_sel = objc_sel_register_name(emu, "arrayWithObject:") |
| 102 | + |
| 103 | + preferred_languages = emu.call_symbol( |
| 104 | + "_objc_msgSend", |
| 105 | + ns_array_cls, |
| 106 | + array_with_object_sel, |
| 107 | + create_ns_string(emu, "zh-cn"), |
| 108 | + ) |
| 109 | + |
| 110 | + emu.add_interceptor("+[NSLocale preferredLanguages]", hook_retval(preferred_languages)) |
| 111 | + |
| 112 | + |
| 113 | +def hook_ui_device(emu): |
| 114 | + system_version = create_ns_string(emu, "14.4.0") |
| 115 | + device_name = create_ns_string(emu, "iPhone") |
| 116 | + device_model = create_ns_string(emu, "iPhone13,1") |
| 117 | + |
| 118 | + emu.add_interceptor("-[UIDevice systemVersion]", hook_retval(system_version)) |
| 119 | + emu.add_interceptor("-[UIDevice name]", hook_retval(device_name)) |
| 120 | + emu.add_interceptor("-[UIDevice model]", hook_retval(device_model)) |
| 121 | + |
| 122 | + |
| 123 | +def main(): |
| 124 | + emu = create_emulator() |
| 125 | + |
| 126 | + hook_ns_bundle(emu) |
| 127 | + hook_ns_locale(emu) |
| 128 | + hook_ui_device(emu) |
| 129 | + |
| 130 | + emu.add_interceptor("_fopen", hook_retval(0)) |
| 131 | + |
| 132 | + emu.load_module(os.path.join(base_path, "ios/apps/com.csair.MBP/CSMBP-AppStore-Package")) |
| 133 | + |
| 134 | + ali_tiger_tally_class = objc_get_class(emu, "AliTigerTally") |
| 135 | + |
| 136 | + shared_instance_sel = objc_sel_register_name(emu, "sharedInstance") |
| 137 | + initialize_sel = objc_sel_register_name(emu, "initialize:") |
| 138 | + vmp_sign_sel = objc_sel_register_name(emu, "vmpSign:") |
| 139 | + data_using_encoding_sel = objc_sel_register_name(emu, "dataUsingEncoding:") |
| 140 | + |
| 141 | + ali_tiger_tally_instance = emu.call_symbol("_objc_msgSend", ali_tiger_tally_class, shared_instance_sel) |
| 142 | + |
| 143 | + app_key = create_ns_string(emu, "xPEj7uv0KuziQnXUyPIBNUjnDvvHuW09VOYFuLYBcY-jV6fgqmfy5B1y75_iSuRM5U2zNq7MRoR9N1F-UthTEgv-QBWk68gr95BrAySzWuDzt08FrkeBZWQCGyZ0iAybalYLOJEF7nkKBtmDGLewcw==",) |
| 144 | + emu.call_symbol("_objc_msgSend", ali_tiger_tally_instance, initialize_sel, app_key) |
| 145 | + |
| 146 | + encrypt_str = create_ns_string(emu, '{"biClassId":["2","3","4"]}') |
| 147 | + encrypt_bytes = emu.call_symbol("_objc_msgSend", encrypt_str, data_using_encoding_sel, 1) |
| 148 | + |
| 149 | + vmp_sign = emu.call_symbol("_objc_msgSend", ali_tiger_tally_instance, vmp_sign_sel, encrypt_bytes) |
| 150 | + |
| 151 | + logger.info("vmp sign: %s", read_ns_string(emu, vmp_sign)) |
| 152 | + |
| 153 | + |
| 154 | +if __name__ == "__main__": |
| 155 | + main() |
0 commit comments