pwnlib.memleak — Helper class for leaking memory

class pwnlib.memleak.MemLeak(f, search_range=20, reraise=True, relative=False)[源代码]

MemLeak is a caching and heuristic tool for exploiting memory leaks.

It can be used as a decorator, around functions of the form:

def some_leaker(addr):
… return data_as_string_or_None

It will cache leaked memory (which requires either non-randomized static data or a continouous session). If required, dynamic or known data can be set with the set-functions, but this is usually not required. If a byte cannot be recovered, it will try to leak nearby bytes in the hope that the byte is recovered as a side-effect.

参数:
  • f (function) – The leaker function.
  • search_range (int) – How many bytes to search backwards in case an address does not work.
  • reraise (bool) – Whether to reraise call pwnlib.log.warning() in case the leaker function throws an exception.

Example

>>> import pwnlib
>>> binsh = pwnlib.util.misc.read('/bin/sh')
>>> @pwnlib.memleak.MemLeak
... def leaker(addr):
...     print "leaking 0x%x" % addr
...     return binsh[addr:addr+4]
>>> leaker.s(0)[:4]
leaking 0x0
leaking 0x4
'\x7fELF'
>>> leaker[:4]
'\x7fELF'
>>> hex(leaker.d(0))
'0x464c457f'
>>> hex(leaker.clearb(1))
'0x45'
>>> hex(leaker.d(0))
leaking 0x1
'0x464c457f'
>>> @pwnlib.memleak.MemLeak
... def leaker_nonulls(addr):
...     print "leaking 0x%x" % addr
...     if addr & 0xff == 0:
...         return None
...     return binsh[addr:addr+4]
>>> leaker_nonulls.d(0) == None
leaking 0x0
True
>>> leaker_nonulls[0x100:0x104] == binsh[0x100:0x104]
leaking 0x100
leaking 0xff
leaking 0x103
True
>>> memory = {-4+i: c for i,c in enumerate('wxyzABCDE')}
>>> def relative_leak(index):
...     return memory.get(index, None)
>>> leak = pwnlib.memleak.MemLeak(relative_leak, relative = True)
>>> leak[-1:2]
'zAB'
static NoNewlines(function)[源代码]

Wrapper for leak functions such that addresses which contain newline bytes are not leaked.

This is useful if the address which is used for the leak is provided by e.g. fgets().

static NoNulls(function)[源代码]

Wrapper for leak functions such that addresses which contain NULL bytes are not leaked.

This is useful if the address which is used for the leak is read in via a string-reading function like scanf("%s") or smilar.

static NoWhitespace(function)[源代码]

Wrapper for leak functions such that addresses which contain whitespace bytes are not leaked.

This is useful if the address which is used for the leak is read in via e.g. scanf().

static String(function)[源代码]

Wrapper for leak functions which leak strings, such that a NULL terminator is automaticall added.

This is useful if the data leaked is printed out as a NULL-terminated string, via e.g. printf().

b(addr, ndx = 0) → int[源代码]

Leak byte at ((uint8_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+2], reraise=False)
>>> l.b(0) == ord('a')
True
>>> l.b(25) == ord('z')
True
>>> l.b(26) is None
True
clearb(addr, ndx = 0) → int[源代码]

Clears byte at ((uint8_t*)addr)[ndx] from the cache and returns the removed value or None if the address was not completely set.

Examples

>>> l = MemLeak(lambda a: None)
>>> l.cache = {0:'a'}
>>> l.n(0,1) == 'a'
True
>>> l.clearb(0) == unpack('a', 8)
True
>>> l.cache
{}
>>> l.clearb(0) is None
True
cleard(addr, ndx = 0) → int[源代码]

Clears dword at ((uint32_t*)addr)[ndx] from the cache and returns the removed value or None if the address was not completely set.

Examples

>>> l = MemLeak(lambda a: None)
>>> l.cache = {0:'a', 1: 'b', 2: 'c', 3: 'd'}
>>> l.n(0, 4) == 'abcd'
True
>>> l.cleard(0) == unpack('abcd', 32)
True
>>> l.cache
{}
clearq(addr, ndx = 0) → int[源代码]

Clears qword at ((uint64_t*)addr)[ndx] from the cache and returns the removed value or None if the address was not completely set.

Examples

>>> c = MemLeak(lambda addr: '')
>>> c.cache = {x:'x' for x in range(0x100, 0x108)}
>>> c.clearq(0x100) == unpack('xxxxxxxx', 64)
True
>>> c.cache == {}
True
clearw(addr, ndx = 0) → int[源代码]

Clears word at ((uint16_t*)addr)[ndx] from the cache and returns the removed value or None if the address was not completely set.

Examples

>>> l = MemLeak(lambda a: None)
>>> l.cache = {0:'a', 1: 'b'}
>>> l.n(0, 2) == 'ab'
True
>>> l.clearw(0) == unpack('ab', 16)
True
>>> l.cache
{}
d(addr, ndx = 0) → int[源代码]

Leak dword at ((uint32_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+8], reraise=False)
>>> l.d(0) == unpack('abcd', 32)
True
>>> l.d(22) == unpack('wxyz', 32)
True
>>> l.d(23) is None
True
field(address, obj)[源代码]

field(address, field) => a structure field.

Leak a field from a structure.

参数:
  • address (int) – Base address to calculate offsets from
  • field (obj) – Instance of a ctypes field
Return Value:
The type of the return value will be dictated by the type of field.
field_compare(address, obj, expected)[源代码]

field_compare(address, field, expected) ==> bool

Leak a field from a structure, with an expected value. As soon as any mismatch is found, stop leaking the structure.

参数:
  • address (int) – Base address to calculate offsets from
  • field (obj) – Instance of a ctypes field
  • expected (int,str) – Expected value
Return Value:
The type of the return value will be dictated by the type of field.
n(addr, ndx = 0) → str[源代码]

Leak numb bytes at addr.

返回:A string with the leaked bytes, will return None if any are missing

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+4], reraise=False)
>>> l.n(0,1) == 'a'
True
>>> l.n(0,26) == data
True
>>> len(l.n(0,26)) == 26
True
>>> l.n(0,27) is None
True
p(addr, ndx = 0) → int[源代码]

Leak a pointer-width value at ((void**) addr)[ndx]

p16(addr, val, ndx=0)[源代码]

Sets word at ((uint16_t*)addr)[ndx] to val in the cache.

Examples

>>> l = MemLeak(lambda x: '')
>>> l.cache == {}
True
>>> l.setw(33, 0x41)
>>> l.cache == {33: 'A', 34: '\x00'}
True
p32(addr, val, ndx=0)[源代码]

Sets dword at ((uint32_t*)addr)[ndx] to val in the cache.

Examples

See setw().

p64(addr, val, ndx=0)[源代码]

Sets qword at ((uint64_t*)addr)[ndx] to val in the cache.

Examples

See setw().

p8(addr, val, ndx=0)[源代码]

Sets byte at ((uint8_t*)addr)[ndx] to val in the cache.

Examples

>>> l = MemLeak(lambda x: '')
>>> l.cache == {}
True
>>> l.setb(33, 0x41)
>>> l.cache == {33: 'A'}
True
q(addr, ndx = 0) → int[源代码]

Leak qword at ((uint64_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+16], reraise=False)
>>> l.q(0) == unpack('abcdefgh', 64)
True
>>> l.q(18) == unpack('stuvwxyz', 64)
True
>>> l.q(19) is None
True
raw(addr, numb) → list[源代码]

Leak numb bytes at addr

s(addr) → str[源代码]

Leak bytes at addr until failure or a nullbyte is found

返回:A string, without a NULL terminator. The returned string will be empty if the first byte is a NULL terminator, or if the first byte could not be retrieved.

Examples

>>> data = "Hello\x00World"
>>> l = MemLeak(lambda a: data[a:a+4], reraise=False)
>>> l.s(0) == "Hello"
True
>>> l.s(5) == ""
True
>>> l.s(6) == "World"
True
>>> l.s(999) == ""
True
setb(addr, val, ndx=0)[源代码]

Sets byte at ((uint8_t*)addr)[ndx] to val in the cache.

Examples

>>> l = MemLeak(lambda x: '')
>>> l.cache == {}
True
>>> l.setb(33, 0x41)
>>> l.cache == {33: 'A'}
True
setd(addr, val, ndx=0)[源代码]

Sets dword at ((uint32_t*)addr)[ndx] to val in the cache.

Examples

See setw().

setq(addr, val, ndx=0)[源代码]

Sets qword at ((uint64_t*)addr)[ndx] to val in the cache.

Examples

See setw().

sets(addr, val, null_terminate=True)[源代码]

Set known string at addr, which will be optionally be null-terminated

Note that this method is a bit dumb about how it handles the data. It will null-terminate the data, but it will not stop at the first null.

Examples

>>> l = MemLeak(lambda x: '')
>>> l.cache == {}
True
>>> l.sets(0, 'H\x00ello')
>>> l.cache == {0: 'H', 1: '\x00', 2: 'e', 3: 'l', 4: 'l', 5: 'o', 6: '\x00'}
True
setw(addr, val, ndx=0)[源代码]

Sets word at ((uint16_t*)addr)[ndx] to val in the cache.

Examples

>>> l = MemLeak(lambda x: '')
>>> l.cache == {}
True
>>> l.setw(33, 0x41)
>>> l.cache == {33: 'A', 34: '\x00'}
True
struct(address, struct)[源代码]

struct(address, struct) => structure object Leak an entire structure. :param address: Addess of structure in memory :type address: int :param struct: A ctypes structure to be instantiated with leaked data :type struct: class

Return Value:
An instance of the provided struct class, with the leaked data decoded

Examples

>>> @pwnlib.memleak.MemLeak
... def leaker(addr):
...     return "A"
>>> e = leaker.struct(0, pwnlib.elf.Elf32_Phdr)
>>> hex(e.p_paddr)
'0x41414141'
u16(addr, ndx=0)[源代码]

w(addr, ndx = 0) -> int

Leak word at ((uint16_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+4], reraise=False)
>>> l.w(0) == unpack('ab', 16)
True
>>> l.w(24) == unpack('yz', 16)
True
>>> l.w(25) is None
True
u32(addr, ndx=0)[源代码]

d(addr, ndx = 0) -> int

Leak dword at ((uint32_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+8], reraise=False)
>>> l.d(0) == unpack('abcd', 32)
True
>>> l.d(22) == unpack('wxyz', 32)
True
>>> l.d(23) is None
True
u64(addr, ndx=0)[源代码]

q(addr, ndx = 0) -> int

Leak qword at ((uint64_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+16], reraise=False)
>>> l.q(0) == unpack('abcdefgh', 64)
True
>>> l.q(18) == unpack('stuvwxyz', 64)
True
>>> l.q(19) is None
True
u8(addr, ndx=0)[源代码]

b(addr, ndx = 0) -> int

Leak byte at ((uint8_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+2], reraise=False)
>>> l.b(0) == ord('a')
True
>>> l.b(25) == ord('z')
True
>>> l.b(26) is None
True
w(addr, ndx = 0) → int[源代码]

Leak word at ((uint16_t*) addr)[ndx]

Examples

>>> import string
>>> data = string.ascii_lowercase
>>> l = MemLeak(lambda a: data[a:a+4], reraise=False)
>>> l.w(0) == unpack('ab', 16)
True
>>> l.w(24) == unpack('yz', 16)
True
>>> l.w(25) is None
True