I’d like to address the control flow used by W32.Stuxnet. The threat has been gaining some attention due to the fact that it uses a currently unpatched Microsoft vulnerability to spread through removable drives but there are other interesting and novel aspects of the threat that I would like to highlight here.
The following files are present on infected removable drives:
- Copy of Shortcut to.lnk
- Copy of Copy of Shortcut to.lnk
- Copy of Copy of Copy of Shortcut to.lnk
- Copy of Copy of Copy of Copy of Shortcut to.lnk
These files exploit the currently unpatched Microsoft Windows Shortcut 'LNK' Files Automatic File Execution Vulnerability (BID 41732).
Infected removable drives also contain the following files:
- ~WTR4141.tmp (~25Kb)
- ~WTR4132.tmp (~500Kb)
The above files are .dll files and the file names are hardcoded.
Once the threat is active on a machine the rootkit portion of the threat will hide these files.
When a removable drive is attached to a system and browsed with an application that can display icons, such as Windows Explorer, the .lnk files will load the first .dll file (~WTR4141.tmp) into memory and pass control to it. This is not possible under normal conditions but using the aforementioned vulnerability the .lnk files are able to achieve this. This first .dll file is small – approximately 25Kb – and has limited functionality. In fact it's main purpose is to load the second larger .dll file (~WTR4132.tmp at approximately 500kb in size) into memory and pass control to that .dll file.
Let's assume that an infected removable drive has been attached to a clean machine. In that case the files on the removable drive will not be hidden yet as the rootkit part of the threat has yet to be installed on the clean machine. It is therefore important for the threat to hide the files on the removable drive as early in the infection process as possible. This is the other function that the first, smaller .dll file takes care of (in addition to loading the larger .dll file).
To achieve the objective of hiding the threat related files the smaller .dll file hooks the following APIs from kernel32.dll and Ntdll.dll:
It replaces the original code for these functions with code that checks for files with the following properties:
- File names ending with ".lnk"
- File names beginning with "~WTR" and ending in ".tmp" (this is why the file names on the removable drive cannot change significantly)
If a request is made to list a file with the above properties, the response from these APIs is altered to state that the file does not exist, thereby hiding all files with those properties.
After the kernel32.dll APIs are hooked the first .dll file loads the larger dll file. It does not do this in the "normal" manner however. Normally to load a .dll file a program calls the "LoadLibrary" API with the file name of the .dll file to be loaded into memory. W32.Stuxnet uses a different approach, not just in the first .dll file but in several different parts of the code.
The method used is to hook certain Ntdll.dll functions, then call LoadLibrary with a specially crafted file name. The file requested to be loaded does not exist on disk, therefore normally LoadLibrary would fail. However, W32.Stuxnet has hooked Ntdll.dll to monitor for requests to load specially crafted file names. If a specially crafted file name is encountered, the hooked ntdll.dll functions know to load a .dll file from another location instead; a location specified by W32.Stuxnet and that location is generally an area in memory where a .dll file has been decrypted and stored by the threat previously.
The functions hooked for this purpose in Ntdll.dll are:
Once a .dll file has been loaded via the method shown above, GetProcAddress is used to find the address of a specific export from the .dll file and that export is called, handing control to that new .dll file.
Everything we have seen so far has just been the loading part of the threat and the installation code with the true functionality of the threat still to come.
After the first .dll file has hidden the threat related files it hands control to the second, larger .dll file. The second .dll file ~WTR4132.tmp is actually just a wrapper for a third .dll file. ~WTR4132.tmp contains an encrypted .dll file in its data section as shown below. In the first diagram the small blue section on the left indicates code and the green area on the right indicates data (in this case an encrypted .dll file). As you can see the majority of the larger .dll file is in fact data not code.
The screen shot below shows the first .dll file for comparison purposes. As you can see the first .dll file consists mostly of code (again shown in blue) and very little non-code data sections.
~WTR4132.tmp contains a small wrapper code section (the small blue section shown in the first image above), which is actually very similar to the code in the first .dll file. There is lots of duplicate code here. An example of the duplicate code is shown below, showing both .dll files using the exact same code to resolve API addresses in the exact same order.
This wrapper code in the larger .dll file is used to decrypt a UPX packed .dll file from inside itself, load that .dll file into memory (using the same method outlined above) and to pass control to that .dll file. It is that decrypted UPX packed .dll file that contains the payload functionality of the threat.
The UPX packed file has 21 different exported functions as show below.
Each of these exports contains code to perform a different part of the threat’s functionality. For example there are exports to:
- Decrypt the configuration data used by the threat
- Drop two .sys files and install them as a kernel level rootkit
- Access files created by the Siemens Step 7 software package
- Update itself
- Drop more .dll and .dat files
- Infect removable drives with custom .lnk files
- Inject into the lsass.exe process and execute custom code
- Inject into the iexplore.exe process
- Check if certain antivirus applications are running
- Scan the network for servers
- Remove itself
- Communicate with the C&C server
Many of these functions are not simply executed but instead code is first injected into some other process on the system and then the functions are called from within the injected process. For example, the first action that the UPX packed .dll file takes is to create a new legitimate lsass.exe process, overwrite the process’ code with its own loader code. The loader code will load the UPX packed file into the address space of lsass.exe and then execute one of the functions outlined above.
As you can see from above many of the threat’s functions are related to SCADA software products. From our analysis we can see that this threat is specifically targeting systems with SCADA software installed. The threat performs many DB queries on the DB used by the Siemens Step 7 software and interacts with the .dll files belonging to that product. It tries to extract specific data from the database and take actions accordingly. For example, it tries to access files with the following characteristics, created by the Step 7 software:
We are continuing our analysis of the threat and we will be posting another blog with more information within the next 24 hours. Stay tuned! For more general information, please also see our previous blog covering the frequently asked questions relating to the W32.Stuxnet attack.