最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++ 實(shí)現(xiàn)PE文件特征碼識(shí)別的步驟

 更新時(shí)間:2021年06月23日 14:36:00   作者:lyshark  
PE文件就是我們常說(shuō)的EXE可執(zhí)行文件,針對(duì)文件特征的識(shí)別可以清晰的知道該程序是使用何種編程語(yǔ)言實(shí)現(xiàn)的,前提是要有特征庫(kù),PE特征識(shí)別有多種形式,第一種是靜態(tài)識(shí)別,第二種則是動(dòng)態(tài)識(shí)別,我們經(jīng)常使用的PEID查殼工具是基于靜態(tài)檢測(cè)的方法。

打開PE文件映射:

在讀取PE結(jié)構(gòu)之前,首先要做的就是打開PE文件到內(nèi)存,這里打開文件我們使用了CreateFile()函數(shù)該函數(shù)可以打開文件并返回文件句柄,接著使用CreateFileMapping()函數(shù)創(chuàng)建文件的內(nèi)存映像,最后使用MapViewOfFile()讀取映射中的內(nèi)存并返回一個(gè)句柄,后面的程序就可以通過(guò)該句柄操作打開后的文件了.

#include <stdio.h>
#include <Windows.h>
#include <ImageHlp.h>

#pragma comment(lib,"Imagehlp.lib")

// 讀取PE結(jié)構(gòu)的封裝
HANDLE OpenPeFile(LPTSTR FileName)
{
	HANDLE hFile, hMapFile, lpMapAddress = NULL;
	DWORD dwFileSize = 0;

	// CreateFile 既可以創(chuàng)建文件,也可以打開文件,這里則是打開文件的含義
	hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return 0;

	// 獲取到文件大小
	dwFileSize = GetFileSize(hFile, NULL);

	// 創(chuàng)建文件的內(nèi)存映像
	// 此方法非常靈活,其不需要將程序完全讀入內(nèi)存中,節(jié)約空間。
	hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);
	if (hMapFile == NULL)
		return 0;

	// 讀取映射中的內(nèi)存并返回一個(gè)句柄
	lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwFileSize);
	if (lpMapAddress != NULL)
		return lpMapAddress;
	return 0;
}

int main(int argc, char * argv[])
{
	HANDLE lpMapAddress = NULL;

	lpMapAddress = OpenPeFile("c://lyshark.exe");
	printf("打開文件句柄: %d \n", lpMapAddress);

	system("pause");
	return 0;
}

判斷是否為PE文件:

當(dāng)文件已經(jīng)打開后,接下來(lái)就要判斷文件是否為有效的PE文件,這里我們首先將鏡像轉(zhuǎn)換為PIMAGE_DOS_HEADER格式并通過(guò)pDosHead->e_magic屬性找到PIMAGE_NT_HEADERS結(jié)構(gòu),然后判斷其是否符合PE文件規(guī)范即可,這里需要注意32位于64位PE結(jié)構(gòu)所使用的的結(jié)構(gòu)定義略有不同,代碼中已經(jīng)對(duì)其進(jìn)行了區(qū)分.

#include <stdio.h>
#include <Windows.h>
#include <ImageHlp.h>

#pragma comment(lib,"Imagehlp.lib")

// 讀取PE結(jié)構(gòu)的封裝
HANDLE OpenPeFile(LPTSTR FileName)
{
	HANDLE hFile, hMapFile, lpMapAddress = NULL;
	DWORD dwFileSize = 0;

	// CreateFile 既可以創(chuàng)建文件,也可以打開文件,這里則是打開文件的含義
	hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return 0;

	// 獲取到文件大小
	dwFileSize = GetFileSize(hFile, NULL);

	// 創(chuàng)建文件的內(nèi)存映像
	// 此方法非常靈活,其不需要將程序完全讀入內(nèi)存中,節(jié)約空間。
	hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);
	if (hMapFile == NULL)
		return 0;

	// 讀取映射中的內(nèi)存并返回一個(gè)句柄
	lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwFileSize);
	if (lpMapAddress != NULL)
		return lpMapAddress;
	return 0;
}

