There are two ways to solve this problem. One is to pass the validation, and the other is to jump to execve
. Since the first one is too time consuming, here I use the second one.
In function main
, there is a alloca
with random parameter, which will disturb the stack. So if we want to get information about the stack, we must leak it first.
In function fsb
, there is a printf
bug, and we can use %1$n
to write any address. So we can just write an address, and use $
to get a reference, and we can write that address! However, all input is saved at .bss
.
So we can consider another way. We can notice that the ebp
is point to an old ebp
, and we can control it.
First, we will let the old ebp
point to function sleep
in GOT
(0x0804a008
).ebp -> ori_ebp -> 0x0
becomes to ebp -> ori_ebp -> sleep_in_GOT
.
And then, we try to leak the pointer that ebp
point to, and the esp
.
Finally, we just write the place that old ebp
point to with address of evecve
(0x080486ab
).
And here is the step:
-
%134520840c%18$n
(%18$
is refer toebp
) -
%18$x %14$x
(%18$
isebp
,%14$ - 0x50
isesp
)Let's say the result is
a b
. And the offset isr = a - b + 0x50
-
%34475c%r$hn
whichr
is calculated in the last step.
The result:
Wait a sec...
$ cat flag
Have you ever saw an example of utilizing [n] format character?? :(
PS: I found it not so hard to pass the validation since we can write anything, we can write the key! So we can just rewrite it to the value we are going to input.
You just got too much output ...
There is a better trick to solve this problem:
the most hard part of this method is to find proper address of addr_1 & addr_2 to meet the requirement of the chain:
addr_1 => addr_2 => 0x8048a0xx => xxx, addr_1 & addr_2 must be in the stack.