#pragma once
 
/*
	Bliblioteka code integrity
	Autor: Regz.pl
 
	Przykład:
		code_integrity::Initialize();
		while (1) {
			if (code_integrity::Check()) {
				MessageBoxA(nullptr, "Zmodyfikowano kod programu.", "", MB_OK);
				PostQuitMessage(0);
			}
		}
 
	Test:
		Uruchom Cheat Engine, kliknij Memory view. Zmień dowolną instrukcję np. JMP na inny adres.
*/
 
#include <Windows.h>
#include <iostream>
#include <cstring>
 
namespace code_integrity {
	HMODULE moduleHandle = GetModuleHandle(nullptr);
	IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)moduleHandle;
	IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((DWORD)dosHeader + dosHeader->e_lfanew);
	PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
 
	DWORD oldProtection;
	DWORD textBaseAddress = 0;
	DWORD textSize = 0;
	DWORD initialTextSectionChecksum = 0;
 
	bool isTextSectionFound = false;
	const DWORD INITIAL_CRC32_VALUE = 0x811C9DC5;
 
	DWORD CalculateSectionChecksum(DWORD sectionStart, DWORD sectionLength) {
		DWORD checksum = INITIAL_CRC32_VALUE;
 
		for (DWORD i = 0; i < sectionLength; i++) {
			checksum = (checksum ^ ((BYTE*)sectionStart)[i]) * 0x1000193;
		}
 
		return checksum;
	}
 
	void Initialize() {
		for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i) {
			if (std::strcmp(".text", (char*)sectionHeader[i].Name) == 0) {
				isTextSectionFound = true;
				textBaseAddress = DWORD((BYTE*)moduleHandle + sectionHeader[i].VirtualAddress);
				textSize = sectionHeader[i].SizeOfRawData;
 
				if (textBaseAddress == 0) {
					textBaseAddress = (DWORD)moduleHandle;
				}
				if (textSize == 0) {
					textSize = 1024 * 1024;
				}
 
				VirtualProtect((LPVOID)textBaseAddress, textSize, PAGE_EXECUTE_READ, &oldProtection);
				initialTextSectionChecksum = CalculateSectionChecksum(textBaseAddress, textSize);
			}
		}
	}
 
	int Check() {
		if (isTextSectionFound) {
			DWORD currentTextSectionChecksum = CalculateSectionChecksum(textBaseAddress, textSize);
			if (initialTextSectionChecksum != currentTextSectionChecksum) {
				return 1;
			}
		}
 
		return 0;
	}
}