
تنفيذ ملفات ويندوز التنفيذية غير المُدارة في بيقون CobaltStrike
Inline-Execute-PE هي مجموعة من ملفات Beacon Object Files (BOFs) وسكريبت Aggressor لـ CobaltStrike، تتيح للمشغلين تحميل برامج ويندوز القابلة للتنفيذ غير المُدارة (unmanaged executables) إلى ذاكرة Beacon وتنفيذها، واسترجاع المخرجات وعرضها في وحدة تحكم Beacon.
يمكّن ذلك المشغلين من استخدام العديد من الأدوات الخارجية (Mimikatz, Dsquery, أدوات Sysinternals, إلخ) دون الحاجة إلى إسقاطها على القرص، أو إعادة تنسيقها إلى كود مستقل عن الموضع (position independent code) باستخدام أداة مثل Donut، أو إنشاء عملية جديدة لتشغيلها.
يتم تعيين هذه البرامج القابلة للتنفيذ في ذاكرة Beacon بحيث يمكن تشغيلها مرارًا دون الحاجة إلى إرسالها عبر الشبكة، أو تخصيص ذاكرة جديدة، أو إنشاء عملية conhost.exe جديدة في كل مرة.
البرامج القابلة للتنفيذ المحملة في Beacons يمكن الوصول إليها وتشغيلها من قبل جميع عملاء CobaltStrike المتصلين بخادم CobaltStrike Team Server.
تم تصميم Inline-Execute-PE لـ Beacons 64 بت وبرامج ويندوز C أو C++ القابلة للتنفيذ 64 بت والمجمعة باستخدام Mingw أو Visual Studio. لا يدعم هذا المشروع برامج 32 بت أو برامج 64 بت المكتوبة بلغة أخرى أو المترجمة باستخدام مترجم مختلف.

استنساخ المستودع، وتشغيل make اختياريًا لإعادة ترجمة الـ BOFs.
قم بتحميل Inline-Execute-PE.cna إلى عميل CobaltStrike. تأكد من أن الدليل الذي يعمل منه CobaltStrike قابل للكتابة بواسطة المستخدم الخاص بك؛ يقوم Inline-Execute-PE بإنشاء ملف نصي هناك (petable.txt) لضمان توفر البيانات المطلوبة لتشغيل Inline-Execute-PE.
يتكون Inline-Execute-PE من 3 أوامر موجهة للهدف تقوم بتشغيل الـ BOFs، و3 أوامر داخلية تتعامل مع بنية بيانات المشروع:
موجهة للهدف:
بنية البيانات الداخلية:
peload هو البداية لـ Inline-Execute-PE. يُستخدم هذا الأمر لتحميل PE في ذاكرة Beacon. يقوم بالإجراءات الرئيسية التالية:
perun هو الخطوة الثانية في Inline-Execute-PE. يقوم بالإجراءات الرئيسية التالية:
يتم استدعاء peunload لإزالة الـ PE من ذاكرة Beacon عندما ينتهي المشغل منه أو يرغب في تحميل PE مختلف. يقوم بالإجراءات الرئيسية التالية:
يتم استخدام petable لعرض معلومات حول جميع الـ PEs المحملة حاليًا في Beacons.
كل عميل CobaltStrike لديه petable خاص به؛ يبذل Inline-Execute-PE جهودًا كبيرة لضمان تزامن بياناته بين جميع عملاء CobaltStrike المتصلين بحيث يمكن لجميع المشغلين استخدام الـ PEs. لمزيد من المعلومات، راجع "اعتبارات التصميم والتعليقات".

يتم استخدام peconfig لتكوين الخيارات المتعلقة بكيفية عمل Inline-Execute-PE. الخياران الحاليان اللذان يمكن تغييرهما هما:
يمكن استخدام pebroadcast لنشر محتويات petable الخاص بأحد العملاء يدويًا إلى جميع عملاء CobaltStrike الآخرين المتصلين.
سيقوم كل عميل CobaltStrike آخر بتحديث petable الخاص به بالبيانات المنشورة. لا ينبغي أن يكون هذا ضروريًا أبدًا، لكن الميزة موجودة فقط في حالة الحاجة.
استخدم peload لتحميل PE في ذاكرة Beacon

بدلاً من ذلك، إذا كان هناك PE على الجهاز الهدف ترغب في استخدامه دون إنشاء عملية جديدة، فقدم المسار والمفتاح --local

