Inspiration + Problem
Criminals gravitate toward blockchain and cryptocurrencies due to their reputation of complete privacy. Although the full ledger of transactions is publicly available, the information is anonymous, so it is difficult to identify the nefarious actors. To date, most blockchain forensics research revolves around analyzing the blockchain to deanonymize transactions, and there has been little work involving the end-user software, or crypto wallets. We believe that when an investigation necessitates control of a user’s wallet and transaction history, a memory forensics solution targeting the crypto wallet will provide immense aid in gathering incriminating evidence.
What it does
BlockBusters (BB) uses memory forensics to recover artifacts from cryptocurrency client applications and link an individual computer to blockchain transactions. We realized traditional disk forensics will not work here as crypto wallets encrypt their keys on the filesystem, but in volatile memory, keys must be stored unencrypted for the wallet to function.
The algorithmic procedure is as follows:
- BB isolates the wallet process memory and finds _PyRuntime, a global default variable linked to the Garbage Collector generations.
- BB traverses the GC and searches for two objects of types “EllipticCurvePublicKey” and “EllipticCurvePrivateKey.”
- After recovering them, BB walks through data structure pointers and recovers the key pair’s raw bytes.
- BB serializes the bytes to a readable string and outputs that to the investigator.
The plugin recovers the public and private key pair which can be used in conjunction with a blockchain search engine to isolate suspicious transactions and also seize funds from the crypto wallet.
How we built it
A big part of forensics is developing a deep understanding of the underlying software before writing any code. We first broke down a crypto wallet application into different layers of components and worked to understand each one separately: the cryptography library, the Python process, the CPython structs, and the key pair.
After tracing their execution using GDB and perusing their source code and documentation, we replicated each critical data structure in Volatility by identifying their memory layouts and operations we needed to conduct on them.
Next, we outlined the procedure to recover a key pair. After realizing a brute force scan of the process heap was too slow, we found that Python’s Garbage Collection generations provided an optimization. They are guaranteed to track the keys because keys in the pyco/cryptography library are non-atomic objects, so we can quickly traverse this doubly linked list to find objects that have that specific type name. Afterwards, we tested and coded the procedure to recover the raw bytes of the public and private keys and serialize that into a human-readable form.
The final stage of our project was extensive testing. We took memory images of various sizes with different key size parameters to ensure robustness. We noticed that the accuracy was consistently 100% and the runtime of our plugin was constantly well under a minute, and we felt happy about the performance.
Challenges we ran into
- We had difficulties understanding pyco/cryptography’s implementation of elliptic curve key generation and how crypto wallets store them.
- Python is interpreted to C++ at the low level, so we took some time to understand and replicate data structures (_PyUnicodeString, _PyBytesObject, _PyInstanceObject)
- The original version of our plugin was a brute force of the entire process memory, so it was slow (> 10 minute runtime). We made some clever optimizations based on our understanding of Python’s Garbage Collector system.
Accomplishments that we're proud of
We are thrilled to have created this memory forensics plugin! These 1168 lines of code represent the culmination of many hours of testing and debugging as well as planning out different optimization strategies. Because of this, our software development skills have improved, and we are grateful for this opportunity.
Learning about cryptography and blockchain was also gratifying because after hearing about them so much, we always wanted to learn more about their inner workings. While we were surprised by their complexity, we are glad we took time to scrutinize the source code and documentation, and we can confidently say that we understand a little more.
What we learned
This project provided us a foundation in cryptography and blockchain. More specifically, we learned about asymmetric encryption and different cipher suites as well as the fundamentals behind cryptocurrencies. Reading about their implementations gave us an appreciation for the work behind securing our transactions.
Before this, we had some experience with memory forensics and reverse engineering, but we definitely improved our capabilities to quickly understand other people’s code and replicate that in a Volatility plugin. We learned how to use GDB to trace a program’s execution and use debug symbols to identify different structs’ memory layouts.
What's next for BlockBusters
More automation. Right now, the processes outlined below must be performed manually, so automation will be invaluable, especially in time-sensitive investigative cases.
- We plan on developing a web-client application that interfaces with blockchain search engines to filter the transactions by the public key recovered from the wallet. This would allow investigators to quickly identify exactly which transactions the perpetrator executed at what times.
- We will combine our current plugin with a memory image profile detection software, so investigators do not have to take time to recognize the operating system and kernel image of the target machine.
We hope that after many revisions, this project can be put in production, so we can help cryptocurrency investigators catch criminals faster.