找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 4687|回复: 0

[分享] 为PE增加一个Section段,让其开始运行先执行这个段

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2010-1-27 20:57:53 | 显示全部楼层 |阅读模式
新增一个Section来加入代码。 如果要加入的代码很多,那么就需要新增一个Section来存放自己的代码。
l 首先,我们需要在PE头内找到NumberOfSections,使之加1
l 然后,在文件末尾增加一个新的空间,假设为200h,记住起始行到PE文件首部的偏移。假如这个值是00034500h。同时将PE头内的SizeOfImage的值加200h
l 然后,找到PE头内的Section头部。通常在Section头部结束到Section数据部分开始间会有一些空间,找到Section头部的最后然后加入一个新的头部。假设最后一个Section头部的数据是:
1. Virtual offset : 34000h
2. Virtual size : 8E00h
3. Raw offset: 2F400h
4. Raw size : 8E00h
而文件对齐和Section对齐的数据分别是:
5. Section Alignment : 1000h
6. File Alignment : 200h
l 那么新增加的Section必须与最后一个Section的边界对齐。它的数据分别:
1. Virtual offset : 3D000h (因为最后一个Section的最后边界是34000h + 8E00h = 3CE00h,加上Section对齐,则Virtual offset的值为3D000h)。
2. Virtual size : 200h。
3. Raw offset: 00034500h。
4. Raw size: 200h.
5. Characteristics : E0000060 (可读、可写、可执行)。这地方最好用windows提供的宏定义来设定IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE
l 最后,只需要修改一下PE头内的SizeOfCode和SizeOfInitialishedData两个字段,分别加上200h
需要注意的问题是 修改过后的PE的入口地址是我们新添加上的Section段的Virtual offset + ImageBase

下面代码:
//Get the alignment Address
DWORD Alignment(DWORD dwValue, DWORD dwDuiQ)
{
while(dwValue % dwDuiQ != 0)
{
dwValue++;
}
return dwValue;
}

//Modify the PE file, include Add new Section and sth else
DWORD SetPeInfo(void *ImageOfPe, DWORD dwFileSize, DWORD dwOffset)
{
WORD NumOfSection=0;
DWORD RawOfEntryPoint=0;
DWORD AddressOfEntryPoint=0;

PIMAGE_DOS_HEADER   pDosHead=NULL;
PIMAGE_NT_HEADERS   pNtHead=NULL;
PIMAGE_SECTION_HEADER pSectionHead=NULL;
pDosHead=(PIMAGE_DOS_HEADER)ImageOfPe;
pNtHead=(PIMAGE_NT_HEADERS)((unsigned char *)pDosHead+pDosHead->e_lfanew);

//Record the old PE EnterPoint, we will modify it later.
AddressOfEntryPoint=pNtHead->OptionalHeader.AddressOfEntryPoint;
//Record the number of the section segment, we will modify it later.
NumOfSection=pNtHead->FileHeader.NumberOfSections;
//the first section's address
pSectionHead=(PIMAGE_SECTION_HEADER)((unsigned char *)pNtHead+
sizeof(pNtHead->Signature)+sizeof(IMAGE_FILE_HEADER)+
pNtHead->FileHeader.SizeOfOptionalHeader);

//Get The Last Section Pointer
PIMAGE_SECTION_HEADER pLastSection = (IMAGE_SECTION_HEADER *)((DWORD)pSectionHead + sizeof(IMAGE_SECTION_HEADER)*(NumOfSection-1));
IMAGE_SECTION_HEADER imageSectionInsert;
memset(&imageSectionInsert, 0, sizeof(IMAGE_SECTION_HEADER));
//Write sth to the new Section
//set a name for the new section
memcpy(imageSectionInsert.Name, ".blue", sizeof(".blue"));
imageSectionInsert.Misc.VirtualSize = 0x200;
imageSectionInsert.VirtualAddress = Alignment(pLastSection->VirtualAddress + pLastSection->Misc.VirtualSize, 0x1000);
imageSectionInsert.SizeOfRawData = 0x200;
imageSectionInsert.PointerToRawData = dwFileSize + dwOffset;

//Set Characteristics to read write and execute.
imageSectionInsert.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE ;
//the add 1, in fact add a sizeof IMAGE_SECTION_HEADER
memcpy(pLastSection + 1, &imageSectionInsert, sizeof(IMAGE_SECTION_HEADER));

//1.Modify the PE Entrypoint
pNtHead->OptionalHeader.AddressOfEntryPoint = imageSectionInsert.VirtualAddress;
//2.Add the number of section segment
pNtHead->FileHeader.NumberOfSections++;
//3.Add 0x200 to SizeofImage
pNtHead->OptionalHeader.SizeOfImage += 0x200;
//4.Add 0x200 to SizeOfCode
pNtHead->OptionalHeader.SizeOfCode += 0x200;
//5.Add 0x200 to SizeOfInitialishedData
pNtHead->OptionalHeader.SizeOfInitializedData += 0x200;

//return the new EntryPoint and the ImageBase.
return AddressOfEntryPoint + pNtHead->OptionalHeader.ImageBase;
}


void CMy2q345wrDlg::OnOK()
{
DWORD dwFileSize = 0;
HANDLE hFile = ::CreateFile("a.exe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return ;
}
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == 0)
{
return;
}
char *szpPE = new char [dwFileSize];
memset (szpPE, 0, dwFileSize);
DWORD dwRead = 0;
ReadFile(hFile, szpPE, dwFileSize, &dwRead, NULL);
if (dwRead != dwFileSize)
{
return ;
}
CloseHandle(hFile);

//Set PE Info
DWORD dwOffset = Alignment(dwFileSize, 0x200) - dwFileSize;
DWORD dwEnterLastPoint = SetPeInfo(szpPE, dwFileSize, dwOffset);

//Add 200 Bytes and create a new file
hFile = ::CreateFile("b.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return ;
}
BYTE *sz200Size = new BYTE[0x200 + dwOffset];
memset(sz200Size, 0, 0x200+dwOffset);
//    Write binary codes here, but do not forget jmp to the old EntryPoint.
//     sz200Size[dwOffset] = 0xe9;
//     sz200Size[dwOffset+1] = 0xbb;
//     sz200Size[dwOffset+2] = 0x7b;
//     sz200Size[dwOffset+3] = 0xFF;
//     sz200Size[dwOffset+4] = 0xFF;

//set the file size
SetFilePointer(hFile, dwFileSize + dwOffset + 0x200, NULL, FILE_BEGIN);
//set file to the start position
SetFilePointer(hFile, NULL, NULL, FILE_BEGIN);
DWORD dwFeiWu = 0;
//write modified szpPE info to new file.
WriteFile(hFile, szpPE, dwFileSize, &dwFeiWu, NULL);
//write the 0x200 section code to new file, do not forget the offset file size.
WriteFile(hFile, sz200Size, dwOffset + 0x200, &dwFeiWu, NULL);
CloseHandle(hFile);

//release the memory we used.
delete [] sz200Size;
delete [] szpPE;
}
这样执行会崩溃的,需要用的下一篇讲到的  破译Jmp指令机器码的内容。
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表