mirror of
https://github.com/Alukym/VMProtect-Source.git
synced 2025-06-24 00:17:55 -05:00
Initial commit
This commit is contained in:
303
runtime/CFGregorianDateCreate.hpp
Normal file
303
runtime/CFGregorianDateCreate.hpp
Normal file
@ -0,0 +1,303 @@
|
||||
/* Arrays of asctime-date day and month strs, rfc1123-date day and month strs, and rfc850-date day and month strs. */
|
||||
static const char* kDayStrs[] = {
|
||||
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday",
|
||||
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
||||
|
||||
static const char* kMonthStrs[] = {
|
||||
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December",
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
/* NOTE that these are ordered this way on purpose. */
|
||||
static const char* kUSTimeZones[] = {"PST", "PDT", "MST", "MDT", "CST", "CDT", "EST", "EDT"};
|
||||
|
||||
|
||||
/* extern */ const UInt8*
|
||||
_CFGregorianDateCreateWithBytes(CFAllocatorRef alloc, const UInt8* bytes, CFIndex length, CFGregorianDate* date, CFTimeZoneRef* tz) {
|
||||
|
||||
UInt8 buffer[256]; /* Any dates longer than this are not understood. */
|
||||
|
||||
length = (length == 256) ? 255 : length;
|
||||
memmove(buffer, bytes, length);
|
||||
buffer[length] = '\0'; /* Guarantees every compare will fail if trying to index off the end. */
|
||||
|
||||
memset(date, 0, sizeof(date[0]));
|
||||
if (tz) *tz = NULL;
|
||||
|
||||
do {
|
||||
size_t i;
|
||||
CFIndex scan = 0;
|
||||
UInt8 c = buffer[scan];
|
||||
|
||||
/* Skip leading whitespace */
|
||||
while (isspace(c))
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Check to see if there is a weekday up front. */
|
||||
if (!isdigit(c)) {
|
||||
|
||||
for (i = 0; i < (sizeof(kDayStrs) / sizeof(kDayStrs[0])); i++) {
|
||||
if (!memcmp(kDayStrs[i], &buffer[scan], strlen(kDayStrs[i])))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >=(sizeof(kDayStrs) / sizeof(kDayStrs[0])))
|
||||
break;
|
||||
|
||||
scan += strlen(kDayStrs[i]);
|
||||
c = buffer[scan];
|
||||
|
||||
while (isspace(c) || c == ',')
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
/* check for asctime where month comes first */
|
||||
if (!isdigit(c)) {
|
||||
|
||||
for (i = 0; i < (sizeof(kMonthStrs) / sizeof(kMonthStrs[0])); i++) {
|
||||
if (!memcmp(kMonthStrs[i], &buffer[scan], strlen(kMonthStrs[i])))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= (sizeof(kMonthStrs) / sizeof(kMonthStrs[0])))
|
||||
break;
|
||||
|
||||
date->month = (i % 12) + 1;
|
||||
|
||||
scan += strlen(kMonthStrs[i]);
|
||||
c = buffer[scan];
|
||||
|
||||
while (isspace(c))
|
||||
c = buffer[++scan];
|
||||
|
||||
if (!isdigit(c))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the day of month */
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
date->day *= 10;
|
||||
date->day += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
while (isspace(c) || c == '-')
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Not asctime so now comes the month. */
|
||||
if (date->month == 0) {
|
||||
|
||||
if (isdigit(c)) {
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
date->month *= 10;
|
||||
date->month += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < (sizeof(kMonthStrs) / sizeof(kMonthStrs[0])); i++) {
|
||||
if (!memcmp(kMonthStrs[i], &buffer[scan], strlen(kMonthStrs[i])))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= (sizeof(kMonthStrs) / sizeof(kMonthStrs[0])))
|
||||
break;
|
||||
|
||||
date->month = (i % 12) + 1;
|
||||
|
||||
scan += strlen(kMonthStrs[i]);
|
||||
c = buffer[scan];
|
||||
}
|
||||
|
||||
while (isspace(c) || c == '-')
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Read the year */
|
||||
for (i = 0; isdigit(c) && (i < 4); i++) {
|
||||
date->year *= 10;
|
||||
date->year += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
while (isspace(c))
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
/* Read the hours */
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
date->hour *= 10;
|
||||
date->hour += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
if (c != ':')
|
||||
break;
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Read the minutes */
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
date->minute *= 10;
|
||||
date->minute += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
if (c == ':') {
|
||||
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Read the seconds */
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
date->second *= 10;
|
||||
date->second += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
/* If haven't read the year yet, now is the time. */
|
||||
if (date->year == 0) {
|
||||
|
||||
while (isspace(c))
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Read the year */
|
||||
for (i = 0; isdigit(c) && (i < 4); i++) {
|
||||
date->year *= 10;
|
||||
date->year += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
}
|
||||
|
||||
if (date->year && date->year < 100) {
|
||||
|
||||
if (date->year < 70)
|
||||
date->year += 2000; /* My CC is still using 2-digit years! */
|
||||
else
|
||||
date->year += 1900; /* Bad 2 byte clients */
|
||||
}
|
||||
|
||||
while (isspace(c))
|
||||
c = buffer[++scan];
|
||||
|
||||
if (c && tz) {
|
||||
|
||||
/* If it has absolute offset, read the hours and minutes. */
|
||||
if ((c == '+') || (c == '-')) {
|
||||
|
||||
char sign = c;
|
||||
CFTimeInterval minutes = 0, offset = 0;
|
||||
|
||||
c = buffer[++scan];
|
||||
|
||||
/* Read the hours */
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
offset *= 10;
|
||||
offset += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
/* Read the minutes */
|
||||
for (i = 0; isdigit(c) && (i < 2); i++) {
|
||||
minutes *= 10;
|
||||
minutes += c - '0';
|
||||
c = buffer[++scan];
|
||||
}
|
||||
|
||||
offset *= 60;
|
||||
offset += minutes;
|
||||
|
||||
if (sign == '-') offset *= -60;
|
||||
else offset *= 60;
|
||||
|
||||
*tz = CFTimeZoneCreateWithTimeIntervalFromGMT(alloc, offset);
|
||||
}
|
||||
|
||||
/* If it's not GMT/UT time, need to parse the alpha offset. */
|
||||
else if (!strncmp((const char*)(&buffer[scan]), "UT", 2)) {
|
||||
*tz = CFTimeZoneCreateWithTimeIntervalFromGMT(alloc, 0);
|
||||
scan += 2;
|
||||
}
|
||||
|
||||
else if (!strncmp((const char*)(&buffer[scan]), "GMT", 3)) {
|
||||
*tz = CFTimeZoneCreateWithTimeIntervalFromGMT(alloc, 0);
|
||||
scan += 3;
|
||||
}
|
||||
|
||||
else if (isalpha(c)) {
|
||||
|
||||
UInt8 next = buffer[scan + 1];
|
||||
|
||||
/* Check for military time. */
|
||||
if ((c != 'J') && (!next || isspace(next) || (next == '*'))) {
|
||||
|
||||
if (c == 'Z')
|
||||
*tz = CFTimeZoneCreateWithTimeIntervalFromGMT(alloc, 0);
|
||||
|
||||
else {
|
||||
|
||||
CFTimeInterval offset = (c < 'N') ? (c - 'A' + 1) : ('M' - c);
|
||||
|
||||
offset *= 60;
|
||||
|
||||
if (next == '*') {
|
||||
scan++;
|
||||
offset = (offset < 0) ? offset - 30 : offset + 30;
|
||||
}
|
||||
|
||||
offset *= 60;
|
||||
|
||||
*tz = CFTimeZoneCreateWithTimeIntervalFromGMT(alloc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
for (i = 0; i < (sizeof(kUSTimeZones) / sizeof(kUSTimeZones[0])); i++) {
|
||||
|
||||
if (!memcmp(kUSTimeZones[i], &buffer[scan], strlen(kUSTimeZones[i]))) {
|
||||
|
||||
*tz = CFTimeZoneCreateWithTimeIntervalFromGMT(alloc, (-8 + (i >> 2) + (i & 0x1)) * 3600);
|
||||
|
||||
scan += strlen(kUSTimeZones[i]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!CFGregorianDateIsValid(*date, kCFGregorianAllUnits))
|
||||
break;
|
||||
|
||||
return bytes + scan;
|
||||
|
||||
} while (1);
|
||||
|
||||
memset(date, 0, sizeof(date[0]));
|
||||
if (tz) {
|
||||
if (*tz) CFRelease(*tz);
|
||||
*tz = NULL;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* extern */ CFIndex
|
||||
_CFGregorianDateCreateWithString(CFAllocatorRef alloc, CFStringRef str, CFGregorianDate* date, CFTimeZoneRef* tz) {
|
||||
|
||||
UInt8 buffer[256]; /* Any dates longer than this are not understood. */
|
||||
CFIndex length = CFStringGetLength(str);
|
||||
CFIndex result = 0;
|
||||
|
||||
CFStringGetBytes(str, CFRangeMake(0, length), kCFStringEncodingASCII, 0, FALSE, buffer, sizeof(buffer), &length);
|
||||
|
||||
if (length)
|
||||
result = _CFGregorianDateCreateWithBytes(alloc, buffer, length, date, tz) - buffer;
|
||||
|
||||
else {
|
||||
memset(date, 0, sizeof(date[0]));
|
||||
if (tz) *tz = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
526
runtime/VMProtect.Runtime/Core.cs
Normal file
526
runtime/VMProtect.Runtime/Core.cs
Normal file
@ -0,0 +1,526 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedParameter.Global
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable once CheckNamespace
|
||||
[assembly: SuppressIldasmAttribute()]
|
||||
[assembly: Obfuscation(Feature = "renaming", Exclude = true)]
|
||||
namespace VMProtect
|
||||
{
|
||||
/// <summary>
|
||||
/// Serial number status flags
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SerialState
|
||||
{
|
||||
/// <summary>
|
||||
/// No problems.
|
||||
/// </summary>
|
||||
Success = 0x00000000,
|
||||
/// <summary>
|
||||
/// Licensing module is corrupted. This may be caused by cracking attempts. Usually you will never get this flag.
|
||||
/// </summary>
|
||||
Corrupted = 0x00000001,
|
||||
/// <summary>
|
||||
/// Serial number is invalid. You will get this flag if licensing module will be unable to decrypt serial number or
|
||||
/// if the serial number is not yet set or it is empty.
|
||||
/// </summary>
|
||||
Invalid = 0x00000002,
|
||||
/// <summary>
|
||||
/// Serial number is correct, but it was blacklisted in VMProtect.
|
||||
/// </summary>
|
||||
Blacklisted = 0x00000004,
|
||||
/// <summary>
|
||||
/// Serial number is expired. You will get this flag if serial number has expiration date chunk and this date is in the past.
|
||||
/// You may read the expiration date by calling GetSerialNumberData() function.
|
||||
/// </summary>
|
||||
DateExpired = 0x00000008,
|
||||
/// <summary>
|
||||
/// Running time limit for this session is over. You may read limit value by calling GetSerialNumberData() function.
|
||||
/// </summary>
|
||||
RunningTimeOver = 0x00000010,
|
||||
/// <summary>
|
||||
/// Serial number is locked to another hardware identifier.
|
||||
/// </summary>
|
||||
BadHwid = 0x00000020,
|
||||
/// <summary>
|
||||
/// Serial number will not work with this version of application, because it has "Max Build Date" block and the application was
|
||||
/// build after those date. You may read maximal build date by calling GetSerialNumberData() function.
|
||||
/// </summary>
|
||||
MaxBuildExpired = 0x00000040,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Serial number contents
|
||||
/// </summary>
|
||||
public class SerialNumberData
|
||||
{
|
||||
/// <summary>
|
||||
/// Serial number status
|
||||
/// </summary>
|
||||
public SerialState State;
|
||||
|
||||
/// <summary>
|
||||
/// End user name
|
||||
/// </summary>
|
||||
public string UserName;
|
||||
|
||||
/// <summary>
|
||||
/// End user E-Mail
|
||||
/// </summary>
|
||||
public string EMail;
|
||||
|
||||
/// <summary>
|
||||
/// Serial number expiration date.
|
||||
/// </summary>
|
||||
public DateTime Expires;
|
||||
|
||||
/// <summary>
|
||||
/// Max date of build, that will accept this key
|
||||
/// </summary>
|
||||
public DateTime MaxBuild;
|
||||
|
||||
/// <summary>
|
||||
/// Running time in minutes
|
||||
/// </summary>
|
||||
public int RunningTime;
|
||||
|
||||
/// <summary>
|
||||
/// Up to 255 bytes of user data
|
||||
/// </summary>
|
||||
public byte[] UserData;
|
||||
|
||||
public SerialNumberData()
|
||||
{
|
||||
State = SerialState.Invalid;
|
||||
Expires = DateTime.MaxValue;
|
||||
MaxBuild = DateTime.MaxValue;
|
||||
RunningTime = 0;
|
||||
UserData = new byte[0];
|
||||
UserName = "";
|
||||
EMail = "";
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Activation API status codes
|
||||
/// </summary>
|
||||
public enum ActivationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Activation successful, the serial field contains a serial number.
|
||||
/// </summary>
|
||||
Ok,
|
||||
/// <summary>
|
||||
/// The activation module was unable to connect the Web License Manager.
|
||||
/// </summary>
|
||||
NoConnection,
|
||||
/// <summary>
|
||||
/// The server returned unexpected reply. This means configuration problems or probably a cracking attempt.
|
||||
/// </summary>
|
||||
BadReply,
|
||||
/// <summary>
|
||||
/// The activation code is blocked on the server. This doesn't mean that the number of possible activations is exceeded,
|
||||
/// this means that this exactly code is banned by the vendor, so the user is trying to cheat you.
|
||||
/// </summary>
|
||||
Banned,
|
||||
/// <summary>
|
||||
/// Something goes really wrong here. The error means that the internal activation stuff is not working,
|
||||
/// it is not safe to continue with the activation, registration and so on.
|
||||
/// </summary>
|
||||
Corrupted,
|
||||
/// <summary>
|
||||
/// The code has been successfully passed to the server and it was unable to find it in the database.
|
||||
/// Probably the user made a mistake, so it is worth asking the user to check the entered code for mistakes.
|
||||
/// </summary>
|
||||
BadCode,
|
||||
/// <summary>
|
||||
/// The code has been used too many times and cannot be used more. This doesn't mean the code is bad or banned, it is OK.
|
||||
/// The user may contact vendor to ask/purchase more activations, or the user may deactivate some installations to increase
|
||||
/// the number of activations available for that code.
|
||||
/// </summary>
|
||||
AlreadyUsed,
|
||||
/// <summary>
|
||||
/// This is the deactivation error code that means that the server can't find the serial number that the user tries to deactivate.
|
||||
/// </summary>
|
||||
SerialUnknown,
|
||||
/// <summary>
|
||||
/// The code is expired.
|
||||
/// </summary>
|
||||
Expired,
|
||||
/// <summary>
|
||||
/// Activation/deactivation features are not available.
|
||||
/// </summary>
|
||||
NotAvailable
|
||||
};
|
||||
|
||||
[Flags]
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
enum CoreOption
|
||||
{
|
||||
MEMORY_PROTECTION = 0x1,
|
||||
CHECK_DEBUGGER = 0x2
|
||||
}
|
||||
|
||||
public class Core
|
||||
{
|
||||
public static bool IsProtected() { return true; }
|
||||
public static bool IsDebuggerPresent(bool checkKernelMode)
|
||||
{
|
||||
if (GlobalData.IsDebuggerDetected())
|
||||
return true;
|
||||
|
||||
if (Debugger.IsAttached || Debugger.IsLogging())
|
||||
return true;
|
||||
|
||||
if (Win32.IsDebuggerPresent() || Win32.CheckRemoteDebuggerPresent())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool FindFirmwareVendor(byte[] data)
|
||||
{
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (i + 3 < data.Length && data[i + 0] == 'Q' && data[i + 1] == 'E' && data[i + 2] == 'M' && data[i + 3] == 'U')
|
||||
return true;
|
||||
if (i + 8 < data.Length && data[i + 0] == 'M' && data[i + 1] == 'i' && data[i + 2] == 'c' && data[i + 3] == 'r' && data[i + 4] == 'o' && data[i + 5] == 's' && data[i + 6] == 'o' && data[i + 7] == 'f' && data[i + 8] == 't')
|
||||
return true;
|
||||
if (i + 6 < data.Length && data[i + 0] == 'i' && data[i + 1] == 'n' && data[i + 2] == 'n' && data[i + 3] == 'o' && data[i + 4] == 't' && data[i + 5] == 'e' && data[i + 6] == 'k')
|
||||
return true;
|
||||
if (i + 9 < data.Length && data[i + 0] == 'V' && data[i + 1] == 'i' && data[i + 2] == 'r' && data[i + 3] == 't' && data[i + 4] == 'u' && data[i + 5] == 'a' && data[i + 6] == 'l' && data[i + 7] == 'B' && data[i + 8] == 'o' && data[i + 9] == 'x')
|
||||
return true;
|
||||
if (i + 5 < data.Length && data[i + 0] == 'V' && data[i + 1] == 'M' && data[i + 2] == 'w' && data[i + 3] == 'a' && data[i + 4] == 'r' && data[i + 5] == 'e')
|
||||
return true;
|
||||
if (i + 8 < data.Length && data[i + 0] == 'P' && data[i + 1] == 'a' && data[i + 2] == 'r' && data[i + 3] == 'a' && data[i + 4] == 'l' && data[i + 5] == 'l' && data[i + 6] == 'e' && data[i + 7] == 'l' && data[i + 8] == 's')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsVirtualMachinePresent()
|
||||
{
|
||||
var info = CpuId.Invoke(1);
|
||||
if (((info[2] >> 31) & 1) != 0)
|
||||
{
|
||||
// check Hyper-V root partition
|
||||
info = CpuId.Invoke(0x40000000);
|
||||
if (info[1] == 0x7263694d && info[2] == 0x666f736f && info[3] == 0x76482074) // "Microsoft Hv"
|
||||
{
|
||||
info = CpuId.Invoke(0x40000003);
|
||||
if ((info[1] & 1) != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size;
|
||||
uint tableSignature = (byte)'R' << 24 | (byte)'S' << 16 | (byte)'M' << 8 | (byte)'B';
|
||||
try
|
||||
{
|
||||
size = (int)Win32.EnumSystemFirmwareTables(tableSignature, IntPtr.Zero, 0);
|
||||
}
|
||||
catch (EntryPointNotFoundException) { size = 0; }
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
IntPtr nativeBuffer = Marshal.AllocHGlobal(size);
|
||||
Win32.EnumSystemFirmwareTables(tableSignature, nativeBuffer, (uint)size);
|
||||
byte[] buffer = new byte[size];
|
||||
Marshal.Copy(nativeBuffer, buffer, 0, size);
|
||||
Marshal.FreeHGlobal(nativeBuffer);
|
||||
for (var i = 0; i < size / sizeof(uint); i += sizeof(uint))
|
||||
{
|
||||
uint tableId = BitConverter.ToUInt32(buffer, i);
|
||||
int dataSize = (int)Win32.GetSystemFirmwareTable(tableSignature, tableId, IntPtr.Zero, 0);
|
||||
if (dataSize > 0)
|
||||
{
|
||||
nativeBuffer = Marshal.AllocHGlobal(dataSize);
|
||||
Win32.GetSystemFirmwareTable(tableSignature, tableId, nativeBuffer, (uint)dataSize);
|
||||
byte[] data = new byte[dataSize];
|
||||
Marshal.Copy(nativeBuffer, data, 0, dataSize);
|
||||
Marshal.FreeHGlobal(nativeBuffer);
|
||||
if (FindFirmwareVendor(data))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsValidImageCRC()
|
||||
{
|
||||
if (GlobalData.IsPatchDetected())
|
||||
return false;
|
||||
|
||||
long instance = Marshal.GetHINSTANCE(typeof(Core).Module).ToInt64();
|
||||
|
||||
// check memory CRC
|
||||
var crcSize = (uint)Marshal.ReadInt32(new IntPtr(instance + (uint)Faces.CRC_TABLE_SIZE));
|
||||
var crcPosition = (uint)Faces.CRC_TABLE_ENTRY;
|
||||
bool isValid = true;
|
||||
var crcInfo = new byte[12];
|
||||
var crc32 = new CRC32();
|
||||
var crcHash = (uint)Marshal.ReadInt32(new IntPtr(instance + (uint)Faces.CRC_TABLE_HASH));
|
||||
if (crcHash != crc32.Hash(new IntPtr(instance + crcPosition), crcSize))
|
||||
isValid = false;
|
||||
{
|
||||
var crcCryptor = new CRCValueCryptor();
|
||||
for (var i = 0; i < crcSize; i += crcInfo.Length)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
|
||||
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
|
||||
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
|
||||
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
|
||||
|
||||
if (crc32.Hash(new IntPtr(instance + address), size) != hash)
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check header and loader CRC
|
||||
crcSize = (uint)Marshal.ReadInt32(new IntPtr(instance + GlobalData.LoaderCrcSize()));
|
||||
crcPosition = GlobalData.LoaderCrcInfo();
|
||||
crcHash = (uint)Marshal.ReadInt32(new IntPtr(instance + GlobalData.LoaderCrcHash()));
|
||||
if (crcHash != crc32.Hash(new IntPtr(instance + crcPosition), crcSize))
|
||||
isValid = false;
|
||||
{
|
||||
var crcCryptor = new CRCValueCryptor();
|
||||
for (var i = 0; i < crcSize; i += crcInfo.Length)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
|
||||
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
|
||||
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
|
||||
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
|
||||
|
||||
if (crc32.Hash(new IntPtr(instance + address), size) != hash)
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
public static string DecryptString() { return DecryptString((uint)Faces.STORAGE_INFO); }
|
||||
public static bool FreeString(ref string value) { value = null; return true; }
|
||||
public static SerialState SetSerialNumber(string serial)
|
||||
{
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.SetSerialNumber(serial) : SerialState.Corrupted;
|
||||
}
|
||||
public static SerialState GetSerialNumberState()
|
||||
{
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.GetSerialNumberState() : SerialState.Corrupted;
|
||||
}
|
||||
public static bool GetSerialNumberData(out SerialNumberData data)
|
||||
{
|
||||
data = new SerialNumberData();
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.GetSerialNumberData(data) : false;
|
||||
}
|
||||
public static string GetCurrentHWID() { return Instance.HWID.ToString(); }
|
||||
public static ActivationStatus ActivateLicense(string code, out string serial)
|
||||
{
|
||||
serial = string.Empty;
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.ActivateLicense(code, out serial) : ActivationStatus.NotAvailable;
|
||||
}
|
||||
public static ActivationStatus DeactivateLicense(string serial)
|
||||
{
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.DeactivateLicense(serial) : ActivationStatus.NotAvailable;
|
||||
}
|
||||
public static ActivationStatus GetOfflineActivationString(string code, out string buf)
|
||||
{
|
||||
buf = string.Empty;
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.GetOfflineActivationString(code, out buf) : ActivationStatus.NotAvailable;
|
||||
}
|
||||
public static ActivationStatus GetOfflineDeactivationString(string serial, out string buf)
|
||||
{
|
||||
buf = string.Empty;
|
||||
LicensingManager licensing_manager = Instance.LicensingManager;
|
||||
return licensing_manager != null ? licensing_manager.GetOfflineDeactivationString(serial, out buf) : ActivationStatus.NotAvailable;
|
||||
}
|
||||
|
||||
public static readonly Core Instance = new Core();
|
||||
public HardwareID HWID { get; private set; }
|
||||
public StringManager StringManager { get; private set; }
|
||||
public LicensingManager LicensingManager { get; private set; }
|
||||
public ResourceManager ResourceManager { get; private set; }
|
||||
|
||||
private static string DecryptString(uint stringId) { return Instance.StringManager.DecryptString(stringId); }
|
||||
public static void ShowMessage(string message) { Win32.ShowMessage(message, Assembly.GetExecutingAssembly().GetName().Name, MessageBoxButtons.OK, MessageBoxIcon.Error); }
|
||||
|
||||
private static void AntidebugThread()
|
||||
{
|
||||
Win32.NtSetInformationThread(Win32.CurrentThread, Win32.THREADINFOCLASS.ThreadHideFromDebugger, IntPtr.Zero, 0);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Debugger.IsAttached || Debugger.IsLogging())
|
||||
Environment.FailFast("");
|
||||
|
||||
if (Win32.IsDebuggerPresent() || Win32.CheckRemoteDebuggerPresent())
|
||||
Environment.FailFast("");
|
||||
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Init(long instance)
|
||||
{
|
||||
var options = (uint)Faces.CORE_OPTIONS;
|
||||
if ((options & (uint)CoreOption.CHECK_DEBUGGER) != 0)
|
||||
{
|
||||
var thread = new Thread(AntidebugThread);
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
HWID = new HardwareID();
|
||||
|
||||
var pos = (uint)Faces.STRING_INFO;
|
||||
if (pos != 0)
|
||||
StringManager = new StringManager(instance);
|
||||
|
||||
pos = (uint)Faces.LICENSE_INFO;
|
||||
if (pos != 0)
|
||||
LicensingManager = new LicensingManager(instance);
|
||||
|
||||
pos = (uint)Faces.TRIAL_HWID;
|
||||
if (pos != 0) {
|
||||
var key = new byte[8];
|
||||
Marshal.Copy(new IntPtr(instance + (uint)Faces.KEY_INFO), key, 0, key.Length);
|
||||
|
||||
var entry = new byte[64];
|
||||
Marshal.Copy(new IntPtr(instance + pos), entry, 0, entry.Length);
|
||||
CipherRC5 cipher = new CipherRC5(key);
|
||||
entry = cipher.Decrypt(entry);
|
||||
|
||||
var value = new byte[(uint)Faces.TRIAL_HWID_SIZE];
|
||||
Array.Copy(entry, 0, value, 0, value.Length);
|
||||
|
||||
if (!HWID.IsCorrect(value))
|
||||
{
|
||||
ShowMessage("This application cannot be executed on this computer.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pos = (uint)Faces.RESOURCE_INFO;
|
||||
if (pos != 0)
|
||||
ResourceManager = new ResourceManager(instance);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static uint DecryptBuffer(uint p3, uint p2, uint p1, uint p0)
|
||||
{
|
||||
return Instance.LicensingManager.DecryptBuffer(p3, p2, p1, p0);
|
||||
}
|
||||
|
||||
#if !RUNTIME
|
||||
public readonly Random RndGenerator = new Random();
|
||||
|
||||
public uint Rand32()
|
||||
{
|
||||
var a4 = new byte[4];
|
||||
RndGenerator.NextBytes(a4);
|
||||
return BitConverter.ToUInt32(a4, 0);
|
||||
}
|
||||
|
||||
public ulong Rand64()
|
||||
{
|
||||
return (Rand32() << 32) | Rand32();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public class ResourceManager
|
||||
{
|
||||
public ResourceManager(long instance)
|
||||
{
|
||||
_instance = instance;
|
||||
var key = new byte[8];
|
||||
Marshal.Copy(new IntPtr(instance + (uint)Faces.KEY_INFO), key, 0, key.Length);
|
||||
_cipher = new CipherRC5(key);
|
||||
|
||||
var resourceInfo = new byte[16];
|
||||
var pos = (uint)Faces.RESOURCE_INFO;
|
||||
var buffer = new byte[1024];
|
||||
for (var i = 0; ;i += resourceInfo.Length)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + pos + i), resourceInfo, 0, resourceInfo.Length);
|
||||
byte[] entry = _cipher.Decrypt(resourceInfo);
|
||||
uint nameOffset = BitConverter.ToUInt32(entry, 0);
|
||||
if (nameOffset == 0)
|
||||
break;
|
||||
|
||||
for (var j = 0; j < buffer.Length / 2; j++)
|
||||
{
|
||||
var c = (ushort)(Marshal.ReadInt16(new IntPtr(instance + nameOffset + j * 2)) ^ (BitRotate.Left((uint)Faces.STRING_DECRYPT_KEY, j) + j));
|
||||
if (c == 0)
|
||||
{
|
||||
_entries.Add(Encoding.Unicode.GetString(buffer, 0, j * 2), (uint)(pos + i));
|
||||
break;
|
||||
}
|
||||
buffer[j * 2] = (byte)c;
|
||||
buffer[j * 2 + 1] = (byte)(c >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyResolve += Handler;
|
||||
}
|
||||
|
||||
private void DecryptData(ref byte[] data, uint key)
|
||||
{
|
||||
for (var c = 0; c < data.Length; c++)
|
||||
{
|
||||
data[c] = (byte)(data[c] ^ BitRotate.Left(key, c) + c);
|
||||
}
|
||||
}
|
||||
|
||||
private Assembly Handler(object sender, ResolveEventArgs args)
|
||||
{
|
||||
uint pos;
|
||||
if (_entries.TryGetValue(args.Name, out pos))
|
||||
{
|
||||
var resourceInfo = new byte[16];
|
||||
Marshal.Copy(new IntPtr(_instance + pos), resourceInfo, 0, resourceInfo.Length);
|
||||
byte[] entry = _cipher.Decrypt(resourceInfo);
|
||||
uint dataOffset = BitConverter.ToUInt32(entry, 4);
|
||||
var data = new byte[BitConverter.ToUInt32(entry, 8)];
|
||||
Marshal.Copy(new IntPtr(_instance + dataOffset), data, 0, data.Length);
|
||||
DecryptData(ref data, (uint)Faces.STRING_DECRYPT_KEY);
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.Load(data);
|
||||
return assembly;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private long _instance;
|
||||
private CipherRC5 _cipher;
|
||||
private readonly Dictionary<string, uint> _entries = new Dictionary<string, uint>();
|
||||
}
|
||||
}
|
87
runtime/VMProtect.Runtime/CpuId.cs
Normal file
87
runtime/VMProtect.Runtime/CpuId.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public static class CpuId
|
||||
{
|
||||
public static int[] Invoke(int level)
|
||||
{
|
||||
var codePointer = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
// compile
|
||||
byte[] codeBytes;
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
codeBytes = new byte[30];
|
||||
codeBytes[0] = 0x55; // push ebp
|
||||
codeBytes[1] = 0x8B; codeBytes[2] = 0xEC; // mov ebp,esp
|
||||
codeBytes[3] = 0x53; // push ebx
|
||||
codeBytes[4] = 0x57; // push edi
|
||||
codeBytes[5] = 0x8B; codeBytes[6] = 0x45; codeBytes[7] = 0x08; // mov eax, dword ptr [ebp+8] (move level into eax)
|
||||
codeBytes[8] = 0x0F; codeBytes[9] = 0xA2; // cpuid
|
||||
codeBytes[10] = 0x8B; codeBytes[11] = 0x7D; codeBytes[12] = 0x0C; // mov edi, dword ptr [ebp+12] (move address of buffer into edi)
|
||||
codeBytes[13] = 0x89; codeBytes[14] = 0x07; // mov dword ptr [edi+0], eax (write eax, ... to buffer)
|
||||
codeBytes[15] = 0x89; codeBytes[16] = 0x5F; codeBytes[17] = 0x04; // mov dword ptr [edi+4], ebx
|
||||
codeBytes[18] = 0x89; codeBytes[19] = 0x4F; codeBytes[20] = 0x08; // mov dword ptr [edi+8], ecx
|
||||
codeBytes[21] = 0x89; codeBytes[22] = 0x57; codeBytes[23] = 0x0C; // mov dword ptr [edi+12],edx
|
||||
codeBytes[24] = 0x5F; // pop edi
|
||||
codeBytes[25] = 0x5B; // pop ebx
|
||||
codeBytes[26] = 0x8B; codeBytes[27] = 0xE5; // mov esp,ebp
|
||||
codeBytes[28] = 0x5D; // pop ebp
|
||||
codeBytes[29] = 0xc3; // ret
|
||||
} else
|
||||
{
|
||||
codeBytes = new byte[26];
|
||||
codeBytes[0] = 0x53; // push rbx this gets clobbered by cpuid
|
||||
codeBytes[1] = 0x49; codeBytes[2] = 0x89; codeBytes[3] = 0xd0; // mov r8, rdx
|
||||
codeBytes[4] = 0x89; codeBytes[5] = 0xc8; // mov eax, ecx
|
||||
codeBytes[6] = 0x0F; codeBytes[7] = 0xA2; // cpuid
|
||||
codeBytes[8] = 0x41; codeBytes[9] = 0x89; codeBytes[10] = 0x40; codeBytes[11] = 0x00; // mov dword ptr [r8+0], eax
|
||||
codeBytes[12] = 0x41; codeBytes[13] = 0x89; codeBytes[14] = 0x58; codeBytes[15] = 0x04; // mov dword ptr [r8+4], ebx
|
||||
codeBytes[16] = 0x41; codeBytes[17] = 0x89; codeBytes[18] = 0x48; codeBytes[19] = 0x08; // mov dword ptr [r8+8], ecx
|
||||
codeBytes[20] = 0x41; codeBytes[21] = 0x89; codeBytes[22] = 0x50; codeBytes[23] = 0x0c; // mov dword ptr [r8+12], edx
|
||||
codeBytes[24] = 0x5b; // pop rbx
|
||||
codeBytes[25] = 0xc3; // ret
|
||||
}
|
||||
|
||||
codePointer = Win32.VirtualAlloc(
|
||||
IntPtr.Zero,
|
||||
new UIntPtr((uint)codeBytes.Length),
|
||||
Win32.AllocationType.Commit | Win32.AllocationType.Reserve,
|
||||
Win32.MemoryProtection.ExecuteReadWrite
|
||||
);
|
||||
|
||||
Marshal.Copy(codeBytes, 0, codePointer, codeBytes.Length);
|
||||
|
||||
var cpuIdDelg = (CpuIdDelegate)Marshal.GetDelegateForFunctionPointer(codePointer, typeof(CpuIdDelegate));
|
||||
|
||||
// invoke
|
||||
var buffer = new int[4];
|
||||
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
cpuIdDelg(level, buffer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (codePointer != IntPtr.Zero)
|
||||
{
|
||||
Win32.VirtualFree(codePointer, UIntPtr.Zero, Win32.FreeType.Release);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
|
||||
private delegate void CpuIdDelegate(int level, int []buffer);
|
||||
}
|
||||
}
|
195
runtime/VMProtect.Runtime/Crypto.cs
Normal file
195
runtime/VMProtect.Runtime/Crypto.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public class CipherRC5
|
||||
{
|
||||
private const int R = 15; // number of rounds
|
||||
private const int B = 8; // number of bytes in key
|
||||
private const int C = 8 * B / BitRotate.W; // 16 - number u32s in key = ceil(8*B/W)
|
||||
private const int T = 2 * (R + 1); // 34 - size of table _s = 2*(R+1) u32s
|
||||
|
||||
private readonly uint[] _s; // expanded key table
|
||||
|
||||
#if RUNTIME
|
||||
private const uint P = (uint)Faces.RC5_P;
|
||||
private const uint Q = (uint)Faces.RC5_Q;
|
||||
#else
|
||||
private static readonly uint P = Core.Instance.Rand32();
|
||||
private static readonly uint Q = Core.Instance.Rand32();
|
||||
|
||||
public static byte[] CreateRandomKey()
|
||||
{
|
||||
var ret = new byte[B];
|
||||
Core.Instance.RndGenerator.NextBytes(ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
public CipherRC5(byte[] key)
|
||||
{
|
||||
uint i, j, k, u = BitRotate.W / 8, a, b;
|
||||
var l = new uint[C];
|
||||
_s = new uint[T];
|
||||
|
||||
for (i = B - 1, l[C - 1] = 0; i != uint.MaxValue; i--)
|
||||
l[i / u] = (l[i / u] << 8) + key[i];
|
||||
|
||||
for (_s[0] = P, i = 1; i < T; i++)
|
||||
_s[i] = _s[i - 1] + Q;
|
||||
for (a = b = i = j = k = 0; k < 3 * T; k++, i = (i + 1) % T, j = (j + 1) % C) // 3*T > 3*C
|
||||
{
|
||||
a = _s[i] = BitRotate.Left(_s[i] + a + b, 3);
|
||||
b = l[j] = BitRotate.Left(l[j] + a + b, (int)(a + b));
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct Dword
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public ulong dw;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public uint w0;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public uint w1;
|
||||
}
|
||||
|
||||
private void Encrypt(ref Dword io)
|
||||
{
|
||||
uint i, a = io.w0 + _s[0], b = io.w1 + _s[1];
|
||||
for (i = 1; i <= R; i++)
|
||||
{
|
||||
a = BitRotate.Left(a ^ b, (int)b) + _s[2 * i];
|
||||
b = BitRotate.Left(b ^ a, (int)a) + _s[2 * i + 1];
|
||||
}
|
||||
io.w0 = a;
|
||||
io.w1 = b;
|
||||
}
|
||||
|
||||
private void Decrypt(ref Dword io)
|
||||
{
|
||||
uint i, b = io.w1, a = io.w0;
|
||||
for (i = R; i > 0; i--)
|
||||
{
|
||||
b = BitRotate.Right(b - _s[2 * i + 1], (int)a) ^ a;
|
||||
a = BitRotate.Right(a - _s[2 * i], (int)b) ^ b;
|
||||
}
|
||||
io.w1 = b - _s[1];
|
||||
io.w0 = a - _s[0];
|
||||
}
|
||||
|
||||
public byte[] Encrypt(byte[] ain)
|
||||
{
|
||||
var aout = new byte[ain.Length];
|
||||
Encrypt(ain, aout);
|
||||
return aout;
|
||||
}
|
||||
|
||||
public byte[] Decrypt(byte[] ain)
|
||||
{
|
||||
var aout = new byte[ain.Length];
|
||||
Decrypt(ain, aout);
|
||||
return aout;
|
||||
}
|
||||
|
||||
public void Encrypt(byte[] ain, byte[] aout)
|
||||
{
|
||||
var block = new Dword();
|
||||
for (var i = 0; i < ain.Length; i += 8)
|
||||
{
|
||||
block.dw = BitConverter.ToUInt64(ain, i);
|
||||
Encrypt(ref block);
|
||||
BitConverter.GetBytes(block.dw).CopyTo(aout, i);
|
||||
}
|
||||
}
|
||||
|
||||
public void Decrypt(byte[] ain, byte[] aout)
|
||||
{
|
||||
var block = new Dword();
|
||||
for (var i = 0; i < ain.Length; i += 8)
|
||||
{
|
||||
block.dw = BitConverter.ToUInt64(ain, i);
|
||||
Decrypt(ref block);
|
||||
BitConverter.GetBytes(block.dw).CopyTo(aout, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CRC32
|
||||
{
|
||||
static uint[] _table;
|
||||
|
||||
public CRC32()
|
||||
{
|
||||
if (_table == null)
|
||||
{
|
||||
_table = new uint[256];
|
||||
for (var i = 0; i < 256; i++)
|
||||
{
|
||||
var entry = (uint)i;
|
||||
for (var j = 0; j < 8; j++)
|
||||
if ((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ 0xedb88320u;
|
||||
else
|
||||
entry = entry >> 1;
|
||||
_table[i] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint Hash(IntPtr ptr, uint size)
|
||||
{
|
||||
uint crc = 0;
|
||||
for (var i = 0; i < size; i++)
|
||||
crc = _table[(Marshal.ReadByte(new IntPtr(ptr.ToInt64() + i)) ^ crc) & 0xff] ^ (crc >> 8);
|
||||
return ~crc;
|
||||
}
|
||||
}
|
||||
|
||||
public class CRCValueCryptor
|
||||
{
|
||||
private uint _key;
|
||||
public CRCValueCryptor()
|
||||
{
|
||||
_key = (uint)Faces.CRC_INFO_SALT;
|
||||
}
|
||||
|
||||
public uint Decrypt(uint value)
|
||||
{
|
||||
uint res = value ^ _key;
|
||||
_key = BitRotate.Left(_key, 7) ^ res;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public class BitRotate
|
||||
{
|
||||
public const int W = 32; // u32 size in bits
|
||||
public static uint Left(uint a, int offset)
|
||||
{
|
||||
var r1 = a << offset;
|
||||
var r2 = a >> (W - offset);
|
||||
return r1 | r2;
|
||||
}
|
||||
|
||||
public static uint Right(uint a, int offset)
|
||||
{
|
||||
var r1 = a >> offset;
|
||||
var r2 = a << (W - offset);
|
||||
return r1 | r2;
|
||||
}
|
||||
|
||||
public static uint Swap(uint value)
|
||||
{
|
||||
uint mask_xx_zz = (value & 0x00FF00FFU);
|
||||
uint mask_ww_yy = (value & 0xFF00FF00U);
|
||||
return ((mask_xx_zz >> 8) | (mask_xx_zz << 24)) +
|
||||
((mask_ww_yy << 8) | (mask_ww_yy >> 24));
|
||||
}
|
||||
}
|
||||
}
|
170
runtime/VMProtect.Runtime/Faces.cs
Normal file
170
runtime/VMProtect.Runtime/Faces.cs
Normal file
@ -0,0 +1,170 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
// ReSharper disable InconsistentNaming
|
||||
namespace VMProtect
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Enum)]
|
||||
public sealed class DeleteOnCompilation : Attribute { }
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
public enum Variables : uint
|
||||
{
|
||||
IS_PATCH_DETECTED,
|
||||
IS_DEBUGGER_DETECTED,
|
||||
LOADER_CRC_INFO,
|
||||
LOADER_CRC_INFO_SIZE,
|
||||
LOADER_CRC_INFO_HASH,
|
||||
SESSION_KEY,
|
||||
DRIVER_UNLOAD,
|
||||
CRC_IMAGE_SIZE,
|
||||
LOADER_STATUS,
|
||||
SERVER_DATE,
|
||||
RESERVED,
|
||||
CPU_COUNT,
|
||||
CPU_HASH,
|
||||
COUNT = CPU_HASH + 32
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
public enum Faces : uint
|
||||
{
|
||||
MASK = 0xFACE0000U,
|
||||
|
||||
RC5_P,
|
||||
RC5_Q,
|
||||
|
||||
STRING_INFO,
|
||||
RESOURCE_INFO,
|
||||
STORAGE_INFO,
|
||||
REGISTRY_INFO,
|
||||
LICENSE_INFO,
|
||||
LICENSE_INFO_SIZE,
|
||||
KEY_INFO,
|
||||
RUNTIME_ENTRY,
|
||||
CRC_INFO_SALT,
|
||||
CRC_TABLE_ENTRY,
|
||||
CRC_TABLE_SIZE,
|
||||
CRC_TABLE_HASH,
|
||||
TRIAL_HWID,
|
||||
TRIAL_HWID_SIZE,
|
||||
CORE_OPTIONS,
|
||||
IMAGE_BASE,
|
||||
FILE_BASE,
|
||||
|
||||
NTOSKRNL_NAME,
|
||||
HAL_NAME,
|
||||
USER32_NAME,
|
||||
MESSAGE_BOX_NAME,
|
||||
KERNEL32_NAME,
|
||||
CREATE_FILE_NAME,
|
||||
CLOSE_HANDLE_NAME,
|
||||
INITIALIZATION_ERROR,
|
||||
PROC_NOT_FOUND,
|
||||
ORDINAL_NOT_FOUND,
|
||||
STRING_DECRYPT_KEY,
|
||||
DRIVER_FORMAT_VALUE,
|
||||
FILE_CORRUPTED,
|
||||
LOADER_OPTIONS,
|
||||
LOADER_DATA,
|
||||
DEBUGGER_FOUND,
|
||||
NT_SET_INFORMATION_PROCESS_NAME,
|
||||
NT_RAISE_HARD_ERROR_NAME,
|
||||
IS_WOW64_PROCESS_NAME,
|
||||
WINE_GET_VERSION_NAME,
|
||||
MACOSX_FORMAT_VALUE,
|
||||
GNU_PTRACE,
|
||||
UNREGISTERED_VERSION,
|
||||
WTSAPI32_NAME,
|
||||
WTS_SEND_MESSAGE_NAME,
|
||||
NTDLL_NAME,
|
||||
NT_QUERY_INFORMATION_NAME,
|
||||
NT_SET_INFORMATION_THREAD_NAME,
|
||||
SICE_NAME,
|
||||
SIWVID_NAME,
|
||||
NTICE_NAME,
|
||||
ICEEXT_NAME,
|
||||
SYSER_NAME,
|
||||
VIRTUAL_MACHINE_FOUND,
|
||||
SBIEDLL_NAME,
|
||||
QUERY_VIRTUAL_MEMORY_NAME,
|
||||
ENUM_SYSTEM_FIRMWARE_NAME,
|
||||
GET_SYSTEM_FIRMWARE_NAME,
|
||||
NT_QUERY_INFORMATION_PROCESS_NAME,
|
||||
NT_VIRTUAL_PROTECT_NAME,
|
||||
NT_OPEN_FILE_NAME,
|
||||
NT_CREATE_SECTION_NAME,
|
||||
NT_OPEN_SECTION_NAME,
|
||||
NT_MAP_VIEW_OF_SECTION,
|
||||
NT_UNMAP_VIEW_OF_SECTION,
|
||||
NT_CLOSE,
|
||||
SYSCALL,
|
||||
NT_ALLOCATE_VIRTUAL_MEMORY_NAME,
|
||||
NT_FREE_VIRTUAL_MEMORY_NAME,
|
||||
|
||||
PACKER_INFO = 0xFACE0100U,
|
||||
PACKER_INFO_SIZE,
|
||||
FILE_CRC_INFO,
|
||||
FILE_CRC_INFO_SIZE,
|
||||
LOADER_CRC_INFO,
|
||||
LOADER_CRC_INFO_SIZE,
|
||||
SECTION_INFO,
|
||||
SECTION_INFO_SIZE,
|
||||
FIXUP_INFO,
|
||||
FIXUP_INFO_SIZE,
|
||||
RELOCATION_INFO,
|
||||
RELOCATION_INFO_SIZE,
|
||||
IAT_INFO,
|
||||
IAT_INFO_SIZE,
|
||||
IMPORT_INFO,
|
||||
IMPORT_INFO_SIZE,
|
||||
INTERNAL_IMPORT_INFO,
|
||||
INTERNAL_IMPORT_INFO_SIZE,
|
||||
MEMORY_CRC_INFO,
|
||||
MEMORY_CRC_INFO_SIZE,
|
||||
DELAY_IMPORT_INFO,
|
||||
DELAY_IMPORT_INFO_SIZE,
|
||||
LOADER_CRC_INFO_HASH,
|
||||
MEMORY_CRC_INFO_HASH,
|
||||
TLS_INDEX_INFO,
|
||||
|
||||
VAR = 0xFACE0200U,
|
||||
VAR_IS_PATCH_DETECTED = VAR | (Variables.IS_PATCH_DETECTED << 4),
|
||||
VAR_IS_DEBUGGER_DETECTED = VAR | (Variables.IS_DEBUGGER_DETECTED << 4),
|
||||
VAR_LOADER_CRC_INFO = VAR | (Variables.LOADER_CRC_INFO << 4),
|
||||
VAR_LOADER_CRC_INFO_SIZE = VAR | (Variables.LOADER_CRC_INFO_SIZE << 4),
|
||||
VAR_LOADER_CRC_INFO_HASH = VAR | (Variables.LOADER_CRC_INFO_HASH << 4),
|
||||
VAR_SESSION_KEY = VAR | (Variables.SESSION_KEY << 4),
|
||||
VAR_LOADER_STATUS = VAR | (Variables.LOADER_STATUS << 4),
|
||||
VAR_SERVER_DATE = VAR | (Variables.SERVER_DATE << 4),
|
||||
|
||||
VAR_SALT = 0xFACE0300U,
|
||||
VAR_IS_PATCH_DETECTED_SALT = VAR_SALT | Variables.IS_PATCH_DETECTED,
|
||||
VAR_IS_DEBUGGER_DETECTED_SALT = VAR_SALT | Variables.IS_DEBUGGER_DETECTED,
|
||||
VAR_LOADER_CRC_INFO_SALT = VAR_SALT | Variables.LOADER_CRC_INFO,
|
||||
VAR_LOADER_CRC_INFO_SIZE_SALT = VAR_SALT | Variables.LOADER_CRC_INFO_SIZE,
|
||||
VAR_LOADER_CRC_INFO_HASH_SALT = VAR_SALT | Variables.LOADER_CRC_INFO_HASH,
|
||||
VAR_SERVER_DATE_SALT = VAR_SALT | Variables.SERVER_DATE,
|
||||
}
|
||||
|
||||
public static class GlobalData
|
||||
{
|
||||
private static uint[] _v = new uint[(uint)Variables.COUNT];
|
||||
public static bool IsPatchDetected() { return (_v[(uint)Faces.VAR_IS_PATCH_DETECTED] ^ (uint)Faces.VAR_IS_PATCH_DETECTED_SALT) != 0; }
|
||||
public static bool IsDebuggerDetected() { return (_v[(uint)Faces.VAR_IS_DEBUGGER_DETECTED] ^ (uint)Faces.VAR_IS_DEBUGGER_DETECTED_SALT) != 0; }
|
||||
public static uint LoaderCrcInfo() { return _v[(uint)Faces.VAR_LOADER_CRC_INFO] ^ (uint)Faces.VAR_LOADER_CRC_INFO_SALT; }
|
||||
public static uint LoaderCrcSize() { return _v[(uint)Faces.VAR_LOADER_CRC_INFO_SIZE] ^ (uint)Faces.VAR_LOADER_CRC_INFO_SIZE_SALT; }
|
||||
public static uint LoaderCrcHash() { return _v[(uint)Faces.VAR_LOADER_CRC_INFO_HASH] ^ (uint)Faces.VAR_LOADER_CRC_INFO_HASH_SALT; }
|
||||
public static uint SessionKey() { return _v[(uint)Faces.VAR_SESSION_KEY]; }
|
||||
public static uint LoaderStatus() { return _v[(uint)Faces.VAR_LOADER_STATUS]; }
|
||||
public static uint ServerDate() { return _v[(uint)Faces.VAR_SERVER_DATE] ^ (uint)Faces.VAR_SERVER_DATE_SALT; }
|
||||
public static void SetIsPatchDetected(bool value) { _v[(uint)Faces.VAR_IS_PATCH_DETECTED] = (uint)(value ? 1 : 0) ^ (uint)Faces.VAR_IS_PATCH_DETECTED_SALT; }
|
||||
public static void SetIsDebuggerDetected(bool value) { _v[(uint)Faces.VAR_IS_DEBUGGER_DETECTED] = (uint)(value ? 1 : 0) ^ (uint)Faces.VAR_IS_DEBUGGER_DETECTED_SALT; }
|
||||
public static void SetLoaderCrcInfo(uint value) { _v[(uint)Faces.VAR_LOADER_CRC_INFO] = value ^ (uint)Faces.VAR_LOADER_CRC_INFO_SALT; }
|
||||
public static void SetLoaderCrcSize(uint value) { _v[(uint)Faces.VAR_LOADER_CRC_INFO_SIZE] = value ^ (uint)Faces.VAR_LOADER_CRC_INFO_SIZE_SALT; }
|
||||
public static void SetLoaderCrcHash(uint value) { _v[(uint)Faces.VAR_LOADER_CRC_INFO_HASH] = value ^ (uint)Faces.VAR_LOADER_CRC_INFO_HASH_SALT; }
|
||||
public static void SetSessionKey(uint value) { _v[(uint)Faces.VAR_SESSION_KEY] = value; }
|
||||
public static void SetLoaderStatus(uint value) { _v[(uint)Faces.VAR_LOADER_STATUS] = value; }
|
||||
public static void SetServerDate(uint value) { _v[(uint)Faces.VAR_SERVER_DATE] = value ^ (uint)Faces.VAR_SERVER_DATE_SALT; }
|
||||
}
|
||||
}
|
266
runtime/VMProtect.Runtime/HardwareID.cs
Normal file
266
runtime/VMProtect.Runtime/HardwareID.cs
Normal file
@ -0,0 +1,266 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public class HardwareID
|
||||
{
|
||||
private const int OldMethodBlocks = 8;
|
||||
private const int MaxBlocks = 16 + OldMethodBlocks;
|
||||
private const uint TypeMask = 3;
|
||||
|
||||
private enum BlockType {
|
||||
Cpu,
|
||||
Host,
|
||||
Mac,
|
||||
Hdd
|
||||
};
|
||||
|
||||
private readonly int _startBlock;
|
||||
private readonly List<uint> _blocks = new List<uint>();
|
||||
|
||||
public HardwareID()
|
||||
{
|
||||
// old methods
|
||||
GetCpu(0);
|
||||
GetCpu(1);
|
||||
_startBlock = _blocks.Count;
|
||||
// new methods, we'll return HWID starting from this DWORD
|
||||
GetCpu(2);
|
||||
GetMachineName();
|
||||
GetHdd();
|
||||
GetMacAddresses();
|
||||
}
|
||||
|
||||
private void AddBlock(byte[] p, BlockType type)
|
||||
{
|
||||
if (_blocks.Count == MaxBlocks) return; // no free space
|
||||
if (p.Length == 0) return;
|
||||
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var h = hash.ComputeHash(p);
|
||||
var block = (uint)((h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]);
|
||||
block &= ~TypeMask; // zero two lower bits
|
||||
block |= (uint)type & TypeMask; // set type bits
|
||||
|
||||
// check existing blocks
|
||||
for (var i = _blocks.Count; i > _startBlock; i--) {
|
||||
var prevBlock = _blocks[i - 1];
|
||||
if (prevBlock == block)
|
||||
return;
|
||||
if ((prevBlock & TypeMask) != (block & TypeMask))
|
||||
break;
|
||||
}
|
||||
|
||||
_blocks.Add(block);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetCpu(int method)
|
||||
{
|
||||
//TODO: foreach cpu:
|
||||
var info = CpuId.Invoke(1);
|
||||
if ((info[0] & 0xFF0) == 0xFE0)
|
||||
info[0] ^= 0x20; // fix Athlon bug
|
||||
info[1] &= 0x00FFFFFF; // mask out APIC Physical ID
|
||||
|
||||
if (method == 2) {
|
||||
info[2] = 0;
|
||||
} else if (method == 1) {
|
||||
info[2] &= ~(1 << 27);
|
||||
}
|
||||
|
||||
var infob = new byte[16];
|
||||
Buffer.BlockCopy(info, 0, infob, 0, infob.Length);
|
||||
AddBlock(infob, BlockType.Cpu);
|
||||
}
|
||||
|
||||
private void GetMachineName()
|
||||
{
|
||||
try
|
||||
{
|
||||
var hn = Encoding.Unicode.GetBytes(Dns.GetHostName().ToUpperInvariant());
|
||||
AddBlock(hn, BlockType.Host);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessMac(byte[] p)
|
||||
{
|
||||
// this big IF construction allows to put constants to the code, not to the data segment
|
||||
// it is harder to find them in the code after virtualisation
|
||||
var dw = (p[0] << 16) + (p[1] << 8) + p[2];
|
||||
if (dw == 0x000569 || dw == 0x000C29 || dw == 0x001C14 || dw == 0x005056 || // vmware
|
||||
dw == 0x0003FF || dw == 0x000D3A || dw == 0x00125A || dw == 0x00155D || dw == 0x0017FA || dw == 0x001DD8 || dw == 0x002248 || dw == 0x0025AE || dw == 0x0050F2 || // microsoft
|
||||
dw == 0x001C42 || // parallels
|
||||
dw == 0x0021F6) // virtual iron
|
||||
return;
|
||||
|
||||
AddBlock(p, BlockType.Mac);
|
||||
}
|
||||
|
||||
private void GetMacAddresses()
|
||||
{
|
||||
var blockCountNoMac = _blocks.Count;
|
||||
byte[] paBytes = null;
|
||||
foreach (var nic in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if(nic.NetworkInterfaceType != NetworkInterfaceType.Ethernet)
|
||||
continue;
|
||||
paBytes = nic.GetPhysicalAddress().GetAddressBytes();
|
||||
if (paBytes.Length >= 3)
|
||||
ProcessMac(paBytes);
|
||||
}
|
||||
if (blockCountNoMac == _blocks.Count && paBytes != null && paBytes.Length >= 3)
|
||||
AddBlock(paBytes, BlockType.Mac);
|
||||
}
|
||||
|
||||
private void GetHdd()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (Environment.OSVersion.Platform)
|
||||
{
|
||||
case PlatformID.MacOSX:
|
||||
//TODO
|
||||
/*
|
||||
DASessionRef session = DASessionCreate(NULL);
|
||||
if (session) {
|
||||
struct statfs statFS;
|
||||
statfs ("/", &statFS);
|
||||
DADiskRef disk = DADiskCreateFromBSDName(NULL, session, statFS.f_mntfromname);
|
||||
if (disk) {
|
||||
CFDictionaryRef descDict = DADiskCopyDescription(disk);
|
||||
if (descDict) {
|
||||
CFUUIDRef value = (CFUUIDRef)CFDictionaryGetValue(descDict, CFSTR("DAVolumeUUID"));
|
||||
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(value);
|
||||
AddBlock(&bytes, sizeof(bytes), BLOCK_HDD);
|
||||
CFRelease(descDict);
|
||||
}
|
||||
CFRelease(disk);
|
||||
}
|
||||
CFRelease(session);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case PlatformID.Unix:
|
||||
//TODO: нет ли здесь лишних дисков?
|
||||
var rootUuids = new DirectoryInfo ("/dev/disk/by-uuid");
|
||||
var uuids = new StringBuilder();
|
||||
foreach (var f in rootUuids.GetFiles("*"))
|
||||
{
|
||||
uuids.Append(f.Name);
|
||||
}
|
||||
if(uuids.Length > 0)
|
||||
AddBlock(Encoding.UTF8.GetBytes(uuids.ToString()), BlockType.Hdd);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* mono for windows: unimplemented
|
||||
*
|
||||
* var moType = Assembly.Load("System.Management, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a").
|
||||
GetType("System.Management.ManagementObject");
|
||||
var disk = Activator.CreateInstance(moType,
|
||||
BindingFlags.CreateInstance, null,
|
||||
new object[] { string.Format("Win32_LogicalDisk.DeviceID='{0}:'", Environment.SystemDirectory[0]) },
|
||||
CultureInfo.InvariantCulture);
|
||||
var props = moType.InvokeMember("Properties", BindingFlags.GetProperty, null, disk, null);
|
||||
var sn = props.GetType().GetMethod("get_Item").Invoke(props, new object[] { "volumeSerialNumber" });
|
||||
var snv = sn.GetType().GetMethod("get_Value").Invoke(sn, null).ToString();
|
||||
Console.WriteLine("GetHdd volumeSerialNumber = {0}", snv);
|
||||
var bytes = BitConverter.GetBytes(Convert.ToUInt32(snv, 16));*/
|
||||
|
||||
var driveLetter = Path.GetPathRoot(Environment.SystemDirectory);
|
||||
uint serialNumber = 0;
|
||||
uint maxComponentLength = 0, fileSystemFlags = 0;
|
||||
if (Win32.GetVolumeInformation(driveLetter, null,
|
||||
0, ref serialNumber, ref maxComponentLength,
|
||||
ref fileSystemFlags, null, 0) && serialNumber != 0)
|
||||
{
|
||||
AddBlock(BitConverter.GetBytes(serialNumber), BlockType.Hdd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
for (var i = _startBlock; i < _blocks.Count; i++)
|
||||
{
|
||||
ms.Write(BitConverter.GetBytes(_blocks[i]), 0, 4);
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Convert.ToBase64String(GetBytes());
|
||||
}
|
||||
|
||||
public bool IsCorrect(byte[] p)
|
||||
{
|
||||
if (p.Length == 0 || (p.Length & 3) != 0)
|
||||
return false;
|
||||
|
||||
var equals = new bool[4];
|
||||
var found = new bool[4];
|
||||
|
||||
foreach (var id1 in _blocks)
|
||||
{
|
||||
found[id1 & 3] = true;
|
||||
for (var i = 0; i < p.Length; i += 4) {
|
||||
var id2 = BitConverter.ToUInt32(p, i);
|
||||
if (id1 == id2) {
|
||||
equals[id1 & 3] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1. check CPU
|
||||
if (!equals[0])
|
||||
return false;
|
||||
|
||||
// 2. check if at least 2 of 3 items are OK
|
||||
var n = 0;
|
||||
var c = 0;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (found[i])
|
||||
c++;
|
||||
if (equals[i])
|
||||
n++;
|
||||
}
|
||||
return n == c || n >= 3;
|
||||
}
|
||||
|
||||
/*public bool IsCorrect(CryptoContainer &cont, size_t offset, size_t size)
|
||||
{
|
||||
if (size == 0 || (size & 3) || size > MAX_BLOCKS * sizeof(uint32_t))
|
||||
return false;
|
||||
|
||||
uint32_t buff[MAX_BLOCKS];
|
||||
for (size_t i = 0; i < size / sizeof(uint32_t); i++) {
|
||||
buff[i] = cont.GetDWord(offset + i * sizeof(uint32_t));
|
||||
}
|
||||
return IsCorrect(reinterpret_cast<uint8_t *>(buff), size);
|
||||
}*/
|
||||
}
|
||||
}
|
664
runtime/VMProtect.Runtime/LicensingManager.cs
Normal file
664
runtime/VMProtect.Runtime/LicensingManager.cs
Normal file
@ -0,0 +1,664 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Cache;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Numerics;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public class LicensingManager
|
||||
{
|
||||
public class BaseRequest
|
||||
{
|
||||
protected bool BuildUrl(byte[] licenseData)
|
||||
{
|
||||
var urlSize = BitConverter.ToInt32(licenseData, (int)Fields.ActivationUrlSize * sizeof(uint));
|
||||
if (urlSize == 0)
|
||||
return false;
|
||||
|
||||
var urlOffset = BitConverter.ToInt32(licenseData, (int)Fields.ActivationUrlOffset * sizeof(uint));
|
||||
Url = Encoding.UTF8.GetString(licenseData, urlOffset, urlSize);
|
||||
if (Url[Url.Length - 1] != '/')
|
||||
Url += '/';
|
||||
return true;
|
||||
}
|
||||
protected void EncodeUrl()
|
||||
{
|
||||
Url = Convert.ToBase64String(Encoding.UTF8.GetBytes(Url));
|
||||
}
|
||||
protected void AppendUrlParam(string param, string value)
|
||||
{
|
||||
AppendUrl(param, false);
|
||||
AppendUrl(value, true);
|
||||
}
|
||||
private void AppendUrl(string str, bool escape)
|
||||
{
|
||||
if (escape)
|
||||
{
|
||||
var sb = new StringBuilder(Url);
|
||||
foreach (var c in str)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '+':
|
||||
sb.Append("%2B");
|
||||
break;
|
||||
case '/':
|
||||
sb.Append("%2F");
|
||||
break;
|
||||
case '=':
|
||||
sb.Append("%3D");
|
||||
break;
|
||||
default:
|
||||
sb.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Url = sb.ToString();
|
||||
} else
|
||||
{
|
||||
Url += str;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Send()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback +=
|
||||
(sender, certificate, chain, sslPolicyErrors) => true;
|
||||
wc.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
|
||||
wc.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
|
||||
Response = wc.DownloadString(Url);
|
||||
try
|
||||
{
|
||||
var strDt = wc.ResponseHeaders.Get("Date");
|
||||
var dt = DateTime.ParseExact(strDt, "ddd, dd MMM yyyy HH:mm:ss 'GMT'",
|
||||
CultureInfo.InvariantCulture.DateTimeFormat, DateTimeStyles.AssumeUniversal);
|
||||
GlobalData.SetServerDate((uint)((dt.Year << 16) + (dt.Month << 8) + dt.Day));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//не смогли вытащить дату из заголовков - прощаем?
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Url { get; private set; }
|
||||
public string Response { get; private set; }
|
||||
}
|
||||
|
||||
public class ActivationRequest : BaseRequest
|
||||
{
|
||||
public ActivationStatus Process(byte[] licenseData, string code, bool offline)
|
||||
{
|
||||
if (!VerifyCode(code))
|
||||
return ActivationStatus.BadCode;
|
||||
|
||||
if (!BuildUrl(licenseData, code, offline))
|
||||
return ActivationStatus.NotAvailable;
|
||||
|
||||
if (offline)
|
||||
return ActivationStatus.Ok;
|
||||
|
||||
if (!Send())
|
||||
return ActivationStatus.NoConnection;
|
||||
|
||||
var res = Response;
|
||||
if (string.IsNullOrEmpty(res))
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
// possible answers: OK, BAD, BANNED, USED, EXPIRED
|
||||
// if OK - see the Serial number below
|
||||
|
||||
if (res == "BAD")
|
||||
return ActivationStatus.BadCode;
|
||||
|
||||
if (res == "BANNED")
|
||||
return ActivationStatus.Banned;
|
||||
|
||||
if (res == "USED")
|
||||
return ActivationStatus.AlreadyUsed;
|
||||
|
||||
if (res == "EXPIRED")
|
||||
return ActivationStatus.Expired;
|
||||
|
||||
var crPos = res.IndexOf('\n');
|
||||
if (crPos != 2)
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
if (res[0] != 'O' || res[1] != 'K')
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
if (res.Length - 3 < 64)
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
Serial = res.Substring(3);
|
||||
return ActivationStatus.Ok;
|
||||
}
|
||||
public string Serial
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
private bool VerifyCode(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code) || code.Length > 32)
|
||||
return false;
|
||||
return code.ToLower().TrimEnd("0123456789abcdefghijklmnopqrstuvwxyz-".ToCharArray()).Length == 0;
|
||||
}
|
||||
private bool BuildUrl(byte[] licenseData, string code, bool offline)
|
||||
{
|
||||
if (!offline) {
|
||||
if (!base.BuildUrl(licenseData))
|
||||
return false;
|
||||
}
|
||||
|
||||
// hwid -> base64
|
||||
var hwid = Convert.ToBase64String(Core.Instance.HWID.GetBytes());
|
||||
|
||||
// hash -> base64
|
||||
var modSize = BitConverter.ToInt32(licenseData, (int)Fields.ModulusSize * sizeof(uint));
|
||||
var modOffset = BitConverter.ToInt32(licenseData, (int)Fields.ModulusOffset * sizeof(uint));
|
||||
using (var sha = new SHA1Managed())
|
||||
{
|
||||
var modulus = sha.ComputeHash(licenseData, modOffset, modSize);
|
||||
var hash = Convert.ToBase64String(modulus, 0, 20);
|
||||
|
||||
// build Url
|
||||
AppendUrlParam(offline ? "type=activation&code=" : "activation.php?code=", code);
|
||||
AppendUrlParam("&hwid=", hwid);
|
||||
AppendUrlParam("&hash=", hash);
|
||||
}
|
||||
|
||||
if (offline)
|
||||
EncodeUrl();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class DeactivationRequest : BaseRequest
|
||||
{
|
||||
public ActivationStatus Process(byte[] licenseData, string serial, bool offline)
|
||||
{
|
||||
if (!VerifySerial(serial))
|
||||
return ActivationStatus.BadCode;
|
||||
|
||||
if (!BuildUrl(licenseData, serial, offline))
|
||||
return ActivationStatus.NotAvailable;
|
||||
|
||||
if (offline)
|
||||
return ActivationStatus.Ok;
|
||||
|
||||
if (!Send())
|
||||
return ActivationStatus.NoConnection;
|
||||
|
||||
var res = Response;
|
||||
if (string.IsNullOrEmpty(res))
|
||||
return ActivationStatus.BadReply;
|
||||
|
||||
if (res == "OK")
|
||||
return ActivationStatus.Ok;
|
||||
|
||||
if (res == "ERROR")
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
if (res == "UNKNOWN")
|
||||
return ActivationStatus.SerialUnknown;
|
||||
|
||||
return ActivationStatus.BadReply;
|
||||
}
|
||||
|
||||
private bool VerifySerial(string serial)
|
||||
{
|
||||
return !string.IsNullOrEmpty(serial);
|
||||
}
|
||||
|
||||
private bool BuildUrl(byte[] licenseData, string serial, bool offline)
|
||||
{
|
||||
if (!offline) {
|
||||
if (!base.BuildUrl(licenseData))
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var serialBytes = Convert.FromBase64String(serial);
|
||||
using (var sha = new SHA1Managed())
|
||||
{
|
||||
var serialHash = sha.ComputeHash(serialBytes);
|
||||
var hash = Convert.ToBase64String(serialHash, 0, 20);
|
||||
|
||||
AppendUrlParam(offline ? "type=deactivation&hash=" : "deactivation.php?hash=", hash);
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offline)
|
||||
EncodeUrl();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public LicensingManager(long instance)
|
||||
{
|
||||
_sessionKey = 0 - GlobalData.SessionKey();
|
||||
_licenseData = new byte[(uint)Faces.LICENSE_INFO_SIZE];
|
||||
Marshal.Copy(new IntPtr(instance + (uint)Faces.LICENSE_INFO), _licenseData, 0, _licenseData.Length);
|
||||
_startTickCount = Environment.TickCount;
|
||||
}
|
||||
public LicensingManager(byte [] licenseData)
|
||||
{
|
||||
_licenseData = licenseData;
|
||||
}
|
||||
public SerialState GetSerialNumberState()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return (_state & (SerialState.Corrupted | SerialState.Invalid | SerialState.BadHwid | SerialState.Blacklisted)) != 0 ? _state : ParseSerial(null);
|
||||
}
|
||||
}
|
||||
public ActivationStatus ActivateLicense(string code, out string serial)
|
||||
{
|
||||
serial = string.Empty;
|
||||
if (!CheckLicenseDataCRC())
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
var request = new ActivationRequest();
|
||||
var res = request.Process(_licenseData, code, false);
|
||||
if (res == ActivationStatus.Ok)
|
||||
{
|
||||
serial = request.Serial;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public ActivationStatus DeactivateLicense(string serial)
|
||||
{
|
||||
return CheckLicenseDataCRC() ?
|
||||
new DeactivationRequest().Process(_licenseData, serial, false) :
|
||||
ActivationStatus.Corrupted;
|
||||
}
|
||||
|
||||
public ActivationStatus GetOfflineActivationString(string code, out string buf)
|
||||
{
|
||||
buf = string.Empty;
|
||||
if (!CheckLicenseDataCRC())
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
var request = new ActivationRequest();
|
||||
var res = request.Process(_licenseData, code, true);
|
||||
if (res == ActivationStatus.Ok)
|
||||
{
|
||||
buf = request.Url;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public ActivationStatus GetOfflineDeactivationString(string serial, out string buf)
|
||||
{
|
||||
buf = string.Empty;
|
||||
if (!CheckLicenseDataCRC())
|
||||
return ActivationStatus.Corrupted;
|
||||
|
||||
var request = new DeactivationRequest();
|
||||
var res = request.Process(_licenseData, serial, true);
|
||||
if (res == ActivationStatus.Ok)
|
||||
{
|
||||
buf = request.Url;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static BigInteger B2Bi(byte[] b) //reverse & make positive
|
||||
{
|
||||
Array.Reverse(b);
|
||||
var b2 = new byte[b.Length + 1];
|
||||
Array.Copy(b, b2, b.Length);
|
||||
return new BigInteger(b2);
|
||||
}
|
||||
|
||||
public SerialState SetSerialNumber(string serial)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
SaveState(SerialState.Invalid);
|
||||
|
||||
if (string.IsNullOrEmpty(serial))
|
||||
return SerialState.Invalid; // the key is empty
|
||||
|
||||
// decode serial number from base64
|
||||
byte[] binarySerial;
|
||||
try
|
||||
{
|
||||
binarySerial = Convert.FromBase64String(serial);
|
||||
if (binarySerial.Length < 16)
|
||||
return SerialState.Invalid;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return SerialState.Invalid;
|
||||
}
|
||||
|
||||
// check license data integrity
|
||||
if (!CheckLicenseDataCRC()) {
|
||||
return SaveState(SerialState.Corrupted);
|
||||
}
|
||||
|
||||
// check serial by black list
|
||||
var blackListSize = BitConverter.ToInt32(_licenseData, (int)Fields.BlacklistSize * sizeof(uint));
|
||||
if (blackListSize != 0) {
|
||||
var blackListOffset = BitConverter.ToInt32(_licenseData, (int)Fields.BlacklistOffset * sizeof(uint));
|
||||
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var p = hash.ComputeHash(binarySerial);
|
||||
int min = 0;
|
||||
int max = blackListSize / 20 - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int i = (min + max) / 2;
|
||||
var blocked = true;
|
||||
for (var j = 0; j < 20 / sizeof(uint); j++) {
|
||||
var dw = BitConverter.ToUInt32(_licenseData, blackListOffset + i * 20 + j * sizeof(uint));
|
||||
var v = BitConverter.ToUInt32(p, j * sizeof(uint));
|
||||
if (dw == v)
|
||||
continue;
|
||||
|
||||
if (BitRotate.Swap(dw) > BitRotate.Swap(v))
|
||||
{
|
||||
max = i - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = i + 1;
|
||||
}
|
||||
blocked = false;
|
||||
break;
|
||||
}
|
||||
if (blocked) {
|
||||
return SaveState(SerialState.Blacklisted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// decode serial number
|
||||
var ebytes = new byte[BitConverter.ToInt32(_licenseData, (int)Fields.PublicExpSize * sizeof(uint))];
|
||||
Array.Copy(_licenseData, BitConverter.ToInt32(_licenseData, (int)Fields.PublicExpOffset * sizeof(uint)), ebytes, 0, ebytes.Length);
|
||||
var e = B2Bi(ebytes);
|
||||
var nbytes = new byte[BitConverter.ToInt32(_licenseData, (int)Fields.ModulusSize * sizeof(uint))];
|
||||
Array.Copy(_licenseData, BitConverter.ToInt32(_licenseData, (int)Fields.ModulusOffset * sizeof(uint)), nbytes, 0, nbytes.Length);
|
||||
var n = B2Bi(nbytes);
|
||||
var x = B2Bi(binarySerial);
|
||||
|
||||
if (n < x) {
|
||||
// data is too long to crypt
|
||||
return SerialState.Invalid;
|
||||
}
|
||||
|
||||
_serial = BigInteger.ModPow(x, e, n).ToByteArray();
|
||||
Array.Reverse(_serial);
|
||||
|
||||
if (_serial[0] != 0 || _serial[1] != 2)
|
||||
return SerialState.Invalid;
|
||||
|
||||
int pos;
|
||||
for (pos = 2; pos < _serial.Length; pos++) {
|
||||
if (_serial[pos] == 0) {
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos == _serial.Length)
|
||||
return SerialState.Invalid;
|
||||
|
||||
_start = pos;
|
||||
return ParseSerial(null);
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetSerialNumberData(SerialNumberData data)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_state == SerialState.Corrupted)
|
||||
return false;
|
||||
|
||||
data.State = (_state & (SerialState.Invalid | SerialState.Blacklisted | SerialState.BadHwid)) != 0 ? _state : ParseSerial(data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public uint DecryptBuffer(uint p3, uint p2, uint p1, uint p0)
|
||||
{
|
||||
uint key0 = (uint)_productCode;
|
||||
uint key1 = (uint)(_productCode >> 32) + _sessionKey;
|
||||
|
||||
p0 = BitRotate.Left((p0 + _sessionKey) ^ key0, 7) + key1;
|
||||
p1 = BitRotate.Left((p1 + _sessionKey) ^ key0, 11) + key1;
|
||||
p2 = BitRotate.Left((p2 + _sessionKey) ^ key0, 17) + key1;
|
||||
p3 = BitRotate.Left((p3 + _sessionKey) ^ key0, 23) + key1;
|
||||
|
||||
if (p0 + p1 + p2 + p3 != _sessionKey * 4)
|
||||
{
|
||||
Core.ShowMessage("This code requires valid serial number to run.\nProgram will be terminated.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
return p3;
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
private enum ChunkType
|
||||
{
|
||||
Version = 0x01, // 1 byte of data - version
|
||||
UserName = 0x02, // 1 + N bytes - length + N bytes of customer's name (without enging \0).
|
||||
Email = 0x03, // 1 + N bytes - length + N bytes of customer's email (without ending \0).
|
||||
HWID = 0x04, // 1 + N bytes - length + N bytes of hardware id (N % 4 == 0)
|
||||
ExpDate = 0x05, // 4 bytes - (year << 16) + (month << 8) + (day)
|
||||
RunningTimeLimit = 0x06, // 1 byte - number of minutes
|
||||
ProductCode = 0x07, // 8 bytes - used for decrypting some parts of exe-file
|
||||
UserData = 0x08, // 1 + N bytes - length + N bytes of user data
|
||||
MaxBuild = 0x09, // 4 bytes - (year << 16) + (month << 8) + (day)
|
||||
End = 0xFF // 4 bytes - checksum: the first four bytes of sha-1 hash from the data before that chunk
|
||||
}
|
||||
|
||||
private SerialState SaveState(SerialState state)
|
||||
{
|
||||
_state = state;
|
||||
if ((_state & (SerialState.Invalid | SerialState.BadHwid)) != 0)
|
||||
{
|
||||
_serial = null;
|
||||
_productCode = 0;
|
||||
}
|
||||
return _state;
|
||||
}
|
||||
private SerialState ParseSerial(SerialNumberData data)
|
||||
{
|
||||
if (_serial == null)
|
||||
return SerialState.Invalid;
|
||||
|
||||
var newState = _state & (SerialState.MaxBuildExpired | SerialState.DateExpired | SerialState.RunningTimeOver);
|
||||
var pos = _start;
|
||||
while (pos < _serial.Length) {
|
||||
var b = _serial[pos++];
|
||||
byte s;
|
||||
switch (b) {
|
||||
case (byte)ChunkType.Version:
|
||||
if (_serial[pos] != 1)
|
||||
return SaveState(SerialState.Invalid);
|
||||
pos += 1;
|
||||
break;
|
||||
case (byte)ChunkType.ExpDate:
|
||||
var expDate = BitConverter.ToUInt32(_serial, pos);
|
||||
if ((newState & SerialState.DateExpired) == 0) {
|
||||
if (BitConverter.ToUInt32(_licenseData, (int)Fields.BuildDate * sizeof(uint)) > expDate || GetCurrentDate() > expDate)
|
||||
newState |= SerialState.DateExpired;
|
||||
}
|
||||
if (data != null) {
|
||||
data.Expires = new DateTime((int)(expDate >> 16), (byte)(expDate >> 8), (byte)expDate);
|
||||
}
|
||||
pos += 4;
|
||||
break;
|
||||
case (byte)ChunkType.RunningTimeLimit:
|
||||
s = _serial[pos];
|
||||
if ((newState & SerialState.RunningTimeOver) == 0) {
|
||||
var curTime = (Environment.TickCount - _startTickCount) / 1000 / 60;
|
||||
if (curTime > s)
|
||||
newState |= SerialState.RunningTimeOver;
|
||||
}
|
||||
if (data != null)
|
||||
data.RunningTime = s;
|
||||
pos += 1;
|
||||
break;
|
||||
case (byte)ChunkType.ProductCode:
|
||||
if ((_state & SerialState.Invalid) != 0)
|
||||
_productCode = BitConverter.ToInt64(_serial, pos);
|
||||
pos += 8;
|
||||
break;
|
||||
case (byte)ChunkType.MaxBuild:
|
||||
var maxBuildDate = BitConverter.ToUInt32(_serial, pos);
|
||||
if ((newState & SerialState.MaxBuildExpired) == 0) {
|
||||
if (BitConverter.ToUInt32(_licenseData, (int)Fields.BuildDate * sizeof(uint)) > maxBuildDate)
|
||||
newState |= SerialState.MaxBuildExpired;
|
||||
}
|
||||
if (data != null)
|
||||
{
|
||||
data.MaxBuild = new DateTime((int)(maxBuildDate >> 16), (byte)(maxBuildDate >> 8), (byte)maxBuildDate);
|
||||
}
|
||||
pos += 4;
|
||||
break;
|
||||
case (byte)ChunkType.UserName:
|
||||
s = _serial[pos++];
|
||||
if (data != null)
|
||||
data.UserName = Encoding.UTF8.GetString(_serial, pos, s);
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.Email:
|
||||
s = _serial[pos++];
|
||||
if (data != null)
|
||||
data.EMail = Encoding.UTF8.GetString(_serial, pos, s);
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.HWID:
|
||||
s = _serial[pos++];
|
||||
if ((_state & SerialState.Invalid) != 0)
|
||||
{
|
||||
var shwid = new byte[s];
|
||||
Array.Copy(_serial, pos, shwid, 0, s);
|
||||
if (!Core.Instance.HWID.IsCorrect(shwid))
|
||||
return SaveState(SerialState.BadHwid);
|
||||
}
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.UserData:
|
||||
s = _serial[pos++];
|
||||
if (data != null) {
|
||||
data.UserData = new byte[s];
|
||||
for (var i = 0; i < s; i++) {
|
||||
data.UserData[i] = _serial[pos + i];
|
||||
}
|
||||
}
|
||||
pos += s;
|
||||
break;
|
||||
case (byte)ChunkType.End:
|
||||
if (pos + 4 > _serial.Length)
|
||||
return SaveState(SerialState.Invalid);
|
||||
|
||||
if ((_state & SerialState.Invalid) != 0) {
|
||||
// calc hash without last chunk
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var p = hash.ComputeHash(_serial, _start, pos - _start - 1);
|
||||
|
||||
// check CRC
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (_serial[pos + i] != p[3 - i])
|
||||
return SaveState(SerialState.Invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SaveState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
// SERIAL_CHUNK_END not found
|
||||
return SaveState(SerialState.Invalid);
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
internal enum Fields
|
||||
{
|
||||
BuildDate,
|
||||
PublicExpOffset,
|
||||
PublicExpSize,
|
||||
ModulusOffset,
|
||||
ModulusSize,
|
||||
BlacklistOffset,
|
||||
BlacklistSize,
|
||||
ActivationUrlOffset,
|
||||
ActivationUrlSize,
|
||||
CRCOffset,
|
||||
Count
|
||||
}
|
||||
private bool CheckLicenseDataCRC()
|
||||
{
|
||||
var crcPos = BitConverter.ToInt32(_licenseData, (int)Fields.CRCOffset * sizeof(uint));
|
||||
var size = crcPos + 16;
|
||||
if (size != _licenseData.Length)
|
||||
return false; // bad key size
|
||||
|
||||
// CRC check
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var h = hash.ComputeHash(_licenseData, 0, crcPos);
|
||||
for (var i = crcPos; i < size; i++)
|
||||
{
|
||||
if (_licenseData[i] != h[i - crcPos])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static uint GetCurrentDate()
|
||||
{
|
||||
var dt = DateTime.Now;
|
||||
var curDate = (uint)((dt.Year << 16) + (dt.Month << 8) + dt.Day);
|
||||
var serverDate = GlobalData.ServerDate();
|
||||
return serverDate > curDate ? serverDate : curDate;
|
||||
}
|
||||
|
||||
private readonly byte[] _licenseData;
|
||||
private byte[] _serial;
|
||||
private readonly object _lock = new object();
|
||||
private SerialState _state = SerialState.Invalid;
|
||||
//TODO
|
||||
//ReSharper disable once NotAccessedField.Local
|
||||
private long _productCode;
|
||||
private readonly int _startTickCount;
|
||||
private int _start;
|
||||
private uint _sessionKey;
|
||||
/*
|
||||
CryptoContainer *_serial;
|
||||
*/
|
||||
}
|
||||
}
|
703
runtime/VMProtect.Runtime/Loader.cs
Normal file
703
runtime/VMProtect.Runtime/Loader.cs
Normal file
@ -0,0 +1,703 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
enum MessageType
|
||||
{
|
||||
InitializationError,
|
||||
ProcNotFound,
|
||||
OrdinalNotFound,
|
||||
FileCorrupted,
|
||||
DebuggerFound,
|
||||
UnregisteredVersion,
|
||||
VirtualMachineFound
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
enum ErrorType
|
||||
{
|
||||
VIRTUAL_PROTECT_ERROR = 1,
|
||||
UNPACKER_ERROR = 2
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
enum LoaderOption
|
||||
{
|
||||
CHECK_PATCH = 0x1,
|
||||
CHECK_DEBUGGER = 0x2,
|
||||
CHECK_KERNEL_DEBUGGER = 0x4,
|
||||
EXIT_PROCESS = 0x8,
|
||||
CHECK_VIRTUAL_MACHINE = 0x10
|
||||
}
|
||||
|
||||
[VMProtect.DeleteOnCompilation]
|
||||
enum FixupType
|
||||
{
|
||||
Absolute = 0,
|
||||
High = 1,
|
||||
Low = 2,
|
||||
HighLow = 3,
|
||||
Dir64 = 10
|
||||
}
|
||||
|
||||
public static class Loader
|
||||
{
|
||||
public static object[] IAT;
|
||||
|
||||
internal static bool FindFirmwareVendor(byte[] data)
|
||||
{
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
if (i + 3 < data.Length && data[i + 0] == 'Q' && data[i + 1] == 'E' && data[i + 2] == 'M' && data[i + 3] == 'U')
|
||||
return true;
|
||||
if (i + 8 < data.Length && data[i + 0] == 'M' && data[i + 1] == 'i' && data[i + 2] == 'c' && data[i + 3] == 'r' && data[i + 4] == 'o' && data[i + 5] == 's' && data[i + 6] == 'o' && data[i + 7] == 'f' && data[i + 8] == 't')
|
||||
return true;
|
||||
if (i + 6 < data.Length && data[i + 0] == 'i' && data[i + 1] == 'n' && data[i + 2] == 'n' && data[i + 3] == 'o' && data[i + 4] == 't' && data[i + 5] == 'e' && data[i + 6] == 'k')
|
||||
return true;
|
||||
if (i + 9 < data.Length && data[i + 0] == 'V' && data[i + 1] == 'i' && data[i + 2] == 'r' && data[i + 3] == 't' && data[i + 4] == 'u' && data[i + 5] == 'a' && data[i + 6] == 'l' && data[i + 7] == 'B' && data[i + 8] == 'o' && data[i + 9] == 'x')
|
||||
return true;
|
||||
if (i + 5 < data.Length && data[i + 0] == 'V' && data[i + 1] == 'M' && data[i + 2] == 'w' && data[i + 3] == 'a' && data[i + 4] == 'r' && data[i + 5] == 'e')
|
||||
return true;
|
||||
if (i + 8 < data.Length && data[i + 0] == 'P' && data[i + 1] == 'a' && data[i + 2] == 'r' && data[i + 3] == 'a' && data[i + 4] == 'l' && data[i + 5] == 'l' && data[i + 6] == 'e' && data[i + 7] == 'l' && data[i + 8] == 's')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ShowMessage(uint type, uint param = 0)
|
||||
{
|
||||
uint position;
|
||||
switch (type)
|
||||
{
|
||||
case (uint)MessageType.DebuggerFound:
|
||||
position = (uint)Faces.DEBUGGER_FOUND;
|
||||
break;
|
||||
case (uint)MessageType.VirtualMachineFound:
|
||||
position = (uint)Faces.VIRTUAL_MACHINE_FOUND;
|
||||
break;
|
||||
case (uint)MessageType.FileCorrupted:
|
||||
position = (uint)Faces.FILE_CORRUPTED;
|
||||
break;
|
||||
case (uint)MessageType.UnregisteredVersion:
|
||||
position = (uint)Faces.UNREGISTERED_VERSION;
|
||||
break;
|
||||
case (uint)MessageType.InitializationError:
|
||||
position = (uint)Faces.INITIALIZATION_ERROR;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
long instance = Marshal.GetHINSTANCE(typeof(Loader).Module).ToInt64();
|
||||
String message = null;
|
||||
var buffer = new byte[1024];
|
||||
for (var pos = 0; pos < 512; pos++)
|
||||
{
|
||||
var c = (ushort)(Marshal.ReadInt16(new IntPtr(instance + position + pos * 2)) ^ (BitRotate.Left((uint)Faces.STRING_DECRYPT_KEY, pos) + pos));
|
||||
if (c == 0)
|
||||
{
|
||||
if (pos > 0)
|
||||
message = Encoding.Unicode.GetString(buffer, 0, pos * 2);
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[pos * 2] = (byte)c;
|
||||
buffer[pos * 2 + 1] = (byte)(c >> 8);
|
||||
}
|
||||
if (message != null)
|
||||
{
|
||||
if (type == (uint)MessageType.InitializationError)
|
||||
message = String.Format(message, param);
|
||||
Win32.ShowMessage(message, Assembly.GetExecutingAssembly().GetName().Name, MessageBoxButtons.OK, type == (uint)MessageType.UnregisteredVersion ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool LzmaDecode(IntPtr dst, IntPtr src, byte[] properties, ref uint dstSize, out uint srcSize)
|
||||
{
|
||||
srcSize = 0;
|
||||
unsafe
|
||||
{
|
||||
using (
|
||||
var srcStream = new UnmanagedMemoryStream((byte*)src.ToPointer(), int.MaxValue, int.MaxValue, FileAccess.Read)
|
||||
)
|
||||
{
|
||||
using (
|
||||
var dstStream = new UnmanagedMemoryStream((byte*) dst.ToPointer(), dstSize, dstSize,
|
||||
FileAccess.Write))
|
||||
{
|
||||
try
|
||||
{
|
||||
var coder = new SevenZip.Compression.LZMA.Decoder();
|
||||
coder.SetDecoderProperties(properties);
|
||||
coder.Code(srcStream, dstStream, dstSize);
|
||||
dstStream.Flush();
|
||||
|
||||
srcSize = (uint)srcStream.Position;
|
||||
dstSize = (uint)dstStream.Position;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
if (GlobalData.LoaderStatus() != 0)
|
||||
return;
|
||||
|
||||
var module = typeof(Loader).Module;
|
||||
long instance = Marshal.GetHINSTANCE(module).ToInt64();
|
||||
var options = (uint)Faces.LOADER_OPTIONS;
|
||||
GlobalData.SetIsPatchDetected(false);
|
||||
GlobalData.SetIsDebuggerDetected(false);
|
||||
GlobalData.SetLoaderCrcInfo((uint)Faces.LOADER_CRC_INFO);
|
||||
GlobalData.SetLoaderCrcSize((uint)Faces.LOADER_CRC_INFO_SIZE);
|
||||
GlobalData.SetLoaderCrcHash((uint)Faces.LOADER_CRC_INFO_HASH);
|
||||
GlobalData.SetServerDate(0);
|
||||
|
||||
// detect a debugger
|
||||
if ((options & (uint)LoaderOption.CHECK_DEBUGGER) != 0)
|
||||
{
|
||||
if (Debugger.IsAttached || Debugger.IsLogging())
|
||||
{
|
||||
ShowMessage((uint)MessageType.DebuggerFound);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Win32.IsDebuggerPresent() || Win32.CheckRemoteDebuggerPresent())
|
||||
{
|
||||
ShowMessage((uint)MessageType.DebuggerFound);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
Win32.NtSetInformationThread(Win32.CurrentThread, Win32.THREADINFOCLASS.ThreadHideFromDebugger, IntPtr.Zero, 0);
|
||||
}
|
||||
|
||||
// check header and loader CRC
|
||||
var crcSize = (uint)Faces.LOADER_CRC_INFO_SIZE;
|
||||
if (crcSize != 0)
|
||||
{
|
||||
crcSize = (uint)Marshal.ReadInt32(new IntPtr(instance + crcSize));
|
||||
var crcPosition = (uint)Faces.LOADER_CRC_INFO;
|
||||
var crcCryptor = new CRCValueCryptor();
|
||||
bool isValid = true;
|
||||
var crcInfo = new byte[12];
|
||||
var crc32 = new CRC32();
|
||||
var crcHash = (uint)Marshal.ReadInt32(new IntPtr(instance + (uint)Faces.LOADER_CRC_INFO_HASH));
|
||||
if (crcHash != crc32.Hash(new IntPtr(instance + crcPosition), crcSize))
|
||||
isValid = false;
|
||||
for (var i = 0; i < crcSize; i += crcInfo.Length)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
|
||||
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
|
||||
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
|
||||
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
|
||||
|
||||
if (crc32.Hash(new IntPtr(instance + address), size) != hash)
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
if ((options & (uint)LoaderOption.CHECK_PATCH) != 0)
|
||||
{
|
||||
ShowMessage((uint)MessageType.FileCorrupted);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
GlobalData.SetIsPatchDetected(true);
|
||||
}
|
||||
}
|
||||
|
||||
// check file CRC
|
||||
crcSize = (uint)Faces.FILE_CRC_INFO_SIZE;
|
||||
if (crcSize != 0) //-V3022
|
||||
{
|
||||
crcSize = (uint)Marshal.ReadInt32(new IntPtr(instance + crcSize));
|
||||
var crcPosition = (uint)Faces.FILE_CRC_INFO;
|
||||
bool isValid = true;
|
||||
var file = Win32.OpenFile(Assembly.GetExecutingAssembly().Location, (uint)Win32.Values.GENERIC_READ, (uint)Win32.Values.FILE_SHARE_READ | (uint)Win32.Values.FILE_SHARE_WRITE);
|
||||
if (file != Win32.InvalidHandleValue)
|
||||
{
|
||||
var fileSize = Win32.GetFileSize(file, IntPtr.Zero);
|
||||
if (fileSize < (uint)Marshal.ReadInt32(new IntPtr(instance + crcPosition)))
|
||||
isValid = false;
|
||||
else
|
||||
{
|
||||
var map = Win32.CreateFileMapping(file, IntPtr.Zero, Win32.MemoryProtection.ReadOnly, 0, 0, null);
|
||||
if (map != Win32.NullHandle)
|
||||
{
|
||||
IntPtr baseAddress = Win32.MapViewOfFile(map, Win32.MapAccess.Read, 0, 0, IntPtr.Zero);
|
||||
if (baseAddress != IntPtr.Zero)
|
||||
{
|
||||
var crcInfo = new byte[12];
|
||||
var crc32 = new CRC32();
|
||||
var crcCryptor = new CRCValueCryptor();
|
||||
for (var i = 4; i < crcSize; i += crcInfo.Length)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
|
||||
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
|
||||
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
|
||||
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
|
||||
|
||||
if (crc32.Hash(new IntPtr(baseAddress.ToInt64() + address), size) != hash)
|
||||
isValid = false;
|
||||
}
|
||||
Win32.UnmapViewOfFile(baseAddress);
|
||||
}
|
||||
Win32.CloseHandle(map);
|
||||
}
|
||||
}
|
||||
Win32.CloseHandle(file);
|
||||
}
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
if ((options & (uint)LoaderOption.CHECK_PATCH) != 0)
|
||||
{
|
||||
ShowMessage((uint)MessageType.FileCorrupted);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
GlobalData.SetIsPatchDetected(true);
|
||||
}
|
||||
}
|
||||
|
||||
// setup WRITABLE flag for memory pages
|
||||
var sectionSize = (uint)Faces.SECTION_INFO_SIZE;
|
||||
if (sectionSize != 0)
|
||||
{
|
||||
var sectionPos = (uint)Faces.SECTION_INFO;
|
||||
var sectionInfo = new byte[12];
|
||||
for (var i = 0; i < sectionSize; i += sectionInfo.Length) //-V3022
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + sectionPos + i), sectionInfo, 0, sectionInfo.Length);
|
||||
uint address = BitConverter.ToUInt32(sectionInfo, 0);
|
||||
uint size = BitConverter.ToUInt32(sectionInfo, 4);
|
||||
uint type = BitConverter.ToUInt32(sectionInfo, 8);
|
||||
|
||||
Win32.MemoryProtection protect, old_protect;
|
||||
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.ExecuteReadWrite : Win32.MemoryProtection.ReadWrite;
|
||||
if (!Win32.VirtualProtect(new IntPtr(instance + address), new UIntPtr(size), protect, out old_protect))
|
||||
{
|
||||
ShowMessage((uint)MessageType.InitializationError, (uint)ErrorType.VIRTUAL_PROTECT_ERROR);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
if (((uint)old_protect & ((uint)Win32.MemoryProtection.NoAccess | (uint)Win32.MemoryProtection.Guard)) != 0)
|
||||
{
|
||||
if ((options & (uint)LoaderOption.CHECK_DEBUGGER) != 0)
|
||||
{
|
||||
ShowMessage((uint)MessageType.DebuggerFound);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
GlobalData.SetIsDebuggerDetected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unpack regions
|
||||
var packerSize = (uint)Faces.PACKER_INFO_SIZE;
|
||||
if (packerSize != 0)
|
||||
{
|
||||
int tlsIndex = 0;
|
||||
var tlsIndexPos = (uint)Faces.TLS_INDEX_INFO;
|
||||
if (tlsIndexPos != 0)
|
||||
tlsIndex = Marshal.ReadInt32(new IntPtr(instance + tlsIndexPos));
|
||||
|
||||
var packerPos = (uint)Faces.PACKER_INFO;
|
||||
var packerInfo = new byte[8];
|
||||
Marshal.Copy(new IntPtr(instance + packerPos), packerInfo, 0, packerInfo.Length);
|
||||
uint src = BitConverter.ToUInt32(packerInfo, 0);
|
||||
uint dst = BitConverter.ToUInt32(packerInfo, 4);
|
||||
var properties = new byte[dst];
|
||||
Marshal.Copy(new IntPtr(instance + src), properties, 0, properties.Length);
|
||||
for (var i = packerInfo.Length; i < packerSize; i += packerInfo.Length) //-V3022
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + packerPos + i), packerInfo, 0, packerInfo.Length);
|
||||
src = BitConverter.ToUInt32(packerInfo, 0);
|
||||
dst = BitConverter.ToUInt32(packerInfo, 4);
|
||||
uint dstSize = int.MaxValue, srcSize;
|
||||
|
||||
if (!LzmaDecode(new IntPtr(instance + dst), new IntPtr(instance + src), properties, ref dstSize, out srcSize))
|
||||
{
|
||||
ShowMessage((uint)MessageType.InitializationError, (uint)ErrorType.UNPACKER_ERROR);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (tlsIndexPos != 0)
|
||||
Marshal.WriteInt32(new IntPtr(instance + tlsIndexPos), tlsIndex);
|
||||
}
|
||||
|
||||
// setup fixups
|
||||
long fileBase = (uint)Faces.FILE_BASE;
|
||||
long deltaBase = instance - fileBase;
|
||||
if (deltaBase != 0)
|
||||
{
|
||||
var fixupSize = (uint)Faces.FIXUP_INFO_SIZE;
|
||||
if (fixupSize != 0)
|
||||
{
|
||||
var fixupPos = (uint)Faces.FIXUP_INFO;
|
||||
var fixupInfo = new byte[8];
|
||||
uint blockSize = 0;
|
||||
for (uint i = 0; i < fixupSize; i += blockSize)
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + fixupPos + i), fixupInfo, 0, fixupInfo.Length);
|
||||
uint address = BitConverter.ToUInt32(fixupInfo, 0);
|
||||
blockSize = BitConverter.ToUInt32(fixupInfo, 4);
|
||||
if (blockSize < fixupInfo.Length)
|
||||
break;
|
||||
|
||||
var c = blockSize - fixupInfo.Length;
|
||||
var block = new byte[c];
|
||||
Marshal.Copy(new IntPtr(instance + fixupPos + i + fixupInfo.Length), block, 0, block.Length);
|
||||
for (var j = 0; j < c; j += 2)
|
||||
{
|
||||
ushort typeOffset = BitConverter.ToUInt16(block, j);
|
||||
var type = (typeOffset & 0xf);
|
||||
var ptr = new IntPtr(instance + address + (typeOffset >> 4));
|
||||
|
||||
if (type == (uint)FixupType.HighLow)
|
||||
{
|
||||
int value = Marshal.ReadInt32(ptr);
|
||||
value += (int)deltaBase;
|
||||
Marshal.WriteInt32(ptr, value);
|
||||
}
|
||||
else if (type == (uint)FixupType.Dir64)
|
||||
{
|
||||
long value = Marshal.ReadInt64(ptr);
|
||||
value += deltaBase;
|
||||
Marshal.WriteInt64(ptr, value);
|
||||
}
|
||||
else if (type == (uint)FixupType.High)
|
||||
{
|
||||
short value = Marshal.ReadInt16(ptr);
|
||||
value += (short)(deltaBase >> 16);
|
||||
Marshal.WriteInt16(ptr, value);
|
||||
}
|
||||
else if (type == (uint)FixupType.Low)
|
||||
{
|
||||
short value = Marshal.ReadInt16(ptr);
|
||||
value += (short)deltaBase;
|
||||
Marshal.WriteInt16(ptr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup IAT
|
||||
var iatSize = (uint)Faces.IAT_INFO_SIZE;
|
||||
if (iatSize != 0)
|
||||
{
|
||||
var iatPos = (uint)Faces.IAT_INFO;
|
||||
var iatInfo = new byte[12];
|
||||
for (var i = 0; i < iatSize; i += iatInfo.Length) //-V3022
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + iatPos + i), iatInfo, 0, iatInfo.Length);
|
||||
uint src = BitConverter.ToUInt32(iatInfo, 0);
|
||||
uint dst = BitConverter.ToUInt32(iatInfo, 4);
|
||||
uint size = BitConverter.ToUInt32(iatInfo, 8);
|
||||
|
||||
var data = new byte[size];
|
||||
Marshal.Copy(new IntPtr(instance + src), data, 0, data.Length);
|
||||
Marshal.Copy(data, 0, new IntPtr(instance + dst), data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
// reset WRITABLE flag for memory pages
|
||||
if (sectionSize != 0) //-V3022
|
||||
{
|
||||
var sectionPos = (uint)Faces.SECTION_INFO;
|
||||
var sectionInfo = new byte[12];
|
||||
for (var i = 0; i < sectionSize; i += sectionInfo.Length) //-V3022
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + sectionPos + i), sectionInfo, 0, sectionInfo.Length);
|
||||
uint address = BitConverter.ToUInt32(sectionInfo, 0);
|
||||
uint size = BitConverter.ToUInt32(sectionInfo, 4);
|
||||
uint type = BitConverter.ToUInt32(sectionInfo, 8);
|
||||
|
||||
Win32.MemoryProtection protect, old_protect;
|
||||
if ((type & (uint)Win32.SectionType.Read) != 0)
|
||||
{
|
||||
if ((type & (uint)Win32.SectionType.Write) != 0)
|
||||
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.ExecuteReadWrite : Win32.MemoryProtection.ReadWrite;
|
||||
else
|
||||
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.ExecuteRead : Win32.MemoryProtection.ReadOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
protect = ((type & (uint)Win32.SectionType.Execute) != 0) ? Win32.MemoryProtection.Execute : Win32.MemoryProtection.NoAccess;
|
||||
}
|
||||
if (!Win32.VirtualProtect(new IntPtr(instance + address), new UIntPtr(size), protect, out old_protect))
|
||||
{
|
||||
ShowMessage((uint)MessageType.InitializationError, (uint)ErrorType.VIRTUAL_PROTECT_ERROR);
|
||||
Environment.Exit(1);
|
||||
}
|
||||
if (((uint)old_protect & ((uint)Win32.MemoryProtection.NoAccess | (uint)Win32.MemoryProtection.Guard)) != 0)
|
||||
{
|
||||
if ((options & (uint)LoaderOption.CHECK_DEBUGGER) != 0)
|
||||
{
|
||||
ShowMessage((uint)MessageType.DebuggerFound);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
GlobalData.SetIsDebuggerDetected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// detect a virtual machine
|
||||
if ((options & (uint)LoaderOption.CHECK_VIRTUAL_MACHINE) != 0)
|
||||
{
|
||||
var info = CpuId.Invoke(1);
|
||||
if (((info[2] >> 31) & 1) != 0)
|
||||
{
|
||||
// hypervisor found
|
||||
bool isFound = true;
|
||||
// check Hyper-V root partition
|
||||
info = CpuId.Invoke(0x40000000);
|
||||
if (info[1] == 0x7263694d && info[2] == 0x666f736f && info[3] == 0x76482074) // "Microsoft Hv"
|
||||
{
|
||||
info = CpuId.Invoke(0x40000003);
|
||||
if ((info[1] & 1) != 0)
|
||||
isFound = false;
|
||||
}
|
||||
if (isFound)
|
||||
{
|
||||
ShowMessage((uint)MessageType.VirtualMachineFound);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int size;
|
||||
uint tableSignature = (byte)'R' << 24 | (byte)'S' << 16 | (byte)'M' << 8 | (byte)'B';
|
||||
try
|
||||
{
|
||||
size = (int)Win32.EnumSystemFirmwareTables(tableSignature, IntPtr.Zero, 0);
|
||||
}
|
||||
catch (EntryPointNotFoundException) { size = 0; }
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
IntPtr nativeBuffer = Marshal.AllocHGlobal(size);
|
||||
Win32.EnumSystemFirmwareTables(tableSignature, nativeBuffer, (uint)size);
|
||||
byte[] buffer = new byte[size];
|
||||
Marshal.Copy(nativeBuffer, buffer, 0, size);
|
||||
Marshal.FreeHGlobal(nativeBuffer);
|
||||
for (var i = 0; i < size / sizeof(uint); i += sizeof(uint))
|
||||
{
|
||||
uint tableId = BitConverter.ToUInt32(buffer, i);
|
||||
int dataSize = (int)Win32.GetSystemFirmwareTable(tableSignature, tableId, IntPtr.Zero, 0);
|
||||
if (dataSize > 0)
|
||||
{
|
||||
nativeBuffer = Marshal.AllocHGlobal(dataSize);
|
||||
Win32.GetSystemFirmwareTable(tableSignature, tableId, nativeBuffer, (uint)dataSize);
|
||||
byte[] data = new byte[dataSize];
|
||||
Marshal.Copy(nativeBuffer, data, 0, dataSize);
|
||||
Marshal.FreeHGlobal(nativeBuffer);
|
||||
if (FindFirmwareVendor(data))
|
||||
{
|
||||
ShowMessage((uint)MessageType.VirtualMachineFound);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check memory CRC
|
||||
crcSize = (uint)Faces.MEMORY_CRC_INFO_SIZE;
|
||||
if (crcSize != 0) //-V3022
|
||||
{
|
||||
var crcPosition = (uint)Faces.MEMORY_CRC_INFO;
|
||||
var crcCryptor = new CRCValueCryptor();
|
||||
bool isValid = true;
|
||||
var crcInfo = new byte[12];
|
||||
var crc32 = new CRC32();
|
||||
var crcHash = (uint)Faces.MEMORY_CRC_INFO_HASH;
|
||||
if (crcHash != crc32.Hash(new IntPtr(instance + crcPosition), crcSize))
|
||||
isValid = false;
|
||||
for (var i = 0; i < crcSize; i += crcInfo.Length) //-V3022
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + crcPosition + i), crcInfo, 0, crcInfo.Length);
|
||||
uint address = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 0));
|
||||
uint size = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 4));
|
||||
uint hash = crcCryptor.Decrypt(BitConverter.ToUInt32(crcInfo, 8));
|
||||
|
||||
if (crc32.Hash(new IntPtr(instance + address), size) != hash)
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
if ((options & (uint)LoaderOption.CHECK_PATCH) != 0)
|
||||
{
|
||||
ShowMessage((uint)MessageType.FileCorrupted);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
GlobalData.SetIsPatchDetected(true);
|
||||
}
|
||||
}
|
||||
|
||||
GlobalData.SetSessionKey((uint)new Random().Next());
|
||||
|
||||
if (!Core.Instance.Init(instance))
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// setup Import
|
||||
var importSize = (uint)Faces.IMPORT_INFO_SIZE;
|
||||
if (importSize != 0)
|
||||
{
|
||||
var importPos = (uint)Faces.IMPORT_INFO;
|
||||
var key = (uint)Faces.STRING_DECRYPT_KEY;
|
||||
var importInfo = new byte[12];
|
||||
object[] iat = new object[importSize / importInfo.Length];
|
||||
uint index = 0;
|
||||
for (var i = 0; i < importSize; i += importInfo.Length) //-V3022
|
||||
{
|
||||
Marshal.Copy(new IntPtr(instance + importPos + i), importInfo, 0, importInfo.Length);
|
||||
uint token = BitConverter.ToUInt32(importInfo, 0) ^ key;
|
||||
uint delegateToken = BitConverter.ToUInt32(importInfo, 4) ^ key;
|
||||
uint callType = BitConverter.ToUInt32(importInfo, 8);
|
||||
|
||||
MethodBase method = null;
|
||||
FieldInfo field = null;
|
||||
try
|
||||
{
|
||||
if ((callType & 8) != 0)
|
||||
field = module.ResolveField((int)token);
|
||||
else
|
||||
method = module.ResolveMethod((int)token);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Win32.ShowMessage(e.InnerException.Message, Assembly.GetExecutingAssembly().GetName().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
var invoke = (MethodInfo)module.ResolveMethod((int)delegateToken);
|
||||
var delegateType = invoke.DeclaringType;
|
||||
object delegateObject;
|
||||
if (callType == 0 && method.IsStatic)
|
||||
delegateObject = Delegate.CreateDelegate(delegateType, (MethodInfo)method);
|
||||
else
|
||||
{
|
||||
ParameterInfo[] parameters = invoke.GetParameters();
|
||||
Type[] paramTypes = new Type[parameters.Length];
|
||||
for (var j = 0; j < paramTypes.Length; j++)
|
||||
paramTypes[j] = parameters[j].ParameterType;
|
||||
|
||||
Type declType = (method != null) ? method.DeclaringType : field.DeclaringType;
|
||||
DynamicMethod dynamicMethod = new DynamicMethod("", invoke.ReturnType, paramTypes, (declType.IsInterface || declType.IsArray) ? delegateType : declType, true);
|
||||
DynamicILInfo dynamicInfo = dynamicMethod.GetDynamicILInfo();
|
||||
dynamicInfo.SetLocalSignature(new byte[] { 0x7, 0x0 });
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
parameters = method.GetParameters();
|
||||
int s = 0;
|
||||
if (paramTypes.Length > parameters.Length)
|
||||
{
|
||||
paramTypes[0] = method.DeclaringType;
|
||||
s = 1;
|
||||
}
|
||||
for (var j = 0; j < parameters.Length; j++)
|
||||
paramTypes[s + j] = parameters[j].ParameterType;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (paramTypes.Length > 0)
|
||||
paramTypes[0] = field.DeclaringType;
|
||||
}
|
||||
|
||||
var code = new byte[7 * paramTypes.Length + 6];
|
||||
int codePos = 0;
|
||||
int dynamicToken;
|
||||
for (var j = 0; j < paramTypes.Length; j++)
|
||||
{
|
||||
code[codePos++] = 0x0e; // Ldarg_s
|
||||
code[codePos++] = (byte)j;
|
||||
|
||||
Type type = paramTypes[j];
|
||||
if ((type.IsClass || type.IsInterface) && !type.IsPointer && !type.IsByRef)
|
||||
{
|
||||
code[codePos++] = 0x74; // Castclass
|
||||
dynamicToken = dynamicInfo.GetTokenFor(type.TypeHandle);
|
||||
code[codePos++] = (byte)dynamicToken;
|
||||
code[codePos++] = (byte)(dynamicToken >> 8);
|
||||
code[codePos++] = (byte)(dynamicToken >> 16);
|
||||
code[codePos++] = (byte)(dynamicToken >> 24);
|
||||
}
|
||||
else
|
||||
codePos += 5;
|
||||
}
|
||||
|
||||
switch (callType)
|
||||
{
|
||||
case 1:
|
||||
code[codePos++] = 0x73; // Newobj
|
||||
break;
|
||||
case 2:
|
||||
code[codePos++] = 0x6f; // Callvirt
|
||||
break;
|
||||
case 8:
|
||||
code[codePos++] = 0x7e; // Ldsfld
|
||||
break;
|
||||
case 9:
|
||||
code[codePos++] = 0x7b; // Ldfld
|
||||
break;
|
||||
default:
|
||||
code[codePos++] = 0x28; // Call
|
||||
break;
|
||||
}
|
||||
dynamicToken = (method != null) ? dynamicInfo.GetTokenFor(method.MethodHandle) : dynamicInfo.GetTokenFor(field.FieldHandle);
|
||||
code[codePos++] = (byte)dynamicToken;
|
||||
code[codePos++] = (byte)(dynamicToken >> 8);
|
||||
code[codePos++] = (byte)(dynamicToken >> 16);
|
||||
code[codePos++] = (byte)(dynamicToken >> 24);
|
||||
|
||||
code[codePos] = 0x2a; // Ret
|
||||
dynamicInfo.SetCode(code, paramTypes.Length + 1);
|
||||
|
||||
delegateObject = dynamicMethod.CreateDelegate(delegateType);
|
||||
}
|
||||
iat[index++] = delegateObject;
|
||||
}
|
||||
IAT = iat;
|
||||
}
|
||||
|
||||
ShowMessage((uint)MessageType.UnregisteredVersion);
|
||||
|
||||
GlobalData.SetLoaderStatus(1);
|
||||
}
|
||||
}
|
||||
}
|
651
runtime/VMProtect.Runtime/LzmaDecoder.cs
Normal file
651
runtime/VMProtect.Runtime/LzmaDecoder.cs
Normal file
@ -0,0 +1,651 @@
|
||||
// LzmaDecoder.cs
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using SevenZip.Compression.RangeCoder;
|
||||
#pragma warning disable 414
|
||||
|
||||
namespace SevenZip.Compression.LZ
|
||||
{
|
||||
public class OutWindow
|
||||
{
|
||||
byte[] _buffer;
|
||||
uint _pos;
|
||||
uint _windowSize;
|
||||
uint _streamPos;
|
||||
Stream _stream;
|
||||
uint _id = 1;
|
||||
|
||||
public uint TrainSize;
|
||||
|
||||
public void Create(uint windowSize)
|
||||
{
|
||||
if (_windowSize != windowSize)
|
||||
{
|
||||
_buffer = new byte[windowSize];
|
||||
}
|
||||
_windowSize = windowSize;
|
||||
_pos = 0;
|
||||
_streamPos = 0;
|
||||
}
|
||||
|
||||
public void Init(Stream stream, bool solid)
|
||||
{
|
||||
ReleaseStream();
|
||||
_stream = stream;
|
||||
if (!solid)
|
||||
{
|
||||
_streamPos = 0;
|
||||
_pos = 0;
|
||||
TrainSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseStream()
|
||||
{
|
||||
Flush();
|
||||
_stream = null;
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
uint size = _pos - _streamPos;
|
||||
if (size == 0)
|
||||
return;
|
||||
_stream.Write(_buffer, (int)_streamPos, (int)size);
|
||||
if (_pos >= _windowSize)
|
||||
_pos = 0;
|
||||
_streamPos = _pos;
|
||||
}
|
||||
|
||||
public void CopyBlock(uint distance, uint len)
|
||||
{
|
||||
uint pos = _pos - distance - 1;
|
||||
if (pos >= _windowSize)
|
||||
pos += _windowSize;
|
||||
for (; len > 0; len--)
|
||||
{
|
||||
if (pos >= _windowSize)
|
||||
pos = 0;
|
||||
_buffer[_pos++] = _buffer[pos++];
|
||||
if (_pos >= _windowSize)
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void PutByte(byte b)
|
||||
{
|
||||
_buffer[_pos++] = b;
|
||||
if (_pos >= _windowSize)
|
||||
Flush();
|
||||
}
|
||||
|
||||
public byte GetByte(uint distance)
|
||||
{
|
||||
uint pos = _pos - distance - 1;
|
||||
if (pos >= _windowSize)
|
||||
pos += _windowSize;
|
||||
return _buffer[pos];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace SevenZip.Compression.RangeCoder
|
||||
{
|
||||
class Decoder
|
||||
{
|
||||
uint _id = 1;
|
||||
|
||||
public const uint KTopValue = (1 << 24);
|
||||
public uint Range;
|
||||
public uint Code;
|
||||
public Stream Stream;
|
||||
|
||||
public void Init(Stream stream)
|
||||
{
|
||||
Stream = stream;
|
||||
|
||||
Code = 0;
|
||||
Range = 0xFFFFFFFF;
|
||||
for (int i = 0; i < 5; i++)
|
||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
||||
}
|
||||
|
||||
public void ReleaseStream()
|
||||
{
|
||||
Stream = null;
|
||||
}
|
||||
|
||||
|
||||
public uint DecodeDirectBits(int numTotalBits)
|
||||
{
|
||||
uint range = Range;
|
||||
uint code = Code;
|
||||
uint result = 0;
|
||||
for (int i = numTotalBits; i > 0; i--)
|
||||
{
|
||||
range >>= 1;
|
||||
uint t = (code - range) >> 31;
|
||||
code -= range & (t - 1);
|
||||
result = (result << 1) | (1 - t);
|
||||
|
||||
if (range < KTopValue)
|
||||
{
|
||||
code = (code << 8) | (byte)Stream.ReadByte();
|
||||
range <<= 8;
|
||||
}
|
||||
}
|
||||
Range = range;
|
||||
Code = code;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
struct BitDecoder
|
||||
{
|
||||
private const int KNumBitModelTotalBits = 11;
|
||||
private const uint KBitModelTotal = (1 << KNumBitModelTotalBits);
|
||||
const int KNumMoveBits = 5;
|
||||
|
||||
uint _prob;
|
||||
|
||||
public void Init() { _prob = KBitModelTotal >> 1; }
|
||||
|
||||
public uint Decode(Decoder rangeDecoder)
|
||||
{
|
||||
uint newBound = (rangeDecoder.Range >> KNumBitModelTotalBits) * _prob;
|
||||
if (rangeDecoder.Code < newBound)
|
||||
{
|
||||
rangeDecoder.Range = newBound;
|
||||
_prob += (KBitModelTotal - _prob) >> KNumMoveBits;
|
||||
if (rangeDecoder.Range < Decoder.KTopValue)
|
||||
{
|
||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
||||
rangeDecoder.Range <<= 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeDecoder.Range -= newBound;
|
||||
rangeDecoder.Code -= newBound;
|
||||
_prob -= (_prob) >> KNumMoveBits;
|
||||
if (rangeDecoder.Range < Decoder.KTopValue)
|
||||
{
|
||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
||||
rangeDecoder.Range <<= 8;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BitTreeDecoder
|
||||
{
|
||||
private readonly BitDecoder[] _models;
|
||||
private readonly int _numBitLevels;
|
||||
|
||||
public BitTreeDecoder(int numBitLevels)
|
||||
{
|
||||
_numBitLevels = numBitLevels;
|
||||
_models = new BitDecoder[1 << numBitLevels];
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
for (uint i = 1; i < (1 << _numBitLevels); i++)
|
||||
_models[i].Init();
|
||||
}
|
||||
|
||||
public uint Decode(Decoder rangeDecoder)
|
||||
{
|
||||
uint m = 1;
|
||||
for (int bitIndex = _numBitLevels; bitIndex > 0; bitIndex--)
|
||||
m = (m << 1) + _models[m].Decode(rangeDecoder);
|
||||
return m - ((uint)1 << _numBitLevels);
|
||||
}
|
||||
|
||||
public uint ReverseDecode(Decoder rangeDecoder)
|
||||
{
|
||||
uint m = 1;
|
||||
uint symbol = 0;
|
||||
for (int bitIndex = 0; bitIndex < _numBitLevels; bitIndex++)
|
||||
{
|
||||
uint bit = _models[m].Decode(rangeDecoder);
|
||||
m <<= 1;
|
||||
m += bit;
|
||||
symbol |= (bit << bitIndex);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public static uint ReverseDecode(BitDecoder[] models, UInt32 startIndex,
|
||||
Decoder rangeDecoder, int numBitLevels)
|
||||
{
|
||||
uint m = 1;
|
||||
uint symbol = 0;
|
||||
for (int bitIndex = 0; bitIndex < numBitLevels; bitIndex++)
|
||||
{
|
||||
uint bit = models[startIndex + m].Decode(rangeDecoder);
|
||||
m <<= 1;
|
||||
m += bit;
|
||||
symbol |= (bit << bitIndex);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace SevenZip.Compression.LZMA
|
||||
{
|
||||
internal abstract class Base
|
||||
{
|
||||
public const uint KNumStates = 12;
|
||||
|
||||
public struct State
|
||||
{
|
||||
public uint Index;
|
||||
public void Init() { Index = 0; }
|
||||
public void UpdateChar()
|
||||
{
|
||||
if (Index < 4) Index = 0;
|
||||
else if (Index < 10) Index -= 3;
|
||||
else Index -= 6;
|
||||
}
|
||||
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
|
||||
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
|
||||
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
|
||||
public bool IsCharState() { return Index < 7; }
|
||||
}
|
||||
|
||||
public const int KNumPosSlotBits = 6;
|
||||
|
||||
private const int KNumLenToPosStatesBits = 2; // it's for speed optimization
|
||||
public const uint KNumLenToPosStates = 1 << KNumLenToPosStatesBits;
|
||||
|
||||
public const uint KMatchMinLen = 2;
|
||||
|
||||
public static uint GetLenToPosState(uint len)
|
||||
{
|
||||
len -= KMatchMinLen;
|
||||
if (len < KNumLenToPosStates)
|
||||
return len;
|
||||
return KNumLenToPosStates - 1;
|
||||
}
|
||||
|
||||
public const int KNumAlignBits = 4;
|
||||
|
||||
public const uint KStartPosModelIndex = 4;
|
||||
public const uint KEndPosModelIndex = 14;
|
||||
|
||||
public const uint KNumFullDistances = 1 << ((int)KEndPosModelIndex / 2);
|
||||
|
||||
public const int KNumPosStatesBitsMax = 4;
|
||||
public const uint KNumPosStatesMax = (1 << KNumPosStatesBitsMax);
|
||||
|
||||
public const int KNumLowLenBits = 3;
|
||||
public const int KNumMidLenBits = 3;
|
||||
public const int KNumHighLenBits = 8;
|
||||
public const uint KNumLowLenSymbols = 1 << KNumLowLenBits;
|
||||
public const uint KNumMidLenSymbols = 1 << KNumMidLenBits;
|
||||
}
|
||||
public class Decoder
|
||||
{
|
||||
uint _id = 1;
|
||||
|
||||
class LenDecoder
|
||||
{
|
||||
BitDecoder _mChoice = new BitDecoder();
|
||||
BitDecoder _mChoice2 = new BitDecoder();
|
||||
readonly BitTreeDecoder[] _mLowCoder = new BitTreeDecoder[Base.KNumPosStatesMax];
|
||||
readonly BitTreeDecoder[] _mMidCoder = new BitTreeDecoder[Base.KNumPosStatesMax];
|
||||
BitTreeDecoder _mHighCoder = new BitTreeDecoder(Base.KNumHighLenBits);
|
||||
uint _mNumPosStates;
|
||||
|
||||
public void Create(uint numPosStates)
|
||||
{
|
||||
for (uint posState = _mNumPosStates; posState < numPosStates; posState++)
|
||||
{
|
||||
_mLowCoder[posState] = new BitTreeDecoder(Base.KNumLowLenBits);
|
||||
_mMidCoder[posState] = new BitTreeDecoder(Base.KNumMidLenBits);
|
||||
}
|
||||
_mNumPosStates = numPosStates;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_mChoice.Init();
|
||||
for (uint posState = 0; posState < _mNumPosStates; posState++)
|
||||
{
|
||||
_mLowCoder[posState].Init();
|
||||
_mMidCoder[posState].Init();
|
||||
}
|
||||
_mChoice2.Init();
|
||||
_mHighCoder.Init();
|
||||
}
|
||||
|
||||
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
|
||||
{
|
||||
if (_mChoice.Decode(rangeDecoder) == 0)
|
||||
return _mLowCoder[posState].Decode(rangeDecoder);
|
||||
else
|
||||
{
|
||||
uint symbol = Base.KNumLowLenSymbols;
|
||||
if (_mChoice2.Decode(rangeDecoder) == 0)
|
||||
symbol += _mMidCoder[posState].Decode(rangeDecoder);
|
||||
else
|
||||
{
|
||||
symbol += Base.KNumMidLenSymbols;
|
||||
symbol += _mHighCoder.Decode(rangeDecoder);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LiteralDecoder
|
||||
{
|
||||
uint _id = 1;
|
||||
|
||||
struct Decoder2
|
||||
{
|
||||
BitDecoder[] _mDecoders;
|
||||
public void Create() { _mDecoders = new BitDecoder[0x300]; }
|
||||
public void Init() { for (int i = 0; i < 0x300; i++) _mDecoders[i].Init(); }
|
||||
|
||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
|
||||
{
|
||||
uint symbol = 1;
|
||||
do
|
||||
symbol = (symbol << 1) | _mDecoders[symbol].Decode(rangeDecoder);
|
||||
while (symbol < 0x100);
|
||||
return (byte)symbol;
|
||||
}
|
||||
|
||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
|
||||
{
|
||||
uint symbol = 1;
|
||||
do
|
||||
{
|
||||
uint matchBit = (uint)(matchByte >> 7) & 1;
|
||||
matchByte <<= 1;
|
||||
uint bit = _mDecoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
|
||||
symbol = (symbol << 1) | bit;
|
||||
if (matchBit != bit)
|
||||
{
|
||||
while (symbol < 0x100)
|
||||
symbol = (symbol << 1) | _mDecoders[symbol].Decode(rangeDecoder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (symbol < 0x100);
|
||||
return (byte)symbol;
|
||||
}
|
||||
}
|
||||
|
||||
Decoder2[] _mCoders;
|
||||
int _mNumPrevBits;
|
||||
int _mNumPosBits;
|
||||
uint _mPosMask;
|
||||
|
||||
public void Create(int numPosBits, int numPrevBits)
|
||||
{
|
||||
if (_mCoders != null && _mNumPrevBits == numPrevBits &&
|
||||
_mNumPosBits == numPosBits)
|
||||
return;
|
||||
_mNumPosBits = numPosBits;
|
||||
_mPosMask = ((uint)1 << numPosBits) - 1;
|
||||
_mNumPrevBits = numPrevBits;
|
||||
uint numStates = (uint)1 << (_mNumPrevBits + _mNumPosBits);
|
||||
_mCoders = new Decoder2[numStates];
|
||||
for (uint i = 0; i < numStates; i++)
|
||||
_mCoders[i].Create();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
uint numStates = (uint)1 << (_mNumPrevBits + _mNumPosBits);
|
||||
for (uint i = 0; i < numStates; i++)
|
||||
_mCoders[i].Init();
|
||||
}
|
||||
|
||||
uint GetState(uint pos, byte prevByte)
|
||||
{ return ((pos & _mPosMask) << _mNumPrevBits) + (uint)(prevByte >> (8 - _mNumPrevBits)); }
|
||||
|
||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
|
||||
{ return _mCoders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
|
||||
|
||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
|
||||
{ return _mCoders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
|
||||
};
|
||||
|
||||
readonly LZ.OutWindow _mOutWindow = new LZ.OutWindow();
|
||||
readonly RangeCoder.Decoder _mRangeDecoder = new RangeCoder.Decoder();
|
||||
|
||||
readonly BitDecoder[] _mIsMatchDecoders = new BitDecoder[Base.KNumStates << Base.KNumPosStatesBitsMax];
|
||||
readonly BitDecoder[] _mIsRepDecoders = new BitDecoder[Base.KNumStates];
|
||||
readonly BitDecoder[] _mIsRepG0Decoders = new BitDecoder[Base.KNumStates];
|
||||
readonly BitDecoder[] _mIsRepG1Decoders = new BitDecoder[Base.KNumStates];
|
||||
readonly BitDecoder[] _mIsRepG2Decoders = new BitDecoder[Base.KNumStates];
|
||||
readonly BitDecoder[] _mIsRep0LongDecoders = new BitDecoder[Base.KNumStates << Base.KNumPosStatesBitsMax];
|
||||
|
||||
readonly BitTreeDecoder[] _mPosSlotDecoder = new BitTreeDecoder[Base.KNumLenToPosStates];
|
||||
readonly BitDecoder[] _mPosDecoders = new BitDecoder[Base.KNumFullDistances - Base.KEndPosModelIndex];
|
||||
|
||||
BitTreeDecoder _mPosAlignDecoder = new BitTreeDecoder(Base.KNumAlignBits);
|
||||
|
||||
readonly LenDecoder _mLenDecoder = new LenDecoder();
|
||||
readonly LenDecoder _mRepLenDecoder = new LenDecoder();
|
||||
|
||||
readonly LiteralDecoder _mLiteralDecoder = new LiteralDecoder();
|
||||
|
||||
uint _mDictionarySize;
|
||||
uint _mDictionarySizeCheck;
|
||||
|
||||
uint _mPosStateMask;
|
||||
|
||||
public Decoder()
|
||||
{
|
||||
_mDictionarySize = 0xFFFFFFFF;
|
||||
for (int i = 0; i < Base.KNumLenToPosStates; i++)
|
||||
_mPosSlotDecoder[i] = new BitTreeDecoder(Base.KNumPosSlotBits);
|
||||
}
|
||||
|
||||
void SetDictionarySize(uint dictionarySize)
|
||||
{
|
||||
if (_mDictionarySize != dictionarySize)
|
||||
{
|
||||
_mDictionarySize = dictionarySize;
|
||||
_mDictionarySizeCheck = Math.Max(_mDictionarySize, 1);
|
||||
uint blockSize = Math.Max(_mDictionarySizeCheck, (1 << 12));
|
||||
_mOutWindow.Create(blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
void SetLiteralProperties(int lp, int lc)
|
||||
{
|
||||
if (lp > 8)
|
||||
throw new ArgumentException("lp > 8");
|
||||
if (lc > 8)
|
||||
throw new ArgumentException("lc > 8");
|
||||
_mLiteralDecoder.Create(lp, lc);
|
||||
}
|
||||
|
||||
void SetPosBitsProperties(int pb)
|
||||
{
|
||||
if (pb > Base.KNumPosStatesBitsMax)
|
||||
throw new ArgumentException("pb > Base.KNumPosStatesBitsMax");
|
||||
uint numPosStates = (uint)1 << pb;
|
||||
_mLenDecoder.Create(numPosStates);
|
||||
_mRepLenDecoder.Create(numPosStates);
|
||||
_mPosStateMask = numPosStates - 1;
|
||||
}
|
||||
|
||||
void Init(Stream inStream, Stream outStream)
|
||||
{
|
||||
_mRangeDecoder.Init(inStream);
|
||||
_mOutWindow.Init(outStream, false);
|
||||
|
||||
uint i;
|
||||
for (i = 0; i < Base.KNumStates; i++)
|
||||
{
|
||||
for (uint j = 0; j <= _mPosStateMask; j++)
|
||||
{
|
||||
uint index = (i << Base.KNumPosStatesBitsMax) + j;
|
||||
_mIsMatchDecoders[index].Init();
|
||||
_mIsRep0LongDecoders[index].Init();
|
||||
}
|
||||
_mIsRepDecoders[i].Init();
|
||||
_mIsRepG0Decoders[i].Init();
|
||||
_mIsRepG1Decoders[i].Init();
|
||||
_mIsRepG2Decoders[i].Init();
|
||||
}
|
||||
|
||||
_mLiteralDecoder.Init();
|
||||
for (i = 0; i < Base.KNumLenToPosStates; i++)
|
||||
_mPosSlotDecoder[i].Init();
|
||||
for (i = 0; i < Base.KNumFullDistances - Base.KEndPosModelIndex; i++)
|
||||
_mPosDecoders[i].Init();
|
||||
|
||||
_mLenDecoder.Init();
|
||||
_mRepLenDecoder.Init();
|
||||
_mPosAlignDecoder.Init();
|
||||
}
|
||||
|
||||
public void Code(Stream inStream, Stream outStream, Int64 outSize)
|
||||
{
|
||||
Init(inStream, outStream);
|
||||
|
||||
Base.State state = new Base.State();
|
||||
state.Init();
|
||||
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
|
||||
|
||||
UInt64 nowPos64 = 0;
|
||||
UInt64 outSize64 = (UInt64)outSize;
|
||||
if (nowPos64 < outSize64)
|
||||
{
|
||||
if (_mIsMatchDecoders[state.Index << Base.KNumPosStatesBitsMax].Decode(_mRangeDecoder) != 0)
|
||||
throw new InvalidDataException("IsMatchDecoders");
|
||||
state.UpdateChar();
|
||||
byte b = _mLiteralDecoder.DecodeNormal(_mRangeDecoder, 0, 0);
|
||||
_mOutWindow.PutByte(b);
|
||||
nowPos64++;
|
||||
}
|
||||
while (nowPos64 < outSize64)
|
||||
{
|
||||
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
|
||||
// while(nowPos64 < next)
|
||||
{
|
||||
uint posState = (uint)nowPos64 & _mPosStateMask;
|
||||
if (_mIsMatchDecoders[(state.Index << Base.KNumPosStatesBitsMax) + posState].Decode(_mRangeDecoder) == 0)
|
||||
{
|
||||
byte b;
|
||||
byte prevByte = _mOutWindow.GetByte(0);
|
||||
if (!state.IsCharState())
|
||||
b = _mLiteralDecoder.DecodeWithMatchByte(_mRangeDecoder,
|
||||
(uint)nowPos64, prevByte, _mOutWindow.GetByte(rep0));
|
||||
else
|
||||
b = _mLiteralDecoder.DecodeNormal(_mRangeDecoder, (uint)nowPos64, prevByte);
|
||||
_mOutWindow.PutByte(b);
|
||||
state.UpdateChar();
|
||||
nowPos64++;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint len;
|
||||
if (_mIsRepDecoders[state.Index].Decode(_mRangeDecoder) == 1)
|
||||
{
|
||||
if (_mIsRepG0Decoders[state.Index].Decode(_mRangeDecoder) == 0)
|
||||
{
|
||||
if (_mIsRep0LongDecoders[(state.Index << Base.KNumPosStatesBitsMax) + posState].Decode(_mRangeDecoder) == 0)
|
||||
{
|
||||
state.UpdateShortRep();
|
||||
_mOutWindow.PutByte(_mOutWindow.GetByte(rep0));
|
||||
nowPos64++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 distance;
|
||||
if (_mIsRepG1Decoders[state.Index].Decode(_mRangeDecoder) == 0)
|
||||
{
|
||||
distance = rep1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_mIsRepG2Decoders[state.Index].Decode(_mRangeDecoder) == 0)
|
||||
distance = rep2;
|
||||
else
|
||||
{
|
||||
distance = rep3;
|
||||
rep3 = rep2;
|
||||
}
|
||||
rep2 = rep1;
|
||||
}
|
||||
rep1 = rep0;
|
||||
rep0 = distance;
|
||||
}
|
||||
len = _mRepLenDecoder.Decode(_mRangeDecoder, posState) + Base.KMatchMinLen;
|
||||
state.UpdateRep();
|
||||
}
|
||||
else
|
||||
{
|
||||
rep3 = rep2;
|
||||
rep2 = rep1;
|
||||
rep1 = rep0;
|
||||
len = Base.KMatchMinLen + _mLenDecoder.Decode(_mRangeDecoder, posState);
|
||||
state.UpdateMatch();
|
||||
uint posSlot = _mPosSlotDecoder[Base.GetLenToPosState(len)].Decode(_mRangeDecoder);
|
||||
if (posSlot >= Base.KStartPosModelIndex)
|
||||
{
|
||||
int numDirectBits = (int)((posSlot >> 1) - 1);
|
||||
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
|
||||
if (posSlot < Base.KEndPosModelIndex)
|
||||
rep0 += BitTreeDecoder.ReverseDecode(_mPosDecoders,
|
||||
rep0 - posSlot - 1, _mRangeDecoder, numDirectBits);
|
||||
else
|
||||
{
|
||||
rep0 += (_mRangeDecoder.DecodeDirectBits(
|
||||
numDirectBits - Base.KNumAlignBits) << Base.KNumAlignBits);
|
||||
rep0 += _mPosAlignDecoder.ReverseDecode(_mRangeDecoder);
|
||||
}
|
||||
}
|
||||
else
|
||||
rep0 = posSlot;
|
||||
}
|
||||
if (rep0 >= _mOutWindow.TrainSize + nowPos64 || rep0 >= _mDictionarySizeCheck)
|
||||
{
|
||||
if (rep0 == 0xFFFFFFFF)
|
||||
break;
|
||||
throw new InvalidDataException("rep0");
|
||||
}
|
||||
_mOutWindow.CopyBlock(rep0, len);
|
||||
nowPos64 += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
_mOutWindow.Flush();
|
||||
_mOutWindow.ReleaseStream();
|
||||
_mRangeDecoder.ReleaseStream();
|
||||
}
|
||||
|
||||
public void SetDecoderProperties(byte[] properties)
|
||||
{
|
||||
if (properties.Length < 5)
|
||||
throw new ArgumentException("properties.Length < 5");
|
||||
int lc = properties[0] % 9;
|
||||
int remainder = properties[0] / 9;
|
||||
int lp = remainder % 5;
|
||||
int pb = remainder / 5;
|
||||
if (pb > Base.KNumPosStatesBitsMax)
|
||||
throw new ArgumentException("pb > Base.kNumPosStatesBitsMax");
|
||||
UInt32 dictionarySize = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
|
||||
SetDictionarySize(dictionarySize);
|
||||
SetLiteralProperties(lp, lc);
|
||||
SetPosBitsProperties(pb);
|
||||
}
|
||||
}
|
||||
}
|
2012
runtime/VMProtect.Runtime/Numerics/BigInteger.cs
Normal file
2012
runtime/VMProtect.Runtime/Numerics/BigInteger.cs
Normal file
File diff suppressed because it is too large
Load Diff
1529
runtime/VMProtect.Runtime/Numerics/BigIntegerBuilder.cs
Normal file
1529
runtime/VMProtect.Runtime/Numerics/BigIntegerBuilder.cs
Normal file
File diff suppressed because it is too large
Load Diff
425
runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
Normal file
425
runtime/VMProtect.Runtime/Numerics/NumericHelpers.cs
Normal file
@ -0,0 +1,425 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
using System;
|
||||
|
||||
using Contracts = System.Diagnostics.Debug;
|
||||
using Contract = System.Diagnostics.Debug;
|
||||
//using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Numerics
|
||||
{
|
||||
|
||||
/*
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct DoubleUlong
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal double dbl;
|
||||
[FieldOffset(0)]
|
||||
internal ulong uu;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
internal static class NumericsHelpers
|
||||
{
|
||||
private const int KcbitUint = 32;
|
||||
|
||||
/*internal static void GetDoubleParts(double dbl, out int sign, out int exp, out ulong man, out bool fFinite)
|
||||
{
|
||||
//Contract.Ensures(Contract.ValueAtReturn(out sign) == +1 || Contract.ValueAtReturn(out sign) == -1);
|
||||
|
||||
DoubleUlong du;
|
||||
du.uu = 0;
|
||||
du.dbl = dbl;
|
||||
|
||||
sign = 1 - ((int)(du.uu >> 62) & 2);
|
||||
man = du.uu & 0x000FFFFFFFFFFFFF;
|
||||
exp = (int)(du.uu >> 52) & 0x7FF;
|
||||
if (exp == 0)
|
||||
{
|
||||
// Denormalized number.
|
||||
fFinite = true;
|
||||
if (man != 0)
|
||||
exp = -1074;
|
||||
}
|
||||
else if (exp == 0x7FF)
|
||||
{
|
||||
// NaN or Inifite.
|
||||
fFinite = false;
|
||||
exp = int.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fFinite = true;
|
||||
man |= 0x0010000000000000;
|
||||
exp -= 1075;
|
||||
}
|
||||
}
|
||||
|
||||
internal static double GetDoubleFromParts(int sign, int exp, ulong man)
|
||||
{
|
||||
DoubleUlong du;
|
||||
du.dbl = 0;
|
||||
|
||||
if (man == 0)
|
||||
du.uu = 0;
|
||||
else
|
||||
{
|
||||
// Normalize so that 0x0010 0000 0000 0000 is the highest bit set.
|
||||
int cbitShift = CbitHighZero(man) - 11;
|
||||
if (cbitShift < 0)
|
||||
man >>= -cbitShift;
|
||||
else
|
||||
man <<= cbitShift;
|
||||
exp -= cbitShift;
|
||||
Contract.Assert((man & 0xFFF0000000000000) == 0x0010000000000000);
|
||||
|
||||
// Move the point to just behind the leading 1: 0x001.0 0000 0000 0000
|
||||
// (52 bits) and skew the exponent (by 0x3FF == 1023).
|
||||
exp += 1075;
|
||||
|
||||
if (exp >= 0x7FF)
|
||||
{
|
||||
// Infinity.
|
||||
du.uu = 0x7FF0000000000000;
|
||||
}
|
||||
else if (exp <= 0)
|
||||
{
|
||||
// Denormalized.
|
||||
exp--;
|
||||
if (exp < -52)
|
||||
{
|
||||
// Underflow to zero.
|
||||
du.uu = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
du.uu = man >> -exp;
|
||||
Contract.Assert(du.uu != 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mask off the implicit high bit.
|
||||
du.uu = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52);
|
||||
}
|
||||
}
|
||||
|
||||
if (sign < 0)
|
||||
du.uu |= 0x8000000000000000;
|
||||
|
||||
return du.dbl;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Do an in-place twos complement of d and also return the result.
|
||||
// "Dangerous" because it causes a mutation and needs to be used
|
||||
// with care for immutable types
|
||||
internal static void DangerousMakeTwosComplement(uint[] d)
|
||||
{
|
||||
// first do complement and +1 as long as carry is needed
|
||||
int i = 0;
|
||||
uint v = 0;
|
||||
for (; i < d.Length; i++)
|
||||
{
|
||||
v = ~d[i] + 1;
|
||||
d[i] = v;
|
||||
if (v != 0) { i++; break; }
|
||||
}
|
||||
if (v != 0)
|
||||
{
|
||||
// now ones complement is sufficient
|
||||
for (; i < d.Length; i++)
|
||||
{
|
||||
d[i] = ~d[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//??? this is weird
|
||||
d = resize(d, d.Length + 1);
|
||||
d[d.Length - 1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private static uint[] resize(uint[] v, int len)
|
||||
{
|
||||
if (v.Length == len) return v;
|
||||
uint[] ret = new uint[len];
|
||||
int n = Math.Min(v.Length, len);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
ret[i] = v[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
internal static void Swap<T>(ref T a, ref T b)
|
||||
{
|
||||
T tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/*
|
||||
internal static uint GCD(uint u1, uint u2)
|
||||
{
|
||||
const int cvMax = 32;
|
||||
if (u1 < u2)
|
||||
goto LOther;
|
||||
LTop:
|
||||
Contract.Assert(u2 <= u1);
|
||||
if (u2 == 0)
|
||||
return u1;
|
||||
for (int cv = cvMax; ; )
|
||||
{
|
||||
u1 -= u2;
|
||||
if (u1 < u2)
|
||||
break;
|
||||
if (--cv == 0)
|
||||
{
|
||||
u1 %= u2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOther:
|
||||
Contract.Assert(u1 < u2);
|
||||
if (u1 == 0)
|
||||
return u2;
|
||||
for (int cv = cvMax; ; )
|
||||
{
|
||||
u2 -= u1;
|
||||
if (u2 < u1)
|
||||
break;
|
||||
if (--cv == 0)
|
||||
{
|
||||
u2 %= u1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto LTop;
|
||||
}
|
||||
*/
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
/*
|
||||
internal static ulong GCD(ulong uu1, ulong uu2)
|
||||
{
|
||||
const int cvMax = 32;
|
||||
if (uu1 < uu2)
|
||||
goto LOther;
|
||||
LTop:
|
||||
Contract.Assert(uu2 <= uu1);
|
||||
if (uu1 <= uint.MaxValue)
|
||||
goto LSmall;
|
||||
if (uu2 == 0)
|
||||
return uu1;
|
||||
for (int cv = cvMax; ; )
|
||||
{
|
||||
uu1 -= uu2;
|
||||
if (uu1 < uu2)
|
||||
break;
|
||||
if (--cv == 0)
|
||||
{
|
||||
uu1 %= uu2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOther:
|
||||
Contract.Assert(uu1 < uu2);
|
||||
if (uu2 <= uint.MaxValue)
|
||||
goto LSmall;
|
||||
if (uu1 == 0)
|
||||
return uu2;
|
||||
for (int cv = cvMax; ; )
|
||||
{
|
||||
uu2 -= uu1;
|
||||
if (uu2 < uu1)
|
||||
break;
|
||||
if (--cv == 0)
|
||||
{
|
||||
uu2 %= uu1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto LTop;
|
||||
|
||||
LSmall:
|
||||
uint u1 = (uint)uu1;
|
||||
uint u2 = (uint)uu2;
|
||||
if (u1 < u2)
|
||||
goto LOtherSmall;
|
||||
LTopSmall:
|
||||
Contract.Assert(u2 <= u1);
|
||||
if (u2 == 0)
|
||||
return u1;
|
||||
for (int cv = cvMax; ; )
|
||||
{
|
||||
u1 -= u2;
|
||||
if (u1 < u2)
|
||||
break;
|
||||
if (--cv == 0)
|
||||
{
|
||||
u1 %= u2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOtherSmall:
|
||||
Contract.Assert(u1 < u2);
|
||||
if (u1 == 0)
|
||||
return u2;
|
||||
for (int cv = cvMax; ; )
|
||||
{
|
||||
u2 -= u1;
|
||||
if (u2 < u1)
|
||||
break;
|
||||
if (--cv == 0)
|
||||
{
|
||||
u2 %= u1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto LTopSmall;
|
||||
}
|
||||
*/
|
||||
|
||||
internal static ulong MakeUlong(uint uHi, uint uLo)
|
||||
{
|
||||
return ((ulong)uHi << KcbitUint) | uLo;
|
||||
}
|
||||
|
||||
internal static uint GetLo(ulong uu)
|
||||
{
|
||||
return (uint)uu;
|
||||
}
|
||||
|
||||
internal static uint GetHi(ulong uu)
|
||||
{
|
||||
return (uint)(uu >> KcbitUint);
|
||||
}
|
||||
|
||||
/*
|
||||
internal static uint Abs(int a)
|
||||
{
|
||||
uint mask = (uint)(a >> 31);
|
||||
return ((uint)a ^ mask) - mask;
|
||||
}
|
||||
*/
|
||||
|
||||
// internal static ulong Abs(long a) {
|
||||
// ulong mask = (ulong)(a >> 63);
|
||||
// return ((ulong)a ^ mask) - mask;
|
||||
// }
|
||||
|
||||
private static uint CombineHash(uint u1, uint u2)
|
||||
{
|
||||
return ((u1 << 7) | (u1 >> 25)) ^ u2;
|
||||
}
|
||||
|
||||
internal static int CombineHash(int n1, int n2)
|
||||
{
|
||||
return (int)CombineHash((uint)n1, (uint)n2);
|
||||
}
|
||||
internal static int CbitHighZero(uint u)
|
||||
{
|
||||
if (u == 0)
|
||||
return 32;
|
||||
|
||||
int cbit = 0;
|
||||
if ((u & 0xFFFF0000) == 0)
|
||||
{
|
||||
cbit += 16;
|
||||
u <<= 16;
|
||||
}
|
||||
if ((u & 0xFF000000) == 0)
|
||||
{
|
||||
cbit += 8;
|
||||
u <<= 8;
|
||||
}
|
||||
if ((u & 0xF0000000) == 0)
|
||||
{
|
||||
cbit += 4;
|
||||
u <<= 4;
|
||||
}
|
||||
if ((u & 0xC0000000) == 0)
|
||||
{
|
||||
cbit += 2;
|
||||
u <<= 2;
|
||||
}
|
||||
if ((u & 0x80000000) == 0)
|
||||
cbit += 1;
|
||||
return cbit;
|
||||
}
|
||||
|
||||
/*internal static int CbitLowZero(uint u)
|
||||
{
|
||||
if (u == 0)
|
||||
return 32;
|
||||
|
||||
int cbit = 0;
|
||||
if ((u & 0x0000FFFF) == 0)
|
||||
{
|
||||
cbit += 16;
|
||||
u >>= 16;
|
||||
}
|
||||
if ((u & 0x000000FF) == 0)
|
||||
{
|
||||
cbit += 8;
|
||||
u >>= 8;
|
||||
}
|
||||
if ((u & 0x0000000F) == 0)
|
||||
{
|
||||
cbit += 4;
|
||||
u >>= 4;
|
||||
}
|
||||
if ((u & 0x00000003) == 0)
|
||||
{
|
||||
cbit += 2;
|
||||
u >>= 2;
|
||||
}
|
||||
if ((u & 0x00000001) == 0)
|
||||
cbit += 1;
|
||||
return cbit;
|
||||
}
|
||||
|
||||
internal static int CbitHighZero(ulong uu)
|
||||
{
|
||||
if ((uu & 0xFFFFFFFF00000000) == 0)
|
||||
return 32 + CbitHighZero((uint)uu);
|
||||
return CbitHighZero((uint)(uu >> 32));
|
||||
}*/
|
||||
|
||||
// internal static int CbitLowZero(ulong uu) {
|
||||
// if ((uint)uu == 0)
|
||||
// return 32 + CbitLowZero((uint)(uu >> 32));
|
||||
// return CbitLowZero((uint)uu);
|
||||
// }
|
||||
//
|
||||
// internal static int Cbit(uint u) {
|
||||
// u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
|
||||
// u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
|
||||
// u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
|
||||
// u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
|
||||
// return (int)((ushort)u + (ushort)(u >> 16));
|
||||
// }
|
||||
//
|
||||
// static int Cbit(ulong uu) {
|
||||
// uu = (uu & 0x5555555555555555) + ((uu >> 1) & 0x5555555555555555);
|
||||
// uu = (uu & 0x3333333333333333) + ((uu >> 2) & 0x3333333333333333);
|
||||
// uu = (uu & 0x0F0F0F0F0F0F0F0F) + ((uu >> 4) & 0x0F0F0F0F0F0F0F0F);
|
||||
// uu = (uu & 0x00FF00FF00FF00FF) + ((uu >> 8) & 0x00FF00FF00FF00FF);
|
||||
// uu = (uu & 0x0000FFFF0000FFFF) + ((uu >> 16) & 0x0000FFFF0000FFFF);
|
||||
// return (int)((uint)uu + (uint)(uu >> 32));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
35
runtime/VMProtect.Runtime/Properties/AssemblyInfo.cs
Normal file
35
runtime/VMProtect.Runtime/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("VMProtect.Runtime")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("VMProtect.Runtime")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("544f194e-b3a9-40a8-8f75-bd12b10868bf")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
65
runtime/VMProtect.Runtime/StringManager.cs
Normal file
65
runtime/VMProtect.Runtime/StringManager.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public class StringManager
|
||||
{
|
||||
public StringManager(long instance)
|
||||
{
|
||||
_instance = instance;
|
||||
var key = new byte[8];
|
||||
Marshal.Copy(new IntPtr(_instance + (uint)Faces.KEY_INFO), key, 0, key.Length);
|
||||
_cipher = new CipherRC5(key);
|
||||
_entries = new Dictionary<uint, uint>();
|
||||
_key = BitConverter.ToUInt32(key, 0);
|
||||
|
||||
var startPosition = (uint)Faces.STRING_INFO;
|
||||
// DecryptDirectory
|
||||
var directory = new byte[8];
|
||||
Marshal.Copy(new IntPtr(_instance + startPosition), directory, 0, directory.Length);
|
||||
directory = _cipher.Decrypt(directory);
|
||||
var numberOfEntries = BitConverter.ToUInt32(directory, 0);
|
||||
|
||||
var entry = new byte[16];
|
||||
for (uint i = 0; i < numberOfEntries; i++)
|
||||
{
|
||||
// DecryptEntry
|
||||
uint pos = startPosition + 8 + i * 16;
|
||||
Marshal.Copy(new IntPtr(_instance + pos), entry, 0, 16);
|
||||
entry = _cipher.Decrypt(entry);
|
||||
_entries.Add(BitConverter.ToUInt32(entry, 0), pos);
|
||||
}
|
||||
}
|
||||
|
||||
public string DecryptString(uint stringId)
|
||||
{
|
||||
uint pos;
|
||||
if (_entries.TryGetValue(stringId, out pos))
|
||||
{
|
||||
var entry = new byte[16];
|
||||
Marshal.Copy(new IntPtr(_instance + pos), entry, 0, 16);
|
||||
entry = _cipher.Decrypt(entry);
|
||||
|
||||
var size = BitConverter.ToInt32(entry, 8);
|
||||
var stringData = new byte[size];
|
||||
Marshal.Copy(new IntPtr(_instance + BitConverter.ToUInt32(entry, 4)), stringData, 0, size);
|
||||
for (var c = 0; c < size; c++)
|
||||
{
|
||||
stringData[c] = (byte)(stringData[c] ^ BitRotate.Left(_key, c) + c);
|
||||
}
|
||||
return Encoding.Unicode.GetString(stringData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private readonly long _instance;
|
||||
private readonly CipherRC5 _cipher;
|
||||
private readonly Dictionary<uint, uint> _entries;
|
||||
private readonly uint _key;
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using VMProtect;
|
||||
|
||||
namespace UnitTestProject
|
||||
{
|
||||
[TestClass]
|
||||
public class LicensingManagerTests
|
||||
{
|
||||
private class Data
|
||||
{
|
||||
public void PushByte(byte b) { _data.Add(b); }
|
||||
//void PushDWord(int d) { PushBuff(BitConverter.GetBytes(d)); }
|
||||
/*void PushQWord(ulong q) { PushBuff(&q, sizeof(q)); }
|
||||
void PushWord(ushort w) { PushBuff(&w, sizeof(w)); }*/
|
||||
public void PushBuff(byte[] buff)
|
||||
{
|
||||
_data.AddRange(buff);
|
||||
}
|
||||
/*public void InsertByte(int position, byte value)
|
||||
{
|
||||
_data.Insert(position, value);
|
||||
}*/
|
||||
|
||||
/*uint32_t ReadDWord(size_t nPosition) const
|
||||
{
|
||||
return *reinterpret_cast<const uint32_t *>(&m_vData[nPosition]);
|
||||
}*/
|
||||
|
||||
public void WriteDWord(int position, int value)
|
||||
{
|
||||
foreach (var b in BitConverter.GetBytes(value))
|
||||
{
|
||||
_data[position++] = b;
|
||||
}
|
||||
}
|
||||
|
||||
public int Size => _data.Count;
|
||||
//public void clear() { _data.Clear(); }
|
||||
//public bool empty() { return _data.Count == 0; }
|
||||
//void resize(int size) { _data.resize(size); }
|
||||
//void resize(int size, uint8_t value) { m_vData.resize(size, value); }
|
||||
public byte[] ToArray() { return _data.ToArray(); }
|
||||
|
||||
private readonly List<byte> _data;
|
||||
|
||||
public Data(int sz)
|
||||
{
|
||||
_data = new List<byte>(new byte[sz]);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ParseSerial()
|
||||
{
|
||||
//var key = new byte[] {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
var data = new Data(sizeof(uint) * (int)LicensingManager.Fields.Count);
|
||||
|
||||
var publicExp = Convert.FromBase64String("AAEAAQ==");
|
||||
var modulus = Convert.FromBase64String("pwUqwaM8IOukyx06Lvi5YNQ70JE7pwg7K+pmM/vCe1CUseHKFM1v1m11geDjVsAt38AnaiFs3JhtTs80ySCIxOSyvMw6Cd52k6N6dn7LAx1mxQLJLhYeMMJYbplMHnMLwYN0+IO58OVbEqRyaJV2ExolnK2EYZL7QRXujGY7/sOoOMF3p6GsWJK6kkBJICIoL9hHWBQMO6/9rmls/+EhaWuP80Vx0+H2OlrQ58K+TJeyE393cvb4QufiEPpCNaB50Klee9QUnsjSW/bTnmGn4Bi5+cowRbawUY73Q5I58fMAXiH9ueDPuNMR9YKDgW9GxunLmYkbuwqIp/v7kw3cfMBM0ihhB0B8UhjyAMAGLzJWX3H/H6Zrz41g9PbPjTAxfsTaCrxoqjaTaO4zk9YsI//VX9Fhivcy913SevBpNandziGfYH/oHW2xDy9AfwkE1wuIBlLj7c/k8U1YmmRAmkoCzlmB7EU4ClNltboh1uARUQ6wW30upppnuYhGkTy7");
|
||||
var black = Convert.FromBase64String("A7zybXsboP8UVQ4x8mCSPVlm4W8G2gMbKOiLDFIX28dpdl6AzdqGCxIeiXRfaPBgeGeyL1BB+3pLVJ9SGkjc/BXy1hYkjJCwacADVEWoR14blpa3hdx+R/WHe8uhS9ShV1hxviIKRt4UJbIjyqH7tMu2p8KuVbB0IwM0dFPnVujgNmNN2/BeOQl/RFMmD+TpLzFHetvt0Dx7rk8MKINv3SoyL97QWNvwCbL35JIZN5DtMdZ3MfO/fxz/1kSTNbccciqEljRiC74zMsNz2LNkf1hwxES96yGBsd2oOTe+DJx43j8iZ7UD75iwIGKoPxysOYnHTewT2ofK9d6SMl4rIyxt6TI+KzXppRyhVieHtEIo9/NIm7ABnkLTJvy4tjFftPocJP3E5v9ra8YBQ2y3PKz04BkesCeKiVPyBqy9phxHtjKpIimlm73GSfDMVZ+xgLsn/Ui6XSW8kB8ai+rEA1KFosfmsVPASiuXJAHJaNfY4ULKZWOfGcoPDh1KjhmFq7INiQaMy+rml/EiKv4p9k3vomv41ll5IoIVkxZaMY8Gtkl5UYWWJUMlJgphM9+LOkWCLX1fm7ZUiJbfHkmVTTFZ6SxhxoeO73yovFdt37I/17tbM0jjQjC1Q172ZPQmWPBP2NaPTXglJdkSKWYWw8pG6EJh+eRrfZ1USmdkU2TI0FUDSwJ2F2RSkObaDx4WFrBz0xddLmEl0XEJaQI/TTRZk5hQB/20NPzavgiAQ39p62LR7hZTqnR4zshiFv2sChe4x2p4XzBx4NKx1Zw6QaZrfwX47R3dc2K80jHIisj9Ltnr3qUgr5S0Nbp6+8BKB6RFcPuPAi24SVh7e5KgvoKNB/FzJqZnE9FCiryEeRbRwU26g3l+orZTM/jm1niFKlgrvdRweVqVza4JBnbeTGF2t8PstMH6Vx4+gpoJWyoQY6acm5MSFyl2DLXCcd6MmoRyp30Ge209zoOjj7c5PGRYxjiiUO04gaGhh7YyUp7VTHmd2llSQaKhsyw/7k3OqEKTinSRmdiDNsmfp8fOqtd388jGyhME6zzda8u1Ex6uvHkrk2arjVSeQk3XED4ZPqyRbLDZYGZcp9HheDdciX56rK39NTXetOWN8p4KW6aMa91EUTaCiafQVhO6dYzO+1ybRjOR7ND7nOnt9zUEerzNbIkCFT6uGTqtue0FZe4Zxunlv9D1mA4266xWfZfIPSzXD2cVAerBjr2BtYHOolDP1dRu1JcPwXGxOMiDL76x1NghovHsQxlwcfWT9CO+ywvhEkiwirt0UsTbACSslWD2sNLTdQ1aLNkqM9FjJzN7uKHk/J4OZtmNFRsxxZUvWYKYb/+q93FEsbMr5YfSPLlezvf6fL3k6tSKB5sFuk/rsgeBQYOwUGIKDRc8c0yNd8kEXOxvmzCGEv2/95Lh7XxXEUaHYKki7TR73v+H6pIiYmTOHg/Z9F4OjzHxb6HIUq6bzNywpzguJjBKqhnoRfJMwBr9P3NQ+CU5VaBXwxTlMWtW9Ihou7a+Hio34w2YGYdtr8BzMjT03VrAOtLH4V0HZj/UTAkTFaGDK/bdOAYXH/fz9GVBVU94hB86ii4e9ulYanZkiRJMDwTlNTup5jRVAR7/nM4H0Q0evDGRo7k4IP5CtLb6fg==");
|
||||
|
||||
data.WriteDWord((int)LicensingManager.Fields.PublicExpOffset * sizeof(uint), data.Size);
|
||||
data.WriteDWord((int)LicensingManager.Fields.PublicExpSize * sizeof(uint), publicExp.Length);
|
||||
data.PushBuff(publicExp);
|
||||
|
||||
data.WriteDWord((int)LicensingManager.Fields.ModulusOffset * sizeof(uint), data.Size);
|
||||
data.WriteDWord((int)LicensingManager.Fields.ModulusSize * sizeof(uint), modulus.Length);
|
||||
data.PushBuff(modulus);
|
||||
|
||||
data.WriteDWord((int)LicensingManager.Fields.BlacklistOffset * sizeof(uint), data.Size);
|
||||
data.WriteDWord((int)LicensingManager.Fields.BlacklistSize * sizeof(uint), black.Length);
|
||||
data.PushBuff(black);
|
||||
|
||||
var crcPos = data.Size;
|
||||
data.WriteDWord((int)LicensingManager.Fields.CRCOffset * sizeof(uint), crcPos);
|
||||
var size = crcPos + 16;
|
||||
|
||||
using (var hash = new SHA1Managed())
|
||||
{
|
||||
var p = hash.ComputeHash(data.ToArray());
|
||||
for (var i = crcPos; i < size; i++)
|
||||
{
|
||||
data.PushByte(p[i - crcPos]);
|
||||
}
|
||||
}
|
||||
|
||||
var licensingManager = new LicensingManager(data.ToArray());
|
||||
Assert.AreEqual(SerialState.Blacklisted, licensingManager.SetSerialNumber("H2GfYz579KQ5poUTxKRWsUd7o+1XSwaJrK7CmwG15rNuo3Wa+vy660rJkRaWTrELbyyIe2k15973P13WJvxDR8myQCMi8Pv9D9k9iblCTAZL9vOcX55g2Vk4i+x+DEDn601kjvkL7RvHug1SYq6GqKm4dnApwlGvbnSebSDwrhh0E5g9I/XA5pa7hQUQwcBoXq6A7e7Blj8FbJ1JBdYUJY7RavgFE9KYfTXn5ceCwPr0gR3A++W66amQdxWnFxyyOFwfCPuZDk+LCgqqAgMyj5PRPcLA3nanXLDLPGva1wa1EEP0qvx6yCSpDURP94GxQGY1xjPlZagbuLaYyWn7bb/sLsYNXVHE1a+YNFORn890tbZ1D6i+wTEa254oF3yKa5GYTQmRWJQR+OXqaTK/wNG4y8dAUisOmQpevrSrD7pQj7ZLGOChmw+KWB6SozSHtIMY665ji9tMP8mq8OUSVSZ9N9q3Zh/xnW0W8sGck5IzTr3JtT0a3iOXSYfijpmy"));
|
||||
Assert.AreEqual(SerialState.Blacklisted, licensingManager.GetSerialNumberState());
|
||||
var snd = new SerialNumberData();
|
||||
Assert.IsTrue(licensingManager.GetSerialNumberData(snd));
|
||||
Assert.AreEqual("", snd.EMail); //a20071234@163.com
|
||||
Assert.AreEqual("", snd.UserName); //Su Ying
|
||||
Assert.AreEqual(DateTime.MaxValue, snd.Expires);
|
||||
Assert.AreEqual(DateTime.MaxValue, snd.MaxBuild);
|
||||
Assert.AreEqual(0, snd.RunningTime);
|
||||
Assert.AreEqual(SerialState.Blacklisted, snd.State);
|
||||
Assert.AreEqual(0, snd.UserData.Length);
|
||||
|
||||
Assert.AreEqual(SerialState.Success, licensingManager.SetSerialNumber("V5z/4JRVkIhN/D7KkHUBfM2ww3VMxq4r7SgRViTG840294nBiqLer9QUyuX/oyS5sxwzgtMruYYK2n8PvrilVRhFj3rgoK67V + 0 / kJxNmypnWY + PbNurXbimp8KfTF6aOydLQyo26M2iRJhnPCXXInXB4QMi5dPNf41cdVelwt + C5hSfV7zPeJZRLbWv + AMScBJEmy1AW3AWUokfHUMSonq75LxBc3jLnDESz8UGTNWrIXSEiRjrueszSM7uGEmWemUjS + MzgL + F + DfsKNTc2KTEctprxQmxcJZsN4rZS0q8UJo3eA0HXgrrFlxYkLqgcq + 8 / 018W3l79nR17ZDQsUuJFfrElY8F6OGtbis2j9YyCszcWoKQLB3bSgWrKXPAlrEN4VuxMk0wbq + sYZLIt / npAmFheE7wHhnN1PubK84BpQFZKnkrIrsC43PJ2ss2WOQl / vqTxhTbbDyPEE69NW8R + fUanth5sglfableZjt4WH + hwgiGL + D8wHQlWgT7"));
|
||||
Assert.AreEqual(SerialState.Success, licensingManager.GetSerialNumberState());
|
||||
Assert.IsTrue(licensingManager.GetSerialNumberData(snd));
|
||||
Assert.AreEqual("jleber@onvisionnetworks.com", snd.EMail);
|
||||
Assert.AreEqual("Onvision Networks Limited", snd.UserName);
|
||||
Assert.AreEqual(DateTime.MaxValue, snd.Expires);
|
||||
Assert.AreEqual(new DateTime(2017, 4, 11), snd.MaxBuild);
|
||||
Assert.AreEqual(0, snd.RunningTime);
|
||||
Assert.AreEqual(SerialState.Success, snd.State);
|
||||
Assert.AreEqual(1, snd.UserData.Length);
|
||||
CollectionAssert.AreEqual(snd.UserData, new byte[] {4});
|
||||
}
|
||||
|
||||
/*[TestMethod]
|
||||
public void ParseSerialTimeLimitedHWID()
|
||||
{
|
||||
//TODO
|
||||
}*/
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using VMProtect;
|
||||
|
||||
namespace UnitTestProject
|
||||
{
|
||||
[TestClass]
|
||||
public class LoaderTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void LzmaDecode()
|
||||
{
|
||||
byte[] properties =
|
||||
{
|
||||
0x5d, 0, 0, 0, 1 // 5 bytes props
|
||||
};
|
||||
byte[] src =
|
||||
{
|
||||
0x00, 0x4e, 0x3a, 0x46, 0xeb, 0xe0, 0x06, 0x71, 0xc9, 0xe1,
|
||||
0xe6, 0x37, 0xfd, 0x9b, 0xb6, 0xd0, 0x76, 0x3f, 0xc8, 0x73,
|
||||
0xee, 0x11, 0xb6, 0x41, 0xaa, 0xb1, 0x7b, 0x7b, 0xef, 0xc6,
|
||||
0x9f, 0xff, 0xf6, 0x1d, 0x28, 0x00 //36 bytes packed
|
||||
};
|
||||
byte [] dstExpected = { 0x9c, 0xe9, 0x57, 0xbe, 0x00, 0x00, 0xc3, 0xe9, 0x24, 0x2c, 0x01, 0x00, 0xe9, 0xef, 0x65, 0x00, 0x00, 0xe9, 0xc0, 0x41, 0x06, 0x00, 0xc3, 0x56, 0x57 };
|
||||
var pinnedSrc = GCHandle.Alloc(src, GCHandleType.Pinned);
|
||||
uint dstSize = 65536;
|
||||
var dstPtr = Marshal.AllocHGlobal((int)dstSize);
|
||||
try
|
||||
{
|
||||
dstSize = int.MaxValue;
|
||||
uint srcSize /*= (uint)src.Length*/;
|
||||
var res = Loader.LzmaDecode(dstPtr, pinnedSrc.AddrOfPinnedObject(), properties, ref dstSize, out srcSize);
|
||||
Assert.AreEqual(true, res);
|
||||
Assert.AreEqual(dstExpected.Length, (int)dstSize);
|
||||
var dst = new byte[dstSize];
|
||||
Marshal.Copy(dstPtr, dst, 0, (int)dstSize);
|
||||
CollectionAssert.AreEqual(dstExpected, dst);
|
||||
Assert.AreEqual(src.Length, (int)srcSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
pinnedSrc.Free();
|
||||
Marshal.FreeHGlobal(dstPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTestProject
|
||||
{
|
||||
public abstract class MsilToVmTestCompiler
|
||||
{
|
||||
public enum LongEnum : long { Eval1 = 1, Evalm1 = -1 }
|
||||
public enum ULongEnum : ulong { Evalm1 = 0xFFFFFFFFFFFFFFFF }
|
||||
public enum ByteEnum : byte {}
|
||||
public enum SByteEnum : sbyte { }
|
||||
public enum IntEnum /*: int*/ { }
|
||||
public enum UIntEnum : uint { }
|
||||
public enum ShortEnum : short { }
|
||||
public enum UShortEnum : ushort { }
|
||||
|
||||
public static byte[] GetIlBytes(DynamicMethod dynamicMethod)
|
||||
{
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
|
||||
if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
return (byte[])resolver.GetType().GetField("m_code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(resolver);
|
||||
}
|
||||
|
||||
public abstract Stream CreateVmStream(Type rt, ParameterInfo[] pi, Type[] locals, byte[] ilBytes);
|
||||
|
||||
public enum InvokeTestCombineError
|
||||
{
|
||||
NoError,
|
||||
NoErrorByStdEx, // текущий стандарт ECMA-335 оставляет некоторые сценарии как "неопределенное поведение", но их можно определить
|
||||
VmOtherExceptionExpected,
|
||||
VmOtherTypeExpected,
|
||||
VmOtherValueExpected,
|
||||
Cnt
|
||||
};
|
||||
// dyn/vm обязаны что-то возвратить, либо выбросить исключение
|
||||
// (в тестах не должно быть методов, возвращающих void, null или исключение в качестве retVal)
|
||||
[HandleProcessCorruptedStateExceptions]
|
||||
public InvokeTestCombineError InvokeTestCombine(DynamicMethod dyn, object[] parameters, out object dynRet, out object vmRet, out string err)
|
||||
{
|
||||
Type exceptionType = null;
|
||||
err = "";
|
||||
try
|
||||
{
|
||||
dynRet = dyn.Invoke(null, parameters);
|
||||
Assert.IsNotNull(dynRet);
|
||||
Assert.IsInstanceOfType(dynRet, dyn.ReturnType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Assert.IsInstanceOfType(e, typeof(TargetInvocationException));
|
||||
Assert.IsNotNull(e.InnerException);
|
||||
exceptionType = e.InnerException.GetType();
|
||||
dynRet = e.InnerException;
|
||||
}
|
||||
var vmStream = CreateVmStream(dyn.ReturnType, dyn.GetBaseDefinition().GetParameters(),
|
||||
//FIXME dyn.GetMethodBody().LocalVariables.Select(o => o.LocalType).ToArray(),
|
||||
new Type[] {},
|
||||
GetIlBytes(dyn));
|
||||
try
|
||||
{
|
||||
vmRet = Invoke(parameters, vmStream);
|
||||
if(exceptionType != null)
|
||||
{
|
||||
err = $"VmOtherExceptionExpected: {exceptionType.FullName}, actual: {vmRet}";
|
||||
return InvokeTestCombineError.VmOtherExceptionExpected;
|
||||
}
|
||||
if (vmRet == null || vmRet.GetType() != dyn.ReturnType)
|
||||
{
|
||||
err = $"VmOtherTypeExpected: {dyn.ReturnType.FullName}, actual: {((vmRet != null) ? vmRet.GetType().FullName : "null")}";
|
||||
return InvokeTestCombineError.VmOtherTypeExpected;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
vmRet = e;
|
||||
if (e.GetType() != exceptionType)
|
||||
{
|
||||
err = $"VmOtherExceptionExpected: {((exceptionType != null) ? exceptionType.FullName : dynRet)}, actual: {e.GetType().FullName}";
|
||||
return InvokeTestCombineError.VmOtherExceptionExpected;
|
||||
}
|
||||
return InvokeTestCombineError.NoError;
|
||||
}
|
||||
if (dynRet.Equals(vmRet))
|
||||
{
|
||||
return InvokeTestCombineError.NoError;
|
||||
}
|
||||
err = $"VmOtherValueExpected: {dynRet}, actual: {vmRet}";
|
||||
return InvokeTestCombineError.VmOtherValueExpected;
|
||||
}
|
||||
|
||||
public abstract object Invoke(object[] parameters, Stream vmStream);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("UnitTestProject")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("UnitTestProject")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("aefca063-245a-4d50-a5a3-82188ce677fa")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000048 RID: 72
|
||||
internal static class ElementedTypeHelper // \u0008\u2005
|
||||
{
|
||||
// Token: 0x06000307 RID: 775 RVA: 0x000148D8 File Offset: 0x00012AD8
|
||||
public static Type TryGoToElementType(Type t) // \u0002
|
||||
{
|
||||
if (t.IsByRef || t.IsArray || t.IsPointer)
|
||||
{
|
||||
return TryGoToElementType(t.GetElementType());
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
// Token: 0x06000308 RID: 776 RVA: 0x00014900 File Offset: 0x00012B00
|
||||
public static Type TryGoToPointerOrReferenceElementType(Type t) // \u0003
|
||||
{
|
||||
if (t.HasElementType && !t.IsArray)
|
||||
{
|
||||
t = t.GetElementType();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
// Token: 0x06000309 RID: 777 RVA: 0x00014920 File Offset: 0x00012B20
|
||||
public static MyCollection<ElementedTypeDescrItem> NestedElementTypes(Type type) // \u0002
|
||||
{
|
||||
var collection = new MyCollection<ElementedTypeDescrItem>();
|
||||
while (true)
|
||||
{
|
||||
Debug.Assert(type != null, "type != null");
|
||||
if(type == null) return collection;
|
||||
if (type.IsArray)
|
||||
{
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.Array1,
|
||||
ArrayRank = type.GetArrayRank()
|
||||
});
|
||||
}
|
||||
else if (type.IsByRef)
|
||||
{
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.ByRef2
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!type.IsPointer)
|
||||
{
|
||||
break;
|
||||
}
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.Ponter0
|
||||
});
|
||||
}
|
||||
type = type.GetElementType();
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
// Token: 0x0600030A RID: 778 RVA: 0x000149B0 File Offset: 0x00012BB0
|
||||
public static MyCollection<ElementedTypeDescrItem> NestedElementTypes(string text) // \u0002
|
||||
{
|
||||
var collection = new MyCollection<ElementedTypeDescrItem>();
|
||||
while (true)
|
||||
{
|
||||
if (text.EndsWith(StringDecryptor.GetString(-1550346966) /* & */, StringComparison.Ordinal))
|
||||
{
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.ByRef2
|
||||
});
|
||||
text = text.Substring(0, text.Length - 1);
|
||||
}
|
||||
else if (text.EndsWith(StringDecryptor.GetString(-1550346958) /* * */, StringComparison.Ordinal))
|
||||
{
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.Ponter0
|
||||
});
|
||||
text = text.Substring(0, text.Length - 1);
|
||||
}
|
||||
else if (text.EndsWith(StringDecryptor.GetString(-1550346950) /* [] */, StringComparison.Ordinal))
|
||||
{
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.Array1,
|
||||
ArrayRank = 1
|
||||
});
|
||||
text = text.Substring(0, text.Length - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!text.EndsWith(StringDecryptor.GetString(-1550346811) /* ,] */, StringComparison.Ordinal))
|
||||
{
|
||||
return collection;
|
||||
}
|
||||
var rank = 1;
|
||||
var remainLen = -1;
|
||||
for (var i = text.Length - 2; i >= 0; i--)
|
||||
{
|
||||
var c = text[i];
|
||||
if (c != ',')
|
||||
{
|
||||
if (c != '[')
|
||||
{
|
||||
throw new InvalidOperationException(StringDecryptor.GetString(-1550346804) /* VM-3012 */);
|
||||
}
|
||||
remainLen = i;
|
||||
i = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rank++;
|
||||
}
|
||||
}
|
||||
if (remainLen < 0)
|
||||
{
|
||||
throw new InvalidOperationException(StringDecryptor.GetString(-1550346790) /* VM-3014 */);
|
||||
}
|
||||
text = text.Substring(0, remainLen);
|
||||
collection.PushBack(new ElementedTypeDescrItem
|
||||
{
|
||||
K = ElementedTypeDescrItem.Kind.Array1,
|
||||
ArrayRank = rank
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0600030B RID: 779 RVA: 0x00014B30 File Offset: 0x00012D30
|
||||
public static Type PopType(Type type, MyCollection<ElementedTypeDescrItem> descr) // \u0002
|
||||
{
|
||||
while (descr.Count > 0)
|
||||
{
|
||||
var p = descr.PopBack();
|
||||
switch (p.K)
|
||||
{
|
||||
case ElementedTypeDescrItem.Kind.Ponter0:
|
||||
type = type.MakePointerType();
|
||||
break;
|
||||
case ElementedTypeDescrItem.Kind.Array1:
|
||||
type = (p.ArrayRank == 1) ? type.MakeArrayType() : type.MakeArrayType(p.ArrayRank);
|
||||
break;
|
||||
case ElementedTypeDescrItem.Kind.ByRef2:
|
||||
type = type.MakeByRefType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000054 RID: 84
|
||||
internal struct ElementedTypeDescrItem // \u000E\u2005
|
||||
{
|
||||
internal enum Kind { Ponter0, Array1, ByRef2 }
|
||||
|
||||
// Token: 0x04000183 RID: 387
|
||||
public Kind K; // \u0002
|
||||
|
||||
// Token: 0x04000184 RID: 388
|
||||
public int ArrayRank; // \u0003
|
||||
}
|
||||
}
|
@ -0,0 +1,569 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000024 RID: 36
|
||||
internal sealed class MyBuffer : IDisposable // \u0005\u2007
|
||||
{
|
||||
// Token: 0x060000F2 RID: 242 RVA: 0x000051C8 File begin: 0x000033C8
|
||||
public MyBuffer() : this(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x060000F3 RID: 243 RVA: 0x000051D4 File begin: 0x000033D4
|
||||
public MyBuffer(int sz)
|
||||
{
|
||||
if (sz < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_data = new byte[sz];
|
||||
_size = sz;
|
||||
_internal = true;
|
||||
_writable = true;
|
||||
_begin = 0;
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
// Token: 0x060000F4 RID: 244 RVA: 0x00005220 File begin: 0x00003420
|
||||
public MyBuffer(byte[] src) : this(src, true)
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x060000F5 RID: 245 RVA: 0x0000522C File begin: 0x0000342C
|
||||
public MyBuffer(byte[] src, bool writable)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
_data = src;
|
||||
_end = (_size = src.Length);
|
||||
_writable = writable;
|
||||
_begin = 0;
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
// Token: 0x060000F6 RID: 246 RVA: 0x00005278 File begin: 0x00003478
|
||||
public MyBuffer(byte[] src, int begin, int count) : this(src, begin, count, true)
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x060000F7 RID: 247 RVA: 0x00005284 File begin: 0x00003484
|
||||
public MyBuffer(byte[] src, int begin, int count, bool writable)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (begin < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (src.Length - begin < count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
_data = src;
|
||||
_cursor = begin;
|
||||
_begin = begin;
|
||||
_end = (_size = begin + count);
|
||||
_writable = writable;
|
||||
_internal = false;
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
// Token: 0x060000F8 RID: 248 RVA: 0x00005304 File begin: 0x00003504
|
||||
public bool IsValid() // \u0002
|
||||
{
|
||||
return _valid;
|
||||
}
|
||||
|
||||
// Token: 0x060000F9 RID: 249 RVA: 0x0000530C File begin: 0x0000350C
|
||||
public bool IsValid2() // \u0003
|
||||
{
|
||||
return _valid;
|
||||
}
|
||||
|
||||
// Token: 0x060000FA RID: 250 RVA: 0x00005314 File begin: 0x00003514
|
||||
public bool IsWritable() // \u0005
|
||||
{
|
||||
return _writable;
|
||||
}
|
||||
|
||||
// Token: 0x060000FB RID: 251 RVA: 0x0000531C File begin: 0x0000351C
|
||||
public void DoDispose() // \u0002
|
||||
{
|
||||
Dispose(true);
|
||||
// ReSharper disable once GCSuppressFinalizeForTypeWithoutDestructor
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Token: 0x060000FC RID: 252 RVA: 0x0000532C File begin: 0x0000352C
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
// Token: 0x060000FD RID: 253 RVA: 0x00005334 File begin: 0x00003534
|
||||
private void Dispose(bool disposing) // \u0002
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_valid = false;
|
||||
_writable = false;
|
||||
_internal = false;
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000FE RID: 254 RVA: 0x00005360 File begin: 0x00003560
|
||||
private bool Expand(int newSize) // \u0002
|
||||
{
|
||||
if (newSize < 0)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
if (newSize > _size)
|
||||
{
|
||||
if (newSize < 256)
|
||||
{
|
||||
newSize = 256;
|
||||
}
|
||||
if (newSize < _size * 2)
|
||||
{
|
||||
newSize = _size * 2;
|
||||
}
|
||||
ExpandExact(newSize);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Token: 0x060000FF RID: 255 RVA: 0x000053B0 File begin: 0x000035B0
|
||||
public void DoNothing() // \u0003
|
||||
{}
|
||||
|
||||
// Token: 0x06000100 RID: 256 RVA: 0x000053B4 File begin: 0x000035B4
|
||||
internal byte[] Data() // \u0002
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
// Token: 0x06000101 RID: 257 RVA: 0x000053BC File begin: 0x000035BC
|
||||
internal void GetRanges(out int begin, out int end) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
begin = _begin;
|
||||
end = _end;
|
||||
}
|
||||
|
||||
// Token: 0x06000102 RID: 258 RVA: 0x000053DC File begin: 0x000035DC
|
||||
internal int GetCursor() // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return _cursor;
|
||||
}
|
||||
|
||||
// Token: 0x06000103 RID: 259 RVA: 0x000053F4 File begin: 0x000035F4
|
||||
public int SkipBytes(int cnt) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
var num = _end - _cursor;
|
||||
if (num > cnt)
|
||||
{
|
||||
num = cnt;
|
||||
}
|
||||
if (num < 0)
|
||||
{
|
||||
num = 0;
|
||||
}
|
||||
_cursor += num;
|
||||
return num;
|
||||
}
|
||||
|
||||
// Token: 0x06000104 RID: 260 RVA: 0x00005438 File begin: 0x00003638
|
||||
public int Capacity() // \u0003
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return _size - _begin;
|
||||
}
|
||||
|
||||
// Token: 0x06000105 RID: 261 RVA: 0x00005458 File begin: 0x00003658
|
||||
public void ExpandExact(int newSize) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (newSize != _size)
|
||||
{
|
||||
if (!_internal)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (newSize < _end)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (newSize > 0)
|
||||
{
|
||||
var dst = new byte[newSize];
|
||||
if (_end > 0)
|
||||
{
|
||||
Buffer.BlockCopy(_data, 0, dst, 0, _end);
|
||||
}
|
||||
_data = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
_data = null;
|
||||
}
|
||||
_size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x06000106 RID: 262 RVA: 0x000054D8 File begin: 0x000036D8
|
||||
public long UsedSize() // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return _end - _begin;
|
||||
}
|
||||
|
||||
// Token: 0x06000107 RID: 263 RVA: 0x000054F8 File begin: 0x000036F8
|
||||
public long GetPos() // \u0003
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return _cursor - _begin;
|
||||
}
|
||||
|
||||
// Token: 0x06000108 RID: 264 RVA: 0x00005518 File begin: 0x00003718
|
||||
public void SetPos(long newPos) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (newPos < 0L)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (newPos > 2147483647L)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
_cursor = _begin + (int)newPos;
|
||||
}
|
||||
|
||||
// Token: 0x06000109 RID: 265 RVA: 0x00005554 File begin: 0x00003754
|
||||
public int Read([In] [Out] byte[] dest, int offset, int cnt) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (cnt < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (dest.Length - offset < cnt)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
var num = _end - _cursor;
|
||||
if (num > cnt)
|
||||
{
|
||||
num = cnt;
|
||||
}
|
||||
if (num <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (num <= 8)
|
||||
{
|
||||
var num2 = num;
|
||||
while (--num2 >= 0)
|
||||
{
|
||||
dest[offset + num2] = _data[_cursor + num2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(_data, _cursor, dest, offset, num);
|
||||
}
|
||||
_cursor += num;
|
||||
return num;
|
||||
}
|
||||
|
||||
// Token: 0x0600010A RID: 266 RVA: 0x00005600 File begin: 0x00003800
|
||||
public int ReadByte() // \u0005
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (_cursor >= _end)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
var num = _cursor;
|
||||
_cursor = num + 1;
|
||||
return _data[num];
|
||||
}
|
||||
|
||||
// Token: 0x0600010B RID: 267 RVA: 0x00005644 File begin: 0x00003844
|
||||
public long Seek(long distance, SeekOrigin org) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (distance > 2147483647L)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
switch (org)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
if (distance < 0L)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
_cursor = _begin + (int)distance;
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
if (distance + _cursor < _begin)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
_cursor += (int)distance;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
if (_end + distance < _begin)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
_cursor = _end + (int)distance;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException();
|
||||
}
|
||||
return _cursor;
|
||||
}
|
||||
|
||||
// Token: 0x0600010C RID: 268 RVA: 0x00005700 File begin: 0x00003900
|
||||
public void LazyShrink(long newCount) // \u0003
|
||||
{
|
||||
if (!_writable)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (newCount > 2147483647L)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (newCount < 0L || newCount > 2147483647 - _begin)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
var num = _begin + (int)newCount;
|
||||
if (!Expand(num) && num > _end)
|
||||
{
|
||||
Array.Clear(_data, _end, num - _end);
|
||||
}
|
||||
_end = num;
|
||||
if (_cursor > num)
|
||||
{
|
||||
_cursor = num;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0600010D RID: 269 RVA: 0x00005794 File begin: 0x00003994
|
||||
public byte[] ToArray() // \u0003
|
||||
{
|
||||
var array = new byte[_end - _begin];
|
||||
Buffer.BlockCopy(_data, _begin, array, 0, _end - _begin);
|
||||
return array;
|
||||
}
|
||||
|
||||
// Token: 0x0600010E RID: 270 RVA: 0x000057D8 File begin: 0x000039D8
|
||||
public void Write(byte[] src, int offset, int cnt) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (!_writable)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (src == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (cnt < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (src.Length - offset < cnt)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
var num = _cursor + cnt;
|
||||
if (num < 0)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
if (num > _end)
|
||||
{
|
||||
var flag = _cursor > _end;
|
||||
if (num > _size && Expand(num))
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
Array.Clear(_data, _end, num - _end);
|
||||
}
|
||||
_end = num;
|
||||
}
|
||||
if (cnt <= 8)
|
||||
{
|
||||
while (--cnt >= 0)
|
||||
{
|
||||
_data[_cursor + cnt] = src[offset + cnt];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(src, offset, _data, _cursor, cnt);
|
||||
}
|
||||
_cursor = num;
|
||||
}
|
||||
|
||||
// Token: 0x0600010F RID: 271 RVA: 0x000058D0 File begin: 0x00003AD0
|
||||
public void AppendByte(byte b) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (!_writable)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (_cursor >= _end)
|
||||
{
|
||||
var num = _cursor + 1;
|
||||
var flag = _cursor > _end;
|
||||
if (num >= _size && Expand(num))
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
Array.Clear(_data, _end, _cursor - _end);
|
||||
}
|
||||
_end = num;
|
||||
}
|
||||
_data[_cursor] = b;
|
||||
_cursor++;
|
||||
}
|
||||
|
||||
// Token: 0x06000110 RID: 272 RVA: 0x00005974 File begin: 0x00003B74
|
||||
public void WriteTo(Stream s) // \u0002
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (s == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
s.Write(_data, _begin, _end - _begin);
|
||||
}
|
||||
|
||||
// Token: 0x06000111 RID: 273 RVA: 0x000059AC File begin: 0x00003BAC
|
||||
internal int ReadInt32() // \u0008
|
||||
{
|
||||
if (!_valid)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
var num = _cursor += 4;
|
||||
if (num > _end)
|
||||
{
|
||||
_cursor = _end;
|
||||
throw new Exception();
|
||||
}
|
||||
return _data[num - 2] | _data[num - 3] << 24 | _data[num - 1] << 8 | _data[num - 4] << 16;
|
||||
}
|
||||
|
||||
// Token: 0x04000034 RID: 52
|
||||
private byte[] _data; // \u0002
|
||||
|
||||
// Token: 0x04000035 RID: 53
|
||||
private readonly int _begin; // \u0003
|
||||
|
||||
// Token: 0x04000036 RID: 54
|
||||
private int _cursor; // \u0005
|
||||
|
||||
// Token: 0x04000037 RID: 55
|
||||
private int _end; // \u0008
|
||||
|
||||
// Token: 0x04000038 RID: 56
|
||||
private int _size; // \u0006
|
||||
|
||||
// Token: 0x04000039 RID: 57
|
||||
private bool _internal; // \u000E
|
||||
|
||||
// Token: 0x0400003A RID: 58
|
||||
private bool _writable; // \u000F
|
||||
|
||||
// Token: 0x0400003B RID: 59
|
||||
private bool _valid; // \u0002\u2000
|
||||
|
||||
// Token: 0x0400003C RID: 60
|
||||
private bool _disposed; // \u0003\u2000
|
||||
}
|
||||
}
|
@ -0,0 +1,563 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using forms_cil;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x0200000A RID: 10
|
||||
internal sealed class MyBufferReader : IDisposable // \u0002\u2007
|
||||
{
|
||||
// Token: 0x0400000C RID: 12
|
||||
private MyBuffer _src; // \u0002
|
||||
|
||||
// Token: 0x0400000D RID: 13
|
||||
private byte[] _inputRawBuf; // \u0003
|
||||
|
||||
// Token: 0x0400000E RID: 14
|
||||
private Decoder _decoder; // \u0005
|
||||
|
||||
// Token: 0x0400000F RID: 15
|
||||
private byte[] _inputCharRawBuf; // \u0008
|
||||
|
||||
// Token: 0x04000010 RID: 16
|
||||
private char[] _inputCharsDecoded; // \u0006
|
||||
|
||||
// Token: 0x04000011 RID: 17
|
||||
private char[] _stringChunk; // \u000E
|
||||
|
||||
// Token: 0x04000012 RID: 18
|
||||
private readonly int _maxCharsIn128Bytes; // \u000F
|
||||
|
||||
// Token: 0x04000013 RID: 19
|
||||
private readonly bool _isUnicode; // \u0002\u2000
|
||||
|
||||
// Token: 0x04000014 RID: 20
|
||||
private readonly bool _alwaysTrue; // \u0003\u2000
|
||||
|
||||
// Token: 0x06000034 RID: 52 RVA: 0x000027C8 File Offset: 0x000009C8
|
||||
public MyBufferReader(MyBuffer src) : this(src, new UTF8Encoding())
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x06000035 RID: 53 RVA: 0x000027D8 File Offset: 0x000009D8
|
||||
private MyBufferReader(MyBuffer src, Encoding encoding)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (encoding == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (!src.IsValid())
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
_src = src;
|
||||
_decoder = encoding.GetDecoder();
|
||||
_maxCharsIn128Bytes = encoding.GetMaxCharCount(128);
|
||||
var num = encoding.GetMaxByteCount(1);
|
||||
if (num < 16)
|
||||
num = 16;
|
||||
_inputRawBuf = new byte[num];
|
||||
_stringChunk = null;
|
||||
_inputCharRawBuf = null;
|
||||
_isUnicode = (encoding is UnicodeEncoding);
|
||||
_alwaysTrue = (_src != null);
|
||||
}
|
||||
|
||||
// Token: 0x06000036 RID: 54 RVA: 0x00002878 File Offset: 0x00000A78
|
||||
public MyBuffer GetBuffer() // \u0002
|
||||
{
|
||||
return _src;
|
||||
}
|
||||
|
||||
// Token: 0x06000037 RID: 55 RVA: 0x00002880 File Offset: 0x00000A80
|
||||
public void Dispose() // \u0002
|
||||
{
|
||||
DoDispose(true);
|
||||
}
|
||||
|
||||
// Token: 0x06000038 RID: 56 RVA: 0x0000288C File Offset: 0x00000A8C
|
||||
private void DoDispose(bool disposing) // \u0002
|
||||
{
|
||||
if (disposing)
|
||||
_src?.DoDispose();
|
||||
_src = null;
|
||||
_inputRawBuf = null;
|
||||
_decoder = null;
|
||||
_inputCharRawBuf = null;
|
||||
_inputCharsDecoded = null;
|
||||
_stringChunk = null;
|
||||
}
|
||||
|
||||
// Token: 0x06000039 RID: 57 RVA: 0x000028E0 File Offset: 0x00000AE0
|
||||
void IDisposable.Dispose() // \u0002\u2007\u2008\u2000\u2002\u200A\u0003
|
||||
{
|
||||
DoDispose(true);
|
||||
}
|
||||
|
||||
// Token: 0x0600003A RID: 58 RVA: 0x000028EC File Offset: 0x00000AEC
|
||||
public int PeekUnicodeChar() // \u0002
|
||||
{
|
||||
SrcPrecondition();
|
||||
if (!_src.IsValid2())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
var pos = _src.GetPos();
|
||||
var ret = SafeReadUnicodeChar();
|
||||
_src.SetPos(pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Token: 0x06000051 RID: 81 RVA: 0x00002FE8 File Offset: 0x000011E8
|
||||
private void SrcPrecondition() // \u0005
|
||||
{
|
||||
if (_src == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0600003B RID: 59 RVA: 0x0000292C File Offset: 0x00000B2C
|
||||
public int SafeReadUnicodeChar() // \u0003
|
||||
{
|
||||
SrcPrecondition();
|
||||
return ReadUnicodeChar();
|
||||
}
|
||||
|
||||
// Token: 0x0600004E RID: 78 RVA: 0x00002E38 File Offset: 0x00001038
|
||||
private int ReadUnicodeChar() // \u0005
|
||||
{
|
||||
var charCnt = 0;
|
||||
var savedPos = 0L;
|
||||
if (_src.IsValid2())
|
||||
{
|
||||
savedPos = _src.GetPos();
|
||||
}
|
||||
if (_inputCharRawBuf == null)
|
||||
{
|
||||
_inputCharRawBuf = new byte[128];
|
||||
}
|
||||
if (_inputCharsDecoded == null)
|
||||
{
|
||||
_inputCharsDecoded = new char[1];
|
||||
}
|
||||
while (charCnt == 0)
|
||||
{
|
||||
var bytesToRead = _isUnicode ? 2 : 1;
|
||||
var b = _src.ReadByte();
|
||||
_inputCharRawBuf[0] = (byte)b;
|
||||
if (b == -1)
|
||||
{
|
||||
bytesToRead = 0;
|
||||
}
|
||||
if (bytesToRead == 2)
|
||||
{
|
||||
b = _src.ReadByte();
|
||||
_inputCharRawBuf[1] = (byte)b;
|
||||
if (b == -1)
|
||||
{
|
||||
bytesToRead = 1;
|
||||
}
|
||||
}
|
||||
if (bytesToRead == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
try
|
||||
{
|
||||
charCnt = _decoder.GetChars(_inputCharRawBuf, 0, bytesToRead, _inputCharsDecoded, 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (_src.IsValid2())
|
||||
{
|
||||
_src.Seek(savedPos - _src.GetPos(), SeekOrigin.Current);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
if (charCnt == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return _inputCharsDecoded[0];
|
||||
}
|
||||
|
||||
// Token: 0x06000053 RID: 83 RVA: 0x0000305C File Offset: 0x0000125C
|
||||
private void ReadToRawBuf(int cnt) // \u0002
|
||||
{
|
||||
SrcPrecondition();
|
||||
var offset = 0;
|
||||
int bytesRead;
|
||||
if (cnt != 1)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
bytesRead = _src.Read(_inputRawBuf, offset, cnt - offset);
|
||||
if (bytesRead == 0)
|
||||
break;
|
||||
offset += bytesRead;
|
||||
if (offset >= cnt)
|
||||
return;
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
bytesRead = _src.ReadByte();
|
||||
if (bytesRead == -1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
_inputRawBuf[0] = (byte)bytesRead;
|
||||
}
|
||||
|
||||
// Token: 0x0600003C RID: 60 RVA: 0x0000293C File Offset: 0x00000B3C
|
||||
public bool ReadByteInternal() // \u0002
|
||||
{
|
||||
ReadToRawBuf(1);
|
||||
return _inputRawBuf[0] > 0;
|
||||
}
|
||||
|
||||
// Token: 0x0600003D RID: 61 RVA: 0x00002950 File Offset: 0x00000B50
|
||||
public byte ReadByte() // \u0002
|
||||
{
|
||||
SrcPrecondition();
|
||||
var b = _src.ReadByte();
|
||||
if (b == -1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return (byte)b;
|
||||
}
|
||||
|
||||
// Token: 0x0600003E RID: 62 RVA: 0x00002970 File Offset: 0x00000B70
|
||||
public sbyte ReadSbyte() // \u0002
|
||||
{
|
||||
ReadToRawBuf(1);
|
||||
return (sbyte)_inputRawBuf[0];
|
||||
}
|
||||
|
||||
// Token: 0x0600003F RID: 63 RVA: 0x00002984 File Offset: 0x00000B84
|
||||
public char ReadChar() // \u0002
|
||||
{
|
||||
var c = SafeReadUnicodeChar();
|
||||
if (c == -1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return (char)c;
|
||||
}
|
||||
|
||||
// Token: 0x06000040 RID: 64 RVA: 0x00002998 File Offset: 0x00000B98
|
||||
public short ReadShort() // \u0002
|
||||
{
|
||||
ReadToRawBuf(2);
|
||||
return (short)(_inputRawBuf[0] | _inputRawBuf[1] << 8);
|
||||
}
|
||||
|
||||
// Token: 0x06000041 RID: 65 RVA: 0x000029B8 File Offset: 0x00000BB8
|
||||
public ushort ReadUshort() // \u0002
|
||||
{
|
||||
ReadToRawBuf(2);
|
||||
return (ushort)(_inputRawBuf[0] | _inputRawBuf[1] << 8);
|
||||
}
|
||||
|
||||
// Token: 0x06000042 RID: 66 RVA: 0x000029D8 File Offset: 0x00000BD8
|
||||
public uint ReadUint() // \u0002
|
||||
{
|
||||
ReadToRawBuf(4);
|
||||
return (uint)(_inputRawBuf[0] | _inputRawBuf[1] << 8 | _inputRawBuf[2] << 16 | _inputRawBuf[3] << 24);
|
||||
}
|
||||
|
||||
// Token: 0x06000043 RID: 67 RVA: 0x00002A0C File Offset: 0x00000C0C
|
||||
public long ReadLong() // \u0002
|
||||
{
|
||||
ReadToRawBuf(8);
|
||||
var num = (uint)(_inputRawBuf[0] | _inputRawBuf[1] << 8 | _inputRawBuf[2] << 16 | _inputRawBuf[3] << 24);
|
||||
return (long)((ulong)(_inputRawBuf[4] | _inputRawBuf[5] << 8 | _inputRawBuf[6] << 16 | _inputRawBuf[7] << 24) << 32 | num);
|
||||
}
|
||||
|
||||
// Token: 0x06000044 RID: 68 RVA: 0x00002A80 File Offset: 0x00000C80
|
||||
public ulong ReadUlong() // \u0002
|
||||
{
|
||||
ReadToRawBuf(8);
|
||||
var num = (uint)(_inputRawBuf[0] | _inputRawBuf[1] << 8 | _inputRawBuf[2] << 16 | _inputRawBuf[3] << 24);
|
||||
return (ulong)(_inputRawBuf[4] | _inputRawBuf[5] << 8 | _inputRawBuf[6] << 16 | _inputRawBuf[7] << 24) << 32 | num;
|
||||
}
|
||||
|
||||
// Token: 0x06000045 RID: 69 RVA: 0x00002AF4 File Offset: 0x00000CF4
|
||||
private BinaryReader ReaderFor(int cnt) // \u0002
|
||||
{
|
||||
ReadToRawBuf(cnt);
|
||||
return new BinaryReader(new MemoryStream(_inputRawBuf, 0, cnt, false));
|
||||
}
|
||||
|
||||
// Token: 0x06000046 RID: 70 RVA: 0x00002B10 File Offset: 0x00000D10
|
||||
public float ReadFloat() // \u0002
|
||||
{
|
||||
var r = ReaderFor(4);
|
||||
var result = r.ReadSingle();
|
||||
r.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Token: 0x06000047 RID: 71 RVA: 0x00002B34 File Offset: 0x00000D34
|
||||
public double ReadDouble() // \u0002
|
||||
{
|
||||
var r = ReaderFor(8);
|
||||
var result = r.ReadDouble();
|
||||
r.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Token: 0x06000048 RID: 72 RVA: 0x00002B58 File Offset: 0x00000D58
|
||||
private static decimal CreateDecimal(int lo, int mid, int hi, int scaleNeg) // \u0002
|
||||
{
|
||||
var isNegative = (scaleNeg & -2147483648) != 0;
|
||||
var scale = (byte)(scaleNeg >> 16);
|
||||
return new decimal(lo, mid, hi, isNegative, scale);
|
||||
}
|
||||
|
||||
// Token: 0x06000049 RID: 73 RVA: 0x00002B80 File Offset: 0x00000D80
|
||||
internal static decimal CreateDecimal(byte[] b) // b
|
||||
{
|
||||
var lo = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24;
|
||||
var mid = b[4] | b[5] << 8 | b[6] << 16 | b[7] << 24;
|
||||
var hi = b[8] | b[9] << 8 | b[10] << 16 | b[11] << 24;
|
||||
var scaleNeg = b[12] | b[13] << 8 | b[14] << 16 | b[15] << 24;
|
||||
return CreateDecimal(lo, mid, hi, scaleNeg);
|
||||
}
|
||||
|
||||
// Token: 0x0600004A RID: 74 RVA: 0x00002BFC File Offset: 0x00000DFC
|
||||
public decimal ReadDecimal() // \u0002
|
||||
{
|
||||
ReadToRawBuf(16);
|
||||
return CreateDecimal(_inputRawBuf);
|
||||
}
|
||||
|
||||
// Token: 0x0600004B RID: 75 RVA: 0x00002C14 File Offset: 0x00000E14
|
||||
public string ReadString() // \u0002
|
||||
{
|
||||
var totalRead = 0;
|
||||
SrcPrecondition();
|
||||
var strLen = Read28Bit();
|
||||
if (strLen < 0)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
if (strLen == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
if (_inputCharRawBuf == null)
|
||||
{
|
||||
_inputCharRawBuf = new byte[128];
|
||||
}
|
||||
if (_stringChunk == null)
|
||||
{
|
||||
_stringChunk = new char[_maxCharsIn128Bytes];
|
||||
}
|
||||
StringBuilder stringBuilder = null;
|
||||
while (true)
|
||||
{
|
||||
var needChunkCnt = (strLen - totalRead > 128) ? 128 : (strLen - totalRead);
|
||||
var realChunkRead = _src.Read(_inputCharRawBuf, 0, needChunkCnt);
|
||||
if (realChunkRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
var chars = _decoder.GetChars(_inputCharRawBuf, 0, realChunkRead, _stringChunk, 0);
|
||||
if (totalRead == 0 && realChunkRead == strLen)
|
||||
{
|
||||
return new string(_stringChunk, 0, chars);
|
||||
}
|
||||
if (stringBuilder == null)
|
||||
{
|
||||
stringBuilder = new StringBuilder(strLen);
|
||||
}
|
||||
stringBuilder.Append(_stringChunk, 0, chars);
|
||||
totalRead += realChunkRead;
|
||||
if (totalRead >= strLen)
|
||||
{
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
// Token: 0x0600004C RID: 76 RVA: 0x00002D08 File Offset: 0x00000F08
|
||||
public int Read(char[] dest, int offset, int cnt) // \u0002
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException(StringDecryptor.GetString(-1550347170), /* \u0002 */
|
||||
StringDecryptor.GetString(-1550347157) /* ArgumentNull_Buffer */);
|
||||
}
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (cnt < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (dest.Length - offset < cnt)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
SrcPrecondition();
|
||||
return DoRead(dest, offset, cnt);
|
||||
}
|
||||
|
||||
// Token: 0x0600004D RID: 77 RVA: 0x00002D64 File Offset: 0x00000F64
|
||||
private int DoRead(char[] dest, int offset, int cnt) // \u0003
|
||||
{
|
||||
var remainCharsToRead = cnt;
|
||||
if (_inputCharRawBuf == null)
|
||||
{
|
||||
_inputCharRawBuf = new byte[128];
|
||||
}
|
||||
while (remainCharsToRead > 0)
|
||||
{
|
||||
var chunkSize = remainCharsToRead;
|
||||
if (_isUnicode)
|
||||
{
|
||||
chunkSize <<= 1;
|
||||
}
|
||||
if (chunkSize > 128)
|
||||
{
|
||||
chunkSize = 128;
|
||||
}
|
||||
int chars;
|
||||
if (_alwaysTrue)
|
||||
{
|
||||
var byteIndex = _src.GetCursor();
|
||||
chunkSize = _src.SkipBytes(chunkSize);
|
||||
if (chunkSize == 0)
|
||||
{
|
||||
return cnt - remainCharsToRead;
|
||||
}
|
||||
chars = _decoder.GetChars(_src.Data(), byteIndex, chunkSize, dest, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunkSize = _src.Read(_inputCharRawBuf, 0, chunkSize);
|
||||
if (chunkSize == 0)
|
||||
{
|
||||
return cnt - remainCharsToRead;
|
||||
}
|
||||
chars = _decoder.GetChars(_inputCharRawBuf, 0, chunkSize, dest, offset);
|
||||
}
|
||||
remainCharsToRead -= chars;
|
||||
offset += chars;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
// Token: 0x0600004F RID: 79 RVA: 0x00002F54 File Offset: 0x00001154
|
||||
public char[] ReadChars(int cnt) // \u0002
|
||||
{
|
||||
SrcPrecondition();
|
||||
if (cnt < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
var ret = new char[cnt];
|
||||
var realLength = DoRead(ret, 0, cnt);
|
||||
if (realLength != cnt)
|
||||
{
|
||||
var shrinked = new char[realLength];
|
||||
Buffer.BlockCopy(ret, 0, shrinked, 0, 2 * realLength);
|
||||
ret = shrinked;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Token: 0x06000050 RID: 80 RVA: 0x00002F9C File Offset: 0x0000119C
|
||||
public int Read(byte[] dest, int offset, int cnt) // dest
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (cnt < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (dest.Length - offset < cnt)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
SrcPrecondition();
|
||||
return _src.Read(dest, offset, cnt);
|
||||
}
|
||||
|
||||
// Token: 0x06000052 RID: 82 RVA: 0x00002FF8 File Offset: 0x000011F8
|
||||
public byte[] ReadBytes(int cnt) // \u0002
|
||||
{
|
||||
if (cnt < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
SrcPrecondition();
|
||||
var ret = new byte[cnt];
|
||||
var offset = 0;
|
||||
do
|
||||
{
|
||||
var chunkSize = _src.Read(ret, offset, cnt);
|
||||
if (chunkSize == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
offset += chunkSize;
|
||||
cnt -= chunkSize;
|
||||
}
|
||||
while (cnt > 0);
|
||||
if (offset != ret.Length)
|
||||
{
|
||||
var shrinked = new byte[offset];
|
||||
Buffer.BlockCopy(ret, 0, shrinked, 0, offset);
|
||||
ret = shrinked;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Token: 0x06000054 RID: 84 RVA: 0x000030C0 File Offset: 0x000012C0
|
||||
internal int Read28Bit() // \u0008
|
||||
{
|
||||
var ret = 0;
|
||||
var bitCnt = 0;
|
||||
while (bitCnt != 35)
|
||||
{
|
||||
var b = ReadByte();
|
||||
ret |= (b & 127) << bitCnt;
|
||||
bitCnt += 7;
|
||||
if ((b & 128) == 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
// Token: 0x06000055 RID: 85 RVA: 0x00003100 File Offset: 0x00001300
|
||||
public int ReadInt32() // \u0006
|
||||
{
|
||||
if (_alwaysTrue)
|
||||
{
|
||||
return _src.ReadInt32();
|
||||
}
|
||||
ReadToRawBuf(4);
|
||||
return _inputRawBuf[3] << 8 | _inputRawBuf[1] << 24 | _inputRawBuf[0] << 16 | _inputRawBuf[2];
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000006 RID: 6
|
||||
internal static class EmptyArray<T> // \u0002\u2003
|
||||
{
|
||||
// Token: 0x04000004 RID: 4
|
||||
public static readonly T[] Data = new T[0];
|
||||
}
|
||||
|
||||
// Token: 0x02000022 RID: 34
|
||||
internal sealed class MyCollection<T> : IEnumerable<T>, ICollection // \u0005\u2006
|
||||
{
|
||||
// Token: 0x0400002C RID: 44
|
||||
internal T[] Data; // \u0002
|
||||
|
||||
// Token: 0x0400002E RID: 46
|
||||
internal int ChangeCounter; // \u0005
|
||||
|
||||
// Token: 0x0400002F RID: 47
|
||||
private object _sync; // \u0008
|
||||
|
||||
// Token: 0x060000DA RID: 218 RVA: 0x00004B9C File Offset: 0x00002D9C
|
||||
public MyCollection()
|
||||
{
|
||||
Data = EmptyArray<T>.Data;
|
||||
Count = 0;
|
||||
ChangeCounter = 0;
|
||||
}
|
||||
|
||||
// Token: 0x060000DB RID: 219 RVA: 0x00004BC0 File Offset: 0x00002DC0
|
||||
public MyCollection(int capacity)
|
||||
{
|
||||
if (capacity < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
Data = new T[capacity];
|
||||
Count = 0;
|
||||
ChangeCounter = 0;
|
||||
}
|
||||
|
||||
// Token: 0x060000DC RID: 220 RVA: 0x00004BEC File Offset: 0x00002DEC
|
||||
public MyCollection(IEnumerable<T> src)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
var collection = src as ICollection<T>;
|
||||
if (collection != null)
|
||||
{
|
||||
var count = collection.Count;
|
||||
Data = new T[count];
|
||||
collection.CopyTo(Data, 0);
|
||||
Count = count;
|
||||
return;
|
||||
}
|
||||
Count = 0;
|
||||
Data = new T[4];
|
||||
foreach (var i in Data)
|
||||
{
|
||||
PushBack(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0400002D RID: 45
|
||||
// Token: 0x17000006 RID: 6
|
||||
// (get) Token: 0x060000DD RID: 221 RVA: 0x00004C88 File Offset: 0x00002E88
|
||||
public int Count { get; private set; } // \u0003
|
||||
|
||||
// Token: 0x060000DE RID: 222 RVA: 0x00004C90 File Offset: 0x00002E90
|
||||
bool ICollection.IsSynchronized => false; // \u0005\u2006\u2008\u2000\u2002\u200A\u0002
|
||||
|
||||
// Token: 0x060000DF RID: 223 RVA: 0x00004C94 File Offset: 0x00002E94
|
||||
object ICollection.SyncRoot // \u0005\u2006\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sync == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref _sync, new object(), null);
|
||||
}
|
||||
return _sync;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000E0 RID: 224 RVA: 0x00004CB8 File Offset: 0x00002EB8
|
||||
public void Clear() // \u0002
|
||||
{
|
||||
Array.Clear(Data, 0, Count);
|
||||
Count = 0;
|
||||
ChangeCounter++;
|
||||
}
|
||||
|
||||
// Token: 0x060000E1 RID: 225 RVA: 0x00004CE4 File Offset: 0x00002EE4
|
||||
public bool Contains(T what) // \u0002
|
||||
{
|
||||
var num = Count;
|
||||
var @default = EqualityComparer<T>.Default;
|
||||
while (num-- > 0)
|
||||
{
|
||||
if (what == null)
|
||||
{
|
||||
if (Data[num] == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (Data[num] != null && @default.Equals(Data[num], what))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Token: 0x060000E2 RID: 226 RVA: 0x00004D50 File Offset: 0x00002F50
|
||||
public void CopyTo(T[] dest, int offset) // \u0003
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException(StringDecryptor.GetString(-1550346880) /* \u0002 */);
|
||||
}
|
||||
if (offset < 0 || offset > dest.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(StringDecryptor.GetString(-1550346867) /* \u0003 */,
|
||||
StringDecryptor.GetString(-1550346858) /* arrayIndex < 0 || arrayIndex > array.Length */);
|
||||
}
|
||||
if (dest.Length - offset < Count)
|
||||
{
|
||||
throw new ArgumentException(StringDecryptor.GetString(-1550347192) /* Invalid Off Len */);
|
||||
}
|
||||
Array.Copy(Data, 0, dest, offset, Count);
|
||||
Array.Reverse(dest, offset, Count);
|
||||
}
|
||||
|
||||
// Token: 0x060000E3 RID: 227 RVA: 0x00004DD4 File Offset: 0x00002FD4
|
||||
void ICollection.CopyTo(Array dest, int offset) // \u0005\u2006\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
if (dest.Rank != 1)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
if (dest.GetLowerBound(0) != 0)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
if (offset < 0 || offset > dest.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
if (dest.Length - offset < Count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
try
|
||||
{
|
||||
Array.Copy(Data, 0, dest, offset, Count);
|
||||
Array.Reverse(dest, offset, Count);
|
||||
}
|
||||
catch (ArrayTypeMismatchException)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000E4 RID: 228 RVA: 0x00004E6C File Offset: 0x0000306C
|
||||
public MyEnumerator<T> GetEnumerator() // \u0005
|
||||
{
|
||||
return new MyEnumerator<T>(this);
|
||||
}
|
||||
|
||||
// Token: 0x060000E5 RID: 229 RVA: 0x00004E74 File Offset: 0x00003074
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() // \u0005\u2006\u2008\u2000\u2002\u200A\u0008
|
||||
{
|
||||
return new MyEnumerator<T>(this);
|
||||
}
|
||||
|
||||
// Token: 0x060000E6 RID: 230 RVA: 0x00004E84 File Offset: 0x00003084
|
||||
IEnumerator IEnumerable.GetEnumerator() // \u0005\u2006\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
return new MyEnumerator<T>(this);
|
||||
}
|
||||
|
||||
// Token: 0x060000E7 RID: 231 RVA: 0x00004E94 File Offset: 0x00003094
|
||||
public void Shrink() // \u0003
|
||||
{
|
||||
var num = (int)(Data.Length * 0.9);
|
||||
if (Count < num)
|
||||
{
|
||||
var destinationArray = new T[Count];
|
||||
Array.Copy(Data, 0, destinationArray, 0, Count);
|
||||
Data = destinationArray;
|
||||
ChangeCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000E8 RID: 232 RVA: 0x00004EF4 File Offset: 0x000030F4
|
||||
public T PeekBack() // \u0006
|
||||
{
|
||||
if (Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
return Data[Count - 1];
|
||||
}
|
||||
|
||||
// Token: 0x060000E9 RID: 233 RVA: 0x00004F18 File Offset: 0x00003118
|
||||
public T PopBack() // \u000E
|
||||
{
|
||||
if (Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
ChangeCounter++;
|
||||
var ret = Data[--Count];
|
||||
Data[Count] = default(T);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Token: 0x060000EA RID: 234 RVA: 0x00004F78 File Offset: 0x00003178
|
||||
public void PushBack(T obj) // \u000F
|
||||
{
|
||||
if (Count == Data.Length)
|
||||
{
|
||||
var destinationArray = new T[(Data.Length == 0) ? 4 : (2 * Data.Length)];
|
||||
Array.Copy(Data, 0, destinationArray, 0, Count);
|
||||
Data = destinationArray;
|
||||
}
|
||||
var num = Count;
|
||||
Count = num + 1;
|
||||
Data[num] = obj;
|
||||
ChangeCounter++;
|
||||
}
|
||||
|
||||
// Token: 0x060000EB RID: 235 RVA: 0x00004FF8 File Offset: 0x000031F8
|
||||
public T[] Reverse() // \u0002\u2000
|
||||
{
|
||||
var array = new T[Count];
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
array[i] = Data[Count - i - 1];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Token: 0x02000023 RID: 35
|
||||
public struct MyEnumerator<T1> : IEnumerator<T1> // \u0002
|
||||
{
|
||||
// Token: 0x060000EC RID: 236 RVA: 0x00005040 File Offset: 0x00003240
|
||||
internal MyEnumerator(MyCollection<T1> src)
|
||||
{
|
||||
_src = src;
|
||||
_changeCounter = _src.ChangeCounter;
|
||||
_curPos = -2;
|
||||
_current = default(T1);
|
||||
}
|
||||
|
||||
// Token: 0x060000ED RID: 237 RVA: 0x00005070 File Offset: 0x00003270
|
||||
public void Dispose()
|
||||
{
|
||||
_curPos = -1;
|
||||
}
|
||||
|
||||
// Token: 0x060000EE RID: 238 RVA: 0x0000507C File Offset: 0x0000327C
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_changeCounter != _src.ChangeCounter)
|
||||
{
|
||||
throw new InvalidOperationException(StringDecryptor.GetString(-1550346776) /* EnumFailedVersion */);
|
||||
}
|
||||
if (_curPos == -2)
|
||||
{
|
||||
_curPos = _src.Count - 1;
|
||||
if (_curPos < 0) return false;
|
||||
_current = _src.Data[_curPos];
|
||||
return true;
|
||||
}
|
||||
if (_curPos == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (--_curPos >= 0)
|
||||
{
|
||||
_current = _src.Data[_curPos];
|
||||
return true;
|
||||
}
|
||||
_current = default(T1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Token: 0x17000007 RID: 7
|
||||
// (get) Token: 0x060000EF RID: 239 RVA: 0x00005144 File Offset: 0x00003344
|
||||
public T1 Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_curPos == -2)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
if (_curPos == -1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
return _current;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000F0 RID: 240 RVA: 0x0000516C File Offset: 0x0000336C
|
||||
object IEnumerator.Current // \u0002\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_curPos == -2)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
if (_curPos == -1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
return _current;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000F1 RID: 241 RVA: 0x00005198 File Offset: 0x00003398
|
||||
void IEnumerator.Reset() // \u0002\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
if (_changeCounter != _src.ChangeCounter)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
_curPos = -2;
|
||||
_current = default(T1);
|
||||
}
|
||||
|
||||
// Token: 0x04000030 RID: 48
|
||||
private readonly MyCollection<T1> _src; // \u0002
|
||||
|
||||
// Token: 0x04000031 RID: 49
|
||||
private int _curPos; // \u0003
|
||||
|
||||
// Token: 0x04000032 RID: 50
|
||||
private readonly int _changeCounter; // \u0005
|
||||
|
||||
// Token: 0x04000033 RID: 51
|
||||
private T1 _current; // \u0008
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,288 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000063 RID: 99
|
||||
internal static class SdMetadataTokens // \u000F\u2009
|
||||
{
|
||||
// Token: 0x06000399 RID: 921 RVA: 0x00015D18 File Offset: 0x00013F18
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static long GetLong() // \u0002
|
||||
{
|
||||
if (Assembly.GetCallingAssembly() != typeof(SdMetadataTokens).Assembly || !CheckStack())
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
long result;
|
||||
lock (Obj)
|
||||
{
|
||||
var num = Obj.GetLong7();
|
||||
if (num == 0L)
|
||||
{
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
var list = new List<byte>();
|
||||
AssemblyName assemblyName;
|
||||
try
|
||||
{
|
||||
assemblyName = executingAssembly.GetName();
|
||||
}
|
||||
catch
|
||||
{
|
||||
assemblyName = new AssemblyName(executingAssembly.FullName);
|
||||
}
|
||||
var array = assemblyName.GetPublicKeyToken();
|
||||
if (array != null && array.Length == 0)
|
||||
{
|
||||
array = null;
|
||||
}
|
||||
if (array != null)
|
||||
{
|
||||
list.AddRange(array);
|
||||
}
|
||||
list.AddRange(Encoding.Unicode.GetBytes(assemblyName.Name));
|
||||
var num2 = 0x02000063; //GetMdt(typeof(SdMetadataTokens));
|
||||
var num3 = Class1.M();
|
||||
list.Add((byte)(num2 >> 24));
|
||||
list.Add((byte)(num3 >> 16));
|
||||
list.Add((byte)(num2 >> 8));
|
||||
list.Add((byte)num3);
|
||||
list.Add((byte)(num2 >> 16));
|
||||
list.Add((byte)(num3 >> 8));
|
||||
list.Add((byte)num2);
|
||||
list.Add((byte)(num3 >> 24));
|
||||
var count = list.Count;
|
||||
var num4 = 0uL;
|
||||
for (var num5 = 0; num5 != count; num5++)
|
||||
{
|
||||
num4 += list[num5];
|
||||
num4 += num4 << 20;
|
||||
num4 ^= num4 >> 12;
|
||||
list[num5] = 0;
|
||||
}
|
||||
num4 += num4 << 6;
|
||||
num4 ^= num4 >> 22;
|
||||
num4 += num4 << 30;
|
||||
num = (long)num4;
|
||||
num ^= 7895633081549295753L;
|
||||
Obj.SetLong(num);
|
||||
}
|
||||
result = num;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Token: 0x0600039A RID: 922 RVA: 0x00015EE0 File Offset: 0x000140E0
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool CheckStack() // \u0002
|
||||
{
|
||||
return CheckStackImpl();
|
||||
}
|
||||
|
||||
// Token: 0x0600039B RID: 923 RVA: 0x00015EEC File Offset: 0x000140EC
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool CheckStackImpl() // \u0003
|
||||
{
|
||||
var stackTrace = new StackTrace();
|
||||
var frame = stackTrace.GetFrame(3);
|
||||
var methodBase = frame?.GetMethod();
|
||||
var type = methodBase?.DeclaringType;
|
||||
return type != typeof(RuntimeMethodHandle) && type != null && type.Assembly == typeof(SdMetadataTokens).Assembly;
|
||||
}
|
||||
|
||||
// Token: 0x0600039C RID: 924 RVA: 0x00015F50 File Offset: 0x00014150
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private static int GetMdt(Type t) // \u0002
|
||||
{
|
||||
return t.MetadataToken;
|
||||
}
|
||||
|
||||
// Token: 0x0400019A RID: 410
|
||||
// \u0002
|
||||
private static readonly Class7 Obj = new Class7();
|
||||
|
||||
// Token: 0x02000064 RID: 100
|
||||
public sealed class Class1 // \u0002\u2007\u2007\u2009\u2002\u2006\u2003\u2003\u2002\u2004\u2007\u200A\u2009\u200A\u2008\u200A\u2000\u2003\u200B\u2007\u200A\u2008\u200A\u2003\u2006\u200B
|
||||
{
|
||||
// Token: 0x0600039E RID: 926 RVA: 0x00015F60 File Offset: 0x00014160
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static int M()
|
||||
{
|
||||
return Class2.M3(Class2.M2(0x02000067 /*GetMdt(typeof(Class4))*/, Class2.M3(0x02000064 /*GetMdt(typeof(Class1))*/, 0x02000066 /*GetMdt(typeof(Class3))*/)), Class5.M1());
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000065 RID: 101
|
||||
private static class Class2 // \u0002\u200A\u2003\u2000\u2002\u2000\u2007\u2008\u2004\u2006\u2007\u2003\u2007\u2004\u2000\u2003\u2009\u2007\u2003\u2006\u2007\u2008\u200A
|
||||
{
|
||||
// Token: 0x0600039F RID: 927 RVA: 0x00015FB0 File Offset: 0x000141B0
|
||||
internal static int M1(int p1, int p2) // \u0002
|
||||
{
|
||||
return p1 ^ p2 - -~~- -~~- -~~-1683504797;
|
||||
}
|
||||
|
||||
// Token: 0x060003A0 RID: 928 RVA: 0x00015FC8 File Offset: 0x000141C8
|
||||
internal static int M2(int p1, int p2) // \u0003
|
||||
{
|
||||
return p1 - -~-~-~~- -~~-1670271084 ^ p2 + -~-~-~~-~-~699406271;
|
||||
}
|
||||
|
||||
// Token: 0x060003A1 RID: 929 RVA: 0x00015FF0 File Offset: 0x000141F0
|
||||
internal static int M3(int p1, int p2) // \u0005
|
||||
{
|
||||
return p1 ^ p2 - -~~-~-~- -~~-1466097638 ^ p1 - p2;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000066 RID: 102
|
||||
public sealed class Class3 // \u0003\u2001\u2003\u2009\u2009\u2008\u2006\u2006\u2006\u200A\u2003\u2006\u2005\u2005\u2009\u200B\u2009\u200A\u2003\u2007
|
||||
{
|
||||
// Token: 0x060003A3 RID: 931 RVA: 0x00016014 File Offset: 0x00014214
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static int M1() // \u0002
|
||||
{
|
||||
return Class2.M2(Class2.M2(Class6.M1(), Class2.M1(0x02000066 /*GetMdt(typeof(Class3))*/, Class4.M1())), 0x02000068 /*GetMdt(typeof(Class5))*/);
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000067 RID: 103
|
||||
public sealed class Class4 // \u0003\u2007\u2006\u2000\u2001\u2003\u2006\u200B\u2003\u2009\u200B\u2008\u200A\u2008\u2004\u2005\u2006\u200A\u2008\u2000\u2000\u200B\u2008\u200A
|
||||
{
|
||||
// Token: 0x060003A5 RID: 933 RVA: 0x00016058 File Offset: 0x00014258
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static int M1() // \u0002
|
||||
{
|
||||
return Class2.M1(0x02000069 /*GetMdt(typeof(Class6))*/, 0x0200006B /*GetMdt(typeof(Class8))*/ ^ Class2.M2(0x02000067 /*GetMdt(typeof(Class4))*/, Class2.M3(0x02000068 /*GetMdt(typeof(Class5))*/, Class8.M1())));
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000068 RID: 104
|
||||
public sealed class Class5 // \u0005\u2006\u200A\u2004\u200B\u2005\u200B\u2004\u2005\u2002\u2000\u2001\u2002\u2004\u2000\u2002\u2007\u2003\u2009\u200B\u2007\u200A\u200B\u2000\u2008\u2002\u2003\u2002
|
||||
{
|
||||
// Token: 0x060003A7 RID: 935 RVA: 0x000160C0 File Offset: 0x000142C0
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static int M1() // \u0002
|
||||
{
|
||||
return Class2.M1(0x02000068 /*GetMdt(typeof(Class5))*/, Class2.M3(Class2.M2(0x02000066 /*GetMdt(typeof(Class3))*/, 0x02000064 /*GetMdt(typeof(Class1))*/), Class2.M3(0x02000069 /*GetMdt(typeof(Class6))*/ ^ -~-~~- -~~-1251689633, Class3.M1())));
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000069 RID: 105
|
||||
public sealed class Class6 // \u0008\u2007\u2007\u2004\u2006\u2006\u200A\u2009\u2005\u2006\u2008\u200A\u2000\u200A\u2008\u2002\u2009\u2003\u2006\u2008\u2000\u2005\u2004\u200A\u2004\u2008\u2008\u2001\u2004\u200B
|
||||
{
|
||||
// Token: 0x060003A9 RID: 937 RVA: 0x0001613C File Offset: 0x0001433C
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static int M1() // \u0002
|
||||
{
|
||||
return Class2.M3(Class2.M1(Class4.M1() ^ ~-~- -~~- -~~-527758448, 0x0200006B /*GetMdt(typeof(Class8))*/), Class2.M2(0x02000064 /*GetMdt(typeof(Class1))*/ ^ 0x02000068 /*GetMdt(typeof(Class5))*/, -~~- -~-~~1892236202));
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0200006A RID: 106
|
||||
internal sealed class Class7 // \u000F\u2005\u2007\u2007\u2009\u2009\u2002\u2004\u2008\u2009\u2002\u2000\u2000\u2009\u2009\u200B\u2008\u2004\u2003\u200B\u200A\u2002\u2002\u2003\u2006\u2007\u2000\u2006\u2002\u2003
|
||||
{
|
||||
// Token: 0x060003AA RID: 938 RVA: 0x000161AC File Offset: 0x000143AC
|
||||
internal Class7()
|
||||
{
|
||||
SetLong(0L);
|
||||
}
|
||||
|
||||
// Token: 0x060003AB RID: 939 RVA: 0x000161BC File Offset: 0x000143BC
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public long GetLong7() // \u0002
|
||||
{
|
||||
if (Assembly.GetCallingAssembly() != typeof(Class7).Assembly)
|
||||
{
|
||||
return 2918384L;
|
||||
}
|
||||
if (!CheckStack())
|
||||
{
|
||||
return 2918384L;
|
||||
}
|
||||
var array = new[]
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-~~- -~-~~1688528055
|
||||
};
|
||||
array[1] = ~-~- -~~-~1937298816;
|
||||
array[2] = ~-~- -~-~~-~-2131774929;
|
||||
array[0] = ~-~-~- -~~-~859851913;
|
||||
var num = _i1;
|
||||
var num2 = _i2;
|
||||
var num3 = -~-~-~~-~1640531528;
|
||||
var num4 = -~-~~- -~~-~957401312;
|
||||
for (var num5 = 0; num5 != 32; num5++)
|
||||
{
|
||||
num2 -= (num << 4 ^ num >> 5) + num ^ num4 + array[num4 >> 11 & 3];
|
||||
num4 -= num3;
|
||||
num -= (num2 << 4 ^ num2 >> 5) + num2 ^ num4 + array[num4 & 3];
|
||||
}
|
||||
for (var num6 = 0; num6 != 4; num6++)
|
||||
{
|
||||
array[num6] = 0;
|
||||
}
|
||||
var num7 = ((ulong)num2 << 32);
|
||||
var n = (ulong)_i1;
|
||||
return (long)(num7 | n);
|
||||
}
|
||||
|
||||
// Token: 0x060003AC RID: 940 RVA: 0x000162D8 File Offset: 0x000144D8
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal void SetLong(long p) // \u0002
|
||||
{
|
||||
if (Assembly.GetCallingAssembly() != typeof(Class7).Assembly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!CheckStack())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var array = new int[4];
|
||||
array[1] = -~~-~- -~~-~1937298817;
|
||||
array[0] = -~~-~-~-~859851914;
|
||||
array[2] = ~-~- -~~-~-2131774930;
|
||||
array[3] = -~-~~-~- -~~1688528054;
|
||||
var num = -~-~~- -~-~~1640531529;
|
||||
var num2 = (int)p;
|
||||
var num3 = (int)(p >> 32);
|
||||
var num4 = 0;
|
||||
for (var num5 = 0; num5 != 32; num5++)
|
||||
{
|
||||
num2 += (num3 << 4 ^ num3 >> 5) + num3 ^ num4 + array[num4 & 3];
|
||||
num4 += num;
|
||||
num3 += (num2 << 4 ^ num2 >> 5) + num2 ^ num4 + array[num4 >> 11 & 3];
|
||||
}
|
||||
for (var num6 = 0; num6 != 4; num6++)
|
||||
{
|
||||
array[num6] = 0;
|
||||
}
|
||||
_i1 = num2;
|
||||
_i2 = num3;
|
||||
}
|
||||
|
||||
// Token: 0x0400019B RID: 411
|
||||
private int _i1; // \u0002
|
||||
|
||||
// Token: 0x0400019C RID: 412
|
||||
private int _i2; // \u0003
|
||||
}
|
||||
|
||||
// Token: 0x0200006B RID: 107
|
||||
public sealed class Class8 // \u000F\u200A\u2002\u2009\u2000\u2009\u2003\u200A\u2005\u2001\u2002\u2002\u2003\u200B\u2000\u2009\u2003\u2009\u2009\u2001\u2002\u200B\u2000\u200A
|
||||
{
|
||||
// Token: 0x060003AE RID: 942 RVA: 0x000163DC File Offset: 0x000145DC
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static int M1()
|
||||
{
|
||||
return Class2.M3(0x0200006B /*GetMdt(typeof(Class8))*/, Class2.M1(0x02000064 /*GetMdt(typeof(Class1))*/, Class2.M2(0x02000067 /*GetMdt(typeof(Class4))*/, Class2.M3(0x02000069 /*GetMdt(typeof(Class6))*/, Class2.M1(0x02000066 /*GetMdt(typeof(Class3))*/, 0x02000068 /*GetMdt(typeof(Class5))*/)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace forms_cil
|
||||
{
|
||||
// Token: 0x02000057 RID: 87
|
||||
internal interface I4 // \u000E\u2008
|
||||
{
|
||||
// Token: 0x06000346 RID: 838
|
||||
bool I4M(); // \u000E\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
|
||||
// Token: 0x06000347 RID: 839
|
||||
object M2(); // \u000E\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
|
||||
// Token: 0x06000348 RID: 840
|
||||
void M3(); // \u000E\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
}
|
||||
|
||||
// Token: 0x02000062 RID: 98
|
||||
internal interface I5 // \u000F\u2008
|
||||
{
|
||||
// Token: 0x06000397 RID: 919
|
||||
void I5M(); // \u000F\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
}
|
||||
|
||||
// Token: 0x0200000C RID: 12
|
||||
internal interface I1<out T> : I4, I5 // \u0002\u2009
|
||||
{
|
||||
// Token: 0x06000057 RID: 87
|
||||
T I1M(); // \u000E\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
}
|
||||
|
||||
// Token: 0x0200004B RID: 75
|
||||
internal interface I3 // \u0008\u2008
|
||||
{
|
||||
// Token: 0x0600031E RID: 798
|
||||
I4 M1(); // \u0008\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
}
|
||||
|
||||
// Token: 0x0200003C RID: 60
|
||||
internal interface I2<out T> : I3 // \u0006\u2008
|
||||
{
|
||||
// Token: 0x060002CD RID: 717
|
||||
I1<T> I2M(); // \u0008\u2008\u2008\u2000\u2002\u200A\u0002
|
||||
}
|
||||
|
||||
// Token: 0x02000025 RID: 37
|
||||
internal static class SdTemplateStuff // \u0005\u2008
|
||||
{
|
||||
// Token: 0x02000026 RID: 38
|
||||
internal sealed class C : I2<int>, I1<int> // \u0002
|
||||
{
|
||||
// Token: 0x06000112 RID: 274 RVA: 0x00005A28 File Offset: 0x00003C28
|
||||
public C(int val)
|
||||
{
|
||||
_i2 = val;
|
||||
_i5 = Thread.CurrentThread.ManagedThreadId;
|
||||
}
|
||||
|
||||
// Token: 0x06000113 RID: 275 RVA: 0x00005A48 File Offset: 0x00003C48
|
||||
void I5.I5M()
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x06000114 RID: 276 RVA: 0x00005A4C File Offset: 0x00003C4C
|
||||
bool I4.I4M()
|
||||
{
|
||||
switch (_i2)
|
||||
{
|
||||
case 0:
|
||||
_i2 = -1;
|
||||
_i3 = -1496196691;
|
||||
_i2 = 1;
|
||||
return true;
|
||||
case 1:
|
||||
_i2 = -1;
|
||||
_i3 = _i8 ^ 70939052;
|
||||
_i2 = 2;
|
||||
return true;
|
||||
case 2:
|
||||
_i2 = -1;
|
||||
_i3 = _i8 ^ -1812634754;
|
||||
_i2 = 3;
|
||||
return true;
|
||||
case 3:
|
||||
_i2 = -1;
|
||||
_i3 = -5623460;
|
||||
_i2 = 4;
|
||||
return true;
|
||||
case 4:
|
||||
_i2 = -1;
|
||||
_i3 = 401181880;
|
||||
_i2 = 5;
|
||||
return true;
|
||||
case 5:
|
||||
_i2 = -1;
|
||||
_i3 = 2075948002;
|
||||
_i2 = 6;
|
||||
return true;
|
||||
case 6:
|
||||
_i2 = -1;
|
||||
_i3 = _i8 ^ 70939052;
|
||||
_i2 = 7;
|
||||
return true;
|
||||
case 7:
|
||||
_i2 = -1;
|
||||
_i3 = -783689628;
|
||||
_i2 = 8;
|
||||
return true;
|
||||
case 8:
|
||||
_i2 = -1;
|
||||
_i3 = _i8 ^ 70939052;
|
||||
_i2 = 9;
|
||||
return true;
|
||||
case 9:
|
||||
_i2 = -1;
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x06000115 RID: 277 RVA: 0x00005BA8 File Offset: 0x00003DA8
|
||||
int I1<int>.I1M()
|
||||
{
|
||||
return _i3;
|
||||
}
|
||||
|
||||
// Token: 0x06000116 RID: 278 RVA: 0x00005BB0 File Offset: 0x00003DB0
|
||||
void I4.M3()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
// Token: 0x06000117 RID: 279 RVA: 0x00005BB8 File Offset: 0x00003DB8
|
||||
object I4.M2()
|
||||
{
|
||||
return _i3;
|
||||
}
|
||||
|
||||
// Token: 0x06000118 RID: 280 RVA: 0x00005BC8 File Offset: 0x00003DC8
|
||||
I1<int> I2<int>.I2M()
|
||||
{
|
||||
C ret;
|
||||
if (_i2 == -2 && _i5 == Thread.CurrentThread.ManagedThreadId)
|
||||
{
|
||||
_i2 = 0;
|
||||
ret = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = new C(0);
|
||||
}
|
||||
ret._i8 = I6;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Token: 0x06000119 RID: 281 RVA: 0x00005C10 File Offset: 0x00003E10
|
||||
I4 I3.M1()
|
||||
{
|
||||
return ((I2<int>)this).I2M();
|
||||
}
|
||||
|
||||
// Token: 0x0400003D RID: 61
|
||||
private int _i2; // \u0002
|
||||
|
||||
// Token: 0x0400003E RID: 62
|
||||
private int _i3; // \u0003
|
||||
|
||||
// Token: 0x0400003F RID: 63
|
||||
private readonly int _i5; // \u0005
|
||||
|
||||
// Token: 0x04000040 RID: 64
|
||||
private int _i8; // \u0008
|
||||
|
||||
// Token: 0x04000041 RID: 65
|
||||
public int I6; // \u0006
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000009 RID: 9
|
||||
static class SimpleTypeHelper // \u0002\u2006
|
||||
{
|
||||
// Token: 0x06000033 RID: 51 RVA: 0x000027AC File Offset: 0x000009AC
|
||||
public static bool IsNullableGeneric(Type t) // \u0002
|
||||
{
|
||||
return t.IsGenericType && t.GetGenericTypeDefinition() == NullableType; // \u0003
|
||||
}
|
||||
|
||||
// Token: 0x04000008 RID: 8
|
||||
public static readonly Type ObjectType = typeof(object); // \u0002
|
||||
|
||||
// Token: 0x04000009 RID: 9
|
||||
private static readonly Type NullableType = typeof(Nullable<>); // \u0003
|
||||
|
||||
// Token: 0x0400000A RID: 10
|
||||
public static readonly Type TypedReferenceType = typeof(TypedReference); // \u0005
|
||||
|
||||
// Token: 0x0400000B RID: 11
|
||||
public static readonly Type EnumType = typeof(Enum); // \u0008
|
||||
}
|
||||
}
|
@ -0,0 +1,648 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using forms_cil;
|
||||
|
||||
// Token: 0x0200003D RID: 61
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
public static class StringDecryptor // \u0006\u2009
|
||||
{
|
||||
private static BinStreamReader _binStreamReader; // \u0003
|
||||
private static readonly DecryptedStrings DecryptedStringsGlobal; // \u0002
|
||||
private static byte[] _commonKey; // \u0005
|
||||
private static short _keyLength; // \u0008
|
||||
private static readonly Enum1 Enum1Dummy; // \u0003\u2000
|
||||
private static int _int1Dummy; // \u0002\u2000
|
||||
private static int _int2Dummy; // \u000F
|
||||
private static int _int3Dummy; // \u0006
|
||||
private static byte[] _pkt; // \u000E
|
||||
|
||||
// Token: 0x060002CE RID: 718 RVA: 0x00013060 File Offset: 0x00011260
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
static StringDecryptor()
|
||||
{
|
||||
var num = -42518532;
|
||||
var num2 = num ^ 1885636661;
|
||||
DecryptedStringsGlobal = new DecryptedStrings(1970604170 + num + num2 /*9*/);
|
||||
|
||||
var num3 = 2;
|
||||
var stackTrace = new StackTrace(num3, false);
|
||||
num3 -= 2;
|
||||
var frame = stackTrace.GetFrame(num3);
|
||||
var index = num3;
|
||||
if (frame == null)
|
||||
{
|
||||
stackTrace = new StackTrace();
|
||||
index = 1;
|
||||
frame = stackTrace.GetFrame(index);
|
||||
}
|
||||
var num4 = ~- -~~-~-~(1341405001 ^ num ^ num2) ^ -~~- -~-~~(2095196650 + num - num2);
|
||||
var methodBase = frame?.GetMethod();
|
||||
if (frame != null)
|
||||
{
|
||||
num4 ^= ~- -~~-~-~(num ^ -1658751032 ^ num2);
|
||||
}
|
||||
var type = methodBase?.DeclaringType;
|
||||
if (type == typeof(RuntimeMethodHandle))
|
||||
{
|
||||
Enum1Dummy = (Enum1)(4 | (int)Enum1Dummy);
|
||||
num4 ^= 1970604898 + num + num2 + num3;
|
||||
}
|
||||
else if (type == null)
|
||||
{
|
||||
if (CheckStack(stackTrace, index))
|
||||
{
|
||||
num4 ^= ~-~- -~~-~(-1970628130 - num - num2) - num3;
|
||||
Enum1Dummy = (Enum1)(16 | (int)Enum1Dummy);
|
||||
}
|
||||
else
|
||||
{
|
||||
num4 ^= ~- -~~-~-~(num ^ -1885608078 ^ num2);
|
||||
Enum1Dummy = (Enum1)(1 | (int)Enum1Dummy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num4 ^= ~-~- -~~-~(1885542988 - num + num2) - num3;
|
||||
Enum1Dummy = (Enum1)(16 | (int)Enum1Dummy);
|
||||
}
|
||||
_int1Dummy += num4;
|
||||
}
|
||||
|
||||
// Token: 0x060002CF RID: 719 RVA: 0x000131D4 File Offset: 0x000113D4
|
||||
public static string GetString(int id) // \u0002
|
||||
{
|
||||
lock (DecryptedStringsGlobal)
|
||||
{
|
||||
return DecryptedStringsGlobal[id] ?? DecryptString(id, true);
|
||||
}
|
||||
}
|
||||
public static void SetString(int id, string val) // for unit tests
|
||||
{
|
||||
lock (DecryptedStringsGlobal)
|
||||
{
|
||||
DecryptedStringsGlobal[id] = val;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060002D0 RID: 720 RVA: 0x00013224 File Offset: 0x00011424
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static string DecryptString(int id, bool dummy) // \u0002
|
||||
{
|
||||
var num = 1500675437;
|
||||
var num2 = 1065028357 - num;
|
||||
byte[] key;
|
||||
string str;
|
||||
int num6;
|
||||
if (_binStreamReader == null)
|
||||
{
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
_int3Dummy |= num ^ -1084071305 ^ num2;
|
||||
var stringBuilder = new StringBuilder();
|
||||
var num3 = -1821765671 - num + num2;
|
||||
stringBuilder.Append((char)(num3 >> 16)).Append((char)num3);
|
||||
num3 = 1822175277 + num ^ num2;
|
||||
stringBuilder.Append((char)(num3 >> 16)).Append((char)num3);
|
||||
num3 = (1619914499 ^ num) + num2;
|
||||
stringBuilder.Append((char)num3).Append((char)(num3 >> 16));
|
||||
num3 = 1602104074 - num - num2;
|
||||
stringBuilder.Append((char)num3).Append((char)(num3 >> 16));
|
||||
num3 = (num ^ 1619980037) + num2;
|
||||
stringBuilder.Append((char)num3).Append((char)(num3 >> 16));
|
||||
num3 = num + -1398984659 - num2;
|
||||
stringBuilder.Append((char)num3).Append((char)(num3 >> 16));
|
||||
var manifestResourceStream = executingAssembly.GetManifestResourceStream(/* added by ursoft */ "forms_cil." +
|
||||
stringBuilder.ToString()
|
||||
/* added by ursoft */.GetHashCode().ToString());
|
||||
var num4 = 2;
|
||||
var stackTrace = new StackTrace(num4, false);
|
||||
_int3Dummy ^= (1082521283 ^ num) + num2 | num4;
|
||||
num4 -= 2;
|
||||
var frame = stackTrace.GetFrame(num4);
|
||||
var index = num4;
|
||||
if (frame == null)
|
||||
{
|
||||
stackTrace = new StackTrace();
|
||||
index = 1;
|
||||
frame = stackTrace.GetFrame(index);
|
||||
}
|
||||
var methodBase = frame?.GetMethod();
|
||||
_int3Dummy ^= num4 + (num + -1936322645 ^ num2);
|
||||
var type = methodBase?.DeclaringType;
|
||||
if (frame == null)
|
||||
{
|
||||
_int3Dummy ^= 1065247672 - num - num2;
|
||||
}
|
||||
var flag = type == typeof(RuntimeMethodHandle);
|
||||
_int3Dummy ^= (num ^ 1082461797) + num2;
|
||||
if (!flag)
|
||||
{
|
||||
flag = type == null;
|
||||
if (flag)
|
||||
{
|
||||
if (CheckStack(stackTrace, index))
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_int3Dummy ^= 1065247640 - num - num2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
_int3Dummy ^= 32;
|
||||
}
|
||||
_int3Dummy ^= (num ^ 1082521251) + num2 | num4 + 1;
|
||||
_binStreamReader = new BinStreamReader(manifestResourceStream);
|
||||
var commonKeyLength = (short)(_binStreamReader.ReadHeaderInt16() ^ ~(short)-(short)-(short)~(short)~(short)-(short)~(short)-(short)~(short)-(short)~(short)(-1065050389 + num ^ num2));
|
||||
if (commonKeyLength == 0)
|
||||
{
|
||||
_keyLength = (short)(_binStreamReader.ReadHeaderInt16() ^ -(short)~(short)~(short)-(short)-(short)~(short)~(short)-(short)-(short)~(short)~(short)((-1082482306 ^ num) - num2));
|
||||
}
|
||||
else
|
||||
{
|
||||
_commonKey = _binStreamReader.Read(commonKeyLength);
|
||||
}
|
||||
var assembly = executingAssembly;
|
||||
var assemblyName = SafeAssemblyName(assembly);
|
||||
_pkt = SafeAssemblyPkt(assemblyName);
|
||||
num6 = _int1Dummy;
|
||||
_int1Dummy = 0;
|
||||
var num7 = SdMetadataTokens.GetLong();
|
||||
num6 ^= (int)(uint)num7;
|
||||
num6 ^= -888987382 - num + num2;
|
||||
var num8 = num6;
|
||||
var num9 = num8;
|
||||
var num10 = 0;
|
||||
var num11 = num9 ^ -1693408934 + num - num2;
|
||||
var num12 = num11 * (1936327810 - num + num2) % ((num ^ -1092770072) - num2);
|
||||
var num13 = num12;
|
||||
var obj = ((I2<int>)new SdTemplateStuff.C(-1065028359 + num | num2)
|
||||
{
|
||||
I6 = num13
|
||||
}).I2M();
|
||||
try
|
||||
{
|
||||
while (obj.I4M())
|
||||
{
|
||||
var num14 = obj.I1M();
|
||||
num12 ^= num10 - num14 << 2;
|
||||
num10 += num12 >> 3;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
obj?.I5M();
|
||||
}
|
||||
num6 ^= ~- -~-~~- -~~(num ^ 1140387705 ^ num2);
|
||||
var num15 = num12;
|
||||
num6 = num15 + num6;
|
||||
_int2Dummy = num6;
|
||||
_int3Dummy = (_int3Dummy & -1667887203 + num - num2) ^ (num ^ 1082519937) + num2;
|
||||
if ((Enum1Dummy & (Enum1)(-~~- -~-~~(1936322518 - num ^ num2))) == 0)
|
||||
{
|
||||
_int3Dummy = (-1082440641 ^ num) - num2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num6 = _int2Dummy;
|
||||
}
|
||||
if (_int3Dummy == 1936366479 - num + num2)
|
||||
{
|
||||
return new string(new[] { (char)((-1082462051 ^ num) - num2), '0', (char)(num + -1065028269 + num2) });
|
||||
}
|
||||
var num16 = id ^ -1010833342 ^ num ^ num2 ^ num6;
|
||||
num16 ^= -1459130838 - num + num2;
|
||||
_binStreamReader.GetStream().Position = num16;
|
||||
if (_commonKey != null)
|
||||
{
|
||||
key = _commonKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
short keyLength;
|
||||
if (_keyLength == -1)
|
||||
{
|
||||
keyLength = (short)(_binStreamReader.ReadHeaderInt32() ^ num + -1936293566 - num2 ^ num16);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyLength = _keyLength;
|
||||
}
|
||||
if (keyLength == 0)
|
||||
{
|
||||
key = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = _binStreamReader.Read(keyLength);
|
||||
for (var i = 0; i != key.Length; i = 1 + i)
|
||||
{
|
||||
key[i] ^= (byte)(_int2Dummy >> ((3 & i) << 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
var stringHeader = _binStreamReader.ReadHeaderInt32() ^ num16 ^ -~~-~-~-~((num ^ -1882046960) + num2) ^ num6;
|
||||
if (stringHeader != (1936322515 - num | num2))
|
||||
{
|
||||
var flagAnsi = (stringHeader & 211161131 + num - num2) != 0;
|
||||
var flagCompressed = (stringHeader & (-8713467 - num ^ num2)) != 0;
|
||||
var flagSecure = (stringHeader & (1619332869 ^ num) + num2) != 0;
|
||||
stringHeader &= num + -1870334726 ^ num2;
|
||||
var packedStringBuf = _binStreamReader.Read(stringHeader);
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
var key1 = key[1];
|
||||
var length = packedStringBuf.Length;
|
||||
var key1XorLen = (byte)(11 + length ^ 7 + key1);
|
||||
var keysXorLen = (uint)((key[0] | key[2] << 8) + (key1XorLen << 3));
|
||||
ushort keysXorLenLowWord = 0;
|
||||
for (var index = 0; index < length; ++index)
|
||||
{
|
||||
if ((index & 1) == 0)
|
||||
{
|
||||
keysXorLen = keysXorLen * (uint)((num ^ -1082544904) - num2) + (uint)(num + -1933863442 ^ num2);
|
||||
keysXorLenLowWord = (ushort)(keysXorLen >> 16);
|
||||
}
|
||||
var keysXorLenLowByte = (byte)keysXorLenLowWord;
|
||||
keysXorLenLowWord = (ushort)(keysXorLenLowWord >> 8);
|
||||
var inByte = packedStringBuf[index];
|
||||
packedStringBuf[index] = (byte)(inByte ^ key1 ^ 3 + key1XorLen ^ keysXorLenLowByte);
|
||||
key1XorLen = inByte;
|
||||
}
|
||||
if (_pkt != null != (_int3Dummy != (-1085052045 ^ num) - num2))
|
||||
{
|
||||
for (var j = 0; j < stringHeader; j = 1 + j)
|
||||
{
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
var b5 = _pkt[7 & j];
|
||||
b5 = (byte)(b5 << 3 | b5 >> 5);
|
||||
packedStringBuf[j] ^= b5;
|
||||
}
|
||||
}
|
||||
var num23 = _int3Dummy - 12;
|
||||
int unpackedLength;
|
||||
byte[] unpackedStringBuf;
|
||||
if (!flagCompressed)
|
||||
{
|
||||
unpackedLength = stringHeader;
|
||||
unpackedStringBuf = packedStringBuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
unpackedLength = packedStringBuf[2] | packedStringBuf[0] << 16 | packedStringBuf[3] << 8 | packedStringBuf[1] << 24;
|
||||
unpackedStringBuf = new byte[unpackedLength];
|
||||
Unpack(packedStringBuf, 4, unpackedStringBuf);
|
||||
}
|
||||
if (flagAnsi && num23 == (num + -1935832971 ^ num2))
|
||||
{
|
||||
var chArray = new char[unpackedLength];
|
||||
for (var k = 0; k < unpackedLength; k++)
|
||||
{
|
||||
chArray[k] = (char)unpackedStringBuf[k];
|
||||
}
|
||||
str = new string(chArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = Encoding.Unicode.GetString(unpackedStringBuf, 0, unpackedStringBuf.Length);
|
||||
}
|
||||
num23 += (-1082461318 ^ num) - num2 + (3 & num23) << 5;
|
||||
if (num23 != (1065521775 - num ^ num2))
|
||||
{
|
||||
var num25 = stringHeader + id ^ -1935385949 + num - num2 ^ (num23 & (-1082460680 ^ num ^ num2));
|
||||
var stringBuilder = new StringBuilder();
|
||||
var num3 = 1065028445 - num - num2;
|
||||
stringBuilder.Append((char)(byte)num3);
|
||||
str = num25.ToString(stringBuilder.ToString());
|
||||
}
|
||||
if (!flagSecure & dummy)
|
||||
{
|
||||
str = string.Intern(str);
|
||||
DecryptedStringsGlobal[id] = str;
|
||||
if (DecryptedStringsGlobal.GetCachedPairs() == (num + -1936322454 ^ num2))
|
||||
{
|
||||
_binStreamReader.Close();
|
||||
_binStreamReader = null;
|
||||
_commonKey = null;
|
||||
_pkt = null;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
var refId = _binStreamReader.Read(4);
|
||||
id = -64102883 ^ num ^ num2 ^ num6;
|
||||
id = (refId[2] | refId[3] << 16 | refId[0] << 8 | refId[1] << 24) ^ -id;
|
||||
str = DecryptedStringsGlobal[id];
|
||||
return str;
|
||||
}
|
||||
|
||||
// Token: 0x060002D1 RID: 721 RVA: 0x00013A28 File Offset: 0x00011C28
|
||||
private static AssemblyName SafeAssemblyName(Assembly a) // \u0002
|
||||
{
|
||||
AssemblyName result;
|
||||
try
|
||||
{
|
||||
result = a.GetName();
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = new AssemblyName(a.FullName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Token: 0x060002D2 RID: 722 RVA: 0x00013A60 File Offset: 0x00011C60
|
||||
private static byte[] SafeAssemblyPkt(AssemblyName an) // \u0002
|
||||
{
|
||||
var array = an.GetPublicKeyToken();
|
||||
if (array != null && array.Length == 0)
|
||||
{
|
||||
array = null;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Token: 0x060002D3 RID: 723 RVA: 0x00013A80 File Offset: 0x00011C80
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool CheckStack(StackTrace st, int idx) // \u0002
|
||||
{
|
||||
var a = st.GetFrame(idx + 1)?.GetMethod()?.DeclaringType?.Assembly;
|
||||
if (a != null)
|
||||
{
|
||||
var assemblyName = SafeAssemblyName(a);
|
||||
var array = SafeAssemblyPkt(assemblyName);
|
||||
if (array != null && array.Length == 8 && array[0] == 183 && array[7] == 137)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Token: 0x060002D4 RID: 724 RVA: 0x00013AF0 File Offset: 0x00011CF0
|
||||
private static void Unpack(byte[] packedStringBuf, int idxPacked, byte[] unpackedStringBuf) // \u0002
|
||||
{
|
||||
var idxUnpacked = 0;
|
||||
var packedBlockHeader = 0;
|
||||
var byteMask = 0x80;
|
||||
var unpackLen = unpackedStringBuf.Length;
|
||||
while (idxUnpacked < unpackLen)
|
||||
{
|
||||
byteMask <<= 1;
|
||||
if (byteMask == 0x100)
|
||||
{
|
||||
byteMask = 1;
|
||||
packedBlockHeader = packedStringBuf[idxPacked++];
|
||||
}
|
||||
if ((packedBlockHeader & byteMask) == 0)
|
||||
{
|
||||
unpackedStringBuf[idxUnpacked++] = packedStringBuf[idxPacked++];
|
||||
continue;
|
||||
}
|
||||
var knownWordLen = (packedStringBuf[idxPacked] >> 2) + 3;
|
||||
var knownWordOffset = ((packedStringBuf[idxPacked] << 8) | packedStringBuf[idxPacked + 1]) & 0x3ff;
|
||||
idxPacked += 2;
|
||||
var knownWordIdx = idxUnpacked - knownWordOffset;
|
||||
if (knownWordIdx < 0)
|
||||
return;
|
||||
while (--knownWordLen >= 0 && idxUnpacked < unpackLen)
|
||||
{
|
||||
unpackedStringBuf[idxUnpacked++] = unpackedStringBuf[knownWordIdx++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0200003E RID: 62
|
||||
internal sealed class BinStreamReader // \u0003\u2002\u200A\u2008\u2008\u200B\u2002\u2006\u2002\u2009\u2009\u2006\u2004\u2006\u2002\u2007\u2006\u2003\u2001\u2007\u2003\u200A\u2009\u200B\u2003\u2001
|
||||
{
|
||||
private byte[] _header; // \u0003
|
||||
private Stream _stream; // \u0002
|
||||
|
||||
// Token: 0x060002D5 RID: 725 RVA: 0x00013B94 File Offset: 0x00011D94
|
||||
public BinStreamReader(Stream stream)
|
||||
{
|
||||
_stream = stream;
|
||||
_header = new byte[4];
|
||||
}
|
||||
|
||||
// Token: 0x060002D6 RID: 726 RVA: 0x00013BB0 File Offset: 0x00011DB0
|
||||
public Stream GetStream() // \u0002
|
||||
{
|
||||
return _stream;
|
||||
}
|
||||
|
||||
// Token: 0x060002D7 RID: 727 RVA: 0x00013BB8 File Offset: 0x00011DB8
|
||||
public short ReadHeaderInt16() // \u0002
|
||||
{
|
||||
ReadHeader(2);
|
||||
return (short) (_header[0] | (_header[1] << 8));
|
||||
}
|
||||
|
||||
// Token: 0x060002D8 RID: 728 RVA: 0x00013BD8 File Offset: 0x00011DD8
|
||||
public int ReadHeaderInt32() // \u0002
|
||||
{
|
||||
ReadHeader(4);
|
||||
return _header[0] | (_header[1] << 8) | (_header[2] << 0x10) | (_header[3] << 0x18);
|
||||
}
|
||||
|
||||
// Token: 0x060002D9 RID: 729 RVA: 0x00013C0C File Offset: 0x00011E0C
|
||||
private void ThrowEOS() // \u0002
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
// Token: 0x060002DA RID: 730 RVA: 0x00013C14 File Offset: 0x00011E14
|
||||
private void ReadHeader(int headerSize) // \u0002
|
||||
{
|
||||
var offset = 0;
|
||||
int read;
|
||||
if (headerSize == 1)
|
||||
{
|
||||
read = _stream.ReadByte();
|
||||
if (read == -1)
|
||||
ThrowEOS();
|
||||
_header[0] = (byte) read;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
read = _stream.Read(_header, offset, headerSize - offset);
|
||||
if (read == 0)
|
||||
ThrowEOS();
|
||||
offset += read;
|
||||
} while (offset < headerSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060002DB RID: 731 RVA: 0x00013C74 File Offset: 0x00011E74
|
||||
public void Close() // \u0003
|
||||
{
|
||||
var stream = _stream;
|
||||
_stream = null;
|
||||
stream?.Close();
|
||||
_header = null;
|
||||
}
|
||||
|
||||
// Token: 0x060002DC RID: 732 RVA: 0x00013CA0 File Offset: 0x00011EA0
|
||||
public byte[] Read(int bytesCount) // \u0002
|
||||
{
|
||||
if (bytesCount < 0)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
var buffer = new byte[bytesCount];
|
||||
var offset = 0;
|
||||
do
|
||||
{
|
||||
var read = _stream.Read(buffer, offset, bytesCount);
|
||||
if (read == 0)
|
||||
break;
|
||||
offset += read;
|
||||
bytesCount -= read;
|
||||
} while (bytesCount > 0);
|
||||
if (offset != buffer.Length)
|
||||
{
|
||||
var dst = new byte[offset];
|
||||
Buffer.BlockCopy(buffer, 0, dst, 0, offset);
|
||||
buffer = dst;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x0200003F RID: 63
|
||||
internal sealed class DecryptedStrings // \u0005\u2001\u2007\u200B\u2000\u2008\u2008\u2000\u2000\u2006\u2004\u2008\u200B\u2002\u2006\u200B\u2001\u200B\u2003\u2004\u2001\u2004
|
||||
{
|
||||
private int _cachedPairs; // \u0003
|
||||
private Pair[] _arr; // \u0002
|
||||
|
||||
// Token: 0x060002DD RID: 733 RVA: 0x00013CFC File Offset: 0x00011EFC
|
||||
public DecryptedStrings()
|
||||
{
|
||||
_arr = new Pair[0x10];
|
||||
}
|
||||
|
||||
// Token: 0x060002DE RID: 734 RVA: 0x00013D14 File Offset: 0x00011F14
|
||||
public DecryptedStrings(int capacityHint)
|
||||
{
|
||||
var capacity = 0x10;
|
||||
capacityHint = capacityHint << 1;
|
||||
while ((capacity < capacityHint) && (capacity > 0))
|
||||
{
|
||||
capacity = capacity << 1;
|
||||
}
|
||||
if (capacity < 0)
|
||||
{
|
||||
capacity = 0x10;
|
||||
}
|
||||
_arr = new Pair[capacity];
|
||||
}
|
||||
|
||||
// Token: 0x060002DF RID: 735 RVA: 0x00013D54 File Offset: 0x00011F54
|
||||
public int GetCachedPairs()
|
||||
{
|
||||
return _cachedPairs;
|
||||
}
|
||||
|
||||
// Token: 0x060002E0 RID: 736 RVA: 0x00013D5C File Offset: 0x00011F5C
|
||||
private void GrowCache() // \u0002
|
||||
{
|
||||
var length = _arr.Length;
|
||||
var newLength = length * 2;
|
||||
if (newLength > 0)
|
||||
{
|
||||
var newArr = new Pair[newLength];
|
||||
var cnt = 0;
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
if (_arr[i].val != null)
|
||||
{
|
||||
var index = _arr[i].id & (newLength - 1);
|
||||
while (true)
|
||||
{
|
||||
if (newArr[index].val == null)
|
||||
{
|
||||
newArr[index].val = _arr[i].val;
|
||||
newArr[index].id = _arr[i].id;
|
||||
cnt++;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
if (index >= newLength)
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
_arr = newArr;
|
||||
_cachedPairs = cnt;
|
||||
}
|
||||
}
|
||||
|
||||
public string this[int id]
|
||||
{
|
||||
// Token: 0x060002E1 RID: 737 RVA: 0x00013E10 File Offset: 0x00012010
|
||||
get // \u0002
|
||||
{
|
||||
var length = _arr.Length;
|
||||
var index = id & (length - 1);
|
||||
do
|
||||
{
|
||||
if (_arr[index].id == id || _arr[index].val == null)
|
||||
return _arr[index].val;
|
||||
index++;
|
||||
if (index >= length)
|
||||
index = 0;
|
||||
} while (true);
|
||||
}
|
||||
// Token: 0x060002E2 RID: 738 RVA: 0x00013E6C File Offset: 0x0001206C
|
||||
set // \u0002
|
||||
{
|
||||
var length = _arr.Length;
|
||||
var halfLength = length >> 1;
|
||||
var index = id & (length - 1);
|
||||
do
|
||||
{
|
||||
var emptySlot = _arr[index].val == null;
|
||||
if (_arr[index].id == id || emptySlot)
|
||||
{
|
||||
_arr[index].val = value;
|
||||
if (emptySlot)
|
||||
{
|
||||
_arr[index].id = id;
|
||||
_cachedPairs++;
|
||||
if (_cachedPairs > halfLength)
|
||||
GrowCache();
|
||||
}
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
if (index >= length)
|
||||
index = 0;
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000040 RID: 64
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct Pair // \u0002
|
||||
{
|
||||
public int id;
|
||||
public string val;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x02000041 RID: 65
|
||||
[Flags]
|
||||
internal enum Enum1
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000055 RID: 85
|
||||
internal static class TypeCompatibility // \u000E\u2006
|
||||
{
|
||||
// Token: 0x06000341 RID: 833 RVA: 0x000152D4 File Offset: 0x000134D4
|
||||
public static bool Check(Type t1, Type t2) // t1
|
||||
{
|
||||
if (t1 == t2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (t1 == null || t2 == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t1.IsByRef)
|
||||
{
|
||||
return t2.IsByRef && Check(t1.GetElementType(), t2.GetElementType());
|
||||
}
|
||||
if (t2.IsByRef)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t1.IsPointer)
|
||||
{
|
||||
return t2.IsPointer && Check(t1.GetElementType(), t2.GetElementType());
|
||||
}
|
||||
if (t2.IsPointer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t1.IsArray)
|
||||
{
|
||||
return t2.IsArray && t1.GetArrayRank() == t2.GetArrayRank() && Check(t1.GetElementType(), t2.GetElementType());
|
||||
}
|
||||
if (t2.IsArray)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t1.IsGenericType && !t1.IsGenericTypeDefinition)
|
||||
{
|
||||
t1 = t1.GetGenericTypeDefinition();
|
||||
}
|
||||
if (t2.IsGenericType && !t2.IsGenericTypeDefinition)
|
||||
{
|
||||
t2 = t2.GetGenericTypeDefinition();
|
||||
}
|
||||
return t1 == t2;
|
||||
}
|
||||
}
|
||||
}
|
2621
runtime/VMProtect.Runtime/Tests/UnitTestProject/RefVm/VariantBase.cs
Normal file
2621
runtime/VMProtect.Runtime/Tests/UnitTestProject/RefVm/VariantBase.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000045 RID: 69
|
||||
internal static class VariantFactory // \u0008\u2002
|
||||
{
|
||||
// Token: 0x060002F6 RID: 758 RVA: 0x000144E0 File Offset: 0x000126E0
|
||||
private static bool IsDerivedFrom<T>(Type obj) // \u0002
|
||||
{
|
||||
var typeFromHandle = typeof(T);
|
||||
return obj == typeFromHandle || obj.IsSubclassOf(typeFromHandle);
|
||||
}
|
||||
|
||||
// Token: 0x060002F7 RID: 759 RVA: 0x00014508 File Offset: 0x00012708
|
||||
public static VariantBase Convert(object src, Type t) // \u0002
|
||||
{
|
||||
var ret = src as VariantBase;
|
||||
if (ret != null)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (t == null)
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
return new ObjectVariant();
|
||||
}
|
||||
t = src.GetType();
|
||||
}
|
||||
t = ElementedTypeHelper.TryGoToPointerOrReferenceElementType(t);
|
||||
if (t == SimpleTypeHelper.ObjectType)
|
||||
{
|
||||
ret = new ObjectVariant();
|
||||
if (src != null && src.GetType() != SimpleTypeHelper.ObjectType)
|
||||
{
|
||||
ret.SetVariantType(src.GetType());
|
||||
}
|
||||
}
|
||||
else if (IsDerivedFrom<Array>(t))
|
||||
{
|
||||
ret = new ArrayVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<string>(t))
|
||||
{
|
||||
ret = new StringVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<IntPtr>(t))
|
||||
{
|
||||
ret = new IntPtrVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<UIntPtr>(t))
|
||||
{
|
||||
ret = new UIntPtrVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<ulong>(t))
|
||||
{
|
||||
ret = new UlongVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<uint>(t))
|
||||
{
|
||||
ret = new UintVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<ushort>(t))
|
||||
{
|
||||
ret = new UshortVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<long>(t))
|
||||
{
|
||||
ret = new LongVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<int>(t))
|
||||
{
|
||||
ret = new IntVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<short>(t))
|
||||
{
|
||||
ret = new ShortVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<byte>(t))
|
||||
{
|
||||
ret = new ByteVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<sbyte>(t))
|
||||
{
|
||||
ret = new SbyteVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<double>(t))
|
||||
{
|
||||
ret = new DoubleVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<float>(t))
|
||||
{
|
||||
ret = new FloatVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<bool>(t))
|
||||
{
|
||||
ret = new BoolVariant();
|
||||
}
|
||||
else if (IsDerivedFrom<char>(t))
|
||||
{
|
||||
ret = new CharVariant();
|
||||
}
|
||||
else if (SimpleTypeHelper.IsNullableGeneric(t))
|
||||
{
|
||||
var ov = new ObjectVariant();
|
||||
ov.SetVariantType(t);
|
||||
ret = ov;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsDerivedFrom<Enum>(t))
|
||||
{
|
||||
Enum e;
|
||||
if (src == null)
|
||||
{
|
||||
e = (Enum)Activator.CreateInstance(t);
|
||||
}
|
||||
else if (t == SimpleTypeHelper.EnumType && src is Enum)
|
||||
{
|
||||
e = (Enum)src;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = (Enum)Enum.ToObject(t, src);
|
||||
}
|
||||
return new EnumVariant(e);
|
||||
}
|
||||
if (IsDerivedFrom<ValueType>(t))
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
var vt = (t == SimpleTypeHelper.TypedReferenceType) ?
|
||||
FormatterServices.GetSafeUninitializedObject(SimpleTypeHelper.TypedReferenceType) :
|
||||
Activator.CreateInstance(t);
|
||||
ret = new ValueTypeVariant(vt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src.GetType() != t)
|
||||
{
|
||||
try
|
||||
{
|
||||
src = System.Convert.ChangeType(src, t);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
ret = new ValueTypeVariant(src);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ret = new ObjectVariant();
|
||||
}
|
||||
if (src != null)
|
||||
{
|
||||
ret.SetValueAbstract(src);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
7505
runtime/VMProtect.Runtime/Tests/UnitTestProject/RefVm/VmExecutor.cs
Normal file
7505
runtime/VMProtect.Runtime/Tests/UnitTestProject/RefVm/VmExecutor.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,899 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
// ReSharper disable UnusedMember.Global
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x0200002E RID: 46
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public class VmInstrCodesDb // \u0006\u2005
|
||||
{
|
||||
// Token: 0x04000068 RID: 104
|
||||
private VmInstrInfo[] _all;
|
||||
|
||||
// Token: 0x0400011D RID: 285
|
||||
private bool _initialized;
|
||||
|
||||
// Token: 0x0600015B RID: 347 RVA: 0x000075B8 File Offset: 0x000057B8
|
||||
public bool IsInitialized() // \u0002
|
||||
{
|
||||
return _initialized;
|
||||
}
|
||||
|
||||
// Token: 0x0600015C RID: 348 RVA: 0x000075C0 File Offset: 0x000057C0
|
||||
public void SetInitialized(bool val) // \u0002
|
||||
{
|
||||
_initialized = val;
|
||||
}
|
||||
|
||||
// Token: 0x0600015A RID: 346 RVA: 0x000075A8 File Offset: 0x000057A8
|
||||
public IEnumerable<VmInstrInfo> MyFieldsEnumerator() // \u0002
|
||||
{
|
||||
return new FieldsEnumerator(-2)
|
||||
{
|
||||
Source = this
|
||||
};
|
||||
}
|
||||
|
||||
// Token: 0x0600015D RID: 349 RVA: 0x000075CC File Offset: 0x000057CC
|
||||
public VmInstrInfo[] ToSortedArray() // \u0002
|
||||
{
|
||||
if (_all == null)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (_all == null)
|
||||
{
|
||||
var list = new List<VmInstrInfo>(256);
|
||||
list.AddRange(MyFieldsEnumerator());
|
||||
if (SortHelper.MyComparison == null)
|
||||
{
|
||||
SortHelper.MyComparison = SortHelper.MySortHelper.Compare;
|
||||
}
|
||||
list.Sort(SortHelper.MyComparison);
|
||||
_all = list.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _all;
|
||||
}
|
||||
|
||||
// Token: 0x0200002F RID: 47
|
||||
[Serializable]
|
||||
private sealed class SortHelper // \u0002
|
||||
{
|
||||
// Token: 0x06000160 RID: 352 RVA: 0x000076A0 File Offset: 0x000058A0
|
||||
internal int Compare(VmInstrInfo v1, VmInstrInfo v2) // \u0002
|
||||
{
|
||||
return v1.Id.CompareTo(v2.Id);
|
||||
}
|
||||
|
||||
// Token: 0x04000129 RID: 297
|
||||
public static readonly SortHelper MySortHelper = new SortHelper(); // \u0002
|
||||
|
||||
// Token: 0x0400012A RID: 298
|
||||
public static Comparison<VmInstrInfo> MyComparison; // \u0003
|
||||
}
|
||||
|
||||
// Token: 0x02000030 RID: 48
|
||||
private sealed class FieldsEnumerator : IEnumerable<VmInstrInfo>, IEnumerator<VmInstrInfo> // \u0003
|
||||
{
|
||||
// Token: 0x06000161 RID: 353 RVA: 0x000076C4 File Offset: 0x000058C4
|
||||
public FieldsEnumerator(int st)
|
||||
{
|
||||
_state = st;
|
||||
_threadId = Thread.CurrentThread.ManagedThreadId;
|
||||
}
|
||||
|
||||
// Token: 0x06000162 RID: 354 RVA: 0x000076E4 File Offset: 0x000058E4
|
||||
void IDisposable.Dispose() // \u0003\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x06000163 RID: 355 RVA: 0x000076E8 File Offset: 0x000058E8
|
||||
bool IEnumerator.MoveNext()
|
||||
{
|
||||
var num = _state;
|
||||
if (num != 0)
|
||||
{
|
||||
if (num != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_state = -1;
|
||||
_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = -1;
|
||||
var fields = typeof(VmInstrCodesDb).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
|
||||
_data = fields;
|
||||
_index = 0;
|
||||
}
|
||||
if (_index >= _data.Length)
|
||||
{
|
||||
_data = null;
|
||||
return false;
|
||||
}
|
||||
var p = (VmInstrInfo)_data[_index].GetValue(Source);
|
||||
_current = p;
|
||||
_state = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Token: 0x06000164 RID: 356 RVA: 0x00007790 File Offset: 0x00005990
|
||||
VmInstrInfo IEnumerator<VmInstrInfo>.Current // \u0003\u2008\u2000\u2002\u200A\u0002
|
||||
=> _current;
|
||||
|
||||
// Token: 0x06000165 RID: 357 RVA: 0x00007798 File Offset: 0x00005998
|
||||
[DebuggerHidden]
|
||||
void IEnumerator.Reset() // \u0003\u2008\u2000\u2002\u200A\u0003
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
// Token: 0x06000166 RID: 358 RVA: 0x000077A0 File Offset: 0x000059A0
|
||||
[DebuggerHidden]
|
||||
object IEnumerator.Current // \u0003\u2008\u2000\u2002\u200A\u0002
|
||||
=> _current;
|
||||
|
||||
// Token: 0x06000167 RID: 359 RVA: 0x000077A8 File Offset: 0x000059A8
|
||||
[DebuggerHidden]
|
||||
IEnumerator<VmInstrInfo> IEnumerable<VmInstrInfo>.GetEnumerator() // \u0003\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
FieldsEnumerator ret;
|
||||
if (_state == -2 && _threadId == Thread.CurrentThread.ManagedThreadId)
|
||||
{
|
||||
_state = 0;
|
||||
ret = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = new FieldsEnumerator(0) {Source = Source};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Token: 0x06000168 RID: 360 RVA: 0x000077F0 File Offset: 0x000059F0
|
||||
[DebuggerHidden]
|
||||
IEnumerator IEnumerable.GetEnumerator() // \u0003\u2008\u2000\u2002\u200A\u0002
|
||||
{
|
||||
return ((IEnumerable<VmInstrInfo>)this).GetEnumerator();
|
||||
}
|
||||
|
||||
// Token: 0x0400012B RID: 299
|
||||
private int _state; // \u0002
|
||||
|
||||
// Token: 0x0400012C RID: 300
|
||||
private VmInstrInfo _current; // \u0003
|
||||
|
||||
// Token: 0x0400012D RID: 301
|
||||
private readonly int _threadId; // \u0005
|
||||
|
||||
// Token: 0x0400012E RID: 302
|
||||
public VmInstrCodesDb Source; // \u0008
|
||||
|
||||
// Token: 0x0400012F RID: 303
|
||||
private FieldInfo[] _data; // \u0006
|
||||
|
||||
// Token: 0x04000130 RID: 304
|
||||
private int _index; // \u000E
|
||||
}
|
||||
|
||||
#region all
|
||||
/*
|
||||
no. { typecheck, rangecheck, nullcheck } The specified fault check(s) normally performed as part of the execution of the subsequent instruction can/shall be skipped. Prefix to instruction
|
||||
readonly. Specify that the subsequent array address operation performs no type check at runtime, and that it returns a controlled-mutability managed pointer Prefix to instruction
|
||||
tail. Subsequent call terminates current method Prefix to instruction
|
||||
unaligned. (alignment) Subsequent pointer instruction might be unaligned. Prefix to instruction
|
||||
volatile. Subsequent pointer reference is volatile. Prefix to instruction
|
||||
*/
|
||||
// Token: 0x04000063 RID: 99
|
||||
public readonly VmInstrInfo U0002U2000 = new VmInstrInfo(690984147, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x04000077 RID: 119
|
||||
public readonly VmInstrInfo U0006U2001U2000 = new VmInstrInfo(733028785, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x0400007A RID: 122
|
||||
public readonly VmInstrInfo U0006U2001 = new VmInstrInfo(701247957, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x04000086 RID: 134
|
||||
public readonly VmInstrInfo U0006U2004 = new VmInstrInfo(-377358754, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x040000B0 RID: 176
|
||||
public readonly VmInstrInfo U0006U2008U2000 = new VmInstrInfo(1026942272, VmOperandType.Ot11Nope); // empty impl
|
||||
|
||||
// Token: 0x040000B2 RID: 178
|
||||
public readonly VmInstrInfo Endfilter_ = new VmInstrInfo(-1041717787, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C6 RID: 198
|
||||
public readonly VmInstrInfo Mul_ovf_ = new VmInstrInfo(717697778, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000CB RID: 203
|
||||
public readonly VmInstrInfo Endfinally_ = new VmInstrInfo(-860175516, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000E0 RID: 224
|
||||
public readonly VmInstrInfo U0003U2009 = new VmInstrInfo(-1535884281, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x04000080 RID: 128
|
||||
public readonly VmInstrInfo U000EU2006U2000 = new VmInstrInfo(1756761351, VmOperandType.Ot5Int); // ??? invoke some method
|
||||
|
||||
// Token: 0x04000082 RID: 130
|
||||
public readonly VmInstrInfo Jmp_ = new VmInstrInfo(-512817309, VmOperandType.Ot12Int);
|
||||
|
||||
// Token: 0x040000CC RID: 204
|
||||
public readonly VmInstrInfo Initobj_ = new VmInstrInfo(-647649665, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000065 RID: 101
|
||||
public readonly VmInstrInfo Calli_ = new VmInstrInfo(1295283437, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400006F RID: 111
|
||||
public readonly VmInstrInfo Constrained_ = new VmInstrInfo(1803463719, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000098 RID: 152
|
||||
public readonly VmInstrInfo U000FU2001 = new VmInstrInfo(-1952417400, VmOperandType.Ot5Int); // empty impl
|
||||
|
||||
// Token: 0x040000E1 RID: 225
|
||||
public readonly VmInstrInfo Box_ = new VmInstrInfo(1491096114, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000E4 RID: 228
|
||||
public readonly VmInstrInfo U0006U200BU2000 = new VmInstrInfo(-1858492701, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x040000ED RID: 237
|
||||
public readonly VmInstrInfo U0002U2002U2001 = new VmInstrInfo(113196648, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x040000EF RID: 239
|
||||
public readonly VmInstrInfo Ldobj_ = new VmInstrInfo(-564585233, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000104 RID: 260
|
||||
public readonly VmInstrInfo Rethrow_ = new VmInstrInfo(989001448, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000125 RID: 293
|
||||
public readonly VmInstrInfo U000EU2000U2000 = new VmInstrInfo(814546329, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x040000B8 RID: 184
|
||||
public readonly VmInstrInfo Newobj_ = new VmInstrInfo(783240206, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000B9 RID: 185
|
||||
public readonly VmInstrInfo U0006U2000U2000 = new VmInstrInfo(569679686, VmOperandType.Ot11Nope); // not implemented
|
||||
|
||||
// Token: 0x040000BD RID: 189
|
||||
public readonly VmInstrInfo U0002U200B = new VmInstrInfo(578506051, VmOperandType.Ot6SByte); // leave.s not implemented
|
||||
|
||||
// Token: 0x040000BE RID: 190
|
||||
public readonly VmInstrInfo Leave_ = new VmInstrInfo(182069479, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000B3 RID: 179
|
||||
//public readonly VmInstrInfo U0003U2008 = new VmInstrInfo(56035065, VmOperandType.Nope11);
|
||||
|
||||
// Token: 0x04000052 RID: 82
|
||||
public readonly VmInstrInfo Ldnull_ = new VmInstrInfo(1672432034, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000057 RID: 87
|
||||
public readonly VmInstrInfo Pop_ = new VmInstrInfo(-423590017, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400005B RID: 91
|
||||
public readonly VmInstrInfo Ckfinite_ = new VmInstrInfo(-624596400, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400005D RID: 93
|
||||
public readonly VmInstrInfo Stind_i2_ = new VmInstrInfo(81292670, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400006C RID: 108
|
||||
public readonly VmInstrInfo Stind_r8_ = new VmInstrInfo(-239256528, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000074 RID: 116
|
||||
public readonly VmInstrInfo Ldftn_ = new VmInstrInfo(-204727488, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000076 RID: 118
|
||||
public readonly VmInstrInfo Ldlen_ = new VmInstrInfo(-1528794514, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000079 RID: 121
|
||||
public readonly VmInstrInfo Isinst_ = new VmInstrInfo(-1879745689, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000081 RID: 129
|
||||
public readonly VmInstrInfo Stind_i8_ = new VmInstrInfo(-279385973, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000087 RID: 135
|
||||
public readonly VmInstrInfo Newarr_ = new VmInstrInfo(1211659810, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000089 RID: 137
|
||||
public readonly VmInstrInfo Callvirt_ = new VmInstrInfo(497685394, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400008A RID: 138
|
||||
public readonly VmInstrInfo Ldc_i8_ = new VmInstrInfo(598097099, VmOperandType.Ot7Long);
|
||||
|
||||
// Token: 0x0400009A RID: 154
|
||||
public readonly VmInstrInfo Castclass_ = new VmInstrInfo(1816382558, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400009C RID: 156
|
||||
public readonly VmInstrInfo Stind_i_ = new VmInstrInfo(-774914583, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400009D RID: 157
|
||||
public readonly VmInstrInfo Ldc_i4_s_ = new VmInstrInfo(1440000960, VmOperandType.Ot6SByte);
|
||||
|
||||
// Token: 0x040000A7 RID: 167
|
||||
public readonly VmInstrInfo Not_ = new VmInstrInfo(2044815068, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A8 RID: 168
|
||||
public readonly VmInstrInfo Ldtoken_ = new VmInstrInfo(757747961, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000AD RID: 173
|
||||
public readonly VmInstrInfo Stind_i4_ = new VmInstrInfo(-587303415, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000B6 RID: 182
|
||||
public readonly VmInstrInfo Ldvirtftn_ = new VmInstrInfo(-1088007919, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000BA RID: 186
|
||||
public readonly VmInstrInfo Stind_i1_ = new VmInstrInfo(122987244, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000BC RID: 188
|
||||
public readonly VmInstrInfo Cgt_ = new VmInstrInfo(-290816002, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C4 RID: 196
|
||||
public readonly VmInstrInfo Stobj_ = new VmInstrInfo(-18831398, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000C5 RID: 197
|
||||
public readonly VmInstrInfo Clt_un_ = new VmInstrInfo(-377042092, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000DD RID: 221
|
||||
public readonly VmInstrInfo Cgt_un_ = new VmInstrInfo(-244421767, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000D6 RID: 214
|
||||
public readonly VmInstrInfo Stind_ref_ = new VmInstrInfo(-572078212, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000DF RID: 223
|
||||
public readonly VmInstrInfo Ldloca_ = new VmInstrInfo(-1112986259, VmOperandType.Ot1UShort);
|
||||
|
||||
// Token: 0x040000E9 RID: 233
|
||||
public readonly VmInstrInfo Call_ = new VmInstrInfo(-1118186024, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000F9 RID: 249
|
||||
public readonly VmInstrInfo Ldc_r8_ = new VmInstrInfo(-557730397, VmOperandType.Ot4Double);
|
||||
|
||||
// Token: 0x040000FD RID: 253
|
||||
public readonly VmInstrInfo Clt_ = new VmInstrInfo(-1789431058, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000107 RID: 263
|
||||
public readonly VmInstrInfo Ldc_i4_ = new VmInstrInfo(-763377227, VmOperandType.Ot12Int);
|
||||
|
||||
// Token: 0x04000112 RID: 274
|
||||
public readonly VmInstrInfo Ldc_r4_ = new VmInstrInfo(-976252990, VmOperandType.Ot10Float);
|
||||
|
||||
// Token: 0x04000116 RID: 278
|
||||
public readonly VmInstrInfo Stind_r4_ = new VmInstrInfo(2036802079, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000119 RID: 281
|
||||
public readonly VmInstrInfo Nop_ = new VmInstrInfo(-724560934, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400011E RID: 286
|
||||
public readonly VmInstrInfo Ldloca_s_ = new VmInstrInfo(1851592203, VmOperandType.Ot8Byte);
|
||||
|
||||
// Token: 0x04000053 RID: 83
|
||||
public readonly VmInstrInfo Sizeof_ = new VmInstrInfo(-1163259743, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000054 RID: 84
|
||||
public readonly VmInstrInfo Ldind_r4_ = new VmInstrInfo(1144322863, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000055 RID: 85
|
||||
public readonly VmInstrInfo Ldelem_i1_ = new VmInstrInfo(322204500, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000056 RID: 86
|
||||
public readonly VmInstrInfo Conv_r8_ = new VmInstrInfo(-195608730, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000058 RID: 88
|
||||
public readonly VmInstrInfo Stelem_i1_ = new VmInstrInfo(-1560659480, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000059 RID: 89
|
||||
public readonly VmInstrInfo Ldstr_ = new VmInstrInfo(-883753595, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400005A RID: 90
|
||||
public readonly VmInstrInfo Conv_i4_ = new VmInstrInfo(1738936149, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400005C RID: 92
|
||||
public readonly VmInstrInfo Ldarg_2_ = new VmInstrInfo(917707539, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400005E RID: 94
|
||||
public readonly VmInstrInfo Conv_i1_ = new VmInstrInfo(443736782, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400005F RID: 95
|
||||
public readonly VmInstrInfo Div_ = new VmInstrInfo(873071583, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000060 RID: 96
|
||||
public readonly VmInstrInfo Conv_i_ = new VmInstrInfo(863451657, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000061 RID: 97
|
||||
public readonly VmInstrInfo Stelem_ref_ = new VmInstrInfo(1243606418, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000062 RID: 98
|
||||
public readonly VmInstrInfo Shl_ = new VmInstrInfo(1269228253, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000064 RID: 100
|
||||
public readonly VmInstrInfo Conv_u4_ = new VmInstrInfo(-1046006878, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000066 RID: 102
|
||||
public readonly VmInstrInfo Break_ = new VmInstrInfo(-979485219, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000067 RID: 103
|
||||
public readonly VmInstrInfo Ldc_i4_1_ = new VmInstrInfo(-2108713475, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000069 RID: 105
|
||||
public readonly VmInstrInfo Or_ = new VmInstrInfo(1569462844, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400006A RID: 106
|
||||
public readonly VmInstrInfo Ldelem_ = new VmInstrInfo(-1705118555, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400006B RID: 107
|
||||
public readonly VmInstrInfo Conv_u1_ = new VmInstrInfo(1055970854, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400006D RID: 109
|
||||
public readonly VmInstrInfo Ldind_i1_ = new VmInstrInfo(33169414, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400006E RID: 110
|
||||
public readonly VmInstrInfo Ldind_i_ = new VmInstrInfo(-1790442498, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000070 RID: 112
|
||||
public readonly VmInstrInfo Ldsfld_ = new VmInstrInfo(-1369658342, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x04000071 RID: 113
|
||||
public readonly VmInstrInfo Ldloc_ = new VmInstrInfo(766115889, VmOperandType.Ot1UShort);
|
||||
|
||||
// Token: 0x04000072 RID: 114
|
||||
public readonly VmInstrInfo Rem_un_ = new VmInstrInfo(-2121309775, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000073 RID: 115
|
||||
public readonly VmInstrInfo Conv_ovf_i8_ = new VmInstrInfo(-287049786, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000075 RID: 117
|
||||
public readonly VmInstrInfo Ldc_i4_0_ = new VmInstrInfo(89715609, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000078 RID: 120
|
||||
public readonly VmInstrInfo Ldloc_3_ = new VmInstrInfo(1790654656, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400007B RID: 123
|
||||
public readonly VmInstrInfo Ldsflda_ = new VmInstrInfo(-2097007575, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400007C RID: 124
|
||||
public readonly VmInstrInfo Add_ovf_ = new VmInstrInfo(-545700640, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400007D RID: 125
|
||||
public readonly VmInstrInfo Refanytype_ = new VmInstrInfo(-971088331, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400007E RID: 126
|
||||
public readonly VmInstrInfo Blt_ = new VmInstrInfo(1978323310, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x0400007F RID: 127
|
||||
public readonly VmInstrInfo Conv_ovf_u8_un_ = new VmInstrInfo(1527584358, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000083 RID: 131
|
||||
public readonly VmInstrInfo Ldelem_i8_ = new VmInstrInfo(1272142104, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000084 RID: 132
|
||||
public readonly VmInstrInfo Ldc_i4_6_ = new VmInstrInfo(871172961, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000085 RID: 133
|
||||
public readonly VmInstrInfo Starg_s_ = new VmInstrInfo(-687376789, VmOperandType.Ot8Byte);
|
||||
|
||||
// Token: 0x04000088 RID: 136
|
||||
public readonly VmInstrInfo Beq_ = new VmInstrInfo(352236975, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x0400008B RID: 139
|
||||
public readonly VmInstrInfo Ldfld_ = new VmInstrInfo(-688284774, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x0400008C RID: 140
|
||||
public readonly VmInstrInfo Conv_ovf_i2_un_ = new VmInstrInfo(1663762471, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400008D RID: 141
|
||||
public readonly VmInstrInfo Conv_ovf_i_un_ = new VmInstrInfo(2093357171, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400008E RID: 142
|
||||
public readonly VmInstrInfo Ldelem_u4_ = new VmInstrInfo(896332376, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400008F RID: 143
|
||||
public readonly VmInstrInfo Conv_ovf_u4_un_ = new VmInstrInfo(-107488823, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000090 RID: 144
|
||||
public readonly VmInstrInfo Ldarga_ = new VmInstrInfo(2044160323, VmOperandType.Ot1UShort);
|
||||
|
||||
// Token: 0x04000091 RID: 145
|
||||
public readonly VmInstrInfo Div_un_ = new VmInstrInfo(742839562, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000092 RID: 146
|
||||
public readonly VmInstrInfo Ldelem_r4_ = new VmInstrInfo(-1447311583, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000093 RID: 147
|
||||
public readonly VmInstrInfo And_ = new VmInstrInfo(1968373082, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000094 RID: 148
|
||||
public readonly VmInstrInfo Add_ = new VmInstrInfo(-1892228817, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000095 RID: 149
|
||||
public readonly VmInstrInfo Conv_ovf_u2_ = new VmInstrInfo(1775410326, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000096 RID: 150
|
||||
public readonly VmInstrInfo Xor_ = new VmInstrInfo(-273395395, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000097 RID: 151
|
||||
public readonly VmInstrInfo Stloc_1_ = new VmInstrInfo(-1446892238, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000099 RID: 153
|
||||
public readonly VmInstrInfo Conv_ovf_u2_un_ = new VmInstrInfo(-1274139658, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400009B RID: 155
|
||||
public readonly VmInstrInfo Ldc_i4_3_ = new VmInstrInfo(-722334296, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400009E RID: 158
|
||||
public readonly VmInstrInfo Ldelem_u1_ = new VmInstrInfo(580121148, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400009F RID: 159
|
||||
public readonly VmInstrInfo Ldelem_i4_ = new VmInstrInfo(778369289, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A0 RID: 160
|
||||
public readonly VmInstrInfo Stfld_ = new VmInstrInfo(1721102239, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000A1 RID: 161
|
||||
public readonly VmInstrInfo Ldc_i4_m1_ = new VmInstrInfo(-1374936951, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A2 RID: 162
|
||||
public readonly VmInstrInfo Brfalse_ = new VmInstrInfo(476056811, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000A3 RID: 163
|
||||
public readonly VmInstrInfo Rem_ = new VmInstrInfo(1127773841, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A4 RID: 164
|
||||
public readonly VmInstrInfo Neg_ = new VmInstrInfo(1824866698, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A5 RID: 165
|
||||
public readonly VmInstrInfo Initblk_ = new VmInstrInfo(1848160160, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A6 RID: 166
|
||||
public readonly VmInstrInfo Ldelem_r8_ = new VmInstrInfo(-522987252, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000A9 RID: 169
|
||||
public readonly VmInstrInfo Cpobj_ = new VmInstrInfo(1238115537, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000AA RID: 170
|
||||
public readonly VmInstrInfo Ldarga_s_ = new VmInstrInfo(-1193068213, VmOperandType.Ot8Byte);
|
||||
|
||||
// Token: 0x040000AB RID: 171
|
||||
public readonly VmInstrInfo Br_ = new VmInstrInfo(658728581, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000AC RID: 172
|
||||
public readonly VmInstrInfo Conv_u2_ = new VmInstrInfo(-2099750455, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000AE RID: 174
|
||||
public readonly VmInstrInfo Stelem_i_ = new VmInstrInfo(-358560507, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000AF RID: 175
|
||||
public readonly VmInstrInfo Stloc_s_ = new VmInstrInfo(1804315644, VmOperandType.Ot8Byte);
|
||||
|
||||
// Token: 0x040000B1 RID: 177
|
||||
public readonly VmInstrInfo Ble_un_ = new VmInstrInfo(1001656673, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000B4 RID: 180
|
||||
public readonly VmInstrInfo Ldc_i4_2_ = new VmInstrInfo(-2082446517, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000B5 RID: 181
|
||||
public readonly VmInstrInfo Blt_un_ = new VmInstrInfo(-1002275164, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000B7 RID: 183
|
||||
public readonly VmInstrInfo Ldind_ref_ = new VmInstrInfo(-101579585, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000BB RID: 187
|
||||
public readonly VmInstrInfo Ldind_i2_ = new VmInstrInfo(1338544134, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000BF RID: 191
|
||||
public readonly VmInstrInfo Shr_ = new VmInstrInfo(2061114403, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C0 RID: 192
|
||||
public readonly VmInstrInfo Sub_ovf_ = new VmInstrInfo(-1326124455, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C1 RID: 193
|
||||
public readonly VmInstrInfo Mul_ = new VmInstrInfo(-368354161, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C2 RID: 194
|
||||
public readonly VmInstrInfo Conv_r4_ = new VmInstrInfo(461467744, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C3 RID: 195
|
||||
public readonly VmInstrInfo Ldarg_s_ = new VmInstrInfo(916919316, VmOperandType.Ot8Byte);
|
||||
|
||||
// Token: 0x040000C7 RID: 199
|
||||
public readonly VmInstrInfo Conv_ovf_u8_ = new VmInstrInfo(-1916788012, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C8 RID: 200
|
||||
public readonly VmInstrInfo Ldind_u2_ = new VmInstrInfo(-1831891367, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000C9 RID: 201
|
||||
public readonly VmInstrInfo Ldind_u4_ = new VmInstrInfo(-1620795876, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000CA RID: 202
|
||||
public readonly VmInstrInfo Conv_ovf_i4_ = new VmInstrInfo(488024265, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000CD RID: 205
|
||||
public readonly VmInstrInfo Ldarg_1_ = new VmInstrInfo(326597331, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000CE RID: 206
|
||||
public readonly VmInstrInfo Conv_ovf_u_ = new VmInstrInfo(115989675, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000CF RID: 207
|
||||
public readonly VmInstrInfo Ldloc_s_ = new VmInstrInfo(1019004451, VmOperandType.Ot8Byte);
|
||||
|
||||
// Token: 0x040000D0 RID: 208
|
||||
public readonly VmInstrInfo Conv_i2_ = new VmInstrInfo(-108178384, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000D1 RID: 209
|
||||
public readonly VmInstrInfo Conv_ovf_i_ = new VmInstrInfo(-2109763431, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000D2 RID: 210
|
||||
public readonly VmInstrInfo Ble_ = new VmInstrInfo(1321262543, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000D3 RID: 211
|
||||
public readonly VmInstrInfo Unbox_ = new VmInstrInfo(-1668682548, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000D4 RID: 212
|
||||
public readonly VmInstrInfo Stelem_r4_ = new VmInstrInfo(-1251429380, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000D5 RID: 213
|
||||
public readonly VmInstrInfo Stloc_3_ = new VmInstrInfo(1073782561, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000D7 RID: 215
|
||||
public readonly VmInstrInfo Brtrue_ = new VmInstrInfo(1985375111, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000D8 RID: 216
|
||||
public readonly VmInstrInfo Stelem_ = new VmInstrInfo(-633052479, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000D9 RID: 217
|
||||
public readonly VmInstrInfo Stelem_i4_ = new VmInstrInfo(-638226942, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000DA RID: 218
|
||||
public readonly VmInstrInfo Conv_ovf_u1_un_ = new VmInstrInfo(-854623375, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000DB RID: 219
|
||||
public readonly VmInstrInfo Add_ovf_un_ = new VmInstrInfo(-2145629048, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000DC RID: 220
|
||||
public readonly VmInstrInfo Conv_u8_ = new VmInstrInfo(1396092080, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000DE RID: 222
|
||||
public readonly VmInstrInfo Bgt_ = new VmInstrInfo(-939929863, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000E2 RID: 226
|
||||
public readonly VmInstrInfo Bgt_un_ = new VmInstrInfo(-73779400, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000E3 RID: 227
|
||||
public readonly VmInstrInfo Stelem_r8_ = new VmInstrInfo(849078739, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000E5 RID: 229
|
||||
public readonly VmInstrInfo Mkrefany_ = new VmInstrInfo(1810420701, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000E6 RID: 230
|
||||
public readonly VmInstrInfo Conv_ovf_u_un_ = new VmInstrInfo(-1209242284, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000E7 RID: 231
|
||||
public readonly VmInstrInfo Conv_ovf_i1_ = new VmInstrInfo(-1678823314, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000E8 RID: 232
|
||||
public readonly VmInstrInfo Conv_ovf_i1_un_ = new VmInstrInfo(-1171707127, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000EA RID: 234
|
||||
public readonly VmInstrInfo Stsfld_ = new VmInstrInfo(-1272257470, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000EB RID: 235
|
||||
public readonly VmInstrInfo Starg_ = new VmInstrInfo(-1559324355, VmOperandType.Ot1UShort);
|
||||
|
||||
// Token: 0x040000EC RID: 236
|
||||
public readonly VmInstrInfo Ldflda_ = new VmInstrInfo(685223722, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000EE RID: 238
|
||||
public readonly VmInstrInfo Sub_ = new VmInstrInfo(1925911547, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F0 RID: 240
|
||||
public readonly VmInstrInfo Conv_ovf_i2_ = new VmInstrInfo(2079826493, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F1 RID: 241
|
||||
public readonly VmInstrInfo Ldarg_0_ = new VmInstrInfo(-1817778622, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F2 RID: 242
|
||||
public readonly VmInstrInfo Ldelem_i2_ = new VmInstrInfo(-1703864226, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F3 RID: 243
|
||||
public readonly VmInstrInfo Ceq_ = new VmInstrInfo(-490385948, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F4 RID: 244
|
||||
public readonly VmInstrInfo Ldelema_ = new VmInstrInfo(-659575843, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000F5 RID: 245
|
||||
public readonly VmInstrInfo Localloc_ = new VmInstrInfo(487454996, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F6 RID: 246
|
||||
public readonly VmInstrInfo Conv_ovf_i4_un_ = new VmInstrInfo(-900057353, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000F7 RID: 247
|
||||
public readonly VmInstrInfo Bge_un_ = new VmInstrInfo(784647969, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x040000F8 RID: 248
|
||||
public readonly VmInstrInfo Ldelem_ref_ = new VmInstrInfo(880972378, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000FA RID: 250
|
||||
public readonly VmInstrInfo Conv_ovf_i8_un_ = new VmInstrInfo(20637445, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000FB RID: 251
|
||||
public readonly VmInstrInfo Ldind_i8_ = new VmInstrInfo(-607543449, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000FC RID: 252
|
||||
public readonly VmInstrInfo Refanyval_ = new VmInstrInfo(1010177566, VmOperandType.Ot5Int);
|
||||
|
||||
// Token: 0x040000FE RID: 254
|
||||
public readonly VmInstrInfo Dup_ = new VmInstrInfo(85722172, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x040000FF RID: 255
|
||||
public readonly VmInstrInfo Stloc_0_ = new VmInstrInfo(-1071153572, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000100 RID: 256
|
||||
public readonly VmInstrInfo Ldc_i4_4_ = new VmInstrInfo(-72363801, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000101 RID: 257
|
||||
public readonly VmInstrInfo Ldind_r8_ = new VmInstrInfo(813030660, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000102 RID: 258
|
||||
public readonly VmInstrInfo Ldc_i4_7_ = new VmInstrInfo(-1136876649, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000103 RID: 259
|
||||
public readonly VmInstrInfo Stelem_i8_ = new VmInstrInfo(588832478, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000105 RID: 261
|
||||
public readonly VmInstrInfo Mul_ovf_un_ = new VmInstrInfo(-356198078, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000106 RID: 262
|
||||
public readonly VmInstrInfo Conv_u_ = new VmInstrInfo(1795519976, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000108 RID: 264
|
||||
public readonly VmInstrInfo Ldelem_i_ = new VmInstrInfo(1499071663, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000109 RID: 265
|
||||
public readonly VmInstrInfo Ldarg_ = new VmInstrInfo(-1071239412, VmOperandType.Ot1UShort);
|
||||
|
||||
// Token: 0x0400010A RID: 266
|
||||
public readonly VmInstrInfo Conv_r_un_ = new VmInstrInfo(-23925463, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400010B RID: 267
|
||||
public readonly VmInstrInfo Ldc_i4_8_ = new VmInstrInfo(1119515810, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400010C RID: 268
|
||||
public readonly VmInstrInfo Conv_i8_ = new VmInstrInfo(1980167243, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400010D RID: 269
|
||||
public readonly VmInstrInfo Ldloc_1_ = new VmInstrInfo(704985473, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400010E RID: 270
|
||||
public readonly VmInstrInfo Ldelem_u2_ = new VmInstrInfo(-1142530894, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400010F RID: 271
|
||||
public readonly VmInstrInfo Throw_ = new VmInstrInfo(-958454075, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000110 RID: 272
|
||||
public readonly VmInstrInfo Cpblk_ = new VmInstrInfo(-123910492, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000111 RID: 273
|
||||
public readonly VmInstrInfo Ldind_u1_ = new VmInstrInfo(1476085916, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000113 RID: 275
|
||||
public readonly VmInstrInfo Stloc_2_ = new VmInstrInfo(392938325, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000114 RID: 276
|
||||
public readonly VmInstrInfo Ldarg_3_ = new VmInstrInfo(-1756998893, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000115 RID: 277
|
||||
public readonly VmInstrInfo Stloc_ = new VmInstrInfo(1447397361, VmOperandType.Ot1UShort);
|
||||
|
||||
// Token: 0x04000117 RID: 279
|
||||
public readonly VmInstrInfo Ldc_i4_5_ = new VmInstrInfo(-656328799, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000118 RID: 280
|
||||
public readonly VmInstrInfo Conv_ovf_u1_ = new VmInstrInfo(344575979, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400011A RID: 282
|
||||
public readonly VmInstrInfo Ldind_i4_ = new VmInstrInfo(234126039, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400011B RID: 283
|
||||
public readonly VmInstrInfo Switch_ = new VmInstrInfo(8625656, VmOperandType.Ot9IntArr);
|
||||
|
||||
// Token: 0x0400011C RID: 284
|
||||
public readonly VmInstrInfo Arglist_ = new VmInstrInfo(1783361912, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x0400011F RID: 287
|
||||
public readonly VmInstrInfo Shr_un_ = new VmInstrInfo(897680915, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000120 RID: 288
|
||||
public readonly VmInstrInfo Ldloc_2_ = new VmInstrInfo(-17993965, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000121 RID: 289
|
||||
public readonly VmInstrInfo Conv_ovf_u4_ = new VmInstrInfo(1596489702, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000122 RID: 290
|
||||
public readonly VmInstrInfo Bge_ = new VmInstrInfo(-1225693454, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x04000123 RID: 291
|
||||
public readonly VmInstrInfo Ldloc_0_ = new VmInstrInfo(1021709264, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000124 RID: 292
|
||||
public readonly VmInstrInfo Bne_un_ = new VmInstrInfo(68951288, VmOperandType.Ot0UInt);
|
||||
|
||||
// Token: 0x04000126 RID: 294
|
||||
public readonly VmInstrInfo Stelem_i2_ = new VmInstrInfo(1223054294, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000127 RID: 295
|
||||
public readonly VmInstrInfo Sub_ovf_un_ = new VmInstrInfo(-851734976, VmOperandType.Ot11Nope);
|
||||
|
||||
// Token: 0x04000128 RID: 296
|
||||
public readonly VmInstrInfo Ret_ = new VmInstrInfo(1882847521, VmOperandType.Ot11Nope);
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum VmOperandType
|
||||
{
|
||||
Ot0UInt, Ot1UShort, Ot2Byte, Ot3UShort, Ot4Double, Ot5Int, Ot6SByte, Ot7Long, Ot8Byte, Ot9IntArr, Ot10Float, Ot11Nope, Ot12Int
|
||||
}
|
||||
// Token: 0x0200005F RID: 95
|
||||
public class VmInstrInfo // \u000F\u2005
|
||||
{
|
||||
// Token: 0x06000377 RID: 887 RVA: 0x00015B74 File Offset: 0x00013D74
|
||||
public VmInstrInfo(int id, VmOperandType operandType)
|
||||
{
|
||||
Id = id;
|
||||
OperandType = operandType;
|
||||
}
|
||||
|
||||
// Token: 0x06000378 RID: 888 RVA: 0x00015B8C File Offset: 0x00013D8C
|
||||
// Token: 0x06000379 RID: 889 RVA: 0x00015B94 File Offset: 0x00013D94
|
||||
// Token: 0x0400018F RID: 399
|
||||
public int Id { get; }
|
||||
|
||||
// Token: 0x0600037A RID: 890 RVA: 0x00015BA0 File Offset: 0x00013DA0
|
||||
// Token: 0x04000190 RID: 400
|
||||
public VmOperandType OperandType { get; }
|
||||
|
||||
// Token: 0x0600037B RID: 891 RVA: 0x00015BA8 File Offset: 0x00013DA8
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
var p = o as VmInstrInfo;
|
||||
return (p != null) && EqualTo(p);
|
||||
}
|
||||
|
||||
// Token: 0x0600037C RID: 892 RVA: 0x00015BD0 File Offset: 0x00013DD0
|
||||
private bool EqualTo(VmInstrInfo p)
|
||||
{
|
||||
return p.Id== Id;
|
||||
}
|
||||
|
||||
// Token: 0x0600037D RID: 893 RVA: 0x00015BE0 File Offset: 0x00013DE0
|
||||
public static bool operator ==(VmInstrInfo o1, VmInstrInfo o2)
|
||||
{
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
return o1.EqualTo(o2);
|
||||
}
|
||||
|
||||
// Token: 0x0600037E RID: 894 RVA: 0x00015BEC File Offset: 0x00013DEC
|
||||
public static bool operator !=(VmInstrInfo o1, VmInstrInfo o2)
|
||||
{
|
||||
return !(o1 == o2);
|
||||
}
|
||||
|
||||
// Token: 0x0600037F RID: 895 RVA: 0x00015BF8 File Offset: 0x00013DF8
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Id.GetHashCode();
|
||||
}
|
||||
|
||||
// Token: 0x06000380 RID: 896 RVA: 0x00015C14 File Offset: 0x00013E14
|
||||
public override string ToString()
|
||||
{
|
||||
return Id.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000028 RID: 40
|
||||
public sealed class VmMethodHeader // \u0006
|
||||
{
|
||||
// Token: 0x06000120 RID: 288 RVA: 0x00005F08 File Offset: 0x00004108
|
||||
// Token: 0x06000121 RID: 289 RVA: 0x00005F10 File Offset: 0x00004110
|
||||
// Token: 0x04000047 RID: 71
|
||||
public LocalVarType[] LocalVarTypes /* \u0003 */ { get; set; }
|
||||
|
||||
// Token: 0x06000122 RID: 290 RVA: 0x00005F1C File Offset: 0x0000411C
|
||||
// Token: 0x06000123 RID: 291 RVA: 0x00005F24 File Offset: 0x00004124
|
||||
// Token: 0x0400004B RID: 75
|
||||
public ArgTypeToOutput[] ArgsTypeToOutput /* \u000E */ { get; set; }
|
||||
|
||||
// Token: 0x06000124 RID: 292 RVA: 0x00005F30 File Offset: 0x00004130
|
||||
// Token: 0x06000125 RID: 293 RVA: 0x00005F38 File Offset: 0x00004138
|
||||
// Token: 0x04000048 RID: 72
|
||||
public string Name /* \u0002 */ { get; set; }
|
||||
|
||||
// Token: 0x06000126 RID: 294 RVA: 0x00005F44 File Offset: 0x00004144
|
||||
// Token: 0x06000127 RID: 295 RVA: 0x00005F4C File Offset: 0x0000414C
|
||||
// Token: 0x04000046 RID: 70
|
||||
public int ClassId /* \u0002 */ { get; set; }
|
||||
|
||||
// Token: 0x06000128 RID: 296 RVA: 0x00005F58 File Offset: 0x00004158
|
||||
// Token: 0x06000129 RID: 297 RVA: 0x00005F60 File Offset: 0x00004160
|
||||
// Token: 0x04000049 RID: 73
|
||||
public int ReturnTypeId /* \u0008 */ { get; set; }
|
||||
|
||||
// Token: 0x0600012A RID: 298 RVA: 0x00005F6C File Offset: 0x0000416C
|
||||
// Token: 0x0600012B RID: 299 RVA: 0x00005F74 File Offset: 0x00004174
|
||||
// Token: 0x0400004A RID: 74
|
||||
public byte Flags /* \u0006 */ { private get; set; }
|
||||
|
||||
// Token: 0x0600012C RID: 300 RVA: 0x00005F80 File Offset: 0x00004180
|
||||
public bool IsStatic() // \u0002
|
||||
{
|
||||
return (Flags & 2) > 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
internal static class VmPosParser // \u0006\u2006
|
||||
{
|
||||
// Token: 0x0600016A RID: 362 RVA: 0x00007810 File Offset: 0x00005A10
|
||||
public static byte[] Parse(string pos) // dest
|
||||
{
|
||||
if (pos == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
var memoryStream = new MemoryStream(pos.Length * 4 / 5);
|
||||
byte[] result;
|
||||
using(memoryStream)
|
||||
{
|
||||
var cnt = 0;
|
||||
var val = 0u;
|
||||
foreach (var c in pos)
|
||||
{
|
||||
if (c == 'z' && cnt == 0)
|
||||
{
|
||||
WriteDwPart(memoryStream, val, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c< '!' || c> 'u')
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
checked
|
||||
{
|
||||
val += (uint)(Arr[cnt] * (ulong)checked(c - '!'));
|
||||
}
|
||||
cnt++;
|
||||
if (cnt == 5)
|
||||
{
|
||||
WriteDwPart(memoryStream, val, 0);
|
||||
cnt = 0;
|
||||
val = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cnt == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
if (cnt > 1)
|
||||
{
|
||||
for (var j = cnt; j < 5; j++)
|
||||
{
|
||||
checked
|
||||
{
|
||||
val += 84u * Arr[j];
|
||||
}
|
||||
}
|
||||
WriteDwPart(memoryStream, val, 5 - cnt);
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Token: 0x0600016B RID: 363 RVA: 0x00007900 File Offset: 0x00005B00
|
||||
private static void WriteDwPart(Stream dest, uint val, int ignoreLow) // dest
|
||||
{
|
||||
dest.WriteByte((byte)(val >> 24));
|
||||
if (ignoreLow == 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
dest.WriteByte((byte)(val >> 16 & 255u));
|
||||
if (ignoreLow == 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
dest.WriteByte((byte)(val >> 8 & 255u));
|
||||
if (ignoreLow == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
dest.WriteByte((byte)(val & 255u));
|
||||
}
|
||||
|
||||
// Token: 0x04000131 RID: 305
|
||||
private static readonly uint[] Arr = {
|
||||
52200625u,
|
||||
614125u,
|
||||
7225u,
|
||||
85u,
|
||||
1u
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace UnitTestProject.RefVm
|
||||
{
|
||||
// Token: 0x02000021 RID: 33
|
||||
public sealed class VmStreamWrapper : Stream // \u0005\u2005
|
||||
{
|
||||
// Token: 0x060000CB RID: 203 RVA: 0x00004A20 File Offset: 0x00002C20
|
||||
public VmStreamWrapper(Stream src, int xorKey)
|
||||
{
|
||||
SetStream(src);
|
||||
_xorKey = xorKey;
|
||||
}
|
||||
|
||||
// Token: 0x060000CC RID: 204 RVA: 0x00004A38 File Offset: 0x00002C38
|
||||
public Stream GetStream() // \u0008\u2003\u2003\u2001\u2001\u2000\u2000\u2008\u2000\u2001\u2000\u2008\u200A\u2008\u200B\u2003\u200B
|
||||
{
|
||||
return _srcStream;
|
||||
}
|
||||
|
||||
// Token: 0x060000CD RID: 205 RVA: 0x00004A40 File Offset: 0x00002C40
|
||||
private void SetStream(Stream src) // \u0002
|
||||
{
|
||||
_srcStream = src;
|
||||
}
|
||||
|
||||
// Token: 0x17000001 RID: 1
|
||||
// (get) Token: 0x060000CE RID: 206 RVA: 0x00004A4C File Offset: 0x00002C4C
|
||||
public override bool CanRead => GetStream().CanRead;
|
||||
|
||||
// Token: 0x17000002 RID: 2
|
||||
// (get) Token: 0x060000CF RID: 207 RVA: 0x00004A5C File Offset: 0x00002C5C
|
||||
public override bool CanSeek => GetStream().CanSeek;
|
||||
|
||||
// Token: 0x17000003 RID: 3
|
||||
// (get) Token: 0x060000D0 RID: 208 RVA: 0x00004A6C File Offset: 0x00002C6C
|
||||
public override bool CanWrite => GetStream().CanWrite;
|
||||
|
||||
// Token: 0x060000D1 RID: 209 RVA: 0x00004A7C File Offset: 0x00002C7C
|
||||
public override void Flush()
|
||||
{
|
||||
GetStream().Flush();
|
||||
}
|
||||
|
||||
// Token: 0x17000004 RID: 4
|
||||
// (get) Token: 0x060000D2 RID: 210 RVA: 0x00004A8C File Offset: 0x00002C8C
|
||||
public override long Length => GetStream().Length;
|
||||
|
||||
// Token: 0x17000005 RID: 5
|
||||
// (get) Token: 0x060000D3 RID: 211 RVA: 0x00004A9C File Offset: 0x00002C9C
|
||||
// (set) Token: 0x060000D4 RID: 212 RVA: 0x00004AAC File Offset: 0x00002CAC
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetStream().Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
GetStream().Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Token: 0x060000D5 RID: 213 RVA: 0x00004ABC File Offset: 0x00002CBC
|
||||
private byte Xor(byte data, long key2) // \u0002
|
||||
{
|
||||
var b = (byte)(_xorKey ^ -559030707 ^ (int)((uint)key2));
|
||||
return (byte)(data ^ b);
|
||||
}
|
||||
|
||||
// Token: 0x060000D6 RID: 214 RVA: 0x00004AE0 File Offset: 0x00002CE0
|
||||
public override void Write(byte[] data, int offset, int size)
|
||||
{
|
||||
var array = new byte[size];
|
||||
Buffer.BlockCopy(data, offset, array, 0, size);
|
||||
var position = Position;
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
array[i] = Xor(array[i], position + i);
|
||||
}
|
||||
GetStream().Write(array, 0, size);
|
||||
}
|
||||
|
||||
// Token: 0x060000D7 RID: 215 RVA: 0x00004B30 File Offset: 0x00002D30
|
||||
public override int Read(byte[] data, int offset, int size)
|
||||
{
|
||||
var position = Position;
|
||||
var array = new byte[size];
|
||||
var num = GetStream().Read(array, 0, size);
|
||||
for (var i = 0; i < num; i++)
|
||||
{
|
||||
data[i + offset] = Xor(array[i], position + i);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
// Token: 0x060000D8 RID: 216 RVA: 0x00004B7C File Offset: 0x00002D7C
|
||||
public override long Seek(long pos, SeekOrigin from)
|
||||
{
|
||||
return GetStream().Seek(pos, from);
|
||||
}
|
||||
|
||||
// Token: 0x060000D9 RID: 217 RVA: 0x00004B8C File Offset: 0x00002D8C
|
||||
public override void SetLength(long val)
|
||||
{
|
||||
GetStream().SetLength(val);
|
||||
}
|
||||
|
||||
// Token: 0x0400002A RID: 42
|
||||
private readonly int _xorKey; // \u0002
|
||||
|
||||
// Token: 0x0400002B RID: 43
|
||||
private Stream _srcStream; // \u0003
|
||||
}
|
||||
}
|
110
runtime/VMProtect.Runtime/Tests/UnitTestProject/UnitTest1.cs
Normal file
110
runtime/VMProtect.Runtime/Tests/UnitTestProject/UnitTest1.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using VMProtect;
|
||||
|
||||
namespace UnitTestProject
|
||||
{
|
||||
[TestClass]
|
||||
public class UnitTest1
|
||||
{
|
||||
[TestMethod]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public void TestRC5()
|
||||
{
|
||||
var key = CipherRC5.CreateRandomKey();
|
||||
var rc5 = new CipherRC5(key);
|
||||
|
||||
var dataStr = "Тестовые данные для TestRC5";
|
||||
var dataBytes = Encoding.UTF8.GetBytes(dataStr);
|
||||
Array.Resize(ref dataBytes, (dataBytes.Length + 7)/8*8);
|
||||
|
||||
var encodedBytes = rc5.Encrypt(dataBytes);
|
||||
var dataBytes2 = rc5.Decrypt(encodedBytes);
|
||||
|
||||
CollectionAssert.AreNotEqual(dataBytes, encodedBytes);
|
||||
CollectionAssert.AreEqual(dataBytes, dataBytes2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestHwid()
|
||||
{
|
||||
var hwid = new HardwareID();
|
||||
Assert.AreNotSame(0, hwid.ToString().Length);
|
||||
var machine = Dns.GetHostName().ToUpperInvariant();
|
||||
var txtHwid = hwid.ToString();
|
||||
if (machine == "ACER-V3")
|
||||
Assert.AreEqual("2D3kAD28P7M7soVoCjyOUA==", txtHwid);
|
||||
else if (machine == "WORK")
|
||||
Assert.AreEqual("AIUkDL3k4HTLFrVrPmOIpw==", txtHwid);
|
||||
else if (machine == "BUILD7N1")
|
||||
Assert.AreEqual("HBG8w5UkOMh714KeZow8vg==", txtHwid);
|
||||
else
|
||||
Assert.Fail("Append branch for machine '{0}' with result '{1}'", machine, txtHwid);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestHwidCompare()
|
||||
{
|
||||
var hwid = new HardwareID();
|
||||
var cur = hwid.GetBytes();
|
||||
var test = new byte[cur.Length];
|
||||
|
||||
Array.Copy(cur, test, cur.Length);
|
||||
// change one id
|
||||
for (var i = 0; i < cur.Length; i += 4)
|
||||
{
|
||||
test[i] = cur[i];
|
||||
switch (test[i] & 3) {
|
||||
case 3:
|
||||
test[i] ^= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.IsTrue(hwid.IsCorrect(test));
|
||||
|
||||
|
||||
// change two ids
|
||||
Array.Copy(cur, test, cur.Length);
|
||||
for (var i = 0; i < cur.Length; i += 4)
|
||||
{
|
||||
switch (test[i] & 3)
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
test[i] ^= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.IsFalse(hwid.IsCorrect(test));
|
||||
|
||||
// change three ids
|
||||
Array.Copy(cur, test, cur.Length);
|
||||
for (var i = 0; i < cur.Length; i += 4)
|
||||
{
|
||||
switch (test[i] & 3)
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
test[i] ^= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.IsFalse(hwid.IsCorrect(test));
|
||||
|
||||
// change cpu`s id
|
||||
Array.Copy(cur, test, cur.Length);
|
||||
for (var i = 0; i < cur.Length; i += 4)
|
||||
{
|
||||
switch (test[i] & 3)
|
||||
{
|
||||
case 0:
|
||||
test[i] ^= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.IsFalse(hwid.IsCorrect(test));
|
||||
}
|
||||
}
|
||||
}
|
1715
runtime/VMProtect.Runtime/Tests/UnitTestProject/UnitTestCombine.cs
Normal file
1715
runtime/VMProtect.Runtime/Tests/UnitTestProject/UnitTestCombine.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{85318BED-28D8-4B31-A7BA-9ED7882D11FC}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UnitTestProject</RootNamespace>
|
||||
<AssemblyName>UnitTestProject</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\Crypto.cs">
|
||||
<Link>CipherRC5.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Core.cs">
|
||||
<Link>Core.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\CpuId.cs">
|
||||
<Link>CpuId.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Faces.cs">
|
||||
<Link>Faces.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\HardwareID.cs">
|
||||
<Link>HardwareID.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\LicensingManager.cs">
|
||||
<Link>LicensingManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Loader.cs">
|
||||
<Link>Loader.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\LzmaDecoder.cs">
|
||||
<Link>LzmaDecoder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Numerics\BigInteger.cs">
|
||||
<Link>Numerics\BigInteger.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Numerics\BigIntegerBuilder.cs">
|
||||
<Link>Numerics\BigIntegerBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Numerics\NumericHelpers.cs">
|
||||
<Link>Numerics\NumericHelpers.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\StringManager.cs">
|
||||
<Link>StringManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\VirtualMachine.cs">
|
||||
<Link>VirtualMachine.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Win32.cs">
|
||||
<Link>Win32.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="LicensingManagerTests.cs" />
|
||||
<Compile Include="LoaderTests.cs" />
|
||||
<Compile Include="MsilToVmTestCompiler.cs" />
|
||||
<Compile Include="RefVm\ElementedTypeHelper.cs" />
|
||||
<Compile Include="RefVm\MyBuffer.cs" />
|
||||
<Compile Include="RefVm\MyBufferReader.cs" />
|
||||
<Compile Include="RefVm\MyCollection.cs" />
|
||||
<Compile Include="RefVm\SdMetadataTokens.cs" />
|
||||
<Compile Include="RefVm\SdTemplateStuff.cs" />
|
||||
<Compile Include="RefVm\SimpleTypeHelper.cs" />
|
||||
<Compile Include="RefVm\StringDecryptor.cs" />
|
||||
<Compile Include="RefVm\TypeCompatibility.cs" />
|
||||
<Compile Include="RefVm\VariantBase.cs" />
|
||||
<Compile Include="RefVm\VariantFactory.cs" />
|
||||
<Compile Include="RefVm\VmExecutor.cs" />
|
||||
<Compile Include="RefVm\VmInstrCodesDb.cs" />
|
||||
<Compile Include="RefVm\VmMethodHeader.cs" />
|
||||
<Compile Include="RefVm\VmPosParser.cs" />
|
||||
<Compile Include="RefVm\VmStreamWrapper.cs" />
|
||||
<Compile Include="UnitTest1.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UnitTestCombine.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Service References\" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{85318BED-28D8-4B31-A7BA-9ED7882D11FC}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UnitTestProject</RootNamespace>
|
||||
<AssemblyName>UnitTestProject</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\CipherRC5.cs">
|
||||
<Link>CipherRC5.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Core.cs">
|
||||
<Link>Core.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\CpuId.cs">
|
||||
<Link>CpuId.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\CRC32.cs">
|
||||
<Link>CRC32.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Faces.cs">
|
||||
<Link>Faces.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\HardwareID.cs">
|
||||
<Link>HardwareID.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\LicensingManager.cs">
|
||||
<Link>LicensingManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Numerics\BigInteger.cs">
|
||||
<Link>Numerics\BigInteger.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Numerics\BigIntegerBuilder.cs">
|
||||
<Link>Numerics\BigIntegerBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Numerics\NumericHelpers.cs">
|
||||
<Link>Numerics\NumericHelpers.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\StringManager.cs">
|
||||
<Link>StringManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Win32.cs">
|
||||
<Link>Win32.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="LicensingManagerTests.cs" />
|
||||
<Compile Include="UnitTest1.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Service References\" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
65
runtime/VMProtect.Runtime/VMProtect.Netcore.csproj
Normal file
65
runtime/VMProtect.Runtime/VMProtect.Netcore.csproj
Normal file
@ -0,0 +1,65 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFrameworks>netstandard2.1;netcoreapp3.0;net20;net40</TargetFrameworks>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net20' Or '$(TargetFramework)' == 'net40'">
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<Optimize>true</Optimize>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>$(DefineConstants);TRACE;RUNTIME</DefineConstants>
|
||||
<OutputPath>..\..\bin\32\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Optimize>true</Optimize>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>$(DefineConstants);TRACE;RUNTIME</DefineConstants>
|
||||
<OutputPath>..\..\bin\64\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<Optimize>true</Optimize>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>$(DefineConstants);TRACE;DEBUG;RUNTIME</DefineConstants>
|
||||
<OutputPath>..\..\bin\32\Debug\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Optimize>true</Optimize>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants>$(DefineConstants);TRACE;DEBUG;RUNTIME</DefineConstants>
|
||||
<OutputPath>..\..\bin\64\Debug\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Tests\**" />
|
||||
<Compile Remove="VMProtect.Netcore\**" />
|
||||
<Compile Remove="VMProtect.Runtime.Netstandard\**" />
|
||||
<EmbeddedResource Remove="Tests\**" />
|
||||
<EmbeddedResource Remove="VMProtect.Netcore\**" />
|
||||
<EmbeddedResource Remove="VMProtect.Runtime.Netstandard\**" />
|
||||
<None Remove="Tests\**" />
|
||||
<None Remove="VMProtect.Netcore\**" />
|
||||
<None Remove="VMProtect.Runtime.Netstandard\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
93
runtime/VMProtect.Runtime/VMProtect.Runtime.csproj
Normal file
93
runtime/VMProtect.Runtime/VMProtect.Runtime.csproj
Normal file
@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{946D07D4-1AE4-4FC3-9A8C-563B5F64B0B6}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>VMProtect.Runtime</RootNamespace>
|
||||
<AssemblyName>VMProtect.Runtime</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\bin\32\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;RUNTIME;NETFRAMEWORK</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\bin\32\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;RUNTIME;NETFRAMEWORK</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\bin\64\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;RUNTIME;NETFRAMEWORK</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>..\..\bin\64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;RUNTIME;NETFRAMEWORK</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="LzmaDecoder.cs" />
|
||||
<Compile Include="Numerics\BigInteger.cs" />
|
||||
<Compile Include="Numerics\BigIntegerBuilder.cs" />
|
||||
<Compile Include="Crypto.cs" />
|
||||
<Compile Include="Core.cs" />
|
||||
<Compile Include="CpuId.cs" />
|
||||
<Compile Include="Faces.cs" />
|
||||
<Compile Include="HardwareID.cs" />
|
||||
<Compile Include="LicensingManager.cs" />
|
||||
<Compile Include="Loader.cs" />
|
||||
<Compile Include="Numerics\NumericHelpers.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StringManager.cs" />
|
||||
<Compile Include="VirtualMachine.cs" />
|
||||
<Compile Include="Win32.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
4285
runtime/VMProtect.Runtime/VirtualMachine.cs
Normal file
4285
runtime/VMProtect.Runtime/VirtualMachine.cs
Normal file
File diff suppressed because it is too large
Load Diff
825
runtime/VMProtect.Runtime/Win32.cs
Normal file
825
runtime/VMProtect.Runtime/Win32.cs
Normal file
@ -0,0 +1,825 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace VMProtect
|
||||
{
|
||||
public enum MessageBoxButtons : uint
|
||||
{
|
||||
OK,
|
||||
OKCancel,
|
||||
AbortRetryIgnore,
|
||||
YesNoCancel,
|
||||
YesNo,
|
||||
RetryCancel,
|
||||
CancelTryAgainContinue
|
||||
}
|
||||
|
||||
public enum MessageBoxIcon : uint
|
||||
{
|
||||
Asterisk = 0x40,
|
||||
Error = 0x10,
|
||||
Exclamation = 0x30,
|
||||
Hand = 0x10,
|
||||
Information = 0x40,
|
||||
None = 0,
|
||||
Question = 0x20,
|
||||
Stop = 0x10,
|
||||
Warning = 0x30,
|
||||
UserIcon = 0x80
|
||||
}
|
||||
|
||||
|
||||
internal static class Win32
|
||||
{
|
||||
[Flags()]
|
||||
public enum AllocationType : uint
|
||||
{
|
||||
Commit = 0x1000,
|
||||
Reserve = 0x2000,
|
||||
}
|
||||
|
||||
[Flags()]
|
||||
public enum FreeType : uint
|
||||
{
|
||||
Release = 0x8000,
|
||||
}
|
||||
|
||||
[Flags()]
|
||||
public enum MemoryProtection : uint
|
||||
{
|
||||
NoAccess = 0x01,
|
||||
ReadOnly = 0x02,
|
||||
ReadWrite = 0x04,
|
||||
WriteCopy = 0x08,
|
||||
Execute = 0x10,
|
||||
ExecuteRead = 0x20,
|
||||
ExecuteReadWrite = 0x40,
|
||||
Guard = 0x100
|
||||
}
|
||||
|
||||
[Flags()]
|
||||
public enum MapAccess : uint
|
||||
{
|
||||
Copy = 0x0001,
|
||||
Write = 0x0002,
|
||||
Read = 0x0004,
|
||||
AllAccess = 0x001f
|
||||
}
|
||||
|
||||
[Flags()]
|
||||
public enum SectionType : uint
|
||||
{
|
||||
Execute = 0x20000000,
|
||||
Read = 0x40000000,
|
||||
Write = 0x80000000
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct UNICODE_STRING
|
||||
{
|
||||
public readonly ushort Length;
|
||||
public readonly ushort MaximumLength;
|
||||
private readonly IntPtr Buffer;
|
||||
|
||||
public UNICODE_STRING(string str)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
Length = 0;
|
||||
MaximumLength = 0;
|
||||
Buffer = IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = (ushort)(str.Length * UnicodeEncoding.CharSize);
|
||||
MaximumLength = (ushort)(Length + UnicodeEncoding.CharSize);
|
||||
Buffer = Marshal.StringToHGlobalUni(str);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Buffer != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct OBJECT_ATTRIBUTES
|
||||
{
|
||||
public readonly uint Length;
|
||||
public readonly IntPtr RootDirectory;
|
||||
public readonly IntPtr ObjectName;
|
||||
public readonly uint Attributes;
|
||||
public readonly IntPtr SecurityDescriptor;
|
||||
public readonly IntPtr SecurityQualityOfService;
|
||||
|
||||
public OBJECT_ATTRIBUTES(UNICODE_STRING name, uint attrs)
|
||||
{
|
||||
Length = (uint)Marshal.SizeOf(typeof(OBJECT_ATTRIBUTES));
|
||||
RootDirectory = IntPtr.Zero;
|
||||
ObjectName = IntPtr.Zero;
|
||||
Attributes = attrs;
|
||||
SecurityDescriptor = IntPtr.Zero;
|
||||
SecurityQualityOfService = IntPtr.Zero;
|
||||
|
||||
ObjectName = Marshal.AllocHGlobal(Marshal.SizeOf(name));
|
||||
Marshal.StructureToPtr(name, ObjectName, false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Marshal.FreeHGlobal(ObjectName);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IO_STATUS_BLOCK
|
||||
{
|
||||
public uint Status;
|
||||
public IntPtr Information;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct LARGE_INTEGER
|
||||
{
|
||||
public uint LowPart;
|
||||
public uint HighPart;
|
||||
}
|
||||
|
||||
public enum HardErrorResponse
|
||||
{
|
||||
ReturnToCaller,
|
||||
NotHandled,
|
||||
Abort, Cancel,
|
||||
Ignore,
|
||||
No,
|
||||
Ok,
|
||||
Retry,
|
||||
Yes
|
||||
}
|
||||
|
||||
public enum Values : uint
|
||||
{
|
||||
GENERIC_READ = 0x80000000,
|
||||
FILE_SHARE_READ = 0x00000001,
|
||||
FILE_SHARE_WRITE = 0x00000002,
|
||||
FILE_READ_ATTRIBUTES = 0x00000080,
|
||||
SYNCHRONIZE = 0x00100000,
|
||||
SECTION_QUERY = 0x0001,
|
||||
SECTION_MAP_WRITE = 0x0002,
|
||||
SECTION_MAP_READ = 0x0004,
|
||||
SECTION_MAP_EXECUTE = 0x0008,
|
||||
SEC_COMMIT = 0x8000000,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020,
|
||||
FILE_NON_DIRECTORY_FILE = 0x00000040,
|
||||
}
|
||||
|
||||
public static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
|
||||
public static readonly IntPtr NullHandle = IntPtr.Zero;
|
||||
public static readonly IntPtr CurrentProcess = new IntPtr(-1);
|
||||
public static readonly IntPtr CurrentThread = new IntPtr(-2);
|
||||
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtQueryInformationProcess(IntPtr ProcessHandle, PROCESSINFOCLASS ProcessInformationClass,
|
||||
IntPtr ProcessInformation, int ProcessInformationLength, out uint ReturnLength);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtSetInformationThread(IntPtr ThreadHandle, THREADINFOCLASS ThreadInformationClass, IntPtr ThreadInformation,
|
||||
uint ThreadInformationLength);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tEnumSystemFirmwareTables(uint firmwareTableProviderSignature, IntPtr firmwareTableBuffer, uint bufferSize);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tGetSystemFirmwareTable(uint firmwareTableProviderSignature, uint firmwareTableID, IntPtr firmwareTableBuffer, uint bufferSize);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtClose(IntPtr Handle);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtProtectVirtualMemory(IntPtr ProcesssHandle, ref IntPtr BaseAddress, ref UIntPtr RegionSize, MemoryProtection Protect, out MemoryProtection OldProtect);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtAllocateVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref UIntPtr RegionSize, AllocationType AllocationType, MemoryProtection Protect);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtFreeVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref UIntPtr RegionSize, FreeType FreeType);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtUnmapViewOfSection(IntPtr ProcessHandle, IntPtr BaseAddress);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate IntPtr tMapViewOfFile(IntPtr hFileMappingObject, MapAccess dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, IntPtr dwNumBytesToMap);
|
||||
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtRaiseHardError(uint ErrorStatus, uint NumberOfParameters, uint UnicodeStringParameterMask, IntPtr[] Parameters, uint ValidResponseOptions, out HardErrorResponse Response);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtOpenFile(out IntPtr FileHandle, uint DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, out IO_STATUS_BLOCK IoStatusBlock, uint ShareAccess, uint OpenOptions);
|
||||
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
|
||||
private delegate uint tNtCreateSection(out IntPtr SectionHandle, uint DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, ref LARGE_INTEGER MaximumSize, MemoryProtection SectionPageProtection, uint AllocationAttributes, IntPtr FileHandle);
|
||||
|
||||
|
||||
private static IntPtr _ntdll;
|
||||
private static tNtQueryInformationProcess _nt_query_information_process;
|
||||
private static tNtSetInformationThread _nt_set_information_thread;
|
||||
private static tNtClose _nt_close;
|
||||
private static tNtProtectVirtualMemory _nt_protect_virtual_memory;
|
||||
private static tNtAllocateVirtualMemory _nt_allocate_virtual_memory;
|
||||
private static tNtFreeVirtualMemory _nt_free_virtual_memory;
|
||||
private static tNtUnmapViewOfSection _nt_unmap_view_of_section;
|
||||
private static tNtRaiseHardError _nt_raise_hard_error;
|
||||
private static tNtOpenFile _nt_open_file;
|
||||
private static tNtCreateSection _nt_create_section;
|
||||
private static IntPtr _kernel32;
|
||||
private static tEnumSystemFirmwareTables _enum_system_firmware_tables;
|
||||
private static tGetSystemFirmwareTable _get_system_firmware_table;
|
||||
private static tMapViewOfFile _map_view_of_file;
|
||||
|
||||
|
||||
static Win32()
|
||||
{
|
||||
_ntdll = GetModuleHandleEnc((uint)Faces.NTDLL_NAME);
|
||||
_nt_query_information_process = (tNtQueryInformationProcess)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_QUERY_INFORMATION_PROCESS_NAME), typeof(tNtQueryInformationProcess));
|
||||
_nt_set_information_thread = (tNtSetInformationThread)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_SET_INFORMATION_THREAD_NAME), typeof(tNtSetInformationThread));
|
||||
_nt_close = (tNtClose)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_CLOSE), typeof(tNtClose));
|
||||
_nt_protect_virtual_memory = (tNtProtectVirtualMemory)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_VIRTUAL_PROTECT_NAME), typeof(tNtProtectVirtualMemory));
|
||||
_nt_allocate_virtual_memory = (tNtAllocateVirtualMemory)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_ALLOCATE_VIRTUAL_MEMORY_NAME), typeof(tNtAllocateVirtualMemory));
|
||||
_nt_free_virtual_memory = (tNtFreeVirtualMemory)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_FREE_VIRTUAL_MEMORY_NAME), typeof(tNtFreeVirtualMemory));
|
||||
_nt_unmap_view_of_section = (tNtUnmapViewOfSection)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_UNMAP_VIEW_OF_SECTION), typeof(tNtUnmapViewOfSection));
|
||||
_nt_raise_hard_error = (tNtRaiseHardError)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_RAISE_HARD_ERROR_NAME), typeof(tNtRaiseHardError));
|
||||
_nt_open_file = (tNtOpenFile)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_OPEN_FILE_NAME), typeof(tNtOpenFile));
|
||||
_nt_create_section = (tNtCreateSection)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_ntdll, (uint)Faces.NT_CREATE_SECTION_NAME), typeof(tNtCreateSection));
|
||||
|
||||
_kernel32 = GetModuleHandleEnc((uint)Faces.KERNEL32_NAME);
|
||||
IntPtr proc = GetProcAddressEnc(_kernel32, (uint)Faces.ENUM_SYSTEM_FIRMWARE_NAME);
|
||||
if (proc != IntPtr.Zero)
|
||||
_enum_system_firmware_tables = (tEnumSystemFirmwareTables)Marshal.GetDelegateForFunctionPointer(proc, typeof(tEnumSystemFirmwareTables));
|
||||
proc = GetProcAddressEnc(_kernel32, (uint)Faces.GET_SYSTEM_FIRMWARE_NAME);
|
||||
if (proc != IntPtr.Zero)
|
||||
_get_system_firmware_table = (tGetSystemFirmwareTable)Marshal.GetDelegateForFunctionPointer(proc, typeof(tGetSystemFirmwareTable));
|
||||
_map_view_of_file = (tMapViewOfFile)Marshal.GetDelegateForFunctionPointer(GetProcAddressEnc(_kernel32, (uint)Faces.NT_MAP_VIEW_OF_SECTION), typeof(tMapViewOfFile));
|
||||
}
|
||||
|
||||
internal static IntPtr GetModuleHandleEnc(uint position)
|
||||
{
|
||||
long instance = Marshal.GetHINSTANCE(typeof(Loader).Module).ToInt64();
|
||||
var buffer = new byte[100];
|
||||
for (var pos = 0; pos < buffer.Length; pos++)
|
||||
{
|
||||
var c = (byte)(Marshal.ReadByte(new IntPtr(instance + position + pos)) ^ (BitRotate.Left((uint)Faces.STRING_DECRYPT_KEY, pos) + pos));
|
||||
if (c == 0)
|
||||
{
|
||||
if (pos > 0)
|
||||
return Win32.GetModuleHandle(Encoding.ASCII.GetString(buffer, 0, pos));
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[pos] = c;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
[DllImport("kernel32", SetLastError = true)]
|
||||
public static extern uint GetFileSize(IntPtr handle, IntPtr lpFileSizeHigh);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true)]
|
||||
public static extern bool GetVolumeInformation(
|
||||
string pathName,
|
||||
StringBuilder volumeNameBuffer,
|
||||
uint volumeNameSize,
|
||||
ref uint volumeSerialNumber,
|
||||
ref uint maximumComponentLength,
|
||||
ref uint fileSystemFlags,
|
||||
StringBuilder fileSystemNameBuffer,
|
||||
uint fileSystemNameSize);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr GetModuleHandle(String lpModuleName);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
public IntPtr Reserved1;
|
||||
public IntPtr PebBaseAddress;
|
||||
public IntPtr Reserved2_0;
|
||||
public IntPtr Reserved2_1;
|
||||
public IntPtr UniqueProcessId;
|
||||
public IntPtr InheritedFromUniqueProcessId;
|
||||
}
|
||||
|
||||
public enum PROCESSINFOCLASS
|
||||
{
|
||||
ProcessBasicInformation = 0x00,
|
||||
ProcessDebugPort = 0x07,
|
||||
ProcessDebugObjectHandle = 0x1e
|
||||
}
|
||||
|
||||
public enum THREADINFOCLASS
|
||||
{
|
||||
ThreadHideFromDebugger = 0x11
|
||||
}
|
||||
|
||||
internal static IntPtr GetProcAddress(IntPtr module, object proc_name)
|
||||
{
|
||||
if (module == IntPtr.Zero || proc_name == null)
|
||||
return IntPtr.Zero;
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = (byte*)module.ToPointer();
|
||||
|
||||
PE.IMAGE_DOS_HEADER* dos_header = (PE.IMAGE_DOS_HEADER*)ptr;
|
||||
if (dos_header->e_magic != PE.IMAGE_DOS_SIGNATURE)
|
||||
return IntPtr.Zero;
|
||||
|
||||
PE.IMAGE_NT_HEADERS* pe_header = (PE.IMAGE_NT_HEADERS*)(ptr + dos_header->e_lfanew);
|
||||
if (pe_header->Signature != PE.IMAGE_NT_SIGNATURE)
|
||||
return IntPtr.Zero;
|
||||
|
||||
if (pe_header->FileHeader.SizeOfOptionalHeader == 0)
|
||||
return IntPtr.Zero;
|
||||
|
||||
PE.IMAGE_DATA_DIRECTORY* export_table;
|
||||
byte* optional_header = (byte*)pe_header + Marshal.SizeOf(typeof(PE.IMAGE_NT_HEADERS));
|
||||
switch (*(UInt16*)(optional_header))
|
||||
{
|
||||
case PE.IMAGE_NT_OPTIONAL_HDR32_MAGIC:
|
||||
export_table = &((PE.IMAGE_OPTIONAL_HEADER32*)(optional_header))->ExportTable;
|
||||
break;
|
||||
case PE.IMAGE_NT_OPTIONAL_HDR64_MAGIC:
|
||||
export_table = &((PE.IMAGE_OPTIONAL_HEADER64*)(optional_header))->ExportTable;
|
||||
break;
|
||||
default:
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (export_table->VirtualAddress == 0)
|
||||
return IntPtr.Zero;
|
||||
|
||||
uint address = 0;
|
||||
PE.IMAGE_EXPORT_DIRECTORY* export_directory = (PE.IMAGE_EXPORT_DIRECTORY*)(ptr + export_table->VirtualAddress);
|
||||
if (proc_name is string)
|
||||
{
|
||||
string name = (string)proc_name;
|
||||
if (export_directory->NumberOfNames > 0)
|
||||
{
|
||||
int left_index = 0;
|
||||
int right_index = (int)export_directory->NumberOfNames - 1;
|
||||
uint* names = (UInt32*)(ptr + export_directory->AddressOfNames);
|
||||
while (left_index <= right_index)
|
||||
{
|
||||
int cur_index = (left_index + right_index) >> 1;
|
||||
int cmp = String.CompareOrdinal(name, Marshal.PtrToStringAnsi(new IntPtr(module.ToInt64() + names[cur_index])));
|
||||
if (cmp < 0)
|
||||
right_index = cur_index - 1;
|
||||
else if (cmp > 0)
|
||||
left_index = cur_index + 1;
|
||||
else
|
||||
{
|
||||
uint ordinal_index = ((UInt16*)(ptr + export_directory->AddressOfNameOrdinals))[cur_index];
|
||||
if (ordinal_index < export_directory->NumberOfFunctions)
|
||||
address = ((UInt32*)(ptr + export_directory->AddressOfFunctions))[ordinal_index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint ordinal_index = System.Convert.ToUInt32(proc_name) - export_directory->Base;
|
||||
if (ordinal_index < export_directory->NumberOfFunctions)
|
||||
address = ((UInt32*)(ptr + export_directory->AddressOfFunctions))[ordinal_index];
|
||||
}
|
||||
|
||||
if (address == 0)
|
||||
return IntPtr.Zero;
|
||||
|
||||
if (address < export_table->VirtualAddress || address >= export_table->VirtualAddress + export_table->Size)
|
||||
return new IntPtr(module.ToInt64() + address);
|
||||
|
||||
string forwarded_name = Marshal.PtrToStringAnsi(new IntPtr(module.ToInt64() + address));
|
||||
int dot_pos = forwarded_name.IndexOf('.');
|
||||
if (dot_pos > 0)
|
||||
{
|
||||
IntPtr forwarded_module = Win32.GetModuleHandle(forwarded_name.Substring(0, dot_pos));
|
||||
if (forwarded_name[dot_pos + 1] == '#')
|
||||
{
|
||||
uint ordinal;
|
||||
if (UInt32.TryParse(forwarded_name.Substring(dot_pos + 2), out ordinal))
|
||||
return GetProcAddress(forwarded_module, ordinal);
|
||||
}
|
||||
else
|
||||
return GetProcAddress(forwarded_module, forwarded_name.Substring(dot_pos + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
internal static IntPtr GetProcAddressEnc(IntPtr module, uint position)
|
||||
{
|
||||
long instance = Marshal.GetHINSTANCE(typeof(Loader).Module).ToInt64();
|
||||
var buffer = new byte[100];
|
||||
for (var pos = 0; pos < buffer.Length; pos++)
|
||||
{
|
||||
var c = (byte)(Marshal.ReadByte(new IntPtr(instance + position + pos)) ^ (BitRotate.Left((uint)Faces.STRING_DECRYPT_KEY, pos) + pos));
|
||||
if (c == 0)
|
||||
{
|
||||
if (pos > 0)
|
||||
return GetProcAddress(module, Encoding.ASCII.GetString(buffer, 0, pos));
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[pos] = c;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static uint NtQueryInformationProcess(IntPtr processHandle, Win32.PROCESSINFOCLASS processInformationClass,
|
||||
out object processInformation, int processInformationLength, out uint returnLength)
|
||||
{
|
||||
IntPtr mem = Marshal.AllocHGlobal(processInformationLength);
|
||||
uint res = _nt_query_information_process(processHandle, processInformationClass, mem, processInformationLength, out returnLength);
|
||||
if (res == 0)
|
||||
{
|
||||
Type type;
|
||||
switch (processInformationClass)
|
||||
{
|
||||
case Win32.PROCESSINFOCLASS.ProcessBasicInformation:
|
||||
type = typeof(Win32.PROCESS_BASIC_INFORMATION);
|
||||
break;
|
||||
case Win32.PROCESSINFOCLASS.ProcessDebugPort:
|
||||
case Win32.PROCESSINFOCLASS.ProcessDebugObjectHandle:
|
||||
type = typeof(IntPtr);
|
||||
break;
|
||||
default:
|
||||
type = null;
|
||||
break;
|
||||
}
|
||||
processInformation = Marshal.PtrToStructure(mem, type);
|
||||
}
|
||||
else
|
||||
processInformation = null;
|
||||
|
||||
Marshal.FreeHGlobal(mem);
|
||||
return res;
|
||||
}
|
||||
|
||||
public static uint NtSetInformationThread(IntPtr ThreadHandle, Win32.THREADINFOCLASS ThreadInformationClass, IntPtr ThreadInformation, uint ThreadInformationLength)
|
||||
{
|
||||
return _nt_set_information_thread(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength);
|
||||
}
|
||||
|
||||
public static uint EnumSystemFirmwareTables(uint firmwareTableProviderSignature, IntPtr firmwareTableBuffer, uint bufferSize)
|
||||
{
|
||||
return _enum_system_firmware_tables(firmwareTableProviderSignature, firmwareTableBuffer, bufferSize);
|
||||
}
|
||||
|
||||
public static uint GetSystemFirmwareTable(uint firmwareTableProviderSignature, uint firmwareTableID, IntPtr firmwareTableBuffer, uint bufferSize)
|
||||
{
|
||||
return _get_system_firmware_table(firmwareTableProviderSignature, firmwareTableID, firmwareTableBuffer, bufferSize);
|
||||
}
|
||||
|
||||
public static bool CloseHandle(IntPtr handle)
|
||||
{
|
||||
return (_nt_close(handle) == 0);
|
||||
}
|
||||
|
||||
public static IntPtr OpenFile(String FileName, uint DesiredAccess, uint ShareMode)
|
||||
{
|
||||
char[] preffix;
|
||||
if (FileName[0] == '\\' && FileName[1] == '\\')
|
||||
{
|
||||
preffix = new char[7];
|
||||
|
||||
preffix[0] = '\\';
|
||||
preffix[1] = '?';
|
||||
preffix[2] = '?';
|
||||
preffix[3] = '\\';
|
||||
preffix[4] = 'U';
|
||||
preffix[5] = 'N';
|
||||
preffix[6] = 'C';
|
||||
}
|
||||
else
|
||||
{
|
||||
preffix = new char[4];
|
||||
|
||||
preffix[0] = '\\';
|
||||
preffix[1] = '?';
|
||||
preffix[2] = '?';
|
||||
preffix[3] = '\\';
|
||||
}
|
||||
|
||||
var str = new UNICODE_STRING(new string(preffix) + FileName);
|
||||
var objectAttributes = new OBJECT_ATTRIBUTES(str, 0);
|
||||
try
|
||||
{
|
||||
IntPtr res;
|
||||
IO_STATUS_BLOCK io_status_block;
|
||||
if (_nt_open_file(out res, DesiredAccess | (uint)Values.SYNCHRONIZE | (uint)Values.FILE_READ_ATTRIBUTES, ref objectAttributes, out io_status_block, ShareMode, (uint)Values.FILE_SYNCHRONOUS_IO_NONALERT | (uint)Values.FILE_NON_DIRECTORY_FILE) == 0)
|
||||
return res;
|
||||
}
|
||||
finally
|
||||
{
|
||||
str.Dispose();
|
||||
objectAttributes.Dispose();
|
||||
}
|
||||
|
||||
return InvalidHandleValue;
|
||||
}
|
||||
|
||||
public static bool VirtualProtect(IntPtr BaseAddress, UIntPtr RegionSize, MemoryProtection Protect, out MemoryProtection OldProtect)
|
||||
{
|
||||
return (_nt_protect_virtual_memory(CurrentProcess, ref BaseAddress, ref RegionSize, Protect, out OldProtect) == 0);
|
||||
}
|
||||
|
||||
public static IntPtr VirtualAlloc(IntPtr BaseAddress, UIntPtr RegionSize, AllocationType AllocationType, MemoryProtection Protect)
|
||||
{
|
||||
if (_nt_allocate_virtual_memory(CurrentProcess, ref BaseAddress, IntPtr.Zero, ref RegionSize, AllocationType, Protect) == 0)
|
||||
return BaseAddress;
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static bool VirtualFree(IntPtr BaseAddress, UIntPtr RegionSize, FreeType FreeType)
|
||||
{
|
||||
return (_nt_free_virtual_memory(CurrentProcess, ref BaseAddress, ref RegionSize, FreeType) == 0);
|
||||
}
|
||||
|
||||
public static IntPtr CreateFileMapping(IntPtr FileHandle, IntPtr Attributes, MemoryProtection Protect, uint MaximumSizeLow, uint MaximumSizeHigh, String Name)
|
||||
{
|
||||
uint desiredAccess = (uint)Values.SECTION_MAP_READ;
|
||||
if (Protect == MemoryProtection.ReadWrite)
|
||||
desiredAccess |= (uint)Values.SECTION_MAP_WRITE;
|
||||
else if (Protect == MemoryProtection.ExecuteReadWrite)
|
||||
desiredAccess |= (uint)Values.SECTION_MAP_WRITE | (uint)Values.SECTION_MAP_EXECUTE;
|
||||
else if (Protect == MemoryProtection.ExecuteRead)
|
||||
desiredAccess |= (uint)Values.SECTION_MAP_EXECUTE;
|
||||
|
||||
IntPtr res;
|
||||
var str = new UNICODE_STRING(null);
|
||||
var objectAttributes = new OBJECT_ATTRIBUTES(str, 0);
|
||||
try
|
||||
{
|
||||
var size = new LARGE_INTEGER();
|
||||
size.LowPart = MaximumSizeLow;
|
||||
size.HighPart = MaximumSizeHigh;
|
||||
if (_nt_create_section(out res, desiredAccess, ref objectAttributes, ref size, Protect, (uint)Values.SEC_COMMIT, FileHandle) == 0)
|
||||
return res;
|
||||
}
|
||||
finally
|
||||
{
|
||||
str.Dispose();
|
||||
objectAttributes.Dispose();
|
||||
}
|
||||
|
||||
return NullHandle;
|
||||
}
|
||||
|
||||
public static IntPtr MapViewOfFile(IntPtr hFileMappingObject, MapAccess dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, IntPtr dwNumBytesToMap)
|
||||
{
|
||||
return _map_view_of_file(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumBytesToMap);
|
||||
}
|
||||
|
||||
public static bool UnmapViewOfFile(IntPtr BaseAddress)
|
||||
{
|
||||
return (_nt_unmap_view_of_section(CurrentProcess, BaseAddress) == 0);
|
||||
}
|
||||
|
||||
public static bool IsDebuggerPresent()
|
||||
{
|
||||
object obj;
|
||||
if (NtQueryInformationProcess(CurrentProcess, PROCESSINFOCLASS.ProcessBasicInformation, out obj, Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)), out _) == 0)
|
||||
{
|
||||
if (Marshal.ReadByte(new IntPtr(((PROCESS_BASIC_INFORMATION)obj).PebBaseAddress.ToInt64() + 2)) != 0) // PEB.BeingDebugged
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CheckRemoteDebuggerPresent()
|
||||
{
|
||||
object obj;
|
||||
if (NtQueryInformationProcess(CurrentProcess, PROCESSINFOCLASS.ProcessDebugPort, out obj, IntPtr.Size, out _) == 0)
|
||||
{
|
||||
if ((IntPtr)obj != IntPtr.Zero)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NtQueryInformationProcess(CurrentProcess, PROCESSINFOCLASS.ProcessDebugObjectHandle, out _, IntPtr.Size, out _) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ShowMessage(string Text, string Caption, MessageBoxButtons Buttons, MessageBoxIcon Icon)
|
||||
{
|
||||
IntPtr[] p = new IntPtr[4];
|
||||
var strText = new UNICODE_STRING(Text);
|
||||
var strCaption = new UNICODE_STRING(Caption);
|
||||
p[0] = Marshal.AllocHGlobal(Marshal.SizeOf(strText));
|
||||
p[1] = Marshal.AllocHGlobal(Marshal.SizeOf(strCaption));
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr(strText, p[0], false);
|
||||
Marshal.StructureToPtr(strCaption, p[1], false);
|
||||
p[2] = new IntPtr((uint)Buttons | (uint)Icon);
|
||||
p[3] = new IntPtr(-1);
|
||||
|
||||
_nt_raise_hard_error(0x40000018 | 0x10000000, 4, 3, p, 0, out _);
|
||||
}
|
||||
finally
|
||||
{
|
||||
strText.Dispose();
|
||||
strCaption.Dispose();
|
||||
Marshal.FreeHGlobal(p[0]);
|
||||
Marshal.FreeHGlobal(p[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class PE
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_DOS_HEADER
|
||||
{
|
||||
public UInt16 e_magic;
|
||||
public UInt16 e_cblp;
|
||||
public UInt16 e_cp;
|
||||
public UInt16 e_crlc;
|
||||
public UInt16 e_cparhdr;
|
||||
public UInt16 e_minalloc;
|
||||
public UInt16 e_maxalloc;
|
||||
public UInt16 e_ss;
|
||||
public UInt16 e_sp;
|
||||
public UInt16 e_csum;
|
||||
public UInt16 e_ip;
|
||||
public UInt16 e_cs;
|
||||
public UInt16 e_lfarlc;
|
||||
public UInt16 e_ovno;
|
||||
public UInt16 e_res_0;
|
||||
public UInt16 e_res_1;
|
||||
public UInt16 e_res_2;
|
||||
public UInt16 e_res_3;
|
||||
public UInt16 e_oemid;
|
||||
public UInt16 e_oeminfo;
|
||||
public UInt16 e_res2_0;
|
||||
public UInt16 e_res2_1;
|
||||
public UInt16 e_res2_2;
|
||||
public UInt16 e_res2_3;
|
||||
public UInt16 e_res2_4;
|
||||
public UInt16 e_res2_5;
|
||||
public UInt16 e_res2_6;
|
||||
public UInt16 e_res2_7;
|
||||
public UInt16 e_res2_8;
|
||||
public UInt16 e_res2_9;
|
||||
public UInt32 e_lfanew;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_FILE_HEADER
|
||||
{
|
||||
public UInt16 Machine;
|
||||
public UInt16 NumberOfSections;
|
||||
public UInt32 TimeDateStamp;
|
||||
public UInt32 PointerToSymbolTable;
|
||||
public UInt32 NumberOfSymbols;
|
||||
public UInt16 SizeOfOptionalHeader;
|
||||
public UInt16 Characteristics;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_NT_HEADERS
|
||||
{
|
||||
public UInt32 Signature;
|
||||
public IMAGE_FILE_HEADER FileHeader;
|
||||
//IMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
}
|
||||
|
||||
public const UInt16 IMAGE_DOS_SIGNATURE = 0x5A4D;
|
||||
public const UInt32 IMAGE_NT_SIGNATURE = 0x00004550;
|
||||
public const UInt16 IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
|
||||
public const UInt16 IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
public UInt32 VirtualAddress;
|
||||
public UInt32 Size;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_OPTIONAL_HEADER32
|
||||
{
|
||||
public UInt16 Magic;
|
||||
public Byte MajorLinkerVersion;
|
||||
public Byte MinorLinkerVersion;
|
||||
public UInt32 SizeOfCode;
|
||||
public UInt32 SizeOfInitializedData;
|
||||
public UInt32 SizeOfUninitializedData;
|
||||
public UInt32 AddressOfEntryPoint;
|
||||
public UInt32 BaseOfCode;
|
||||
public UInt32 BaseOfData;
|
||||
public UInt32 ImageBase;
|
||||
public UInt32 SectionAlignment;
|
||||
public UInt32 FileAlignment;
|
||||
public UInt16 MajorOperatingSystemVersion;
|
||||
public UInt16 MinorOperatingSystemVersion;
|
||||
public UInt16 MajorImageVersion;
|
||||
public UInt16 MinorImageVersion;
|
||||
public UInt16 MajorSubsystemVersion;
|
||||
public UInt16 MinorSubsystemVersion;
|
||||
public UInt32 Win32VersionValue;
|
||||
public UInt32 SizeOfImage;
|
||||
public UInt32 SizeOfHeaders;
|
||||
public UInt32 CheckSum;
|
||||
public UInt16 Subsystem;
|
||||
public UInt16 DllCharacteristics;
|
||||
public UInt32 SizeOfStackReserve;
|
||||
public UInt32 SizeOfStackCommit;
|
||||
public UInt32 SizeOfHeapReserve;
|
||||
public UInt32 SizeOfHeapCommit;
|
||||
public UInt32 LoaderFlags;
|
||||
public UInt32 NumberOfRvaAndSizes;
|
||||
|
||||
public IMAGE_DATA_DIRECTORY ExportTable;
|
||||
public IMAGE_DATA_DIRECTORY ImportTable;
|
||||
public IMAGE_DATA_DIRECTORY ResourceTable;
|
||||
public IMAGE_DATA_DIRECTORY ExceptionTable;
|
||||
public IMAGE_DATA_DIRECTORY CertificateTable;
|
||||
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
|
||||
public IMAGE_DATA_DIRECTORY Debug;
|
||||
public IMAGE_DATA_DIRECTORY Architecture;
|
||||
public IMAGE_DATA_DIRECTORY GlobalPtr;
|
||||
public IMAGE_DATA_DIRECTORY TLSTable;
|
||||
public IMAGE_DATA_DIRECTORY LoadConfigTable;
|
||||
public IMAGE_DATA_DIRECTORY BoundImport;
|
||||
public IMAGE_DATA_DIRECTORY IAT;
|
||||
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
|
||||
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
|
||||
public IMAGE_DATA_DIRECTORY Reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct IMAGE_OPTIONAL_HEADER64
|
||||
{
|
||||
public UInt16 Magic;
|
||||
public Byte MajorLinkerVersion;
|
||||
public Byte MinorLinkerVersion;
|
||||
public UInt32 SizeOfCode;
|
||||
public UInt32 SizeOfInitializedData;
|
||||
public UInt32 SizeOfUninitializedData;
|
||||
public UInt32 AddressOfEntryPoint;
|
||||
public UInt32 BaseOfCode;
|
||||
public UInt64 ImageBase;
|
||||
public UInt32 SectionAlignment;
|
||||
public UInt32 FileAlignment;
|
||||
public UInt16 MajorOperatingSystemVersion;
|
||||
public UInt16 MinorOperatingSystemVersion;
|
||||
public UInt16 MajorImageVersion;
|
||||
public UInt16 MinorImageVersion;
|
||||
public UInt16 MajorSubsystemVersion;
|
||||
public UInt16 MinorSubsystemVersion;
|
||||
public UInt32 Win32VersionValue;
|
||||
public UInt32 SizeOfImage;
|
||||
public UInt32 SizeOfHeaders;
|
||||
public UInt32 CheckSum;
|
||||
public UInt16 Subsystem;
|
||||
public UInt16 DllCharacteristics;
|
||||
public UInt64 SizeOfStackReserve;
|
||||
public UInt64 SizeOfStackCommit;
|
||||
public UInt64 SizeOfHeapReserve;
|
||||
public UInt64 SizeOfHeapCommit;
|
||||
public UInt32 LoaderFlags;
|
||||
public UInt32 NumberOfRvaAndSizes;
|
||||
|
||||
public IMAGE_DATA_DIRECTORY ExportTable;
|
||||
public IMAGE_DATA_DIRECTORY ImportTable;
|
||||
public IMAGE_DATA_DIRECTORY ResourceTable;
|
||||
public IMAGE_DATA_DIRECTORY ExceptionTable;
|
||||
public IMAGE_DATA_DIRECTORY CertificateTable;
|
||||
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
|
||||
public IMAGE_DATA_DIRECTORY Debug;
|
||||
public IMAGE_DATA_DIRECTORY Architecture;
|
||||
public IMAGE_DATA_DIRECTORY GlobalPtr;
|
||||
public IMAGE_DATA_DIRECTORY TLSTable;
|
||||
public IMAGE_DATA_DIRECTORY LoadConfigTable;
|
||||
public IMAGE_DATA_DIRECTORY BoundImport;
|
||||
public IMAGE_DATA_DIRECTORY IAT;
|
||||
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
|
||||
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
|
||||
public IMAGE_DATA_DIRECTORY Reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct IMAGE_EXPORT_DIRECTORY
|
||||
{
|
||||
public UInt32 Characteristics;
|
||||
public UInt32 TimeDateStamp;
|
||||
public UInt16 MajorVersion;
|
||||
public UInt16 MinorVersion;
|
||||
public UInt32 Name;
|
||||
public UInt32 Base;
|
||||
public UInt32 NumberOfFunctions;
|
||||
public UInt32 NumberOfNames;
|
||||
public UInt32 AddressOfFunctions;
|
||||
public UInt32 AddressOfNames;
|
||||
public UInt32 AddressOfNameOrdinals;
|
||||
}
|
||||
}
|
||||
}
|
291
runtime/common.h
Normal file
291
runtime/common.h
Normal file
@ -0,0 +1,291 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#ifdef VMP_GNU
|
||||
#define VMP_IMPORT
|
||||
#else
|
||||
#define VMP_IMPORT __declspec(dllimport)
|
||||
#ifdef WIN_DRIVER
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "../bin/64/Driver/VMProtectDDK64.lib")
|
||||
#else
|
||||
#pragma comment(lib, "../bin/32/Driver/VMProtectDDK32.lib")
|
||||
#endif // _WIN64
|
||||
#else
|
||||
#ifdef _WIN64
|
||||
#ifdef NDEBUG
|
||||
#pragma comment(lib, "../bin/64/Release/VMProtectSDK64.lib")
|
||||
#else
|
||||
#pragma comment(lib, "../bin/64/Debug/VMProtectSDK64.lib")
|
||||
#endif
|
||||
#else
|
||||
#ifdef NDEBUG
|
||||
#pragma comment(lib, "../bin/32/Release/VMProtectSDK32.lib")
|
||||
#else
|
||||
#pragma comment(lib, "../bin/32/Debug/VMProtectSDK32.lib")
|
||||
#endif
|
||||
#endif // _WIN64
|
||||
#endif // WIN_DRIVER
|
||||
#endif // VMP_GNU
|
||||
|
||||
#include "../sdk/sdk.h"
|
||||
|
||||
const size_t NOT_ID = (size_t)-1;
|
||||
|
||||
enum {
|
||||
MESSAGE_DEBUGGER_FOUND,
|
||||
MESSAGE_VIRTUAL_MACHINE_FOUND,
|
||||
MESSAGE_FILE_CORRUPTED,
|
||||
MESSAGE_SERIAL_NUMBER_REQUIRED,
|
||||
MESSAGE_HWID_MISMATCHED,
|
||||
MESSAGE_COUNT
|
||||
};
|
||||
|
||||
#ifdef VMP_GNU
|
||||
#define VMP_STR(s) s
|
||||
#else
|
||||
#define VMP_STR(s) L##s
|
||||
#endif
|
||||
|
||||
#define MESSAGE_DEBUGGER_FOUND_STR VMP_STR("A debugger has been found running in your system.\nPlease, unload it from memory and restart your program.")
|
||||
#define MESSAGE_VIRTUAL_MACHINE_FOUND_STR VMP_STR("Sorry, this application cannot run under a Virtual Machine.")
|
||||
#define MESSAGE_FILE_CORRUPTED_STR VMP_STR("File corrupted! This program has been manipulated and maybe\nit's infected by a Virus or cracked. This file won't work anymore.")
|
||||
#define MESSAGE_SERIAL_NUMBER_REQUIRED_STR VMP_STR("This code requires valid serial number to run.\nProgram will be terminated.")
|
||||
#define MESSAGE_HWID_MISMATCHED_STR VMP_STR("This application cannot be executed on this computer.")
|
||||
#define MESSAGE_UNREGISTERED_VERSION_STR VMP_STR("This application is protected with unregistered version of VMProtect and cannot be executed on this computer.")
|
||||
|
||||
enum {
|
||||
VAR_IS_PATCH_DETECTED,
|
||||
VAR_IS_DEBUGGER_DETECTED,
|
||||
VAR_LOADER_CRC_INFO,
|
||||
VAR_LOADER_CRC_INFO_SIZE,
|
||||
VAR_LOADER_CRC_INFO_HASH,
|
||||
VAR_SESSION_KEY,
|
||||
VAR_DRIVER_UNLOAD,
|
||||
VAR_CRC_IMAGE_SIZE,
|
||||
VAR_LOADER_STATUS,
|
||||
VAR_SERVER_DATE,
|
||||
VAR_OS_BUILD_NUMBER,
|
||||
VAR_CPU_COUNT,
|
||||
VAR_CPU_HASH,
|
||||
VAR_COUNT = VAR_CPU_HASH + 32
|
||||
};
|
||||
|
||||
enum {
|
||||
FACE_MASK = 0xFACE0000U,
|
||||
|
||||
FACE_RC5_P,
|
||||
FACE_RC5_Q,
|
||||
|
||||
FACE_STRING_INFO,
|
||||
FACE_RESOURCE_INFO,
|
||||
FACE_STORAGE_INFO,
|
||||
FACE_REGISTRY_INFO,
|
||||
FACE_LICENSE_INFO,
|
||||
FACE_LICENSE_INFO_SIZE,
|
||||
FACE_KEY_INFO,
|
||||
FACE_RUNTIME_ENTRY,
|
||||
FACE_CRC_INFO_SALT,
|
||||
FACE_CRC_TABLE_ENTRY,
|
||||
FACE_CRC_TABLE_SIZE,
|
||||
FACE_CRC_TABLE_HASH,
|
||||
FACE_TRIAL_HWID,
|
||||
FACE_TRIAL_HWID_SIZE,
|
||||
FACE_CORE_OPTIONS,
|
||||
FACE_IMAGE_BASE,
|
||||
FACE_FILE_BASE,
|
||||
|
||||
FACE_NTOSKRNL_NAME,
|
||||
FACE_HAL_NAME,
|
||||
FACE_USER32_NAME,
|
||||
FACE_MESSAGE_BOX_NAME,
|
||||
FACE_KERNEL32_NAME,
|
||||
FACE_CREATE_FILE_NAME,
|
||||
FACE_CLOSE_HANDLE_NAME,
|
||||
FACE_INITIALIZATION_ERROR,
|
||||
FACE_PROC_NOT_FOUND,
|
||||
FACE_ORDINAL_NOT_FOUND,
|
||||
FACE_STRING_DECRYPT_KEY,
|
||||
FACE_DRIVER_FORMAT_VALUE,
|
||||
FACE_FILE_CORRUPTED,
|
||||
FACE_LOADER_OPTIONS,
|
||||
FACE_LOADER_DATA,
|
||||
FACE_DEBUGGER_FOUND,
|
||||
FACE_NT_SET_INFORMATION_PROCESS_NAME,
|
||||
FACE_NT_RAISE_HARD_ERROR_NAME,
|
||||
FACE_IS_WOW64_PROCESS_NAME,
|
||||
FACE_WINE_GET_VERSION_NAME,
|
||||
FACE_MACOSX_FORMAT_VALUE,
|
||||
FACE_GNU_PTRACE,
|
||||
FACE_UNREGISTERED_VERSION,
|
||||
FACE_WTSAPI32_NAME,
|
||||
FACE_WTS_SEND_MESSAGE_NAME,
|
||||
FACE_NTDLL_NAME,
|
||||
FACE_NT_QUERY_INFORMATION_NAME,
|
||||
FACE_NT_SET_INFORMATION_THREAD_NAME,
|
||||
FACE_SICE_NAME,
|
||||
FACE_SIWVID_NAME,
|
||||
FACE_NTICE_NAME,
|
||||
FACE_ICEEXT_NAME,
|
||||
FACE_SYSER_NAME,
|
||||
FACE_VIRTUAL_MACHINE_FOUND,
|
||||
FACE_SBIEDLL_NAME,
|
||||
FACE_QUERY_VIRTUAL_MEMORY_NAME,
|
||||
FACE_ENUM_SYSTEM_FIRMWARE_NAME,
|
||||
FACE_GET_SYSTEM_FIRMWARE_NAME,
|
||||
FACE_NT_QUERY_INFORMATION_PROCESS_NAME,
|
||||
FACE_NT_VIRTUAL_PROTECT_NAME,
|
||||
FACE_NT_OPEN_FILE_NAME,
|
||||
FACE_NT_CREATE_SECTION_NAME,
|
||||
FACE_NT_OPEN_SECTION_NAME,
|
||||
FACE_NT_MAP_VIEW_OF_SECTION,
|
||||
FACE_NT_UNMAP_VIEW_OF_SECTION,
|
||||
FACE_NT_CLOSE,
|
||||
FACE_SYSCALL,
|
||||
FACE_NT_ALLOCATE_VIRTUAL_MEMORY_NAME,
|
||||
FACE_NT_FREE_VIRTUAL_MEMORY_NAME,
|
||||
|
||||
FACE_PACKER_INFO = 0xFACE0100U,
|
||||
FACE_PACKER_INFO_SIZE,
|
||||
FACE_FILE_CRC_INFO,
|
||||
FACE_FILE_CRC_INFO_SIZE,
|
||||
FACE_LOADER_CRC_INFO,
|
||||
FACE_LOADER_CRC_INFO_SIZE,
|
||||
FACE_SECTION_INFO,
|
||||
FACE_SECTION_INFO_SIZE,
|
||||
FACE_FIXUP_INFO,
|
||||
FACE_FIXUP_INFO_SIZE,
|
||||
FACE_RELOCATION_INFO,
|
||||
FACE_RELOCATION_INFO_SIZE,
|
||||
FACE_IAT_INFO,
|
||||
FACE_IAT_INFO_SIZE,
|
||||
FACE_IMPORT_INFO,
|
||||
FACE_IMPORT_INFO_SIZE,
|
||||
FACE_INTERNAL_IMPORT_INFO,
|
||||
FACE_INTERNAL_IMPORT_INFO_SIZE,
|
||||
FACE_MEMORY_CRC_INFO,
|
||||
FACE_MEMORY_CRC_INFO_SIZE,
|
||||
FACE_DELAY_IMPORT_INFO,
|
||||
FACE_DELAY_IMPORT_INFO_SIZE,
|
||||
FACE_LOADER_CRC_INFO_HASH,
|
||||
FACE_MEMORY_CRC_INFO_HASH,
|
||||
FACE_TLS_INDEX_INFO,
|
||||
FACE_GNU_RELRO_INFO,
|
||||
FACE_NON_PAGED_POOL_NX,
|
||||
FACE_DEFAULT_MDL_PRIORITY,
|
||||
|
||||
FACE_VAR = 0xFACE0200U,
|
||||
FACE_VAR_IS_PATCH_DETECTED = FACE_VAR | (VAR_IS_PATCH_DETECTED << 4),
|
||||
FACE_VAR_IS_DEBUGGER_DETECTED = FACE_VAR | (VAR_IS_DEBUGGER_DETECTED << 4),
|
||||
FACE_VAR_LOADER_CRC_INFO = FACE_VAR | (VAR_LOADER_CRC_INFO << 4),
|
||||
FACE_VAR_LOADER_CRC_INFO_SIZE = FACE_VAR | (VAR_LOADER_CRC_INFO_SIZE << 4),
|
||||
FACE_VAR_LOADER_CRC_INFO_HASH = FACE_VAR | (VAR_LOADER_CRC_INFO_HASH << 4),
|
||||
FACE_VAR_SESSION_KEY = FACE_VAR | (VAR_SESSION_KEY << 4),
|
||||
FACE_VAR_DRIVER_UNLOAD = FACE_VAR | (VAR_DRIVER_UNLOAD << 4),
|
||||
FACE_VAR_CRC_IMAGE_SIZE = FACE_VAR | (VAR_CRC_IMAGE_SIZE << 4),
|
||||
FACE_VAR_LOADER_STATUS = FACE_VAR | (VAR_LOADER_STATUS << 4),
|
||||
FACE_VAR_SERVER_DATE = FACE_VAR | (VAR_SERVER_DATE << 4),
|
||||
FACE_VAR_CPU_COUNT = FACE_VAR | (VAR_CPU_COUNT << 4),
|
||||
FACE_VAR_CPU_HASH = FACE_VAR | (VAR_CPU_HASH << 4),
|
||||
FACE_VAR_OS_BUILD_NUMBER = FACE_VAR | (VAR_OS_BUILD_NUMBER << 4),
|
||||
|
||||
FACE_VAR_SALT = 0xFACE0300U,
|
||||
FACE_VAR_IS_PATCH_DETECTED_SALT = FACE_VAR_SALT | VAR_IS_PATCH_DETECTED,
|
||||
FACE_VAR_IS_DEBUGGER_DETECTED_SALT = FACE_VAR_SALT | VAR_IS_DEBUGGER_DETECTED,
|
||||
FACE_VAR_LOADER_CRC_INFO_SALT = FACE_VAR_SALT | VAR_LOADER_CRC_INFO,
|
||||
FACE_VAR_LOADER_CRC_INFO_SIZE_SALT = FACE_VAR_SALT | VAR_LOADER_CRC_INFO_SIZE,
|
||||
FACE_VAR_LOADER_CRC_INFO_HASH_SALT = FACE_VAR_SALT | VAR_LOADER_CRC_INFO_HASH,
|
||||
FACE_VAR_DRIVER_UNLOAD_SALT = FACE_VAR_SALT | VAR_DRIVER_UNLOAD,
|
||||
FACE_VAR_CRC_IMAGE_SIZE_SALT = FACE_VAR_SALT | VAR_CRC_IMAGE_SIZE,
|
||||
FACE_VAR_SERVER_DATE_SALT = FACE_VAR_SALT | VAR_SERVER_DATE,
|
||||
FACE_VAR_CPU_COUNT_SALT = FACE_VAR_SALT | VAR_CPU_COUNT,
|
||||
FACE_VAR_CPU_HASH_SALT = FACE_VAR_SALT | VAR_CPU_HASH,
|
||||
FACE_VAR_OS_BUILD_NUMBER_SALT = FACE_VAR_SALT | VAR_OS_BUILD_NUMBER,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOADER_OPTION_CHECK_PATCH = 0x1,
|
||||
LOADER_OPTION_CHECK_DEBUGGER = 0x2,
|
||||
LOADER_OPTION_CHECK_KERNEL_DEBUGGER = 0x4,
|
||||
LOADER_OPTION_EXIT_PROCESS = 0x8,
|
||||
LOADER_OPTION_CHECK_VIRTUAL_MACHINE = 0x10
|
||||
};
|
||||
|
||||
enum {
|
||||
CORE_OPTION_MEMORY_PROTECTION = 0x1,
|
||||
CORE_OPTION_CHECK_DEBUGGER = 0x2
|
||||
};
|
||||
|
||||
enum {
|
||||
FILE_LOAD = 0x1,
|
||||
FILE_REGISTER = 0x2,
|
||||
FILE_INSTALL = 0x4,
|
||||
};
|
||||
|
||||
enum {
|
||||
FIELD_BUILD_DATE,
|
||||
FIELD_PUBLIC_EXP_OFFSET,
|
||||
FIELD_PUBLIC_EXP_SIZE,
|
||||
FIELD_MODULUS_OFFSET,
|
||||
FIELD_MODULUS_SIZE,
|
||||
FIELD_BLACKLIST_OFFSET,
|
||||
FIELD_BLACKLIST_SIZE,
|
||||
FIELD_ACTIVATION_URL_OFFSET,
|
||||
FIELD_ACTIVATION_URL_SIZE,
|
||||
FIELD_CRC_OFFSET,
|
||||
FIELD_COUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
WOW64_FLAG = 0x8000
|
||||
};
|
||||
|
||||
#ifndef _CONSOLE // google test
|
||||
#define FACE_TO_INDEX(i) ((uint32_t)(i)/sizeof(size_t))
|
||||
#ifdef VMP_GNU
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
#else
|
||||
#define FACE_TO_INDEX(i) (((uint32_t)(i) & 0xff) >> 4)
|
||||
#endif
|
||||
|
||||
struct GlobalData {
|
||||
bool is_patch_detected() { return ((v_[FACE_TO_INDEX(FACE_VAR_IS_PATCH_DETECTED)] ^ FACE_VAR_IS_PATCH_DETECTED_SALT) != 0); } //-V557
|
||||
bool is_debugger_detected() { return ((v_[FACE_TO_INDEX(FACE_VAR_IS_DEBUGGER_DETECTED)] ^ FACE_VAR_IS_DEBUGGER_DETECTED_SALT) != 0); } //-V557
|
||||
size_t loader_crc_info() { return (v_[FACE_TO_INDEX(FACE_VAR_LOADER_CRC_INFO)] ^ FACE_VAR_LOADER_CRC_INFO_SALT); } //-V557
|
||||
size_t loader_crc_size() { return (v_[FACE_TO_INDEX(FACE_VAR_LOADER_CRC_INFO_SIZE)] ^ FACE_VAR_LOADER_CRC_INFO_SIZE_SALT); } //-V557
|
||||
size_t loader_crc_hash() { return (v_[FACE_TO_INDEX(FACE_VAR_LOADER_CRC_INFO_HASH)] ^ FACE_VAR_LOADER_CRC_INFO_HASH_SALT); } //-V557
|
||||
size_t cpu_hash(size_t index) { return (v_[FACE_TO_INDEX(FACE_VAR_CPU_HASH) + index] ^ FACE_VAR_CPU_HASH_SALT); }
|
||||
size_t cpu_count() { return (v_[FACE_TO_INDEX(FACE_VAR_CPU_COUNT)] ^ FACE_VAR_CPU_COUNT_SALT); } //-V557
|
||||
size_t session_key() { return (v_[FACE_TO_INDEX(FACE_VAR_SESSION_KEY)]); } //-V557
|
||||
size_t driver_unload() { return (v_[FACE_TO_INDEX(FACE_VAR_DRIVER_UNLOAD)] ^ FACE_VAR_DRIVER_UNLOAD_SALT); } //-V557
|
||||
size_t crc_image_size() { return (v_[FACE_TO_INDEX(FACE_VAR_CRC_IMAGE_SIZE)] ^ FACE_VAR_CRC_IMAGE_SIZE_SALT); } //-V557
|
||||
uint32_t loader_status() { return static_cast<uint32_t>(v_[FACE_TO_INDEX(FACE_VAR_LOADER_STATUS)]); } //-V557
|
||||
uint32_t server_date() { return static_cast<uint32_t>(v_[FACE_TO_INDEX(FACE_VAR_SERVER_DATE)] ^ FACE_VAR_SERVER_DATE_SALT); } //-V557
|
||||
uint32_t os_build_number() { return static_cast<uint32_t>(v_[FACE_TO_INDEX(FACE_VAR_OS_BUILD_NUMBER)] ^ FACE_VAR_OS_BUILD_NUMBER_SALT); } //-V557
|
||||
|
||||
void set_is_patch_detected(bool value) { v_[FACE_TO_INDEX(FACE_VAR_IS_PATCH_DETECTED)] = static_cast<size_t>(value) ^ FACE_VAR_IS_PATCH_DETECTED_SALT; } //-V557
|
||||
void set_is_debugger_detected(bool value) { v_[FACE_TO_INDEX(FACE_VAR_IS_DEBUGGER_DETECTED)] = static_cast<size_t>(value) ^ FACE_VAR_IS_DEBUGGER_DETECTED_SALT; } //-V557
|
||||
void set_loader_crc_info(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_LOADER_CRC_INFO)] = value ^ FACE_VAR_LOADER_CRC_INFO_SALT; } //-V557
|
||||
void set_loader_crc_size(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_LOADER_CRC_INFO_SIZE)] = value ^ FACE_VAR_LOADER_CRC_INFO_SIZE_SALT; } //-V557
|
||||
void set_loader_crc_hash(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_LOADER_CRC_INFO_HASH)] = value ^ FACE_VAR_LOADER_CRC_INFO_HASH_SALT; } //-V557
|
||||
void set_cpu_hash(size_t index, size_t value) { v_[FACE_TO_INDEX(FACE_VAR_CPU_HASH) + index] = value ^ FACE_VAR_CPU_HASH_SALT; }
|
||||
void set_cpu_count(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_CPU_COUNT)] = value ^ FACE_VAR_CPU_COUNT_SALT; } //-V557
|
||||
void set_session_key(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_SESSION_KEY)] = value; } //-V557
|
||||
void set_driver_unload(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_DRIVER_UNLOAD)] = value ^ FACE_VAR_DRIVER_UNLOAD_SALT; } //-V557
|
||||
void set_crc_image_size(size_t value) { v_[FACE_TO_INDEX(FACE_VAR_CRC_IMAGE_SIZE)] = value ^ FACE_VAR_CRC_IMAGE_SIZE_SALT; } //-V557
|
||||
void set_loader_status(uint32_t value) { v_[FACE_TO_INDEX(FACE_VAR_LOADER_STATUS)] = value; } //-V557
|
||||
void set_server_date(uint32_t value) { v_[FACE_TO_INDEX(FACE_VAR_SERVER_DATE)] = value ^ FACE_VAR_SERVER_DATE_SALT; } //-V557
|
||||
void set_os_build_number(uint32_t value) { v_[FACE_TO_INDEX(FACE_VAR_OS_BUILD_NUMBER)] = value ^ FACE_VAR_OS_BUILD_NUMBER_SALT; } //-V557
|
||||
private:
|
||||
size_t v_[VAR_COUNT];
|
||||
};
|
||||
|
||||
#ifndef _CONSOLE
|
||||
#ifdef VMP_GNU
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
1365
runtime/core.cc
Normal file
1365
runtime/core.cc
Normal file
File diff suppressed because it is too large
Load Diff
149
runtime/core.h
Normal file
149
runtime/core.h
Normal file
@ -0,0 +1,149 @@
|
||||
#ifndef CORE_H
|
||||
#define CORE_H
|
||||
|
||||
class StringManager;
|
||||
class LicensingManager;
|
||||
class HardwareID;
|
||||
|
||||
#ifdef VMP_GNU
|
||||
#elif defined(WIN_DRIVER)
|
||||
#else
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
|
||||
#endif
|
||||
|
||||
#ifndef NTDDI_WIN7 //SDK 6.0
|
||||
typedef enum _OBJECT_INFORMATION_CLASS {
|
||||
ObjectBasicInformation = 0,
|
||||
ObjectTypeInformation = 2
|
||||
} OBJECT_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _PUBLIC_OBJECT_BASIC_INFORMATION {
|
||||
ULONG Attributes;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG HandleCount;
|
||||
ULONG PointerCount;
|
||||
|
||||
ULONG Reserved[10]; // reserved for internal use
|
||||
|
||||
} PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION;
|
||||
#endif
|
||||
|
||||
class ResourceManager;
|
||||
class FileManager;
|
||||
class RegistryManager;
|
||||
class HookManager;
|
||||
|
||||
enum VirtualObjectType {
|
||||
OBJECT_FILE,
|
||||
OBJECT_SECTION,
|
||||
OBJECT_MAP,
|
||||
OBJECT_KEY,
|
||||
};
|
||||
|
||||
class VirtualObject
|
||||
{
|
||||
public:
|
||||
VirtualObject(VirtualObjectType type, void *ref, HANDLE handle, uint32_t access);
|
||||
~VirtualObject();
|
||||
void *ref() const { return ref_; }
|
||||
VirtualObjectType type() const { return type_; }
|
||||
HANDLE handle() const { return handle_; }
|
||||
uint64_t file_position() const { return file_position_; }
|
||||
void set_file_position(uint64_t position) { file_position_ = position; }
|
||||
uint32_t attributes() const { return attributes_; }
|
||||
void set_attributes(uint32_t attributes) { attributes_ = attributes; }
|
||||
uint32_t access() const { return access_; }
|
||||
private:
|
||||
void *ref_;
|
||||
HANDLE handle_;
|
||||
VirtualObjectType type_;
|
||||
uint64_t file_position_;
|
||||
uint32_t attributes_;
|
||||
uint32_t access_;
|
||||
};
|
||||
|
||||
class VirtualObjectList
|
||||
{
|
||||
public:
|
||||
VirtualObjectList();
|
||||
~VirtualObjectList();
|
||||
VirtualObject *Add(VirtualObjectType type, void *ref, HANDLE handle, uint32_t access);
|
||||
void DeleteObject(HANDLE handle);
|
||||
void DeleteRef(void *ref, HANDLE handle = 0);
|
||||
VirtualObject *GetObject(HANDLE handle) const;
|
||||
VirtualObject *GetFile(HANDLE handle) const;
|
||||
VirtualObject *GetSection(HANDLE handle) const;
|
||||
VirtualObject *GetMap(HANDLE process, void *map) const;
|
||||
VirtualObject *GetKey(HANDLE handle) const;
|
||||
VirtualObject *operator [] (size_t index) const { return v_[index]; }
|
||||
size_t size() const { return v_.size(); }
|
||||
CRITICAL_SECTION &critical_section() { return critical_section_; };
|
||||
uint32_t GetHandleCount(HANDLE handle) const;
|
||||
uint32_t GetPointerCount(const void *ref) const;
|
||||
private:
|
||||
void Delete(size_t index);
|
||||
CRITICAL_SECTION critical_section_;
|
||||
vector<VirtualObject *> v_;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef VMP_GNU
|
||||
EXPORT_API extern GlobalData *loader_data;
|
||||
#else
|
||||
extern GlobalData *loader_data;
|
||||
#endif
|
||||
|
||||
class Core
|
||||
{
|
||||
public:
|
||||
static Core *Instance();
|
||||
static void Free();
|
||||
bool Init(HMODULE instance);
|
||||
~Core();
|
||||
StringManager *string_manager() const { return string_manager_; }
|
||||
LicensingManager *licensing_manager() const { return licensing_manager_; }
|
||||
HardwareID *hardware_id();
|
||||
#ifdef VMP_GNU
|
||||
#elif defined(WIN_DRIVER)
|
||||
#else
|
||||
NTSTATUS NtProtectVirtualMemory(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect);
|
||||
NTSTATUS NtClose(HANDLE Handle);
|
||||
NTSTATUS NtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
|
||||
NTSTATUS TrueNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
|
||||
ResourceManager *resource_manager() const { return resource_manager_; }
|
||||
FileManager *file_manager() const { return file_manager_; }
|
||||
RegistryManager *registry_manager() const { return registry_manager_; }
|
||||
#endif
|
||||
protected:
|
||||
Core();
|
||||
private:
|
||||
StringManager *string_manager_;
|
||||
LicensingManager *licensing_manager_;
|
||||
HardwareID *hardware_id_;
|
||||
#ifdef VMP_GNU
|
||||
#elif defined(WIN_DRIVER)
|
||||
#else
|
||||
NTSTATUS TrueNtProtectVirtualMemory(HANDLE ProcesssHandle, LPVOID *BaseAddress, SIZE_T *Size, DWORD NewProtect, PDWORD OldProtect);
|
||||
NTSTATUS TrueNtClose(HANDLE Handle);
|
||||
void HookAPIs(HookManager &hook_manager, uint32_t options);
|
||||
void UnhookAPIs(HookManager &hook_manager);
|
||||
VirtualObjectList objects_;
|
||||
ResourceManager *resource_manager_;
|
||||
FileManager *file_manager_;
|
||||
RegistryManager *registry_manager_;
|
||||
HookManager *hook_manager_;
|
||||
void *nt_protect_virtual_memory_;
|
||||
void *nt_close_;
|
||||
void *nt_query_object_;
|
||||
void *dbg_ui_remote_breakin_;
|
||||
#endif
|
||||
static Core *self_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
Core(const Core &);
|
||||
Core &operator=(const Core &);
|
||||
};
|
||||
|
||||
#endif
|
1086
runtime/crypto.cc
Normal file
1086
runtime/crypto.cc
Normal file
File diff suppressed because it is too large
Load Diff
388
runtime/crypto.h
Normal file
388
runtime/crypto.h
Normal file
@ -0,0 +1,388 @@
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
uint32_t rand32();
|
||||
uint64_t rand64();
|
||||
|
||||
#ifdef VMP_GNU
|
||||
|
||||
inline uint8_t _rotl8(uint8_t value, int shift)
|
||||
{
|
||||
__asm__ __volatile__ ("rolb %%cl, %0"
|
||||
: "=r"(value)
|
||||
: "0"(value), "c"(shift)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint16_t _rotl16(uint16_t value, int shift)
|
||||
{
|
||||
__asm__ __volatile__ ("rolw %%cl, %0"
|
||||
: "=r"(value)
|
||||
: "0"(value), "c"(shift)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint32_t _rotl32(uint32_t value, int shift)
|
||||
{
|
||||
__asm__ __volatile__ ("roll %%cl, %0"
|
||||
: "=r"(value)
|
||||
: "0"(value), "c"(shift)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint64_t _rotl64(uint64_t value, int shift)
|
||||
{
|
||||
return (value << shift) | (value >> (sizeof(value) * 8 - shift));
|
||||
}
|
||||
|
||||
inline uint8_t _rotr8(uint8_t value, int shift)
|
||||
{
|
||||
__asm__ __volatile__ ("rorb %%cl, %0"
|
||||
: "=r"(value)
|
||||
: "0"(value), "c"(shift)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint16_t _rotr16(uint16_t value, int shift)
|
||||
{
|
||||
__asm__ __volatile__ ("rorw %%cl, %0"
|
||||
: "=r"(value)
|
||||
: "0"(value), "c"(shift)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint32_t _rotr32(uint32_t value, int shift)
|
||||
{
|
||||
__asm__ __volatile__ ("rorl %%cl, %0"
|
||||
: "=r"(value)
|
||||
: "0"(value), "c"(shift)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint64_t _rotr64(uint64_t value, int shift)
|
||||
{
|
||||
return (value >> shift) | (value << (sizeof(value) * 8 - shift));
|
||||
}
|
||||
|
||||
inline uint64_t __rdtsc()
|
||||
{
|
||||
uint32_t hi, lo;
|
||||
__asm__ __volatile__ ("rdtsc"
|
||||
: "=a"(lo), "=d"(hi)
|
||||
);
|
||||
return static_cast<uint64_t>(lo) | static_cast<uint64_t>(hi) << 32;
|
||||
}
|
||||
|
||||
|
||||
inline void __cpuid(int regs[4], uint32_t value)
|
||||
{
|
||||
__asm__ __volatile__ ("cpuid"
|
||||
: "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
|
||||
: "a"(value)
|
||||
);
|
||||
}
|
||||
|
||||
inline void __movsb(void *d, const void *s, size_t n) {
|
||||
asm volatile ("rep movsb"
|
||||
: "=D" (d),
|
||||
"=S" (s),
|
||||
"=c" (n)
|
||||
: "0" (d),
|
||||
"1" (s),
|
||||
"2" (n)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
inline uint16_t __builtin_bswap16(uint16_t value)
|
||||
{
|
||||
__asm__ __volatile__ ("rorw $8, %0"
|
||||
: "+r"(value)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define _rotl32 _lrotl
|
||||
#define _rotr32 _lrotr
|
||||
#define __builtin_bswap16 _byteswap_ushort
|
||||
#define __builtin_bswap32 _byteswap_ulong
|
||||
#define __builtin_bswap64 _byteswap_uint64
|
||||
inline unsigned long __builtin_ctz(unsigned int x) { unsigned long r; _BitScanForward(&r, x); return r; }
|
||||
|
||||
#if defined(WIN_DRIVER) && (WDK_NTDDI_VERSION <= NTDDI_WIN7)
|
||||
#ifndef WIN64
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
VOID
|
||||
__movsb(
|
||||
__out_ecount_full(Count) PUCHAR Destination,
|
||||
__in_ecount(Count) UCHAR const *Source,
|
||||
__in SIZE_T Count
|
||||
);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
inline uint64_t ByteToInt64(uint8_t value)
|
||||
{
|
||||
return static_cast<int64_t>(static_cast<int8_t>(value));
|
||||
}
|
||||
|
||||
inline uint64_t WordToInt64(uint16_t value)
|
||||
{
|
||||
return static_cast<int64_t>(static_cast<int16_t>(value));
|
||||
}
|
||||
|
||||
inline uint64_t DWordToInt64(uint32_t value)
|
||||
{
|
||||
return static_cast<int64_t>(static_cast<int32_t>(value));
|
||||
}
|
||||
|
||||
struct RC5Key {
|
||||
uint8_t Value[8];
|
||||
#ifndef RUNTIME
|
||||
uint32_t P;
|
||||
uint32_t Q;
|
||||
#endif
|
||||
RC5Key() {} //-V730 <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#ifdef RUNTIME
|
||||
RC5Key(const uint8_t *key)
|
||||
{
|
||||
memcpy(Value, key, sizeof(Value));
|
||||
}
|
||||
#endif
|
||||
void Create();
|
||||
};
|
||||
|
||||
class CipherRC5
|
||||
{
|
||||
public:
|
||||
CipherRC5(const RC5Key &key);
|
||||
void Encrypt(uint8_t *buff, size_t count) const;
|
||||
void Decrypt(const uint8_t *in, uint8_t *out, size_t count) const;
|
||||
void Encrypt(const uint32_t *in, uint32_t *out) const;
|
||||
void Decrypt(const uint32_t *in, uint32_t *out) const;
|
||||
private:
|
||||
enum {
|
||||
w = 32, // u32 size in bits
|
||||
r = 15, // number of rounds
|
||||
b = 8, // number of bytes in key
|
||||
c = 8 * b / w, // 16 - number u32s in key = ceil(8*b/w)
|
||||
t = 2 * (r + 1), // 34 - size of table S = 2*(r+1) u32s
|
||||
};
|
||||
uint32_t S[t]; // expanded key table
|
||||
#ifdef RUNTIME
|
||||
enum {
|
||||
P = FACE_RC5_P,
|
||||
Q = FACE_RC5_Q
|
||||
};
|
||||
#else
|
||||
uint32_t P;
|
||||
uint32_t Q;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CryptoContainer;
|
||||
|
||||
typedef unsigned short BignumInt;
|
||||
typedef unsigned long BignumDblInt;
|
||||
typedef BignumInt *Bignum;
|
||||
|
||||
class BigNumber
|
||||
{
|
||||
public:
|
||||
BigNumber();
|
||||
BigNumber(const BigNumber &src);
|
||||
BigNumber(const uint8_t *data, size_t size, bool inverse_order = false);
|
||||
~BigNumber();
|
||||
BigNumber modpow(const BigNumber &exp, const BigNumber &mod) const;
|
||||
CryptoContainer *modpow(const CryptoContainer &source, size_t exp_offset, size_t exp_size, size_t mod_offset, size_t mod_size) const;
|
||||
size_t size() const;
|
||||
bool operator < (const BigNumber &b) const;
|
||||
uint8_t operator [] (size_t index) const;
|
||||
BignumInt data(size_t index) const { return bignum_get_word(data_ + index); }
|
||||
private:
|
||||
|
||||
// no assignment op
|
||||
BigNumber &operator =(const BigNumber &);
|
||||
|
||||
BigNumber(Bignum data, const BignumInt *salt);
|
||||
BignumInt bignum_get_word(Bignum b) const;
|
||||
void bignum_set_word(Bignum b, BignumInt value) const;
|
||||
void init(size_t length);
|
||||
void internal_mul(BignumInt *a, BignumInt *b, BignumInt *c, int len) const;
|
||||
void internal_add_shifted(BignumInt *number, unsigned n, int shift) const;
|
||||
void internal_mod(BignumInt *a, int alen, BignumInt *m, int mlen, BignumInt *quot, int qshift) const;
|
||||
uint8_t bignum_byte(Bignum bn, size_t i) const;
|
||||
int bignum_cmp(const BigNumber &b) const;
|
||||
enum {
|
||||
BIGNUM_INT_MASK = 0xFFFFU,
|
||||
BIGNUM_TOP_BIT = 0x8000U,
|
||||
BIGNUM_INT_BITS = 16,
|
||||
BIGNUM_INT_BYTES = (BIGNUM_INT_BITS / 8)
|
||||
};
|
||||
|
||||
Bignum data_;
|
||||
#ifdef RUNTIME
|
||||
BignumInt salt_[20 / BIGNUM_INT_BYTES];
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
ATL_BASE64_FLAG_NONE = 0,
|
||||
ATL_BASE64_FLAG_NOPAD,
|
||||
ATL_BASE64_FLAG_NOCRLF
|
||||
};
|
||||
bool Base64Encode(const uint8_t *src, size_t src_len, char *dst, size_t &dst_len);
|
||||
bool Base64Decode(const char *src, size_t src_len, uint8_t *dst, size_t &dst_len);
|
||||
size_t Base64EncodeGetRequiredLength(size_t src_len);
|
||||
|
||||
class CryptoContainer
|
||||
{
|
||||
public:
|
||||
CryptoContainer(uint8_t *data, size_t size, const RC5Key &key);
|
||||
CryptoContainer(size_t size, const RC5Key &key);
|
||||
CryptoContainer(const BigNumber &bn);
|
||||
~CryptoContainer();
|
||||
const uint8_t *data() const { return reinterpret_cast<const uint8_t *>(data_); }
|
||||
size_t size() const { return size_; }
|
||||
uint32_t GetDWord(size_t pos) const;
|
||||
uint16_t GetWord(size_t pos) const;
|
||||
uint8_t GetByte(size_t pos) const;
|
||||
uint64_t GetQWord(size_t pos) const;
|
||||
bool SetDWord(size_t pos, uint32_t value) const;
|
||||
bool SetWord(size_t pos, uint16_t value) const;
|
||||
bool SetByte(size_t pos, uint8_t value) const;
|
||||
void UTF8ToUnicode(size_t offset, size_t len, VMP_WCHAR *dest, size_t dest_size) const;
|
||||
private:
|
||||
#define RC5_BLOCK_SIZE 8
|
||||
bool EncryptValue(size_t pos, uint8_t *value, size_t value_size) const;
|
||||
bool DecryptValue(size_t pos, uint8_t *value, size_t value_size) const;
|
||||
bool is_own_data_;
|
||||
uint32_t *data_;
|
||||
size_t size_;
|
||||
CipherRC5 *cipher_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
CryptoContainer(const CryptoContainer &);
|
||||
CryptoContainer &operator =(const CryptoContainer &);
|
||||
};
|
||||
|
||||
class SHA1
|
||||
{
|
||||
public:
|
||||
SHA1();
|
||||
void Reset();
|
||||
void Input(const uint8_t *data, size_t size);
|
||||
void Input(const CryptoContainer &data, size_t offset, size_t size);
|
||||
const uint8_t *Result();
|
||||
size_t ResultSize() const { return sizeof(digest_); }
|
||||
bool operator ==(SHA1 &other) { return memcmp(Result(), other.Result(), ResultSize()) == 0; }
|
||||
private:
|
||||
void ProcessMessageBlock();
|
||||
void PadMessage();
|
||||
bool computed_;
|
||||
size_t message_block_index_;
|
||||
uint8_t message_block_[64];
|
||||
uint32_t length_high_;
|
||||
uint32_t length_low_;
|
||||
uint32_t hash_[5];
|
||||
uint32_t digest_[5];
|
||||
};
|
||||
|
||||
static uint32_t crc32_table[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
#ifdef RUNTIME
|
||||
#ifdef VMP_GNU
|
||||
EXPORT_API uint32_t WINAPI CalcCRC(const void * key, size_t len) __asm__ ("CalcCRC");
|
||||
#else
|
||||
EXPORT_API uint32_t WINAPI CalcCRC(const void * key, size_t len);
|
||||
#endif
|
||||
#else
|
||||
uint32_t CalcCRC(const void * key, size_t len);
|
||||
#endif
|
||||
|
||||
class CRCValueCryptor
|
||||
{
|
||||
public:
|
||||
#ifdef RUNTIME
|
||||
FORCE_INLINE CRCValueCryptor() : key_(FACE_CRC_INFO_SALT) {}
|
||||
FORCE_INLINE uint32_t Decrypt(uint32_t value)
|
||||
{
|
||||
uint32_t res = value ^ key_;
|
||||
key_ = _rotl32(key_, 7) ^ res;
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
CRCValueCryptor(uint32_t key) : key_(key) {}
|
||||
uint32_t Encrypt(uint32_t value)
|
||||
{
|
||||
uint32_t old_key = key_;
|
||||
key_ = _rotl32(key_, 7) ^ value;
|
||||
return value ^ old_key;
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
uint32_t key_;
|
||||
};
|
||||
|
||||
#endif
|
1189
runtime/file_manager.cc
Normal file
1189
runtime/file_manager.cc
Normal file
File diff suppressed because it is too large
Load Diff
348
runtime/file_manager.h
Normal file
348
runtime/file_manager.h
Normal file
@ -0,0 +1,348 @@
|
||||
#ifndef FILE_MANAGER_H
|
||||
#define FILE_MANAGER_H
|
||||
|
||||
#include "loader.h"
|
||||
#include "registry_manager.h"
|
||||
|
||||
class CipherRC5;
|
||||
|
||||
typedef struct _FILE_BASIC_INFORMATION {
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
ULONG FileAttributes;
|
||||
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
|
||||
|
||||
typedef enum _SECTION_INFORMATION_CLASS {
|
||||
SectionBasicInformation,
|
||||
SectionImageInformation,
|
||||
SectionRelocationInformation
|
||||
} SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _SECTION_BASIC_INFORMATION {
|
||||
ULONG BaseAddress;
|
||||
ULONG Attributes;
|
||||
LARGE_INTEGER Size;
|
||||
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _SECTION_IMAGE_INFORMATION {
|
||||
PVOID EntryPoint;
|
||||
ULONG StackZeroBits;
|
||||
ULONG StackReserved;
|
||||
ULONG StackCommit;
|
||||
ULONG ImageSubsystem;
|
||||
WORD SubSystemVersionLow;
|
||||
WORD SubSystemVersionHigh;
|
||||
ULONG Unknown1;
|
||||
ULONG ImageCharacteristics;
|
||||
ULONG ImageMachineType;
|
||||
ULONG Unknown2[3];
|
||||
} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
|
||||
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
||||
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
|
||||
#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL)
|
||||
#define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS)0xC0000045L)
|
||||
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
|
||||
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L)
|
||||
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
|
||||
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
|
||||
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
|
||||
#define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001AL)
|
||||
#ifndef STATUS_INVALID_PARAMETER
|
||||
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
|
||||
#endif
|
||||
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
|
||||
#define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS)0xC0000020L)
|
||||
|
||||
#define OBJ_HANDLE_TAGBITS 0x00000003L
|
||||
#define EXHANDLE(x) ((HANDLE)((ULONG_PTR)(x) &~ OBJ_HANDLE_TAGBITS))
|
||||
|
||||
#define FILE_SUPERSEDE 0x00000000
|
||||
#define FILE_OPEN 0x00000001
|
||||
#define FILE_CREATE 0x00000002
|
||||
#define FILE_OPEN_IF 0x00000003
|
||||
#define FILE_OVERWRITE 0x00000004
|
||||
#define FILE_OVERWRITE_IF 0x00000005
|
||||
#define FILE_MAXIMUM_DISPOSITION 0x00000005
|
||||
|
||||
#define FILE_SUPERSEDED 0x00000000
|
||||
#define FILE_OPENED 0x00000001
|
||||
#define FILE_CREATED 0x00000002
|
||||
#define FILE_OVERWRITTEN 0x00000003
|
||||
#define FILE_EXISTS 0x00000004
|
||||
#define FILE_DOES_NOT_EXIST 0x00000005
|
||||
|
||||
#define FILE_USE_FILE_POINTER_POSITION 0xfffffffe
|
||||
|
||||
#define IMAGE_FILE_MACHINE_I486 0x14D
|
||||
#define IMAGE_FILE_MACHINE_I586 0x14E
|
||||
|
||||
#define FileBothDirectoryInformation (FILE_INFORMATION_CLASS)0x03
|
||||
#define FileBasicInformation (FILE_INFORMATION_CLASS)0x04
|
||||
#define FileStandardInformation (FILE_INFORMATION_CLASS)0x05
|
||||
#define FileNameInformation (FILE_INFORMATION_CLASS)0x09
|
||||
#define FilePositionInformation (FILE_INFORMATION_CLASS)0x0e
|
||||
#define FileIdBothDirectoryInformation (FILE_INFORMATION_CLASS)0x25
|
||||
#define FileAllInformation (FILE_INFORMATION_CLASS)0x12
|
||||
|
||||
typedef struct _FILE_POSITION_INFORMATION {
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
|
||||
|
||||
typedef struct _FILE_STANDARD_INFORMATION {
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG NumberOfLinks;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN Directory;
|
||||
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
|
||||
|
||||
typedef struct _FILE_NAME_INFORMATION {
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
|
||||
|
||||
typedef struct _FILE_INTERNAL_INFORMATION {
|
||||
LARGE_INTEGER IndexNumber;
|
||||
} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
|
||||
|
||||
typedef struct _FILE_EA_INFORMATION {
|
||||
ULONG EaSize;
|
||||
} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
|
||||
|
||||
typedef struct _FILE_ACCESS_INFORMATION {
|
||||
ACCESS_MASK AccessFlags;
|
||||
} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
|
||||
|
||||
typedef struct _FILE_MODE_INFORMATION {
|
||||
ULONG Mode;
|
||||
} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_ALIGNMENT_INFORMATION {
|
||||
ULONG AlignmentRequirement;
|
||||
} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
|
||||
|
||||
typedef struct _FILE_ALL_INFORMATION {
|
||||
FILE_BASIC_INFORMATION BasicInformation;
|
||||
FILE_STANDARD_INFORMATION StandardInformation;
|
||||
FILE_INTERNAL_INFORMATION InternalInformation;
|
||||
FILE_EA_INFORMATION EaInformation;
|
||||
FILE_ACCESS_INFORMATION AccessInformation;
|
||||
FILE_POSITION_INFORMATION PositionInformation;
|
||||
FILE_MODE_INFORMATION ModeInformation;
|
||||
FILE_ALIGNMENT_INFORMATION AlignmentInformation;
|
||||
FILE_NAME_INFORMATION NameInformation;
|
||||
} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
|
||||
|
||||
typedef struct _OBJECT_NAME_INFORMATION {
|
||||
UNICODE_STRING Name;
|
||||
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
|
||||
|
||||
typedef enum _FSINFOCLASS {
|
||||
FileFsVolumeInformation = 1,
|
||||
FileFsLabelInformation, // 2
|
||||
FileFsSizeInformation, // 3
|
||||
FileFsDeviceInformation, // 4
|
||||
FileFsAttributeInformation, // 5
|
||||
FileFsControlInformation, // 6
|
||||
FileFsFullSizeInformation, // 7
|
||||
FileFsObjectIdInformation, // 8
|
||||
FileFsDriverPathInformation, // 9
|
||||
FileFsVolumeFlagsInformation,// 10
|
||||
FileFsMaximumInformation
|
||||
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _FILE_FS_DEVICE_INFORMATION {
|
||||
DEVICE_TYPE DeviceType;
|
||||
ULONG Characteristics;
|
||||
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
|
||||
ULONG FileSystemAttributes;
|
||||
LONG MaximumComponentNameLength;
|
||||
ULONG FileSystemNameLength;
|
||||
WCHAR FileSystemName[1];
|
||||
} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
|
||||
|
||||
typedef struct _FILE_FS_VOLUME_INFORMATION {
|
||||
LARGE_INTEGER VolumeCreationTime;
|
||||
ULONG VolumeSerialNumber;
|
||||
ULONG VolumeLabelLength;
|
||||
BOOLEAN SupportsObjects;
|
||||
WCHAR VolumeLabel[1];
|
||||
} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
|
||||
|
||||
typedef struct _FILE_BOTH_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
CCHAR ShortNameLength;
|
||||
WCHAR ShortName[12];
|
||||
WCHAR FileName[1];
|
||||
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
|
||||
|
||||
typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG FileIndex;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
ULONG FileAttributes;
|
||||
ULONG FileNameLength;
|
||||
ULONG EaSize;
|
||||
CCHAR ShortNameLength;
|
||||
WCHAR ShortName[12];
|
||||
LARGE_INTEGER FileId;
|
||||
WCHAR FileName[1];
|
||||
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
|
||||
|
||||
struct OBJECT_DIRECTORY {
|
||||
uint32_t NumberOfEntries;
|
||||
// OBJECT_ENTRY Entries[];
|
||||
};
|
||||
|
||||
#define ObjectNameInformation (OBJECT_INFORMATION_CLASS)1
|
||||
|
||||
struct OBJECT_ENTRY {
|
||||
uint32_t NameOffset;
|
||||
uint32_t OffsetToData;
|
||||
uint32_t Size;
|
||||
uint32_t Options;
|
||||
};
|
||||
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
Path(wchar_t *str)
|
||||
{
|
||||
const wchar_t *last = str;
|
||||
const wchar_t *cur = str;
|
||||
while (*cur) {
|
||||
if (*cur == '\\') {
|
||||
if (cur > last)
|
||||
list_.push_back(UnicodeString(last, cur - last));
|
||||
last = cur + 1;
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
if (cur > last)
|
||||
list_.push_back(UnicodeString(last, cur - last));
|
||||
}
|
||||
|
||||
UnicodeString Combine(wchar_t *str)
|
||||
{
|
||||
vector<const UnicodeString *> folder_list;
|
||||
for (size_t i = 0; i < list_.size(); i++) {
|
||||
folder_list.push_back(&list_[i]);
|
||||
}
|
||||
|
||||
Path p(str);
|
||||
for (size_t i = 0; i < p.list_.size(); i++) {
|
||||
const UnicodeString &folder = p.list_[i];
|
||||
if (folder == L".")
|
||||
continue;
|
||||
|
||||
if (folder == L"..")
|
||||
folder_list.pop_back();
|
||||
else
|
||||
folder_list.push_back(&folder);
|
||||
}
|
||||
|
||||
UnicodeString res;
|
||||
for (size_t i = 0; i < folder_list.size(); i++) {
|
||||
if (i > 0)
|
||||
res.append(L"\\", 1);
|
||||
res.append(folder_list[i]->c_str());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
vector<UnicodeString> list_;
|
||||
};
|
||||
|
||||
class HookManager;
|
||||
class FileManager
|
||||
{
|
||||
public:
|
||||
FileManager(const uint8_t *data, HMODULE instance, const uint8_t *key, VirtualObjectList *objects);
|
||||
void HookAPIs(HookManager &hook_manager);
|
||||
void UnhookAPIs(HookManager &hook_manager);
|
||||
bool OpenFiles(RegistryManager ®istry_manager);
|
||||
NTSTATUS NtQueryAttributesFile(POBJECT_ATTRIBUTES ObjectAttributes, PFILE_BASIC_INFORMATION FileInformation);
|
||||
NTSTATUS NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
|
||||
NTSTATUS NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions);
|
||||
NTSTATUS NtQueryInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);
|
||||
NTSTATUS NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass);
|
||||
NTSTATUS NtSetInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);
|
||||
NTSTATUS NtQueryDirectoryFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry, PUNICODE_STRING FileName, BOOLEAN RestartScan);
|
||||
NTSTATUS NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key);
|
||||
NTSTATUS NtCreateSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER MaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle);
|
||||
NTSTATUS NtQuerySection(HANDLE SectionHandle, SECTION_INFORMATION_CLASS InformationClass, PVOID InformationBuffer, ULONG InformationBufferSize, PULONG ResultLength);
|
||||
NTSTATUS NtMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect);
|
||||
NTSTATUS NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
|
||||
NTSTATUS NtQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID Buffer, ULONG Length, PULONG ResultLength);
|
||||
private:
|
||||
NTSTATUS TrueNtQueryAttributesFile(POBJECT_ATTRIBUTES ObjectAttributes, PFILE_BASIC_INFORMATION FileInformation);
|
||||
NTSTATUS TrueNtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
|
||||
NTSTATUS TrueNtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions);
|
||||
NTSTATUS TrueNtQueryInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);
|
||||
NTSTATUS TrueNtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass);
|
||||
NTSTATUS TrueNtSetInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);
|
||||
NTSTATUS TrueNtQueryDirectoryFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry, PUNICODE_STRING FileName, BOOLEAN RestartScan);
|
||||
NTSTATUS TrueNtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key);
|
||||
NTSTATUS TrueNtCreateSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER MaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle);
|
||||
NTSTATUS TrueNtQuerySection(HANDLE SectionHandle, SECTION_INFORMATION_CLASS InformationClass, PVOID InformationBuffer, ULONG InformationBufferSize, PULONG ResultLength);
|
||||
NTSTATUS TrueNtMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Win32Protect);
|
||||
NTSTATUS TrueNtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
|
||||
NTSTATUS TrueNtQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID Buffer, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS TrueNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
|
||||
OBJECT_DIRECTORY DecryptDirectory(const OBJECT_DIRECTORY *directory_enc) const;
|
||||
OBJECT_ENTRY DecryptEntry(const OBJECT_ENTRY *entry_enc) const;
|
||||
bool DecryptString(LPCWSTR str_enc, LPWSTR str, size_t max_size) const;
|
||||
const OBJECT_ENTRY *FindEntry(HANDLE directory, PUNICODE_STRING object_name);
|
||||
bool ReadFile(const OBJECT_ENTRY *entry, uint64_t offset, void *dst, size_t size) const;
|
||||
NTSTATUS ReadImageHeader(const OBJECT_ENTRY *entry, IMAGE_NT_HEADERS *header) const;
|
||||
NTSTATUS ReadImage(const OBJECT_ENTRY *entry, void *image_base) const;
|
||||
|
||||
HMODULE instance_;
|
||||
uint32_t key_;
|
||||
VirtualObjectList *objects_;
|
||||
const uint8_t *data_;
|
||||
void *nt_query_attributes_file_;
|
||||
void *nt_create_file_;
|
||||
void *nt_open_file_;
|
||||
void *nt_read_file_;
|
||||
void *nt_query_information_file_;
|
||||
void *nt_query_volume_information_file_;
|
||||
void *nt_set_information_file_;
|
||||
void *nt_query_directory_file_;
|
||||
void *nt_close_;
|
||||
void *nt_create_section_;
|
||||
void *nt_query_section_;
|
||||
void *nt_map_view_of_section_;
|
||||
void *nt_unmap_view_of_section_;
|
||||
void *nt_query_virtual_memory_;
|
||||
vector<UnicodeString> file_name_list_;
|
||||
UnicodeString dos_root_;
|
||||
UnicodeString nt_root_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
FileManager(const FileManager &);
|
||||
FileManager &operator =(const FileManager &);
|
||||
};
|
||||
|
||||
#endif
|
738
runtime/hook_manager.cc
Normal file
738
runtime/hook_manager.cc
Normal file
@ -0,0 +1,738 @@
|
||||
#ifdef WIN_DRIVER
|
||||
#else
|
||||
#include "common.h"
|
||||
#include "objects.h"
|
||||
#include "utils.h"
|
||||
#include "hook_manager.h"
|
||||
|
||||
/**
|
||||
* HookManager
|
||||
*/
|
||||
|
||||
HookManager::HookManager()
|
||||
: update_count_(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void *HookManager::HookAPI(HMODULE dll, const char *api_name, void *handler, bool show_error, void **result)
|
||||
{
|
||||
void *res = NULL;
|
||||
void *api_address = InternalGetProcAddress(dll, api_name);
|
||||
if (api_address) {
|
||||
Begin();
|
||||
HookedAPI *hooked_api = new HookedAPI();
|
||||
if (hooked_api->Hook(api_address, handler, result)) {
|
||||
api_list_.push_back(hooked_api);
|
||||
res = hooked_api->old_handler();
|
||||
} else {
|
||||
delete hooked_api;
|
||||
}
|
||||
End();
|
||||
}
|
||||
|
||||
if (!res && show_error) {
|
||||
wchar_t error[512] = {};
|
||||
{
|
||||
// string "Error at hooking API \"%S\"\n"
|
||||
wchar_t str[] = { L'E', L'r', L'r', L'o', L'r', L' ', L'a', L't', L' ', L'h', L'o', L'o', L'k', L'i', L'n', L'g', L' ', L'A', L'P', L'I', L' ', L'\"', L'%', L'S', L'\"', L'\n', 0 };
|
||||
swprintf_s(error, str, api_name);
|
||||
}
|
||||
if (api_address){
|
||||
int n = 32;
|
||||
wchar_t line[100] = {};
|
||||
{
|
||||
// string "Dumping first %d bytes:\n"
|
||||
wchar_t str[] = { L'D', L'u', L'm', L'p', L'i', L'n', L'g', L' ', L'f', L'i', L'r', L's', L't', L' ', L'%', L'd', L' ', L'b', L'y', L't', L'e', L's', L':', L'\n', 0 };
|
||||
swprintf_s(line, str, n);
|
||||
}
|
||||
wcscat_s(error, line);
|
||||
for (int i = 0; i < n; i++) {
|
||||
wchar_t str[] = { L'%', L'0', L'2', L'X', (i % 16 == 15) ? L'\n' : L' ', 0};
|
||||
swprintf_s(line, str, reinterpret_cast<uint8_t *>(api_address)[i]);
|
||||
wcscat_s(error, line);
|
||||
}
|
||||
}
|
||||
ShowMessage(error);
|
||||
::TerminateProcess(::GetCurrentProcess(), 0xDEADC0DE);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool HookManager::UnhookAPI(void *handler)
|
||||
{
|
||||
if (!handler)
|
||||
return false;
|
||||
|
||||
bool res = false;
|
||||
Begin();
|
||||
for (size_t i = 0; i < api_list_.size(); i++) {
|
||||
HookedAPI *hooked_api = api_list_[i];
|
||||
if (hooked_api->old_handler() == handler) {
|
||||
api_list_.erase(i);
|
||||
hooked_api->Unhook();
|
||||
delete hooked_api;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
End();
|
||||
return res;
|
||||
}
|
||||
|
||||
void HookManager::GetThreads()
|
||||
{
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
THREADENTRY32 thread_entry;
|
||||
thread_entry.dwSize = sizeof(thread_entry);
|
||||
if (Thread32First(h, &thread_entry)) {
|
||||
DWORD process_id = GetCurrentProcessId();
|
||||
DWORD thread_id = GetCurrentThreadId();
|
||||
|
||||
do {
|
||||
if (thread_entry.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(thread_entry.th32OwnerProcessID))
|
||||
{
|
||||
if (thread_entry.th32OwnerProcessID == process_id && thread_entry.th32ThreadID != thread_id) {
|
||||
HANDLE thread = ::OpenThread(THREAD_SUSPEND_RESUME, FALSE, thread_entry.th32ThreadID);
|
||||
if (thread)
|
||||
thread_list_.push_back(thread);
|
||||
}
|
||||
}
|
||||
thread_entry.dwSize = sizeof(thread_entry);
|
||||
} while (Thread32Next(h, &thread_entry));
|
||||
}
|
||||
|
||||
::CloseHandle(h);
|
||||
}
|
||||
|
||||
void HookManager::SuspendThreads()
|
||||
{
|
||||
for (size_t i = 0; i < thread_list_.size(); i++) {
|
||||
::SuspendThread(thread_list_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void HookManager::ResumeThreads()
|
||||
{
|
||||
for (size_t i = 0; i < thread_list_.size(); i++) {
|
||||
::ResumeThread(thread_list_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void HookManager::FreeThreads()
|
||||
{
|
||||
for (size_t i = 0; i < thread_list_.size(); i++) {
|
||||
::CloseHandle(thread_list_[i]);
|
||||
}
|
||||
thread_list_.clear();
|
||||
}
|
||||
|
||||
void HookManager::Begin()
|
||||
{
|
||||
if (!update_count_) {
|
||||
GetThreads();
|
||||
SuspendThreads();
|
||||
}
|
||||
update_count_++;
|
||||
}
|
||||
|
||||
void HookManager::End()
|
||||
{
|
||||
update_count_--;
|
||||
if (!update_count_) {
|
||||
ResumeThreads();
|
||||
FreeThreads();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HookedAPI
|
||||
*/
|
||||
|
||||
static bool PutJump(uint8_t *address, const uint8_t *jump_dest)
|
||||
{
|
||||
INT64 offset = reinterpret_cast<uint64_t>(jump_dest) - reinterpret_cast<uint64_t>(address) - 5;
|
||||
if (offset < INT_MIN || offset > INT_MAX)
|
||||
return false;
|
||||
|
||||
uint8_t buff[5];
|
||||
buff[0] = 0xE9;
|
||||
*(reinterpret_cast<uint32_t *>(buff + 1)) = static_cast<uint32_t>(offset);
|
||||
|
||||
return FALSE != WriteProcessMemory(GetCurrentProcess(), address, buff, sizeof(buff), NULL);
|
||||
}
|
||||
|
||||
static bool PutJumpMem(uint8_t *address, const uint8_t *memory)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
// offset is relative
|
||||
INT64 offset = reinterpret_cast<uint64_t>(memory) - reinterpret_cast<uint64_t>(address) - 6;
|
||||
if (offset < INT_MIN || offset > INT_MAX)
|
||||
return false;
|
||||
#else
|
||||
// offset is absolute
|
||||
uint32_t offset = reinterpret_cast<uint32_t>(memory);
|
||||
#endif
|
||||
|
||||
uint8_t buff[6];
|
||||
buff[0] = 0xFF;
|
||||
buff[1] = 0x25;
|
||||
*(reinterpret_cast<uint32_t *>(buff + 2)) = static_cast<uint32_t>(offset);
|
||||
|
||||
return FALSE != WriteProcessMemory(GetCurrentProcess(), address, buff, sizeof(buff), NULL);
|
||||
}
|
||||
|
||||
enum eCommandType
|
||||
{
|
||||
CT_UNKNOWN = 0,
|
||||
CT_JMP,
|
||||
CT_RET
|
||||
};
|
||||
|
||||
struct sCommandInfo
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwRelOffset;
|
||||
eCommandType cmdType;
|
||||
};
|
||||
|
||||
#define C_66 0x00000001 // 66-prefix
|
||||
#define C_67 0x00000002 // 67-prefix
|
||||
#define C_LOCK 0x00000004 // lock
|
||||
#define C_REP 0x00000008 // repz/repnz
|
||||
#define C_SEG 0x00000010 // seg-prefix
|
||||
#define C_OPCODE2 0x00000020 // 2nd opcode present (1st == 0F)
|
||||
#define C_MODRM 0x00000040 // modrm present
|
||||
#define C_SIB 0x00000080 // sib present
|
||||
|
||||
bool GetInstructionSize(const byte *pOpCode, sCommandInfo &info)
|
||||
{
|
||||
const byte *opcode = pOpCode;
|
||||
|
||||
// BYTE disasm_seg = 0; // CS DS ES SS FS GS
|
||||
// BYTE disasm_rep = 0; // REPZ/REPNZ
|
||||
BYTE disasm_opcode = 0; // opcode
|
||||
BYTE disasm_opcode2 = 0; // used when opcode == 0F
|
||||
BYTE disasm_modrm = 0; // modxxxrm
|
||||
BYTE disasm_sib = 0; // scale-index-base
|
||||
#ifdef _WIN64
|
||||
BYTE disasm_preffix = {0};
|
||||
#endif
|
||||
|
||||
// DWORD disasm_len = 0; // 0 if error
|
||||
DWORD disasm_flag = 0; // C_xxx
|
||||
DWORD disasm_memsize = 0; // value = disasm_mem
|
||||
DWORD disasm_datasize = 0; // value = disasm_data
|
||||
DWORD disasm_defdata = 4; // == C_66 ? 2 : 4
|
||||
DWORD disasm_defmem = 4; // == C_67 ? 2 : 4
|
||||
DWORD disasm_offset = 0;
|
||||
|
||||
BYTE mod = 0;
|
||||
BYTE rm = 0;
|
||||
|
||||
if (! pOpCode) return false;
|
||||
|
||||
info.dwSize = 0;
|
||||
info.dwRelOffset = 0;
|
||||
info.cmdType = CT_UNKNOWN;
|
||||
|
||||
RETRY:
|
||||
|
||||
disasm_opcode = *opcode ++;
|
||||
|
||||
switch (disasm_opcode)
|
||||
{
|
||||
case 0x00: case 0x01: case 0x02: case 0x03:
|
||||
case 0x08: case 0x09: case 0x0A: case 0x0B:
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
case 0x18: case 0x19: case 0x1A: case 0x1B:
|
||||
case 0x20: case 0x21: case 0x22: case 0x23:
|
||||
case 0x28: case 0x29: case 0x2A: case 0x2B:
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
case 0x38: case 0x39: case 0x3A: case 0x3B:
|
||||
case 0x84: case 0x85: case 0x86: case 0x87:
|
||||
case 0x88: case 0x89: case 0x8A: case 0x8B:
|
||||
case 0x8C: case 0x8D: case 0x8E:
|
||||
case 0xD0: case 0xD1: case 0xD2: case 0xD3:
|
||||
case 0xD8: case 0xD9: case 0xDA: case 0xDB:
|
||||
case 0xDC: case 0xDD: case 0xDE: case 0xDF:
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
|
||||
case 0x04: case 0x05: case 0x0C: case 0x0D:
|
||||
case 0x14: case 0x15: case 0x1C: case 0x1D:
|
||||
case 0x24: case 0x25: case 0x2C: case 0x2D:
|
||||
case 0x34: case 0x35: case 0x3C: case 0x3D:
|
||||
case 0xA8: case 0xA9:
|
||||
|
||||
if (disasm_opcode & 1)
|
||||
{
|
||||
disasm_datasize += disasm_defdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
disasm_datasize ++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA0: case 0xA1: case 0xA2: case 0xA3:
|
||||
|
||||
if (disasm_opcode & 1)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
if (!(disasm_flag & C_66) && (disasm_preffix & 8))
|
||||
{
|
||||
disasm_datasize += 8;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
disasm_datasize += disasm_defdata;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disasm_datasize ++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06: case 0x07: case 0x0E:
|
||||
case 0x16: case 0x17: case 0x1E: case 0x1F:
|
||||
case 0x27: case 0x2F:
|
||||
case 0x37: case 0x3F:
|
||||
case 0x60: case 0x61:
|
||||
case 0xCE:
|
||||
#ifdef _WIN64
|
||||
return false;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0x26: case 0x2E:
|
||||
case 0x36: case 0x3E:
|
||||
case 0x64: case 0x65:
|
||||
disasm_flag |= C_SEG;
|
||||
goto RETRY;
|
||||
|
||||
case 0x40: case 0x41: case 0x42: case 0x43:
|
||||
case 0x44: case 0x45: case 0x46: case 0x47:
|
||||
case 0x48: case 0x49: case 0x4A: case 0x4B:
|
||||
case 0x4C: case 0x4D: case 0x4E: case 0x4F:
|
||||
#ifdef _WIN64
|
||||
disasm_preffix = disasm_opcode;
|
||||
goto RETRY;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0x50: case 0x51: case 0x52: case 0x53:
|
||||
case 0x54: case 0x55: case 0x56: case 0x57:
|
||||
case 0x58: case 0x59: case 0x5A: case 0x5B:
|
||||
case 0x5C: case 0x5D: case 0x5E: case 0x5F:
|
||||
case 0x6C: case 0x6D: case 0x6E: case 0x6F:
|
||||
case 0x90: case 0x91: case 0x92: case 0x93:
|
||||
case 0x94: case 0x95: case 0x96: case 0x97:
|
||||
case 0x98: case 0x99: case 0x9B: case 0x9C:
|
||||
case 0x9D: case 0x9E: case 0x9F:
|
||||
case 0xA4: case 0xA5: case 0xA6: case 0xA7:
|
||||
case 0xAA: case 0xAB: case 0xAC: case 0xAD:
|
||||
case 0xAE: case 0xAF:
|
||||
case 0xC3: case 0xC9: case 0xCB: case 0xCC:
|
||||
case 0xCF:
|
||||
case 0xD7:
|
||||
case 0xEC: case 0xED: case 0xEE: case 0xEF:
|
||||
case 0xF4: case 0xF5: case 0xF8: case 0xF9:
|
||||
case 0xFA: case 0xFB: case 0xFC: case 0xFD:
|
||||
break;
|
||||
|
||||
case 0x62:
|
||||
case 0xC4: case 0xC5:
|
||||
#ifdef _WIN64
|
||||
return false;
|
||||
#else
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0x66:
|
||||
disasm_flag |= C_66;
|
||||
disasm_defdata = 2;
|
||||
goto RETRY;
|
||||
|
||||
case 0x67:
|
||||
disasm_flag |= C_67;
|
||||
disasm_defmem = 2;
|
||||
goto RETRY;
|
||||
|
||||
case 0x69:
|
||||
case 0x81:
|
||||
case 0xC1:
|
||||
disasm_flag |= C_MODRM;
|
||||
disasm_datasize += disasm_defdata;
|
||||
break;
|
||||
|
||||
case 0x6A:
|
||||
case 0x70: case 0x71: case 0x72: case 0x73:
|
||||
case 0x74: case 0x75: case 0x76: case 0x77:
|
||||
case 0x78: case 0x79: case 0x7A: case 0x7B:
|
||||
case 0x7C: case 0x7D: case 0x7E: case 0x7F:
|
||||
case 0xB0: case 0xB1: case 0xB2: case 0xB3:
|
||||
case 0xB4: case 0xB5: case 0xB6: case 0xB7:
|
||||
case 0xCD:
|
||||
case 0xE0: case 0xE1: case 0xE2: case 0xE3:
|
||||
case 0xE4: case 0xE5: case 0xE6: case 0xE7:
|
||||
disasm_datasize ++;
|
||||
break;
|
||||
|
||||
case 0xEB:
|
||||
info.cmdType = CT_JMP;
|
||||
disasm_offset = (DWORD) (opcode - pOpCode);
|
||||
disasm_datasize ++;
|
||||
break;
|
||||
|
||||
case 0x8F:
|
||||
if ((*opcode >> 3) & 7)
|
||||
return false;
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
|
||||
case 0x9A: case 0xEA:
|
||||
#ifdef _WIN64
|
||||
return false;
|
||||
#else
|
||||
disasm_datasize += (disasm_defdata + 2);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0x68:
|
||||
disasm_datasize += disasm_defdata;
|
||||
break;
|
||||
|
||||
case 0xB8: case 0xB9: case 0xBA: case 0xBB:
|
||||
case 0xBC: case 0xBD: case 0xBE: case 0xBF:
|
||||
#ifdef _WIN64
|
||||
if (!(disasm_flag & C_66) && (disasm_preffix & 8))
|
||||
disasm_datasize += 8;
|
||||
else
|
||||
#endif
|
||||
disasm_datasize += disasm_defdata;
|
||||
break;
|
||||
|
||||
|
||||
//case 0x68:
|
||||
//case 0xB8: case 0xB9: case 0xBA: case 0xBB:
|
||||
//case 0xBC: case 0xBD: case 0xBE: case 0xBF:
|
||||
// disasm_datasize += disasm_defdata;
|
||||
// break;
|
||||
|
||||
case 0xE8: case 0xE9:
|
||||
if (disasm_defdata == 2)
|
||||
return false;
|
||||
disasm_offset = (DWORD) (opcode - pOpCode);
|
||||
disasm_datasize += disasm_defdata;
|
||||
break;
|
||||
|
||||
case 0x6B:
|
||||
case 0x80: case 0x82: case 0x83:
|
||||
case 0xC0:
|
||||
disasm_flag |= C_MODRM;
|
||||
disasm_datasize ++;
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
disasm_datasize += 2;
|
||||
break;
|
||||
|
||||
case 0xC6: case 0xC7:
|
||||
if ((*opcode >> 3) & 7)
|
||||
return false;
|
||||
disasm_flag |= C_MODRM;
|
||||
if (disasm_opcode & 1)
|
||||
{
|
||||
disasm_datasize += disasm_defdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
disasm_datasize ++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
disasm_datasize += 3;
|
||||
break;
|
||||
|
||||
case 0xCA:
|
||||
disasm_datasize += 2;
|
||||
break;
|
||||
|
||||
case 0xD4: case 0xD5:
|
||||
#ifdef _WIN64
|
||||
return false;
|
||||
#else
|
||||
disasm_datasize ++;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0xF0:
|
||||
disasm_flag |= C_LOCK;
|
||||
goto RETRY;
|
||||
|
||||
case 0xF2: case 0xF3:
|
||||
disasm_flag |= C_REP;
|
||||
goto RETRY;
|
||||
|
||||
case 0xF6: case 0xF7:
|
||||
disasm_flag |= C_MODRM;
|
||||
if (((*opcode >> 3) & 7) < 2)
|
||||
{
|
||||
if (disasm_opcode & 1)
|
||||
{
|
||||
disasm_datasize += disasm_defdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
disasm_datasize ++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFE:
|
||||
if (((*opcode >> 3) & 7) > 1)
|
||||
return false;
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
if (((*opcode >> 3) & 7) == 7)
|
||||
return false;
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
|
||||
disasm_flag |= C_OPCODE2;
|
||||
disasm_opcode2 = *opcode ++;
|
||||
|
||||
switch (disasm_opcode2)
|
||||
{
|
||||
case 0x00: case 0x01: case 0x02: case 0x03:
|
||||
case 0x90: case 0x91: case 0x92: case 0x93:
|
||||
case 0x94: case 0x95: case 0x96: case 0x97:
|
||||
case 0x98: case 0x99: case 0x9A: case 0x9B:
|
||||
case 0x9C: case 0x9D: case 0x9E: case 0x9F:
|
||||
case 0xA3: case 0xA5: case 0xAB: case 0xAD:
|
||||
case 0xAF:
|
||||
case 0xB0: case 0xB1: case 0xB2: case 0xB3:
|
||||
case 0xB4: case 0xB5: case 0xB6: case 0xB7:
|
||||
case 0xBB:
|
||||
case 0xBC: case 0xBD: case 0xBE: case 0xBF:
|
||||
case 0xC0: case 0xC1:
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
case 0x08: case 0x09: case 0x0A: case 0x0B:
|
||||
case 0xA0: case 0xA1: case 0xA2: case 0xA8:
|
||||
case 0xA9: case 0xAA:
|
||||
case 0xC8: case 0xC9: case 0xCA: case 0xCB:
|
||||
case 0xCC: case 0xCD: case 0xCE: case 0xCF:
|
||||
break;
|
||||
|
||||
case 0x80: case 0x81: case 0x82: case 0x83:
|
||||
case 0x84: case 0x85: case 0x86: case 0x87:
|
||||
case 0x88: case 0x89: case 0x8A: case 0x8B:
|
||||
case 0x8C: case 0x8D: case 0x8E: case 0x8F:
|
||||
if (disasm_defdata == 2)
|
||||
return false;
|
||||
disasm_offset = (DWORD) (opcode - pOpCode);
|
||||
disasm_datasize += disasm_defdata;
|
||||
break;
|
||||
|
||||
case 0xA4: case 0xAC:
|
||||
case 0xBA:
|
||||
disasm_datasize ++;
|
||||
disasm_flag |= C_MODRM;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
if (disasm_flag & C_MODRM)
|
||||
{
|
||||
disasm_modrm = *opcode ++;
|
||||
mod = disasm_modrm & 0xC0;
|
||||
rm = disasm_modrm & 0x07;
|
||||
|
||||
if (mod != 0xC0)
|
||||
{
|
||||
if (mod == 0x40) disasm_memsize ++;
|
||||
if (mod == 0x80) disasm_memsize += disasm_defmem;
|
||||
|
||||
if (disasm_defmem == 2) // modrm16
|
||||
{
|
||||
if ((mod == 0x00) && (rm == 0x06))
|
||||
{
|
||||
disasm_memsize += 2;
|
||||
}
|
||||
}
|
||||
else // modrm32
|
||||
{
|
||||
if (rm == 0x04)
|
||||
{
|
||||
disasm_flag |= C_SIB;
|
||||
disasm_sib = *opcode ++;
|
||||
rm = disasm_sib & 0x07;
|
||||
}
|
||||
|
||||
if ((mod == 0x00) && (rm == 0x05))
|
||||
{
|
||||
|
||||
#ifdef _WIN64
|
||||
if (!(disasm_flag & C_SIB))
|
||||
disasm_offset = (DWORD) (opcode - pOpCode);
|
||||
#endif
|
||||
disasm_memsize += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info.dwSize =(DWORD) (opcode - pOpCode) + disasm_memsize + disasm_datasize;
|
||||
info.dwRelOffset = disasm_offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t MoveCode(byte *&pSrcOriginal, byte *pDst, size_t nNeedBytes)
|
||||
{
|
||||
size_t nBytes = 0;
|
||||
byte *pSrc = pSrcOriginal;
|
||||
sCommandInfo ii;
|
||||
while (nBytes < nNeedBytes)
|
||||
{
|
||||
if (!GetInstructionSize(pSrc, ii))
|
||||
return 0; // error
|
||||
if (nBytes == 0 && ii.cmdType == CT_JMP && ii.dwSize - ii.dwRelOffset == 1)
|
||||
{ // this is a short jump and we need to follow it
|
||||
ptrdiff_t offset = static_cast<char>(pSrc[ii.dwSize - 1]);
|
||||
pSrcOriginal += offset + ii.dwSize; // skip JMP XX
|
||||
pSrc = pSrcOriginal;
|
||||
continue;
|
||||
}
|
||||
memcpy(pDst, pSrc, ii.dwSize); // copy original bytes
|
||||
if (ii.dwRelOffset)
|
||||
*reinterpret_cast<int32_t*>(pDst + ii.dwRelOffset) = static_cast<int32_t>(pSrc + *reinterpret_cast<int32_t*>(pSrc + ii.dwRelOffset) - pDst);
|
||||
pSrc += ii.dwSize;
|
||||
pDst += ii.dwSize;
|
||||
nBytes += ii.dwSize;
|
||||
}
|
||||
return nBytes; // return number of bytes copied
|
||||
}
|
||||
|
||||
size_t HookedAPI::page_size_ = 0;
|
||||
|
||||
HookedAPI::HookedAPI()
|
||||
: size_(0), api_(NULL), old_handler_(NULL), crc_(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool HookedAPI::Hook(void *api, void *handler, void **result)
|
||||
{
|
||||
if (!page_size_) {
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
page_size_ = (system_info.dwPageSize > 2048) ? system_info.dwPageSize : 2048;
|
||||
}
|
||||
uint8_t *p = static_cast<uint8_t *>(api);
|
||||
|
||||
// alloc virtual memory
|
||||
#ifdef _WIN64
|
||||
for (size_t i = 0; i < 0x70000000; i += page_size_) {
|
||||
old_handler_ = ::VirtualAlloc(p + i, page_size_, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
if (old_handler_)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
old_handler_ = ::VirtualAlloc(NULL, page_size_, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#endif
|
||||
|
||||
if (!old_handler_)
|
||||
return false;
|
||||
|
||||
uint8_t *memory = static_cast<uint8_t *>(old_handler_);
|
||||
if (result)
|
||||
*result = memory;
|
||||
|
||||
// structure of the block:
|
||||
// some api commands
|
||||
// jmp api + 5
|
||||
// original commands
|
||||
// jmp [handler]
|
||||
// handler
|
||||
|
||||
// copy api code to the new place
|
||||
size_ = MoveCode(p, memory, 5);
|
||||
if (!size_)
|
||||
return false;
|
||||
|
||||
// add JMP command
|
||||
if (!PutJump(memory + size_, p + size_))
|
||||
return false;
|
||||
|
||||
// copy original commands
|
||||
memcpy(memory + size_ + 5, p, size_);
|
||||
|
||||
// jmp [handler]
|
||||
uint8_t *jump = memory + size_ * 2 + 5;
|
||||
if (!PutJumpMem(jump, jump + 6))
|
||||
return false;
|
||||
|
||||
// put handler to [handler]
|
||||
*(reinterpret_cast<void **>(jump + 6)) = handler;
|
||||
|
||||
// put JMP at the beginning of the API
|
||||
if (!PutJump(p, jump))
|
||||
return false;
|
||||
|
||||
api_ = p; // this line should be below MoveCode, because pAPI can be corrected by it
|
||||
crc_ = *reinterpret_cast<uint32_t *>(p + 1);
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(old_handler_, page_size_, PAGE_EXECUTE_READ, &old_protect);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HookedAPI::Unhook()
|
||||
{
|
||||
if (!api_)
|
||||
return;
|
||||
|
||||
// check CRC
|
||||
uint8_t *p = static_cast<uint8_t *>(api_);
|
||||
if (*p == 0xE9 && *reinterpret_cast<uint32_t *>(p + 1) == crc_) {
|
||||
// put original bytes back
|
||||
WriteProcessMemory(GetCurrentProcess(), api_, reinterpret_cast<uint8_t *>(old_handler_) + size_ + 5, size_, NULL);
|
||||
VirtualFree(old_handler_, 0, MEM_RELEASE);
|
||||
} else {
|
||||
// API hooked by another code
|
||||
WriteProcessMemory(GetCurrentProcess(), static_cast<uint8_t *>(old_handler_) + size_ * 2 + 5 + 6, &old_handler_, sizeof(old_handler_), NULL);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
size_ = 0;
|
||||
api_ = old_handler_ = NULL;
|
||||
}
|
||||
|
||||
#endif
|
40
runtime/hook_manager.h
Normal file
40
runtime/hook_manager.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef HOOK_MANAGER_H
|
||||
#define HOOK_MANAGER_H
|
||||
|
||||
class HookedAPI
|
||||
{
|
||||
public:
|
||||
HookedAPI();
|
||||
bool Hook(void *api, void *handler, void **result);
|
||||
void Unhook();
|
||||
void *old_handler() const { return old_handler_; }
|
||||
private:
|
||||
static size_t page_size_;
|
||||
size_t size_;
|
||||
void *api_;
|
||||
void *old_handler_;
|
||||
uint32_t crc_;
|
||||
};
|
||||
|
||||
class HookManager
|
||||
{
|
||||
public:
|
||||
HookManager();
|
||||
void Begin();
|
||||
void End();
|
||||
void *HookAPI(HMODULE dll, const char *api_name, void *handler, bool show_error = true, void **result = NULL);
|
||||
bool UnhookAPI(void * handler);
|
||||
private:
|
||||
HookManager(const HookManager &src);
|
||||
HookManager & operator = (const HookManager &);// block the assignment operator
|
||||
void GetThreads();
|
||||
void SuspendThreads();
|
||||
void ResumeThreads();
|
||||
void FreeThreads();
|
||||
|
||||
vector<HookedAPI *> api_list_;
|
||||
vector<HANDLE> thread_list_;
|
||||
size_t update_count_;
|
||||
};
|
||||
|
||||
#endif
|
688
runtime/hwid.cc
Normal file
688
runtime/hwid.cc
Normal file
@ -0,0 +1,688 @@
|
||||
#include "common.h"
|
||||
#include "objects.h"
|
||||
#include "utils.h"
|
||||
#include "hwid.h"
|
||||
#include "core.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#ifdef __unix__
|
||||
#include <mntent.h>
|
||||
#include <dirent.h>
|
||||
#include <net/if.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#ifdef VMP_GNU
|
||||
EXPORT_API int WINAPI ExportedGetCurrentHWID(char *buffer, int size) __asm__ ("ExportedGetCurrentHWID");
|
||||
#endif
|
||||
#ifdef WIN_DRIVER
|
||||
#include <ntddndis.h>
|
||||
extern "C" {
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ZwCreateEvent (
|
||||
PHANDLE EventHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
EVENT_TYPE EventType,
|
||||
BOOLEAN InitialState
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ZwWaitForSingleObject(
|
||||
HANDLE Handle,
|
||||
BOOLEAN Alertable,
|
||||
PLARGE_INTEGER Timeout
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
int WINAPI ExportedGetCurrentHWID(char *buffer, int size)
|
||||
{
|
||||
HardwareID *hardware_id = Core::Instance()->hardware_id();
|
||||
return hardware_id ? hardware_id->GetCurrent(buffer, size) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* HardwareID
|
||||
*/
|
||||
|
||||
#ifdef WIN_DRIVER
|
||||
bool GetRegValue(LPCWSTR reg_path, LPCWSTR value_name, LPWSTR buffer, size_t *size)
|
||||
{
|
||||
UNICODE_STRING unicode_reg_path, unicode_value_name;
|
||||
OBJECT_ATTRIBUTES object_attributes;
|
||||
NTSTATUS status;
|
||||
HANDLE key_handle;
|
||||
ULONG information_size;
|
||||
KEY_VALUE_PARTIAL_INFORMATION *information;
|
||||
bool res = false;
|
||||
|
||||
RtlInitUnicodeString(&unicode_reg_path, reg_path);
|
||||
RtlInitUnicodeString(&unicode_value_name, value_name);
|
||||
InitializeObjectAttributes(&object_attributes, &unicode_reg_path, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
status = ZwOpenKey(&key_handle, KEY_QUERY_VALUE, &object_attributes);
|
||||
if (NT_SUCCESS(status)) {
|
||||
information_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH * sizeof(WCHAR);
|
||||
information = reinterpret_cast<KEY_VALUE_PARTIAL_INFORMATION*>(new uint8_t[information_size]);
|
||||
status = ZwQueryValueKey(key_handle, &unicode_value_name, KeyValuePartialInformation, information, information_size, &information_size);
|
||||
if (NT_SUCCESS(status)) {
|
||||
size_t len = information->DataLength / sizeof(wchar_t);
|
||||
if (*size < len + 1) {
|
||||
*size = len + 1;
|
||||
} else {
|
||||
RtlCopyMemory(buffer, information->Data, information->DataLength);
|
||||
buffer[len] = 0;
|
||||
*size = wcslen(buffer);
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
delete [] information;
|
||||
ZwClose(key_handle);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
HardwareID::HardwareID()
|
||||
: block_count_(0), start_block_(0)
|
||||
{
|
||||
uint64_t timestamp = __rdtsc(); // exactly 8 bytes
|
||||
timestamp ^= ~timestamp << 32; // remove zeroes at the beginning
|
||||
blocks_ = new CryptoContainer(sizeof(uint32_t) * MAX_BLOCKS, reinterpret_cast<uint8_t *>(×tamp));
|
||||
|
||||
// old methods
|
||||
GetCPU(0);
|
||||
GetCPU(1);
|
||||
start_block_ = block_count_;
|
||||
// new methods, we'll return HWID starting from this DWORD
|
||||
GetCPU(2);
|
||||
GetMachineName();
|
||||
GetHDD();
|
||||
GetMacAddresses();
|
||||
}
|
||||
|
||||
HardwareID::~HardwareID()
|
||||
{
|
||||
delete blocks_;
|
||||
}
|
||||
|
||||
void HardwareID::AddBlock(const void *p, size_t size, BlockType type)
|
||||
{
|
||||
if (block_count_ == MAX_BLOCKS) return; // no free space
|
||||
|
||||
SHA1 hash;
|
||||
hash.Input(reinterpret_cast<const uint8_t *>(p), size);
|
||||
uint32_t block = __builtin_bswap32(*reinterpret_cast<const uint32_t *>(hash.Result()));
|
||||
|
||||
block &= ~TYPE_MASK; // zero two lower bits
|
||||
block |= type & TYPE_MASK; // set type bits
|
||||
|
||||
// check existing blocks
|
||||
for (size_t i = block_count_; i > start_block_; i--) {
|
||||
uint32_t prev_block = blocks_->GetDWord((i - 1) * sizeof(uint32_t));
|
||||
if (prev_block == block)
|
||||
return;
|
||||
if ((prev_block & TYPE_MASK) != (block & TYPE_MASK))
|
||||
break;
|
||||
}
|
||||
|
||||
blocks_->SetDWord(block_count_ * sizeof(uint32_t), block);
|
||||
block_count_++;
|
||||
}
|
||||
|
||||
void HardwareID::GetCPU(uint8_t method)
|
||||
{
|
||||
uint32_t old_block_count = block_count_;
|
||||
|
||||
#ifdef WIN_DRIVER
|
||||
KAFFINITY system_mask = KeQueryActiveProcessors();
|
||||
KAFFINITY mask = 1;
|
||||
#endif
|
||||
#ifdef VMP_GNU
|
||||
// set process affinity mask to system affinity mask
|
||||
#ifdef __APPLE__
|
||||
//FIXME
|
||||
if (0) {
|
||||
#else
|
||||
cpu_set_t process_mask, system_mask;
|
||||
memset(&system_mask, 0xFF, sizeof(system_mask));
|
||||
if (0 == sched_getaffinity(0, sizeof(process_mask), &process_mask)) {
|
||||
sched_setaffinity(0, sizeof(system_mask), &system_mask); //try all CPUs, will set MAX CPUs
|
||||
sched_getaffinity(0, sizeof(system_mask), &system_mask); //get MAX CPUs
|
||||
#endif
|
||||
#else
|
||||
#ifndef WIN_DRIVER
|
||||
DWORD_PTR process_mask, system_mask;
|
||||
HANDLE process = GetCurrentProcess();
|
||||
if (GetProcessAffinityMask(process, &process_mask, &system_mask)) {
|
||||
if (process_mask != system_mask)
|
||||
SetProcessAffinityMask(process, system_mask);
|
||||
DWORD_PTR mask = 1;
|
||||
HANDLE thread = GetCurrentThread();
|
||||
#endif
|
||||
#endif
|
||||
#ifdef VMP_GNU
|
||||
// set thread affinity mask to mask
|
||||
#ifdef __APPLE__
|
||||
//FIXME
|
||||
while (false) {
|
||||
if (false) {
|
||||
#else
|
||||
for (size_t i = 0; i < sizeof(system_mask) * 8; i++) {
|
||||
if (__CPU_ISSET_S(i, sizeof(system_mask), &system_mask)) {
|
||||
cpu_set_t mask;
|
||||
__CPU_ZERO_S(sizeof(mask), &mask);
|
||||
__CPU_SET_S(i, sizeof(mask), &mask);
|
||||
sched_setaffinity(0, sizeof(mask), &mask);
|
||||
#endif
|
||||
#else
|
||||
for (size_t i = 0; i < sizeof(mask) * 8; i++) {
|
||||
if (system_mask & mask) {
|
||||
#ifdef WIN_DRIVER
|
||||
KeSetSystemAffinityThread(mask);
|
||||
#else
|
||||
DWORD_PTR old_mask = SetThreadAffinityMask(thread, mask);
|
||||
Sleep(0);
|
||||
#endif
|
||||
#endif
|
||||
ProcessCPU(method);
|
||||
#ifdef VMP_GNU
|
||||
// set thread affinity mask back to old_mask
|
||||
#ifdef __APPLE__
|
||||
//FIXME
|
||||
#else
|
||||
//do nothing
|
||||
#endif
|
||||
#else
|
||||
#ifdef WIN_DRIVER
|
||||
KeRevertToUserAffinityThread();
|
||||
#else
|
||||
SetThreadAffinityMask(thread, old_mask);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#ifndef VMP_GNU
|
||||
mask <<= 1;
|
||||
#endif
|
||||
}
|
||||
#ifndef WIN_DRIVER
|
||||
#ifdef VMP_GNU
|
||||
// set process affinity mask back to process_mask
|
||||
#ifdef __APPLE__
|
||||
//FIXME
|
||||
#else
|
||||
sched_setaffinity(0, sizeof(process_mask), &process_mask);
|
||||
#endif
|
||||
#else
|
||||
if (process_mask != system_mask)
|
||||
SetProcessAffinityMask(process, process_mask);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (old_block_count == block_count_)
|
||||
ProcessCPU(method);
|
||||
}
|
||||
|
||||
void HardwareID::ProcessCPU(uint8_t method)
|
||||
{
|
||||
int info[4];
|
||||
__cpuid(info, 1);
|
||||
if ((info[0] & 0xFF0) == 0xFE0)
|
||||
info[0] ^= 0x20; // fix Athlon bug
|
||||
info[1] &= 0x00FFFFFF; // mask out APIC Physical ID
|
||||
|
||||
if (method == 2) {
|
||||
info[2] = 0;
|
||||
} else if (method == 1) {
|
||||
info[2] &= ~(1 << 27);
|
||||
}
|
||||
|
||||
AddBlock(info, sizeof(info), BLOCK_CPU);
|
||||
}
|
||||
|
||||
void HardwareID::GetMachineName()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
CFStringRef computer_name = SCDynamicStoreCopyComputerName(NULL, NULL);
|
||||
if (!computer_name)
|
||||
return;
|
||||
|
||||
CFIndex len = CFStringGetLength(computer_name);
|
||||
CFIndex size = CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
|
||||
char *buf = new char[size];
|
||||
if (CFStringGetCString(computer_name, buf, size, kCFStringEncodingUTF8))
|
||||
AddBlock(buf, strlen(buf), BLOCK_HOST);
|
||||
delete [] buf;
|
||||
CFRelease(computer_name);
|
||||
#elif defined(__unix__)
|
||||
char buf[HOST_NAME_MAX+1] = {0};
|
||||
if (0 == gethostname(buf, HOST_NAME_MAX))
|
||||
AddBlock(buf, strlen(buf), BLOCK_HOST);
|
||||
#elif defined(WIN_DRIVER)
|
||||
#define MAX_COMPUTERNAME_LENGTH 31
|
||||
|
||||
wchar_t buf[MAX_COMPUTERNAME_LENGTH + 1];
|
||||
size_t size = _countof(buf);
|
||||
|
||||
if (GetRegValue(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName", L"ComputerName", buf, &size) ||
|
||||
GetRegValue(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName", L"ComputerName", buf, &size)) {
|
||||
AddBlock(buf, size * sizeof(wchar_t), BLOCK_HOST);
|
||||
}
|
||||
#else
|
||||
HMODULE dll = LoadLibraryA(VMProtectDecryptStringA("kernel32.dll"));
|
||||
if (!dll)
|
||||
return;
|
||||
|
||||
typedef ULONG (WINAPI *GET_COMPUTER_NAME) (wchar_t *, uint32_t *);
|
||||
GET_COMPUTER_NAME get_computer_name = reinterpret_cast<GET_COMPUTER_NAME>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetComputerNameW")));
|
||||
|
||||
if (get_computer_name) {
|
||||
wchar_t buf[MAX_COMPUTERNAME_LENGTH + 1];
|
||||
uint32_t size = _countof(buf);
|
||||
|
||||
if (get_computer_name(buf, &size))
|
||||
AddBlock(buf, size * sizeof(wchar_t), BLOCK_HOST);
|
||||
}
|
||||
|
||||
FreeLibrary(dll);
|
||||
#endif
|
||||
}
|
||||
|
||||
void HardwareID::ProcessMAC(const uint8_t *p, size_t size)
|
||||
{
|
||||
// this big IF construction allows to put constants to the code, not to the data segment
|
||||
// it is harder to find them in the code after virtualisation
|
||||
uint32_t dw = (p[0] << 16) + (p[1] << 8) + p[2];
|
||||
if (dw == 0x000569 || dw == 0x000C29 || dw == 0x001C14 || dw == 0x005056 || // vmware
|
||||
dw == 0x0003FF || dw == 0x000D3A || dw == 0x00125A || dw == 0x00155D || dw == 0x0017FA || dw == 0x001DD8 || dw == 0x002248 || dw == 0x0025AE || dw == 0x0050F2 || // microsoft
|
||||
dw == 0x001C42 || // parallels
|
||||
dw == 0x0021F6) // virtual iron
|
||||
return;
|
||||
|
||||
AddBlock(p, size, BLOCK_MAC);
|
||||
}
|
||||
|
||||
void HardwareID::GetMacAddresses()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
ifaddrs *addrs;
|
||||
if (getifaddrs(&addrs) == 0) {
|
||||
uint32_t block_count_no_mac = block_count_;
|
||||
const uint8_t *mac = NULL;
|
||||
size_t size = 0;
|
||||
for (ifaddrs *cur_addr = addrs; cur_addr != 0; cur_addr = cur_addr->ifa_next) {
|
||||
if (cur_addr->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
|
||||
const sockaddr_dl *dl_addr = reinterpret_cast<const sockaddr_dl *>(cur_addr->ifa_addr);
|
||||
if (dl_addr->sdl_type == IFT_ETHER) {
|
||||
mac = reinterpret_cast<const uint8_t *>(&dl_addr->sdl_data[dl_addr->sdl_nlen]);
|
||||
size = dl_addr->sdl_alen;
|
||||
ProcessMAC(mac, size);
|
||||
}
|
||||
}
|
||||
if (block_count_no_mac == block_count_ && mac && size)
|
||||
AddBlock(mac, size, BLOCK_MAC);
|
||||
freeifaddrs(addrs);
|
||||
}
|
||||
#elif defined(__unix__)
|
||||
std::string dir_name("/sys/class/net/");
|
||||
if (DIR *dir = opendir(dir_name.c_str())) {
|
||||
uint32_t block_count_no_mac = block_count_;
|
||||
uint8_t mac[6];
|
||||
size_t size = 0;
|
||||
while (struct dirent *entry = readdir(dir)) {
|
||||
// skip "." and ".."
|
||||
if (entry->d_name[0] == '.') {
|
||||
if (entry->d_name[1] == 0 || (entry->d_name[1] == '.' && entry->d_name[2] == 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
struct stat st;
|
||||
if (fstatat(dirfd(dir), entry->d_name, &st, 0) >= 0 && S_ISDIR(st.st_mode)) {
|
||||
std::string file_name = dir_name + entry->d_name + "/address";
|
||||
if (FILE *faddr = fopen(file_name.c_str(), "r")) {
|
||||
char addr[18] = {0};
|
||||
if (fgets(addr, sizeof(addr) - 1, faddr)) {
|
||||
uint8_t m[6];
|
||||
size_t c = sscanf_s(addr, "%02hx:%02hx:%02hx:%02hx:%02hx:%02hx",
|
||||
m+0, m+1, m+2, m+3, m+4, m+5);
|
||||
if (c == 6 && m[0]+m[1]+m[2]+m[3]+m[4]+m[5] != 0) {
|
||||
memcpy(mac, m, sizeof(mac));
|
||||
size = c;
|
||||
ProcessMAC(mac, size);
|
||||
}
|
||||
}
|
||||
fclose(faddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
if (block_count_no_mac == block_count_ && size)
|
||||
AddBlock(mac, size, BLOCK_MAC);
|
||||
}
|
||||
#elif defined(WIN_DRIVER)
|
||||
UNICODE_STRING unicode_string;
|
||||
OBJECT_ATTRIBUTES object_attributes;
|
||||
NTSTATUS status;
|
||||
HANDLE key_handle, file_handle, event_handle;
|
||||
IO_STATUS_BLOCK status_block;
|
||||
ULONG code = OID_802_3_CURRENT_ADDRESS;
|
||||
uint8_t mac[6];
|
||||
size_t size = 0;
|
||||
|
||||
InitializeObjectAttributes(&object_attributes, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
status = ZwCreateEvent(&event_handle, EVENT_ALL_ACCESS, &object_attributes, NotificationEvent, FALSE);
|
||||
if (!NT_SUCCESS(status))
|
||||
return;
|
||||
|
||||
RtlInitUnicodeString(&unicode_string, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters");
|
||||
InitializeObjectAttributes(&object_attributes, &unicode_string, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
status = ZwOpenKey(&key_handle, GENERIC_READ, &object_attributes);
|
||||
if (NT_SUCCESS(status)) {
|
||||
uint32_t block_count_no_mac = block_count_;
|
||||
ULONG sub_key_size = sizeof(KEY_BASIC_INFORMATION) + sizeof(wchar_t) * MAX_PATH;
|
||||
KEY_BASIC_INFORMATION *sub_key_value = static_cast<KEY_BASIC_INFORMATION *>(ExAllocatePool(PagedPool, sub_key_size));
|
||||
wchar_t *service_name = static_cast<wchar_t *>(ExAllocatePool(PagedPool, sizeof(wchar_t) * MAX_PATH));
|
||||
|
||||
ULONG ret_size;
|
||||
for (ULONG i = 0; NT_SUCCESS(ZwEnumerateKey(key_handle, i, KeyBasicInformation, sub_key_value, sub_key_size, &ret_size)); i++) {
|
||||
if (sub_key_value->NameLength > (MAX_PATH - 10) * sizeof(wchar_t))
|
||||
continue;
|
||||
|
||||
if (sub_key_value->NameLength == 18 && _wcsnicmp(sub_key_value->Name, L"NdisWanIp", 9) == 0)
|
||||
continue;
|
||||
|
||||
RtlZeroMemory(service_name, sizeof(wchar_t) * MAX_PATH);
|
||||
#if WDK_NTDDI_VERSION > NTDDI_WIN7
|
||||
wcscat_s(service_name, MAX_PATH, L"\\??\\");
|
||||
#else
|
||||
wcscat(service_name, L"\\??\\");
|
||||
#endif
|
||||
RtlCopyMemory(service_name + wcslen(service_name), sub_key_value->Name, sub_key_value->NameLength);
|
||||
RtlInitUnicodeString(&unicode_string, service_name);
|
||||
InitializeObjectAttributes(&object_attributes, &unicode_string, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
status = ZwOpenFile(&file_handle, 0, &object_attributes, &status_block, FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
|
||||
if (NT_SUCCESS(status)) {
|
||||
status = ZwDeviceIoControlFile(file_handle, event_handle, 0, 0, &status_block, IOCTL_NDIS_QUERY_GLOBAL_STATS, &code, sizeof(code), mac, sizeof(mac));
|
||||
if (status == STATUS_PENDING)
|
||||
status = ZwWaitForSingleObject(event_handle, FALSE, NULL);
|
||||
if (NT_SUCCESS(status)) {
|
||||
size = sizeof(mac);
|
||||
ProcessMAC(mac, size);
|
||||
}
|
||||
ZwClose(file_handle);
|
||||
}
|
||||
}
|
||||
ExFreePool(service_name);
|
||||
ExFreePool(sub_key_value);
|
||||
ZwClose(key_handle);
|
||||
|
||||
if (block_count_no_mac == block_count_ && size)
|
||||
AddBlock(mac, size, BLOCK_MAC);
|
||||
}
|
||||
ZwClose(event_handle);
|
||||
|
||||
#else
|
||||
HMODULE dll = LoadLibraryA(VMProtectDecryptStringA("iphlpapi.dll"));
|
||||
if (!dll)
|
||||
return;
|
||||
|
||||
typedef ULONG (WINAPI *GET_ADAPTERS_INFO) (PIP_ADAPTER_INFO AdapterInfo, PULONG SizePointer);
|
||||
GET_ADAPTERS_INFO get_adapters_info = reinterpret_cast<GET_ADAPTERS_INFO>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetAdaptersInfo")));
|
||||
|
||||
if (get_adapters_info) {
|
||||
ULONG buf_len = 0;
|
||||
if (ERROR_BUFFER_OVERFLOW == get_adapters_info(NULL, &buf_len)) {
|
||||
uint32_t block_count_no_mac = block_count_;
|
||||
const uint8_t *mac = NULL;
|
||||
size_t size = 0;
|
||||
uint8_t *info = new uint8_t[buf_len];
|
||||
if (ERROR_SUCCESS == get_adapters_info(reinterpret_cast<IP_ADAPTER_INFO *>(info), &buf_len)) {
|
||||
for (IP_ADAPTER_INFO *adapter_info = reinterpret_cast<IP_ADAPTER_INFO *>(info); adapter_info != 0; adapter_info = adapter_info->Next) {
|
||||
mac = adapter_info->Address;
|
||||
size = adapter_info->AddressLength;
|
||||
ProcessMAC(mac, size);
|
||||
}
|
||||
}
|
||||
if (block_count_no_mac == block_count_ && mac && size)
|
||||
AddBlock(mac, size, BLOCK_MAC);
|
||||
delete [] info;
|
||||
}
|
||||
}
|
||||
FreeLibrary(dll);
|
||||
#endif
|
||||
}
|
||||
|
||||
void HardwareID::GetHDD()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
DASessionRef session = DASessionCreate(NULL);
|
||||
if (session) {
|
||||
struct statfs statFS;
|
||||
statfs ("/", &statFS);
|
||||
DADiskRef disk = DADiskCreateFromBSDName(NULL, session, statFS.f_mntfromname);
|
||||
if (disk) {
|
||||
CFDictionaryRef descDict = DADiskCopyDescription(disk);
|
||||
if (descDict) {
|
||||
CFUUIDRef value = (CFUUIDRef)CFDictionaryGetValue(descDict, CFSTR("DAVolumeUUID"));
|
||||
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(value);
|
||||
AddBlock(&bytes, sizeof(bytes), BLOCK_HDD);
|
||||
CFRelease(descDict);
|
||||
}
|
||||
CFRelease(disk);
|
||||
}
|
||||
CFRelease(session);
|
||||
}
|
||||
#elif defined(__unix__)
|
||||
std::string root_uuid;
|
||||
if (FILE *mtab = setmntent("/etc/mtab", "r")) {
|
||||
std::string root_fs_path;
|
||||
while (struct mntent *entry = getmntent(mtab)) {
|
||||
if (entry->mnt_dir[0] == '/' && entry->mnt_dir[1] == 0) {
|
||||
root_fs_path = entry->mnt_fsname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
endmntent(mtab);
|
||||
|
||||
if (!root_fs_path.empty()) {
|
||||
std::string dir_name("/dev/disk/by-uuid/");
|
||||
if (DIR *dir = opendir(dir_name.c_str())) {
|
||||
while (struct dirent *entry = readdir(dir)) {
|
||||
// skip "." and ".."
|
||||
if (entry->d_name[0] == '.') {
|
||||
if (entry->d_name[1] == 0 || (entry->d_name[1] == '.' && entry->d_name[2] == 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
char resolved_link_path[PATH_MAX];
|
||||
std::string path = dir_name + entry->d_name;
|
||||
if (realpath(path.c_str(), resolved_link_path)) {
|
||||
if (strcmp(resolved_link_path, root_fs_path.c_str()) == 0) {
|
||||
root_uuid = entry->d_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!root_uuid.empty())
|
||||
AddBlock(root_uuid.c_str(), root_uuid.size(), BLOCK_HDD);
|
||||
#elif defined(WIN_DRIVER)
|
||||
wchar_t buf[MAX_PATH];
|
||||
size_t size = _countof(buf);
|
||||
UNICODE_STRING unicode_string;
|
||||
OBJECT_ATTRIBUTES object_attributes;
|
||||
NTSTATUS status;
|
||||
HANDLE handle;
|
||||
IO_STATUS_BLOCK status_block;
|
||||
|
||||
if (!GetRegValue(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion", L"SystemRoot", buf, &size))
|
||||
return;
|
||||
|
||||
if (buf[1] == ':' && buf[2] == '\\') {
|
||||
wchar_t system_drive[] = {'\\', 'D', 'o', 's', 'D', 'e', 'v', 'i', 'c', 'e', 's', '\\', buf[0], ':', '\\', 0};
|
||||
|
||||
RtlInitUnicodeString(&unicode_string, system_drive);
|
||||
InitializeObjectAttributes(&object_attributes, &unicode_string, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
status = ZwCreateFile(&handle, SYNCHRONIZE | FILE_READ_ACCESS,
|
||||
&object_attributes,
|
||||
&status_block,
|
||||
NULL,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0);
|
||||
if (NT_SUCCESS(status)) {
|
||||
RtlInitUnicodeString(&unicode_string, L"ZwQueryVolumeInformationFile");
|
||||
typedef NTSTATUS (NTAPI *QUERY_VOLUME_INFORMATION_FILE) (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS);
|
||||
QUERY_VOLUME_INFORMATION_FILE query_volume_information_file = reinterpret_cast<QUERY_VOLUME_INFORMATION_FILE>(MmGetSystemRoutineAddress(&unicode_string));
|
||||
if (query_volume_information_file) {
|
||||
ULONG size = sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
|
||||
FILE_FS_VOLUME_INFORMATION *information = reinterpret_cast<FILE_FS_VOLUME_INFORMATION*>(new uint8_t[size]);
|
||||
status = query_volume_information_file(handle, &status_block, information, size, FileFsVolumeInformation);
|
||||
if (NT_SUCCESS(status))
|
||||
AddBlock(&information->VolumeSerialNumber, sizeof(information->VolumeSerialNumber), BLOCK_HDD);
|
||||
delete [] information;
|
||||
}
|
||||
ZwClose(handle);
|
||||
}
|
||||
}
|
||||
#else
|
||||
HMODULE dll = LoadLibraryA(VMProtectDecryptStringA("kernel32.dll"));
|
||||
if (!dll)
|
||||
return;
|
||||
|
||||
typedef ULONG (WINAPI *GET_WINDOWS_DIRECTORY) (wchar_t *, DWORD);
|
||||
GET_WINDOWS_DIRECTORY get_windows_directory = reinterpret_cast<GET_WINDOWS_DIRECTORY>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetWindowsDirectoryW")));
|
||||
typedef BOOL (WINAPI *GET_VOLUME_INFORMATION) (const wchar_t *, wchar_t *, DWORD, DWORD *, DWORD *, DWORD *, wchar_t *, DWORD);
|
||||
GET_VOLUME_INFORMATION get_volume_information = reinterpret_cast<GET_VOLUME_INFORMATION>(InternalGetProcAddress(dll, VMProtectDecryptStringA("GetVolumeInformationW")));
|
||||
|
||||
if (get_windows_directory && get_volume_information) {
|
||||
wchar_t buf[MAX_PATH] = {0};
|
||||
UINT ures = get_windows_directory(buf, _countof(buf));
|
||||
if (ures > 0 && buf[1] == ':' && buf[2] == '\\') {
|
||||
buf[3] = 0;
|
||||
DWORD volumeSerialNumber = 0;
|
||||
if (get_volume_information(buf, NULL, 0, &volumeSerialNumber, NULL, NULL, NULL, 0)) {
|
||||
AddBlock(&volumeSerialNumber, sizeof(volumeSerialNumber), BLOCK_HDD);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeLibrary(dll);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t HardwareID::Copy(void *dest, size_t size) const
|
||||
{
|
||||
uint32_t *p = reinterpret_cast<uint32_t *>(dest);
|
||||
// need skip old methods
|
||||
size_t res = std::min(static_cast<size_t>(block_count_ - start_block_), size / sizeof(uint32_t));
|
||||
for (size_t i = 0; i < res; i++) {
|
||||
p[i] = blocks_->GetDWord((start_block_ + i) * sizeof(uint32_t));
|
||||
}
|
||||
return res * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
/*
|
||||
Rules:
|
||||
1. if pointer to buffer is NULL, second parameter is ignored and returned size of buffer that will fit HWID (with trailing 0)
|
||||
2. if buffer is ok and the second parameters is zero, we should return zero and doesn't change the buffer
|
||||
3. if buffer is OK and the second parameter is less than we need, we should return as much bytes as we can and return the second parameter itself
|
||||
and we should put 0 to the last available position at buffer
|
||||
4. if buffer is bigger that we need, we should put HWID, trailing 0 and return strlen(hwid) + 1
|
||||
*/
|
||||
|
||||
int HardwareID::GetCurrent(char *buffer, int size)
|
||||
{
|
||||
if (buffer && size == 0)
|
||||
return 0; // see rule #2
|
||||
|
||||
uint8_t b[MAX_BLOCKS *sizeof(uint32_t)];
|
||||
size_t hwid_size = Copy(b, sizeof(b));
|
||||
size_t need_size = Base64EncodeGetRequiredLength(hwid_size);
|
||||
char *p = new char[need_size + 1];
|
||||
Base64Encode(b, hwid_size, p, need_size); // it never should return false
|
||||
|
||||
size_t copy = 0;
|
||||
if (buffer) {
|
||||
// if nSize is less, we have to leave space for trailing zero (see rule #3)
|
||||
// if nNeedSize is less, we already have this space, as we allocated nNeedSize + 1 bytes
|
||||
copy = std::min(static_cast<size_t>(size - 1), need_size);
|
||||
for (size_t i = 0; i < copy; i++) {
|
||||
buffer[i] = p[i];
|
||||
}
|
||||
buffer[copy++] = 0;
|
||||
}
|
||||
else {
|
||||
// see rule #1
|
||||
copy = need_size + 1;
|
||||
}
|
||||
|
||||
delete [] p;
|
||||
return static_cast<int>(copy);
|
||||
}
|
||||
|
||||
bool HardwareID::IsCorrect(uint8_t *p, size_t size) const
|
||||
{
|
||||
if (p == 0 || size == 0 || (size & 3))
|
||||
return false;
|
||||
|
||||
bool equals[4];
|
||||
bool found[4];
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
equals[i] = false;
|
||||
found[i] = false;
|
||||
}
|
||||
|
||||
size_t blocks = size / sizeof(uint32_t);
|
||||
uint32_t *d = reinterpret_cast<uint32_t *>(p);
|
||||
for (size_t j = 0; j < block_count_; j++) {
|
||||
uint32_t id1 = blocks_->GetDWord(j * sizeof(uint32_t));
|
||||
found[id1 & 3] = true;
|
||||
for (size_t i = 0; i < blocks; i++) {
|
||||
uint32_t id2 = d[i];
|
||||
if (id1 == id2) {
|
||||
equals[id1 & 3] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check CPU
|
||||
if (!equals[0])
|
||||
return false;
|
||||
|
||||
// check if at least 3 items are OK
|
||||
size_t n = 0;
|
||||
size_t c = 0;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
if (found[i])
|
||||
c++;
|
||||
if (equals[i])
|
||||
n++;
|
||||
}
|
||||
return (n == c || n >= 3);
|
||||
}
|
||||
|
||||
bool HardwareID::IsCorrect(CryptoContainer &cont, size_t offset, size_t size) const
|
||||
{
|
||||
if (size == 0 || (size & 3) || size > MAX_BLOCKS * sizeof(uint32_t))
|
||||
return false;
|
||||
|
||||
uint32_t buff[MAX_BLOCKS];
|
||||
for (size_t i = 0; i < size / sizeof(uint32_t); i++) {
|
||||
buff[i] = cont.GetDWord(offset + i * sizeof(uint32_t));
|
||||
}
|
||||
return IsCorrect(reinterpret_cast<uint8_t *>(buff), size);
|
||||
}
|
45
runtime/hwid.h
Normal file
45
runtime/hwid.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef HWID_H
|
||||
#define HWID_H
|
||||
|
||||
class CryptoContainer;
|
||||
|
||||
class HardwareID
|
||||
{
|
||||
public:
|
||||
HardwareID();
|
||||
~HardwareID();
|
||||
|
||||
size_t Copy(void *dest, size_t size) const;
|
||||
int GetCurrent(char *buffer, int size);
|
||||
bool IsCorrect(uint8_t *p, size_t s) const;
|
||||
bool IsCorrect(CryptoContainer &cont, size_t offset, size_t size) const;
|
||||
private:
|
||||
enum {
|
||||
MAX_BLOCKS = 16,
|
||||
TYPE_MASK = 3
|
||||
};
|
||||
enum BlockType {
|
||||
BLOCK_CPU,
|
||||
BLOCK_HOST,
|
||||
BLOCK_MAC,
|
||||
BLOCK_HDD,
|
||||
};
|
||||
uint32_t block_count_;
|
||||
uint32_t start_block_;
|
||||
CryptoContainer *blocks_;
|
||||
|
||||
void AddBlock(const void *p, size_t size, BlockType type);
|
||||
void ProcessMAC(const uint8_t *p, size_t size);
|
||||
void ProcessCPU(uint8_t method);
|
||||
|
||||
void GetCPU(uint8_t method);
|
||||
void GetMacAddresses();
|
||||
void GetMachineName();
|
||||
void GetHDD();
|
||||
|
||||
// no copy ctr or assignment op
|
||||
HardwareID(const HardwareID &);
|
||||
HardwareID &operator =(const HardwareID &);
|
||||
};
|
||||
|
||||
#endif
|
1135
runtime/licensing_manager.cc
Normal file
1135
runtime/licensing_manager.cc
Normal file
File diff suppressed because it is too large
Load Diff
100
runtime/licensing_manager.h
Normal file
100
runtime/licensing_manager.h
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef LICENSING_MANAGER_H
|
||||
#define LICENSING_MANAGER_H
|
||||
|
||||
class CryptoContainer;
|
||||
|
||||
class LicensingManager
|
||||
{
|
||||
public:
|
||||
LicensingManager(uint8_t *data, uint32_t size, uint8_t *key);
|
||||
~LicensingManager();
|
||||
int SetSerialNumber(const char *serial);
|
||||
int GetSerialNumberState();
|
||||
bool GetSerialNumberData(VMProtectSerialNumberData *data, int size);
|
||||
int ActivateLicense(const char *code, char *serial, int size) const;
|
||||
int DeactivateLicense(const char *serial) const;
|
||||
int GetOfflineActivationString(const char *code, char *buf, int size) const;
|
||||
int GetOfflineDeactivationString(const char *serial, char *buf, int size) const;
|
||||
void DecryptBuffer(uint8_t *buffer);
|
||||
static uint32_t GetCurrentDate();
|
||||
private:
|
||||
enum ChunkType
|
||||
{
|
||||
SERIAL_CHUNK_VERSION = 0x01, // 1 byte of data - version
|
||||
SERIAL_CHUNK_USER_NAME = 0x02, // 1 + N bytes - length + N bytes of customer's name (without enging \0).
|
||||
SERIAL_CHUNK_EMAIL = 0x03, // 1 + N bytes - length + N bytes of customer's email (without ending \0).
|
||||
SERIAL_CHUNK_HWID = 0x04, // 1 + N bytes - length + N bytes of hardware id (N % 4 == 0)
|
||||
SERIAL_CHUNK_EXP_DATE = 0x05, // 4 bytes - (year << 16) + (month << 8) + (day)
|
||||
SERIAL_CHUNK_RUNNING_TIME_LIMIT = 0x06, // 1 byte - number of minutes
|
||||
SERIAL_CHUNK_PRODUCT_CODE = 0x07, // 8 bytes - used for decrypting some parts of exe-file
|
||||
SERIAL_CHUNK_USER_DATA = 0x08, // 1 + N bytes - length + N bytes of user data
|
||||
SERIAL_CHUNK_MAX_BUILD = 0x09, // 4 bytes - (year << 16) + (month << 8) + (day)
|
||||
SERIAL_CHUNK_END = 0xFF // 4 bytes - checksum: the first four bytes of sha-1 hash from the data before that chunk
|
||||
};
|
||||
|
||||
int save_state(int state);
|
||||
int ParseSerial(VMProtectSerialNumberData *data);
|
||||
bool CheckLicenseDataCRC() const;
|
||||
bool SendRequest(char *url, char *response, size_t size) const;
|
||||
|
||||
CryptoContainer *license_data_;
|
||||
int state_;
|
||||
uint32_t start_tick_count_;
|
||||
size_t start_;
|
||||
CryptoContainer *serial_;
|
||||
uint64_t product_code_;
|
||||
uint32_t session_key_;
|
||||
CRITICAL_SECTION critical_section_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
LicensingManager(const LicensingManager &);
|
||||
LicensingManager &operator =(const LicensingManager &);
|
||||
};
|
||||
|
||||
#ifndef WIN_DRIVER
|
||||
class BaseRequest
|
||||
{
|
||||
public:
|
||||
BaseRequest();
|
||||
virtual ~BaseRequest();
|
||||
bool Send();
|
||||
const char *response() const { return response_; }
|
||||
const char *url() const { return url_; }
|
||||
protected:
|
||||
bool BuildUrl(const CryptoContainer &license_data);
|
||||
void EncodeUrl();
|
||||
void AppendUrlParam(const char *param, const char *value);
|
||||
private:
|
||||
void AppendUrl(const char *str, bool escape);
|
||||
char url_[2048];
|
||||
char *response_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
BaseRequest(const BaseRequest &);
|
||||
BaseRequest &operator =(const BaseRequest &);
|
||||
};
|
||||
|
||||
class ActivationRequest : public BaseRequest
|
||||
{
|
||||
public:
|
||||
ActivationRequest();
|
||||
int Process(const CryptoContainer &license_data, const char *code, bool offline);
|
||||
const char *serial() const { return serial_; }
|
||||
private:
|
||||
bool VerifyCode(const char *code) const;
|
||||
bool BuildUrl(const CryptoContainer &license_data, const char *code, bool offline);
|
||||
|
||||
const char *serial_;
|
||||
};
|
||||
|
||||
class DeactivationRequest : public BaseRequest
|
||||
{
|
||||
public:
|
||||
int Process(const CryptoContainer &license_data, const char *serial, bool offline);
|
||||
private:
|
||||
bool VerifySerial(const char *serial) const;
|
||||
bool BuildUrl(const CryptoContainer &license_data, const char *serial, bool offline);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
32
runtime/lin_runtime.mak
Normal file
32
runtime/lin_runtime.mak
Normal file
@ -0,0 +1,32 @@
|
||||
SOURCES := core.cc crypto.cc loader.cc licensing_manager.cc string_manager.cc hwid.cc objects.cc utils.cc ../third-party/lzma/LzmaDecode.cc
|
||||
|
||||
PROJECT := lin_runtime
|
||||
TARGET := $(PROJECT).so
|
||||
BIN_DIR := ../bin/$(ARCH_DIR)/Release
|
||||
LIB_TARGET := $(BIN_DIR)/$(PROJECT).a
|
||||
TMP_DIR := ../tmp/lin/runtime/$(ARCH_DIR)/runtime
|
||||
PCH_DIR := $(TMP_DIR)/runtime.gch
|
||||
DEFINES :=
|
||||
LFLAGS := $(LFLAGS) -Wl,--no-undefined -shared -Wl,--wrap=memcpy -Wl,--wrap=__poll_chk -Wl,--wrap=__fdelt_chk
|
||||
LIBS = ~/curl-7.35.0-$(ARCH_DIR)/lib/libcurl.so -ldl -lrt -L../bin/ -lVMProtectSDK$(ARCH_DIR)
|
||||
DYLIBS := ../bin/libVMProtectSDK$(ARCH_DIR).so
|
||||
OBJCOMP :=
|
||||
OBJECTS := $(addprefix $(TMP_DIR)/, $(SOURCES:.cc=.o))
|
||||
INCFLAGS := -I ~/curl-7.35.0-$(ARCH_DIR)/include
|
||||
|
||||
include ../lin_common.mak
|
||||
|
||||
clean:
|
||||
-$(DEL_FILE) $(LIB_TARGET)
|
||||
-$(DEL_FILE) $(OBJECTS)
|
||||
-$(DEL_FILE) $(PCH_CPP)
|
||||
-$(DEL_FILE) $(BIN_TARGET)
|
||||
|
||||
$(LIB_TARGET): $(OBJECTS) $(BIN_DIR)/.sentinel
|
||||
ar $(SLIBFLAGS) $(LIB_TARGET) $(abspath $(OBJECTS)) $(OBJCOMP)
|
||||
|
||||
$(BIN_TARGET): $(LIB_TARGET) $(OBJCOMP) $(DYLIBS)
|
||||
$(LINK) $(LFLAGS) -o $(BIN_TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP)
|
||||
|
||||
$(TMP_DIR)/%.o: %.cc $(PCH_CPP) $(TMP_DIR)/%/../.sentinel
|
||||
$(CXX) -c -include-pch $(PCH_CPP) $(CXXFLAGS) $(INCFLAGS) -o $(abspath $@) $(abspath $<)
|
3
runtime/lin_runtime32.mak
Normal file
3
runtime/lin_runtime32.mak
Normal file
@ -0,0 +1,3 @@
|
||||
ARCH := i386-linux-gnu
|
||||
ARCH_DIR := 32
|
||||
include lin_runtime.mak
|
4
runtime/lin_runtime64.mak
Normal file
4
runtime/lin_runtime64.mak
Normal file
@ -0,0 +1,4 @@
|
||||
ARCH := x86_64-linux-gnu
|
||||
ARCH_DIR := 64
|
||||
LFLAGS := $(LFLAGS) -Wl,-z,max-page-size=4096
|
||||
include lin_runtime.mak
|
2946
runtime/loader.cc
Normal file
2946
runtime/loader.cc
Normal file
File diff suppressed because it is too large
Load Diff
570
runtime/loader.h
Normal file
570
runtime/loader.h
Normal file
@ -0,0 +1,570 @@
|
||||
#ifndef LOADER_H
|
||||
#define LOADER_H
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct CRC_INFO {
|
||||
uint32_t Address;
|
||||
uint32_t Size;
|
||||
uint32_t Hash;
|
||||
};
|
||||
|
||||
struct FILE_CRC_INFO {
|
||||
uint32_t FileSize;
|
||||
// CRCInfo crc_info[1]
|
||||
};
|
||||
|
||||
struct SECTION_INFO {
|
||||
uint32_t Address;
|
||||
uint32_t Size;
|
||||
uint32_t Type;
|
||||
};
|
||||
|
||||
struct PACKER_INFO {
|
||||
uint32_t Src;
|
||||
uint32_t Dst;
|
||||
};
|
||||
|
||||
struct IAT_INFO {
|
||||
uint32_t Src;
|
||||
uint32_t Dst;
|
||||
uint32_t Size;
|
||||
};
|
||||
|
||||
struct DLL_INFO {
|
||||
uint32_t Name;
|
||||
// IMPORT_INFO import_info[1];
|
||||
};
|
||||
|
||||
struct IMPORT_INFO {
|
||||
uint32_t Name;
|
||||
uint32_t Address;
|
||||
int32_t Key;
|
||||
};
|
||||
|
||||
struct FIXUP_INFO {
|
||||
uint32_t Address;
|
||||
uint32_t BlockSize;
|
||||
// uint32_t type_offset[1];
|
||||
};
|
||||
|
||||
struct RELOCATION_INFO {
|
||||
uint32_t Address;
|
||||
uint32_t Source;
|
||||
uint32_t Type;
|
||||
};
|
||||
|
||||
struct SETUP_IMAGE_DATA {
|
||||
NOINLINE SETUP_IMAGE_DATA() { empty_ = 0; }
|
||||
|
||||
NOINLINE uint8_t *file_base() { return reinterpret_cast<uint8_t *>(FACE_FILE_BASE) - empty_; }
|
||||
NOINLINE uint8_t *image_base() { return reinterpret_cast<uint8_t *>(FACE_IMAGE_BASE) - empty_; }
|
||||
NOINLINE uint32_t options() { return FACE_LOADER_OPTIONS - empty_; }
|
||||
NOINLINE uint32_t storage() { return FACE_LOADER_DATA - empty_; }
|
||||
NOINLINE uint32_t runtime_entry() { return FACE_RUNTIME_ENTRY - empty_; }
|
||||
#ifdef __unix__
|
||||
NOINLINE uint32_t relro_info() { return FACE_GNU_RELRO_INFO - empty_; }
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(WIN_DRIVER)
|
||||
#else
|
||||
NOINLINE uint32_t tls_index_info() { return FACE_TLS_INDEX_INFO - empty_; }
|
||||
#endif
|
||||
|
||||
// file CRC information
|
||||
NOINLINE uint32_t file_crc_info() { return FACE_FILE_CRC_INFO - empty_; }
|
||||
NOINLINE uint32_t file_crc_info_size() { return FACE_FILE_CRC_INFO_SIZE - empty_; }
|
||||
|
||||
// header and loader CRC information
|
||||
NOINLINE uint32_t loader_crc_info() { return FACE_LOADER_CRC_INFO - empty_; }
|
||||
NOINLINE uint32_t loader_crc_info_size() { return FACE_LOADER_CRC_INFO_SIZE - empty_; }
|
||||
NOINLINE uint32_t loader_crc_info_hash() { return FACE_LOADER_CRC_INFO_HASH - empty_; }
|
||||
|
||||
// section information
|
||||
NOINLINE uint32_t section_info() { return FACE_SECTION_INFO - empty_; }
|
||||
NOINLINE uint32_t section_info_size() { return FACE_SECTION_INFO_SIZE - empty_; }
|
||||
|
||||
// packer information
|
||||
NOINLINE uint32_t packer_info() { return FACE_PACKER_INFO - empty_; }
|
||||
NOINLINE uint32_t packer_info_size() { return FACE_PACKER_INFO_SIZE - empty_; }
|
||||
|
||||
// fixups information
|
||||
NOINLINE uint32_t fixup_info() { return FACE_FIXUP_INFO - empty_; }
|
||||
NOINLINE uint32_t fixup_info_size() { return FACE_FIXUP_INFO_SIZE - empty_; }
|
||||
|
||||
// relocations information
|
||||
NOINLINE uint32_t relocation_info() { return FACE_RELOCATION_INFO - empty_; }
|
||||
NOINLINE uint32_t relocation_info_size() { return FACE_RELOCATION_INFO_SIZE - empty_; }
|
||||
|
||||
// IAT information
|
||||
NOINLINE uint32_t iat_info() { return FACE_IAT_INFO - empty_; }
|
||||
NOINLINE uint32_t iat_info_size() { return FACE_IAT_INFO_SIZE - empty_; }
|
||||
|
||||
// import information
|
||||
NOINLINE uint32_t import_info() { return FACE_IMPORT_INFO - empty_; }
|
||||
NOINLINE uint32_t import_info_size() { return FACE_IMPORT_INFO_SIZE - empty_; }
|
||||
|
||||
// internal import information
|
||||
NOINLINE uint32_t internal_import_info() { return FACE_INTERNAL_IMPORT_INFO - empty_; }
|
||||
NOINLINE uint32_t internal_import_info_size() { return FACE_INTERNAL_IMPORT_INFO_SIZE - empty_; }
|
||||
|
||||
// memory CRC information
|
||||
NOINLINE uint32_t memory_crc_info() { return FACE_MEMORY_CRC_INFO - empty_; }
|
||||
NOINLINE uint32_t memory_crc_info_size() { return FACE_MEMORY_CRC_INFO_SIZE - empty_; }
|
||||
NOINLINE uint32_t memory_crc_info_hash() { return FACE_MEMORY_CRC_INFO_HASH - empty_; }
|
||||
|
||||
// delay import information
|
||||
NOINLINE uint32_t delay_import_info() { return FACE_DELAY_IMPORT_INFO - empty_; }
|
||||
NOINLINE uint32_t delay_import_info_size() { return FACE_DELAY_IMPORT_INFO_SIZE - empty_; }
|
||||
private:
|
||||
uint32_t empty_;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifndef VMP_GNU
|
||||
|
||||
#define MAXIMUM_FILENAME_LENGTH 256
|
||||
|
||||
typedef struct _SYSTEM_MODULE_ENTRY
|
||||
{
|
||||
#ifdef _WIN64
|
||||
ULONGLONG Unknown1;
|
||||
ULONGLONG Unknown2;
|
||||
#else
|
||||
ULONG Unknown1;
|
||||
ULONG Unknown2;
|
||||
#endif
|
||||
PVOID BaseAddress;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
ULONG EntryIndex;
|
||||
USHORT NameLength; // Length of module name not including the path, this field contains valid value only for NTOSKRNL module
|
||||
USHORT PathLength; // Length of 'directory path' part of modulename
|
||||
CHAR Name[MAXIMUM_FILENAME_LENGTH];
|
||||
} SYSTEM_MODULE_ENTRY;
|
||||
|
||||
typedef struct _SYSTEM_MODULE_INFORMATION
|
||||
{
|
||||
ULONG Count;
|
||||
#ifdef _WIN64
|
||||
ULONG Unknown1;
|
||||
#endif
|
||||
SYSTEM_MODULE_ENTRY Module[1];
|
||||
} SYSTEM_MODULE_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION
|
||||
{
|
||||
BOOLEAN DebuggerEnabled;
|
||||
BOOLEAN DebuggerNotPresent;
|
||||
} SYSTEM_KERNEL_DEBUGGER_INFORMATION;
|
||||
|
||||
typedef enum _MEMORY_INFORMATION_CLASS {
|
||||
MemoryBasicInformation
|
||||
} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS;
|
||||
|
||||
#ifdef WIN_DRIVER
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
|
||||
#define IMAGE_OS2_SIGNATURE 0x454E // NE
|
||||
#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
|
||||
#define IMAGE_VXD_SIGNATURE 0x454C // LE
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
|
||||
|
||||
#pragma pack(push, 2)
|
||||
|
||||
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
|
||||
WORD e_magic; // Magic number
|
||||
WORD e_cblp; // Bytes on last page of file
|
||||
WORD e_cp; // Pages in file
|
||||
WORD e_crlc; // Relocations
|
||||
WORD e_cparhdr; // Size of header in paragraphs
|
||||
WORD e_minalloc; // Minimum extra paragraphs needed
|
||||
WORD e_maxalloc; // Maximum extra paragraphs needed
|
||||
WORD e_ss; // Initial (relative) SS value
|
||||
WORD e_sp; // Initial SP value
|
||||
WORD e_csum; // Checksum
|
||||
WORD e_ip; // Initial IP value
|
||||
WORD e_cs; // Initial (relative) CS value
|
||||
WORD e_lfarlc; // File address of relocation table
|
||||
WORD e_ovno; // Overlay number
|
||||
WORD e_res[4]; // Reserved words
|
||||
WORD e_oemid; // OEM identifier (for e_oeminfo)
|
||||
WORD e_oeminfo; // OEM information; e_oemid specific
|
||||
WORD e_res2[10]; // Reserved words
|
||||
LONG e_lfanew; // File address of new exe header
|
||||
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct _IMAGE_FILE_HEADER {
|
||||
WORD Machine;
|
||||
WORD NumberOfSections;
|
||||
DWORD TimeDateStamp;
|
||||
DWORD PointerToSymbolTable;
|
||||
DWORD NumberOfSymbols;
|
||||
WORD SizeOfOptionalHeader;
|
||||
WORD Characteristics;
|
||||
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
|
||||
|
||||
typedef struct _IMAGE_DATA_DIRECTORY {
|
||||
DWORD VirtualAddress;
|
||||
DWORD Size;
|
||||
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER {
|
||||
//
|
||||
// Standard fields.
|
||||
//
|
||||
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
DWORD BaseOfData;
|
||||
|
||||
//
|
||||
// NT additional fields.
|
||||
//
|
||||
|
||||
DWORD ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Win32VersionValue;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
DWORD SizeOfStackReserve;
|
||||
DWORD SizeOfStackCommit;
|
||||
DWORD SizeOfHeapReserve;
|
||||
DWORD SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
|
||||
|
||||
typedef struct _IMAGE_ROM_OPTIONAL_HEADER {
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
DWORD BaseOfData;
|
||||
DWORD BaseOfBss;
|
||||
DWORD GprMask;
|
||||
DWORD CprMask[4];
|
||||
DWORD GpValue;
|
||||
} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER;
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER64 {
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
ULONGLONG ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Win32VersionValue;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
ULONGLONG SizeOfStackReserve;
|
||||
ULONGLONG SizeOfStackCommit;
|
||||
ULONGLONG SizeOfHeapReserve;
|
||||
ULONGLONG SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
|
||||
|
||||
typedef struct _IMAGE_NT_HEADERS64 {
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
|
||||
|
||||
typedef struct _IMAGE_NT_HEADERS {
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
|
||||
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
|
||||
|
||||
typedef struct _IMAGE_ROM_HEADERS {
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
|
||||
} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS;
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
|
||||
typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
|
||||
#else
|
||||
typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
|
||||
typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
|
||||
#endif
|
||||
|
||||
typedef struct _IMAGE_SECTION_HEADER {
|
||||
BYTE Name[8];
|
||||
union {
|
||||
DWORD PhysicalAddress;
|
||||
DWORD VirtualSize;
|
||||
} Misc;
|
||||
DWORD VirtualAddress;
|
||||
DWORD SizeOfRawData;
|
||||
DWORD PointerToRawData;
|
||||
DWORD PointerToRelocations;
|
||||
DWORD PointerToLinenumbers;
|
||||
WORD NumberOfRelocations;
|
||||
WORD NumberOfLinenumbers;
|
||||
DWORD Characteristics;
|
||||
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
|
||||
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
|
||||
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
|
||||
// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage)
|
||||
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data
|
||||
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP
|
||||
#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
|
||||
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
|
||||
#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table
|
||||
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors
|
||||
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
|
||||
|
||||
#define IMAGE_REL_BASED_ABSOLUTE 0
|
||||
#define IMAGE_REL_BASED_HIGH 1
|
||||
#define IMAGE_REL_BASED_LOW 2
|
||||
#define IMAGE_REL_BASED_HIGHLOW 3
|
||||
#define IMAGE_REL_BASED_HIGHADJ 4
|
||||
#define IMAGE_REL_BASED_MIPS_JMPADDR 5
|
||||
#define IMAGE_REL_BASED_MIPS_JMPADDR16 9
|
||||
#define IMAGE_REL_BASED_IA64_IMM64 9
|
||||
#define IMAGE_REL_BASED_DIR64 10
|
||||
|
||||
#define IMAGE_ORDINAL_FLAG64 0x8000000000000000
|
||||
#define IMAGE_ORDINAL_FLAG32 0x80000000
|
||||
#define IMAGE_ORDINAL64(Ordinal) (Ordinal & 0xffff)
|
||||
#define IMAGE_ORDINAL32(Ordinal) (Ordinal & 0xffff)
|
||||
#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0)
|
||||
#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0)
|
||||
|
||||
typedef struct _IMAGE_EXPORT_DIRECTORY {
|
||||
DWORD Characteristics;
|
||||
DWORD TimeDateStamp;
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
DWORD Name;
|
||||
DWORD Base;
|
||||
DWORD NumberOfFunctions;
|
||||
DWORD NumberOfNames;
|
||||
DWORD AddressOfFunctions; // RVA from base of image
|
||||
DWORD AddressOfNames; // RVA from base of image
|
||||
DWORD AddressOfNameOrdinals; // RVA from base of image
|
||||
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
#define MAX_PATH 260
|
||||
|
||||
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations.
|
||||
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
|
||||
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.
|
||||
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.
|
||||
#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
|
||||
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
|
||||
#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
|
||||
#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
|
||||
|
||||
typedef enum _SYSTEM_INFORMATION_CLASS {
|
||||
SystemModuleInformation = 0xb,
|
||||
SystemKernelDebuggerInformation = 0x23,
|
||||
SystemFirmwareTableInformation = 0x4c
|
||||
} SYSTEM_INFORMATION_CLASS;
|
||||
|
||||
extern "C" {
|
||||
NTKERNELAPI NTSTATUS NTAPI NtQuerySystemInformation(
|
||||
SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength);
|
||||
}
|
||||
|
||||
#else
|
||||
#define FILE_OPEN 0x00000001
|
||||
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
|
||||
#define FILE_NON_DIRECTORY_FILE 0x00000040
|
||||
|
||||
typedef enum _SECTION_INHERIT {
|
||||
ViewShare=1,
|
||||
ViewUnmap=2
|
||||
} SECTION_INHERIT, *PSECTION_INHERIT;
|
||||
|
||||
#define SystemModuleInformation (SYSTEM_INFORMATION_CLASS)11
|
||||
#define SystemKernelDebuggerInformation (SYSTEM_INFORMATION_CLASS)35
|
||||
|
||||
#define ThreadHideFromDebugger (THREADINFOCLASS)17
|
||||
|
||||
#define ProcessDebugPort (PROCESSINFOCLASS)0x7
|
||||
#define ProcessDebugObjectHandle (PROCESSINFOCLASS)0x1e
|
||||
#define ProcessDefaultHardErrorMode (PROCESSINFOCLASS)0x0c
|
||||
#define ProcessInstrumentationCallback (PROCESSINFOCLASS)40
|
||||
|
||||
#define MemoryMappedFilenameInformation (MEMORY_INFORMATION_CLASS)2
|
||||
|
||||
#define STATUS_PORT_NOT_SET ((NTSTATUS)0xC0000353L)
|
||||
#define STATUS_SERVICE_NOTIFICATION ((NTSTATUS)0x40000018L)
|
||||
#define HARDERROR_OVERRIDE_ERRORMODE 0x10000000
|
||||
|
||||
#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
|
||||
#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 )
|
||||
|
||||
typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG Reserved;
|
||||
PVOID Callback;
|
||||
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;
|
||||
|
||||
typedef enum HardErrorResponse {
|
||||
ResponseReturnToCaller,
|
||||
ResponseNotHandled,
|
||||
ResponseAbort, ResponseCancel,
|
||||
ResponseIgnore,
|
||||
ResponseNo,
|
||||
ResponseOk,
|
||||
ResponseRetry,
|
||||
ResponseYes
|
||||
} HardErrorResponse;
|
||||
|
||||
typedef enum HardErrorResponseButton {
|
||||
ResponseButtonOK,
|
||||
ResponseButtonOKCancel,
|
||||
ResponseButtonAbortRetryIgnore,
|
||||
ResponseButtonYesNoCancel,
|
||||
ResponseButtonYesNo,
|
||||
ResponseButtonRetryCancel,
|
||||
ResponseButtonCancelTryAgainContinue
|
||||
} HardErrorResponseButton;
|
||||
|
||||
typedef enum HardErrorResponseIcon {
|
||||
IconAsterisk = 0x40,
|
||||
IconError = 0x10,
|
||||
IconExclamation = 0x30,
|
||||
IconHand = 0x10,
|
||||
IconInformation = 0x40,
|
||||
IconNone = 0,
|
||||
IconQuestion = 0x20,
|
||||
IconStop = 0x10,
|
||||
IconWarning = 0x30,
|
||||
IconUserIcon = 0x80
|
||||
} HardErrorResponseIcon;
|
||||
|
||||
#define SEC_IMAGE_NO_EXECUTE (SEC_IMAGE | SEC_NOCACHE)
|
||||
|
||||
enum {
|
||||
WINDOWS_XP = 2600,
|
||||
WINDOWS_2003 = 3790,
|
||||
WINDOWS_VISTA = 6000,
|
||||
WINDOWS_VISTA_SP1 = 6001,
|
||||
WINDOWS_VISTA_SP2 = 6002,
|
||||
WINDOWS_7 = 7600,
|
||||
WINDOWS_7_SP1 = 7601,
|
||||
WINDOWS_8 = 9200,
|
||||
WINDOWS_8_1 = 9600,
|
||||
WINDOWS_10_TH1 = 10240,
|
||||
WINDOWS_10_TH2 = 10586,
|
||||
WINDOWS_10_RS1 = 14393,
|
||||
WINDOWS_10_RS2 = 15063,
|
||||
WINDOWS_10_RS3 = 16299,
|
||||
WINDOWS_10_RS4 = 17134,
|
||||
WINDOWS_10_RS5 = 17763,
|
||||
WINDOWS_10_19H1 = 18362,
|
||||
WINDOWS_10_19H2 = 18363,
|
||||
WINDOWS_10_20H1 = 19041,
|
||||
WINDOWS_10_20H2 = 19042,
|
||||
WINDOWS_10_21H1 = 19043,
|
||||
WINDOWS_10_21H2 = 19044,
|
||||
WINDOWS_10_22H2 = 19045,
|
||||
WINDOWS_11_21H2 = 22000,
|
||||
WINDOWS_11_22H2 = 22621,
|
||||
};
|
||||
|
||||
#define IS_KNOWN_WINDOWS_BUILD(b) ( \
|
||||
(b) == WINDOWS_XP || \
|
||||
(b) == WINDOWS_2003 || \
|
||||
(b) == WINDOWS_VISTA || \
|
||||
(b) == WINDOWS_VISTA_SP1 || \
|
||||
(b) == WINDOWS_VISTA_SP2 || \
|
||||
(b) == WINDOWS_7 || \
|
||||
(b) == WINDOWS_7_SP1 || \
|
||||
(b) == WINDOWS_8 || \
|
||||
(b) == WINDOWS_8_1 || \
|
||||
(b) == WINDOWS_10_TH1 || \
|
||||
(b) == WINDOWS_10_TH2 || \
|
||||
(b) == WINDOWS_10_RS1 || \
|
||||
(b) == WINDOWS_10_RS2 || \
|
||||
(b) == WINDOWS_10_RS3 || \
|
||||
(b) == WINDOWS_10_RS4 || \
|
||||
(b) == WINDOWS_10_RS5 || \
|
||||
(b) == WINDOWS_10_19H1 || \
|
||||
(b) == WINDOWS_10_19H2 || \
|
||||
(b) == WINDOWS_10_20H1 || \
|
||||
(b) == WINDOWS_10_20H2 || \
|
||||
(b) == WINDOWS_10_21H1 || \
|
||||
(b) == WINDOWS_10_21H2 || \
|
||||
(b) == WINDOWS_10_22H2 \
|
||||
)
|
||||
|
||||
#endif // WIN_DRIVER
|
||||
|
||||
#endif // VMP_GNU
|
||||
|
||||
typedef struct _PEB32 {
|
||||
BYTE Reserved1[2];
|
||||
BYTE BeingDebugged;
|
||||
BYTE Reserved2[0xa1];
|
||||
ULONG OSMajorVersion;
|
||||
ULONG OSMinorVersion;
|
||||
USHORT OSBuildNumber;
|
||||
} PEB32;
|
||||
|
||||
typedef struct _PEB64 {
|
||||
BYTE Reserved1[2];
|
||||
BYTE BeingDebugged;
|
||||
BYTE Reserved2[0x115];
|
||||
ULONG OSMajorVersion;
|
||||
ULONG OSMinorVersion;
|
||||
USHORT OSBuildNumber;
|
||||
} PEB64;
|
||||
|
||||
#endif
|
31
runtime/mac_runtime.mak
Normal file
31
runtime/mac_runtime.mak
Normal file
@ -0,0 +1,31 @@
|
||||
SOURCES := core.cc crypto.cc loader.cc licensing_manager.cc string_manager.cc hwid.cc objects.cc utils.cc ../third-party/lzma/LzmaDecode.cc
|
||||
|
||||
PROJECT := mac_runtime
|
||||
TARGET := $(PROJECT).dylib
|
||||
BIN_DIR := ../bin/$(ARCH_DIR)/Release
|
||||
LIB_TARGET := $(BIN_DIR)/$(PROJECT).a
|
||||
TMP_DIR := ../tmp/mac/runtime/$(ARCH_DIR)/runtime
|
||||
PCH_DIR := $(TMP_DIR)/runtime.gch
|
||||
DEFINES :=
|
||||
LFLAGS := -dynamiclib
|
||||
LIBS = $(SDK_LIBS) -framework DiskArbitration
|
||||
DYLIBS := ../bin/libVMProtectSDK.dylib
|
||||
OBJCOMP :=
|
||||
OBJECTS := $(addprefix $(TMP_DIR)/, $(SOURCES:.cc=.o))
|
||||
|
||||
include ../mac_common.mak
|
||||
|
||||
clean:
|
||||
-$(DEL_FILE) $(LIB_TARGET)
|
||||
-$(DEL_FILE) $(OBJECTS)
|
||||
-$(DEL_FILE) $(PCH_CPP)
|
||||
-$(DEL_FILE) $(BIN_TARGET)
|
||||
|
||||
$(LIB_TARGET): $(OBJECTS) $(BIN_DIR)/.sentinel
|
||||
libtool $(SLIBFLAGS) -o $(LIB_TARGET) $(abspath $(OBJECTS)) $(OBJCOMP)
|
||||
|
||||
$(BIN_TARGET): $(LIB_TARGET) $(OBJCOMP) $(DYLIBS)
|
||||
$(LINK) $(LFLAGS) -o $(BIN_TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP) $(DYLIBS)
|
||||
|
||||
$(TMP_DIR)/%.o: %.cc $(PCH_CPP) $(TMP_DIR)/%/../.sentinel
|
||||
$(CXX) -c -include-pch $(PCH_CPP) $(CXXFLAGS) $(INCFLAGS) -o $(abspath $@) $(abspath $<)
|
3
runtime/mac_runtime32.mak
Normal file
3
runtime/mac_runtime32.mak
Normal file
@ -0,0 +1,3 @@
|
||||
ARCH := i386
|
||||
ARCH_DIR := 32
|
||||
include mac_runtime.mak
|
3
runtime/mac_runtime64.mak
Normal file
3
runtime/mac_runtime64.mak
Normal file
@ -0,0 +1,3 @@
|
||||
ARCH := x86_64
|
||||
ARCH_DIR := 64
|
||||
include mac_runtime.mak
|
59
runtime/objects.cc
Normal file
59
runtime/objects.cc
Normal file
@ -0,0 +1,59 @@
|
||||
#include "objects.h"
|
||||
|
||||
#ifdef WIN_DRIVER
|
||||
|
||||
extern "C" EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler3(int a, int b, int c, int d)
|
||||
{
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* CriticalSection
|
||||
*/
|
||||
|
||||
CriticalSection::CriticalSection(CRITICAL_SECTION &critical_section)
|
||||
: critical_section_(critical_section)
|
||||
{
|
||||
#ifdef VMP_GNU
|
||||
pthread_mutex_lock(&critical_section_);
|
||||
#elif defined(WIN_DRIVER)
|
||||
KeWaitForMutexObject(&critical_section_, Executive, KernelMode, FALSE, NULL);
|
||||
#else
|
||||
EnterCriticalSection(&critical_section_);
|
||||
#endif
|
||||
}
|
||||
|
||||
CriticalSection::~CriticalSection()
|
||||
{
|
||||
#ifdef VMP_GNU
|
||||
pthread_mutex_unlock(&critical_section_);
|
||||
#elif defined(WIN_DRIVER)
|
||||
KeReleaseMutex(&critical_section_, FALSE);
|
||||
#else
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CriticalSection::Init(CRITICAL_SECTION &critical_section)
|
||||
{
|
||||
#ifdef VMP_GNU
|
||||
pthread_mutex_init(&critical_section, NULL);
|
||||
#elif defined(WIN_DRIVER)
|
||||
KeInitializeMutex(&critical_section, 0);
|
||||
#else
|
||||
InitializeCriticalSection(&critical_section);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CriticalSection::Free(CRITICAL_SECTION &critical_section)
|
||||
{
|
||||
#ifdef VMP_GNU
|
||||
pthread_mutex_destroy(&critical_section);
|
||||
#elif defined(WIN_DRIVER)
|
||||
// do nothing
|
||||
#else
|
||||
DeleteCriticalSection(&critical_section);
|
||||
#endif
|
||||
}
|
78
runtime/objects.h
Normal file
78
runtime/objects.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef OBJECTS_H
|
||||
#define OBJECTS_H
|
||||
|
||||
template<class T>
|
||||
class vector
|
||||
{
|
||||
public:
|
||||
vector() : data_(NULL), total_(0), size_(0) {}
|
||||
~vector() { delete [] data_; }
|
||||
size_t size() const { return size_; }
|
||||
bool empty() const { return size_ == 0; }
|
||||
const T &operator[] (size_t index) const { return data_[index]; }
|
||||
T &operator[] (size_t index) {return data_[index]; }
|
||||
void push_back(const T &t)
|
||||
{
|
||||
if (size_ == total_) {
|
||||
// no free space
|
||||
size_t new_total = (total_ == 0) ? 1 : total_ * 2;
|
||||
T *new_data = new T[new_total];
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
new_data[i] = data_[i];
|
||||
}
|
||||
delete [] data_;
|
||||
data_ = new_data;
|
||||
total_ = new_total;
|
||||
}
|
||||
data_[size_++] = t;
|
||||
}
|
||||
void pop_back()
|
||||
{
|
||||
if (size_)
|
||||
size_--;
|
||||
}
|
||||
|
||||
void erase(size_t pos)
|
||||
{
|
||||
if (pos >= size_)
|
||||
return; // error
|
||||
for (size_t i = pos; i < size_ - 1; i++) {
|
||||
data_[i] = data_[i + 1];
|
||||
}
|
||||
size_--;
|
||||
}
|
||||
|
||||
template <typename X>
|
||||
size_t find(const X &v) const
|
||||
{
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
if (data_[i] == v)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
size_ = total_ = 0;
|
||||
delete [] data_;
|
||||
data_ = NULL;
|
||||
}
|
||||
private:
|
||||
T *data_;
|
||||
size_t total_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
class CriticalSection
|
||||
{
|
||||
public:
|
||||
CriticalSection(CRITICAL_SECTION &critical_section);
|
||||
~CriticalSection();
|
||||
static void Init(CRITICAL_SECTION &critical_section);
|
||||
static void Free(CRITICAL_SECTION &critical_section);
|
||||
private:
|
||||
CRITICAL_SECTION &critical_section_;
|
||||
};
|
||||
|
||||
#endif
|
146
runtime/precommon.h
Normal file
146
runtime/precommon.h
Normal file
@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
#ifndef PRECOMMON_PCH
|
||||
#define PRECOMMON_PCH
|
||||
|
||||
#define NOMINMAX
|
||||
#ifdef WIN_DRIVER
|
||||
#define _STL70_
|
||||
#include <ntddk.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string> // because of non-usual new operator
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#ifndef DBG_NEW
|
||||
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
|
||||
#define new DBG_NEW
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(__unix__)
|
||||
#include <linux/limits.h>
|
||||
enum { FALSE, TRUE };
|
||||
typedef void VOID;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#define FORCE_INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
#define NOINLINE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__APPLE__) || defined(__unix__)
|
||||
#define VMP_GNU
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef int HANDLE;
|
||||
typedef void *LPVOID;
|
||||
typedef void *HMODULE;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
typedef mach_port_t HPROCESS;
|
||||
#endif
|
||||
|
||||
#if defined(__unix__)
|
||||
typedef int HPROCESS;
|
||||
inline size_t strlcpy(char *dst, const char *src, size_t size)
|
||||
{
|
||||
dst[size - 1] = '\0';
|
||||
strncpy(dst, src, size - 1);
|
||||
return strlen(dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
|
||||
#define _countof(x) (sizeof(x) / sizeof(x[0]))
|
||||
#define _strtoui64 strtoull
|
||||
#define _strtoi64 strtoll
|
||||
#define VMP_API
|
||||
typedef char VMP_CHAR;
|
||||
typedef unsigned short VMP_WCHAR;
|
||||
inline void strncpy_s(char *strDestination, size_t sz, const char *strSource, size_t src_sz) { strncpy(strDestination, strSource, sz + 0 * src_sz); }
|
||||
#ifdef __cplusplus
|
||||
namespace os {
|
||||
typedef unsigned short unicode_char;
|
||||
typedef std::basic_string<unicode_char, std::char_traits<unicode_char>, std::allocator<unicode_char> > unicode_string;
|
||||
};
|
||||
template <size_t sz> void strcpy_s(char (&strDestination)[sz], const char *strSource) { strlcpy(strDestination, strSource, sz); }
|
||||
template <size_t sz> void strncpy_s(char (&strDestination)[sz], const char *strSource, size_t src_sz) { strncpy_s(&strDestination[0], sz, strSource, src_sz); }
|
||||
#endif
|
||||
#define _TRUNCATE ((size_t)-1)
|
||||
#define _vsnprintf_s(dest, dest_sz, cnt, fmt, args) _vsnprintf((dest), (dest_sz), (fmt), (args))
|
||||
#define _vsnprintf vsnprintf
|
||||
#define vsprintf_s vsprintf
|
||||
#define sprintf_s sprintf
|
||||
#define _strcmpi strcasecmp
|
||||
#define _strdup strdup
|
||||
#define sscanf_s sscanf
|
||||
#define strcat_s strcat
|
||||
#define LOWORD(l) ((uint16_t)(((uint32_t)(l)) & 0xffff))
|
||||
#define HIWORD(l) ((uint16_t)((((uint32_t)(l)) >> 16) & 0xffff))
|
||||
typedef int BOOL;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
typedef char CHAR;
|
||||
typedef uint8_t BYTE, *PBYTE;
|
||||
typedef short SHORT;
|
||||
typedef uint16_t WORD, USHORT, *PWORD, *PUSHORT;
|
||||
typedef uint32_t DWORD, ULONG, ULONG32, *PDWORD, *PULONG, *PULONG32;
|
||||
typedef int32_t LONG, LONG32, *PLONG, *PLONG32;
|
||||
typedef uint64_t DWORD64, ULONGLONG, ULONG64, *PDWORD64, *PULONGLONG, *PULONG64;
|
||||
typedef struct _GUID {
|
||||
uint32_t Data1;
|
||||
uint16_t Data2;
|
||||
uint16_t Data3;
|
||||
uint8_t Data4[8];
|
||||
} GUID;
|
||||
|
||||
#define CRITICAL_SECTION pthread_mutex_t
|
||||
|
||||
#else
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#define VMP_API __stdcall
|
||||
typedef wchar_t VMP_CHAR;
|
||||
typedef wchar_t VMP_WCHAR;
|
||||
#ifdef __cplusplus
|
||||
namespace os {
|
||||
typedef std::wstring unicode_string;
|
||||
typedef wchar_t unicode_char;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef void *HPROCESS;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
#endif //PRECOMMON_PCH
|
1
runtime/precompiled.cc
Normal file
1
runtime/precompiled.cc
Normal file
@ -0,0 +1 @@
|
||||
#include "precompiled.h"
|
133
runtime/precompiled.h
Normal file
133
runtime/precompiled.h
Normal file
@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
#ifndef WR_PCH
|
||||
#define WR_PCH
|
||||
|
||||
#ifndef VMP_GNU
|
||||
#define WINVER 0x0500
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
|
||||
#include "precommon.h"
|
||||
|
||||
#ifdef WIN_DRIVER
|
||||
void * __cdecl operator new(size_t size);
|
||||
void __cdecl operator delete(void* p);
|
||||
void __cdecl operator delete(void* p, size_t);
|
||||
void * __cdecl operator new[](size_t size);
|
||||
void __cdecl operator delete[](void *p);
|
||||
#endif
|
||||
|
||||
#define RUNTIME
|
||||
|
||||
#ifdef VMP_GNU
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <sys/syslimits.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach/vm_map.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/fat.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
#endif
|
||||
|
||||
#define WINAPI
|
||||
#ifdef __APPLE__
|
||||
#define EXPORT_API __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define EXPORT_API __attribute__ ((visibility ("protected")))
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define EXPORT_API __declspec(dllexport)
|
||||
|
||||
#ifdef WIN_DRIVER
|
||||
#include <windef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
void __cpuid(int a[4], int b);
|
||||
void __nop();
|
||||
|
||||
#ifdef _WIN64
|
||||
unsigned __int64 __readeflags(void);
|
||||
void __writeeflags(unsigned __int64);
|
||||
#else
|
||||
unsigned __readeflags(void);
|
||||
void __writeeflags(unsigned);
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif // WIN_DRIVER
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
typedef int BOOL;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef HANDLE HGLOBAL;
|
||||
typedef unsigned int UINT;
|
||||
#define WINAPI __stdcall
|
||||
#define CRITICAL_SECTION KMUTEX
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef INT_PTR (FAR WINAPI *FARPROC)();
|
||||
#else
|
||||
typedef int (FAR WINAPI *FARPROC)();
|
||||
#endif // _WIN64
|
||||
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <intrin.h>
|
||||
#include <wtsapi32.h>
|
||||
#include <winternl.h>
|
||||
#include <tlhelp32.h>
|
||||
#endif
|
||||
#endif // VMP_GNU
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
|
||||
#endif
|
||||
|
||||
#ifndef InitializeObjectAttributes
|
||||
#define InitializeObjectAttributes( p, n, a, r, s ) { \
|
||||
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
|
||||
(p)->RootDirectory = r; \
|
||||
(p)->Attributes = a; \
|
||||
(p)->ObjectName = n; \
|
||||
(p)->SecurityDescriptor = s; \
|
||||
(p)->SecurityQualityOfService = NULL; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OBJ_CASE_INSENSITIVE
|
||||
#define OBJ_CASE_INSENSITIVE 0x00000040L
|
||||
#endif
|
||||
|
||||
#endif //WR_PCH
|
1390
runtime/registry_manager.cc
Normal file
1390
runtime/registry_manager.cc
Normal file
File diff suppressed because it is too large
Load Diff
299
runtime/registry_manager.h
Normal file
299
runtime/registry_manager.h
Normal file
@ -0,0 +1,299 @@
|
||||
#ifndef REGISTRY_MANAGER_H
|
||||
#define REGISTRY_MANAGER_H
|
||||
|
||||
struct REGISTRY_DIRECTORY {
|
||||
uint32_t Reserved1;
|
||||
uint32_t Reserved2;
|
||||
};
|
||||
|
||||
typedef struct _KEY_VALUE_BASIC_INFORMATION {
|
||||
ULONG TitleIndex;
|
||||
ULONG Type;
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1]; // Variable size
|
||||
} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _KEY_VALUE_FULL_INFORMATION {
|
||||
ULONG TitleIndex;
|
||||
ULONG Type;
|
||||
ULONG DataOffset;
|
||||
ULONG DataLength;
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1]; // Variable size
|
||||
// Data[1]; // Variable size data not declared
|
||||
} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
|
||||
|
||||
typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
|
||||
ULONG TitleIndex;
|
||||
ULONG Type;
|
||||
ULONG DataLength;
|
||||
UCHAR Data[1]; // Variable size
|
||||
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
|
||||
|
||||
typedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 {
|
||||
ULONG Type;
|
||||
ULONG DataLength;
|
||||
UCHAR Data[1]; // Variable size
|
||||
} KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, *PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64;
|
||||
|
||||
typedef enum _KEY_VALUE_INFORMATION_CLASS {
|
||||
KeyValueBasicInformation,
|
||||
KeyValueFullInformation,
|
||||
KeyValuePartialInformation,
|
||||
KeyValueFullInformationAlign64,
|
||||
KeyValuePartialInformationAlign64,
|
||||
MaxKeyValueInfoClass // MaxKeyValueInfoClass should always be the last enum
|
||||
} KEY_VALUE_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _KEY_BASIC_INFORMATION {
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG TitleIndex;
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1]; // Variable length string
|
||||
} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _KEY_NODE_INFORMATION {
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG TitleIndex;
|
||||
ULONG ClassOffset;
|
||||
ULONG ClassLength;
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1]; // Variable length string
|
||||
// Class[1]; // Variable length string not declared
|
||||
} KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION;
|
||||
|
||||
typedef struct _KEY_FULL_INFORMATION {
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG TitleIndex;
|
||||
ULONG ClassOffset;
|
||||
ULONG ClassLength;
|
||||
ULONG SubKeys;
|
||||
ULONG MaxNameLen;
|
||||
ULONG MaxClassLen;
|
||||
ULONG Values;
|
||||
ULONG MaxValueNameLen;
|
||||
ULONG MaxValueDataLen;
|
||||
WCHAR Class[1]; // Variable length
|
||||
} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;
|
||||
|
||||
typedef struct _KEY_NAME_INFORMATION {
|
||||
ULONG NameLength;
|
||||
WCHAR Name[1]; // Variable length
|
||||
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
|
||||
|
||||
typedef struct _KEY_CACHED_INFORMATION {
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG TitleIndex;
|
||||
ULONG SubKeys;
|
||||
ULONG MaxNameLen;
|
||||
ULONG Values;
|
||||
ULONG MaxValueNameLen;
|
||||
ULONG MaxValueDataLen;
|
||||
ULONG NameLength;
|
||||
} KEY_CACHED_INFORMATION, *PKEY_CACHED_INFORMATION;
|
||||
|
||||
typedef struct _KEY_HANDLE_TAGS_INFORMATION {
|
||||
ULONG HandleTags;
|
||||
} KEY_HANDLE_TAGS_INFORMATION, *PKEY_HANDLE_TAGS_INFORMATION;
|
||||
|
||||
typedef enum _KEY_INFORMATION_CLASS {
|
||||
KeyBasicInformation,
|
||||
KeyNodeInformation,
|
||||
KeyFullInformation,
|
||||
KeyNameInformation,
|
||||
KeyCachedInformation,
|
||||
KeyFlagsInformation,
|
||||
KeyVirtualizationInformation,
|
||||
KeyHandleTagsInformation,
|
||||
MaxKeyInfoClass // MaxKeyInfoClass should always be the last enum
|
||||
} KEY_INFORMATION_CLASS;
|
||||
|
||||
class RegistryValue
|
||||
{
|
||||
public:
|
||||
RegistryValue(const wchar_t *name);
|
||||
~RegistryValue();
|
||||
const wchar_t *name() const { return name_; }
|
||||
uint32_t type() const { return type_; }
|
||||
uint32_t size() const { return size_; }
|
||||
void *data() const { return data_; }
|
||||
void SetValue(uint32_t type, void *data, uint32_t size);
|
||||
private:
|
||||
wchar_t *name_;
|
||||
uint32_t type_;
|
||||
uint8_t *data_;
|
||||
uint32_t size_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
RegistryValue(const RegistryValue &);
|
||||
RegistryValue &operator =(const RegistryValue &);
|
||||
};
|
||||
|
||||
class UnicodeString
|
||||
{
|
||||
public:
|
||||
UnicodeString()
|
||||
: data_(NULL), size_(0)
|
||||
{
|
||||
data_ = new wchar_t[size_ + 1];
|
||||
data_[size_] = 0;
|
||||
}
|
||||
UnicodeString(const wchar_t *str)
|
||||
: data_(NULL), size_(wcslen(str))
|
||||
{
|
||||
data_ = new wchar_t[size_ + 1];
|
||||
memcpy(data_, str, size_ * sizeof(wchar_t));
|
||||
data_[size_] = 0;
|
||||
}
|
||||
UnicodeString(const wchar_t *str, size_t size)
|
||||
: data_(NULL), size_(size)
|
||||
{
|
||||
data_ = new wchar_t[size_ + 1];
|
||||
memcpy(data_, str, size_ * sizeof(wchar_t));
|
||||
data_[size_] = 0;
|
||||
}
|
||||
UnicodeString(const UnicodeString &str)
|
||||
: data_(NULL), size_(str.size_)
|
||||
{
|
||||
data_ = new wchar_t[size_ + 1];
|
||||
memcpy(data_, str.data_, size_ * sizeof(wchar_t));
|
||||
data_[size_] = 0;
|
||||
}
|
||||
UnicodeString &operator=(const UnicodeString &src)
|
||||
{
|
||||
if (&src != this)
|
||||
{
|
||||
delete [] data_;
|
||||
size_ = src.size();
|
||||
data_ = new wchar_t[size_ + 1];
|
||||
memcpy(data_, src.c_str(), size_ * sizeof(wchar_t));
|
||||
data_[size_] = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~UnicodeString()
|
||||
{
|
||||
delete [] data_;
|
||||
}
|
||||
size_t size() const { return size_; }
|
||||
const wchar_t *c_str() const { return data_; }
|
||||
UnicodeString &append(const wchar_t *str) { return append (str, wcslen(str)); }
|
||||
UnicodeString &append(const wchar_t *str, size_t str_size)
|
||||
{
|
||||
size_t new_size = size_ + str_size;
|
||||
wchar_t *new_data = new wchar_t[new_size + 1];
|
||||
memcpy(new_data, data_, size_ * sizeof(wchar_t));
|
||||
memcpy(new_data + size_, str, str_size * sizeof(wchar_t));
|
||||
new_data[new_size] = 0;
|
||||
delete [] data_;
|
||||
data_ = new_data;
|
||||
size_ = new_size;
|
||||
return *this;
|
||||
}
|
||||
UnicodeString &operator + (wchar_t c) { return append(&c, 1); }
|
||||
UnicodeString &operator + (const wchar_t *str) { return append(str, wcslen(str)); }
|
||||
bool operator == (const wchar_t *str) const { return wcscmp(c_str(), str) == 0; }
|
||||
private:
|
||||
wchar_t *data_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
class RegistryKey
|
||||
{
|
||||
public:
|
||||
RegistryKey();
|
||||
RegistryKey(RegistryKey *owner, const wchar_t *name, bool is_real);
|
||||
~RegistryKey();
|
||||
RegistryKey *GetKey(const wchar_t *name) const;
|
||||
RegistryKey *AddKey(const wchar_t *name, bool is_real, bool *is_exists);
|
||||
bool DeleteKey(RegistryKey *key);
|
||||
const wchar_t *name() const { return name_; }
|
||||
UnicodeString full_name() const;
|
||||
void SetValue(wchar_t *name, uint32_t type, void *data, uint32_t size);
|
||||
bool DeleteValue(wchar_t *name);
|
||||
RegistryValue *GetValue(const wchar_t *name) const;
|
||||
bool is_real() const { return is_real_; }
|
||||
void set_is_wow(bool value) { is_wow_ = value; }
|
||||
RegistryKey *owner() const { return owner_; }
|
||||
RegistryKey *key(size_t index) const { return keys_[index]; }
|
||||
size_t keys_size() const { return keys_.size(); }
|
||||
RegistryValue *value(size_t index) const { return values_[index]; }
|
||||
size_t values_size() const { return values_.size(); }
|
||||
uint64_t last_write_time() const { return last_write_time_; }
|
||||
private:
|
||||
RegistryKey *GetChild(const wchar_t *name) const;
|
||||
RegistryKey *AddChild(const wchar_t *name, bool is_real, bool *is_exists);
|
||||
RegistryValue *AddValue(wchar_t *value_name);
|
||||
bool is_wow_node(const wchar_t *name) const;
|
||||
wchar_t *name_;
|
||||
RegistryKey *owner_;
|
||||
bool is_real_;
|
||||
bool is_wow_;
|
||||
vector<RegistryKey *> keys_;
|
||||
vector<RegistryValue *> values_;
|
||||
uint64_t last_write_time_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
RegistryKey(const RegistryKey &);
|
||||
RegistryKey &operator =(const RegistryKey &);
|
||||
};
|
||||
|
||||
class VirtualObjectList;
|
||||
class RegistryManager
|
||||
{
|
||||
public:
|
||||
RegistryManager(const uint8_t *data, HMODULE instance, const uint8_t *key, VirtualObjectList *objects);
|
||||
void HookAPIs(HookManager &hook_manager);
|
||||
void UnhookAPIs(HookManager &hook_manager);
|
||||
void BeginRegisterServer();
|
||||
void EndRegisterServer();
|
||||
NTSTATUS NtSetValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName, ULONG TitleIndex, ULONG Type, PVOID Data, ULONG DataSize);
|
||||
NTSTATUS NtDeleteValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName);
|
||||
NTSTATUS NtCreateKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG TitleIndex, PUNICODE_STRING Class, ULONG CreateOptions, PULONG Disposition);
|
||||
NTSTATUS NtQueryValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS NtOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
|
||||
NTSTATUS NtOpenKeyEx(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG OpenOptions);
|
||||
NTSTATUS NtDeleteKey(HANDLE KeyHandle);
|
||||
NTSTATUS NtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS NtEnumerateValueKey(HANDLE KeyHandle, ULONG Index, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS NtEnumerateKey(HANDLE KeyHandle, ULONG Index, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength);
|
||||
private:
|
||||
NTSTATUS TrueNtSetValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName, ULONG TitleIndex, ULONG Type, PVOID Data, ULONG DataSize);
|
||||
NTSTATUS TrueNtDeleteValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName);
|
||||
NTSTATUS TrueNtCreateKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG TitleIndex, PUNICODE_STRING Class, ULONG CreateOptions, PULONG Disposition);
|
||||
NTSTATUS TrueNtQueryValueKey(HANDLE KeyHandle, PUNICODE_STRING ValueName, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS TrueNtOpenKey(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
|
||||
NTSTATUS TrueNtOpenKeyEx(PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG OpenOptions);
|
||||
NTSTATUS TrueNtDeleteKey(HANDLE KeyHandle);
|
||||
NTSTATUS TrueNtQueryKey(HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS TrueNtEnumerateValueKey(HANDLE KeyHandle, ULONG Index, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS TrueNtEnumerateKey(HANDLE KeyHandle, ULONG Index, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS TrueNtQueryObject(HANDLE Handle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
|
||||
REGISTRY_DIRECTORY DecryptDirectory(const REGISTRY_DIRECTORY *directory_enc) const;
|
||||
RegistryKey *GetRootKey(HANDLE root, uint32_t *access, bool can_create);
|
||||
NTSTATUS QueryValueKey(RegistryValue *value, KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, PVOID KeyValueInformation, ULONG Length, PULONG ResultLength);
|
||||
NTSTATUS QueryKey(RegistryKey *key, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength);
|
||||
|
||||
HMODULE instance_;
|
||||
const uint8_t *data_;
|
||||
uint32_t key_;
|
||||
void *nt_set_value_key_;
|
||||
void *nt_delete_value_key_;
|
||||
void *nt_create_key_;
|
||||
void *nt_open_key_;
|
||||
void *nt_open_key_ex_;
|
||||
void *nt_query_value_key_;
|
||||
void *nt_delete_key_;
|
||||
void *nt_query_key_;
|
||||
void *nt_enumerate_value_key_;
|
||||
void *nt_enumerate_key_;
|
||||
RegistryKey cache_;
|
||||
VirtualObjectList *objects_;
|
||||
bool append_mode_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
RegistryManager(const RegistryManager &);
|
||||
RegistryManager &operator =(const RegistryManager &);
|
||||
};
|
||||
|
||||
#endif
|
1022
runtime/resource_manager.cc
Normal file
1022
runtime/resource_manager.cc
Normal file
File diff suppressed because it is too large
Load Diff
148
runtime/resource_manager.h
Normal file
148
runtime/resource_manager.h
Normal file
@ -0,0 +1,148 @@
|
||||
#ifndef RESOURCE_MANAGER_H
|
||||
#define RESOURCE_MANAGER_H
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
class CipherRC5;
|
||||
|
||||
struct RESOURCE_DIRECTORY {
|
||||
uint32_t NumberOfNamedEntries;
|
||||
uint32_t NumberOfIdEntries;
|
||||
// RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
|
||||
};
|
||||
|
||||
//#pragma warning(push)
|
||||
//#pragma warning(disable:4201) // named type definition in parentheses
|
||||
struct RESOURCE_DIRECTORY_ENTRY {
|
||||
union {
|
||||
struct {
|
||||
uint32_t NameOffset:31;
|
||||
uint32_t NameIsString:1;
|
||||
} /*DUMMYSTRUCTNAME*/;
|
||||
uint32_t Name;
|
||||
uint16_t Id;
|
||||
} /*DUMMYUNIONNAME*/;
|
||||
union {
|
||||
uint32_t OffsetToData;
|
||||
struct {
|
||||
uint32_t OffsetToDirectory:31;
|
||||
uint32_t DataIsDirectory:1;
|
||||
} /*DUMMYSTRUCTNAME2*/;
|
||||
} /*DUMMYUNIONNAME2*/;
|
||||
};
|
||||
//#pragma warning(pop)
|
||||
|
||||
struct RESOURCE_DATA_ENTRY {
|
||||
uint32_t OffsetToData;
|
||||
uint32_t Size;
|
||||
uint32_t CodePage;
|
||||
uint32_t Reserved;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
struct LDR_RESOURCE_INFO {
|
||||
LPWSTR Type;
|
||||
LPWSTR Name;
|
||||
WORD Language;
|
||||
};
|
||||
|
||||
class VirtualResource
|
||||
{
|
||||
public:
|
||||
VirtualResource(const RESOURCE_DATA_ENTRY *entry, uint32_t key);
|
||||
~VirtualResource();
|
||||
HGLOBAL Decrypt(HMODULE instance, uint32_t key);
|
||||
const RESOURCE_DATA_ENTRY *entry() const { return entry_; }
|
||||
HRSRC handle() const { return reinterpret_cast<HRSRC>(const_cast<IMAGE_RESOURCE_DATA_ENTRY *>(&handle_)); }
|
||||
private:
|
||||
const RESOURCE_DATA_ENTRY *entry_;
|
||||
IMAGE_RESOURCE_DATA_ENTRY handle_;
|
||||
uint8_t *address_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
VirtualResource(const VirtualResource &);
|
||||
VirtualResource &operator =(const VirtualResource &);
|
||||
};
|
||||
|
||||
class VirtualResourceList
|
||||
{
|
||||
public:
|
||||
~VirtualResourceList();
|
||||
VirtualResource *Add(const RESOURCE_DATA_ENTRY *entry, uint32_t key);
|
||||
void Delete(size_t index);
|
||||
size_t IndexByEntry(const RESOURCE_DATA_ENTRY *entry) const;
|
||||
size_t IndexByHandle(HRSRC handle) const;
|
||||
VirtualResource *operator [] (size_t index) const { return v_[index]; }
|
||||
size_t size() const { return v_.size(); }
|
||||
private:
|
||||
vector<VirtualResource *> v_;
|
||||
};
|
||||
|
||||
class ResourceManager
|
||||
{
|
||||
public:
|
||||
ResourceManager(const uint8_t *data, HMODULE instance, const uint8_t *key);
|
||||
~ResourceManager();
|
||||
|
||||
void HookAPIs(HookManager &hook_manager);
|
||||
void UnhookAPIs(HookManager &hook_manager);
|
||||
|
||||
HGLOBAL LoadResource(HMODULE module, HRSRC res_info);
|
||||
HRSRC FindResourceA(HMODULE module, LPCSTR name, LPCSTR type);
|
||||
HRSRC FindResourceExA(HMODULE module, LPCSTR type, LPCSTR name, WORD language);
|
||||
HRSRC FindResourceW(HMODULE module, LPCWSTR name, LPCWSTR type);
|
||||
HRSRC FindResourceExW(HMODULE module, LPCWSTR type, LPCWSTR name, WORD language);
|
||||
int LoadStringA(HMODULE module, UINT id, LPSTR buffer, int buffer_max);
|
||||
int LoadStringW(HMODULE module, UINT id, LPWSTR buffer, int buffer_max);
|
||||
NTSTATUS LdrFindResource_U(HMODULE module, const LDR_RESOURCE_INFO *res_info, ULONG level, const IMAGE_RESOURCE_DATA_ENTRY **entry);
|
||||
NTSTATUS LdrAccessResource(HMODULE module, const IMAGE_RESOURCE_DATA_ENTRY *entry, void **res, ULONG *size);
|
||||
BOOL EnumResourceNamesA(HMODULE module, LPCSTR type, ENUMRESNAMEPROCA enum_func, LONG_PTR param);
|
||||
BOOL EnumResourceNamesW(HMODULE module, LPCWSTR type, ENUMRESNAMEPROCW enum_func, LONG_PTR param);
|
||||
BOOL EnumResourceLanguagesA(HMODULE module, LPCSTR type, LPCSTR name, ENUMRESLANGPROCA enum_func, LONG_PTR param);
|
||||
BOOL EnumResourceLanguagesW(HMODULE module, LPCWSTR type, LPCWSTR name, ENUMRESLANGPROCW enum_func, LONG_PTR param);
|
||||
BOOL EnumResourceTypesA(HMODULE module, ENUMRESTYPEPROCA enum_func, LONG_PTR param);
|
||||
BOOL EnumResourceTypesW(HMODULE module, ENUMRESTYPEPROCW enum_func, LONG_PTR param);
|
||||
private:
|
||||
RESOURCE_DIRECTORY DecryptDirectory(const RESOURCE_DIRECTORY *directory_enc) const;
|
||||
RESOURCE_DIRECTORY_ENTRY DecryptDirectoryEntry(const RESOURCE_DIRECTORY_ENTRY *entry_enc) const;
|
||||
int CompareStringEnc(LPCWSTR name, LPCWSTR str_enc) const;
|
||||
LPWSTR DecryptStringW(LPCWSTR src_enc) const;
|
||||
LPSTR DecryptStringA(LPCWSTR src_enc) const;
|
||||
const RESOURCE_DIRECTORY *FindEntryById(const RESOURCE_DIRECTORY *directory, WORD id, DWORD dir_type);
|
||||
const RESOURCE_DIRECTORY *FindEntryByName(const RESOURCE_DIRECTORY *directory, LPCWSTR name, DWORD dir_type);
|
||||
const RESOURCE_DIRECTORY *FindEntry(const RESOURCE_DIRECTORY *directory, LPCWSTR name, DWORD dir_type);
|
||||
const RESOURCE_DIRECTORY *FindFirstEntry(const RESOURCE_DIRECTORY *directory, DWORD dir_type);
|
||||
const RESOURCE_DIRECTORY *FindResourceEntry(LPCWSTR type, LPCWSTR name, WORD language);
|
||||
HRSRC InternalFindResourceExW(HMODULE module, LPCWSTR type, LPCWSTR name, WORD language);
|
||||
HGLOBAL InternalLoadResource(HMODULE module, HRSRC res_info);
|
||||
LPWSTR InternalFindStringResource(HMODULE module, UINT id);
|
||||
int InternalLoadStringW(LPCWSTR res, LPWSTR buffer, int buffer_max);
|
||||
int InternalLoadStringA(LPCWSTR res, LPSTR buffer, int buffer_max);
|
||||
uint16_t DecryptWord(uint16_t value) const;
|
||||
|
||||
int TrueLoadStringA(HMODULE module, UINT id, LPSTR buffer, int buffer_max);
|
||||
int TrueLoadStringW(HMODULE module, UINT id, LPWSTR buffer, int buffer_max);
|
||||
NTSTATUS TrueLdrFindResource_U(HMODULE module, const LDR_RESOURCE_INFO *res_info, ULONG level, const IMAGE_RESOURCE_DATA_ENTRY **entry);
|
||||
NTSTATUS TrueLdrAccessResource(HMODULE module, const IMAGE_RESOURCE_DATA_ENTRY *entry, void **res, ULONG *size);
|
||||
|
||||
HMODULE instance_;
|
||||
uint32_t key_;
|
||||
CRITICAL_SECTION critical_section_;
|
||||
VirtualResourceList resources_;
|
||||
const uint8_t *data_;
|
||||
void *load_resource_;
|
||||
void *load_string_a_;
|
||||
void *load_string_w_;
|
||||
void *load_string_a_kernel_;
|
||||
void *load_string_w_kernel_;
|
||||
void *ldr_find_resource_u_;
|
||||
void *ldr_access_resource_;
|
||||
void *get_thread_ui_language_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
ResourceManager(const ResourceManager &);
|
||||
ResourceManager &operator =(const ResourceManager &);
|
||||
};
|
||||
|
||||
#endif
|
33
runtime/runtime.def
Normal file
33
runtime/runtime.def
Normal file
@ -0,0 +1,33 @@
|
||||
EXPORTS
|
||||
SetupImage
|
||||
FreeImage
|
||||
ExportedDecryptString
|
||||
ExportedFreeString
|
||||
ExportedLoadResource
|
||||
ExportedFindResourceA
|
||||
ExportedFindResourceExA
|
||||
ExportedFindResourceW
|
||||
ExportedFindResourceExW
|
||||
ExportedLoadStringA
|
||||
ExportedLoadStringW
|
||||
ExportedEnumResourceNamesA
|
||||
ExportedEnumResourceNamesW
|
||||
ExportedEnumResourceLanguagesA
|
||||
ExportedEnumResourceLanguagesW
|
||||
ExportedEnumResourceTypesA
|
||||
ExportedEnumResourceTypesW
|
||||
ExportedSetSerialNumber
|
||||
ExportedGetSerialNumberState
|
||||
ExportedGetSerialNumberData
|
||||
ExportedGetCurrentHWID
|
||||
ExportedActivateLicense
|
||||
ExportedDeactivateLicense
|
||||
ExportedGetOfflineActivationString
|
||||
ExportedGetOfflineDeactivationString
|
||||
ExportedIsValidImageCRC
|
||||
ExportedIsDebuggerPresent
|
||||
ExportedIsVirtualMachinePresent
|
||||
ExportedDecryptBuffer
|
||||
ExportedIsProtected
|
||||
CalcCRC
|
||||
LoaderData = loader_data
|
184
runtime/string_manager.cc
Normal file
184
runtime/string_manager.cc
Normal file
@ -0,0 +1,184 @@
|
||||
#include "objects.h"
|
||||
#include "common.h"
|
||||
#include "core.h"
|
||||
#include "crypto.h"
|
||||
#include "string_manager.h"
|
||||
|
||||
/**
|
||||
* exported functions
|
||||
*/
|
||||
|
||||
#ifdef VMP_GNU
|
||||
EXPORT_API const void * WINAPI ExportedDecryptString(const void *str) __asm__ ("ExportedDecryptString");
|
||||
EXPORT_API bool WINAPI ExportedFreeString(const void *str) __asm__ ("ExportedFreeString");
|
||||
#endif
|
||||
|
||||
const void * WINAPI ExportedDecryptString(const void *str)
|
||||
{
|
||||
StringManager *string_manager = Core::Instance()->string_manager();
|
||||
return string_manager ? string_manager->DecryptString(str) : str;
|
||||
}
|
||||
|
||||
bool WINAPI ExportedFreeString(const void *str)
|
||||
{
|
||||
StringManager *string_manager = Core::Instance()->string_manager();
|
||||
return string_manager ? string_manager->FreeString(str) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* StringManager
|
||||
*/
|
||||
|
||||
StringManager::StringManager(const uint8_t *data, HMODULE instance, const uint8_t *key)
|
||||
: data_(data), instance_(instance)
|
||||
{
|
||||
CriticalSection::Init(critical_section_);
|
||||
key_ = *(reinterpret_cast<const uint32_t *>(key));
|
||||
const STRING_DIRECTORY *directory_enc = reinterpret_cast<const STRING_DIRECTORY *>(data_);
|
||||
STRING_DIRECTORY directory = DecryptDirectory(directory_enc);
|
||||
size_ = directory.NumberOfEntries;
|
||||
strings_ = new VirtualString*[size_];
|
||||
memset(strings_, 0, sizeof(VirtualString *) * size_);
|
||||
}
|
||||
|
||||
StringManager::~StringManager()
|
||||
{
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
delete strings_[i];
|
||||
}
|
||||
delete [] strings_;
|
||||
CriticalSection::Free(critical_section_);
|
||||
}
|
||||
|
||||
STRING_DIRECTORY StringManager::DecryptDirectory(const STRING_DIRECTORY *directory_enc) const
|
||||
{
|
||||
STRING_DIRECTORY res;
|
||||
res.NumberOfEntries = directory_enc->NumberOfEntries ^ key_;
|
||||
return res;
|
||||
}
|
||||
|
||||
STRING_ENTRY StringManager::DecryptEntry(const STRING_ENTRY *entry_enc) const
|
||||
{
|
||||
STRING_ENTRY res;
|
||||
res.Id = entry_enc->Id ^ key_;
|
||||
res.OffsetToData = entry_enc->OffsetToData ^ key_;
|
||||
res.Size = entry_enc->Size ^ key_;
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t StringManager::IndexById(uint32_t id) const
|
||||
{
|
||||
const STRING_ENTRY *entry_enc = reinterpret_cast<const STRING_ENTRY *>(data_ + sizeof(STRING_DIRECTORY));
|
||||
|
||||
int min = 0;
|
||||
int max = (int)size_ - 1;
|
||||
while (min <= max) {
|
||||
int i = (min + max) / 2;
|
||||
STRING_ENTRY entry = DecryptEntry(entry_enc + i);
|
||||
if (entry.Id == id) {
|
||||
return i;
|
||||
}
|
||||
if (entry.Id > id) {
|
||||
max = i - 1;
|
||||
} else {
|
||||
min = i + 1;
|
||||
}
|
||||
}
|
||||
return NOT_ID;
|
||||
}
|
||||
|
||||
const void *StringManager::DecryptString(const void *str)
|
||||
{
|
||||
size_t id = reinterpret_cast<size_t>(str) - reinterpret_cast<size_t>(instance_);
|
||||
if ((id >> 31) == 0) {
|
||||
size_t i = IndexById(static_cast<uint32_t>(id));
|
||||
if (i != NOT_ID) {
|
||||
CriticalSection cs(critical_section_);
|
||||
VirtualString *string = strings_[i];
|
||||
if (!string) {
|
||||
const STRING_ENTRY *entry_enc = reinterpret_cast<const STRING_ENTRY *>(data_ + sizeof(STRING_DIRECTORY));
|
||||
string = new VirtualString(entry_enc + i, instance_, key_);
|
||||
strings_[i] = string;
|
||||
}
|
||||
return string->AcquirePointer();
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
size_t StringManager::IndexByAddress(const void *address) const
|
||||
{
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
VirtualString *string = strings_[i];
|
||||
if (string && string->address() == address)
|
||||
return i;
|
||||
}
|
||||
return NOT_ID;
|
||||
}
|
||||
|
||||
bool StringManager::FreeString(const void *str)
|
||||
{
|
||||
CriticalSection cs(critical_section_);
|
||||
|
||||
size_t i = IndexByAddress(str);
|
||||
if (i == NOT_ID)
|
||||
return false;
|
||||
|
||||
VirtualString *string = strings_[i];
|
||||
if (string->Release()) {
|
||||
delete string;
|
||||
strings_[i] = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* VirtualString
|
||||
*/
|
||||
|
||||
VirtualString::VirtualString(const STRING_ENTRY *entry_enc, HMODULE instance, uint32_t key)
|
||||
: use_count_(0)
|
||||
{
|
||||
STRING_ENTRY entry;
|
||||
entry.Id = entry_enc->Id ^ key;
|
||||
entry.OffsetToData = entry_enc->OffsetToData ^ key;
|
||||
entry.Size = entry_enc->Size ^ key;
|
||||
|
||||
size_ = entry.Size;
|
||||
address_ = new uint8_t[size_];
|
||||
uint8_t *source = reinterpret_cast<uint8_t *>(instance) + entry.OffsetToData;
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
address_[i] = static_cast<uint8_t>(source[i] ^ (_rotl32(key, static_cast<int>(i)) + i));
|
||||
}
|
||||
}
|
||||
|
||||
VirtualString::~VirtualString()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void VirtualString::Clear()
|
||||
{
|
||||
if (address_) {
|
||||
volatile uint8_t *ptrSecureZeroing = address_;
|
||||
while (size_--) *ptrSecureZeroing++ = 0;
|
||||
delete [] address_;
|
||||
address_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *VirtualString::AcquirePointer()
|
||||
{
|
||||
use_count_++;
|
||||
return address_;
|
||||
}
|
||||
|
||||
bool VirtualString::Release()
|
||||
{
|
||||
use_count_--;
|
||||
if (use_count_)
|
||||
return false;
|
||||
|
||||
Clear();
|
||||
return true;
|
||||
}
|
60
runtime/string_manager.h
Normal file
60
runtime/string_manager.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef STRING_MANAGER_H
|
||||
#define STRING_MANAGER_H
|
||||
|
||||
class CipherRC5;
|
||||
|
||||
struct STRING_DIRECTORY {
|
||||
uint32_t NumberOfEntries;
|
||||
// STRING_ENTRY Entries[];
|
||||
};
|
||||
|
||||
struct STRING_ENTRY {
|
||||
uint32_t Id;
|
||||
uint32_t OffsetToData;
|
||||
uint32_t Size;
|
||||
};
|
||||
|
||||
class VirtualString
|
||||
{
|
||||
public:
|
||||
VirtualString(const STRING_ENTRY *entry, HMODULE instance, uint32_t key);
|
||||
~VirtualString();
|
||||
uint8_t *AcquirePointer();
|
||||
bool Release();
|
||||
uint8_t *address() const { return address_; }
|
||||
private:
|
||||
void Clear();
|
||||
size_t use_count_;
|
||||
uint8_t *address_;
|
||||
size_t size_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
VirtualString(const VirtualString &);
|
||||
VirtualString &operator =(const VirtualString &);
|
||||
};
|
||||
|
||||
class StringManager
|
||||
{
|
||||
public:
|
||||
StringManager(const uint8_t *data, HMODULE instance, const uint8_t *key);
|
||||
~StringManager();
|
||||
const void *DecryptString(const void *str);
|
||||
bool FreeString(const void *str);
|
||||
private:
|
||||
STRING_DIRECTORY DecryptDirectory(const STRING_DIRECTORY *directory_enc) const;
|
||||
STRING_ENTRY DecryptEntry(const STRING_ENTRY *entry_enc) const;
|
||||
size_t IndexById(uint32_t id) const;
|
||||
size_t IndexByAddress(const void *address) const;
|
||||
const uint8_t *data_;
|
||||
HMODULE instance_;
|
||||
CRITICAL_SECTION critical_section_;
|
||||
VirtualString **strings_;
|
||||
uint32_t key_;
|
||||
size_t size_;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
StringManager(const StringManager &);
|
||||
StringManager &operator =(const StringManager &);
|
||||
};
|
||||
|
||||
#endif
|
290
runtime/utils.cc
Normal file
290
runtime/utils.cc
Normal file
@ -0,0 +1,290 @@
|
||||
#include "common.h"
|
||||
#include "utils.h"
|
||||
#include "loader.h"
|
||||
|
||||
#ifdef __unix__
|
||||
#ifdef __i386__
|
||||
__asm__(".symver memcpy,memcpy@GLIBC_2.0");
|
||||
__asm__(".symver clock_gettime,clock_gettime@LIBRT_2.12");
|
||||
#else
|
||||
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
|
||||
__asm__(".symver clock_gettime,clock_gettime@LIBRT_2.12");
|
||||
#endif
|
||||
extern "C"
|
||||
{
|
||||
void *__wrap_memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
#include <sys/poll.h>
|
||||
int __wrap___poll_chk (struct pollfd *fds, nfds_t nfds, int timeout, __SIZE_TYPE__ fdslen)
|
||||
{
|
||||
if (fdslen / sizeof (*fds) < nfds)
|
||||
abort();
|
||||
|
||||
return poll (fds, nfds, timeout);
|
||||
}
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
|
||||
long int __wrap___fdelt_chk (long int d)
|
||||
{
|
||||
if (d < 0 || d >= FD_SETSIZE)
|
||||
abort();
|
||||
return d / __NFDBITS;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" size_t __fread_chk (void *destv, size_t dest_size, size_t size, size_t nmemb, FILE *f)
|
||||
{
|
||||
if (size > dest_size) {
|
||||
//_chk_fail(__FUNCTION__);
|
||||
size = dest_size;
|
||||
}
|
||||
return fread(destv, size, nmemb, f);
|
||||
}
|
||||
|
||||
extern "C" int __isoc99_sscanf(const char *a, const char *b, va_list args)
|
||||
{
|
||||
int i;
|
||||
va_list ap;
|
||||
va_copy(ap, args);
|
||||
i = sscanf(a, b, ap);
|
||||
va_end(ap);
|
||||
return i;
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
extern "C" void __longjmp_chk (jmp_buf env, int val)
|
||||
{
|
||||
// TODO: Glibc's __longjmp_chk additionally does some sanity checks about
|
||||
// whether we're jumping a sane stack frame.
|
||||
longjmp(env, val);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ShowMessage(const VMP_CHAR *message)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
char file_name[PATH_MAX];
|
||||
uint32_t name_size = sizeof(file_name);
|
||||
const char *title;
|
||||
if (_NSGetExecutablePath(file_name, &name_size) == 0) {
|
||||
char *p = strrchr(file_name, '/');
|
||||
title = p ? p + 1 : file_name;
|
||||
} else {
|
||||
title = "Fatal Error";
|
||||
}
|
||||
|
||||
CFStringRef title_ref = CFStringCreateWithCString(NULL, title, kCFStringEncodingMacRoman);
|
||||
CFStringRef message_ref = CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8);
|
||||
CFOptionFlags result;
|
||||
|
||||
CFUserNotificationDisplayAlert(
|
||||
0, // no timeout
|
||||
kCFUserNotificationStopAlertLevel, //change it depending message_type flags ( MB_ICONASTERISK.... etc.)
|
||||
NULL, //icon url, use default, you can change it depending message_type flags
|
||||
NULL, //not used
|
||||
NULL, //localization of strings
|
||||
title_ref, //title text
|
||||
message_ref, //message text
|
||||
NULL, //default "ok" text in button
|
||||
NULL, //alternate button title
|
||||
NULL, //other button title, null--> no other button
|
||||
&result //response flags
|
||||
);
|
||||
|
||||
CFRelease(title_ref);
|
||||
CFRelease(message_ref);
|
||||
#elif defined(__unix__)
|
||||
char file_name[PATH_MAX] = {0};
|
||||
const char *title = file_name;
|
||||
ssize_t len = ::readlink("/proc/self/exe", file_name, sizeof(file_name)-1);
|
||||
if (len != -1) {
|
||||
for (ssize_t i = 0; i < len; i++) {
|
||||
if (file_name[i] == '/')
|
||||
title = file_name + i + 1;
|
||||
if (file_name[i] == '\'' || file_name[i] == '\\')
|
||||
file_name[i] = '"';
|
||||
}
|
||||
file_name[len] = '\0';
|
||||
} else {
|
||||
title = "Fatal Error";
|
||||
}
|
||||
std::string cmd_line = "zenity";
|
||||
cmd_line += " --error --no-markup --text='";
|
||||
cmd_line += title;
|
||||
cmd_line += ": ";
|
||||
char *message_buffer = strdup(message);
|
||||
char *msg_ptr = message_buffer;
|
||||
while (*msg_ptr)
|
||||
{
|
||||
if (*msg_ptr == '\'' || *msg_ptr == '\\')
|
||||
*msg_ptr = '"';
|
||||
msg_ptr++;
|
||||
}
|
||||
cmd_line += message_buffer;
|
||||
free(message_buffer);
|
||||
cmd_line += "'";
|
||||
int status = system(cmd_line.c_str());
|
||||
if (status == -1 || WEXITSTATUS(status) == 127)
|
||||
puts(message);
|
||||
#elif defined(WIN_DRIVER)
|
||||
DbgPrint("%ws\n", message);
|
||||
#else
|
||||
VMP_CHAR file_name[MAX_PATH + 1] = {0};
|
||||
const VMP_CHAR *title;
|
||||
if (GetModuleFileNameW(reinterpret_cast<HMODULE>(FACE_IMAGE_BASE), file_name, _countof(file_name) - 1)) {
|
||||
wchar_t *p = wcsrchr(file_name, L'\\');
|
||||
title = p ? p + 1 : file_name;
|
||||
} else {
|
||||
title = L"Fatal Error";
|
||||
}
|
||||
|
||||
HMODULE ntdll = GetModuleHandleA(VMProtectDecryptStringA("ntdll.dll"));
|
||||
typedef NTSTATUS(NTAPI tNtRaiseHardError)(NTSTATUS ErrorStatus, ULONG NumberOfParameters,
|
||||
ULONG UnicodeStringParameterMask, PULONG_PTR Parameters,
|
||||
ULONG ValidResponseOptions,
|
||||
HardErrorResponse *Response);
|
||||
if (tNtRaiseHardError *raise_hard_error = reinterpret_cast<tNtRaiseHardError *>(InternalGetProcAddress(ntdll, VMProtectDecryptStringA("NtRaiseHardError")))) {
|
||||
UNICODE_STRING message_str;
|
||||
UNICODE_STRING title_str;
|
||||
|
||||
InitUnicodeString(&message_str, (PWSTR)message);
|
||||
InitUnicodeString(&title_str, (PWSTR)title);
|
||||
|
||||
ULONG_PTR params[4] = {
|
||||
(ULONG_PTR)&message_str,
|
||||
(ULONG_PTR)&title_str,
|
||||
(
|
||||
(ULONG)ResponseButtonOK | IconError
|
||||
),
|
||||
INFINITE
|
||||
};
|
||||
|
||||
HardErrorResponse response;
|
||||
raise_hard_error(STATUS_SERVICE_NOTIFICATION | HARDERROR_OVERRIDE_ERRORMODE, 4, 3, params, 0, &response);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef VMP_GNU
|
||||
#elif defined(WIN_DRIVER)
|
||||
#else
|
||||
void *InternalGetProcAddress(HMODULE module, const char *proc_name)
|
||||
{
|
||||
// check input
|
||||
if (!module || !proc_name)
|
||||
return NULL;
|
||||
|
||||
// check module's header
|
||||
PIMAGE_DOS_HEADER dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(module);
|
||||
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
// check NT header
|
||||
PIMAGE_NT_HEADERS pe_header = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<uint8_t *>(module) + dos_header->e_lfanew);
|
||||
if (pe_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
// get the export directory
|
||||
uint32_t export_adress = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
if (!export_adress)
|
||||
return NULL;
|
||||
|
||||
uint32_t export_size = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
uint32_t address;
|
||||
uint32_t ordinal_index = -1;
|
||||
PIMAGE_EXPORT_DIRECTORY export_directory = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<uint8_t *>(module) + export_adress);
|
||||
|
||||
if (proc_name <= reinterpret_cast<const char *>(0xFFFF)) {
|
||||
// ordinal
|
||||
ordinal_index = static_cast<uint32_t>(INT_PTR(proc_name)) - export_directory->Base; //-V221
|
||||
// index is either less than base or bigger than number of functions
|
||||
if (ordinal_index >= export_directory->NumberOfFunctions)
|
||||
return NULL;
|
||||
// get the function offset by the ordinal
|
||||
address = (reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(module) + export_directory->AddressOfFunctions))[ordinal_index];
|
||||
// check for empty offset
|
||||
if (!address)
|
||||
return NULL;
|
||||
} else {
|
||||
// name of function
|
||||
if (export_directory->NumberOfNames) {
|
||||
// start binary search
|
||||
int left_index = 0;
|
||||
int right_index = export_directory->NumberOfNames - 1;
|
||||
uint32_t *names = reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(module) + export_directory->AddressOfNames);
|
||||
while (left_index <= right_index) {
|
||||
uint32_t cur_index = (left_index + right_index) >> 1;
|
||||
switch (strcmp((const char *)(reinterpret_cast<uint8_t *>(module) + names[cur_index]), proc_name)) {
|
||||
case 0:
|
||||
ordinal_index = (reinterpret_cast<WORD *>(reinterpret_cast<uint8_t *>(module) + export_directory->AddressOfNameOrdinals))[cur_index];
|
||||
left_index = right_index + 1;
|
||||
break;
|
||||
case 1:
|
||||
right_index = cur_index - 1;
|
||||
break;
|
||||
case -1:
|
||||
left_index = cur_index + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if nothing has been found
|
||||
if (ordinal_index >= export_directory->NumberOfFunctions)
|
||||
return NULL;
|
||||
// get the function offset by the ordinal
|
||||
address = (reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(module) + export_directory->AddressOfFunctions))[ordinal_index];
|
||||
if (!address)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if it is just a pointer - return it
|
||||
if (address < export_adress || address >= export_adress + export_size)
|
||||
return reinterpret_cast<FARPROC>(reinterpret_cast<uint8_t *>(module) + address);
|
||||
|
||||
// it is a forward
|
||||
const char *name = reinterpret_cast<const char *>(reinterpret_cast<uint8_t *>(module) + address); // get a pointer to the module's name
|
||||
const char *tmp = name;
|
||||
const char *name_dot = NULL;
|
||||
// get a pointer to the function's name
|
||||
while (*tmp) {
|
||||
if (*tmp == '.') {
|
||||
name_dot = tmp;
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
if (!name_dot)
|
||||
return NULL;
|
||||
|
||||
size_t name_len = name_dot - name;
|
||||
if (name_len >= MAX_PATH)
|
||||
return NULL;
|
||||
|
||||
// copy module name
|
||||
char file_name[MAX_PATH];
|
||||
size_t i;
|
||||
for (i = 0; i < name_len && name[i] != 0; i++) {
|
||||
file_name[i] = name[i];
|
||||
}
|
||||
file_name[i] = 0;
|
||||
|
||||
module = GetModuleHandleA(file_name);
|
||||
if (!module)
|
||||
return NULL;
|
||||
|
||||
// now the function's name
|
||||
// if it is not an ordinal, just forward it
|
||||
if (name_dot[1] != '#')
|
||||
return InternalGetProcAddress(module, name_dot + 1);
|
||||
|
||||
// is is an ordinal
|
||||
int ordinal = atoi(name_dot + 2);
|
||||
return InternalGetProcAddress(module, LPCSTR(INT_PTR(ordinal)));
|
||||
}
|
||||
#endif
|
23
runtime/utils.h
Normal file
23
runtime/utils.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
void ShowMessage(const VMP_CHAR *message);
|
||||
|
||||
#ifdef VMP_GNU
|
||||
#elif defined(WIN_DRIVER)
|
||||
HMODULE GetModuleHandleA(const char *name);
|
||||
#else
|
||||
void *InternalGetProcAddress(HMODULE module, const char *proc_name);
|
||||
|
||||
__forceinline void InitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
|
||||
{
|
||||
if (SourceString)
|
||||
DestinationString->MaximumLength = (DestinationString->Length = (USHORT)(wcslen(SourceString) * sizeof(WCHAR))) + sizeof(UNICODE_NULL);
|
||||
else
|
||||
DestinationString->MaximumLength = DestinationString->Length = 0;
|
||||
|
||||
DestinationString->Buffer = (PWCH)SourceString;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user