de l'art binaire: des PEs explosifs fait main

Preview:

DESCRIPTION

une vue d'ensemble des exécutables Windows et de leurs malformations. voir http://hashdays2012.corkami.com pour plus d'informations (en anglais)

Citation preview

de l'art binairedes PEs explosifs fait main

3 Novembre 2012Lucerne, Suisse

Ange Albertinihttp://corkami.com

version longue

● la présentation avait une 60aine de diapos● celle-ci en a plus de 140

● plus d'explications● plus d'exemples

plan

qu'est-ce qu'un PE?

le problème et mon approche

vue d'ensemble du format PE

pièges classiques

nouvelles astuces

© ID software

PPortable EExecutable

CCommon OObject FFile FFormatbasé sur

exécutables Windows, mais aussi

● presque tous les exécutables depuis 1993● 32bits, 64bits, .Net● DLL, pilotes, ActiveX...

● aussi comme conteneur de données● icones, chaînes, dialogues, images...

omniprésent sous Windows

mais aussi EFI, portables CE, Xbox,...(mais pas couvert ici)

PEbinaire Windows binaire Windows universeluniversel

depuis 1993

pe101pe101.corkami.com.corkami.com

le problème...

crimes & châtiments

● la documentation officielle est pauvre et floue● décrit juste des PEs standards● totalement insuffisante

● plantage (OS, security tools)

● empêche de développer ses propres outils

● gêne l'automatisation et le tri● PE ou pas?● corrompu ou malveillant?

● les meilleurs outils échouent → ça empêche même l'analyse manuelle

“le guide naïf des PEs standards”

CVE-2012-2273

version_mini

ibke

rnel

norm

al

...et mon approche

en partant de zéro

● analyser ce qu'on trouve dans la nature● devoir attendre le virus/bug suivant?

● écrire le binaire entier à partir de zéro● manuellement

● pas de limites dûes à un compilateur● des PoCs concises

→ meilleure couverture de l'ensemble

je partage mes connaissances et mes PoCs

brique par brique

un exécutable complet

pepe.corkami.com.corkami.com

Fichier

PE

(Appended data)

PE PEdé

fini p

ar l'

en-t

ête

PE

Appendeddata

PEen-têteSections

code, données...

en-tête

en-tête DOS

en-têtes 'modernes'

depuis IBM PC-DOS 1.0 (1981)

depuis Windows NT 3.1 (1993)

MZ

PE (ou NE/LE/LX/VZ/...)

en-tête

en-tête DOS

'en-têtes PE'

(code DOS) 16 bits

(en-tête Rich) infos de compil.

code DOS

PoC: compiled

● code 16bits obsolète● affiche message & termine

● encore présent dans les PEs● même les 64 bits

en-tête 'Rich'

PoC: compiled

● information de compilation● officiellement non documentée

● chiffrement xor32 pitoyable● complètement couvert par Daniel Pistelli

http://ntcore.com/files/richsign.htm

en-tête DOS

● obsolète● utilisé uniquement si exécuté en mode DOS● ignoré dans les autres cas

● indique où l'en-tête PE se trouve

'en-têtes PE'

File header

table des Sections

Optional header

'en-têtes NT'

organisationmémoire

déclare ce qui suit

pas dans .obj

PE\0\0

File header

● combien de section(s)?● y a-t-il un Optional Header?● 32b or 64b, DLL ou EXE...

valeurs de NumberOfSections

● 0: Corkami :p● 1: packer● 3-6: standard

● code, données, données (non) initialisées, imports, ressources...

● 16: free basic :D● à quoi bon?

Optional header

● propriétés géométriques● alignements, début en mémoire, taille

● indique où l'exécution démarre● 32/64b, pilote/standard/ligne de commande● beaucoup d'informations non cruciales● data directory

Sections

● définir l'organisation en mémoire:● où sera chargée telle partie du fichier● à quelles fins? (inscriptible, exécutable...)

Data Directory

● (RVA, Size) DataDirectory[NumbersOfRvaAndSizes]● chacun des 16 premiers, en standard, a une

utilité particulière

→ distincts, on les met souvent au pluriel

...call [API]…

Imports

PE

API: … ret

Exports

DLL

Exports

● 3 pointeurs vers 3 listes● définir en parallèle (nom, adresse, numéro)

● une adresse peut avoir plusieurs noms

Imports

● une liste à zéro terminal de descripteurs● d'habitude, un par DLL

● chaque descripteur spécifie● un nom de DLL● 2 listes de pointeurs à zéro terminal

– noms d'API et futures adresses

● ImportsAddressTable indique la liste des adresses

● elle doit être une zone mémoire inscriptible

Relocations

● les PEs ont des ImageBases standard● EXE: 0x400000, DLL 0x1000000

→ conflits entre DLLs

→ le SE doit imposer des ImageBases différentes

