Skip to content

shawngraham.io

Menu
Menu

Steganography Reveals Hidden Monero CoinMiner

Posted on June 18, 2026June 18, 2026 by Shawn

Malware Analysis Template

Basic File Information

Filename:Player.exe
SHA-256 Hash:CE7CB2767010C3F6DABF6FBD6E7A68510D6390DBD59C97C815EEF626E20DFAD6
File Location/Source:https://www.virustotal.com/gui/file/ce7cb2767010c3f6dabf6fbd6e7a68510d6390dbd59c97c815eef626e20dfad6/detection
Date Acquired:6/17/2026
Detection Context:N/A

Automated Triage

YARA Matches (local ruleset, Thor Lite, VT):SIGNATURE_BASE_SUSP_XMRIG_Reference
FLOSS Decoded Strings:N/A
Capa Findings:link function at runtime on Windows (6 matches) write file on Windows  
PE-Seive/mal_unpack Results:N/A

Static File Analysis

File Size (bytes):156672 bytes
Compile Time:Tue May 29 13:07:05 2018 | UTC
File Type:64-bit GUI
File Path:N/A
Digital Signature: 
Icon Graphic: 
Packer/Compiler:N/A
Development Language:C++
File Entropy:6.07
Imphash:083D7B72808A921C8E9AE5424319766A
Section Hashes: 
Version Information: 
Exported DLL Name: 
Debug Info (e.g., PDB Path):F:\W\xmrig\iskander\x64\Release\iskander.pdb

Initial Analysis of this file consisted of observing static information that was present (i.e., Debug path, imphash, OSINT research, etc.)

The debug path listed above helped me identify potential association with XMRIG Monero coin miner. My initial analysis consisted of reviewing static findings, like bundled files, Windows API imports, strings, and using other tooling to help identify possible capabilities. OSINT on the debug path revealed a propensity for these files to read from audio files. Which is an interesting concept for me. YARA also flagged for XMRIG further supporting this concept of a potential coinminer.

I used x64dbg to set a break point on one of the APIs observed, ReadFile.

Here, I set a breakpoint on the API, returned to the original function, and then refreshed my handles. This supports some of the OSINT research we observed as we now have a handle to one of the bundled files (film.wav) it was discovered with.

Ghidra reveals that the function that called this API was a library function. I have learned that it is often a bad idea to waste time while performing static analysis by reviewing library code, so I went to search for the User defined entry point, where user code is likely to be written. During static analysis, we identified this as a GUI application, so we are looking for WinMain. A string search revealed a call to _get_wide_winmain_command_line and immediately after the call the data in the accumulator register (RAX) is put into the R8 register as an argument for the following call. This supports the idea that the following function call is a likely candidate for WinMain.

Review of our suspected WinMain identifies two windows API calls (GetModuleHandleW & GetModuleFileNameW) and then possibly a user defined function: FUN_1400011f0.

FUN_1400011f0 has multiple calls to fread. Looking at the fread API calls and the .WAV file format, we see that there are calls to read the size of the data based on the offset of bytes read into the .WAV file and then there is a memory allocation for the sound data via operator new. Our analysis tells us that the sound data is being read in after size determinations. Following static code analysis via the decompiler reveals a do while loop.

Initially we see a value from ECX being placed into RAX. Via MOVSXD. MOVXSD is used to Move DWORD with sign extension to QWORD, so it is essentially moving a sign extended value from a 32-bit register into a 64-bit register. Looking above the loop we see ECX is XOR’d (zeroed) out with itself. The next instruction tests the lower eight bits of EDI (DIL) against 0 (RAX) plus the byte read into RBP. Again, looking above, we see after the call to operator new the value of RAX is placed into RBP. So RBP is pointing at film.wav audio data. Looking above we see EDI as a dest receiving 0x1 so we know it is set to one.

The BTS instruction is only ran if the JZ is not taken. We see R8D, the lower 32 bits of R8, being set with the value of 31 and then the bit being set (left most) is 1. We then later see R8D being decremented by one further down in the loop, showing the bits being set in a decremented order. The add instruction adds 2 to ecx with each loop iteration and ESI being shifted right three bits from 10 also equates to 2.

The loop iterates over every other byte of audio data to extract Least significant bits. Each LSB is assigned to a bit position within a 32-bit value, starting at the left most bit. In total, the loop spans 64 bytes of audio data and extracts 32 LSBs since it skips a byte with each iteration of the loop.

In our debugger, we follow the calls to operator new after the loop. We followed our address from operator new in a dump window and then went to the end of our loop. Following this address in our dump window revealed our MZ header.

After dumping to file, we are able to see an unhindered xmrig.exe miner.

Recent Posts

  • Steganography Reveals Hidden Monero CoinMiner
  • Wireshark intro
  • Tcpdump Intro
  • Why This Blog Sucks
  • Smoke loader targets Ukraine

Recent Comments

    Archives

    • June 2026
    • March 2026
    • February 2026
    • May 2023
    • December 2022
    • October 2022
    • July 2022
    • June 2022
    • May 2022
    • April 2022

    Categories

    • Uncategorized
    © 2026 shawngraham.io | Powered by Minimalist Blog WordPress Theme