DEF分析與打造其脫殼軟體----我的一篇析文

看雪資料發表於2015-11-15

標 題:DEF分析與打造其脫殼軟體----我的一篇析文

發信人:藍星

時 間:2004年2月26日 07:16 

詳細資訊: 



DEF分析與打造其脫殼軟體  

初來貴地.獻析文一篇. 請高手勿笑  .
我不知道有這麼個地方, 以後請大家多指教.
我寫的不怎麼好的地方,請大家指正.
我不怎麼懂脫殼,請不要大家找我脫殼。。。   

作者:牛博威 

Email:advice107@sina.com 

http://nboy.cnwlt.com 

qq:  343538175
       加殼軟體一種可以對別的程式進行修改但是不影響其使用的工具軟體。程式設計師經常利用加殼軟體對自己的軟體進行加殼,以加密或者壓縮自己的軟體。加殼後的軟體一般來說難以被逆向分析,因此,脫殼軟體應運而生。從某種角度來說,瞭解加殼和脫殼技術的原理是很有必要的。 

       下面我以Def為例說明其加殼原理,同時,我們改造Def使其具有針對自身的脫殼功能。 

Def是一款原始碼開放的小型加殼軟體,精煉易懂,便於學習。其原始碼和程式可以去http://protools.cjb.net下載 或 點選此處下載(或滑鼠右鍵另存為)

       首先根據其原始碼分析其加殼原理。它的加殼流程主要如下: 

1、  以檔案記憶體映象方式開啟被加殼檔案,並判斷是否是有效的PE檔案且不是Dll檔案; 

2、  遍歷所有節表,根據節表名判斷是否是輸入表,資源節表或者其他節表,如果不是,定位到該節區,根據本節區大小對該節區的內容進行簡單的異或加密,加密方式如下: 

_encrypt:                              ;加密該節區 

              xor  byte ptr[esi],al        ;進行異或加密 

       inc   esi                        ;esi指向節區下一個位元組 

              dec  eax                       ;判斷是否到節區尾部,同時也是下一次異或操作的變數 

       jne   _encrypt 

              然後把節表名稱修改為.def,對未進行加密的節表,新增未加密標誌,具體見下文; 

3、  為被加殼檔案新增自解密部分,用於被加殼檔案執行時候自行解密。這一段可以參考原始碼中的_loader部分。這段自解密程式碼被新增到檔案節表的後面,同時修改檔案的入口地址為此處的偏移地址。新增自解密部分的程式碼如下: 

              mov esi,offset _loader           ; 初始化_loader的偏移地址 

       mov ecx,_loader_size            ; 初始化loader部分的大小 

              rep   movsb                          ; 把loader部分複製到被加殼檔案的節表尾部 

                                                 ;其實這裡最好判斷一下是否有足夠空間放置本段程式碼 

4、  最後關閉檔案記憶體映象; 

根據上面的流程分析,再仔細研究一下其程式碼,相信你可以很快明白它的具體工作方式。下面我們來修改def,使其具有脫殼功能。 

       Def手工脫殼很簡單,我以脫去Def自身的殼為例,說明其脫殼流程: 

1、  用Trw載入Def; 

2、  F10單步執行至xxxx:400244   push   dword  ptr  00401000  處,其中00401000為Def原來的入口地址。下命令Suspend,將程式掛起,F5回到windows介面; 

3、  開啟Peditor,點task,選擇被掛起的Def程式,點右鍵dump(full),儲存為unDef; 

4、  用Peditor修改unDef檔案的入口地址為00001000,注意這裡是00401000減去00400000得到的。 

好了,這樣unDef就是Def的脫殼檔案。我們現在要修改Def為自身的脫殼程式,也就是要對unDef進行處理。 

首先,脫殼程式應該可以判斷一個檔案是否被Def加殼,利用Def的判斷方式,判斷第一個節表名稱是否為.def便可以。故此,修改: 

:00401091 813A2E646566            cmp dword ptr [edx], 6665642E              ;.def ? 

:00401097 0F858B000000            je 00401128 

為: 

:00401091 813A2E646566            cmp dword ptr [edx], 6665642E 

