// WinMain001.cpp : Defines the entry point for the application.
//
//http://blog.csdn.net/ooyyee/article/details/51842075
#include <windows.h>
#include "stdio.h"
typedef IMAGE_SECTION_HEADER (*PIMAGE_SECTION_HEADERS)[1];
// 计算对齐后的大小
unsigned long GetAlignedSize(unsigned long Origin, unsigned long Alignment)
{
return (Origin + Alignment - 1) / Alignment * Alignment;
}
// 计算加载pe并对齐需要占用多少内存
// 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0
unsigned long CalcTotalImageSize(PIMAGE_DOS_HEADER MzH
, unsigned long FileLen
, PIMAGE_NT_HEADERS peH
, PIMAGE_SECTION_HEADERS peSecH)
{
unsigned long res;
// 计算pe头的大小
res = GetAlignedSize( peH->OptionalHeader.SizeOfHeaders
, peH->OptionalHeader.SectionAlignment
);
// 计算所有节的大小
for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i)
{
// 超出文件范围
if(peSecH[i]->PointerToRawData + peSecH[i]->SizeOfRawData > FileLen)
return 0;
else if(peSecH[i]->VirtualAddress)//计算对齐后某节的大小
{
if(peSecH[i]->Misc.VirtualSize)
{
res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->Misc.VirtualSize
, peH->OptionalHeader.SectionAlignment
);
}
else
{
res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->SizeOfRawData
, peH->OptionalHeader.SectionAlignment
);
}
}
else if( peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData )
{
res += GetAlignedSize( peSecH[i]->SizeOfRawData
, peH->OptionalHeader.SectionAlignment
);
}
else
{
res += GetAlignedSize( peSecH[i]->Misc.VirtualSize
, peH->OptionalHeader.SectionAlignment
);
}// if_else
}// for
return res;
}
// 加载pe到内存并对齐所有节
BOOL AlignPEToMem( void *Buf
, long Len
, PIMAGE_NT_HEADERS &peH
, PIMAGE_SECTION_HEADERS &peSecH
, void *&Mem
, unsigned long &ImageSize)
{
PIMAGE_DOS_HEADER SrcMz;// DOS头
PIMAGE_NT_HEADERS SrcPeH;// PE头
PIMAGE_SECTION_HEADERS SrcPeSecH;// 节表
SrcMz = (PIMAGE_DOS_HEADER)Buf;
if( Len < sizeof(IMAGE_DOS_HEADER) )
return FALSE;
if( SrcMz->e_magic != IMAGE_DOS_SIGNATURE )
return FALSE;
if( Len < SrcMz->e_lfanew + (long)sizeof(IMAGE_NT_HEADERS) )
return FALSE;
SrcPeH = (PIMAGE_NT_HEADERS)((int)SrcMz + SrcMz->e_lfanew);
if( SrcPeH->Signature != IMAGE_NT_SIGNATURE )
return FALSE;
if( (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL) ||
(SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0) ||
(SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) )
{
return FALSE;
}
SrcPeSecH = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS));
ImageSize = CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);
if( ImageSize == 0 )
return FALSE;
Mem = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存
if( Mem != NULL )
{
// 计算需要复制的PE头字节数
unsigned long l = SrcPeH->OptionalHeader.SizeOfHeaders;
for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i)
{
if( (SrcPeSecH[i]->PointerToRawData) &&
(SrcPeSecH[i]->PointerToRawData < l) )
{
l = SrcPeSecH[i]->PointerToRawData;
}
}
memmove( Mem, SrcMz, l);
peH = (PIMAGE_NT_HEADERS)((int)Mem + ((PIMAGE_DOS_HEADER)Mem)->e_lfanew);
peSecH = (PIMAGE_SECTION_HEADERS)((int)peH + sizeof(IMAGE_NT_HEADERS));
void *Pt = (void *)((unsigned long)Mem
+ GetAlignedSize( peH->OptionalHeader.SizeOfHeaders
, peH->OptionalHeader.SectionAlignment)
);
for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i)
{
// 定位该节在内存中的位置
if(peSecH[i]->VirtualAddress)
Pt = (void *)((unsigned long)Mem + peSecH[i]->VirtualAddress);
if(peSecH[i]->SizeOfRawData)
{
// 复制数据到内存
memmove(Pt, (const void *)((unsigned long)(SrcMz) + peSecH[i]->PointerToRawData), peSecH[i]->SizeOfRawData);
if(peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData)
Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->SizeOfRawData, peH->OptionalHeader.SectionAlignment));
else // pt 定位到下一节开始位置
Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));
}
else
{
Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));
}
}
}
return TRUE;
}
typedef void *(__stdcall *pfVirtualAllocEx)(unsigned long, void *, unsigned long, unsigned long, unsigned long);
pfVirtualAllocEx MyVirtualAllocEx = NULL;
BOOL IsNT()
{
HMODULE hModule = GetModuleHandle(TEXT("Kernel32.dll"));
MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(hModule, "VirtualAllocEx");
return MyVirtualAllocEx!=NULL;
}
// 生成外壳程序命令行
char *PrepareShellExe(char *CmdParam, unsigned long BaseAddr, unsigned long ImageSize)
{
if(IsNT())
{
char *Buf = new char[256];
memset(Buf, 0, 256);
GetModuleFileNameA(0, Buf, 256);
strcat(Buf, CmdParam);
//memset(Buf , 0,256);
//strcpy(Buf,"C:\\WINDOWS\\system32\\notepad.exe");
//svchost.exe
return Buf; // 请记得释放内存;-)
}
else
{
// Win98下的处理请参考原文;-)
// http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03
return NULL;
}
}
// 是否包含可重定向列表
BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)
{
return (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
&& (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
}
#pragma pack(push, 1)
typedef struct{
unsigned long VirtualAddress;
unsigned long SizeOfBlock;
} *PImageBaseRelocation;
#pragma pack(pop)
// 重定向PE用到的地址
void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase)
{
unsigned long Delta = (unsigned long)NewBase - peH->OptionalHeader.ImageBase;
PImageBaseRelocation p = (PImageBaseRelocation)((unsigned long)OldBase
+ peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
while(p->VirtualAddress + p->SizeOfBlock)
{
unsigned short *pw = (unsigned short *)((int)p + sizeof(*p));
for(unsigned int i=1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i)
{
if((*pw) & 0xF000 == 0x3000){
unsigned long *t = (unsigned long *)((unsigned long)(OldBase) + p->VirtualAddress + ((*pw) & 0x0FFF));
*t += Delta;
}
++pw;
}
p = (PImageBaseRelocation)pw;
}
}
// 卸载原外壳占用内存
BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)
{
typedef unsigned long (__stdcall *pfZwUnmapViewOfSection)(unsigned long, unsigned long);
pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
BOOL res = FALSE;
HMODULE m = LoadLibrary(L"ntdll.dll");
if(m){
ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");
if(ZwUnmapViewOfSection)
res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);
FreeLibrary(m);
}
return res;
}
// 创建外壳进程并获取其基址、大小和当前运行状态
BOOL CreateChild(char *Cmd, CONTEXT &Ctx, HANDLE &ProcHnd, HANDLE &ThrdHnd,
unsigned long &ProcId, unsigned long &BaseAddr, unsigned long &ImageSize)
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
unsigned long old;
MEMORY_BA
- 1
- 2
- 3
- 4
前往页