Join Trustwave at the 2023 Gartner Security & Risk Management Summit in London, September 26-28. Learn More

Join Trustwave at the 2023 Gartner Security & Risk Management Summit in London, September 26-28. Learn More

Managed Detection & Response

Eradicate cyberthreats with world-class intel and expertise

Managed Security Services

Expand your team’s capabilities and strengthen your security posture

Consulting & Professional Services

Tap into our global team of tenured cybersecurity specialists

Penetration Testing

Subscription- or project-based testing, delivered by global experts

Database Security

Get ahead of database risk, protect data and exceed compliance requirements

Email Security & Management

Catch email threats others miss with layered security & maximum control

Co-Managed SOC (SIEM)

Eliminate alert fatigue, focus your SecOps team, stop threats fast, and reduce cyber risk

Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
The Trustwave Approach
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Platform
SpiderLabs Fusion Center
Security Operations Centers
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats

Reversing (and Recreating) Cryptographic Secrets Found in .NET Assemblies Using Python

Picture the scene - you’re on a penetration test, somehow you’ve got hold of a bunch of .NET assemblies for the application you’re assessing, be it a web application or thick client. On a thick client test, getting a hold of these files is somewhat trivial as they’re right there in front of you. On a web application test, however, things are not as easy - but it still is possible, depending on permissions and such. I won’t go into "the how-to" in order get these in this blog post, instead I will assume you’re sitting there, a cup of coffee in hand, staring at a bunch of .DLL files decompiled in something like dotPeek, ILSpy, etc.

Looking at the source code of decompiled assemblies relating to an application you’re assessing is an eye-opening experience. You’ll learn the inner workings of the application which will support the testing, and often, as a bonus, you’ll find hardcoded secrets, mostly in the form of user credentials – ranging from database connection strings to domain accounts. Sometimes this process can make you work a little bit harder for the rewards.

You may, for example, find no quick wins - no plaintext credentials, no advance to go and collect $200. Instead, you may find something like a reference in the source code to an external configuration file. The application may use this configuration file to look up some values and then utilise them. Imagine a reference in the source code to something like the below, we’ll call the file it references spiderconfig.xml.


Let’s imagine this spiderconfig.xml file relates to a .NET web application, which utilises the domain account “SPIDER\SpideyAdmin” to carry out privileged functionality. The “==” padding right at the end of the password value should scream out right away that this is likely to be base64 encoded. Decode it and profit? Not quite! Mostly unprintables are returned – not a password in this form.


It is also worth stating at this point that the password may actually be the value in the config file as is, without any encoding and actually contains the characters “==” at the end. I wouldn’t rule this completely out!

Assuming that this is not actually the password, we must go back to the assembly in question and find some cryptographic references. After some browsing, a class called “crypto_component” is found, byte object names such as c_key (32 bytes) and c_iv (16 bytes), references to Rijndael, etc. I think we’re onto a winner here.


We have the initialization vector (IV) and encryption key. The “Rijndael” reference reveals it to be using Advanced Encryption Standard (AES), a symmetric block cipher. We have everything we need to be able to decrypt the password value in the spiderconfig.xml file, we are just missing magical crypto stuff.

Enter Python. *faint trumpet noise can be heard in the background*

We import AES from Crypto.Cipher, together with a bunch of useful things from binascii.
[1] Both the encryption key (c_key) and iv (c_iv) are loaded into bytes objects.
We setup AES using our key and IV and configure AES in cipher block chaining (CBC) mode.
[2] We provide the base64 encoded value from the configuration file, call “a2b_base64” from binascii on it to turn it back into binary data.
[3] We then call AES decrypt on the ciphertext (which uses our key and IV).


We pull the magic crypto levers and something which more likely resembles a password is returned: Welcome1
(note: the \x08 at the end is just padding due to the block size of 16 and this being an 8 character password)

Just for fun, let’s reverse things around and encrypt this back, validating that our IV works.

[4] The plaintext “Welcome1” is passed back into AES but this time encrypting it (with our key and IV).
[5] The result of this is then passed into “b2a_base64” from binascii (but not a2b_ like last time), this converts a line of ASCII characters into base64 encoding, as per our configuration file.


The final result matches the base64 encoded value in our configuration file from the start, so this confirms that both the key and IV we have work as intended.

One privileged domain account obtained. Time for a cup of tea and biscuits.