Hello guys, it's about time we did some assembly. I decided to wrap up a quick blog post in 30 minutes, so here is one:
I will discuss a quick and dirty method that can be easily automated to check for format string vulnerabilities. I will assume you already know what buffer overflow and format string vulnerabilities are.
Assume this very very vulnerable code:
This code obviously suffers from a format string vulnerability. However, if you don't have the source code, how can you quickly tell (not 100 percent accurate, but a very quick indicator nonetheless) ?
By checking stack adjustment after the call to printf. Let's dive to assembly:
8: printf(x);
00401510 lea ecx,[ebp-64h]
00401513 push ecx
00401514 call printf (0041f150)
00401519 add esp,4
9:
10: return 0;
0040151C xor eax,eax
11: }
After the call to printf(x), the stack was adjusted by 4 bytes (add esp,4) , why? Because of this:
The function printf can accept one parameter, but ideally it should be two: The format string itself and the variables corresponding to each placeholder. For example printf("%d",4) where "%d" is the format string and 4 is the variable corresponding to the %d inside the format string.
If we call printf("Hello") then we are only pushing one set of 4-bytes, a DWORD (in our past example the register ecx).
So what if we changed printf(x) to printf("%s",x)? Let's look at the dissassembly.
8: printf("%s",x);
00401510 lea ecx,[ebp-64h]
00401513 push ecx
00401514 push offset string "%s" (0046c01c)
00401519 call printf (0041f150)
0040151E add esp,8
As we can see, the stack was adjusted by 8 bytes, or two DWORDs. What we pushed was the address of x (in ecx) and the address of "%s" to the function.
When we only called printf(x) we pushed the address of x stored in ecx, so only 4 bytes were pushed in the vulnerable call so only 4 bytes had to be corrected for the stack pointer (ESP). In the correct call we pushed 8 bytes and hence had to correct the stack pointer (ESP) by 8 bytes.
Very simple, no? The great thing about this is the extreme ease which which you can automate the search for such vulnerable usage in any binary with any tool you want: IDA Pro, PyDASM...etc
This trick is very simple and not complicated in any form, but it can really speed up the search for format string vulnerabilities. Enjoy!
I will discuss a quick and dirty method that can be easily automated to check for format string vulnerabilities. I will assume you already know what buffer overflow and format string vulnerabilities are.
Assume this very very vulnerable code:
#include <iostream>
int main()
{
char x[100];
printf("%s","Enter your string:\n");
std::cin.get(x, 99);
printf(x); //WARNING: BAD VULNERABLE CODE, TEST ONLY
return 0;
}
int main()
{
char x[100];
printf("%s","Enter your string:\n");
std::cin.get(x, 99);
printf(x); //WARNING: BAD VULNERABLE CODE, TEST ONLY
return 0;
}
This code obviously suffers from a format string vulnerability. However, if you don't have the source code, how can you quickly tell (not 100 percent accurate, but a very quick indicator nonetheless) ?
By checking stack adjustment after the call to printf. Let's dive to assembly:
00401510 lea ecx,[ebp-64h]
00401513 push ecx
00401514 call printf (0041f150)
00401519 add esp,4
9:
10: return 0;
0040151C xor eax,eax
11: }
After the call to printf(x), the stack was adjusted by 4 bytes (add esp,4) , why? Because of this:
int printf ( const char * format, ... );
The function printf can accept one parameter, but ideally it should be two: The format string itself and the variables corresponding to each placeholder. For example printf("%d",4) where "%d" is the format string and 4 is the variable corresponding to the %d inside the format string.
If we call printf("Hello") then we are only pushing one set of 4-bytes, a DWORD (in our past example the register ecx).
So what if we changed printf(x) to printf("%s",x)? Let's look at the dissassembly.
8: printf("%s",x);
00401510 lea ecx,[ebp-64h]
00401513 push ecx
00401514 push offset string "%s" (0046c01c)
00401519 call printf (0041f150)
0040151E add esp,8
As we can see, the stack was adjusted by 8 bytes, or two DWORDs. What we pushed was the address of x (in ecx) and the address of "%s" to the function.
When we only called printf(x) we pushed the address of x stored in ecx, so only 4 bytes were pushed in the vulnerable call so only 4 bytes had to be corrected for the stack pointer (ESP). In the correct call we pushed 8 bytes and hence had to correct the stack pointer (ESP) by 8 bytes.
Very simple, no? The great thing about this is the extreme ease which which you can automate the search for such vulnerable usage in any binary with any tool you want: IDA Pro, PyDASM...etc
This trick is very simple and not complicated in any form, but it can really speed up the search for format string vulnerabilities. Enjoy!
No comments:
Post a Comment