Welcome to ASMLevel11
==================================================
To interact with any level you will send raw bytes over stdin to this program.
To efficiently solve these problems, first run it once to see what you need
then craft, assemble, and pipe your bytes to this program.
We will now set some values in memory dynamically before each run. On each run
the values will change. This means you will need to do some type of formulaic
operation with registers_use. We will tell you which registers_use are set beforehand
and where you should put the result. In most cases, its rax.
In this level you will be working with memory. This will require you to read or write
to things stored linearly in memory. If you are confused, go look at the linear
addressing module in 'ike. You may also be asked to dereference things, possibly multiple
times, to things we dynamically put in memory for your use.
Recall that registers in x86_64 are 64 bits wide, meaning they can store 64 bits in them.
Similarly, each memory location is 64 bits wide. We refer to something that is 64 bits
(8 bytes) as a quad word. Here is the breakdown of the names of memory sizes:
* Quad Word = 8 Bytes = 64 bits
* Double Word = 4 bytes = 32 bits
* Word = 2 bytes = 16 bits
* Byte = 1 byte = 8 bits
In x86_64, you can access each of these sizes when dereferencing an address, just like using
bigger or smaller register accesses:
mov al, [address] <=> moves the least significant byte from address to rax
mov ax, [address] <=> moves the least significant word from address to rax
mov eax, [address] <=> moves the least significant double word from address to rax
mov rax, [address] <=> moves the full quad word from address to rax
Remember that moving only into al for instance does not fully clear the upper bytes.
Please perform the following:
1) Set rax to the byte at 0x404000
2) Set rbx to the word at 0x404000
3) Set rcx to the double word at 0x404000
4) Set rdx to the quad word at 0x404000
We will now set the following in preparation for your code:
[0x404000] = 0x1d7cc4
Please give me your assembly in bytes (up to 0x1000 bytes):
Solution
-----------------------------------------------------------------------------------------
Executing your code...
---------------- CODE ----------------
0x400000: mov al, byte ptr [0x404000]
0x400007: mov bx, word ptr [0x404000]
0x40000f: mov ecx, dword ptr [0x404000]
0x400016: mov rdx, qword ptr [0x404000]
In [1]: import pwn
In [2]: pwn.context.update(arch="amd64")
In [3]: process = pwn.process("/challenge/run")
[x] Starting local process '/challenge/run'
[+] Starting local process '/challenge/run': pid 2392
In [4]: process.write(pwn.asm("""
...: mov al, [0x404000]
...: mov bx, [0x404000]
...: mov ecx, [0x404000]
...: mov rdx, [0x404000]"""))
In [5]: print(process.recvallS())
[x] Receiving all data
[x] Receiving all data: 0B
[*] Process '/challenge/run' stopped with exit code 0 (pid 2392)
[x] Receiving all data: 2.46KB
[+] Receiving all data: Done (2.46KB)
--------------------------------------
Flag: pwn.college{8x7YK56sNsCm40c0RvvLpuGZV55.0FNwIDLxUjNyEzW}
-------------------------------------------------------------------------------------------------------------------
Welcome to ASMLevel12
==================================================
To interact with any level you will send raw bytes over stdin to this program.
To efficiently solve these problems, first run it once to see what you need
then craft, assemble, and pipe your bytes to this program.
We will now set some values in memory dynamically before each run. On each run
the values will change. This means you will need to do some type of formulaic
operation with registers_use. We will tell you which registers_use are set beforehand
and where you should put the result. In most cases, its rax.
In this level you will be working with memory. This will require you to read or write
to things stored linearly in memory. If you are confused, go look at the linear
addressing module in 'ike. You may also be asked to dereference things, possibly multiple
times, to things we dynamically put in memory for your use.
It is worth noting, as you may have noticed, that values are stored in reverse order of how we
represent them. As an example, say:
[0x1330] = 0x00000000deadc0de
If you examined how it actually looked in memory, you would see:
[0x1330] = 0xde 0xc0 0xad 0xde 0x00 0x00 0x00 0x00
This format of storing things in 'reverse' is intentional in x86, and its called Little Endian.
For this challenge we will give you two addresses created dynamically each run. The first address
will be placed in rdi. The second will be placed in rsi.
Using the earlier mentioned info, perform the following:
1. set [rdi] = 0xdeadbeef00001337
2. set [rsi] = 0xc0ffee0000
Hint: it may require some tricks to assign a big constant to a dereferenced register. Try setting
a register to the constant then assigning that register to the derefed register.
We will now set the following in preparation for your code:
[0x4040b0] = 0xffffffffffffffff
[0x404c60] = 0xffffffffffffffff
rdi = 0x4040b0
rsi = 0x404c60
Please give me your assembly in bytes (up to 0x1000 bytes):
Solution
----------------------------------------------------------------------------------------
In order to solve this challenge, we can assume that we should store "0xdeadbeef00001337" into
[rdi].
mov eax, 0xdeadbeef00001337 ; this will store the value into eax
mov [rdi], eax ; this will store eax into [rdi]
2. We will be able to store "0xc0ffee0000" into eax.
mov eax, 0xc0ffee0000 ; store "0xc0ffee0000" into eax
mov [rsi], eax ; store eax into [rsi]
In [34]: process.write(pwn.asm("""
...: mov rax, 0xdeadbeef00001337
...: mov [rdi], rax
...: mov rax, 0xc0ffee0000
...: mov [rsi], rax
...: int3"""))
0x400000: movabs rax, 0xdeadbeef00001337
0x40000a: mov qword ptr [rdi], rax
0x40000d: movabs rax, 0xc0ffee0000
0x400017: mov qword ptr [rsi], rax
0x40001a: int3
--------------------------------------
+--------------------------------------------------------------------------------+
| Registers |
+-------+----------------------+-------+----------------------+------------------+
| rax | 0x000000c0ffee0000 | rbx | 0x0000000000000000 | |
| rcx | 0x0000000000000000 | rdx | 0x0000000000000000 | |
| rsi | 0x0000000000404898 | rdi | 0x0000000000404208 | |
| rbp | 0x0000000000000000 | rsp | 0x00007fffff200000 | |
| r8 | 0x0000000000000000 | r9 | 0x0000000000000000 | |
| r10 | 0x0000000000000000 | r11 | 0x0000000000000000 | |
| r12 | 0x0000000000000000 | r13 | 0x0000000000000000 | |
| r14 | 0x0000000000000000 | r15 | 0x0000000000000000 | |
| rip | 0x000000000040001b | | | |
+---------------------------------+-------------------------+--------------------+
| Stack location | Data (bytes) | Data (LE int) |
+---------------------------------+-------------------------+--------------------+
+---------------------------------+-------------------------+--------------------+
| Memory location | Data (bytes) | Data (LE int) |
+---------------------------------+-------------------------+--------------------+
| 0x0000000000404208 (+0x0000) | 37 13 00 00 ef be ad de | 0xdeadbeef00001337 |
| 0x0000000000404210 (+0x0008) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x0000000000404218 (+0x0010) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x0000000000404220 (+0x0018) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| ------------------------- | ----------------- | ------------ |
| 0x0000000000404898 (+0x0000) | 00 00 ee ff c0 00 00 00 | 0x000000c0ffee0000 |
| 0x00000000004048a0 (+0x0008) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x00000000004048a8 (+0x0010) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x00000000004048b0 (+0x0018) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
+---------------------------------+-------------------------+--------------------+
Flag: pwn.college{g-fjVH4ktMpsnaz29IuHA0XfCSv.0VNwIDLxUjNyEzW}
--------------------------------------------------------------------------------------------------------------------------------
Welcome to ASMLevel13
==================================================
To interact with any level you will send raw bytes over stdin to this program.
To efficiently solve these problems, first run it once to see what you need
then craft, assemble, and pipe your bytes to this program.
We will now set some values in memory dynamically before each run. On each run
the values will change. This means you will need to do some type of formulaic
operation with registers_use. We will tell you which registers_use are set beforehand
and where you should put the result. In most cases, its rax.
In this level you will be working with memory. This will require you to read or write
to things stored linearly in memory. If you are confused, go look at the linear
addressing module in 'ike. You may also be asked to dereference things, possibly multiple
times, to things we dynamically put in memory for your use.
Recall that memory is stored linearly. What does that mean? Say we access the quad word at 0x1337:
[0x1337] = 0x00000000deadbeef
The real way memory is layed out is byte by byte, little endian:
[0x1337] = 0xef
[0x1337 + 1] = 0xbe
[0x1337 + 2] = 0xad
...
[0x1337 + 7] = 0x00
What does this do for us? Well, it means that we can access things next to each other using offsets,
like what was shown above. Say you want the 5th *byte* from an address, you can access it like:
mov al, [address+4]
Remember, offsets start at 0.
Perform the following:
1. load two consecutive quad words from the address stored in rdi
2. calculate the sum of the previous steps quad words.
3. store the sum at the address in rsi
We will now set the following in preparation for your code:
[0x404320] = 0x8c533
[0x404328] = 0x9f264
rdi = 0x404320
rsi = 0x404678
Please give me your assembly in bytes (up to 0x1000 bytes):
Solution
-------------------------------------------------------------------------------------------
1. In order to solve this challenge, we should know about the offsets. We can see from the example:
[0x1337] = 0x00000000deadbeef
The real way memory is layed out is byte by byte, little endian:
[0x1337] = 0xef
[0x1337 + 1] = 0xbe
[0x1337 + 2] = 0xad
...
[0x1337 + 7] = 0x00
We can work with offsets to store the part of memory into RDI register.
1. The first part:
mov rax, [rdi] ; store RDI+0 into rax --> we know that RDI is 64 bit: 8 byte
2. The second part:
We are going to add [rdi+8] into RAX register.
add rax, [rdi+8] ; rax = rax + [rdi+8]
3. Just store RAX register into RSI
mov [rsi], rax
ax
ah al
ah = high bit
al = low bit
In [4]: process.write(pwn.asm("""
...: mov rax, [rdi]
...: add rax, [rdi+8]
...: mov [rsi], rax
...: int3"""))
Executing your code...
---------------- CODE ----------------
0x400000: mov rax, qword ptr [rdi]
0x400003: add rax, qword ptr [rdi + 8]
0x400007: mov qword ptr [rsi], rax
0x40000a: int3
--------------------------------------
+--------------------------------------------------------------------------------+
| Registers |
+-------+----------------------+-------+----------------------+------------------+
| rax | 0x00000000000e9229 | rbx | 0x0000000000000000 | |
| rcx | 0x0000000000000000 | rdx | 0x0000000000000000 | |
| rsi | 0x0000000000404798 | rdi | 0x0000000000404318 | |
| rbp | 0x0000000000000000 | rsp | 0x00007fffff200000 | |
| r8 | 0x0000000000000000 | r9 | 0x0000000000000000 | |
| r10 | 0x0000000000000000 | r11 | 0x0000000000000000 | |
| r12 | 0x0000000000000000 | r13 | 0x0000000000000000 | |
| r14 | 0x0000000000000000 | r15 | 0x0000000000000000 | |
| rip | 0x000000000040000b | | | |
+---------------------------------+-------------------------+--------------------+
| Stack location | Data (bytes) | Data (LE int) |
+---------------------------------+-------------------------+--------------------+
+---------------------------------+-------------------------+--------------------+
| Memory location | Data (bytes) | Data (LE int) |
+---------------------------------+-------------------------+--------------------+
| 0x0000000000404318 (+0x0000) | 95 55 09 00 00 00 00 00 | 0x0000000000095595 |
| 0x0000000000404320 (+0x0008) | 94 3c 05 00 00 00 00 00 | 0x0000000000053c94 |
| 0x0000000000404328 (+0x0010) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x0000000000404330 (+0x0018) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| ------------------------- | ----------------- | ------------ |
| 0x0000000000404798 (+0x0000) | 29 92 0e 00 00 00 00 00 | 0x00000000000e9229 |
| 0x00000000004047a0 (+0x0008) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x00000000004047a8 (+0x0010) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
| 0x00000000004047b0 (+0x0018) | 00 00 00 00 00 00 00 00 | 0x0000000000000000 |
+---------------------------------+-------------------------+--------------------+
Flag: pwn.college{gQAei527h6ghMsddYyyFOxCOLUa.0lNwIDLxUjNyEzW}
-----------------------------------------------------------------------------------------------------------------------------
Welcome to ASMLevel14
==================================================
To interact with any level you will send raw bytes over stdin to this program.
To efficiently solve these problems, first run it once to see what you need
then craft, assemble, and pipe your bytes to this program.
We will now set some values in memory dynamically before each run. On each run
the values will change. This means you will need to do some type of formulaic
operation with registers_use. We will tell you which registers_use are set beforehand
and where you should put the result. In most cases, its rax.
In this level you will be working with the Stack, the memory region that dynamically expands
and shrinks. You will be required to read and write to the Stack, which may require you to use
the pop & push instructions. You may also need to utilize rsp to know where the stack is pointing.
In these levels we are going to introduce the stack.
The stack is a region of memory, that can store values for later.
To store a value a on the stack we use the push instruction, and to retrieve a value we use pop.
The stack is a last in first out (LIFO) memory structure this means
the last value pushed in the first value popped.
Imagine unloading plates from the dishwasher let's say there are 1 red, 1 green, and 1 blue.
First we place the red one in the cabinet, then the green on top of the red, then the blue.
Out stack of plates would look like:
Top ----> Blue
Green
Bottom -> Red
Now if we wanted a plate to make a sandwich we would retrieve the top plate from the stack
which would be the blue one that was last into the cabinet, ergo the first one out.
Replace the top value of the stack with (top value of the stack - rdi).
We will now set the following in preparation for your code:
rdi = 0x18114
(stack) [0x7fffff1ffff8] = 0x1b4e2f38
Please give me your assembly in bytes (up to 0x1000 bytes):
Solution
----------------------------------------------------------------------------------------
pop rax ; Load the value from the top of the stack into rax using the pop instruction
sub rax, rdi ; Subtract the value of rdi from rax
push rax ; Store the result back onto the top of the stack using the push instruction
1. First of all, we need to pop the last element into the stack
**pop rax**
We used pop rax because rax is a general purpose register that can be used to hold any type of value or address,
and it is commonly used for arithmetic and data manipulation.
When we popped from the stack, we can manipulate the data
**sub rax, rdi**
We are using sub rax,
rdi to subtract the value of rdi from the value that was loaded from the top of the stack in rax.
2. In order to push the last result into the stack, we can just use "push" instruction
**push rax**
using push rbx. However, since rax is often used for arithmetic and is a natural choice for holding temporary values,
it is a common choice in assembly code.
0x400000: pop rax
0x400001: sub rax, rdi
0x400004: push rax
--------------------------------------
Flag: pwn.college{M_GtNRp_KIwJdQGQqgDzQuVqjch.01NwIDLxUjNyEzW}
----------------------------------------------------------------------------------------------------------------------------
Welcome to ASMLevel15
==================================================
To interact with any level you will send raw bytes over stdin to this program.
To efficiently solve these problems, first run it once to see what you need
then craft, assemble, and pipe your bytes to this program.
We will now set some values in memory dynamically before each run. On each run
the values will change. This means you will need to do some type of formulaic
operation with registers_use. We will tell you which registers_use are set beforehand
and where you should put the result. In most cases, its rax.
In this level you will be working with the Stack, the memory region that dynamically expands
and shrinks. You will be required to read and write to the Stack, which may require you to use
the pop & push instructions. You may also need to utilize rsp to know where the stack is pointing.
In this level we are going to explore the last in first out (LIFO) property of the stack.
Using only following instructions:
push, pop
Swap values in rdi and rsi.
i.e.
If to start rdi = 2 and rsi = 5
Then to end rdi = 5 and rsi = 2
We will now set the following in preparation for your code:
rdi = 0x3b8ed336
rsi = 0xd8aaf75
Please give me your assembly in bytes (up to 0x1000 bytes):
Solution
------------------------------------------------------------------------------------------
I have been asked to swap 2 register "RDI" and "RSI"
1. In order to swap: we need to push those 2 values into the stack
|
| 5
| 2
we can push "2" and then "5"
push rdi ; push 2
push rsi ; push 5
in order to swap:
pop rdi ; this means we pop 2 to rdi
pop rsi ; this means we pop 5 to rsi
0x400000: push rdi
0x400001: push rsi
0x400002: pop rdi
0x400003: pop rsi
--------------------------------------
Flag: pwn.college{4ebUF_VYMbaZMa4M7Gnbv0-VGGq.0FOwIDLxUjNyEzW}
0 comments:
Post a Comment