Monstrosity
9 minutos de lectura
Tenemos esta descripción del reto:
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.
Si seguimos la cuenta de Twitter, tenemos un usuario que publica muchos tweets extraños:
Para analizar tantos tweets, podemos usar la API de Twitter. Para eso, necesitamos crear una cuenta en developer.twitter.com y usar un bearer token:
$ export BEARER_TOKEN='...'
Después de eso, necesitamos encontrar el ID de usuario de @miounster, que se puede encontrar en algunas peticiones web:
Usando la API de Twitter
En este punto, podemos extraer información sobre los tweets (por ejemplo, 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"
}
}
Solo estamos viendo 10 / 3000 tweets, por lo que es posible que necesitemos buscar más. Para esto, podemos agregar max_results=100
(el máximo que la API admite). Para filtrar los datos JSON, utilizaré 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"
}
}
}
]
}
Parece que necesitamos tomar las coordenadas de los tweets que tienen un campo geo
.
Extrayendo todos los tweets
Para analizar todos los tweets, vamos a pasar a Python (aquí se puede encontrar una implementación oficial). Podemos usar el parámetro pagination_token
para avanzar a la página siguiente de resultados hasta que obtengamos todos los 3000 tweets. Luego, tomamos los que tienen geo
y extraemos las coordenadas:
$ 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
Localización de las coordenadas
Podríamos usar una herramienta online para colocar todas las coordenadas en un mapa. Sin embargo, es mejor colocarlos en una gráfica de matplotlib
:
Vamos a acercar un poco:
Claramente, vemos esta cadena de texto: 407180F14EBB5D998E0083034ED9A21B
, que parece estar en hexadecimal. Probablemente, sea el resultado de un hash MD5. Si es así, podemos intentar encontrar una pre-imagen en crackstation.net:
Flag
Y ahí está. Por lo tanto, la flag es: HTB{covertops}
.
El script completo se puede encontrar aquí: analyze.py
.