Chaque exemple de la liste ci-dessous aborde une fonction speécifique de la bibliothèque. Je vous propose donc ici de voir dans un premier temps l'utilisation la plus simple qui soit de la lib puis je montre comment faire intervenir les options proposées afin de répondre à des questions spécifiques. Vous pouvez toujours télécharger ces exemples ICI
BeaEngine ne nécessite aucune initialisation. La fonction Disasm se charge de tout cela pour vous. La seule chose que vous devez faire est de mettre à zéro toute la structure MyDisasm que vous passez en paramètre. Le seul champ à renseigner obligatoirement est le champ MyDisasm.EIP.
Ce petit programme désassemble 100 lignes de son propre code à partir de l'adresse virtuelle 0x401000.
#include <windows.h> #include <stdio.h> #include "BeaEngine.h" int main(void) { /* ============================= Init datas */ DISASM MyDisasm; int false = 0, true = 1; int len, i = 0; _Bool Error = false; /* ============================= Init the Disasm structure (important !)*/ (void) memset (&MyDisasm, 0, sizeof(DISASM)); /* ============================= Init EIP */ MyDisasm.EIP = 0x401000; /* ============================= Loop for Disasm */ while ((!Error) && (i<100)){ len = Disasm(&MyDisasm); if (len != UNKNOWN_OPCODE) { (void) puts(MyDisasm.CompleteInstr); MyDisasm.EIP = MyDisasm.EIP + len; i++; } else { Error = true; } }; return 0; }
Il est possible de demander à BeaEngine de ne pas désassembler le code au delà d'une certaine limite. Voici par exemple un programme qui ne va désassembler que les instructions situées entre les adresses 0x401000 et 0x401020 (valeurs choisies arbitrairement ici). Ceci signifie que BeaEngine ne lira aucun octet au delà de 0x401020 même s'il est en cours de décodage d'une instruction. Pour réaliser cette restriction, BeaEngine utilise le champ MyDisasm.SecurityBlock qui contient le nombres de bytes lisibles durant le décodage. Par défaut, une instruction intel ne peut excéder 15 bytes. De ce fait, seuls les SecurityBlocks de moins de 15 bytes seront pris en compte (BeaEngine se limite déjà automatiquement à la valeur des 15 bytes).
#include <windows.h> #include <stdio.h> #include "BeaEngine.h" int main(void) { /* ============================= Init datas */ DISASM MyDisasm; int false = 0, true = 1; int len; _Bool Error = false; int EndCodeSection = 0x401020; /* ============================= Init the Disasm structure (important !)*/ (void) memset (&MyDisasm, 0, sizeof(DISASM)); /* ============================= Init EIP */ MyDisasm.EIP = 0x401000; /* ============================= Loop for Disasm */ while (!Error){ /* ============================= Fix SecurityBlock */ MyDisasm.SecurityBlock = EndCodeSection - MyDisasm.EIP; len = Disasm(&MyDisasm); if (len == OUT_OF_BLOCK) { (void) printf("disasm engine is not allowed to read more memory \n"); Error = true; } else if (len == UNKNOWN_OPCODE) { (void) printf("unknown opcode"); Error = true; } else { (void) puts(MyDisasm.CompleteInstr); MyDisasm.EIP = MyDisasm.EIP + len; if (MyDisasm.EIP >= EndCodeSection) { (void) printf("End of buffer reached ! \n"); Error = true; } } }; return 0; }
Cette fois-ci, nous sommes en situation réelle. Vous voulez désassembler une portion de code que vous avez copié au préalable dans une zone allouée. Cependant, vous désirez voir un désassemblage avec les adresses virtuelles d'origine. En termes plus clairs, imaginons que vous ayez copié 100 bytes d'un binaire situés à l'adresse &main dans une zone que vous avez alloué préalablement (malloc), voici ce que vous devez faire pour réaliser le désassemblage :
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include "BeaEngine.h" /* ============================= Init datas */ DISASM MyDisasm; int len; _Bool Error = 0; void *pBuffer; int (*pSourceCode) (void); /* function pointer */ /* ================================================================================= */ /* */ /* Disassemble code in the specified buffer using the correct VA */ /* */ /*==================================================================================*/ void DisassembleCode(char *StartCodeSection, char *EndCodeSection, int (*Virtual_Address)(void)) { /* ============================= Init the Disasm structure (important !)*/ (void) memset (&MyDisasm, 0, sizeof(DISASM)); /* ============================= Init EIP */ MyDisasm.EIP = (int) StartCodeSection; /* ============================= Init VirtualAddr */ MyDisasm.VirtualAddr = (long long) Virtual_Address; /* ============================= set IA-32 architecture */ MyDisasm.Archi = 0; /* ============================= Loop for Disasm */ while ( !Error){ /* ============================= Fix SecurityBlock */ MyDisasm.SecurityBlock = (int) EndCodeSection - MyDisasm.EIP; len = Disasm(&MyDisasm); if (len == OUT_OF_BLOCK) { (void) printf("disasm engine is not allowed to read more memory \n"); Error = 1; } else if (len == UNKNOWN_OPCODE) { (void) printf("unknown opcode"); Error = 1; } else { (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr); MyDisasm.EIP = MyDisasm.EIP + len; MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + len; if (MyDisasm.EIP >= (int) EndCodeSection) { (void) printf("End of buffer reached ! \n"); Error = 1; } } }; return; } /* ================================================================================= */ /* */ /* MAIN */ /* */ /*==================================================================================*/ int main(void) { pSourceCode = &main; pBuffer = malloc(100); /* ============================= Let's NOP the buffer */ (void) memset (pBuffer, 0x90, 100); /* ============================= Copy 100 bytes in it */ (void) memcpy (pBuffer,(void*)(int) pSourceCode, 100); /* ============================= Disassemble code located in that buffer */ DisassembleCode (pBuffer, (char*) pBuffer + 100, pSourceCode); return 0; }
BeaEngine met à disposition plusieurs syntaxes : masm, nasm, GoAsm, GNU Assembler. Elle permet également d'afficher les nombres aux formats préfixés ou suffixés et laisse le choix d'afficher ou non les registres de segments utilisés dans les adressages mémoires. Pour plus de clareté, vous pouvez également demander une tabulation entre le mnémonic et les opérandes.
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include "BeaEngine.h" /* ============================= Init datas */ DISASM MyDisasm; int len; _Bool Error = 0; void *pBuffer; int (*pSourceCode) (void); /* function pointer */ /* DisassembleCode function is documented in previous examples */ int main(void) { /* ============================= Init the Disasm structure (important !)*/ (void) memset (&MyDisasm, 0, sizeof(DISASM)); pSourceCode = &main; pBuffer = malloc(100); /* ============================= Let's NOP the buffer */ (void) memset (pBuffer, 0x90, 100); /* ============================= Copy 100 bytes in it */ (void) memcpy (pBuffer,(void*)(int) pSourceCode, 100); /* ============================= Select Display Option */ MyDisasm.Options = Tabulation + NasmSyntax + PrefixedNumeral + ShowSegmentRegs; /* ============================= Disassemble code located in that buffer */ DisassembleCode (pBuffer, (char*) pBuffer + 100, pSourceCode); return 0; }
L'usage de BeaEngine sous Python se fait par l'intermédiaire de la librairie ctypes. L'exemple présenté ici permet de désassembler un binaire chargé statiquement en mémoire. On suppose ici que la première section a une RawOffset de 0x200
from BeaEnginePython import * Instruction = DISASM() # ====================================== Open File2Disasm.exe try: FileObject = open('File2Disasm.exe','rb') except IOError: print "can't find specified file" else: FileObject.seek(0,0) Buffer= FileObject.read() FileObject.close() # ====================================== Create a ctypes buffer Target = create_string_buffer(Buffer,len(Buffer)) # ====================================== init structure Instruction.EIP = addressof(Target) + 0x200 # Jump on the ".text" section with RawOffset = 0x200 Instruction.VirtualAddr = 0x401000 Instruction.Options = Tabulation + NasmSyntax + SuffixedNumeral + ShowSegmentRegs #define syntax # ====================================== Disasm 20 instructions for i in range(20): InstrLength = Disasm(addressof(Instruction)) print hex(Instruction.VirtualAddr)," ",Instruction.CompleteInstr if InstrLength == -1: Instruction.EIP = Instruction.EIP + 1 Instruction.VirtualAddr = Instruction.VirtualAddr + 1 else: Instruction.EIP = Instruction.EIP + InstrLength Instruction.VirtualAddr= Instruction.VirtualAddr+ InstrLength
Voici le premier exemple d'utilisation de BeaEngine pour réaliser une analyse de data-flow. Pour cela, on utilise les champs relatifs aux Arguments (opérandes) de l'instruction. L'utilisation conjointe de MyDisasm.Argument1.AccessMode et MyDisasm.Argument1.ArgType permet de déterminer par exemple si le registre eax est modifié. AccessMode permet de savoir si l'argument est lu ou modifié. ArgType permet de savoir si l'argument est bel et bien eax. On n'oubliera pas que certaines instructions modifient parfois des registres de façon implicite. Le champ MyDisasm.Instruction.ImplicitModifiedRegs permet de détecter ces instructions.
#include <windows.h> #include <stdlib.h> #include <stdio.h> #include "BeaEngine.h" /* ============================= Init datas */ DISASM MyDisasm; int len; _Bool Error = 0; void *pBuffer; int (*pSourceCode) (void); /* function pointer */ /* ================================================================================= */ /* */ /* Disassemble code in the specified buffer using the correct VA */ /* */ /*==================================================================================*/ void DisassembleCode(char *StartCodeSection, char *EndCodeSection, int (*Virtual_Address)(void)) { Error = 0; /* ============================= Init EIP */ MyDisasm.EIP = (int) StartCodeSection; /* ============================= Init VirtualAddr */ MyDisasm.VirtualAddr = (long long) Virtual_Address; /* ============================= set IA-32 architecture */ MyDisasm.Archi = 0; /* ============================= Loop for Disasm */ while ( !Error){ /* ============================= Fix SecurityBlock */ MyDisasm.SecurityBlock = (long) EndCodeSection - MyDisasm.EIP; len = Disasm(&MyDisasm); if (len == OUT_OF_BLOCK) { (void) printf("disasm engine is not allowed to read more memory \n"); Error = 1; } else if (len == UNKNOWN_OPCODE) { (void) printf("unknown opcode"); Error = 1; } else { /* ============================= Make a filter on Instruction */ if ((MyDisasm.Argument1.AccessMode == WRITE) && (MyDisasm.Argument1.ArgType & GENERAL_REG) && (MyDisasm.Argument1.ArgType & REG0)) { (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr); } else if ((MyDisasm.Argument2.AccessMode == WRITE) && (MyDisasm.Argument2.ArgType & GENERAL_REG) && (MyDisasm.Argument2.ArgType & REG0)) { (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr); } else if (MyDisasm.Instruction.ImplicitModifiedRegs & REG0) { (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr); } MyDisasm.EIP = MyDisasm.EIP + len; MyDisasm.VirtualAddr = MyDisasm.VirtualAddr + len; if (MyDisasm.EIP >= (long) EndCodeSection) { (void) printf("End of buffer reached ! \n"); Error = 1; } } }; return; } /* ================================================================================= */ /* */ /* MAIN */ /* */ /*==================================================================================*/ int main(void) { /* ============================= Init the Disasm structure (important !)*/ (void) memset (&MyDisasm, 0, sizeof(DISASM)); pSourceCode = &main; pBuffer = malloc(0x600); /* ============================= Let's NOP the buffer */ (void) memset (pBuffer, 0x90, 0x600); /* ============================= Copy 100 bytes in it */ (void) memcpy (pBuffer,(void*)(int) pSourceCode, 0x600); (void) printf("******************************************************* \n"); (void) printf("Display only Instructions modifying EAX. \n"); (void) printf("******************************************************* \n"); /* ============================= Select Display Option */ MyDisasm.Options = Tabulation + MasmSyntax; /* ============================= Disassemble code located in that buffer */ DisassembleCode (pBuffer, (char*) pBuffer + 0x600, pSourceCode); return 0; }
Dans certains cas, les sauts inconditionnels sont utilisés comme éléments d'obfuscation. L'exemple proposé ici montre comment supprimer les sauts inconditionnels et surtout comment les suivre (le fichier cible msgbox.exe est récupérable dans l'archive des exemples). Pour cela, on utilise les champs MyDisasm.Instruction.BranchType et MyDisasm.Instruction.AddrValue pour repérer les instructions de branche qui pointent vers des adresses identifiables. J'ai codé la routine RVA2OFFSET juste pour convertir l'adresse virtuelle pointée par le saut inconditionnel en adresse "réelle" utilisable par le champ MyDisasm.EIP.
#include <windows.h> #include <stdlib.h> #include <stdio.h> #include "BeaEngine.h" /* ============================= Init datas */ DISASM MyDisasm; int len,i,FileSize; _Bool Error = 0; unsigned char *pBuffer; int (*pSourceCode) (void); /* function pointer */ FILE *FileHandle; int RVA2OFFSET(int Address, unsigned char *pBuff); /* =================================================================================*/ /* */ /* eliminate JUMPS and reorder instructions */ /* */ /*==================================================================================*/ void DisassembleCodeFilter(unsigned char *StartCodeSection, unsigned char *EndCodeSection, int (Virtual_Address)) { Error = 0; MyDisasm.EIP = (int) StartCodeSection; MyDisasm.VirtualAddr = (long long) Virtual_Address; MyDisasm.Archi = 0; /* ============================= Loop for Disasm */ while (!Error){ MyDisasm.SecurityBlock = (int) EndCodeSection - MyDisasm.EIP; len = Disasm(&MyDisasm); if ((len != OUT_OF_BLOCK) && (len != UNKNOWN_OPCODE)) { if ((MyDisasm.Instruction.BranchType == JmpType) && (MyDisasm.Instruction.AddrValue != 0)) { MyDisasm.EIP = RVA2OFFSET((int) MyDisasm.Instruction.AddrValue - 0x400000,pBuffer); MyDisasm.VirtualAddr = MyDisasm.Instruction.AddrValue; } else { (void) printf("%.8X %s\n",(int) MyDisasm.VirtualAddr, &MyDisasm.CompleteInstr); MyDisasm.EIP = MyDisasm.EIP+len; MyDisasm.VirtualAddr = MyDisasm.VirtualAddr+len; } if (MyDisasm.EIP >= (long) EndCodeSection) { Error = 1; } } else { Error = 1; } } return; } /* =================================================================================*/ /* */ /* Convert Relative Virtual Address to offset in the file */ /* works fine even in naughty binaries */ /* BeatriX manufacture :) */ /* */ /*==================================================================================*/ int RVA2OFFSET(int RVA, unsigned char *pBuff) { int RawSize, VirtualBorneInf, RawBorneInf, SectionHeader; int OffsetNtHeaders,OffsetSectionHeaders, NumberOfSections, SizeOfOptionalHeaders, VirtualAddress; OffsetNtHeaders = (int) *((int*) (pBuff + 0x3c)); NumberOfSections = (int) *((unsigned short*) (pBuff + OffsetNtHeaders + 6)); SizeOfOptionalHeaders = (int) *((unsigned short*) (pBuff + OffsetNtHeaders + 0x14)); OffsetSectionHeaders = OffsetNtHeaders + SizeOfOptionalHeaders + 0x18; VirtualBorneInf = 0; RawBorneInf = 0; VirtualAddress = 0; SectionHeader = 0; while (VirtualAddress <= RVA) { if (VirtualAddress != 0) { VirtualBorneInf = VirtualAddress; RawSize = (int) *((unsigned int*) (pBuff + OffsetSectionHeaders + 0x10)); RawBorneInf = (int) *((unsigned int*) (pBuff + OffsetSectionHeaders + 0x14)); } VirtualAddress = (int) *((unsigned int*) (pBuff + OffsetSectionHeaders + SectionHeader*0x28 + 0x0C)); SectionHeader ++; } if ((RVA-VirtualBorneInf)>RawSize) return -1; RawBorneInf = RawBorneInf >> 8; if (RawBorneInf & 1) RawBorneInf--; RawBorneInf = RawBorneInf << 8; return RVA - VirtualBorneInf + RawBorneInf + (int) pBuff; } /* =================================================================================*/ /* */ /* MAIN */ /* */ /*==================================================================================*/ int main(void) { FileHandle = fopen("msgbox.exe", "rb"); (void)fseek(FileHandle,0,SEEK_END); FileSize = ftell(FileHandle); (void)rewind(FileHandle); pBuffer = malloc(FileSize); (void)fread(pBuffer,1,FileSize, FileHandle); (void)fclose(FileHandle); /* ============================= Init the Disasm structure (important !)*/ (void) memset (&MyDisasm, 0, sizeof(DISASM)); (void) printf("******************************************************* \n"); (void) printf("Disassemble code by following jumps\n"); (void) printf("******************************************************* \n"); DisassembleCodeFilter ((unsigned char*) pBuffer + 0x400, (unsigned char*) pBuffer + 0x430, 0x401000); return 0; }
BeaEngine est proposé en téléchargement sous deux versions : la version pour windows 32 bits et la version pour windows 64 bits. Indépendamment de cela, ces deux versions sont capables de désassembler du code 32 bits et du code 64 bits.
/* =================== Define 64 bits architecture =================== */ MyDisasm.Archi = 64;
BeaEngine est fourni avec les headers pour nasm, GoAsm, fasm et masm32. Pour faire gagner du temps aux codeurs, je propose quelques exemples simples d'utilisation.
Utiliser BeaEngine avec masm32
.386 .MODEL flat,stdcall option casemap:none .mmx include \masm32\include\kernel32.inc include \masm32\include\windows.inc includelib \masm32\lib\kernel32.lib include BeaEngineMasm.inc puts PROTO:DWORD .data MyDisasm _Disasm <> szoutofblock BYTE "Security alert. Disasm tries to read unreadable memory",0 i DWORD 100 .code start: ; *********************** Init EIP mov eax, start mov MyDisasm.EIP, eax ; *********************** Just for fun : init VirtualAddr with funky value :) mov eax, 0bea2008h movd mm0, eax movq MyDisasm.VirtualAddr, mm0 ; *********************** loop for disasm MakeDisasm: push offset MyDisasm call Disasm .if (eax == OUT_OF_BLOCK) push offset szoutofblock call puts add esp, 4 push 0 call ExitProcess .elseif (eax == UNKNOWN_OPCODE) push offset MyDisasm.CompleteInstr call puts add esp, 4 push 0 call ExitProcess .endif add MyDisasm.EIP, eax push offset MyDisasm.CompleteInstr call puts add esp, 4 dec i jne MakeDisasm push 0 call ExitProcess End start
Utiliser BeaEngine avec nasm
extern _puts@4 ; define external symbols extern _ExitProcess@4 extern _Disasm@4 global start %include "BeaEngineNasm.inc" section .data use32 i db 100 MyDisasm: istruc _Disasm iend section .text use32 start: ; ***************************** Init EIP mov eax, start mov [MyDisasm+EIP], eax ; ***************************** just for fun : init VirtualAddr with weird address :) mov eax, 0xbea2008 movd mm0, eax movq [MyDisasm+VirtualAddr], mm0 ; ***************************** loop for disasm MakeDisasm: push MyDisasm call _Disasm@4 cmp eax, UNKNOWN_OPCODE je IncreaseEIP add [MyDisasm+EIP], eax jmp DisplayInstruction IncreaseEIP: inc dword [MyDisasm+EIP] DisplayInstruction: push MyDisasm+CompleteInstr call _puts@4 add esp, 4 dec byte [i] jne MakeDisasm push 0 call _ExitProcess@4
Utiliser BeaEngine avec fasm
format MS COFF ; ************************************** Define "prototype" extrn '_puts@4' as puts:dword extrn '_Disasm@4' as Disasm:dword extrn '_ExitProcess@4' as ExitProcess:dword ; ************************************** includes include '\fasm\INCLUDE\win32ax.inc' ; <--- extended headers to enable macroinstruction .if .elseif .end include 'BeaEngineFasm.inc' section '.data' data readable writeable MyDisasm _Disasm <> i db 100 szoutofblock db "Security alert. Disasm tries to read unreadable memory",0 section '.text' code readable executable public start start: ; *********************** Init EIP mov eax, start mov [MyDisasm.EIP], eax ; *********************** loop for disasm MakeDisasm: push MyDisasm call Disasm .if eax = OUT_OF_BLOCK push szoutofblock call puts add esp, 4 push 0 call ExitProcess .elseif eax = UNKNOWN_OPCODE inc [MyDisasm.EIP] .else add [MyDisasm.EIP], eax .endif push MyDisasm.CompleteInstr call puts add esp, 4 dec byte [i] jne MakeDisasm push 0 call ExitProcess
Utiliser BeaEngine avec GoAsm
#include BeaEngineGoAsm.inc Disasm = BeaEngine.lib:Disasm .data MyDisasm _Disasm <> szoutofblock db "Security alert. Disasm tries to read unreadable memory",0 i db 100 .code start: ; *********************** Init EIP mov eax, offset start mov [MyDisasm.EIP], eax ; *********************** loop for disasm MakeDisasm: push offset MyDisasm call Disasm cmp eax, OUT_OF_BLOCK jne > push offset szoutofblock call puts add esp, 4 push 0 call ExitProcess : cmp eax, UNKNOWN_OPCODE jne > inc d[MyDisasm.EIP] jmp Display : add [MyDisasm.EIP], eax Display: push offset MyDisasm.CompleteInstr call puts add esp, 4 dec b[i] jne MakeDisasm push 0 call ExitProcess
Utiliser BeaEngine avec masm64
include ..\..\HEADERS\BeaEngineMasm.inc extrn puts:PROC extrn ExitProcess: PROC .data MyDisasm _Disasm <> szoutofblock BYTE "Security alert. Disasm tries to read unreadable memory",0 i DWORD 100 .code main proc ; *********************** Init EIP mov rax, main mov MyDisasm.EIP, rax ; *********************** Init Architecture mov MyDisasm.Archi, 64 ; *********************** loop for disasm MakeDisasm: mov rcx, offset MyDisasm call Disasm cmp eax, OUT_OF_BLOCK jne @F mov rcx, offset szoutofblock sub rsp, 20h call puts add rsp, 20h mov rcx, 0 call ExitProcess @@: cmp eax, UNKNOWN_OPCODE jne @F inc MyDisasm.EIP jmp Display @@: add MyDisasm.EIP, rax Display: mov rcx, offset MyDisasm.CompleteInstr sub rsp, 20h call puts add rsp, 20h dec i jne MakeDisasm mov rcx, 0 call ExitProcess main endp end
Utiliser BeaEngine avec GoAsm64
#include BeaEngineGoAsm.inc Disasm = BeaEngine64.lib:Disasm .data MyDisasm _Disasm <> szoutofblock db "Security alert. Disasm tries to read unreadable memory",0 i db 100 .code start: ; *********************** Init EIP mov rax, offset start mov q [MyDisasm.EIP], rax ; *********************** Init Architecture mov d [MyDisasm.Archi], 64 ; *********************** loop for disasm MakeDisasm: mov rcx, offset MyDisasm call Disasm cmp rax, OUT_OF_BLOCK jne > mov rcx, offset szoutofblock sub rsp, 20h call puts add rsp, 20h mov rcx, 0 call ExitProcess : cmp rax, UNKNOWN_OPCODE jne > inc q[MyDisasm.EIP] jmp Display : add q[MyDisasm.EIP], rax Display: mov rcx, offset MyDisasm.CompleteInstr sub rsp, 20h call puts add rsp, 20h dec b[i] jne MakeDisasm mov rcx, 0 call ExitProcess
Voici un exemple proposé par un ami, Vincent Roy, codeur spécialisé en WinDev.
// Creation du Header beaEngine pour Windev // Creation des constantes CONSTANT NoTabulation = 0x0 Tabulation = 0x1 MasmSyntax = 0x000 GoAsmSyntax = 0x100 NasmSyntax = 0x200 ATSyntax = 0x400 PrefixedNumeral = 0x10000 SuffixedNumeral = 0x00000 ShowSegmentRegs = 0x1000000 UNKNOWN_OPCODE = -1 FIN // Creation des structures // Rajout Code Vince pour la nouvelle DLL de beatrix2004 REX_Struct est une structure W_ est un entier sur 1 octets R_ est un entier sur 1 octets X_ est un entier sur 1 octets B_ est un entier sur 1 octets state est un entier sur 1 octets FIN PREFIXINFO est une structure Number est un entier NbUndefined est un entier LockPrefix est un entier sur 1 octets OperandSize est un entier sur 1 octets AddressSize est un entier sur 1 octets RepnePrefix est un entier sur 1 octets RepPrefix est un entier sur 1 octets FSPrefix est un entier sur 1 octets SSPrefix est un entier sur 1 octets GSPrefix est un entier sur 1 octets ESPrefix est un entier sur 1 octets CSPrefix est un entier sur 1 octets DSPrefix est un entier sur 1 octets REX est un REX_Struct FIN EFLStruct est une structure nOF_ est un entier sur 1 octet nSF_ est un entier sur 1 octet nZF_ est un entier sur 1 octet nAF_ est un entier sur 1 octet nPF_ est un entier sur 1 octet nCF_ est un entier sur 1 octet nTF_ est un entier sur 1 octet nIF_ est un entier sur 1 octet nDF_ est un entier sur 1 octet nNT_ est un entier sur 1 octet nRF_ est un entier sur 1 octet nAlignment est un entier sur 1 octet FIN MEMORYTYPE est une structure nBaseRegister est un entier sur 4 octets nIndexRegister est un entier sur 4 octets nScale est un entier sur 4 octets nDisplacement est un entier sur 8 octets FIN INSTRTYPE est une structure nCategory est un entier sur 4 octets nOpcode est un entier sur 4 octets Mnemonic est une chaîne fixe sur 16 nBranchType est un entier sur 4 octets stFlags est un EFLStruct nAddrValue est un entier sur 8 octets nImmediat est un entier sur 8 octets nImplicitModifiedRegs est un entier sur 4 octets FIN ARGTYPE est une structure ArgMnemonic est une chaîne fixe sur 32 nArgType est un entier sur 4 octets nArgSize est un entier sur 4 octets nAccessMode est un entier sur 4 octets stMemory est un MEMORYTYPE nSegmentReg est un entier sur 4 octets FIN _Disasm est une structure EIP est un entier sans signe sur 8 octets VirtualAddr est un entier sans signe sur 8 octets SecurityBlock est un entier sur 4 octets CompleteInstr est une chaîne fixe sur 64 Archi est un entier sur 4 octets nOptions est un entier sur 4 octets stInstruction est un INSTRTYPE stArgument1 est un ARGTYPE stArgument2 est un ARGTYPE stArgument3 est un ARGTYPE Prefix est un PREFIXINFO FIN // Creation d un objet Disasm (equivalent à struct _Disasm MonDisasm; en C) Disasm est un _Disasm // Mise à jour des Options (optionnel) Disasm:nOptions = Tabulation+NasmSyntax+PrefixedNumeral // Chargement de la dll BeaEngine (ChargeDLL est une fonction windev) HandleDLL est un entier = ChargeDLL ("C:\BeaEngine.dll") si HandleDLL = -1 ALORS Erreur ("chargement impossible de la DLL.") RETOUR FIN // Initialisation des Datas Disasm:EIP = 0x401000 Disasm:VirtualAddr = 0x0 Disasm:Archi = 0 len est un entier = 0 myError est un entier = 0 i est un entier = 1 TANTQUE (i<=100 ET myError=0) // Appel de la fonction exportée Disam (AppelDLL32 est une fonction windev) len = AppelDLL32("C:\BeaEngine.dll","Disasm",&Disasm) SI (len=UNKNOWN_OPCODE) ALORS myError = 1 SINON // Liste les instructions (Trace est une fonction windev. Elle affiche une fenetre de "Trace" de couleur jaune) Trace (Disasm:CompleteInstr) Disasm:EIP += len i++ FIN FIN dechargeDLL (HandleDLL)