Analyse d’un malware iOS : Unflod.dylib

Suite à la parution de commentaires sur /r/jailbreak concernant un malware ciblant iOS, je me suis dis qu’une analyse serait intéressante vu que cette plateforme est encore peu ciblée par ce type de menaces du à son architecture.

La première étape fut de récupérer des informations sur le binaire, ie. Entitlements et signature du code. Le premier point n’apporte pas grand chose sur le binaire, à part qu’il peut être débuggé et accéder au Keychain.

checksignBien que n’ayant été trouvée que sur des terminaux jailbreakés, cette bibliothèque est signée avec le compte iPhone Developer de Wang Xin. Ce procédé est étrange vu que le jailbreak désactive la validation de code signé sur iOS.

L’EntryPoint de la bibliothèque est assez simple et ne réalise qu’une seule action: remplacer la fonction SSLWrite du système par une fonction implémentée dans la bibliothèque: replace_SSLWrite. Le hooking de la fonction est réalisée à l’aide de la fonction libsubstrate.dylib!MSHookFunction. La bibliothèque MobileSubstrate est utilisée par  beaucoup d’applications provenant d’AppStore tierce afin de réaliser du Swizzling/hooking, il n’est donc pas étonnant de la voir utilisée ici.

call_mshookfunction

La fonctionnalité de la fonction remplaçant SSLWrite est elle aussi très simple: détecter une tentative d’authentification sur les serveurs d’Apple et intercepter les authentifiants de l’utilisateur. Pour ce faire, la chaine /WebObjects/MZFinance.woa/wa/authenticate est recherchée dans les données envoyées via SSL. Cette chaine fait en général partie des URLs pointants sur *.itunes.apple.com.

searching_iTunes_login

Une fois identifiés, les authentifiants sont envoyés à un serveur en écoute sur le port 7878 soit à l’IP 23.88.10.4, soit à l’IP 23.228.204.55.sending_info

Pour le moment, aucune information n’est disponible quant-à la source de l’infection. Il est toutefois intéressant de voir que les terminaux iOS jailbreakés commencent à être la cible de malware grand-public.

Analyse et détection de cyber-attaques: Import-Module IncidentDetection

Introduction

Le 16 octobre dernier nous avons eu l’opportunité de présenter sur le sujet de la détection d’incidents lors de l’Application Security Forum d’Yverdon. Ce sujet, bien que relativement bien connu est encore trop peu utilisé en entreprise où l’on voit principalement le déploiement de défenses périmètriques, d’antivirus ou encore d’IDS.

Le résultat lié au déploiement de telles solutions dépend fortement du niveau de l’attaquant et peut très vite être réduit suite à une erreur de configuration. Un tel exemple pourrait être le non-filtrage des archives au format XYZ permettant à l’attaquant de mener une attaque à base de spear-phishing . Les solutions anti-virales sont quant-à elles très vite contournées…

D’un autre coté nous avons des politiques de logs qui sont inexistantes ou aucunement gérée, produisant des montagnes d’entrées qui ne sont pas revues.

Une solution

Une des solutions au problème peut se trouver dans la détection de l’intrusion dans le cas où la prévention a échouée. Nous avons détaillé dans notre présentation différents points pouvant indiquer un comportement suspect dans un environnement Microsoft.

Une grande partie des actions peut être détectée en activant les règles d’audit dans les GPOs, comme les évènements indiquant une authentification échouée par exemple.

Les phases liées à l’exécution de programmes ou l’exploitation de vulnérabilités nécessitent quant-à elles l’utilisation d’outils tierces. Dans ce cadre là, la technologie AppLocker de Microsoft peut être déployée de manière à non pas bloquer une exécution, mais dans son mode ‘Audit Only’. Concernant l’exploitation les évènements générés par EMET sont à surveiller.

Bien entendu, la simple génération d’évènements ne va pas indiquer qu’une attaque est en cour. Un outil remontant ces informations de manière centralisée est alors nécessaire. Dans le contexte de la conférence nous avons développé un module PowerShell permettant de trier les évènements et lever une alerte en cas de comportement suspicieux. Cet outil sera prochainement mis à disposition sur notre site web.

Implémentation

Conscients de cette problématique présente dans de nombreuses sociétés, SCRT propose du conseil pour la mise en place de mécanismes de détection d’incidents ainsi que de l’aide pour l’écriture de procédure de réponse à incidents.

Hack in The Box Amsterdam 2013

Keynote jour 1 : Embracing the uncertainty of advanced attacks with Big Data analytics

La keynote de lancement de la conférence avait pour thème la détection d’incidents à l’aide du Big Data. Ce terme est présent dans de nombreux milieux depuis des années mais commence à peine à être utilisé dans le monde de la sécurité.

Comme Edward Schwartz (CISO de RSA) le repète à plusieurs reprises, la détection d’incidents se heurte à différents problèmes comme la génération d’évènements utiles et utilisables, ainsi qu’à leur traitement. On commence à avoir une bonne vision de ce qui est clairement une attaque (signature de virus connus par exemple), mais comment détecter des attaques plus évoluées? Pour répondre à ces problèmes, M. Schwartz a formé des équipes avec des personnes spécialisées dans des domaines précis (malware analysis, exploit analysis, …) dans le but d’avoir l’expertise nécessaire pour la création des filtres appliqués sur les données ainsi que les validations.

Il est intéressant de voir comment des entreprises qui ont subis des attaques “APT” changent leur comportement, mais reste à voir comment cela peut se porter à des groupes de plus petite taille ou avec une équipe sécurité plus limitée en taille et/ou ressources.

Papparazi over IP

Les attaques présentées n’avaient rien de nouveau et bien au contraire, elles sont généralement absentes dans les environnements que nous utilisons tous les jours. Daniel Mende démontre ici que ces attaques, même si très simples, sont présentent dans des équipements embarqués high-end comme les EOS 1DX de Canon.

Ces derniers possèdent une interface ethernet et peuvent acceuillir une carte WiFi afin de permettre aux photographes d’uploader leurs photos directement sur un serveur FTP, d’y accéder depuis leur laptop au travers du protocole DLNA, un serveur web embarqué ou encore le client EOS Utility. On voit clairement 2 points critiques avec le FTP non-chiffré et le DLNA qui est un protocole ne demandant aucune authentification. Heureusement, le serveur web utilise des identifiants de sessions de 32bits (environ 20min pour tester toutes les combinaisons sur cet appareil) et le client lourd requière un nom d’hôte (qui n’est pas validé côté serveur) et un secret (qui est broadcasté sur le réseau au démarrage de l’appareil)…

Ce type de vulnérabilités peut avoir un impact critique pour des photographes professionels, comme la suppression de photos, l’ajout de photos comprométentes ou encore la prise de contrôle à distance pour surveiller ce qui se passe dans une pièce. Du chemin reste donc encore à parcourir dans certains domaines pour que le niveau de sécurité rejoigne celui auquel nous sommes habitué sur les OS courants.

Nifty tricks and sage advices for shellcode on embedded devices

En lisant le titre de cette présentation on pourrait penser à une Nième présentation sur l’exploitation sur Android ou le routeur XYZ. C’est sans connaitre Travis Goodspeed qui parle ici de microcontrolleurs de 8, 16 ou 32 bits comme le 8051 d’Intel sans système d’exploitation et avec tout au plus une version limitée de la libc.

Le but ici n’est alors pas forcément d’obtenir une exécution de code, qui pourrait servir par exemple dans le cas où la fonctionalité de mise à jour a été omise, mais l’exploitation d’une vulnérabilité va servir à extraire le contenu de la flash afin d’obtenir le code présent. Les protections rencontrées sur x64/ARM ne sont pas présentent mais remplacées par des limitations de concept comme l’interdiction d’exécution de code depuis la RAM. L’extraction des données peut également posé problème du fait de limitation de taille sur les caches disponibles. Il faut alors faire preuve d’ingéniosité comme par exemple utilisé les ports GPIO des LEDs.

Virtually secure: analysis to remote 0day in an industry leading SSL-VPN appliance

Le contenu de cette conférence n’était pas impressionant (injection SQL sur une page accessible sans authentification), mais le fait d’expliquer les différentes étapes de la recherche de vulnérabilité sur ce type d’équipement ainsi que les problèmes rencontré ainsi que leurs solutions en ont fait une bonne présentation.

Cette présentation permet également de rappeler un point important: bien souvent trop de confiance peut être accordée aux produits de sécurité qui une fois compromis offrent un accès quasi-total au LAN de l’entreprise (dans le cas d’un portail VPN). C’est dans ce type de cas qu’une surveillance comme celle présentée dans la keynote de lancement fait tout son sens.

Page fault liberation army or better security through creative x86 trapping

Excellente présentation de Sergey Bratus et Julian Bangert. Concrêtement l’utilité de leur recherche n’est pas visible, mais le concept est intéressant: construire une machine Turing-complete qui utilise une seule instruction.

Ici, un jeu de la vie complêt (souvenirs d’école d’ingénieur…) a été développé sans écrire une seule instruction assembleur. C’est le mécanisme qui est hardcodé dans la MMU qui est utilisé pour modifier des valeurs en mémoires. L’équivalent d’une instruction est réalisé grâce aux TLBs et le signal d’horloge est simulé par une exception page-fault. Attention, une bonne thermos de café est requise pour la lecture de ces slides 😉

Aircraft hacking: Practical aero series

Un titre de conférence qui fait peur, non sans raisons. Hugo Teso y a présenté les résultats de plus de 3ans de recherches personnelles sur la sécurité des avions. Comme toute attaque, les phases de reconnaissance, exploitation, post-exploitation ont été respectées. La phase de reconnaissance et l’exploitation se passe par les canaux de communication qu’utilisent les avions et les équipes au sol pour communiquer.

Hugo a également présenté son laboratoire monté pour ses recherches, comprenant des systèmes d’entrainement de pilotes ou encore des vraies composants achetés sur des sites d’enchères en ligne.

Les outils d’exploitation et post-exploitation ne fonctionnent que sur la partie virtualisée du lab afin de ne pas permettre à de personnes mal intentionnées de les utiliser. Les autorités Européennes concernées ont également été contacté et les résultats des recherches vont permettre d’améliorer la sécurité via une collaboration de ces instances.

Keynote jour 2 : Rethinking the front lines

Bob Lord (Director of Information Security, Twitter) nous y présente son retour d’expérience sur le thème des sensibilisations utilisateurs dans le contexte de Twitter.

Cet exercice est loin d’être facile du fait des mauvaises habitudes que les employés ont pu prendre par le passé et nécessite ainsi de faire la formation au plus tôt lors de l’arrivée des nouveaux employés et de rendre ça le plus fun possible afin de laisser une trace dans la mémoire des gens. Un suivi constant via différentes statistiques sur le suivi des bonnes pratiques présentées ainsi que des campagnes de phishing lui permette de remettre en question la formation données afin d’avoir au fur et à mesure de meilleurs résultats.

Swiping though modern security features

Nous ne rentrerons pas dans la technique utilisée pour ce jailbreak du fait qu’il est déjà détaillé à différents endroits et les slides seront disponibles sous peu. On retiendra néanmoins que le contournement du mécanisme de Code Signing a été possible sans une seule vulnérabilité mémoire, tout est lié à des erreurs de logiques. La seconde partie est plus complexe mais ne requière qu’une fonction vulnérable, liée à la stack USB, afin d’appeler du code coté kernel (reste à connaitre une adresse intéressante).

Les protections mises en place par Apple sont complexes à contourner, mais il reste certains points non-protégés qui peuvent être utilisés comme rebonds.

Conclusion

En conclusion, cette édition 2013 d’HiTB était très intéresante et d’un bon niveau. On regrettera tout de même les présentations “hardware” qui consistaient, dans les grandes lignes, à exploiter des Linux embarqués comprenant des serveurs web ou des scripts CGI vulnérables, ce qui est connu depuis plusieurs années.

Insomni’hack 2013 – Armory level3

This challenge was the last level on the ARM platform. It was a crackme with a stripped binary including a basic anti-debugging trick. Sadly, only one team managed to complete this challenge before the end of Insomni’hack and another wasn’t far from what we discussed later.

Running the binary alone we can learn that two things should be provided: a username and a serial number. Maybe the two are linked, maybe not…

The check for the username is easily spotted using IDA and searching for cross-references to strcmp(). Also, the serial is XOR’d with this username.


