加壳:挂起方式创建进程
写入部分
1,壳文件新增一个节
2,源文件与Harmonica异或
3,加密后源文件放入新增节中
4,存盘
VOID Shell(WCHAR* shellName, WCHAR* srcName) {
FILE* fpShell;
FILE* fpSrc;
_wfopen_s(&fpShell, shellName, L"rb");
_wfopen_s(&fpSrc, srcName, L"rb");
if (fpShell == NULL||fpSrc==NULL) {
MessageBox(0, L"can't open file", 0, MB_OK);
return;
}
fseek(fpShell, 0, SEEK_END);
int shellLen = ftell(fpShell);
fseek(fpShell, 0, SEEK_SET);
fseek(fpSrc, 0, SEEK_END);
int srcLen = ftell(fpSrc);
fseek(fpSrc, 0, SEEK_SET);
CHAR* shellBuffer = (CHAR*)malloc(2 * (shellLen + srcLen));
if (shellBuffer != NULL) {
memset(shellBuffer, '\x00', 2 * (shellLen + srcLen));
fread(shellBuffer, shellLen , 1, fpShell);
}
else {
return;
}
fclose(fpShell);
CHAR* srcBuffer = (CHAR*)malloc(srcLen);
if (srcBuffer != NULL) {
memset(srcBuffer, '\x00', srcLen);
fread(srcBuffer, srcLen, 1, fpSrc);
}
else {
free(shellBuffer);
shellBuffer = NULL;
return;
}
fclose(fpSrc);
DWORD e_lfanew = *(DWORD*)(shellBuffer + 0x3c);
CHAR* peHeader = shellBuffer + e_lfanew + 0x4;
CHAR* opHeader = peHeader + 0x14;
DWORD SectionAlignment = *(DWORD*)(opHeader + 0x20);
DWORD SizeOfImage = *(DWORD*)(opHeader + 0x38);
*(DWORD*)(opHeader + 0x38) = SizeOfImage + (srcLen / SectionAlignment + 1) * SectionAlignment;
SizeOfImage = *(DWORD*)(opHeader + 0x38);
DWORD SizeoOfHeaders = *(DWORD*)(opHeader + 0x3c);
WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
*(WORD*)(peHeader + 0x2) = NumberOfSections + 1;
WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
DWORD Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
for (DWORD j = 0; j < NumberOfSections; j++) {
Misc = *(DWORD*)(Sections_addr + 0x8);
VirtualAddress = *(DWORD*)(Sections_addr + 0xc);
SizeOfRawData = *(DWORD*)(Sections_addr + 0x10);
PointerToRawData = *(DWORD*)(Sections_addr + 0x14);
Sections_addr = Sections_addr + 0x28;
}
DWORD check = SizeoOfHeaders - (Sections_addr - shellBuffer);
if (check < 0x50) {//太小了无法新增节
free(shellBuffer);
shellBuffer = NULL;
free(srcBuffer);
srcBuffer = NULL;
return;
}
DWORD newSec_addr = VirtualAddress + SectionAlignment;
DWORD newSec_PointerToRawData = PointerToRawData + SizeOfRawData;
*(DWORD64*)Sections_addr = 0x000000007261482e;
*(DWORD*)(Sections_addr + 0x8) = srcLen;
*(DWORD*)(Sections_addr + 0xc) = newSec_addr;
*(DWORD*)(Sections_addr + 0x10) = (srcLen / SectionAlignment + 1) * SectionAlignment;
*(DWORD*)(Sections_addr + 0x14) = newSec_PointerToRawData;
*(DWORD*)(Sections_addr + 0x24) = 0xC0000040;
UCHAR key[9] = { 0x48,0x61,0x72,0x6d,0x6f,0x6e,0x69,0x63,0x61 };
for (DWORD i = 0; i < srcLen; i++) {
*(UCHAR*)(shellBuffer + newSec_PointerToRawData + i) = *(UCHAR*)(srcBuffer + i) ^ key[i % 9];
}
FILE* fpout;
WCHAR fileName[256] = { 0 };
wcscpy(fileName, srcName);
WCHAR* tmp = wcsstr(fileName, L".exe");
wcscpy(tmp, L"_shell.exe");
_wfopen_s(&fpout, fileName, L"wb");
if (fpout == NULL) {
free(shellBuffer);
shellBuffer = NULL;
free(srcBuffer);
srcBuffer = NULL;
return;
}
fwrite(shellBuffer, (srcLen / SectionAlignment + 1) * SectionAlignment + newSec_PointerToRawData, 1, fpout);
fclose(fpout);
free(shellBuffer);
shellBuffer = NULL;
free(srcBuffer);
srcBuffer = NULL;
MessageBox(0, L"加壳成功", L"", MB_OK);
}
壳部分
1,解密源文件
2,拉伸源文件
3,以挂起方式创建进程,获取进程信息
4,强制卸载进程模块
5,在进程内分配空间
6,修复重定位表
7,源文件写入进程
8,修复Imagebase和oep
9,恢复进程
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
CONTEXT cs;
CHAR* SrcBuffer; //
CHAR* ImageBuffer; //拉伸后的源文件
DWORD SizeOfImage;
DWORD ImageBase;
DWORD OEP;
LPVOID lp; //VirtualAllocEx返回的地址
BOOL HasReloc = FALSE;
BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)
{
typedef unsigned long(__stdcall* pfZwUnmapViewOfSection)(unsigned long, unsigned long);
pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
BOOL res = FALSE;
HMODULE m = LoadLibraryA("ntdll.dll");
if (m) {
ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");
if (ZwUnmapViewOfSection)
res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);
FreeLibrary(m);
}
return res;
}
BOOL DecodeSrc(HANDLE hShellModule) {
//解密源程序
CHAR* lpShellModule = (CHAR*)hShellModule;
DWORD e_lfanew = *(DWORD*)(lpShellModule + 0x3c);
CHAR* peHeader = lpShellModule + e_lfanew + 0x4;
CHAR* opHeader = peHeader + 0x14;
WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
DWORD Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
for (DWORD j = 0; j < NumberOfSections - 1; j++) {
Sections_addr = Sections_addr + 0x28;
}
if (*(DWORD64*)Sections_addr != 0x000000007261482e) {
return FALSE;
}
UCHAR key[9] = { 0x48,0x61,0x72,0x6d,0x6f,0x6e,0x69,0x63,0x61 };
DWORD srcLen = *(DWORD*)(Sections_addr + 0x8);
CHAR* lpSrc = lpShellModule + *(DWORD*)(Sections_addr + 0xc);
SrcBuffer = (CHAR*)malloc(srcLen + 1);
if (SrcBuffer != NULL) {
memset(SrcBuffer, '\x00', srcLen + 1);
for (DWORD i = 0; i < srcLen; i++) {
*(SrcBuffer + i) = *(lpSrc + i) ^ key[i % 9];
}
}
else {
return FALSE;
}
return TRUE;
}
BOOL ExtendSrc() {
WORD peCheck = *(WORD*)(SrcBuffer);
if (peCheck != 0x5A4D) {
return FALSE;
}
DWORD e_lfanew = *(DWORD*)(SrcBuffer + 0x3c);
CHAR* peHeader = SrcBuffer + e_lfanew + 0x4;
CHAR* opHeader = peHeader + 0x14;
DWORD SectionAlignment = *(DWORD*)(opHeader + 0x20);
SizeOfImage = *(DWORD*)(opHeader + 0x38);
ImageBase = *(DWORD*)(opHeader + 0x1c);
OEP = *(DWORD*)(opHeader + 0x10);
if (*(DWORD*)(opHeader + 0x60 + 0x28) != NULL) {
HasReloc = TRUE;
}
DWORD SizeoOfHeaders = *(DWORD*)(opHeader + 0x3c);
WORD NumberOfSections = *(WORD*)(peHeader + 0x2);
WORD SizeOfOptionalHeader = *(WORD*)(peHeader + 0x10);
CHAR* Sections_addr = opHeader + SizeOfOptionalHeader;
ImageBuffer = (CHAR*)malloc(SizeOfImage + 1);
if (ImageBuffer == NULL) {
return FALSE;
}
else {
memset(ImageBuffer, '\x00', SizeOfImage + 1);
}
memcpy(ImageBuffer, SrcBuffer, SizeoOfHeaders);
DWORD Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
for (DWORD j = 0; j < NumberOfSections; j++) {
Misc = *(DWORD*)(Sections_addr + 0x8);
VirtualAddress = *(DWORD*)(Sections_addr + 0xc);
SizeOfRawData = *(DWORD*)(Sections_addr + 0x10);
PointerToRawData = *(DWORD*)(Sections_addr + 0x14);
if (SizeOfRawData == NULL) {
Sections_addr = Sections_addr + 0x28;
continue;
}
if (Misc > SizeOfRawData) {
memcpy(ImageBuffer + VirtualAddress, SrcBuffer + PointerToRawData, Misc);
}
else {
memcpy(ImageBuffer + VirtualAddress, SrcBuffer + PointerToRawData, SizeOfRawData);
}
Sections_addr = Sections_addr + 0x28;
}
free(SrcBuffer);
SrcBuffer = NULL;
return TRUE;
}
VOID repairReloc(DWORD newAddr) {
DWORD e_lfanew = *(DWORD*)(ImageBuffer + 0x3c);
CHAR* peHeader = ImageBuffer + e_lfanew + 0x4;
CHAR* opHeader = peHeader + 0x14;
DWORD relocRVA = *(DWORD*)(opHeader + 0x60 + 0x28);
CHAR* addr = ImageBuffer + relocRVA;
CHAR* size = addr + 4;
CHAR* data = size + 4;
while (*(DWORD*)addr != 0 && *(DWORD*)size != 0) {
DWORD num = (*(DWORD*)size - 8) / 2;
for (DWORD i = 0; i < num; i++) {
WORD Characteristics = (*(WORD*)data & 0xf000) >> 12;
WORD offset = *(WORD*)data & 0x0fff;
if (Characteristics == 0x3) {
DWORD NewData = *(DWORD*)(ImageBuffer + *(DWORD*)addr + offset) - ImageBase + newAddr;
*(DWORD*)(ImageBuffer + *(DWORD*)addr + offset) = NewData;
}
data += 2;
}
addr += *(DWORD*)size;
size = addr + 4;
data = size + 4;
}
}
BOOL MyAlloc(HANDLE p) {
lp = VirtualAllocEx(p, (VOID*)ImageBase, SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lp == NULL) {
if (HasReloc) {
lp = VirtualAllocEx(p, NULL, SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lp == NULL) {
return FALSE;
}
repairReloc((DWORD)lp);
}
else
{
return FALSE;
}
}
return TRUE;
}
int main()
{
LPWSTR fileName;
fileName = GetCommandLineW();
HANDLE hShellProcess = GetCurrentProcess();
HANDLE hShellModule = GetModuleHandleW(NULL);
cs.ContextFlags = CONTEXT_FULL;
//解密源文件
BOOL isDecode = DecodeSrc(hShellModule);
if (isDecode == FALSE) {
return 0;
}
//拉伸源文件
BOOL isExtend = ExtendSrc();
if (isExtend == FALSE) {
free(SrcBuffer);
SrcBuffer = NULL;
// return 0;
}
//以挂起方式创建进程
STARTUPINFO s = { 0 };
s.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION p;
::CreateProcess(
NULL,
fileName,
NULL, NULL,
FALSE,
CREATE_SUSPENDED,
NULL, NULL,
&s, &p);
//获取进程信息
GetThreadContext(p.hThread, &cs);
DWORD shellOEP = cs.Eax;
CHAR* baseAddress = (CHAR*)cs.Ebx + 8;
TCHAR szBuffer[4] = { 0 };
ReadProcessMemory(p.hProcess, baseAddress, szBuffer, 4, NULL);
DWORD shellImageBase = *(DWORD*)szBuffer;
//卸载模块
BOOL UnloadCheck = UnloadShell(p.hProcess, shellImageBase);
if (UnloadCheck == FALSE) {
free(ImageBuffer);
ImageBuffer = NULL;
::TerminateProcess(p.hProcess, 0);
return 0;
}
//分配空间
BOOL allocCheck = MyAlloc(p.hProcess);
if (allocCheck == FALSE) {
free(ImageBuffer);
ImageBuffer = NULL;
::TerminateProcess(p.hProcess, 0);
return 0;
}
BOOL writeCheck = WriteProcessMemory(p.hProcess, lp, ImageBuffer, SizeOfImage, NULL);
if (writeCheck == FALSE) {
free(ImageBuffer);
ImageBuffer = NULL;
::TerminateProcess(p.hProcess, 0);
return 0;
}
//更改Imagebase和oep
WriteProcessMemory(p.hProcess, (LPVOID)(cs.Ebx + 8), &lp, sizeof(DWORD), NULL);
cs.Eax = (DWORD)lp + OEP;
SetThreadContext(p.hThread, &cs);
//::TerminateProcess(p.hProcess, 0);
::ResumeThread(p.hThread);
::CloseHandle(p.hProcess);
return 0;
}
因为我没修复IAT表,使用API会挂