反匯編技術筆記-基礎知識


相關學習資源

二進制安全相關工具和教程站點

內容體系

  • 基本概念
  • IA-32處理器體系結構
  • 匯編語言基礎
  • 數據傳送、尋址和算術運算
  • 過程
  • 條件處理
  • 整數算術指令
  • 高級過程
  • 字符串和數組
  • 結構和宏
  • 32位Windows變成
  • 高級語言結構
  • 16位MS-DOS程序設計
  • 磁盤基礎知識
  • BIOS程序設計
  • 高級MS-DOS程序設計
  • 高級主題

匯編和二進制基礎知識

  • CPU指令的基本單位
    1 byte = 8 bit 0~155
    1 word = 2 byte 0~65535
    1 double word = 2 word 0~4294967295
    1 kilobyte = 1024 byte
    1 megabyte = 1024 kbyte

  • 總線
    數據總線
    控制總線
    地址總線

  • 地址空間
    32位寄存器可以使用0-2^32-1,可對4GB內存進行尋址

  • 寄存器
    80386處理器中的寄存器分為8組,每組寬度為32位
    通用寄存器
    段寄存器
    指令寄存器
    標志寄存器
    系統地址寄存器
    控制寄存器
    調試寄存器
    測試寄存器

  • 通用寄存器
    EAX 累加器 在乘法和除法指令中被自動使用
    EBX 基址寄存器
    ECX 計數器 循環計數器
    EDX 數據寄存器
    ESI 源變址寄存器
    EDI 目的變址寄存器
    EBP 擴展基址指針寄存器 由高級語言用來引用函數參數和局部變量
    ESP 棧指針寄存器

EAX EBX ECX EDX ESI EDI EBP ESP #32位
AX BX CX DX SI DI BP SP #低16位
AH BH CH DH #高8位
AL BL CL DL #低8位

  • 段寄存器:
    CS:代碼段(Code Segment)
    DS:數據段(Data Segment)
    ES:附加數據段(Extra Segment)
    SS:堆棧段(Stack Segment)
    FS:附加段
    GS 附加段

  • 指令寄存器:
    EIP 指令指針寄存器
    低16位為IP(8086)
    它存儲的是下一條要執行指令的地址。

  • 標志寄存器:
    IOPL(I/O Privilege Level) I/O特權級字段,它的寬度為2bit,它指定了I/O指令的特權級。如果當前的特權級別在數值上小於或等於IOPL,那么I/O指令可執行。否則,將發生一個保護性異常。
    NT(Nested Task): 控制中斷返回指令IRET,它寬度為1位。NT=0,用堆棧中保存的值恢復EFLAGS,CS和EIP從而實現中斷返回;NT=1,則通過任務切換實現中斷返回。
    RF(Restart Flag): 重啟標志,它的寬度是1位。它主要控制是否接受調試故障。RF=0接受,RF=1忽略。如果你的程序每一條指令都被成功執行,那么RF會被清0。而當接受到一個非調試故障時,處理器置RF=1。
    VM(Virtual Machine): 虛擬8086模式(用軟件來模擬8086的模式,所以也稱虛擬機)。VM=0,處理器工作在一般的保護模式下;VM=1,工作在V8086模式下。
    其它16個標志位的含義和8086一樣:
    CF(Carry Flag): 進位標志位,由CLC,STC兩標志位來控制,在無符號算數運算的結果無法容納於目的操作數中時被設置

PF(Parity Flag): 奇偶標志位
AF(Assistant Flag): 輔助進位標志位
ZF(Zero Flag): 零標志位
SF(Singal Flag): 符號標志位
IF(Interrupt Flag): 中斷允許標志位,由CLI,STI兩條指令來控制
DF(Direction Flag): 向量標志位,由CLD,STD兩條指令來控制
OF(Overflow Flag): 溢出標志位

PSW(Program Flag)程序狀態字寄存器,是一個16位寄存器,由條件碼標志(flag)和控制標志構成
+---------------------------------------------------------------+
|15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
+---------------------------------------------------------------+
|-- -- -- -- OF DF IF TF SF ZF -- AF -- PF -- CF |
+---------------------------------------------------------------+

OF(Overflow Flag)溢出標志。溢出時為1,否則置0
SF(Sign Flag)符號標志。結果為負時置1,否則置0
ZF(Zero Flag)零標志,運算結果為0時ZF位置1,否則置0
CF(Carry Flag)進位標志,進位時置1,否則置0
AF(Auxiliary carry Flag)輔助進位標志,記錄運算時第3位(半個字節)產生的進位置。有進位時1,否則置0
PF(Parity Flag)奇偶標志。結果操作數中1的個數為偶數時置1,否則置0
DF(Direction Flag)方向標志,在串處理指令中控制信息的方向
IF(Interrupt Flag)中斷標志
TF(Trap Flag)陷井標志

  • 直接標志轉移

  • 尋址方式
    段基址*10H+段內偏移地址,形成20位地址
    段基址是16的倍數,長度最大不超過64K

  • 數據的表示方法

匯編指令

  • 整數
    d 十進制
    b 二進制
    q/o 八進制
    h 十六進制
    r 編碼實數
    t 十進制(可選)
    y 二進制(可選)

  • 整數表達式
    優先級
    1 ()
    2 +,- 單目加減
    3 *,/
    3 MOD 取模
    4 +,- 加減

  • 數據傳送
    算術運算/邏輯運算
    移位
    控制轉移
    串操作
    高級語言支持
    條件字節設定
    位操作
    處理器控制
    保護方式

  • 通用數據傳送
    累加器專用傳送
    地址傳送
    標志傳送

  • 偽指令
    .data 標識包含變量的區域
    .code 標識程序中包含指令的區域
    func PROC PROC標識了過程的開始,func可以是任何名字

  • 代碼標號

target:
	mov ax,bx
	jmp target
  • 數據標號
first BYTE 10
  • 注釋
	;單行注釋
COMMENT	;
	多行注釋
;
mov		賦值
add		兩個值相加
sub		相減
mul		相乘
inc		加1
dec		減1
neg		求相反數(轉換成對應的二進制補碼,補碼可通過將目的操作數的所有數據位取反加1)
jmp		跳轉到一個新位置
call	調用一個過程
byte	8位無符號整數
sbyte	8位有符號整數
word	16位無符號整數
sword	16位有符號整數
dword	32位無符號整數
sdword	64位有符號整數
fword	48位整數
qword	64位整數
tbyte	80位整數
real4	32位IEEE短實數
real8	64位IEEE長實數
real10	80位IEEE拓展精度實數
.data
list BYTE 10,20,30,40

;在內存中的形態:
;	0000:10
;	0001:20
;	0002:30
;	0004:50

list BYTE 10,20,30,40
BYTE 50,60,70,80
BYTE 81,82,83,84

;定義字符串
str1 BYTE 'This is a test', 0			;
str2 BYTE "This is a test ",0dh,0ah,	;CRLF
BYTE "This is a test ",0dh,0ah,0	;
	
dup		
BYTE 20 DUP(0)	;20字節,全部用0填充
BYTE 4 DUP("stack")	;20字節,"STACKSTACKSTACKSTACK"

word1 WORD 65535	;最大無符號字
word2 WORD -32768	;最小無符號字
word3 WORD ?		;未初始化的字

push 壓棧
pop 出棧
MOV 賦值
MOVZX 零拓展傳送
MOVSX 符號拓展傳送

MOV DL,90H		;DL=90H
MOVSX AX,DL		;AX=FF90H
MOVZX AX,DL		;AX=0090H
MOVSX ESI,DL	;ESI=FFFFFF90H
MOVZX ESI,DL	;ESI=00000090H

CBW 將字節數據擴展成字,符號位擴展到AH中
CWD 將字數據擴展成雙字,符號位放到DX中

MOV AL,70H	;
CBW			;AX=0070(2byte,1word)
CWD			;DX=0000,AX=0070(4byte,2word)

XCHG 交換兩個操作數的數據,支持8位、16位、32位
PUSH 入棧,支持立即數入棧
PUSHA 將8個16位通用寄存器全部入棧,順序為AX,CX,DX,BX,SP,BP,SI,DI,然后SP指針寄存減16,內容為PUSHA指令執行前的內容
PUSHAD 將8個32位通用寄存器全部入棧,順序為EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI,然后ESP的內容是執行指令PUSHAD之前的內容
POP 出棧
POPA 8個16位通用寄存器全部出棧,堆棧指針寄存器不是堆棧中彈出的內容,而是加16之后得到
POPAD 8個32位通用寄存器全部出棧,ESP的內容是執行指令PUSHAD之前的內容
LEA 取有效地址

MOV EAX, 11111111h
MOV EBX, 11111111h
LEA ECX, [EAX+EBX]	;ECX = 22222222h

