一个压缩壳源码

《加密与解密》书中的壳,不过为了加深印象还是手写一下

抄代码的时候突然想起了以前见过的一个VS插件,代码高亮,自动完成等功能都相当完美,写起代码来也爽很多。。

壳的流程(写到再更新):

1 把文件各区块按照内存对齐的方式加载到内存

3 转储输入表


源码:

void LoadFile(char *szFileName)
{
	HANDLE hFile;
	IMAGE_DOS_HEADER dosHeader;
	IMAGE_NT_HEADERS ntHeader;
	PIMAGE_SECTION_HEADER psecHeader;
	long nFileSize;
	long nFileAlign;
	long nSectionAlign;
	long nNTHeaderSize;
	int nHeaderSize;
	int nSectionNum;
	int nIndex;
	long nRawDataSize;
	long nRawDataOffset;
	long nVirtualAddress;
	long nVirtualSize;
	unsigned long NumberOfBytesRead;
	
	//读取文件信息
	hFile=CreateFile(szFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if(hFile==INVALID_HANDLE_VALUE)
	{
		//printf("打开文件失败\n");
	}
	
	ReadFile(hFile,&dosHeader,sizeof(dosHeader),&NumberOfBytesRead,NULL);
	//判断MZ标志
	if (dosHeader.e_magic!=0x5A4D)
	{
		//Not Standard PE File
	}

	SetFilePointer(hFile,dosHeader.e_lfanew,NULL,FILE_BEGIN);
	ReadFile(hFile,&ntHeader,sizeof(ntHeader),&NumberOfBytesRead,NULL);
	//判断PE标志
	if (ntHeader.Signature!=0x4550)
	{
		//Not Standard PE File
	}

    nFileSize=GetFileSize(hFile,NULL);
	nSectionNum=ntHeader.FileHeader.NumberOfSections;
	m_nImageSize=ntHeader.OptionalHeader.SizeOfImage;
	nFileAlign=ntHeader.OptionalHeader.FileAlignment;
	nSectionAlign=ntHeader.OptionalHeader.SectionAlignment;
	nHeaderSize=ntHeader.OptionalHeader.SizeOfHeaders;		//这是从开头一直包括到区块表的大小
	
	m_nImageSize=Align_Size(m_nImageSize,nSectionAlign);
	m_pImageBase=(char*)malloc(m_nImageSize);
	memset(m_pImageBase,0,m_nImageSize);
	
	SetFilePointer(hFile,0,NULL,FILE_BEGIN);
	ReadFile(hFile,m_pImageBase,nHeaderSize,&NumberOfBytesRead,NULL);
	m_pntHeaders=(PIMAGE_NT_HEADERS)((DWORD)m_pImageBase+dosHeader.e_lfanew);
	nNTHeaderSize=sizeof(ntHeader.Signature)+sizeof(ntHeader.FileHeader)+ntHeader.FileHeader.SizeOfOptionalHeader;		//由于数据目录个数不一定所以需要自己计算
	m_psecHeaders=(PIMAGE_SECTION_HEADER)((DWORD)m_pntHeaders+nNTHeaderSize);
	
	//把各个节的数据复制到对应位置
	for(nIndex=0,psecHeader=m_psecHeaders;nIndexSizeOfRawData;
		nRawDataOffset=psecHeader->PointerToRawData;
		nVirtualAddress=psecHeader->VirtualAddress;
		nVirtualSize=psecHeader->Misc.VirtualSize;
		SetFilePointer(hFile,nRawDataOffset,NULL,FILE_BEGIN);
		ReadFile(hFile,&m_pImageBase[nVirtualAddress],nRawDataSize,&NumberOfBytesRead,NULL);
	}
	//此时指向最后一个节,顺便保存下附加数据
	SaveExtraData(hFile,psecHeader,nFileSize);

}
long Align_Size(long nImageSize,long nSectionAlign)
{
	return (nImageSize+nSectionAlign-1) / nSectionAlign * nSectionAlign;
}

void SaveExtraData(HANDLE hFile,PIMAGE_SECTION_HEADER pLastSectionHead,long nFileSize)
{
	long nExtraDataSize=nFileSize-(pLastSectionHead->PointerToRawData+pLastSectionHead->SizeOfRawData);
	unsigned long NumberOfBytesRead;
	if (nExtraDataSize>0)
	{
		pExtraData=new char[nExtraDataSize];
		memset(pExtraData,0,nExtraDataSize);
		ReadFile(hFile,pExtraData,nExtraDataSize,&NumberOfBytesRead,NULL);
	}
	else
	{
		//no extra data
	}
}

PCHAR RVAToPtr(DWORD dwRva)
{
	if ((UINT)dwRva

UINT AddressImportTable(PCHAR m_pImportTable)
{
	PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor=NULL,pDescriptor=NULL;
	PIMAGE_DATA_DIRECTORY    pImportDir=NULL;
	UINT			         nSize=0;
	PCHAR					 pData=NULL;
	PCHAR					 pFuncNum=0;
	PCHAR                    pszDllName;
	PIMAGE_THUNK_DATA32      pFirstThunk=NULL;
	PIMAGE_IMPORT_BY_NAME	 pImportName=NULL;
	
	pImportDir=&m_pntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
	pImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)RVAToPtr(pImportDir->VirtualAddress);
	//移动输入表
	for(pData=m_pImportTable,pDescriptor=pImportDescriptor;pDescriptor->Name!=0;pDescriptor++)
	{
		//保存FirstThunk
		*(DWORD*)pData=pDescriptor->FirstThunk;
		pData=pData+sizeof(DWORD);
		pszDllName=(PCHAR)RVAToPtr(pDescriptor->Name);
		//保存dll名长度
		*(BYTE*)(pData)=(BYTE)(strlen(pszDllName));
		pData=pData+sizeof(BYTE);
		//保存dll名
		memcpy(pData,pszDllName,strlen(pszDllName+1));
		pData=pData+strlen(pszDllName)+1;
		//保存函数个数记录变量
		pFuncNum=pData;
		*(BYTE*)pFuncNum=0;
		pData=pData+sizeof(DWORD);
		if (pDescriptor->OriginalFirstThunk!=0)
		{
			pFirstThunk=(PIMAGE_THUNK_DATA32)RVAToPtr(pDescriptor->OriginalFirstThunk);
		} 
		else
		{
			pFirstThunk=(PIMAGE_THUNK_DATA32)RVAToPtr(pDescriptor->FirstThunk);
		}
		while(pFirstThunk->u1.AddressOfData!=NULL)
		{
			if (IMAGE_SNAP_BY_ORDINAL32(pFirstThunk->u1.Ordinal))
			{
				//序号导入
				*(BYTE*)pData=0;
				pData=pData+sizeof(BYTE);
				*(DWORD*)pData=(DWORD)pFirstThunk->u1.Ordinal & 0x7FFFFFFF;
				pData=pData+sizeof(DWORD)+1;
				(*(DWORD*)pFuncNum)++;
				
			} 
			else
			{
				//字符串导入
				pImportName=(PIMAGE_IMPORT_BY_NAME)RVAToPtr((DWORD)pFirstThunk->u1.AddressOfData);
				*(BYTE*)pData=(BYTE)(strlen((char*)pImportName->Name));
				(*(DWORD*)pFuncNum)++;
				pData=pData+(strlen((char*)pImportName->Name))+1;
			}
			pFirstThunk++;
		}
	}
	*(DWORD*)pData=(DWORD)0;
	pData=pData+sizeof(DWORD);
	return (pData-m_pImportTable);
	
}




你可能感兴趣的:(C/C++,脱壳,PE文件结构)