lldb_help

some lldb tips

通用

計算偏移/ida地址

p/x 0X000000010095ECCC+0X0000000000038000
(lldb) p/x 0x0000000100e595b4-0x0000000000038000 (long) $18 = 0x0000000100e215b4
查看某個地址所在模塊的信息

觀察斷點

watchpoint set expression -w write ―- 0xl01801a48 :給某個地址設置觀察斷點,內存進行寫操作時就會觸發斷點

讀取目標地址的內存指令

x/10xg 0xl01801a48 這裏的x 表示用十六進制來顯示結果。"g"代表giant word(8字節)大小。所以就是用十六進制顯示 0x101801a48所指恐懼的10個64位的元素內容。常見的大小格式爲"b-byte"(1字節),"h-half word"(2字節),"w- word”(4字節),"g-giantword”(8字節)。

dis-a$pc 反彙編指定地址

這裏是pc寄存器所對應的地址。

f2:切換到當前調用棧爲2的位置,也就是bt中的frame #2。

threadinfo:輸出當前線程的信息。

b ptrace -c xxx:滿足某個條件之後程序纔會中斷。

help/apropos

斷點後執行命令

b +[Manager performLoginWithUsernameOnEmail: password: preAuthToken: twoFAMethod: confirmReactivation: rememberDevice:fromDeepLink:onComplete:]
Breakpoint 2: where = Snapchat'+[Manager
br com add 2
> po $x2
> po $x3
> c
> DONE

xcode預處理快捷鍵

單擊 Product -> PerformAction ->Preprocess xxxx 可以對文件進行預處理,還可以將代碼轉換成彙編代碼。可以幫助我們理解這些宏的作用

pdb來排查了一個腳本中的問題

(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;

--debug選項是定位JIT代碼中的問題的非常好的手段,調試lldb 的好方法
expression --debug -lobjc -O --
可以選擇使用frame variable命令打印變量

如何將斷點設置在動態庫的入口

LLDB命令行進行調試時自 動中斷在 _dyld_start 處,因爲此時dyld已經加載,所以在dyld裏面設置一個在所有庫中加載並且在constructor 函數執行之前執行的斷點,例如initializeMainExecutable
settings set target.process.stop-on-sharedlibrary-events 1

基本的類:

  • lldb.SBDebugger:在你的腳本中用來訪問類的實例的類,非常中心,還處理LLDB命令的輸入和輸出
  • lldb.SBTarget:與被調試的可執行文件有關(相關調試文件,磁盤上的文件)。
    你可以用SBDebugger的實例來獲取到當前選擇的SBTarget。然後 你就可以通過SBTarget訪問大部分其餘類。
  • lldb.SBProcess:SBTarget和SBProcess是一對多的關係:SBTarget管理者一個或多個SBProcess實例。SBProcess處理內存讀寫還有它自己的線程。
  • lldb.SBThread:管理對應線程的棧幀和stepping的控制邏輯
  • lldb.SBFrame:管理局部變量(debug信息有提供的)和當時的寄存器快照
  • lldb.SBModule:代表着一個可執行文件。
  • lldb.SBFunction:這代表着一個加載到內存中的函數(或者對應代碼),它與SBFrame是一對一的關係。
    實例是 lldb.debugger/lldb.target…
    https://lldb.llvm.org/python_reference/index.html
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-n0KmuAtf-1582438651905)
    在這裏插入圖片描述
    演示了LLDB Python主要的幾個類之間的相互關係
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qA1gppOl-1582438651906)
    在這裏插入圖片描述
    暫停在某函數時幾個類的交互

android


iOS

砸殼

Cronet.framework git:(master) X otool -hf Cronet Fat headers
fat_magic 0xcafebabe
nfat_arch 2
architecture 0  cputype 12 cpusubtype 9  capabilities 0x0
	offset 16384 size 2749664 align 2A14 (16384)
architecture 1 cputype 16777228 cpusubtype 0 capabilities 0x0
	offset 2768896 size 3612224 align 2A14 (16384)
Mach header
	magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
	Oxfeedface 12 9 0x00 6 27 3328 0x00118085
Mach header
	magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
	0xfeedfacf 16777228 0 0x00 6 27 3816 0X00118085

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

查詢按鈕事件

error: error: use of undeclared identifier 'UIApplication'
None
(lldb) expression @import UIKit
pviews
   |    |    |    |    |    |    |    |    |    | <UIButtonLabel: 0x101c730a0; frame = (7.5 12.5; 69.5 20.5); text = '所有圖書'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x174295a90>>
   |    |    |    |    |    |    |    |    |    |    | <_UILabelContentLayer: 0x170425fa0> (layer)
   |    |    |    |    |    |    |    |    | <IMTouchInsetsButton: 0x101c73f60; baseClass = UIButton; frame = (324 5.5; 35 33); opaque = NO; layer = <CALayer: 0x17422d880>>
   |    |    |    |    |    |    |    |    |    | <UIButtonLabel: 0x101c31460; frame = (9 6.5; 35 20.5); text = '選擇'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x174295360>>