LDS 裝入指針,目的寄存器必須是16位或32位的通用寄存器,操作數必須是內存單元,不能是立即數

LDS EAX, [1000H];將偏移地址為1000,1001h這兩個字節單元的內容送給DS,將1002,1003,1004,1005這四個字節單元的內容送往EAX
LDS AX,[1000H];這表明將偏移地址為1000,1001H這兩個字節單元的內容送給段寄存器DS,將偏移地址1002,1003H兩個字節單元的內容送往EAX

LES 同LDS,不過段寄存器是ES
LFS 同LDS,不過段寄存器是FS
LGS 同LDS,不過段寄存器是GS
LSS 同LDS,不過段寄存器是SS

LAHF 將標志寄存器的低8位送至AH中,包括SF,ZF,ZF,PF,CF。
SAHF 與LAHF的過程恰好相反
PUSHF 將標志寄存器的EFLAGS低16位內容入棧
PUSHFD 將標志寄存器EFLAGS的內容入棧
POPF 將棧頂的一個字彈出,並將它送到標志寄存器EFLAGS的低16位
POPFD 將棧頂的兩個字彈出,並將它送到標志寄存器EFLAGS

OFFSET 取當前內存的地址

offset Array

EBP EBP指向棧底
ESP 指向棧區域的棧頂位置
EIP 指向下一個將會被執行的指令

EAX = [AX]+[AH+AL]

db: 聲明 1 byte(字節)變量
dw: 聲明 2 byte(字節)變量 = 1 word
dd: 聲明 4 byte(字節)變量 = 2 word = 1 double word

mov eax ebx
mov eax 333h
mov eax [ebx]
mov eax [ebx+66h]

和C語言的對比:
a = b[0x66] => mov eax [ebx+66h]

數據交換:

lea edx, b			;將edx指向b
mov [edx], ebx		;賦值a = b
mov ebx, a			;賦值ebx = a
mov b,ebx			;賦值a = b
mov ecx, offset a	;將ecx指向a

條件跳轉:
cmp 比較結果
jx 檢查條件x,有大於、小於、等於三個狀態
je 相等時跳轉
jne 不相等時跳轉
jb、ja 比較無符號數然后決定是否跳轉
jl、jg 比較有符號數然后決定是否跳轉
jbe 在一個無符號數小於或者等於另一個無符號數時發生跳轉
jmp 無條件跳轉

cmp EAX,EBX		;比較EAX和EBX
jz	xxx			;如果相等就跳轉到xxx
cafebabe
cmp [ECX], EDX	;比較*ECX和EDX的值
JAE	yyy			;如果*ECX>=EDX,就跳轉到yyy
  • 函數調用:
push offset, LibName	;將字符串偏移量壓入堆棧
call LoadLibrary		;進行函數調用
mov h,EAX				;將EAX中的值傳給變量h

PE、ELF基礎知識

  • PE文件結構:
    .text 二進制代碼
    .data 初始化的數據塊
    .idata 動態鏈接庫等外來函數與文件
    .rsrc 資源

文件偏移地址 = 虛擬內存地址-裝載基址-節偏移
= RVA - 節偏移

  • 文件幻數
    Windows PE File
4d 5a							MZ

Jpeg Image File

ff d8 ff e0 00 10 4a 46 49 46	JFIF

Java .class file

ca fe ba be

基本工具

  • PE Tools 分析Windows進程和可執行文件
  • PEiD 識別構建PE文件所使用的編譯器
  • nm 檢查中間目標文件(拓展名為.o的文件),可以顯示符號、函數等信息
    動態鏈接二進制文件,未定義的符號在C語言共享庫中定義
  • ldd 鏈接器(靜態鏈接、動態鏈接)
    靜態鏈接:鏈接器將應用程序的目標文件和所需的庫文件組合起來,可執行文件更大
    動態鏈接:不需要復制庫,方便維護,可執行文件更小
gcc -o test test.c
gcc -o test test.c --static

編譯好之后可以通過file參數查看類型

ldd ./test	
#查看庫依賴(mac:otool -L windows:dumpbin)