:00401097 0F848B000000            jne 00401128       ;如果第一個節表名不為.def則跳出 

                                                                                    ;請注意這裡最好不要改成jmp 

現在就可以對加殼檔案進行脫殼了,由於def採用了簡單的異或加密,因此解密部分不需要修改。找個加殼檔案實驗一下,竟然發生異常。為什麼這樣呢?因為Def並不是把所有的節表都加密,對於引入表,資源節表等,def是不處理的。但我們的unDef會把所有的節表都進行解密,因此當然會發生錯誤。也許你會問,在程式中不是有call _is_encryptable(也就是:004010A7 call 004011A0)用來判斷是否應該被加密麼?不錯,雖然如此,但是仔細再看一下_is_encryptable這個函式,它透過節表名來判斷節表的修改合法性,而被加殼的檔案所有節表名稱都被改成了.def。因此,對這個函式來說加殼檔案中所有的節表都應該被修改。 

難道我們就沒有辦法判斷了麼?當然不是,仔細研究一下加殼檔案的引導部分,也就是Def原始碼中的_loader部分,在程式自身解密的時候有cmp byte ptr [esi+07], 00,其中esi指向節表頭,如果[edx+07]=0 則跳過解密部分,否則進行解密。這樣一來,我們修改unDef的解密部分。從VA=004010A7開始,修改後如下: 

:004010A7 807A0700                cmp byte ptr [edx+07], 00  ;判斷節區修改標誌 

:004010AB 90                      nop      ;保證檔案後面的內容不變 

:004010AC 90                      nop 

:004010AD 90                      nop 

:004010AE 740F                    je 004010BF ;如果不該解密,便跳過解密部分 

到這裡,就可以把所有加密部分恢復。但是脫殼檔案仍然無法執行,因為我們還沒有把檔案的入口地址修改過來。看一下def如何修改入口地址,你可以很容易編寫恢復入口地址的程式碼,如下: 

:004010D6 50                      push eax 

:004010D7 8B4225                  mov eax, dword ptr [edx+25]    ;edx指向節表最後 

                                                                                           ;[edx+25]為真正的入口地址 

:004010DA 2D00004000              sub eax, 00400000            ;入口地址的RVA->eax 

;減去imagebase,我這裡圖省事,直接減去00400000H,正規的應該從檔案中讀取 

:004010DF 894728                  mov dword ptr [edi+28], eax     ;edi+28指向入口地址 

:004010E2 58                      pop eax 

:004010E3 E92B000000              jmp 00401113             ;跳轉到新增_loader處 

:004010E8 90                      nop                            ;保證原來的檔案內容不變 

最後,修改_loader處的程式碼為自己的資訊(這就是上面為何跳到401113)。把 "The Undef Made by NBW  QQ:37122085  http://nboy.cnwlt.com"的ASCII碼覆蓋到檔案地址1154處,同時要修改: 

:00401118 B92A000000              mov ecx, 0000002A 

因為這個地方定義了新增的新程式碼的長度,如下: 

:00401118 B93A000000              mov ecx, 00000036     ;36H就是我新增的資訊的長度 

       到此,我們的unDef就製作完畢了,找一個被Def加殼的程式,用unDef進行脫殼,OK!很好用。 

       最後再多說幾句,上面的這些地址除註明外都是程式的虛擬地址,在修改unDef的時候,不妨用Hiew開啟,按F3,再按F2進入Asm修改狀態,你可以直接輸入彙編程式進行修改,但是由於Hiew支援的Asm程式碼不全面,因此有些語句還需要在16進位制狀態進行修改。從這個修改過程也可以看到,由於加殼軟體對原檔案的破壞,我們做的脫殼軟體並不可能100%地恢復加殼軟體原狀,至少節表的名稱和屬性沒有修改過來。因此,一些軟體被專家級別的加殼軟體所加殼,在脫殼的時候出現較大偏差是很正常的。 

下面是原始碼分析篇::::: 

        Def是一款典型的加殼軟體,軟體可以進行簡單的異或加密,並且也未對輸入表等進行處理,總體來說非常簡單。 
      我在這裡對其原始碼寫了詳細的註釋,仔細看一看會有不少收穫。原始碼也有註釋,但是我現在還不明白那是哪國天書。要有高手明白,不妨告知一二,這裡先謝過了。unDef是我寫對Def進行修改,使其可以脫自身的殼。  

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 
; DEF - prostacki encryptor plikow PE EXE 
; kompatybilny z 95,NT 

;原作: bart/xtreeme 

;這是一款典型的加殼軟體,軟體可以進行簡單的異或加密,並且也未對輸入表等進行處理,總體來說非常簡單。 
;其原始碼是開放的,並且非常簡練和易讀,仔細看一看會有不少收穫。原始碼也有註釋,但是我現在還不明白那是那國天書, 
;要有高手明白,不妨告知一二,這裡先謝過了。 



;註釋:牛博威 
;http://nboy.cnwlt.com 
;QQ : 37122085 
;Email: advice107@sina.com 
;我的資料被人拿走了,因此有些地方應該還有問題,不足指出還請大家包涵和指出 
;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

.586 ; 定義用的指令結合 
.mmx ; +mmx 
.model flat,stdcall 

includelib e:devmasmlibkernel32.lib ; 包含所需類庫 
includelib e:devmasmlibuser32.lib 
includelib e:devmasmlibcomdlg32.lib 

include e:devmasmincludekernel32.inc 
include e:devmasmincludeuser32.inc 
include e:devmasmincludecomdlg32.inc 

include e:devmasmincludewindows.inc 
include pe.inc ;pe.inc中定義了所需的常量,多與PE格式有關 

.data? 
lpFilename db 256 dup(?) ; 檔名 
lpFile MEMF <> ; 檔案控制程式碼 
lpPeheader dd ? ; PE頭 
lpSectionTable dd ? ;指向第一個節表的頭部 

.data 
lpOfn dd lOfn ; 定義開啟檔案所需要的結構 
dd 0 ; hWnd 
dd 0 ; hInst 
dd offset szFilter ; filtr 
dd 0  
dd 0  
dd 0  
dd offset lpFilename  
dd 256  
dd 0 ; lpstrFileTitle;  
dd 0 ; nMaxFileTitle;  
dd 0 ; lpstrInitialDir;  
dd offset szCaption ; lpstrTitle;  
dd OFN_HIDEREADONLY ; Flags;  

dw 0 ; nFileOffset;  
dw 0 ; nFileExtension;  
dd 0 ; lpstrDefExt;  
dd 0 ; lCustData;  
dd 0 ; lpfnHook;  
dd 0 ; lpTemplateName;  
lOfn equ $-lpOfn 


szCaption db 'DEF v1.0 by bart/xt - wybierz plik do zaszyfrowania',0 
szFilter db 'Pliki EXE (*.exe)',0,'*.exe',0 
db 'Wszystkie pliki (*.*)',0,'*.*',0,0 

szError db 'Nieprawidlowy format pliku!',0 
szDef db 'DEF v1.0 by bart/xt',0 

.code 
_start: 


push offset lpOfn ; lpOfn偏移入棧(廢話) 
call GetOpenFileNameA ; 呼叫通用對話方塊開啟檔案 
test eax,eax ; 判斷出錯否? 
je _exit 

push offset lpFilename ; 檔案路徑入棧 
call _open_file  
inc eax ; 這種判斷方式也算一種技巧 
je _exit  

test ecx,ecx 
je _exit  

dec eax  

mov ebx,offset lpFile ;ebx->檔案控制程式碼,也相當於檔案頭 
assume ebx:ptr MEMF ;把ebx賦值為MEMF結構 

mov [ebx].file_handle,eax ;儲存控制程式碼 
mov [ebx].file_size,ecx ;儲存大小 

push eax  
push ecx  
call _map_file ;以檔案記憶體映像的方式開啟檔案,這樣個方式的好處真是多多 
test eax,eax  
je _exit_close  

test ecx,ecx 
je _exit_close  

mov [ebx].mem_ptr,eax  
mov [ebx].mem_handle,ecx  
;下面是檔案合法性判斷 
cmp word ptr[eax],'ZM' ;判斷檔案頭部的Dos標誌“MZ”  
jne _bad_format 

