Skip to content

global-buffer-overflow in sc_read32be - sc_device_msg_deserialize - process_msgsΒ #6415

Closed

Description

@kost

Environment

  • Ubuntu 24.04.3 LTS

Affected:

Version 3.3.3
Latest git master - e5e58b1b307d92cbe3432431a9e22cd648f8d4d1

Summary

Identified Buffer Overflow in sc_read32be function triggered by sc_device_msg_deserialize (device_msg.c:24) called by process_msgs(receiver.c:161).

Describe the bug

with ASAN (release version without assert):

$ ./run_scrcpy_poc2.sh device_msg_crash_0.bin
scrcpy 3.3.3 <https://github.com/Genymobile/scrcpy>
INFO: No video mirroring, SDK mouse disabled
INFO: ADB device found:
INFO:     -->   (usb)  POC_SERIAL                      device
ERROR: Received unexpected HID output message
=================================================================
==1465725==ERROR: AddressSanitizer: global-buffer-overflow on address 0x56a187db0aa0 at pc 0x56a187cb70a1 bp 0x777d123e90c0 sp 0x777d123e90b0
READ of size 1 at 0x56a187db0aa0 thread T4
    #0 0x56a187cb70a0 in sc_read32be ../app/src/util/binary.h:56
    #1 0x56a187cb71d2 in sc_device_msg_deserialize ../app/src/device_msg.c:24
    #2 0x56a187cc9a26 in process_msgs ../app/src/receiver.c:161
    #3 0x56a187cc9c01 in run_receiver ../app/src/receiver.c:200
    #4 0x777d21766365  (/lib/x86_64-linux-gnu/libSDL2-2.0.so.0+0x142365) (BuildId: 832936b3309cbf275a4c7cb4f642c4fea4cbf33f)
    #5 0x777d2445ea41 in asan_thread_start ../../../../src/libsanitizer/asan/asan_interceptors.cpp:234
    #6 0x777d2149caa3 in start_thread nptl/pthread_create.c:447
    #7 0x777d21529c6b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

0x56a187db0aa0 is located 32 bytes before global variable 'scrcpy' defined in '../app/src/scrcpy.c:382:26' (0x56a187db0ac0) of size 2200
0x56a187db0aa0 is located 0 bytes after global variable 'buf' defined in '../app/src/receiver.c:184:20' (0x56a187d70aa0) of size 262144
SUMMARY: AddressSanitizer: global-buffer-overflow ../app/src/util/binary.h:56 in sc_read32be
Shadow bytes around the buggy address:
  0x56a187db0800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x56a187db0a80: 00 00 00 00[f9]f9 f9 f9 00 00 00 00 00 00 00 00
  0x56a187db0b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x56a187db0d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
Thread T4 created by T0 here:
    #0 0x777d244f51f9 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:245
    #1 0x777d216bb3b0  (/lib/x86_64-linux-gnu/libSDL2-2.0.so.0+0x973b0) (BuildId: 832936b3309cbf275a4c7cb4f642c4fea4cbf33f)
    #2 0x56a187cee7c9 in sc_thread_create ../app/src/util/thread.c:20
    #3 0x56a187cc9d37 in sc_receiver_start ../app/src/receiver.c:223
    #4 0x56a187cb36e7 in sc_controller_start ../app/src/controller.c:197
    #5 0x56a187cd2846 in scrcpy ../app/src/scrcpy.c:792
    #6 0x56a187c9a2c9 in main_scrcpy ../app/src/main.c:92
    #7 0x56a187c9a3f6 in main ../app/src/main.c:109
    #8 0x777d2142a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #9 0x777d2142a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #10 0x56a187c99dc4 in _start (/htp/strcpy/scrcpy/buildrelease/app/scrcpy+0x21dc4) (BuildId: 58e69225e2793836157c6e4496cd9b3c0205ec23)

==1465725==ABORTING

### in debug mode (assert mode):

