0:00:05.007,0:00:10.009 Quel processeur bizarre - faire des misères au x86... et un peu de PE [Portable Executable] 0:00:10.009,0:00:19.004 Bienvenue... et surtout, dites-moi si je vais trop vite 0:00:19.004,0:00:28.002 Je vais parler des opcodes, et un peu du format PE et de leurs bizarreries 0:00:28.002,0:00:35.000 Je fais du reverse depuis quelque temps. J'ai créé un projet appelé Corkami. 0:00:35.000,0:00:42.003 Dans le passé, j'ai participé à Mame, l'émulateur Arcade, et professionnellement, analyste de virus, 0:00:42.003,0:00:48.001 mais je suis ici à titre personnel, ce sont mes propres expériences à la maison. 0:00:48.001,0:00:57.000 Donc, je viens de mentionner Corkami. C'est le nom du projet de mon projet de reverse [rétro-ingénierie] 0:00:57.000,0:01:03.007 Je n'y parle que de choses techniques, pas de pubs, pas de login requis 0:01:03.007,0:01:06.005 Directement le pur jus. 0:01:06.005,0:01:12.004 J'essaie de le maintenir à jour, et util. J'ai créé des fiches pense-bêtes et d'autre documents 0:01:12.004,0:01:15.008 que j'utilise moi-même au boulot, au quotidien 0:01:15.008,0:01:18.006 mais c'est juste un loisir. je commence quand les enfants sont couchés 0:01:18.006,0:01:23.001 tard dans la nuit, donc ça n'a probablement pas le polish professionnel 0:01:23.001,0:01:25.002 que j'aimerais qu'il ait. 0:01:25.002,0:01:30.005 Actuellement, Corkami est un wiki et des pense-bêtes 0:01:30.005,0:01:37.005 et je me focalise sur la création de preuves de concepts [démonstration d'hypothèse, "proof of concept] [Tiens, salut Bob!] 0:01:37.005,0:01:42.008 donc les binaires sont fait-main, d'habitude je n'utilise pas de compilateurs, je créé la structure du PE à la main 0:01:42.008,0:01:46.004 pour que ce soit focalisé sur le point pertinent 0:01:46.004,0:01:49.000 et qu'on est pas de parasites. on n'a probablement pas besoin d'IDA 0:01:49.000,0:01:51.004 pour comprendre ce qui se passe 0:01:51.004,0:01:54.009 car je me concentre uniquement sur ce qui est important. 0:01:54.009,0:01:58.002 Les binaires sont directement téléchargeables pour que vous puissiez 0:01:58.002,0:02:01.003 tester avec votre débogueur, vos outils, vos connaissances, 0:02:01.003,0:02:03.008 directement. 0:02:03.008,0:02:07.006 pour l'instant, je me suis concentré sur le PDF, l'assembleur et le format PE 0:02:07.006,0:02:11.002 quelques autres trucs, mais ce sont les sujets les plus approfondis 0:02:11.002,0:02:15.000 du site, et je partage tout ça avec une licence 0:02:15.000,0:02:19.008 très permissive, BSD, donc vous pouvez réutiliser commercialement 0:02:19.008,0:02:24.006 Même les images sont en format ouvert. 0:02:24.006,0:02:29.003 Donc, la raison de cette présentation... il y a quelque temps, 0:02:29.003,0:02:32.003 J'étais jeune et innocent, et je pensais que les CPUs, fait de transistors, 0:02:32.003,0:02:38.004 était parfaitement logique 0:02:38.004,0:02:41.006 et ensuite, un virus m'a piégé... simplement, 0:02:41.006,0:02:46.005 IDA était rendu inutile. Donc j'ai décidé de repartir à zéro 0:02:46.005,0:02:49.007 et d'étudier l'assembleur et le PE du début. 0:02:49.007,0:02:52.009 j'ai écrit en chemin des documents, partagés sur Corkami 0:02:52.009,0:02:57.006 et maintenant je vous présente le résultat plus ou moins final, 0:02:57.006,0:03:01.006 ou du moins quelques buts atteints. Si j'étais juste un gars qui a étudié l'assembleur 0:03:01.006,0:03:05.004 je ne serais probablement pas en train de présenter ici, 0:03:05.004,0:03:10.005 à moins d'avoir eu quelques résultats avec certains outils. 0:03:10.005,0:03:13.008 Donc, pour résumer, j'ai trouvés des bogues dans tous les désassembleurs que j'ai essayé 0:03:13.008,0:03:22.000 et j'ai aussi obtenus quelques plantages. J'insiste que tous les auteurs ont été contactés 0:03:22.000,0:03:26.000 et que la plupart des problèmes ont déjà été corrigé, 0:03:26.000,0:03:30.009 mais en tout cas, en version 6.1, il plante directement, mais dans la version 6.2 0:03:30.009,0:03:33.003 c'est corrigé. 0:03:33.003,0:03:37.004 et la dernière version de Hiew [Hacker's view] (enfin, pas la dernière publique) 0:03:37.004,0:03:41.004 corrige ça aussi. 0:03:41.004,0:03:44.008 Donc, pour cette présentation, je commencerais facile, 0:03:44.008,0:03:50.008 je pars du principe que vous êtes tous habitués à l'assembleur ? 0:03:50.008,0:03:57.003 Oui. et vous êtes tous habitués, ou 0:03:57.003,0:04:02.009 vous avez déjà rencontré des cas d'opcodes non documentés? 0:04:02.009,0:04:06.001 Genre vous faites confiance à IDA, point barre. 0:04:06.001,0:04:10.005 Est-ce habituel de voir quelque chose non géré par IDA ? 0:04:10.005,0:04:14.003 Levez les bras... ok, pas tant que ça. 0:04:14.003,0:04:19.005 Bon, après l'introduction en accéléré, 0:04:19.005,0:04:25.003 Je parlerais de quelques techniques, puis présenterai CoST, mon programme 0:04:25.003,0:04:28.009 et je parlerais aussi un peu du format PE 0:04:28.009,0:04:34.000 Bon, vous connaissez tous l'assembleur, on va survoler ... 0:04:34.000,0:04:37.009 Donc, on compile un binaire, il y a de l'assembleur, il y a 0:04:37.009,0:04:44.002 un rapport, des points communs entre le code source et l'assembleur généré... 0:04:44.002,0:04:48.007 et bien sûr, une relation entre langage machine et les opcodes 0:04:48.007,0:04:53.006 ce qui est important est que l'assembleur est généré par le compilateur, mais ce qui reste 0:04:56.006,0:04:59.007 dans le binaire, sont uniquement les opcodes, qui sont interprétés 0:04:59.007,0:05:03.003 directement par le processeur, ce qui implique qu'il sache quoi faire avec, 0:05:03.003,0:05:07.003 il s'en fiche si vous ou vos outils 0:05:07.003,0:05:10.008 ne savent pas ce qui va arriver. il le fait, tout simplement. 0:05:10.008,0:05:16.001 Et le problème, c'est que d'habitude, on ne lit pas les opcodes directement, mais le désassemblage 0:05:16.001,0:05:20.006 donc si le désassemblage échoue, on est bloqué 0:05:20.006,0:05:25.004 on est aveugle, on ne sait pas ce qui va s'exécuter 0:05:25.004,0:05:28.000 l'autre problème est comme les instructions sont de longueurs variables 0:05:28.000,0:05:30.003 on ne sait pas ou la suivante commence 0:05:30.003,0:05:32.003 donc même la suite est inconnue. 0:05:32.003,0:05:40.001 Donc, on créé une seule instruction non documentée dans un programme simple 0:05:40.001,0:05:48.006 on utilise le mot-clef 'emit' -- c'est Visual Studio 2010 ultimate -- 0:05:48.006,0:05:52.002 et on obtient un octet non identifié au désassemblage 0:05:52.002,0:05:58.004 on a des juste points d'interrogations. 0:05:58.004,0:06:01.007 et donc, même si Visual Studio coûte plusieurs milliers d'euros 0:06:01.007,0:06:05.000 il ne sait pas ce qui va se produire.... 0:06:05.000,0:06:09.000 et si on regarde les documentations Intel 0:06:09.000,0:06:14.002 circulez, il y a rien a voir... l'opcode D6... inconnu au bataillon 0:06:14.002,0:06:17.009 Microsoft n'a rien à dire, Intel non plus, 0:06:17.009,0:06:21.001 donc d'habitude, si vous essayez des choses comme ça, attendez-vous au pire. 0:06:21.001,0:06:26.005 Donc, aucune information... en général, ça annonce un plantage... 0:06:26.005,0:06:29.007 mais dans ce cas particulier, aucun problème... 0:06:29.007,0:06:35.002 nous ne savons pas ce qui se passe, si on regarde les docs Intel et Microsoft, on n'en sait pas plus. 0:06:35.002,0:06:41.002 Mais le CPU a juste fait son boulot dans son coin. Ce qui s'est passé est qu'en fait 0:06:41.002,0:06:49.001 D6 est un opcode très simple, qui ne fait pas grand chose, mais pas documenté par Intel, 0:06:49.001,0:06:53.009 par contre, il l'est par AMD, et la plupart le sont aussi également, par AMD mais pas Intel 0:06:53.009,0:06:58.001 aucune idée pourquoi. si quelqu'un le sait... 0:06:58.001,0:07:04.001 c'est un opcode pourtant trivial, pourtant... 'y a rien à voir, continuez votre chemin' 0:07:04.001,0:07:08.003 Il est utilisé souvent... l'utilisation habituelle de tels opcodes sont les virus et les packeurs 0:07:08.003,0:07:13.003 pour éviter les analyses automatisées où trop facile. 0:07:13.003,0:07:22.002 Ce qui est ironique, c'est que si vous regardez la doc, elle est pleine de trous. mais le désassembleur d'Intel, 0:07:22.002,0:07:25.002 Xed, qui est gratuit mais pas ouvert, gère tous ces opcodes sans problème... 0:07:25.002,0:07:35.005 Alors que Microsoft, Visual Studio, et WinDBG, suivent la documentation aveuglément 0:07:35.005,0:07:43.000 Donc vous obtiendrez des points d'interrogation alors qu'Intel sait très bien ce qui se passe 0:07:43.000,0:07:52.003 'faites ce que je fais, pas ce que je dit' 0:07:52.003,0:08:01.001 donc, bien sûr, vous me direz que WinDbg est fait uniquement ce qui est généré 0:08:01.001,0:08:08.000 par les compilateurs Microsoft, mais ça exclut WinDBG comme outil d'analyse de virus: 0:08:08.000,0:08:17.006 vous rajoutez D6, trivial, et WinDbg est muet. 0:08:17.006,0:08:25.005 pas génial 0:08:25.005,0:08:32.007 un autre problème est que toutes ses choses non documentées 0:08:32.007,0:08:37.006 sont peut-être présentes, l'une dans un virus, 0:08:37.006,0:08:42.003 l'autre dans un packeur, etc... donc il n'est pas facile 0:08:42.003,0:08:46.005 de trouver un bon regroupement de tels fichiers pour rassembler toutes ces informations 0:08:46.005,0:08:50.002 donc par exemple, 0:08:50.002,0:08:53.004 quelqu'un vous parle d'une astuce 0:08:53.004,0:08:55.008 et vous dit qu'elle est enfouit dans MebRoot (un virus costaud) 0:08:55.008,0:08:58.007 donc vous êtes obligé de creuser pour voir juste la partie qui vous intéresse 0:08:58.007,0:09:03.009 et en plus, on sait que c'est un virus, donc ca ne circule pas facilement, 0:09:03.009,0:09:08.006 et il y a plein de trucs dedans qui n'ont rien à voir dedans, 0:09:08.006,0:09:15.001 avant ou après ce qui vous intéresse. Donc c'est le fossé que je veux remplir en fournissant 0:09:15.001,0:09:21.001 un groupe de fichier à la fois simple et complet, et focalisé. 0:09:21.001,0:09:27.007 Donc, on commence. enfin, du vrai, quelques opcodes non documentés. 0:09:27.007,0:09:37.000 Mais avant d'avoir commencé à étudier, je me suis demandé quelles étaient les vrais capacités 0:09:37.000,0:09:44.005 des processeurs, quelles instructions existent vraiment. 0:09:44.005,0:09:52.002 C'est un peu comme l'anglais: la plupart de la population mondiale comprend ces mots, et 0:09:52.002,0:09:57.007 si vous avez déjà désassemblé quelque chose, vous êtes habitués à ces instructions 0:09:57.007,0:10:04.003 tous les compilateurs les utilisent. elles sont tellement répandues que si elles sont absentes, 0:10:04.003,0:10:08.006 on se sent pris au dépourvu. 0:10:08.006,0:10:19.007 mais les processeurs Intels datent des années 70. Donc, 0:10:19.007,0:10:27.007 comme l'anglais de Shakespeare, vous voyez que c'est de l'anglais... mais, ça veut dire quoi en fait ? 0:10:27.007,0:10:30.005 d'ailleurs, j'ai déjà oublié 0:10:30.005,0:10:36.003 ces instructions sont toutes gérées par tous nos processeurs, pourtant, on n'a plus l'habitude de les lire 0:10:36.003,0:10:41.009 c'est plus que génant 0:10:41.009,0:10:46.008 En fait, j'ai écrit un exemple qui n'utilisent que ces vieilles instructions, qui font vraiment quelque chose 0:10:46.008,0:10:53.001 donc si vous vous sentez ici comme chez vous, je voudrais vous demander 'quel âge avez-vous ?' 0:10:53.001,0:10:59.007 parce que même moi, j'ai l'habitude de PUSH/JUMP/CALLs, mais ça, euhh... 0:10:59.007,0:11:05.008 pourtant, ça marche même sur un i7, et c'est utilisable par les virus, 0:11:05.008,0:11:13.009 les packeurs, etc... pourtant, la plupart est complètement inutilisée de nos jours, bien que parfaitement 0:11:13.009,0:11:15.009 gérées par nos processeurs modernes. 0:11:15.009,0:11:21.004 Et, tel l'anglais, c'est une langue qui évolue, et les générations précédentes 0:11:21.004,0:11:27.007 n'ont pas l'habitude des derniers mots à la mode. 0:11:27.007,0:11:35.001 Ces instructions sont parfois présentes sur les processeurs les plus récent. en une seule instruction, on fait 0:11:35.001,0:11:41.003 un CRC32, on décrypte l'AES, on compare des chaînes, ou d'autres opérations complexes. 0:11:41.003,0:11:47.006 Donc, c'est possible sur un processeur moderne. pas tous, bien sûr. 0:11:47.006,0:11:54.006 une que j'aime bien est MOVBE -- move big endian -- parce que c'est le vilain petit canard du lot... 0:11:54.006,0:12:01.008 uniquement implémentée sur les processeurs Atom, donc comme ce netbook, qui la gère... 0:12:01.008,0:12:09.003 alors qu'un i7 64-bits ne l'a pas, même si lui aura CRC32, peut-être AES, etc... 0:12:09.003,0:12:12.005 donc, tant pis pour la retro-compatibilité 0:12:12.005,0:12:20.002 à ma connaissance, il n'y existe aucun processeur qui gère à la fois CRC32 et MOVBE. 0:12:20.002,0:12:24.008 De plus, MOVBE est un peu inutile car il fait la même chose que MOV et BSWAP réunit... 0:12:24.008,0:12:32.000 donc, bizarre. en tout cas, ce mini-PC a une instruction que la plupart des PC n'ont pas 0:12:32.000,0:12:35.002 Pourquoi ? quelqu'un sait? 0:12:35.002,0:12:37.008 [Auditeur:] "cette instruction est documentée ?" 0:12:37.008,0:12:38.007 oui 0:12:38.007,0:12:42.008 totalement documentée officiellement 0:12:42.008,0:12:46.008 [Auditeur:] "Mais, c'est un drapeau du processeur juste pour cette instruction, ou implicitement lié au 0:12:46.008,0:12:51.003 processeurs Atom ? 0:12:51.003,0:12:58.003 mmm, je ne sais pas. je vérifie la valeur par CPUID, mais j'ai oublié la définition exacte. 0:12:58.003,0:13:07.005 il y a tant d'informations données par CPUID que j'ai vite oublié. 0:13:07.005,0:13:13.006 Autre chose, spécifique à Windows, car je m'intéresse aux virus... 0:13:13.006,0:13:22.005 avant d'exécuter quoi que ce soit, je me demandais quelle était la valeur initiale de chaque registre 0:13:22.005,0:13:28.007 quand le programme démarre. 0:13:28.007,0:13:33.006 et ça vous donne en fait de l'information fiable, qu'on retrouve utilisée par les virus 0:13:33.006,0:13:40.005 donc par exemple, au démarrage, EAX vous dit si vous êtes sur un OS ancien (XP ou avant) 0:13:40.005,0:13:42.008 ou plus récent, Vista ou 7. 0:13:42.008,0:13:50.007 de même, ce n'est pas utilisé par les virus à mon souvenir, mais si GS est nul, on est dans un OS 32 bits 0:13:50.007,0:13:54.002 sinon, sur un 64b. 0:13:54.002,0:13:56.009 J'utilise ça régulièrement, on le verra plus tard. 0:13:56.009,0:14:04.003 De même, la relation entre les registres n'est pas forcément évidente. il y en a beaucoup, 0:14:04.003,0:14:10.007 et j'ai été surpris qu'une instruction à virgule flottante (FPU) change le statut (FST), les registres 0:14:10.007,0:14:18.005 eux-mêmes (STx), les registres MMx aussi, mais en plus, toutes les documentations en ligne associent 0:14:18.005,0:14:24.009 ST0 et MM0, ce qui semble logique, alors qu'en fait, une seule instruction modifie 0:14:24.009,0:14:31.003 non pas MM0, mais MM7, dans l'autre sens. 0:14:31.003,0:14:36.007 donc après une instruction comme "load PI" [FLDPI] on regarde la valeur de MM7, 0:14:36.007,0:14:39.004 ça peut-être utilisé comme astuce simple. 0:14:39.004,0:14:45.009 alors que toutes les documentations, Wikipedia ou autre, se trompent. 0:14:45.009,0:14:53.003 quelque chose d'autre qui peut être utilisé comme anti-débogueur sous XP: le FPU modifie aussi CR0 0:14:53.003,0:14:59.007 donc ça fait une astuce anti-émulateur plutôt inattendue rien qu'avec le FPU. 0:14:59.007,0:15:09.000 'store machine status word' [SMSW] est une instruction qui date du 286, quand le mode protégé était 0:15:09.000,0:15:18.004 récent et incomplet, qui permet de lire les valeurs de CR0, même depuis le mode utilisateur. 0:15:18.004,0:15:26.009 alors que 'MOV CR0' est privilégiée 0:15:26.009,0:15:34.001 pour une raison inconnue, le mot de poid fort est officiellement non défini. 0:15:34.001,0:15:40.004 donc à priori, on ne sait pas ce qu'il va contenir, 0:15:40.004,0:15:45.007 mais en fait il s'agit bien du même mot de poid fort que CR0. 0:15:45.007,0:15:52.009 et, sous XP, après une instruction FPU, la valeur de CR0 est modifiée, mais reprend sa valeur initiale 0:15:52.009,0:16:00.003 toute seule par la suite. donc juste avec SMSW, verifier le résultat, puis faire une opération FPU, 0:16:00.003,0:16:05.009 alors SMSW donnera un résultat différent, mais ensuite, le résultat redeviendra comme à l'origine. 0:16:05.009,0:16:11.000 un moyen élégant de faire des boucles en apparence infinies. une astuce complexe anti-émulateurs. 0:16:11.000,0:16:18.008 Une astuce similaire sous Windows 32b, où GS n'est pas stocké dans le CONTEXT, donc quand l'OS passe d'un 0:16:18.008,0:16:25.006 fil d'exécution à l'autre (thread-switch), GS est remis à zero. Donc, si on attend, quoi qu'on fasse, 0:16:25.006,0:16:33.003 GS change comme par enchantement. Mais si vous faites du pas à pas, c'est lent, donc l'OS change de fil, 0:16:33.003,0:16:40.005 et GS est perdu dès l'instruction suivante. 0:16:40.005,0:16:45.006 De même, si on attend que GS devienne nul, on finira par sortir de la boucle. 0:16:45.006,0:16:53.001 En tout cas, la première fois, ça défiait mon entendement... sans autres process ou autre, je ne comprenais 0:16:53.001,0:16:58.007 pas d'où ça venait. Au moins, mon exemple commence dès le début avec ça 0:16:58.007,0:17:02.009 c'est plus pratique 0:17:02.009,0:17:11.000 une autre particularité, c'est que ça met du temps pour être remis à zéro. en faisant 2 boucles d'attentes, 0:17:11.000,0:17:17.005 et mesurant le temps entre les 2 (changement de fil), ça prend somme toute assez longtemps, comparé à une 0:17:17.005,0:17:25.005 exécution standard. ça fait un anti-émulation solide. 0:17:25.005,0:17:33.001 Je pensais tout naturellement que NOP était parfait! NOP, c'est NOP, ça ne fait rien, donc, aucun problème ! 0:17:33.001,0:17:44.001 Mais à l'origine, NOP est 'échange ?AX avec lui-même' (xchg ?ax, ?ax) mais c'est le cas pour le NOP encodé 0x90 0:17:44.001,0:17:51.001 mais il y a un autre encodage de XCHG EAX, EAX, qui ne fait rien non plus en 32b 0:17:51.001,0:17:54.006 mais, à l'instar de toutes les instructions sur 32b en mode 64b 0:17:54.006,0:17:58.007 cette instruction remet à zéro le double mot de poid fort 0:17:58.007,0:18:02.007 donc on a un XCHG EAX [,EAX] qui fait quelque chose. 0:18:02.007,0:18:05.007 bien qu'initialement il semblerait ne rien faire, de sa relation avec NOP 0:18:05.007,0:18:10.001 mais heureusement, le NOP 0x90, lui, ne fait toujours rien, un vrai fainéant ;) 0:18:10.001,0:18:14.001 Celui-ci est maintenant bien répandu, 0:18:14.001,0:18:18.004 le HINT NOP est un NOP sur plusieurs octets 0:18:18.004,0:18:23.004 qui indique au processeur ce qui va être exécuté ou accédé ensuite 0:18:23.004,0:18:24.005 quelque soit l'adresse dans un HINT NOP en mémoire, 0:18:24.005,0:18:26.002 aucune exception n'est déclenchée 0:18:26.002,0:18:32.003 mais ... 0:18:32.003,0:18:37.002 autre chose, il est partiellement non documenté par Intel 0:18:37.002,0:18:44.005 (comme d'habitude, ce n'est pas le cas avec AMD) 0:18:44.005,0:18:48.003 en outre, comme c'est une instruction sur plusieurs octets, avec des opérandes immédiates 0:18:48.003,0:18:51.007 si on met ces octets à la fin d'une page mémoire 0:18:51.007,0:18:55.000 alors le processeur va vouloir lire l'encodage des opérandes, 0:18:55.000,0:18:56.006 et ça va déclencher une exception 0:18:56.006,0:19:01.003 donc c'est un NOP qui peut déclencher une exception en bas de page 0:19:01.003,0:19:04.005 Merci, Intel 0:19:04.005,0:19:07.000 MOV également, je croyais... 0:19:07.000,0:19:11.003 qu'il devrait être parfaitement logique 0:19:11.003,0:19:16.000 mais, même s'il est documenté, il y a des cas compliqués, 0:19:16.000,0:19:19.007 qui n'étaient pas parfaitement gérés dans tous les assembleurs que j'ai essayé 0:19:19.007,0:19:22.009 sauf peut-être Xed 0:19:22.009,0:19:29.005 on ne peut pas faire un MOV de ou vers CR0 en mémoire, 0:19:29.005,0:19:33.000 la documentation dit que le Mod/RM est ignoré 0:19:33.000,0:19:34.001 ce qui ne veut pas dire que l'instruction est invalide 0:19:34.001,0:19:35.000 simplement, considéré comme n'utilisant pas la mémoire 0:19:35.000,0:19:36.007 sinon, ça ferait un plantage 0:19:36.007,0:19:39.005 donc, voici l'équivalent 0:19:39.005,0:19:42.003 ce qui mettait en tord tous les désassembleurs 0:19:42.003,0:19:44.004 jusque récemment 0:19:44.004,0:19:50.000 MOVSXD est une instruction 64b, qui étend un registre 0:19:50.000,0:19:55.003 donc, d'un registre vers un plus gros 0:19:55.003,0:19:58.002 mais sans préfixe REX - ce qui n'est pas encouragé, 0:19:58.002,0:20:02.000 on peut l'utiliser comme un MOV standard, de 32b vers 32b 0:20:02.000,0:20:04.003 et dans l'autre sens, 0:20:04.003,0:20:09.009 MOV d'un selecteur à un registre 32b marche sans problème, 0:20:09.009,0:20:13.002 alors que beaucoup de désassembleurs afficheraient MOV AX, CS, ce qui semble logique 0:20:13.002,0:20:16.000 niveau taille 0:20:16.000,0:20:19.007 mais en fait le mot de poid fort du registre cible est 'non défini' 0:20:19.007,0:20:21.008 mais ici, pas de surprise amusante, 0:20:21.008,0:20:25.002 ce sont juste des zéros 0:20:25.002,0:20:30.003 donc c'est équivalent à MOV EAX, CS 0:20:30.003,0:20:32.005 BSWAP est un de mes favoris 0:20:32.005,0:20:35.001 parce que je le compare à une administration: 0:20:35.001,0:20:38.002 il est supposé passer d'un endianisme [endianness] à l' autre 0:20:38.002,0:20:42.008 mais pour diverses raisons, 0:20:42.008,0:20:45.001 il ne peut jamais faire son travail correctement 0:20:45.001,0:20:50.004 donc, c'est juste en 64b que tout se passe 0:20:50.004,0:20:51.009 comme prévu 0:20:51.009,0:20:55.009 en 32b, comme toutes les autres instruction 32b 0:20:55.009,0:20:59.003 le double mot de poid fort est mis à zéro... 0:20:59.003,0:21:02.007 et sur un mot, il est non défini officiellement, 0:21:02.007,0:21:04.001 mais il est pourtant utilisé couramment dans les virus et les packeurs 0:21:04.007,0:21:07.000 car il remet simplement à zéro le registre, 0:21:07.000,0:21:09.005 comme un simple XOR AX, AX 0:21:09.005,0:21:14.005 donc, devant un résultat si inexplicable, je comprends 0:21:14.005,0:21:18.007 qu'Intel ne veuille pas en parler 0:21:18.007,0:21:20.009 ça serait sûrement gênant de devoir expliquer 0:21:20.009,0:21:24.007 ce résultat plutôt comique. 0:21:24.007,0:21:33.004 BSWAP AX est aussi mal géré par WinDbg et les autres 0:21:33.004,0:21:35.006 on lira BSWAP EAX 0:21:35.006,0:21:42.000 alors que le registre est remis à zéro... génant 0:21:42.000,0:21:47.003 tout le monde comprend ce code? 0:21:47.003,0:21:53.000 quelqu'un voit un piège possible? 0:21:53.000,0:21:56.006 l'adresse de est empilée 0:21:56.006,0:22:00.003 puis dépilée par RETN 0:22:00.003,0:22:05.006 donc, on saute vers une adresse immédiates 0:22:05.006,0:22:11.003 l'ordre d'exécution ? 0:22:11.003,0:22:18.000 oui, l'exécution démarre ici 0:22:18.000,0:22:20.009 non, rien à voir ici 0:22:20.009,0:22:26.000 voilà OllyDbg 1 - c'est corrigé dans le 2 0:22:26.000,0:22:28.002 Olly essaie même d'être sympa et de vous dire 0:22:28.002,0:22:30.005 via un commentaire automatique, 0:22:30.005,0:22:33.005 que RET sera utilisé comme saut vers 0:22:33.005,0:22:36.003 et, voyez le résultat, plutôt différent 0:22:36.003,0:22:37.004 donc, que c'est-il passé ? 0:22:37.004,0:22:40.002 quelqu'un voit ? 0:22:40.002,0:22:43.002 donc, RETN a un prefix 66 0:22:43.002,0:22:47.003 donc, il retourne vers IP (16b), pas EIP 0:22:47.003,0:22:56.001 donc on ne saute pas vers 401008, mais 00001008 0:22:56.001,0:22:58.007 et dans mon exemple, la page nulle a été allouée 0:22:58.007,0:23:01.000 et du code a été placé à 1008 0:23:01.000,0:23:06.000 donc, ça ne retourne pas vers [] 0:23:06.000,0:23:10.008 mais l'autre problème est que c'est aussi appelé un RETN 0:23:10.008,0:23:15.007 bien que ce soit différent. les désassembleurs ont leur propre façon de l'afficher 0:23:15.007,0:23:19.005 tel que 'small retn', 'ret.16', ou autre 0:23:19.005,0:23:22.007 mais officiellement, c'est la même instruction qu'un RETN standard. 0:23:22.007,0:23:28.006 donc, le dernier Hiew, et OllyDbg 1 0:23:28.006,0:23:31.001 peut-être pas le 2 0:23:31.001,0:23:33.001 mais on peut se faire avoir 0:23:33.001,0:23:41.002 et le préfixe 66 a le même role avec CALLs, RETs, LOOPs, JMPs 0:23:41.002,0:23:45.008 toutes les instructions contrôlant le flux d'exécution 0:23:45.008,0:23:48.002 je ne vais pas tout énumérer 0:23:48.002,0:23:51.007 car sinon vous allez mourir d'ennui 0:23:51.007,0:23:55.004 pour en savoir plus, j'ai créé une page sur Corkami [x86.corkami.com], 0:23:55.004,0:24:00.007 avec quelques graphiques et penses-bêtes 0:24:00.007,0:24:04.007 pour faciliter le boulot 0:24:04.007,0:24:06.009 bon, trop de théorie 0:24:06.009,0:24:11.008 je n'aime pas lire sans avoir quelque chose à me mettre sous le débogueur, 0:24:11.008,0:24:13.006 donc j'ai créé CoST 0:24:13.006,0:24:16.000 ce qui signifie Corkami Standard Test 0:24:16.000,0:24:20.000 CoST est un unique binaire, sans option de ligne de commande 0:24:20.000,0:24:25.004 on l'exécute, il fait plein de tests 0:24:25.004,0:24:28.006 le tout dans un PE compliqué 0:24:28.006,0:24:35.001 pour aussi tester vos outils PE 0:24:35.001,0:24:36.004 ou vos connaissances 0:24:36.004,0:24:40.001 mais, dans ce PE compliqué, il est casse-pied à déboguer 0:24:40.001,0:24:42.007 donc j'ai fait aussi une version 'PE standard' 0:24:42.007,0:24:47.004 si on ne veut étudier que l'assembleur 0:24:47.004,0:24:49.004 sans difficultés 0:24:49.004,0:24:57.008 donc, CoST contient de nombreux tests 0:24:57.008,0:24:59.007 les classiques, triviaux, 0:24:59.007,0:25:03.009 un peu plus compliqués, JMP to IP, IRET... 0:25:03.009,0:25:05.003 les non documentés 0:25:05.003,0:25:10.004 les spécifiques aux processeurs, comme MOVBE, POPCNT, CRC32 0:25:10.004,0:25:17.008 les détections d'OS et VM 0:25:17.008,0:25:25.004 comme le fameux 'red pill'... juste une instruction SLDT, on compare le résultat, 0:25:25.004,0:25:29.001 et on baptise ça 'red pill'... sans commentaire... 0:25:29.001,0:25:32.009 et aussi, des bogues des SE, parce que Windows XP 0:25:32.009,0:25:35.005 se trompe en essayant de vous dire 0:25:35.005,0:25:38.006 quelle exception vient de se produire, 0:25:38.006,0:25:44.007 ce qui permettrait de différencier un SE réel d'un émulateur. 0:25:44.007,0:25:50.002 CoST est écrit en assembleur, donc rien de superflu 0:25:50.002,0:25:52.007 pas compilé, ni généré 0:25:52.007,0:25:56.007 mais pour le documenter un peu plus, j'ai ajouté des exports internes 0:25:56.007,0:26:00.000 donc on peut aller facilement d'une section à l'autre 0:26:00.000,0:26:05.008 donc on se retrouve facilement à la partie qui nous intéresse 0:26:05.008,0:26:08.003 via les exports, 0:26:08.003,0:26:13.007 et je voulais pouvoir afficher un message de manière pratique 0:26:13.007,0:26:18.005 sans que ça allonge trop le listing 0:26:18.005,0:26:21.009 je veux dire, devoir faire défiler l'écran parce qu'il est couvert d'appel à printf 0:26:21.009,0:26:25.007 donc j'au utilisé un Vectored Exception Handler, et une instruction-marqueur 0:26:25.007,0:26:28.005 donc plein de commentaires sont affichés, 0:26:28.005,0:26:30.003 directement dans le code 0:26:30.003,0:26:34.008 donc ça fait un code binaire documenté sans fichier de symboles de débogage 0:26:34.008,0:26:38.009 et vous avez vu, il n'y a pas beaucoup d'affichage 0:26:38.009,0:26:41.009 mais en fait, il y a beaucoup plus d'affichage de déboguage 0:26:41.009,0:26:46.008 une centaine au moins, qui indiquent même ce qui va se produire, etc 0:26:46.008,0:26:49.006 donc on est pas pris au dépourvu 0:26:49.006,0:26:57.007 on est guidé lors de l'analyse 0:26:57.007,0:27:00.002 quelqu'un comprend de quoi il s'agit? 0:27:00.002,0:27:02.008 c'est un de mes préférés 0:27:02.008,0:27:06.001 on ne peut pas voir les opcodes 0:27:06.001,0:27:17.006 ah, il n'y a pas d'astuce à ce niveau là cette fois-ci ;) 0:27:17.006,0:27:19.006 donc, on empile des valeurs 0:27:19.006,0:27:21.000 on saute ici 0:27:21.000,0:27:26.001 et avec le RETF, j'ai empilé l'adresse de 'push_eip' 0:27:26.001,0:27:28.005 et un mot, 0x33 0:27:28.005,0:27:31.000 donc on va revenir de loin ici 0:27:31.000,0:27:35.006 donc on retourne à cette adresse avec un sélecteur 33 0:27:35.006,0:27:39.001 qui est réservé au mode 64b, même pour un programme en 32b 0:27:39.001,0:27:42.007 donc on va revenir ici, en mode 64b 0:27:42.007,0:27:47.007 car 33 est le sélecteur pour le mode 64b 0:27:47.007,0:27:49.008 qu'on peut atteindre depuis un programme 32b 0:27:49.008,0:27:56.003 donc le code sera d'abord exécuté en mode 32b, avec le sélecteur standard, 0:27:56.003,0:28:01.009 puis à nouveau, avec le sélecteur 33 0:28:01.009,0:28:04.003 en mode 64b 0:28:04.003,0:28:08.003 donc on a la même adresse, les mêmes opcodes, 0:28:08.003,0:28:10.001 mais le désassemblage sera différent 0:28:10.001,0:28:14.002 et j'ai choisi des opcodes qui génèrent des instructions 0:28:14.002,0:28:18.001 spécifique à chaque mode 0:28:18.001,0:28:22.009 donc, c'est déjà une belle s*loperie à désassembler, 0:28:22.009,0:28:27.009 car avec la même EIP, si on ne fait pas attention au sélecteur, 0:28:27.009,0:28:29.001 on est bloqué 0:28:29.001,0:28:46.006 On peut déboguer un tel code - voir ma présentation à BerlinSides, transparent de démonstration 58 0:28:46.006,0:28:50.006 Si on l'exécute en passant par dessus, on retourne au sélecteur d'origine 0:28:50.006,0:28:52.005 qui était sauvé par le PUSH CS 0:28:52.005,0:28:56.002 donc on retourne à avec le sélecteur initial 0:28:56.002,0:28:58.007 l'exécution est rapide, 0:28:58.007,0:29:00.007 mais difficile à déboguer (uniquement avec WinDbg+wow64exts) 0:29:00.007,0:29:03.007 ça rend inutile les désassembleurs, et la plupart des débogueurs 0:29:03.007,0:29:04.009 pourtant, c'est si simple. 0:29:04.009,0:29:07.003 Voilà ce que donne CoST 0:29:07.003,0:29:10.006 sous la dernière version de Hiew 0:29:10.006,0:29:13.003 je pense que ce sera bientôt corrigé 0:29:13.003,0:29:16.007 c'est un HINT NOP non documenté par Intel 0:29:16.007,0:29:21.000 et oublié par la plupart des désassembleurs 0:29:21.000,0:29:24.005 donc WinDbg et Hiew 0:29:24.005,0:29:29.007 vous donnent des points d'interrogations 0:29:29.007,0:29:34.006 au début, je pensais m'arrêter là pour Hashdays 0:29:34.006,0:29:39.006 mais j'ai décidé de rajouter quelques astuces PE à CoST 0:29:39.006,0:29:43.002 donc, en voici l'en-tête... MZ, puis du texte 0:29:43.002,0:29:44.004 donc on peut taper 'type cost.exe', comme ce bon vieux Budokan... 0:29:44.004,0:29:46.008 et ensuite, 0:29:46.008,0:29:51.007 l'en-tête 'NT headers' - appelé 'PE' car il commence par ces lettres-là, 0:29:51.007,0:29:54.007 et en fait à la fin du fichier 0:29:54.007,0:29:56.000 le 'pied-de-page PE' 0:29:56.000,0:29:59.003 et les valeurs de l'en-tête sont un peu extrême 0:29:59.003,0:30:01.003 donc, pour le moins inattendu 0:30:01.003,0:30:03.004 donc voici ce qu'IDA 6.1 en pensait 0:30:03.004,0:30:07.001 ...plantage directe... 0:30:07.001,0:30:11.002 ça lui apprendra à se fier aux valeurs 0:30:11.002,0:30:15.009 mais, aussi bien dans CoST, on peut changer un registre, faire une comparaison, tester, 0:30:15.009,0:30:17.000 et enchaîner ainsi plein de tests, 0:30:17.000,0:30:19.006 aussi bien, côté PE, on n'a qu'un seul binaire, donc 0:30:19.006,0:30:21.006 un seul essai 0:30:21.006,0:30:25.007 donc même si CoST n'a pas de section, des TLS bizarres,.... 0:30:25.007,0:30:27.007 il ne peut pas tout tester 0:30:27.007,0:30:31.001 donc, j'ai créé pour ça une autre page sur Corkami 0:30:31.001,0:30:37.002 avec comme d'habitudes, des exemples, des graphiques, 0:30:37.002,0:30:40.007 elle n'est pas finie, mais déjà largement suffisante pour tester ou faire planter 0:30:40.007,0:30:42.009 n'importe quel outil 0:30:42.009,0:30:46.003 j'ai déjà une centaine d'exemples, 0:30:46.003,0:30:51.006 qui mettent l'accent sur de nombreux aspects, avec parfois des résultats inattendus 0:30:51.006,0:30:55.001 donc, voici une table de section virtuelle, et Hiew 0:30:55.001,0:31:00.000 quand les alignements sont bas, on n'a pas besoin de section 0:31:00.000,0:31:03.002 ou la table peut être vide 0:31:03.002,0:31:08.003 donc, j'ai modifié SizeOfOptionalHeader pour qu'il pointe en espace mémoire virtuel 0:31:08.003,0:31:11.009 donc la table des sections est en dehors du PE, pleines de zéros 0:31:11.009,0:31:16.002 et Hiew n'aime pas ça. En conséquence, il ne pense même pas que c'est un PE 0:31:16.002,0:31:18.008 alors que ça marche parfaitement, du moins sous XP 0:31:18.008,0:31:27.002 car Windows 7 est plus capricieux concernant les valeurs de la table des section 0:31:27.002,0:31:29.005 ensuite... 0:31:29.005,0:31:34.002 si on fait de l'art dans les Data Directories 0:31:34.002,0:31:37.001 vous pouvez commencer à vous inquiéter 0:31:37.001,0:31:40.000 si vous avez un dessin plus joli, je suis preneur 0:31:40.000,0:31:43.003 donc, il s'agit du 'Dual PE header', présenté 0:31:43.003,0:31:46.001 par Reversing Labs à la BlackHat 0:31:46.001,0:31:50.003 quelqu'un connaît ? 0:31:50.003,0:31:52.005 donc, on augmente SizeOfHeader pour que 0:31:52.005,0:31:59.006 les en-têtes NT soient en fait assez loin, 0:31:59.006,0:32:04.000 pour qu'il soit aligné avec les sections 0:32:04.000,0:32:05.005 quand il se charge en mémoire 0:32:05.005,0:32:08.000 la première section sera chargée par dessus 0:32:08.000,0:32:13.005 la première partie du OPTIONAL_HEADER est lue dans le fichier 0:32:13.005,0:32:16.005 donc, prise en compte pour charger le fichier 0:32:16.005,0:32:20.009 mais les Data Directories sont lus en mémoire 0:32:20.009,0:32:25.000 donc, d'abord l'OPTIONAL_HEADER est analysé, chargé en mémoire, 0:32:25.000,0:32:29.003 puis la section est dépliée sur la partie basse de l'en-tête 0:32:29.003,0:32:31.008 et les vrais Data directories qui étaient initialement au début de la section 0:32:31.008,0:32:34.002 vont être pris en compte, 0:32:34.002,0:32:39.006 donc tout ceci est du pipeau présent dans le fichier, à la suite de SizeOfOptionalHeader 0:32:39.006,0:32:45.000 mais en mémoire, ce sera écrasé et ignoré 0:32:45.000,0:32:47.003 une autre bizarrerie est que les noms d'exports peuvent avoir n'importe quelle valeur, 0:32:47.003,0:32:51.000 jusqu'au caractère zéro 0:32:51.000,0:32:53.007 donc, absolument n'importe quoi, 0:32:53.007,0:32:56.001 et de plus, 0:32:56.001,0:32:57.005 Hiew les affichent directement 0:32:57.005,0:32:59.003 donc on peut insérer ses propres messages 0:32:59.003,0:33:02.005 ce sont juste des noms d'exports, d'ailleurs 0:33:02.005,0:33:05.008 l'un d'entre eux est excessivement long, 0:33:05.008,0:33:08.002 idéal pour tester les dépassement de tampon [buffer overflow] 0:33:08.002,0:33:10.005 dans votre outil favori 0:33:10.005,0:33:14.002 et il est également possible d'avoir un export avec un nom nul, 0:33:14.002,0:33:16.003 on peut donc importer l'api nulle 0:33:16.003,0:33:19.002 sans problème 0:33:19.002,0:33:23.000 j'ai aussi essayé les différentes possibilités, 0:33:23.000,0:33:26.004 avec des fichiers contenant un maximum de section, 0:33:26.004,0:33:31.006 la limite est 96 sous XP, et 64K sous Vista et Windows 7 0:33:31.006,0:33:33.000 ce qui donne 0:33:33.000,0:33:36.007 avec le dernier OllyDbg 2 ce message surprenant 0:33:36.007,0:33:38.002 mais le fichier charge quand même 0:33:38.002,0:33:41.003 OllyDbg 1, lui, plante directement 0:33:41.003,0:33:45.002 il reste du temps ? 0:33:45.002,0:33:48.005 un dernier... pas très visuel 0:33:48.005,0:33:52.006 l'adresse AddressOfIndex du TLS est mise à zéro au chargement 0:33:52.006,0:33:59.002 et le terminus [terminator] des imports n'a pas besoin d'être composé de 5 doubles mots nuls 0:33:59.002,0:34:03.000 mais juste d'un seul, pour son AddressOfName 0:34:03.000,0:34:05.009 pour être considéré comme le terminus 0:34:05.009,0:34:10.002 donc, si on fait pointer AddressOfIndex vers l'AddressOfName d'un descripteur d'imports 0:34:10.002,0:34:15.002 s'il est mis à zéro, 0:34:15.002,0:34:16.006 les imports seront tronqués 0:34:16.006,0:34:20.005 et en fait, le comportement est différent sous XP ou 7 0:34:20.005,0:34:25.008 donc, sous XP, il est écrasé après que les imports soient chargés, 0:34:25.008,0:34:28.002 donc la table n'est pas tronquée 0:34:28.002,0:34:32.003 alors que sous 7, il est écrasé avant les imports 0:34:32.003,0:34:35.003 donc, pour le même PE, on a 2 comportements différents 0:34:35.003,0:34:37.001 sous deux versions de Windows différentes, 0:34:37.001,0:34:43.004 alors que le fichier marche sous les 2 versions. 0:34:43.004,0:34:55.004 ah, attendez, on a encore le temps? 0:34:55.004,0:34:56.005 15 minutes ? ok 0:34:56.005,0:35:01.000 je vais commencer la démonstration 0:35:01.000,0:35:23.008 pour vous montrer... 0:35:23.008,0:35:26.000 le style de PE que je créé d'habitude 0:35:26.000,0:35:29.001 avec le minimum d'éléments définis 0:35:29.001,0:35:31.001 c'est en fait un pilotes [driver] 0:35:31.001,0:35:36.008 même si j'ai utilisé des opcodes non documentés, 0:35:36.008,0:35:40.008 ce pilote marche, sans le vrac 0:35:40.008,0:35:43.002 habituel rajouté par le compilateurs 0:35:43.002,0:35:47.009 donc, un exemple clair, simple 0:35:47.009,0:35:51.004 sans rien pour vous géner la vue 0:35:51.004,0:35:52.008 ou votre débogueur 0:35:52.008,0:36:02.006 donc, cet exemple regarde les valeurs de CR0 0:36:02.006,0:36:07.005 via SMSW, officiellement non défini sur un double mot 0:36:07.005,0:36:10.000 mais en fait donne la même valeur 0:36:10.000,0:36:11.007 que le MOV EAX, CR0 standard 0:36:11.007,0:36:16.005 ensuite, MOV EAX, CR0 avec un 'mauvais' Mod/RM 0:36:16.005,0:36:39.002 sous le dernier Hiew, ce n'est en fait même pas désassemblé 0:36:39.002,0:36:43.007 on espère que ça ne plante pas... 0:36:43.007,0:36:47.003 donc, vous voyez, on obtient les mêmes valeurs 0:36:47.003,0:36:55.006 via le CR0 standard, l'invalide, et le non défini 0:36:55.006,0:36:57.005 dont la partie de poids fort est non définie 0:36:57.005,0:37:00.007 d'habitude, en langage Intel, non défini signifie 'mis à zéro', 0:37:00.007,0:37:02.002 mais ici, on a bien CR0 entier 0:37:02.002,0:37:03.006 et ma machine n'a même pas plantée 0:37:03.006,0:37:05.009 ce qui signifie que le pilote fonctionne correctement 0:37:05.009,0:37:08.004 donc vous pouvez étudier des petits pilotes 0:37:08.004,0:37:12.004 le premier exemple présenté aujourd'hui 0:37:12.004,0:37:15.007 était celui avec l'assembleur ancien 0:37:15.007,0:37:20.002 quelqu'un connaît le résultat final ? 0:37:20.002,0:37:23.007 certaines instructions sont inutiles, 0:37:23.007,0:37:28.002 juste pour vérifier que le processeur les gère 0:37:28.002,0:37:30.008 mais d'autres modifient les registres 0:37:30.008,0:37:37.007 et ces instructions des années 70-80 0:37:37.007,0:37:43.008 sont toujours gérées par les processeurs modernes 0:37:43.008,0:37:47.007 un des exemples que j'ai crée teste 0:37:47.007,0:37:50.004 les valeurs initiales de chaque registre 0:37:50.004,0:37:56.001 donc on peut voir les valeurs possibles sous XP ou W7 0:37:56.001,0:38:01.008 à chaque fois [TLS, EntryPoint, DllMain], je sauve tous les registres 0:38:01.008,0:38:04.000 et je compare à diverses valeurs possibles 0:38:04.000,0:38:06.002 successivement 0:38:06.002,0:38:10.007 en fait, au TLS, on a beaucoup de contrôles de ces valeurs, 0:38:10.007,0:38:16.007 car ces valeurs proviennent du Data Directory 0:38:16.007,0:38:20.002 en particulier, son adresse relative, sa taille, les callbacks... 0:38:20.002,0:38:26.007 pour plus de détail, voir le source... 0:38:26.007,0:38:33.006 ça vous permet d'imiter mieux un SE dans votre émulateur, 0:38:33.006,0:38:35.005 si ça vous intéresse 0:38:35.005,0:38:41.006 on utilise SMSW, on compare la valeur 0:38:41.006,0:38:46.004 ensuite, après une opération FPU, on regarde si la valeur a changé 0:38:46.004,0:38:48.007 et si elle revient à sa valeur initiale. 0:38:48.007,0:38:52.005 une autre bizarrerie, si quelqu'un a l'explication 0:38:52.005,0:38:54.007 est qu'en fait 0:38:54.007,0:39:01.001 ça se comporte différemment si on exécute le fichier normalement 0:39:01.001,0:39:04.006 ou avec une redirection 0:39:04.006,0:39:08.004 si on redirige, 'échec' 0:39:08.004,0:39:11.005 sinon, ça marche normalement. 0:39:11.005,0:39:22.002 pour vous montrer... on exécute, et on lance TYPE 0:39:22.002,0:39:24.007 normal : OK 0:39:24.007,0:39:26.005 redirection: ECHEC 0:39:26.005,0:39:30.006 si vous avez une explication, je suis preneur 0:39:30.006,0:39:37.008 tu as essayé de rediriger vers autre chose ? 0:39:37.008,0:39:42.000 non, je n'ai pas essayé 0:39:42.000,0:39:45.002 donc, rediriger vers un autre périphérique? 0:39:45.002,0:39:46.007 mais, comment on récupère le résultat ? 0:39:46.007,0:39:48.001 imprimante ? 0:39:48.001,0:39:54.002 je n'ai pas de périphérique COM 0:39:54.002,0:39:56.007 non, je ne sais pas 0:39:56.007,0:39:59.009 mais c'était surprenant, car je lançais tous mes tests... 0:39:59.009,0:40:02.003 et d'un coup, 'ECHEC'... 0:40:02.003,0:40:07.002 alors qu'à la main, aucun problème. 0:40:07.002,0:40:09.007 l'astuce avec GS 0:40:09.007,0:40:11.002 très simple 0:40:11.002,0:40:19.006 et quelques affichages 0:40:19.006,0:40:21.008 je modifie GS, qui se remet à zéro 0:40:21.008,0:40:23.006 puis j'attends le résultat, 0:40:23.006,0:40:26.005 ensuite je fais 2 tests et je compare le temps entre 0:40:26.005,0:40:30.000 car ça ne doit pas arriver trop vite 0:40:30.000,0:40:37.002 NOPs 0:40:37.002,0:40:39.005 je teste les NOPs non documentés 0:40:39.005,0:40:45.006 celui sur une page invalide 0:40:45.006,0:41:01.000 NOP standard 0:41:01.000,0:41:07.005 32 bits 0:41:07.005,0:41:15.007 tous mes tests 64b sont fait dans des programmes 32b, car on peut les exécuter sur un OS normal 0:41:15.007,0:41:19.003 et ensuite je regarde GS pour voir si le mode 64b est disponible 0:41:19.003,0:41:21.006 dans ce cas, on obtiendrait un résultat différent 0:41:21.006,0:41:26.005 donc, en 64b, que je n'ai aps ici, on obtiendrait 0:41:26.005,0:41:28.006 les tests en 64b 0:41:28.006,0:41:31.000 et ces results. 0:41:31.000,0:41:35.001 mais, pas si facile à déboguer 0:41:35.001,0:41:39.004 mais ici, pas de piège, donc on peut revenir facilement en 32b 0:41:39.004,0:41:45.000 on saute le code 64b et revient en 32b 0:41:45.000,0:41:48.004 PUSH/RET 0:41:48.004,0:41:52.002 on affiche le message et ensuite... 0:41:52.002,0:41:58.000 Olly vous dit qu'on va sauter vers [4010]08 0:41:58.000,0:42:03.007 mais en fait - ici, c'est correct 0:42:03.007,0:42:05.009 et le TLS a alloué la page NULLE 0:42:05.009,0:42:09.005 qui affiche 'ECHEC' 0:42:09.005,0:42:15.003 donc, comme mentionné auparavant, pas de façon standard de désassembler ça correctement 0:42:15.003,0:42:23.006 je ne peux pas exécuter les 64K sections 0:42:23.006,0:42:27.007 et en fait, cet exemple exécute tout le code (l'espace virtuel complet des 65535 sections) 0:42:27.007,0:42:29.002 elles sont grosses, 0:42:29.002,0:42:33.002 et je modifie EAX pour que tous les 00 00 soient exécutés 0:42:33.002,0:42:35.007 juste pour faire un printf à la fin 0:42:35.007,0:42:39.000 ça prend plusieurs secondes sur un i7 0:42:39.000,0:42:43.000 c'est assez amusant: on le lance, et même avec le cache, 0:42:43.000,0:42:50.009 et que le SE n'est pas occupé, ça prend un temps visible, juste pour un tas de 00 0:42:50.009,0:43:00.005 les sections virtuelles... celui que le dernier Hiew ne voit pas comme un PE 0:43:00.005,0:43:02.003 enfin, bientôt corrigé 0:43:02.003,0:43:08.006 ah, je ne peux pas l'analyser car il ne pense même pas que c'est un PE 0:43:08.006,0:43:13.001 mais, pour simplifier, OPTIONAL_HEADER pointe au delà 0:43:13.001,0:43:14.004 du fichier 0:43:14.004,0:43:17.000 l'en-tête plié... 0:43:17.000,0:43:18.006 quelques messages d'erreurs, 0:43:18.006,0:43:21.000 à cause des faux Data Directories 0:43:21.000,0:43:30.002 et les DD réels sont au début 0:43:30.002,0:43:33.001 de la première section 0:43:33.001,0:43:42.004 ceci deviendra les imports, et le vrai Data Directory 0:43:42.004,0:43:49.002 et pour finir, celui avec TLS AddressOfIndex qui pointe... 0:43:49.002,0:44:02.003 ...dans les descripteurs d'imports, sur AddressOfName 0:44:02.003,0:44:04.003 donc, il sera écrasé au chargement 0:44:04.003,0:44:11.009 et quand on le charge, il reconnait XP 0:44:11.009,0:44:14.007 à la façon dont les imports ont été chargés 0:44:14.007,0:44:17.001 et sous 7, on obtiendra un autre résultat. 0:44:17.001,0:44:19.005 pour finir, les exports 0:44:19.005,0:44:24.005 certains ont des noms très longs 0:44:24.005,0:44:30.005 en fait, on remarque que j'écrase le désassemblage même 0:44:30.005,0:44:33.009 donc je répète les faux opcodes et adresses 0:44:33.009,0:44:37.005 donc le désassembleur est perturbé 0:44:37.005,0:44:40.005 mais c'est juste visuel, pas vraiment grave 0:44:40.005,0:44:43.001 bien que ce soit un problème récent dans IDA 0:44:43.001,0:44:47.000 ou si on met un export au milieu d'une instruction 0:44:47.000,0:44:49.007 l'export aura priorité sur le désassemblage, 0:44:49.007,0:44:52.001 et casse l'instruction en deux 0:44:52.001,0:44:58.005 il y a bien sûr un exemple pour ça sur Corkami 0:44:58.005,0:45:05.001 donc, voilà pour les démonstrations 0:45:05.001,0:45:10.001 Je voulais donc en savoir plus sur le x86 et le PE 0:45:10.001,0:45:12.006 qui sont loin d'être correctement documentés 0:45:12.006,0:45:14.007 et qui ne le sont toujours pas, 0:45:14.007,0:45:18.004 mais j'en ai couvert un peu 0:45:18.004,0:45:20.004 il y a encore des flous 0:45:20.004,0:45:24.000 mais de moins en moins, j'y travaille 0:45:24.000,0:45:27.005 en publiant mes recherches librement 0:45:27.005,0:45:31.007 tel WinDbg, si vous suivez les documentations officielles à la lettre, 0:45:31.007,0:45:36.001 vous êtes voués à l'échec, surtout avec tous les virus et packeurs existants 0:45:36.001,0:45:40.006 si vous êtes intéressés, ou que vous programmez un outil, un émulateur, un moteur... 0:45:40.006,0:45:44.005 vous savez que vous pouvez aller sur Corkami, lire les pages 0:45:44.005,0:45:48.002 télécharger les exemples, qui sont disponibles librement, à tout point de vue 0:45:48.002,0:45:50.007 et si vous trouvez des bugs, ce qui pourrait arriver 0:45:50.007,0:45:57.000 envoyez-moi une carte postale, ou un t-shirt croix rouge ;) 0:45:57.000,0:46:01.007 Merci à Peter Ferrie, et tous mes relecteurs et contributeurs 0:46:01.007,0:46:03.006 vous avez des questions ? 0:46:03.006,0:46:10.008 tu les as testés sur des anti-virus ? tu devrais trouver une ch*ée de 0days 0:46:10.008,0:46:23.009 mouai, non, je ne saurais pas en faire des exploits... 0:46:23.009,0:46:29.000 tenir en échec les désassembleurs me suffit 0:46:29.000,0:46:40.002 j'ai trouvé un crash dans Xed d'Intel, ça me suffit 0:46:40.002,0:46:45.000 une autre question ? tout le monde a survécu ? 0:46:45.000,0:46:46.005 c'était une super présentation, mec 0:46:46.005,0:46:48.002 merci! 0:46:48.002,0:46:50.007 MERCI!