Overview

Notes from our live stream where we reverse engineered the squirrelwaffle loader and built a static config extractor for it.

References

Setup

Make sure you have pefile installed pip install pefile and you change the SAMPLE_PATH to the squirrelwaffle sample you have downloaded.

import pefile
SAMPLE_PATH = r'/tmp/squirrel.bin'
data = open(SAMPLE_PATH,'rb').read()

Extract the .rdata section

The .rdata section has the encrypted data and the decryption keys so let's grab that first.

pe = pefile.PE(data=data)
rdata = None
for s in pe.sections:
    if b'.rdata' in s.Name:
        rdata = s.get_data()
len(rdata)
20480

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)

Decryption function

The config decryption is a simple xor so we want to replicate this in python

def decrypt(key, data):
    out = ''
    for i in range(len(data)):
        out += chr(data[i] ^ key[i % len(key)])
    return out

Decrypt the blocklist

The largest encrupted block is likely the blocklist so let's decrypt that first.

for i in range(len(blocks)):
    if blocks[i] == blocks_sorted[-1]:
        out = decrypt(blocks[i+1], blocks[i])
print(out)
94.46.179.80
206.189.205.251
88.242.66.45
85.75.110.214
87.104.3.136
207.244.91.171
49.230.88.160
91.149.252.75
91.149.252.88
92.211.109.152
178.0.250.168
88.69.16.230
95.223.77.160
99.234.62.23
2.206.105.223
84.222.8.201
89.183.239.142
5.146.132.101
77.7.60.154
45.41.106.122
45.74.72.13
74.58.152.123
88.87.68.197
109.70.100.25
185.67.82.114
207.102.138.19
204.101.161.14
193.128.108.251
111.7.100.17
111.7.100.16
74.125.210.62
74.125.210.36
104.244.74.57
185.220.101.145
185.220.101.144
185.220.101.18
185.220.100.246
185.220.101.228
185.220.100.243
185.220.101.229
185.220.101.147
185.220.102.250
185.220.100.241
199.195.251.84
213.164.204.94
74.125.213.7
74.125.213.9
185.220.100.249
37.71.173.58
93.2.220.100
188.10.191.109
81.36.17.247
70.28.47.118
45.133.172.222
108.41.227.196
37.235.53.46
162.216.47.22
154.3.42.51
45.86.200.60
212.230.181.152
185.192.70.11
37.142.65.69
87.166.51.31
178.198.76.175
128.90.172.136
172.58.227.224
201.77.112.133
64.124.12.162
87.166.51.28
104.244.72.115
109.70.100.23
192.145.127.220
194.186.142.122
185.207.249.217
52.250.42.144
45.86.201.156
195.245.199.125
213.33.190.70
154.61.71.13
154.13.1.22
191.96.185.151
40.94.25.22
40.94.25.39
40.94.25.5
40.94.25.79
40.94.25.69
40.94.25.71
40.94.25.60
40.94.25.64
40.94.25.29
40.94.25.23
40.94.25.89
40.94.26.165
40.94.26.210
40.94.26.208
40.94.26.166
40.94.26.216
40.94.26.173
40.94.26.182
40.94.35.75
40.94.35.97
40.94.35.27
40.94.35.38
40.94.35.46
40.94.35.76
40.94.35.70
40.94.35.80
40.94.35.98
40.94.35.40
45.86.200.23
198.167.212.98
40.94.31.87
40.94.31.85
40.94.31.29
40.94.31.97
40.94.31.88
40.94.31.80
40.94.31.65
198.167.195.112
40.94.31.58
40.94.31.48
40.94.31.64
40.94.31.26
40.94.31.66
40.94.31.90
40.94.31.46
40.94.31.47
212.119.227.184
72.12.194.93
72.12.194.94
72.12.194.92
134.209.213.55
35.198.84.59
89.208.29.2
40.94.30.159
40.94.30.139
40.94.30.152
40.94.30.167
40.94.30.164
40.94.30.166
40.94.30.174
40.94.30.151
154.61.71.53
40.94.30.157
40.94.30.136
40.94.30.149
52.154.162.74
213.33.190.161
83.84.25.214
162.251.62.154
188.241.177.152
92.211.110.221
154.61.71.51
185.183.107.236
72.12.194.90
40.94.25.36
40.94.29.4
40.94.25.50
40.94.29.31
40.94.25.31
40.94.29.41
40.94.31.5
40.94.25.80
40.94.29.82
40.94.31.81
40.94.25.96
40.94.29.59
40.94.31.3
40.94.25.58
40.94.31.61
40.94.31.49
40.94.31.54
40.94.31.62
40.94.31.70
40.94.30.211
40.94.30.148
40.94.30.218
40.94.30.147
40.94.30.129
40.94.31.15
40.94.30.169
40.94.31.36
40.94.30.223
40.94.30.203
95.211.36.179
64.233.172.102
153.246.206.71
198.167.193.35
90.187.12.209
37.49.116.179
52.167.22.240
160.177.96.15
185.123.143.220
167.99.172.253
40.94.36.81
86.107.21.203
24.37.31.38
71.19.154.84
34.142.74.220
192.160.102.170
216.251.130.74
49.44.76.43
109.147.65.157
86.217.130.91
178.174.15.54
86.242.244.97
92.46.70.105
81.201.234.26
78.94.217.60
141.226.236.91
95.26.228.102
89.208.29.3
213.33.190.205
213.33.190.121
5.154.174.45
23.154.177.3
195.65.152.138
93.231.174.227
185.220.101.132
54.36.101.21
72.12.194.91
46.14.116.174
141.19.232.57
185.220.101.149
45.74.46.69
157.230.210.133
82.199.130.36
104.237.193.28
187.46.138.56
195.164.49.162
156.146.49.135
195.164.49.191
79.104.209.54
35.245.134.90
20.52.139.186
189.139.144.151
94.31.102.187
39.43.45.71
107.189.10.143
39.43.123.57
106.75.76.179
194.186.142.131
210.22.129.194
45.130.83.77
154.6.16.175
162.247.73.192
107.189.1.160
185.107.47.215
46.166.139.111
185.56.80.65
185.220.100.245
209.141.59.180
77.247.181.163
185.220.101.137
185.220.100.242
104.244.76.13
185.83.214.69
185.220.100.252
185.112.146.73
185.57.82.28
89.187.171.116
66.220.242.222
39.43.72.17
5.171.90.80
185.152.32.77
23.129.64.157
92.151.9.187
106.75.31.237
122.167.79.251
109.70.100.33
199.249.230.154
64.233.172.108
64.233.172.106
64.233.172.104
77.247.181.165
107.189.12.240
79.142.76.203
193.128.114.34
185.92.26.59
185.65.210.119
70.39.159.79
70.39.159.29
151.48.26.15
151.48.26.15
2.228.159.178
188.174.248.154
188.174.248.154
95.90.198.182
95.90.198.182
193.0.200.36
193.0.200.36
151.127.13.232
89.97.249.158
212.115.152.225
185.217.117.179
199.249.230.164
80.233.134.134
109.74.154.92
65.39.88.250
90.84.192.187
37.70.202.24
85.203.45.30
109.190.93.219
151.8.114.194
176.235.38.106
149.56.99.85
138.128.136.169
213.82.23.224
192.42.123.107
128.90.151.188
162.245.206.249
85.203.45.40
95.211.95.242
185.220.102.251
66.203.112.160
193.128.108.246
193.128.108.242
31.204.150.74
34.141.245.25
122.167.85.191
212.6.86.133
171.25.193.25
149.3.170.147
162.247.74.217
109.70.100.34
89.208.29.5
79.104.209.91
79.104.209.157
194.186.142.205
198.167.217.20
198.167.193.112
204.101.161.31
198.167.219.82
195.74.76.222
70.93.153.224
87.118.110.27
185.247.225.43
193.128.108.250
188.212.135.7
106.75.75.245
86.142.177.106
185.192.69.77
198.167.209.37
59.144.163.235
193.128.108.243
31.204.152.150
211.177.21.222
87.166.49.39
82.127.202.176
58.40.175.6

