SquirrelWaffel Config Extraction
Writing a config extractor for SquirrelWaffel
- Overview
- References
- Setup
- Extract the .rdata section
- Parse .rdata
- Decryption function
- Decrypt the blocklist
- Decrypt the c2s
- Clean up the c2 list
import pefile
SAMPLE_PATH = r'/tmp/squirrel.bin'
data = open(SAMPLE_PATH,'rb').read()
pe = pefile.PE(data=data)
rdata = None
for s in pe.sections:
if b'.rdata' in s.Name:
rdata = s.get_data()
len(rdata)
Parse .rdata
The encrypted strings in the .rdata
section are followed by their key and all data, keys, and strings are seperated by null bytes. We can parse out the data and key by splitting the .rdata
on null bytes then looking for the largest blocks of data. These are likely the encrypted blocklist and the encrypted c2 list.
We want to maintain two lists of data blocks, one sorted and one original order. This way we can use the sorted list to get the largest blocks, and the original order list to find the key which is sequentially after the encrypted data.
blocks = rdata.split(b'\x00')
blocks = [x for x in blocks if x != b'']
blocks_sorted = sorted(blocks, key=len)
def decrypt(key, data):
out = ''
for i in range(len(data)):
out += chr(data[i] ^ key[i % len(key)])
return out
for i in range(len(blocks)):
if blocks[i] == blocks_sorted[-1]:
out = decrypt(blocks[i+1], blocks[i])
print(out)
for i in range(len(blocks)):
if blocks[i] == blocks_sorted[-2]:
out = decrypt(blocks[i+1], blocks[i])
print(out)
print(out.replace('|','\n'))