Introduction to the formatting String Vulnerability
0x00 Introduction
Formatting strings is also a common vulnerability type. The function that triggers this vulnerability is limited. This mainly refers to the print family functions in the c library, such as printf and sprintf and fprintf. Let's take a look at the function declaration of printf> int printf (const char * format,...). This is a function that everyone who has learned the C language will know and use. First, a string pointer pointing to a format string. The variable number parameter is followed. Generally, char str [100]; scanf ("% s", str); printf ("% s", str); this program is normal. Some people will write char str [100]; scanf ("% s", str); printf (str) in this way for laziness) this program uses a lazy method in printf. It seems that there is no problem. However, a very serious vulnerability exists. Do not grant the operation permission of the format string in printf to the user. Make sure that the first parameter of the printf function is immutable and can be used by programmers. The operating principle of the 0x01 vulnerability is described in detail here. Because the behavior of the printf function on 64-bit has changed a lot. It is not described here. However, if you know the cause of the vulnerability, you can still use it. First check the normal situation # include <stdio. h> int main (void) {printf ("% d % s", 5, 6, 8, 0x21, "test"); return 0 ;}first, let's take a look at the source code of the compilation. We can't do it for now. Just write it manually.
.datastr db "test",0format db "%d%d%d%d%s",0.codepush strpush 21hpush 8push 6push 5push formatcall printf
This is almost the case. The stack will look like this at this time.
-00000003 db ? ;-00000002 db ? ;-00000001 db ? ;+00000000 s db 4 dup(?)+00000004 r db 4 dup(?)+00000008 format db 4 ;"%d%d%d%c"+0000000c %d db 4 ; 4+00000010 %d db 4 ; 6+00000014 %d db 4 ; 8+00000018 %x db 4 ; 0x21+0000001c %s db 4 ; "test"+0000001c ; end of stack variables
(~~ Amount, do not spit out the original stack Structure Representation, IDA should know ~~). According to cdecl's function call regulations, the function is stacked one by one starting from the rightmost parameters. If you want to input a string, press the string pointer to the stack. This is all done in a well-organized manner. For a common function, both the caller and the called should know the number of function parameters and the type of each parameter. For different types, the compiler automatically converts the types or prompts the program writer if a compilation error occurs. However, when it comes to the printf function, everything will be different. Because printf is a rare library function that supports variable parameters in C language. For variable parameter functions, everything becomes blurred. Function callers can specify the number and type of function parameters. The caller cannot know how many parameters are pushed into the stack frame before the function is called. Therefore, the printf function requires the input of a format parameter to specify the actual number of parameters. Then it will faithfully print the data one by one according to the format passed by the function caller. Of course, this will produce a serious problem. What if we do not intend or intend to, in format, or require that the number of data printed by printf is greater than the number we give? The printf function cannot know which data in the stack frame is passed into its parameter and which data belongs to the function caller. See the following code # include <stdio. h> int main (void) {printf ("% 08x, % 08x, % 08x, % 08x, % 08x, % 08x, % 08x, % 08x, % 08x, % 08x, % 08x, % 08x "); return 0;} Here we only gave printf a parameter, but asked it to print 12 int data, let's compile and run it to see what the results will be. Here we can see that printf faithfully prints 12 values as we wish. These values are not input parameters, but other values stored in the stack. With this feature, hackers have created a string Formatting Vulnerability. 0x02 vulnerabilities may be exploited by someone (~~ Weak scum like me ~~) May be confused about the hazards of this vulnerability, because it seems to be just printing useless junk data. In fact, it is no less harmful than stack overflow. if used properly, it is even better than stack overflow. If Stack Overflow is a blanket bombing, the formatting string vulnerability is a terrible sniper. A single blow can be fatal. As for the exploitation method of this vulnerability, there are two main types of printing memory. Just now we can see that printf can print the information in the caller's stack frame. In the 0-day attack, it is very important to obtain data from the memory of the other party, one of the exploitation methods of the formatting string vulnerability is to obtain data that should not be known in the memory. This process is called the leak memory. An important method in 0-day attacks: ret to libc is based on the leak base address. As long as we fill in enough parameters in the format, then printf can output the information stored in the stack that cannot be known. You only need to calculate the difference between the address of the format in the stack and the information address of the leak. You can get the desired data, such as the format at 0x20 and the dest at 0x00. They differ by 32 bytes in total, so we can construct strings like "% f % d, % x. "% F % d" shown before the comma can print 28 bytes of data higher than foramt. Of course this is not what we want. Then the last % x can print the desired data in hexadecimal format. Further, we know that the formatted string has the % s parameter. So, if there is a pointer in the stack that points to the data we are interested in, we can use a % s to print the content elsewhere when printing the pointer. In addition, common programs store user input data on the stack. This gives us a chance to construct a pointer and then combine the formatting string vulnerability to obtain almost all the memory data. Modifying memory or formatting string vulnerabilities can print memory information, which is not surprising. However, formatting strings can also modify data in the memory. Let's take a look at the following code.
#include <stdio.h>int main(void) { int a; printf("aaaaaaa%n\n",&a); printf("%d\n",a); return 0; }
This is a magic piece of code. Let's take a look at its running results.
We can find that the value of a is changed to 7 by the printf function. This is the efficacy of % n. This is an uncommon parameter. Its function is to assign the number of characters printed by printf before % n to the passed pointer. With % n, we can modify the value in the memory. Like % sleak memory, you can use the format string vulnerability to modify the address of memory that needs to be modified in the stack. Of course, if the data to be modified is a very large value, we can use % 02333d. On the right side of the print value, use 0 to fill in the number of digits below the limit. We can see that the memory range that can be modified by formatting strings is wider. As long as a pointer is constructed, any value in the memory can be rewritten. It is different from Stack Overflow carpet bombing. This attack method can only rewrite the memory size of one dword at a time is more refined and fatal 0x03 practice the best learning method is practice. Now let's test the effectiveness of the format string vulnerability. First, the code
#include <stdio.h>int main(void) { int flag = 0; int *p = &flag; char a[100]; scanf("%s",a); printf(a); if(flag == 2000) { printf("good!!\n"); } return 0;}
Compile with gcc. Here <-- is an executable file compiled by me. You can try it. Drag it into IDA to analyze the stack structure. The stack structure when the printf function is called is as follows:
-00000010 r dd? <-- Here is the return address of printf, And the upstream is the stack frame of printf-00000010 format dd? -00000010 dd? -00000010 dd? -00000010 dd? -0000000C flag dd? -00000008 p dd? -00000004 a db? -00000000 db? ; <-- Then down is the space of array.
The variable we can modify is the flag, and the pointer p is the pointer to the flag. So we can use p to modify the flag value to 2000, so that we can print out good !! Target> % 010x % 010x % 010x % 01970x % n this is the poc I constructed, very short, but very powerful (→ _ → ). Let's take a look at the effect.