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

C++ 使用CRC32檢測內(nèi)存映像完整性的實現(xiàn)步驟

 更新時間:2021年06月23日 15:36:28   作者:lyshark  
當(dāng)我們使用動態(tài)補(bǔ)丁的時候,那么內(nèi)存中同樣不存在校驗效果,也就無法抵御對方動態(tài)修改機(jī)器碼了,為了防止解密者直接對內(nèi)存打補(bǔ)丁,我們需要在硬盤校驗的基礎(chǔ)上,增加內(nèi)存校驗,防止動態(tài)補(bǔ)丁的運(yùn)用。

僅對.text代碼段進(jìn)行校驗:

通常程序中至少包括了代碼段,數(shù)據(jù)段,而數(shù)據(jù)段中所存儲的數(shù)據(jù)是經(jīng)常會發(fā)生變動的,例如我們的全局變量,靜態(tài)變量等都會默認(rèn)存儲在數(shù)據(jù)段,而代碼段則不會發(fā)生變化,我們在檢驗時只需要注重.text內(nèi)存段中的數(shù)據(jù)完整性即可,針對內(nèi)存的校驗同樣可以抵御調(diào)試器的CC斷點(diǎn),該斷點(diǎn)原理就是在下端處寫入int3指令,同樣可以檢測得到。

校驗思路如下
1.首先從內(nèi)存得到PE的代碼節(jié)的RVA和節(jié)大小
2.根據(jù)得到的RVA和節(jié)大小計算出crc32或是RC4值
3.讀取自身保存的原始CRC32值,與校驗結(jié)果進(jìn)行比較

1.先來實現(xiàn)第一步,讀取內(nèi)存映像的起始地址與大小,我們可以這樣做。

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNtHeader = NULL;
	PIMAGE_SECTION_HEADER pSecHeader = NULL;
	DWORD ImageBase;

	// 獲取基地址
	ImageBase = (DWORD)GetModuleHandle(NULL);

	// 定位到PE頭結(jié)構(gòu)
	pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;

	// 定位到NT頭
	pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);

	// 定位第一個區(qū)塊地址,因為默認(rèn)的話第一個就是.text節(jié)
	pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);

	// 取出節(jié)內(nèi)偏移與節(jié)表長度
	DWORD va_base = ImageBase + pSecHeader->VirtualAddress;   // 定位代碼節(jié)va基地址
	DWORD sec_len = pSecHeader->Misc.VirtualSize;             // 獲取代碼節(jié)長度
	
	printf("鏡像基址(.text): %x --> 鏡像大小: %x \n", va_base, sec_len);

	system("pause");
	return 0;
}

2.第二部就是計算校驗和,然后計算該節(jié)的CRC32值,并存入全局變量,也就是程序打開后自動初始化計算一次內(nèi)存crc32值并放入全局變量中,然后開一個線程,每三秒檢測一次內(nèi)存變化,如果變化則終止執(zhí)行或彈窗提示,你也可以提前計算處校驗和并寫入PE空缺位置。

#include <stdio.h>
#include <windows.h>

DWORD CRC32(BYTE* ptr, DWORD Size)
{
	DWORD crcTable[256], crcTmp1;

	// 動態(tài)生成CRC-32表
	for (int i = 0; i<256; i++)
	{
		crcTmp1 = i;
		for (int j = 8; j>0; j--)
		{
			if (crcTmp1 & 1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;
			else crcTmp1 >>= 1;
		}
		crcTable[i] = crcTmp1;
	}
	// 計算CRC32值
	DWORD crcTmp2 = 0xFFFFFFFF;
	while (Size--)
	{
		crcTmp2 = ((crcTmp2 >> 8) & 0x00FFFFFF) ^ crcTable[(crcTmp2 ^ (*ptr)) & 0xFF];
		ptr++;
	}
	return (crcTmp2 ^ 0xFFFFFFFF);
}

// 檢查內(nèi)存中CRC32特征值
DWORD CheckMemory()
{
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNtHeader = NULL;
	PIMAGE_SECTION_HEADER pSecHeader = NULL;
	DWORD ImageBase;

	// 獲取基地址
	ImageBase = (DWORD)GetModuleHandle(NULL);

	// 定位到PE頭結(jié)構(gòu)
	pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
	pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);

	// 定位第一個區(qū)塊地址,因為默認(rèn)的話第一個就是.text節(jié)
	pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);
	DWORD va_base = ImageBase + pSecHeader->VirtualAddress;   // 定位代碼節(jié)va基地址
	DWORD sec_len = pSecHeader->Misc.VirtualSize;             // 獲取代碼節(jié)長度
	//printf("鏡像基址(.text): %x --> 鏡像大小: %x \n", va_base, sec_len);

	DWORD CheckCRC32 = CRC32((BYTE*)(va_base), sec_len);
	// printf(".text節(jié)CRC32 = %x \n", CheckCRC32);
	return CheckCRC32;
}

