Click here to Skip to main content
15,896,606 members
Articles / Programming Languages / C++

ExeScanner

Rate me:
Please Sign up or sign in to vote.
4.91/5 (67 votes)
6 Jun 20052 min read 115.9K   4.3K   102  
This article explains how to enumerate all the objects in a Portable Executable and manipulate them.
/******************************************************************************
*
* PROJECT:		ExeScanner
* FILE NAME:	PEResBitmap.cpp
*
* DEVELOPER:	Vishalsinh Jhala
* DATE:			2-Apr-2005
*
* DESCRIPTION:	Defination file for class PEResBitmap.
*
* NOTES:		Encapsulates Bitmap Resource. Such resources, when requested
*				by user to be displayed, are shown in View.
*
******************************************************************************/
#include "StdAfx.h"
#include "peresbitmap.h"
#include "ImageImportDlg.h"

PEResBitmap::PEResBitmap(PEFile *pFile, DWORD dwOffset, DWORD dwSize)
	:m_dwOffset(dwOffset),m_dwSize(dwSize)
{
	//Validate the inputs
	if( !pFile )
	{
		char *szErrMsg = new char[1024];
		strcpy(szErrMsg,"Cannot Proceed with NULL File");
		throw new PEFileException(szErrMsg);
	}
	m_pFile = pFile;

	//who am i?
	strcpy(m_pszMyName,"BITMAP");
}

PEResBitmap::~PEResBitmap(void)
{

}
const char* PEResBitmap::GetName()
{
	return (const char*)m_pszMyName;
}

void PEResBitmap::GetPropertyInfo(CString& strInfo)
{
	BITMAPINFOHEADER bih;
	m_pFile->Read(m_dwOffset,0,(BYTE*)&bih,sizeof(BITMAPINFOHEADER));
	
	int iColors = (int)pow(2,bih.biBitCount);
	strInfo.Format("RESOURCE TYPE\n%s\n"
		"OFFSET\n%d\n"
		"SIZE\n%d\n"
		"WIDTH\n%d\n"
		"HEIGHT\n%d\n"
		"BITS PER PIXEL#\n%d\n"
		"COLORS\n%d\n",
		"Bitmap Image",
		m_dwOffset,
		m_dwSize,
		bih.biWidth,
		bih.biHeight,
		bih.biBitCount,
		iColors		
		);

}
void PEResBitmap::IterateElements(PETreeList *pList)
{

}
void PEResBitmap::Draw(CDC **pDC,CBitmap **pBmp,CWnd **pWnd)
{
	//Load the date from File
	m_pResData = new BYTE[m_dwSize];
	m_pFile->Read(m_dwOffset,0,m_pResData,m_dwSize);

	*pDC = new CDC();
	*pBmp = new CBitmap();

	BITMAPINFOHEADER bih;
	BITMAPINFO *bi;
	
	//First thing that appears in data is the BITMAPINFOHEADER
	memcpy(&bih,m_pResData,sizeof(BITMAPINFOHEADER));
	if( bih.biSize !=40 || bih.biWidth <=0 || bih.biHeight <=0 )
	{
		char *szErrMsg = new char[1024];
		strcpy(szErrMsg,"Invalid Bitmap Header");
		throw new PEResParseException(szErrMsg);
	}

	//Decide the presence of color table in bitmap
	int iColors = (int)pow(2,bih.biBitCount);
	bi = NULL;
	if( iColors > 0 && iColors <= 256 )
	{
		if(bih.biBitCount == 1)
		{
			typedef struct tag{
					BITMAPINFOHEADER bmiHeader;
					RGBQUAD bmiColors[2];
					} bi1;
			bi = (BITMAPINFO*)new bi1;

		}
		else if(bih.biBitCount == 2)
		{
			typedef struct tag{
					BITMAPINFOHEADER bmiHeader;
					RGBQUAD bmiColors[4];
					} bi1;
			bi = (BITMAPINFO*)new bi1;

		}
		else if(bih.biBitCount == 3)
		{
			typedef struct tag{
					BITMAPINFOHEADER bmiHeader;
					RGBQUAD bmiColors[8];
					} bi1;
			bi = (BITMAPINFO*)new bi1;

		}
		else if(bih.biBitCount == 4)
		{
			typedef struct tag{
					BITMAPINFOHEADER bmiHeader;
					RGBQUAD bmiColors[16];
					} bi1;
			bi = (BITMAPINFO*)new bi1;

		}
		else if(bih.biBitCount == 8)
		{
			typedef struct tag{
					BITMAPINFOHEADER bmiHeader;
					RGBQUAD bmiColors[256];
					} bi1;
			bi = (BITMAPINFO*)new bi1;

		}
	}
	else
	{
		iColors = 0;
		bi = new BITMAPINFO;
	}
	//Read colortable
	memcpy(bi,m_pResData,sizeof(BITMAPINFOHEADER)+iColors*4);
	
	//Initialize the bitmap and DC object that will be send back to UI.
	(*pDC)->CreateCompatibleDC(CDC::FromHandle(::GetDC(NULL)));
	(*pBmp)->CreateCompatibleBitmap(CDC::FromHandle(::GetDC(NULL)),bih.biWidth,bih.biHeight);
	(*pDC)->SelectObject(*pBmp);

	//Convert data loaded from file to bitmap and copy bitmap bits to DC.
	int iRet = SetDIBitsToDevice((*pDC)->GetSafeHdc(),0,0,bih.biWidth,bih.biHeight,0,0,0,bih.biHeight,m_pResData+sizeof(BITMAPINFOHEADER)+iColors*4,bi,DIB_RGB_COLORS);
	if(iRet == 0)
	{
		int iErr = GetLastError();
		char *szErrMsg = new char[1024];
		strcpy(szErrMsg,"Error while copying Bitmap to memory:");
		itoa(iErr,szErrMsg+37,10);
		throw new PEResParseException(szErrMsg);
	}

	//Release Memory
	delete m_pResData;
	m_pResData = NULL;
	delete bi;
}
void PEResBitmap::Import(BOOL bFromFile)
{
	IMAGE_RESOURCE irSrc,irDest;
	
	//Get the file to be imported
	CFileDialog dlgOpen(TRUE,0,0,
		OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST,
		"Bitmaps (*.bmp)|*.bmp||");
	
	if(dlgOpen.DoModal() == IDOK)
	{
		irSrc.strFile = dlgOpen.GetPathName();
	}
	else
		return;
	
	CFileStatus fs;
	CFile::GetStatus(irSrc.strFile,fs);

	HANDLE handle = NULL;

	//Load the file
	handle = ::LoadImage(::AfxGetInstanceHandle(),
		irSrc.strFile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_DEFAULTCOLOR);
	if(handle == NULL)
	{
		char *szErrMsg = new char[27];
		strcpy(szErrMsg,"Error while Loading bitmap");
		throw new PEResParseException(szErrMsg);
	}

	CBitmap bmpSrc,*pbmpDest;
	CDC dcSrc,*pdcDest;
	BITMAP bitmap;

	//Prepare the source bitmap loaded from file.
	bmpSrc.Attach(handle);
	bmpSrc.GetBitmap(&bitmap);
	
	dcSrc.CreateCompatibleDC(CDC::FromHandle(::GetDC(NULL)));
	dcSrc.SelectObject(&bmpSrc);
	
	BITMAPINFOHEADER bih;
	BITMAPFILEHEADER bfh;

	//Get the info headers of source file
	CFile fileSrc;
	
	fileSrc.Open(irSrc.strFile,CFile::modeRead|CFile::typeBinary);
	fileSrc.Read(&bfh,sizeof(BITMAPFILEHEADER));
	fileSrc.Read(&bih,sizeof(BITMAPINFOHEADER));
	

	//Prepare image resource structure.
	irSrc.iWidth = bitmap.bmWidth;
	irSrc.iHeight = bitmap.bmHeight;
	irSrc.iBPP = bih.biBitCount;
	irSrc.iSize = (int)(fs.m_size - sizeof(BITMAPFILEHEADER));
	irSrc.pDC = &dcSrc;

	//Load destination image with in PE file for display.
	m_pResData = new BYTE[m_dwSize];
	m_pFile->Read(m_dwOffset,0,m_pResData,m_dwSize);
	memcpy(&bih,m_pResData,sizeof(BITMAPINFOHEADER));
	delete m_pResData;
	m_pResData = NULL;

	Draw(&pdcDest,&pbmpDest);
	
	pbmpDest->GetBitmap(&bitmap);
	irDest.strFile = "RESOURCE";
	irDest.iWidth = bitmap.bmWidth;
	irDest.iHeight = bitmap.bmHeight;
	irDest.iBPP = bih.biBitCount;
	irDest.iSize = m_dwSize;
	irDest.pDC = pdcDest;

	//Call the Dialog
	CImageImportDlg ImportDlg(irSrc,irDest);
	if( ImportDlg.DoModal() == IDOK )
	{
		//CFile f1;
		m_pResData = new BYTE[m_dwSize];
		//f1.Open(irSrc.strFile,CFile::modeRead|CFile::typeBinary);
		
		fileSrc.Seek(0,CFile::begin);
		fileSrc.Read(&bfh,sizeof(BITMAPFILEHEADER));
		fileSrc.Read(m_pResData,m_dwSize);
		
		//f1.Close();

		m_pFile->Write(m_dwOffset,0,m_pResData,m_dwSize);
		
		AfxMessageBox("Resource Updated");
		delete m_pResData;
		m_pResData = NULL;
	}
	fileSrc.Close();

	delete pbmpDest;
	delete pdcDest;
	//DeleteObject(bmpSrc.Detach());

}
void PEResBitmap::Export(BOOL bFromFile)
{
	//Load the resource 
	m_pResData = new BYTE[m_dwSize];
	m_pFile->Read(m_dwOffset,0,m_pResData,m_dwSize);

	BITMAPFILEHEADER bfh;
	BITMAPINFOHEADER bih;
	
	//Determine dimensions
	memcpy(&bih,m_pResData,sizeof(BITMAPINFOHEADER));
	if( bih.biSize !=40 || bih.biWidth <=0 || bih.biHeight <=0 )
	{
		char *szErrMsg = new char[1024];
		strcpy(szErrMsg,"Invalid Bitmap Header");
		throw new PEResParseException(szErrMsg);
	}

	int iColors = (int)pow(2,bih.biBitCount);
	if( iColors < 0 || iColors > 256 )
		iColors = 0;

	//Prepare file header
	ZeroMemory(&bfh,sizeof(BITMAPFILEHEADER));
	bfh.bfType = 0x4D42;
	bfh.bfSize = m_dwSize + sizeof(BITMAPFILEHEADER);
	bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+iColors*4;
	
	//Get the saveas name from user
	CFileDialog fd(FALSE,0,"Untitled.bmp",
		OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST,
		"Bitmaps (*.bmp)|*.bmp;||");

	if(fd.DoModal() == IDOK)
	{
		CString strPath = fd.GetPathName();
		if(strPath.Right(4).CompareNoCase(".bmp") != 0)
			strPath.Append(".bmp");

		CFile fSave;
		
		fSave.Open(strPath,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
		fSave.Write(&bfh,sizeof(BITMAPFILEHEADER));
		fSave.Write(m_pResData,m_dwSize);
		
		fSave.Close();
	}
	
	//Release Memory
	delete m_pResData;
	m_pResData = NULL;

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions