About This Blog

This blog serves as a repository for articles and short posts on my projects in cybersecurity. The content ranges from breakdowns of malware obfuscation techniques to custom implementations of security tools, analyses of CVEs, and low-level programming experiments.

Some recurring themes you’ll find here:

These posts represent my notes from the field, structured into (mostly) coherent technical narratives. While the code samples and techniques demonstrated here have legitimate educational and professional uses, I maintain a strong emphasis on responsible disclosure and ethical application of security research.

The blog theme is currently based on The Monospace Web project, with a few tweaks, built on Hugo. I firmly believe in the power of text and simple documents for sharing ideas.

Recent Posts

Latest Post: Brief Post: Ghidra Workaround for Program Diffing on Unaligned Address Ranges

Brief post.

While working in Ghidra recently, I noticed that there is a good amount of shared code between the AMD and Intel provider executables for the Windows Hypervisor (hvax64.exe, hvix64.exe). Accordingly, I wanted to compare disassembly on certain functions, but noticed that the built-in Program Differences tool in Ghidra does not support custom address mappings (or if it exists, its buried in menus). This means that if two programs expect different memory locations, the Program Differences tool will not produce immediately useful results. Additionally, I did not see an obvious way to do highly specific function or block level diffing.

A quick google search didn’t reveal any cheat-sheet-like guides on how to resolve this without going to an external tool, so I’m writing here to discuss a hack-ish approach to selectively diff when addresses don’t line up. The approach is a bit sketchy but can be done natively in Ghidra with no special tooling:

  • Identify the function offset and section base address for the targets in both programs.
  • Open the Memory Map (View -> Memory Map) and re-base the block/section of the comparison target to match the target function based on the offset.

A simplistic example is to just re-base the section to 0x0 (whose function is at a higher offset) and re-base the target at the difference in the offsets. Then the Program Differences tool can be used like normal.

Example Rebase for Program Differences

This approach isn’t ideal as it will have effects on the Code Browser overall (as whole sections have just been moved) but might be useful as a quick hack to get the built-in Program Differences tool to work when image bases, sections, and functions don’t align nicely.

In my use-case of hvax64.exe, and hvix64.exe, this approach allowed me to quickly see (without using a different tool) a large amount of the shared code between the binaries. This is of course expected, but allows one to key in on some of the model-specific differences (and similarities) in the implementations, which is pretty neat!

Diff View for Intel/AMD Hypervisor Binaries
Snippet of VMCALL Opcode Differences

...

Read more

Previous Post: Covert IPC With the Windows Kernel Transaction Manager

This post documents a potential technique for stealthy inter-process communication on Windows. The idea is based on the apparent absence of Etw (and EtwTi) instrumentation of system calls involving the Windows Kernel Transaction Manager, and the ability for processes to receive handles to transaction objects without accessing instrumented system calls.

Overview

While re-reading Matt Hand’s “Evading EDR”, I was following along with the methodology described involving graph analysis of function call trees. The premise is to convert a Ghidra analysis of call graphs in a binary to a JSON format suitable for use in Neo4j, allowing for robust querying.

The example provided in Chapter 12 demonstrates identifying Nt family functions with edges to known EtwTi functions. Reading this gave me the idea to write a query that does something slightly different: Identify system call functions without known calls to Etw functions.

The query for this is relatively simple:

MATCH (f:Function)
WHERE f.name STARTS WITH 'Nt'
  AND NOT f.name CONTAINS '$'
  AND NOT EXISTS {
    CALL {
      WITH f
      MATCH (f)-[:CALLS*1..25]->(t:Function)
      WHERE t.name STARTS WITH 'Etw'
      RETURN t
    }
  }
RETURN f;

This will simply traverse the call graph from Nt-family functions and report on those which do not have an outgoing ETW call somewhere inside.

On my Windows 11 26100 reversing machine, this query identified 47 records. Nearly all are related to the Windows Kernel Transaction Manager (KTM). After briefly reviewing the Microsoft documentation, I started to wonder if the KTM service was suitable for anything useful for offensive purposes, as it appears to be ignored by Etw.

While I haven’t gone into depth to verify that no form of security instrumentation exists for these system calls in the kernel, the graph analysis results are promising. With this in mind, I set out with the purpose of at least determining if some sort of inter-process communication could be implemented using KTM. If true, it may merit a closer look and potentially some utility in same-host offensive scenarios. As a side note, I haven’t extensively surveyed the previous work in the area of KTM, so it’s possible that someone has stumbled upon this before, but it still seems quite niche and potentially under-explored.

While reviewing the documentation, an initial objective was to determine how one would work with the transaction manager in the first place. Fortunately, it is relatively straightforward and decently documented.

The first step is to simply create a transaction object with NtCreateTransaction. This can be done from unprivileged user-mode contexts. While reading the function documentation, I noticed that it takes a parameter of type PUNICODE_STRING, potentially allowing for the storage of a decently large amount of information inside the kernel. If there is a way to recover this, it could be used as an odd form of generic inter-process communication.

At this point I set some criteria for the technology for further investigation:

  1. The technique must allow for some sort of data to be sent to the kernel and recovered by another process.
  2. There must be a way to use only the uninstrumented system calls.
  3. All system calls must be shown as uninstrumented by the graph query.
  4. All operations must be from an unprivileged context.
  5. ...

Read more

All Posts