// 判斷是否為PE文件
BOOL IsPeFile(HANDLE ImageBase, BOOL Is64 = FALSE)
{
	PIMAGE_DOS_HEADER pDosHead = NULL;
	if (ImageBase == NULL)
		return FALSE;

	// 將映射文件轉(zhuǎn)為DOS結(jié)構(gòu),并判斷開頭是否為MZ
	pDosHead = (PIMAGE_DOS_HEADER)ImageBase;
	if (IMAGE_DOS_SIGNATURE != pDosHead->e_magic)
		return FALSE;

	if (Is64 == TRUE)
	{
		// 根據(jù) IMAGE_DOS_HEADER 的 e_lfanew 的值得到 64位 NT 頭的位置
		PIMAGE_NT_HEADERS64 pNtHead64 = NULL;
		pNtHead64 = (PIMAGE_NT_HEADERS64)((DWORD64)pDosHead + pDosHead->e_lfanew);
		if (pNtHead64->Signature != IMAGE_NT_SIGNATURE)
			return FALSE;
	}
	else if (Is64 == FALSE)
	{
		// 根據(jù) IMAGE_DOS_HEADER 的 e_lfanew 的值得到 32位 NT 頭的位置
		PIMAGE_NT_HEADERS pNtHead32 = NULL;
		pNtHead32 = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
		if (pNtHead32->Signature != IMAGE_NT_SIGNATURE)
			return FALSE;
	}
	return TRUE;
}

int main(int argc, char * argv[])
{
	HANDLE lpMapAddress = NULL;

	// 打開文件拿到PE句柄
	lpMapAddress = OpenPeFile("c://lyshark.exe");

	// 判斷是否為PE文件,這里定義的為真返回1,為假返回0
	BOOL ret = IsPeFile(lpMapAddress, 0);
	printf("是否為PE文件: %d \n", ret);

	system("pause");
	return 0;
}

判斷PE文件特征碼:

判斷程序使用了何種編譯器編寫,通常情況是要用文件的入口處代碼和特征碼進(jìn)行匹配,通常情況下我們只需要匹配程序開頭的前32個(gè)字節(jié)就差不多了,當(dāng)然為了匹配精度更高,我們也可以對(duì)多個(gè)字段進(jìn)行驗(yàn)證,這里就只寫出大體輪廓吧.

#include <stdio.h>
#include <Windows.h>
#include <ImageHlp.h>

#pragma comment(lib,"Imagehlp.lib")

// 讀取PE結(jié)構(gòu)的封裝
HANDLE OpenPeFile(LPTSTR FileName)
{
	HANDLE hFile, hMapFile, lpMapAddress = NULL;
	DWORD dwFileSize = 0;

	// CreateFile 既可以創(chuàng)建文件,也可以打開文件,這里則是打開文件的含義
	hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return 0;

	// 獲取到文件大小
	dwFileSize = GetFileSize(hFile, NULL);

	// 創(chuàng)建文件的內(nèi)存映像
	// 此方法非常靈活,其不需要將程序完全讀入內(nèi)存中,節(jié)約空間。
	hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);
	if (hMapFile == NULL)
		return 0;

	// 讀取映射中的內(nèi)存并返回一個(gè)句柄
	lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, dwFileSize);
	if (lpMapAddress != NULL)
		return lpMapAddress;
	return 0;
}

