您現在的位置是:首頁 > 手機遊戲首頁手機遊戲
免殺常用的彙編指令有哪些?如何等價替換匯編指令實現免殺?
- 2021-09-05
指令傳輸如何確定開頭
一、 什麼是PE檔案?
在Windows下所謂
PE檔案即Portable Executable,意為可移植的可執行的檔案
。常見的
.EXE、.DLL、.OCX、.SYS、.COM都是PE檔案。PE檔案有一個共同特點:前兩個位元組為4D 5A(MZ)
。如果一個檔案前兩個位元組不是4D 5A則其肯定不是可執行檔案。比如用16進位制文字編輯器開啟一個“。xls”檔案其前兩個位元組為:0XD0 0XCF;開啟一個“。pdf”其前兩個位元組為:0X25 0X50。
PE檔案結構
:DOS頭+PE頭+節表+。data/。rdata/。text。而今天我們就來具體瞭解一下PE檔案的DOS頭和PE頭的結構成員與部分成員的作用。注意:一個exe檔案本身是一個PE檔案,但是由於包含dll庫,所以一個exe檔案也是許多PE檔案組成的(包含多個dll)一個PE檔案
1、DOS頭:共40H(64位元組)
DOS頭中宣告用的暫存器(我們可以看到e_ss、e_sp、e_ip、e_cs還是16位的暫存器),所以在32位/64為系統中用到的只有兩個成員了(第一個和最後一個):
①e_magic:判斷一個檔案是不是PE檔案;
②e_lfanew:相對於檔案首的偏移量,用於找到PE頭;
2、PE頭
PE頭分為標準PE頭和可選PE頭,其同為NT結構的成員:
//NT頭
//pNTHeader = dosHeader + dosHeader->e_lfanew;
struct _IMAGE_NT_HEADERS{
0x00 DWORD Signature; //PE檔案標識:ASCII的“PE\0\0”
0x04 _IMAGE_FILE_HEADER FileHeader;
0x18 _IMAGE_OPTIONAL_HEADER OptionalHeader;
};
根據DOS頭的e_lfanew成員我們就可以找到NT頭,NT頭的第一個成員是“PE\0\0”(0X50 0X45 0X00 0X00四位元組的簽名,可以在上圖00000100H地址處觀察),後兩個成員則分別是標準PE頭(_IMAGE_FILE_HEADER)和可選PE頭(_IMAGE_OPTIONAL_HEADER)。
3、幾個重點的資料成員
(1)、檔案對齊(FileAlignment)和記憶體對齊(SectionAlignment):
一個PE檔案載入進記憶體中可能大於在硬碟上的大小,並且無論是在記憶體中還是硬碟上,都是是分塊管理(分節),一塊和一塊儲存空間之間是空隙。在硬碟上空隙有可能小於記憶體中空隙;在記憶體中空隙較大(相較於硬碟)。而存在間隙的原因則是分塊管理。
分塊的一個原因是節省硬碟:比如notepad。exe,由於是早期的程式,當時硬碟容量比較小,編譯器在生成可執行檔案時,不僅要考慮效率問題使得記憶體對齊/檔案對齊,還需要設計成節省硬碟空間的結構。所以這種結構遵循的對齊原則:記憶體對齊(1000H)和硬碟對齊(200H),對齊的補充資料(0X0000)便是間隙。硬碟的對齊值較小,補充間隙自然小,因此同一個可執行程式在記憶體中可能比在硬碟上大。但是現如今的硬碟空間更大,所以編譯器生成的可執行程式在硬碟上與記憶體中對齊方式都是1000H。統一對齊為1000H的目的依舊是提高效率。
而分塊的另一個目的是節省記憶體空間,比如同時在電腦上執行登入多個QQ賬號,就需要執行多次QQ可執行程式。而程式碼段為只讀資料需要一份即可,資料段則需要為每個賬號均開闢一份,,多個QQ程式共享程式碼塊,單獨使用資料塊,這樣就節省了多份程式碼塊的記憶體。(這些塊是使用結構體來維護的,分塊即建立結構體)。
(2)、映象地址/基址ImageBase的作用:
FileBuffer是磁碟上。exe檔案在記憶體中的一份複製,但是FileBuffer無法直接在記憶體中執行,必須經過PE loader(裝載器)裝載以後成為ImageBuffer。ImageBuffer是FileBuffer的“拉伸”。即“。exe–>FileBuffer–>ImageBuffer”
①.exe首地址(基址)為0
②FileBuffer首地址也為0
③ImageBuffer首地址為ImageBase
④而真正的程式入口地址是:ImageBase + AddressOfEntryPoint(OEP)
一個exe檔案預設映象地址為400000H(有可能不是,總之有一個預設值),如果一個exe檔案中用到了多個dll,而dll檔案作為一個PE檔案,其預設映象地址也均是400000H,作業系統不會修改exe的映象基址。因為。exe先被載入,在。exe中才載入的dll庫,由於400000已經被。exe佔用,所以裝載器會修改dll的映象基址。而採用ImageBase + OEP的目的也就是:採用偏移地址的方式可以更方便地修改基址,使得任何一個dll檔案基址修改後程式依舊不會出錯。比如:dll和exe基址有衝突,本只需要將衝突的。dll的檔案基址修改為600000H(假設是編譯器為其分配的是600000H);如果不採用“基址+偏移地址”的方式,而採用絕對地址,那麼要修改的就不是一個基址為600000H了,而是dll中所有的地址統一加上200000H(因為原來預設為400000H)。
二、 彙編基礎知識
1、
暫存器
顧名思義,暫存器就是暫時儲存資料的地方,暫存器被設計在CPU內部,對於一個彙編程式設計師來說,CPU中最主要的部分就是暫存器了。暫存器是程式設計師能透過指令讀寫的部件,程式設計師透過改變暫存器的值間接的控制CPU
eax:拓展累加暫存器;ecx:迴圈計數器;edx:資料暫存器;ebx:基址暫存器;
2、堆疊
堆疊是連續的記憶體單元,存取方式遵循“先進後出”原則,棧是一種特殊的儲存方式,特殊在最先進入這個空間的資料卻是最後出去的。但是堆和棧不是同一個概念,棧一般由編譯器自動分配釋放,儲存函式的引數值、區域性變數值等;而堆,一般由程式設計師分配釋放,程式結束時可能由OS(系統)回收。
esp:棧頂;ebp:棧底;esi:拓展目地指標;edi:拓展目地指標;eip:指令指標
。
3、彙編指令
彙編指令有5類:1.資料傳輸指令:mov2.邏輯計算指令:add3.串操作指令:movs4.控制轉移指令:jmp5.處理器控制指令:nop
其中1,2,4類指令對免殺有用。
4、常用免殺彙編指令
mov ebp,9:傳送指令push ebp :進棧指令pop ebp :出棧指令add esp,8 :加法指令sub esp,8 :減法指令inc ecx :增量指令dec ecx :減量指令jmp 00000001 :無條件跳轉指令call 00000001 :呼叫指令
xchg 交換指令
pushad 壓棧8個暫存器
popad 彈出8個暫存器(先進後出)
三、免殺常用等價替換匯編指令修改方法
A開頭:
add 改adc
ADD 改ADC
ADD 1 改 sub -1
add dword ptr ss:[ebp-130],edx ————-adc dword ptr ss:[ebp-130],edx
ADD [EAX],CH——————————————ADD [EAX],DH
ADD [EAX],BH 0038 ————————————ADD [EAX+40],AL 0040 40
ADD [EAX+EAX*2+46],AL ——————————ADD [EAX+EAX*2+46],CL
ADD [EAX+40],DL 0050 40 ————————0058 40 ADD [EAX+40],DL
ADD AH,CH 00EC ————————————-00F4 ADD AH,DH
add dword ptr ss:[ebp-130],edx ———— adc dword ptr ss:[ebp-130],edx
C開頭:
CMP 改SUB
call 復件_(4)。004CF607 ————————- push 復件_(4)。004CF607
CMP DWORD PTR DS:[100170A4],0 ——————-sub DWORD PTR DS:[100170A4],0
CALL ————-看到了CALL跟隨進去看NOP就可以把CALL的地址該成NOP
方法2——看下附近有沒有MOV修該成NOP看下可以免殺不。可以的話該XOR
方法3——看附近jnz跳轉該下跳轉的地址/可免殺不/
CALL EAX |CALL EBX
比效指令 CMP:看下是個比效指令 在看下JNZ條件轉移指令
就是說CMP比效正確就跳那我們可以把CMP用NOP掉在把JNZ該成JMP
不進行CMP比效
CMP ESI,1
call 改 jmp
D開頭:
DAA 組合的十進位制加法調整指令 ————DAS 減法的十進位制調整。
J開頭:
JE 改 JNB
JNZ 改 JNL
jnz 改 JB
JE 改 JNA
je 改 jb
jnz 改 jg
js 改 jp
je 改 jle
jnz 改 jle
je 改 jge
JE 改 jnz
JE 改 JB
JNS 改 POP ECX
JNS 改 jnc-jnb
JNB 改 JGE
jnb short fsg2_0。0040015D————————ja short fsg2_0。0040015D
JMP NEAR [1071c]——————————-JMP NEAR [1071B]
jnz——je-jmp修改中要看下跳的地址是不是很重要說明[1]
JNZ 00874E85——MOV EAX,88B6D0 可以是該成JE 00874E85——MOV EAX,88B6D0
L開頭:
LEA EBP,[ESP+10] 改 LEA EBP,[ESP+10]
M開頭:
MOVSX 改 MOVZX
MOV EBP,ESP 改 AND AH,CH
MOV [EBP-18],ESP 改 MOV [EBP-18],AH
MOV EAX,[ESP+10] 改 MOV EAX,[ESP+10]
MOV [ESP+10],EBP 改 MOV [ESP+10],EBP
mov [ebp-256], eax 改 adc [ebp-226], eax
MOV EDI,[EBP+10] 改 MOV EDI,[EBP+11]
MOV EBX,DWORD PTR DS:[ESI] 改 XOR EBX,DWORD PTR DS:[ESI]
MOV EBP,ESP————AND AH,CH
MOV EBX,DWORD PTR DS:[ESI]————-XOR EBX,DWORD PTR DS:[ESI]
P開頭:
push 改call
PUSH EBX PUSH EDI
PUSH ESI PUSH EAX
PUSH EDI PUSH ESI
PUSH EAX PUSH EBX
pop 改 nop
S開頭:
sbb 改adc
sub 改mov
SHL 改 SAL
SAR 改 SHR
sub ebp,7—————— add ebp,-7
sub ebx,eax——————sbb esi,ecx
SBB ECX,DWORD PTR DS:[ESI+2]——————ADC ECX,DWORD PTR DS:[ESI+2]
sub ebx,eax——————sbb esi,ecx
X開頭:
xor 改sub
XOR [EAX],AL————-改————MOV [EAX],AL
XOR EAX,EAX——-改————-OR EAX,EAX