# Carbon DLL Installer

# Usage

To run the installer, simply run the dropper.exe executable (release builds located in bin/) as an administrator.

# Component Breakdown

# Dropper

The Carbon DLL dropper will create the following subdirectories in the Carbon working directory:

  • %programfiles%\Windows NT\0511 for tasking info
  • %programfiles%\Windows NT\2028 for task output
  • %programfiles%\Windows NT\Nlts for task config files

The Carbon DLL dropper will drop the following files to disk1,3:

  • Configuration file to %programfiles%\Windows NT\setuplst.xml
  • Loader DLL to %systemroot%\System32\mressvc.dll
  • Orchestrator DLL to %programfiles%\Windows NT\MSSVCCFG.dll
  • Communications library DLL to %programfiles%\Windows NT\MSXHLP.dll

After successful file writes, the dropper will create a service to execute the loader DLL.3

The service details are as follows:

  • Service Name: WinResSvc
  • Display name: WinSys Restore Service
  • Bin path: C:\Windows\System32\svchost.exe -k WinSysRestoreGroup (svchost is used since we are running a DLL as a service).

Turla has used the same display name in the past, though we changed the service name to avoid using the exact same naming convention.

The dropper then performs two registry writes to make sure that the service can find the loader DLL and that the service will run under svchost:

  1. The loader DLL path (%systemroot%\system32\mressvc.dll) is written to registry key HKLM:\SYSTEM\CurrentControlSet\services\WinResSvc\Parameters under the ServiceDll value
  2. The service name (WinResSvc) is written to registry key HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost under the WinSysRestoreGroup value

Once the service is set up, the dropper will start it before terminating its own execution.

# Dropper Build Instructions

Since the Carbon DLL dropper contains the various implant components (config file and DLLs), you will need to add those components in as resources at compile-time. Use the add_resources.py script to auto-generate the src/components.cpp file that contains each of the latest resource components. Supply the appropriate file paths to the latest version of each resource that you want to include.

Note that PyCryptoDome is required. You can installed it with the following command:

pip install pycryptodome

To generate the src/components.cpp file:

# Run from the Dropper directory
python3 add_resources.py --config-path path/to/config/file --loader-path path/to/loader/dll --orchestrator-path path/to/orchestrator/dll --commslib-path path/to/commslib/dll -o src/components.cpp -k [key hex string] -l DEBUG

The encryption key used for adding resources is f2d4560891bd948692c28d2a9391e7d9, which was generated by using PBKDF2 with 5 iterations of SHA1, passphrase of checkmatepepper and salt of salty, resulting in a 128-bit key. Example using CyberChef)

Now that you have all of the resources in src/components.cpp, you can build the dropper executable.

The dropper executable was built on Kali Linux using the following build command from the Dropper directory:

x86_64-w64-mingw32-g++ -I include/ -static -std=c++20 -lstdc++fs -Wall -Wextra -Werror -o bin/dropper.exe src/*.cpp

To remove symbols, you can use the strip command:

strip -s bin/dropper.exe

To verify, you can run strings or objdump --syms bin/dropper.exe - you should see an empty symbols table.

# Loader DLL

The loader DLL is one of the components dropped by the Carbon DLL dropper. The dropper will then create a service to run the loader DLL under svchost, which requires some registry key creation and modification. The loader DLL exports a ServiceMain function in order to be run as a service.

When running as a service, the loader DLL will execute the orchestrator DLL by calling its exported CompCreate function.3

# Loader DLL Build Instructions

The loader DLL executable was built on Kali Linux using the following build command from the Loader directory:

x86_64-w64-mingw32-g++ -I include/ -static -shared -std=c++20 -Wall -Wextra -Werror -o bin/loader.dll src/*.cpp

To remove symbols, you can use the strip command:

strip -s bin/loader.dll

To verify, you can run strings or objdump --syms bin/loader.dll - you should see an empty symbols table.

# Cleanup

To remove artifacts, run the Resources/cleanup/Carbon/carbon_cleanup.ps1 Powershell Script as an administrator on the target host(s).

You can do so from a domain controller using the following powershell command (from a directory containing the script):

Set-ExecutionPolicy bypass -force
$targethosts = "host1","host2","host3"
foreach ($targethost in $targethosts) {
    Write-Host "[+] Performing Carbon cleanup on $targethost"
    Invoke-Command -ComputerName $targethost -FilePath .\carbon_cleanup.ps1
}

# Troubleshooting

  • If the installer returns an error in its output, the error code will either be a Windows system error code or a custom error code defined in Dropper/include/file_handler.h or Dropper/include/service_handler.h.

  • To check if files were dropped, you can open up file explorer on the target host and look in C:\Program Files\Windows NT

  • To check if the service is created and running, open up task manager, go to the services tab, and then look for the WinResSvc service.

    • If the service does not exist or is not running, you may need to check privileges or cleanup and try again.
  • If the WinResSvc is stopped, or if it's running and you still don't have a Carbon beacon even with Edge open, you can check for the Carbon Orchestrator log and error files at C:\Program Files\Windows NT\history.jpg and C:\Program Files\Windows NT\bootinfo.dat, respectively.

    • These log files can be decrypted on a Windows machine using the Resources/Carbon/Orchestrator/bin/castDecrypt.exe utility.
    • The bootinfo.dat error file will likely explain why injection into Edge failed, or if the orchestrator failed in an earlier spot.
    • If neither file exists, it's likely the service was unable to start, and you will likely need to perform cleanup and try executing the installer again.
  • If you're still having issues obtaining an initial beacon, or if you obtained a beacon and then lost communication from the Carbon implant, look for the C:\Program Files\Windows NT\2028\dsntport.dat communications library log file.

    • This log file can be decrypted on a Linux machine using the Resources/Carbon/CommLib/decrypt_logs.py utility:
python3 decrypt_logs.py -p /path/to/commslib/log -o /plaintext/output/log/path
  • If this file does not exist, then that means the communications library was either not injected or was not even able to start up.
  • Once decrypted, you can look through the log for indicators of problems, such as pipe communication issues for peer-to-peer.

# Installer Build Commands for the Scenario

Optional: rebuild the Loader DLL (run from the Loader directory:

x86_64-w64-mingw32-g++ -I include/ -static -shared -std=c++20 -Wall -Wextra -Werror -o bin/loader.dll src/*.cpp;
strip -s bin/loader.dll

To compile the installer, run the following from a Linux machine from the Dropper directory:

rm src/components.cpp
python3 add_resources.py --config-path resources/carbon_w1_config --loader-path ../Loader/bin/loader.dll --orchestrator-path ../../Orchestrator/bin/MSSVCCFG.dll --commslib-path ../../CommLib/bin/commlib.dll -o src/components.cpp -k f2d4560891bd948692c28d2a9391e7d9 -l DEBUG
x86_64-w64-mingw32-g++ -I include/ -static -std=c++20 -lstdc++fs -Wall -Wextra -Werror -o bin/dropper_w1.exe src/*.cpp && strip -s bin/dropper_w1.exe && objdump --syms bin/dropper_w1.exe && cp bin/dropper_w1.exe ../../../payloads/epic/dropper.exe

rm src/components.cpp
python3 add_resources.py --config-path resources/carbon_w2_config --loader-path ../Loader/bin/loader.dll --orchestrator-path ../../Orchestrator/bin/MSSVCCFG.dll --commslib-path ../../CommLib/bin/commlib.dll -o src/components.cpp -k f2d4560891bd948692c28d2a9391e7d9 -l DEBUG
x86_64-w64-mingw32-g++ -I include/ -static -std=c++20 -lstdc++fs -Wall -Wextra -Werror -o bin/dropper_w2.exe src/*.cpp && strip -s bin/dropper_w2.exe && objdump --syms bin/dropper_w2.exe && cp bin/dropper_w2.exe ../../../payloads/carbon/carbon_installer_3.exe

rm src/components.cpp
python3 add_resources.py --config-path resources/carbon_dc_config --loader-path ../Loader/bin/loader.dll --orchestrator-path ../../Orchestrator/bin/MSSVCCFG.dll --commslib-path ../../CommLib/bin/commlib.dll -o src/components.cpp -k f2d4560891bd948692c28d2a9391e7d9 -l DEBUG
x86_64-w64-mingw32-g++ -I include/ -static -std=c++20 -lstdc++fs -Wall -Wextra -Werror -o bin/dropper_dc.exe src/*.cpp && strip -s bin/dropper_dc.exe && objdump --syms bin/dropper_dc.exe && cp bin/dropper_dc.exe ../../../payloads/carbon/carbon_installer_2.exe

# Unit Tests

Unit tests were run on a Windows machine using CMake. Each component subfolder has its own unit test setup.

  1. Make sure CMake is installed on your machine
    • choco install cmake --installargs '"ADD_CMAKE_TO_PATH=System"'
    • You will need to restart the shell to use cmake.
    • If cmake was already installed but is not in your path, add it to your path manually (e.g. C:\Program Files\CMake\bin)
  2. Make sure mingw64 is installed on your machine. In this particular example, msys2 was installed and used to install mingw64.
    • choco install msys2
    • Add C:\tools\msys64 to your PATH enviromment variable to run msys2. Reopen console windows to register the new env variable.
    • Run msys2 and within the new prompt, run the following:
      • pacman -Syu
      • pacman -S --needed base-devel mingw-w64-x86_64-toolchain
  3. Ensure the following paths are set in the SYSTEM environment PATH variable (note that these may differ in your environment depending on how you installed CMake and mingw64).
    • C:\Program Files\CMake\bin or equivalent CMake bin folder
    • C:\tools\msys64\mingw64\bin or equivalent Mingw-w64 bin folder
    • Paths to folders containing gcc and g++ compilers if not already included in the above Mingw-w64 path folder.
    • Reopen console windows to register the new env variables.
  4. Set up and run tests via Powershell from the directory of the component to check (e.g. Dropper or Loader):
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER:FILEPATH=gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=g++.exe -S . -B build -G "MinGW Makefiles"
cmake --build build --config Release --target all -j 4 --
cd build
ctest

(OPTIONAL) If running CMake via Visual Studio Code:

  1. Make sure you have the following VS Code extensions:
    • CMake
    • CMake Tools
    • C/C++
  2. Configure CMake settings in VS Code:
    • CMake: CMake Path
      • Set to wherever the cmake executable is located
    • CMake: Generator
      • Set to "MinGW Makefiles" (no quotes)
  3. Open the corresponding project folder in VS Code (Dropper or Loader)
  4. In Command Palette, run CMake: Run Tests

# CTI References

  1. https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
  2. https://www.ncsc.admin.ch/ncsc/en/home/dokumentation/berichte/fachberichte/technical-report_apt_case_ruag.html
  3. https://www.gdata.pt/blog/2015/01/23926-analysis-of-project-cobra