`objdump 節頭部 程序每節的摘要信息
專用頭部 程序內存分布信息,還有運行時加載器所需的其他信息
調試信息 程序中的調試信息
符號信息 類似nm的方式轉儲符號表信息
反匯編代碼清單 對文件中標記為代碼的部分執行線性掃描反匯編

  • dumpbin 從PE文件提取符號、導入函數名、導出函數名和反匯編代碼
  • c++filt nm test | grep demo |c++filt
    跟C++函數重載有關的操作,顯示重載函數的不同形態
  • strings 提取文件中的字符串內容 strings test
    strings -t 可顯示字符串文件的偏移量信息
    strings -e 可搜索更廣泛的字符

反匯編器:

msfpayload linux/x86/shell_findport CPORT=4444 R >test
ls -l test
ndisasm -u test

分析網絡數據包中可能包含shellcode的計算機網絡攻擊時,可以采用流式反匯編器來反匯編數據包中包含shellcode的部分

棧幀: 程序運行時棧中分配的內存塊,專門用於特定的函數調用。
因為每個遞歸函數調用都有自己的棧幀,使得遞歸成為可能。

  • 函數調用步驟:
    1.調用方將被調用方所需的參數放到該函數所采用的調用約定制定的位置
    2.調用方將控制權轉交給被調用方
    3.如有必要,為被調用的函數配置棧指針
    4.被調用方為局部變量分配空間
    5.被調用函數執行操作
    6.函數完成操作后,為局部變量保留的棧空間被釋放。(逆向執行第4步中的操作)
    7.還原寄存器值
    8.被調用函數將控制權返還給調用方
    9.刪除棧中的參數

  • 調用約定: 通過調用函數將函數參數存入棧中,調用函數必須存儲被調用函數所需的參數。
    調用約定指定調用方放置函數所需參數的具體位置。
    調用約定可能要求將參數放置在制定的寄存器、程序棧或者寄存器和棧中。
    c調用規定。
    cdecl調用約定規定:
    調用方按從右到左的順序將函數參數放入棧中。
    在被調用的函數完成操作時,調用方負責從棧中清除參數。

ida基本知識

ida目錄結構

  • cfg 配置文件
  • idc 包含內置腳本語言IDC所需的核心文件
  • ids 包含一些符號文件
  • loaders 在加載過程中用於識別和解析PE或ELF等一直格式的IDA拓展
  • plugins 包含專門為IDA提供的附加功能
  • procs 包含已安裝的IDA版本所支持的處理器模塊
  • sig 包含IDA在各種模式匹配操作中利用的現有代碼的簽名
  • til 包含一些類型庫信息

ida基本操作

  • HKEY_CURRENT_USER\Software\Hex-Rays\IDA IDA注冊表項

ida數據庫文件

要分析的文件為main.exe
會在目錄中生成

  • main.id0 二叉樹形式的數據庫
  • main.id1 包含描述每個程序字節的標記
  • main.nam 包含於IDA的Names窗口中顯示的給定程序位置有關的索引信息
  • main.til til文件用於存儲與一個給定數據庫的本地類型定義有關的信息
  • main.idb ida數據庫文件

IDA創建數據庫

從磁盤加載文件,解析文件頭信息,創建包含代碼或數據的程序塊
編譯器識別:IDA嘗試確定用於創建輸入文件的編譯器,如果能確定,就可以掃描該編譯器使用的樣板代碼序列
函數參數和局部變量識別:
數據類型信息:

ida桌面

  • IDA View-A
  • Hex View-A Hex View可以右鍵編輯並提交
  • Hex View-B
  • String Window
  • Names Window F:常規函數
  • L:庫函數,通過簽名匹配算法來識別
  • I:導入的名稱,通常為共享庫導入的函數名稱。
  • C:命名代碼
  • D:數據。已命名數據的位置通常表示全局變量。
  • A:字符串數據。
  • sub_xxxx:地址xxxx處的子例程
  • loc_xxxx:地址xxxx出的e指令
  • byte_xxx:位置xxx處的8位數據
  • word_xxx:位置xxx處的16位數據
  • dword_xx:位置xx處的32位數據
  • unk_xxxx:位置xxxx處的大小未知的數據

ida熱鍵

  • IDA>View:
  • View>Open Subviews 恢復需要的窗口
  • ESC 后退(跳轉到上一個)
  • Ctrl+Enter 前進(跳轉到下一個)
  • G (GoTo) Jump To Address

加深理解-匯編指令、長度和十六進制的關系

+---------------------------------------------------------------------+
|位置:地址 指令 對應16進制指令 長度 |
+---------------------------------------------------------------------+
|.text:00401010 push ebp 55 1byte |
|.text:00401011 mov ebp, esp 8B EC 2byte |
|.text:00401013 sub esp, 44h 83 EC 44 3byte |
|.text:00401016 push ebx 53 1byte |
+---------------------------------------------------------------------+


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM