diff options
author | Emile <git@emile.space> | 2023-04-09 00:37:54 +0200 |
---|---|---|
committer | Emile <git@emile.space> | 2023-04-09 00:37:54 +0200 |
commit | 87142c0cb5f42d877327c357497a5be6f3c5dbd0 (patch) | |
tree | e4b2094315dc16fe680ad0a15587bb0671dea636 | |
parent | 907f5bc763959c3cc2196329a600a8afedebac5a (diff) |
Should work, lol
-rw-r--r-- | README.md | 46 | ||||
-rw-r--r-- | go.mod | 10 | ||||
-rw-r--r-- | go.sum | 25 | ||||
-rw-r--r-- | main.go (renamed from src/init.go) | 235 | ||||
-rw-r--r-- | src/cmd.go | 20 | ||||
-rw-r--r-- | src/config.go | 76 | ||||
-rw-r--r-- | src/logic.go | 17 | ||||
-rw-r--r-- | src/main.go | 27 | ||||
-rw-r--r-- | src/run.go | 84 | ||||
-rw-r--r-- | src/structs.go | 49 |
10 files changed, 257 insertions, 332 deletions
diff --git a/README.md b/README.md index e2887cb..c473557 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,11 @@ -## r2wars +# r2wars-new -The goal of r2wars is to place two bots in as shared memory space and let -them battle against each other until one of them cannot run anymore, because -of some kind of broken instruction. +This is a quick and dirty implementation of r2wars for the easterhegg 20 +workshops I'm giving (It's currently 01:00 of the day of the workshop and I'm +realizing that the code I wrote about 3 years ago is kind of broken). -A more informal README can be found -[here](https://github.com/radareorg/radare2-extras/tree/master/r2wars). - -## Usage - -You'll probably first of all want to simply play with the two provided bots. In -order to do so, run the game like this: - -```go -go run ./... -t 1s -v ./bots/warrior0.asm ./bots/warrior1.asm ``` - -This runs the game with a round duration of 1 second and an info verbosity -level using the two provided bots. You can attach more bots if you'd like, -each bot increases the arena size by 512 bytes by default. - -You can tweak most of the settings as displayed in the help: - -```go -$ go run ./... -h -Usage of src: - -arch string - bot architecture (mips|arm|x86) (default "x86") - -bits int - bot bitness (8|16|32|64) (default 32) - -maxProgSize int - the maximum bot size (default 64) - -memPerBot int - the amount of memory each bot should add to the arena (default 512) - -t duration - The duration of a round (default 250ns) - -v info - -vv - debug - -vvv - trace +; CGO_ENABLED=0 go run ./... -t 1s -v ./bots/warrior0.asm ./bots/warrior1.as ``` + +#worksonmymachine diff --git a/go.mod b/go.mod index 170fcbc..e344fca 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ -module git.darknebu.la/emile/genetic_r2_bots +module github.com/hanemile/r2wars -go 1.13 +go 1.19 require ( - github.com/radare/r2pipe-go v0.0.0-20171013021603-08f2b4f8ca0a - github.com/rainycape/dl v0.0.0-20151222075243-1b01514224a1 // indirect - github.com/sirupsen/logrus v1.4.2 + github.com/radareorg/r2pipe-go v0.2.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect ) diff --git a/go.sum b/go.sum index ecc0ad3..0d37478 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,13 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/radare/r2pipe-go v0.0.0-20171013021603-08f2b4f8ca0a h1:enQJXC+C+uCM0rpONspYMD6+Jf6eYNj4gCD4MIXkP8c= -github.com/radare/r2pipe-go v0.0.0-20171013021603-08f2b4f8ca0a/go.mod h1:xnSZtTv/jeHkBsW7Mg6lJWB8Ke17mg3dMCMRwI16LnM= -github.com/rainycape/dl v0.0.0-20151222075243-1b01514224a1 h1:XZlja+DeIOJeEPWAfM9M5wko0keB9qgRfuuWbry6VBQ= -github.com/rainycape/dl v0.0.0-20151222075243-1b01514224a1/go.mod h1:lh74SQgfeEuNq74dKWzDLuVB+/ntX5c4g1oDyL4GkGg= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/radareorg/r2pipe-go v0.2.1 h1:2bVIi7qHPQCdjjngcJbQO2VHSqPaRBt5LUAMk2uq84o= +github.com/radareorg/r2pipe-go v0.2.1/go.mod h1:HNUWNjS7SjzhZ7McDLhvIBSOLz1X9DNLjj4J52pAj3Y= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/init.go b/main.go index ee6db87..abaf5fa 100644 --- a/src/init.go +++ b/main.go @@ -1,15 +1,141 @@ package main import ( + "flag" "fmt" "math/rand" + "os" "strings" "time" - r2pipe "github.com/radare/r2pipe-go" + "github.com/radareorg/r2pipe-go" "github.com/sirupsen/logrus" ) +// Config defines the meta config +type Config struct { + + // Arch defines the architecture the battle should run in + Arch string + + // Bits defines the bitness + Bits int + + // Memsize defines the arena size + Memsize int + + // MaxProgSize defines the maximal bot size + MaxProgSize int + + // Bots defines a list of bots to take part in the battle + Bots []Bot + + // AmountOfBots defines the amount of bots taking part in the tournament + AmountOfBots int + + // RandomOffsets defines the offset in memory where the bots should be placed + RandomOffsets []int + + // GameRoundTime defines the length of a gameround + GameRoundDuration time.Duration +} + +// Bot defines a bot +type Bot struct { + + // Path defines the path to the source of the bot + Path string + + // Source defines the source of the bot after being compiled with rasm2 + Source string + + // Addr defines the initial address the bot is placed at + Addr int + + // 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 string +} + +func parseConfig() Config { + arch := flag.String("arch", "x86", "bot architecture (mips|arm|x86)") + bits := flag.Int("bits", 32, "bot bitness (8|16|32|64)") + maxProgSize := flag.Int("maxProgSize", 64, "the maximum bot size") + memPerBot := flag.Int("memPerBot", 512, "the amount of memory each bot should add to the arena") + gameRoundDuration := flag.Duration("t", 250*time.Millisecond, "The duration of a round") + + v := flag.Bool("v", false, "info") + vv := flag.Bool("vv", false, "debug") + vvv := flag.Bool("vvv", false, "trace") + + flag.Parse() + + if *v == true { + logrus.SetLevel(logrus.InfoLevel) + } else if *vv == true { + logrus.SetLevel(logrus.DebugLevel) + } else if *vvv == true { + logrus.SetLevel(logrus.TraceLevel) + } else { + logrus.SetLevel(logrus.WarnLevel) + } + + // parse all trailing command line arguments as path to bot sourcecode + amountOfBots := flag.NArg() + + memsize := amountOfBots * *memPerBot + + logrus.WithFields(logrus.Fields{ + "mem per bot": *memPerBot, + "amountOfBots": amountOfBots, + "memsize": memsize, + }).Infof("Loaded config") + + // define a config to return + config := Config{ + Arch: *arch, + Bits: *bits, + Memsize: memsize, + MaxProgSize: *maxProgSize, + AmountOfBots: amountOfBots, + GameRoundDuration: *gameRoundDuration, + } + + return config +} + +// define bots defines the bots given via command line arguments +func defineBots(config *Config) { + + logrus.Info("Defining the bots") + + // define a list of bots by parsing the command line arguments one by one + var bots []Bot + for i := 0; i < config.AmountOfBots; i++ { + bot := Bot{ + Path: flag.Arg(i), + } + bots = append(bots, bot) + } + + config.Bots = bots +} + +func r2cmd(r2p *r2pipe.Pipe, input string) string { + + logrus.Tracef("> %s", input) + + // send a command + buf1, err := r2p.Cmd(input) + if err != nil { + panic(err) + } + + // return the result of the command as a string + return buf1 +} + func buildBots(config *Config) { logrus.Info("Building all bots") @@ -228,3 +354,110 @@ func defineErrors(r2p *r2pipe.Pipe) { _ = r2cmd(r2p, "e cmd.esil.ioer=f theend=1") _ = r2cmd(r2p, "f theend=0") } + +// StepIn steps in and stores the state of the registers for the given bot +func stepIn(r2p *r2pipe.Pipe) { + _ = r2cmd(r2p, "aes") +} + +// switchPlayer returns the id of the next Player +func switchPlayer(r2p *r2pipe.Pipe, currentPlayer int, config *Config) int { + + // calculate the index of the nextPlayer + nextPlayer := (currentPlayer + 1) % config.AmountOfBots + + return nextPlayer +} + +func arena(r2p *r2pipe.Pipe, config *Config, id, gen int) string { + var res string = "" + + // clear the screen + res += "\x1b[2J\x1b[0;0H" + // res += fmt.Sprintf("%s\n", r2cmd(r2p, "?eg 0 0")) + + // print some general information such as the current user and the round the + // game is in + ip := fmt.Sprintf("%s\n", r2cmd(r2p, "aer~eip")) + res += fmt.Sprintf("Round: %d \t\t User: %d \t\t ip: %s\n", gen, id, ip) + + // print the memory space + res += fmt.Sprintf("%s\n", r2cmd(r2p, "pxa 0x400 @ 0")) + // res += fmt.Sprintf("%s\n", r2cmd(r2p, fmt.Sprintf("pd 0x10 @ %d", config.Bots[id].Addr))) + + // res += fmt.Sprintf("%s\n", r2cmd(r2p, "prc 0x200 @ 0")) + + return res +} + +// runGame actually runs the game (surprise!) +func runGame(r2p *r2pipe.Pipe, config *Config) { + + // start the competition + var botid int = 0 + var round int = 0 + for true { + + // load the registers + r2cmd(r2p, config.Bots[botid].Regs) + + // Step + stepIn(r2p) + + // store the regisers + registers := r2cmd(r2p, "aerR") + registersStripped := strings.Replace(registers, "\n", ";", -1) + config.Bots[botid].Regs = registersStripped + + logrus.Info(arena(r2p, config, botid, round)) + + if dead(r2p, botid) == true { + logrus.Warnf("DEAD (round %d)", round) + os.Exit(1) + } + + // switch players, if the new botid is 0, a new round has begun + botid = switchPlayer(r2p, botid, config) + if botid == 0 { + round++ + } + + // sleep only a partial of the total round time, as a round is made up of + // the movements of multiple bots + time.Sleep(config.GameRoundDuration / time.Duration(config.AmountOfBots)) + } +} + +func dead(r2p *r2pipe.Pipe, botid int) bool { + status := r2cmd(r2p, "?v 1+theend") + + if status != "" && status != "0x1" { + logrus.Warn("[!] Bot %d has died", botid) + return true + } + return false +} + +func main() { + fmt.Println("hi") + + config := parseConfig() + defineBots(&config) + buildBots(&config) + genRandomOffsets(&config) + + // initialize the arena (allocate memory + initialize the ESIL VM & stack) + r2p := initArena(&config) + + // place the bots in the arena + placeBots(r2p, &config) + + // if an error occurs (interrupt, ioerror, trap, ...), the ESIL VM should set + // a flag that can be used to determine if a player has died + defineErrors(r2p) + + // run the actual game + runGame(r2p, &config) + + r2p.Close() +} diff --git a/src/cmd.go b/src/cmd.go deleted file mode 100644 index a17da4a..0000000 --- a/src/cmd.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "github.com/radare/r2pipe-go" - "github.com/sirupsen/logrus" -) - -func r2cmd(r2p *r2pipe.Pipe, input string) string { - - logrus.Tracef("> %s", input) - - // send a command - buf1, err := r2p.Cmd(input) - if err != nil { - panic(err) - } - - // return the result of the command as a string - return buf1 -} diff --git a/src/config.go b/src/config.go deleted file mode 100644 index 706d29e..0000000 --- a/src/config.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "flag" - "time" - - "github.com/sirupsen/logrus" -) - -// parseConfig parses the config needed to start the game -func parseConfig() Config { - - // bot configs - arch := flag.String("arch", "x86", "bot architecture (mips|arm|x86)") - bits := flag.Int("bits", 32, "bot bitness (8|16|32|64)") - maxProgSize := flag.Int("maxProgSize", 64, "the maximum bot size") - memPerBot := flag.Int("memPerBot", 512, "the amount of memory each bot should add to the arena") - gameRoundDuration := flag.Duration("t", 250*time.Millisecond, "The duration of a round") - - v := flag.Bool("v", false, "info") - vv := flag.Bool("vv", false, "debug") - vvv := flag.Bool("vvv", false, "trace") - - // parse the flags - flag.Parse() - - if *v == true { - logrus.SetLevel(logrus.InfoLevel) - } else if *vv == true { - logrus.SetLevel(logrus.DebugLevel) - } else if *vvv == true { - logrus.SetLevel(logrus.TraceLevel) - } else { - logrus.SetLevel(logrus.WarnLevel) - } - - // parse all trailing command line arguments as path to bot sourcecode - amountOfBots := flag.NArg() - - memsize := amountOfBots * *memPerBot - - logrus.WithFields(logrus.Fields{ - "mem per bot": *memPerBot, - "amountOfBots": amountOfBots, - "memsize": memsize, - }).Infof("Loaded config") - - // define a config to return - config := Config{ - Arch: *arch, - Bits: *bits, - Memsize: memsize, - MaxProgSize: *maxProgSize, - AmountOfBots: amountOfBots, - GameRoundDuration: *gameRoundDuration, - } - - return config -} - -// define bots defines the bots given via command line arguments -func defineBots(config *Config) { - - logrus.Info("Defining the bots") - - // define a list of bots by parsing the command line arguments one by one - var bots []Bot - for i := 0; i < config.AmountOfBots; i++ { - bot := Bot{ - Path: flag.Arg(i), - } - bots = append(bots, bot) - } - - config.Bots = bots -} diff --git a/src/logic.go b/src/logic.go deleted file mode 100644 index 5bc6461..0000000 --- a/src/logic.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "log" - - "github.com/radare/r2pipe-go" -) - -func dead(r2p *r2pipe.Pipe, botid int) bool { - status := r2cmd(r2p, "?v 1+theend") - - if status != "" && status != "0x1" { - log.Printf("[!] Bot %d has died", botid) - return true - } - return false -} diff --git a/src/main.go b/src/main.go deleted file mode 100644 index d5e0107..0000000 --- a/src/main.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -func main() { - - // initialize the game by parsing the config, defining the bots, building the - // bots and generating random offsets where the bots should be placed in - // memory - config := parseConfig() - defineBots(&config) - buildBots(&config) - genRandomOffsets(&config) - - // initialize the arena (allocate memory + initialize the ESIL VM & stack) - r2p := initArena(&config) - - // place the bots in the arena - placeBots(r2p, &config) - - // if an error occurs (interrupt, ioerror, trap, ...), the ESIL VM should set - // a flag that can be used to determine if a player has died - defineErrors(r2p) - - // run the actual game - runGame(r2p, &config) - - r2p.Close() -} diff --git a/src/run.go b/src/run.go deleted file mode 100644 index fb3c249..0000000 --- a/src/run.go +++ /dev/null @@ -1,84 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strings" - "time" - - "github.com/radare/r2pipe-go" - "github.com/sirupsen/logrus" -) - -// StepIn steps in and stores the state of the registers for the given bot -func stepIn(r2p *r2pipe.Pipe) { - _ = r2cmd(r2p, "aes") -} - -// switchPlayer returns the id of the next Player -func switchPlayer(r2p *r2pipe.Pipe, currentPlayer int, config *Config) int { - - // calculate the index of the nextPlayer - nextPlayer := (currentPlayer + 1) % config.AmountOfBots - - return nextPlayer -} - -func arena(r2p *r2pipe.Pipe, config *Config, id, gen int) string { - var res string = "" - - // clear the screen - res += "\x1b[2J\x1b[0;0H" - // res += fmt.Sprintf("%s\n", r2cmd(r2p, "?eg 0 0")) - - // print some general information such as the current user and the round the - // game is in - ip := fmt.Sprintf("%s\n", r2cmd(r2p, "aer~eip")) - res += fmt.Sprintf("Round: %d \t\t User: %d \t\t ip: %s\n", gen, id, ip) - - // print the memory space - res += fmt.Sprintf("%s\n", r2cmd(r2p, "pxa 0x400 @ 0")) - // res += fmt.Sprintf("%s\n", r2cmd(r2p, fmt.Sprintf("pd 0x10 @ %d", config.Bots[id].Addr))) - - // res += fmt.Sprintf("%s\n", r2cmd(r2p, "prc 0x200 @ 0")) - - return res -} - -// runGame actually runs the game (surprise!) -func runGame(r2p *r2pipe.Pipe, config *Config) { - - // start the competition - var botid int = 0 - var round int = 0 - for true { - - // load the registers - r2cmd(r2p, config.Bots[botid].Regs) - - // Step - stepIn(r2p) - - // store the regisers - registers := r2cmd(r2p, "aerR") - registersStripped := strings.Replace(registers, "\n", ";", -1) - config.Bots[botid].Regs = registersStripped - - logrus.Info(arena(r2p, config, botid, round)) - - if dead(r2p, botid) == true { - logrus.Warnf("DEAD (round %d)", round) - os.Exit(1) - } - - // switch players, if the new botid is 0, a new round has begun - botid = switchPlayer(r2p, botid, config) - if botid == 0 { - round++ - } - - // sleep only a partial of the total round time, as a round is made up of - // the movements of multiple bots - time.Sleep(config.GameRoundDuration / time.Duration(config.AmountOfBots)) - } -} diff --git a/src/structs.go b/src/structs.go deleted file mode 100644 index c0cddc2..0000000 --- a/src/structs.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import "time" - -// Config defines the meta config -type Config struct { - - // Arch defines the architecture the battle should run in - Arch string - - // Bits defines the bitness - Bits int - - // Memsize defines the arena size - Memsize int - - // MaxProgSize defines the maximal bot size - MaxProgSize int - - // Bots defines a list of bots to take part in the battle - Bots []Bot - - // AmountOfBots defines the amount of bots taking part in the tournament - AmountOfBots int - - // RandomOffsets defines the offset in memory where the bots should be placed - RandomOffsets []int - - // GameRoundTime defines the length of a gameround - GameRoundDuration time.Duration -} - -// Bot defines a bot -type Bot struct { - - // Path defines the path to the source of the bot - Path string - - // Source defines the source of the bot after being compiled with rasm2 - Source string - - // Addr defines the initial address the bot is placed at - Addr int - - // 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 string -} |