2021-07-03 15:29:13 +02:00
# include <final/final.h>
2021-07-04 19:20:46 +02:00
# include <unistd.h>
2021-07-03 19:32:11 +02:00
# include <iostream>
# include <string>
# include <sstream>
2021-07-04 12:35:46 +02:00
# include <iomanip>
2021-07-03 15:29:13 +02:00
# include <keystone/keystone.h>
# include <unicorn/unicorn.h>
# include <capstone/capstone.h>
2021-07-04 11:15:24 +02:00
# include <vector>
2021-07-03 19:32:11 +02:00
using namespace std ;
2021-07-04 11:15:24 +02:00
using std : : cout ; using std : : endl ;
using std : : vector ; using std : : string ;
2021-07-03 15:29:13 +02:00
2021-07-03 19:32:11 +02:00
using FKey = finalcut : : FKey ;
using finalcut : : FPoint ;
using finalcut : : FSize ;
2021-07-03 15:29:13 +02:00
2021-07-04 19:20:46 +02:00
//----------------------------------------------------------------------
// Types & classes mineures
//----------------------------------------------------------------------
2021-07-04 11:15:24 +02:00
typedef union {
struct {
union {
uint8_t l ;
uint8_t byte ;
} ;
uint8_t h ;
} __attribute__ ( ( packed ) ) ;
uint16_t word ;
} __attribute__ ( ( packed ) ) reg16_t ;
typedef union {
struct {
union {
uint8_t l ;
uint8_t byte ;
} ;
uint8_t h ;
} __attribute__ ( ( packed ) ) ;
uint16_t word ;
uint32_t dword ;
} __attribute__ ( ( packed ) ) reg32_t ;
struct i386_regs {
union {
uint16_t ip ;
uint32_t eip ;
} ;
union {
uint16_t di ;
uint32_t edi ;
} ;
union {
uint16_t si ;
uint32_t esi ;
} ;
union {
uint16_t bp ;
uint32_t ebp ;
} ;
union {
uint16_t sp ;
uint32_t esp ;
} ;
union {
struct {
uint8_t bl ;
uint8_t bh ;
} __attribute__ ( ( packed ) ) ;
uint16_t bx ;
uint32_t ebx ;
} ;
union {
struct {
uint8_t dl ;
uint8_t dh ;
} __attribute__ ( ( packed ) ) ;
uint16_t dx ;
uint32_t edx ;
} ;
union {
struct {
uint8_t cl ;
uint8_t ch ;
} __attribute__ ( ( packed ) ) ;
uint16_t cx ;
uint32_t ecx ;
} ;
union {
struct {
uint8_t al ;
uint8_t ah ;
} __attribute__ ( ( packed ) ) ;
uint16_t ax ;
uint32_t eax ;
} ;
} __attribute__ ( ( packed ) ) ;
struct i386_seg_regs
{
uint16_t cs ;
uint16_t ss ;
uint16_t ds ;
uint16_t es ;
uint16_t fs ;
uint16_t gs ;
} __attribute__ ( ( packed ) ) ;
struct i386_all_regs
{
struct i386_seg_regs segs ;
struct i386_regs regs ;
uint32_t flags ;
} __attribute__ ( ( packed ) ) ;
class Memzone
{
public :
uint32_t address ;
uint32_t size ;
uint8_t * content ;
} ;
class State {
public :
i386_all_regs dump ;
std : : vector < Memzone > memzone ;
} ;
class Goal {
public :
std : : string title ;
std : : string description ;
2021-07-04 12:35:46 +02:00
std : : string help ;
std : : string code ;
2021-07-04 11:15:24 +02:00
State init ;
State goal ;
} ;
2021-07-04 19:20:46 +02:00
2021-07-05 15:00:22 +02:00
class Code
{
public :
uint32_t address ;
size_t size ;
unsigned char * content ;
bool assembled ;
} ;
2021-07-05 13:21:35 +02:00
//----------------------------------------------------------------------
// Fonctions diverses
//----------------------------------------------------------------------
std : : string intToHexString ( int intValue , int size ) {
string hexStr ;
std : : stringstream sstream ;
sstream < < std : : setfill ( ' 0 ' ) < < std : : setw ( size )
< < std : : hex < < ( int ) intValue ;
hexStr = sstream . str ( ) ;
sstream . clear ( ) ;
return hexStr ;
}
2021-07-04 19:20:46 +02:00
//----------------------------------------------------------------------
// Objectifs de jeux
//----------------------------------------------------------------------
// Ordre des registres ... IP DI SI BP SP BX DX CX AX
Goal goals [ ] =
{
{
2021-07-05 13:21:35 +02:00
" L'instruction MOV et les registres " , " Le but est de bouger du registre AX au registre BX, l' ensemble des données " , " Aide.... " , " inc ax \n dec cx \n mov ax,0x33 \n add ax,[bx+2] " ,
2021-07-04 19:20:46 +02:00
{
{
{ } ,
{ . bx = 0x0002 , . ax = 0x1920 } ,
0x00000000
} ,
{ }
} ,
{
{
{ } ,
{ . bx = 25 , . dx = 0b101 , . cx = 0x4650 , . ax = 0xCCDD } ,
0x00000000
} ,
{ }
}
}
} ;
2021-07-05 13:21:35 +02:00
//----------------------------------------------------------------------
// Classe ListWindow
//----------------------------------------------------------------------
class ListWindow final : public finalcut : : FDialog
{
public :
// Constructor
explicit ListWindow ( finalcut : : FWidget * = nullptr ) ;
// Disable copy constructor
ListWindow ( const ListWindow & ) = delete ;
// Destructor
~ ListWindow ( ) override = default ;
// Disable copy assignment operator (=)
ListWindow & operator = ( const ListWindow & ) = delete ;
// Method
std : : vector < std : : array < std : : string , 5 > > get ( ) ;
void set ( std : : vector < std : : array < std : : string , 5 > > src ) ;
private :
// Method
std : : vector < std : : array < std : : string , 5 > > content ;
void initLayout ( ) override ;
void adjustSize ( ) override ;
// Data members
finalcut : : FListView listview { this } ;
} ;
ListWindow : : ListWindow ( finalcut : : FWidget * parent )
: finalcut : : FDialog { parent }
{
listview . ignorePadding ( ) ;
listview . addColumn ( " P " ) ;
listview . addColumn ( " Adresse " ) ;
listview . addColumn ( " Opcodes " ) ;
listview . addColumn ( " Mnémo. " ) ;
listview . addColumn ( " Opérandes " ) ;
listview . hideSortIndicator ( true ) ;
listview . setFocus ( ) ;
}
std : : vector < std : : array < std : : string , 5 > > ListWindow : : get ( )
{
return content ;
}
void ListWindow : : set ( std : : vector < std : : array < std : : string , 5 > > src )
{
content = src ;
listview . clear ( ) ;
for ( const auto & place : content )
{
const finalcut : : FStringList line ( place . begin ( ) , place . end ( ) ) ;
listview . insert ( line ) ;
}
}
void ListWindow : : initLayout ( )
{
listview . setGeometry ( FPoint { 1 , 2 } , FSize { getWidth ( ) , getHeight ( ) - 1 } ) ;
setMinimumSize ( FSize { 51 , 6 } ) ;
FDialog : : initLayout ( ) ;
}
void ListWindow : : adjustSize ( )
{
finalcut : : FDialog : : adjustSize ( ) ;
listview . setGeometry ( FPoint { 1 , 2 } , FSize ( getWidth ( ) , getHeight ( ) - 1 ) ) ;
}
2021-07-04 11:15:24 +02:00
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Classe TextFixedWindow
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
2021-07-03 15:29:13 +02:00
2021-07-03 19:32:11 +02:00
class TextFixedWindow final : public finalcut : : FDialog
{
public :
// Constructor
explicit TextFixedWindow ( finalcut : : FWidget * = nullptr ) ;
// Disable copy constructor
TextFixedWindow ( const TextFixedWindow & ) = delete ;
// Destructor
~ TextFixedWindow ( ) override = default ;
// Disable copy assignment operator (=)
TextFixedWindow & operator = ( const TextFixedWindow & ) = delete ;
// Method
2021-07-04 21:32:53 +02:00
std : : string get ( ) ;
void set ( std : : string str ) ;
2021-07-03 19:32:11 +02:00
private :
// Method
void initLayout ( ) override ;
void adjustSize ( ) override ;
// Data members
finalcut : : FLabel fixedtext { this } ;
} ;
TextFixedWindow : : TextFixedWindow ( finalcut : : FWidget * parent )
: finalcut : : FDialog { parent }
{
fixedtext . ignorePadding ( ) ;
fixedtext . setFocus ( ) ;
}
2021-07-04 21:32:53 +02:00
std : : string TextFixedWindow : : get ( )
{
2021-07-05 13:21:35 +02:00
std : : stringstream out ;
2021-07-04 21:32:53 +02:00
out < < fixedtext . getText ( ) ;
return out . str ( ) ;
}
void TextFixedWindow : : set ( std : : string str )
2021-07-03 15:29:13 +02:00
{
2021-07-04 21:32:53 +02:00
fixedtext . setText ( str ) ;
2021-07-03 19:32:11 +02:00
}
void TextFixedWindow : : initLayout ( )
{
fixedtext . setGeometry ( FPoint { 1 , 2 } , FSize { getWidth ( ) , getHeight ( ) - 1 } ) ;
setMinimumSize ( FSize { 51 , 6 } ) ;
FDialog : : initLayout ( ) ;
}
void TextFixedWindow : : adjustSize ( )
{
finalcut : : FDialog : : adjustSize ( ) ;
fixedtext . setGeometry ( FPoint { 1 , 2 } , FSize ( getWidth ( ) , getHeight ( ) - 1 ) ) ;
}
2021-07-04 15:13:35 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Classe TextEditWindow
2021-07-04 15:13:35 +02:00
//----------------------------------------------------------------------
class TextEditWindow final : public finalcut : : FDialog
{
public :
// Constructor
explicit TextEditWindow ( finalcut : : FWidget * = nullptr ) ;
// Disable copy constructor
TextEditWindow ( const TextEditWindow & ) = delete ;
// Destructor
~ TextEditWindow ( ) override = default ;
// Disable copy assignment operator (=)
TextEditWindow & operator = ( const TextEditWindow & ) = delete ;
// Method
std : : string get ( ) ;
2021-07-04 19:20:46 +02:00
void set ( std : : string str ) ;
2021-07-04 15:13:35 +02:00
private :
// Method
void initLayout ( ) override ;
void adjustSize ( ) override ;
// Data members
finalcut : : FLabel fixedtext { this } ;
} ;
TextEditWindow : : TextEditWindow ( finalcut : : FWidget * parent )
: finalcut : : FDialog { parent }
{
fixedtext . ignorePadding ( ) ;
fixedtext . setFocus ( ) ;
}
std : : string TextEditWindow : : get ( )
{
2021-07-05 10:22:48 +02:00
std : : stringstream out ;
2021-07-04 19:20:46 +02:00
out < < fixedtext . getText ( ) ;
return out . str ( ) ;
}
void TextEditWindow : : set ( std : : string str )
{
fixedtext . setText ( str ) ;
2021-07-04 15:13:35 +02:00
}
void TextEditWindow : : initLayout ( )
{
2021-07-04 19:20:46 +02:00
fixedtext . setGeometry ( FPoint { 2 , 3 } , FSize ( 12 , 12 ) ) ;
2021-07-04 15:13:35 +02:00
FDialog : : initLayout ( ) ;
}
void TextEditWindow : : adjustSize ( )
{
finalcut : : FDialog : : adjustSize ( ) ;
}
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Classe TextWindow
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
class TextWindow final : public finalcut : : FDialog
{
public :
// Constructor
explicit TextWindow ( finalcut : : FWidget * = nullptr ) ;
// Disable copy constructor
TextWindow ( const TextWindow & ) = delete ;
// Destructor
~ TextWindow ( ) override = default ;
// Disable copy assignment operator (=)
TextWindow & operator = ( const TextWindow & ) = delete ;
// Method
2021-07-04 15:13:35 +02:00
void append ( const finalcut : : FString & ) ;
2021-07-03 19:32:11 +02:00
private :
// Method
2021-07-04 15:13:35 +02:00
void onClose ( finalcut : : FCloseEvent * ) override ;
2021-07-03 19:32:11 +02:00
void initLayout ( ) override ;
void adjustSize ( ) override ;
// Data members
finalcut : : FTextView scrolltext { this } ;
} ;
2021-07-04 19:20:46 +02:00
2021-07-03 19:32:11 +02:00
TextWindow : : TextWindow ( finalcut : : FWidget * parent )
: finalcut : : FDialog { parent }
{
scrolltext . ignorePadding ( ) ;
scrolltext . setFocus ( ) ;
}
2021-07-04 19:20:46 +02:00
2021-07-04 15:13:35 +02:00
void TextWindow : : onClose ( finalcut : : FCloseEvent * )
2021-07-04 11:15:24 +02:00
{
return ;
}
2021-07-04 19:20:46 +02:00
2021-07-04 15:13:35 +02:00
void TextWindow : : append ( const finalcut : : FString & str )
2021-07-03 19:32:11 +02:00
{
scrolltext . append ( str ) ;
2021-07-05 10:22:48 +02:00
scrolltext . scrollBy ( 0 , 1 ) ;
2021-07-03 19:32:11 +02:00
}
void TextWindow : : initLayout ( )
{
scrolltext . setGeometry ( FPoint { 1 , 2 } , FSize { getWidth ( ) , getHeight ( ) - 1 } ) ;
setMinimumSize ( FSize { 51 , 6 } ) ;
FDialog : : initLayout ( ) ;
}
void TextWindow : : adjustSize ( )
{
finalcut : : FDialog : : adjustSize ( ) ;
scrolltext . setGeometry ( FPoint { 1 , 2 } , FSize ( getWidth ( ) , getHeight ( ) - 1 ) ) ;
}
2021-07-05 10:22:48 +02:00
//----------------------------------------------------------------------
// Classe Desassembler
//----------------------------------------------------------------------
class Desassembler
{
public :
Desassembler ( TextWindow * log ) ;
2021-07-05 15:00:22 +02:00
std : : vector < std : : array < std : : string , 5 > > Desassemble ( Code * code ) ;
2021-07-05 10:22:48 +02:00
private :
csh handle ;
cs_insn * insn ;
int err ;
TextWindow * log ;
TextEditWindow * edit ;
size_t srcsize ;
size_t codesize ;
2021-07-05 13:21:35 +02:00
std : : vector < std : : array < std : : string , 5 > > src ;
2021-07-05 10:22:48 +02:00
unsigned char * src_char = new unsigned char [ 64 * 1024 ] ;
} ;
Desassembler : : Desassembler ( TextWindow * log ) : log ( log )
{
std : : stringstream out ;
err = cs_open ( CS_ARCH_X86 , CS_MODE_16 , & handle ) ;
if ( err ! = CS_ERR_OK ) {
out < < " Erreur : Initialisation du désassembleur X86 " < < err ;
log - > append ( out . str ( ) ) ;
}
else
log - > append ( " Initialisation du désassembleur X86 " ) ;
}
2021-07-05 15:00:22 +02:00
std : : vector < std : : array < std : : string , 5 > > Desassembler : : Desassemble ( Code * code )
2021-07-05 10:22:48 +02:00
{
std : : stringstream out ;
2021-07-05 15:00:22 +02:00
srcsize = cs_disasm ( handle , code - > content , code - > size , code - > address , 0 , & insn ) ;
2021-07-05 10:22:48 +02:00
if ( srcsize = = 0 )
log - > append ( " Erreur de désassemblage " ) ;
else
{
2021-07-05 13:53:01 +02:00
out < < " Désassemblage réussi, taille du source : " < < srcsize ;
2021-07-05 10:22:48 +02:00
log - > append ( out . str ( ) ) ;
for ( size_t j = 0 ; j < srcsize ; j + + )
2021-07-05 13:21:35 +02:00
{
std : : string * bytes = new std : : string ( " " ) ;
for ( size_t k = 0 ; k < insn [ j ] . size ; k + + )
* bytes = * bytes + intToHexString ( ( int ) insn [ j ] . bytes [ k ] , 1 ) ;
std : : string adresse = intToHexString ( ( int ) insn [ j ] . address , 8 ) ;
std : : string * menmonic = new std : : string ( ( char * ) insn [ j ] . mnemonic ) ;
std : : string * op_str = new std : : string ( ( char * ) insn [ j ] . op_str ) ;
std : : array < std : : string , 5 > * array = new std : : array < std : : string , 5 > { " " , adresse , * bytes , * menmonic , * op_str } ;
src . push_back ( * array ) ;
}
2021-07-05 10:22:48 +02:00
cs_free ( insn , srcsize ) ;
}
2021-07-05 13:21:35 +02:00
return src ;
2021-07-05 10:22:48 +02:00
}
2021-07-04 15:13:35 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Classe Assembler
2021-07-04 15:13:35 +02:00
//----------------------------------------------------------------------
class Assembler
{
public :
2021-07-05 10:22:48 +02:00
Assembler ( TextWindow * log ) ;
2021-07-05 15:00:22 +02:00
Code * Assemble ( std : : string source , uint32_t address ) ;
2021-07-04 15:13:35 +02:00
private :
ks_engine * ks ;
ks_err err ;
int err2 ;
TextWindow * log ;
TextEditWindow * edit ;
2021-07-05 15:00:22 +02:00
Code * code = new Code ;
2021-07-04 15:13:35 +02:00
} ;
2021-07-05 10:22:48 +02:00
Assembler : : Assembler ( TextWindow * log ) : log ( log )
2021-07-04 15:13:35 +02:00
{
2021-07-05 10:22:48 +02:00
std : : stringstream out ;
err = ks_open ( KS_ARCH_X86 , KS_MODE_16 , & ks ) ;
2021-07-04 15:13:35 +02:00
if ( err ! = KS_ERR_OK ) {
out < < " Erreur : Initialisation de l'assembleur X86 " < < err ;
log - > append ( out . str ( ) ) ;
}
else
log - > append ( " Initialisation de l'assembleur X86 " ) ;
2021-07-05 15:00:22 +02:00
code - > assembled = false ;
2021-07-04 15:13:35 +02:00
}
2021-07-05 15:00:22 +02:00
Code * Assembler : : Assemble ( std : : string source , uint32_t address )
2021-07-05 10:22:48 +02:00
{
std : : stringstream out ;
2021-07-05 15:00:22 +02:00
code - > address = address ;
size_t srcsize = source . size ( ) ;
2021-07-04 15:13:35 +02:00
unsigned char src_char [ srcsize + 1 ] ;
2021-07-05 15:00:22 +02:00
strcpy ( reinterpret_cast < char * > ( src_char ) , source . c_str ( ) ) ;
err2 = ks_asm ( ks , reinterpret_cast < const char * > ( src_char ) , code - > address , & code - > content , & code - > size , & srcsize ) ;
2021-07-04 15:13:35 +02:00
if ( err2 ! = KS_ERR_OK )
2021-07-05 13:53:01 +02:00
{
2021-07-05 10:22:48 +02:00
log - > append ( " Erreur d'assemblage " ) ;
2021-07-05 15:00:22 +02:00
code - > size = 0 ;
code - > assembled = false ;
2021-07-05 13:53:01 +02:00
}
2021-07-04 15:13:35 +02:00
else
2021-07-05 10:22:48 +02:00
{
2021-07-05 15:00:22 +02:00
out < < " Assemblage réussi, taille du code : " < < code - > size ;
code - > assembled = true ;
2021-07-04 15:13:35 +02:00
log - > append ( out . str ( ) ) ;
2021-07-05 13:53:01 +02:00
/*out.str("");
2021-07-04 15:13:35 +02:00
out . clear ( ) ;
if ( codesize < 30 )
{
out < < " " ;
for ( size_t count = 0 ; count < codesize ; count + + )
out < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < std : : hex < < ( int ) ( ( uint8_t ) code [ count ] ) ;
log - > append ( out . str ( ) ) ;
2021-07-05 13:53:01 +02:00
} */
2021-07-04 15:13:35 +02:00
}
2021-07-05 15:00:22 +02:00
return code ;
2021-07-04 15:13:35 +02:00
}
2021-07-04 11:15:24 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Classe VMEngine
2021-07-04 11:15:24 +02:00
//----------------------------------------------------------------------
class VMEngine
{
public :
VMEngine ( TextWindow * log ) ;
2021-07-05 15:00:22 +02:00
void Configure ( State * init , Code * code ) ;
void Run ( uint32_t start , uint32_t stop ) ;
2021-07-04 11:15:24 +02:00
private :
uc_engine * uc ;
uc_err err ;
TextWindow * log ;
} ;
VMEngine : : VMEngine ( TextWindow * log ) : log ( log )
{
2021-07-05 10:22:48 +02:00
std : : stringstream out ;
2021-07-04 11:15:24 +02:00
err = uc_open ( UC_ARCH_X86 , UC_MODE_16 , & uc ) ;
if ( err ! = UC_ERR_OK ) {
out < < " Impossible d'initialiser la machine virtuelle: " < < err ;
log - > append ( out . str ( ) ) ;
}
else
log - > append ( " Initialisation de l'ordinateur IA86 " ) ;
}
2021-07-04 12:35:46 +02:00
2021-07-05 15:00:22 +02:00
void VMEngine : : Configure ( State * init , Code * code )
2021-07-04 11:15:24 +02:00
{
2021-07-05 10:22:48 +02:00
std : : stringstream out ;
2021-07-04 12:35:46 +02:00
out < < " Configuration initiale de l'ordinateur IA86: \n " ;
err = uc_reg_write ( uc , UC_X86_REG_EIP , & init - > dump . regs . eip ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: EIP " ) ;
else
if ( init - > dump . regs . eip ! = 0x00000000 )
if ( ( init - > dump . regs . eip & 0xFFFF0000 ) = = 0x00000000 )
out < < " IP= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . ip < < " " ;
else
out < < " EIP= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . eip < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_EDI , & init - > dump . regs . edi ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: EDI " ) ;
else
if ( init - > dump . regs . edi ! = 0x00000000 )
if ( ( init - > dump . regs . edi & 0xFFFF0000 ) = = 0x00000000 )
out < < " DI= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . di < < " " ;
else
out < < " EDI= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . edi < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_ESI , & init - > dump . regs . esi ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: ESE " ) ;
else
if ( init - > dump . regs . esi ! = 0x00000000 )
if ( ( init - > dump . regs . esi & 0xFFFF0000 ) = = 0x00000000 )
out < < " SI= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . si < < " " ;
else
out < < " ESI= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . esi < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_EBP , & init - > dump . regs . ebp ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: EBP " ) ;
else
if ( init - > dump . regs . ebp ! = 0x00000000 )
if ( ( init - > dump . regs . ebp & 0xFFFF0000 ) = = 0x00000000 )
out < < " BP= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . bp < < " " ;
else
out < < " EBP= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . ebp < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_ESP , & init - > dump . regs . esp ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: ESP " ) ;
else
if ( init - > dump . regs . esp ! = 0x00000000 )
if ( ( init - > dump . regs . esp & 0xFFFF0000 ) = = 0x00000000 )
out < < " SP= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . sp < < " " ;
else
out < < " ESP= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . esp < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_EBX , & init - > dump . regs . ebx ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: EBX " ) ;
else
if ( init - > dump . regs . ebx ! = 0x00000000 )
if ( ( init - > dump . regs . ebx & 0xFFFF0000 ) = = 0x00000000 )
out < < " BX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . bx < < " " ;
else
out < < " EBX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . ebx < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_EDX , & init - > dump . regs . edx ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: EDX " ) ;
else
if ( init - > dump . regs . edx ! = 0x00000000 )
if ( ( init - > dump . regs . edx & 0xFFFF0000 ) = = 0x00000000 )
out < < " DX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . dx < < " " ;
else
out < < " EDX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . edx < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_ECX , & init - > dump . regs . ecx ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: ECX " ) ;
else
if ( init - > dump . regs . ecx ! = 0x00000000 )
if ( ( init - > dump . regs . ecx & 0xFFFF0000 ) = = 0x00000000 )
out < < " CX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . cx < < " " ;
else
out < < " ECX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . ecx < < " " ;
err = uc_reg_write ( uc , UC_X86_REG_EAX , & init - > dump . regs . eax ) ;
if ( err ! = UC_ERR_OK )
log - > append ( " Impossible d'initialiser le registre: EAX " ) ;
else
if ( init - > dump . regs . eax ! = 0x00000000 )
if ( ( init - > dump . regs . eax & 0xFFFF0000 ) = = 0x00000000 )
out < < " AX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 4 ) < < std : : hex < < init - > dump . regs . ax < < " " ;
else
out < < " EAX= " < < std : : uppercase < < std : : setfill ( ' 0 ' ) < < std : : setw ( 8 ) < < std : : hex < < init - > dump . regs . eax < < " " ;
log - > append ( out . str ( ) ) ;
2021-07-05 15:00:22 +02:00
uc_mem_map ( uc , init - > dump . regs . eip , code - > size , UC_PROT_ALL ) ;
if ( uc_mem_write ( uc , init - > dump . regs . eip , code - > content , code - > size ) )
{
log - > append ( " Erreur de copie mémoire dans la machine virtuelle " ) ;
return ;
}
2021-07-04 11:15:24 +02:00
}
2021-07-05 15:00:22 +02:00
void VMEngine : : Run ( uint32_t start , uint32_t stop )
2021-07-04 11:15:24 +02:00
{
2021-07-05 15:00:22 +02:00
err = uc_emu_start ( uc , start , stop , 0 , 0 ) ;
2021-07-04 11:15:24 +02:00
}
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Classe Menu
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
class Menu final : public finalcut : : FDialog
{
public :
// Constructor
explicit Menu ( finalcut : : FWidget * = nullptr ) ;
// Disable copy constructor
Menu ( const Menu & ) = delete ;
// Destructor
~ Menu ( ) override = default ;
// Disable copy assignment operator (=)
Menu & operator = ( const Menu & ) = delete ;
// Methods
2021-07-04 19:20:46 +02:00
void setGoal ( int num ) ;
void loadGoal ( ) ;
2021-07-03 19:32:11 +02:00
private :
2021-07-04 19:20:46 +02:00
int scenario = 0 ;
2021-07-05 15:00:22 +02:00
Code * code = new Code ( ) ;
2021-07-03 19:32:11 +02:00
void configureFileMenuItems ( ) ;
2021-07-04 19:20:46 +02:00
void initMenusCallBack ( ) ;
void initMenus ( ) ;
void initMisc ( ) ;
void initNow ( ) ;
void initCore ( ) ;
void compile ( ) ;
void exec ( ) ;
2021-07-05 13:53:01 +02:00
void trace ( ) ;
void step ( ) ;
void verify ( ) ;
2021-07-04 19:20:46 +02:00
void initWindows ( ) ;
void splash ( ) ;
2021-07-03 19:32:11 +02:00
void initLayout ( ) override ;
void adjustSize ( ) override ;
// Event handler
void onClose ( finalcut : : FCloseEvent * ) override ;
// Callback method
void cb_message ( const finalcut : : FMenuItem * ) ;
// Data members
finalcut : : FString line { 13 , finalcut : : UniChar : : BoxDrawingsHorizontal } ;
finalcut : : FMenuBar Menubar { this } ;
2021-07-04 21:32:53 +02:00
finalcut : : FMenu Game { " &Partie " , & Menubar } ;
finalcut : : FMenuItem New { " &Nouvelle partie " , & Game } ;
finalcut : : FMenuItem Line2 { & Game } ;
finalcut : : FMenuItem Quit { " &Quitter " , & Game } ;
finalcut : : FMenu Scenarios { " &Scénarios " , & Menubar } ;
finalcut : : FMenu Tools { " &Outils " , & Menubar } ;
finalcut : : FMenuItem Assemble { " &Compilation " , & Tools } ;
finalcut : : FMenuItem Rearange { " &Ordonne les fenêtres " , & Tools } ;
finalcut : : FMenu Debug { " &Déboguage " , & Menubar } ;
finalcut : : FMenuItem Run { " &Exécuter " , & Debug } ;
finalcut : : FMenuItem End { " &Terminer " , & Debug } ;
finalcut : : FMenuItem TraceInto { " Pas à pas &détaillé " , & Debug } ;
finalcut : : FMenuItem StepOver { " &Pas à pas " , & Debug } ;
finalcut : : FMenuItem Breakpoint { " &Point d'arrêt " , & Debug } ;
2021-07-04 19:20:46 +02:00
finalcut : : FDialogListMenu Window { " &Fenêtres " , & Menubar } ;
2021-07-04 21:32:53 +02:00
finalcut : : FMenu Help { " &Aide " , & Menubar } ;
finalcut : : FMenuItem About { " &A propos " , & Help } ;
2021-07-03 19:32:11 +02:00
finalcut : : FLabel Info { this } ;
finalcut : : FStatusBar Statusbar { this } ;
2021-07-04 19:20:46 +02:00
TextWindow log { this } ;
TextWindow view { this } ;
2021-07-05 13:21:35 +02:00
ListWindow debug { this } ;
2021-07-04 21:32:53 +02:00
TextFixedWindow regs { this } ;
2021-07-04 23:41:49 +02:00
TextFixedWindow flags { this } ;
TextFixedWindow stack { this } ;
TextFixedWindow mem { this } ;
TextFixedWindow tuto { this } ;
2021-07-05 10:22:48 +02:00
TextFixedWindow screen { this } ;
2021-07-04 19:20:46 +02:00
TextEditWindow edit { this } ;
VMEngine vm { & log } ;
2021-07-05 10:22:48 +02:00
Assembler asmer { & log } ;
Desassembler unasmer { & log } ;
2021-07-03 19:32:11 +02:00
} ;
Menu : : Menu ( finalcut : : FWidget * parent )
: finalcut : : FDialog { parent }
{
2021-07-04 19:20:46 +02:00
initNow ( ) ;
2021-07-03 19:32:11 +02:00
}
2021-07-04 19:20:46 +02:00
void Menu : : initNow ( )
2021-07-03 19:32:11 +02:00
{
2021-07-04 19:20:46 +02:00
initWindows ( ) ;
initMisc ( ) ;
initMenus ( ) ;
initMenusCallBack ( ) ;
initCore ( ) ;
}
void Menu : : initCore ( )
{
setGoal ( 0 ) ;
}
2021-07-04 23:41:49 +02:00
//EAX:00000000 | AX:0000 | AH:00 | AL:00
2021-07-04 19:20:46 +02:00
void Menu : : initWindows ( )
{
log . setText ( " Journaux " ) ;
2021-07-04 23:41:49 +02:00
log . setGeometry ( FPoint { 63 , 45 } , FSize { 60 , 11 } ) ;
2021-07-04 19:20:46 +02:00
log . setResizeable ( ) ;
log . append ( " Lancement des journaux " ) ;
log . show ( ) ;
edit . setText ( " Code source " ) ;
2021-07-04 23:41:49 +02:00
edit . setGeometry ( FPoint { 01 , 17 } , FSize { 39 , 27 } ) ;
2021-07-04 19:20:46 +02:00
edit . setResizeable ( ) ;
edit . show ( ) ;
view . setText ( " Objectif " ) ;
2021-07-04 23:41:49 +02:00
view . setGeometry ( FPoint { 01 , 45 } , FSize { 60 , 11 } ) ;
2021-07-04 19:20:46 +02:00
view . setResizeable ( ) ;
view . show ( ) ;
2021-07-04 21:32:53 +02:00
regs . setText ( " Registres " ) ;
2021-07-04 23:41:49 +02:00
regs . setGeometry ( FPoint { 01 , 01 } , FSize { 39 , 15 } ) ;
2021-07-04 21:32:53 +02:00
regs . show ( ) ;
2021-07-04 23:41:49 +02:00
flags . setText ( " Drapeaux " ) ;
flags . setGeometry ( FPoint { 59 , 01 } , FSize { 15 , 15 } ) ;
flags . show ( ) ;
stack . setText ( " Pile " ) ;
stack . setGeometry ( FPoint { 42 , 01 } , FSize { 15 , 15 } ) ;
stack . show ( ) ;
mem . setText ( " Mémoire " ) ;
2021-07-05 10:22:48 +02:00
mem . setGeometry ( FPoint { 76 , 01 } , FSize { 109 , 15 } ) ;
2021-07-04 23:41:49 +02:00
mem . show ( ) ;
tuto . setText ( " Guide " ) ;
tuto . setGeometry ( FPoint { 125 , 45 } , FSize { 60 , 11 } ) ;
tuto . setResizeable ( ) ;
tuto . show ( ) ;
2021-07-05 10:22:48 +02:00
screen . setText ( " Ecran " ) ;
screen . setGeometry ( FPoint { 105 , 18 } , FSize { 80 , 25 } ) ;
screen . show ( ) ;
2021-07-05 13:21:35 +02:00
debug . setText ( " Instructions " ) ;
debug . setGeometry ( FPoint { 42 , 17 } , FSize { 60 , 27 } ) ;
debug . setResizeable ( ) ;
debug . show ( ) ;
2021-07-04 19:20:46 +02:00
}
void Menu : : initMenus ( )
{
2021-07-04 21:32:53 +02:00
Game . setStatusbarMessage ( " Menu principal du jeu " ) ;
Scenarios . setStatusbarMessage ( " Scénario disponibles " ) ;
Tools . setStatusbarMessage ( " Outils divers " ) ;
Debug . setStatusbarMessage ( " Fonctionnalitées de déboguages " ) ;
Window . setStatusbarMessage ( " Fenêtres en cours d'exécution " ) ;
Help . setStatusbarMessage ( " Aide et informations IA86 " ) ;
2021-07-03 19:32:11 +02:00
Line2 . setSeparator ( ) ;
2021-07-04 21:32:53 +02:00
New . addAccelerator ( FKey : : Meta_n ) ;
New . setStatusbarMessage ( " Debuter une nouvelle partie " ) ;
2021-07-03 19:32:11 +02:00
Quit . addAccelerator ( FKey : : Meta_x ) ;
2021-07-04 21:32:53 +02:00
Quit . setStatusbarMessage ( " Quitter IA86 " ) ;
Run . addAccelerator ( FKey : : Meta_f9 ) ;
Run . setStatusbarMessage ( " Exécuter le programme - seul un breakpoint arrête " ) ;
TraceInto . addAccelerator ( FKey : : F7 ) ;
TraceInto . setStatusbarMessage ( " Pas à pas détaillé - entre dans les CALL " ) ;
StepOver . addAccelerator ( FKey : : F8 ) ;
StepOver . setStatusbarMessage ( " Pas à pas - ne rentre pas dans les CALL " ) ;
Assemble . addAccelerator ( FKey : : F2 ) ;
Assemble . setStatusbarMessage ( " Assemble le source vers du code machine " ) ;
Rearange . addAccelerator ( FKey : : F1 ) ;
Rearange . setStatusbarMessage ( " Reorganise les fenêtres dans leur état initial " ) ;
Breakpoint . addAccelerator ( FKey : : F5 ) ;
Breakpoint . setStatusbarMessage ( " Enlève ou met un point d'arrêt " ) ;
End . addAccelerator ( FKey : : Meta_f2 ) ;
End . setStatusbarMessage ( " Termine le programme et remet à zéro la machine IA86 " ) ;
About . setStatusbarMessage ( " A propos de IA86 " ) ;
2021-07-04 19:20:46 +02:00
}
void Menu : : initMenusCallBack ( )
{
2021-07-03 19:32:11 +02:00
Quit . addCallback
(
" clicked " ,
finalcut : : getFApplication ( ) ,
& finalcut : : FApplication : : cb_exitApp ,
this
) ;
2021-07-04 21:32:53 +02:00
Assemble . addCallback
2021-07-04 19:20:46 +02:00
(
" clicked " ,
this ,
& Menu : : compile
) ;
2021-07-05 13:53:01 +02:00
Run . addCallback
(
" clicked " ,
this ,
& Menu : : exec
) ;
2021-07-04 21:32:53 +02:00
Rearange . addCallback
(
" clicked " ,
this ,
& Menu : : initWindows
) ;
2021-07-05 13:53:01 +02:00
TraceInto . addCallback
(
" clicked " ,
this ,
& Menu : : trace
) ;
StepOver . addCallback
(
" clicked " ,
this ,
& Menu : : step
) ;
2021-07-03 19:32:11 +02:00
}
2021-07-04 19:20:46 +02:00
void Menu : : initMisc ( )
{
Info < < " █████ █████████ ████████ ████████ \n "
< < " ░░███ ███░░░░░███ ███░░░░███ ███░░░░███ \n "
< < " ░███ ░███ ░███ ░███ ░███ ░███ ░░░ \n "
< < " ░███ ░███████████ ░░████████ ░█████████ \n "
< < " ░███ ░███░░░░░███ ███░░░░███ ░███░░░░███ \n "
< < " ░███ ░███ ░███ ░███ ░███ ░███ ░███ \n "
< < " █████ █████ █████░░████████ ░░████████ \n "
< < " ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ ░░░░░░░░ \n "
< < " THE EVEN MORE PEDAGOGICAL SYSTEM !! \n "
< < " \n "
< < " Episode 1 : Apprendre l'assembleur X86 " ;
Statusbar . setMessage ( " THE EVEN MORE PEDAGOGICAL SYSTEM !! " ) ;
2021-07-03 19:32:11 +02:00
}
void Menu : : initLayout ( )
{
Info . setGeometry ( FPoint { 2 , 1 } , FSize { 43 , 12 } ) ;
FDialog : : initLayout ( ) ;
}
void Menu : : adjustSize ( )
{
const auto pw = int ( getDesktopWidth ( ) ) ;
const auto ph = int ( getDesktopHeight ( ) ) ;
2021-07-04 19:20:46 +02:00
setX ( 1 + ( pw - int ( getWidth ( ) ) ) / 2 , false ) ;
setY ( 1 + ( ph - int ( getHeight ( ) ) ) / 4 , false ) ;
2021-07-03 19:32:11 +02:00
finalcut : : FDialog : : adjustSize ( ) ;
}
void Menu : : onClose ( finalcut : : FCloseEvent * ev )
{
finalcut : : FApplication : : closeConfirmationDialog ( this , ev ) ;
}
2021-07-04 19:20:46 +02:00
void Menu : : setGoal ( int num )
{
scenario = num ;
loadGoal ( ) ;
2021-07-04 11:15:24 +02:00
}
2021-07-03 19:32:11 +02:00
2021-07-04 19:20:46 +02:00
void Menu : : loadGoal ( )
{
view . setText ( " Objectif: " + goals [ scenario ] . title ) ;
view . append ( goals [ scenario ] . description ) ;
edit . set ( goals [ scenario ] . code ) ;
}
2021-07-03 19:32:11 +02:00
2021-07-04 19:20:46 +02:00
void Menu : : compile ( )
{
2021-07-05 13:53:01 +02:00
code = asmer . Assemble ( edit . get ( ) , goals [ scenario ] . init . dump . regs . eip ) ;
2021-07-05 15:00:22 +02:00
debug . set ( unasmer . Desassemble ( code ) ) ;
2021-07-05 13:53:01 +02:00
}
void Menu : : verify ( )
{
2021-07-05 15:00:22 +02:00
2021-07-04 19:20:46 +02:00
}
void Menu : : exec ( )
{
2021-07-05 15:00:22 +02:00
if ( ! code - > assembled )
{
finalcut : : FMessageBox : : error ( this , " Vous devez compiler le source d'abord ! " ) ;
return ;
}
vm . Configure ( & goals [ scenario ] . init , code ) ;
2021-07-05 13:53:01 +02:00
}
void Menu : : trace ( )
{
2021-07-05 15:00:22 +02:00
if ( ! code - > assembled )
{
finalcut : : FMessageBox : : error ( this , " Vous devez compiler le source d'abord ! " ) ;
return ;
} }
2021-07-05 13:53:01 +02:00
void Menu : : step ( )
{
2021-07-05 15:00:22 +02:00
if ( ! code - > assembled )
{
finalcut : : FMessageBox : : error ( this , " Vous devez compiler le source d'abord ! " ) ;
return ;
} }
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
2021-07-04 19:20:46 +02:00
// Fonction Main
2021-07-03 19:32:11 +02:00
//----------------------------------------------------------------------
int main ( int argc , char * argv [ ] )
{
2021-07-04 11:15:24 +02:00
2021-07-03 19:32:11 +02:00
finalcut : : FApplication app { argc , argv } ;
Menu main_dlg { & app } ;
2021-07-04 15:13:35 +02:00
main_dlg . setText ( " IA86 " ) ;
2021-07-03 19:32:11 +02:00
main_dlg . setSize ( { 50 , 14 } ) ;
main_dlg . setShadow ( ) ;
main_dlg . show ( ) ;
2021-07-04 19:20:46 +02:00
finalcut : : FWidget : : setMainWidget ( & main_dlg ) ;
//usleep(5 * 1000000);
main_dlg . hide ( ) ;
2021-07-03 15:29:13 +02:00
return app . exec ( ) ;
}