本篇內(nèi)容介紹了“如何從零開始寫一個(gè)加殼器”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、網(wǎng)頁空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、永定網(wǎng)站維護(hù)、網(wǎng)站推廣。
即我們向PE文件添加一個(gè)區(qū)段并將其設(shè)置為入口點(diǎn),這樣PE文件最開始執(zhí)行的命令就是我們添加的區(qū)段也就是殼的指令,殼對(duì)加密區(qū)進(jìn)行解密,對(duì)壓縮區(qū)進(jìn)行解壓,將原本的EXE文件還原出來,然后跳轉(zhuǎn)至原程序入口,程序照常運(yùn)行。
首先生成一個(gè)打印hello的exe文件。
#include <stdio.h>
int main() {
printf("hello");
}我們目前要干的事情是:以手動(dòng)的形式向PE文件添加一個(gè)殼部分并設(shè)為程序入口,并使其能跳轉(zhuǎn)回原入口。 那就來吧
用010editor打開我們的exe文件,啟用exe模板分析。 我們首先修改其文件頭numverofsection屬性,這個(gè)屬性用來定義當(dāng)前PE文件存在多少個(gè)區(qū)段,因?yàn)槲覀円砑右粋€(gè)殼區(qū)段,所以我們將其加1變成6

在我們重載模板后我們就會(huì)在區(qū)段表發(fā)現(xiàn)多出來一個(gè)空的區(qū)段表

從上到下各個(gè)比較重要字段的意思是 \1. Name 表示該區(qū)段的名字 2.VirtualSize 表示在內(nèi)存中的大小(一般內(nèi)存對(duì)齊為0x1000) 3.virtualaddress 虛擬地址 即上一個(gè)區(qū)段的VirtualAddress + 上一個(gè)區(qū)段經(jīng)內(nèi)存對(duì)齊粒度對(duì)齊后的大小 4.sizeofdata 表示在文件中的大小(一般文件對(duì)齊為0x200) 5.pointertorawdata 文件的偏移 即 上一個(gè)區(qū)段的PointerToRawData + 上一個(gè)區(qū)段的SizeOfRawData
然后我們通過修改以上各值來定義一個(gè)新區(qū)段(殼區(qū)段)的屬性

這里的virtualsize看著填一個(gè)就行了。 此時(shí)我們只是定義了區(qū)段表,但文件中并沒有該區(qū)段存在,所以我們得創(chuàng)建該區(qū)段。 然后還要讓區(qū)段可編輯,把下列值改為1即可


ctrl+shift+i 向目標(biāo)文件偏移處插入0x200大小的空間。 這樣一來,殼區(qū)段就創(chuàng)建好了。 然后我們還要修改 擴(kuò)展頭的SizeofImage 。將他改為最后一個(gè)區(qū)段的內(nèi)存地址+內(nèi)存大小

然后去掉隨機(jī)基址選項(xiàng)。
找到擴(kuò)展頭的DLL屬性字段,去掉隨機(jī)基址,把40 81改為 00 81

接下來我們把程序入口點(diǎn)設(shè)置給殼區(qū)段。 使用LORDPE把入口點(diǎn)設(shè)為殼區(qū)塊的虛擬地址
然后我們用OD打開這個(gè)文件


