Didier Stevens

Monday 14 December 2020

Decrypting TLS Streams With Wireshark: Part 1

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

In this first example, I show how to decrypt a TLS stream with Wireshark.

I made my example as such, that the encryption in this example is done with keys derived from a master secret. This master secret is derived from a pre-master secret, which is securely exchanged between the client and server using RSA crypto.

Remark that this method will not work with modern browsers and web servers, as they use perfect forward secrecy. This will be explained in part 2.

I use my TCP honeypot to set up a web server, and curl to request a page over TLS. I use curl for Windows build with OpenSSL, and not the curl version distributed with Windows 10, that relies on schannel.

I use the following curl command with options to force a TLS encryption method that is based on a pre-master secret that is encrypted with the public RSA key of the server:

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

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.

Option –insecure is necessary because I’m using a self-signed certificate.

I choose the other options to produce as much information as possible: downloaded content (01.data), headers (01.headers) and a trace file (01.trace).

Here is a screenshot of the packet capture for this HTTPS traffic:

Following the TCP stream shows that the data is encrypted (except for some parts during the handshake, like the certificate):

If we inspect that handshake, more precisely, looking at the Server Hello packet, we see that a cipher suite was selected that relies on RSA and AES:

Data encrypted with this cipher suite can be decrypted by Wireshark when we provide the private RSA key of the server. That’s because in this example, Wireshark needs to decrypt the pre-master secret sent by the client to the server. This pre-master secret is encrypted with the public RSA key of the server.

These are the steps to follow:

Go to preferences:

Search for the TLS protocol, and edit the RSA Keys list.

Click the + button to add a key:

Then add the RSA private key key-20180317-161753.pem.

When you then close the dialogs, and the main screen regains focus, the TLS data will be decrypted:

Remark that for packets 9 and 10, the Protocol column value changed from TLSv1.2 to HTTP, and the Info column from Application Data to HTTP methods and replies.

And in the bottom view (hexadecimal & ASCII dump), a “Decrypted TLS” tab was added:

We will now try the 3 available Follow Streams commands:

When we select TCP, we still have encrypted data:

But when we select Follow TLS stream, we can now see the decrypted data:

And with Follow HTTP, we also have decrypted data:

But remark that there is some data duplication, this is possibly a bug in Wireshark. To be investigated.

In part 2, we will look at the same request, but without using the server’s RSA private key, and also at an example with perfect forward secrecy.

Next blog posts:

Decrypting TLS Streams With Wireshark: Part 2
Decrypting TLS Streams With Wireshark: Part 3

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

tls-decryption-part-1.zip (https)
MD5: 905A5D3F2D0AEAA98BD3751AD5CAD9E2
SHA256: 03175A0C6EC5B451769AA7627BFA0487FFFB2485D455D467CCCA9CCD1075ACA9

Wednesday 18 November 2020

Decrypting With translate.py

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

You’ve probably encountered malicious PowerShell scripts with an encrypted payload (shellcode, PowerShellScript, …).

Here is an example that I created:

Update: this example is on pastebin: https://pastebin.com/QUGiWTHj

There are 2 BASE64 strings in this script. The first one (cfr. variable $cfii) is the encryption key. The second one (cfr. variable $hctqdvb) is the payload.

The script uses AES encryption, with a 256-bit key, CBC mode, PKCS7 padding and an initialization vector (IV) that is stored in the first 16 bytes of the payload (0..15).

And after the payload is decrypted, it has to be decompressed with the Gzip algorithm.

With base64dump.py, I can find the 2 BASE64 strings in the PowerShell script:

I select the second BASE64 string (payload) to pipe into translate.py, using the following small Python script (decrypt.py) to do the decryption:

from Crypto.Cipher import AES
from Crypto.Util import Padding

def Decrypt(data):
    iv = data[0:16]
    ciphertext = data[16:]
    key = binascii.a2b_base64(keybase64)
    oAES = AES.new(key, AES.MODE_CBC, iv)

return Padding.unpad(oAES.decrypt(ciphertext), 16)

This small script uses crypto functions from pycryptodome.

I use translate.py in fullread mode (-f –fullread, to “translate” the file in a single step, in stead of byte per byte) and use function Decrypt to decrypt the block of data, like this:

