all repos — site @ a96c997192b4ff6f9c3ac321596d2f72d97d4fbe

source for my site, found at icyphox.sh

pages/blog/r2wars-2020.md (view raw)

  1---
  2template:
  3url: r2wars-2020
  4title: My submissions for r2wars 2020
  5subtitle: If I learnt one thing, it's that ARM is the future
  6date: 2020-09-13
  7---
  8
  9[r2wars](https://github.com/radareorg/r2wars) is
 10a [CoreWar](http://corewars.org)-like game thar runs within the radare2
 11[ESIL](https://radare.gitbooks.io/radare2book/content/disassembling/esil.html)
 12virtual machine. In short, you have two programs running in a shared
 13memory space (1kb), with the goal of killing the other and surviving as
 14long as possible. r2wars was conducted as a part of
 15[r2con2020](https://rada.re/con/2020).
 16
 17## day 1
 18
 19My first submission was an incredibly simple "bomber". All it does is
 20write code to a location, jump there, and continue executing the same
 21thing over and over.
 22
 23```asm
 24mov eax, 0xfeebfeeb; just some bad jumps
 25mov ebx, eax
 26mov ecx, eax
 27mov edx, eax
 28mov ebp, eax
 29mov edi, eax
 30mov esp, 0x3fc
 31mov esi, 0x3fd
 32mov [esi], 0xe6ff60
 33jmp esi
 34```
 35
 36Specifically, it writes `0xe6ff60`, which is
 37```asm
 38pushal
 39jmp esi
 40```
 41effectively looping over and over. `pushal` is a very interesting x86
 42instruction, that pushes all the registers and decrements the stack
 43pointer `esp` by how many ever bytes were pushed. Nifty, especially if
 44you're looking for high throughput (to bomb the address space). Here, it
 45starts bombing from `0x3fc` - `0x000` (and below, because there's no
 46bounds checking in place), and ends up killing itself, since writing
 47outside of the arena (`0x000` - `0x400`) is illegal.
 48
 49Ultimately, this bot placed 7th out of 9 contestants -- an underwhelming
 50outcome. I had to fix this.
 51
 52![day 1](https://x.icyphox.sh/gk1i0.png)
 53
 54## day 2
 55
 56I sat for a second and recollected the different reasons for my bot
 57getting killed, and the one that occurred the most was my bot
 58insta-dying to bad instructions being written from `0x400` -- i.e. from
 59near where I'm positioned. Nearly all competing bots write from bottom
 60up, because `pushal` _decrements_ the stack pointer. So the obvious
 61solution was to reposition my initial payload way above, at `0x000`. And
 62of course, it goes without saying that this assumes everyone's using
 63`pushal` (they are).
 64
 65```asm
 66mov eax, 0xffffffff
 67mov ecx, eax
 68mov edx, eax
 69mov ebx, eax
 70mov ebp, eax
 71mov esi, eax
 72
 73check:
 74    mov edi, 0x000
 75    cmp [edi], 0
 76    jne planb
 77    mov esp, 0x400
 78    inc edi
 79    mov [edi], 0xe7ff6060; pushal, jmp edi
 80    jmp edi
 81
 82planb:
 83    mov edi, 0x3fb
 84    mov [edi], 0xe7ff6060
 85    mov esp, 0x3fa
 86    jmp edi
 87```
 88
 89I also added a (pretty redundant) check to see if the stuff at `edi` was
 900, since the entire arena is initially `0x0`. My reasoning, albeit
 91flawed, was that if it wasn't 0, then it was unsafe to go there. In
 92hindsight, it would've been _safer_, since it's already been written
 93over by somebody. In any case, `planb` never got executed because of
 94what I'd mentioned earlier -- *everyone* writes from `0x400`. Or
 95anywhere above `0x000`, for that matter. So I'm relatively safer than
 96I was in day 1.
 97
 98These changes paid off, though. I placed 4th on day 2, out of 13
 99contestants! This screenshot was taken on my phone as I was eating
100dinner.
101
102![day 2](https://x.icyphox.sh/5ZJfT.png)
103
104All wasn't well though -- I still lost 4 matches, for the reasons below:
105
1061. I'd get snuffed out before my bomb wave from `0x400` would reach
107   the opponent.
1082. I'd end up bombing myself without hitting anyone on the way up.
109
110## day 3
111
112I needed to add some checks to prevent killing myself in the process of
113bombing.
114```asm
115mov eax, 0xffffffff
116mov ecx, eax
117mov edx, eax
118mov ebx, eax
119mov ebp, eax
120mov esi, eax
121
122mov edi, 0x000
123mov esp, 0x400
124mov [edi], 0x20fc8360
125mov [edi+4], 0xff600374
126mov [edi+8], 0x0400bce7
127mov [edi+12], 0xe7ff0000
128jmp edi
129```
130
131If you noticed, the initial payload I'm writing to the address at `edi`
132is a bit more complex this time -- let's break it down.
133
134```
1350x20fc8360
1360xff600374
1370x0400bce7
1380xe7ff0000
139```
140
141This translates to:
142```asm
14360                pushal 
14483 FC 20          cmp    esp, 0x20
14574 03             je     9
14660                pushal 
147FF E7             jmp    edi
148BC 04 00 00 00    mov    esp, 0x400; <- 0x9
149FF E7             jmp    edi
150```
151
152I check if the stack pointer is `0x20` (decrements from `0x400` due to
153`pushal`); if yes, reset to `0x400`, else continue looping. This
154prevented me from writing myself over, and also resets bombing from
155`0x400` -- better chance of hitting someone we missed in our first wave.
156
157Sounds good? That's what I thought too. Day 3 had a bunch of new bot
158submissions (and some updated submissions), and a lot of them checked
159`0x000` for existence of a bot, effectively recking me. I placed 8th out
160of 14 contestants, with 7 wins and 6 losses. Tough day.
161
162![day 3](https://x.icyphox.sh/IKqxD.png)
163
164## day 4: the finals
165
166I spent a lot of time refactoring my bot. I tried all kinds of things,
167even reworked it to be entirely mobile using the `pushal` + `jmp esp`
168trick, but I just wasn't satisfied. In the end, I decided to address the
169problem in the simplest way possible. You're checking `0x000`? Okay,
170I'll reposition my initial payload to `0xd`. 
171
172And this surprisingly tiny change landed me in 4th place out of 15
173contestants, which was _way_ better than I'd anticipated! The top spots
174were all claimed by ARM, and naturally so -- they had a potential
175throughput of 64 bytes per cycle thanks to `stmia`, compared to x86's 32
176bytes. Pretty neat!
177
178![day 4](https://x.icyphox.sh/DJbEE.png)
179
180## links and references
181
182- [Anisse's r2wars 2019 post](https://anisse.astier.eu/r2wars-2019.html)
183- [Emile's intro to r2wars](https://www.tildeho.me/r2wars/)
184- [How not to suck at r2wars](https://bananamafia.dev/post/r2wars-2019/)
185- [r2wars: Shall we play a game?](https://ackcent.com/r2wars-shall-we-play-a-game/)
186- [Shell Storm's online (dis)assembler](http://shell-storm.org/online/Online-Assembler-and-Disassembler)
187- [radare2](https://github.com/radareorg/radare2)
188- [r2wars game engine](https://github.com/radareorg/r2wars)
189- [Anisse's bot workspace](https://github.com/anisse/r2warsbots)
190- [My bot dev workspace](https://github.com/icyphox/r2wars-bots)
191- [r2con YouTube](https://www.youtube.com/channel/UCZo6gyBPj6Vgg8u2dfIhY4Q)
192
193## closing thoughts
194
195This was my first ever r2wars, and it was an incredible experience. Who
196woulda thunk staring at colored boxes on the screen would be so much
197fun?! So much so that my parents walked over to see what all the fuss
198was about. Shoutout to [Abel](https://twitter.com/sanguinawer)
199and [pancake](https://twitter.com/trufae) for taking the time out to
200work on this, and _especially_ Abel for dealing with all the last minute
201updates and bot submissions!
202
203All things said, mine was still the best x86 bot -- so that's a win. ;)