94.46.179.80
206.189.205.251
178.255.172.194
84.221.205.40
155.138.242.103
178.212.98.156
85.65.32.191
31.167.184.201
88.242.66.45
36.65.102.42
203.213.127.79
85.75.110.214
93.78.214.187
204.152.81.185
183.171.72.218
168.194.101.130
87.104.3.136
92.211.196.33
197.92.140.125
207.244.91.171
49.230.88.160
196.74.16.153
91.149.252.75
91.149.252.88
92.206.15.202
82.21.114.63
92.211.109.152
178.0.250.168
178.203.145.135
85.210.36.4
199.83.207.72
86.132.134.203
88.69.16.230
99.247.129.88
37.201.195.12
87.140.192.0
88.152.185.188
87.156.177.91
99.229.57.160
95.223.77.160
88.130.54.214
99.234.62.23
2.206.105.223
94.134.179.130
84.221.255.199
84.222.8.201
89.183.239.142
87.158.21.26
93.206.148.216
5.146.132.101
77.7.60.154
95.223.75.85
162.254.173.187
50.99.254.163
45.41.106.122
99.237.13.3
45.74.72.13
108.171.64.202
74.58.152.123
216.209.253.121
88.87.68.197
211.107.25.121
109.70.100.25
185.67.82.114
207.102.138.19
204.101.161.14
193.128.108.251
111.7.100.17
111.7.100.16
74.125.210.62
74.125.210.36

