Ajout du chargement de fichiers de scenarios, mise en place de code multizones avec directive .org

This commit is contained in:
Horde Nicolas 2021-07-08 12:06:23 +02:00
parent 98db70cd7f
commit d9531cd143
5 changed files with 215 additions and 113 deletions

View File

@ -1,21 +1,16 @@
FROM alpine:3.12.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.12/main" > /etc/apk/repositories
RUN echo "http://alpine.42.fr/v3.12/community" >> /etc/apk/repositories
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 zlib-dev \
git sed tar wget gzip indent binutils hexdump dos2unix xxd autoconf automake autoconf-archive\
libtool linux-headers ncurses-dev
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 wget https://github.com/unicorn-engine/unicorn/archive/${UNICORN_VER}.tar.gz && tar -xzf ${UNICORN_VER}.tar.gz
WORKDIR /usr/src/unicorn-${UNICORN_VER}
@ -38,6 +33,18 @@ RUN wget https://github.com/aquynh/capstone/archive/${CAPSTONE_VER}.tar.gz && ta
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
RUN adduser -D -H -u 502 utilisateur
RUN adduser -D -H -u 1000 utilisateurs
RUN mkdir /data

View File

@ -1,17 +1,24 @@
CC=g++ -O2
LFLAGS=-lfinal -lkeystone -lstdc++ -lm -lcapstone -lunicorn
OPTIONS=-std=c++17
DOCKER=docker run -it -e COLUMNS="$$(tput cols)" -e LINES="$$(tput lines)" --name maker --rm -v $$(pwd):/data maker
XTERM=terminator -f -e
all: dockerfile files run
clean: dockerclean
dockerclean:
(docker rmi $$(docker images | grep "^<none>" | awk '{print $$3}') --force;true)
docker image ls
dockerfile:
docker build . -t maker
files: ./ia86
ia86: ./ia86.cpp
$(DOCKER) $(CC) -o $@ $^ $(LFLAGS)
$(DOCKER) $(CC) $(OPTIONS) -o $@ $^ $(LFLAGS)
run:
$(XTERM) '$(DOCKER) bash -c "sleep 0.4;./ia86"'

206
ia86.cpp
View File