● les adresses absolues doivent être déplacées● la plupart dans l'en-tête sont relatives● valeurs immédiates dans le code, TLS callbacks● ajouter (NouvelleImageBase - AncienneImageBase)

Resources

● icones, dialogues, numéro de version, ...● nécessite juste 3 appels de fonctions

→ utilisé partout

● structure récursive dossier & documents● 3 niveaux en standards

TThread LLocal SStorage

● Callbacks exécutés au démarrage et à l'arrêt de chaque thread● avant l'EntryPoint● après un appel à ExitProcess

32 bits ↔ 64 bits

● IMAGE_FILE_HEADER.Machine● 0x14c I386 ↔ 0x8664 AMD64

● IMAGE_OPTIONAL_HEADER.Magic● 0x10b ↔ 0x20b

● ImageBase, stack, heap● double ↔ quad● sizeof(OptionalHeader): 0xe0 ↔ 0xf0

● TLS, import thunks deviennent aussi des qmots

NumberOfSections

● 96 sections (XP)● 65536 Sections (Vista ou ultérieur)

→ suffisant pour faire planter des outils!

65535sects

maxsecXP

SizeOfOptionalHeader

● sizeof(OptionalHeader)● ce qui donnerait 0xe0 (32b)/0xf0 (64b)● beacoup d'outils naïfs plantent si ce n'est pas le cas

● offset(SectionTable) – offset(OptionalHeader)● peut être:

● plus grand– que le fichier (→ table virtuelle, sous xp)

