diff --git a/x86/example.vcxproj b/x86/example.vcxproj
index 95a006d..e48e181 100644
--- a/x86/example.vcxproj
+++ b/x86/example.vcxproj
@@ -169,6 +169,7 @@
+
diff --git a/x86/example.vcxproj.filters b/x86/example.vcxproj.filters
index 16397e1..2c25b2d 100644
--- a/x86/example.vcxproj.filters
+++ b/x86/example.vcxproj.filters
@@ -200,6 +200,9 @@
Header Files
+
+ Header Files
+
diff --git a/x86/lib/auth.cpp b/x86/lib/auth.cpp
index 4eaf90d..e44e57e 100644
--- a/x86/lib/auth.cpp
+++ b/x86/lib/auth.cpp
@@ -55,6 +55,7 @@
#include
#include "Security.hpp"
+#include "integrity.h"
#define SHA256_HASH_SIZE 32
@@ -71,9 +72,7 @@ bool initalized;
void KeyAuth::api::init()
{
- #if defined(__x86_64__) || defined(_M_X64)
- CreateThread(0, 0, (LPTHREAD_START_ROUTINE)modify, 0, 0, 0);
- #endif
+ CreateThread(0, 0, (LPTHREAD_START_ROUTINE)modify, 0, 0, 0);
if (ownerid.length() != 10 || secret.length() != 64)
{
@@ -1454,7 +1453,11 @@ void error(std::string message) {
return patched;
}
#elif defined(__i386) || defined(_M_IX86)
-
+ // code submitted in pull request from https://github.com/autumnlikescode authored by https://github.com/Vasie1337/integrity-check
+ auto check_section_integrity() {
+ _integrity_check check;
+ return check.check_integrity();
+ }
#endif
std::string checksum()
@@ -1691,5 +1694,12 @@ DWORD64 FindPattern(BYTE* bMask, const char* szMask)
}
}
#elif defined(__i386) || defined(_M_IX86)
-
+// code submitted in pull request from https://github.com/autumnlikescode authored by https://github.com/Vasie1337/integrity-check
+ void modify() {
+ while (true) {
+ if (check_section_integrity()) {
+ error(XorStr("check_section_integrity() failed, don't tamper with the program."));
+ }
+ }
+ }
#endif
diff --git a/x86/lib/integrity.h b/x86/lib/integrity.h
new file mode 100644
index 0000000..511a572
--- /dev/null
+++ b/x86/lib/integrity.h
@@ -0,0 +1,63 @@
+#pragma once
+#include
+#include
+#include
+
+typedef struct _integrity_check
+{
+ struct section {
+ std::uint8_t* name = {};
+ void* address = {};
+ std::uint32_t checksum = {};
+
+ bool operator==(section& other)
+ {
+ return checksum == other.checksum;
+ }
+ }; section _cached;
+
+ _integrity_check()
+ {
+ _cached = get_text_section(reinterpret_cast(GetModuleHandle(nullptr)));
+ }
+
+ std::uint32_t crc32(void* data, std::size_t size)
+ {
+ std::uint32_t result = {};
+
+ for (std::size_t index = {}; index < size; ++index)
+ result = _mm_crc32_u32(result, reinterpret_cast(data)[index]);
+
+ return result;
+ }
+
+ section get_text_section(std::uintptr_t module)
+ {
+ section text_section = {};
+
+ PIMAGE_DOS_HEADER dosheader = reinterpret_cast(module);
+ PIMAGE_NT_HEADERS nt_headers = reinterpret_cast(module + dosheader->e_lfanew);
+
+ PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt_headers);
+
+ for (int i = 0; i < nt_headers->FileHeader.NumberOfSections; i++, section++)
+ {
+ std::string name(reinterpret_cast(section->Name));
+ if (name != ".text")
+ continue;
+
+ void* address = reinterpret_cast(module + section->VirtualAddress);
+ text_section = { section->Name, address, crc32(address, section->Misc.VirtualSize) };
+ }
+ return text_section;
+ }
+ ///
+ /// Checks .text integrity.
+ ///
+ /// Returns true if it has been changed.
+ bool check_integrity()
+ {
+ section section2 = get_text_section(reinterpret_cast(GetModuleHandle(nullptr)));
+ return (!(_cached == section2));
+ }
+};
\ No newline at end of file