Didier Stevens

Thursday 31 December 2020

Update: rtfdump.py Version 0.0.10

Filed under: My Software,Update — Didier Stevens @ 10:38

This is a Python 3 update for my tool to analyze RTF files. There are some new features, like option -O, to produce an overview:

More details in upcoming maldoc analysis posts.

rtfdump_V0_0_10.zip (https)
MD5: E7D235AC14A83DAABCD433DE1948E989
SHA256: 750430C0DA0B9D25B0BBBB972F107D1459FEAF45A2D61EAB6C10E84CB8AA01F8

Monday 28 December 2020

Decrypting TLS Streams With Wireshark: Part 2

Filed under: Encryption,Networking — Didier Stevens @ 0:00

In blog post “Decrypting TLS Streams With Wireshark: Part 1“, I explain how to decrypt TLS streams with a specific type of encryption (pre-master secret exchanged via RSA) using the web server’s private key.

In this blog post, we will use the client to get the necessary information to decrypt TLS streams.

We do this by setting environment variable SSLKEYLOGFILE and subsequently launching our client (Chrome, Firefox, curl, …, but not Internet Explorer).

When this environment variable is set, a compatible TLS client will write data in the text file pointed to by SSLKEYLOGFILE. This data can be used to decrypt the TLS stream.

In a first test, I set SSLKEYLOGFILE=secrets-1.txt and issue exactly the same curl command as in part 1:

curl.exe –verbose –insecure –tls-max 1.2 –ciphers AES256-SHA –dump-header 01.headers –output 01.data –trace 01.trace –trace-time

To force a cipher suite that is based on RSA for the exchange of the pre-master secret, I use options –tls-max 1.2 and –ciphers AES256-SHA.

Here is the content of secrets-1.txt:

RSA b73e7985e324abc0 030330f29c3ac42f28d91c967ad9c4b484f625ac95f6ad1dfe4474eecb6395f8a6b607f80594ebe97b45f24cae774800
CLIENT_RANDOM 53a7bcdb320d3cc85dbb21956403da8801617a2980fb79f7b50fd6d1189d0472 cce8feba2219194646201279f1bbc551035ce3d1f8a34d3514df8297078fa80f0e5b19e5aa965adf285e93e41c93c210

This file can be used in Wireshark to decrypt the TLS stream. Just like in part 1, we go to preferences for the TLS protocol:

I already removed the RSA private key that was set in part 1 (so that it will not influence my part 2 tests):

And then I set the “(Pre)-Master-Secret log filename” to secrets-1.txt, the file that was written by curl because environment variable SSLKEYLOGFILE is set to secrets-1.txt.

When this is done, the TLS data is decrypted, as can be witnessed by the appearance of (green) HTTP protocol packets:

Wireshark is able to decrypt this TLS stream because of the secrets in file secrets-1.txt. There are 2 secrets in file secrets-1.txt, and each one, by itself, contains enough information for Wireshark to do the decryption.


The first secret in secrets-1.txt is: RSA b73e7985e324abc0 030330f29c3ac42f28d91c967ad9c4b484f625ac95f6ad1dfe4474eecb6395f8a6b607f80594ebe97b45f24cae774800
This is the pre-master secret.

b73e7985e324abc0 is the start (first 8 bytes) of the encrypted pre-master secret:

And 030330f29c3ac42f28d91c967ad9c4b484f625ac95f6ad1dfe4474eecb6395f8a6b607f80594ebe97b45f24cae774800 is the unencrypted pre-master secret.

Wireshark can use this pre-master secret, together with cleartext data found inside the TLS stream (client and server random), to calculate the master secret and session keys.

This RSA entry in itself is enough for Wireshark to decrypt this TLS stream (if we only keep the RSA entry in secrets-1.txt, Wireshark can still decrypt).


The second secret in secrets-1.txt is: CLIENT_RANDOM 53a7bcdb320d3cc85dbb21956403da8801617a2980fb79f7b50fd6d1189d0472 cce8feba2219194646201279f1bbc551035ce3d1f8a34d3514df8297078fa80f0e5b19e5aa965adf285e93e41c93c210