104.244.74.57
185.220.101.145
185.220.101.144
185.220.101.18
185.220.100.246
185.220.101.228
185.220.100.243
185.220.101.229
185.220.101.147
185.220.102.250
185.220.100.241
199.195.251.84
213.164.204.94
74.125.213.7
74.125.213.9
177.38.183.13
185.220.100.249

Decrypt the c2s

The second largest encrupted block is likely the C2 list so let's decrypt that now.

for i in range(len(blocks)):
    if blocks[i] == blocks_sorted[-2]:
        out = decrypt(blocks[i+1], blocks[i])
print(out)
celulasmadreenmexico.com.mx/Wt793Aua|gerencial.institutoacqua.org.br/XynFkhJAxnm|dashboard.adlytic.ai/LlvLoc9O3|bussiness-z.ml/3pdEiqsni|ifiengineers.com/hGVc55g2e|bonusvulkanvegas.srdm.in/U7oOxmI1m|ebrouteindia.com/JEqGe1hNR|test.dirigu.ro/dXf4cS4GPL|cablingpoint.com/LjDG0hkp|perfectdemos.com/T6PQGYCMt|afrizam.360cyberlink.com/f36rjSN5D1|giasuphire.tddvn.com/miFO43YP9b|priyacareers.com/GiTHMPbU|assurant.360cyberlink.com/DGx4k8U9Hil|sig.institutoacqua.org.br/tM7tINg2sCU|

Clean up the c2 list

It looks like the C2 list is seperated by pipes | so let's turn that into a nice list.

print(out.replace('|','\n'))
celulasmadreenmexico.com.mx/Wt793Aua
gerencial.institutoacqua.org.br/XynFkhJAxnm
dashboard.adlytic.ai/LlvLoc9O3
bussiness-z.ml/3pdEiqsni
ifiengineers.com/hGVc55g2e
bonusvulkanvegas.srdm.in/U7oOxmI1m
ebrouteindia.com/JEqGe1hNR
test.dirigu.ro/dXf4cS4GPL
cablingpoint.com/LjDG0hkp
perfectdemos.com/T6PQGYCMt
afrizam.360cyberlink.com/f36rjSN5D1
giasuphire.tddvn.com/miFO43YP9b
priyacareers.com/GiTHMPbU
assurant.360cyberlink.com/DGx4k8U9Hil
sig.institutoacqua.org.br/tM7tINg2sCU