@ -1,6 +1,7 @@
#include <final/final.h>
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <string>
#include <sstream>
#include <iomanip>
@ -10,6 +11,7 @@
#include <vector>
#include "ia86.h"
#include "struct_mapping/struct_mapping.h"
//----------------------------------------------------------------------
// Fonctions diverses
@ -24,52 +26,53 @@ std::string intToHexString(int intValue, int size) {
return hexStr;
}
//----------------------------------------------------------------------
// Objectifs de jeux
//----------------------------------------------------------------------
void mapping()
{
struct_mapping::reg(&Scenario::title, "scenario_titre");
struct_mapping::reg(&Scenario::Levels, "scenario_objectifs");
struct_mapping::reg(&Level::title, "niveau_titre");
struct_mapping::reg(&Level::description, "niveau_description");
struct_mapping::reg(&Level::tutorial, "niveau_tutoriel");
struct_mapping::reg(&Level::code, "niveau_code");
struct_mapping::reg(&Level::level, "niveau_droits");
struct_mapping::reg(&Level::init, "niveau_initial");
struct_mapping::reg(&Level::goal, "niveau_objectif");
struct_mapping::reg(&State::dump, "registres");
struct_mapping::reg(&State::memzone, "memoires");
struct_mapping::reg(&i386_all_regs::segs, "segments");
struct_mapping::reg(&i386_all_regs::regs, "généraux");
struct_mapping::reg(&i386_all_regs::flags, "drapeaux");
struct_mapping::reg(&i386_segs::cs, "cs");
struct_mapping::reg(&i386_segs::ss, "ss");
struct_mapping::reg(&i386_segs::ds, "ds");
struct_mapping::reg(&i386_segs::es, "es");
struct_mapping::reg(&i386_segs::fs, "fs");
struct_mapping::reg(&i386_segs::gs, "gs");
struct_mapping::reg(&i386_regs::eax, "eax");
struct_mapping::reg(&i386_regs::ebx, "ebx");
struct_mapping::reg(&i386_regs::ecx, "ecx");
struct_mapping::reg(&i386_regs::edx, "edx");
struct_mapping::reg(&i386_regs::esi, "esi");
struct_mapping::reg(&i386_regs::edi, "edi");
struct_mapping::reg(&i386_regs::esp, "esp");
struct_mapping::reg(&i386_regs::ebp, "ebp");
struct_mapping::reg(&i386_regs::eip, "eip");
}
// Ordre des registres ... IP DI SI BP SP BX DX CX AX
Goal goals[]=
{
{
"L'instruction MOV","Le but est de bouger du registre AX au registre BX, l' ensemble des données", "Aide....", "inc ax\ndec cx\nmov ax,0x33\nadd dx,[bx+2]\nmov cx,12", 1,
{
{
{},
{.bx=0x0002,.ax=0x1920},
0x00000000
},
{}
},
{
{
{},
{.bx=25,.dx=0b101,.cx=0x4650, .ax=0xCCDD},
0x00000000
},
{}
}
},
{
"Les registres","Il est important de...", "Aide....", "add cl,2\nmov si,0X1234", 2,
{
{
{},
{.bx=0x0002,.ax=0x1920},
0x00000000
},
{}
},
{
{
{},
{.bx=25,.dx=0b101,.cx=0x4650, .ax=0xCCDD},
0x00000000
},
{}
}
}
};
Scenario readscenario(std::string filename) {
std::ifstream inFile;
inFile.open(filename);
std::stringstream strStream;
strStream << inFile.rdbuf();
std::string json=strStream.str();
std::istringstream json_data(json);
Scenario scenar;
struct_mapping::map_json_to_struct(scenar, json_data);
return scenar;
}
Scenario scenario;
//----------------------------------------------------------------------
// Classe ScenarioWindow
@ -78,22 +81,18 @@ Goal goals[]=
ScenarioWindow::ScenarioWindow (finalcut::FWidget* parent)
: finalcut::FDialog{parent}
{
scenario=readscenario("./scenarios.txt");
listview.ignorePadding();
listview.addColumn ("Niv");
listview.addColumn ("*");
listview.addColumn ("Intitulé");
listview.addColumn ("Difficulté");
listview.addColumn ("Cycles");
listview.addColumn ("Taille");
listview.hideSortIndicator(true);
listview.setFocus();
std::vector<std::string> items;
for(size_t i=0; i < (sizeof(goals)/sizeof(goals[0])); i++)
for(size_t i=0; i < (sizeof(scenario.Levels)/sizeof(scenario.Levels[0])); i++)
{
items.clear();
items.push_back(to_string(i));
items.push_back(goals[i].title);
items.push_back(to_string(goals[i].level));
items.push_back(scenario.Levels[i].title);
const finalcut::FStringList line (items.begin(), items.end());
listview.insert (line);
}
@ -109,7 +108,7 @@ void ScenarioWindow::click()
const auto& item = listview.getCurrentItem();
std::string temp=item->getText(1).toString();
selected=stoi(temp);
((Menu*)this->getParent())->loadGoal();
((Menu*)this->getParent())->loadLevel();
}
int ScenarioWindow::getselected()
@ -120,7 +119,6 @@ int ScenarioWindow::getselected()
void ScenarioWindow::initLayout()
{
listview.setGeometry (FPoint{1, 2}, FSize{getWidth(), getHeight() - 1});
setMinimumSize (FSize{51, 6});
FDialog::initLayout();
}
@ -406,6 +404,50 @@ VMEngine::VMEngine(TextWindow *log) : log(log)
// Level 10 : EIP EAX EBX ECX EDX EFLAGS ESI EDI ESP EBP CS DS ES SS FS GS ST0 ST1 ST2 ST3 ST4 ST5 ST6 ST7
// Level 11 : EIP EAX EBX ECX EDX EFLAGS ESI EDI ESP EBP CS DS ES SS FS GS ST0 ST1 ST2 ST3 ST4 ST5 ST6 ST7 CR0 CR2 CR3 CR4 CR8
// Level 12 : EIP EAX EBX ECX EDX EFLAGS ESI EDI ESP EBP CS DS ES SS FS GS ST0 ST1 ST2 ST3 ST4 ST5 ST6 ST7 CR0 CR2 CR3 CR4 CR8 DB0 DB1 DB2 DB3 DB6 DB7
std::string VMEngine::getFlags(int level)
{
int eflags=0;
err = uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags);
if (err != UC_ERR_OK)
log->append("Impossible de récupérer le registre: EFLAGS");
std::stringstream out;
out << " CF:" << std::dec << ((eflags & 0x0001));
if (level > 8)
out << " RF:" << std::dec << ((eflags & 0x00010000)>>16) << "\n";
else
out << "\n";
out << " PF:" << std::dec << ((eflags & 0x0004)>>2);
if (level > 8)
out << " VM:" << std::dec << ((eflags & 0x00020000)>>17) << "\n";
else
out << "\n";
out << " AF:" << std::dec << ((eflags & 0x0010)>>4);
if (level > 8)
out << " AC:" << std::dec << ((eflags & 0x00040000)>>18) << "\n";
else
out << "\n";
out << " ZF:" << std::dec << ((eflags & 0x0040)>>6);
if (level > 8)
out << " VIF:" << std::dec << ((eflags & 0x00080000)>>19) << "\n";
else
out << "\n";
out << " SF:" << std::dec << ((eflags & 0x0080)>>7);
if (level > 8)
out << " VIP:" << std::dec << ((eflags & 0x00100000)>>20) << "\n";
else
out << "\n";
out << " TF:" << std::dec << ((eflags & 0x0100)>>8);
if (level > 8)
out << " ID:" << std::dec << ((eflags & 0x00200000)>>21) << "\n";
else
out << "\n";
out << " IF:" << std::dec << ((eflags & 0x0200)>>9) << "\n";
out << " DF:" << std::dec << ((eflags & 0x0400)>>10) << "\n";
out << " OF:" << std::dec << ((eflags & 0x0800)>>11) << "\n";
out << "IOPL:" << std::dec << ((eflags & 0x3000)>>12) << "\n";
out << " NT:" << std::dec << ((eflags & 0x4000)>>13) << "\n";
return out.str();
}
std::string VMEngine::getRegs(int level)
{
@ -697,44 +739,34 @@ void Menu::initNow()
void Menu::initCore()
{
addTimer (50);
loadGoal();
log.append(scenario.title);
loadLevel();
}
void Menu::initWindows()
{
log.setText ("Journaux");
log.setGeometry ( FPoint { 63, 45 }, FSize{60, 11} );
log.setResizeable();
log.show();
edit.setText ("Code source");
edit.setGeometry ( FPoint { 01, 17 }, FSize{39, 27} );
edit.setResizeable();
edit.show();
view.setText ("Objectif");
view.setGeometry ( FPoint { 01, 45 }, FSize{60, 11} );
view.setResizeable();
view.show();
regs.setText ("Registres");
regs.setGeometry ( FPoint { 01, 01 }, FSize{40, 15} );
regs.show();
flags.setText ("Drapeaux");
flags.setGeometry ( FPoint { 60, 01 }, FSize{15, 15} );
stack.setText ("Pile");
stack.setGeometry ( FPoint { 43, 01 }, FSize{15, 15} );
mem.setText ("Mémoire");
mem.setGeometry ( FPoint { 77, 01 }, FSize{108, 15} );
tuto.setText ("Guide");
tuto.setGeometry ( FPoint { 125, 45 }, FSize{60, 11} );
tuto.setResizeable();
tuto.show();
screen.setText ("Ecran");
screen.setGeometry ( FPoint { 105, 18 }, FSize{80, 25} );
debug.setText ("Instructions");
debug.setGeometry ( FPoint { 42, 17 }, FSize{60, 27} );
debug.setResizeable();
debug.show();
scenar.setText ("Scénarios");
scenar.setGeometry ( FPoint { 187, 01 }, FSize{23, 55} );
scenar.setResizeable();
scenar.show();
}
@ -764,7 +796,7 @@ void Menu::AdjustWindows()
tuto.setGeometry ( FPoint { 125, 45 }, FSize{60, 11} );
screen.setGeometry ( FPoint { 105, 18 }, FSize{80, 25} );
debug.setGeometry ( FPoint { 42, 17 }, FSize{60, 27} );
scenar.setGeometry ( FPoint { 187, 01 }, FSize{23, 55} );
scenar.setGeometry ( FPoint { 187, 01 }, FSize{25, 55} );
this->hide();
flags.hide();
stack.hide();
@ -777,13 +809,13 @@ void Menu::AdjustWindows()
tuto.show();
debug.show();
scenar.show();
if (goals[scenar.getselected()].level > 3)
if (scenario.Levels[scenar.getselected()].level > 3)
flags.show();
if (goals[scenar.getselected()].level > 5)
if (scenario.Levels[scenar.getselected()].level > 5)
stack.show();
if (goals[scenar.getselected()].level > 2)
if (scenario.Levels[scenar.getselected()].level > 2)
mem.show();
if (goals[scenar.getselected()].level > 6)
if (scenario.Levels[scenar.getselected()].level > 6)
screen.show();
}
@ -918,19 +950,19 @@ void Menu::onClose (finalcut::FCloseEvent* ev)
finalcut::FApplication::closeConfirmationDialog (this, ev);
}
void Menu::loadGoal()
void Menu::loadLevel()
{
log.append("Chargement du scénario "+goals[scenar.getselected()].title);
view.setText("Objectif: "+goals[scenar.getselected()].title);
log.append("Chargement du scénario "+scenario.Levels[scenar.getselected()].title);
view.setText("Objectif: "+scenario.Levels[scenar.getselected()].title);
view.clear();
view.append(goals[scenar.getselected()].description);
view.append(scenario.Levels[scenar.getselected()].description);
tuto.clear();
tuto.append(goals[scenar.getselected()].help);
tuto.append(scenario.Levels[scenar.getselected()].tutorial);
regs.set("En attente d'initialisation...");
edit.set(goals[scenar.getselected()].code);
edit.set(scenario.Levels[scenar.getselected()].code);
AdjustWindows();
debug.clear();
vm.Configure(&goals[scenar.getselected()].init,code);
vm.Configure(&scenario.Levels[scenar.getselected()].init,code);
end();
}
@ -941,7 +973,7 @@ void Menu::end()
void Menu::compile()
{
code=asmer.Assemble(edit.get(),goals[scenar.getselected()].init.dump.regs.eip);
code=asmer.Assemble(edit.get(),scenario.Levels[scenar.getselected()].init.dump.regs.eip);
debug.set(unasmer.Desassemble(code));
}
@ -974,7 +1006,7 @@ bool Menu::verify()
return false;
}
if (!code->initialized)
vm.Prepare(&goals[scenar.getselected()].init,code);
vm.Prepare(&scenario.Levels[scenar.getselected()].init,code);
if (!code->initialized)
return false;
return true;
@ -984,13 +1016,15 @@ void Menu::refresh()
{
if (!code->initialized)
{
regs.set("En attente d'initialisation...");
debug.setindex(-666);
regs.set("En attente d'initialisation...");
flags.set("Attente...");
//debug.setindex(-666);
}
else
{
regs.set(vm.getRegs(goals[scenar.getselected()].level));
debug.setindex(vm.getEIP(code));
regs.set(vm.getRegs(scenario.Levels[scenar.getselected()].level));
flags.set(vm.getFlags(scenario.Levels[scenar.getselected()].level));
//debug.setindex(vm.getEIP(code));
}
if (!code->executed)
{
@ -1027,7 +1061,7 @@ void Menu::step()
//----------------------------------------------------------------------
int main (int argc, char* argv[])
{
mapping();
finalcut::FApplication app {argc, argv};
Menu main_dlg {&app};
main_dlg.setText ("IA86");

37
ia86.h
View File

@ -90,7 +90,7 @@ using finalcut::FSize;
};
} __attribute__ (( packed ));
struct i386_seg_regs
struct i386_segs
{
uint16_t cs;
uint16_t ss;
@ -102,46 +102,46 @@ using finalcut::FSize;
struct i386_all_regs
{
struct i386_seg_regs segs;
struct i386_segs segs;
struct i386_regs regs;
uint32_t flags;
} __attribute__ (( packed ));
class Memzone
struct Memzone
{
public:
uint32_t address;
uint32_t size;
std::string code;
uint8_t *content;
};
class State {
public:
struct State {
i386_all_regs dump;
std::vector<Memzone> memzone;
};
class Goal {
public:
struct Level {
std::string title;
std::string description;
std::string help;
std::string tutorial;
std::string code;
int level;
State init;
State goal;
};
class Code
struct Scenario {
std::string title;
std::vector<Level> Levels;
};
struct Code
{
public:
uint32_t address;
size_t size;
unsigned char *content;
bool assembled;
bool initialized;
bool executed;
std::vector<Memzone> memzones;
bool assembled;
bool initialized;
bool executed;
};
class ScenarioWindow final : public finalcut::FDialog
@ -280,6 +280,7 @@ class VMEngine
void Configure(State *init,Code *code);
void Halt(Code *code);
void Run(Code *code, uint32_t start, uint32_t stop, uint64_t timeout);
std::string getFlags(int level);
std::string getRegs(int level);
void Prepare(State *init, Code *code);
void SetMem(State *init, Code *code);
@ -305,7 +306,7 @@ class Menu final : public finalcut::FDialog
// Disable copy assignment operator (=)
Menu& operator = (const Menu&) = delete;
// Methods
void loadGoal();
void loadLevel();
private:
Code *code = new Code();
void onTimer (finalcut::FTimerEvent*) override;

53
scenarios.txt Normal file
View File

@ -0,0 +1,53 @@
{
"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
mov esi,0x44441234
hlt",
"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
},
"memoires" :
{
}
},
"niveau_objectif" :
{
}
}
]
}