This is the master secret.

53a7bcdb320d3cc85dbb21956403da8801617a2980fb79f7b50fd6d1189d0472 is the client random:

And cce8feba2219194646201279f1bbc551035ce3d1f8a34d3514df8297078fa80f0e5b19e5aa965adf285e93e41c93c210 is the unencrypted master secret.

Wireshark can use this master secret to calculate the session keys.

This CLIENT_RANDOM entry in itself is enough for Wireshark to decrypt this TLS stream (if we only keep the CLIENT_RANDOM entry in secrets-1.txt, Wireshark can still decrypt).


SSLKEYLOGFILE can also be used to capture the secrets necessary to decrypt TLS streams encrypted with perfect forward secrecy (e.g. not relying on the server’s private key).

In a second test, I set SSLKEYLOGFILE=secrets-2.txt and issue this curl command:

curl.exe –verbose –insecure –dump-header 01.headers –output 01.data –trace 01.trace –trace-time

In this test, curl uses TLS 1.3 with perfect forward secrecy:

x25519 is Diffie-Helman based on elliptic curve Curve25519: we have perfect forward secrecy here that uses ephemeral Diffie-Hellman key exchange. Hence the private key of the server can not help us decrypt this TLS stream. We need the secrets saved in SSLKEYLOGFILE secrets-2.txt:

SERVER_HANDSHAKE_TRAFFIC_SECRET 3928c6ded8c2e9c251dc4c57f2a81935a3f0e5a61f3d40b25fd87d5f05db3e47 b8c81cee570a35f077664f16780017d7037adb1efacc448d05de9c806868290c32f587a1c29e577abcc7e5d1609f070b
EXPORTER_SECRET 3928c6ded8c2e9c251dc4c57f2a81935a3f0e5a61f3d40b25fd87d5f05db3e47 bc8a82770f43dc9b326cd8565b93ebfd3c6f9d9be53693510685b265980d98be7f8a7de613895b76454ec19d06e12825
SERVER_TRAFFIC_SECRET_0 3928c6ded8c2e9c251dc4c57f2a81935a3f0e5a61f3d40b25fd87d5f05db3e47 7e40bb08f33bfc281878450c08e21e1d2e92ca1214436aa8353925fee2fe39d69175710e90bd6c76940af5596862525e
CLIENT_HANDSHAKE_TRAFFIC_SECRET 3928c6ded8c2e9c251dc4c57f2a81935a3f0e5a61f3d40b25fd87d5f05db3e47 7aec5af0565c8fa05431534daf6a98da645ccf9eb791626008ebe5d9053e2e5046986e577e09b5a9f3355d4aff685111
CLIENT_TRAFFIC_SECRET_0 3928c6ded8c2e9c251dc4c57f2a81935a3f0e5a61f3d40b25fd87d5f05db3e47 7a31364a743eee1ba3ed10fc082099c1fb09ad9175fd5ec81101521a3f34e3f3ab6e83f0bd77529ce9ff3eb9f4beedad

And when I use this secrets-2.txt file with Wireshark, the TLS stream is decrypted:

