观看滴水逆向视频总结(部分截图来自于滴水课件)
编译器:vc++6.0
编写语言:c
欢迎大家留言交流^ __ ^
可以加我qq一起学习:1245885144
模拟系统加载一个exe的过程,
通过pe重载的方法,可以将原有exe分割、加密、任意操作后,再通过pe重载的方法去启动对应exe的代码。实现对其核心代码的保护什么的0.0 ……
PE的拉伸
PE模拟重定位表运作
读取exe的导入表
通过LoadLibrary函数加载dll(多个dll要循环加载)
LoadLibrary( 参数:dll的地址字符串 )
:将dll加载至内存,同时按需要修正dll的重定位表和IAT表,返回dll在文件中的句柄(首地址),失败返回NULL。
Ps:LoadLibrary不能用于加载exe,否则不会修正重定位表和IAT表
题外话:如果一个exe通过LoadLibrary加载dll,那他的导入表中不会出现该dll。
推荐资料:LoadLibrary函数详细说明
通过GetProcAddress获取对应函数地址
GetProcAddress(参数1:dll句柄or首地址, 参数2:函数名字符串)
:通过dll的句柄获取dll导出表信息,匹配参数2对应的函数名,返回该函数的地址,失败返回NULL。
Ps:GetProcAddress返回地址的默认类型是int (__stdcall *)(),即参数为空返回int型数据的函数。如果我们要返回的函数地址实际上是有参数的,那我们就得强转类型,不然会报错。
//返回的函数地址,"Plus"这个函数实际上是有两个参数返回值为int的函数。 int (*myPlus)(int , int) = ( int (*)(int , int))GetProcAddress( hModule , "Plus")
导出表工作方式
导入表与IAT表运作原理
构造函数指针 void (*pFunc)( void ) 指向PE入口AddressOfEntryPoint
void (*pFunc)( void ) = (void (*)() )( (DWORD)pDosHeader + pOptionHeader->AddressOfEntryPoint );
然后pFunc( ); 即可跳转,执行对应PE的代码。
printf("\n**************** PE Load *************************\n");
pFunc();
效果展示:
发现一个问题:这个重载PE程序并没有为我们弹出新的控制台黑框,而是在原有的控制台黑框里运行。
说明,一个控制台exe程序在运行的时候,系统会在运行代码段之前还有一个调用系统中“控制台黑框”的过程,但是似乎我以前一直都忽视了,不明白其中的底层原理。
编译语言:c
编译环境:vc++6.0
Ps:因为这个代码写了很久,缝缝补补、修修改改,所以多少有点糙,见谅!
#include
#include
#include
#include
/*
#define Situation1 "C:/Windows/System32/"
#define Situation2 "C:/Windows/SysWOW64/"
#define Situation3 "./"
*/
//char DllSituation[300];
char FileName[500]={0};//读取的文件名(地址)
DWORD FileSize = 0;//文件状态下的大小
//功能:将文件PE读入内存1
//参数:文件地址
//返回值:指向内存1的指针
LPVOID ReadPeFile( char FileName[] );
//功能:将内存1的文件copy到内存2,构造成PE内存状态
//参数:指向内存1的指针
//返回值:指向内存2的指针
LPVOID CreateImageBuffer( LPVOID pFileBuffer);
//功能:修正重定位表
void AmendRelocation( LPVOID pImageBuffer );
//第六步函数指针启动exe
//参数:完成所有操作后的exe首地址
void ReloadPE( LPVOID pImageBuffer );
//第一步映射exe,修正重定位表表
//参数:exe地址名字
void ReadEXE( char FileName[] );
//第二步读取exe导入表
//参数:exe的首地址
//返回值:若成功返回pImageBuffer,失败返回NULL
LPVOID Read_EXE_Import( LPVOID pImageBuffer);
int main()
{
printf("for example: D:/user/Desktop/学习笔记/2020.8.8_PE重载/exe重载/实验.exe\n");
printf("Please input: ");
gets(FileName);
//第一步读取exe
ReadEXE( FileName );
}
//第一步映射exe,修正重定位表表
//参数:exe地址名字
void ReadEXE( char FileName[] )
{
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
pFileBuffer = ReadPeFile( FileName );
if( pFileBuffer )
{
//映射exe
pImageBuffer = CreateImageBuffer( pFileBuffer );
if( pImageBuffer )
{
system("pause");
//修正 重定位表
AmendRelocation( pImageBuffer );
//读取dll函数
pImageBuffer = Read_EXE_Import( pImageBuffer );
//第六步:函数指针启动exe
if( pImageBuffer )
{
system("pause");
ReloadPE( pImageBuffer );
}
}
}
}
//第二步读取exe导入表
//参数:exe的首地址
//返回值:若成功返回pImageBuffer,失败返回NULL
LPVOID Read_EXE_Import( LPVOID pImageBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNtHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader =NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL;
PBYTE pDllName = NULL;
PDWORD pIAT = NULL;
PIMAGE_IMPORT_BY_NAME pImportByName = NULL;
int i;
//dll句柄
HINSTANCE hModule = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
pNtHeader = (PIMAGE_NT_HEADERS32)( (DWORD)pDosHeader + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)( (DWORD)pNtHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)( (DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER );
pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory ;
if(pDataDirectory[1].VirtualAddress )
{
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)( (DWORD)pDosHeader + pDataDirectory[1].VirtualAddress );
//遍历exe的导入表
while( pImportDescriptor->OriginalFirstThunk && pImportDescriptor->FirstThunk )
{
//初始化参数
pDllName = (PBYTE)( (DWORD)pDosHeader + pImportDescriptor->Name );
pIAT = (PDWORD)( (DWORD)pDosHeader + pImportDescriptor->FirstThunk );
hModule = LoadLibrary( pDllName );
if(!hModule)
{
printf("Sorry,not found Dll:%s\n",pDllName);
return NULL;
}
for(i=0 ; *(pIAT+i) ; i++)
{
if(*(pIAT+i) & 0x80000000)
*(pIAT+i) = GetProcAddress( hModule , (char*)(*pIAT&0x7fffffff) );
else
{
pImportByName = (PIMAGE_IMPORT_BY_NAME)( (DWORD)pDosHeader + *(pIAT+i) );
*(pIAT+i) = GetProcAddress( hModule , (char*)pImportByName->Name );
}
}
pImportDescriptor++;
}
//遍历
}
return pImageBuffer ;
}
//功能:将文件PE读入内存1
//参数:文件地址
//返回值:指向内存1的指针
LPVOID ReadPeFile( char FileName[] )
{
LPVOID pFileBuffer = NULL;
FILE* pFile = NULL;
DWORD FileSize = 0;
size_t flag = 0;
//打开文件
pFile = fopen(FileName , "rb");
if(!pFile)
{
printf("open file failure!\n");
return NULL;
}
//读取文件大小
fseek(pFile , 0 , SEEK_END);
FileSize = ftell( pFile );
fseek(pFile , 0 , SEEK_SET);
//分配内存1 空间 并初始化为0
pFileBuffer = calloc( FileSize , 1 );
if(!pFileBuffer)
{
printf("Failed to allocate memory space_1!\n");
fclose(pFile);
return NULL;
}
//读取文件数据 至 内存1
flag = fread(pFileBuffer , FileSize , 1 , pFile );
if(!flag)
{
printf("read data failure!\n");
fclose(pFile);
free(pFileBuffer);
return NULL;
}
//关闭文件
fclose(pFile);
//
// printf("%x\n" , *(PWORD)(pFileBuffer));
return pFileBuffer;
}
//功能:将内存1的文件copy到内存2,构造成PE内存状态(拉伸)
//参数:指向内存1的指针
//返回值:指向内存2的指针
LPVOID CreateImageBuffer( LPVOID pFileBuffer)
{
LPVOID pImageBuffer = NULL;//指向内存2
PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头 指针
PIMAGE_NT_HEADERS32 pNtHeader = NULL ;//NT头 指针
PIMAGE_FILE_HEADER pFileHeader = NULL;//文件头 指针
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;//可选头 指针
PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节区头 指针
size_t i;//记录节区
// printf("%x\n" , *(PWORD)(pFileBuffer));
//检测是否是'MZ'标志
if( *(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE )
{
printf("sorry , not a void 'MZ' signature!\n");
free(pFileBuffer);
return NULL;
}
pDosHeader = ( PIMAGE_DOS_HEADER )pFileBuffer;
//检测是否是'PE'标志
pNtHeader = ( PIMAGE_NT_HEADERS32 )( (DWORD)pFileBuffer + pDosHeader->e_lfanew );
if(pNtHeader->Signature != IMAGE_NT_SIGNATURE )
{
printf("sorry , not a void 'PE' signature\n");
free(pFileBuffer);
return NULL;
}
pFileHeader = ( PIMAGE_FILE_HEADER )( (DWORD)pNtHeader + 4 );
pOptionHeader = ( PIMAGE_OPTIONAL_HEADER)( (DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER );
//分配内存2 空间 并初始化为0
pImageBuffer = calloc( pOptionHeader->SizeOfImage , 1 );//
if(!pImageBuffer)
{
printf("failed to allocate memory space_2!\n");
free( pFileBuffer );
return NULL;
}
// printf("size = %x\n",pOptionHeader->SizeOfImage );
//将header复制到ImageBuffer
memcpy( pImageBuffer , pFileBuffer , pOptionHeader->SizeOfHeaders );
// printf("SizeOfHeaders = %x\n",pOptionHeader->SizeOfHeaders );
//printf("1\n");
//将 多个 节区复制到ImageBuffer
pSectionHeader = (PIMAGE_SECTION_HEADER)( (DWORD)pOptionHeader + pFileHeader->SizeOfOptionalHeader );
for(i=pFileHeader->NumberOfSections ; i>0 ; i--)
{
memcpy( (LPVOID)( (DWORD)pImageBuffer + pSectionHeader->VirtualAddress) , (LPVOID)( (DWORD)pDosHeader + pSectionHeader->PointerToRawData ) , pSectionHeader->SizeOfRawData );
//循环遍历 再 copy
pSectionHeader = (PIMAGE_SECTION_HEADER)( (DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER );
}
//释放 内存1 的空间
free(pFileBuffer);
// printf("%x\n" , *(PWORD)(pImageBuffer));
return pImageBuffer;
}
//功能:修正重定位表
void AmendRelocation( LPVOID pImageBuffer )
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNtHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_BASE_RELOCATION pBaseRelocation = NULL;
// int j=0;
DWORD i =0;
DWORD ImageBaseOffset = 0;//ImageBase的偏移
PWORD pRelocation = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer ;
pNtHeader = (PIMAGE_NT_HEADERS32)( (DWORD)pDosHeader + pDosHeader->e_lfanew );
pFileHeader = (PIMAGE_FILE_HEADER)( (DWORD)pNtHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)( (DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory ;
if(pDataDirectory[5].VirtualAddress == 0)
{
printf("exe have not Base Relocation Table!\n");
return ;
}
pBaseRelocation = (PIMAGE_BASE_RELOCATION)( (DWORD)pDosHeader + pDataDirectory[5].VirtualAddress );
ImageBaseOffset = (DWORD)pDosHeader - pOptionHeader->ImageBase ;
printf("ImageBase :%X\n",pOptionHeader->ImageBase );
pOptionHeader->ImageBase = (DWORD)pDosHeader;
printf("Amended,ImageBase :%X\n",pOptionHeader->ImageBase );
while(pBaseRelocation->SizeOfBlock && pBaseRelocation->VirtualAddress )
{
pRelocation = (PWORD)( (DWORD)pBaseRelocation + 8);
for(i=(pBaseRelocation->SizeOfBlock - 8)/2 ; i>0 ;i--,pRelocation++)
if( (*pRelocation) >> 12 )
{
*(PDWORD)( (DWORD)pDosHeader + (pBaseRelocation->VirtualAddress| ((*pRelocation)&0xfff) ) ) += ImageBaseOffset;
// j++;
}
pBaseRelocation = (PIMAGE_BASE_RELOCATION)( (DWORD)pBaseRelocation + pBaseRelocation->SizeOfBlock );
}
// printf("j=%d\n",j);
}
//第六步函数指针启动exe
//参数:完成所有操作后的exe首地址
void ReloadPE( LPVOID pImageBuffer )
{
void (*pFunc)() = NULL;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS32 pNtHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer ;
pNtHeader = (PIMAGE_NT_HEADERS32)( (DWORD)pDosHeader + pDosHeader->e_lfanew );
pFileHeader = (PIMAGE_FILE_HEADER)( (DWORD)pNtHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)( (DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
*pFunc = (void (*)() )( (DWORD)pDosHeader + pOptionHeader->AddressOfEntryPoint );
printf("\n**************** PE Load *************************\n");
pFunc();
printf("666\n");
getchar();\
}
—————————————————————————————————————
欢迎大家留言交流!