1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#pragma once
// std::unique_ptr
#include <memory>
// Intrinsics (_ReturnAddress)
#include <intrin.h>
// PEB
#include <windows.h>
#include <winternl.h>
// IOCTL
#include <winioctl.h>
// EnumDeviceDrivers
#include <psapi.h>
// WinInet
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
// Required for the SDK from VMP which offers
// virtual machines and string encryption, as
// well as debug/VM checks.
#include <VMProtectSDK.h>
// Required for MinHook.
#include <MinHook.h>
#pragma comment(lib, "MinHook.lib")
// Used for wrapping Themida's macros along with some other things.
// e.g: WRAP_IF_RELEASE( VM_SHARK_BLACK_START ) will only trigger in Release mode.
// Likewise, WRAP_IF_DEBUG( printf( "Error: %08x", GetLastError() ) ) will only
// trigger in Debug mode.
// Just a neat little feature that I decided to implement :-)
#ifdef DEBUG
// Sick macros, retard.
#define WRAP_IF_RELEASE( s )
#define WRAP_IF_DEBUG( s ) { s; }
#define STR( s ) s
#else
// Sick macros, retard.
#define WRAP_IF_RELEASE( s ) { s; }
#define WRAP_IF_DEBUG( s )
#define STR( s ) VMProtectDecryptStringA( s )
#endif
namespace Security
{
// Sigh..
struct CodeIntegrityInformation {
uint32_t m_Size;
uint32_t m_Options;
};
enum SpecialMode {
SAFE_MODE,
TEST_SIGN_MODE,
TEST_BUILD_MODE,
DEBUGGING_MODE
};
// Hardware ID structure (this is hashed and sent to server, but it's easier to use it
// this way internally)
struct HardwareIdentifier
{
// Generic CPU information.
uint16_t m_CpuArchitecture;
uint32_t m_CpuCount;
// Hash of the hard disk serial identifier.
uint64_t m_HardDiskSerialHash;
// VMP HWID
char m_CustomDetail[256];
// Safe-mode/Test-signing mode status
uint8_t m_SpecialMode[4];
};
// This class implements the runtime security system.
// In short, upon initialization, the system applies detours to numerous API functions
// which will be checked for integrity every time they are called.
// Also, a few threads are dispatched in the process in order to ensure that there are no
// forbidden programs/conditions being triggered.
// The class has an (inlined) security callback which can be used to phone home and infract/ban
// any potentially malicious actions from users.
class RuntimeSecurity
{
HardwareIdentifier m_Identifier;
protected:
// Applies necessary API hooks.
bool ApplyApiHooks();
// Patches common debugging functions to crash the program.
void PatchDebugFunctions();
// Dispatches security threads.
void DispatchSecurityThreads();
// Grabs all hardware data.
void SetupSystemIdentifier();
// The following functions are used in security threads to run checks.
void CheckForVirtualMachine();
void CheckForDebugger();
void CheckForDrivers();
void CheckForTampering();
public:
// Initializes the runtime security system.
bool Start();
// Retrieves the current Hardware ID for the system.
HardwareIdentifier GetHardwareId();
// Syscall wrapper for ZwQueryVirtualMemory.
// This is so we don't get hooked.
MEMORY_BASIC_INFORMATION QueryMemory(void *Address);
// Security callback.
// This should phone back to the server and log any tampering.
// TODO: Nave, actually implement this.
void SecurityCallback(const char *Reason);
};
// Readability
using RuntimeSecurityPtr = std::unique_ptr<RuntimeSecurity>;
}
extern Security::RuntimeSecurityPtr Protection;
|