Replacing the HWID in VMProtect 3.8.4
About the author. I’m Colin Xiao — an independent reverse engineer, mostly working solo on contract jobs. I dig into compiled code of every kind, including but not limited to: Android and iOS apps, x86/x64/ARM native binaries, packers and obfuscators, DRM and license checks, network protocols and APIs, crypto and signature algorithms, malware, game binaries, and embedded/IoT firmware. I also handle large-scale data collection and vulnerability research. If you have any project in mind, I’d be glad to take it on — whatever it is, as long as it’s within my wheelhouse. Just reach out. You can reach me on X at @colinxiao_lab or on Telegram at https://t.me/ColinXiao666.
This research is published for educational and defensive purposes. The target sample is anonymized throughout.
Replacing the HWID in VMProtect 3.8.4
The approach
VMProtectGetCurrentHWID
From analysis of the leaked VMProtect source, the HWID is composed as shown below. Each component is hashed with SHA-1 and the first 4 bytes of each result are taken; the combined result is then stored with an RC5-encrypted random key. When VMProtectGetCurrentHWID is called, the whole thing is assembled and presented as Base64.

GetComputerNameW
Some of the functions in the diagram get virtualized when compiled, but there’s an entry point we can still hook: GetComputerNameW.
Break on GetComputerNameW and swap the HWID in memory via the stack:

Implementation
Compile the target and debug it with OllyDbg:

Break on GetComputerNameW and inspect the stack — but don’t break at the function prologue.
[ebp+0x8]+0x8 is the pointer to the structure that holds the HWID encryption result. At this point it isn’t fully written yet — only the CPUID part has been computed. So set a breakpoint at the function’s return instead (again, not at the prologue):

Once it hits, the data has been written. Follow the structure pointer in the memory window:

- pointer+0x4 — where the HWID encryption is stored
- pointer+0x8 — total HWID group count
- pointer+0x9 — old-method group count
Follow the HWID encryption location (pointer+0x4):

- pointer+0x4 — pointer to the RC5-encrypted HWID data

- pointer+0xC — pointer to the RC5 encryption key

With those two blobs you can decrypt the HWID:

The same two locations can also be patched to replace the HWID outright.
Colin Xiao — I take on contract reverse-engineering work, and writeups like this are how I show what I can do. If you need help with anything in this space — including but not limited to the areas I cover above — I’m available. No project is too big or too small — if it’s reverse engineering and I can do it, I’ll take it. DM me on X (@colinxiao_lab) or Telegram (@ColinXiao666).
Get in touch