逆向基礎 Finding important/interesting stuff in the code (二)
第58章
呼叫assert
有時,assert()宏的出現也是有用的:通常這個宏會洩漏原始檔名,行號和條件。
最有用的資訊包含在assert的條件中,我們可以從中推斷出變數名或者結構體名。另一個有用的資訊是檔名。我們可以從中推斷出使用了什麼型別的程式碼。並且也可能透過檔名識別出有名的開源庫。
.text:107D4B29 mov dx, [ecx+42h]
.text:107D4B2D cmp edx, 1
.text:107D4B30 jz short loc_107D4B4A
.text:107D4B32 push 1ECh
.text:107D4B37 push offset aWrite_c ; "write.c"
.text:107D4B3C push offset aTdTd_planarcon ; "td->td_planarconfig == PLANARCONFIG_CON"...
.text:107D4B41 call ds:_assert
...
.text:107D52CA mov edx, [ebp-4]
.text:107D52CD and edx, 3
.text:107D52D0 test edx, edx
.text:107D52D2 jz short loc_107D52E9
.text:107D52D4 push 58h
.text:107D52D6 push offset aDumpmode_c ; "dumpmode.c"
.text:107D52DB push offset aN30 ; "(n & 3) == 0"
.text:107D52E0 call ds:_assert
...
.text:107D6759 mov cx, [eax+6]
.text:107D675D cmp ecx, 0Ch
.text:107D6760 jle short loc_107D677A
.text:107D6762 push 2D8h
.text:107D6767 push offset aLzw_c ; "lzw.c"
.text:107D676C push offset aSpLzw_nbitsBit ; "sp->lzw_nbits <= BITS_MAX"
.text:107D6771 call ds:_assert
同時google一下條件和檔名是明智的,可能會因此找到開源庫。舉個例子,如果我們google查詢“sp->lzw_nbits <= BITS_MAX”,將會顯示一些與LZW壓縮有關的開原始碼。
第59章
常量
通常人們在生活中或者程式設計師在編寫程式碼時喜歡使用像10,100,1000這樣的整數。
有經驗的逆向工程師會對這些數字的十六進位制形式很熟悉:10=0xA, 100=0x64, 1000=0x3E8, 10000=0x2710。
常量 0xAAAAAAAA (10101010101010101010101010101010)和0x55555555 (01010101010101010101010101010101)也很常用——構成alternating bits。舉個例子,0x55AA在引導扇區,MBR,IBM相容擴充套件卡中使用過。
某些演算法,特別是密碼學方面的使用的常量很有代表性,我們可以在IDA中輕鬆找到。
舉個例子,MD5演算法這樣初始化內部變數:
var int h0 := 0x67452301
var int h1 := 0xEFCDAB89
var int h2 := 0x98BADCFE
var int h3 := 0x10325476
如果你在程式碼中某行發現這四個常量,那麼極有可能該處函式與MD5有關。
另一個有關CRC16/CRC32演算法的例子,通常使用預先計算好的表來計算:
/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
u16 const crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
...
CRC3預計算表同見:第37節
59.1 幻數
許多檔案格式定義了標準的檔案頭,使用了幻數。
舉個例子,所有的Win32和MS-DOS可執行檔案以"MZ"這兩個字元開始。
MIDI檔案的開始有"MThd"標誌。如果我們有一個使用MIDI檔案的程式,它很有可能會檢查至少4位元組的檔案頭來確認檔案型別。
可以這樣實現:
(buf指向記憶體檔案載入的開始處)
cmp [buf], 0x6468544D ; "MThd"
jnz _error_not_a_MIDI_file
也可能會呼叫某個函式比如memcmp()或者等同於CMPSB指令(A.6.3節)的程式碼用於比對記憶體塊。
當你發現這樣的地方,你就可以確定的MIDI檔案載入的開始處,同時我們可以看到緩衝區存放MIDI檔案內容的地方,什麼內容被使用以及如何使用。
59.1.1 DHCP
上面的方法對於網路協議也同樣適用。舉個例子,DHCP協議網路包包含了magic cookie:0x6353826。任何生成DHCP包的程式碼在某處一定將這個常量嵌入了包中。它在程式碼中出現的地方可能就與執行這些操作有關,或者不僅是如此。任何接收DHCP的包都會檢查這個magic cookie,比對是否相同。
舉個例子,我們在Windows 7 x64的dhcpcore.dll檔案中搜尋這個常量。找到兩處:看上去這個常量在名為DhcpExtractOptionsForValidation()和 DhcpExtractFullOptions()函式中使用:
.rdata:000007FF6483CBE8 dword_7FF6483CBE8 dd 63538263h ; DATA XREF: ⤦
DhcpExtractOptionsForValidation+79
.rdata:000007FF6483CBEC dword_7 DATA XREF: ⤦
DhcpExtractFullOptions+97
下面是常量被引用的地址:
.text:000007FF6480875F mov eax, [rsi]
.text:000007FF64808761 cmp eax, cs:dword_7FF6483CBE8
.text:000007FF64808767 jnz loc_7FF64817179
還有:
.text:000007FF648082C7 mov eax, [r12]
.text:000007FF648082CB cmp eax, cs:dword_7FF6483CBEC
.text:000007FF648082D1 jnz loc_7FF648173AF
59.2 搜尋常量
在IDA中很容易:使用ALT-B或者ALT-I。如果是在大量檔案或者在不可執行檔案中搜尋常量,我會使用自己編寫一個叫binary grep的小工具。
第60章
尋找合適的指令
如果程式使用了FPU指令但使用不多,你可以嘗試用偵錯程式手工逐個檢查。
舉個例子,我們可能會對使用者如何在微軟的Excel中輸入計算公式感興趣,比如除法操作。
如果我們載入excel.exe(Offic 2010)版本為14.0.4756.1000 到IDA中,列出所有的條目,查詢每一條FDIV指令(除了使用常量作為第二個運算元的——顯然不是我們所關心的):
#!bash
cat EXCEL.lst | grep fdiv | grep -v dbl_ > EXCEL.fdiv
然後我們就會看到有144條相關結果。
我們可以在Excel中輸入像"=(1/3)"這樣的字串然後對指令進行檢查。
透過使用偵錯程式或者tracer(一次性檢查4條指令)檢查指令,我們幸運地發現目標指令是第14個:
.text:3011E919 DC 33 fdiv qword ptr [ebx]
PID=13944|TID=28744|(0) 0x2f64e919 (Excel.exe!BASE+0x11e919)
EAX=0x02088006 EBX=0x02088018 ECX=0x00000001 EDX=0x00000001
ESI=0x02088000 EDI=0x00544804 EBP=0x0274FA3C ESP=0x0274F9F8
EIP=0x2F64E919
FLAGS=PF IF
FPU ControlWord=IC RC=NEAR PC=64bits PM UM OM ZM DM IM
FPU StatusWord=
FPU ST(0): 1.000000
ST(0)存放了第一個引數,[EBX]存放了第二個引數。
FDIV(FSTP)之後的指令在記憶體中寫入了結果:
.text:3011E91B DD 1E fstp qword ptr [esi]
如果我們設定一個斷點,就可以看到結果:
PID=32852|TID=36488|(0) 0x2f40e91b (Excel.exe!BASE+0x11e91b)
EAX=0x00598006 EBX=0x00598018 ECX=0x00000001 EDX=0x00000001
ESI=0x00598000 EDI=0x00294804 EBP=0x026CF93C ESP=0x026CF8F8
EIP=0x2F40E91B
FLAGS=PF IF
FPU ControlWord=IC RC=NEAR PC=64bits PM UM OM ZM DM IM
FPU StatusWord=C1 P
FPU ST(0): 0.333333
我們也可以惡作劇地修改一下這個值:
#!bash
tracer -l:excel.exe bpx=excel.exe!BASE+0x11E91B,set(st0,666)
PID=36540|TID=24056|(0) 0x2f40e91b (Excel.exe!BASE+0x11e91b)
EAX=0x00680006 EBX=0x00680018 ECX=0x00000001 EDX=0x00000001
ESI=0x00680000 EDI=0x00395404 EBP=0x0290FD9C ESP=0x0290FD58
EIP=0x2F40E91B
FLAGS=PF IF
FPU ControlWord=IC RC=NEAR PC=64bits PM UM OM ZM DM IM
FPU StatusWord=C1 P
FPU ST(0): 0.333333
Set ST0 register to 666.000000
Excel在這個單元中顯示666,我們也可以確信的確找到了正確的位置。
如果我們嘗試使用同樣的Excel版本,但是是64位的,會發現只有12個FDIV指令,我們的目標指令在第三個。
tracer.exe -l:excel.exe bpx=excel.exe!BASE+0x1B7FCC,set(st0,666)
看起來似乎許多浮點數和雙精度型別的除法操作都被編譯器用SSE指令比如DIVSD(DIVSD總共出現了268次)替換了。
第61章
可疑的程式碼模式
61.1 XOR 指令
像XOR op這樣的指令,op為暫存器(比如,xor eax,eax)通常用於將暫存器的值設定為零,但如果運算元不同,"互斥或"運算將被執行。在普通的程式中這種操作較罕見,但在密碼學中應用較廣,包括業餘的。如果第二個運算元是一個很大的數字,那麼就更可疑了。可能會指向加密/解密操作或校驗和的計算等等。
而這種觀察也可能是無意義的,比如"canary"(18.3節)。canary的產生和檢測通常使用XOR指令。
下面這個awk指令碼可用於處理IDA的.list檔案:
gawk -e '$2=="xor" { tmp=substr($3, 0, length($3)-1); if (tmp!=$4) if($4!="esp") if ($4!="ebp")⤦ 
相關文章
- 逆向基礎(二)2020-08-19
- 羽夏逆向——逆向基礎2021-11-19
- 逆向基礎(六)2020-08-19
- 逆向基礎(五)2020-08-19
- 逆向基礎(四)2020-08-19
- 逆向基礎(三)2020-08-19
- 逆向基礎(十一)2020-08-19
- 逆向基礎(十)2020-08-19
- 逆向基礎(十二)2020-08-19
- 逆向基礎(一)2020-08-19
- 逆向基礎(九)2020-08-19
- 逆向基礎(八)2020-08-19
- 逆向基礎(七)2020-08-19
- 逆向工程核心原理(1)逆向基礎2023-03-16
- BUUCTF 基礎CODE REVIEW2021-04-04View
- 逆向基礎(十三) JAVA (一)2020-08-19Java
- iOS逆向-彙編基礎(一)2018-11-05iOS
- iOS逆向與安全:基礎篇2018-10-31iOS
- iOS逆向之旅(基礎篇) — 彙編(二) — 彙編下的 IF語句2018-10-25iOS
- Terraform基礎入門 (Infrastructure as Code)2023-02-18ORMASTStruct
- iOS逆向之旅(基礎篇) — 彙編(一)— 彙編基礎2018-10-25iOS
- 20192204-exp1-逆向與Bof基礎2022-03-17
- iOS逆向之旅(基礎篇) — Macho檔案2018-10-26iOSMac
- An important person2024-04-06Import
- CSS !important2018-10-30CSSImport
- Java逆向基礎之靜態變數存取2021-09-09Java變數
- 基礎題二2024-08-21
- Dart基礎(二)2019-07-08Dart
- Kotlin基礎二2018-06-11Kotlin
- 逆向WeChat (二)2024-05-17
- 『杭電1937』Finding Seats2020-11-13
- Writing on important details2024-03-30ImportAI
- Java基礎 —— 集合(二)2024-12-09Java
- 二、MySQL基礎操作2024-07-05MySql
- 前端基礎——HTML(二)2020-10-22前端HTML
- JAVA SE基礎(二)2020-12-09Java
- DataBinding基礎使用二2018-08-10
- CF1987F Interesting Problem2024-10-14REST