add eax,dword ptr[eax+3Ch] ; eax->檔案NTHeader 
mov lpPeheader,eax  
xchg eax,edi ;edi->檔案NTHeader 

cmp dword ptr[edi],00004550h ; 判斷是否是PE檔案 
jne _bad_format  


cmp dword ptr[edi+entrypointRVA],0 ;判斷檔案的入口地址為0否? 
je _bad_format  

test word ptr[edi+DllFlags],2000h ; 判斷是否是Dll檔案 
jne _bad_format  

movzx edx,word ptr[edi+NtHeaderSize] ;edx->NtHeader尾部,我記不清楚這裡是否是節表開頭了,你可以查一下 
lea edx,[edi+edx+18h] ; edx->節表頭部 

cmp dword ptr[edx],'fed.' ; 判斷該檔案是否被Def加殼 
je _bad_format  


mov lpSectionTable,edx ; 儲存節表頭部 

movzx ecx,word ptr[edi+numObj] ; ecx->節表數目 

; edx <-- 節表頭部 
; edi <-- PE頭 
; ecx <-- 節表數目 

_encrypt_sections: 
; 判斷edx指向的節區是否該加密 
call _is_encryptable  
test eax,eax  
je _encrypt_skip  

mov esi,dword ptr[edx+objpoff] ;esi->節區檔案偏移地址 
add esi,[ebx].mem_ptr  
;esi->節區虛擬地址 

mov eax,dword ptr[edx+objpsize] ;eax->節區大小 

_encrypt: ;加密該節區 
xor byte ptr[esi],al ;進行異或加密 
inc esi ;指向節區下一個位元組 
dec eax ;判斷是否到節區尾部,同時也是下一次異或操作的一個變數 
jne _encrypt 

inc eax  
_encrypt_skip:  
mov dword ptr[edx],'fed.' ;修改節表名稱 
bswap eax ;eax由01000000改為00000001,如果開始為0,則仍然為0 
mov dword ptr[edx+4],eax ;把eax寫入節表名稱後面,這樣做是為了標誌該節表是否被加密 
;1->被加密 
;0->未被加密 
mov dword ptr[edx+objflags],0C00000E0h ;修改節區屬性為可寫可讀 

add edx,objlen ;edx->下一個節表 
loop _encrypt_sections ;轉入下一個節表的處理  


; korygowanie offsetow loadera 
mov edx,dword ptr[edi+imagebase] ;讀入基址 
mov dword ptr[_ldr_imagebase],edx ;儲存基址,便於被加殼檔案的載入 

mov eax,dword ptr[edi+entrypointRVA];讀入入口地址 
add eax,edx ;入口地址的VA 
mov dword ptr[_ldr_host],eax ;儲存入口地址,便於被加殼檔案的載入 

mov eax,lpSectionTable  
sub eax,[ebx].mem_ptr 
add eax,edx ; VA 
mov dword ptr[_ldr_sections],eax ;儲存節表頭的地址 

movzx ecx,word ptr[edi+numObj] ;節表數目 
mov byte ptr[_ldr_count],cl 

imul ecx,objlen ;ecx->節表大小 

mov eax,lpSectionTable ; 
sub eax,[ebx].mem_ptr 

add eax,ecx ;eax->節表尾部的RVA 

mov dword ptr[edi+entrypointRVA],eax;再次儲存入口地址,上面的儲存其實多餘 

add eax,[ebx].mem_ptr 
xchg eax,edi  
mov esi,offset _loader ; 初始化_loader的偏移地址 
mov ecx,_loader_size ; 初始化loader部分的大小 
rep movsb ; 把loader部分複製到被加殼檔案的節表尾部 
;其實這裡最好判斷一下是否有足夠空間放置本段程式碼 

push -1  
call MessageBeep ;響鈴 
jmp _exit_unmap 

_bad_format:  
push 10h  
push offset szDef 
push offset szError 
push 0 
call MessageBoxA 

_exit_unmap:  
push [ebx].mem_ptr 
push [ebx].mem_handle 
call _unmap 

_exit_close: 
push [ebx].file_handle  
call CloseHandle 

_exit: 
push -1 
call ExitProcess ; bye bye 



