(lldb) expr (void*)dlopen("/path/to/build/SSLKillSwitch.framework/Versions/A/SSLKillSwitch", 1) (lldb) expr (void*)dlopen("/Library/MobileSubstrate/DynamicLibraries/Reveal2Loader.dylib",1) (lldb) command alias reveal_load_sim expr (void*)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/RevealServer.framework/RevealServer", 0x2); (lldb) expr (void*)dlopen("/Library/RHRevealLoader/libReveal.dylib",1) (void *) $1 = 0x00007f92e74d10c0 Using DYLD_INSERT_LIBRARIES to inject SSLKillSwitch and start the process.
lldb expr 相关
[xxx setHidden:YES] show/hide caflush Force Core Animation to flush. This will ‘repaint’ the UI but also may mess with ongoing animations
断点相关
1. 对函数下断点
breakpoint set -n text: -c ret == YES //使用-c设置条件断点 breakpoint set -f xxx.m -l 38 //使用-f指定文件 使用-l指定文件某一行设置断点 breakpoint set -n "-[xxx xxx]" //根据函数名下断点(调试信息) breakpoint set -a VitrualAddress //根据虚拟地址下断点
b isEven, br s -F isEven //符号断点 breakpoint set -f main.m -l 16:在源码文件的某一行断点 b main.m:17。b是_regexp-break的缩写
watchpoint set expression -w write ―- 0xl01801a48 :给某个地址设置观察断点,内存进行写操作时就会触发断点
// 获取需要监控的内存地址 p (ptrdiff_t)ivar_getOffset((struct Ivar *)class_getInstanceVariable([MyView class], "_layer"))
(ptrdiff_t) $0 = 8
watchpoint set expression -- (int *)$myView + 8:监控_layer的地址
变量监控:watchpoint set variable -w read_write 条件监控:watchpoint modify -c '(global==5)'
3.断点后执行命令
b +[Manager performLoginWithUsernameOnEmail: password: preAuthToken: twoFAMethod: confirmReactivation:rememberDevice:fromDeepLink:onComplete:] Breakpoint 2: where = Snapchat'+[Manager br com add 2 > po $x2 > po $x3 > c > po F.viewCFG() > DONE
7.如何将断点设置在动态库的入口
LLDB命令行进行调试时自 动中断在 _dyld_start 处,因为此时dyld已经加载,所以在dyld里面设置一个在所有库中加载并且在constructor 函数执行之前执行的断点,例如initializeMainExecutable settings set target.process.stop-on-sharedlibrary-events 1
(lldb) findclass error: libarclite_macosx.a(arclite.o) failed to load objfile for /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_macosx.a error: libarclite_macosx.a(arclite.o) failed to load objfile for /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_macosx.a Traceback (most recent call last): File "/Users/gogleyin/lldb/findclass.py", line 40, in findclass raise AssertionError("Uhoh... something went wrong, can you figure it out? :]") AssertionError: Uhoh... something went wrong, can you figure it out? :]
(lldb) script import pdb (lldb) findclass Traceback (most recent call last): File "/Users/gogleyin/lldb/findclass.py", line 40, in findclass raise AssertionError("Uhoh... something went wrong, can you figure it out? :]") AssertionError: Uhoh... something went wrong, can you figure it out? :]
(lldb) script pdb.pm() > /Users/gogleyin/lldb/findclass.py(40)findclass() -> raise AssertionError("Uhoh... something went wrong, can you figure it out? :]")
(Pdb) print(codeString) # 这个东西包含了一段oc代码,用oc runtime来找出runtime的所有类 @import Foundation; int numClasses; Class * classes = NULL; classes = NULL; numClasses = objc_getClassList(NULL, 0); NSMutableString *returnString = [NSMutableString string]; classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses); numClasses = objc_getClassList(classes, numClasses); for (int i = 0; i < numClasses; i++) { Class c = classes[i]; [returnString appendFormat:@"%s,", class_getName(c)]; } free(classes); returnString; # 返回returnString的值给Python脚本
(Pdb) l 35, 45 # 会列出35到45行代码,注意40行的 -> 表示当前pdb停在的位置 35 ''' 36 37 res = lldb.SBCommandReturnObject() 38 debugger.GetCommandInterpreter().HandleCommand("expression -lobjc -O -- " + codeString, res) 39 if res.GetError(): 40 -> raise AssertionError("Uhoh... something went wrong, can you figure it out? :]") 41 elif not res.HasResult(): 42 raise AssertionError("There's no result. Womp womp....") 43 44 returnVal = res.GetOutput() 45 resultArray = returnVal.split(",") # 嗯,似乎res.GetError()看起来更加有趣,玩一下先
(Pdb) print res.GetError() error: 'objc_getClassList' has unknown return type; cast the call to its declared return type error: 'objc_getClassList' has unknown return type; cast the call to its declared return type error: 'class_getName' has unknown return type; cast the call to its declared return type # 到这里可以看到,问题是codeString里面的代码让LLDB迷惑了。 # 实际这种错误在LLDB里面是非常常见的。你需要告诉LLDB一个函数的返回类型,因为它无法知道那是啥。 # 在这个case下, objc_getClassList 和 class_getName 都有未知的返回类型 # Google一下便知这两个函数的签名如下: int objc_getClassList(Class *buffer, int bufferCount); const char * class_getName(Class cls); # 所有我们需要做的事转换返回类型到正确的值就可以啦。如下:
codeString = r''' @import Foundation; int numClasses; Class * classes = NULL; classes = NULL; numClasses = (int)objc_getClassList(NULL, 0); NSMutableString *returnString = [NSMutableString string]; classes = (__unsafe_unretained Class *)malloc(sizeof(Class) *numClasses); numClasses = (int)objc_getClassList(classes, numClasses); for (int i = 0; i < numClasses; i++) { Class c = classes[i]; [returnString appendFormat:@"%s,", (char *)class_getName(c)]; } free(classes); returnString;
otool -arch arm64 -1 Cronet | grep crypt cryptoff 16384 cryptsize 3309568 cryptid 1 (lldb) im li Cronet [0] 188F5BF7-B4C4-36EF-BB9A-976FA870F9D7 0x0000000105920000 /private/var/mobile/Containers/Bundle/Application/3A4C68EB-4059-47D4-ACE6-BE9C492DF205/ Snapchat.app/Frameworks/Cronet.framework/Cronet (0x0000000105920000) (lldb) memory read --force --outfile ~/Desktop/dumpoutput --binary count 3309568 16384+0x0000000105920000 因为dump出来的文件都没有Mach-0文件头,所以在这里要先把dump出来的数据写回原 来加密的文件,以替换原来加密的部分 2768896(之前获取的ARM64架构的偏移值)+16384(加密数据的偏移值)=2785280(写入的加密数据在文件中的偏移值) seek=n Seek n blocks from the beginning of the output before copying. bs=n Set both input and output block size to n bytes conv=value[,value ...] notrunc Do not truncate the output file. Cronet.framework git:(master) X dd seek=2785280 bs=l conv=notrunc if=/Users/monkey/Desktop/dumpoutput of=./Cronet 3309568+0 records in 3309568+0 records out 3309568 bytes transferred in 4.698067 secs (704453 bytes/sec) Cronet.framework git:(master) X lipo Cronet -thin arm64 -output Cronet_arm64 MachOView.app 修改Cronet_arm64 crypid 为0
(lldb) e @import UIKit (lldb) e UIApplication *$app = [UIApplication sharedApplication]; (lldb) e UlWindow *$keyWindow = $app.keyWindow (lldb) e UlViewController *$root = $keyWindow.rootViewController (lldb) po $root <NavigationController: 0xl2c03d200> (lldb) e [(SCButton *)0xl2bd4b760 setTitle:@"AloneMonkey" forStaterUIControlStateNormal] (lldb) e (void)[CATransaction flush] (lldb) c
在 Snapchat模块中查看与login有关的符号信息
image lookup -rn login UserLogin
(lldb) b -[UIView setTail:] Breakpoint 3: where = UserLogin`-[UIView(Frame) setTail:] at UIView+Frame.m:102, address = 0x0000000100b5ee34 (lldb) il 0x0000000100b5ee34 image lookup -a 0x0000000100b5ee34
This will tell LLDB to attach to the process named Finder whenever it next launches.
lldb -n Finder -w process attach --name "Finder" --waitfor
直接调试启动
lldb -f /bin/ls process launch
将Speech框架加载到DeleteMe流程空间
(lldb) process load /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk//System/Library/Frameworks/Speech.framework/Speech
异常
Disabling Rootless
Command + R,start your macOS machine. csrutil disable && reboot
-w工作目录
选项在哪里启动来更改当前的工作目录。输入以下内容: (lldb) process launch -w /Applications
环境变量
(lldb) process launch -v LSCOLORS=Af -v CLICOLOR=1 – /Applications/