欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

1.先來(lái)實(shí)現(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);

	// 定位第一個(gè)區(qū)塊地址,因?yàn)槟J(rèn)的話第一個(gè)就是.text節(jié)
	pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);

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

	system("pause");
	return 0;
}

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

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

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

	// 動(dòng)態(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;
	}
	// 計(jì)算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);

	// 定位第一個(gè)區(qū)塊地址,因?yàn)槟J(rèn)的話第一個(gè)就是.text節(jié)
	pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);
	DWORD va_base = ImageBase + pSecHeader->VirtualAddress;   // 定位代碼節(jié)va基地址
	DWORD sec_len = pSecHeader->Misc.VirtualSize;             // 獲取代碼節(jié)長(zhǎng)度
	//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[])
{
	// 用于保存初始化時(shí) .text 節(jié)中的CRC32值
	DWORD OriginalCRC32 = 0;

	// 初始化時(shí),給全局變量賦值,記錄下初始的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ù)了整個(gè)程序,在實(shí)際應(yīng)用中,為了提高效率,有時(shí)我們只需要保護(hù)其中一個(gè)片段代碼就好,這樣可以提高效率,所有我們對(duì)上面代碼稍作修改即可實(shí)現(xiàn)針對(duì)特定片段的內(nèi)存校驗(yàn)。

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

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

	// 動(dòng)態(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;
	}
	// 計(jì)算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);

	// 以下三條語(yǔ)句可用于確定位置
	// pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);
	// DWORD va_base1 = ImageBase + pSecHeader->VirtualAddress;   // 定位代碼節(jié)va基地址
	// DWORD sec_len1 = pSecHeader->Misc.VirtualSize;             // 獲取代碼節(jié)長(zhǎng)度
	// 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[])
{
	// 用于保存初始化時(shí) .text 節(jié)中的CRC32值
	DWORD OriginalCRC32 = 0;

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

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

	// 校驗(yàn)指定內(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;
}

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

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

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

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)順序表的示例代碼

    C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)順序表的示例代碼

    順序表是用一段物理地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)數(shù)據(jù)元素的線性結(jié)構(gòu)。順序表一般分為靜態(tài)順序表和動(dòng)態(tài)順序表,本文主要和大家介紹的是動(dòng)態(tài)順序表的實(shí)現(xiàn),需要的可以參考一下
    2022-10-10
  • 解析C++函數(shù)的默認(rèn)參數(shù)和占位參數(shù)及較之C語(yǔ)言的拓展

    解析C++函數(shù)的默認(rèn)參數(shù)和占位參數(shù)及較之C語(yǔ)言的拓展

    這篇文章主要介紹了C++中的默認(rèn)參數(shù)和占位參數(shù)及較之C語(yǔ)言的拓展,需要的朋友可以參考下
    2016-03-03
  • C++細(xì)講深淺拷貝與初始化列表如何操作

    C++細(xì)講深淺拷貝與初始化列表如何操作

    C++對(duì)象特性里的拷貝構(gòu)造函數(shù)有更深入的含義,而且面試曾經(jīng)問(wèn)過(guò)關(guān)于拷貝的析構(gòu)問(wèn)題,那么今天就好好解析一下深淺拷貝的問(wèn)題;還有初始化列表的形式,這個(gè)在給對(duì)象屬性初始化的時(shí)候非常方便,建議大家熟練掌握,話不多說(shuō),開始正文
    2022-05-05
  • C++獲取項(xiàng)目路徑的兩種方式詳解

    C++獲取項(xiàng)目路徑的兩種方式詳解

    這篇文章主要介紹了C++獲取項(xiàng)目路徑的兩種方式的相關(guān)資料,需要的朋友可以參考下,希望能夠給你帶來(lái)幫助
    2021-10-10
  • 冒泡排序的三種實(shí)現(xiàn)方法

    冒泡排序的三種實(shí)現(xiàn)方法

    本篇文章是對(duì)冒泡排序的三種實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下。希望對(duì)大家有所幫助
    2013-10-10
  • C++實(shí)現(xiàn)LeetCode(37.求解數(shù)獨(dú))

    C++實(shí)現(xiàn)LeetCode(37.求解數(shù)獨(dú))

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(37.求解數(shù)獨(dú)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語(yǔ)言實(shí)現(xiàn)飛機(jī)游戲(進(jìn)階版)的示例代碼

    C語(yǔ)言實(shí)現(xiàn)飛機(jī)游戲(進(jìn)階版)的示例代碼

    在前文中,已經(jīng)帶大家利用C語(yǔ)言實(shí)現(xiàn)了簡(jiǎn)單的飛機(jī)游戲,但它還存在一些缺陷。因此,本文將給大家?guī)?lái)進(jìn)階版的飛機(jī)游戲,需要的可以參考一下
    2022-10-10
  • EasyC++單獨(dú)編譯

    EasyC++單獨(dú)編譯

    這篇文章主要介紹了EasyC++單獨(dú)編譯,在上一篇當(dāng)中,我們編寫好了頭文件coordin.h,現(xiàn)在我們要完成它的實(shí)現(xiàn)。需要的小伙伴可以先學(xué)習(xí)上一篇內(nèi)容然后一起與小編一起進(jìn)入本篇內(nèi)容一起學(xué)習(xí)吧
    2021-12-12
  • 基于C語(yǔ)言實(shí)現(xiàn)創(chuàng)意多彩貪吃蛇游戲

    基于C語(yǔ)言實(shí)現(xiàn)創(chuàng)意多彩貪吃蛇游戲

    這篇文章主要介紹了如何利用C語(yǔ)言實(shí)現(xiàn)一個(gè)創(chuàng)意多彩貪吃蛇游戲,這是一個(gè)純C語(yǔ)言外加easyx庫(kù)的繪圖函數(shù)制作而成的有趣小游戲,無(wú)需引入額外資源,感興趣的可以動(dòng)手嘗試一下
    2022-08-08
  • C++實(shí)現(xiàn)從數(shù)組中同時(shí)取出最大最小元素算法示例

    C++實(shí)現(xiàn)從數(shù)組中同時(shí)取出最大最小元素算法示例

    這篇文章主要介紹了C++實(shí)現(xiàn)從數(shù)組中同時(shí)取出最大最小元素算法,結(jié)合具體實(shí)例形式分析了C++通過(guò)數(shù)組的遍歷、排序獲取最大與最小元素的相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09

最新評(píng)論