
Реверс-инжиниринговый обход драйвера ядра Easy Anti-Cheat, перехватывающий выделение памяти для подавления пакетов нарушений, с процедурами расшифровки отчётов и заметками по анализу.
Не мой код. Только для сохранения https://www.unknowncheats.me/forum/anti-cheat-bypass/503052-easy-anti-cheat-kernel-packet-fucker.html
Это Easy Anti-Cheat Kernel Packet Fucker (сокращённо EACKPFucker). Что это такое? По сути, пакеты через их драйвер режима ядра не будут им отправляться, а значит, ваши pasta pasta 2023 kdmapper FUD-обходы можно использовать без каких-либо проблем.
Ладно, ты меня заинтриговал. Как, чёрт возьми, это работает? Путём простого изменения одного адреса. А теперь давайте глубоко разберёмся, как на самом деле работает EAC.
С самого начала Easy Anti-Cheat должен фактически получить ваши данные, чтобы забанить вас. Эти пакеты отправляются через их канал Hydra и криптографически защищены. Это всё, что вам нужно знать для этого обхода, я не буду вдаваться в подробности об этом.
Давайте посмотрим, как это работает внутри их драйвера ядра, на примере случайного нарушения:

Не кажется ли вам это уязвимым? Потому что мне точно кажется.
Давайте взглянем на нашу первую функцию: kalloc_rt
Хм, ладно. Давайте перейдём в alloc_pool_with_tag
Он динамически импортирует ExAllocatePoolWithTag. Хмммм... Интересно, что произойдёт, если кто-то изменит этот qword на свою модифицированную функцию malloc... (да, это работает -- и поскольку вы изменяете записываемую секцию, EAC ни о чём не догадывается)
Ладно, теперь у нас есть контроль над выделением памяти. Круто! Что мы можем с этим сделать?
Рад, что вы спросили! Вот в чём дело: все пакеты из режима ядра имеют размер 33096i64.. иии ранее мы видели, что если память не выделяется, EAC просто.. игнорирует нарушение.
Ладно, скажем, кто-то просто.. сделал бы так:



---------------------------------------------------------------------------------------------------------------------------------------```C++ // report encryption looks like this (some parts may vary for each report, i believe they use key1, key2, key3 to use only 1 function for decryption) static report_t* encrypt(uint8_t* data, uint64_t size) {
report_t* packet = (report_t*)malloc(sizeof(report_t));
if (!packet) return nullptr;
uint32_t seed = 0x80BE5ED5 * ((uint64_t)&data >> 2);
memset(&packet->key1, 0, 0x8200);
packet->raw_size = 0;
packet->key1 = 0x66259F86; // gives key4?
packet->key2 = 0x21EBA81; // gives key5?
packet->key3 = 0xACE987AF; // gives key6?
packet->key4 = 0x50BFC583; // gives seed
packet->key5 = 0x3C61A927; // gives dynamic_key (from end)
packet->key6 = 0x70881859; // gives actual payload size
uint8_t* raw_data = packet->raw;
uint64_t raw_size = 24;
uint8_t* payload_data = packet->payload;
uint64_t payload_size = 0;
uint32_t dynamic_key = seed ^ 0x6957FDB6;
while (payload_size < size && payload_size < 0x8000) {
uint32_t a = (dynamic_key << 0xD) ^ dynamic_key;
uint32_t b = (a >> 0x11) ^ a;
uint32_t c = (b << 0x5) ^ b;
uint32_t d = _rotr(c, 2);
uint8_t shift = 8 * (payload_size & 3);
payload_data[payload_size] = data[payload_size] ^ (d >> shift);
dynamic_key = data[payload_size] ^ d;
payload_size++;
raw_size++;
}
uint64_t aligned_size = (raw_size + 0xFF) & ~0xFF; // align up by 0x100
while (raw_size < aligned_size) {
dynamic_key *= 0x80BE5ED5;
raw_data[raw_size++] = dynamic_key;
}
packet->key4 ^= seed;
packet->key5 ^= dynamic_key;
packet->key6 ^= payload_size;
packet->raw_size = raw_size;
return packet;
}
// thus my decryption looks like this static void decrypt(report_t* packet) {
uint32_t seed = packet->key4 ^ 0x50BFC583;
uint32_t dynamic_key = seed ^ 0x6957FDB6;
//uint32_t dynamic_key = packet->key5 ^ 0x3C61A927;
uint8_t* payload_data = packet->payload;
uint32_t payload_size = packet->key6 ^ 0x70881859;
for (uint32_t i = 0; i < payload_size; i++) {
uint32_t a = (dynamic_key << 0xD) ^ dynamic_key;
uint32_t b = (a >> 0x11) ^ a;
uint32_t c = (b << 0x5) ^ b;
uint32_t d = _rotr(c, 2);
uint8_t shift = 8 * (i & 3);
payload_data[i] ^= (d >> shift);
dynamic_key = payload_data[i] ^ d;
}
}
после выгрузки некоторых отчётов и расшифровки: