about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..34f73e1
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,179 @@
+use r2pipe::R2Pipe;
+use structopt::StructOpt;
+use std::path::PathBuf;
+use std::time::Duration;
+
+// we're using a custom int type here, as we want to set defaults using
+// structopt which leads to a problem, as structopt only allows strings to be
+// set as default values ()
+#[derive(Debug)]
+struct Int(u64);
+
+impl std::str::FromStr for Int {
+    type Err = Box<dyn std::error::Error>;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(Int(s.parse::<u64>().unwrap()))
+    }
+}
+impl std::fmt::Display for Int {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
+// we're using a custom "Delay" type here, as we want to define the duration
+// #of a game round, but structopt (as with the int stuff above) can't use time
+// durations (it's time, not easy!). [derive(Debug)]
+#[derive(Debug)]
+struct Delay(Duration);
+
+impl std::str::FromStr for Delay {
+    type Err = Box<dyn std::error::Error>;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(Delay(Duration::from_secs(s.parse::<u64>().unwrap())))
+    }
+}
+
+#[derive(Debug)]
+struct Bot {
+	// Path defines the path to the source of the bot
+    path: PathBuf,
+
+	// Source defines the source of the bot after being compiled with rasm2
+    source: Option<String>,
+
+	// Addr defines the initial address the bot is placed at
+    addr: Option<u64>,
+
+	// Regs defines the state of the registers of the bot
+	// It is used to store the registers after each round and restore them in the
+	// next round when the bot's turn has come
+    regs: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Clone)]
+struct BotPaths(Vec<String>);
+
+impl std::str::FromStr for BotPaths {
+    type Err = Box<dyn std::error::Error>;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(BotPaths(s.split(",").map(|x| x.trim().to_owned()).collect()))
+    }
+}
+
+// these are the options you can use, list them nicely using
+// `cargo run -- --help`
+#[derive(Debug, StructOpt)]
+#[structopt(about = "Yet another r2wars implementation, made with <3 @ AFRA Berlin")]
+struct Opt {
+
+    #[structopt(short = "a", long = "arch", default_value = "x86")]
+    architecture: String,
+
+    #[structopt(short = "b", long = "bits", default_value = "64")]
+    bits: Int,
+
+    #[structopt(long = "memsize", default_value = "4096")]
+    memory_size: Int,
+
+    #[structopt(long = "maxbotsize", default_value = "256")]
+    max_bot_size: Int,
+
+    #[structopt(long = "bots", default_value = "bots/warrior0.asm, bots/warrior1.asm")]
+    bots: BotPaths,
+
+    #[structopt(long = "delay", default_value = "1")]
+    game_round_duration_seconds: Delay,
+}
+
+fn init_arena(r2p: &mut R2Pipe, opt: &Opt) {
+    println!("[ ] Initializing the arena");
+    println!("[ ] Allocating {} bytes of memory...", opt.memory_size);
+
+    let _ = r2p.cmd(format!("malloc://{}", opt.memory_size).as_str())
+                .expect("could not allocate memory");
+    
+    println!("[ ] General configuration...");
+    let _ = r2p.cmd(format!("e asm.arch = {}", opt.architecture).as_str())
+                .expect("could not set the desired architecture");
+    let _ = r2p.cmd(format!("e asm.bits = {}", opt.bits).as_str())
+                .expect("could not set the desired bits");
+    println!("[ ]     ...Done");
+
+    println!("[ ] Theming...");
+    let _ = r2p.cmd("e scr.color = 3").expect("set color err");
+    let _ = r2p.cmd("e scr.color.args = true").expect("set color err");
+    let _ = r2p.cmd("e scr.color.bytes = true").expect("set color err");
+    let _ = r2p.cmd("e scr.color.grep = true").expect("set color err");
+    let _ = r2p.cmd("e scr.color.ops = true").expect("set color err");
+    let _ = r2p.cmd("e scr.color.pipe = true").expect("set color err");
+    let _ = r2p.cmd("e scr.bgfill = true").expect("set color err");
+    let _ = r2p.cmd("e scr.utf8 = true").expect("set color err");
+    let _ = r2p.cmd("e hex.cols = 32").expect("set hex col width err");
+    println!("[ ]     ...Done");
+
+    println!("[ ] ESIL...");
+    let _ = r2p.cmd("aei").expect("init esil vm failed"); // init ESIL VM
+    let _ = r2p.cmd("aeim").expect("init esil vm stack failed"); // init ESIL VM stack
+    println!("[ ]     ...Done");
+}
+
+fn build_bots(opt: &Opt, bots: &mut Vec<Bot>) {
+    for bot_path in opt.bots.0.clone().into_iter() {
+        bots.push(
+            build_bot(PathBuf::from(bot_path))
+                .expect("could not build a bot!")
+        )
+    }
+}
+
+fn build_bot(bot_path: PathBuf) -> Result<Bot, ()> {
+
+    let mut r2p = r2pipe::open_pipe!(Some("--").to_owned()).expect("could not open r2pipe");
+
+    let source = r2p.cmd(format!("rasm2 -a {} -b {} -f {:?}", "x86", "32", bot_path).as_str())
+        .expect("failed to build the bot!");
+    
+    let new_bot: Bot = Bot {
+        path: bot_path,
+        source: Some(source),
+        addr: None, 
+        regs: None, 
+    };
+    
+    Ok(new_bot)
+}
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let mut bots: Vec<Bot> = vec![];
+    
+    let opt = Opt::from_args();
+
+    println!("{:?}", opt.architecture);
+    println!("{:?}", opt.bits);
+    println!("{:?}", opt.memory_size);
+    println!("{:?}", opt.max_bot_size);
+    println!("{:?}", opt.bots);
+    println!("{:?}", opt.game_round_duration_seconds);
+
+    let path = Some("/Users/emilehansmaennel/Documents/CTF/2023/indore/Lengan/main_fixed".to_owned());
+    let mut r2p = r2pipe::open_pipe!(path).expect("could not open r2pipe");
+
+    init_arena(&mut r2p, &opt);
+
+    build_bots(&opt, &mut bots);
+
+    for bot in bots {
+        println!("{:?}", bot);
+    }
+    
+    // println!("{}", r2p.cmd("?e Hello World").expect("could not exec command"));
+    // println!("{}", r2p.cmd("aaa").expect("could not exec command"));
+    // println!("---");
+    // println!("{}", r2p.cmd("afl").expect("could not exec command"));
+    // println!("---");
+    r2p.close();
+
+    Ok(())
+}