www.pudn.com > PEInject.rar > ChildView.cpp


// ChildView.cpp : CChildView 类的实现 
// 
 
#include "stdafx.h" 
#include "PEInject.h" 
#include "ChildView.h" 
#include ".\childview.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 
 
 
// CChildView 
 
CChildView::CChildView() 
{ 
} 
 
CChildView::~CChildView() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CChildView, CWnd) 
	ON_WM_PAINT() 
	ON_COMMAND(ID_FILEOPEN, OnFileopen) 
	ON_COMMAND(ID_MYPLAYER, OnMyplayer) 
	ON_COMMAND(ID_SWFPLAYER, OnSwfplayer) 
END_MESSAGE_MAP() 
 
 
 
// CChildView 消息处理程序 
 
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)  
{ 
	if (!CWnd::PreCreateWindow(cs)) 
		return FALSE; 
 
	cs.dwExStyle |= WS_EX_CLIENTEDGE; 
	cs.style &= ~WS_BORDER; 
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,  
		::LoadCursor(NULL, IDC_ARROW), reinterpret_cast(COLOR_WINDOW+1), NULL); 
 
	return TRUE; 
} 
 
void CChildView::OnPaint()  
{ 
	CPaintDC dc(this); // 用于绘制的设备上下文 
	 
	// TODO: 在此处添加消息处理程序代码 
	 
	// 不要为绘制消息而调用 CWnd::OnPaint() 
} 
 
 
void CChildView::OnFileopen() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CString str,str1; 
	CFileDialog fdlg(TRUE, 0, 0, OFN_NOCHANGEDIR, "*.exe|*.EXE||"); 
	fdlg.DoModal(); 
 
	str.Empty(); 
	str = fdlg.GetFileExt(); 
	str.MakeUpper(); 
	 
	str1.Empty(); 
	str1 = fdlg.GetPathName(); 
	 
	if (!str1.IsEmpty() && strcmp(str.GetBuffer(), "EXE") ==0) 
	{ 
			CInputPassWord  dlg(this); 
			dlg.DoModal(); 
			memset(m_PassWord, 0, 12); 
			memcpy(m_PassWord, dlg.m_PassWord.GetBuffer(), 10); 
			ListPEFile(str1);	 
	} 
} 
 
 
void CChildView::ListPEFile(CString FileName) 
{	 
	IMAGE_DOS_HEADER dosHeader; 
	IMAGE_NT_HEADERS NtHeader; 
	IMAGE_SECTION_HEADER  MySHeader; 
	DWORD  MySHeadOffset = 0; 
	IMAGE_SECTION_HEADER  LastSHeader; 
	DWORD  LastHeadOffset = 0; 
	unsigned char *buff = NULL; 
	DWORD RunModeSZ = 0; 
 
	CFile fExe(FileName, CFile::modeReadWrite |CFile::typeBinary); 
	 
	CFile fR("data.bin", CFile::modeReadWrite |CFile::modeReadWrite|CFile::typeBinary); 
	RunModeSZ = fR.Seek(0, CFile::end); 
 
	fExe.Read(&dosHeader, sizeof(IMAGE_DOS_HEADER)); 
	 
	fExe.Seek(dosHeader.e_lfanew, CFile::begin ); 
	fExe.Read(&NtHeader, sizeof(IMAGE_NT_HEADERS)); 
	 
 
	DWORD  nSections = NtHeader.FileHeader.NumberOfSections; 
	 
	MySHeadOffset += 4; 
	MySHeadOffset += sizeof(IMAGE_FILE_HEADER); 
	MySHeadOffset += sizeof(IMAGE_OPTIONAL_HEADER); 
	MySHeadOffset += nSections * sizeof(IMAGE_SECTION_HEADER); 
 
	if (MySHeadOffset > NtHeader.OptionalHeader.SizeOfHeaders) 
	{ 
		::AfxMessageBox("文件空间不够!存储不下新节头!", 0, 0);		 
	} 
	 
	//新节表在文件中的偏移地址 
	MySHeadOffset += dosHeader.e_lfanew; 
	 
	//新节表的上一节表在文件中的偏移地址 
	LastHeadOffset = MySHeadOffset - sizeof(IMAGE_SECTION_HEADER); 
	 
	//读取新节表的上一节表的数据 
	fExe.Seek(LastHeadOffset, CFile::begin); 
	fExe.Read(&LastSHeader, sizeof(IMAGE_SECTION_HEADER)); 
 
	memset(&MySHeader, 0, sizeof(IMAGE_SECTION_HEADER)); 
	//新节名称 
	strcpy((char*)MySHeader.Name, ".GZL"); 
	 
	//新节的实际大小(末对齐)Virtual理解为:事实上的,Actual 
	MySHeader.Misc.VirtualSize =  RunModeSZ; 
	 
	/******************************************************** 
	*  MySHeader.VirtualAddress是 
	*  新节被装载到内存中后的偏移地址, 
	*  这是一个RVA地址。这个地址是按照内存页对齐的, 
	*  它的数值总是SectionAlignment的值的整数倍。 
	*  MySHeader.VirtualAddress = NtHeader.OptionalHeader.SizeOfImage; 
	**********************************************************/ 
	//上一节装载到内存中按照内存页对齐的大小 
	DWORD LastSectionVirtualSZ = ((LastSHeader.Misc.VirtualSize  
		/ NtHeader.OptionalHeader.SectionAlignment) + 1) 
		*  NtHeader.OptionalHeader.SectionAlignment; 
	//新节装载到内存中的偏移地址:上一节装载到内存中的偏移地址 + 上一节装载到内存中按照内存页对齐的大小 
	MySHeader.VirtualAddress = LastSHeader.VirtualAddress + LastSectionVirtualSZ; 
	 
	//计算新节在文件中对齐后大小 
	DWORD sz = MySHeader.Misc.VirtualSize /  NtHeader.OptionalHeader.FileAlignment; 
	sz += 1; 
	sz *= NtHeader.OptionalHeader.FileAlignment; 
	MySHeader.SizeOfRawData = sz; 
	 
 
	//每个节表的 PointerToRawData 等于它的上一节的 SizeOfRawData + PointerToRawData 
	//MySHeader.PointerToRawData即新节在文件中的偏移地址 
	//等于上一节在文件中的偏移地址(PointerToRawData) + 上一节在文件中的大小(SizeOfRawData) 
	MySHeader.PointerToRawData =  LastSHeader.PointerToRawData 
								+  LastSHeader.SizeOfRawData; 
 
	MySHeader.PointerToRelocations = 0; 
	MySHeader.PointerToLinenumbers = 0; 
	MySHeader.NumberOfRelocations = 0; 
	MySHeader.NumberOfLinenumbers = 0; 
	MySHeader.Characteristics = 0x0E0000020;    //可读可写可执行 
 
	//写入新“节表” 
	fExe.Seek(MySHeadOffset, CFile::begin); 
	fExe.Write(&MySHeader, sizeof(IMAGE_SECTION_HEADER)); 
 
	//读取新节的数据 
	buff = new unsigned char[MySHeader.SizeOfRawData]; 
	memset(buff, 0, MySHeader.SizeOfRawData); 
	fR.Seek(0, CFile::begin); 
	fR.Read(buff,  RunModeSZ); 
	fR.Close(); 
 
	//记录下原来ImageBase,AddressOfEntryPoint 
	//按执行模块中存储原来ImageBase,AddressOfEntryPoint的地址 
	//要求按顺序在最后两个DWORD 
	DWORD* p = (DWORD*)(buff +  RunModeSZ - 8); 
	*p = NtHeader.OptionalHeader.ImageBase; 
	p++; 
	*p = NtHeader.OptionalHeader.AddressOfEntryPoint; 
 
	p = (DWORD*)(buff +  RunModeSZ - 20); 
	strcpy((char *)p, m_PassWord); 
	//在文件中写入新节的数据 
	fExe.Seek(MySHeader.PointerToRawData, CFile::begin); 
	fExe.Write(buff, MySHeader.SizeOfRawData); 
 
	delete []buff; 
 
    /************************************************************ 
    *  改写IMAGE_NT_HEADERS,使新节可以首先执行: 
    * (需要改写 SizeOfImage , AddressOfEntryPoint 
	* ,NumberOfSections) 
	*  SizeOfImage :内存中整个PE映像大小,对齐到SectionAlignment 
    *************************************************************/ 
	NtHeader.FileHeader.NumberOfSections += 1; 
	sz = MySHeader.Misc.VirtualSize / NtHeader.OptionalHeader.SectionAlignment; 
	sz += 1; 
	sz *= NtHeader.OptionalHeader.SectionAlignment; 
	NtHeader.OptionalHeader.SizeOfImage += sz; 
	NtHeader.OptionalHeader.AddressOfEntryPoint = MySHeader.VirtualAddress; 
	 
	fExe.Seek(dosHeader.e_lfanew, CFile::begin); 
	fExe.Write(&NtHeader, sizeof (IMAGE_NT_HEADERS)); 
 
	fExe.Close(); 
 
	::AfxMessageBox("成功写入新节!", 0, 0); 
} 
void CChildView::OnMyplayer() 
{ 
	// TODO: 在此添加命令处理程序代码 
	int Len = 0; 
	char buff[1024] = ""; 
	DWORD SWFFlg = 0; 
	DWORD SWFlen = 0; 
 
	CFile fR("tt.exe", CFile::modeRead |CFile::typeBinary); 
	CFile fW("MyPlayer.exe", CFile::modeCreate|CFile::modeReadWrite |CFile::typeBinary); 
 
	Len = fR.GetLength(); 
	fR.Seek(Len - 8, CFile::begin); 
 
	//读取SWF文件标识 
	fR.Read(&SWFFlg, sizeof(DWORD)); 
	 
	//读取SWF文件大小减去8的值  
	fR.Read(&SWFlen, sizeof(DWORD)); 
	 
	//文件总长度减去SWF文件长度,即为播器长度。 
	Len = Len - (SWFlen + 8); 
 
	fR.Seek(0, CFile::begin); 
	 
	int n = Len / 1024; 
	for (int i = 0; i