lldb积累
lldb 真难用
# 运行
运行程序以及远程调试:
debugserver 127.0.0.1:1234 /var/containers/Bundle/Application/B1A257AC-7E38-4131-8A72-6DE17F9C2C61/Aweme.app
process connect connect://127.0.0.1:1234
# 基址相关
断点加载新 module:
breakpoint set --name _dyld_register_func_for_add_image
breakpoint set --name _dyld_image_count
查看基址:
image list -o -f|grep 'AwemeCore'
检查函数是否加载以及断点函数名:
image lookup -vn awemeMain
breakpoint set --name awemeMain
查看模块:
target modules lookup -a 0x10826ad98
# 调试操作
寄存器操作:
register read
register $x0
register write x0 0x12345678
读内存到文件:
memory read --outfile /Users/lixiangyu102/Desktop/douyin/douyin/secDump 0x0000000101e235a8 0x0000000101e23600 --force
按相关格式查看地址:
expr -l objc++ -- (id)$x0
po (id)$x0
po (Class)$x0
监视断点:
watchpoint set expression -w read -- 0x123456
watchpoint set expression -w write -- 0x123456
# 使用外部脚本
python 脚本,dump 内存
command script import /Users/lixiangyu102/Desktop/douyin/douyin/testDump.py | |
# 下面是 dump 内存的 | |
import lldb | |
def __lldb_init_module(debugger, internal_dict): | |
debugger.HandleCommand('command script add -f read_strings.read_strings read_strings') | |
print("[*started*]") | |
start_address = 0x000000010826ad98 | |
end_address = 0x000000010862cc88 | |
output_file = '/Users/lixiangyu102/Desktop/douyin/douyin/testStrings.txt' | |
process = debugger.GetSelectedTarget().GetProcess() | |
try: | |
with open(output_file, 'w') as f: | |
address = start_address | |
while address < end_address: | |
error = lldb.SBError() | |
pointer = process.ReadPointerFromMemory(address, error) | |
if error.Success(): | |
string = process.ReadCStringFromMemory(pointer, 256, error) | |
if error.Success(): | |
f.write(f"0x{address:x} -> 0x{pointer:x}: {string}\n") | |
else: | |
f.write(f"0x{address:x} -> 0x{pointer:x}: [Failed to read string]\n") | |
else: | |
f.write(f"Failed to read pointer at 0x{address:x}\n") | |
address += 8 # Move to the next pointer (8 bytes for 64-bit) | |
except IOError as e: | |
result.SetError(f"Failed to open or write to file: {e}") |
打印这个具体类具体方法的
(lldb) expr (IMP)class_getMethodImplementation((Class)objc_getMetaClass("internal_DeviceInfoZZZX"), (SEL)NSSelectorFromString(@"16923bf24c2b4257b579fcc6bffd0888720170518L")) |
expr (IMP)class_getMethodImplementation((Class)[TTInstallIDManager class], @selector(_identifierFromFileForKey:)) |
获取所有已加载的类 class:
expr -- @import ObjectiveC | |
expr -- unsigned int outCount; Class *classes = objc_copyClassList(&outCount); for (unsigned int i = 0; i < outCount; i++) { printf("%s\n", class_getName(classes[i])); } free(classes); |
expr -- @import ObjectiveC | |
expr -- unsigned int outCount; FILE * pFile;pFile = fopen("/tmp/test", "w"); Class *classes = objc_copyClassList(&outCount); for (unsigned int i = 0; i < outCount; i++) { fprintf(pFile,"%s\n", class_getName(classes[i])); } fflush(pFile);fclose(pFile);printf("1");free(classes); |
从类名获取对象并打印结构体:
po [internal_DeviceInfoZZZX _methodDescription]
expr Class $class = objc_getClass("internal_DeviceInfoZZZX") | |
expr unsigned int $methodCount = 0 | |
expr Method *$methods = class_copyMethodList($class, &$methodCount) | |
expr for (unsigned int $k1 = 0; $k1 < $methodCount; $k1++) { Method $method = $methods[$k1]; printf("Method address: %p\n", $method); printf("Method name: %s\n", sel_getName(method_getName($method))); printf("Method types: %s\n", method_getTypeEncoding($method)); printf("Method imp: %p\n", method_getImplementation($method)); } |
expr -l objc++ -- @import ObjectiveC; { Class cls = objc_getClass("internal_DeviceInfoZZZX"); unsigned int methodCount = 0; Method *methods = class_copyMethodList(cls, &methodCount); for (unsigned int i = 0; i < methodCount; i++) { Method method = methods[i]; SEL sel = method_getName(method); IMP imp = method_getImplementation(method); const char *name = sel_getName(sel); printf("Method name: %s\n", name); printf("Method address: %p\n", (void *)imp); printf("Method types: %s\n", method_getTypeEncoding(method)); } free(methods); } |
expr -l objc++ -- @import ObjectiveC; { Class cls = (Class)objc_getClass("internal_DeviceInfoZZZX"); unsigned int methodCount = 0; Method *methods = class_copyMethodList(cls, &methodCount); for (unsigned int i = 0; i < methodCount; i++) { Method method = methods[i]; SEL sel = method_getName(method); IMP imp = method_getImplementation(method); const char *name = sel_getName(sel); printf("Method name: %s\n", name); printf("Method address: %p\n", (void *)imp); printf("Method types: %s\n", method_getTypeEncoding(method)); } free(methods); } |
# 批量拿方法名以及地址
import lldb | |
def __lldb_init_module(debugger, internal_dict): | |
classnames = [] | |
with open('Class.txt', 'r') as f: | |
for line in f: | |
classnames.append(line.strip()) | |
output_file = "method_descriptions.txt" | |
with open(output_file, "w") as f: | |
pass | |
# 获取命令解释器 | |
command_interpreter = debugger.GetCommandInterpreter() | |
# 遍历类名并执行命令 po | |
for classname in classnames: | |
po_command = f'po [{classname} _methodDescription]' | |
result = lldb.SBCommandReturnObject() | |
command_interpreter.HandleCommand(po_command, result) | |
with open(output_file, "a") as f: | |
f.write(f"Class: {classname}\n") | |
f.write(result.GetOutput()) | |
f.write("\n\n") | |
if result.GetError(): | |
with open(output_file, "a") as f: | |
f.write(f"Error for class {classname}:\n") | |
f.write(result.GetError()) | |
f.write("\n\n") | |
print(f"Results saved to {output_file}") | |
print("The 'dump_methods' command has been installed. Use 'dump_methods' to run the script.") |
# 初始化脚本
不会