直接运行内存中的程序
Windows的PE加载器在启动程序的时候,会将磁盘上的文件加载到内存,然后做很多操作,如函数导入表重定位,变量预处理之类的。这位仁兄等于是自己写了一个PE加载器。直接将内存中的程序启动。记得以前的“红色代码”病毒也有相同的特性。
直接启动内存中的程序相当于加了一个壳,可以把程序加密保存,运行时解密到内存,然后启动,不过对于增加破解难度还要稍微复杂点。否则人家把内存中的进程DUMP出来然后修复导入表就被拖出来了。
#include \
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( 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() {
return MyVirtualAllocEx!=NULL;
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库直接运行内存中的程序在线全文阅读。
相关推荐: