Skip to content

Commit

Permalink
Fix ROP without a writeable cache directory (#2123)
Browse files Browse the repository at this point in the history
* Fix ROP without a writeable cache directory

`context.cache_dir` can be None, but the ROP class assumed it would always be a valid path and crash. Disable rop-cache if we can't save it.

Fixes #2072

* Update CHANGELOG.md
  • Loading branch information
peace-maker committed Oct 27, 2022
1 parent 493a3e3 commit a7cb549
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -94,11 +94,13 @@ The table below shows which release corresponds to each branch, and what date th
- [#1828][1828] libcdb: Load debug info and unstrip libc binary
- [#1939][1939] Fix error in validating log levels
- [#1981][1981] Fix `cyclic_find()` to make it work with large int values
- [#2123][2123] Fix ROP without a writeable cache directory

[1922]: https://github.com/Gallopsled/pwntools/pull/1922
[1828]: https://github.com/Gallopsled/pwntools/pull/1828
[1939]: https://github.com/Gallopsled/pwntools/pull/1939
[1981]: https://github.com/Gallopsled/pwntools/pull/1981
[2123]: https://github.com/Gallopsled/pwntools/pull/2123

## 4.7.1

Expand Down
12 changes: 10 additions & 2 deletions pwnlib/rop/rop.py
Expand Up @@ -1189,6 +1189,9 @@ def __flat_at__(self, address):

def __get_cachefile_name(self, files):
"""Given an ELF or list of ELF objects, return a cache file for the set of files"""
if context.cache_dir is None:
return None

cachedir = os.path.join(context.cache_dir, 'rop-cache')
if not os.path.exists(cachedir):
os.mkdir(cachedir)
Expand All @@ -1205,21 +1208,26 @@ def __get_cachefile_name(self, files):
@staticmethod
def clear_cache():
"""Clears the ROP gadget cache"""
if context.cache_dir is None:
return
cachedir = os.path.join(context.cache_dir, 'rop-cache')
shutil.rmtree(cachedir)

def __cache_load(self, elf):
filename = self.__get_cachefile_name(elf)
if not os.path.exists(filename):
if filename is None or not os.path.exists(filename):
return None
gadgets = eval(open(filename).read())
gadgets = {k - elf.load_addr + elf.address:v for k, v in gadgets.items()}
log.info_once('Loaded %s cached gadgets for %r', len(gadgets), elf.file.name)
return gadgets

def __cache_save(self, elf, data):
filename = self.__get_cachefile_name(elf)
if filename is None:
return
data = {k + elf.load_addr - elf.address:v for k, v in data.items()}
open(self.__get_cachefile_name(elf), 'w+').write(repr(data))
open(filename, 'w+').write(repr(data))

def __load(self):
"""Load all ROP gadgets for the selected ELF files"""
Expand Down

0 comments on commit a7cb549

Please sign in to comment.