int main(int argc,char *argv[])
{
	// 用于保存初始化時 .text 節(jié)中的CRC32值
	DWORD OriginalCRC32 = 0;

	// 初始化時,給全局變量賦值,記錄下初始的CRC32值
	OriginalCRC32 = CheckMemory();

	while (1)
	{
		Sleep(3000);
		DWORD NewCRC32 = CheckMemory();
		if (OriginalCRC32 == NewCRC32)
			printf("程序沒有被打補(bǔ)丁. \n");
		else
			printf("程序被打補(bǔ)丁 \n");
	}

	system("pause");
	return 0;
}

上方代碼是保護(hù)了整個程序,在實際應(yīng)用中,為了提高效率,有時我們只需要保護(hù)其中一個片段代碼就好,這樣可以提高效率,所有我們對上面代碼稍作修改即可實現(xiàn)針對特定片段的內(nèi)存校驗。

#include <stdio.h>
#include <windows.h>

DWORD CRC32(BYTE* ptr, DWORD Size)
{
	DWORD crcTable[256], crcTmp1;

	// 動態(tài)生成CRC-32表
	for (int i = 0; i<256; i++)
	{
		crcTmp1 = i;
		for (int j = 8; j>0; j--)
		{
			if (crcTmp1 & 1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;
			else crcTmp1 >>= 1;
		}
		crcTable[i] = crcTmp1;
	}
	// 計算CRC32值
	DWORD crcTmp2 = 0xFFFFFFFF;
	while (Size--)
	{
		crcTmp2 = ((crcTmp2 >> 8) & 0x00FFFFFF) ^ crcTable[(crcTmp2 ^ (*ptr)) & 0xFF];
		ptr++;
	}
	return (crcTmp2 ^ 0xFFFFFFFF);
}

// 檢查內(nèi)存中CRC32特征值
DWORD CheckMemory(DWORD va_base, DWORD sec_len)
{
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNtHeader = NULL;
	PIMAGE_SECTION_HEADER pSecHeader = NULL;
	DWORD ImageBase;
	ImageBase = (DWORD)GetModuleHandle(NULL);
	pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
	pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);

	// 以下三條語句可用于確定位置
	// pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);
	// DWORD va_base1 = ImageBase + pSecHeader->VirtualAddress;   // 定位代碼節(jié)va基地址
	// DWORD sec_len1 = pSecHeader->Misc.VirtualSize;             // 獲取代碼節(jié)長度
	// printf("鏡像基址(.text): %x --> 鏡像大小: %x \n", va_base1, sec_len1);

	DWORD CheckCRC32 = CRC32((BYTE*)(va_base), sec_len);
	return CheckCRC32;
}

int main(int argc, char *argv[])
{
	// 用于保存初始化時 .text 節(jié)中的CRC32值
	DWORD OriginalCRC32 = 0;

	DWORD begin_addr, end_addr, size;
	// 獲取到兩個位置的偏移地址
	__asm mov begin_addr, offset begin;
	__asm mov end_addr, offset end;

	// 計算出 兩者內(nèi)存差值
	size = end_addr - begin_addr;

	// 校驗指定內(nèi)存位置
	OriginalCRC32 = CheckMemory(begin_addr, size);

	while (1)
	{
	begin: // 標(biāo)記為需要保護(hù)的區(qū)域
		printf("hello lyshark \n");
		printf("hello lyshark \n");
		printf("hello lyshark \n");
	end:   // 保護(hù)區(qū)域聲明結(jié)束

		if (OriginalCRC32 == CheckMemory(begin_addr, size))
			printf("此區(qū)域沒有被破解 \n");
		else
			printf("此區(qū)域已被修改\n");

		Sleep(3000);
	}
	system("pause");
	return 0;
}

