靜態庫的管理與文件格式分析
靜態庫與動態庫都屬於Mach-O格式的文件,動態庫使用.dylib作為文件的擴展名,靜態庫的擴展名則是.a;在功能上,動態庫通過動態鏈接的方式向其它程序提供介面,而靜態庫則是將功能代碼直接編譯進目標Mach-O文件中去,多個程序使用同一個動態庫並不會增加目標文件的大小,使用靜態庫則會將每份功能代碼都拷貝到目標文件中;從運行效率上來說,動態庫需要在載入後做符號綁定操作,而靜態庫代碼直接在目標程序中運行,理論上來講,使用靜態庫的運行效率比動態庫要高一些。
0x1 構建靜態庫
XCode提供了創建靜態庫的工程模板,創建靜態庫的方法與創建動態庫幾乎一樣,唯一不同的是,在項目設置時,Type選擇Static。還是與創建動態庫一樣的代碼:
//mystaticlib.hn#import <Foundation/Foundation.h>nn@interface mystaticlib : NSObjectn-(void) hello;n@endnn//mystaticlib.mn#import "mystaticlib.h"nn@implementation mystaticlibn-(void) hello {n NSLog(@"hello world");n}n@endn
分別保存為mystaticlib.h與mystaticlib.m。然後使用xcodebuild編譯會有如下輸出:
$ xcodebuildn=== BUILD TARGET mystaticlib OF PROJECT mystaticlib WITH THE DEFAULT CONFIGURATION (Release) ===nnCheck dependenciesnnWrite auxiliary filesnwrite-file /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/mystaticlib-generated-files.hmapnwrite-file /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/mystaticlib-all-target-headers.hmapn......n/bin/mkdir -p /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64nwrite-file /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64/mystaticlib.LinkFileListnnCompileC build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64/mystaticlib.o mystaticlib/mystaticlib.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compilern cd /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlibn export LANG=en_US.US-ASCIIn /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch x86_64 -fmessage-length=94 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -fcolor-diagnostics -std=gnu99 -fobjc-arc -fmodules -gmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fbuild-session-file=/var/folders/rd/mts0362j0n92rq0z1cnmdb580000gn/C/org.llvm.clang/ModuleCache/Session.modulevalidation -fmodules-validate-once-per-build-session -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module -Wno-trigraphs -fpascal-strings -Os -fno-common -Wno-missing-field-initializers -Wno-missing-prototypes -Werror=return-type -Wunreachable-code -Wno-implicit-atomic-properties -Werror=deprecated-objc-isa-usage -Werror=objc-root-class -Wno-arc-repeated-use-of-weak -Wduplicate-method-match -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wundeclared-selector -Wno-deprecated-implementations -DNS_BLOCK_ASSERTIONS=1 -DOBJC_OLD_DISPATCH_PROTOTYPES=0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -fasm-blocks -fstrict-aliasing -Wprotocol -Wdeprecated-declarations -mmacosx-version-min=10.11 -g -Wno-sign-conversion -iquote /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/mystaticlib-generated-files.hmap -I/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/mystaticlib-own-target-headers.hmap -I/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/mystaticlib-all-target-headers.hmap -iquote /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/mystaticlib-project-headers.hmap -I/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/Release/include -I/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/DerivedSources/x86_64 -I/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/DerivedSources -F/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/Release -MMD -MT dependencies -MF /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64/mystaticlib.d --serialize-diagnostics /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64/mystaticlib.dia -c /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/mystaticlib/mystaticlib.m -o /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64/mystaticlib.onnLibtool build/Release/libmystaticlib.a normal x86_64n cd /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlibn export MACOSX_DEPLOYMENT_TARGET=10.11n /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static -arch_only x86_64 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -L/Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/Release -filelist /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/mystaticlib.build/Release/mystaticlib.build/Objects-normal/x86_64/mystaticlib.LinkFileList -o /Users/macbook/Documents/macbook/macbook/code/chapter4/mystaticlib/build/Release/libmystaticlib.ann** BUILD SUCCEEDED **n
整個編譯過程分為: 檢查依賴(Check dependencies)、生成輔助文件(Write auxiliary files)、編譯(CompileC)、打包生成庫(Libtool)等幾步。最終打包生成庫的環節使用的libtool工具,該工具除了生成靜態庫,也可以生成動態庫,上一節生成動態庫使用鏈接器ld,它底層也是通過libtool來生成動態庫的。最後,靜態庫不需要簽名,靜態庫中的代碼最終會被插入到目標程序中,由目標程序來簽名。
0x2 靜態庫格式
上一節講到的動態庫文件,它的格式就是標準的Mach-O文件,它與Mach-O可執行文件不同的是,動態庫在Mach-O頭部指定文件類型為MH_DYLIB,可執行程序為MH_EXECUTE。與動態庫不同的是,靜態庫文件不是標準的Mach-O,它的格式如下:
StartnSymtab HeadernSymbol TablenString TablenObject Header 0nObjName0.on......nObject Header NnObjNameN.on
Start為靜態庫的開始,它是一個固定長度的簽名值「!<arch>n」,十六進位為「21 3C 61 72 63 68 3E 0A」。
Symtab Header為符號表頭,描述了符號表的信息。它使用symtab_header結構體表示,具體定義為:
struct symtab_header {n char name[16]; /* 名稱 */n char timestamp[12]; /* 庫創建的時間戳 */n char userid[6]; /* 用戶id */n char groupid[char]; /* 組id */n uint64_t mode; /* 文件訪問模式 */n uint64_t size; /* 符號表佔總位元組大小 */n uint32_t endheader; /* 頭結束標誌 */n char longname[20]; /* 符號表長名 */n};n
Symbol Table為當前靜態庫導出的符號表。它使用symbol_table結構體表示,具體定義為:
struct symbol_table {n uint32_t size; /* 符號表佔用的總位元組數 */n symbol_info syminfo[0]; /* 符號信息,它的個數是 size / sizeof(symbol_info) */n};nnstruct symbol_info {n uint32_t symnameoff; /* 符號名在字元串表數據中的偏移值 */n uint32_t objheaderoff; /* 符號所屬的目標文件的文件頭在文件中的偏移值 */n};n
String Table為字元串表,該結構體存儲的字元串信息供符號表使用。使用string_table結構體表示,具體定義為:
struct string_table {n uint32_t size; /* 字元串表佔用的總位元組數 */n char data[size]; /* 字元串數據 */n};n
Object Header為目標文件的頭,描述了接下來的目標文件的信息。使用object_header結構體表示,具體定義為:
struct object_header {n char name[16]; /* 名稱 */n char timestamp[12]; /* 目標文件創建的時間戳 */n char userid[6]; /* 用戶id */n char groupid[char]; /* 組id */n uint64_t mode; /* 文件訪問模式 */n uint64_t size; /* 符號表佔總位元組大小 */n uint32_t endheader; /* 頭結束標誌 */n char longname[20]; /* 符號表長名 */n};n
object_header結構體的布局與symtab_header基本一樣的。
ObjName.o:在object_header結構體下面緊接著就是具體的目標文件內容了。目標文件是以.o結尾的Mach-O格式的文件,它是由編譯器生成的中間文件。目標文件在它的Mach-O頭部被標識為MH_OBJECT類型的文件。
最後,可以使用MachOView查看本小節生成的libmystaticlib.a的結構信息,效果如圖所示:
0x3 管理靜態庫
通過上一小節的分析,我們知道,靜態庫是由一些頭信息加一系統的.o目標文件組成的。在分析靜態庫中的具體目標文件時,需要先將目標文件解壓出來,還好目前主流的靜態分析工具都支持直接讀取靜態庫中的目標文件。但如果想要修改靜態庫中目標文件的內容,就需要先將目標文件取出後,修改後再替換回去,在了解了靜態庫文件格式後,完全可以自己動手寫工具解出靜態庫中的目標文件,但實現上不用這麼麻煩,可以使用庫管理工具ar來完成該工作。
執行如下命令就可以解出上一小節生成的靜態庫中的目標文件:
$ ar -x ./libmystaticlib.an
操作成功後沒有輸出信息,但可以發現,當前目錄中已經生成了mystaticlib.o文件。在修改完目標文件後,可以將其打包進原來的庫,或者直接生成新的靜態庫,執行以下的命令:
$ ar rcs libmystaticlib_new.a *.on
同樣沒有輸出信息,但ar已經成功將當前目錄下所有的目標文件打包進了libmystaticlib_new.a中。
推薦閱讀:
※盤點七大可怕的勒索軟體家族
※PKG安裝包的管理與文件格式分析
※macOS平台軟體的下載與安裝
TAG:软件安全 |