pages/blog/r2wars-2020.md (view raw)
1---
2template:
3slug: 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. ;)