通過使用磁盤校驗結(jié)合內(nèi)存校驗兩種方式綜合保護(hù),可以極大的提高軟件的安全性,繞過方式則是找到哪兒跟全局變量將其修正為正確的值即可,同樣的也可以更暴力一些直接將判斷條件改掉均可。

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

以上就是C++ 使用CRC32檢測內(nèi)存映像完整性的實現(xiàn)步驟的詳細(xì)內(nèi)容,更多關(guān)于C++用CRC32檢測內(nèi)存映像完整性的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解析C語言中空指針、空指針常量、NULL & 0的詳解

    解析C語言中空指針、空指針常量、NULL & 0的詳解

    本篇文章是對C語言中空指針、空指針常量、NULL & 0 進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言結(jié)合ffmpeg打印音視頻信息

    C語言結(jié)合ffmpeg打印音視頻信息

    這篇文章主要介紹了如何通過C語言或者C++編程語言結(jié)合ffmpeg拿到一些音視頻的關(guān)鍵信息,例如:幀率等。感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2021-12-12
  • Visual Studio2000系列版本安裝OpenGL的圖文教程

    Visual Studio2000系列版本安裝OpenGL的圖文教程

    這篇文章主要介紹了Visual Studio2000系列版本安裝OpenGL的圖文教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • C++游戲教程基本技巧之隨機(jī)化詳解

    C++游戲教程基本技巧之隨機(jī)化詳解

    在小游戲的制作中時常常會要用到隨機(jī)數(shù),這篇文章就來和大家談?wù)凜++中這個所謂的“隨機(jī)”。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-11-11
  • C語言實現(xiàn)五子棋人人對戰(zhàn)

    C語言實現(xiàn)五子棋人人對戰(zhàn)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)五子棋人人對戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • QT中在QLabel顯示圖片并且利用鼠標(biāo)點(diǎn)擊畫線問題

    QT中在QLabel顯示圖片并且利用鼠標(biāo)點(diǎn)擊畫線問題

    這篇文章主要介紹了QT中在QLabel顯示圖片并且利用鼠標(biāo)點(diǎn)擊畫線問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++ 名稱空間詳情

    C++ 名稱空間詳情

    當(dāng)一個項目變得大型之后,我們會引入很多的庫,這么一來兩個庫很可能會定義List、Tree、Node同名的類,編譯器要是不考慮這情況的話,程序員調(diào)用時就會出現(xiàn)沖突問題。C++提供了名稱空間工具,以更好的控制名稱的作用域,本文就來談?wù)凜++ 名稱空間,需要的朋友可以參考一下
    2021-09-09
  • C++掃盲篇之指針詳解

    C++掃盲篇之指針詳解

    C++中一個指針的使用就已經(jīng)讓很多人欲哭無淚,可是更不幸的是他還有指向指針的指針,這篇文章主要給大家介紹了關(guān)于C++掃盲篇之指針的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • Qt使用Matlab函數(shù)的詳細(xì)步驟

    Qt使用Matlab函數(shù)的詳細(xì)步驟

    由于項目需要,需要調(diào)用現(xiàn)有的matlab程序,下面這篇文章主要給大家介紹了關(guān)于Qt使用Matlab函數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • C++指針 詳細(xì)介紹及總結(jié)

    C++指針 詳細(xì)介紹及總結(jié)

    這篇文章主要介紹了C++指針 詳細(xì)介紹及總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2016-09-09

最新評論

库车县| 华池县| 贵阳市| 永定县| 仁化县| 茌平县| 景德镇市| 宁阳县| 关岭| 沛县| 肥城市| 雅江县| 阿拉尔市| 南汇区| 宜州市| 渝北区| 武山县| 武平县| 图片| 寻乌县| 三亚市| 正镶白旗| 乌审旗| 中西区| 黑水县| 军事| 改则县| 甘孜县| 普安县| 德保县| 崇阳县| 博客| 莱阳市| 通渭县| 涿州市| 洪洞县| 安泽县| 扎赉特旗| 沁阳市| 菏泽市| 邵武市|