Compare commits

..

No commits in common. "develop" and "master" have entirely different histories.

8 changed files with 0 additions and 2712 deletions

4
.gitignore vendored
View File

@ -1,4 +0,0 @@
ia86
*.old
lib*
a.out

View File

@ -1,61 +0,0 @@
FROM alpine:3.13.0
ENV UNICORN_VER 1.0.3
ENV CAPSTONE_VER 4.0.2
ENV KEYSTONE_VER 0.9.2
RUN echo "http://alpine.42.fr/v3.13/main" > /etc/apk/repositories
RUN echo "http://alpine.42.fr/v3.13/community" >> /etc/apk/repositories
RUN apk --no-cache update
RUN apk --no-cache upgrade
RUN apk --no-cache add bash util-linux coreutils curl make cmake gcc g++ libstdc++ libgcc \
git sed tar wget gzip indent binutils autoconf automake autoconf-archive\
libtool linux-headers ncurses-dev python3-dev
WORKDIR /usr/src
RUN wget https://github.com/unicorn-engine/unicorn/archive/${UNICORN_VER}.tar.gz && tar -xzf ${UNICORN_VER}.tar.gz
WORKDIR /usr/src/unicorn-${UNICORN_VER}
RUN UNICORN_ARCHS="x86" ./make.sh && UNICORN_ARCHS="x86" ./make.sh install
WORKDIR /usr/src
RUN wget https://github.com/keystone-engine/keystone/archive/${KEYSTONE_VER}.tar.gz && tar -xzf ${KEYSTONE_VER}.tar.gz
RUN ls
WORKDIR /usr/src/keystone-${KEYSTONE_VER}
RUN mkdir build
WORKDIR /usr/src/keystone-${KEYSTONE_VER}/build
RUN cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DLLVM_TARGETS_TO_BUILD="X86" -G "Unix Makefiles" ..
RUN make -j8
RUN make install
RUN MAKE_INSTALL_PREFIX=/usr CMAKE_BUILD_TYPE=Release BUILD_SHARED_LIBS=ON LLVM_TARGETS_TO_BUILD="X86" ../make-lib.sh
RUN cp /usr/src/keystone-0.9.2/build/llvm/lib64/libkeystone.a /usr/lib64/
WORKDIR /usr/src
RUN wget https://github.com/aquynh/capstone/archive/${CAPSTONE_VER}.tar.gz && tar -xzf ${CAPSTONE_VER}.tar.gz
WORKDIR /usr/src/capstone-${CAPSTONE_VER}
RUN CAPSTONE_ARCHS="x86" CAPTONE_X86_REDUCE="yes" ./make.sh && CAPSTONE_ARCHS="x86" CAPTONE_X86_REDUCE="yes" ./make.sh install
WORKDIR /usr/src
RUN git clone https://github.com/bk192077/struct_mapping.git
WORKDIR /usr/src/struct_mapping
RUN mkdir build
WORKDIR /usr/src/struct_mapping/build
RUN cmake .. && cmake --build . && cmake --install .
WORKDIR /usr/src
RUN git clone https://github.com/dahut87/finalcut.git
WORKDIR /usr/src/finalcut
RUN autoreconf --install --force && ./configure --prefix=/usr && make && make install
WORKDIR /usr/src
RUN git clone https://github.com/madler/zlib.git
WORKDIR /usr/src/zlib
RUN ./configure && make && make install prefix=/usr/
RUN apk --no-cache add ncurses-static
RUN adduser -D -H -u 502 utilisateur
RUN adduser -D -H -u 1000 utilisateurs
RUN mkdir /data
WORKDIR /data
ENV LD_LIBRARY_PATH /usr/lib64

View File

@ -1,44 +0,0 @@
CC=g++ -O2 -static
LFLAGS=-lfinal -lkeystone -lstdc++ -lm -lcapstone -lunicorn -lz -lncursesw
OPTIONS=-std=c++17
DOCKER=docker run --name maker --rm -v $$(pwd):/data maker
START=./start.sh
all: dockerfile run
clean: dockerclean
clear:
clear
dockerclean:
(docker rmi $$(docker images | grep "^<none>" | awk '{print $$3}') --force;true)
(docker rmi maker;true)
docker image ls
dockerfile:
docker build . -t maker
dockerfile_force: dockerclean dockerfile
compile: ./ia86
ia86: ./ia86.cpp
$(DOCKER) $(CC) $(OPTIONS) -o $@ $^ $(LFLAGS)
rerun:
$(START)
redebug:
$(START) debug
run: clear delete compile rerun
debug: clear delete compile redebug
stop:
docker stop maker
delete:
rm -rf ./ia86

View File

@ -1,60 +0,0 @@
```
█████ █████████ ████████ ████████
░░███ ███░░░░░███ ███░░░░███ ███░░░░███
░███ ░███ ░███ ░███ ░███ ░███ ░░░
░███ ░███████████ ░░████████ ░█████████
░███ ░███░░░░░███ ███░░░░███ ░███░░░░███
░███ ░███ ░███ ░███ ░███ ░███ ░███
█████ █████ █████░░████████ ░░████████
░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ ░░░░░░░░
THE EVEN MORE PEDAGOGICAL SYSTEM !!
Episode 1 : Apprendre l'assembleur X86
```
## Descriptif
IA86 est un logiciel pour apprendre l'assembleur et la programmation système. Celui-ci se présente sous la forme d'un jeu assorti de plusieurs niveaux à la difficulté croissante. Progressivement le joueur acquier les concepts fondamentaux de l'informatique système au travers des différents défis à relever. Une machine virtuelle permet de vérifier que le code écrit par le joueur rempli les objectifs du niveau.
## Structure
Ecrit en C++, IA86 s'appuie sur la célèbre trilogie de librairies :
* Capstone (Désassembleur) - https://www.capstone-engine.org/
* Keystone (Assembleur) - https://www.keystone-engine.org/
* Unicore (Emulateur de processeur) - https://www.unicorn-engine.org/
L'interface est basée sur un système de fenêtre en terminal afin de préserver un style "ancien système" (librairie FinalCut, f - https://github.com/gansm/finalcut).
## Developpement
La compilation du logiciel s'opère par g++ au travers d'un conteneur docker afin d'assurer de disposer d'un environnement de compilation sur mesure et d'une reproductibilité totale. Un makefile permet de centraliser les différentes tâches au sein d'un même fichier.
Pour compiler
```
make all
```
Pour lancer le logiciel
```
make rerun
```
ou
```
./start.sh"
```
En mode déboguage (avec plus d'informations)
```
make redebug
```
ou
```
./start.sh debug"
```

1892
ia86.cpp

File diff suppressed because it is too large Load Diff

485
ia86.h
View File

@ -1,485 +0,0 @@
using namespace std;
using std::cout; using std::endl;
using std::vector; using std::string;
using FKey = finalcut::FKey;
using finalcut::FColor;
using finalcut::FPoint;
using finalcut::FRect;
using finalcut::FSize;
//----------------------------------------------------------------------
// Types & classes mineures
//----------------------------------------------------------------------
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_segs
{
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_segs segs;
struct i386_regs regs;
uint32_t flags;
} __attribute__ (( packed ));
struct State {
i386_all_regs dump;
std::string code;
};
struct Level {
std::string title;
std::string description;
std::string tutorial;
std::string code;
int rights;
State init;
State goal;
};
struct Scenario {
std::string title;
std::vector<Level> levels;
bool loaded;
};
struct Code
{
uint32_t address;
size_t size;
std::string name;
uint8_t *content;
bool assembled;
bool loaded;
std::string src;
};
struct Unasm
{
std::vector<std::array<std::string, 4>> src;
std::vector<uint32_t> pos;
};
class Error: public exception
{
public:
Error(string const& phrase="") throw()
:m_phrase(phrase)
{}
virtual const char* what() const throw()
{
return m_phrase.c_str();
}
virtual ~Error() throw()
{}
private:
string m_phrase;
};
class ScenarioWindow final : public finalcut::FDialog
{
public:
// Constructor
explicit ScenarioWindow (finalcut::FWidget* = nullptr);
// Disable copy constructor
ScenarioWindow (const ScenarioWindow&) = delete;
// Destructor
~ScenarioWindow() override = default;
// Disable copy assignment operator (=)
ScenarioWindow& operator = (const ScenarioWindow&) = delete;
// Method
void Load(std::vector<Level> items);
private:
// Method
void click();
void initLayout() override;
void adjustSize() override;
// Data members
finalcut::FListView listview{this};
};
class CodeWindow final : public finalcut::FDialog
{
public:
// Constructor
explicit CodeWindow (finalcut::FWidget* = nullptr);
// Disable copy constructor
CodeWindow (const CodeWindow&) = delete;
// Destructor
~CodeWindow() override = default;
// Disable copy assignment operator (=)
CodeWindow& operator = (const CodeWindow&) = delete;
// Method
std::vector<std::array<std::string, 7>> get();
void set(std::vector<std::array<std::string, 7>> src);
void clear();
int getindex();
int getsize();
private:
// Method
std::vector<std::array<std::string, 7>> content;
void initLayout() override;
void adjustSize() override;
// Data members
finalcut::FListView listview{this};
};
class InstructionWindow final : public finalcut::FDialog
{
public:
// Constructor
explicit InstructionWindow (finalcut::FWidget* = nullptr);
// Disable copy constructor
InstructionWindow (const InstructionWindow&) = delete;
// Destructor
~InstructionWindow() override = default;
// Disable copy assignment operator (=)
InstructionWindow& operator = (const InstructionWindow&) = delete;
// Method
std::vector<std::array<std::string, 4>> get();
void set(std::vector<std::array<std::string, 4>> src);
void clear();
int getindex();
void setmultimark(std::vector<int> mark);
void setmark(int index);
int getsize();
std::string getaddress();
private:
// Method
std::vector<std::array<std::string, 4>> content;
void initLayout() override;
void adjustSize() override;
// Data members
finalcut::FListView listview{this};
};
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
void append(const finalcut::FString&);
void clear();
std::string get();
void set(const finalcut::FString&);
private:
// Method
void onClose(finalcut::FCloseEvent*) override;
void initLayout() override;
void adjustSize() override;
// Data members
finalcut::FTextView scrolltext{this};
};
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
void append(const finalcut::FString&);
void clear();
std::string get();
void set(const finalcut::FString&);
private:
// Method
void onClose(finalcut::FCloseEvent*) override;
void initLayout() override;
void adjustSize() override;
// Data members
finalcut::FTextView scrolltext{this};
};
class Menu;
class Desassembler
{
public:
Desassembler(Menu *widget);
void setSyntax(int syntax);
void Desassemble(uint8_t *content, uint32_t address,uint32_t size, Unasm *unasm);
private:
csh handle;
cs_insn *insn;
int err;
Menu *widget;
TextEditWindow *edit;
size_t srcsize;
size_t codesize;
std::vector<std::array<std::string, 4>> src;
unsigned char *src_char = new unsigned char[64*1024];
};
class Assembler
{
public:
Assembler(Menu *widget);
void setSyntax(int syntax);
void Assemble(Code *code);
std::vector<Code> MultiAssemble(std::string source,uint32_t address);
private:
ks_engine *ks;
ks_err err;
int err2;
Menu *widget;
TextEditWindow *edit;
};
class VMEngine
{
public:
VMEngine(Menu *widget);
void Configure(State *init, std::string code);
void Halt();
void Unconfigure();
uint32_t getCurrent();
void setSyntax(int asmsyntax,int unasmsyntax);
void Run(bool astep, bool acall, uint64_t timeout);
std::string getFlags();
std::string getRegs();
std::string getStack();
std::vector<std::array<std::string, 4>> getInstr(int segment, int address,int size);
std::vector<std::array<std::string, 7>> getCode();
void SetMem(Code *code);
void SetRegs(State *init);
std::string getRam(int segment, int address,int lines, int linesize);
int verify();
bool isExecuted();
bool isInitialized();
void setRights(int rights);
void clearbreakpoints();
void addbreakpoint(uint16_t segment, uint32_t address);
void removebreakpoint(uint16_t segment, uint32_t address);
std::vector<int> getBreapoints();
int getLine();
uint32_t getEIP();
uint32_t getESI();
uint32_t getEDI();
uint32_t getESP();
uint32_t getEBP();
uint16_t getCS();
uint16_t getDS();
uint16_t getES();
uint16_t getSS();
private:
int rights;
void Init();
void Close();
uc_engine *uc;
uc_err err;
int bufferaddress;
int address_old;
uint8_t *code;
uLong crc,crc_old;
std::vector<Code> mcode;
Menu *widget;
Assembler asmer{widget};
Desassembler unasmer{widget};
};
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
void loadLevel(int alevel);
void closeLevel();
void tolog(std::string str);
std::vector<std::array<std::string, 4>> getsrc();
void SetScreen(uint16_t x, uint16_t y, char value);
private:
void onTimer (finalcut::FTimerEvent*) override;
void refresh();
void configureFileMenuItems();
void initMenusCallBack ();
void initMenus();
void initMisc();
void compile();
void end();
void loadScenario(std::string file);
void showInstr();
void addbp();
void exec();
void trace();
void step();
void about();
void changesyntax();
void ClearScreen();
void AdjustWindows();
void initWindows();
void openscenar();
void closescenar();
void initLayout() 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};
finalcut::FMenu Game{"&Partie", &Menubar};
finalcut::FMenuItem New{"&Nouvelle partie", &Game};
finalcut::FMenuItem Open{"&Ouvrir une partie", &Game};
finalcut::FMenuItem Save{"&Sauver la partie", &Game};
finalcut::FMenuItem Close{"&Fermer une partie", &Game};
finalcut::FMenuItem Line2{&Game};
finalcut::FMenuItem OpenScenar{"&Ouvrir un scénario", &Game};
finalcut::FMenuItem CloseScenar{"&Fermer un scénario", &Game};
finalcut::FMenuItem Line3{&Game};
finalcut::FMenuItem Quit{"&Quitter", &Game};
finalcut::FMenu Views{"&vues", &Menubar};
finalcut::FRadioMenuItem Rearange1{"&Scénarios", &Views};
finalcut::FRadioMenuItem Rearange3{"&Objectifs", &Views};
finalcut::FRadioMenuItem Rearange{"&Deboguage", &Views};
finalcut::FRadioMenuItem Rearange2{"&Données", &Views};
finalcut::FMenu Tools{"&Outils", &Menubar};
finalcut::FMenuItem Assemble{"&Assembler", &Tools};
finalcut::FMenu Debug{"&Exécution", &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::FMenu Breakpoint{"&Point d'arrêt", &Menubar};
finalcut::FMenuItem AddBp{"&Ajouter", &Breakpoint};
finalcut::FMenuItem ClearBp{"&Supprimer", &Breakpoint};
finalcut::FMenuItem ClearAllBp{"&Tout supprimer", &Breakpoint};
finalcut::FMenu Options{"&Options", &Menubar};
finalcut::FMenu Memory{"&Visualisateur Mémoire", &Options};
finalcut::FRadioMenuItem Ds_000{"DS:0000", &Memory};
finalcut::FRadioMenuItem Ds_esi{"DS:ESI", &Memory};
finalcut::FRadioMenuItem Es_edi{"ES:EDI", &Memory};
finalcut::FRadioMenuItem Cs_eip{"CS:EIP", &Memory};
finalcut::FRadioMenuItem Ss_esp{"SS:ESP", &Memory};
finalcut::FRadioMenuItem Ss_FFF{"SS:FFFF", &Memory};
finalcut::FRadioMenuItem Value{"Valeur...", &Memory};
finalcut::FMenu Code{"&Syntaxe", &Options};
finalcut::FCheckMenuItem AsmAtt{"Assembleur AT&T", &Code};
finalcut::FCheckMenuItem UnasmAtt{"Désassembleur AT&T", &Code};
finalcut::FDialogListMenu Window{"&Fenêtres", &Menubar};
finalcut::FMenu Help{"&Aide", &Menubar};
finalcut::FMenuItem About{"&A propos", &Help};
finalcut::FTextView Log{this};
finalcut::FStatusBar Statusbar{this};
TextWindow info{this};
TextWindow view{this};
InstructionWindow debug{this};
CodeWindow codes{this};
TextWindow regs{this};
TextWindow flags{this};
TextWindow stack{this};
TextWindow mem{this};
TextWindow tuto{this};
TextWindow screen{this};
TextEditWindow edit{this};
ScenarioWindow scenar{this};
VMEngine vm{this};
};

View File

@ -1,140 +0,0 @@
{
"scenario_titre" : "Scénario de Nicolas H.",
"scenario_objectifs" :
[
{
"niveau_titre" : "Les bases...",
"niveau_description" : "Il faut connaitre...",
"niveau_tutoriel" : "Ceci vous...",
"niveau_code" : "mov ax,0x545
inc dx
.title test
mov esi,0x44440234
syscall
mov ax,0x9000
mov ss,ax
mov ax,0xFFFF
mov sp,ax
mov cx,10
go:
push cx
dec cx
cmp cx,0
jnz go
hlt
jmp 0x14D
.org 0x8D
.title next
mov es,ax
.org 0x14D
mov es,ax
",
"niveau_droits" : 10,
"niveau_initial" :
{
"registres" :
{
"segments" :
{
"cs" : 0000,
"ds" : 0000,
"ss" : 0000,
"es" : 0000,
"fs" : 0000,
"gs" : 0000
},
"généraux" :
{
"eax" : 0,
"ebx" : 0,
"ecx" : 0,
"edx" : 0,
"esi" : 0,
"edi" : 0,
"esp" : 0,
"ebp" : 0,
"eip" : 0
},
"drapeaux" : 1
},
"code" : "ceci est le code"
},
"niveau_objectif" :
{
}
},
{
"niveau_titre" : "Suite",
"niveau_description" : "Il faut connaitre...",
"niveau_tutoriel" : "Ceci vous...",
"niveau_code" : "mov ax,0x9000
mov ss,ax
mov ax,0xFFFF
mov sp,ax
_pour:
lea si,[msg]
call show
int 21
hlt
show:
push ax
push es
push di
push cx
mov ax,0xB800
mov es,ax
mov di,(80*2+40)*2
mov cx,16
mov al,0
boucle:
movsb
stosb
dec cx
cmp cx,0
jnz boucle
pop cx
pop di
pop es
pop ax
ret
msg:
db 'c','e','c','i',' ','e','s','t',' ','u','n',' ','t','e','s','t',0
.org 0x1000
hlt",
"niveau_droits" : 10,
"niveau_initial" :
{
"registres" :
{
"segments" :
{
},
"généraux" :
{
"eax" : 0,
"ebx" : 0,
"ecx" : 0,
"edx" : 0,
"esi" : 0,
"edi" : 0,
"esp" : 0,
"ebp" : 0,
"eip" : 0
},
"drapeaux" : 1
},
"code" : "ceci est le code"
},
"niveau_objectif" :
{
}
}
]
}

View File

@ -1,26 +0,0 @@
#!/bin/bash
X=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f1)
Y=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f2)
KITTY=$(kitty -v|grep created)
if [ "${KITTY}" != "" ]; then
echo "Utilisation de Kitty..."
if [ ${X} -ge 1920 ]; then
kitty --start-as fullscreen ./ia86 $1
exit
fi
fi
if [ ${X} -ge 1920 ]; then
SIZE=11
elif [ ${X} -ge 1680 ]; then
SIZE=10
elif [ ${X} -ge 1440 ]; then
SIZE=9
elif [ ${X} -ge 1368 ]; then
SIZE=8
elif [ ${X} -ge 1280 ]; then
SIZE=7
else
SIZE=6
fi
echo "Utilisation de xTerm..."
xterm -fullscreen -fa monaco -fs ${SIZE} -bg black -fg green -e "sleep 0.4;./ia86 $1"