; 下面這一段被放入被加殼檔案的節表尾部,作為程式執行時候的解密部分 

_loader: 
mov esi,987654321 ;這裡的987654321只是為了給_ldr_sections留夠4個位元組的空間 
_ldr_sections equ dword ptr $-4 ;定義_ldr_sections及其地址,請注意查詢前面的設定 

push 0 ;節表數目 
_ldr_count equ byte ptr $-1 
pop ecx ;ecx->節表數目,在前面有設定 

_ldr_next: ;解密開始 
cmp byte ptr[esi+7],0 ;判斷這個節區是否該解密,根據[esi+7]判斷,請參考前面的註釋 
je _ldr_not_encrypted ;如果不該解密,越過下面的部分 

mov eax,dword ptr[esi+objrva] ;eax->節區的Rva 
add eax,987654321 ;eax->節區的VA 
_ldr_imagebase equ dword ptr $-4 ;請注意參考前面的設定 

mov edx,dword ptr[esi+objpsize] ;節區大小 

_ldr_decrypt: ;異或解密 
xor byte ptr[eax],dl 
inc eax ;下一個位元組 
dec edx 
jne _ldr_decrypt 

_ldr_not_encrypted: 

add esi,objlen ;esi->下一個節區 
loop _ldr_next ;開始下一個節區的解密 

push 987654321 ;程式原來的入口地址入棧,這樣,下面的ret便返回到_ldr_host處執行 
_ldr_host equ dword ptr $-4 
ret 

_loader_end: 
_loader_size equ $-_loader 

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

; mov edx,offset section_header 
; call _is_rsrc 

; sprawdza, czy sekcja zawiera zasoby 

; na wyjsciu: 
; eax - 1 sekcja zasobow 
; 0 brak zasobow 

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

_is_rsrc proc near ;判斷節表名稱是否為rsr或者reso,因為這些節區不可以加密 

cmp dword ptr[edx],'rsr.' ; rsrc 
je _rsrc_section 

cmp dword ptr[edx],'oser' ; resource 
je _rsrc_section 

mov eax,dword ptr[edx+objrva] 
cmp eax,dword ptr[ebx+resource]  
je _rsrc_section  

sub eax,eax 
ret 

_rsrc_section: 
sub eax,eax 
inc eax 
ret 

_is_rsrc endp 



;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

; mov edx,offset section_header 
; call _is_encryptable 

; eax - 0 不可加密 
; 1 可加密 

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

_is_encryptable proc near 
push ebx 
mov ebx,dword ptr[lpPeheader] 

call _is_rsrc  
dec eax 
je _bad_section 


cmp dword ptr[edx],'ler.' ; reloc 
je _bad_section 

cmp dword ptr[edx],'ade.' ; edata 
je _bad_section 

cmp dword ptr[edx],'ete.' ; etext 
je _bad_section 

cmp dword ptr[edx],'adr.' ; rdata 
je _bad_section 

cmp dword ptr[edx],'slt.' ; tls 
je _bad_section 

cmp dword ptr[edx],'adi.' ; idata 
je _bad_section 


sub eax,eax 

cmp dword ptr[edx+objpoff],eax ;判斷節區的屬性是否合法,下面的幾個也是 
je _bad_section  

cmp dword ptr[edx+objpsize],eax  
je _bad_section  


mov eax,dword ptr[edx+objrva] ;儲存rva 

cmp eax,dword ptr[ebx+resource] ;判斷節區的rva是否和資源的rva一樣,如果一樣則不可加密 
je _bad_section  

cmp eax,dword ptr[ebx+edatadir] ;我也不太清楚,你可以跟蹤看一下 
je _bad_section  

cmp eax,dword ptr[ebx+import] 
je _bad_section 

cmp eax,dword ptr[ebx+reloc] ;reloc是說重定位表 
je _bad_section  

cmp eax,dword ptr[ebx+tls] ;我也不知道 
je _bad_section ; 

sub eax,eax 
jmp _check_exit 

_bad_section: 
or eax,-1 

_check_exit: 
inc eax 
pop ebx 

ret 

_is_encryptable endp 


;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 
;下面是檔案的開啟和關閉部分,我就不獻醜寫註釋了。大家要不太清楚,查以下書好了 
; push offset lpFilename 
; call _open_file 