// 判斷是否為PE文件
BOOL IsPeFile(HANDLE ImageBase, BOOL Is64 = FALSE)
{
	PIMAGE_DOS_HEADER pDosHead = NULL;
	if (ImageBase == NULL)
		return FALSE;

	// 將映射文件轉(zhuǎn)為DOS結(jié)構(gòu),并判斷開頭是否為MZ
	pDosHead = (PIMAGE_DOS_HEADER)ImageBase;
	if (IMAGE_DOS_SIGNATURE != pDosHead->e_magic)
		return FALSE;

	if (Is64 == TRUE)
	{
		// 根據(jù) IMAGE_DOS_HEADER 的 e_lfanew 的值得到 64位 NT 頭的位置
		PIMAGE_NT_HEADERS64 pNtHead64 = NULL;
		pNtHead64 = (PIMAGE_NT_HEADERS64)((DWORD64)pDosHead + pDosHead->e_lfanew);
		if (pNtHead64->Signature != IMAGE_NT_SIGNATURE)
			return FALSE;
	}
	else if (Is64 == FALSE)
	{
		// 根據(jù) IMAGE_DOS_HEADER 的 e_lfanew 的值得到 32位 NT 頭的位置
		PIMAGE_NT_HEADERS pNtHead32 = NULL;
		pNtHead32 = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
		if (pNtHead32->Signature != IMAGE_NT_SIGNATURE)
			return FALSE;
	}
	return TRUE;
}

