Monstrosity
9 minutes to read
We have this challenge description:
The following social media account is associated with a widespread banking trojan that is silently infecting an increasing number of victims the past few days. There is intense interaction with the aforementioned account right before the self-decryption function of the malicious executable. Investigators around the world are trying to reverse engineer this specific part of the malware with no success so far. Search the account for potential clues that could prove useful.
If we follow the Twitter account, we have a user that posts a lot of weird tweets:
In order to analyze so many tweets, we can use Twitter’s API. For that, we need to create an account in developer.twitter.com and use a bearer token:
$ export BEARER_TOKEN='...'
After that, we need to find the user ID of @miounster, which can be found in some web requests:
Using Twitter’s API
At this point, we can extract information about the tweets (for example, created_at
, geo
, id
):
$ curl 'https://api.twitter.com/2/users/885213010314317825/tweets?tweet.fields=created_at,geo,id' -sH "Authorization: Bearer $BEARER_TOKEN" | jq
{
"data": [
{
"id": "886062876926107648",
"edit_history_tweet_ids": [
"886062876926107648"
],
"text": "Ggggggggggggggggggggggggggggggggggggggggggggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!! <3 <3 <3",
"created_at": "2017-07-15T03:20:26.000Z"
},
{
"id": "886062707493015555",
"edit_history_tweet_ids": [
"886062707493015555"
],
"text": "Gggggggggggrrrrrrrrrrrrrrrrrrrr!!! <3 <3",
"created_at": "2017-07-15T03:19:46.000Z"
},
{
"id": "886062538420625409",
"edit_history_tweet_ids": [
"886062538420625409"
],
"text": "Ggggggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!! <3 <3 <3",
"created_at": "2017-07-15T03:19:06.000Z"
},
{
"id": "886062369427902466",
"edit_history_tweet_ids": [
"886062369427902466"
],
"text": "Ggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!!! <3 <3 <3",
"created_at": "2017-07-15T03:18:25.000Z"
},
{
"id": "886062200133222401",
"edit_history_tweet_ids": [
"886062200133222401"
],
"text": "Ggggggggggggggggggggggggggggggggggggggggggggggggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!! <3",
"created_at": "2017-07-15T03:17:45.000Z"
},
{
"id": "886062030628761600",
"edit_history_tweet_ids": [
"886062030628761600"
],
"text": "Ggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!! <3 <3 <3",
"created_at": "2017-07-15T03:17:04.000Z"
},
{
"id": "886061861321535490",
"edit_history_tweet_ids": [
"886061861321535490"
],
"text": "Ggggggggggggggggggggggggrrrrrrrrrrrrrrrrrr!! <3 <3 <3",
"created_at": "2017-07-15T03:16:24.000Z"
},
{
"id": "886061692031037440",
"edit_history_tweet_ids": [
"886061692031037440"
],
"text": "Gggggggggggggggggggggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!!! <3",
"created_at": "2017-07-15T03:15:44.000Z"
},
{
"id": "886061522824433664",
"edit_history_tweet_ids": [
"886061522824433664"
],
"text": "Ggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr!!! <3 <3",
"created_at": "2017-07-15T03:15:03.000Z"
},
{
"id": "886061352707645441",
"edit_history_tweet_ids": [
"886061352707645441"
],
"text": "Ggggggggggggrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr! <3 <3 <3",
"created_at": "2017-07-15T03:14:23.000Z"
}
],
"meta": {
"result_count": 10,
"newest_id": "886062876926107648",
"oldest_id": "886061352707645441",
"next_token": "zldjwdz3w6sba13nnt893hir5r4s4gxlaje19hwfz8x"
}
}
We are only watching 10 / 3000 tweets, so we might need to search more. For this, we can add max_results=100
(the maximum that the API supports). To filter JSON data, I will use gron
:
$ curl 'https://api.twitter.com/2/users/885213010314317825/tweets?tweet.fields=created_at,geo,id&max_results=100' -sH "Authorization: Bearer $BEARER_TOKEN" | gron | grep geo | norg | grep -v null | jq
{
"data": [
{
"geo": {
"coordinates": {
"coordinates": [
61.5,
-54
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
120,
-54
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
16.5,
-60
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
69,
-60
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
127.5,
-57
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
-57,
-57
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
67.5,
-60
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
-30,
-59
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
138,
-54
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
64.5,
-56
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
0,
-55
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
-48,
-54
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
100.5,
-54
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
54,
-54
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
48,
-57
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
117,
-55
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
27,
-55
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
61.5,
-57
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
109.5,
-57
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
10.5,
-60
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
30,
-57
],
"type": "Point"
}
}
},
{
"geo": {
"coordinates": {
"coordinates": [
18,
-57
],
"type": "Point"
}
}
}
]
}
It seems that we need to take the coordinates of the tweets that have a geo
field.
Extracting all the tweets
To analyze all the tweets, let’s move to Python (here you can find an official implementation). We can use pagination_token
to advance to next page of results until we get all the 3000 tweets. Then, we take the ones that have geo
and extract the coordinates:
$ python3 analyze.py 885213010314317825
[+] Tweets: 3000 / 3000
[+] Coordinates:
61.5, -54.0
120.0, -54.0
16.5, -60.0
69.0, -60.0
127.5, -57.0
-57.0, -57.0
67.5, -60.0
-30.0, -59.0
138.0, -54.0
64.5, -56.0
0.0, -55.0
-48.0, -54.0
100.5, -54.0
54.0, -54.0
48.0, -57.0
117.0, -55.0
27.0, -55.0
61.5, -57.0
109.5, -57.0
10.5, -60.0
30.0, -57.0
18.0, -57.0
90.0, -54.0
97.5, -60.0
22.5, -55.0
159.0, -57.0
-25.5, -56.0
-43.5, -54.0
-48.0, -59.0
127.5, -59.0
67.5, -59.0
-18.0, -56.0
70.5, -57.0
82.5, -55.0
-12.0, -54.0
-15.0, -54.0
97.5, -57.0
-3.0, -60.0
135.0, -60.0
33.0, -57.0
60.0, -57.0
157.5, -60.0
87.0, -56.0
87.0, -55.0
87.0, -54.0
-27.0, -54.0
117.0, -54.0
153.0, -54.0
157.5, -59.0
138.0, -60.0
100.5, -57.0
10.5, -57.0
-30.0, -60.0
115.5, -57.0
60.0, -58.0
22.5, -54.0
121.5, -57.0
-19.5, -60.0
90.0, -60.0
4.5, -54.0
60.0, -54.0
-55.5, -54.0
-55.5, -56.0
-48.0, -55.0
79.5, -54.0
90.0, -59.0
10.5, -54.0
105.0, -56.0
150.0, -59.0
75.0, -57.0
-55.5, -58.0
79.5, -60.0
124.5, -56.0
55.5, -54.0
-45.0, -54.0
55.5, -57.0
25.5, -54.0
100.5, -60.0
-58.5, -57.0
-33.0, -59.0
-40.5, -59.0
30.0, -55.0
160.5, -57.0
157.5, -54.0
132.0, -60.0
-55.5, -59.0
135.0, -57.0
0.0, -56.0
-52.5, -54.0
37.5, -59.0
114.0, -57.0
64.5, -59.0
-48.0, -57.0
72.0, -60.0
154.5, -60.0
172.5, -58.0
27.0, -56.0
112.5, -60.0
12.0, -60.0
-51.0, -54.0
117.0, -58.0
40.5, -54.0
102.0, -56.0
117.0, -57.0
82.5, -60.0
7.5, -58.0
27.0, -59.0
37.5, -57.0
150.0, -56.0
57.0, -55.0
57.0, -56.0
-21.0, -54.0
-21.0, -60.0
-30.0, -57.0
55.5, -60.0
139.5, -59.0
7.5, -59.0
-22.5, -55.0
105.0, -54.0
42.0, -58.0
-52.5, -56.0
154.5, -54.0
49.5, -58.0
-22.5, -59.0
-25.5, -58.0
52.5, -56.0
-15.0, -58.0
33.0, -60.0
127.5, -58.0
-30.0, -56.0
142.5, -54.0
139.5, -56.0
142.5, -57.0
105.0, -57.0
49.5, -57.0
-13.5, -54.0
112.5, -57.0
124.5, -60.0
82.5, -58.0
25.5, -60.0
-52.5, -57.0
115.5, -60.0
78.0, -54.0
159.0, -60.0
75.0, -56.0
130.5, -54.0
15.0, -54.0
150.0, -58.0
18.0, -54.0
42.0, -59.0
-25.5, -57.0
-3.0, -56.0
-33.0, -60.0
-18.0, -58.0
172.5, -60.0
48.0, -60.0
4.5, -55.0
169.5, -59.0
85.5, -60.0
120.0, -57.0
60.0, -56.0
19.5, -58.0
169.5, -57.0
64.5, -57.0
108.0, -60.0
52.5, -54.0
45.0, -57.0
169.5, -54.0
30.0, -60.0
7.5, -60.0
9.0, -57.0
142.5, -56.0
94.5, -59.0
-52.5, -60.0
-3.0, -54.0
85.5, -54.0
90.0, -56.0
115.5, -54.0
54.0, -60.0
7.5, -55.0
45.0, -56.0
-22.5, -54.0
93.0, -57.0
154.5, -59.0
-22.5, -60.0
-25.5, -54.0
-28.5, -54.0
99.0, -60.0
132.0, -54.0
63.0, -60.0
150.0, -55.0
117.0, -59.0
34.5, -54.0
82.5, -56.0
109.5, -60.0
-18.0, -57.0
94.5, -60.0
159.0, -54.0
-15.0, -60.0
90.0, -55.0
-15.0, -59.0
45.0, -55.0
49.5, -60.0
102.0, -57.0
34.5, -57.0
-48.0, -60.0
93.0, -54.0
172.5, -59.0
63.0, -57.0
117.0, -56.0
57.0, -54.0
31.5, -60.0
4.5, -60.0
37.5, -54.0
127.5, -56.0
-25.5, -59.0
157.5, -58.0
153.0, -57.0
175.5, -57.0
-55.5, -55.0
52.5, -57.0
76.5, -60.0
177.0, -58.0
57.0, -57.0
87.0, -57.0
-25.5, -55.0
147.0, -54.0
147.0, -60.0
0.0, -57.0
139.5, -57.0
64.5, -60.0
42.0, -55.0
22.5, -59.0
105.0, -58.0
64.5, -58.0
31.5, -54.0
136.5, -60.0
22.5, -58.0
105.0, -59.0
-48.0, -58.0
109.5, -54.0
169.5, -55.0
106.5, -54.0
52.5, -60.0
75.0, -59.0
130.5, -60.0
37.5, -60.0
-13.5, -57.0
105.0, -55.0
135.0, -58.0
-30.0, -54.0
142.5, -60.0
-60.0, -54.0
120.0, -55.0
34.5, -58.0
94.5, -57.0
22.5, -60.0
76.5, -54.0
-49.5, -54.0
102.0, -54.0
42.0, -56.0
124.5, -58.0
130.5, -57.0
112.5, -54.0
3.0, -57.0
154.5, -57.0
108.0, -54.0
4.5, -58.0
24.0, -57.0
99.0, -54.0
52.5, -55.0
-52.5, -58.0
45.0, -54.0
39.0, -60.0
-18.0, -59.0
-33.0, -56.0
135.0, -55.0
70.5, -60.0
-25.5, -60.0
45.0, -60.0
-40.5, -60.0
48.0, -54.0
-40.5, -57.0
124.5, -54.0
70.5, -54.0
79.5, -57.0
91.5, -57.0
102.0, -55.0
-40.5, -58.0
46.5, -54.0
67.5, -54.0
-18.0, -60.0
91.5, -60.0
172.5, -57.0
145.5, -57.0
67.5, -57.0
54.0, -57.0
46.5, -60.0
49.5, -55.0
-12.0, -57.0
-19.5, -54.0
87.0, -60.0
67.5, -55.0
15.0, -58.0
84.0, -60.0
144.0, -54.0
-3.0, -59.0
90.0, -57.0
-33.0, -58.0
46.5, -57.0
-3.0, -57.0
139.5, -58.0
135.0, -56.0
150.0, -60.0
162.0, -57.0
24.0, -60.0
4.5, -57.0
63.0, -54.0
-27.0, -60.0
114.0, -54.0
-3.0, -58.0
-33.0, -54.0
33.0, -54.0
19.5, -59.0
139.5, -55.0
69.0, -54.0
49.5, -54.0
172.5, -54.0
144.0, -57.0
93.0, -60.0
75.0, -60.0
12.0, -57.0
129.0, -54.0
37.5, -58.0
169.5, -56.0
79.5, -55.0
72.0, -54.0
60.0, -55.0
19.5, -56.0
157.5, -57.0
124.5, -57.0
-22.5, -58.0
79.5, -59.0
7.5, -56.0
150.0, -54.0
132.0, -57.0
0.0, -54.0
94.5, -54.0
117.0, -60.0
172.5, -55.0
72.0, -57.0
106.5, -60.0
120.0, -56.0
-52.5, -59.0
78.0, -60.0
94.5, -58.0
147.0, -56.0
91.5, -54.0
127.5, -60.0
124.5, -59.0
24.0, -54.0
15.0, -55.0
177.0, -56.0
129.0, -57.0
34.5, -59.0
145.5, -54.0
-33.0, -55.0
15.0, -56.0
22.5, -56.0
109.5, -55.0
-60.0, -57.0
147.0, -58.0
99.0, -57.0
90.0, -58.0
-42.0, -54.0
-40.5, -55.0
7.5, -57.0
162.0, -56.0
15.0, -60.0
150.0, -57.0
79.5, -56.0
175.5, -60.0
-18.0, -54.0
84.0, -54.0
-33.0, -57.0
87.0, -59.0
-30.0, -55.0
123.0, -57.0
177.0, -55.0
30.0, -54.0
49.5, -56.0
18.0, -60.0
82.5, -59.0
82.5, -54.0
1.5, -57.0
160.5, -54.0
75.0, -54.0
129.0, -60.0
147.0, -59.0
97.5, -54.0
102.0, -58.0
19.5, -55.0
-40.5, -56.0
162.0, -54.0
109.5, -58.0
57.0, -59.0
-48.0, -56.0
30.0, -56.0
60.0, -59.0
64.5, -54.0
69.0, -57.0
169.5, -58.0
-28.5, -60.0
-22.5, -57.0
135.0, -59.0
-10.5, -57.0
154.5, -55.0
151.5, -54.0
174.0, -60.0
-49.5, -60.0
-55.5, -57.0
34.5, -60.0
154.5, -56.0
94.5, -56.0
127.5, -55.0
82.5, -57.0
75.0, -58.0
-15.0, -56.0
136.5, -54.0
49.5, -59.0
124.5, -55.0
15.0, -59.0
160.5, -60.0
142.5, -55.0
-52.5, -55.0
12.0, -54.0
169.5, -60.0
127.5, -54.0
4.5, -56.0
-18.0, -55.0
4.5, -59.0
154.5, -58.0
135.0, -54.0
175.5, -54.0
40.5, -60.0
172.5, -56.0
151.5, -57.0
16.5, -57.0
174.0, -57.0
-60.0, -56.0
60.0, -60.0
15.0, -57.0
57.0, -60.0
162.0, -60.0
16.5, -54.0
25.5, -57.0
-28.5, -57.0
-15.0, -57.0
64.5, -55.0
147.0, -57.0
-51.0, -60.0
22.5, -57.0
-22.5, -56.0
9.0, -54.0
37.5, -55.0
67.5, -58.0
-55.5, -60.0
87.0, -58.0
177.0, -59.0
-3.0, -55.0
79.5, -58.0
174.0, -54.0
-10.5, -54.0
-40.5, -54.0
-15.0, -55.0
109.5, -59.0
75.0, -55.0
145.5, -60.0
27.0, -58.0
162.0, -55.0
102.0, -60.0
94.5, -55.0
67.5, -56.0
147.0, -55.0
102.0, -59.0
37.5, -56.0
9.0, -60.0
-30.0, -58.0
57.0, -58.0
-27.0, -57.0
114.0, -60.0
31.5, -57.0
105.0, -60.0
144.0, -60.0
42.0, -57.0
39.0, -54.0
-60.0, -55.0
7.5, -54.0
109.5, -56.0
61.5, -60.0
Plotting coordinates
We could use an online tool to place all the coordinates in a map. However, it is better to place them in a plot using matplotlib
:
Let’s zoom in a bit:
Clearly, we see this string: 407180F14EBB5D998E0083034ED9A21B
, which seems to be a hexadecimal string. Probably, it is the output of an MD5 hash. If so, we can try to find a pre-image in crackstation.net:
Flag
And there it is. Therefore, the flag is: HTB{covertops}
.
The full script can be found in here: analyze.py
.