اتصل بـ perun، مررًا أي وسائط إلى الـ PE المحمل

يجب الهروب من علامات الاقتباس المزدوجة في الوسائط باستخدام الخطوط المائلة العكسية

إذا اكتشفت أن PE يسبب مشاكل عند محاولة تحرير الـ DLLs أثناء التفريغ، استخدم peconfig لضبط unloadlibraries على false

بمجرد الانتهاء من استخدام PE، اتصل بـ peunload لتنظيفه من Beacon

يمكن الآن تحميل PE مختلف إلى Beacon

يجب أن تكون حذرًا بشأن وسائط سطر الأوامر التي تمررها إلى الـ PE؛ بعض الـ PEs ستعطل تمامًا إذا أعطيت وسائط خاطئة، بينما سيعمل البعض الآخر إلى ما لا نهاية مما يؤدي إلى عدم عودة Beacon أبدًا على الرغم من أن العملية لا تزال قيد التشغيل.
يمكن رؤية ذلك مع Mimikatz.exe عندما لا يتم تحديد 'exit' في نهاية قائمة الوسائط

...

سيقوم Inline-Execute-PE بإنهاء سلسلة محادثات الـ PE الجاري تشغيله بعد الوصول إلى قيمة المهلة المحددة. يتيح ذلك لـ Beacon استئناف الاتصالات العادية (لا يتصل Beacon مرة أخرى حتى يكتمل تنفيذ BOF perun). بينما لا يزال من الممكن استخدام أوامر CobaltStrike العادية و BOFs الأخرى في هذا Beacon، فإن Inline-Execute-PE معطل الآن؛ عندما يتم إنهاء PE قيد التشغيل بهذه الطريقة، يبدو أنه يعطل stdout و stderr في عملية Beacon، ولا تعمل الـ PEs المحملة لاحقًا بشكل صحيح.
لا يزال من الممكن (ويجب) تفريغ الـ PE من ذاكرة Beacon، ومع ذلك فإن النظر إلى petable سيظهر أن هذا Beacon لم يعد بإمكانه تحميل PEs إضافية إليه. 
من الضروري أن تختبر الـ PEs التي ترغب في تشغيلها باستخدام Inline-Execute-PE، وأن تكون حذرًا عند تمرير وسائط سطر الأوامر إلى perun. بعض الـ PEs أكثر تسامحًا من غيرها.
فيما يلي بعض الملاحظات دون ترتيب معين والتي تم إجراؤها أثناء الاختبار والتطوير بخصوص بعض الـ PEs التي قد يرغب المستخدمون في تحميلها إلى Beacon.
تشمل IOC's المرتبطة بـ Inline-Execute-Pe على سبيل المثال لا الحصر:
لم أقم باختبار كامل للبطارية ضد EDR أثناء التطوير، جزئيًا بسبب الكسل وجزئيًا لعدم توفر بيئة اختبار. ومع ذلك، تم اختباره ضد أحدث إصدار من Windows Defender (وهو في تجربتي منتج AV جيد جدًا).
Mimikatz.exe هو على الأرجح أكثر PE اشتباهًا ومعروفًا يتبادر إلى الذهن كمرشح للاستخدام مع Inline-Execute-PE. وجدت أن قدرة Windows Defender على اكتشاف Mimikatz الجاري تشغيله باستخدام Inline-Execute-PE تعتمد على العملية التي يعمل فيها Beacon.
سيتم اكتشاف Beacon يعمل في برنامج مستقل (فكر في beacon.exe مع Artifact Kit بحيث يمكنه التنفيذ والعمل بشكل طبيعي عبر Defender) عند استخدام Mimikatz.exe مع Inline-Execute-PE.
لن يتم اكتشاف Beacon يعمل في عملية ويندوز (محقون في Explorer.exe أو notepad.exe إلخ أو تحميل DLL بشكل جانبي في عملية شرعية) عند استخدام Mimikatz.exe مع Inline-Execute-PE.
فيما يتعلق بـ EDRs التي تقوم بـ userland hooking، كما قلت لم أختبر ولكن لدي الأفكار العامة التالية:
نظرًا لأن الـ PE يعمل داخل عملية Beacon، والتي من المفترض أنك قد أزلت فيها/أنعشت NTDLL بالفعل، أعتقد أنه لا ينبغي أن تواجه مشاكل كبيرة مع استدعاءات API التي يقوم بها الـ PE والتي يتم وضع علامة عليها. لا تزال نفس المشكلات المتعلقة بما يفعله الـ PE فعليًا (لمس العمليات، تغيير مفاتيح التسجيل، إلخ) سارية.
قبل بضعة أشهر عثرت على RunPE-In-Memory وفكرت في محاولة تحويله إلى BOF لـ CobaltStrike. الرحلة التي تلت ذلك كانت أكثر تعقيدًا واستغرقت وقتًا أطول بكثير مما كان متوقعًا. كان هذا المشروع صعبًا بشكل خاص لأنه ليس أداة قائمة بذاتها بحد ذاتها، بل هو أداة تستخدم لتشغيل أدوات أخرى. يتطلب هذا قدرًا كبيرًا من المرونة والجهد باتجاه التوافق مع مجموعة واسعة من الـ PEs وجميع الطرق المختلفة التي قد تحقق بها تلك الـ PEs نفس المهمة (الحصول على الوسائط، الإنهاء، إلخ).
في البداية، تم تصور Inline-Execute-PE كـ BOF متكامل، مسؤول عن تحميل وتنفيذ وتحرير PE في Beacon. بعد حوالي 3 أسابيع من المشروع، كنت قد أكملت حوالي 75% من برهان المفهوم (POC)، وجدت Pezor الذي تم إصداره منذ حوالي 1.5 سنة وكان يقوم بالفعل بكل ما كنت أحاول فعله تقريبًا؛ الفرق الرئيسي هو أن Pezor كان يستدعي Donut تحت الغطاء لتحويل الـ PE إلى شيل كود، بدلاً من تعيين الـ PE الأصلي يدويًا في الذاكرة.
كان هذا الاكتشاف مرحبًا به من ناحية ومخيبًا للآمال من ناحية أخرى؛ كان من الرائع وجود مشروع ناضج يمكن استلهام الأفكار منه ومساعدتي في تجاوز بعض النقاط الصعبة في الكود الخاص بي، ولكن كان محبطًا أنني كنت أعيد اختراع العجلة دون علمي. بعد القراءة عن Pezor والتفكير في تصميمه، وبعض الأمور المتعلقة بحرفية العمل (tradecraft)، والاحتياجات التشغيلية لمؤسستي، قمت بتغيير مسار Inline-Execute-PE إلى ما تراه اليوم. كان هذا القرار مدفوعًا بعدة عوامل سيتم مناقشتها أدناه، بالإضافة إلى بعض خيارات التصميم الأكثر فضولًا التي ربما أثارت الدهشة لدى أولئك الذين قرأوا حتى الآن.
عند فحص خبرتي التشغيلية، توصلت إلى حالات وأدوات متعددة حيث كنت بحاجة إلى تشغيل الأداة بشكل متكرر؛ مع Pezor، يجب على المشغل إرسال الـ PE بشكل متكرر عبر الشبكة، وإنشاء conhost.exe، وتخصيص ذاكرة جديدة في Beacon، إلخ، مما بدا لي غير مرغوب فيه عند التفكير في AV/EDR. قادني هذا التفكير إلى فكرة "تحميل" PE في Beacon، على غرار كيفية تحميل .PS1 في Beacon للاستخدام المتكرر. يتم إنشاء conhost.exe عند تحميل الـ PE لأول مرة ويستمر طالما أن الـ PE محمل في الذاكرة؛ وبالمثل، يتم تخصيص ذاكرة جديدة للـ PE مرة واحدة عند تحميله لأول مرة، وبالطبع تتجنب الحاجة إلى إرسال الـ PE عبر الشبكة في كل مرة تريد استخدامه. النموذج الذي اعتمده Inline-Execute-Pe ليس خالياً من العيوب، والتي حاولت معالجتها بدرجات متفاوتة من النجاح.
يجب أن يلفت الانتباه خيار التصميم المتمثل في أن Inline-Execute-Pe يقوم بتعيين الـ PE في Beacon مرتين. هذا بالتأكيد ليس مرغوبًا أو خيارًا اتخذته عن طيب خاطر، بل وُلد من الضرورة. كما ذكرنا سابقًا، يجب على Inline-Execute-Pe ربط العديد من الوظائف المتعلقة بوسائط سطر الأوامر في الـ PE. نظرًا لأن الـ PE المُخطط يعمل داخل عملية Beacon، سيحاول الـ PE استخدام وسائط سطر الأوامر المحددة في قسم PROCESS_PARAMETERS من PEB؛ لتجاوز ذلك، عندما يستدعي الـ PE إحدى الوظائف المختلفة التي تسترجع وسائط سطر الأوامر، يجب علينا توجيه الـ PE إلى وظائفنا المخصصة حيث يمكننا تقديم الوسائط المقصودة كما تم تمريرها من CobaltStrike باستخدام perun.
يعمل هذا بشكل جيد، لكن خلال التطوير لاحظت شيئًا غريبًا مع العديد من الـ PEs المختلفة. في المرة الأولى التي يتم فيها تشغيل الـ PE، تم استدعاء الوظيفة المخصصة التي قدمناها لـ IAT الخاصة بالـ PE بشكل صحيح، ولكن في جميع المرات اللاحقة التي تم فيها تشغيل الـ PE وتم تقديم وسائط مختلفة، لم يستدعي الـ PE الوظيفة المخصصة وبالتالي لم يتلق الوسائط الممررة من CobaltStrike. لست متأكدًا مما يحدث بالفعل تحت الغطاء، لكنني أميل إلى الاعتقاد أنه بعد تشغيل الـ PE مرة واحدة، يقوم بنسخ وسائط سطر الأوامر في مكان ما في الذاكرة، وفي عمليات التشغيل اللاحقة ينظر إلى ذلك الموقع في الذاكرة أولاً قبل استدعاء الوظائف المرتبطة لاسترجاع وسائط سطر الأوامر كما فعل في المرة الأولى. لقد دعمت هذه النظرية عن طريق استرجاع الموقع في الذاكرة حيث يوجد مؤشر لمؤشر آخر لمصفوفة المؤشرات التي تحتوي على الوسائط، وتعديل هذا الموقع يدويًا في الذاكرة ليحتوي على المؤشر الصحيح في كل تشغيل. نجح هذا مع وظائف __getmainargs و __wgetmainargs، لكن الـ PEs الأخرى تستدعي وظائف بديلة مثل __p___argv و __p___argc والتي لم تعمل معها هذه الطريقة.
لكي أتمكن من "إعادة ضبط" الـ PE إلى حالة يستدعي فيها الوظائف المرتبطة فعليًا لجلب الوسائط، لجأت إلى إنشاء نسخة ثانية من الـ PE في الذاكرة أثناء peload. هذه النسخة مشفرة أيضًا بـ XOR وتجلس بحماية RX طوال دورة حياة Inline-Execute-PE، ويتم استخدامها ببساطة لاستبدال نسخة الـ PE التي يتم تنفيذها فعليًا باستخدام perun. كما ذكرنا، إنه ليس حلاً مثاليًا، لكنه حل شامل يغطي جميع الـ PEs دون الحاجة إلى الضياع في التفاصيل الدقيقة لمحاولة التوصل إلى حل لجميع الـ PEs المختلفة وواجهات برمجة التطبيقات المختلفة التي تستخدمها.
مع أن أحد أهم نقاط البيع لـ Inline-Execute-Pe هو أنه يمكنك تشغيل الأدوات دون إنشاء عمليات جديدة، فإنها ضربة قوية لدرجة أنني مضطر إلى ... إنشاء عملية جديدة (conhost.exe) للقيام بذلك. يأتي هذا المطلب من حقيقة أن التدفقات القياسية (stdin/stdout/stderr) لا يتم تهيئتها في برامج ويندوز ما لم يكن هناك وحدة تحكم (console). في حالتنا لا نحتاج إلى وحدة التحكم على الإطلاق؛ يتم إعادة توجيه التدفقات القياسية إلى أنبوب مجهول والتقاطها بهذه الطريقة، ولكن بدون conhost لا يتم تهيئة التدفقات ولا يمكن إعادة توجيهها.
يتعامل Inline-Execute-Pe مع مشكلة conhost بنفس الطريقة التي يتعامل بها Pezor، حيث يستدعي AllocConsole ثم يخفيها على الفور عن العرض باستخدام ShowWindow. على جهاز افتراضي يعمل بنظام Windows 11 مع 8 جيجابايت من ذاكرة الوصول العشوائي، لا أرى أبدًا نافذة وحدة التحكم تومض ثم تختفي، لكن المسافة المقطوعة ستختلف بناءً على النظام الهدف.
تحدثت مع مطور يعمل على C2 تجاري متقدم جدًا أصدر مؤخرًا ما يعادل محليًا (حسنًا، إصدار أكثر تقدمًا بكثير) من Inline-Execute-Pe، وأخبرني أنهم تمكنوا من تجنب إنشاء conhost.exe عن طريق "خداع ويندوز لتعتقد أن لديها وحدة تحكم". مع هذه المعلومة، قضيت حوالي أسبوع في البحث في الإنترنت عن وثائق حول كيفية تفاعل برامج ويندوز مع conhost، محاولاً تتبع استدعاءات API المرتبطة بوظائف الكتابة ووحدة التحكم في WinDBG، وحتى فحص شفرة مصدر Windows Terminal المتاحة بشكل مدهش على Github. بينما تعلمت الكثير عن PEB والأشياء المتعلقة بالتدفق القياسي، خرجت من الجانب الآخر من هذا خالي الوفاض. أشتبه في أن الطريق إلى الأمام قد يتضمن تصحيح وظائف معينة متعلقة بوحدة التحكم في kernel32 لكني لا أعرف. أنا صادقًا أشعر بخيبة أمل كبيرة لعدم تمكني من إيجاد حل هنا، ولكن كونني علمت نفسي بنفسي وفقط بضع سنوات في مسيرتي المهنية، فمن المحتمل أن يكون متوقعًا.### مهلة PE والإنقاذ جميع الذين حاولوا كتابة BOF يعلمون أنه رغم كل المزايا المصاحبة لها، يكمن خطر كبير في حقيقة أن خطأ أو تعطل في BOF الخاص بك يمكنه بل وسيقتل Beacon الخاص بك. ويتضاعف الخطر في هذا المشروع بسبب طبيعة مقدار التحكم الذي يتمتع به المستخدمون في البيانات التي يتم تمريرها إلى Inline-Execute-PE وقلة إجراءات السلامة التي يمكنني كمطور وضعها بسهولة أو بشكل موثوق. يمكن للمستخدمين مثلاً تعطيل Beacon الخاص بهم عن طريق تحميل PE خاص بمعمارية x86 في Beacon بمعمارية x64، أو بشكل أكثر شيوعاً عن طريق تمرير وسائط غير صحيحة إلى PE المُعيّن كما أشرت سابقًا. بينما لا أستطيع منع المستخدمين من تعطيل Beacons الخاصة بهم بوسائط خاطئة لـ PE الخاصة بهم، يمكنني محاولة إنقاذ Beacon الخاص بهم في حالة تشغيل PE بشكل لا نهائي، كما في حالة Mimikatz عندما لا يتم تحديد 'exit'.
من الناحية المثالية، أود أن أكون قادرًا على إيقاف تنفيذ PE، مما يسمح لـ Beacon باستئناف وظيفته الطبيعية، ثم السماح للمستخدم فورًا بإعادة المحاولة مع الوسائط الصحيحة (على أمل) هذه المرة. عمليًا، وجدت أن إنهاء PE يبدو أنه يكسر FILE* المرتبطة بـ stdout/stderr، وحتى تفريغ PE بالكامل ثم تحميله من جديد لا يحل هذه المشكلة؛ فهي معطلة على مستوى العملية بأكملها.
لإنهاء PE الذي يستمر في التشغيل بعد تجاوز خيار 'timeout'، يتم استدعاء TerminateThread على المعالج الذي تم إرجاعه من CreateThread. هذا لا يسمح للخيط بالخروج بأمان من أي شيء، لذلك من المنطقي أن بعض الأشياء قد تنكسر. حاولت التخفيف من ذلك عن طريق تطبيق اختطاف الخيوط، بهدف تعليق خيط PE وتوجيه تنفيذه إلى API ExitThread(). كان الأمل هنا أنه إذا كان الخيط هو الذي بدأ إجراءات الخروج (بدلاً من إنهائه بالقوة من الخارج)، فقد يؤدي ذلك إلى استمرار عمل stdout/stderr، لكن انتهى بي الأمر بنفس المشكلة (بالإضافة إلى عدم القدرة على تعليق خيط PE في حالة Mimikatz).
نظرًا لعدم تمكني من تخفيف هذه المشكلة، استقررت ببساطة على منع المستخدمين من الاستمرار في تشغيل PE أو تحميل PEs إضافية في Beacon المتأثر (مما سيؤدي إلى تعطل). هذه حالة أخرى حيث يقصر Inline-Execute-PE عن المستوى الذي أريده، لكنني اقتنعت بحقيقة أن المشغل سيظل على الأقل يحتفظ بـ Beacon الخاص به ويمكنه استخدامه للوظائف العادية.
كان الجزء الصعب في هذا المشروع هو ضمان توفر PEs المُحمّلة في Beacons لجميع عملاء CobaltStrike المتصلين بخادم الفريق. يتم تخزين بيانات Inline-Execute-PE في هياكل تم إنشاؤها بواسطة Inline-Execute-PE.cna، والتي يجب تحميلها في كل عميل يرغب في استخدام الأداة؛ ونتيجة لذلك، تعيش هياكل البيانات هذه داخل كل عميل، وليس على خادم الفريق. إذا كانت هذه البيانات موجودة في موقع مركزي واحد (خادم الفريق) لكان من السهل استرجاعها من كل عميل وسيكون هذا الموضوع برمته غير ذي أهمية؛ لو قام فريق CobaltStrike بدمج إمكانية مثل Inline-Execute-PE رسميًا في CobaltStrike، فأنا متأكد أنهم سيسلكون هذا الاتجاه. ولكن نظرًا لأن هذه إضافة مجتمعية، فإننا نتعامل بما لدينا.
هناك عدة سيناريوهات مختلفة يجب أن نقلق بشأنها فيما يتعلق بضمان حصول كل عميل CobaltStrike على أحدث البيانات الدقيقة حول PEs المُحمّلة في Beacons:
تم اتخاذ نهج متعدد الجوانب لمعالجة هذه السيناريوهات. للتعامل مع حالة اتصال عميل CobaltStrike واحد فقط بخادم الفريق (وبالتالي هو الكيان الوحيد الذي لديه بيانات petable)، في كل مرة يقوم العميل بتعديل petable (peload، peconfig، peunload، إلخ)، فإنه يكتب أيضًا محتويات petable الخاصة به إلى ملف نصي محلي موجود في دليل CobaltStrike. إذا خرج العميل/أعاد التشغيل، أو عند إعادة تحميل Inline-Execute-PE.cna، فإنه سيحاول أولاً القراءة من ملف petable.txt المحلي لتعبئة petable في الذاكرة.
عندما يكون عدة عملاء متصلين بخادم الفريق وينضم عميل جديد (وفقاً لسجل الأحداث)، يقوم كل عميل بجلب قائمة بجميع المستخدمين المتصلين بخادم الفريق وفرزها أبجديًا. يتم اختيار العميل الأول في تلك القائمة كـ "بث" العميل، وبعد الانتظار لمدة 5 ثوانٍ (للسماح للعميل الجديد بالتهيئة وقراءة ملف petable.txt المحلي الخاص به)، سيرسل رسائل (إجراءات) في سجل الأحداث لكل إدخال في petable الخاصة به. جميع العملاء (باستثناء العميل الذي يبث) سيقرؤون هذه الرسائل ويحدّثون petables الخاصة بهم بمعلومات البث؛ يتضمن ذلك تحديث الإدخالات الحالية بالإضافة إلى إضافة أي إدخالات إضافية لا تحتويها petables الخاصة بهم.
تعتمد العمليات العادية التي تتضمن Inline-Execute-PE أيضًا على إرسال رسائل في سجل الأحداث. عندما يقوم العميل A بتشغيل peload، يتم بث رسالة تحتوي على جميع معلومات petable ذات الصلة؛ يقوم جميع العملاء بتحديث petables الخاصة بهم عن طريق تحليل رسائل سجل الأحداث المُبثّة هذه باستخدام خطاف "on Event_Action". يتم أيضًا إجراء تغييرات على بيانات Inline-Execute-PE عند انتهاء تنفيذ BOFs لكل من peload و peunload؛ يتم إبلاغ هذه التغييرات مرة أخرى بواسطة Beacon (على سبيل المثال، بعد تشغيل peload، يتصل Beacon مرة أخرى بموقع الذاكرة لهيكل pMemAddrs) وبالتالي فهي مرئية لجميع العملاء المتصلين، الذين يقومون بتحديث petables الخاصة بهم باستخدام خطاف "on Beacon_Output".
تؤدي هذه الجهود المنفصلة مجتمعة إلى قدرة Inline-Execute-PE على مزامنة البيانات الهامة بكفاءة وموثوقية بين عدة عملاء.
لم يكن هذا المشروع ممكنًا لولا المشاريع والموارد التالية التي تم الرجوع إليها بشكل كبير والتي نشأت منها الأجزاء الأساسية لهذا المشروع. شكر كبير للمؤلفين على كودهم ورؤيتهم.