If I comment-out all SSLKEYLOGFILE secrets-2.txt entries except the client secret entries, Wireshark can only decrypt data coming from the client (# is a line-comment):

And vice versa when I comment-out everything except the server secret entries:

Value 3928c6ded8c2e9c251dc4c57f2a81935a3f0e5a61f3d40b25fd87d5f05db3e47 found in each secrets-2.txt entry is the client random:

Remark that in these 2 tests, I set SSLKEYLOGFILE=secrets.txt. This makes that curl will create a file secrets.txt in its working directory. You can also use an absolute path, for example:

set SSLKEYLOGFILE=c:\demo\secrets.txt


In part 3, I’ll give some practical tips.


Previous blog post:

Decrypting TLS Streams With Wireshark: Part 1

Next blog post:

Decrypting TLS Streams With Wireshark: Part 3


The capture file, secrets, and other data used in this blog post can be downloaded here:

tls-decryption-part-2.zip (https)
MD5: 562F169A57557737D3E4B1F9CDF3B252
SHA256: 8DD27510B2F6CD58A55F42515EF756572658D2ADFE7CEA6151DD45EE5F7DB171

Sunday 27 December 2020

Update: 1768.py Version 0.0.4

Filed under: My Software,Update — Didier Stevens @ 0:00

This is an update of my tool to analyze Cobalt Strike beacons.

Option -l can be used to generate YARA rules to search for Cobalt Strike beacons with a given license ID.


1768_v0_0_4.zip (https)
MD5: 35779393F2DC6171731446F8E0AC361B
SHA256: 59148C2DA13BE4DB203F9444E837911476BDE74E41E5A82C865E9729101336D2

Saturday 26 December 2020

Update: base64dump.py Version 0.0.13

Filed under: My Software,Update — Didier Stevens @ 0:00

This is an update to my tool base64dump.py: a tool to detect and decode encodings like base64, hexadecimal, …

A new decoding option was added with version 0.0.13: dec (decimal).

base64dump_V0_0_13.zip (https)
MD5: B322C1E55108FB1559009FC4C1CF12DE
SHA256: EE6527B4F558439916D9854980D6980EECA9F130F37BBF4034453ABBD8BF3260

Friday 25 December 2020

Update: zipdump.py Version 0.0.21

Filed under: My Software,Update — Didier Stevens @ 0:00

This is a Python 3 bug fix version of my tool to analyze ZIP files.

zipdump_v0_0_21.zip (https)
MD5: 9B2839C1028FA5D07F2E07FDB56306D9
SHA256: 48653BB2B3009241C4C536BF64D16A6DFDA4B66D6658EC6BCFA79647AE4D5FA8

Thursday 24 December 2020

Video: Using numbers-to-string.py To Analyze FireEye Maldocs

Filed under: My Software,video — Didier Stevens @ 0:00

I created a video where I use my updated numbers-to-string.py tool to analyze a maldoc created with FireEye’s red team tool.

Wednesday 23 December 2020

Update: byte-stats.py Version 0.0.8

Filed under: My Software,Update — Didier Stevens @ 0:00

This is a Python 3 version of my byte-stats.py tool to produce statistics for arbitrary binary input.

byte-stats_V0_0_8.zip (https)
MD5: 2F6E672D821356EDBDA51A83662075E8
SHA256: 23A108A849FEB84002505463101D7DC47C52D12C80F812465B25996DBB34775C

Tuesday 22 December 2020

Update: cut-bytes.py Version 0.0.13

Filed under: My Software,Update — Didier Stevens @ 0:00

This is a bug fix version for cut-bytes.py, my tool to select (cut) bytes from binary input.

cut-bytes_V0_0_13.zip (https)
MD5: E16C2B6358A2AA642BCC9CC9B033FAEC
SHA256: 2276257173FD1DF65338CFA53DDE5522ED8A7D7E94BCC302117F535F584F14CF

Monday 21 December 2020

Update: translate.py Version 2.5.11

Filed under: My Software,Update — Didier Stevens @ 0:00

This version adds bit shift functions shl and shr. There’s also a bug fix.

translate_v2_5_11.zip (https)
MD5: CB3B7F284B2F5C73FC583BB8E91B33AA
SHA256: 99717783D1225E1B95EE721AA2C7F3A09AE02647E28E7C6337776363B9BFFC33

Saturday 19 December 2020

Update: strings.py Version 0.0.6

Filed under: My Software,Update — Didier Stevens @ 9:22

This new update to strings.py, my tool to extract strings, brings statistics with a new option: -a.

This option can be used together with other filtering options:

strings_V0_0_6.zip (https)
MD5: C4633CDAF3AEADE23738AA9356F50298
SHA256: 93A87F515103A0C9DA01D6DA034CE7FB5CC7E562B095EFF614EF09C8DD92D455

Next Page »

Blog at WordPress.com.