剛剛提到的手工加殼,不過是最最基礎(chǔ)的加殼原型而已,真正的加殼還涉及了代碼加解密等操作.
真正寫殼時(shí)一般寫兩個(gè)東西,加殼器和stub 所謂加殼器,就是給被加殼文件創(chuàng)造出一個(gè)新的區(qū)段, 在此同時(shí)將程序以某種方式加密,然后把stub放入新區(qū)段,并將程序入口點(diǎn)設(shè)為新區(qū)段的地址,然后在新區(qū)段結(jié)束后跳轉(zhuǎn)回原程序入口。這個(gè)新區(qū)段我們叫做殼區(qū)段. 那么這個(gè)stub就是加殼后程序最先執(zhí)行的命令了,它執(zhí)行解密算法,將原程序釋放出來。
https://github.com/ConsT27/PackingEXE/tree/master項(xiàng)目地址
stub是被植入到PE文件中的代碼,它一般會(huì)干下面這些事情。
流程如下
0.合并data,rdata到text 1.PEB動(dòng)態(tài)尋址,遍歷導(dǎo)出表找到GetProcAddress函數(shù) 2.解密 3.修改入口點(diǎn)到原入口點(diǎn)
同時(shí)stub一般以dll的形式存在。原因是DLL通常自帶重定位表,這在我們的移植過程中的重定位操作中提供了巨大的便利。
我們要移植stub過去,肯定需要移植代碼段,也需要移植數(shù)據(jù)段。不如我們干脆把數(shù)據(jù)段合并到代碼段,一塊移植過去。
為什么會(huì)用到這個(gè)技術(shù)編寫stub? 因?yàn)槲覀兊膕tub.dll植入到宿主程序時(shí),只有.text植入過去,沒有對(duì)應(yīng)的導(dǎo)入表,所以我們的stub無法直接調(diào)用一些API。所以我們需要?jiǎng)討B(tài)獲取各種API。 其中我采用的是PEB動(dòng)態(tài)查詢得到GetProcAddress函數(shù),然后用GetProcAddress函數(shù)去獲取各個(gè)API。
那么,什么是PEB? PEB是一個(gè)微軟還未完全公開作用的一個(gè)結(jié)構(gòu),它叫做 進(jìn)程環(huán)境信息塊 ,包含了進(jìn)程的信息。其結(jié)構(gòu)如下
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged; //被調(diào)試狀態(tài)
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
復(fù)制代碼我們關(guān)心的是PEB偏移0c得到的 PPEB_LDR_DATA Ldr; 它是一個(gè)指針,指向一個(gè) PPEB_LDR_DATA 結(jié)構(gòu), 存放著已經(jīng)被進(jìn)程裝在的動(dòng)態(tài)鏈接庫(kù)的信息
typedef struct _PEB_LDR_DATA
{
ULONG Length; // +0x00
BOOLEAN Initialized; // +0x04
PVOID SsHandle; // +0x08
LIST_ENTRY InLoadOrderModuleList; // +0x0c
LIST_ENTRY InMemoryOrderModuleList; // +0x14
LIST_ENTRY InInitializationOrderModuleList;// +0x1c
} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24PPEB_LDR_DATA 偏移1c是一個(gè)指向LIST_ENTRY InInitializationOrderModuleList結(jié)構(gòu)的指針,這個(gè)結(jié)構(gòu) 存放著指向模塊初始化鏈表的頭 , 按順序存放著PE裝入運(yùn)行時(shí)初始化模塊信息,一般來說第一個(gè)鏈表結(jié)點(diǎn)是ntdll.dll,第二個(gè)鏈表結(jié)點(diǎn)就是kernel32.dll 。我們就在其中找到kernel32.dll的信息,獲取其PE信息,得到導(dǎo)出表,循環(huán)遍歷得到GetProcAddress函數(shù)。 另外,PEB地址再TEB偏移0x30處。用匯編語言表示就是 fs:[0x30]。
以上是PEB尋址的大致流程,另外還有一個(gè)比較關(guān)鍵的點(diǎn)是遍歷kernel32.dll導(dǎo)出表獲得GetProcAddress函數(shù)信息。 關(guān)于導(dǎo)出表可以看看這個(gè)文章https://blog.csdn.net/evileagle/article/details/12176797
首先一個(gè)導(dǎo)出表結(jié)構(gòu)體如下
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics; //一般為0,沒啥用
DWORD TimeDateStamp; //導(dǎo)出表生成的時(shí)間
WORD MajorVersion; //版本,也是0沒啥用
WORD MinorVersion; //也是沒啥用的版本信息一般為0
DWORD Name; //當(dāng)前導(dǎo)出表的模塊名字
DWORD Base; //序號(hào)表中序號(hào)的基數(shù)
DWORD NumberOfFunctions; //導(dǎo)出函數(shù)數(shù)量
DWORD NumberOfNames; //按名字導(dǎo)出函數(shù)的數(shù)量
DWORD AddressOfFunctions; // 序號(hào)表
DWORD AddressOfNames; // 名稱表
DWORD AddressOfNameOrdinals; // 地址表
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;其中序號(hào)表的起始序號(hào)是Base屬性定義的值。以下是導(dǎo)出表的序號(hào)名稱地址表的關(guān)系