查看 “登錄”按鈕UIButtonLabel的響應鏈
presponder 0x101c31460
(lldb) presponder 0x101c31460
<UIButtonLabel: 0x101c31460; frame = (9 6.5; 35 20.5); text = '選擇'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x174295360>>
   | <IMTouchInsetsButton: 0x101c73f60; baseClass = UIButton; frame = (324 5.5; 35 33); opaque = NO; layer = <CALayer: 0x17422d880>>
   |    | <IMToolbar: 0x101c1d8b0; baseClass = UIToolbar; frame = (0 20; 375 44); opaque = NO; autoresize = W; tintColor = UIExtendedSRGBColorSpace 0 0.478431 1 1; layer = <CALayer: 0x174224ec0>>
查看“登錄”按鈕的Action事件
(lldb) pactions 0x101c73f60
<BKLibraryViewController: 0x102817600>: editButtonPressed:

chisel 打印結構

< NSMallocBlock : 0Xl7444b6d0>
(lldb) pblock 0xl7444b6d0

(lldb) pvc
<ICSplitViewController 0x10079eab0>, state: appeared, view: <UILayoutContainerView 0x1009261c0>
   | <UIMultiColumnViewController 0x10079f410>, state: appeared, view: <UIView 0x1007aee70>

(lldb) methods 0x10079eab0
<ICSplitViewController: 0x10079eab0>:
in ICSplitViewController:
	Properties:
		@property (nonatomic, getter=isDetailDimmed) BOOL detailDimmed;  (@synthesize detailDimmed = _detailDimmed;)

搜索UITextField的實例對象和Cycript中的choose—樣的

search UIButton
search UITextField
# Find all UIViews, ignore subclasses
find UIView  -e

# Find all instances of UIViews (and subclasses) where tag == 5
find UIView -c "[obj tag] == 5"

查看對象內存關係,xcode觀看

/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/lldb/macosx/heap.py
command alias iheap command script import lldb.macosx.heap
"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs"

爲了查看某個對象內存分配的調用堆棧,需要在程序啓動的環境變量中設置 MallocSlack Logging。
在環境變量中增加 MallocStackLogging 的值1
單擊Xcode調試工具欄上的“Debug Momery Graph”按鈕

執行script

(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

某個類的所有方法下斷點並跟蹤打印調用參數

command regex bclass 's/(.+)/rb \[%1 /'
rb -> breakpoint set -r %1
bclass ULLoginViewController -> breakpoint set -r \[ULLoginViewController

br set -r '\[WAChatSessionViewController .*\]'

如果不在MethodTraCeCcmflg.PliSt文件裏面配置需要跟蹤的類,那麼如下設置:
@interface MethodTrace : NSObject
+ (void)addClassTrace:(NSString*) className;
+ (void)addClassTrace: (NSString *)className methodName: (NSString*) methodName;
+ (void)addClassTrace: (NSString *)className methodList: (NSArray*) methodList;
@end

e [MethodTrace addClassTrace:@"WAChatDataStore"]
筆者在MethodTrace的代碼裏面調試了—下,發現 NSLog沒有被輸出到Xcode的控制檯,但是在Console.app裏面可以看到NSLog,所以改用printf來輸出。
ENABLE_METHODTRACE

xcode 設置環境變量

打印參數和當前的環境變量, segment加載的詳細信息,加載dylib,顯示是否加載,各階段的時間消耗
xcode  DYLD_PRINT_OPTS, DYLD_PRINT_EN, DYLD_PRINT_SEGMENTS

簽名InsertDyUb.dylib,拷貝 InsertDylib.dylib 到Bundle Resources
xcode  設置環境變量DYLD_INSERT_LIBRARIES @executable_path/InsertDylib.dylib

xcode  設置環境變量 DYLD_PRINT_INTERPOSING 運行 App,日誌如下即爲hook生效
dyld: interposing 2 tuples onto image: /var/containers/Bundle/Application/AB57C532-19F2-4022-B757-7D211296E64D/AppStart.app/InsertDylib.dylib

xcode 設置 DYLD_PRINT_STATISTICS,DYLD_PRINT_STATISTICS_DETAILS 打印各階段的時間消耗。

@executable_path:表示可執行程序所在的目錄,一般是xxx.app
@loader_path:表示每一個被加載的二進制文件的目錄。例如,xxxx.plugin/aaa/abc依賴xxx.plugin/bb/ccc.dylib,那麼依賴的路徑可以寫成 @loader_path/../bbb. 這樣不管xxx.plugin放在那都能找到ccc.dylib
@rpath:這個變量是在 Xcode build裏面設置, Dynamic Libray Install Name設置爲(#=@path/xxx/xxx,就可以在使用的工程中設置一個或多個RunPath Search Paths 來指定搜索路徑。在運行時,會將@rpath分別替換爲Runpath Search Paths中指定的路徑來査找動態庫。

iOS 分析常見點

handleLongPressAtPoint函數就是用於處理長按事件的函數
第一響應者實現 canPerformAction:withSender: 來確定當前哪些操 作是被允許的、哪些操作是不被允許的。

macos

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章