Carbon Paper: Peering into Turla’s second stage backdoor
By ESET Research
Archived: 2026-04-05 16:40:28 UTC
The following analysis is based on the version 4.x of msximl. This component may have changed in the latest
versions.
Configuration fetching
Besides the code in the "Configuration fetching" thread from the orchestrator (which is similar), a field "sethttp1"
is retrieved from the [TRANSPORT] section.
If this value is set, HTTP 1.1 will be used for future connections.
Tasks execution
The tasks are retrieved from the C&C server.
The tasks to be executed by the communication library are listed in the file "b9s3coff.ax" (for Carbon v3.7x) or
"cifrado.xml" (for Carbon v3.8x).
Each line of this file is composed in the following way:
task_id | task_filepath | task_config_filepath | task_result_filepath | task_log_filepath
The task file and its config are decrypted (CAST-128) and the task executed. There are some options that are
retrieved from the Carbon configuration file: "time2task" is used to set a timeout for the task execution (1 hour by
default) while "task_min" and "task_max" are used as to wait a random time between the execution of the tasks on
the task list (the random time will be set between "task_min" and "task_max"). These parameters come from the
section [TIME].
If the task is a valid DLL file, it is loaded in the current process memory and a new thread is created to execute its
"start" export. Otherwise, this is probably a command to execute. In this case, the configuration file is parsed. Like
the Carbon configuration file, the task configuration file is formed as a windows "inf" file and should contain a
section [CONFIG] with the following parameters:
[CONFIG]
NAME ("cmd.exe" by default)
ARG
RESULT ("stdout" by default)
COMPRESSION ("yes" by default)
DELETE ("no" by default)
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 1 of 8
The command with its arguments is executed through CreateProcess() function and the results are stored in the
%task_result_filepath% file if the RESULT option is not set to "stdout", while error or additional info are added to
the task logfile.
If the option RESULT is set to stdout:
the result task file is deleted and the task execution output is written to the log task file
the line "task_id | "1" | task_log_filepath | object_id" is added at the end of the file "C_56743.NLS"
(Carbon 3.7x) or "dsntype.gif" (Carbon 3.8x)
Otherwise:
the task execution is outputted to the task result file and the errors / additional info to the task logfile
the line "task_id | "2" | task_log_filepath | task_result_filepath | object_id" is added at the end of the file
"C_56743.NLS" (Carbon 3.7x) or "dsntype.gif" (Carbon 3.8x)
In both cases, the same line as written into "C_56743.NLS" is also written into the field "run_task" from the
Carbon configuration file. It might be intended as a way for the malware authors to know which is the last task
executed when the configuration file is sent to the C&C server (check "Configuration file backup").
Log rotation
The logfile is backed up and sent to the C&C server periodically (by default this is done every two hours).
Like the backup of the configuration file, this action is performed only during specific times of the day.
Indeed, the log rotation will be performed only when the current local time is in the range of what is defined in the
configuration file.
The fields "wh_min" and "wh_max" are retrieved from the [TIME] section of the configuration file (by default: 8
and 20). The thread will execute the code only if the current hour of the day is between %wh_min% and
%wh_max%.
If there is a value for the attribute "timestop" from the [TIME] section (which looks like
"wDay:wMonth:wYear:wHour:wMinute"), the thread will execute the code only after this specific datetime.
The attributes "lastsend" and "logperiod" from the [LOG] section are used to specify a delay time when to backup
and send the log to the C&C server. (by default: every two hours).
A temporary file with a random name prefixed by "~D" is created in the folder "208" (for Carbon v3.7x) or "1033"
(for Carbon v3.8x). The logfile content is copied into this new file. It is then compressed with Bzip2 and
encrypted (CAST-128).
A new line is added at the end of the file "C_56743.NLS" (for Carbon v3.7x) or "dsntype.gif" (for Carbon v3.8x):
"10|1|%s|%s"
1st field: an ID to identify the file as a logfile
2nd field: 1 (file to be sent to the C&C server)
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 2 of 8
3rd field: the temp file path
4rd field: the victim uuid
Last but not least, the attribute "lastsend" is updated with the current time and the original logfile is deleted.
Communication with the C&C server
The code of this thread is used to retrieve new tasks from the C&C server, to send new files to the server (the files
listed in the file "C_56743.NLS" / "dsntype.gif") and to send the new tasks to the orchestrator.
First request
A random C&C server address is chosen from the ones in the section "CW_INET". If the port and HTTP resource
path are not specified, the default is to use port 80 and "/javascript/view.php".
A user agent is set up in the following way:
the version of Internet Explorer is retrieved through the registry key: "HKLM\Software\Microsoft\Internet
Explorer\Version" and is concatenated to the string "Mozilla/4.0 (compatible; MSIE %d.0; "
example: "Mozilla/4.0 (compatible; MSIE 8.0.6001.18702.0;"
concatenate the previous string with the OS major/minor version values (through GetVersionExA())
"Mozilla/4.0 (compatible; MSIE 8.0.6001.18702.0; Windows NT 5.1; Trident/4.0"
enumerate the values key in "HKLM\Software\Microsoft\Windows\CurrentVersion\Internet
Settings\5.0\User Agent\Post Platform" and concatenate each value to the previous string and then append
a closing paren.
example: "Mozilla/4.0 (compatible; MSIE 8.0.6001.18702.0; Windows NT 5.1; Trident/4.0; .NET
CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E; Media Center
PC 6.0; SLCC2)
The field "trans_timemax" from the section [TIME] is retrieved. It is used to set the timeout for internet requests
(through InternetSetOption()). It has a value of 10 minutes by default.
A first GET request is performed on the root page of the C&C web server to check that the host is alive. If no
packet capture is running on the system, a new request is done on the C&C server to check if new tasks are
available. A "PHPSESSID" cookie is added to the request with the victim uuid as its value. A header "Referer" is
added as well and set to the C&C server URL.
The malware is expecting to get an answer to the GET request similar to:
If the field "value" contains something, a new task is available.
Send data to the server
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 3 of 8
If the file "C_56743.NLS" / "dsntype.gif" is not empty, it means there are data to be sent the C&C server. The file
is parsed and the last line is retrieved. It contains details about the data to be sent. A data blob is built and each of
the following fields is encrypted with CAST-128:
id | val | tmp_filesize | tmp_content | [OPTIONAL (if val == 2) tmp2_filesize | tmp2_content] |
len_object_id | object_id
id = the type of data to send to the C&C server, it can be:
10: log backup
11: configuration file
20: a cryptographic key
otherwise: an id associated to a task, it can be the result of a task or an error log in the case of
task execution failure
val = 1 if there is only one file to send, 2 if there are two files
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 4 of 8
object_id = the victim uuid
If the field "dtc" from the section [CRYPTO] of the configuration file is set to 0, this whole blob is base64
encoded and sent to the C&C server through a POST request.
Otherwise, another layer of encryption is used. In this case, the data blob is signed and a random 3DES key is
used to encrypt it. Because the 3DES key is randomly generated and the server needs it to decrypt the data, the
key is encrypted with the server public key. The server key is retrieved from the field "publicc" of the section
[CRYPTO] from the configuration file.
This new blob (encrypted_key | signature_data | encrypted data) is encoded in base64 and sent to the C&C server
through a POST request.
In order to avoid detection based on the data size sent in a request, the blob can be fragmented into several
packets. An option in the configuration file ("post_frag" in the section [TRANSPORT]) defines whether the blob
will be fragmented or sent in only one POST request.
If this option is set to "yes", the blob is divided into several fragments of a specific size. This size comes from
another field in the configuration file: "post_frag_size".
An additional header will be added to the request:
"Content-Range: bytes %u-%u/%u; id=%u\r\n", i, i+(fragment_size-1), data_size, task_id"
If the option http11 is set, a specific header is added as well:
"Expect: 100-continue\r\n"
For each fragments sent, the fields "post_frag_size" and "pfslastset" from the config file (section
[CW_INET_RESULTS]) are updated with the fragment size and the timestamp.
Get new tasks
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 5 of 8
New tasks are retrieved from the C&C server by parsing the html page. The malware expects to find the html tag
in the page with a base64 encoded blob in its "value" attribute. Once decoded, this blob contains:
an encrypted block of 128 bytes that contains a structure "PUBLICKEYSTRUC" followed by a
cryptographic key (probably a 3DES key)
signature data (128 bytes) to verify the integrity of the next block
a block of encrypted data that contains the task
The malware uses an RSA private key (retrieved from the field "keypair" from the section [CRYPTO] of the
configuration file) to decrypt the first block and then uses the freshly decrypted key to decrypt the third block.
This block of data can be either:
a task to be executed [6]
the data are decrypted and stored in few temporary files, the task (a command or a PE file) and its
configuration file in the "Nls" folder and the output files (file that will contains the task results and
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 6 of 8
the logfile) are stored in the folder "0208" (or respectively "0409" and "1033" for Carbon v3.8x)
task_id | task_filepath | task_config_filepath | task_result_filepath | task_log_filepath
this line is appended to beginning of the file "b9s3coff.ax" (cifrado.xml on v3.8x)
a task to be executed by the orchestrator [7]
the data are decrypted and stored in few temporary files (the task, its configuration etc) in the "Nls"
and "0208" folder (or "0409" and "1033" for Carbon v3.8x)
depending of the content of the data, one of these lines will be added to the beginning of the file
"a67ncode.ax" (encodebase.info on v3.8x)
task_id | task_filepath | task_config_filepath | task_result_filepath | task_log_filepath
task_id | task_filepath | task_config_filepath | task_result_filepath | task_log_filepath |
execution_mode | username | password
task_id | task_filepath | task_config_filepath | task_result_filepath | task_log_filepath |
execution_mode
a new RSA server public key
in this case, the configuration file is updated with the new key encoded in base64 (field publicc)
data to be sent to an instance of Carbon running in another computer in the same network
the data can contains a specific IP address and port, a named pipe or a named pipe with a username
and password.
Check Internet availability
Each hour, the internet connection is checked. A first check is done by calling the function
InternetAttemptConnect(). If it works, another test is done by sending HTTP GET requests to the following
websites:
www.google.com
www.yahoo.com
www.bing.com
update.microsoft.com
windowsupdate.microsoft.com
microsoft.com
An event is used to notify the other threads in case of the loss of Internet access.
Configuration file backup
Similar to the logfile, the configuration file is also periodically backed up and sent to the C&C server. The thread
executes the code in a specific range of time (between 8h and 20h by default) [8].
The value "configlastsend" is retrieved from the section [TIME] of the configuration file. If the config file has
been sent over a month ago, the config file is copied into a temporary file with a random name prefixed by "~D"
in the folder "208" (for Carbon v3.7x) or "1033" (for Carbon v3.8x). This file is then encrypted with CAST-128
algorithm.
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 7 of 8
To notify the thread that communicates with the C&C server that a new file is ready to be sent to the server, the
following line is appending to the file "C_56743.NLS" (for Carbon v3.7x) or "dsntype.gif" (for Carbon v3.8x):
"11|1|%s|%s"
1st field: an ID to identify the file as a config file
2nd field: 1 (file to be sent to the C&C server)
3rd field: the temp filepath
4rd field: the victim uuid
Last but not least, the attribute "configlastsend" is updated with the current time.
Source: https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-second-stage-backdoor/
Page 8 of 8