● plus petit ou nul (→ superposé à l'OptionalHeader)● nul (aucune section)

PE sans section

● mode standard:● 200 ≤ FileAlignment ≤ SectionAlignment● 1000 ≤ SectionAlignment

● mode 'pilote':● 1 ≤ FileAlignment == SectionAlignment ≤ 800

→ virtuelle == physique● le fichier entier est chargé tel quel● les sections sont inutiles

● aucune, beaucoup (factices ou non)

nosection*

1 ≤ FileAlignment == SectionAlignment ≤ 800

TinyPE

exemple classique de malformation manuelle● en-tête PE dans l'en-tête DOS● OptionalHeader tronqué

● ne nécessite pas de section● compatible 64b & pilote● 92 octets

● uniquement sous XP (OptionalHeader tronqué)● rembourrage nécessaire depuis Vista

→ plus petit PE universel: 268 octets

tiny*

double en-têtes 'pliables'

les DD sont pris en compte après chargementhttp://www.reversinglabs.com/advisory/pecoff.php

1.déplacer l'en-tête plus loin

2.début de section et DD factices superposés en mémoire.

3.la section contient les vrais DD

● au chargement:

1.en-têtes et section sont analysés

2.le fichier est chargé en mémoire

3.les DD sont écrasés par leurs vraies valeurs● les imports sont localisés, etc...

foldedhdr

EntryPoint nul● pour les EXEs

● 'MZ' désassemblé en tant que 'dec ebp/pop edx'(pas d'appel à DllMain si l'EP est nul)

nullEP

EntryPoint virtuel● 1er octet absent physiquement dans le fichier

● 00 C0 => add al, al

virtEP

TLS à la volée

● la liste des callbacks est m-a-j à la volée● le callback #1 ajoute un callback #2

tls_onthefly

TLS ignoré

● le TLS n'est pas exécuté si seul kernel32 est importée

● et si aucune DLL important kernel32 est importée

– Kaspersky & Ferrie

tls_k32

points terminaux superflus

● uniquement sous XP● trivial

● les points en fin de nom de DLL sont ignorés

● certaines heuristiques échouent

dll-ld

boucles dans les Ressources

● boucles (infinies)● ignorées lors le chargement● ignorées si le chemin pour atteindre une ressource

est différent

resourceloop

EntryPoint modifié par une DLL statique

les DLLs statiques sont appelé avant l'EntryPoint● DllMain reçoit le thread context via lpvReserved

● contient déjà l'addresse de l'EntryPoint

→ toute DLL statique peut librement le modifier

documenté par Skywing (http://www.nynaeve.net/?p=127),mais peu connu

ctxt*ctxt*

Win32VersionValue

● officiellement reserved● 'should be null'

● utilisé en réalité pour forcer les informations de version du SE dans le PEB

● anti-émulateur dynamique simple● utilisé dans les virus

winver

★★NNoouuvveelllleess★★ astuces

Characteristics

● IMAGE_FILE_32BIT_MACHINE● vrai même en 64 bits● non requis!!

● IMAGE_FILE_DLL● non requis pour les DLLs

– les exports sont toujours utilisables– aucun appel à DllMain!

● EP invalide → pas un EXE● FILE_DLL absent → pas une DLL non plus

→ 'indéboguable'

mininormal64

dllnomain*

descripteurs d'Imports

● INT factice ou absente● uniquement DllName et IAT sont requis

● le descripteur est sauté si aucun thunk● DllName ignoré

– peut être nul ou TRÈS gros● l'analyse devrait ne pas abandonner trop tôt

● isTerminator = (IAT == 0 || DllName == 0)● le terminateur peut être virtuel ou en dehors du

fichier● de même que le début du premier descripteur

imports_virtdesc

dd OriginalFirstThunkdd TimeDateStampdd ForwarderChain----------------------------dd Namedd FirstThunk

Imports 'torturés'

malformation complexe● DllName sans extension● IAT dans le descriptor

● l'INT presque valide est ignorée

● noms et indices/noms dans le terminateur● valide car le dernier dmot est nul

corkamix

DD Exceptions

● 64 bits Structured Exception Handler● avec beaucoup de code rajouté par le compilateur

● utilisé par W32.Deelae pour infecter● Peter Ferrie, Virus Bulletin, Septembre 2011

● modifiable manuellement, à la volée● aucun appel d'API nécessaire

exceptions

seh_change64

Relocations

● autorise n'importe quelle ImageBase● requises pour les adresses absolues: code, TLS,

.Net

● ignorée si non requises● aucun changement d'ImageBase (→ factices!)● pas de code● code 64 bits relatif à RIP● code indépendant de l'IP (shellcode)

● peut tout déplacer● déplacer l'ImageBase altère l'EntryPoint

no_dd

ibknoreloc64

ibreloc

fakerelocs

types de Relocations (en théorie)

HIGHLOW● delta d'ImageBase standard

ABSOLUTE● ne fait rien● juste utilisé pour l'alignement

● les types 6 et 7 sont ignorés● alors que le type 8 est interdit

● le type 4 (HIGHADJ) nécessite un param.● qui est en fait ignoré (bug du SE)

● le type 2 (LOW) ne fait rien● car les ImageBases sont alignées à 64kb

● les types MIPS et IA64 sont toujours présents● enfin, du nettoyage sous Windows 8!

type de Relocations en pratique

un peu d'histoire

● HIGHADJ est là depuis le début● MIPS était reconnu mais rejeté par Win95● NT3.1 introduit MIPS – sous toutes les archs.● LOW était rejeté par Win95/WinME

● alors qu'il ne fait rien sous les autres versions

● Windows 2000 avait un type supplémentaire, aussi avec un paramètre

Bonus:

les relocations de Win95 utilisent 2 copies identiques du même code – quelle optimisation!

s'amuser avec les relocations

● 4 types ne font en fait rien● tous peuvent être utilisés sur une adresse factice

● HighAdj's peut être utilisé comme piège● des Relocations peuvent en modifier d'autres

● un bloc peut modifier le suivant● des Relocations peuvent décrypter des données

● mettre une ImageBase dans le noyau● sa future valeur est connue

● pas d'analyse statique possible

● mais c'est très louche :D

reloccrypt

reloccrypt

reloccrypt

Code dans l'en-tête

● l'en-tête est exécutable● les packers y mettent code ou données

● beaucoup de champs inutilisés (→ format TE)● beaucoup de champs contrôlables

● Peter Ferriehttp://pferrie.host22.com/misc/pehdr.htm

→ du vrai code dans l'en-tête

maxvals

hdrcode

traceless

.Net

étapes du chargement:

1.chargement du PE• uniquement les imports (DD[1]) à cette étape

2.appel de MSCoree.dll

3.chargement de la partie .Net● nécessite CLR (DD[13]) et relocations (DD[5])● oublie de vérifier NumberOfRvaAndSizes :(

– fonctionne avec NumberOfRvaAndSizes = 2

échec d'IDA, reflector – mais déjà dans la nature

tinynet

PE

...imports

...

...

...

...

...

...

...

...

...

...

...

...

...

...

.NET

...

...

...

...

...relocs

...

...

...

...

...

...

...

...CLR

...

PE sans zéro

● LoadlibraryEx avec LOAD_LIBRARY_AS_DATAFILE

● un PE de données nécessite uniquementMZ, e_lfanew, 'PE\0\0'

● 'PE' à la fin du fichier● assez de rembourrage pour que e_lfanew ne

contienne pas de zéro

un PE non-null peut être créé et chargé

d_nonnull-*

uniquement des resources

● 1 seule section valide● 65535 sections sous XP!

● 1 DataDirectory

d_resource*

subsystems

● pas de différences particulières● alignements bas pour les pilotes● imports incompatibles: NTOSKRNL ↔ KERNEL32● texte ↔ graphique : IsConsoleAttached

→ un PE avec des alignements bas et sans imports peut marcher avec les 3 subsystems

multiss*

un PE nu avec du code

● alignments bas → pas de sections● pas d'imports → APIs chargées à la main● TLS → pas d'EntryPoint

ni EntryPoint, ni section, ni import,

mais le code s'exécute sans problème

nothing*nothing*

EntryPoint externe (1/2)● dans une DLL (sans relocations)

dllextEP

EntryPoint externe (2/2)● mémoire allouée juste avant par le TLS

tls_virtEP

EntryPoint ignoréle TLS termine l'exécution mais sera rappelé ensuite

tls_noEP

du noyau à l'utilisateur

● le déboguage noyau est compliqué● alors que les packers noyau sont limités

1.changer le subsystem

2.utiliser de fausses DLLs noyau (ntoskrnl, etc...)● rediriger les APIs

– DbgPrint → MessageBoxA, ExAllocatePool → VirtualAlloc

→ automatisation de l'unpacking noyau

ntoskrnl

TLS AddressOfIndex

● pointeur vers un double mot● reçoit 0, 1... au chargement du nème TLS● astuce dynamique facile

call <garbage> dans le fichier → call $+5 en mémoire

● modifié avant les imports sous XP,après sous W7

même PE, mais chargement différent

tls_aoiOSDET

Manifest

● ressource XML● peut faire échouer le chargement● peut faire planter le SE! (KB921337)

● difficile à analyser en détail● ignoré si le type est incorrect

Manifest minimal:<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'/>

corruption de DllMain/TLS

● DllMain et TLS ont juste besoin de restaurer ESI● même ESP peut être corrompu● anti-émulateur simple

● le TLS peut déclencher une exception● pas d'erreur pour le SE● l'EntryPoint est exécuté comme si de rien n'était

fakeregs

un PE 'quine'

● afficher son code source● totalement inutile – très divertissant :D

● remplir l'en-tête DOS de caractères ASCII● code ASM entre les en-têtes DOS et PE

● visible par affichage texte● s'affiche lui-même si exécuté

quine

un polyglotte binaire

● ajouter %PDF dans les 400h premiers octets

→ votre PE est aussi un PDF (→ Acrobat)

● ajouter PK\03\04 n'importe où

→ votre PE est aussi un ZIP (→ PKZip)

● mettre une .CLASS Java .CLASS dans le ZIP

→ votre PE est aussi un JAR (→ Java)

● ajouter <HTML> quelque part

→ votre PE est aussi une page HTML (→ Mosaic)

● Bonus: Python, JavaScript

corkamix

Conclusion

Conclusion

● le format des exécutables de Windows est complexe

● la majeure partie est documentée, mais c'est un vrai champ de mines● avec de nouvelles découvertes chaque jour :(

http://pe101.corkami.com

http://pe.corkami.com

des questions?

Merci à

Fabian Sauter, Peter Ferrie, وليد عصرBernhard Treutwein, Costin Ionescu, Deroko, Ivanlef0u, Kris Kaspersky, Moritz Kroll, Thomas Siebert, Tomislav Peričin, Kris McConkey, Lyr1k, Gunther, Sergey Bratus, frank2, Ero Carrera, Jindřich Kubec, Lord Noteworthy, Mohab Ali, Ashutosh Mehra, Gynvael Coldwind, Nicolas Ruff, Aurélien Lebrun, Daniel Plohmann, Gorka Ramírez, 최진영 , Adam Błaszczyk, 板橋一正 , Gil Dabah, Juriaan Bremer, Bruce Dang, Mateusz Jurczyk, Markus Hinderhofer, Sebastian Biallas, Igor Skochinsky, Ильфак Гильфанов, Alex Ionescu, Alexander Sotirov, Cathal Mullaney

Merci!

@ange4771@ange4771Ange Albertini @gmail.com

http://corkami.com

Bonus

pas du PE, mais quand même amusant

formats anciens

● en 32b, Windows gère encore les EXE et COM● moins courant, ils échappent aux détections

● un EXE peut s'auto-modifier en PE● en utilisant une signature 'ZM'● pas en mémoire :(

● un COM écrit en symboles peut créer un PE● grâce à http://utf-8.jp/public/sas/ de Yosuke

Hasegawa

exe2pe, dosZMXP

aa86drop.com

archéologie binaire

● les polices pt/pt (.FON) sont en format NE● crée en 1985 pour Windows 1.0

● vgasys.fon toujours présent dans Windows 8● tel quel depuis 1991 (Windows 3.11)● police créée en 1984

● les propriétés montrent le copyright

→ Windows 8 gère encore (partiellement)

un format d'exécutable 16b datant de 1985

instruction en état d'ébriété

● Lock:Prefetch● ne peut pas être exécutée (illégale)

● fonctionne bizarrement sous W7 x64● ne déclenche pas d'exception● modifiée par le SE (mal 'réparée')

– mais encore incorrecte après!

boucle infinie d'erreurs silencieuses

this is the end...my only friend, the end...

(les Portes)

Recommended