printf cannot write anywhere without using the %n format specifier. This is the one you're missing. Something like %.987654d%n will write the number 987654 (the number of characters output so far) to an address specified by the second argument, where the first argument is an int. This should be enough to get you started.

Answer from R.. GitHub STOP HELPING ICE on Stack Overflow
🌐
OWASP Foundation
owasp.org › www-community › attacks › Format_string_attack
Format string attack | OWASP Foundation
The line printf(argv[1]); in the example is vulnerable, if you compile the program and run it: ... The printf in the second line will interpret the %s%s%s%s%s%s in the input string as a reference to string pointers, so it will try to interpret every %s as a pointer to a string, starting from the location of the buffer (probably on the Stack). At some point, it will get to an invalid address, and attempting to access it will cause the program to crash.
🌐
Vickieli
vickieli.dev › binary exploitation › format-string-vulnerabilities
Format String Vulnerabilities - Vickie Li’s Security Blog
August 9, 2020 - Using these techniques, and the trick to access any memory location mentioned in the last section, an attacker can write to arbitrary memory locations. This can allow the attacker to overwrite return addresses, function pointers, the global offset table (GOT), and the destructor table (DTORS), thereby hijacking the flow of the program and execute arbitrary code. Since function arguments for %s are passed by reference, for each %s in the format string, the function will retrieve a value from the stack, treat the value as an address, and print out the string stored at that address.
Discussions

c - How to write value into an address in format string attack - Stack Overflow
I'm taking a security course which needs us to do format string attack on an unix virtual machine. The vulnerability is a format string using command line argument. My question is how can I write value into an address in format string (like write shell code address into function return address)? More on stackoverflow.com
🌐 stackoverflow.com
c - How can a Format-String vulnerability be exploited? - Stack Overflow
Uncontrolled format string is a type of software vulnerability, discovered around 1999, that can be used in security exploits. Previously thought harmless, format string exploits can be used to crash a program or to execute harmful code. A typical exploit uses a combination of these techniques to force a program to overwrite the address ... More on stackoverflow.com
🌐 stackoverflow.com
Confused about format string vulnerability explanation
Could you provide an excerpt so people can look at it? More on reddit.com
🌐 r/netsecstudents
7
12
January 13, 2022
c - Overwrite return address simple format string exploit - Stack Overflow
Yes, quite a few similar questions exist already (5037601, 19166698, 4855162, 14505995, 5052648, 13409508, 7745146, 7459630; sorry, not enough rep for more than 2 links), and yes, there are some nice More on stackoverflow.com
🌐 stackoverflow.com
🌐
Gts3
tc.gts3.org › cs6265 › tut › tut05-fmtstr.html
Tut05: Format String Vulnerability - CS6265: Information Security Lab
Please modify template.py to overwrite ... a control-hijacking attack using this format string vulnerability. The plan is simple: overwrite the GOT of puts() with the address of print_key(), so that when puts() is invoked, execution is actually redirected to print_key()...
🌐
Stanford
cs155.stanford.edu › papers › formatstring-1.2.pdf pdf
Exploiting Format String Vulnerabilities scut / team teso September 1, 2001
September 1, 2001 - we can extend its length by abusing format string parameters. Since the · second sprintf is not checking the length, this can be used to break out · of the boundaries of outbuf. Now we write a return address (0xbfffd33c)
🌐
Medium
medium.com › @danielorihuelarodriguez › format-string-vulnerability-439acbe81ddf
Format string vulnerability. What’s a format string vulnerability? | by DanielOrihuela | Medium
November 5, 2024 - The main problem is that the format string, when unchecked, let’s user insert format parameters to read and write memory addresses inside and before the stack.
🌐
Hacking Lab
hackinglab.cz › en › blog › format-string-vulnerability
Format String Vulnerability - Hacking Lab
October 21, 2024 - So in the example above, an attacker would prepare four write addresses (offset by one byte) at the beginning of the format string, followed by format parameters to ensure that the address is written correctly. Since he would want to write a specific value to each address, he would separate the addresses with any four characters.
🌐
BreakInSecurity
axcheron.github.io › exploit-101-format-strings
Exploit 101 - Format Strings - BreakInSecurity
April 22, 2018 - We have to change the value pointed by 080498ac (exit()) with the address of hello(): 080484cb. Now, concerning the position of our string, it’s the 4th parameters on the stack : $ ./format4 AAAAx.x.x.x.x.x AAAA00000200.b7fcb5a0.08048508.41414141.78383025.3830252e $ ./format4 AAAA%4$p AAAA0x41414141 · Here, we’ll write 080484cb in two parts, the low order bytes then, the high order bytes.
Find elsewhere
🌐
Cheese-hub
cheese-hub.github.io › secure-coding › 04-formatstring › index.html
Secure Coding: Format String Vulnerability
August 5, 2019 - However, although secret[1] is just right after secret[0], its address is not available on the stack. This poses a major challenge for your format-string exploit, which needs to have the exact address right on the stack in order to read or write to that address.
Top answer
1 of 6
98

You may be able to exploit a format string vulnerability in many ways, directly or indirectly. Let's use the following as an example (assuming no relevant OS protections, which is very rare anyways):

int main(int argc, char **argv)
{
    char text[1024];
    static int some_value = -72;

    strcpy(text, argv[1]); /* ignore the buffer overflow here */

    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);

    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}

The basis of this vulnerability is the behaviour of functions with variable arguments. A function which implements handling of a variable number of parameters has to read them from the stack, essentially. If we specify a format string that will make printf() expect two integers on the stack, and we provide only one parameter, the second one will have to be something else on the stack. By extension, and if we have control over the format string, we can have the two most fundamental primitives:


Reading from arbitrary memory addresses

[EDIT] IMPORTANT: I'm making some assumptions about the stack frame layout here. You can ignore them if you understand the basic premise behind the vulnerability, and they vary across OS, platform, program and configuration anyways.

It's possible to use the %s format parameter to read data. You can read the data of the original format string in printf(text), hence you can use it to read anything off the stack:

./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]

Writing to arbitrary memory addresses

You can use the %n format specifier to write to an arbitrary address (almost). Again, let's assume our vulnerable program above, and let's try changing the value of some_value, which is located at 0x08049794, as seen above:

./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]

We've overwritten some_value with the number of bytes written before the %n specifier was encountered (man printf). We can use the format string itself, or field width to control this value:

./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]

There are many possibilities and tricks to try (direct parameter access, large field width making wrap-around possible, building your own primitives), and this just touches the tip of the iceberg. I would suggest reading more articles on fmt string vulnerabilities (Phrack has some mostly excellent ones, although they may be a little advanced) or a book which touches on the subject.


Disclaimer: the examples are taken [although not verbatim] from the book Hacking: The art of exploitation (2nd ed) by Jon Erickson.

2 of 6
21

It is interesting that no-one has mentioned the n$ notation supported by POSIX. If you can control the format string as the attacker, you can use notations such as:

"%200$p"

to read the 200th item on the stack (if there is one). The intention is that you should list all the n$ numbers from 1 to the maximum, and it provides a way of resequencing how the parameters appear in a format string, which is handy when dealing with I18N (L10N, G11N, M18N*).

However, some (probably most) systems are somewhat lackadaisical about how they validate the n$ values and this can lead to abuse by attackers who can control the format string. Combined with the %n format specifier, this can lead to writing at pointer locations.


* The acronyms I18N, L10N, G11N and M18N are for internationalization, localization, globalization, and multinationalization respectively. The number represents the number of omitted letters.

🌐
Invicti
invicti.com › blog › web-security › format-string-vulnerabilities
What Are Format String Vulnerabilities?
By crafting format strings that contain a specific number of bytes, attackers can read memory from arbitrary addresses. This is already a critical buffer overread vulnerability that can be used to extract information and prepare other attacks ...
🌐
Exploit-DB
exploit-db.com › docs › english › 28476-linux-format-string-exploitation.pdf pdf
Format String Exploitation-Tutorial By Saif El-Sherei www.elsherei.com
Now to write address 0xDDCCBBAA 4 writes 1 byte at a time are required shown below: ... The width of the format string “%8x” for example is the minimum which will pad the output of the
🌐
Medium
medium.com › swlh › binary-exploitation-format-string-vulnerabilities-70edd501c5be
Binary Exploitation: Format String Vulnerabilities | by Vickie Li | The Startup | Medium
September 10, 2020 - Using these techniques, and the trick to access any memory location mentioned in the last section, an attacker can write to arbitrary memory locations. This can allow the attacker to overwrite return addresses, function pointers, the global offset table (GOT), and the destructor table (DTORS), thereby hijacking the flow of the program and execute arbitrary code. Since function arguments for %s are passed by reference, for each %s in the format string, the function will retrieve a value from the stack, treat the value as an address, and print out the string stored at that address.
🌐
Null Byte
null-byte.wonderhowto.com › how-to › exploit-development-write-specific-values-memory-with-format-string-exploitation-0182112
Exploit Development: How to Write Specific Values to Memory with Format String Exploitation :: Null Byte
March 9, 2018 - This way, we'll be able to start the vulnerable program and pass it our exploit code all from one place. The struct package allows us to write addresses such as 0x01025544 to variables in a format that the vulnerable program will understand easily.
🌐
Codearcana
codearcana.com › posts › 2013 › 05 › 02 › introduction-to-format-string-exploits.html
Introduction to format string exploits
May 2, 2013 - Well, printf has a really interesting format specifier: %n. From the man page of printf: The number of characters written so far is stored into the integer indicated by the int * (or variant) pointer argument. No argument is converted. If we were to pass the string AAAA$n, we would write the value 4 to the address 0x41414141!
🌐
CTF Handbook
ctf101.org › binary-exploitation › what-is-a-format-string-vulnerability
Format String Vulnerability - CTF Handbook
While these bugs are powerful, they're very rare nowadays, as all modern compilers warn when printf is called with a non-constant string. #include <stdio.h> #include <unistd.h> int main() { int secret_num = 0x8badf00d; char name[64] = {0}; read(0, name, 64); printf("Hello "); printf(name); printf("! You'll never get my secret!\n"); return 0; } Due to how GCC decided to lay out the stack, secret_num is actually at a lower address on the stack than name, so we only have to go to the 7th "argument" in printf to leak the secret:
🌐
NVISO Labs
blog.nviso.eu › 2024 › 05 › 23 › format-string-exploitation-a-hands-on-exploration-for-linux
Format String Exploitation: A Hands-On Exploration for Linux – NVISO Labs
May 23, 2024 - This is a type of vulnerability where submitted data of an input string is evaluated as an argument to an unsafe use of e.g., a printf() function by the application, resulting in the ability to read and/or write to memory.
🌐
GitHub
github.com › whatsyourask › basics-of-pwn › blob › main › content › format-string › format-string.md
basics-of-pwn/content/format-string/format-string.md at main · whatsyourask/basics-of-pwn
Let's read the strings Access denied. and Access granted. which are just before our input string. $ ./read-arbitrary-data asfsadfas Access denied. AAAA$s$s Say goodbye!!!AAAAAccess granted. Access denied. Now you know how to read data that is not meant to be read. Then try writing some data, and here I will show you how to write an arbitrary address into the return address in the format-string binary so that you can jump to it later.
Author   whatsyourask