marxixing兄是我灵感的源泉,他写过这种loader,看的小弟一时兴起,也想做一个。顺便再回顾一下PE文件格式,以前看过好多遍只不过从没实践过,都忘的差不多了。
,在不在?
不要怪我盗窃你的思路哦
改天小弟给你倒茶赔罪行不?
好了,进入正题
marxixing兄做的loader是通过文件映射再创建挂起进程的方式实现的。
我的这个纯粹是从PE文件中修改,通过一个个指针,我指指指。。。。
有几个问题需要提一下:
1)。在使用fread( )后指针会后移。
2)。程序对那些经过人工修改过的程序会失败,比如把区块名去掉(OH,NO。。)
3)。由于本人菜,还没开发什么大的项目,所以对平台差异没考虑。。。
所以如果有这方面问题都反馈给marxixing兄吧,
程序很简单,我也加了一些注释,大家浏览一下就可以了。
#include "stdafx.h"
#include <iostream.h>
#include <fstream.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if ( argc <= 1)
exit(0) ;
FILE *file ;
if ( ( file = fopen( argv[1], "r+" ) ) == NULL )
{
cout << "ErrorCode:" << GetLastError() << endl ;
exit (0) ;
}
//检测“MZ”标志
char pDosHeadSign[2] ;
fread ( &pDosHeadSign, 1, 2, file ) ;
if ( !(pDosHeadSign[0] == 'M' && pDosHeadSign[1] == 'Z' ) )
{
cout << "Invaliable PE file!" << endl ;
fclose ( file ) ;
exit(0) ;
}
//定位到偏移文件头0X3C
int result = fseek ( file, 0X3C, SEEK_SET ) ;
if( result )
{
cout << "Seek file Error!" << endl ;
fclose ( file ) ;
exit (0) ;
}
//取得PEHead的偏移值
DWORD pPEHeadOffset ;
fread ( &pPEHeadOffset, sizeof(DWORD), 1, file ) ;
//定位到PEHead,同时检测“PE”标志
char pPEHeadSign[2] ;
fseek ( file, pPEHeadOffset, SEEK_SET ) ;
fread ( &pPEHeadSign, 2, 1, file ) ;
if ( !( pPEHeadSign[0] == 'P' && pPEHeadSign[1] == 'E' ) )
{
cout << "Invaliable PE file!" << endl ;
fclose ( file ) ;
exit(0) ;
}
//取得区块数目, 由于前面取PE标志时已经后移两个字节 ==> pPEHeadOffset + 0X6 - 0X2 )
WORD NumberOfSection ;
fseek ( file, 0x4, SEEK_CUR ) ;
fread ( &NumberOfSection, sizeof(WORD), 1, file ) ;
cout << "NumberOfSection: " << NumberOfSection << endl ;
//取得IMAGE_OPENTION_HEADER32结构的大小(pPEHeadOffset + 0X14 ) - 0X6 -0X2 == 0XC
fseek ( file, 0XC, SEEK_CUR ) ;
WORD SizeOfOptionalHeader ;
fread ( &SizeOfOptionalHeader, sizeof(WORD), 1, file ) ;
cout << "SizeOfOptionalHeader: 0X" << hex << SizeOfOptionalHeader << endl ;
//取得程序执行的入口地址(RVA)(后移4个字节)
//定位到 ( pPEHeadOffset + 0X28 ) -0X14 - sizeof(WORD) ==> 0X12
fseek ( file, 0X12, SEEK_CUR ) ;
DWORD AddressOfEntryPoint ;
fread ( &AddressOfEntryPoint, sizeof(DWORD), 1, file ) ;
cout << "AddressOfEntryPoint(RVA):0X" << hex << AddressOfEntryPoint << endl ;
//定位到块表 ( pPEHeadOffset + SizeOfFileHead(0X18) + SizeOfOptionalHeader )
DWORD SectionTableOffset = pPEHeadOffset + 0X18 + SizeOfOptionalHeader ;
cout << "SectionTableOffset:0X" << hex << SectionTableOffset << endl ;
fseek ( file, SectionTableOffset, SEEK_SET ) ;
char SectionName[8] = {0} ;
for ( int i = 0; i < NumberOfSection; i++ )
{
fread ( &SectionName, 8, 1, file ) ;
if ( !strcmp( SectionName, ".text" ) )
{
DWORD MemoryOffset, FileOffset, EntryPointFileOffset ;
fseek ( file, 4, SEEK_CUR ) ;
fread ( &MemoryOffset, sizeof(DWORD), 1, file ) ;
fseek ( file, 4, SEEK_CUR ) ;
fread ( &FileOffset, sizeof(DWORD), 1, file ) ;
EntryPointFileOffset = AddressOfEntryPoint - ( MemoryOffset - FileOffset ) ;
cout << "EntryPointFileOffset: 0X" << EntryPointFileOffset << endl ;
char EntryPointFirstByte ;
fseek ( file, EntryPointFileOffset, SEEK_SET ) ;
fread ( &EntryPointFirstByte, sizeof(char), 1, file ) ;
cout << "EntryPointFirstByte:0X" << hex << (int)EntryPointFirstByte ;
cout << "----" << "You shoud keep this value in mind!" << endl ;
byte Int3 = 0xCC ;
fseek ( file, EntryPointFileOffset, SEEK_SET ) ;
fwrite ( &Int3, sizeof(byte), 1, file ) ;
cout << "\"Int3\" insert success" << endl ;
break ;
}
else
{
fseek ( file, 0X20, SEEK_CUR ) ;
}
}
fclose ( file ) ;
cout << "Press \"ENTER\" key to leave...." << endl ;
getchar();
return 0 ;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!