
مكتبة POC بسيطة لتنفيذ استدعاءات عشوائية عبر تمريرها عبر NdrServerCall2 أو ما شابه
لإنشاء طريقة عامة لتنفيذ الكود المحلي والبعيد، صممنا طريقة غامضة نسبياً لتنفيذ الكود، والتي نشير إليها داخلياً باسم RpcCraft (Self) وRpcExec (Remote Process). تستغل هذه التقنية منهجية معروفة جيداً بين مطوري الاستغلال، وهي إساءة استخدام استدعاءات خادم RPC (استدعاء الإجراء البعيد) مثل NdrServerCall2 أو NdrServerCallAll لتنفيذ كود عشوائي.
داخل RPCRT4.dll، يتم تنفيذ دوال مثل NdrServerCall2 وNdrServerCallAll وNdrServerCallNdr64 (اسم مستعار لـ NdrServerCallAll) كأغلفة لاستدعاء الدوال ديناميكياً بما يتعلق بوظائف الخادم. تأخذ هذه الدوال وسيطاً واحداً، وهو مؤشر إلى بنية RPC_MESSAGE.
بنية RPC_MESSAGE:
typedef struct _RPC_MESSAGE {
RPC_BINDING_HANDLE Handle;
unsigned long DataRepresentation;
void *Buffer;
unsigned int BufferLength;
unsigned int ProcNum;
PRPC_SYNTAX_IDENTIFIER TransferSyntax;
void *RpcInterfaceInformation;
void *ReservedForRuntime;
RPC_MGR_EPV *ManagerEpv;
void *ImportContext;
unsigned long RpcFlags;
} RPC_MESSAGE, *PRPC_MESSAGE;
لتهيئة بيئة التشغيل دون ربط بخدمة، يتم استخدام دالة PerformRpcInitialization. تقوم هذه الدالة داخلياً بتهيئة البنى اللازمة دون الحاجة إلى ربط يدوي.
تم تطوير هذا الإصدار العام من التقنية كإثبات للمفهوم (POC) لإظهار الجدوى، وهو يولّد حالياً استثناءً على NdrGetBuffer بسبب عدم وجود مقبض ربط (Binding Handle). يمكن التعامل مع هذا بعدة طرق، لكن التنفيذ الحالي يقوم بما يلي:
int FetchReturnValue(const PEXCEPTION_POINTERS ExceptionInfo) {
ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
g_ReturnValue = (PVOID)ExceptionInfo->ContextRecord->Rax;
return EXCEPTION_CONTINUE_EXECUTION;
}
استدعاء RPC محمي بواسطة CFG، مما يعني أنه من أجل تحقيق تنفيذ كامل وغير مقيد للكود، من الضروري إما تحديد الهدف كصالح باستخدام SetProcessValidCallTargets أو تصحيح RpcInvokeCheckICall.
يعرض مشروع RpcProxyInvoke تقنية بديلة يمكن إساءة استخدامها لتنفيذ مكتبة بأسلوب RailGun. على الرغم من أن التنفيذ العام ليس مثالياً، إلا أنه يمكن أن يكون أساساً لمزيد من التطوير.
هذا المشروع مرخص بموجب رخصة MIT - راجع ملف LICENSE للحصول على التفاصيل.