Problem Overview
In ASM2, we are given assembly source code to reverse engineer. We know that the function takes two arguments: 0x4
and 0x2d
|
|
I had to learn how function arguments are managed on the stack, and it wasn't that bad! Before we walk through the assembly code and get the flag, let's explore arguments and the stack.
Arguments and the Stack…
Coming from a background of higher-level languages, I never really had to wonder how arguments in code like below was represented in assembly:
|
|
This is a good chance to learn! Let's see what fancy stuff is going on in the code.
Creating a New Stack Frame
The below sequence is a commonly-found sequence for many compilers. The push
and mov
instructions sets up a new stack frame.
The sub
instruction creates space in memory for automatic local variables. You can read about this sequence here.
|
|
Now, we have a new stack frame with 16 bytes of memory allocated.
Accessing Function Parameters
I found out that there are different conventions for how arguments are passed onto the stack.
The assembly code looked like x86, so I assumed it was using the cdecl
calling convention.
In cdecl, functions arguments are passed onto the stack from right to left.
So in the example below, the assembly representation would first push num3
onto the stack, then num2
, and finally num1
.
|
|
For our CTF challenge, we now know that the last function parameter is the first thing pushed onto the stack.
Getting the 2nd Parameter
For this code segment, we get the value 12 bytes above ebp, the 2nd parameter, and push it into eax.
Afterwards, we move the value from eax 4 bytes below ebp, making it easier to call in our stack frame.
We know that the 2nd paramter is 0x2d
, or 45.
|
|
Getting the 1st Parameter
Likewise, we repeat the same process to get the first function parameter, 0x4
, into the stack frame.
|
|
Simple Calculations
Now that we know where our function parameter values are, we are left with a relatively straight-forward algorithm to follow:
|
|
The algorithm is something like:
If the first function parameter is less than or equal to
24481
- Add 1 to the second function parameter
- Add 209 to the first function parameter
- Return to the less than or equal comparison
If the first function parameter is >
24481
, move the second function parameter into eax- Return the value in eax
More or less, we can translate the assembly code here into this simple Python script:
|
|
Running the Python Script
When we run the Python script, the output is:
looped 118 times, arg1: 24666, arg2: 163
We know that the function returns the value of arg2, so the flag is simply the hexadecimal representation of 163, or 0xA3