I load the script decrypt.py with option -s, and I pass the key as a BASE64 string via option -e.

The output is non-printable bytes, because the decrypted payload is Gzip compressed. I use translate.py again to do the decompression:

And now the “payload” I used is decrypted and decompressed: “This is a test!”

 

Monday 20 July 2020

Cracking VBA Project Passwords

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

VBA projects can be protected with a password. The password is not used to encrypt the content of the VBA project, it is just used as protection by the VBA IDE: when the password is set, you will be prompted for the password.

Tools like oledump.py are not hindered by a VBA password, they can extract VBA code without problem, as it is not encrypted.

The VBA password is stored as the DPB value of the PROJECT stream:

You can remove password protection by replacing the values of ID, CMG, DPB and GC with the values of an unprotected VBA Project.

Thus a VBA password is no hindrance for staticanalysis.

However, we might still want to recover the password, just for the fun of it. How do we proceed?

The password itself is not stored inside the PROJECT stream. In stead, a hash is stored: the SHA1 hash of the password (MBCS representation) + 4 byte salt.

Then, this hash is encrypted (data encryption as described in MS-OVBA 2.4.3.2) and the hexadecimal representation of this encrypted hash is the value of DPB.

This data encryption is done according to an algorithm that does not use a secret key. I wrote an oledump.py plugin (plugin_vbaproject.py) to decrypt the hash and display it in a format suitable for John the Ripper and Hashcat:

The SHA1 of a password + salt is a dynamic format in John the Ripper: dynamic_24.

For Hashcat, it is mode 110 and you also need to use option –hex-salt.

Remark that the password passed as argument to the SHA1 function is represented in Multi Byte Character Set format. This means that ASCII characters are represented as bytes, but that non-ASCII characters might be represented with more than one byte, depending on the VBA project’s code page.

 

Thursday 30 April 2020

Update: zipdump.py Version 0.0.19

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

This new version of zipdump uses module pyzipper in stead of build-in module zipfile.

pyzipper supports AES encryption. It is not a built-in module, and needs to be installed (with pip for example). pyzipper does not support Python 2.

If module pyzipper is not installed, zipdump will fall back to module zipfile.

zipdump_v0_0_19.zip (https)
MD5: 6DDE072811D4B44B15D0B8EE4E7B4C03
SHA256: EB38D57E63B12EFAC531B4F0BA866BF47CAEC7F64E0C3CCF4557476FFF1C6226

Tuesday 31 March 2020

Update: msoffcrypto-crack.py Version 0.0.5

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

This new version of msoffcrypto-crack.py, a tool to crack encrypted MS Office documents, comes with a new option to generated a password dictionary based on the filename of the document.

Option -p allows the user to provide a dictionary file. Use value #f to generate a dictionary based on the filename: This will generate a dictionary of all possible substrings of the filename.

I had to analyze an encrypted spreadsheet yesterday, and the password was in the name, like this:

msoffcrypto-crack_V0_0_5.zip (https)
MD5: 1514DA367DCFF7051AB117266CE65BD3
SHA256: FEEFDD89134083EA19936494C8FCBD05804B3B9C0D4C5FBAFE06578D466B50AE

Wednesday 15 January 2020

Using CveEventWrite From VBA (CVE-2020-0601)

Filed under: Encryption — Didier Stevens @ 19:46

Microsoft’s patch for CVE-2020-0601 introduces a call to CveEventWrite in CryptoAPI when a faked certificate is detected.

This will write a Windows event entry in the Application event log.

For all of you out there in restricted corporate environments who need to test the processing of this event log entry, I wrote some VBA code to generate this event. The generated event will mimic a CVE-2020-0601 warning to some extent (didn’t bother getting para and otherPara right).

Copy the VBA code below in an Office application that supports VBA, like Word, and run the code. Then check your Application event log.


Option Explicit

'VBA7
Declare PtrSafe Sub CveEventWrite Lib "advapi32" (ByVal CveId As String, ByVal AdditionalDetails As String)

