# AnyPwn: AnyDesk Pre-auth Heap Buffer Overflow RCE This vulnerability was discovered with [V12](https://v12.sh) by Rick de Jager of the [V12 security team](https://x.com/v12sec). > Want to find issues like this in your own code? Try V12 at > [v12.sh](https://v12.sh). Fixed in AnyDesk 8.0.3. The vendor appears to have deleted (?) the 8.0.2 build of anydesk upon the release of our poc video. Porting the exploit to 8.0.1 or obtaining a 8.0.2 build is left as an exercise to the reader. ## Abstract AnyPwn is a pre-approval remote code execution vulnerability in AnyDesk Linux 8.0.2. The session protocol's mode-5 stream packet handler trusts a remote payload length before validating it. Adding the 16-byte object header to that length with 32-bit arithmetic can wrap to a tiny allocation while the object retains the original large logical length. AnyDesk then copies attacker-controlled packet bytes beyond the allocation. The supplied PoC exploits the resulting heap corruption through the direct, local TCP/7070 transport and executes an arbitrary command. The same vulnerable session-protocol path is reachable over AnyDesk relay connections, which we validated with a minimal Frida trigger. To limit engineering time, the included minimal PoC demonstrates the full exploit only over direct TCP/7070 connections. The service normally runs as root on Linux, so successful exploitation yields root command execution before desktop-control approval. ## Exploitation Run the vulnerable AnyDesk Linux 8.0.2 service with TCP/7070 reachable, then execute: ```bash cd exploit python3 anypwn.py --host 127.0.0.1 --command 'id>/tmp/anypwn' ``` Verify command execution: ```bash cat /tmp/anypwn ``` For a directly reachable remote target, replace `127.0.0.1` with the target host. The exploit requires Python 3 and the `rich` package. The included offsets target this exact build and environment: ```text AnyDesk Linux 8.0.2 Binary SHA-256: 62ee04ad48dc039dd9c927f998e56143c87a9c5e12d28654f78c7f6340394f5a Service mode: anydesk --service Target port: TCP/7070 Platform: Linux x86_64 Test VM OS: Linux Mint 22.3 (Zena), kernel 6.14.0-37-generic ``` Heap layout is probabilistic. If the victim client object is not immediately after the undersized buffer, the exploit crashes the service instead of executing the command. Other AnyDesk builds require different offsets. ## How It Works A mode-5 packet on an assigned stream has this form: ```text u16be frame_len u16be assigned_stream_id u8 stream_mode_prefix 0x00 varint mode5_declared_len u8[] mode5_body ``` For a valid packet, `mode5_declared_len` must not exceed the bytes remaining in the frame. The vulnerable path instead calculates a backing allocation from the unvalidated 32-bit declared length. AnyPwn declares `0xfffffff0` bytes: ```text declared_len + 0x10 = 0x1_0000_0000 (uint32_t)(declared_len + 0x10) = 0 ``` Values from `0xfffffff0` through `0xffffffff` therefore allocate only 0 through 15 bytes. The object data pointer remains `allocation_base + 0x10`, and its length remains the original large value, so copying even one body byte writes outside the allocation. The attacker does not need to send four gigabytes: the outer frame remains small, its varint causes the integer wrap, and its body supplies the overflow bytes. The PoC uses two complementary heap-spraying strategies. First, it sends 100 persistent mode-5 objects at each size from `0x1` through `0x17f1` in `0x10` increments. Covering that range populates the allocator's relevant size classes and reduces dependence on one exact allocation size. It then opens ten additional client connections, placing candidate victim objects among the groomed allocations. This remains probabilistic: the overflow is useful only when one of those victims is adjacent to the wrapped allocation. The later ROP spray serves a different purpose. Twenty identical `0xf000`-byte objects contain a long `ret`-gadget sled followed by the actual chain. Repeating the object and providing a wide sled gives the corrupted stack pivot many equivalent landing points instead of requiring an exact address within a single copy. The PoC turns the primitive into command execution as follows: 1. Complete service setup and obtain an assigned stream. 2. Send a normal profile object to enter the profile/session mode-5 path. 3. Groom the allocator with the size-graded mode-5 spray, then open the ten candidate victim clients. 4. Send a packet declaring `mode5_declared_len = 0xfffffff0`. Its body overflows the wrapped allocation and replaces dispatch-related fields in an adjacent victim, including a chosen vtable and stack-pivot gadget. 5. Spray the repeated ROP objects so the pivot can land in a `ret` sled and advance to the chain. 6. Continue setup on each victim client. Processing the corrupted victim uses the overwritten control data and transfers execution through the pivot into a sprayed chain. 7. The chain writes the requested command into fixed scratch memory, loads its address as the first argument, and calls the target build's `system()` PLT entry. ## Credit Found with V12 by Rick de Jager of the V12 security team: [v12.sh](https://v12.sh): dangerously powerful agentic security.