for module in emulator.modules: logger.info("=> 0x%08x - %s" % (module.base, module.filename)) try: # Run JNI_OnLoad. # JNI_OnLoad will call 'RegisterNatives'. emulator.call_symbol(lib_module, 'JNI_OnLoad', emulator.java_vm.address_ptr, 0x00) # bypass douyin checks path = "vfs/system/bin/app_process32" sz = os.path.getsize(path) vf = VirtualFile("/system/bin/app_process32", misc_utils.my_open(path, os.O_RDONLY), path) emulator.memory.map(0xab006000, sz, UC_PROT_WRITE | UC_PROT_READ, vf, 0) x = XGorgen() data = 'acde74a94e6b493a3399fac83c7c08b35D58B21D9582AF77647FC9902E36AE70f9c001e9334e6e94916682224fbe4e5f00000000000000000000000000000000' data = bytearray(bytes.fromhex(data)) arr = Array("B", data) result = x.leviathan(emulator, 1562848170, arr) print(''.join(['%02x' % b for b in result])) # 037d560d0000903e34fb093f1d21e78f3bdf3fbebe00b124becc # 036d2a7b000010f4d05395b7df8b0ec2b5ec085b938a473a6a51 # 036d2a7b000010f4d05395b7df8b0ec2b5ec085b938a473a6a51 # 0300000000002034d288fe8d6b95b778105cc36eade709d2b500
#lib_module = emulator.load_library("tests/bin/libcms1050.so") # lib_module = emulator.load_library("../deobf/tests/bin/libcms2.so") # lib_module = emulator.load_library("../deobf/cms.so") # Show loaded modules. logger.info("Loaded modules:") for module in emulator.modules: logger.info("=> 0x%08x - %s" % (module.base, module.filename)) try: # bypass douyin checks path = "vfs/system/bin/app_process32" sz = os.path.getsize(path) vf = VirtualFile("/system/bin/app_process32", misc_utils.my_open(path, os.O_RDONLY), path) emulator.memory.map(0xab006000, sz, UC_PROT_WRITE | UC_PROT_READ, vf, 0) # Run JNI_OnLoad. # JNI_OnLoad will call 'RegisterNatives'. emulator.call_symbol(lib_module, 'JNI_OnLoad', emulator.java_vm.address_ptr, 0x00) #8.5 xg基本检测流程 #1.调用meta,传入以下参数,如果不调用meta,leviathan将会返回null,meta的参数直接影响leviathan的结果 print("begin meta") XGorgen.meta(emulator, 101, 0, String("0")) XGorgen.meta(emulator, 102, 0, String("1128")) XGorgen.meta(emulator, 1020, 0, String(""))
def sgmain_init(emulator): # Register Java class. emulator.java_classloader.add_class(HttpUtil) emulator.java_classloader.add_class(UmidAdapter) emulator.java_classloader.add_class(JNICLibrary) emulator.java_classloader.add_class(SPUtility2) emulator.java_classloader.add_class(DeviceInfoCapturer) emulator.java_classloader.add_class(DataReportJniBridge) emulator.java_classloader.add_class(ZipUtils) emulator.java_classloader.add_class(CallbackHelper) emulator.java_classloader.add_class(UserTrackMethodJniBridge) emulator.java_classloader.add_class(UMIDComponent) emulator.java_classloader.add_class(ECMiscInfo) emulator.java_classloader.add_class(MainApplication) emulator.java_classloader.add_class(JNIBridge) emulator.java_classloader.add_class(SecException) emulator.java_classloader.add_class(SGPluginExtras) emulator.java_classloader.add_class(MalDetect) emulator.java_classloader.add_class(NativeReflectUtils) emulator.java_classloader.add_class(SDKUtils) emulator.java_classloader.add_class(MiuiAd) emulator.java_classloader.add_class(TelephonyManagerEx) emulator.java_classloader.add_class(FtTelephonyAdapter) emulator.java_classloader.add_class(FtTelephony) emulator.java_classloader.add_class(FtDeviceInfo) emulator.java_classloader.add_class(ColorOSTelephonyManager) #map [vectors] path = "vfs/system/lib/vectors" vf = VirtualFile("[vectors]", misc_utils.my_open(path, os.O_RDONLY), path) emulator.memory.map(0xffff0000, 0x1000, UC_PROT_EXEC | UC_PROT_READ, vf, 0) # Load all libraries. lib_module = emulator.load_library( "vfs/data/data/fm.xiami.main/lib/libsgmainso-6.4.163.so") lib_module_secbody = emulator.load_library( "vfs/data/data/fm.xiami.main/lib/libsgsecuritybodyso-6.4.95.so") lib_module_avmp = emulator.load_library( "vfs/data/data/fm.xiami.main/lib/libsgavmpso-6.4.35.so") # Show loaded modules. logger.info("Loaded modules:") for module in emulator.modules: logger.info("=> 0x%08x - %s" % (module.base, module.filename)) # act_thread = ActivityThread() app = act_thread.currentApplication(emulator) emulator.call_symbol(lib_module, 'JNI_OnLoad', emulator.java_vm.address_ptr, 0x00) #10101 10102 sgmain o2 = Integer(1) o3 = String("") o4 = String("/data/data/fm.xiami.main/app_SGLib") o5 = String("") pyarr = [app, o2, o3, o4, o5] arr = Array(pyarr) #print(arr) JNICLibrary.doCommandNative(emulator, 10101, arr) o1 = String("main") o2 = String("6.4.163") o3 = String("/data/data/fm.xiami.main/lib/libsgmainso-6.4.163.so") print("begin 10102") arr = Array([o1, o2, o3]) JNICLibrary.doCommandNative(emulator, 10102, arr) #10102 secbody print("secbody JNI_OnLoad") emulator.call_symbol(lib_module_secbody, 'JNI_OnLoad', emulator.java_vm.address_ptr, 0x00) o1 = String("securitybody") o2 = String("6.4.95") o3 = String("/data/data/fm.xiami.main/lib/libsgsecuritybodyso-6.4.95.so") print("begin securitybodyso 10102") arr = Array([o1, o2, o3]) JNICLibrary.doCommandNative(emulator, 10102, arr) #10102 avmp emulator.call_symbol(lib_module_avmp, 'JNI_OnLoad', emulator.java_vm.address_ptr, 0x00) o1 = String("avmp") o2 = String("6.4.35") o3 = String("/data/data/fm.xiami.main/lib/libsgavmpso-6.4.35.so") print("begin avmp 10102") arr = Array([o1, o2, o3]) JNICLibrary.doCommandNative(emulator, 10102, arr)
def load_module(self, filename, do_init=True): m = self.find_module_by_name(filename) if (m != None): return m # logger.debug("Loading module '%s'." % filename) #do sth like linker with open(filename, 'rb') as fstream: #TODO: load elf without Section Header,pyelftools do not support. reader = elf_reader.ELFReader(fstream) # Parse program header (Execution view). # - LOAD (determinate what parts of the ELF file get mapped into memory) load_segments = reader.get_load() # Find bounds of the load segments. bound_low = 0 bound_high = 0 for segment in load_segments: p_memsz = segment["p_memsz"] if p_memsz == 0: continue p_vaddr = segment["p_vaddr"] if bound_low > p_vaddr: bound_low = p_vaddr high = p_vaddr + p_memsz if bound_high < high: bound_high = high # # ''' // Segment addresses in memory. Elf32_Addr seg_start = phdr->p_vaddr + load_bias_; Elf32_Addr seg_end = seg_start + phdr->p_memsz; Elf32_Addr seg_page_start = PAGE_START(seg_start); Elf32_Addr seg_page_end = PAGE_END(seg_end); // File offsets. Elf32_Addr file_start = phdr->p_offset; Elf32_Addr file_end = file_start + phdr->p_filesz; Elf32_Addr seg_file_end = seg_start + phdr->p_filesz; Elf32_Addr file_page_start = PAGE_START(file_start); Elf32_Addr file_length = file_end - file_page_start; if (file_length != 0) { void* seg_addr = mmap((void*)seg_page_start, file_length, PFLAGS_TO_PROT(phdr->p_flags), MAP_FIXED|MAP_PRIVATE, fd_, file_page_start); ''' # Retrieve a base address for this module. load_base = self.mem_reserve(bound_low, bound_high) vf = VirtualFile( misc_utils.system_path_to_vfs_path(self.__vfs_root, filename), misc_utils.my_open(filename, os.O_RDONLY), filename) for segment in load_segments: p_flags = segment["p_flags"] prot = get_segment_protection(p_flags) prot = prot if prot is not 0 else UC_PROT_ALL p_vaddr = segment["p_vaddr"] seg_start = load_base + p_vaddr seg_page_start = page_start(seg_start) p_offset = segment["p_offset"] file_start = p_offset p_filesz = segment["p_filesz"] file_end = file_start + p_filesz file_page_start = page_start(file_start) file_length = file_end - file_page_start assert (file_length > 0) if (file_length > 0): self.emu.memory.map(seg_page_start, file_length, prot, vf, file_page_start) # p_memsz = segment["p_memsz"] seg_end = seg_start + p_memsz seg_page_end = page_end(seg_end) seg_file_end = seg_start + p_filesz seg_file_end = page_end(seg_file_end) ''' void* zeromap = mmap((void*)seg_file_end, seg_page_end - seg_file_end, PFLAGS_TO_PROT(phdr->p_flags), MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); ''' self.emu.memory.map(seg_file_end, seg_page_end - seg_file_end, prot) # # Find init array. init_array_offset, init_array_size = reader.get_init_array() init_array = [] init_offset = reader.get_init() so_needed = reader.get_so_need() for so_name in so_needed: path = misc_utils.vfs_path_to_system_path( self.__vfs_root, so_name) if (not os.path.exists(path)): logger.warn("%s needed by %s do not exist in vfs %s" % (so_name, filename, self.__vfs_root)) continue # libmod = self.load_module(path) # rels = reader.get_rels() symbols = reader.get_symbols() # Resolve all symbols. symbols_resolved = dict() for symbol in symbols: symbol_address = self._elf_get_symval(load_base, symbol) if symbol_address is not None: name = symbol["name"] symbols_resolved[name] = symbol_address # # # Relocate. for rel_name in rels: rel_tbl = rels[rel_name] for rel in rel_tbl: r_info_sym = rel["r_info_sym"] sym = symbols[r_info_sym] sym_value = sym['st_value'] rel_addr = load_base + rel[ 'r_offset'] # Location where relocation should happen rel_info_type = rel['r_info_type'] #print(filename) #print("%x"%rel_addr) # Relocation table for ARM sym_name = reader.get_dyn_string_by_rel_sym(r_info_sym) if rel_info_type == arm.R_ARM_ABS32: if sym_name in symbols_resolved: sym_addr = symbols_resolved[sym_name] value_orig_bytes = self.emu.mu.mem_read( rel_addr, 4) value_orig = int.from_bytes(value_orig_bytes, byteorder='little') #R_ARM_ABS32 how to relocate see android linker source code #*reinterpret_cast<Elf32_Addr*>(reloc) += sym_addr; value = sym_addr + value_orig # Write the new value #print(value) self.emu.mu.mem_write( rel_addr, value.to_bytes(4, byteorder='little')) # # elif rel_info_type in (arm.R_ARM_GLOB_DAT, arm.R_ARM_JUMP_SLOT, arm.R_AARCH64_GLOB_DAT, arm.R_AARCH64_JUMP_SLOT): # Resolve the symbol. #R_ARM_GLOB_DAT,R_ARM_JUMP_SLOT how to relocate see android linker source code #*reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr; if sym_name in symbols_resolved: value = symbols_resolved[sym_name] # Write the new value #print(value) self.emu.mu.mem_write( rel_addr, value.to_bytes(4, byteorder='little')) # # elif rel_info_type in (arm.R_ARM_RELATIVE, arm.R_AARCH64_RELATIVE): if sym_value == 0: # Load address at which it was linked originally. value_orig_bytes = self.emu.mu.mem_read( rel_addr, 4) value_orig = int.from_bytes(value_orig_bytes, byteorder='little') # Create the new value value = load_base + value_orig #print(value) # Write the new value self.emu.mu.mem_write( rel_addr, value.to_bytes(4, byteorder='little')) else: raise NotImplementedError() else: logger.error("Unhandled relocation type %i." % rel_info_type) # # # if (init_offset != 0): init_array.appen(load_base + init_offset) # for _ in range(int(init_array_size / 4)): b = self.emu.mu.mem_read(load_base + init_array_offset, 4) fun_ptr = int.from_bytes(b, byteorder='little', signed=False) if (fun_ptr != 0): init_array.append(fun_ptr) # init_array_offset += 4 # # Store information about loaded module. module = Module(filename, load_base, bound_high - bound_low, symbols_resolved, init_array) self.modules.append(module) #TODO init tls like linker ''' void __libc_init_tls(KernelArgumentBlock& args) { __libc_auxv = args.auxv; unsigned stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE; unsigned stack_size = 128 * 1024; unsigned stack_bottom = stack_top - stack_size; static void* tls[BIONIC_TLS_SLOTS]; static pthread_internal_t thread; thread.tid = gettid(); thread.tls = tls; pthread_attr_init(&thread.attr); pthread_attr_setstack(&thread.attr, (void*) stack_bottom, stack_size); _init_thread(&thread, false); __init_tls(&thread); tls[TLS_SLOT_BIONIC_PREINIT] = &args; } ''' if do_init: ''' for r in self.emu.mu.mem_regions(): print("region begin :0x%08X end:0x%08X, prot:%d"%(r[0], r[1], r[2])) # ''' module.call_init(self.emu) # logger.info("finish load lib %s" % filename) return module
def load_module(self, filename, do_init=True): m = self.find_module_by_name(filename) if (m != None): return m # logger.debug("Loading module '%s'." % filename) #do sth like linker with open(filename, 'rb') as fstream: #TODO: load elf without Section Header,pyelftools do not support. elf = ELFFile(fstream) dynamic = elf.header.e_type == 'ET_DYN' if not dynamic: raise NotImplementedError( "Only ET_DYN is supported at the moment.") # Parse program header (Execution view). # - LOAD (determinate what parts of the ELF file get mapped into memory) load_segments = [ x for x in elf.iter_segments() if x.header.p_type == 'PT_LOAD' ] # Find bounds of the load segments. bound_low = 0 bound_high = 0 for segment in load_segments: if segment.header.p_memsz == 0: continue if bound_low > segment.header.p_vaddr: bound_low = segment.header.p_vaddr high = segment.header.p_vaddr + segment.header.p_memsz if bound_high < high: bound_high = high ''' // Segment addresses in memory. Elf32_Addr seg_start = phdr->p_vaddr + load_bias_; Elf32_Addr seg_end = seg_start + phdr->p_memsz; Elf32_Addr seg_page_start = PAGE_START(seg_start); Elf32_Addr seg_page_end = PAGE_END(seg_end); // File offsets. Elf32_Addr file_start = phdr->p_offset; Elf32_Addr file_end = file_start + phdr->p_filesz; Elf32_Addr seg_file_end = seg_start + phdr->p_filesz; Elf32_Addr file_page_start = PAGE_START(file_start); Elf32_Addr file_length = file_end - file_page_start; if (file_length != 0) { void* seg_addr = mmap((void*)seg_page_start, file_length, PFLAGS_TO_PROT(phdr->p_flags), MAP_FIXED|MAP_PRIVATE, fd_, file_page_start); ''' # Retrieve a base address for this module. load_base = self.mem_reserve(bound_low, bound_high) vf = VirtualFile( misc_utils.system_path_to_vfs_path(self.__vfs_root, filename), misc_utils.my_open(filename, os.O_RDONLY), filename) for segment in load_segments: prot = get_segment_protection(segment.header.p_flags) prot = prot if prot is not 0 else UC_PROT_ALL #self.emu.memory.map(load_base + segment.header.p_vaddr, segment.header.p_memsz, prot) #self.emu.mu.mem_write(load_base + segment.header.p_vaddr, segment.data()) seg_start = load_base + segment.header.p_vaddr seg_page_start = page_start(seg_start) file_start = segment.header.p_offset file_end = file_start + segment.header.p_filesz file_page_start = page_start(file_start) file_length = file_end - file_page_start assert (file_length > 0) if (file_length > 0): self.emu.memory.map(seg_page_start, file_length, prot, vf, file_page_start) # seg_end = seg_start + segment.header.p_memsz seg_page_end = page_end(seg_end) seg_file_end = seg_start + segment.header.p_filesz seg_file_end = page_end(seg_file_end) ''' void* zeromap = mmap((void*)seg_file_end, seg_page_end - seg_file_end, PFLAGS_TO_PROT(phdr->p_flags), MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); ''' self.emu.memory.map(seg_file_end, seg_page_end - seg_file_end, prot) # # Find init array. init_array_size = 0 init_array_offset = 0 init_array = [] init_addr = 0 dynstr_addr = 0 dt_needed = [] for x in elf.iter_segments(): if x.header.p_type == "PT_DYNAMIC": for tag in x.iter_tags(): if tag.entry.d_tag == "DT_INIT_ARRAYSZ": init_array_size = tag.entry.d_val elif tag.entry.d_tag == "DT_INIT_ARRAY": init_array_offset = tag.entry.d_val elif tag.entry.d_tag == "DT_INIT": init_addr = tag.entry.d_val + load_base elif tag.entry.d_tag == "DT_STRTAB": dynstr_addr = tag.entry.d_val + load_base elif tag.entry.d_tag == "DT_NEEDED": dt_needed.append(tag.entry.d_val) # # break # # so_needed = [] for str_off in dt_needed: str_addr = dynstr_addr + str_off so_name = memory_helpers.read_utf8(self.emu.mu, str_addr) so_needed.append(so_name) # for so_name in so_needed: path = misc_utils.vfs_path_to_system_path( self.__vfs_root, so_name) if (not os.path.exists(path)): logger.warn("%s needed by %s do not exist in vfs %s" % (so_name, filename, self.__vfs_root)) continue # libmod = self.load_module(path) # rel_section = None for section in elf.iter_sections(): if not isinstance(section, RelocationSection): continue rel_section = section break # # Parse section header (Linking view). dynsym = elf.get_section_by_name(".dynsym") for _ in range(int(init_array_size / 4)): b = self.emu.mu.mem_read(load_base + init_array_offset, 4) fun_ptr = int.from_bytes(b, byteorder='little', signed=False) if fun_ptr != 0: # fun_ptr += load_base init_array.append(fun_ptr + load_base) # print ("find init array for :%s %x" % (filename, fun_ptr)) else: # search in reloc for rel in rel_section.iter_relocations(): rel_info_type = rel['r_info_type'] rel_addr = rel['r_offset'] if rel_info_type == arm.R_ARM_ABS32 and rel_addr == init_array_offset: sym = dynsym.get_symbol(rel['r_info_sym']) sym_value = sym['st_value'] init_array.append(load_base + sym_value) # print ("find init array for :%s %x" % (filename, sym_value)) break # # init_array_offset += 4 # Resolve all symbols. symbols_resolved = dict() for section in elf.iter_sections(): if not isinstance(section, SymbolTableSection): continue itersymbols = section.iter_symbols() next(itersymbols) # Skip first symbol which is always NULL. for symbol in itersymbols: symbol_address = self._elf_get_symval( elf, load_base, symbol) if symbol_address is not None: symbols_resolved[symbol.name] = SymbolResolved( symbol_address, symbol) # Relocate. for section in elf.iter_sections(): if not isinstance(section, RelocationSection): continue for rel in section.iter_relocations(): sym = dynsym.get_symbol(rel['r_info_sym']) sym_value = sym['st_value'] rel_addr = load_base + rel[ 'r_offset'] # Location where relocation should happen rel_info_type = rel['r_info_type'] #print(filename) #print("%x"%rel_addr) # Relocation table for ARM if rel_info_type == arm.R_ARM_ABS32: if sym.name in symbols_resolved: sym_addr = symbols_resolved[sym.name].address value_orig_bytes = self.emu.mu.mem_read( rel_addr, 4) value_orig = int.from_bytes(value_orig_bytes, byteorder='little') #R_ARM_ABS32 how to relocate see android linker source code #*reinterpret_cast<Elf32_Addr*>(reloc) += sym_addr; value = sym_addr + value_orig # Write the new value #print(value) self.emu.mu.mem_write( rel_addr, value.to_bytes(4, byteorder='little')) # # elif rel_info_type in (arm.R_ARM_GLOB_DAT, arm.R_ARM_JUMP_SLOT, arm.R_AARCH64_GLOB_DAT, arm.R_AARCH64_JUMP_SLOT): # Resolve the symbol. #R_ARM_GLOB_DAT,R_ARM_JUMP_SLOT how to relocate see android linker source code #*reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr; if sym.name in symbols_resolved: value = symbols_resolved[sym.name].address # Write the new value #print(value) self.emu.mu.mem_write( rel_addr, value.to_bytes(4, byteorder='little')) # # elif rel_info_type in (arm.R_ARM_RELATIVE, arm.R_AARCH64_RELATIVE): if sym_value == 0: # Load address at which it was linked originally. value_orig_bytes = self.emu.mu.mem_read( rel_addr, 4) value_orig = int.from_bytes(value_orig_bytes, byteorder='little') # Create the new value value = load_base + value_orig #print(value) # Write the new value self.emu.mu.mem_write( rel_addr, value.to_bytes(4, byteorder='little')) else: raise NotImplementedError() else: logger.error("Unhandled relocation type %i." % rel_info_type) # # Store information about loaded module. module = Module(filename, load_base, bound_high - bound_low, symbols_resolved, init_addr, init_array) self.modules.append(module) #TODO init tls like linker ''' void __libc_init_tls(KernelArgumentBlock& args) { __libc_auxv = args.auxv; unsigned stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE; unsigned stack_size = 128 * 1024; unsigned stack_bottom = stack_top - stack_size; static void* tls[BIONIC_TLS_SLOTS]; static pthread_internal_t thread; thread.tid = gettid(); thread.tls = tls; pthread_attr_init(&thread.attr); pthread_attr_setstack(&thread.attr, (void*) stack_bottom, stack_size); _init_thread(&thread, false); __init_tls(&thread); tls[TLS_SLOT_BIONIC_PREINIT] = &args; } ''' if do_init: ''' for r in self.emu.mu.mem_regions(): print("region begin :0x%08X end:0x%08X, prot:%d"%(r[0], r[1], r[2])) # ''' module.call_init(self.emu) # logger.info("finish load lib %s" % filename) return module
emulator.java_classloader.add_class(JNIBridge) emulator.java_classloader.add_class(SecException) emulator.java_classloader.add_class(SGPluginExtras) emulator.java_classloader.add_class(MalDetect) emulator.java_classloader.add_class(NativeReflectUtils) emulator.java_classloader.add_class(SDKUtils) emulator.java_classloader.add_class(MiuiAd) emulator.java_classloader.add_class(TelephonyManagerEx) emulator.java_classloader.add_class(FtTelephonyAdapter) emulator.java_classloader.add_class(FtTelephony) emulator.java_classloader.add_class(FtDeviceInfo) emulator.java_classloader.add_class(ColorOSTelephonyManager) path = "vfs/system/lib/vectors" vf = VirtualFile("[vectors]", misc_utils.my_open(path, os.O_RDONLY), path) emulator.memory.map(0xffff0000, 0x1000, UC_PROT_EXEC | UC_PROT_READ, vf, 0) # Load all libraries. lib_module = emulator.load_library( "vfs/data/data/fm.xiami.main/lib/libsgmainso-6.4.163.so") lib_module_secbody = emulator.load_library( "vfs/data/data/fm.xiami.main/lib/libsgsecuritybodyso-6.4.95.so") lib_module_avmp = emulator.load_library( "vfs/data/data/fm.xiami.main/lib/libsgavmpso-6.4.35.so") #androidemu.utils.debug_utils.dump_symbols(emulator, sys.stdout) # Show loaded modules. logger.info("Loaded modules:")