我們的遍歷流程是,先遍歷名稱表找到GetProcAddress在名稱數(shù)組中的下標(biāo),然后根據(jù)這個(gè)下標(biāo)去序號(hào)數(shù)組中找相同下標(biāo)的序號(hào)值,然后以這個(gè)序號(hào)值為下標(biāo)去找地址數(shù)組中的對(duì)應(yīng)值。我們找到的地址表中的值就是函數(shù)入口
下面我把這段程序的匯編代碼放出來。我是用內(nèi)聯(lián)匯編把這段代碼塞進(jìn)C++的
void GetApis()
{
HMODULE hKernel32;
_asm
{
pushad;
; //獲取kernel32.dll的加載基址;
mov eax, fs: [0x30] ; //得到PEB地址
mov eax, [eax + 0ch]; //獲得LDR_PEB_DATA地址
mov eax, [eax + 0ch]; //獲得LIST_ENTRY InLoadOrderModuleList;地址
mov eax, [eax]; //獲得LIST_ENTRY InLoadOrderModuleList下一項(xiàng)的地址
mov eax, [eax]; /獲得LIST_ENTRY InLoadOrderModuleList下下項(xiàng)即我們需要的LIST_ENTRY InInitializationOrderModuleList的地址
mov eax, [eax + 018h]; //獲得kernel32.dll地址
mov hKernel32, eax;
mov ebx, [eax + 03ch];//獲得kernel32.dll NT頭RVA
add ebx, eax; //NT頭的VA
add ebx, 078h; //獲得區(qū)段表
mov ebx, [ebx]; //獲得導(dǎo)出表RVA
add ebx, eax; //導(dǎo)出表VA
lea ecx, [ebx + 020h];
mov ecx, [ecx]; // ecx => 名稱表的首地址(rva);
add ecx, eax; // ecx => 名稱表的首地址(va);
xor edx, edx; // 作為索引(index)來使用.
_WHILE:;
mov esi, [ecx + edx * 4];//名稱數(shù)組入口點(diǎn)rva,名稱數(shù)組單位大小4字節(jié)
lea esi, [esi + eax]; //入口點(diǎn)VA
cmp dword ptr[esi], 050746547h; //進(jìn)行名稱匹配,050746547h即小端存儲(chǔ)的GetP
jne _LOOP;//不相等就跳入_LOOP段
cmp dword ptr[esi + 4], 041636f72h; //名陳匹配,rocA,以下依次為ddre,ss
jne _LOOP;
cmp dword ptr[esi + 8], 065726464h;
jne _LOOP;
cmp word ptr[esi + 0ch], 07373h;
jne _LOOP;
mov edi, [ebx + 024h];
add edi, eax; //獲得序號(hào)表VA
mov di, [edi + edx * 2]; //獲得序號(hào)數(shù)組中對(duì)應(yīng)下標(biāo)的地址,序號(hào)數(shù)組單位大小2字節(jié)
and edi, 0FFFFh; //給di提位到32位,即給予edi 序號(hào)表中對(duì)應(yīng)下標(biāo)的地址
mov edx, [ebx + 01ch];
add edx, eax; //獲得地址表
mov edi, [edx + edi * 4]; //獲得地址數(shù)組中,序號(hào)對(duì)應(yīng)的值,地址數(shù)組單位大小4字節(jié)
add edi, eax; //獲得GetProcAddress的入口地址
mov MyGetProcAddress, edi; //賦值
jmp _ENDWHILE; //END
_LOOP:;
inc edx; // ++index;
jmp _WHILE;
_ENDWHILE:;
popad;
}解密代碼段。這段好寫。
void Decrypt()
{
unsigned char* pText = (unsigned char*)g_conf.textScnRVA + 0x400000;//鎖定到PE文件的text段(因?yàn)榧託r(shí)去掉了基址隨機(jī)化,所以自信的把基址填成0x400000
DWORD old = 0;
MyVirtualProtect(pText, g_conf.textScnSize, PAGE_READWRITE, &old);//修改代碼段的屬性,注意我們這里使用了動(dòng)態(tài)獲得的
//解密代碼段
for (DWORD i = 0; i < g_conf.textScnSize; i++)
{
pText[i] ^= g_conf.key;
}
//把屬性修改回去
MyVirtualProtect(pText, g_conf.textScnSize, old, &old);
}_asm
{
mov eax, g_conf.srcOep; //入口點(diǎn)是g_conf.srcOep
add eax, 0x400000
jmp eax
}加殼器流程如下
1.打開需要被加殼的PE文件 2.加載stub 3.加密代碼段 4.添加新區(qū)段 5.stub重定位修復(fù) 6.stub移植 7.PE文件入口點(diǎn)修改 8.去隨機(jī)基址 9.保存文件
以下的各個(gè)流程描述中會(huì)用到諸多自定義函數(shù),我先貼上來吧。
//****************
//對(duì)齊處理
//time:2020/11/5
//****************
int AlignMent(_In_ int size, _In_ int alignment) {
return (size) % (alignment)==0 ? (size) : ((size) / alignment+1) * (alignment);
}
//***********************
//PE信息獲取函數(shù)簇
//time:2020/11/2
//***********************
PIMAGE_DOS_HEADER GetDosHeader(_In_ char* pBase) {
return PIMAGE_DOS_HEADER(pBase);
}
PIMAGE_NT_HEADERS GetNtHeader(_In_ char* pBase) {
return PIMAGE_NT_HEADERS(GetDosHeader(pBase)->e_lfanew+(SIZE_T)pBase);
}
PIMAGE_FILE_HEADER GetFileHeader(_In_ char* pBase) {
return &(GetNtHeader(pBase)->FileHeader);
}
PIMAGE_OPTIONAL_HEADER32 GetOptHeader(_In_ char* pBase) {
return &(GetNtHeader(pBase)->OptionalHeader);
}
PIMAGE_SECTION_HEADER GetLastSec(_In_ char* pBase) {
DWORD SecNum = GetFileHeader(pBase)->NumberOfSections;
PIMAGE_SECTION_HEADER FirstSec = IMAGE_FIRST_SECTION(GetNtHeader(pBase));
PIMAGE_SECTION_HEADER LastSec = FirstSec + SecNum - 1;
return LastSec;
}
PIMAGE_SECTION_HEADER GetSecByName(_In_ char* pBase,_In_ const char* name) {
DWORD Secnum = GetFileHeader(pBase)->NumberOfSections;
PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(GetNtHeader(pBase));
char buf[10] = { 0 };
for (DWORD i = 0; i < Secnum; i++) {
memcpy_s(buf, 8, (char*)Section[i].Name, 8);
if (!strcmp(buf, name)) {
return Section + i;
}
}
return nullptr;
}
typedef struct _StubConf
{
DWORD srcOep; //入口點(diǎn)
DWORD textScnRVA; //代碼段RVA
DWORD textScnSize; //代碼段的大小
DWORD key; //解密密鑰
}StubConf;
struct StubInfo
{
char* dllbase; //stub.dll的加載基址
DWORD pfnStart; //stub.dll(start)導(dǎo)出函數(shù)的地址
StubConf* pStubConf; //stub.dll(g_conf)導(dǎo)出全局變量的地址
};打開PE文件
這里采用的方法是利用CreateFileA函數(shù)。同時(shí)這個(gè)函數(shù)還拋出了一個(gè)指向PE文件大小的指針
char* GetFileHmoudle(_In_ const char* path,_Out_opt_ DWORD* nFileSize) {
//打開一個(gè)文件并獲得文件句柄
HANDLE hFile = CreateFileA(path,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
//獲得文件大小
DWORD FileSize = GetFileSize(hFile, NULL);
//返回文件大小到變量nFileSize
if(nFileSize)
*nFileSize = FileSize;
//申請(qǐng)一片大小為FileSize的內(nèi)存并將指針置于首位
char* pFileBuf = new CHAR[FileSize]{ 0 };
//給剛剛申請(qǐng)的內(nèi)存讀入數(shù)據(jù)
DWORD dwRead;
ReadFile(hFile, pFileBuf, FileSize, &dwRead, NULL);
CloseHandle(hFile);
return pFileBuf;
}加載STUB
void LoadStub(_In_ StubInfo* pstub) {
pstub->dllbase = (char*)LoadLibraryEx(L"F:\\stubdll.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);
pstub->pfnStart = (DWORD)GetProcAddress((HMODULE)pstub->dllbase, "Start"); //獲得stub的入口函數(shù)Start(自己定義在stub中的一個(gè)函數(shù)
pstub->pStubConf = (StubConf*)GetProcAddress((HMODULE)pstub->dllbase, "g_conf");
}
//不僅加載了stub,還獲得了stub拋出的用于收集信息的全局結(jié)構(gòu)體(g_conf,是一個(gè)stub拋出的結(jié)構(gòu)體,用于獲取信息,結(jié)構(gòu)如下)
typedef struct _StubConf
{
DWORD srcOep; //入口點(diǎn)
DWORD textScnRVA; //代碼段RVA
DWORD textScnSize; //代碼段的大小
DWORD key; //解密密鑰
}StubConf;加密代碼段
DWORD textRVA = GetSecByName(PeHmoudle, ".text")->VirtualAddress;
DWORD textSize = GetSecByName(PeHmoudle, ".text")->Misc.VirtualSize;
Encry(PeHmoudle,pstub);
void Encry(_In_ char* hpe,_In_ StubInfo pstub) {
//獲取代碼段首地址
BYTE* TargetText = GetSecByName(hpe, ".text")->PointerToRawData + (BYTE*)hpe;
//獲取代碼段大小
DWORD TargetTextSize = GetSecByName(hpe, ".text")->Misc.VirtualSize;
//加密代碼段
for (int i = 0; i < TargetTextSize; i++) {
TargetText[i] ^= 0x15;
}
pstub.pStubConf->textScnRVA = GetSecByName(hpe, ".text")->VirtualAddress;
pstub.pStubConf->textScnSize = TargetTextSize;
pstub.pStubConf->key = 0x15;
}
//加密代碼段,并給予了stub一些信息char* AddSec(_In_ char*& hpe, _In_ DWORD& filesize, _In_ const char* secname, _In_ const int secsize) {
GetFileHeader(hpe)->NumberOfSections++;
PIMAGE_SECTION_HEADER pesec = GetLastSec(hpe);
//設(shè)置區(qū)段表屬性
memcpy(pesec->Name, secname, 8);
pesec->Misc.VirtualSize = secsize;
pesec->VirtualAddress = (pesec - 1)->VirtualAddress + AlignMent((pesec - 1)->SizeOfRawData,GetOptHeader(hpe)->SectionAlignment);
pesec->SizeOfRawData = AlignMent(secsize, GetOptHeader(hpe)->FileAlignment);
pesec->PointerToRawData = AlignMent(filesize,GetOptHeader(hpe)->FileAlignment);
pesec->Characteristics = 0xE00000E0;
//設(shè)置OPT頭映像大小
GetOptHeader(hpe)->SizeOfImage = pesec->VirtualAddress + pesec->SizeOfRawData;
//擴(kuò)充文件數(shù)據(jù)
int newSize = pesec->PointerToRawData + pesec->SizeOfRawData;
char* nhpe = new char [newSize] {0};
//向新緩沖區(qū)錄入數(shù)據(jù)
memcpy(nhpe, hpe, filesize);
//緩存區(qū)更替
delete hpe;
filesize = newSize;
return nhpe;
}stub重定位
好家伙,這個(gè)東西稍有不慎就會(huì)讓整個(gè)程序拉跨掉(過來人的忠告 為什么需要stub重定位呢?因?yàn)槲覀兊膕tub最開始是加載在內(nèi)存中的,它的許多指令如跳轉(zhuǎn)到的地址是按內(nèi)存為基準(zhǔn)確定的,但是我們需要把他移植進(jìn)文件,所以它的代碼里許多地址就是錯(cuò)誤的,我們需要對(duì)這些地址進(jìn)行處理,即重定位,使其以宿主程序?yàn)闃?biāo)準(zhǔn)進(jìn)行地址修復(fù)。 可能我表述的不是很清楚
舉個(gè)例子吧,比如stub在加載進(jìn)內(nèi)存時(shí),有一條跳轉(zhuǎn)指令時(shí)jmp 12345678, 如果我們不處理就把這條指令移植進(jìn)PE文件,那么PE文件執(zhí)行到此處時(shí)就會(huì)跳轉(zhuǎn)到12345678,此時(shí)的12345678地址可能就已經(jīng)不是PE文件加載的內(nèi)存區(qū)間了,從而程序會(huì)崩潰。所以要修復(fù)。根據(jù)stub的重定位表進(jìn)行修復(fù)。 重定位表就是記錄哪些地址的數(shù)據(jù)需要被修復(fù)的,我們遍歷這些地址進(jìn)行修復(fù)即可。 如果以下代碼看起來吃力,可以先去了解一下重定位表
void FixStub(DWORD targetDllbase, DWORD stubDllbase,DWORD targetNewScnRva,DWORD stubTextRva )
{
//找到stub.dll的重定位表
DWORD dwRelRva = GetOptHeader((char*)stubDllbase)->DataDirectory[5].VirtualAddress;
IMAGE_BASE_RELOCATION* pRel = (IMAGE_BASE_RELOCATION*)(dwRelRva + stubDllbase);
//遍歷重定位表
while (pRel->SizeOfBlock)
{
struct TypeOffset
{
WORD offset : 12;
WORD type : 4;
};
TypeOffset* pTypeOffset = (TypeOffset*)(pRel + 1);
DWORD dwCount = (pRel->SizeOfBlock - 8) / 2; //需要重定位的數(shù)量
for (int i = 0; i < dwCount; i++)
{
if (pTypeOffset[i].type != 3)
{
continue;
}
//需要重定位的地址
DWORD* pFixAddr = (DWORD*)(pRel->VirtualAddress + pTypeOffset[i].offset + stubDllbase);
DWORD dwOld;
//修改屬性為可寫
VirtualProtect(pFixAddr, 4, PAGE_READWRITE, &dwOld);
//去掉dll當(dāng)前加載基址
*pFixAddr -= stubDllbase;
//去掉默認(rèn)的段首R(shí)VA
*pFixAddr -= stubTextRva;
//換上目標(biāo)文件的加載基址
*pFixAddr += targetDllbase;
//加上新區(qū)段的段首R(shí)VA
*pFixAddr += targetNewScnRva;
//把屬性修改回去
VirtualProtect(pFixAddr, 4, dwOld, &dwOld);
}
//切換到下一個(gè)重定位塊
pRel = (IMAGE_BASE_RELOCATION*)((DWORD)pRel + pRel->SizeOfBlock);
}stub移植
這個(gè)簡(jiǎn)單,沒啥說的
memcpy(GetLastSec(PeNewHmoudle)->PointerToRawData+ PeNewHmoudle, GetSecByName(pstub.dllbase, ".text")->VirtualAddress+pstub.dllbase, GetSecByName(pstub.dllbase,".text")->Misc.VirtualSize);
GetOptHeader(PeNewHmoudle)->AddressOfEntryPoint = pstub.pfnStart-(DWORD)pstub.dllbase-GetSecByName(pstub.dllbase,".text")->VirtualAddress+GetLastSec(PeNewHmoudle)->VirtualAddress;
去隨機(jī)基址
不去掉隨機(jī)基址,加載基址就是不固定的,不方便操作
GetOptHeader(PeNewHmoudle)->DllCharacteristics &= (~0x40);
void SaveFile(_In_ const char* path, _In_ const char* data, _In_ int FileSize) {
HANDLE hFile = CreateFileA(
path,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
DWORD Buf = 0;
WriteFile(hFile, data, FileSize, &Buf,NULL);
CloseHandle(hFile);
}“如何從零開始寫一個(gè)加殼器”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
新聞標(biāo)題:如何從零開始寫一個(gè)加殼器
當(dāng)前地址:http://chinadenli.net/article0/jgpsoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、微信公眾號(hào)、網(wǎng)站維護(hù)、網(wǎng)站策劃、自適應(yīng)網(wǎng)站、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)