
تجاوز مُعاد هندسته عكسياً لبرنامج تشغيل نواة 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;
}
}
بعد إفراغ بعض التقارير وفك التشفير: