我正在尝试在MFC exe中实现自我完整性检查。
参考: - Tamper Aware and Self Healing Code:Codeproject
我转储了文字部分
ofstream myfile;
myfile.open ("textsec.bin");
myfile.write((const char*)pCodeStart,dwCodeSize);
myfile.close();
每次它的不同如此哈希也是不同的。请帮忙
我想检查文本,即内存中的代码部分应与磁盘上存在的文件中的代码部分相同。 所以我们可以确定我们在内存中的exe文件没有修补。 我们可以在分发产品时使用。
我们将通过
开始在内存中启动代码段 VOID ImageInformation( HMODULE& hModule, PVOID& pVirtualAddress,
PVOID& pCodeStart, SIZE_T& dwCodeSize,
PVOID& pCodeEnd )
{
const UINT PATH_SIZE = 2 * MAX_PATH;
TCHAR szFilename[ PATH_SIZE ] = { 0 };
__try {
/////////////////////////////////////////////////
/////////////////////////////////////////////////
if( 0 == GetModuleFileName( NULL, szFilename, PATH_SIZE ) )
{
std::tcerr << _T("Error Retrieving Process Filename");
std::tcerr << std::endl;
__leave;
}
hModule = GetModuleHandle( szFilename );
if( NULL == hModule )
{
std::tcerr << _T("Error Retrieving Process Module Handle");
std::tcerr << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDOSHeader = NULL;
pDOSHeader = static_cast<PIMAGE_DOS_HEADER>( (PVOID)hModule );
if( pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE )
{
std::tcerr << _T("Error - File is not EXE Format");
std::tcerr << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNTHeader = NULL;
pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(
(PBYTE)hModule + pDOSHeader->e_lfanew );
if( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
{
std::tcerr << _T("Error - File is not PE Format") << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>(
(PBYTE)&pNTHeader->FileHeader );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
pOptionalHeader = reinterpret_cast<PIMAGE_OPTIONAL_HEADER>(
(PBYTE)&pNTHeader->OptionalHeader );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
if( IMAGE_NT_OPTIONAL_HDR32_MAGIC !=
pNTHeader->OptionalHeader.Magic )
{
std::tcerr << _T("Error - File is not 32 bit") << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
(PBYTE)&pNTHeader->OptionalHeader +
pNTHeader->FileHeader.SizeOfOptionalHeader );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
const CHAR TEXT[] = ".text";
const CHAR BSSTEXT[] = ".textbss";
UINT nSectionCount = pNTHeader->FileHeader.NumberOfSections;
CHAR szSectionName[ IMAGE_SIZEOF_SHORT_NAME + 1 ];
szSectionName[ IMAGE_SIZEOF_SHORT_NAME ] = '\0';
for( UINT i = 0; i < nSectionCount; i++ )
{
memcpy( szSectionName, pSectionHeader->Name,
IMAGE_SIZEOF_SHORT_NAME );
if( 0 == strncmp( TEXT, szSectionName,
IMAGE_SIZEOF_SHORT_NAME ) )
{
std::tcout << std::endl;
break;
}
pSectionHeader++;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
if( 0 != strncmp( TEXT, szSectionName, IMAGE_SIZEOF_SHORT_NAME ) )
{
std::tcerr << _T("Error - Unable to locate ");
std::cerr << TEXT;
std::tcerr << _T(" TEXT") << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
pVirtualAddress = (PVOID)(pSectionHeader->VirtualAddress);
dwCodeSize = pSectionHeader->Misc.VirtualSize;
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
pCodeStart = (PVOID)(((PBYTE)hModule) +
(SIZE_T)((PBYTE)pVirtualAddress) );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
pCodeEnd = (PVOID)((PBYTE)pCodeStart + dwCodeSize );
}
__except( EXCEPTION_EXECUTE_HANDLER ) {
std::tcerr << std::endl << _T("Caught Exception") << std::endl;
}
}
现在我们可以计算代码段的哈希值
CalculateImageHash( pCodeStart, dwCodeSize, cbCalculatedImageHash );
然后我们与cbExpectedImageHash进行比较。 cbExpectedImageHash是预定义的全局
if( 0 == memcmp( cbExpectedImageHash, cbCalculatedImageHash,
CryptoPP::SHA224::DIGESTSIZE ) )
{
std::tcout << _T("Image is verified.") << std::endl;
}
在MFC中,cbCalculatedImageHash每次都不同。 :(但不是在控制台应用程序。
cbExpectedImageHash和cbCalculatedImageHash是globel。
这是我的对话框的完整代码
// UserAppDlg.cpp : implementation file
//
#include "stdafx.h"
#include "UserApp.h"
#include "UserAppDlg.h"
#include "sha.h" // SHA
#include "hex.h" // HexEncoder
#include "files.h" // FileSink
#include "filters.h" // StringSink
#include "gzip.h"
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
// we can add cbExpectedImageHash new values if we get calcualted hash same every
BYTE cbExpectedImageHash[ CryptoPP::SHA224::DIGESTSIZE ] =
{
0xBA, 0x71, 0x29, 0xD8, 0x79, 0x4E, 0xA3, 0x5A, 0x2C, 0xE0
, 0xC5, 0x3A, 0x68, 0x9E, 0xE8, 0x29, 0x09, 0x44, 0xFA, 0x71
, 0xAF, 0xDB,0x3E,0x88,0xAD,0x65,0x67,0x78
};
BYTE cbCalculatedImageHash[ CryptoPP::SHA224::DIGESTSIZE ] ;
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CUserAppDlg dialog
CUserAppDlg::CUserAppDlg(CWnd* pParent /*=NULL*/)
: CDialog(CUserAppDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CUserAppDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CUserAppDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CUserAppDlg message handlers
int CUserAppDlg::ImageInformation( HMODULE& hModule, PVOID& pVirtualAddress,
PVOID& pCodeStart, SIZE_T& dwCodeSize,
PVOID& pCodeEnd )
{
const UINT PATH_SIZE = 2 * MAX_PATH;
TCHAR szFilename[ PATH_SIZE ] = { 0 };
__try {
/////////////////////////////////////////////////
/////////////////////////////////////////////////
if( 0 == GetModuleFileName( NULL, szFilename, PATH_SIZE ) )
{
// std::tcerr << _T("Error Retrieving Process Filename");
// std::tcerr << std::endl;
__leave;
}
hModule = GetModuleHandle( szFilename );
if( NULL == hModule )
{
// std::tcerr << _T("Error Retrieving Process Module Handle");
// std::tcerr << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDOSHeader = NULL;
pDOSHeader = static_cast<PIMAGE_DOS_HEADER>( (PVOID)hModule );
if( pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE )
{
// std::tcerr << _T("Error - File is not EXE Format");
// std::tcerr << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNTHeader = NULL;
pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(
(PBYTE)hModule + pDOSHeader->e_lfanew );
if( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
{
// std::tcerr << _T("Error - File is not PE Format") << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>(
(PBYTE)&pNTHeader->FileHeader );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
pOptionalHeader = reinterpret_cast<PIMAGE_OPTIONAL_HEADER>(
(PBYTE)&pNTHeader->OptionalHeader );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
if( IMAGE_NT_OPTIONAL_HDR32_MAGIC !=
pNTHeader->OptionalHeader.Magic )
{
// std::tcerr << _T("Error - File is not 32 bit") << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
(PBYTE)&pNTHeader->OptionalHeader +
pNTHeader->FileHeader.SizeOfOptionalHeader );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
const CHAR TEXT[] = ".text";
const CHAR BSSTEXT[] = ".textbss";
UINT nSectionCount = pNTHeader->FileHeader.NumberOfSections;
CHAR szSectionName[ IMAGE_SIZEOF_SHORT_NAME + 1 ];
szSectionName[ IMAGE_SIZEOF_SHORT_NAME ] = '\0';
for( UINT i = 0; i < nSectionCount; i++ )
{
memcpy( szSectionName, pSectionHeader->Name,
IMAGE_SIZEOF_SHORT_NAME );
if( 0 == strncmp( TEXT, szSectionName,
IMAGE_SIZEOF_SHORT_NAME ) )
{
// std::tcout << std::endl;
break;
}
pSectionHeader++;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
if( 0 != strncmp( TEXT, szSectionName, IMAGE_SIZEOF_SHORT_NAME ) )
{
// std::tcerr << _T("Error - Unable to locate ");
// std::cerr << TEXT;
// std::tcerr << _T(" TEXT") << std::endl;
__leave;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
pVirtualAddress = (PVOID)(pSectionHeader->VirtualAddress);
dwCodeSize = pSectionHeader->Misc.VirtualSize;
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
pCodeStart = (PVOID)(((PBYTE)hModule) +
(SIZE_T)((PBYTE)pVirtualAddress) );
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
pCodeEnd = (PVOID)((PBYTE)pCodeStart + dwCodeSize );
}
__except( EXCEPTION_EXECUTE_HANDLER ) {
// std::tcerr << std::endl << _T("Caught Exception") << std::endl;
}
return 0;
}
void CUserAppDlg::CalculateImageHash( PVOID pCodeStart, SIZE_T dwCodeSize,
PBYTE pcbDigest )
{
CryptoPP::SHA224 hash;
hash.Update( (PBYTE)pCodeStart, dwCodeSize );
hash.Final( pcbDigest );
}
BOOL CUserAppDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
HMODULE hModule = NULL;
PVOID pVirtualAddress = NULL;
PVOID pCodeStart = NULL;
PVOID pCodeEnd = NULL;
SIZE_T dwCodeSize = 0;
ImageInformation( hModule, pVirtualAddress, pCodeStart,
dwCodeSize, pCodeEnd );
ofstream myfile;
myfile.open ("textsec.bin"); //textsec.bin changes everytime
myfile.write((const char*)pCodeStart,dwCodeSize);
myfile.close();
CalculateImageHash( pCodeStart, dwCodeSize, cbCalculatedImageHash ); //cbCalculatedImageHash changes everytime
myfile.open ("CalculateImageHash.bin");
myfile.write((const char*)cbCalculatedImageHash,CryptoPP::SHA224::DIGESTSIZE);
myfile.close();
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CUserAppDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CUserAppDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CUserAppDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}