# PeProtect **Repository Path**: xcvk/PeProtect ## Basic Information - **Project Name**: PeProtect - **Description**: 加密壳(Poc) - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2022-05-29 - **Last Updated**: 2025-10-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 加密壳(POC) ## 介绍 实现修复重定位、IAT加密、反调试、代码加密、清除数据目录项。 ## 加载器 ### 加载壳 ``` BOOL CPePack::LoadShell() { m_ShellInfo.BaseOfShell = LoadLibraryEx(PE_SHELL_PATH, nullptr, DONT_RESOLVE_DLL_REFERENCES); if (!m_ShellInfo.BaseOfShell) return FALSE; m_ShellInfo.Start = (LongPtr)GetProcAddress(m_ShellInfo.BaseOfShell, "Start"); m_ShellInfo.Stub = (PSTUB_INFORMATION)GetProcAddress(m_ShellInfo.BaseOfShell, "StubInfo"); return TRUE; } ``` ### 加密代码段 ``` BOOL CPePack::EncryptSection() { PIMAGE_SECTION_HEADER pSection = FindSectionByName(".text"); if (nullptr == pSection) return FALSE; char* pAddressOfSection = (char*)(pSection->PointerToRawData + (LongPtr)m_PeBuf); DWORD dwSize = pSection->Misc.VirtualSize; unsigned char key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; DWORD dwProtect = 0; VirtualProtect(pAddressOfSection, dwSize, PAGE_EXECUTE_READWRITE, &dwProtect); AES aes(key); aes.Cipher(pAddressOfSection, dwSize); VirtualProtect(pAddressOfSection, dwSize, dwProtect, &dwProtect); m_ShellInfo.Stub->RvaOfText = pSection->VirtualAddress; m_ShellInfo.Stub->SizeOfText = dwSize; memcpy(m_ShellInfo.Stub->AesKey, key, sizeof(key)); return TRUE; } ``` ### 清除数据目录项 ``` void CPePack::ClearDataDirectory() { DWORD dwNum = m_pNtHeaders->OptionalHeader.NumberOfRvaAndSizes; m_ShellInfo.Stub->NumberOfDataDirectory = dwNum; for (DWORD i = 0; i < dwNum; i++) { if (IMAGE_DIRECTORY_ENTRY_RESOURCE == i) continue; if (IMAGE_DIRECTORY_ENTRY_BASERELOC == i) { m_ShellInfo.Stub->RvaOfReloc = m_pNtHeaders->OptionalHeader.DataDirectory[i].VirtualAddress; m_ShellInfo.Stub->SizeOfReloc = m_pNtHeaders->OptionalHeader.DataDirectory[i].Size; } m_ShellInfo.Stub->DataDirectory[i][0] = m_pNtHeaders->OptionalHeader.DataDirectory[i].VirtualAddress; m_ShellInfo.Stub->DataDirectory[i][1] = m_pNtHeaders->OptionalHeader.DataDirectory[i].Size; m_pNtHeaders->OptionalHeader.DataDirectory[i].VirtualAddress = 0; m_pNtHeaders->OptionalHeader.DataDirectory[i].Size = 0; } } ``` ### 新增2个区段,用于保存壳代码和壳的重定位数据 ``` BOOL CPePack::AddSection(const char* Name, int Size, PIMAGE_SECTION_HEADER& NewSection) { char strName[IMAGE_SIZEOF_SHORT_NAME] = { 0 }; PIMAGE_SECTION_HEADER pPrevSection = NewSection - 1; char* NewPeBuf; DWORD dwSize; PIMAGE_DOS_HEADER pDosHeader; // // 初始化区段头 // memcpy(strName, Name, IMAGE_SIZEOF_SHORT_NAME); memcpy(NewSection->Name, strName, IMAGE_SIZEOF_SHORT_NAME); NewSection->Misc.VirtualSize = Size; NewSection->VirtualAddress = pPrevSection->VirtualAddress + GetAlignMentSize(pPrevSection->SizeOfRawData, m_pNtHeaders->OptionalHeader.SectionAlignment); NewSection->SizeOfRawData = GetAlignMentSize(Size, m_pNtHeaders->OptionalHeader.FileAlignment); NewSection->PointerToRawData = GetAlignMentSize(m_dwFileSize, m_pNtHeaders->OptionalHeader.FileAlignment); NewSection->Characteristics = 0xE00000E0; dwSize = NewSection->PointerToRawData + NewSection->SizeOfRawData; NewPeBuf = new char[dwSize]; if (!NewPeBuf) return FALSE; // // 修改映像总大小和区段数量 // m_pNtHeaders->OptionalHeader.SizeOfImage += GetAlignMentSize(NewSection->Misc.VirtualSize, m_pNtHeaders->OptionalHeader.SectionAlignment); m_pNtHeaders->FileHeader.NumberOfSections++; // // 替换PE文件缓冲区 // RtlZeroMemory(NewPeBuf, dwSize); memcpy(NewPeBuf, m_PeBuf, m_dwFileSize); delete[] m_PeBuf; m_PeBuf = NewPeBuf; // // 更新部分成员变量 // m_dwFileSize = dwSize; m_nNumberOfSectionByAdded++; pDosHeader = (PIMAGE_DOS_HEADER)m_PeBuf; m_pNtHeaders = (PIMAGE_NT_HEADERS)((LongPtr)m_PeBuf + pDosHeader->e_lfanew); m_pFirstSection = IMAGE_FIRST_SECTION(m_pNtHeaders); m_pShellTextSection = m_pFirstSection + m_pNtHeaders->FileHeader.NumberOfSections - m_nNumberOfSectionByAdded; m_pShellRelocSection = m_pShellTextSection + 1; return TRUE; } ``` ### 修改入口点 ``` m_pNtHeaders->OptionalHeader.AddressOfEntryPoint = (DWORD)(m_ShellInfo.Start - (LongPtr)m_ShellInfo.BaseOfShell - pShellTextSection->VirtualAddress + m_pShellTextSection->VirtualAddress); ``` ### 修复重定位数据 ``` void CPePack::RecoverShellRelocation() { PIMAGE_DOS_HEADER pShellDosHeader = (PIMAGE_DOS_HEADER)m_ShellInfo.BaseOfShell; PIMAGE_NT_HEADERS pShellNtHeaders = (PIMAGE_NT_HEADERS)((LongPtr)pShellDosHeader + pShellDosHeader->e_lfanew); DWORD RvaOfRelocTable = pShellNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; PIMAGE_BASE_RELOCATION pRelocTable = (PIMAGE_BASE_RELOCATION)((LongPtr)pShellDosHeader + RvaOfRelocTable); while (pRelocTable->SizeOfBlock != 0) { if (0xFDFDFDFD == pRelocTable->VirtualAddress) break; DWORD dwSize = pRelocTable->SizeOfBlock; DWORD dwCount = (pRelocTable->SizeOfBlock - 8) / 2; DWORD dwRva = pRelocTable->VirtualAddress; PWORD pwEntry = (PWORD)(pRelocTable + 1); for (DWORD i = 0; i < dwCount; i++) { WORD wVal = *pwEntry; #ifndef _WIN64 if (!(((wVal & 0xF000) >> 12) == 3)) { pwEntry++; continue; } #endif DWORD dwOffset = 0; dwOffset = wVal & 0x0FFF; LongPtr* pRecoverAddress = (LongPtr*)((LongPtr)m_ShellInfo.BaseOfShell + dwRva + dwOffset); DWORD dwOldAttribute = 0; VirtualProtect(pRecoverAddress, sizeof(LongPtr), PAGE_READWRITE, &dwOldAttribute); *pRecoverAddress = *pRecoverAddress - pShellNtHeaders->OptionalHeader.ImageBase - pShellNtHeaders->OptionalHeader.BaseOfCode + m_pNtHeaders->OptionalHeader.ImageBase + m_pShellTextSection->VirtualAddress; VirtualProtect(pRecoverAddress, sizeof(LongPtr), dwOldAttribute, &dwOldAttribute); pwEntry++; } pRelocTable = (PIMAGE_BASE_RELOCATION)((LongPtr)pRelocTable + dwSize); } } ``` ## 壳代码 ### 解密区段 ``` void DecryptSection() { LongPtr BaseOfImage = (LongPtr)_GetModuleHandleA(nullptr); char* pText = (char*)(StubInfo.RvaOfText + BaseOfImage); DWORD dwOldAttribute = 0; _VirtualProtect(pText, StubInfo.SizeOfText, PAGE_READWRITE, &dwOldAttribute); AES aes(StubInfo.AesKey); aes.InvCipher(pText, (int)StubInfo.SizeOfText); _VirtualProtect(pText, StubInfo.SizeOfText, dwOldAttribute, &dwOldAttribute); } ``` ### 恢复数据目录项 ``` void RecoverDataDirectory() { LongPtr BaseOfImage = (LongPtr)_GetModuleHandleA(nullptr); PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)BaseOfImage; PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((LongPtr)pDos + pDos->e_lfanew); PIMAGE_DATA_DIRECTORY pDataDirectory = pNtHeaders->OptionalHeader.DataDirectory; LongPtr nCnt = StubInfo.NumberOfDataDirectory; DWORD dwOldAttribute = 0; for (UINT i = 0; i < nCnt; i++) { if (IMAGE_DIRECTORY_ENTRY_RESOURCE == i) { pDataDirectory++; continue; } _VirtualProtect(pDataDirectory, 8, PAGE_READWRITE, &dwOldAttribute); pDataDirectory->VirtualAddress = StubInfo.DataDirectory[i][0]; pDataDirectory->Size = StubInfo.DataDirectory[i][1]; _VirtualProtect(pDataDirectory, 8, dwOldAttribute, &dwOldAttribute); pDataDirectory++; } } ``` ### 修复IAT并加密 ``` void RecoverAndEncryptIAT() { LongPtr BaseOfImage = (LongPtr)_GetModuleHandleA(nullptr); PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)BaseOfImage; PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((LongPtr)pDos + pDos->e_lfanew); PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR) (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + BaseOfImage); while (pImportDirectory->Name) { PIMAGE_THUNK_DATA pIat = (PIMAGE_THUNK_DATA)(pImportDirectory->FirstThunk + BaseOfImage); PIMAGE_THUNK_DATA pInt = nullptr; if (0 != pImportDirectory->OriginalFirstThunk) { pInt = (PIMAGE_THUNK_DATA)(pImportDirectory->OriginalFirstThunk + BaseOfImage); } else { pInt = pIat; } HMODULE hModule = _LoadLibraryA((LPCSTR)(pImportDirectory->Name + BaseOfImage)); PIMAGE_IMPORT_BY_NAME pName = nullptr; LPVOID pAddress = nullptr; while (pInt->u1.Function) { if (IMAGE_SNAP_BY_ORDINAL(pInt->u1.Ordinal)) // serial number { pAddress = _GetProcAddress(hModule, (LPCSTR)(IMAGE_ORDINAL(pInt->u1.Ordinal))); } else // name string { pName = (PIMAGE_IMPORT_BY_NAME)(pInt->u1.AddressOfData + BaseOfImage); pAddress = _GetProcAddress(hModule, pName->Name); } DWORD dwOldAttribute = 0; _VirtualProtect(&pIat->u1.Function, sizeof(pIat->u1.Function), PAGE_READWRITE, &dwOldAttribute); #ifndef _WIN64 pIat->u1.Function = EncryptIatAddress(pAddress); #else pIat->u1.Function = (LongPtr)pAddress; #endif _VirtualProtect(&pIat->u1.Function, sizeof(pIat->u1.Function), dwOldAttribute, &dwOldAttribute); pIat++; pInt++; } pImportDirectory++; } } ```