; Otwiera plik do zapisu i odczytu z podanej lokalizacji 

; na wejsciu: 
; lpFilename - nazwa pliku do otworzenia 

; na wyjsciu: 
; eax - uchwyt pliku lub -1 jesli blad 
; ecx - rozmiar pliku 

; modyfikowane rejestry: 
; eax,ecx,edx 

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

_open_file proc near 
pop eax 
pop edx 
push eax 

push edx 

push FILE_ATTRIBUTE_ARCHIVE ; atrybuty 
push edx ; nazwa pliku 
call SetFileAttributesA ; usun atrybuty blokujace dostep do zapisu 

pop edx ; pop nazwa pliku 

sub eax,eax 
push eax 
push FILE_ATTRIBUTE_NORMAL 
push OPEN_EXISTING ; akcja, otworz plik 
push eax 
push eax 
push GENERIC_READ + GENERIC_WRITE ; tryb dostepu 
push edx ; nazwa pliku 
call CreateFileA 

cmp eax,-1 ; sprawdz wartosc zwrocona przez CreateFileA 
je _open_err ; jesli to -1 to znaczy, ze wystapil blad 
; wyjdz z takim wynikiem z funkcji 

push eax ; zapamietaj na stosie uchwyt pliku 

push 0 ; 0 dla plikow mniejszych niz 4gb 
push eax ; uchwyt pliku 
call GetFileSize ; pobierz rozmiar pliku 

pop ecx ; pop, uchwyt pliku do ecx 
xchg eax,ecx ; zamien wartosci w rejestrach, tak, ze 
; w eax znajdzie sie uchyt pliku a w ecx 
; rozmiar pliku 
_open_err: 
ret ; wyjscie z funkcji 

_open_file endp 


;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

; push hFile 
; push cbSize 
; call _map_file 

; Mapuje plik do pamieci, wszystkie operacje dokonywane na pamieci maja fizyczne 
; odzwierciedlenie na dysku 

; na wejsciu: 
; hFile - uchwyt pliku otwartego w trybie do odczytu i zapisu 
; cbSize - rozmiar pliku 

; na wyjsciu: 
; eax - wskaznik do mapowanego pliku lub 0 jesli blad 
; ecx - uchwyt mapowanego pliku 

; modyfikowane rejestry: 
; eax,ecx,edx 

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

_map_file proc near 

pop eax ; adres powrotu 
pop ecx ; rozmiar pliku 
pop edx ; uchwyt pliku 

push eax 

sub eax,eax 
push eax 
push ecx ; rozmiar pliku(+opcjonalnie rozmiar 
; dodtkowego obszaru pamieci) 

push eax ; 
push PAGE_READWRITE ; tryb dostepu do mapy pliku 
push eax 
push edx ; uchwyt pliku 
call CreateFileMappingA 

push eax ; zapamietaj uchwyt mapy pliku 

sub edx,edx ; zeruj edx 

push edx ; ilosc bajtow do mapowania, gdy 0 
; mapowany jest caly plik 
push edx ; 
push edx ; 
push FILE_MAP_WRITE ; flagi dostepu 
push eax ; 
call MapViewOfFile ; w eax wskaznik do mapy pliku 

pop ecx ; uchwyt mapy pliku do ecx 
ret 
_map_file endp 


;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

; push lpMap 
; push hMap 
; call _unmap 

; zamyka mapowany plik + zapisuje zmiany jakie dokonano na mapie pliku 

; na wejsciu: 
; lpMap - wskaznik do mapy pliku 
; hMap - uchwyt mapy pliku 

; na wyjsciu: 
; brak 

; modyfikowane rejestry: 
; eax,ecx,edx 

;哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪 

_unmap proc near 
pop eax 

pop ecx ; hMap 
pop edx ; lpMap 

push eax 

push ecx ; zapamietaj parametr dla CloseHandle 

push edx ; lpMap 
call UnmapViewOfFile ; usuwa obraz mapy pliku z przestrzeni adresowej 
; naszego procesu 

call CloseHandle ; zamknij mape pliku 

ret 
_unmap endp 

end _start

相關文章