// 掃描特征碼,對(duì)比
void GetPeSignature(LPCWSTR FilePath)
{
	typedef struct _SIGN
	{
		char FileName[64];         // 存儲(chǔ)文件名或特征描述
		LONG FileOffset;           // 存儲(chǔ)檢測(cè)文件偏移地址
		BYTE VirusSign[32 + 1];    // 存儲(chǔ)特征碼大小32,其中的1是結(jié)束符.
	}SIGN, *pSIGN;

	// 定義特征碼與特征描述信息,你可以自己去提取一段特征碼
	SIGN Sign[2] = {
		{
			"Microsoft Visual C/C++ x86 (2013)",
			0x8a0,
		"\x55\x8B\xEC\x81\xEC\xC4\x00\x00\x00\x53\x56\x57\x8D\xBD\x3C\xFF" \
		"\xFF\xFF\xB9\x31\x00\x00\x00\xB8\xCC\xCC\xCC\xCC\xF3\xAB\x8B\x45" \
		},
		{
			"Microsoft Visual C/C++ x64 (2013)",
			0x400,
		"\xCC\xCC\xCC\xCC\xCC\xE9\x86\x02\x00\x00\xE9\x31\x05\x00\x00\xE9" \
		"\x6C\x01\x00\x00\xE9\x57\x03\x00\x00\xE9\x22\x00\x00\x00\xCC\xCC" \
		}
	};

	DWORD dwNum = 0;
	BYTE buffer[32 + 1];
	HANDLE hFile = NULL;

	// 獲取到FilePath路徑下文件的句柄信息
	hFile = CreateFile(FilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	// 我們有兩段待檢測(cè)特征,這里循環(huán)兩次從零開始
	for (int x = 0; x <= 2; x++)
	{
		// 將待檢測(cè)程序的文件指針指向特征碼的偏移位置
		SetFilePointer(hFile, Sign[x].FileOffset, NULL, FILE_BEGIN);
		// 讀取目標(biāo)程序指定位置的特征碼到內(nèi)存中
		ReadFile(hFile, buffer, sizeof(buffer), &dwNum, NULL);
		// 對(duì)比內(nèi)存中兩個(gè)特征碼是否相等
		if (memcmp(Sign[x].VirusSign, buffer, 32) == 0)
		{
			printf("檢測(cè)結(jié)果: %s \n", Sign[x].FileName);
		}
	}
	CloseHandle(hFile);
}

int main(int argc, char * argv[])
{
	GetPeSignature(L"c://lyshark.exe");
	system("pause");
	return 0;
}

你需要自己提取不同編譯器的特征字段,然后按照我寫好的格式進(jìn)行增加,例如我是用vs2013編譯的,那么檢測(cè)結(jié)果就可能會(huì)是vs2013,特征碼的提取應(yīng)盡量保證一致性。

文章出處:https://www.cnblogs.com/lyshark

以上就是C++ 實(shí)現(xiàn)PE文件特征碼識(shí)別的步驟的詳細(xì)內(nèi)容,更多關(guān)于C++ PE文件特征碼識(shí)別的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Visual Studio 2019安裝使用C語(yǔ)言程序(VS2019 C語(yǔ)言)

    Visual Studio 2019安裝使用C語(yǔ)言程序(VS2019 C語(yǔ)言)

    這篇文章主要介紹了Visual Studio 2019安裝使用C語(yǔ)言程序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • C/C++高精度算法的實(shí)現(xiàn)

    C/C++高精度算法的實(shí)現(xiàn)

    這篇文章主要介紹了C/C++高精度算法的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C++線性表深度解析之動(dòng)態(tài)數(shù)組與單鏈表和棧及隊(duì)列的實(shí)現(xiàn)

    C++線性表深度解析之動(dòng)態(tài)數(shù)組與單鏈表和棧及隊(duì)列的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)動(dòng)態(tài)數(shù)組、單鏈表、棧、隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++初階教程之類和對(duì)象

    C++初階教程之類和對(duì)象

    C++是面向?qū)ο缶幊痰?這也是C++與C語(yǔ)言的最大區(qū)別,而類和對(duì)象就是C++面向?qū)ο蟮幕A(chǔ),下面這篇文章主要給大家介紹了關(guān)于C++初階教程之類和對(duì)象的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • 基于C++全局變量的聲明與定義的詳解

    基于C++全局變量的聲明與定義的詳解

    本篇文章是對(duì)C++全局變量的聲明與定義進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 淺談關(guān)于C語(yǔ)言中#define的副作用

    淺談關(guān)于C語(yǔ)言中#define的副作用

    這篇文章主要介紹了關(guān)于C語(yǔ)言中#define的副作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 如何將編譯過(guò)的C++庫(kù)迅速部署在Visual?Studio新項(xiàng)目中

    如何將編譯過(guò)的C++庫(kù)迅速部署在Visual?Studio新項(xiàng)目中

    本文介紹在Visual?Studio中,通過(guò)屬性表,使得一個(gè)新建解決方案中的項(xiàng)目可以快速配置已有解決方案的項(xiàng)目中各類已編譯好的C++第三方庫(kù)的方法,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • DHCP:解析開發(fā)板上動(dòng)態(tài)獲取ip的2種實(shí)現(xiàn)方法詳解

    DHCP:解析開發(fā)板上動(dòng)態(tài)獲取ip的2種實(shí)現(xiàn)方法詳解

    本篇文章是對(duì)開發(fā)板上動(dòng)態(tài)獲取ip的2種實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中bitset位圖介紹及模擬實(shí)現(xiàn)

    C++中bitset位圖介紹及模擬實(shí)現(xiàn)

    位圖就是用每一位來(lái)存放某種狀態(tài),適用于海量數(shù)據(jù),本文就介紹一下C++中bitset位圖介紹及模擬實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-07-07
  • C++ Opencv imfill孔洞填充函數(shù)的實(shí)現(xiàn)思路與代碼

    C++ Opencv imfill孔洞填充函數(shù)的實(shí)現(xiàn)思路與代碼

    在Matlab下,使用imfill可以很容易的完成孔洞填充操作,下面這篇文章主要給大家介紹了關(guān)于C++ Opencv imfill孔洞填充函數(shù)的實(shí)現(xiàn)思路與代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09

最新評(píng)論

襄垣县| 尤溪县| 汉中市| 图片| 进贤县| 凤翔县| 仙游县| 延川县| 涟水县| 高邮市| 玛纳斯县| 遂川县| 洞口县| 磐安县| 包头市| 基隆市| 崇文区| 广南县| 滁州市| 孝昌县| 道孚县| 蓬安县| 石泉县| 禹州市| 邓州市| 西昌市| 尼勒克县| 崇礼县| 沈阳市| 鹿泉市| 大方县| 海淀区| 乃东县| 通海县| 明光市| 雷波县| 佛山市| 上虞市| 子洲县| 宁明县| 汉川市|