Sub TestCveEventWrite()
    Dim strCveId As String
    Dim strAdditionalDetails As String

    strCveId = "[CVE-2020-0601] cert validation"
    strAdditionalDetails = "CA: <@DidierStevens> sha1: 7A036FBBDBF7F29A3821A8087CE177E60927A6F3 para: something otherPara: something"
    CveEventWrite StrConv(strCveId, vbUnicode), StrConv(strAdditionalDetails, vbUnicode)
End Sub

 

Monday 20 May 2019

WebDAV, NTLM & Responder

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

I was trying to create a capture file with NTLM authenticated WebDAV traffic, using Responder: I couldn’t get it to work. There was WebDAV traffic, but no NTLMSSP headers.

Long story short: there’s a bug in Responder version 2.3.3.9. It manifests itself when the WebDAV client sends a request with just headers, and “Content-Length: 0”, like this:

The code in Responder “sees” just “Content-Length” and waits for more packets:

I made a quick & dirty fix: break out of the loop when we see “Content-Length: 0” (servers/HTTP.py):

And now I have NTLMSSP headers:

I just start my modified version of Responder:

Generate WebDAV traffic from a Windows 7 client:

And Responder participates in the challenge:

This can of course be cracked (if the password is not too complex), with John The Ripper for example:

I also have a blog post with more details about WebDAV traffic from Windows clients.

Once I got Responder to work, I searched on Laurent’s Responder repository, and found a pull-request to fix issues with “Content-Length: 0” requests (this PR has not been merged yet). Hence I’m not going to do my own PR.

You can find the capture file here:

webdav-ntlm-responder.zip (https)
MD5: A427DDBDAF090E93BB75B7A8DE696826
SHA256: 2F92CDD7382DD3622AC1F8769CF9D065C60C235DEF764E6709C32E2C4A7554A8

Sunday 19 May 2019

Quickpost: Retrieving an SSL Certificate with nmap

Filed under: Encryption,Networking,Quickpost — Didier Stevens @ 8:28

One of my first quickposts, more than 10 years ago, was an howto: using openssl to retrieve the certificate of a web site.

Since then, nmap has a scripting engine, and there is a script to check a certificate with nmap: ssl-cert.nse.

You just have to scan the site and port for which you want to check the certificate, like this: nmap -p 443 –script ssl-cert didierstevens.com

If you want the certificate too, increase verbosity with option -v:

Checking a certificate will not work if you scan a port that is not known to provide SSL/TLS:

In that case, you have to use service discovery (-sV):

 


Quickpost info


Saturday 26 January 2019

Update: msoffcrypto-crack.py Version 0.0.3

Filed under: Encryption,My Software,Update — Didier Stevens @ 13:44

This is a bug fix update: for agile encryption, Python module msoffcrypto does not throw an exception in method load_key when an invalid password is provided. It throws an exception when an attempt is made to decrypt the file.

I added a call to method decrypt to handle this case.

msoffcrypto-crack_V0_0_3.zip (https)
MD5: 45BAB81D744DA62182EC58A8F2E05BFE
SHA256: CF9DE02C72C07C07786BE09551CD17F6DBB83BCEF2A1C5435E06A695D7C6770E

Monday 7 January 2019

Update: msoffcrypto-crack.py Version 0.0.2

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

In this update of msoffcrypto-crack.py, two new options were added:

-e takes a text file and extracts all words from this text file to be used in the dictionary attack. Words are strings delimited by space characters. Words between single or double quotes, and words after string “password” are put at the beginning of the list for the dictionary attack.

The idea for option -e, is that you give it the content of an email message that contains the password of the encrypted attachment(s).

-c takes the password to decrypt the document. You use this option after the password was recovered (with option -p or -e for example), and need to run the tool again to decrypt the document. You can run the password cracking each time when you need to decrypt the document, but if this takes too long, then you just run it once and from then on provide the recovered password with option -c.

Password VelvetSweatshop was added to the embedded password list.

msoffcrypto-crack_V0_0_2.zip (https)
MD5: 010B7FA68FCF9CE84427815EFDFE1C42
SHA256: 6B368E40EEE8A907D444A49963B37F456A3645991201CE06F0E46A0F2E188A74

« Previous PageNext Page »

Blog at WordPress.com.