Skip to content

Commit 5a6858a

Browse files
Merge pull request #62 from autumnlikescode/main
x86 Integrity check
2 parents de228e1 + 6734f52 commit 5a6858a

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

x86/example.vcxproj

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@
169169
<ClInclude Include="lib\curl\urlapi.h" />
170170
<ClInclude Include="lib\hmac_sha256.h" />
171171
<ClInclude Include="lib\includes.hpp" />
172+
<ClInclude Include="lib\integrity.h" />
172173
<ClInclude Include="lib\nlohmann\adl_serializer.hpp" />
173174
<ClInclude Include="lib\nlohmann\byte_container_with_subtype.hpp" />
174175
<ClInclude Include="lib\nlohmann\detail\conversions\from_json.hpp" />

x86/example.vcxproj.filters

+3
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@
200200
<ClInclude Include="lib\xorstr.hpp">
201201
<Filter>Header Files</Filter>
202202
</ClInclude>
203+
<ClInclude Include="lib\integrity.h">
204+
<Filter>Header Files</Filter>
205+
</ClInclude>
203206
</ItemGroup>
204207
<ItemGroup>
205208
<Library Include="lib\curl\libcurl.lib" />

x86/lib/auth.cpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include <algorithm>
5656

5757
#include "Security.hpp"
58+
#include "integrity.h"
5859

5960
#define SHA256_HASH_SIZE 32
6061

@@ -71,9 +72,7 @@ bool initalized;
7172

7273
void KeyAuth::api::init()
7374
{
74-
#if defined(__x86_64__) || defined(_M_X64)
75-
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)modify, 0, 0, 0);
76-
#endif
75+
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)modify, 0, 0, 0);
7776

7877
if (ownerid.length() != 10 || secret.length() != 64)
7978
{
@@ -1454,7 +1453,11 @@ void error(std::string message) {
14541453
return patched;
14551454
}
14561455
#elif defined(__i386) || defined(_M_IX86)
1457-
1456+
// code submitted in pull request from https://github.com/autumnlikescode authored by https://github.com/Vasie1337/integrity-check
1457+
auto check_section_integrity() {
1458+
_integrity_check check;
1459+
return check.check_integrity();
1460+
}
14581461
#endif
14591462

14601463
std::string checksum()
@@ -1691,5 +1694,12 @@ DWORD64 FindPattern(BYTE* bMask, const char* szMask)
16911694
}
16921695
}
16931696
#elif defined(__i386) || defined(_M_IX86)
1694-
1697+
// code submitted in pull request from https://github.com/autumnlikescode authored by https://github.com/Vasie1337/integrity-check
1698+
void modify() {
1699+
while (true) {
1700+
if (check_section_integrity()) {
1701+
error(XorStr("check_section_integrity() failed, don't tamper with the program."));
1702+
}
1703+
}
1704+
}
16951705
#endif

x86/lib/integrity.h

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
#include <iostream>
3+
#include <Windows.h>
4+
#include <nmmintrin.h>
5+
6+
typedef struct _integrity_check
7+
{
8+
struct section {
9+
std::uint8_t* name = {};
10+
void* address = {};
11+
std::uint32_t checksum = {};
12+
13+
bool operator==(section& other)
14+
{
15+
return checksum == other.checksum;
16+
}
17+
}; section _cached;
18+
19+
_integrity_check()
20+
{
21+
_cached = get_text_section(reinterpret_cast<std::uintptr_t>(GetModuleHandle(nullptr)));
22+
}
23+
24+
std::uint32_t crc32(void* data, std::size_t size)
25+
{
26+
std::uint32_t result = {};
27+
28+
for (std::size_t index = {}; index < size; ++index)
29+
result = _mm_crc32_u32(result, reinterpret_cast<std::uint8_t*>(data)[index]);
30+
31+
return result;
32+
}
33+
34+
section get_text_section(std::uintptr_t module)
35+
{
36+
section text_section = {};
37+
38+
PIMAGE_DOS_HEADER dosheader = reinterpret_cast<PIMAGE_DOS_HEADER>(module);
39+
PIMAGE_NT_HEADERS nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS>(module + dosheader->e_lfanew);
40+
41+
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt_headers);
42+
43+
for (int i = 0; i < nt_headers->FileHeader.NumberOfSections; i++, section++)
44+
{
45+
std::string name(reinterpret_cast<char const*>(section->Name));
46+
if (name != ".text")
47+
continue;
48+
49+
void* address = reinterpret_cast<void*>(module + section->VirtualAddress);
50+
text_section = { section->Name, address, crc32(address, section->Misc.VirtualSize) };
51+
}
52+
return text_section;
53+
}
54+
/// <summary>
55+
/// Checks .text integrity.
56+
/// </summary>
57+
/// <returns>Returns true if it has been changed.</returns>
58+
bool check_integrity()
59+
{
60+
section section2 = get_text_section(reinterpret_cast<std::uintptr_t>(GetModuleHandle(nullptr)));
61+
return (!(_cached == section2));
62+
}
63+
};

0 commit comments

Comments
 (0)