Welcome to the BeaEngine Sweet Home - x86 x86-64 disassembler library - (IA-32 & Intel64)

Exemples - Tutorial

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

1- Comment désassembler 100 lignes de code ? (exemple basic)

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;
}

2- Comment désassembler une portion de code délimitée ? (usage du SecurityBlock)

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;
}

3- Comment désassembler un code copié dans un buffer tout en gardant les adresses virtuelles d'origine ?

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;
}

4- Comment utiliser la syntaxe nasm avec nombres préfixés ?

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;
}

5- Comment utiliser la librairie avec Python ?

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 


6- Comment retenir seulement les instructions qui modifient eax ?

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;
}

7- Comment réaliser un désassemblage en 'suivant' les sauts inconditionnels ?

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;
}

8- Comment réaliser un désassemblage sur une cible 64 bits ?

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;

9- Comment utiliser BeaEngine avec masm32, nasm, fasm ou GoAsm ?

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

10- Comment utiliser BeaEngine avec masm64 ou GoAsm64 ?

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





11- Comment utiliser BeaEngine avec WinDev (par Vincent Roy)?

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)

Valid XHTML 1.0 Strict

Valid CSS!