.text:00008AE8 E4 01 9F E5 LDR R0, =aJackknife ; "jackknife"
.text:00008AEC 14 10 1B E5 LDR R1, [R11,#s2] ; s2
.text:00008AF0 68 FE FF EB BL strcmp
.text:00008AF4 00 30 A0 E1 MOV R3, R0
.text:00008AF8 00 00 53 E3 CMP R3, #0
.text:00008AFC 08 00 00 1A BNE loc_8b24
...
.text:00008B70 1C 20 1B E5 LDR R2, [R11,#var_1C]
.text:00008B74 10 30 1B E5 LDR R3, [R11,#var_10]
.text:00008B78 03 30 82 E0 ADD R3, R2, R3
.text:00008B7C 14 10 1B E5 LDR R1, [R11,#s2]
.text:00008B80 10 20 1B E5 LDR R2, [R11,#var_10]
.text:00008B84 02 20 81 E0 ADD R2, R1, R2
.text:00008B88 00 10 D2 E5 LDRB R1, [R2]
.text:00008B8C 18 00 1B E5 LDR R0, [R11,#s]
.text:00008B90 10 20 1B E5 LDR R2, [R11,#var_10]
.text:00008B94 02 20 80 E0 ADD R2, R0, R2
.text:00008B98 00 20 D2 E5 LDRB R2, [R2]
.text:00008B9C 02 20 21 E0 EOR R2, R1, R2
.text:00008BA0 72 20 EF E6 UXTB R2, R2
.text:00008BA4 00 20 C3 E5 STRB R2, [R3]
.text:00008BA8 10 30 1B E5 LDR R3, [R11,#var_10]
.text:00008BAC 01 30 83 E2 ADD R3, R3, #1
.text:00008BB0 10 30 0B E5 STR R3, [R11,#var_10]

Next step: run the binary in GDB in order to see how the serial number is validated.


level3@sploitboard:~$ gdb ./level3
(gdb) r foo bar
Starting program: /home/level3/level3 foo bar
Ammo store
----------
Validating your credentials to download ammo for your weapons...

Program received signal SIGTRAP, Trace/breakpoint trap.
0xb6ec0bfc in raise () from /lib/arm-linux-gnueabihf/libc.so.6

Wait what?!? You didn’t put any breakpoint and still a SIGTRAP is raised. Looking more closely we can see that the raise(3) function is called multiple times in the application so it seems that this is our anti-debugging trick.


Direction Type Address Text
--------- ---- ------- ----
Up p sub_889C+20 BL raise
Up p sub_88C8+18 BL raise
Up p sub_88F0+1C BL raise
Up p sub_891C+1C BL raise
Up p sub_8948+18 BL raise
Up p sub_8988+C BL raise
p sub_8A48+9C BL raise
Down p sub_8A48+F0 BL raise
Down p sub_8A48+188 BL raise

We can also see that a signal handler is defined for SIGTRAP and SIGABRT and that this handler is incrementing a global variable:


.text:000089F4 LDR R3, =sig_handler
.text:000089F8 STR R3, [R11,#act]
.text:000089FC SUB R3, R11, #-act
.text:00008A00 MOV R0, #5 ; sig
.text:00008A04 MOV R1, R3 ; act
.text:00008A08 MOV R2, #0 ; oact
.text:00008A0C BL sigaction
.text:00008A10 SUB R3, R11, #-act
.text:00008A14 MOV R0, #6 ; sig
.text:00008A18 MOV R1, R3 ; act
.text:00008A1C MOV R2, #0 ; oact
.text:00008A20 BL
...
; sig_handler:
.text:000089BC 18 30 9F E5 LDR R3, =dword_10F7C
.text:000089C0 00 30 93 E5 LDR R3, [R3]
.text:000089C4 01 20 83 E2 ADD R2, R3, #1
.text:000089C8 0C 30 9F E5 LDR R3, =dword_10F7C
.text:000089CC 00 20 83 E5 STR R2, [R3]

The first check that is done on the XOR’d serial number is using this counter so we might have to run this code to know this value without reversing the complete application. Using a breakpoint on raise(3) and the call method in GDB we can emulate the SIGTRAP without actually triggering it.


.text:00008BD4 1C 30 1B E5 LDR R3, [R11,#XOR_serial]
.text:00008BD8 00 30 D3 E5 LDRB R3, [R3]
.text:00008BDC 03 20 A0 E1 MOV R2, R3
.text:00008BE0 DC 30 9F E5 LDR R3, =dword_10F7C
.text:00008BE4 00 30 93 E5 LDR R3, [R3]
.text:00008BE8 03 30 82 E0 ADD R3, R2, R3
.text:00008BEC 73 30 EF E6 UXTB R3, R3
.text:00008BF0 A3 00 53 E3 CMP R3, #0xA3

Breakpoint 1, 0xb6ec0bbc in raise () from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) call (void)0x89a0(5)
$1 = 35232
(gdb) bt
#0 0xb6ec0bbc in raise () from /lib/arm-linux-gnueabihf/libc.so.6
#1 0x00008ae8 in ?? ()
#2 0x00008ae8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) set $pc=0x8ae8
(gdb) c
Breakpoint 4, 0x00008be0 in ?? ()
(gdb) x /5i $pc
=> 0x8be0: ldr r3, [pc, #220] ; 0x8cc4
0x8be4: ldr r3, [r3]
0x8be8: add r3, r2, r3
0x8bec: uxtb r3, r3
0x8bf0: cmp r3, #163 ; 0xa3
(gdb) p *0x10f7c
$22 = 2

This means that the XOR’d value added to 2 should be equal to 0xa3. Continuing this lenghty process, we can get all the characters of the serial number:


level3@sploitboard:~$ ./level3 jackknife `python -c 'print "xcb"+"bxeaxe2aaaaa"'`
Ammo store
----------
Validating your credentials to download ammo for your weapons...
36760a05c853e6a7444b6a3de2c100591e0ad9c0193c56ca562949f4f7342a808cead86e34f940fb88221403451345e36edddcce51934eb4ea64af7c27aa6650

Insomni’hack 2013 : Money money money

Money Money Money

Even after "The Event", money is still the key to beat your opponents. Our scouts found an old banking server which should contain information about the accounts and the money they contain, but this old computer used to use perforated cards. Our engineers were able to create an interface to use it on modern technology, but they are not able to break the security system to get the data.

When connecting, the following information is given :

Initializing 256 bytes RAM...
Loading security module into memory...Done
Welcome to the truc machine
Please insert program card

When entering the example data, the output is “Hello”. Decoding the example data gives a PNG image :

moneymoneymoney_example

The image contains all black, except on some lines where there is a white pixel. As the description tells, this machine uses punched cards. Looking at the sample image data, we can deduce that the sequence “white-black-black” is the “Print data” opcode. As there are 72 “black-black-black” instructions (which is the ASCII code for ‘H’), this opcode is an “increment value” instruction.

Finding the other instructions is just a mater of time, and there is a total of five instructions that work on a 256 bytes array (pretty much like a brainfuck application)

B-B-B  :  Increment pointed value
B-B-W  :  Decrement pointed value
B-W-B  :  Increment pointer
B-W-W  :  Decrement pointer
W-B-B  :  Print pointed value

Once you found out which instruction is what (There were a lot of error strings displayed to help), you were able to create an image which would dump the whole memory and display it :

moneymoneymoney_dump

That image would give you the flag :

af5811e325cde9b06c697e61fecb8a094e8e1a85d4231aba1c10c70ca20cdd0f894d121221d0dde4af70a5023a129de2e202192dd7b536eec9965fa99d12b5e1

Source code


import SocketServer, base64
from PIL import Image
from StringIO import StringIO

class MachineHandler(SocketServer.BaseRequestHandler):

def handle(self):
self.request.sendall('Initializing 256 bytes RAM...n')
self.request.sendall('Loading security module into memory...')
memory = bytearray('x00'*(256-len(flag))+flag)
self.request.sendall('Donen')

self.request.sendall('Welcome to the truc machinen')
self.request.sendall('Please insert program cardn')
data = self.request.recv(200).strip()
try:
image = self.decodeImage(data)
ops = self.parseImage(image)
self.request.sendall(self.executeOps(ops, memory))
except Exception, e:
self.request.sendall(e.message)

def decodeImage(self, data):
try:
imageData = StringIO(base64.b64decode(data))
image = Image.open(imageData)
if image.size[0]!=3:
raise IOError("Image width must be equal to 3")
colors = [c[1] for c in image.getcolors()]
if len(colors)>2:
raise IOError("Image must be only two colors")
if 0 not in colors:
raise IOError("Image must contain #00 color")
return image
except Exception, e:
raise e

def parseImage(self, image):
i=0
ops = []
try:
for i in range(image.size[1]):
tmp = (image.getpixel((0,i))>0) << 2
tmp += (image.getpixel((1,i))>0) << 1
tmp += (image.getpixel((2,i))>0)
ops.append(tmp)
except Exception, e:
raise e
return ops

def executeOps(self, ops, memory, pt=0):
output=""
for op in ops:
if op == 0:
memory[pt] += 1
elif op == 1:
memory[pt] -= 1
elif op == 2:
if pt == 255:
raise ValueError("Pointer out of range")
else:
pt += 1
elif op == 3:
if pt == 0:
raise ValueError("Pointer out of range")
else:
pt -= 1
elif op == 4:
output += chr(memory[pt])
else:
raise ValueError("Unknown opcode")
return output

if __name__ == '__main__':
flag = open('./flag').read()
HOST, PORT = "0.0.0.0", 7777
SocketServer.ThreadingTCPServer.allow_reuse_address = True
server = SocketServer.ThreadingTCPServer((HOST, PORT), MachineHandler)
server.serve_forever()