Introduction
On it's 10th anniversary of the destructive attacks on Ukraine's power grid, Sandworm gained
access to OT systems at energy plants in Poland at the end of December 2025. Using a wiper
dubbed DynoWiper by Eset,
it was not successful in causing electrical outages.
Nonetheless, Dragos
reported that some OT equipment was bricked on affected sites in what has been described as the
largest cyberattack targeting the country in years.
We have obtained the specific DynoWiper sample that was used in this attack and we will dive
into reversing the wiper in this blog post.
DynoWiper has the following features and behaviours:
- Initializes a pseudorandom number generator using the Mersenne Twister with a seed of 0x1571
- Uses the PRNG to generate 16 pseudorandom bytes for file overwrite operations
- Identify all removable and fixed media drives on the system
- Identify all folders, subfolders and files which it selectively overwrites
- Removal of crucial operating system files
- Obtaining of token privileges to force a system shutdown
| Hash Type | Hash Value |
|---|---|
| SHA1 | 4EC3C90846AF6B79EE1A5188EEFA3FD21F6D4CF6 |
| SHA256 | 835b0d87ed2d49899ab6f9479cddb8b4e03f5aeb2365c50a51f9088dcede68d5 |
Table of Contents
Initializing Mersenne Twister PRNG
Directly at the start of WinMain, sub_403A90 is called, which initializes the internal state
of a pseudorandom number generator, specifically using the Mersenne Twister MT19937 (or a very
close variant). Distinct to Mersenne Twister in this operation is the usage of static value
0x6c078965 and the length of 0x270
(624).
Next, from WinMain, sub_401F40 uses
the pseudorandom number generator to calculate blocks of 16-bytes which are stored at [esi+edi+5000].
Identifying all drives and root paths
In sub_402CE0, all logical drives are obtained after which the malware loops over each drive. For each drive, it will obtain the lpRootPathName and the corresponding drivetype using GetDriveTypeW. When the drive is either a removable media or a fixed media, it will store the lpRootPathName.
Identifying, overwriting and removing files
In sub_402290, the wiper will iterate over each identified drive
and enumerates every file in each drive using the iterator provided by FindFirstFileW and FindNextFileW. It
first ensures that the obtained file is not equal to . or .., which by default are references to the current and top level
directory. Next, it checks if the obtained file is of type directory. If the file is a
directory, it will set the file attributes to FILE_ATTRIBUTE_NORMAL (0x80).
Subsequently, it will call sub_402500 which iterates over each
file. If the file is once again a directory, it will first check that the directory name is
not equal to system32, windows, program files, program files(x86), temp,
recycle.bin, $recycle.bin, boot, perflogs, appdata, documents and settings. It will
then call itself again using the newly obtained subdirectory and continue looping until a file
has been found.
In case the file is actually a file, it will call sub_402B30 which
sets the file's attributes to and then attempts to open the file with generic read/write access.
If it has obtained access, it will overwrite the first 16 bytes with the value stored in [esi+edi+5000] which holds a 16-byte buffer of bytes which were
generated using the Mersenne Twister initialized PRNG. If the size of the file is larger than 16
bytes, it will continuously overwrite blocks of 16 bytes. Once this operation completes, the
function returns to sub_402290.
Back in sub_402290, the obtained file is then removed using DeleteFileW
Obtain token privileges to force a system shutdown
Back in the main function, the wiper obtains the current process token and checks if the
SeShutdownPrivilege is part of the current token privileges. If it
isn't the privilege is attempted to be obtained through a call to AdjustTokenPrivileges.
Lastly, it will call ExitWindowsEx with a reason of SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE or
SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_INSTALLATION |
SHTDN_REASON_MINOR_MAINTENANCE