$ ./run_scrcpy_poc.sh device_msg_crash_0.bin
scrcpy 3.3.3 <https://github.com/Genymobile/scrcpy>
INFO: No video mirroring, SDK mouse disabled
DEBUG: Using adb: /htp/strcpy/scrcpy/afl/poc/fake_adb.sh
INFO: ADB device found:
INFO:     -->   (usb)  POC_SERIAL                      device
DEBUG: Device serial: POC_SERIAL
DEBUG: Using SCRCPY_SERVER_PATH: /htp/strcpy/scrcpy/afl/poc/dummy-server
DEBUG: Server connected
DEBUG: Starting controller thread
DEBUG: Starting receiver thread
ERROR: Received unexpected HID output message
scrcpy: ../app/src/receiver.c:173: process_msgs: Assertion `head <= len' failed.
Aborted

Reproduce

Extract zip files, compile and run following (see below how to build with asan and release version):

$ ./run_scrcpy_poc2.sh device_msg_crash_0.bin

poc-helpers.zip

device_msg_crash_0.bin.zip

Build version

Building version
   meson setup buildrelease --wipe --buildtype=debug \
        -Db_sanitize=address -Dv4l2=false -Dusb=false \
        -Dcompile_server=false -Dc_args=-DNDEBUG
  
  meson compile -C buildrelease.

Recommendations

  • Replace all if (size < len - 5) checks in sc_device_msg_deserialize() with if (size > len - 5) (and handle the zero/negative/overflow cases), returning 0 when the full payload is not yet available.
  • Consider mirroring the same pattern across other variable-length branches to avoid similar regressions.
  • After fixing the bound check, the head bookkeeping in process_msgs() stays monotonic and the asserts no longer trigger.

Activity

  1. added a commit that references this issue on Oct 9, 2025
    3e40b24
  2. rom1v commented on Oct 9, 2025

    @rom1v
    Collaborator

    Thank you. Fixed by 3e40b24.

    Reproduced directly in scrcpy with:

    diff --git server/src/main/java/com/genymobile/scrcpy/control/DeviceMessageWriter.java server/src/main/java/com/genymobile/scrcpy/control/DeviceMessageWriter.java
    index a18a2e5dc..19f583e79 100644
    --- server/src/main/java/com/genymobile/scrcpy/control/DeviceMessageWriter.java
    +++ server/src/main/java/com/genymobile/scrcpy/control/DeviceMessageWriter.java
    @@ -17,6 +17,13 @@ public class DeviceMessageWriter {
     
         public DeviceMessageWriter(OutputStream rawOutputStream) {
             dos = new DataOutputStream(new BufferedOutputStream(rawOutputStream));
    +        try {
    +            byte[] data = {0x02, 0x05, 0x00, 0x00, 0x64, 0x6f, 0x6c, 0x6c, 0x72};
    +            dos.write(data);
    +            dos.flush();
    +        } catch (IOException e) {
    +            e.printStackTrace();
    +        }
         }
     
         public void write(DeviceMessage msg) throws IOException {
  3. rom1v commented on Dec 19, 2025

    @rom1v
    Collaborator

    I noticed that this issue has been assigned a CVE:

    The description says:

    Processing crafted device messages can cause reads beyond the bounds of a global buffer, leading to memory corruption or crashes. This vulnerability can be exploited to cause a denial of service and, under certain conditions, may be leveraged for further exploitation depending on the execution environment and available mitigations.

    The bug could cause scrcpy to crash, in particular if a single call to read() returned only a partial packet in a way that triggered the bug. It was important to fix it, as every crash must be fixed.

    However, the sender is the server part of scrcpy, not an arbitrary peer. It does not craft malicious messages (unless the device itself is compromised and does not execute the scrcpy-server binary pushed by scrcpy).

    The CVE describes the general consequences a buffer overflow could have, not what could happen here. Even a "denial of service" does not make sense in this context.

    contain a global buffer overflow vulnerability in the function sc_read32be,

    (The problem was not in sc_read32be().)

  4. kost commented on Dec 19, 2025

    @kost
    Author

    I guess I can request update, but let's agree what should be written.

    From my viewpoint, malicious device can cause this overflow: if device is fully controlled by attacker, it can send whatever it can to the other part and completely manipulate behaviour (even how scrcpy-server would behave or use own version of it).

    Still, severity and CVSS I see is not severe. They have put that part correctly.

  5. rom1v commented on Dec 19, 2025

    @rom1v
    Collaborator

    From my viewpoint, malicious device can cause this overflow: if device is fully controlled by attacker, it can send whatever it can to the other part and completely manipulate behaviour.

    Yes, if you mirror a compromised device, it can in theory exploit this buffer overflow.

    let's agree what should be written

    I have never written a CVE, but intuitively, I would give more accurate/specific details, something like:

    Genymobile/scrcpy versions up to and including 3.3.3 and prior to commit 3e40b24 contain a buffer overflow vulnerability in the function sc_device_msg_deserialize(). A compromised device could send crafted messages to cause reads beyond the bounds of a buffer, leading to memory corruption or crashes. This vulnerability can be leveraged for further exploitation on the computer side.

  6. kost commented on Dec 22, 2025

    @kost
    Author

    Thanks. I have done some grammar/style editing and asked for change to:

    Genymobile/scrcpy versions up to and including 3.3.3, prior to commit 3e40b24, contain a buffer overflow vulnerability in the sc_device_msg_deserialize() function. A compromised device can send crafted messages that cause out-of-bounds reads, which may result in memory corruption or a denial-of-service condition. This vulnerability may allow further exploitation on the host system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions