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.
参数: 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.
参数: - 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
-
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
-
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