Compare commits

...
663 Commits
Author SHA1 Message Date
Arusekk 904872edc8 Release 4.0.1 2020-01-22 21:57:27 +01:00
Zach RiggleandArusekk 7b072dc7f7 Fix gadget caching for ROP objects with multiple ELFs (#1115)
* Fix test breakage caused by Sphinx deprecation

Closes #1112

* Fix gadget caching for ROP objects with multiple ELFs

Fixes Gallopsled/pwntools#1114

* Update requirements, fix travis failing

Co-authored-by: Arusekk <[email protected]>
2020-01-22 21:49:10 +01:00
CptGibbon eee1503252 Correct self.buffer.add() to self.buffer.unget() in recvline_pred() (#1412) 2020-01-18 20:46:22 +01:00
Arusekk a50265eb30 Release 4.0.0 2020-01-09 18:54:49 +01:00
Arusekk f34783b1f9 Will investigate later 2019-12-13 23:25:36 +01:00
Arusekk 76de9302ef Apply #1391 with additional doctest 2019-12-13 23:00:34 +01:00
Arusekk c578d5661d Merge branch 'stable' into beta 2019-12-13 22:56:02 +01:00
Arusekk 22d441c200 Fix python 2 regression in readline 2019-12-06 10:57:16 +01:00
Arusekk fcc9642250 Fix ugly raw_input()-related stuff
Closes #1373 #1379 #1380
2019-12-06 10:45:30 +01:00
kwendim 9c6ca14eeb fix rop gadgets caching (#1369) 2019-12-05 00:39:49 +01:00
Arusekk f7193293cc Enhance pwnlib.ui python3 support
Closes #1379

side note: will need to redesign the
ugly input()/raw_input() override that goes on somewhere
2019-12-05 00:30:30 +01:00
Arusekk 5b0c6922e7 Release 4.0.0beta0 2019-11-05 19:41:17 +01:00
Arusekk 33524d74a5 Release 3.13.0 2019-11-05 18:39:55 +01:00
Arusekk 2456186f7c Fix elf regression for python3 2019-11-05 13:31:35 +01:00
Arusekk 714ae6ab69 Merge branch 'dev' into dev3 2019-11-05 11:28:57 +01:00
Arusekk c3083d8d92 Merge branch 'beta' into dev 2019-11-05 11:18:42 +01:00
Arusekk 56869f0e47 Fix regression in context 2019-11-05 11:11:07 +01:00
Arusekk 2b843891f4 Fix regression in cyclic 2019-11-05 10:42:39 +01:00
Arusekk d8a2359100 Merge branch 'stable' into beta 2019-11-05 10:40:48 +01:00
Arusekk dd9bbd0e51 Oh that actually broke packing 2019-11-05 10:34:46 +01:00
Arusekk 5babddd95c Fix regression 2019-11-04 19:28:53 +01:00
Arusekk 3720314f4d Merge remote-tracking branch 'zachriggle/context-validation' into dev 2019-11-04 17:53:31 +01:00
Arusekk 0129fdd4af Merge remote-tracking branch 'zachriggle/ELF-populate-maps' into dev 2019-11-04 17:41:23 +01:00
xtrm0 215b2e6920 Reduce cache filename length on rop.py (fix #1180) (#1204)
* Reduce cache filename length on rop.py (fix #1180)

* ROP cache elfs sorting
2019-11-04 17:11:16 +01:00
Arusekk e0af5e864f Merge branch 'dev' into dev3 2019-10-30 15:50:47 +01:00
Arusekk 5a23b22761 Merge branch 'beta' into dev 2019-10-30 15:50:21 +01:00
Arusekk 6f510a3270 Merge branch 'stable' into beta 2019-10-30 15:49:06 +01:00
ipersons ff2f4f5bf2 Fix Nested SSH Connectors (#1175)
* Handle layered proxying in ssh_connecter

* better error handling

* Fix ssh problems
2019-10-30 15:46:22 +01:00
Arusekk f49f931ee8 Fix ROP appended arguments
Closes #1357
2019-10-30 14:50:44 +01:00
veritas501 b75b4aa2f0 fix vmlinux memory read bug (#1272)
* fix vmlinux memory read bug

* remove some comments
2019-10-30 12:59:32 +01:00
erfur 9e0d96b4b6 Add color argument of checksec to docstring (#1352) 2019-10-30 12:57:55 +01:00
Arusekk 2116bf3118 Merge branch 'dev' into dev3 2019-10-22 20:53:04 +02:00
Arusekk ec314ddf71 Merge branch 'beta' into dev 2019-10-22 20:52:12 +02:00
Arusekk c0056b71d7 Merge branch 'stable' into beta 2019-10-22 20:51:03 +02:00
Oshawk 92e01a7dca Fix 'break' syscall (#1355)
* Fix 'break' syscall

Fixed the 'break' syscall by renaming the method to break_ so as not to collide with the keyword.

* Bypass pypa/pip#6275
2019-10-22 20:48:45 +02:00
heinrich5991 fb1178418b Fix update ignore check for Python 3 (#1348)
`read` returns bytes and its result can never equal a string.
2019-10-09 22:30:42 +02:00
Arusekk 8fdfd95df6 Merge branch 'dev' into dev3 2019-09-24 11:51:32 +02:00
Arusekk 2808b5cd57 Code style and clarity 2019-09-24 10:33:38 +02:00
Benno Fünfstück d2b9e48cf0 Improve format string generator (#1216)
* feat(fmtstr): place pointers after format operations

This means that the format string can now also work in certain
cases even if the pointers contain null bytes.

That's especially important on 64 bit where most pointers contain null bytes.

* fix(fmtstr): more stuff

* feat(fmtstr): optimize

* perf(fmtstr): make sorting run in reasonable time (not perfect yet)

* perf(fmtstr): be faster

* style(fmtstr): more docs, some cleanup

* fix(fmtstr): small fixes + more docs

* style(fmtstr): cleanup small style issues

* fix(fmtstr): fix handling of szmax in merge_atoms_overlapping

* fix(fmtstr): fix Atom __getitem__ for out-of-bounds index

* refactor(fmtstr): docs and cleaner code

* fix(fmtstr): small test/doc fixes

* tests(fmtstr): add example as tests for other arches

* doc(fmtstr): more docstrings

* fix(fmtstr): fix cyclic_find warnings

* refactor(fmtstr): remove another nested function

* tests(fmtstr): fix doctest output for wrong arch

* style(fmtstr): remove unused imports

* tests(fmtstr): add binaries for tests
2019-09-24 09:34:25 +02:00
Calle Svensson 138fecf524 Perform all string formatting in log statement 2019-09-23 20:54:59 -07:00
Calle Svensson 8d78806ded Fix #1262 - Static format string for ELF description 2019-09-23 20:54:59 -07:00
colinmkinsella 1566c903ad Dev3 (#1343)
* Updates to requirements.txt.

Removed the < 1.8.0 requirement for sphinx. It appeared no longer
necessary.

Alphabetized the listing for easier searching.

Moved the requirements file under the docker folder. Docker does not
like relative paths to parent directories due to security restrictions.

* Updated Dockerfile to use Python3.

* Fixes to srop test errors.

Moving the imports to the beginning of the file resolved the issue.

The following errors were popping up during testing within Docker:

Document: rop/srop
------------------
**********************************************************************
File "rop/srop.rst", line ?, in default
Failed example:
    p.recvline()
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
        compileflags, 1), test.globs)
      File "<doctest default[18]>", line 1, in <module>
        p.recvline()
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 467, in recvline
        return self.recvuntil(self.newline, drop = not keepends, timeout = timeout)
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 310, in recvuntil
        res = self.recv(timeout=self.timeout)
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 82, in recv
        return self._recv(numb, timeout) or b''
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 160, in _recv
        if not self.buffer and not self._fillbuffer(timeout):
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 131, in _fillbuffer
        data = self.recv_raw(self.buffer.get_fill_size())
      File "/home/travis/pwntools/pwnlib/tubes/process.py", line 707, in recv_raw
        raise EOFError
    EOFError
**********************************************************************
File "rop/srop.rst", line ?, in default
Failed example:
    p.poll(block=True)
Expected:
    0
Got:
    -11
**********************************************************************
File "rop/srop.rst", line ?, in default
Failed example:
    p.recvline()
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
        compileflags, 1), test.globs)
      File "<doctest default[18]>", line 1, in <module>
        p.recvline()
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 467, in recvline
        return self.recvuntil(self.newline, drop = not keepends, timeout = timeout)
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 310, in recvuntil
        res = self.recv(timeout=self.timeout)
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 82, in recv
        return self._recv(numb, timeout) or b''
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 160, in _recv
        if not self.buffer and not self._fillbuffer(timeout):
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 131, in _fillbuffer
        data = self.recv_raw(self.buffer.get_fill_size())
      File "/home/travis/pwntools/pwnlib/tubes/process.py", line 707, in recv_raw
        raise EOFError
    EOFError
**********************************************************************
File "rop/srop.rst", line ?, in default
Failed example:
    p.poll(block=True)
Expected:
    0
Got:
    -11
**********************************************************************
File "rop/srop.rst", line ?, in default
Failed example:
    p.recvline()
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
        compileflags, 1), test.globs)
      File "<doctest default[18]>", line 1, in <module>
        p.recvline()
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 467, in recvline
        return self.recvuntil(self.newline, drop = not keepends, timeout = timeout)
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 310, in recvuntil
        res = self.recv(timeout=self.timeout)
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 82, in recv
        return self._recv(numb, timeout) or b''
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 160, in _recv
        if not self.buffer and not self._fillbuffer(timeout):
      File "/home/travis/pwntools/pwnlib/tubes/tube.py", line 131, in _fillbuffer
        data = self.recv_raw(self.buffer.get_fill_size())
      File "/home/travis/pwntools/pwnlib/tubes/process.py", line 707, in recv_raw
        raise EOFError
    EOFError
**********************************************************************
File "rop/srop.rst", line ?, in default
Failed example:
    p.poll(block=True)
Expected:
    0
Got:
    -11
**********************************************************************
1 items had failures:
   6 of 159 in default
159 tests in 1 items.
153 passed and 6 failed.
***Test Failed*** 6 failures.

* Fix for docstring warning in dynelf.py.

The following warning is resolved with this fix:

/home/travis/pwntools/pwnlib/dynelf.py:docstring of pwnlib.dynelf.DynELF._resolve_symbol_sysv:11: WARNING: Definition list ends without a blank line; unexpected unindent.

* Fix for docstring warnings in gdb.py.

The following warnings are resolved with this fix:

/home/travis/pwntools/pwnlib/gdb.py:docstring of pwnlib.gdb.debug_assembly:8: WARNING: Inline strong start-string without end-string.
/home/travis/pwntools/pwnlib/gdb.py:docstring of pwnlib.gdb.debug_assembly:21: WARNING: Block quote ends without a blank line; unexpected unindent.
/home/travis/pwntools/pwnlib/gdb.py:docstring of pwnlib.gdb.debug_shellcode:4: WARNING: Inline strong start-string without end-string.
/home/travis/pwntools/pwnlib/gdb.py:docstring of pwnlib.gdb.debug_shellcode:17: WARNING: Block quote ends without a blank line; unexpected unindent.

* Fix for adb/__init__.py.

The following error is resolved with this fix:

Document: protocols/adb
-----------------------
**********************************************************************
File "../../pwnlib/protocols/adb/__init__.py", line ?, in default
Failed example:
    pprint(AdbClient().list('/data/user'))
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.5/doctest.py", line 1321, in __run
        compileflags, 1), test.globs)
      File "<doctest default[0]>", line 1, in <module>
        pprint(AdbClient().list('/data/user'))
    TypeError: 'module' object is not callable
**********************************************************************
1 items had failures:
   1 of  10 in default
10 tests in 1 items.
9 passed and 1 failed.
***Test Failed*** 1 failures.

The following warning is resolved with this fix:

/home/travis/pwntools/pwnlib/protocols/adb/__init__.py:docstring of pwnlib.protocols.adb.AdbClient.stat:6: WARNING: Inline literal start-string without end-string.

* Fix for docstring warning in rop.py.

The following warning is resolved with this fix:

/home/travis/pwntools/pwnlib/rop/rop.py:docstring of pwnlib.rop.rop.DescriptiveStack.descriptions:3: WARNING: Inline literal start-string without end-string.

* Fix for docstring warning in ssh.py.

The following warning is resolved with this fix:

/home/travis/pwntools/pwnlib/tubes/ssh.py:docstring of pwnlib.tubes.ssh.ssh._init_remote_platform_info:6: WARNING: Block quote ends without a blank line; unexpected unindent.

* Doctest dictionary ordering problem in misc.py.

There was an ordering problem while running the doctest in misc.py.
Sorting the dictionary with pprint and updating the results fixed the
issue.

Document: util/misc
-------------------
**********************************************************************
File "../../pwnlib/util/misc.py", line ?, in default
Failed example:
    sizes
Expected:
    {'eax': 32, 'ax': 16, 'al': 8, 'ah': 8, 'ebx': 32, 'bx': 16, 'bl': 8, 'bh': 8, 'ecx': 32, 'cx': 16, 'cl': 8, 'ch': 8, 'edx': 32, 'dx': 16, 'dl': 8, 'dh': 8, 'edi': 32, 'di': 16, 'esi': 32, 'si': 16, 'ebp': 32, 'bp': 16, 'esp': 32, 'sp': 16}
Got:
    {'si': 16, 'cx': 16, 'cl': 8, 'dl': 8, 'dh': 8, 'eax': 32, 'bx': 16, 'sp': 16, 'bl': 8, 'bh': 8, 'di': 16, 'esi': 32, 'edx': 32, 'dx': 16, 'ebx': 32, 'ebp': 32, 'ax': 16, 'ch': 8, 'al': 8, 'ah': 8, 'edi': 32, 'esp': 32, 'bp': 16, 'ecx': 32}
**********************************************************************
File "../../pwnlib/util/misc.py", line ?, in default
Failed example:
    bigger
Expected:
    {'eax': ['eax'], 'ax': ['eax', 'ax'], 'al': ['eax', 'ax', 'al'], 'ah': ['eax', 'ax', 'ah'], 'ebx': ['ebx'], 'bx': ['ebx', 'bx'], 'bl': ['ebx', 'bx', 'bl'], 'bh': ['ebx', 'bx', 'bh'], 'ecx': ['ecx'], 'cx': ['ecx', 'cx'], 'cl': ['ecx', 'cx', 'cl'], 'ch': ['ecx', 'cx', 'ch'], 'edx': ['edx'], 'dx': ['edx', 'dx'], 'dl': ['edx', 'dx', 'dl'], 'dh': ['edx', 'dx', 'dh'], 'edi': ['edi'], 'di': ['edi', 'di'], 'esi': ['esi'], 'si': ['esi', 'si'], 'ebp': ['ebp'], 'bp': ['ebp', 'bp'], 'esp': ['esp'], 'sp': ['esp', 'sp']}
Got:
    {'si': ['esi', 'si'], 'cx': ['ecx', 'cx'], 'cl': ['ecx', 'cx', 'cl'], 'dl': ['edx', 'dx', 'dl'], 'dh': ['edx', 'dx', 'dh'], 'eax': ['eax'], 'bx': ['ebx', 'bx'], 'sp': ['esp', 'sp'], 'bl': ['ebx', 'bx', 'bl'], 'bh': ['ebx', 'bx', 'bh'], 'di': ['edi', 'di'], 'esi': ['esi'], 'edx': ['edx'], 'dx': ['edx', 'dx'], 'ebx': ['ebx'], 'ebp': ['ebp'], 'ax': ['eax', 'ax'], 'ch': ['ecx', 'cx', 'ch'], 'al': ['eax', 'ax', 'al'], 'ah': ['eax', 'ax', 'ah'], 'edi': ['edi'], 'esp': ['esp'], 'bp': ['ebp', 'bp'], 'ecx': ['ecx']}
**********************************************************************
File "../../pwnlib/util/misc.py", line ?, in default
Failed example:
    smaller
Expected:
    {'eax': ['ax', 'al', 'ah'], 'ax': ['al', 'ah'], 'al': [], 'ah': [], 'ebx': ['bx', 'bl', 'bh'], 'bx': ['bl', 'bh'], 'bl': [], 'bh': [], 'ecx': ['cx', 'cl', 'ch'], 'cx': ['cl', 'ch'], 'cl': [], 'ch': [], 'edx': ['dx', 'dl', 'dh'], 'dx': ['dl', 'dh'], 'dl': [], 'dh': [], 'edi': ['di'], 'di': [], 'esi': ['si'], 'si': [], 'ebp': ['bp'], 'bp': [], 'esp': ['sp'], 'sp': []}
Got:
    {'si': [], 'cx': ['cl', 'ch'], 'cl': [], 'dl': [], 'dh': [], 'eax': ['ax', 'al', 'ah'], 'bx': ['bl', 'bh'], 'sp': [], 'bl': [], 'bh': [], 'di': [], 'esi': ['si'], 'edx': ['dx', 'dl', 'dh'], 'dx': ['dl', 'dh'], 'ebx': ['bx', 'bl', 'bh'], 'ebp': ['bp'], 'ax': ['al', 'ah'], 'ch': [], 'al': [], 'ah': [], 'edi': ['di'], 'esp': ['sp'], 'bp': [], 'ecx': ['cx', 'cl', 'ch']}
**********************************************************************
1 items had failures:
   3 of  20 in default
20 tests in 1 items.
17 passed and 3 failed.
***Test Failed*** 3 failures.

* Fix for docstring warning in packing.py.

The following warning is resolved with this fix:

/home/travis/pwntools/pwnlib/util/packing.py:docstring of pwnlib.util.packing.flat:2: WARNING: Inline emphasis start-string without end-string.

* Removed commented out test in Dockerfile.

* Forgot to update location of requirements.txt.

Forgot to update the location of requirements.txt in .travis.yml.

* Made recommended changes from Arusekk.
2019-09-23 08:47:43 +02:00
Arusekk e6dc71c6a8 Merge branch 'dev' into dev3 2019-09-22 15:52:46 +02:00
Arusekk 53b2b0d2e7 Merge branch 'beta' into dev 2019-09-22 15:50:54 +02:00
Arusekk e3690538e7 Merge branch 'stable' into beta 2019-09-22 15:22:02 +02:00
WGH ecd6d235cd Fix TypeError: find_module() takes exactly 3 arguments (2 given) (#1342)
pwnlib.shellcraft installs its custom import finder (LazyImporter) into
sys.meta_path.

According to PEP 302, finder is expected to have prototype

    finder.find_module(fullname, path=None)

Note that the second argument is optional. pwnlib's LazyImporter has second
argument required, which leads to compatibility problems, surfacing
when trying to use pwnlib with other third-party modules:

    >>> import pwnlib
    >>> import faker
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/tmp/.venv/lib/python2.7/site-packages/faker/__init__.py", line 2, in <module>
        from faker.factory import Factory  # noqa F401
      File "/tmp/.venv/lib/python2.7/site-packages/faker/factory.py", line 12, in <module>
        from faker.config import AVAILABLE_LOCALES, DEFAULT_LOCALE, PROVIDERS
      File "/tmp/.venv/lib/python2.7/site-packages/faker/config.py", line 15, in <module>
        AVAILABLE_LOCALES = find_available_locales(PROVIDERS)
      File "/tmp/.venv/lib/python2.7/site-packages/faker/utils/loading.py", line 45, in find_available_locales
        provider_module = import_module(provider_path)
      File "/usr/lib64/python2.7/importlib/__init__.py", line 37, in import_module
        __import__(name)
      File "/tmp/.venv/lib/python2.7/site-packages/faker/providers/internet/__init__.py", line 4, in <module>
        from text_unidecode import unidecode
      File "/tmp/.venv/lib/python2.7/site-packages/text_unidecode/__init__.py", line 6, in <module>
        _replaces = pkgutil.get_data(__name__, 'data.bin').decode('utf8').split('\x00')
      File "/usr/lib64/python2.7/pkgutil.py", line 576, in get_data
        loader = get_loader(package)
      File "/usr/lib64/python2.7/pkgutil.py", line 462, in get_loader
        return find_loader(fullname)
      File "/usr/lib64/python2.7/pkgutil.py", line 473, in find_loader
        loader = importer.find_module(fullname)
    TypeError: find_module() takes exactly 3 arguments (2 given)
2019-09-22 15:17:21 +02:00
Arusekk d2423f7117 Unified text_type in py3 2019-08-28 15:07:42 +02:00
Arusekk 9243ae7f26 No print statements in py3
bytes are bytes under py3
2019-08-28 14:44:39 +02:00
Arusekk fe700b08fb Merge branch 'dev' into dev3 2019-08-28 11:50:27 +02:00
Arusekk b784d3a683 Merge branch 'beta' into dev 2019-08-28 11:48:06 +02:00
Arusekk cebd26d85f Merge branch 'stable' into beta 2019-08-28 11:29:54 +02:00
io12 58a846c84d Add freebsd generic syscall templates (#1285)
* Add freebsd generic syscall templates

* Update pwnlib/shellcraft/templates/aarch64/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update pwnlib/shellcraft/templates/aarch64/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update pwnlib/shellcraft/templates/amd64/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update pwnlib/shellcraft/templates/arm/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update pwnlib/shellcraft/templates/i386/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update pwnlib/shellcraft/templates/mips/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update pwnlib/shellcraft/templates/thumb/freebsd/syscall.asm

Co-Authored-By: io12 <[email protected]>

* Update FreeBSD syscall templates to use reversed() for stack args

* Change assignment of ABIs

* Unify sigreturn ABIs with `sysv_*`

* Fix reversed() errors
2019-08-27 11:25:46 +02:00
Arusekk c6b855dd65 Merge branch 'dev' into dev3 2019-08-27 10:52:31 +02:00
lockshaw 5d2798750d Fix timeout parameter passing in sendlineafter and other similar functions (#1277)
* Fix parameter order of sendlineafter

* Fix the same bug for the other functions in tube.py

* Update the docstrings
2019-08-27 10:32:24 +02:00
Arusekk 977f3f7314 Improve doctest coverage (#1275)
* Improve util.proc doctest coverage

* Improve util.crc coverage

* Triggering doctests for getdents and buffer

* Processes behave dynamically
2019-08-27 10:21:47 +02:00
WildfootWandArusekk 47e967238c dev3 update README.md installation part (#1338)
* dev3 update README.md installation part

* Update require python version in README.md

Co-Authored-By: Arusekk <[email protected]>
2019-08-27 10:20:59 +02:00
Arusekk 460c42be90 Fixed ROP better 2019-08-09 13:03:48 +02:00
Arusekk d1a6051360 Fix term and ROP strange behaviour 2019-08-09 11:40:49 +02:00
Arusekk 544ae930c7 Fix gdb for remote processes 2019-07-08 14:43:23 +02:00
Arusekk dce8fde0b6 Fix AttributeError instead of EOFError 2019-07-08 13:44:47 +02:00
Arusekk b0e1ce334e A fix reverted 2019-06-23 00:08:12 +02:00
Arusekk 75000ba16a Various commandline/rop fixes 2019-06-22 23:42:55 +02:00
Arusekk 8ffac64fdc Merge branch 'dev' into dev3 2019-06-22 23:40:43 +02:00
Aaron 6f127e7305 [dev3] Minor changes for python3 support (#1310)
* Removed old dependency for intervaltree and sortedcontainers

Also make the pwn command show usage if no arguments supplied

* Fix errno subcommand

The errno library moved out of os and into its own library

* Change template script to use system env python instead of only py2

* Require updated intervaltree in setup.py

* Update .travis.yml

* Update .travis.yml
2019-06-22 21:50:39 +02:00
Arusekk b2130e319c Tubes with context.encoding (#1317)
* Tubes fixed

* Typo

* Typo + default value

* Fixes on and on

* Many many more

* Missing lines and tests

* Refactoring

* Missing line again

* Missing again

* Copypaste design patterns
2019-06-22 21:19:15 +02:00
Calle Svensson 64f97dfc36 Fixes #1279 (#1304)
* Fixes #1279

* Remove redundant include
2019-05-08 15:09:28 +02:00
cclauss c15afc592a Identity is not the same thing as equality in Python (#1306)
Use ==/!= to compare str, bytes, and int literals: __fmt is not 'raw'__ --> __fmt != 'raw'__

$ __python__
```python
>>> raw = 'ra'
>>> raw += 'w'
>>> raw
'raw'
>>> raw == 'raw'
True
>>> raw is 'raw'
False
```
2019-05-08 15:00:45 +02:00
Zach Riggle 1b55c988b0 Merge pull request #1288 from cclauss/patch-1
Travis CI: The 'sudo' tag is now deprecated
2019-05-07 17:35:25 -05:00
Zach Riggle b3694ab6cb Merge pull request #1292 from xairy/stable
Provide correct arch name to gdb for sparc64
2019-05-07 17:35:10 -05:00
Zach Riggle 7e4477c08b Merge pull request #1297 from ZetaTwo/dev
Quotes around file path in gdbscript - Fixes #1291
2019-05-07 17:34:52 -05:00
Zach Riggle 587f7492b8 Merge pull request #1298 from ZetaTwo/issue-1295
Replace "lsb-release" with "lsb_release" in install script - fixes #1295
2019-05-07 17:34:25 -05:00
Zach Riggle 78be10fdf5 Merge pull request #1300 from ZetaTwo/issue-1289-2
Implements "-c" in "phd" (inefficient) - fixes issue 1289
2019-05-07 17:34:02 -05:00
Zach Riggle 4ac9aa3d1d Merge pull request #1302 from ZetaTwo/issue-1278
Don't try to set non-existing fd to non-blocking - fixes #1278
2019-05-07 17:32:47 -05:00
Calle Svensson 78326b3cf7 Don't try to set non-existing fd to non-blocking, #1278 2019-05-06 23:01:02 +02:00
Calle Svensson 1869148ab8 Implements an (inefficient) solution to issue #1289 2019-05-06 22:25:12 +02:00
Calle Svensson 7f17166aef fixes #1295 2019-05-06 22:02:05 +02:00
Calle Svensson 6c14bc4f0f Fixes #1291 2019-05-06 21:59:36 +02:00
bannsec 4cb67a857e Py3 bytes issue (#1282)
This fixes the following error attempting to use gdb module:

```
~/.virtualenvs/angr/lib/python3.6/site-packages/pwnlib/gdb.py in debug(args, gdbscript, exe, ssh, env, sysroot, **kwargs)
    468
    469     # Some versions of gdbserver output an additional message
--> 470     garbage2 = gdbserver.recvline_startswith("Remote debugging from host ", timeout=1)
    471
    472     return gdbserver

~/.virtualenvs/angr/lib/python3.6/site-packages/pwnlib/tubes/tube.py in recvline_startswith(self, delims, keepends, timeout)
    545         return self.recvline_pred(lambda line: any(map(line.startswith, delims)),
    546                                   keepends=keepends,
--> 547                                   timeout=timeout)
    548
    549     def recvline_endswith(self, delims, keepends = False, timeout = default):

~/.virtualenvs/angr/lib/python3.6/site-packages/pwnlib/tubes/tube.py in recvline_pred(self, pred, keepends, timeout)
    468                     return b''
    469
--> 470                 if pred(line):
    471                     if not keepends:
    472                         line = line[:-len(self.newline)]

~/.virtualenvs/angr/lib/python3.6/site-packages/pwnlib/tubes/tube.py in <lambda>(line)
    543             delims = (delims,)
    544
--> 545         return self.recvline_pred(lambda line: any(map(line.startswith, delims)),
    546                                   keepends=keepends,
    547                                   timeout=timeout)

TypeError: startswith first arg must be bytes or a tuple of bytes, not str
```
2019-04-30 16:37:56 +02:00
Andrey Konovalov 94bb5fde0f Provide correct arch name to gdb for sparc64
"sparc64" is not correct gdb arch name, set it to "sparc:v9" instead.
2019-04-20 15:27:35 +02:00
cclauss a5f4758cbc Travis CI: The 'sudo' tag is now deprecated
[Travis are now recommending removing the __sudo__ tag](https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration).

"_If you currently specify __sudo: false__ in your __.travis.yml__, we recommend removing that configuration_"
2019-03-29 13:14:33 +01:00
Arusekk cf6be82831 Fix that regression for sure
Oh dear not again
2019-02-22 09:52:07 +01:00
Arusekk 7db624bc28 Fix merge regression 2019-02-22 09:18:00 +01:00
Arusekk 24e9501811 Merge branch 'dev' into dev3 2019-02-22 03:35:13 +01:00
Arusekk 224ddb411b Merge pull request #1181 from jonasbb/coredumpctl-support
Add support for coredumps which are stored using systemd-coredump
2019-02-22 03:18:01 +01:00
Arusekk f5062f7b2d Merge pull request #1274 from Gallopsled/stable
Merge travis-ci related changes on stable into dev
2019-02-22 03:08:43 +01:00
Jonas Bushart e625fc28f3 Add support for coredumps which are stored using systemd-coredump
coredumpctl is a tool that can be used to retrieve and process
core dumps and metadata which were saved by systemd-coredump(8).

systemd-coredump works by setting a piped core pattern. For example:

$ cat /proc/sys/kernel/core_pattern
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e

This commit detects `systemd-coredump` in the pattern and then uses
`coredumpctl`, which is the CLI utility for reading the coredumps.
`coredumpctl` is instructed to write the coredump to a file. The
coredump is specified using the process ID and the basename of the
executable.

This commit also updates some doc strings to fix them and make them
more useful.

This fixes #1177, #1178
2019-02-21 21:42:09 +01:00
Zach Riggle 3e58f35da2 Merge pull request #1267 from Mrmaxmeier/cfg-6
fix(py3/config): six.string_types instead of (str, unicode)
2019-02-07 08:51:58 -06:00
Mrmaxmeier 915fdef9df fix(py3/config): six.string_types instead of (str, unicode) 2019-02-07 14:29:07 +01:00
Zach Riggle d01256ef2b Merge pull request #1265 from Arusekk/disasm-1263
Long instructions disassembly without empty lines
2019-02-05 14:50:11 -06:00
Arusekk e5c8b8c288 Long instructions disassembly without empty lines
Fixes #1263
2019-02-03 15:29:55 +01:00
Zach Riggle 5fa4fcd051 Merge pull request #1182 from leommxj/dev
fix:shellcraft mips dupsh wrong redirect
2019-02-02 03:25:04 -06:00
Zach Riggle 4a4b4dcc40 Merge pull request #1186 from quantumbracket/dev
ssl custom arguments
2019-02-02 03:18:26 -06:00
Zach Riggle 239e4e4752 Do not use a dict *instance* as the default arg
While this likely won't cause issues due to the way it's used, better safe than sorry
2019-02-02 03:18:10 -06:00
Zach Riggle 3a033135fb Merge pull request #1230 from Gallopsled/ssh-attach-fix-exe-path
Fix `gdb.attach()` using a local path for remote files.
2019-02-02 03:05:58 -06:00
Zach Riggle 32762bfdb0 Merge pull request #1247 from zachriggle/fix-1244
Fix infinite loop in term.py
2019-02-02 03:01:27 -06:00
Zach Riggle 547905fae4 Merge pull request #1264 from foens/stable
Fix small issues in thumb shellcode
2019-02-02 03:01:03 -06:00
Kasper Føns dec0e1d71f add doctest 2019-02-01 16:35:17 +01:00
Zach Riggle 0d56697583 Merge branch 'stable' into stable 2019-02-01 08:53:30 -06:00
Zach Riggle c03d08b1c4 Merge pull request #1260 from Arusekk/travis-xenial-1260
Switch Travis CI to 16.04 (xenial)
2019-02-01 08:53:14 -06:00
Kasper Føns aeee34f62b Fix erroneous comment 2019-02-01 15:26:49 +01:00
Kasper Føns 3f1dc93245 Fix wrong import of mov instruction 2019-02-01 15:26:28 +01:00
Arusekk 20e9fc2f53 Fix typo 2019-01-31 11:53:38 +01:00
Arusekk c54ad5647d Spawning a process to test its name 2019-01-31 11:47:59 +01:00
Arusekk 010c17dd6f Re-apply #282 changes 2019-01-31 11:14:25 +01:00
Zach Riggle 734f91efdd Remove inaccurate / outdated statement
Pwntools does not bundle any GNU tools for a long time.
2019-01-31 04:10:24 -06:00
Arusekk d5e02f27ac util.proc portability 2019-01-31 10:53:27 +01:00
Arusekk 9609374e97 Fix punctuation in disassemblies 2019-01-31 09:52:48 +01:00
Zach Riggle daa87d6438 Merge branch 'beta' into dev 2019-01-30 17:11:56 -06:00
Zach Riggle 3eac01ed89 Merge branch 'stable' into beta 2019-01-30 17:11:43 -06:00
Zach Riggle 3ecd151f2b Merge branch 'stable' into travis-xenial-1260 2019-01-28 16:47:39 -06:00
Zach Riggle bf10bd70f8 Merge pull request #1252 from Gallopsled/zachriggle-patch-1
Fixes args exception with "=="
2019-01-28 16:47:26 -06:00
Zach Riggle 00bbef79bd Merge branch 'stable' into travis-xenial-1260 2019-01-28 16:47:14 -06:00
Zach Riggle 97ef2d3a74 Merge pull request #1224 from Arusekk/full-3-compat
Python 3 compatibility [ready]
2019-01-28 15:36:19 -06:00
Shivam Beeyani 1ee1488897 Update elf.py (#1235) 2019-01-28 15:24:56 -06:00
Zach Riggle afa7753f87 Merge branch 'stable' into zachriggle-patch-1 2019-01-28 15:24:43 -06:00
Arusekk 39dd2c3fe3 Fixed race condition (#1258)
ssh_channel.close() being called from ssh_channel.recvall()
2019-01-28 15:24:30 -06:00
Zach Riggle 59fe841fe5 Specify Python version and cache directories 2019-01-28 14:43:59 -06:00
Arusekk e6cd97945b Revert "[travis] Try libc6 when ld fails"
This reverts commit f43fd912f6.
2019-01-26 17:13:59 +01:00
Arusekk bb29050756 Revert "[travis] Try libc6 harder"
This reverts commit ab512f7bae.
2019-01-26 17:11:39 +01:00
Arusekk c9fb770507 Switch Travis CI to 16.04 (xenial)
Ubuntu 16.04 finally includes `binutils-mips-linux-gnu`,
which is required.  So there is no need to download
packages manually anymore.  This can help supporting
python 3.
2019-01-26 10:17:44 +01:00
Arusekk cb5c619da9 Revert "Limit the 32-bit complaint to python 2"
This reverts commit ef8d51f518.
2019-01-26 10:10:49 +01:00
Arusekk 8a099d3c2f Fixed race condition
ssh_channel.close() being called from ssh_channel.recvall()
2019-01-24 16:56:27 +01:00
Arusekk 71d44f89ca Remove a todo, trigger rebuild 2019-01-24 11:42:45 +01:00
Arusekk f5711289ce Merge branch 'dev' into full-3-compat 2019-01-24 10:46:59 +01:00
Arusekk ef8d51f518 Limit the 32-bit complaint to python 2 2019-01-24 10:44:21 +01:00
Arusekk 96127c3eaf binutils fixes 2019-01-24 00:05:53 +01:00
Zach Riggle 431cbddcf9 Revert "Slightly improve dupio with loop opcode (#1223)"
This reverts commit 24a9f92a7b.
2019-01-23 16:29:37 -06:00
Arusekk 1ba45e7de8 [tests] expect systemd instead of init 2019-01-23 09:53:50 +01:00
Arusekk 3473400619 [travis] try dist: xenial 2019-01-23 01:14:29 +01:00
Arusekk 67002e3758 [travis] try dist: bionic 2019-01-23 01:10:44 +01:00
Arusekk b486169389 [travis] try automatic config 2019-01-23 00:51:20 +01:00
Arusekk ab512f7bae [travis] Try libc6 harder 2019-01-22 22:18:18 +01:00
Arusekk f43fd912f6 [travis] Try libc6 when ld fails 2019-01-22 21:39:27 +01:00
Arusekk 79e4a269c4 Merge branch 'dev' into full-3-compat 2019-01-22 20:46:10 +01:00
Zach Riggle 927d69986c Upgrade Travis deb files to Bionic (#1255)
Fixes #1254
2019-01-22 12:37:45 -06:00
Arusekk d0a49dbf76 Does ld have different requirements? 2019-01-21 12:49:24 +01:00
Arusekk 1bd049a7bb Fix bytes iteration difference under python 3.
Sorry for overlooking this.
2019-01-21 11:54:10 +01:00
Zach Riggle 19eed571a5 Fixes args exception with "=="
Fixes #1249
2019-01-20 22:47:35 -06:00
Arusekk 351031958d Travis installation please 2019-01-20 17:05:39 +01:00
Arusekk 7a44b2cae0 Try skipping travis-specific installation 2019-01-20 16:18:24 +01:00
Arusekk 0cb5fcb9cc Merge branch 'dev' into full-3-compat 2019-01-16 08:42:19 +01:00
Robert Larsen db8ab632ca Fixed faulty read loop (#1239)
* Fixed faulty read loop

* Added doctest

* Exercise more stager functionality in doctest

* Fix whitespace in doctest

* Fix prefix in doctest

* Fix result alignment in doctest
2019-01-15 19:31:24 -06:00
Moshe Rubin 1acebdc0ec Update elf.py (#1248)
Corrected "in-pace" to read "in-place"
2019-01-15 19:30:33 -06:00
Zach Riggle 61968df85c Fix infinite loop in term.py
If the last character is an escape sequence, and we have entered graphics_mode,
the loop will never exit.

Fixes #1244
2019-01-07 15:51:25 -06:00
Zach Riggle 323ccd08f8 Update CHANGELOG for 3.12.2 2019-01-07 15:15:06 -06:00
Zach Riggle ec00cb3f90 Merge branch 'beta' into dev 2019-01-07 15:09:54 -06:00
Zach Riggle 5befb2f01d Merge branch 'stable' into beta 2019-01-07 15:09:13 -06:00
Kyle Zeng 0dc0a9acc0 check qemu_path correctly and give out a reasonable error msg (#1243) 2019-01-07 14:42:24 -06:00
Zach Riggle 774ed3b85e Do not use intervaltree 3.xx (#1242)
In the future, we may want to update Pwntools to use the newer version.

In the meantime, pin to 2.xx
2018-12-28 23:19:54 -06:00
Francesco Cagnin 3123ffe6a7 Fix typo in the help message of pwn disasm 2018-12-21 10:19:34 +01:00
Arusekk bb7653144c Features in pwn/toplevel 2018-12-01 16:28:01 +01:00
Arusekk c117ec436a Further cleanup 2018-12-01 14:49:57 +01:00
Arusekk dd62e5527e Cleanup 2018-11-27 13:30:57 +01:00
Arusekk dc2be3ae0c sorted(..., key=repr) was yet needed 2018-11-27 10:00:15 +01:00
Arusekk af7fb665ca Fixes requested by Zach Riggle 2018-11-26 23:16:34 +01:00
Zach Riggle e827c8b9f0 Update gdb.py 2018-11-23 17:00:53 -06:00
Zach Riggle b0d3e42686 Fix typo
Closes #1221
2018-11-23 16:53:41 -06:00
Arusekk 68627b0c03 Revert to original useragents.random() and give up 2018-11-22 15:42:00 +01:00
Arusekk 0b82b7c82f Fix indeterministic behavior: dict, random.choice
It's finally working!
2018-11-22 13:44:29 +01:00
Arusekk 27d8a7d615 Doctest bytes part 4 2018-11-22 12:50:12 +01:00
Arusekk 03ff7a568d Doctest bytes part 3 2018-11-22 11:29:15 +01:00
Arusekk 6bd621d7f3 Doctest bytes part 2 2018-11-21 17:35:01 +01:00
Arusekk c6154e81bf Fix python 2 regression 2018-11-21 16:45:18 +01:00
Arusekk 674943747d Doctest bytes part 1 2018-11-21 00:16:05 +01:00
Arusekk 8a2a6adeb4 Fix python 2 doctests again 2018-11-20 23:36:01 +01:00
Arusekk c13791d403 Fix wrong merge 2018-11-20 22:34:53 +01:00
Arusekk 859f884214 Merge branch 'dev' into full-3-compat 2018-11-16 20:10:49 +01:00
Arusekk bf04f1a66d Prepare for b'some_string' doctests 2018-11-16 19:53:06 +01:00
Benno Fünfstück 6a094ec4b0 fix(tests): avoid RecursionError due to weird monkey patching (#1225)
Instead of patching the whole class which produced a RecursionError we now only
patch a single function which should be less invasive.

An example of how this bug manifests can be found at https://gist.github.com/bennofs/6252b45bd026d7e95dbacf7615159ed5.
2018-11-13 14:55:15 -06:00
Arusekk 24a9f92a7b Slightly improve dupio with loop opcode (#1223) 2018-11-12 18:52:58 -06:00
Arusekk 218eb308e8 Prettify some modules 2018-11-12 15:55:10 +01:00
Arusekk 2a7d7251ef Fix ssh download infinite loop 2018-11-12 11:01:17 +01:00
Arusekk 187258792b Fix doctests under python 3 2018-11-12 00:21:50 +01:00
Arusekk 7950e75d48 Fix safeeval with python 3.6 16-bit bytecode
Reference:
https://bugs.python.org/issue26647
2018-11-11 10:03:58 +01:00
Arusekk fec31f3382 Fix python 2 regression on hexdump 2018-11-11 07:12:33 +01:00
Arusekk 566ec386eb Enable python3 testing in .travis.yml 2018-11-10 23:05:22 +01:00
Arusekk 7c8b05539d Fixed arm alphanumeric encoder support for python3 2018-11-10 22:32:42 +01:00
Arusekk ada8a9bdd0 CLI and GDB fixes 2018-11-10 22:32:42 +01:00
Arusekk c8a21cabd3 Adb wait-for-device fix 2018-11-10 22:32:42 +01:00
Arusekk 435b646880 Some fixes in pwntools cli 2018-11-10 22:32:42 +01:00
Arusekk f3d0654f97 file keyword removed, fix doctests 2018-11-10 22:32:42 +01:00
Arusekk e94b071234 Fixed setup failing with pandoc present 2018-11-10 22:32:42 +01:00
Arusekk fd7794b3d4 Some fixes 2018-11-10 22:32:42 +01:00
Arusekk 591e4012e1 Fixed non-ascii keys in readline 2018-11-10 22:32:42 +01:00
Arusekk 1679232515 Fixed readline history 2018-11-10 22:32:42 +01:00
Arusekk 40cb4e9034 Env values can contain bad characters 2018-11-10 22:32:42 +01:00
Arusekk 007d0a9b28 Update setup.py 2018-11-10 22:32:42 +01:00
Arusekk 616d2eb61c Lonely undocumented files happen 2018-11-10 22:32:42 +01:00
Arusekk ddb83dfa38 Fix last xrange 2018-11-10 22:32:42 +01:00
Arusekk 5a15d03224 Fixes for process and ssh compatibility with python3 2018-11-10 22:32:42 +01:00
Arusekk cbb54fb74b Fixed tube.interactive() and tube.stream() strange behaviour under python3 2018-11-10 22:32:42 +01:00
Arusekk a72ff4acb0 Fixed android bootloader module for python3 2018-11-10 22:32:42 +01:00
Arusekk 495a11bbd9 Interactive prompt fix for python3 2018-11-10 22:32:42 +01:00
Arusekk 1ca5cc9467 Made adb to be more python3-compatible 2018-11-10 22:32:42 +01:00
Arusekk 08e9c029ae Further improvements 2018-11-10 22:32:37 +01:00
Arusekk 7a492c6ab3 First python 3 version of up-to-date pwntools 2018-11-10 22:27:49 +01:00
Arusekk 7b5ba5cdc2 Fixed numeric literals for python 3 2018-10-29 21:24:39 +01:00
Arusekk 30a3ed454c Generating python3-compatible constants 2018-10-29 21:24:39 +01:00
Arusekk 57f0ebd762 Python 3 by-hand improvements 2018-10-29 21:24:39 +01:00
Zach Riggle da4a5c4e30 KernelConfig: Fix some typos 2018-10-22 13:28:17 -05:00
Zach Riggle d9e1118f0b Merge branch 'beta' into dev 2018-10-17 13:15:36 -05:00
Zach Riggle b8c826e057 Merge branch 'stable' into beta 2018-10-17 13:15:07 -05:00
joesixpack666 292b81af17 close ssh_channel properly in download() (#1208) (#1209)
* close ssh_channel properly in download() (#1208)

* Update ssh.py
2018-10-17 13:14:20 -05:00
Jörg Thalheim 5359ea76ed corefile: expose address to argc/argv/envp (#1200)
This is useful to reconstruct register state of main even
when the stack is smashed.
As the value is already calculated this does not add much code.
2018-10-08 20:31:17 -05:00
kpcyrd c3c06a3486 Docker: Kill 14 layers in pwntools base images (#1202)
* Docker: Kill 14 layers in pwntools base images

* Docker: Update line wrapping
2018-10-04 13:50:35 -05:00
Zach Riggle 1c99aadaef term: Defer text initialization
Closes #1201
2018-10-03 15:09:38 -05:00
leommxj 58967ddfe0 Rename dup to dupio and Modify dupsh/dupio 2018-09-18 22:31:28 +08:00
Zach Riggle c89bed2555 Merge branch 'beta' into dev 2018-09-17 17:19:10 -05:00
Zach Riggle c627115b85 Merge tag '3.12.1' into beta 2018-09-17 17:18:24 -05:00
Zach Riggle c7e9778007 Update to 3.12.1 2018-09-17 17:17:07 -05:00
Zach Riggle 90056fbeca Version bump to 3.12.1 2018-09-17 17:11:45 -05:00
Zach Riggle 60df8107c0 corefile: Update NT_XXX type names for pyelftools==0.25 (#1198)
* corefile: Update NT_XXX type names for pyelftools==0.25

* travis: Do not use Sphinx version 1.8.0, it fails with recursive errors

* corefile: Fix stack detection and Mapping.__contains__ logic

* corefile: Better detection of AT_EXECFN when NT_AUXV does not have it

* corefile: Avoid trying to parse corrupt stacks

* Fix doctests for new warning

* log: Fix warning_once caching
2018-09-17 17:04:40 -05:00
Zach Riggle 76f366d181 Update CHANGELOG for 3.12.1 2018-09-17 14:59:27 -05:00
n00bSec 9fe9152617 Add .set noat directive to fix MIPS shellcode assembly. (#1188) 2018-09-17 14:30:10 -05:00
Ricky Zhou 7467402ecf Work around renamed ENUM_P_TYPE variables in elftools 0.25 and up. 2018-09-17 14:07:24 -05:00
quantumbracket 5fe760e70b ssl custom arguments 2018-08-23 21:20:59 -04:00
leommxj 59a75055cf adding dup() to mips 2018-08-14 19:01:29 +08:00
leommxj c336932ccf fix:shellcraft mips dupsh wrong redirect 2018-08-09 19:06:10 +08:00
Zach Riggle b666e9eee1 mips: Enable XOR encoder
The encoder was never actually enabled, since we didn't set the
architecture appropriately.
2018-07-19 14:33:01 -05:00
Jörg Thalheim 9023b383af corefile: also expose page_offset (#1169)
* corefile: also expose page_offset

This is useful to load the code from the original files.

* Undo constructor field reordering

* Fix ordering in Mapping instantiation

* Commas are important

* corefile: also put page_offset as last parameter
2018-07-02 22:27:39 -05:00
Zach Riggle 0d25ca35e1 Merge branch 'beta' into dev 2018-07-02 16:58:16 -05:00
Zach Riggle 7dc76c745f Merge branch 'stable' into beta 2018-07-02 16:57:53 -05:00
Zach Riggle 80e12c7031 Switch FTP servers to ftp.ubuntu.com
Fixes Gallopsled/pwntools#1172
2018-07-02 16:57:16 -05:00
Zach Riggle b7609ae4a3 Update changelog for 3.12.1 2018-06-19 12:16:43 -05:00
Mathias Svensson 8970156e8a Revert "Fix #1164 (#1165)" (#1167)
This reverts commit 8e704e72d3.
2018-06-12 13:51:59 -05:00
Mathias Svensson 8e704e72d3 Fix #1164 (#1165) 2018-06-11 18:20:39 +02:00
pwn f4159bdad4 check if ":" exists before index(':') (#1159)
* check if ":" exists before index(':')

* Update proc.py
2018-06-04 11:13:03 -05:00
Zach Riggle c09091055f Merge remote-tracking branch 'upstream/stable' into beta 2018-05-31 15:23:13 -05:00
Zach Riggle 26e6bce81a Fix broken versions of package dependencies (#1162)
Fixes Gallopsled/pwntools#971
Fixes Gallopsled/pwntools#1154
Fixes Gallopsled/pwntools#1160
2018-05-31 15:22:45 -05:00
Inndy 6af09645e7 Prevent crash from not existed cache file in ssh.checksec() (#1150)
* Prevent crash from not existed cache file in ssh.checksec()

* Use path.exists instead of exception handling

* Fix space

* Update ssh.py
2018-05-30 14:35:23 -05:00
Robin Leander Schröder 338fbeba7a Improve pwnup template, gdbserver detection (#1148)
* Improve pwnup template

* Don't want to break at main again if its been hit already

* Always start the program

* Handle extra newline printed by gdb

* Remove moved recvline

* Remove controversial set sysroot

* Update gdb.py

* Update pwnup.mako
2018-05-30 14:32:44 -05:00
Arusekk 8da0827c25 Replaced it.next() with next(it) as of PEP-3114 (#1136)
This will also get us closer to python3.
See https://www.python.org/dev/peps/pep-3114/
2018-05-30 13:32:56 -05:00
Bruce Chen 146348f514 fix wrong gadget selection in setRegisters() (#1118) (#1156)
* fix wrong gadget selection in setRegisters() (#1118)

* Fix detection logic

* Update rop.py

* add test cases for filtering out the bad instructions in rop.py
2018-05-30 13:31:33 -05:00
Michael Rodler fe6619b336 fixed called to qemu.ld_prefix passing env dict as target (#1152) 2018-05-25 16:21:57 -05:00
Zach Riggle 1fbff016f9 Merge branch 'beta' into dev 2018-05-25 14:39:38 -05:00
Zach Riggle eeedb2c10b Merge remote-tracking branch 'upstream/stable' into beta 2018-05-25 14:38:34 -05:00
Bruce Chen 5ae13e8c8c switch to trusty build in travis ci and fix some test cases (#1155) 2018-05-25 14:38:06 -05:00
Arusekk 20cb04984a Replaced except X,Y: with except X as Y: as of PEP-3110 (#1137)
This will also get us closer to python3.
See https://www.python.org/dev/peps/pep-3110/
2018-04-30 16:16:51 -05:00
Zach Riggle 2a4a633e23 Merge remote-tracking branch 'upstream/stable' into beta 2018-04-23 16:21:56 -05:00
Arusekk 3d03a75975 Replace division with floor division as of PEP-238 (#1135)
* Replace division with floor division as of PEP-238

This will also get us closer to python3.
See https://www.python.org/dev/peps/pep-0238/

* Add from __future__ import division to source files
2018-04-11 09:42:34 -07:00
Alexey Vishnyakov 67473560c7 Check libc- as well (#1131) 2018-04-02 14:03:38 -05:00
Zach Riggle ac67b97c4d Add doctests for shellcraft.mips.sh() 2018-04-02 14:02:00 -05:00
Arusekk fc31b51436 Fix MIPS shell shellcraft not working properly (#1129)
Closes #1122
2018-04-02 13:55:45 -05:00
Michael Scherer 93080627b9 Fix compatibility with newer version of sphinx (#1124) 2018-04-02 13:54:40 -05:00
Arusekk 6c794022d5 Remove tuple parameters unpacking due to PEP-3113 (#1119)
* Fix tests relying on broken autocontrib version (#1121)

* Removed tuple parameters unpacking due to PEP-3113

As a step towards python3 compatibility, removed tuple parameters
in :mod:`pwnlib.term.term`. They are now replaced with * unpacking.
See https://www.python.org/dev/peps/pep-3113/
2018-03-19 16:28:18 -05:00
Michael Scherer 6cb9c1fce8 Fix grammar for mips doc (#1123) 2018-03-19 16:26:27 -05:00
Tyler Lambert 1cb0502157 Replace string format char (#1125)
* replace string format char

* add parentheses
2018-03-19 16:26:03 -05:00
Zach Riggle e1b3c27867 Update bootimg.py 2018-03-02 17:40:15 -06:00
Zach Riggle 532f910f9f Update bootimg.py 2018-03-02 17:39:43 -06:00
Zach Riggle c14f1a40d0 Update bootimg.py 2018-03-02 17:39:23 -06:00
Zach Riggle 1854095ee2 Expose adb.BootImage 2018-03-02 15:43:48 -06:00
Zach Riggle 76413fc91c Add pwnlib.adb.bootimg for 'ANDROID!' format boot.img images 2018-03-02 15:41:14 -06:00
Zach Riggle 1f8f294fa3 Expose BootloaderImage.header fields through __getattr__ 2018-03-02 15:40:52 -06:00
Zach Riggle 75b422a046 Fix magic bytes check in pwnlib.adb.bootloader 2018-03-02 15:29:07 -06:00
Zach Riggle 799f9a4f21 Expose BootloaderImage in ADB 2018-03-02 13:49:28 -06:00
Zach Riggle b53ec5e3ce Merge remote-tracking branch 'upstream/stable' into beta 2018-02-28 15:22:16 -06:00
Zach Riggle 9604f7847e Fix tests relying on broken autocontrib version (#1121) 2018-02-28 15:09:35 -06:00
Zach Riggle a28ae524ce Update autoprogram version 2018-02-28 13:22:27 -06:00
Zach Riggle 6e1e96d1c1 Update packages to Artful 2018-02-28 13:18:49 -06:00
Dimos Poupos d67cb152ed Fix input encoding parsing (#1111) 2018-02-23 14:46:28 -06:00
Mathias Svensson aa1f79201b Begin working on 3.14.0 2018-02-22 23:20:05 +01:00
Mathias Svensson 1e6f207956 Release 3.13.0beta0 2018-02-22 16:50:59 +01:00
Mathias Svensson c888a8cbe0 Release 3.12.0 2018-02-22 16:42:25 +01:00
Mathias Svensson 9f9d884790 Merge branch 'beta' into stable 2018-02-22 13:54:37 +01:00
Mathias Svensson 39bc5808ea Update CHANGELOG from dev 2018-02-22 13:54:19 +01:00
Zach Riggle b507bd7ed9 Merge branch 'beta' into dev 2018-02-20 14:50:12 -06:00
Zach Riggle 31f7c61c1f Merge remote-tracking branch 'stable' into beta 2018-02-20 14:49:38 -06:00
Zach Riggle 2a73356c78 Fix test breakage caused by Sphinx deprecation (#1113)
* Fix test breakage caused by Sphinx deprecation

* Fix missing import in RST

Closes #1112
2018-02-20 14:49:09 -06:00
Zach Riggle 758a9549c7 Update CHANGELOG 2018-02-20 12:30:57 -06:00
Zach Riggle 2255b7f546 Update asm.py
Fixes #1108
2018-02-19 12:08:00 -06:00
Andriamilanto T cd8f8d3f8d Removed useragentstring.com as user agents source, fixed BeautifulSoup usages and fetched new UAs (#1107) 2018-02-13 17:33:40 -06:00
david942j 25c84daa8a Fix usage of syscall open in shellcraft templates (#1106) 2018-02-09 12:53:00 -06:00
Arusekk 8a3a577394 Add BUILD_SET to const opcodes (#1103) 2018-02-07 12:43:37 -06:00
eyalitki 90f23df80b Implemented the dump() feature in the DynELF. (#1104)
* Implemented the dump() feature in the DynELF.

* Simplified the return value and made read-only pages optional
2018-02-06 15:14:29 -06:00
Zach Riggle a208251d5f Fix typo (#1099) 2018-01-26 17:40:34 -08:00
Zach Riggle aadf40980d Enable setting context.os via context.binary (#1101)
In order to support this, we detect the interpreter used via PT_INTERP

Currently, Linux is the default and Android is detected based on the path
2018-01-25 15:32:35 -08:00
Zach Riggle 14b2f29d17 Merge branch 'beta' into dev 2018-01-25 10:12:02 -08:00
Zach Riggle 68085012f1 Merge branch 'stable' into beta 2018-01-25 10:11:33 -08:00
Zach Riggle 5fdc08451d Workaround broken "pidof" on older Android emulators 2018-01-25 10:10:56 -08:00
Zach Riggle f3b5a14fb5 Don't accidentally debug init, which causes a kernel panic 2018-01-25 10:10:56 -08:00
Zach Riggle 63dfed74c6 Do not throw an exception if the Corefile cannot be deleted after copy 2018-01-25 10:10:56 -08:00
Dimos Poupos c7c5019b01 Improved hexdump output (#1094)
* improved hexdump output & groupsize feature

* doctest fix

* Parameters rearranged

* Update fiddling.py
2018-01-25 09:41:32 -08:00
Morten Brøns-Pedersen 3ff283cbef unify flat and fit (#1096) 2018-01-25 09:38:25 -08:00
Kristoffer Søholm 9859f54a21 Remove pypandoc as a dependency (#1098)
The project is pretty much unmaintained, and it is much more sane to
assume that the packager has pandoc installed.
2018-01-25 09:36:01 -08:00
Christophe GRENIER 3ff7a9e940 Fix for very old openssl: try sha256 and sha256sum before "openssl sha256" (#1068)
Check for sha256 and sha256sum before trying openssl sha256 as "openssl sha256" doesn't return an error code in some old versions of openssl (OpenSSL 0.9.8g 19 Oct 2007 at least) that doesn't support sha256.
2018-01-23 16:58:56 -08:00
Zach Riggle 7860eecf02 Prevent Python3 installation via "pip3 install pwntools" (#1093)
Pwntools does not work on Python3, so that it installs successfully is misleading.

More information on 'python_requires' can be found here:

    https://packaging.python.org/tutorials/distributing-packages/#python-requires

Specifically, it requires pip 9.0 or better -- but this is the 'official' way to do this.

Fixes Gallopsled/pwntools#1092
2018-01-04 16:42:50 -06:00
Mathias Svensson 5c4def05b2 Start working on 3.13.0dev 2018-01-03 08:23:46 +01:00
Mathias Svensson e50b978398 Release 3.12.0beta0 2018-01-03 08:21:05 +01:00
Mathias Svensson d689805690 Release 3.11.0 2018-01-03 08:19:05 +01:00
Zach Riggle 953e73aa37 Update changelog for 3.11 and 3.12 2018-01-03 08:03:28 +01:00
Mathias Svensson ee9f9fa7de Merge branch 'stable' into beta 2018-01-03 08:02:50 +01:00
Zach Riggle 35789287d8 Update changelog for 3.11 and 3.12 2018-01-02 12:53:30 -06:00
Zach Riggle 7a1ab829eb Expose pwnlib.tubes.server.server in the toplevel 2018-01-02 12:47:43 -06:00
Benno Fünfstück 46a1c44fc9 elf.py: fix variable name typo (fixes dt_rpath undefined var) (#1008) 2018-01-02 11:36:08 -06:00
Zach Riggle 899baec704 Android bootldr extraction, gdb fixes (#1085)
* Add sysroot= argument to gdb.debug, expose via 'pwn debug'

Also sets a sane default sysroot for Android debugging

* Add missing newline for "set deatch-on-fork off"

Introduced in e89a9b66ac

* Add support for extracting Android boot.img

* Fix incorrect variable in 'pwn debug'

* Ensure "file /path/to/file" is the first command
2017-12-21 15:18:38 -06:00
Disconnect3d 932cb57bf9 Better error message when gdbserver fails on LD_PRELOAD (#1083)
When one passes a `LD_PRELOAD` which cannot be preloaded the `process_created` string might end up looking like this:
```
"ERROR: ld.so: object '/bin/bash' from LD_PRELOAD cannot be preloaded (cannot dynamically load executable): ignored.\n"
```

When we end up in such situation, pwndbg shown unintuitive error:
```
$ python -c 'from pwn import *; gdb.debug("/bin/ls", env={"LD_PRELOAD": "/bin/bash"})'
[+] Starting local process '/usr/bin/gdbserver': pid 20691
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "pwnlib/context/__init__.py", line 1349, in setter
    return function(*a, **kw)
  File "pwnlib/gdb.py", line 397, in debug
    port = _gdbserver_port(gdbserver, ssh)
  File "pwnlib/gdb.py", line 234, in _gdbserver_port
    gdbserver.pid   = int(process_created.split()[-1], 0)
ValueError: invalid literal for int() with base 0: 'ignored.'
```

After this patch it will show:
```
$ python -c 'from pwn import *; gdb.debug("/bin/ls", env={"LD_PRELOAD": "/bin/bash"})'
[+] Starting local process '/usr/bin/gdbserver': pid 20863
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "pwnlib/context/__init__.py", line 1349, in setter
    return function(*a, **kw)
  File "pwnlib/gdb.py", line 402, in debug
    port = _gdbserver_port(gdbserver, ssh)
  File "pwnlib/gdb.py", line 236, in _gdbserver_port
    'Failed to spawn process under gdbserver. gdbserver error message: %s' % process_created
ValueError: Failed to spawn process under gdbserver. gdbserver error message: ERROR: ld.so: object '/bin/bash' from LD_PRELOAD cannot be preloaded (cannot dynamically load executable): ignored.

[*] Stopped process '/bin/ls' (pid 20863)
```
2017-12-12 14:22:43 -06:00
Zach Riggle 6a61617c73 Fix emulation of fault_addr (#1066)
As @bennofs noticed, our detection logic was incorrect:

"This is not a good test if I understand the issue correctly.

From my tests, it seems that fault_addr was only null before this patch if it
would've been >= 2**47.

This is because on 64 bit, that's where kernel memory is mapped so we get
"protection fault" instead of "segfault".

A protection fault does not have the same siginfo as a normal segfault:
si_code will be SI_KERNEL = 0x80 and there won't be a fault_addr

(see http://elixir.free-electrons.com/linux/v4.14-rc8/source/kernel/signal.c#L1052)"
2017-12-11 17:48:25 -06:00
Zach Riggle 6944b664e8 Switch server to ftp.ubuntu.org (#1084)
Currently ftp.debian.org is down on port 21

(cherry picked from commit ec5185c0c4)
2017-12-11 17:47:21 -06:00
Devin Neal ab8879afa3 Add server module (#1067)
* add server module

* modify example

* fix travis errors

* add queuing and blocking, fix requests

* add server.rst, change accepter to daemon

* fix import in server.rst

* added server entry in sockets.rst

* fix import in sockets.rst
2017-12-11 17:27:51 -06:00
Zach Riggle d580c0cfd1 Fix imports 2017-12-07 16:22:53 -06:00
bannsec 515f678f2d Adding GNU Screen Support (#1076)
* Adding GNU Screen support

* Adding doc

Fixes Gallopsled/pwntools#1070
2017-12-07 15:25:52 -06:00
bannsec c3afdd681d Adding non-default gdb handling (#1074)
Fixes Gallopsled/pwntools#1071
2017-12-07 15:25:27 -06:00
Owlz 5d537a6189 Fix typo on Gadget.addr -> Gadget.address 2017-12-04 14:30:41 -06:00
Zach Riggle 9ba966ddba Switch server to ftp.ubuntu.org
Currently ftp.debian.org is down on port 21
2017-12-04 14:30:41 -06:00
Zach Riggle 6ea5722f5b Add a comment to dup shellcodes 2017-11-10 17:00:25 -06:00
Zach Riggle 4e24f665b8 Use hex() for some ROP values (#1050)
* Use hex() for some ROP values

* Call str() on everything else

* Fix one more doctest
2017-11-01 16:15:25 -05:00
Zach Riggle 34cedc96d8 Remove old / unused lines in ABI 2017-11-01 16:14:40 -05:00
Zach Riggle e8065440c2 Use badbytes for ROP.search_iter 2017-11-01 16:14:40 -05:00
Zach Riggle de34906b4c Better handling for Corefiles with unsupported architectures 2017-11-01 16:14:40 -05:00
Zach Riggle 1bcf962049 Fix refactor / rename 2017-10-30 18:03:34 -05:00
Zach Riggle e89a9b66ac Handle debugging under Android better with 'pwn debug' (#1053)
* Handle debugging under Android better with 'pwn debug'

Previously, when using --process or --pid, we would terminate the gdbserver instance
when pwntools exited.  Now we wait for the user to tell us to exit.

* Handle launching Android processes by filename

* Use the --multi option with gdbserver; disable detach-on-fork

* Intentionally break doctest to make sure its running

* Revert "Intentionally break doctest to make sure its running"

This reverts commit 00578ad177.
2017-10-30 14:17:47 -05:00
Zach Riggle fcbf37860e Add doctest import to the correct file 2017-10-30 14:14:47 -05:00
cpupower 64acece61b Copy env using .copy method to preserve order (OrderedDict) (#1061)
* Copy env in process._validate using .copy method to keep the order in case of OrderedDict

* Use supplied env object to preserve order in case of OrderedDict
2017-10-30 14:12:45 -05:00
Mathias Svensson bb9004c298 Begin working on 3.12.0 2017-10-25 12:23:09 +02:00
Mathias Svensson 712295f3c5 Release 3.11.0beta0 2017-10-25 12:06:47 +02:00
Mathias Svensson cca1083f0b Release 3.10.0 2017-10-25 12:01:59 +02:00
Mathias Svensson 9dacd1b5d9 Merge branch 'stable' into beta 2017-10-25 11:56:07 +02:00
Zach Riggle d9f5a5b009 Update CHANGELOG.md 2017-10-23 23:48:53 -05:00
Zach Riggle 74a5876c0d Fix corefile environment variables and speed up ELF.string() (#1055)
* Fix corefile environment variables and speed up ELF.string()

* Even more doctests

* Fix doctest arch

* No longer split on = since it isn't necessary

* Fix arch again

* Delete intermediate corefiles

* Do not flag for extended testing when the commit SHA is what matches
2017-10-23 23:45:11 -05:00
Zach Riggle 9d6b4881fe Fix path checking in ssh_process.corefile for edge cases (#1058)
Fixes #1047
2017-10-23 15:37:48 -05:00
Zach Riggle 91025408a4 Fix incorrect variable in log statement (#1057)
Fixes #1056
2017-10-23 14:39:12 -05:00
Zach Riggle b53e58a840 Use "file /path/to/file" when debugging processes 2017-10-18 14:52:13 -05:00
Zach Riggle 438096f97f Remove doctest prefixes, these are just examples 2017-10-18 14:41:49 -05:00
Zach Riggle 7bab49e7b9 Update GDB docs and examples 2017-10-15 15:31:39 -05:00
Zach Riggle eab9eb1890 Include sample data 2017-10-14 11:18:02 -05:00
Zach Riggle 1061684baa Not need for wait() 2017-10-14 11:16:42 -05:00
Zach Riggle 8f5fec40fc Handle exceptions and silence execution 2017-10-14 11:16:12 -05:00
Zach Riggle a962666752 Move function under ELF class 2017-10-14 11:15:10 -05:00
Zach Riggle 71a6a373a0 Try to get elf/maps.py doctests to run 2017-10-13 15:28:40 -05:00
Zach Riggle 3eb738f048 Fix global rename 2017-10-13 15:02:23 -05:00
Zach Riggle 29828c3f45 Add code for injecting proc/self/maps shellcode into an ELF
Closes #925
2017-10-13 14:20:23 -05:00
Zach Riggle 412d345964 QEMU-related enhancements (#1052)
* Add support for finding QEMU's LD_PREFIX

* Refactor pwnlib.qemu and add official documentation

* Add more documentation, support for sysroot

* More docs, binfmt info

* Fix variable name overload

* Fix missed refactor

* Check for empty/null env

* Add qemu.rst to index
2017-10-12 21:41:36 -05:00
Zach Riggle b088f46988 Update CHANGELOG 2017-10-12 11:26:10 -05:00
Zach Riggle 8f3839d69e Add cyclic default args to context (#1049)
* Add cyclic default args to context

Specifically, this adds context.cyclic_alphabet and context.cyclic_size

This helps cut down on writing "n=8" all the time for users who use 8-byte
subsequences on 64-bit architectures.

Exposing the default alphabet means that users can avoid "bad bytes" in
cyclic patterns which are generated by pwntools internally (e.g. ROP padding)

Some pwnlib.util.packing docstrings were changed to clarify that word_size is
in bits.

The doctests in pwnlib.util.cyclic were updated and extended to have more
and better doctests, as well as better exaples.

* Add an example showing an alphabet with NUL bytes

This is important because old code would use pack(..., "all") when an integer
value was provided, instead of using the correct width.
2017-10-11 19:08:31 -05:00
Zach Riggle 5a81e71368 Update README 2017-10-11 16:59:37 -05:00
Zach Riggle 1577263334 Overhaul ROP.setRegisters to support more complex cases needed by AMD64 (#1044)
* Overhaul ROP.setRegisters to support more complex cases needed by AMD64

Additionally, have a separate cache for ROPs composed of multiple ELF files

* Better presentation for stack padding slots

* Remove unnecessary stack adjustment on amd64

For amd64, it is possible that len(stackArguments) == 0.

* Add a doctest for amd64 register dependency stuff

* More i386 adjust optimizations

* Use nextGadgetAddr as the adjust value

* Always use padding for the last "ret" adjustment

* Better dump display

* Update doctests for new ROP dump() enhancements

* Add badchars support for ROP gadgets

* More doctest fixes, also ensure ROP.search does not return gadgets ending in e.g. int 0x80
2017-10-11 16:57:38 -05:00
Mathias Svensson 7ad5a4e34e Merge branch 'beta' into dev 2017-10-05 09:59:45 +02:00
Mathias Svensson 513682373e Release 3.10.0beta2 2017-10-05 09:44:33 +02:00
Mathias Svensson df7c1fef9d Release 3.9.2 2017-10-05 09:40:21 +02:00
Zach Riggle 559ffa7c9e Merge branch 'beta' into dev 2017-10-01 16:56:31 -05:00
Zach Riggle 2512026b3c Merge branch 'stable' into beta 2017-10-01 16:56:09 -05:00
Zach Riggle 518ed71488 Better error message on gdb.debug when qemu-user is missing 2017-10-01 12:27:23 -05:00
Zach Riggle 26d60cbf63 Expose icache_flush for the ARM alphanumeric encoder 2017-10-01 12:27:04 -05:00
Zach Riggle b234b319df Do not attempt to populate the libraries used by statically-linked binaries (#1043)
This causes a background instance to be spawned, which is not intended.
2017-09-29 16:34:47 -05:00
Zach Riggle 6577f24d3a Add --shared to shellcraft 2017-09-29 16:15:26 -05:00
Mathias Svensson 4a7ff431b9 Merge branch 'beta' into dev 2017-09-28 11:41:59 +02:00
Mathias Svensson 716c67d993 Release 3.10.0beta1 2017-09-28 11:37:08 +02:00
Mathias Svensson 91768424ba Release 3.9.1 2017-09-28 11:33:14 +02:00
Zach Riggle af2f8b4bf4 Fix shellcraft.arm.trap (#1041) 2017-09-27 16:21:32 -05:00
Zach Riggle 9ed8ab6d4f Reduce log spam when downloading the Android NDK 2017-09-26 12:22:16 -05:00
Zach Riggle 19f7268701 Reduce log spam when downloading the Android SDK 2017-09-26 12:21:04 -05:00
Zach Riggle e4d919d6bf Update README.md for 3.9.1 release 2017-09-26 12:16:57 -05:00
Zach Riggle 93d9a2cb5e Merge branch 'beta' into dev 2017-09-26 12:13:56 -05:00
Zach Riggle 69f8cc2c47 Merge branch 'stable' into beta 2017-09-26 12:12:20 -05:00
Zach Riggle ab0ac00c73 Disable glibc buffering in fread for processes using PTYs
See issue #1038 for extensive details
2017-09-26 11:26:45 -05:00
Zach Riggle d87ab3ac65 Try to cut down on the crazy verbosity of logging (#1036)
* Prevent Sphinx from dumping all level=INFO logging output to stdout.

See Gallopsled/pwntools#1036 for more information.

* Filter out Paramiko logs too, apply filter to all root handlers during testing

* Remove unused import

(cherry picked from commit 54c47b3daa)
2017-09-26 11:26:45 -05:00
Zach Riggle 23cd5cb819 Fix some unicode problems in readline (#1029)
Technically this introduces issues with e.g. 'unhex ffdf | python foo.py' if
foo.py uses .interactive().  However, that was already broken for other reasons.

Fixes #1004

(cherry picked from commit ebbe917713)
2017-09-26 11:26:45 -05:00
Zach Riggle 47d5cf7da1 Make some docs warnings go away and add some accessor methodds (#1035) 2017-09-22 16:23:47 -07:00
Zach Riggle a7263688db Make 'pwn template' better (#1032)
* Slightly enhance template and advertise for the feature itself in scripts

Add single-dash to the "very good" characters in shell escaping, to avoid
the need to single-quote things like --host and --port.

* Add --quiet option for pwn template, move gdbscript down a bit

* Slightly better docs for 'pwn template'

* Add checksec information directly to 'pwn template' output
2017-09-21 18:55:03 -07:00
Zach Riggle 630c4651fa Synthesize fault_addr on amd64 if it is zero. (#1031)
* Synthesize fault_addr on amd64 if it is zero.

Fixes Gallopsled/pwntool#1018

* Add a doctest for fault_addr on amd64

* Fix doctest
2017-09-21 17:53:32 -07:00
Zach Riggle 54c47b3daa Try to cut down on the crazy verbosity of logging (#1036)
* Prevent Sphinx from dumping all level=INFO logging output to stdout.

See Gallopsled/pwntools#1036 for more information.

* Filter out Paramiko logs too, apply filter to all root handlers during testing

* Remove unused import
2017-09-21 17:50:53 -07:00
Zach Riggle 11e6a2d9a7 Relocate the check to the actual LocalContext wrapper, not the context.local() context handler 2017-09-21 15:41:03 -07:00
Zach Riggle 9c29c82a69 Additional validation handling in context
- Validate default values set via ~/.pwn.conf
- Validate arch/bits and arch/endianness in LocalContext()-decorated functions
2017-09-21 15:20:01 -07:00
Kristoffer Søholm bb25140807 DynELF bug fixes (#1017)
* DynELF: trust ELF base address

* Bug fixes for DynELF:

 * Fixed lookup when not using libcdb
 * Fixed _find_linkmap returning 0 instead of None when linkmap doesn't
   exist
 * Fixed _lookup_build_id crashing if linkmap cannot be found
 * Misc cleanup

* Changes based on feedback
2017-09-21 14:10:21 -07:00
Zach Riggle ebbe917713 Fix some unicode problems in readline (#1029)
Technically this introduces issues with e.g. 'unhex ffdf | python foo.py' if
foo.py uses .interactive().  However, that was already broken for other reasons.

Fixes #1004
2017-09-16 20:11:58 -05:00
Mathias Svensson b62804eff6 Begin working on 3.11.0 2017-09-11 19:13:20 +02:00
Mathias Svensson ec98dc1246 Release 3.10.0beta0 2017-09-11 18:59:06 +02:00
Mathias Svensson 92ad1a4933 Release 3.9.0 2017-09-11 18:52:47 +02:00
Zach Riggle 7cd3c7b300 Merge branch 'beta' into dev 2017-09-08 12:41:42 -05:00
Zach Riggle 3e163e9cf2 Merge branch 'stable' into beta 2017-09-08 12:41:06 -05:00
Zach Riggle 267c6cc15a Force Ubuntu 12.04 until we can migrate to 14.04 (#1023)
* Force use of Ubuntu 12 builds on Travis CI until we can migrate to 14

* Fix Travis Dockerfile

* Add bash command logging to Travis scripts, since Travis removed its own logging

* curl should follow redirects when grabbing Ubuntu packages

* Update Travis cache directories to newer version of Python, as seen in Travis logs

* Use ::1 instead of ip6-localhost since Travis 12.04 changes broke it
2017-09-08 12:40:31 -05:00
Benno Fünfstück 5831796f6f Add configurable gdbinit (#1007)
* fix typo in comment

* new config option: context.gdbinit

This allows setting the default gdbinit for GDB, which is helpful when you want
to enable some GDB extension only when using pwntools and not by default.
2017-09-06 12:56:55 -05:00
Christophe GRENIER c438893d7e Fix for overwritten env when parsing core file (#1014)
* Fix for overwritten env when parsing core file

* warn_once message when dealing with overwritten pointer to env variable in core file
2017-09-06 12:55:37 -05:00
Mathias Svensson 3e33180655 Update CHANGELOG 2017-07-29 13:26:21 +02:00
Mathias Svensson e09543c098 Start working on 3.10 2017-07-29 13:02:55 +02:00
Mathias Svensson 1a94acab67 Release 3.9.0beta0 2017-07-29 12:23:04 +02:00
Mathias Svensson 6263a347bd Release 3.8.0 2017-07-29 10:23:27 +02:00
Mathias Svensson a344047348 Make concat_all faster while also simplifying it's logic (#1003) 2017-07-21 16:34:39 -05:00
Mathias Svensson 4aa96b48ba Merge branch 'beta' into dev 2017-07-15 00:21:49 +02:00
Mathias Svensson 6f2598aee0 Merge branch 'stable' into beta 2017-07-15 00:20:04 +02:00
Mathias Svensson 3f42ce8636 Change the author_email since the new pypi didn't accept the old one 2017-07-15 00:19:05 +02:00
Mathias Svensson 901f3eddb1 Merge branch 'beta' into dev 2017-07-14 22:57:36 +02:00
Mathias Svensson 5180230f04 Merge branch 'stable' into beta; release 3.8.0beta1 2017-07-14 09:05:40 +02:00
Mathias Svensson 1ab07de033 Release 3.7.1 2017-07-14 09:00:42 +02:00
Zach Riggle 5936d0f565 Merge branch 'beta' into dev 2017-06-27 13:53:03 -05:00
Zach Riggle e3fd03458a Merge branch 'stable' into beta 2017-06-27 13:52:27 -05:00
Zach Riggle 55016fb416 Fix config types for integer values (#998)
* Fix config types for integer values

Fixes Gallopsled/pwntools#988

* Add warning for unsupported configuration types
2017-06-26 18:52:38 -05:00
Zach Riggle 08b316098b Update ISSUE_TEMPLATE.md 2017-06-22 00:26:47 -05:00
Zach Riggle a27cb1c168 Update ISSUE_TEMPLATE.md 2017-06-21 11:37:26 -05:00
Zach Riggle d923729dfb Update ISSUE_TEMPLATE
Closes Gallopsled/pwntools#994
2017-06-21 11:35:14 -05:00
Mathias Svensson db75ecb897 Start working on 3.9.0dev 2017-06-19 23:42:29 +02:00
Mathias Svensson 0dc2949790 Release 3.8.0beta0 2017-06-19 22:31:39 +02:00
Mathias Svensson 52b8f4fa29 Release 3.7.0 2017-06-19 22:19:31 +02:00
Zach Riggle 89a848b51f Update CHANGELOG 2017-06-19 13:36:51 -05:00
Zach Riggle 672b4dd090 Update CHANGELOG 2017-06-19 13:34:42 -05:00
Zach Riggle 094e44fd65 Merge branch 'beta' into dev 2017-06-12 12:45:30 -05:00
Zach Riggle 4552624883 Merge branch 'stable' into beta 2017-06-09 17:30:50 -05:00
Kenny K b171f1e2e3 pwn template start() doesn't return io object if only local. (#975) 2017-06-09 17:29:05 -05:00
pedroysb 85523e6d8a Fixing error when setuid=True (#992)
Importing stat module to fix some errors on lines 361 to 364. The errors are caused when using the parameter setuid=True.
2017-06-09 12:41:38 -05:00
Zach Riggle 8b761fc0e3 Fix test which relies on w3challs (#993) 2017-06-09 12:23:00 -05:00
Zach Riggle b83db46c34 Fix issue with newer versions of ADB 2017-06-05 15:45:21 -05:00
Zach Riggle 40c1796fc4 Correct recvrepeat docs 2017-05-28 19:39:32 -05:00
Zach Riggle 984d54d9b2 Empty commit to test whether Docker.io rebuilds are large or small 2017-05-25 20:06:16 -05:00
Zach Riggle 3cbc527deb Update Makefile and generated Makefiles 2017-05-25 14:51:09 -05:00
Zach Riggle 1482fb7545 Add base configuration 2017-05-25 14:48:09 -05:00
Zach Riggle 7ed6f5fe6b Make pwntools:stable depend on pwntools:base 2017-05-25 14:47:36 -05:00
Zach Riggle fd5a7fea68 Fix "Full RELRO" detection in ELFs (targeting dev) (#981)
* Fix Full RELRO detection in ELFs.

This add supports for the newer DF_BIND_NOW and DF_1_NOW flags.
These are used instead of DT_BIND_NOW when linking with gold.
Also fixed the order of checks, now it reports "No RELRO" when
BIND_NOW is present but GNU_RELRO is not (in which case the bindings
are done at start but they will not be marked as read-only).

* Add x86 test binaries for relro check.
2017-05-25 14:32:35 -05:00
Steven Van Acker 8953dc3d5c bandit.labs.overthewire.org SSH is now on port 2220 (#984) 2017-05-25 14:32:05 -05:00
Zach Riggle fda1821fd9 LibcDB Docs, Doctests, Negative Caching, Sane Cache (#986)
* Make libcdb optional

* Add negative caching for libc databases

* Add docs and doctests, add md5/sha1/sha256

* Add libcdb to main docs

* Slightly more useful doctests

* Expose functions in __all__

* Slightly better logging messages

* Fix __all__
2017-05-23 04:42:09 -05:00
Zach Riggle f7568b47b3 Capitalize first words of sentences 2017-05-21 13:40:30 -05:00
Zach Riggle 2ccd36ca7f Fix Ubuntu versions 2017-05-21 13:38:13 -05:00
Zach Riggle 9062360041 Fix document heading 2017-05-15 18:37:00 -05:00
Zach Riggle 3f9c192a5e Add a bit more args docs 2017-05-15 13:02:59 -05:00
Mathias Svensson b8e902b611 Merge branch 'beta' into dev 2017-05-12 10:21:37 +02:00
Mathias Svensson d586d6f660 Merge branch 'stable' into beta 2017-05-12 10:06:53 +02:00
Mathias Svensson 6709a4f747 Release 3.6.1 2017-05-12 10:01:41 +02:00
Mathias Svensson 1a4a1e11ba Follow-up to #980 making it actually work 2017-05-12 09:57:34 +02:00
Zach Riggle f82c0aa3a2 Add mako files to MANIFEST (#980) 2017-05-10 19:59:41 -05:00
Zach Riggle 646ca1eb26 Attempt at fixing #974; I don't have a keyboard with a keypad right now, so can't test. (#979) 2017-05-10 17:00:33 -05:00
Mathias Svensson 8055ec98ce Prepare work on 3.8.0 2017-05-08 20:56:08 +02:00
Mathias Svensson aa1f3f7f5a Merge branch 'beta' into dev 2017-05-08 20:22:39 +02:00
Mathias Svensson 043627a56d Release 3.6.0 2017-05-08 20:00:47 +02:00
Mathias Svensson a40a0ecab4 Merge branch 'stable' into beta 2017-05-08 19:59:31 +02:00
Zach Riggle bbe20c9748 Update CHANGELOG 2017-05-04 13:40:55 -05:00
Zach Riggle c700f9194c Update CHANGELOG 2017-05-04 13:40:08 -05:00
Zach Riggle 71a3e43be3 Update CHANGELOG 2017-05-04 13:38:44 -05:00
Zach Riggle 267b9990c2 Update CHANGELOG 2017-05-04 13:38:32 -05:00
Zach Riggle cfee8e0b24 Update CHANGELOG 2017-05-04 13:37:45 -05:00
Zach Riggle 32a767d469 Update CHANGELOG 2017-05-04 13:37:06 -05:00
Zach Riggle eaea783e2a Verify corefiles are the same via hash before using cached copy (#970) 2017-05-04 13:04:48 -05:00
Zach Riggle 9bda42e45d Merge remote-tracking branch 'upstream/beta' into dev 2017-05-01 23:50:16 -05:00
Zach Riggle f4b3469fb4 Fix incorrect ordering in template for non-ssh remotes (#968) 2017-05-01 23:49:57 -05:00
Zach Riggle 0903f9055b Fix typo: PRSP vs PRPS 2017-05-01 15:13:45 -05:00
Zach Riggle 0a23a457c5 Add ARCH_HAS_ELF_RANDOMIZE 2017-05-01 15:13:45 -05:00
David Tomaschik 7fe6dd0e8e Respect TERM_PROGRAM for run_in_new_terminal. Fixes #964. (#967)
* Respect TERM_PROGRAM for run_in_terminal.  Fixes #964.

* Set args for TERM_PROGRAM.
2017-05-01 01:22:49 -05:00
Zach Riggle 4772a22fed Only use PPA for older Ubuntu releases (#961)
Fixes Gallopsled/pwntools#953
2017-04-28 12:25:38 -05:00
Roman 42692c685e Add ability to set env vars in template (#960)
* added ability to set env vars in template

* changed env param to general *a, **kw
2017-04-21 15:11:09 -05:00
micbou aa3acc162f Fix dd documentation (#959) 2017-04-21 15:10:51 -05:00
Mathias Svensson 676e6869a0 Merge branch 'beta' into dev 2017-04-20 01:25:48 +02:00
Mathias Svensson 9b50163760 Allow setting the terminal through a tuple instead of a list (#957) 2017-04-20 01:25:25 +02:00
Zach Riggle 289109f499 Merge remote-tracking branch 'upstream/beta' into dev 2017-04-18 13:44:45 -05:00
Roman e90fb15596 Fixed processing of lists in config file (#954)
* fixed handling of lists in config file

* changed list to tuple
2017-04-18 13:44:40 -05:00
Zach Riggle 3b9c0db1a2 Better error messages for run_in_new_terminal 2017-04-18 13:44:29 -05:00
Roman dd7a67b6d7 Fixed errors in template generator (#952)
* fixed port type

* missed exploit.py template

* fixed condition availability parameters
2017-04-17 12:35:47 -05:00
Mathias Svensson ad87c17f73 Merge branch 'beta' into dev 2017-04-15 11:24:55 +02:00
Mathias Svensson 2714a30488 Release 3.6.0beta1 2017-04-15 10:52:38 +02:00
Mathias Svensson ac386877d1 Release 3.5.1 2017-04-15 10:43:55 +02:00
Zach Riggle 4f08b6d79c Allow setting context.device=None, and use context.arch to determine default ABI for adb.compile (#950) 2017-04-13 13:54:17 -05:00
Zach Riggle 348f6dfbe7 Update CHANGELOG for 3.5.1 and 3.6.1beta release 2017-04-13 13:40:43 -05:00
Zach Riggle 80219df5cc Require a path for 'pwn template' (#947)
Closes Gallopsled/pwntools#943
2017-04-13 10:37:21 -05:00
Zach Riggle 065c79d29c Speed up ssh via caching checksec results (#945)
* Speed up ssh via caching checksec results

Closes Gallopsled/pwntools#944

* Fix logging message

(cherry picked from commit 8a7bb9b9f4)
2017-04-12 21:47:41 -05:00
Zach Riggle 310f186e5f Do not attempt to populate GOT and PLT symbols for Corefiles (#948)
Closes Gallopsled/pwntools#946
2017-04-12 21:47:05 -05:00
Hlynur Óskar Guðmundsson bac44542ed Made an error message when a default terminal is not found more verbose and helpful (#941) 2017-04-11 12:10:30 -05:00
Zach Riggle a54e697b55 Add CONFIG_COP_ACCESS from CVE-2017-0583 2017-04-04 17:06:18 -05:00
Gábor Szarka 5f1294af09 Make DynELF more robust to different base addresses (#933)
The check for when certain ELF fields contain offsets instead of pointers can be
made more precise by checking for the type field in the ELF header instead of
comparing the value to some hard-coded range.
2017-04-02 17:07:08 -05:00
Grazfather 7cc4ced8d6 gdb: Use quiet (-q) option (#940) 2017-04-02 17:06:17 -05:00
Mathias Svensson 5c72d62c90 Update the CRC list 2017-03-30 13:56:44 -05:00
Zach Riggle 925cb43024 Run autopep8 on known crcsums before merging Idolf's change, so that the difference is visible 2017-03-30 13:55:08 -05:00
Zach Riggle 6f42e1c337 Fix more logging messages 2017-03-28 11:16:08 -05:00
Zach Riggle 8a7bb9b9f4 Fix logging message 2017-03-28 11:14:50 -05:00
Mathias Svensson 512c2544b5 Start working on 3.7.0 2017-03-26 22:43:05 +02:00
Mathias Svensson 8120b5c037 Merge branch 'stable' into beta 2017-03-26 22:18:01 +02:00
Mathias Svensson 55456814fc Release 3.5.0 2017-03-26 21:13:03 +02:00
Zach Riggle eb3e3797cd Update CHANGELOG for 3.6.0beta release 2017-03-23 13:15:03 -05:00
Zach Riggle 3416b7c949 Fix conditional for logging 2017-03-19 17:11:33 -05:00
Zach Riggle dc9882abe7 Use _run for objdump output 2017-03-06 14:27:13 -06:00
Zach Riggle 664622fa07 Use all symbols in inverted PLT search 2017-03-06 14:05:53 -06:00
Zach Riggle 930f2a4a32 Do not dump PLT emulation data to DEBUG logs unless explicitly set via PLT_DEBUG 2017-03-04 18:31:24 -06:00
Zach Riggle 10ef77b997 Add missing link to Changelog 2017-03-04 16:10:50 -06:00
Zach Riggle ecba8e4b38 Update changelog for 3.5.0 2017-03-04 16:09:08 -06:00
Mathias Svensson 0d3b97b378 Merge branch 'beta' into dev 2017-03-03 23:20:08 +01:00
Zach Riggle 33945f6885 Clean up socket-class and socket-type code in sock/remote/listen (#920)
* Clean up socket-class and socket-type code in sock/remote/listen

* Slight change to docs

* Add doctests for listen and attribute documentation

* Fix bug in listen.close()

* Fix regression on ipv6 sockets

* Simplify documentation

* Fix doctest
2017-03-03 14:04:58 -06:00
Zach Riggle b7ddfa995e Fix ARM PLT parsing, and big-endian ARM emulation (#910)
* Do not use UC_MODE_BIG_ENDIAN, its support is poor

* Ghetto-swap endianness for emulation of PLT instructions

* Reduce instruction alignment so that all ARM PLT entries are found

* Add tests for ELF PLT loading

* Fix canary detection on PowerPC

* Fix x32 emulation

* Fix two failing doctests

* Add AArch64 to supported big-endian architectures

* Add MIPS GOT parsing code, fix unpack macros to use ELF settings

* Why, MIPS, are you so complicated?

* Catch weird edge cases

* I don't know what's real anymore

* Fix synthetic symbol generation and add tests

* Remove canary test

* Guard against errors in MIPS GOT

* Fix doctests
2017-03-02 19:03:45 -06:00
Mathias Svensson 3b2be2b2a7 Merge branch 'stable' into beta 2017-03-02 11:47:55 +01:00
Zach Riggle 0a3ac521ad Work around appdirs error for Travis CI builds (#924)
Closes Gallopsled/pwntools#921
2017-03-01 17:58:22 -06:00
Zach Riggle 1f72e45eaf Attempt appdirs workaround 2017-02-25 01:44:55 -05:00
Zach Riggle 421a3093fc Remove spinners that will probably get us yelled at 2017-02-25 01:25:08 -05:00
Zach Riggle d08fc6d3a0 Simplify Travis Dockerfile 2017-02-24 15:50:33 -05:00
Zach Riggle dd6931907a Update user-agents 2017-02-24 14:15:29 -05:00
Zach Riggle de3a68d8b4 Update 'pwn template' template to support argv and auto-downloading the target file (#919) 2017-02-22 12:09:55 -05:00
Zach Riggle 93b828ff97 Add missing basic templates for AArch64 (#918)
* Add missing basic templates for AArch64

* Simplify aarch64 templates

* Fix broken doctests
2017-02-21 19:48:58 -05:00
Zach Riggle 326dd83321 Handle errors during ssh.checksec() (#917)
* Handle errors during ssh.checksec()

Closes Gallopsled/pwntools#916

* Add additional error handling for ulimit checks
2017-02-21 14:57:58 -05:00
Mathias Svensson f8bb49c78f Merge branch 'beta' into dev 2017-02-17 14:56:39 +01:00
Mathias Svensson 510e247034 Merge branch 'stable' into beta 2017-02-17 14:48:14 +01:00
Mathias Svensson 4d529cd543 Release 3.4.1 2017-02-17 14:29:51 +01:00
Kristoffer Søholm e021f57806 Fixed bug in generatePadding (issue #891) 2017-02-17 14:15:31 +01:00
Zach Riggle b6cfec6284 Do not fail with gdb.debug() over ssh when given an absolute path (#894)
* Do not fail with gdb.debug() over ssh when given an absolute path

Fixes Gallopsled/pwntools#885

* Prevent failing on stable since this directory doesn't exist
2017-02-17 00:02:53 -05:00
Zach Riggle 4834032b14 Doctest all members, even if they are not exported via __all__ (#914)
* Doctest all members

* Fix doctest failures in asm and remove canary in context

* Fix failing doctest

* Use automodule for pwnlib.context

* Fix failing tests in context module

* Use automodule for pwnlib.memleak
2017-02-16 23:40:50 -05:00
Zach Riggle 1273552189 Do not skip "hidden" doctests (#912)
* Check to see if hidden members are doctested

* Do not skip undocumented members

* Fix broken tests, promote missing tests
2017-02-16 21:30:35 -05:00
Zach Riggle ef1e3cfb97 Fix regression in f4b0e3a5 2017-02-16 19:43:26 -05:00
Zach Riggle e9fc0125a6 Add "pwn template" command for generating templates (#909) 2017-02-16 19:38:34 -05:00
Zach Riggle 81239be429 Fix checksec nx, execstack, relro reporting (#904)
* Fix checksec nx, execstack, relro reporting

Also add a disable_nx function

* Add disablenx command-line utility

Also fix bug where invoking command-line utilities directly by module name
(python -m pwnlib.commandline.foo) would fail
2017-02-16 17:20:28 -05:00
Zach Riggle f4b0e3a5b9 Do not allow interactive assembly, it doesn't work anyway 2017-02-16 16:48:59 -05:00
Kristoffer Søholm 1f1a6667a1 Added test for issue #891 (#903) 2017-02-15 17:00:54 -05:00
Zach Riggle 464e9e54e1 Add 'pwn debug' command-line utility (#905)
Also fixes a bug in process() which would throw the wrong exception
when qemu-user cannot be located for a non-native binary.
2017-02-15 17:00:24 -05:00
Zach Riggle a786a58db7 Emulate PLT for better symbols (#899)
* Emulate all relocation sections for PLT symbols

This adds a dependency on Unicorn

* Don't look up empty symbols
2017-02-15 16:57:24 -05:00
Zach Riggle bc471d13f9 Fix MIPS ELF bit-ness by checking masks in increasing order (#901)
Closes Gallopsled/pwntools#900
2017-02-14 11:36:28 -05:00
Zach Riggle 6af464fc0e Make SROP doctests slightly more verbose 2017-02-13 18:12:52 -05:00
Zach Riggle 29e38a7d49 Add missing --init to docker invocation 2017-02-13 18:02:11 -05:00
Zach Riggle 658589704a Add pwnlib.config module and documentation (#893)
This adds functionality for user configuration files at ~/.pwn.conf
and /etc/pwn.conf.  Previously this was only used by the pwnlib.log
module, and was entirely undocumented.

This is now documented, and offers an easy mechanism for other parts
of the code to have extension points.
2017-02-13 17:55:01 -05:00
Zach Riggle 71855ebd2f Fix Aarch64 syscalls (#897)
* Remove unavailable syscalls from AArch64

The Linux kernel has apparently stopped supporting these

* Rewrite shellcraft.aarch64.linux.cat, add open which uses openat

Fixes Gallopsled/pwntools#896

* Fix doctests to use openat
2017-02-13 17:50:45 -05:00
Zach Riggle 393751351b Add dockerfile for testing-in-a-box on Xenial (#895) 2017-02-13 17:34:26 -05:00
Mathias Svensson c8a690d617 Removed all uses of sh_command_with and sh_prepare (#892) 2017-02-13 14:59:27 -05:00
Kristoffer Søholm 8b8a50b580 Fixed bug in generatePadding (issue #891) 2017-02-13 11:39:42 +01:00
Mathias Svensson 3b07dfe7cc Begin work on 3.6.0 2017-02-13 01:52:59 +01:00
Mathias Svensson 5877f8e97e Merge branch 'stable' into beta-staging 2017-02-13 01:34:31 +01:00
Mathias Svensson 4ebcbee34b Release 3.4.0 2017-02-13 01:31:16 +01:00
Mathias Svensson d25d62c126 Merge branch 'stable' into stable-staging 2017-02-13 01:31:00 +01:00
Zach Riggle 5392611ed5 Use updated testing scripts from 3.5.0 on 3.4.0 2017-02-13 01:17:57 +01:00
Zach Riggle 7c139c7179 Shellcode syscall templates (#871)
* Add templates from generator

* Add abi.stack to all ABIs

* Enable shellcraft.arch.os.foobar.template

* Add pwnlib.registers.current()

* Add syscalls symlinks

* Add syscall generator

* Enable shellcraft.foo() shortcut for shellcraft.arch.os.syscalls.foo()

* Make templates more verbose

* Remove old templates

* Add makefile

* Delete old templates, make shellcraft --list work

This also speeds up boot time by like 0.05 seconds

* Remove unnecessary execve wrappers

* Check for common arch as well

* Don't explode on string arguments that are register names

* Catch bad argument names

* Remove accidental import

* Add aarch64 ABIs since we enabled aarch64 tests

* Fix mmap vs mmap2 syscall

* Make shellcraft command-line work for syscalls

* Remove unnecessary wrapper templates

* Set all default values to zero

* Add example of automatic determination of types

* Add missing register architectures

* Add PowerPC ABIs

* More syscall examples

* Handle mmap vs mmap2

* Add missing import, use full path

* Just use the string name

* Fix rt_sigreturn on amd64

* __NR_ --> SYS_ because of old expectations

* rstrip to remove blankline

* Fix Thumb doctests which uses unpredictable jump labels

* Import additional syscalls by updating the function source.

Support variable-argument syscalls.

Support spilling to the stack.

* Simplified constants.eval logic means no extra parens

* Simplify vararg representation; fix oepn() argument name explicitly

* Fix syscall examples

* Fix reordering of arguments, since we have to support stack spill

* Fix argument name in doctest

* Make Codacy happy

* Restore connect template accidentally removed in 9fceb12b

* Scrape all architectures for syscall names

* Enable void* and void** to be pushed

* Make Codacy happy

* Add __doc__ to sdist

* Follow shellcraft template symlinks

* Detect syscall shellcodes in shellcraft based on path

(cherry picked from commit 94462845fa)
2017-02-12 18:37:20 -05:00
Zach Riggle da9ce55dfd Fix changelog formatting 2017-02-12 18:26:11 -05:00
Zach Riggle 9d394e0df1 Add missing info to 3.4.0 changelog 2017-02-12 18:26:02 -05:00
Zach Riggle f962d2bd21 Add missing info to 3.4.0 changelog 2017-02-12 18:24:50 -05:00
Zach Riggle 667d290d9b Fix regression from 189b1fb3c 2017-02-11 15:16:14 -05:00
Zach Riggle 766c4d8a7f sh_string should return '' for empty strings (#887) 2017-02-11 15:02:46 -05:00
Zach Riggle 189b1fb3c2 Add missing registers to AArch64 sigreturn frame, and update test 2017-02-10 22:54:24 -05:00
Zach Riggle 6c1b882b40 Upgrade warnings to errors in demo 2017-02-10 22:38:04 -05:00
Zach Riggle 0c76348072 Fix AArch64 SROP register name 2017-02-10 22:37:23 -05:00
Zach Riggle 2f7d78bc64 Add sigreturn/corefile examples and sanity tests 2017-02-10 22:34:27 -05:00
Zach Riggle 646723fa8e Remove unneded arg from aarch64 sigreturn 2017-02-10 22:19:11 -05:00
Zach Riggle e77915fba6 Handle PC/SP being invalid in Corefiles 2017-02-10 22:16:13 -05:00
Zach Riggle a02e8da1ea Add AArch64 support to corefiles 2017-02-10 22:16:13 -05:00
Zach Riggle 6979cb0d2b Search for QEMU coredumps first 2017-02-10 21:57:18 -05:00
Zach Riggle bc8942006b Convert alignment error to a warning; add AArch64 2017-02-10 21:54:26 -05:00
Zach Riggle 07c7b51f25 Add ip and fp aliases to user_regs_struct on arm 2017-02-10 21:51:53 -05:00
Zach Riggle ee655cac60 Add Android and AArch64 support to SigreturnFrame 2017-02-10 21:19:48 -05:00
Zach Riggle b668815323 Fix elf.functions not containing back-references 2017-02-10 21:07:56 -05:00
Zach Riggle a26a1a1f35 Permit setting SROP arguments directly 2017-02-10 21:03:26 -05:00
Zach Riggle ab42519e26 Enable disassembling entire functions 2017-02-10 19:28:59 -05:00
Zach Riggle 59b44b4fe6 Fix typo from 0c8006ca 2017-02-10 19:28:26 -05:00
Zach Riggle f4f21f147b Squelch error messages when restarting the server 2017-02-10 12:54:01 -05:00
Zach Riggle c06822571f Do not overrite tube.flat with ADB protocol Client 2017-02-10 12:40:22 -05:00
Zach Riggle 383a4f4596 adb.push() should return the target path 2017-02-09 15:25:13 -05:00
Zach Riggle 25d63da30e Do not print connection messages when using AdbClient 2017-02-09 15:20:01 -05:00
Zach Riggle dd2ad30a51 Catch exceptions when SSHing into machines with unsupported architectures (#884)
Fixes fefd48f34
2017-02-05 17:00:09 -05:00
Zach Riggle d160f9b7c9 Make corefiles great again (#839)
Adds a large amount of functionality around Corefiles, to support smarter exploitation

Adds a ".corefile" property to both local and remote (ssh) processes.  See the
documentation for the corefile module for extensive examples and tests.

Additionally, context.delete_corefiles and context.rename_corefiles have been added,
to control the behavior of the ".corefile" property.
2017-02-05 10:49:50 -05:00
Zach Riggle 0bdbc2b8c3 Make pwnlib.rop consistent with context.bytes (#882)
Fixes Gallopsled/pwntools#879
2017-02-05 09:36:45 -05:00
Zach Riggle d0c4d8488e Disable exit-on-error at the end of bash scripts (#881) 2017-02-05 07:43:38 -05:00
Zach Riggle f3968afbbb Add aarch64 documentation, which enables doctests (#875)
* Add aarch64 documentation, which enables doctests

* Fix failing doctest

* Attempt to figure out whats going on with Travis

* Use the Xenial version of qemu-static since the Zesty version is broken for AArch64
2017-02-02 00:32:25 -05:00
Zach Riggle 2d04acb867 Enhance adb.which to support all=True 2017-01-31 15:05:26 -05:00
Zach Riggle 62842e20f0 Make command-line tools work better 2017-01-29 18:50:46 -05:00
Zach Riggle c929217947 Restore dupsh from d21af22f82
Closes Gallopsled/pwntools#873
2017-01-27 08:17:16 -05:00
Zach Riggle ff08a859f8 Docker: Install unprivileged user pwntools, use correct tags 2017-01-26 16:03:26 -05:00
Zach Riggle ba24b440c5 Convert symlink to actual file, since Docker Hub doesnt like symlinks 2017-01-26 14:40:34 -05:00
Zach Riggle b31adf27d0 Update dockerfiles and add various distros / release versions 2017-01-26 14:04:37 -05:00
Zach Riggle 20d27c651a Silence commits in the build logs 2017-01-25 18:14:06 -05:00
Zach Riggle ba7911651e Install a recent version of GDB onto Travis (#872)
These files should be cached automagically.
2017-01-25 17:21:59 -05:00
Zach Riggle cded6cda47 Make upgrades / add fields to process() (#869)
- Show the PID when a process is created
- Make process.cwd into a property, which fetches the real CWD from procs
- Record the UID/GID and SUID/SGID of the executed file
- Add a few doctests
- Make _stop_noticed a timestamp
2017-01-24 19:30:26 -05:00
Zach Riggle 25941b52bb Multiple SSH enhancements (#868)
- Break out ssh_channel into subclass ssh_process
- Make ssh.process() directly instantiate ssh_process
- Add ssh_process().ELF
- Add ssh_process().corefile
- Record the UID and GID of the executed binary
- Add the created PID to the ssh_process message
2017-01-24 19:02:57 -05:00
Zach Riggle b79a750af6 Force-install libcapstone3 since it is causing errors 2017-01-24 18:02:43 -05:00
Zach Riggle eede2e2e1d Always upgrade Pip first 2017-01-24 17:43:19 -05:00
Zach Riggle 2a59f5cf4c Fix chunked reading of ELF files (#865)
* Fix chunked reading of ELF files

This introduces a new dependency on 'intervaltree', which is used
to automatically select segments which are relevant for a given
virtual-address range.

This also introduces a new ELF.memory attribute, which is the tree
of memory ranges, which point at the segment objects that describe
the memory range.

These are recalculated when ELF.address is adjusted, and we have
tests for that.

This also optimizes some of the other routines to avoid the wrapped
file-seeking, and to just use the mmap.

* Rewrite install scripts to use more modern versions of binutils

* Load segments in file-order, chop any overlaps
2017-01-24 13:41:29 -05:00
Mathias Svensson a3e82e27bb Fix a few edge cases in weird ELF files (#867)
* Fix a few edge cases in weird ELF files

* Add a check for PT_LOAD
2017-01-24 19:14:29 +01:00
Zach Riggle 368a708663 Upgrade documentation requirements on Travis 2017-01-24 12:00:34 -05:00
Zach Riggle 4a7de306f0 Convert impossible doctest into a code-block 2017-01-23 15:47:43 -05:00
Zach Riggle 69bbd0839a Clean up pwnlib.asm documentation and doctests 2017-01-23 15:39:36 -05:00
Zach Riggle 475ffa632e Always run Android tests on staging branches and new tags (#866) 2017-01-23 14:43:32 -05:00
Zach Riggle 06db497901 Add a bit more documentation to context.rst 2017-01-23 12:16:30 -05:00
Zach Riggle 5106c4eb75 Fix test in dpkg_search_for_binutils 2017-01-23 12:11:02 -05:00
Zach Riggle 08b7b190a7 A few documentation touch-ups 2017-01-23 12:08:36 -05:00
Zach Riggle 8259d07207 Remove useless doctest lines 2017-01-23 12:01:27 -05:00
Zach Riggle ad2eb77cfa Explicitly run a few asm tests 2017-01-23 12:00:08 -05:00
Zach Riggle ec04c860c0 Remove unnecessary doctests:: blocks 2017-01-23 11:59:48 -05:00
Zach Riggle ffe4cf6807 Add doctest for print_binutils_instructions 2017-01-23 11:19:36 -05:00
Zach Riggle 673073f08d Add a test for pwnlib.asm.dpkg_search_for_binutils 2017-01-23 11:15:57 -05:00
Zach Riggle 0e45f23af8 Add pwnlib.protocols module (#860)
* Add pwnlib.protocols module

Migrate pwnlib.adb.protocol into that directory, and add compatibility shims

* Add documentation links, and run doctests

* Make doctests run

* pwnlib.protocols.adb.Client.transport should work with no device
2017-01-20 18:59:23 -05:00
Zach Riggle 31cd98affe Do not truncate the ELF file when saving to the same path 2017-01-20 15:27:46 -05:00
Zach Riggle 3e4a1bcc72 Fix errant version number printing 2017-01-20 15:22:59 -05:00
Zach Riggle 85c3074574 Allow calling ELF.save() with no arguments 2017-01-20 15:22:59 -05:00
Zach Riggle 178e64a4f7 Add symlink option for ssh.set_working_directory to simplify exploits (#862)
* Add symlink option for ssh.set_working_directory to simplify exploit code

* Add additional options and tests to symlink=xxx
2017-01-20 14:58:08 -05:00
Zach Riggle 179476604e Fix error message format string
Closes Gallopsled/pwntools#863
2017-01-20 14:38:37 -05:00
Zach Riggle fc6e00d9f0 Update changelog for 3.5.0 2017-01-19 15:18:17 -05:00
Zach Riggle 8b1f1dce84 Update changelog for 3.5.0 2017-01-19 15:11:44 -05:00
Zach Riggle 8345bc3824 Add parse_kconfig and kernel information to pwnlib.elf.ELF (#861) 2017-01-19 11:01:31 -05:00
Zach Riggle 300f8e0c1a Speed up processing of symbols slightly, by not checking for each entry 2017-01-17 16:38:01 -05:00
Zach Riggle 9ace73a977 Replace broken function-decorator context.quiet with working context.quietfunc
Fixes: ae6a0745f
2017-01-17 15:10:25 -05:00
Zach Riggle fb16e158ec Use tubes.buffer for net.wget, add more tests 2017-01-17 13:58:49 -05:00
Jakub Wilk e519874947 Fix typos (#859) 2017-01-16 11:42:38 -05:00
Zach Riggle 2e90d05156 Actually implement ssh.sftp setter, so it can be set to None 2017-01-14 15:05:15 -05:00
Zach Riggle b6e3d5d8c5 Fix register usage in execve shellcode (#857)
The previous code worked, but we emitted a register swap that hid the fact we were using the wrong registers

Fixes Gallopsled/pwntools#856
2017-01-13 14:00:28 -05:00
Zach Riggle 0726d8d339 Fix hexdump alignment for weird widths
Closes Gallopsled/pwntools#849
2017-01-12 17:57:54 -05:00
Mathias Svensson bd5a368754 Merge branch 'beta' into dev 2017-01-12 23:48:54 +01:00
Mathias Svensson 602efd2790 Release 3.4.0beta4 2017-01-12 23:42:25 +01:00
Mathias Svensson 2f7f0de984 Release 3.3.4 2017-01-12 23:40:13 +01:00
Zach Riggle 45d2c11535 Update changelog for 3.3.4 2017-01-12 17:30:30 -05:00
Zach Riggle 16b507e197 Change hexdump_iter to not rely on the length of its input file (#850)
We cannot determine the length of the file if passed e.g. a tube or a pipe or PTY or character device (e.g. stdin or /dev/null).

Supercedes: 9c2f0f4e
(cherry picked from commit 14f717b7b4)
2017-01-12 17:20:15 -05:00
Zach Riggle 53f041a4d2 Fix shellcraft.amd64.popad registers (#853)
Fixes Gallopsled/pwntools#848
2017-01-12 16:47:44 -05:00
Zach Riggle b2a5b76cf7 Do not perform temporary register selection if we don't need to (#852)
Fixes Gallopsled/pwntools#847
2017-01-12 16:36:49 -05:00
Zach Riggle 9cb438842c Use class- and init-level documentation for Sphinx autodocs 2017-01-12 16:09:23 -05:00
Zach Riggle 14f717b7b4 Change hexdump_iter to not rely on the length of its input file
We cannot determine the length of the file if passed e.g. a tube or a pipe or
or PTY or character device (e.g. stdin or /dev/null).
2017-01-12 15:01:42 -05:00
Zach Riggle f792407c19 Remove hanging comment 2017-01-11 19:22:48 -05:00
Zach Riggle 9c2f0f4e89 Fix hexdump_iter for actual file objects, like those used by phd (#846) 2017-01-11 15:06:11 -05:00
Zach Riggle eb0bb6ea8d Add doctest for hexdump_iter 2017-01-11 00:51:28 -05:00
Zach Riggle f46112e873 Fix hexdump_iter for actual file objects, like those used by phd 2017-01-11 00:45:39 -05:00
Zach Riggle 975844d83d Add SigreturnFrame.__flat__ 2017-01-10 21:29:36 -05:00
Zach Riggle 466c0e4179 Add elf.process, elf.fit, process.fit
Also fix the implementation of elf.flag
2017-01-10 21:27:50 -05:00
Zach Riggle 17e4f01976 Enhance output of amd64.mov shellcraft for very large values 2017-01-10 18:18:34 -05:00
Mathias Svensson fecd6f8222 Merge branch 'beta' into dev 2017-01-11 00:03:09 +01:00
Mathias Svensson 7ba3a1b32f Release 3.4.0beta3 2017-01-10 23:53:59 +01:00
Mathias Svensson d1edd275d9 Release 3.3.3 2017-01-10 23:52:50 +01:00
Zach Riggle 8f012947e9 Add build-essential and pip upgrade to installation steps (#845)
Fixes Gallopsled/pwntools#844
2017-01-10 17:35:50 -05:00
Zach Riggle 36b05bac2b Add doctests for the hexdump utility (#842)
Related: Gallopsled/pwntools#837
Related: Gallopsled/pwntools#840
2017-01-10 17:21:54 -05:00
Zach Riggle cb4991c41d Fix regression in amd64.mov with 32-bit values >= 0x80000000 (#843)
Fixes Gallopsled/pwntools#841
Caused by: Gallopsled/pwntools#504 (9ca377c)
2017-01-10 15:56:50 -05:00
Mathias Svensson 65f18b6091 Merge branch 'beta' into dev 2017-01-10 18:43:46 +01:00
Mathias Svensson 48616c633d Release 3.4.0beta2 2017-01-10 18:30:16 +01:00
Mathias Svensson c928a0425e Merge branch 'beta' into dev 2017-01-10 17:00:15 +01:00
Mathias Svensson f5e16d3db6 Release 3.4.0beta1 2017-01-10 16:59:22 +01:00
Zach Riggle fefd48f341 Add ssh.checksec functionality (#835)
Looks like this:

[x] Connecting to example.pwnme on port 22
[+] Connecting to example.pwnme on port 22: Done
[*] [email protected]:
    Distro    Ubuntu 14.04
    OS:       linux
    Arch:     amd64
    Version:  3.11.0
    ASLR:     Enabled
    Note:     Susceptible to ASLR ulimit trick (CVE-2016-3672)

Fixes Gallopsled/pwntools#753
2017-01-09 13:55:38 -05:00
Zach Riggle 132f48e6ee Fix failing doctest. Not sure what changed, but it was clearly not guaranteed to be right, given global state. 2017-01-07 19:16:04 -05:00
Zach Riggle e205e17b6d Fix doctests in ELF module 2017-01-07 18:32:37 -05:00
Zach Riggle d0267f3ee7 packing.fit() should handle extremely large offsets as if they are cyclic patterns 2017-01-07 18:21:14 -05:00
Zach Riggle 0c8006ca4e Enable passing an elf.Function to flat() 2017-01-07 18:14:57 -05:00
Zach Riggle bd88c92991 Greatly enhance and update the pwnlib.elf module documentation. 2017-01-07 18:10:59 -05:00
Zach Riggle 12f1bb9126 Add signal names to negative exit codes for process.poll() 2017-01-07 16:37:57 -05:00
Zach Riggle 3fa2c659fd Merge branch 'beta' into dev 2017-01-05 12:41:28 -05:00
Zach Riggle a2c67e5075 Merge branch 'stable' into beta 2017-01-05 12:39:25 -05:00
Zach Riggle 179a0656f5 Add better example of NOPTRACE 2017-01-04 23:16:22 -05:00
Zach Riggle 58b2e36a1b Fix empty code-block 2017-01-04 23:13:50 -05:00
Zach Riggle 24ae51dae4 Greatly enhance documentation for the GDB module, and expose its members in toplevel 2017-01-04 23:06:34 -05:00
Zach Riggle 14e68ec226 Remove _raw variants from public documentation 2017-01-04 14:57:22 -05:00
Zach Riggle 485dcede2c Fix heading style for ADB docs 2017-01-04 14:45:54 -05:00
Zach Riggle 50acdbbe41 Add hyperlinks to tube class 2017-01-04 14:44:30 -05:00
Zach Riggle 4e0e9d2acb Add hyperlinks to process class 2017-01-04 14:43:51 -05:00
Zach Riggle bc7c8cd423 Add missing :const: to docstrings 2017-01-04 14:37:43 -05:00
Zach Riggle a8446bef47 Fix sh_string RST formatting 2017-01-04 14:36:21 -05:00
Zach Riggle afdcdec577 Fix sh_string docs 2017-01-04 14:23:06 -05:00
Zach Riggle c13ff2cb08 Clarify documentation and remove leading process.XXX in docs 2017-01-04 14:18:02 -05:00
Zach Riggle a12d0b6a4c Move PTY, PIPE, STDOUT to toplevel 2017-01-04 14:15:38 -05:00
Zach Riggle 3dd6045488 Fix regression caused by 0cead77 2017-01-04 14:14:23 -05:00
Zach Riggle cca9782424 Add PR_SET_PTRACER to process and ssh.process (#828)
* Add PR_SET_PTRACER to initialization, and add doctests for process.leak/corefile

* Add PR_SET_PTRACER to SSH processes

* Do not warn about YAMA if we dont need to

* Fix doctest to use raw strings

* Fix typo in doctest

* Apparently GDB is not installed on Travis by default

* Add warning message to process("foo") vs process("./foo")

* Add gdb.corefile; make run_in_new_terminal return a PID

* Intentionally break doctest because I dont believe that it worked

* Fix codacy issues

* Fix gdb.attach return value

* Add missing import

* Fix typo, use waitpid

* Refactor some code into gdb.version / gdb.binary

* Permit GDB with multipart versions

* Fix repr() on Corefile

* Silence run-in-new-terminal message for gdb.corefile

* Fix version number

* Remove Yama warning message entirely, it should no longer be necessary

* Version detection is hard.  Regular expressions to the rescue!

* Remove process.kill/stop/resume, those will be a different PR

* Fix doctests

* The GDB used by Travis must be so old!

* Apparently Travis is entirely borked.  Use a less robust test.
2017-01-04 12:59:22 -05:00
Zach Riggle 5ce5339ab5 Silence warning during doctests 2017-01-04 12:58:04 -05:00
Zach Riggle 0cead77039 Move STDOUT/PIPE to process class, so they can be referenced directly 2017-01-04 12:52:19 -05:00
Zach Riggle 1d59a90fa8 Change all imports to absolute per PEP-328, and sort imports (#832) 2017-01-03 18:04:45 -05:00
Zach Riggle ac017d97dc Enable leaking memory relatively with MemLeak (#822)
* Enable leaking memory relatively with MemLeak

Fixes Gallopsled/pwntools#758

* Add RelativeMemLeak alias for MemLeak(..., relative=True)

* Make codacy happy
2016-12-29 13:21:02 -05:00
WGH b584ca349a fixed RuntimeError in setup.py caused by pandoc on non-amd64 arches (#820)
If pandoc is not installed locally, pwntools' setup.py
tells pypandoc to download one.

Unfortunately, it fails on non-amd64 arches because
pypandocs provides precompiled binaries only for amd64.

Since pypandoc is not hard dependency for pwntools,
this error can be skipped without major harm.

In fact, pwntools' setup.py already handles ImportError
gracefully. The problem is, arch mismatch causes
a completely different exception.
2016-12-28 19:12:47 -05:00
Mathias Svensson 8b30700f92 Bump to 3.5.0dev 2016-12-24 12:14:05 +01:00
Mathias Svensson 7ed118763b Merge branch 'dev' into beta 2016-12-24 11:54:21 +01:00
Mathias Svensson e997c17397 Merge branch 'beta' into dev 2016-12-24 11:10:10 +01:00
Mathias Svensson 0acc8ee499 Merge branch 'stable' into beta 2016-12-24 11:00:32 +01:00
Zach Riggle f14e0e5652 Reorder get_buffer_size so that the value is validated
This prevents silly things like tube.recv("abcdef") which will hang
2016-12-22 16:41:51 -05:00
Zach Riggle aaa83983ad Merge branch 'beta' into dev 2016-12-22 16:27:46 -05:00
Zach Riggle 1241073391 Remove support for installation without psutil (#821)
* Remove support for installation without psutil.

OpenBSD was the edge case we cared about, it is supported for over a year (giampaolo/psutil#615)

* Bump psutil version to when they introduced OpenBSD support
2016-12-20 14:06:06 -05:00
Zach Riggle cfcd79e169 Update install strings to include libffi-dev and be consistent 2016-12-16 11:37:13 -06:00
Zach Riggle 706a784904 Directly invoke sock.close() when we hit POLLHUP 2016-12-15 20:20:07 -06:00
Zach Riggle 70c96330de Make sock.connected much more robust by using socket.poll (#817)
* Make sock.connected much more robust by using socket.poll

* Fix use of socket.socket.recv vs. ssh transport recv
2016-12-15 20:15:19 -06:00
Zach Riggle cae3cddc07 Fix incorrect error message in serialtube 2016-12-15 20:04:12 -06:00
Zach Riggle 5373dcdeed Fix dev-only regression in serialtube constructor, and use Timeout object properties 2016-12-15 20:04:12 -06:00
Zach Riggle 5d4bf3db6c Add MemLeak.u64/u32/... aliases 2016-12-15 17:15:10 -06:00
Zach Riggle fbfa54ad61 Fix failing doctestse on dev 2016-12-15 16:45:08 -06:00
Zach Riggle b323264032 Merge branch 'beta' into dev 2016-12-15 15:05:16 -06:00
Zach Riggle 2c841eaa21 Add adb.{unlink,mkdir,makedirs,isdir,exists} (#809)
* Add adb.{unlink,mkdir,makedirs,isdir,exists}

* Change unlink() to throw an exception rather than return a string

* Fix doctest and code for isdir

* Remove unused variable
2016-12-14 16:49:41 -06:00
Zach Riggle d2c6184a00 Add missing changelog entry 2016-12-14 14:58:00 -06:00
Zach Riggle e5645e7b53 Update CHANGELOG missing links 2016-12-14 14:49:54 -06:00
Zach Riggle 09dbe0a54d Update CHANGELOG links 2016-12-14 14:49:27 -06:00
Zach Riggle 0bd0de78f9 Update CHANGELOG 2016-12-14 14:48:19 -06:00
Zach Riggle 546061e577 Modify coredump_filter of spawned processes so that library contents are included 2016-12-12 18:26:46 -06:00
Zach Riggle 5ebc8b5bb7 Check the name before attempting to call startswith() 2016-12-12 18:26:46 -06:00
Zach Riggle b83a6c7db8 Fix process.leak by providing a sane default leak size 2016-12-05 15:44:04 -05:00
Owlz 5d9792fb4c Variable Size Buffer Fill (#806)
Support custom buffer-read sizes for `tube` objects via their internal `Buffer` object.  Default buffer size is 4096.  Buffer size can be set per-object at instantiation-time (`tube(buffer_fill_size=...)`), by attribute (`tube.buffer_fill_size=...`), or in a context (`context.buffer_size=...`).
2016-12-05 15:21:08 -05:00
Zach Riggle 1c54e347f2 Add 'shell' option for ssh.process to pass to "sh -c" (#800)
Add 'shell' option for ssh.process to pass to "sh -c"
2016-11-29 11:52:44 -07:00
Zach Riggle 7545dafffb Wrap context.log_console when using terminal I/O (#797)
Fixes Gallopsled/pwntools#792
2016-11-23 11:11:17 -07:00
Zach Riggle 3acec5421f Set shell=False 2016-11-12 23:16:32 -08:00
Mathias Svensson b441cf967a Start work on 3.4.0 2016-11-12 20:39:25 +01:00
3773 changed files with 57773 additions and 28816 deletions

No files matched your search

+6 -1
View File
@@ -4,6 +4,11 @@ Thanks for contributing to Pwntools!
When reporting an issue, be sure that you are running the latest released version of pwntools (`pip install --upgrade pwntools`).
Please verify that your issue occurs on 64-bit Ubuntu 14.04. You can use the Dockerfile in `extra/docker/Dockerfile` to save time.
Please verify that your issue occurs on 64-bit Ubuntu 14.04. You can use the Dockerfile on `docker.io` for quick testing.
```
$ docker pull pwntools/pwntools:stable
$ docker run -it pwntools/pwntools:stable
```
If possible, provide a proof-of-concept which demonstrates the problem. Include any binaries or scripts necessary to reproduce the issue, and please include the full debug output via setting the environment variable `PWNLIB_DEBUG=1`.
+2
View File
@@ -11,6 +11,8 @@ docs/build
build
MANIFEST
dist
venv
.vscode
*.egg-info
*.core
.coverage
+23 -10
View File
@@ -1,10 +1,9 @@
sudo: false
dist: xenial
language: python
addons:
apt:
packages:
- gcc-multilib
- gcc-4.6-arm-linux-gnueabihf
- lib32stdc++6
- ash
- bash
@@ -13,25 +12,39 @@ addons:
- mksh
- zsh
- pandoc
- gdb
- binutils
- qemu-user-static
- binutils-multiarch
- binutils-aarch64-linux-gnu
- binutils-arm-linux-gnueabihf
- binutils-mips-linux-gnu
- binutils-powerpc-linux-gnu
cache:
- pip
- directories:
- usr
- /home/travis/virtualenv/python2.7.9/lib/python2.7/site-packages/
- /home/travis/virtualenv/python2.7.9/bin/
- /home/travis/virtualenv/python2.7.15/lib/python2.7/site-packages/
- /home/travis/virtualenv/python2.7.15/bin/
python:
- "2.7"
- "2.7.15"
- "3.6"
before_install:
- echo $-
- source travis/install.sh
- source travis/ssh_setup.sh
- echo $-
install:
- pip install --upgrade pip
- pip install --upgrade appdirs # https://github.com/ActiveState/appdirs/issues/89#issuecomment-282326570
- python setup.py egg_info # pypa/pip#6275
- pip install --upgrade --editable .
- pip install --requirement docs/requirements.txt
- pip install --upgrade --requirement docs/requirements.txt
before_script:
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
script:
- PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest
after_success:
+403 -10
View File
@@ -9,9 +9,30 @@ The table below shows which release corresponds to each branch, and what date th
| Version | Branch | Release Date |
| ---------------- | -------- | ---------------------- |
| [3.5.0](#350) | `dev` | Mar 18, 2017 (planned)
| [3.4.0](#340) | `beta` | Feb 4, 2017 (planned)
| [3.3.2](#332) | `stable` | Jan 10, 2016
| [4.2.0](#420) | `dev` | Feb 10, 2020 (planned)
| [4.1.0](#410) | `beta` | Jan 30, 2020 (planned)
| [4.0.1](#401) | `stable` | Jan 22, 2020
| [4.0.0](#400) | | Jan 09, 2020
| [3.13.0](#3130) | | Nov 5, 2019
| [3.12.1](#3121) | | Sept 17, 2018
| [3.12.0](#3120) | | Feb 22, 2018
| [3.11.0](#3110) | | Jan 3, 2018
| [3.10.0](#3100) | | Oct 25, 2017
| [3.9.2](#392) | | Oct 5, 2017
| [3.9.1](#391) | | Sep 28, 2017
| [3.9.0](#390) | | Sep 11, 2017
| [3.8.0](#380) | | Jul 29, 2017
| [3.7.1](#371) | | Jul 14, 2017
| [3.7.0](#370) | | Jun 19, 2017
| [3.6.1](#361) | | May 12, 2017
| [3.6.0](#360) | | May 8, 2017
| [3.5.1](#351) | | Apr 15, 2017
| [3.5.0](#350) | | Mar 26, 2017
| [3.4.1](#341) | | Feb 17, 2017
| [3.4.0](#340) | | Feb 13, 2017
| [3.3.4](#334) | | Jan 12, 2016
| [3.3.3](#333) | | Jan 10, 2016
| [3.3.2](#332) | | Jan 10, 2016
| [3.3.1](#331) | | Jan 10, 2016
| [3.3.0](#330) | | Dec 24, 2016
| [3.2.1](#321) | | Dec 24, 2016
@@ -25,19 +46,391 @@ The table below shows which release corresponds to each branch, and what date th
| [3.0.0](#300) | | Aug 20, 2016
| [2.2.0](#220) | | Jan 5, 2015
## 4.2.0 (`dev`)
To be released on Feb 10, 2020.
## 4.1.0 (`beta`)
To be released on Jan 30, 2020.
- [#1316][1316] Fix connect shellcraft in python 3
- [#1323][1323] Fix issues related with debugging
- [#1001][1001] Enhance `unlock_bootloader` with better status messages
- [#1389][1389] remove old dependencies
- [#1241][1241] Launch QEMU with sysroot if specified
- [#1218][1218] Support for FileStructure exploitation
[1241]: https://github.com/Gallopsled/pwntools/pulls/1218
[1218]: https://github.com/Gallopsled/pwntools/pulls/1218
## 4.0.1 (`stable`)
- [#1412][1412] `recvline_pred()` and similar do not reorder data
- Bypass unicorn-engine/unicorn#1100 and unicorn-engine/unicorn#1170 requiring unstable package
[1412]: https://github.com/Gallopsled/pwntools/pulls/1412
## 4.0.0
- **Python 3 support! <3**
- [#1402][1402] Fix serialtube in python 3
- [#1391][1391] Fix process.libs
- [#1317][1317] Tubes with `context.encoding`
- [#1216][1216] Improve format string generator
- [#1285][1285] Add freebsd generic syscall templates
- [76413f][76413f] Add pwnlib.adb.bootimg for 'ANDROID!' format boot.img images
- [#1202][1202] Docker: Kill 14 layers in pwntools base images
- [#1182][1182] shellcraft.dupio() for mips
[1391]: https://github.com/Gallopsled/pwntools/pulls/1391
[1317]: https://github.com/Gallopsled/pwntools/pulls/1317
[1285]: https://github.com/Gallopsled/pwntools/pulls/1285
[1216]: https://github.com/Gallopsled/pwntools/pulls/1216
[1202]: https://github.com/Gallopsled/pwntools/pulls/1202
[1182]: https://github.com/Gallopsled/pwntools/pulls/1182
[76413f]: https://github.com/Gallopsled/pwntools/commit/76413f
## 3.13.0
- [#1204][1204] Reduce ROP cache filename length
- [#1175][1175] Fix nested SSH connectors
- [#1355][1355] Fix 'break' syscall
- [#1277][1277] Fix timeout parameter passing in sendlineafter and other similar functions
- [#1292][1292] Provide correct arch name to gdb for sparc64
[1175]: https://github.com/Gallopsled/pwntools/pulls/1175
[1204]: https://github.com/Gallopsled/pwntools/pulls/1355
[1277]: https://github.com/Gallopsled/pwntools/pulls/1277
[1292]: https://github.com/Gallopsled/pwntools/pulls/1292
[1355]: https://github.com/Gallopsled/pwntools/pulls/1355
## 3.12.1
- [#1104][1104] Add `DynELF.dump()` for dumping remote ELF files
- [#1101][1101] Set `context.os` via `context.binary`, useful for Android exploitation
- [5fdc08][5fdc08] Work around broken `pidof` on Android
- [63dfed][63dfed] Print warning when Corefile deletion fails instead of throwing an exception
- [#1094][1094] Make hexdump output alignment more consistent
- [#1096][1096] `flat()` and `fit()` are now the same function
[1104]: https://github.com/Gallopsled/pwntools/pull/1104
[1101]: https://github.com/Gallopsled/pwntools/pull/1101
[1094]: https://github.com/Gallopsled/pwntools/pull/1094
[1096]: https://github.com/Gallopsled/pwntools/pull/1096
[5fdc08]: https://github.com/Gallopsled/pwntools/commit/5fdc08
[63dfed]: https://github.com/Gallopsled/pwntools/commit/63dfed
## 3.12.2
- [1242][1242] Use IntervalTree 2.xx, disallow use of 3.xx
- [1243][1243] Fix a typo that caused an exception when executing a binary with `process()` which returns `-ENOEXEC` and the system does not have `qemu-user` binaries installed.
[1242]: https://github.com/Gallopsled/pwntools/pull/1242
[1243]: https://github.com/Gallopsled/pwntools/pull/1243
## 3.12.1
- [#1198][1198] More compatibility fixes for pyelftools==0.25, and pin Sphinx<1.8.0 since it causes testing errors
- [#1191][1191] Fix compatibility with pyelftools==0.25
- [#1159][1159] Fix check for `/proc/.../status`
- [#1162][1162] Fix broken package versions
- [#1150][1150] Fix exception raised when a cache file is missing
- [#1156][1156] Fix ROP gadget selection logic involving `int` and `syscall` instructions
- [#1152][1152] Fix QEMU LD_PREFIX calculation (wrong parameter passed)
- [#1155][1155] Use Ubuntu Trusty for all CI builds
- [#1131][1131] Add "libc-" to libc prefixes in `process` tubes
- [#1125][1125] Fix a typo
- [#1121][1121] Fix tests which were broken by an upstream Sphinx change
[1159]: https://github.com/Gallopsled/pwntools/pull/1159
[1162]: https://github.com/Gallopsled/pwntools/pull/1162
[1150]: https://github.com/Gallopsled/pwntools/pull/1150
[1156]: https://github.com/Gallopsled/pwntools/pull/1156
[1152]: https://github.com/Gallopsled/pwntools/pull/1152
[1155]: https://github.com/Gallopsled/pwntools/pull/1155
[1131]: https://github.com/Gallopsled/pwntools/pull/1131
[1125]: https://github.com/Gallopsled/pwntools/pull/1125
[1121]: https://github.com/Gallopsled/pwntools/pull/1121
## 3.12.0
- [#1083][1083] Better error messages for `gdb` when `LD_PRELOAD` is incorrect
- [#1085][1085] Add support for extracting Android `BOOTLDR!` images
- [#1075][1075] Add support for detecting GNU Screen for `run_in_new_terminal`
- [#1074][1074] Add support for running `pwntools-gdb` wrapper script instead of `gdb`
- [#1068][1068] Work around very old OpenSSL versions which don't have sha256 support *AND* don't exit with an error code when trying to use it
- [#1067][1067] Add `pwnlib.tubes.server` module, which adds a reusable `server` listener
- [#1063][1063] Add support for labels in `fit()`, allowing dynamic contents to be injected. (This feature is really cool, check out the pull request!)
[1083]: https://github.com/Gallopsled/pwntools/pull/1083
[1085]: https://github.com/Gallopsled/pwntools/pull/1085
[1075]: https://github.com/Gallopsled/pwntools/pull/1075
[1074]: https://github.com/Gallopsled/pwntools/pull/1074
[1068]: https://github.com/Gallopsled/pwntools/pull/1068
[1067]: https://github.com/Gallopsled/pwntools/pull/1067
[1063]: https://github.com/Gallopsled/pwntools/pull/1063
## 3.11.0
- [#1044][1044] Enhancements to ROP
+ Much better support for 64-bit Intel (amd64) ROP
+ ROP gadget selection is optimized to favor multi-pops instead of multiple single-pop gadgets
+ Added support for blacklisting byte values in ROP gadget addresses
- [#1049][1049] Enhancements to `cyclic`
+ `context` now has two additional attributes, `cyclic_alphabet` and `cyclic_length`, which correspond to the arguments `alphabet` and `n` to `cyclic()` and `cyclic_find()` and related routines.
+ The motivation for this change is to allow setting the `alphabet` globally, so that any padding / patterns generated internally to pwntools can be controlled. The specific motivation is blacklisting values in ROP padding.
- [#1052][1052] Enhancements for detecting `QEMU_LD_PREFIX` used by QEMU user-mode emulation for sysroots
- [#1035][1035] Minor documentation changes
- [#1032][1032] Enhancements to `pwn template`
- [#1031][1031] More accurate `Coredump.fault_addr` on amd64
- [#1084][1084] Fix broken tests due to `ftp.debian.org` going down
[1044]: https://github.com/Gallopsled/pwntools/pull/1044
[1049]: https://github.com/Gallopsled/pwntools/pull/1049
[1052]: https://github.com/Gallopsled/pwntools/pull/1052
[1035]: https://github.com/Gallopsled/pwntools/pull/1035
[1032]: https://github.com/Gallopsled/pwntools/pull/1032
[1031]: https://github.com/Gallopsled/pwntools/pull/1031
[1084]: https://github.com/Gallopsled/pwntools/pull/1084
## 3.10.0
- [#1007][1007] Add support for setting a `gdbinit` file in the context
- [#1055][1055] Fixes for `Corefile` stack parsing, speed up `ELF.string()`
- [#1057][1057] Fix a variable name typo in `DynELF` logging which results in an exception being thrown
- [#1058][1058] Fix an edge case in `ssh_process.exe`
[1007]: https://github.com/Gallopsled/pwntools/pull/1007
[1055]: https://github.com/Gallopsled/pwntools/pull/1055
[1057]: https://github.com/Gallopsled/pwntools/pull/1057
[1058]: https://github.com/Gallopsled/pwntools/pull/1058
## 3.9.2
- [#1043][1043] Do not attempt to populate the libraries used by statically-linked binaries
[1043]: https://github.com/Gallopsled/pwntools/pull/1043
## 3.9.1
- [#1038][1038] Fix an issue with `process()` where glibc would buffer data internally, causing a hang on `select()`
- [#1036][1036] Fix Travis CI logging verbosity
- [#1029][1029] Fix some `unicode` issues when using the `readline` command history in `tube.interactive()`
[1038]: https://github.com/Gallopsled/pwntools/pull/1038
[1036]: https://github.com/Gallopsled/pwntools/pull/1036
[1029]: https://github.com/Gallopsled/pwntools/pull/1029
## 3.9.0
- [#1003][1003] Make `concat_all` faster while also simplifying it's logic
- [#1014][1014] Fix for overwritten env when parsing core file
- [#1023][1023] Fixes to Travis CI
[1003]: https://github.com/Gallopsled/pwntools/pull/1003
[1014]: https://github.com/Gallopsled/pwntools/pull/1014
[1023]: https://github.com/Gallopsled/pwntools/pull/1023
## 3.8.0
- [#981][981] Fixed RELRO detection logic
- [#986][986] Enhancements to DynELF for controlling usage of LibcDB
- A few documentation fixes
- A few fixes for the Docker image
[981]: https://github.com/Gallopsled/pwntools/pull/981
[986]: https://github.com/Gallopsled/pwntools/pull/986
## 3.7.1
- [#998][998] Fix a bug where integer values could not be set in `.pwn.conf`.
[998]: https://github.com/Gallopsled/pwntools/pull/998
## 3.7.0
- [#933][933] DynELF works better with different base addresses
- [#952][952] A few small fixes were made to `pwn template`, and the CRC database was updated.
- [5c72d62c][5c72d62c] Updated the CRC database
[933]: https://github.com/Gallopsled/pwntools/pull/933
[952]: https://github.com/Gallopsled/pwntools/pull/952
[5c72d62c]: https://github.com/Gallopsled/pwntools/commit/5c72d62c
## 3.6.1
- [#979][979]+[1a4a1e1][1a4a1e1] Fixed [#974][974], a bug related to the terminal handling and numlock.
- [#980][980] Fixed the `pwn template` command.
[974]: https://github.com/Gallopsled/pwntools/issues/974
[979]: https://github.com/Gallopsled/pwntools/pull/979
[980]: https://github.com/Gallopsled/pwntools/pull/980
[1a4a1e1]: https://github.com/Gallopsled/pwntools/commit/1a4a1e1
## 3.6.0
- [#895][895] Added a Dockerfile to simplify testing setup and allow testing on OSX
- [#897][897] Fixed some incorrect AArch64 syscals
- [#893][893] Added the `pwnlib.config` module
+ Configuration options can now be set in `~/.pwn.conf`
+ This replaces the old, **undocumented** mechanism for changing logging colors. Only @br0ns and @ebeip90 were likely using this.
+ More information is available in the documentation [here](http://docs.pwntools.com/en/dev/config.html).
- [#899][899] Pwntools now uses Unicorn Engine to emulate PLT instructions to ensure correct mapping of PIE / RELRO binaries.
- [#904][904] Enhancements to the accuracy of the `pwn checksec` command.
- [#905][905] Added a `pwn debug` command-line utility which automates the process of `gdb.attach(process(...))` to spawn GDB
+ More information is available in the documentation [here](http://docs.pwntools.com/en/dev/commandline.html#pwn-debug)
- [#919][919] Added a `pwn template` command-line utility to simplify the process of bootstrapping a new exploit.
+ More information is available in the documentation [here](http://docs.pwntools.com/en/dev/commandline.html#pwn-template).
- [#948][948] Fix unnecessary warning for Core files
- [#954][954] Fix list processing in `~/.pwn.conf`
- [#967][967] Respect `TERM_PROGRAM` for `run_in_new_terminal`
- [#970][970] Fix overly-aggressive corefile caching
[947]: https://github.com/Gallopsled/pwntools/pull/947
[948]: https://github.com/Gallopsled/pwntools/pull/948
[954]: https://github.com/Gallopsled/pwntools/pull/954
[960]: https://github.com/Gallopsled/pwntools/pull/960
[967]: https://github.com/Gallopsled/pwntools/pull/967
[968]: https://github.com/Gallopsled/pwntools/pull/968
[970]: https://github.com/Gallopsled/pwntools/pull/970
[895]: https://github.com/Gallopsled/pwntools/pull/895
[897]: https://github.com/Gallopsled/pwntools/pull/897
[893]: https://github.com/Gallopsled/pwntools/pull/893
[899]: https://github.com/Gallopsled/pwntools/pull/899
[904]: https://github.com/Gallopsled/pwntools/pull/904
[905]: https://github.com/Gallopsled/pwntools/pull/905
[919]: https://github.com/Gallopsled/pwntools/pull/919
## 3.5.1
- [#945][945] Speed up ssh via caching checksec results (fixes [#944][944])
- [#950][950] Fixes a bug where setting `context.arch` does not have an effect on `adb.compile()` output architecture
[944]: https://github.com/Gallopsled/pwntools/issues/944
[945]: https://github.com/Gallopsled/pwntools/pull/945
[950]: https://github.com/Gallopsled/pwntools/pull/950
## 3.5.0
To be released on Mar 18, 2017.
- [b584ca3][b584ca3] Fixed an issue running `setup.py` on ARM
- [#822][822] Enabled relative leaks with `MemLeak`
+ This should be useful for e.g. heap-relative leaks
- [#832][832] Changed all internal imports to use absolute imports (no functional changes)
- [a12d0b6][a12d0b6] Move `STDOUT`, `PIPE`, `PTY` constants to globals
+ `process(..., stdin=process.PTY)` --> `process(..., stdin=PTY)`
- [#828][828] Use `PR_SET_PTRACER` for all `process()` and `ssh.process()` instances
+ This simplifies debugging on systems with YAMA ptrace enabled
- Various documentation enhancements
+ In particular, the [gdb][gdb], [elf][elf], and [ssh][ssh] docs are much better
- [#833][833] Performance enhancements for `adb` module
- [d0267f3][d0267f3] `packing.fit()` now treats large offsets as cyclic patterns (e.g. `0x61616161` behaves the same as `"aaaa"`)
- [#835][835] Added `ssh.checksec`
+ Reports the kernel version and other relevant information on connection
- [#857][857] Slightly shortened `execve` shellcode
- [300f8e0][300f8e0] Slightly speed up processing of large ELF files
- [#861][861] Adds support for extracting `IKCONFIG` configs from Linux kernel images, and extends `checksec` to report on any insecure configurations discovered
- [#871][871] Moves all of the basic syscall templates to `shellcraft/common` and exposes them via symlinks. Closed [#685][685]
+ Should not have any visible effects from any documented APIs
+ `shellcraft.arch.os.syscall_function()` still works the same
+ We now have the ability to differentiate between the `connect` syscall, and a TCP `connect` helper
- [#887][887] `sh_string` now returns a quoted empty string `''` rather than just an empty string
- [#839][839] Exposes a huge amount of functionality via corefiles which was not previously availble. See the [docs][corefile_docs] for examples.
+ `process().corefile` will automatically instantiate a Corefile for the process
+ QEMU-emulated processes are supported
+ Native processes are supported, including extraction of coredumps from `apport` crash logs
+ Native processes can be dumped *while running*, in a manner similar to `GDB`'s `gcore` script
- [#875][857] Added [documentation][aarch64] (and tests) for AArch64 shellcode
- [#882][882] The `ROP` class now respects `context.bytes` instead of using the hard-coded value of `4` (fixed [#879][879])
- [#869][869] Added several fields to the `process` class (`uid`, `gid`, `suid`, `sgid`) which are recorded at execution time, based on the file permissions
- [#868][868] Changed the way that `ssh.process()` works internally, and it now returns a more specialized class, `ssh_process`.
+ Added `ssh_process.corefile` for fetching remote corefiles
+ Added `ssh_process.ELF` for getting an ELF of the remote executable
+ The `uid`, `gid`, and `suid`, and `sgid` which are recorded at execution time, based on the file permissions
- [#865][865] Fixes `ELF.read` to support contiguous memory reads across non-contiguous file-backed segments
- [#862][862] Adds a `symlink=` argument to `ssh.set_working_directory`, which will automatically symlink all of the files in the "old" working directory into the "new" working directory
[ssh]: http://docs.pwntools.com/en/dev/tubes/ssh.html
[gdb]: http://docs.pwntools.com/en/dev/gdb.html
[elf]: http://docs.pwntools.com/en/dev/elf.html
[corefile_docs]: http://docs.pwntools.com/en/dev/elf/corefile.html
[aarch64]: http://docs.pwntools.com/en/dev/shellcraft/aarch64.html
[685]: https://github.com/Gallopsled/pwntools/pull/685
[822]: https://github.com/Gallopsled/pwntools/pull/822
[828]: https://github.com/Gallopsled/pwntools/pull/828
[832]: https://github.com/Gallopsled/pwntools/pull/832
[833]: https://github.com/Gallopsled/pwntools/pull/833
[835]: https://github.com/Gallopsled/pwntools/pull/835
[839]: https://github.com/Gallopsled/pwntools/pull/839
[857]: https://github.com/Gallopsled/pwntools/pull/857
[861]: https://github.com/Gallopsled/pwntools/pull/861
[862]: https://github.com/Gallopsled/pwntools/pull/862
[865]: https://github.com/Gallopsled/pwntools/pull/865
[868]: https://github.com/Gallopsled/pwntools/pull/868
[869]: https://github.com/Gallopsled/pwntools/pull/869
[871]: https://github.com/Gallopsled/pwntools/pull/871
[875]: https://github.com/Gallopsled/pwntools/pull/857
[879]: https://github.com/Gallopsled/pwntools/issues/879
[882]: https://github.com/Gallopsled/pwntools/pull/882
[887]: https://github.com/Gallopsled/pwntools/pull/887
[b584ca3]: https://github.com/Gallopsled/pwntools/commit/b584ca3
[a12d0b6]: https://github.com/Gallopsled/pwntools/commit/a12d0b6
[d0267f3]: https://github.com/Gallopsled/pwntools/commit/d0267f3
[300f8e0]: https://github.com/Gallopsled/pwntools/commit/300f8e0
## 3.4.1
- [#894][894] Fix a bug when using `gdb.debug()` over ssh.
- [e021f57][e021f57] Fix a bug ([#891][891]) in `rop` when needing to insert padding to fix alignment
[e021f57]: https://github.com/Gallopsled/pwntools/commit/e021f57
[894]: https://github.com/Gallopsled/pwntools/pull/894
[891]: https://github.com/Gallopsled/pwntools/issues/891
## 3.4.0
To be released on Feb 4, 2017.
- [#800][800] Add `shell=` option to `ssh.process()`
- [#806][806] Add `context.buffer_size` for fine-tuning `tube` performance
+ Also adds `buffer_fill_size=` argument for all tubes
- [b83a6c7][b83a6c7] Fix undocumented `process.leak` function
- [546061e][546061e] Modify `coredump_filter` of all spawned processes, so that core dumps are more complete
- [#809][809] Add several functions to `adb` (`unlink`, `mkdir`, `makedirs`, `isdir`, `exists`)
- [#817][817] Make disconnection detection more robust
[800]: https://github.com/Gallopsled/pwntools/pull/800
[806]: https://github.com/Gallopsled/pwntools/pull/806
[809]: https://github.com/Gallopsled/pwntools/pull/809
[817]: https://github.com/Gallopsled/pwntools/pull/817
[5d9792f]: https://github.com/Gallopsled/pwntools/commit/5d9792f
[b83a6c7]: https://github.com/Gallopsled/pwntools/commit/b83a6c7
[546061e]: https://github.com/Gallopsled/pwntools/commit/546061e
## 3.3.4
- [#850][850] and [#846][846] fix issues with `hexdump` and the `phd` command-line utility, when using pipes (e.g. `echo foo | phd`)
- [#852][852] Fixes register ordering in `regsort`
- [#853][853] Fixes the registers restored in `shellcraft.amd64.popad`
[846]: https://github.com/gallopsled/pwntools/pull/846
[850]: https://github.com/gallopsled/pwntools/pull/850
[852]: https://github.com/gallopsled/pwntools/pull/852
[853]: https://github.com/gallopsled/pwntools/pull/853
## 3.3.3
- [#843][843] fixed a bug in `amd64.mov`.
[843]: https://github.com/gallopsled/pwntools/pull/843
## 3.3.2
- [#840][840] Fixed a regression introduced by [#837][837].
- [#840][840] fixed a regression introduced by [#837][837].
[840]: https://github.com/Gallopsled/pwntools/pull/840
[840]: https://github.com/gallopsled/pwntools/pull/840
## 3.3.1
@@ -135,7 +528,7 @@ Multiple bug fixes.
- [1e414af][1e414af] Added `connect()` alias for `remote()`
+ For example, `io=connect('google.com', 80)`
+ This also works with `tcp(...)` and `udp(...)` aliases
- [869ec42][869ec42] Added `ssh.read()` and `ssh.write()` aiases
- [869ec42][869ec42] Added `ssh.read()` and `ssh.write()` aliases
- [2af55c9][2af55c9] `AdbDevice` objects exposed via e.g. `adb.devices()` now offer scoped access to all `adb` module properties
+ It is now possible to e.g. `map(lambda d: d.process(['id']).recvall(), adb.devices())`
@@ -222,7 +615,7 @@ Android support via a new `adb` module, `context.device`, `context.adb_host`, an
- Added `context.log_file` setting for sending logs to a file. This can be set with the `LOG_FILE` magic command-line option.
- Added `context.noptrace` setting for disabling actions which require `ptrace` support. This is useful for turning all `gdb.debug` and `gdb.attach` options into no-ops, and can be set via the `NOPTRACE` magic command-line option.
- Added `context.proxy` which hooks all connections and sends them to a SOCKS4/SOCKS5. This can be set via the `PROXY` magic command-line option.
- Added `context.randomize` to control randommization of settings like XOR keys and register ordering (default off).
- Added `context.randomize` to control randomization of settings like XOR keys and register ordering (default off).
- Added `context.terminal` for setting how to launch commands in a new terminal.
#### DynELF and MemLeak Module
@@ -235,7 +628,7 @@ Android support via a new `adb` module, `context.device`, `context.adb_host`, an
#### Encoders Module
- Added a `pwnlib.encoders` module for assembled-shellcode encoders/decoders
- Includes position-indepentent basic XOR encoders
- Includes position-independent basic XOR encoders
- Includes position-independent delta encoders
- Includes non-position-independent alphanumeric encoders for Intel
- Includes position-independent alphanumeric encoders for ARM/Thumb
+1 -1
View File
@@ -2,6 +2,6 @@ graft examples
graft extra
include *.md *.txt *.sh *.yml MANIFEST.in
recursive-include docs *.rst *.png Makefile *.py *.txt
recursive-include pwnlib *.py *.asm *.rst *.md *.txt *.sh
recursive-include pwnlib *.py *.asm *.rst *.md *.txt *.sh __doc__ *.mako
recursive-include pwn *.py *.asm *.rst *.md *.txt *.sh
recursive-exclude *.pyc
+6 -5
View File
@@ -2,13 +2,13 @@
![pwntools logo](https://github.com/Gallopsled/pwntools/blob/stable/docs/source/logo.png?raw=true)
[![Docs](https://readthedocs.org/projects/pwntools/badge/?version=stable)](https://docs.pwntools.com/)
[![PyPI](https://img.shields.io/badge/pypi-v3.3.2-green.svg?style=flat)](https://pypi.python.org/pypi/pwntools/)
[![PyPI](https://img.shields.io/badge/pypi-v3.13.0-green.svg?style=flat)](https://pypi.python.org/pypi/pwntools/)
[![Travis](https://travis-ci.org/Gallopsled/pwntools.svg)](https://travis-ci.org/Gallopsled/pwntools)
[![Coveralls](https://img.shields.io/coveralls/Gallopsled/pwntools/dev.svg)](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
[![Twitter](https://img.shields.io/badge/twitter-pwntools-4099FF.svg?style=flat)](https://twitter.com/pwntools)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://choosealicense.com/licenses/mit/)
pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
Pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
```python
from pwn import *
@@ -32,14 +32,15 @@ To get you started, we've provided some example solutions for past CTF challenge
# Installation
pwntools is best supported on 64-bit Ubuntu 12.04 and 14.04, but most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python 2.7 is required.
Pwntools is best supported on 64-bit Ubuntu LTE releases (12.04, 14.04, 16.04 and 18.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python >= 2.7 is required (Python 3 suggested as best).
Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
```sh
apt-get update
apt-get install python2.7 python-pip python-dev git libssl-dev
pip install --upgrade pwntools
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools.git@dev3
```
However, some of the features (assembling/disassembling foreign architectures) require non-Python dependencies. For more information, see the [complete installation instructions here](https://docs.pwntools.com/en/stable/install.html).
+6 -1
View File
@@ -4,7 +4,6 @@ Pwntools makes extensive use of unit tests and integration tests to ensure every
## Test Suite
To run the test suite, it is best to use Ubuntu 12.04 or 14.04, and run the following commands. **Be aware** that this will add a user to the machine, and create a public key for SSH login!
```sh
@@ -14,6 +13,12 @@ pip install --upgrade --editable .
PWNLIB_NOTERM=1 make -C docs doctest
```
## Testing in Docker
A `Dockerfile` has been provided which has a clean testing environment with Ubuntu Xenial. It is very similar to the online Travis CI testing environment, but uses a more modern version of Ubuntu.
See `travis/docker/README.md` for more information.
## New Tests
To add a new test to an existing module, just add an inline doctest. If the test needs access to an external module, add the import statement to the `testsetup` block in the corresponding file in `docs/source/<module>.rst`.
+1 -1
View File
@@ -44,7 +44,7 @@ def main(args):
doc2dash.__main__.main.main( \
[ os.path.join(dstdir, "html"), "-d", dstdir, "-n", name, \
"-f", "-I", "index.html"], "doc2dash", False)
except SystemExit,e:
except SystemExit as e:
pass
# Insert a link to the online version.
+14 -12
View File
@@ -1,16 +1,18 @@
sphinxcontrib-napoleon
sphinxcontrib-autoprogram==0.1.2
isort
paramiko>=1.15.2
mako>=1.0.0
pyelftools>=0.2.3
capstone
ropgadget>=5.3
coveralls
doc2dash
isort
mako>=1.0.0
paramiko>=1.15.2
pip>=6.0.8
pyelftools>=0.2.3
pygments>=2.0
pypandoc
pyserial>=2.7
requests>=2.5.1
pip>=6.0.8
tox>=1.8.1
pygments>=2.0
ropgadget>=5.3
sphinx
sphinx_rtd_theme
doc2dash
coveralls
sphinxcontrib-napoleon
sphinxcontrib-autoprogram
tox>=1.8.1
+1
View File
@@ -1,5 +1,6 @@
.. testsetup:: *
from pprint import pprint
from pwn import *
adb = pwnlib.adb
+11
View File
@@ -6,6 +6,7 @@
from pwnlib.asm import *
from pwnlib import shellcraft
from pwnlib.tubes.process import process
from pwnlib.util.fiddling import unhex
:mod:`pwnlib.asm` --- Assembler functions
@@ -13,3 +14,13 @@
.. automodule:: pwnlib.asm
:members:
Internal Functions
-----------------------------------------
These are only included so that their tests are run.
You should never need these.
.. autofunction:: pwnlib.asm.dpkg_search_for_binutils
.. autofunction:: pwnlib.asm.print_binutils_instructions
+109 -11
View File
@@ -12,6 +12,8 @@
# serve to show the default.
import os
import doctest
import six
import subprocess
import sys
@@ -24,8 +26,6 @@ sys.path.insert(0, os.path.abspath('../..'))
import pwnlib
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
@@ -44,14 +44,36 @@ extensions = [
'sphinxcontrib.napoleon'
]
# Disable "info" logging directly to stdout by Sphinx
import logging
class SphinxPwnlibFilter(logging.Filter):
def filter(self, record):
if record.name.startswith('pwn'):
return False
if record.name.startswith('paramiko'):
return False
return True
log_filter = SphinxPwnlibFilter()
for i, handler in enumerate(logging.root.handlers):
print("Filtering Sphinx handler", handler)
handler.addFilter(log_filter)
# Napoleon settings
napoleon_use_ivar = True
napoleon_use_rtype = False
doctest_global_setup = '''
import sys, os
os.environ['PWNLIB_NOTERM'] = '1'
os.environ['PWNLIB_RANDOMIZE'] = '0'
import pwnlib
import pwnlib, logging
pwnlib.context.context.reset_local()
pwnlib.context.ContextType.defaults['log_level'] = 'ERROR'
pwnlib.context.ContextType.defaults['log_level'] = logging.ERROR
pwnlib.context.ContextType.defaults['randomize'] = False
pwnlib.util.fiddling.default_style = {}
pwnlib.term.text.when = 'never'
pwnlib.log.install_default_handler()
pwnlib.log.rootlogger.setLevel(1)
@@ -67,12 +89,13 @@ class stdout(object):
pwnlib.context.ContextType.defaults['log_console'] = stdout()
'''
autodoc_member_order = 'alphabetical'
autoclass_content = 'both'
autodoc_member_order = 'groupwise' # 'alphabetical'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
doctest_test_doctest_blocks = True
doctest_test_doctest_blocks = 'true'
# The suffix of source filenames.
source_suffix = '.rst'
@@ -231,7 +254,7 @@ latex_documents = [
]
intersphinx_mapping = {'python': ('https://docs.python.org/2.7', None),
'paramiko': ('https://paramiko-docs.readthedocs.org/en/1.15/', None)}
'paramiko': ('https://paramiko-docs.readthedocs.org/en/2.1/', None)}
# The name of an image file (relative to this directory) to place at the top of
# the title page.
@@ -290,13 +313,13 @@ texinfo_documents = [
branch = release
try:
git_branch = subprocess.check_output('git describe --tags', shell = True)
git_branch = subprocess.check_output('git describe --tags', shell = True, universal_newlines = True)
except subprocess.CalledProcessError:
git_branch = '-'
try:
if '-' in git_branch:
branch = subprocess.check_output('git rev-parse HEAD', shell = True).strip()[:10]
branch = subprocess.check_output('git rev-parse HEAD', shell = True, universal_newlines = True).strip()[:10]
except subprocess.CalledProcessError:
pass
@@ -324,11 +347,11 @@ def linkcode_resolve(domain, info):
else:
filename = info['module'].replace('.', '/') + '.py'
if isinstance(val, (types.ModuleType, types.ClassType, types.MethodType, types.FunctionType, types.TracebackType, types.FrameType, types.CodeType)):
if isinstance(val, (types.ModuleType, types.MethodType, types.FunctionType, types.TracebackType, types.FrameType, types.CodeType) + six.class_types):
try:
lines, first = inspect.getsourcelines(val)
filename += '#L%d-%d' % (first, first + len(lines) - 1)
except IOError:
except (IOError, TypeError):
pass
return "https://github.com/Gallopsled/pwntools/blob/%s/%s" % (branch, filename)
@@ -347,3 +370,78 @@ if build_dash:
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
# -- Customization to Sphinx autodoc generation --------------------------------------------
import sphinx.ext.autodoc
from sphinx.util.inspect import safe_getmembers, safe_getattr
# Test hidden members (e.g. def _foo(...))
def dont_skip_any_doctests(app, what, name, obj, skip, options):
return False
def get_object_members_all(self, want_all):
if want_all:
# if not hasattr(self.object, '__all__'):
# for implicit module members, check __module__ to avoid
# documenting imported objects
return True, safe_getmembers(self.object)
# else:
# memberlist = self.object.__all__
# # Sometimes __all__ is broken...
# if not isinstance(memberlist, (list, tuple)) or not \
# all(isinstance(entry, string_types) for entry in memberlist):
# self.directive.warn(
# '__all__ should be a list of strings, not %r '
# '(in module %s) -- ignoring __all__' %
# (memberlist, self.fullname))
# # fall back to all members
# return True, safe_getmembers(self.object)
else:
memberlist = self.options.members or []
ret = []
for mname in memberlist:
try:
ret.append((mname, safe_getattr(self.object, mname)))
except AttributeError:
self.directive.warn(
'missing attribute mentioned in :members: or __all__: '
'module %s, attribute %s' % (
safe_getattr(self.object, '__name__', '???'), mname))
return False, ret
class _DummyClass(object): pass
class Py2OutputChecker(_DummyClass, doctest.OutputChecker):
def check_output(self, want, got, optionflags):
sup = super(Py2OutputChecker, self).check_output
if sup(want, got, optionflags):
return True
try:
rly_want = pwnlib.util.safeeval.const(want)
if sup(repr(rly_want), got, optionflags):
return True
rly_got = pwnlib.util.safeeval.const(got)
if rly_want == rly_got:
return True
except ValueError:
pass
rly_want = ' '.join(x[:2].replace('b"','"').replace("b'","'")+x[2:] for x in want.replace('\n','\n ').split(' ')).replace('\n ','\n')
if sup(rly_want, got, optionflags):
return True
rly_want = ' '.join(x[:2].replace('b"',' "').replace("b'"," '")+x[2:] for x in want.replace('\n','\n ').split(' ')).replace('\n ','\n')
return sup(rly_want, got, optionflags)
def py2_doctest_init(self, checker=None, verbose=None, optionflags=0):
if checker is None:
checker = Py2OutputChecker()
doctest.DocTestRunner.__init__(self, checker, verbose, optionflags)
if 'doctest' in sys.argv:
def setup(app):
app.connect('autodoc-skip-member', dont_skip_any_doctests)
if sys.version_info[:1] < (3,):
import sphinx.ext.doctest
sphinx.ext.doctest.SphinxDocTestRunner.__init__ = py2_doctest_init
sphinx.ext.autodoc.ModuleDocumenter.get_object_members = get_object_members_all
+4
View File
@@ -0,0 +1,4 @@
:mod:`pwnlib.config` --- Pwntools Configuration File
====================================================
.. automodule:: pwnlib.config
+22 -4
View File
@@ -3,13 +3,31 @@
from pwn import *
import logging
log = pwnlib.log.getLogger('pwnlib.context')
context.clear()
:mod:`pwnlib.context` --- Setting runtime variables
=====================================================
.. autodata:: pwnlib.context.context
Many settings in ``pwntools`` are controlled via the global variable :data:`.context`, such as the selected target operating system, architecture, and bit-width.
.. autoclass:: pwnlib.context.ContextType
:members:
In general, exploits will start with something like:
.. autoclass:: pwnlib.context.Thread
.. code-block:: python
from pwn import *
context.arch = 'amd64'
Which sets up everything in the exploit for exploiting a 64-bit Intel binary.
The recommended method is to use ``context.binary`` to automagically set all of the appropriate values.
.. code-block:: python
from pwn import *
context.binary = './challenge-binary'
Module Members
----------------------------------------------------
.. automodule:: pwnlib.context
:members:
+11 -3
View File
@@ -3,8 +3,16 @@
from pwnlib.elf import *
from pwnlib.util.misc import which
:mod:`pwnlib.elf` --- Working with ELF binaries
===============================================
:mod:`pwnlib.elf` --- ELF Executables and Libraries
===================================================
.. automodule:: pwnlib.elf
:members:
ELF Modules
-------------------
.. toctree::
elf/elf
elf/config
elf/corefile
+10
View File
@@ -0,0 +1,10 @@
.. testsetup:: *
from pwn import *
from pwnlib.elf.config import parse_kconfig
:mod:`pwnlib.elf.config` --- Kernel Config Parsing
===========================================================
.. automodule:: pwnlib.elf.config
:members:
+16
View File
@@ -0,0 +1,16 @@
.. testsetup:: *
from glob import glob
from pwn import *
:mod:`pwnlib.elf.corefile` --- Core Files
===========================================================
.. automodule:: pwnlib.elf.corefile
.. autoclass:: pwnlib.elf.corefile.Corefile
:members:
:show-inheritance:
.. autoclass:: pwnlib.elf.corefile.Mapping
:members:
+29
View File
@@ -0,0 +1,29 @@
.. testsetup:: *
from pwn import *
from glob import glob
from pwnlib.elf.maps import CAT_PROC_MAPS_EXIT
:mod:`pwnlib.elf.elf` --- ELF Files
===========================================================
.. automodule:: pwnlib.elf.elf
.. autoclass:: pwnlib.elf.elf.ELF
:members:
:show-inheritance:
:inherited-members:
:exclude-members: address_offsets,
get_data,
get_dwarf_info,
get_section,
get_segment,
has_dwarf_info,
iter_sections,
iter_segments
.. autoclass:: pwnlib.elf.elf.Function
:members:
.. autoclass:: pwnlib.elf.elf.dotdict
:members:
+4
View File
@@ -1,3 +1,7 @@
.. testsetup:: *
from pwn import *
:mod:`pwnlib.gdb` --- Working with GDB
======================================
+6 -6
View File
@@ -13,11 +13,11 @@ Which imports a bazillion things into the global namespace to make your life eas
This is a quick list of most of the objects and routines imported, in rough order of importance and frequency of use.
- ``context``
- :mod:`pwnlib.context`
- :data:`pwnlib.context.context`
- Responsible for most of the pwntools convenience settings
- Set `context.log_level = 'debug'` when troubleshooting your exploit
- Scope-aware, so you can disable logging for a subsection of code via ``pwnlib.context.ContextType.local``
- Scope-aware, so you can disable logging for a subsection of code via :meth:`.ContextType.local`
- ``remote``, ``listen``, ``ssh``, ``process``
- :mod:`pwnlib.tubes`
- Super convenient wrappers around all of the common functionality for CTF challenges
@@ -57,11 +57,11 @@ This is a quick list of most of the objects and routines imported, in rough orde
- ``gdb.debug`` and ``gdb.attach``
- :mod:`pwnlib.gdb`
- Launch a binary under GDB and pop up a new terminal to interact with it. Automates setting breakpoints and makes iteration on exploits MUCH faster.
- Alternately, attach to a running process given a PID, ``pwnlib.tubes`` object, or even just a socket that's connected to it
- Alternately, attach to a running process given a PID, :mod:`pwnlib.tubes` object, or even just a socket that's connected to it
- ``args``
- Dictionary contining all-caps command-line arguments for quick access
- Dictionary containing all-caps command-line arguments for quick access
- Run via ``python foo.py REMOTE=1`` and ``args['REMOTE'] == '1'``.
- Can also control logging verbosity and terminal fancyness
- Can also control logging verbosity and terminal fanciness
- `NOTERM`
- `SILENT`
- `DEBUG`
@@ -78,7 +78,7 @@ This is a quick list of most of the objects and routines imported, in rough orde
- It's the new ``getch``
- ``safeeval``
- :mod:`pwnlib.util.safeeval`
- Functions for safely evalutaing python code without nasty side-effects.
- Functions for safely evaluating python code without nasty side-effects.
These are all pretty self explanatory, but are useful to have in the global namespace.
+4
View File
@@ -48,6 +48,7 @@ Each of the ``pwntools`` modules is documented here.
atexception
atexit
constants
config
context
dynelf
encoders
@@ -56,8 +57,11 @@ Each of the ``pwntools`` modules is documented here.
flag
fmtstr
gdb
libcdb
log
memleak
protocols
qemu
replacements
rop
rop/*
+3 -1
View File
@@ -24,7 +24,9 @@ pwntools is available as a ``pip`` package.
.. code-block:: bash
$ apt-get install python2.7 python2.7-dev python-pip
$ apt-get update
$ apt-get install python2.7 python-pip python-dev git libssl-dev libffi-dev build-essential
$ pip install --upgrade pip
$ pip install --upgrade pwntools
Development
+36 -36
View File
@@ -27,14 +27,14 @@ This exposes a standard interface to talk to processes, sockets, serial ports,
and all manner of things, along with some nifty helpers for common tasks.
For example, remote connections via :mod:`pwnlib.tubes.remote`.
>>> conn = remote('ftp.debian.org',21)
>>> conn = remote('ftp.ubuntu.com',21)
>>> conn.recvline() # doctest: +ELLIPSIS
'220 ...'
>>> conn.send('USER anonymous\r\n')
>>> conn.recvuntil(' ', drop=True)
'331'
b'220 ...'
>>> conn.send(b'USER anonymous\r\n')
>>> conn.recvuntil(b' ', drop=True)
b'331'
>>> conn.recvline()
'Please specify the password.\r\n'
b'Please specify the password.\r\n'
>>> conn.close()
It's also easy to spin up a listener
@@ -42,20 +42,20 @@ It's also easy to spin up a listener
>>> l = listen()
>>> r = remote('localhost', l.lport)
>>> c = l.wait_for_connection()
>>> r.send('hello')
>>> r.send(b'hello')
>>> c.recv()
'hello'
b'hello'
Interacting with processes is easy thanks to :mod:`pwnlib.tubes.process`.
::
>>> sh = process('/bin/sh')
>>> sh.sendline('sleep 3; echo hello world;')
>>> sh.sendline(b'sleep 3; echo hello world;')
>>> sh.recvline(timeout=1)
''
b''
>>> sh.recvline(timeout=5)
'hello world\n'
b'hello world\n'
>>> sh.close()
Not only can you interact with processes programmatically, but you can
@@ -72,16 +72,16 @@ a ``process`` tube.
::
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0')
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
>>> shell['whoami']
'bandit0'
b'bandit0'
>>> shell.download_file('/etc/motd')
>>> sh = shell.run('sh')
>>> sh.sendline('sleep 3; echo hello world;') # doctest: +SKIP
>>> sh.sendline(b'sleep 3; echo hello world;') # doctest: +SKIP
>>> sh.recvline(timeout=1)
''
b''
>>> sh.recvline(timeout=5)
'hello world\n'
b'hello world\n'
>>> shell.close()
Packing Integers
@@ -97,13 +97,13 @@ unpacking codes, and littering your code with helper routines.
>>> import struct
>>> p32(0xdeadbeef) == struct.pack('I', 0xdeadbeef)
True
>>> leet = '37130000'.decode('hex')
>>> u32('abcd') == struct.unpack('I', 'abcd')[0]
>>> leet = unhex('37130000')
>>> u32(b'abcd') == struct.unpack('I', b'abcd')[0]
True
The packing/unpacking operations are defined for many common bit-widths.
>>> u8('A') == 0x41
>>> u8(b'A') == 0x41
True
Setting the Target Architecture and OS
@@ -112,9 +112,9 @@ Setting the Target Architecture and OS
The target architecture can generally be specified as an argument to the routine that requires it.
>>> asm('nop')
'\x90'
b'\x90'
>>> asm('nop', arch='arm')
'\x00\xf0 \xe3'
b'\x00\xf0 \xe3'
However, it can also be set once in the global ``context``. The operating system, word size, and endianness can also be set here.
@@ -126,10 +126,10 @@ However, it can also be set once in the global ``context``. The operating syste
Additionally, you can use a shorthand to set all of the values at once.
>>> asm('nop')
'\x90'
b'\x90'
>>> context(arch='arm', os='linux', endian='big', word_size=32)
>>> asm('nop')
'\xe3 \xf0\x00'
b'\xe3 \xf0\x00'
.. doctest::
:hide:
@@ -158,12 +158,12 @@ Assembly and Disassembly
Never again will you need to run some already-assembled pile of shellcode
from the internet! The :mod:`pwnlib.asm` module is full of awesome.
>>> asm('mov eax, 0').encode('hex')
>>> enhex(asm('mov eax, 0'))
'b800000000'
But if you do, it's easy to suss out!
>>> print disasm('6a0258cd80ebf9'.decode('hex'))
>>> print(disasm(unhex('6a0258cd80ebf9')))
0: 6a 02 push 0x2
2: 58 pop eax
3: cd 80 int 0x80
@@ -176,7 +176,7 @@ loaded with useful time-saving shellcodes.
Let's say that we want to `setreuid(getuid(), getuid())` followed by `dup`ing
file descriptor 4 to `stdin`, `stdout`, and `stderr`, and then pop a shell!
>>> asm(shellcraft.setreuid() + shellcraft.dupsh(4)).encode('hex') # doctest: +ELLIPSIS
>>> enhex(asm(shellcraft.setreuid() + shellcraft.dupsh(4))) # doctest: +ELLIPSIS
'6a3158cd80...'
@@ -188,10 +188,10 @@ Never write another hexdump, thanks to :mod:`pwnlib.util.fiddling`.
Find offsets in your buffer that cause a crash, thanks to :mod:`pwnlib.cyclic`.
>>> print cyclic(20)
>>> print(cyclic(20).decode())
aaaabaaacaaadaaaeaaa
>>> # Assume EIP = 0x62616166 ('faab' which is pack(0x62616166)) at crash time
>>> print cyclic_find('faab')
>>> # Assume EIP = 0x62616166 (b'faab' which is pack(0x62616166)) at crash time
>>> print(cyclic_find(b'faab'))
120
ELF Manipulation
@@ -200,22 +200,22 @@ ELF Manipulation
Stop hard-coding things! Look them up at runtime with :mod:`pwnlib.elf`.
>>> e = ELF('/bin/cat')
>>> print hex(e.address) #doctest: +SKIP
>>> print(hex(e.address)) #doctest: +SKIP
0x400000
>>> print hex(e.symbols['write']) #doctest: +SKIP
>>> print(hex(e.symbols['write'])) #doctest: +SKIP
0x401680
>>> print hex(e.got['write']) #doctest: +SKIP
>>> print(hex(e.got['write'])) #doctest: +SKIP
0x60b070
>>> print hex(e.plt['write']) #doctest: +SKIP
>>> print(hex(e.plt['write'])) #doctest: +SKIP
0x401680
You can even patch and save the files.
>>> e = ELF('/bin/cat')
>>> e.read(e.address+1, 3)
'ELF'
>>> e.read(e.address, 4)
b'\x7fELF'
>>> e.asm(e.address, 'ret')
>>> e.save('/tmp/quiet-cat')
>>> disasm(file('/tmp/quiet-cat','rb').read(1))
>>> disasm(open('/tmp/quiet-cat','rb').read(1))
' 0: c3 ret'
+10
View File
@@ -0,0 +1,10 @@
.. testsetup:: *
from pwn import *
from pwnlib.libcdb import *
:mod:`pwnlib.libcdb` --- Libc Database
===========================================
.. automodule:: pwnlib.libcdb
:members:
+3 -5
View File
@@ -1,11 +1,9 @@
.. testsetup:: *
from pwnlib.memleak import *
from pwn import *
:mod:`pwnlib.memleak` --- Helper class for leaking memory
=========================================================
.. module:: pwnlib.memleak
.. autoclass:: MemLeak
:members:
.. automodule:: pwnlib.memleak
:members:
+15
View File
@@ -0,0 +1,15 @@
:mod:`pwnlib.protocols` --- Wire Protocols
=============================================
.. automodule:: pwnlib.protocols
Supported Protocols
-------------------
.. toctree::
:maxdepth: 3
:glob:
protocols/*
+10
View File
@@ -0,0 +1,10 @@
.. testsetup:: *
from pwn import *
from pwnlib.protocols.adb import AdbClient
:mod:`pwnlib.protocols.adb` --- ADB Protocol Implementation
===========================================================
.. automodule:: pwnlib.protocols.adb
:members:
+10
View File
@@ -0,0 +1,10 @@
.. testsetup:: *
from pwn import *
:mod:`pwnlib.qemu` --- QEMU Utilities
==========================================
.. automodule:: pwnlib.qemu
:members:
+19
View File
@@ -0,0 +1,19 @@
.. testsetup:: *
from pwn import *
context.clear(arch='aarch64')
:mod:`pwnlib.shellcraft.aarch64` --- Shellcode for AArch64
===========================================================
:mod:`pwnlib.shellcraft.aarch64`
--------------------------------
.. automodule:: pwnlib.shellcraft.aarch64
:members:
:mod:`pwnlib.shellcraft.aarch64.linux`
--------------------------------------
.. automodule:: pwnlib.shellcraft.aarch64.linux
:members:
+6
View File
@@ -3,3 +3,9 @@
.. automodule:: pwnlib.term
:members:
Term Modules
-------------------
.. toctree::
term/readline
+1 -1
View File
@@ -27,4 +27,4 @@ Types of Tubes
.. autoclass:: pwnlib.tubes.tube.tube()
:members:
:exclude-members: recv_raw, send_raw, settimeout_raw,
can_recv_raw
can_recv_raw, shutdown_raw, connected_raw,
+9
View File
@@ -0,0 +1,9 @@
.. testsetup:: *
from pwnlib.tubes.buffer import *
:mod:`pwnlib.tubes.buffer` --- buffer implementation for tubes
==============================================================
.. automodule:: pwnlib.tubes.buffer
:members:
+7
View File
@@ -1,6 +1,7 @@
.. testsetup:: *
from pwn import *
from pwnlib.tubes.server import server
:mod:`pwnlib.tubes.sock` --- Sockets
===========================================================
@@ -23,3 +24,9 @@
.. autoclass:: pwnlib.tubes.listen.listen
:members:
:show-inheritance:
.. automodule:: pwnlib.tubes.server
.. autoclass:: pwnlib.tubes.server.server
:members:
:show-inheritance:
+1
View File
@@ -1,5 +1,6 @@
.. testsetup:: *
from pwn import *
from pwnlib.util.cyclic import *
+2 -1
View File
@@ -1,6 +1,7 @@
.. testsetup:: *
from pwnlib.util.fiddling import *
from pwn import *
from pwnlib.util.fiddling import *
:mod:`pwnlib.util.fiddling` --- Utilities bit fiddling
+11
View File
@@ -0,0 +1,11 @@
.. testsetup:: *
from pwnlib.util.getdents import *
from pwnlib.util.fiddling import unhex
:mod:`pwnlib.util.getdents` --- Linux binary directory listing
==============================================================
.. automodule:: pwnlib.util.getdents
:members:
+1
View File
@@ -1,5 +1,6 @@
.. testsetup:: *
from pprint import pprint
from pwnlib.util.misc import *
import os, subprocess
os.chdir("..")
+1
View File
@@ -1,6 +1,7 @@
.. testsetup:: *
from pwnlib.util.proc import *
from pwnlib.tubes.process import process
import os, sys
+1
View File
@@ -1,6 +1,7 @@
.. testsetup:: *
from pwnlib.util.safeeval import *
_get_opcodes = pwnlib.util.safeeval._get_opcodes
:mod:`pwnlib.util.safeeval` --- Safe evaluation of python code
+51
View File
@@ -0,0 +1,51 @@
CFLAGS := -Wno-unused-result -Wno-format-security
TARGETS := printf.mips printf.mips64 printf.mipsel printf.mips64el printf.arm printf.aarch64 \
printf.ppc printf.ppc64 printf.sparc64 printf.native printf.native32
.PHONY: run
run: all
./exploit.py
.PHONY: all
all: $(TARGETS)
.PHONY: clean
clean:
rm -f $(TARGETS)
# mips variants
%.mips: %.c
mips-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
%.mipsel: %.c
mipsel-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
%.mips64: %.c
mips64-linux-gnuabi64-gcc $(CFLAGS) -static -Os -o "$@" $^
%.mips64el: %.c
mips64el-linux-gnuabi64-gcc $(CFLAGS) -static -Os -o "$@" $^
# arm variants
%.arm: %.c
arm-linux-gnueabi-gcc $(CFLAGS) -static -Os -o "$@" $^
%.aarch64: %.c
aarch64-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
# ppc variants
%.ppc: %.c
powerpc-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
%.ppc64: %.c
powerpc64-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
# sparc variants
%.sparc64: %.c
sparc64-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
# native variants
%.native: %.c
gcc $(CFLAGS) -o "$@" $^
%.native32: %.c
i686-linux-gnu-gcc $(CFLAGS) -o "$@" $^
# install deps on ubuntu xenial
.PHONY: install-apt
install-apt:
apt-get install -y make gcc-mips64el-linux-gnuabi64 gcc-sparc64-linux-gnu gcc-powerpc64-linux-gnu gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu gcc-mips64-linux-gnuabi64 gcc-mipsel-linux-gnu gcc-mips64el-linux-gnuabi64 gcc-mips-linux-gnu gcc-i686-linux-gnu gcc
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python2
from pwn import *
@context.quiet
def exec_fmt(payload):
p = context.binary.process()
p.sendline(payload)
return p.recvall()
def exploit(binary):
context.binary = ELF(binary)
autofmt = FmtStr(exec_fmt)
offset = autofmt.offset
with context.binary.process() as p:
addr = unpack(p.recv(context.bytes))
payload = fmtstr_payload(offset, {addr: p32(0x1337babe)})
p.sendline(payload)
p.recvuntil("DONE")
print hex(u32(p.recv(4)))
binaries = [
"printf.mips",
"printf.mips64",
"printf.mipsel",
"printf.mips64el",
"printf.native",
"printf.native32",
"printf.ppc",
"printf.ppc64",
"printf.sparc64",
"printf.arm",
"printf.aarch64",
]
if len(sys.argv) > 1:
binaries = sys.argv[1:]
for binary in binaries:
exploit(binary)
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
#ifdef _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define MEMORY_ADDRESS ((void*)0x11110000)
#define MEMORY_SIZE 1024
#define TARGET ((int *) 0x11110100)
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, "DONE", 4);
write(1, my_var, sizeof(int));
return 0;
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+31
View File
@@ -0,0 +1,31 @@
from pwn import *
context.arch='aarch64'
frame = SigreturnFrame()
registers = ['x%i' % i for i in range(0, 31)]
registers += ['sp', 'pc']
for index, register in enumerate(registers):
setattr(frame, register, index)
assembly = '\n'.join([
shellcraft.read(constants.STDIN_FILENO, 'sp', 1024),
shellcraft.syscall(constants.SYS_rt_sigreturn)
])
binary = ELF.from_assembly(assembly)
io = binary.process()
io.flat(frame)
io.wait()
assert io.poll() == -11
corefile = io.corefile
for index, register in enumerate(registers):
value = getattr(corefile, register)
if index != value:
log.error("%s != %i (%i)" % (register, index, value))
else:
log.success("%s == %i" % (register, value))
+32
View File
@@ -0,0 +1,32 @@
from pwn import *
context.arch='amd64'
frame = SigreturnFrame()
registers = ['rax', 'rbx', 'rcx', 'rdx',
'rdi', 'rsi', 'rbp', 'rsp',
'rip',
'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15']
for index, register in enumerate(registers):
setattr(frame, register, index)
assembly = '\n'.join([
shellcraft.read(constants.STDIN_FILENO, 'rsp', 1024),
shellcraft.sigreturn()
])
binary = ELF.from_assembly(assembly)
io = binary.process()
io.flat(frame)
io.wait()
assert io.poll() == -11
corefile = io.corefile
for index, register in enumerate(registers):
value = getattr(corefile, register)
if index != value:
log.error("%s != %i (%i)" % (register, index, value))
else:
log.success("%s == %i" % (register, value))
+32
View File
@@ -0,0 +1,32 @@
from pwn import *
context.arch='arm'
frame = SigreturnFrame()
registers = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7',
'r8', 'r9', 'r10', 'fp', 'ip', 'sp', 'pc', 'lr']
for index, register in enumerate(registers):
setattr(frame, register, index)
assembly = '\n'.join([
shellcraft.read(constants.STDIN_FILENO, 'sp', 1024),
shellcraft.sigreturn()
])
binary = ELF.from_assembly(assembly)
io = binary.process()
io.flat(frame)
io.wait()
assert io.poll() == -11
corefile = io.corefile
for index, register in enumerate(registers):
value = getattr(corefile, register)
if index != value:
log.error("%s != %i (%i)" % (register, index, value))
else:
log.success("%s == %i" % (register, value))
+31
View File
@@ -0,0 +1,31 @@
from pwn import *
context.kernel='amd64'
frame = SigreturnFrame()
registers = ['eax', 'ebx', 'ecx', 'edx',
'edi', 'esi', 'ebp', 'esp',
'eip']
for index, register in enumerate(registers):
setattr(frame, register, index)
assembly = '\n'.join([
shellcraft.read(constants.STDIN_FILENO, 'esp', 1024),
shellcraft.sigreturn()
])
binary = ELF.from_assembly(assembly)
io = binary.process()
io.flat(frame)
io.wait()
assert io.poll() == -11
corefile = io.corefile
for index, register in enumerate(registers):
value = getattr(corefile, register)
if index != value:
log.error("%s != %i (%i)" % (register, index, value))
else:
log.success("%s == %i" % (register, value))
+1 -1
View File
@@ -4,7 +4,7 @@ Example showing how to use the ssh class.
from pwn import *
shell = ssh(host='bandit.labs.overthewire.org',user='bandit0',password='bandit0')
shell = ssh(host='bandit.labs.overthewire.org',user='bandit0',password='bandit0', port=2220)
# Show basic command syntax
log.info("username: %s" % shell.whoami())
-58
View File
@@ -1,58 +0,0 @@
############################################################
# Dockerfile to build Pwntools container
# Based on Ubuntu
############################################################
FROM ubuntu:trusty
MAINTAINER Maintainer Gallopsled et al.
RUN apt-get update && apt-get install -y software-properties-common
RUN apt-add-repository --yes ppa:pwntools/binutils
RUN apt-get update
RUN apt-get install -y \
binutils \
binutils-aarch64-linux-gnu \
binutils-arm-linux-gnueabihf \
curl \
gdb \
gdbserver \
gdb-multiarch \
git \
libc6-i386 \
libc6-arm64-cross \
libc6-armhf-cross \
libc6-dev-i386 \
libffi-dev \
libglib2.0-dev \
libncurses5-dev \
libncursesw5-dev \
ltrace \
python-dev \
python-pip \
python3-pip \
python2.7 \
qemu \
qemu-user-static \
strace \
tmux \
wget
RUN pip install --upgrade ipython
RUN useradd -m zerocool
RUN usermod -U zerocool
RUN mkdir -p /etc/qemu-binfmt
RUN ln -s /usr/aarch64-linux-gnu /etc/qemu-binfmt/aarch64
RUN ln -s /usr/arm-linux-gnueabihf /etc/qemu-binfmt/arm
RUN pip install --upgrade pip pycparser psutil python-ptrace
RUN pip3 install --upgrade pip pycparser psutil python-ptrace
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools.git
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
RUN chown -R zerocool.zerocool /home/zerocool
RUN chsh -s /bin/bash zerocool
+13
View File
@@ -0,0 +1,13 @@
subdirs=xenial stable $(wildcard */)
makefiles=$(wildcard */Makefile)
tags=base stable beta dev
all: $(makefiles) $(subdirs)
$(subdirs):
docker build -t pwntools/pwntools:$(shell basename $(@)) "$@"
$(makefiles):
make -C $(shell dirname $@)
.PHONY: all $(subdirs) $(makefiles)
+1
View File
@@ -0,0 +1 @@
xenial
+6
View File
@@ -0,0 +1,6 @@
FROM pwntools/pwntools:stable
USER root
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools@beta
RUN PWNLIB_NOTERM=1 pwn update
USER pwntools
+6
View File
@@ -0,0 +1,6 @@
FROM pwntools/pwntools:stable
USER root
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools@dev
RUN PWNLIB_NOTERM=1 pwn update
USER pwntools
+26
View File
@@ -0,0 +1,26 @@
############################################################
# Dockerfile to build Pwntools container
# Based on Ubuntu
############################################################
FROM kalilinux/kali-linux-docker
MAINTAINER Maintainer Gallopsled et al.
RUN apt-get update \
&& apt-get install -y \
build-essential \
git \
libssl-dev \
libffi-dev \
python2.7 \
python-pip \
python-dev \
&& pip install --upgrade pip \
&& python -m pip install --upgrade pwntools \
&& PWNLIB_NOTERM=1 pwn update \
&& apt-get install -y sudo \
&& useradd -m pwntools \
&& passwd --delete --unlock pwntools \
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+8
View File
@@ -0,0 +1,8 @@
all: Dockerfile
Dockerfile: ../xenial/Dockerfile FORCE
sed "s|ubuntu:xenial|kalilinux/kali-linux-docker|" < "$<" > "$@"
FORCE:
.PHONY: all
+26
View File
@@ -0,0 +1,26 @@
############################################################
# Dockerfile to build Pwntools container
# Based on Ubuntu
############################################################
FROM ubuntu:precise
MAINTAINER Maintainer Gallopsled et al.
RUN apt-get update \
&& apt-get install -y \
build-essential \
git \
libssl-dev \
libffi-dev \
python2.7 \
python-pip \
python-dev \
&& pip install --upgrade pip \
&& python -m pip install --upgrade pwntools \
&& PWNLIB_NOTERM=1 pwn update \
&& apt-get install -y sudo \
&& useradd -m pwntools \
&& passwd --delete --unlock pwntools \
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+8
View File
@@ -0,0 +1,8 @@
all: Dockerfile
Dockerfile: ../xenial/Dockerfile FORCE
sed "s|ubuntu:xenial|ubuntu:precise|" < "$<" > "$@"
FORCE:
.PHONY: all
+6
View File
@@ -0,0 +1,6 @@
FROM pwntools/pwntools:base
USER root
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools@stable
RUN PWNLIB_NOTERM=1 pwn update
USER pwntools
+26
View File
@@ -0,0 +1,26 @@
############################################################
# Dockerfile to build Pwntools container
# Based on Ubuntu
############################################################
FROM ubuntu:trusty
MAINTAINER Maintainer Gallopsled et al.
RUN apt-get update \
&& apt-get install -y \
build-essential \
git \
libssl-dev \
libffi-dev \
python2.7 \
python-pip \
python-dev \
&& pip install --upgrade pip \
&& python -m pip install --upgrade pwntools \
&& PWNLIB_NOTERM=1 pwn update \
&& apt-get install -y sudo \
&& useradd -m pwntools \
&& passwd --delete --unlock pwntools \
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+8
View File
@@ -0,0 +1,8 @@
all: Dockerfile
Dockerfile: ../xenial/Dockerfile FORCE
sed "s|ubuntu:xenial|ubuntu:trusty|" < "$<" > "$@"
FORCE:
.PHONY: all
+26
View File
@@ -0,0 +1,26 @@
############################################################
# Dockerfile to build Pwntools container
# Based on Ubuntu
############################################################
FROM ubuntu:xenial
MAINTAINER Maintainer Gallopsled et al.
RUN apt-get update \
&& apt-get install -y \
build-essential \
git \
libssl-dev \
libffi-dev \
python2.7 \
python-pip \
python-dev \
&& pip install --upgrade pip \
&& python -m pip install --upgrade pwntools \
&& PWNLIB_NOTERM=1 pwn update \
&& apt-get install -y sudo \
&& useradd -m pwntools \
&& passwd --delete --unlock pwntools \
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+4 -1
View File
@@ -1,8 +1,11 @@
# Promote useful stuff to toplevel
from .toplevel import *
from __future__ import absolute_import
from pwn.toplevel import *
pwnlib.args.initialize()
pwnlib.log.install_default_handler()
pwnlib.config.initialize()
log = pwnlib.log.getLogger('pwnlib.exploit')
args = pwnlib.args.args
+11 -15
View File
@@ -21,18 +21,18 @@ import pwnlib
from pwnlib import *
from pwnlib.asm import *
from pwnlib.context import Thread
from pwnlib.context import context
from pwnlib.context import context, LocalContext
from pwnlib.dynelf import DynELF
from pwnlib.encoders import *
from pwnlib.elf import Core
from pwnlib.elf import ELF
from pwnlib.elf import load
from pwnlib.elf.corefile import Core, Corefile, Coredump
from pwnlib.elf.elf import ELF, load
from pwnlib.encoders import *
from pwnlib.exception import PwnlibException
from pwnlib.gdb import attach, debug, debug_assembly, debug_shellcode
from pwnlib.flag import *
from pwnlib.fmtstr import FmtStr, fmtstr_payload
from pwnlib.log import getLogger
from pwnlib.memleak import MemLeak
from pwnlib.memleak import MemLeak, RelativeMemLeak
from pwnlib.regsort import *
from pwnlib.replacements import *
from pwnlib.rop import ROP
@@ -40,9 +40,10 @@ from pwnlib.rop.srop import SigreturnFrame
from pwnlib.runner import *
from pwnlib.timeout import Timeout
from pwnlib.tubes.listen import listen
from pwnlib.tubes.process import process
from pwnlib.tubes.process import process, PTY, PIPE, STDOUT
from pwnlib.tubes.remote import remote, tcp, udp, connect
from pwnlib.tubes.serialtube import serialtube
from pwnlib.tubes.server import server
from pwnlib.tubes.ssh import ssh
from pwnlib.tubes.tube import tube
from pwnlib.ui import *
@@ -66,15 +67,8 @@ from pwnlib.util.web import *
# Promote these modules, so that "from pwn import *" will let you access them
try:
import cPickle as pickle
except ImportError:
import pickle
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from six.moves import cPickle as pickle, cStringIO as StringIO
from six import BytesIO
error = log.error
warning = log.warning
@@ -82,3 +76,5 @@ warn = log.warning
info = log.info
debug = log.debug
success = log.success
__all__ = [x for x in globals().keys() if x != '__name__']
+4 -1
View File
@@ -1,6 +1,8 @@
from __future__ import absolute_import
import importlib
from .version import __version__
from pwnlib.version import __version__
version = __version__
@@ -12,6 +14,7 @@ __all__ = [
'commandline',
'constants',
'context',
'data',
'dynelf',
'encoders',
'elf',
+103 -25
View File
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
from .context import LocalContext
from .context import context
from __future__ import absolute_import
from __future__ import division
from pwnlib.context import LocalContext
from pwnlib.context import context
class ABI(object):
@@ -24,7 +27,8 @@ class ABI(object):
#: Indicates that this ABI returns to the next address on the slot
returns = True
def __init__(self, regs, align, minimum):
def __init__(self, stack, regs, align, minimum):
self.stack = stack
self.register_arguments = regs
self.arg_alignment = align
self.stack_minimum = minimum
@@ -32,12 +36,26 @@ class ABI(object):
@staticmethod
@LocalContext
def default():
if context.os == 'android':
context.os = 'linux'
return {
(32, 'i386', 'linux'): linux_i386,
(64, 'aarch64', 'linux'): linux_aarch64,
(64, 'amd64', 'linux'): linux_amd64,
(32, 'arm', 'linux'): linux_arm,
(32, 'thumb', 'linux'): linux_arm,
(32, 'mips', 'linux'): linux_mips,
(32, 'powerpc', 'linux'): linux_ppc,
(64, 'powerpc', 'linux'): linux_ppc64,
(32, 'i386', 'freebsd'): freebsd_i386,
(64, 'aarch64', 'freebsd'): freebsd_aarch64,
(64, 'amd64', 'freebsd'): freebsd_amd64,
(32, 'arm', 'freebsd'): freebsd_arm,
(32, 'thumb', 'freebsd'): freebsd_arm,
(32, 'mips', 'freebsd'): freebsd_mips,
(32, 'powerpc', 'freebsd'): freebsd_ppc,
(64, 'powerpc', 'freebsd'): freebsd_ppc64,
(32, 'i386', 'windows'): windows_i386,
(64, 'amd64', 'windows'): windows_amd64,
}[(context.bits, context.arch, context.os)]
@@ -45,22 +63,47 @@ class ABI(object):
@staticmethod
@LocalContext
def syscall():
if context.os == 'android':
context.os = 'linux'
return {
(32, 'i386', 'linux'): linux_i386_syscall,
(64, 'amd64', 'linux'): linux_amd64_syscall,
(64, 'aarch64', 'linux'): linux_aarch64_syscall,
(32, 'arm', 'linux'): linux_arm_syscall,
(32, 'thumb', 'linux'): linux_arm_syscall,
(32, 'mips', 'linux'): linux_mips_syscall,
(64, 'aarch64', 'linux'): linux_aarch64_syscall,
(32, 'powerpc', 'linux'): linux_ppc_syscall,
(64, 'powerpc', 'linux'): linux_ppc64_syscall,
(32, 'i386', 'freebsd'): freebsd_i386_syscall,
(64, 'amd64', 'freebsd'): freebsd_amd64_syscall,
(64, 'aarch64', 'freebsd'): freebsd_aarch64_syscall,
(32, 'arm', 'freebsd'): freebsd_arm_syscall,
(32, 'thumb', 'freebsd'): freebsd_arm_syscall,
(32, 'mips', 'freebsd'): freebsd_mips_syscall,
(64, 'aarch64', 'freebsd'): freebsd_aarch64_syscall,
(32, 'powerpc', 'freebsd'): freebsd_ppc_syscall,
(64, 'powerpc', 'freebsd'): freebsd_ppc64_syscall,
}[(context.bits, context.arch, context.os)]
@staticmethod
@LocalContext
def sigreturn():
if context.os == 'android':
context.os = 'linux'
return {
(32, 'i386', 'linux'): linux_i386_sigreturn,
(64, 'amd64', 'linux'): linux_amd64_sigreturn,
(32, 'arm', 'linux'): linux_arm_sigreturn,
(32, 'thumb', 'linux'): linux_arm_sigreturn,
(64, 'aarch64', 'linux'): linux_aarch64_sigreturn,
(32, 'i386', 'freebsd'): freebsd_i386_sigreturn,
(64, 'amd64', 'freebsd'): freebsd_amd64_sigreturn,
(32, 'arm', 'freebsd'): freebsd_arm_sigreturn,
(32, 'thumb', 'freebsd'): freebsd_arm_sigreturn,
(64, 'aarch64', 'freebsd'): freebsd_aarch64_sigreturn,
}[(context.bits, context.arch, context.os)]
class SyscallABI(ABI):
@@ -68,9 +111,9 @@ class SyscallABI(ABI):
The syscall ABI treats the syscall number as the zeroth argument,
which must be loaded into the specified register.
"""
def __init__(self, register_arguments, *a, **kw):
super(SyscallABI, self).__init__(register_arguments, *a, **kw)
self.syscall_register = register_arguments[0]
def __init__(self, *a, **kw):
super(SyscallABI, self).__init__(*a, **kw)
self.syscall_register = self.register_arguments[0]
class SigreturnABI(SyscallABI):
"""
@@ -81,26 +124,61 @@ class SigreturnABI(SyscallABI):
returns = False
linux_i386 = ABI([], 4, 0)
linux_amd64 = ABI(['rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
linux_arm = ABI(['r0', 'r1', 'r2', 'r3'], 8, 0)
linux_aarch64 = ABI(['x0', 'x1', 'x2', 'x3'], 16, 0)
linux_mips = ABI(['$a0','$a1','$a2','$a3'], 4, 0)
# System V ABI used by many UNIXes
linux_i386 = ABI('esp', [], 4, 0)
linux_amd64 = ABI('rsp', ['rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
linux_arm = ABI('sp', ['r0', 'r1', 'r2', 'r3'], 8, 0)
linux_aarch64 = ABI('sp', ['x0', 'x1', 'x2', 'x3'], 16, 0)
linux_mips = ABI('$sp', ['$a0','$a1','$a2','$a3'], 4, 0)
linux_ppc = ABI('sp', ['r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 4, 0)
linux_ppc64 = ABI('sp', ['r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 8, 0)
linux_i386_syscall = SyscallABI(['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp'], 4, 0)
linux_amd64_syscall = SyscallABI(['rax','rdi', 'rsi', 'rdx', 'r10', 'r8', 'r9'], 8, 0)
linux_arm_syscall = SyscallABI(['r7', 'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6'], 4, 0)
linux_aarch64_syscall = SyscallABI(['x8', 'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6'], 16, 0)
linux_mips_syscall = ABI(['$v0', '$a0','$a1','$a2','$a3'], 4, 0)
sysv_i386 = linux_i386
sysv_amd64 = linux_amd64
sysv_arm = linux_arm
sysv_aarch64 = linux_aarch64
sysv_mips = linux_mips
sysv_ppc = linux_ppc
sysv_ppc64 = linux_ppc64
linux_i386_sigreturn = SigreturnABI(['eax'], 4, 0)
linux_amd64_sigreturn = SigreturnABI(['rax'], 4, 0)
linux_arm_sigreturn = SigreturnABI(['r7'], 4, 0)
linux_i386_syscall = SyscallABI('esp', ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp'], 4, 0)
linux_amd64_syscall = SyscallABI('rsp', ['rax', 'rdi', 'rsi', 'rdx', 'r10', 'r8', 'r9'], 8, 0)
linux_arm_syscall = SyscallABI('sp', ['r7', 'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6'], 4, 0)
linux_aarch64_syscall = SyscallABI('sp', ['x8', 'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6'], 16, 0)
linux_mips_syscall = SyscallABI('$sp', ['$v0','$a0','$a1','$a2','$a3'], 4, 0)
linux_ppc_syscall = ABI('sp', ['r0', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9'], 4, 0)
linux_ppc64_syscall = ABI('sp', ['r0', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9'], 8, 0)
windows_i386 = ABI([], 4, 0)
windows_amd64 = ABI(['rcx','rdx','r8','r9'], 32, 32)
linux_i386_sigreturn = SigreturnABI('esp', ['eax'], 4, 0)
linux_amd64_sigreturn = SigreturnABI('rsp', ['rax'], 4, 0)
linux_arm_sigreturn = SigreturnABI('sp', ['r7'], 4, 0)
linux_aarch64_sigreturn = SigreturnABI('sp', ['x8'], 16, 0)
# Fake ABIs used by SROP
linux_i386_srop = ABI(['eax'], 4, 0)
linux_amd64_srop = ABI(['rax'], 4, 0)
linux_arm_srop = ABI(['r7'], 4, 0)
sysv_i386_sigreturn = linux_i386_sigreturn
sysv_amd64_sigreturn = linux_amd64_sigreturn
sysv_arm_sigreturn = linux_arm_sigreturn
sysv_aarch64_sigreturn = linux_aarch64_sigreturn
freebsd_i386 = sysv_i386
freebsd_amd64 = sysv_amd64
freebsd_arm = sysv_arm
freebsd_aarch64 = sysv_aarch64
freebsd_mips = sysv_mips
freebsd_ppc = sysv_ppc
freebsd_ppc64 = sysv_ppc64
freebsd_i386_syscall = SyscallABI('esp', ['eax'], 4, 0)
freebsd_amd64_syscall = SyscallABI('rsp', ['rax','rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
freebsd_arm_syscall = SyscallABI('sp', ['r7', 'r0', 'r1', 'r2', 'r3'], 8, 0)
freebsd_aarch64_syscall = SyscallABI('sp', ['x8', 'x0', 'x1', 'x2', 'x3'], 16, 0)
freebsd_mips_syscall = SyscallABI('$sp', ['$v0','$a0','$a1','$a2','$a3'], 4, 0)
freebsd_ppc_syscall = SyscallABI('sp', ['r0', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 4, 0)
freebsd_ppc64_syscall = SyscallABI('sp', ['r0', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 8, 0)
freebsd_i386_sigreturn = sysv_i386_sigreturn
freebsd_amd64_sigreturn = sysv_amd64_sigreturn
freebsd_arm_sigreturn = sysv_arm_sigreturn
freebsd_aarch64_sigreturn = sysv_aarch64_sigreturn
windows_i386 = ABI('esp', [], 4, 0)
windows_amd64 = ABI('rsp', ['rcx','rdx','r8','r9'], 32, 32)
+6 -2
View File
@@ -1,2 +1,6 @@
from .adb import *
from .protocol import Client
from __future__ import absolute_import
from pwnlib.adb.adb import *
from pwnlib.adb.protocol import Client
from pwnlib.adb.bootimg import BootImage
from pwnlib.adb.bootloader import BootloaderImage
+305 -94
View File
@@ -1,6 +1,7 @@
"""Provides utilities for interacting with Android devices via the Android Debug Bridge.
# Using Android Devices with Pwntools
Using Android Devices with Pwntools
-----------------------------------
Pwntools tries to be as easy as possible to use with Android devices.
@@ -29,42 +30,45 @@ instance.
error("Could not find any shamus!")
Once a device is selected, you can operate on it with any of the functions in
the ``pwnlib.adb`` module.
the :mod:`pwnlib.adb` module.
.. code-block:: python
# Get a process listing
print adb.process(['ps']).recvall()
print(adb.process(['ps']).recvall())
# Fetch properties
print adb.properties.ro.build.fingerprint
print(adb.properties.ro.build.fingerprint)
# Read and write files
print adb.read('/proc/version')
print(adb.read('/proc/version'))
adb.write('/data/local/tmp/foo', 'my data')
"""
from __future__ import absolute_import
from __future__ import division
import functools
import glob
import logging
import os
import platform
import re
import shutil
import six
import stat
import tempfile
import time
import dateutil.parser
from .. import atexit
from .. import tubes
from ..context import LocalContext
from ..context import context
from ..device import Device
from ..log import getLogger
from ..util import misc
from .protocol import Client
from pwnlib import atexit
from pwnlib import tubes
from pwnlib.context import LocalContext
from pwnlib.context import context
from pwnlib.device import Device
from pwnlib.log import getLogger
from pwnlib.protocols.adb import AdbClient
from pwnlib.util import misc
log = getLogger(__name__)
@@ -72,9 +76,9 @@ def adb(argv, *a, **kw):
r"""Returns the output of an ADB subcommand.
>>> adb.adb(['get-serialno'])
'emulator-5554\n'
b'emulator-5554\n'
"""
if isinstance(argv, (str, unicode)):
if isinstance(argv, (bytes, six.text_type)):
argv = [argv]
log.debug("$ " + ' '.join(context.adb + argv))
@@ -85,10 +89,10 @@ def adb(argv, *a, **kw):
return tubes.process.process(context.adb + argv, *a, **kw).recvall()
@context.quiet
@context.quietfunc
def devices(serial=None):
"""Returns a list of ``Device`` objects corresponding to the connected devices."""
with Client() as c:
with AdbClient() as c:
lines = c.devices(long=True)
result = []
@@ -143,7 +147,7 @@ def root():
log.info("Enabling root on %s" % context.device)
with context.quiet:
with Client() as c:
with AdbClient() as c:
reply = c.root()
if 'already running as root' in reply:
@@ -172,7 +176,7 @@ def reboot(wait=True):
"""
log.info('Rebooting device %s' % context.device)
with Client() as c:
with AdbClient() as c:
c.reboot()
if wait:
@@ -185,7 +189,7 @@ def reboot_bootloader():
"""
log.info('Rebooting %s to bootloader' % context.device)
with Client() as c:
with AdbClient() as c:
c.reboot_bootloader()
@with_device
@@ -325,7 +329,7 @@ class AdbDevice(Device):
kwargs['port'] = 'emulator'
for field in fields[2:]:
k,v = field.split(':')
k,v = field.split(':', 1)
kwargs[k] = v
return AdbDevice(serial, type, **kwargs)
@@ -343,7 +347,7 @@ class AdbDevice(Device):
of this device.
>>> property = 'ro.build.fingerprint'
>>> device = adb.current_device()
>>> device = adb.wait_for_device()
>>> adb.getprop(property) == device.getprop(property)
True
"""
@@ -352,7 +356,6 @@ class AdbDevice(Device):
if name not in g:
raise AttributeError('%r object has no attribute %r' % (type(self).__name__,name))
value = g[name]
if not hasattr(value, '__call__'):
@@ -376,7 +379,7 @@ def wait_for_device(kick=False):
>>> device = adb.wait_for_device()
"""
with log.waitfor("Waiting for device to come online") as w:
with Client() as c:
with AdbClient() as c:
if kick:
try:
c.reconnect()
@@ -387,7 +390,7 @@ def wait_for_device(kick=False):
if context.device:
serial = str(context.device)
with Client() as c:
with AdbClient() as c:
c.wait_for_device(serial)
for device in devices():
@@ -412,10 +415,10 @@ def wait_for_device(kick=False):
@with_device
def disable_verity():
"""Disables dm-verity on the device."""
with log.waitfor("Disabling dm-verity on %s" % context.device) as w:
with log.waitfor("Disabling dm-verity on %s" % context.device):
root()
with Client() as c:
with AdbClient() as c:
reply = c.disable_verity()
if 'Verity already disabled' in reply:
@@ -430,11 +433,11 @@ def disable_verity():
@with_device
def remount():
"""Remounts the filesystem as writable."""
with log.waitfor("Remounting filesystem on %s" % context.device) as w:
with log.waitfor("Remounting filesystem on %s" % context.device):
disable_verity()
root()
with Client() as c:
with AdbClient() as c:
reply = c.remount()
if 'remount succeeded' not in reply:
@@ -445,7 +448,7 @@ def unroot():
"""Restarts adbd as AID_SHELL."""
log.info("Unrooting %s" % context.device)
with context.quiet:
with Client() as c:
with AdbClient() as c:
reply = c.unroot()
if '0006closed' == reply:
@@ -483,7 +486,7 @@ def pull(remote_path, local_path=None):
Example:
>>> _=adb.pull('/proc/version', './proc-version')
>>> print read('./proc-version') # doctest: +ELLIPSIS
>>> print(read('./proc-version').decode('utf-8')) # doctest: +ELLIPSIS
Linux version ...
"""
if local_path is None:
@@ -508,12 +511,16 @@ def push(local_path, remote_path):
local_path(str): Path to the local file to push.
remote_path(str): Path or directory to store the file on the device.
Returns:
Remote path of the file.
Example:
>>> write('./filename', 'contents')
>>> _=adb.push('./filename', '/data/local/tmp')
>>> adb.push('./filename', '/data/local/tmp')
'/data/local/tmp/filename'
>>> adb.read('/data/local/tmp/filename')
'contents'
b'contents'
>>> adb.push('./filename', '/does/not/exist')
Traceback (most recent call last):
...
@@ -526,7 +533,7 @@ def push(local_path, remote_path):
msg += ' (%s)' % context.device
with log.waitfor(msg) as w:
with Client() as c:
with AdbClient() as c:
# We need to discover whether remote_path is a directory or not.
# If we cannot stat the full path, assume it's a path-plus-filename,
@@ -546,10 +553,13 @@ def push(local_path, remote_path):
if stat.S_ISDIR(mode):
remote_path = os.path.join(remote_path, remote_filename)
return c.write(remote_path,
misc.read(local_path),
callback=_create_adb_push_pull_callback(w))
@context.quiet
c.write(remote_path,
misc.read(local_path),
callback=_create_adb_push_pull_callback(w))
return remote_path
@context.quietfunc
@with_device
def read(path, target=None, callback=None):
"""Download a file from the device, and extract its contents.
@@ -559,18 +569,18 @@ def read(path, target=None, callback=None):
target(str): Optional, location to store the file.
Uses a temporary file by default.
callback(callable): See the documentation for
``adb.protocol.Client.read``.
``adb.protocol.AdbClient.read``.
Examples:
>>> print adb.read('/proc/version') # doctest: +ELLIPSIS
>>> print(adb.read('/proc/version').decode('utf-8')) # doctest: +ELLIPSIS
Linux version ...
>>> adb.read('/does/not/exist')
Traceback (most recent call last):
...
PwnlibException: Could not stat '/does/not/exist'
"""
with Client() as c:
with AdbClient() as c:
stat = c.stat(path)
if not stat:
log.error('Could not stat %r' % path)
@@ -581,9 +591,9 @@ def read(path, target=None, callback=None):
return data
@context.quiet
@context.quietfunc
@with_device
def write(path, data=''):
def write(path, data=b''):
"""Create a file on the device with the provided contents.
Arguments:
@@ -592,29 +602,173 @@ def write(path, data=''):
Examples:
>>> adb.write('/dev/null', 'data')
>>> adb.write('/dev/null', b'data')
>>> adb.write('/data/local/tmp/')
"""
with tempfile.NamedTemporaryFile() as temp:
misc.write(temp.name, data)
push(temp.name, path)
@context.quietfunc
@with_device
def mkdir(path):
"""Create a directory on the target device.
Note:
Silently succeeds if the directory already exists.
Arguments:
path(str): Directory to create.
Examples:
>>> adb.mkdir('/')
>>> path = '/data/local/tmp/mkdir_test'
>>> adb.exists(path)
False
>>> adb.mkdir(path)
>>> adb.exists(path)
True
>>> adb.mkdir('/init')
Traceback (most recent call last):
...
PwnlibException: mkdir failed for /init, File exists
"""
if not path.startswith('/'):
log.error("Must provide an absolute path: %r" % path)
with AdbClient() as c:
st = c.stat(path)
# Don't re-create existing directories
if st and stat.S_ISDIR(st['mode']):
return
result = process(['mkdir', path]).recvall()
# Any output at all is an error
if result:
log.error(result.rstrip().decode('utf-8'))
@context.quietfunc
@with_device
def makedirs(path):
"""Create a directory and all parent directories on the target device.
Note:
Silently succeeds if the directory already exists.
Examples:
>>> adb.makedirs('/data/local/tmp/this/is/a/directory/heirarchy')
>>> adb.listdir('/data/local/tmp/this/is/a/directory')
['heirarchy']
"""
if path != '/':
makedirs(os.path.dirname(path))
mkdir(path)
@context.quietfunc
@with_device
def exists(path):
"""Return :const:`True` if ``path`` exists on the target device.
Examples:
>>> adb.exists('/')
True
>>> adb.exists('/init')
True
>>> adb.exists('/does/not/exist')
False
"""
with AdbClient() as c:
return bool(c.stat(path))
@context.quietfunc
@with_device
def isdir(path):
"""Return :const:`True` if ``path`` is a on the target device.
Examples:
>>> adb.isdir('/')
True
>>> adb.isdir('/init')
False
>>> adb.isdir('/does/not/exist')
False
"""
with AdbClient() as c:
st = c.stat(path)
return bool(st and stat.S_ISDIR(st['mode']))
@context.quietfunc
@with_device
def unlink(path, recursive=False):
"""Unlinks a file or directory on the target device.
Examples:
>>> adb.unlink("/does/not/exist")
Traceback (most recent call last):
...
PwnlibException: Could not unlink '/does/not/exist': Does not exist
>>> filename = '/data/local/tmp/unlink-test'
>>> adb.write(filename, 'hello')
>>> adb.exists(filename)
True
>>> adb.unlink(filename)
>>> adb.exists(filename)
False
>>> adb.mkdir(filename)
>>> adb.write(filename + '/contents', 'hello')
>>> adb.unlink(filename)
Traceback (most recent call last):
...
PwnlibException: Cannot delete non-empty directory '/data/local/tmp/unlink-test' without recursive=True
>>> adb.unlink(filename, recursive=True)
>>> adb.exists(filename)
False
"""
with AdbClient() as c:
st = c.stat(path)
if not st:
log.error("Could not unlink %r: Does not exist" % path)
# If the directory is not empty, do not delete it
if isdir(path) and c.list(path) and not recursive:
log.error("Cannot delete non-empty directory %r without recursive=True" % path)
flags = '-rf' if recursive else '-f'
output = c.execute(['rm', flags, path]).recvall()
if output:
log.error(output.decode('utf-8'))
@with_device
def process(argv, *a, **kw):
"""Execute a process on the device.
See ``pwnlib.tubes.process.process`` documentation for more info.
See :class:`pwnlib.tubes.process.process` documentation for more info.
Returns:
A ``process`` tube.
A :class:`pwnlib.tubes.process.process` tube.
Examples:
>>> adb.root()
>>> print adb.process(['cat','/proc/version']).recvall() # doctest: +ELLIPSIS
>>> print(adb.process(['cat','/proc/version']).recvall().decode('utf-8')) # doctest: +ELLIPSIS
Linux version ...
"""
if isinstance(argv, (str, unicode)):
if isinstance(argv, (bytes, six.text_type)):
argv = [argv]
message = "Starting %s process %r" % ('Android', argv[0])
@@ -623,7 +777,7 @@ def process(argv, *a, **kw):
if argv != [argv[0]]: message += ' argv=%r ' % argv
with log.progress(message) as p:
return Client().execute(argv)
return AdbClient().execute(argv)
@with_device
def interactive(**kw):
@@ -636,27 +790,62 @@ def shell(**kw):
return process(['sh', '-i'], **kw)
@with_device
def which(name):
"""Retrieves the full path to a binary in ``PATH`` on the device
def which(name, all = False, *a, **kw):
"""Retrieves the full path to a binary in ``$PATH`` on the device
>>> adb.which('sh')
'/system/bin/sh'
Arguments:
name(str): Binary name
all(bool): Whether to return all paths, or just the first
*a: Additional arguments for :func:`.adb.process`
**kw: Additional arguments for :func:`.adb.process`
Returns:
Either a path, or list of paths
Example:
>>> adb.which('sh')
'/system/bin/sh'
>>> adb.which('sh', all=True)
['/system/bin/sh']
>>> adb.which('foobar') is None
True
>>> adb.which('foobar', all=True)
[]
"""
# Unfortunately, there is no native 'which' on many phones.
which_cmd = '''
IFS=:
BINARY=%s
P=($PATH)
for path in "${P[@]}"; do \
if [ -e "$path/$BINARY" ]; then \
echo "$path/$BINARY";
break
fi
echo $PATH | while read -d: directory; do
[ -x "$directory/{name}" ] || continue;
echo -n "$directory/{name}\\x00";
done
''' % name
[ -x "{name}" ] && echo -n "$PWD/{name}\\x00"
'''.format(name=name)
which_cmd = which_cmd.strip()
return process(['sh','-c',which_cmd]).recvall().strip()
data = process(['sh','-c', which_cmd], *a, **kw).recvall()
if not hasattr(data, 'encode'):
data = data.decode('utf-8')
result = []
for path in data.split('\x00'):
# Skip empty entries
if not path:
continue
# Return the first entry if all=False
if not all:
return path
# Accumulate all entries if all=True
result.append(path)
if all:
return result
return None
@with_device
def whoami():
@@ -666,10 +855,10 @@ def whoami():
def forward(port):
"""Sets up a port to forward to the device."""
tcp_port = 'tcp:%s' % port
start_forwarding = adb(['forward', tcp_port, tcp_port])
adb(['forward', tcp_port, tcp_port])
atexit.register(lambda: adb(['forward', '--remove', tcp_port]))
@context.quiet
@context.quietfunc
@with_device
def logcat(stream=False):
"""Reads the system log file.
@@ -677,12 +866,12 @@ def logcat(stream=False):
By default, causes logcat to exit after reading the file.
Arguments:
stream(bool): If ``True``, the contents are streamed rather than
read in a one-shot manner. Default is ``False``.
stream(bool): If :const:`True`, the contents are streamed rather than
read in a one-shot manner. Default is :const:`False`.
Returns:
If ``stream`` is ``False``, returns a string containing the log data.
Otherwise, it returns a ``tube`` connected to the log output.
If ``stream`` is :const:`False`, returns a string containing the log data.
Otherwise, it returns a :class:`pwnlib.tubes.tube.tube` connected to the log output.
"""
if stream:
@@ -694,9 +883,16 @@ def logcat(stream=False):
def pidof(name):
"""Returns a list of PIDs for the named process."""
with context.quiet:
io = process(['pidof', name])
data = io.recvall().split()
return list(map(int, data))
# Older devices have a broken 'pidof', apparently.
# Try pgrep first.
io = process(['pgrep', name])
data = io.recvall()
if 'not found' in data:
io = process(['pidof', name])
data = io.recvall()
return list(map(int, data.split()))
@with_device
def proc_exe(pid):
@@ -719,11 +915,17 @@ def getprop(name=None):
"""
with context.quiet:
if name:
return process(['getprop', name]).recvall().strip()
result = process(['getprop', name]).recvall().strip()
if not hasattr(result, 'encode'):
result = result.decode('utf-8')
return result
result = process(['getprop']).recvall()
if not hasattr(result, 'encode'):
result = result.decode('utf-8')
expr = r'\[([^\]]+)\]: \[(.*)\]'
props = {}
@@ -758,18 +960,17 @@ def listdir(directory='/'):
Otherwise, less files may be returned due to restrictive SELinux
policies on adbd.
"""
return list(sorted(Client().list(directory)))
return list(sorted(AdbClient().list(directory)))
@with_device
def fastboot(args, *a, **kw):
"""Executes a fastboot command.
Returns:
The command output.
"""
serial = context.device
if not serial:
log.error("Unknown device")
return tubes.process.process(['fastboot', '-s', serial] + list(args), **kw).recvall()
argv = ['fastboot', '-s', str(context.device)] + list(args)
return tubes.process.process(argv, *a, **kw).recvall()
@with_device
def fingerprint():
@@ -794,7 +995,7 @@ def unlock_bootloader():
Note:
This requires physical interaction with the device.
"""
Client().reboot_bootloader()
AdbClient().reboot_bootloader()
fastboot(['oem', 'unlock'])
fastboot(['continue'])
@@ -806,7 +1007,7 @@ class Kernel(object):
return self.symbols['_text']
@property
@context.quiet
@context.quietfunc
def symbols(self):
"""Returns a dictionary of kernel symbols"""
result = {}
@@ -818,7 +1019,7 @@ class Kernel(object):
return result
@property
@context.quiet
@context.quietfunc
def kallsyms(self):
"""Returns the raw output of kallsyms"""
if not self._kallsyms:
@@ -829,20 +1030,20 @@ class Kernel(object):
return self._kallsyms
@property
@context.quiet
@context.quietfunc
def version(self):
"""Returns the kernel version of the device."""
root()
return read('/proc/version').strip()
@property
@context.quiet
@context.quietfunc
def cmdline(self):
root()
return read('/proc/cmdline').strip()
@property
@context.quiet
@context.quietfunc
def lastmsg(self):
root()
if 'last_kmsg' in listdir('/proc'):
@@ -864,7 +1065,7 @@ class Kernel(object):
'Nexus 7': 'oem uart-on',
}
with log.waitfor('Enabling kernel UART') as w:
with log.waitfor('Enabling kernel UART'):
if model not in known_commands:
log.error("Device UART is unsupported.")
@@ -904,7 +1105,7 @@ class Property(object):
self.__dict__['_name'] = name
def __str__(self):
return getprop(self._name).strip()
return str(getprop(self._name)).strip()
def __repr__(self):
return repr(str(self))
@@ -1012,14 +1213,24 @@ def compile(source):
if not project:
# Realistically this should inherit from context.arch, but
# this works for now.
abi = 'armeabi-v7a'
sdk = '21'
abi = {
'aarch64': 'arm64-v8a',
'amd64': 'x86_64',
'arm': 'armeabi-v7a',
'i386': 'x86',
'mips': 'mips',
'mips64': 'mips64',
}.get(context.arch, None)
# If we have an attached device, use its settings.
if context.device:
abi = str(properties.ro.product.cpu.abi)
sdk = str(properties.ro.build.version.sdk)
if abi is None:
log.error("Unknown CPU ABI")
project = _generate_ndk_project(source, abi, sdk)
# Remove any output files
@@ -1056,7 +1267,7 @@ class Partition(object):
def walk(top, topdown=True):
join = os.path.join
isdir = lambda x: stat.S_ISDIR(x['mode'])
client = Client()
client = AdbClient()
names = client.list(top)
dirs, nondirs = [], []
@@ -1094,15 +1305,15 @@ def readlink(path):
class Partitions(object):
@property
@context.quiet
@context.quietfunc
def by_name_dir(self):
return next(find('/dev/block/platform','by-name'))
@context.quiet
@context.quietfunc
def __dir__(self):
return list(self)
@context.quiet
@context.quietfunc
@with_device
def __iter__(self):
root()
@@ -1111,7 +1322,7 @@ class Partitions(object):
for name in listdir(self.by_name_dir):
yield name
@context.quiet
@context.quietfunc
@with_device
def __getattr__(self, attr):
for name in self:
@@ -1181,7 +1392,7 @@ def uninstall(package, *arguments):
with context.quiet:
return process(['pm','uninstall',package] + list(arguments)).recvall()
@context.quiet
@context.quietfunc
def packages():
"""Returns a list of packages installed on the system"""
packages = process(['pm', 'list', 'packages']).recvall()
+52
View File
@@ -0,0 +1,52 @@
from __future__ import division
import ctypes
BOOT_MAGIC = b"ANDROID!"
BOOT_MAGIC_SIZE = 8
BOOT_NAME_SIZE = 16
BOOT_ARGS_SIZE = 512
BOOT_EXTRA_ARGS_SIZE = 1024
class boot_img_hdr(ctypes.Structure):
_fields_ = [
('magic', ctypes.c_char * BOOT_MAGIC_SIZE),
('kernel_size', ctypes.c_uint32),
('kernel_addr', ctypes.c_uint32),
('ramdisk_size', ctypes.c_uint32),
('ramdisk_addr', ctypes.c_uint32),
('second_size', ctypes.c_uint32),
('second_addr', ctypes.c_uint32),
('tags_addr', ctypes.c_uint32),
('page_size', ctypes.c_uint32),
('unused', ctypes.c_uint32),
('os_version', ctypes.c_uint32),
('name', ctypes.c_char * BOOT_NAME_SIZE),
('cmdline', ctypes.c_char * BOOT_ARGS_SIZE),
('id', ctypes.c_char * 8),
('extra_cmdline', ctypes.c_char * BOOT_EXTRA_ARGS_SIZE),
]
class BootImage(object):
def __init__(self, data):
self.data = data
self.header = boot_img_hdr.from_buffer_copy(data)
PAGE = self.page_size
# The kernel starts at the beginning of the second page.
self.kernel = self.data[PAGE:PAGE+self.kernel_size]
def __getattr__(self, name):
value = getattr(self.header, name, None)
if value is not None:
return value
return getattr(super(BootImage, self), name)
+124
View File
@@ -0,0 +1,124 @@
from __future__ import unicode_literals
from __future__ import division
import ctypes
import io
import os
import sys
from pwnlib.log import getLogger
log = getLogger(__name__)
class img_info(ctypes.Structure):
_fields_ = [
('name', ctypes.c_char * 64),
('size', ctypes.c_uint32)
]
class bootloader_images_header(ctypes.Structure):
_fields_ = [
('magic', ctypes.c_char * 8),
('num_images', ctypes.c_uint32),
('start_offset', ctypes.c_uint32),
('bootldr_size', ctypes.c_uint32),
]
BOOTLDR_MAGIC = b'BOOTLDR!'
class BootloaderImage(object):
def __init__(self, data):
"""Android Bootloader image
Arguments:
data(str): Binary data from the image file.
"""
self.data = data
self.header = bootloader_images_header.from_buffer_copy(data)
if self.magic != BOOTLDR_MAGIC:
log.error("Incorrect magic (%r, expected %r)" % (self.magic, BOOTLDR_MAGIC))
if(self.bootldr_size > len(data)):
log.warn_once("Bootloader is supposed to be %#x bytes, only have %#x",
self.bootldr_size,
len(data))
if(self.num_images >= 0x100):
old = self.num_images
self.num_images = 1
log.warn_once("Bootloader num_images (%#x) appears corrupted, truncating to 1",
old)
imgarray = ctypes.ARRAY(img_info, self.num_images)
self.img_info = imgarray.from_buffer_copy(data, ctypes.sizeof(self.header))
def extract(self, index_or_name):
"""extract(index_or_name) -> bytes
Extract the contents of an image.
Arguments:
index_or_name(str,int): Either an image index or name.
Returns:
Contents of the image.
"""
if isinstance(index_or_name, int):
index = index_or_name
else:
for i in range(len(self.img_info)):
if self.img_info[i].name == index_or_name:
index = i
break
else:
raise ValueError("Invalid img name: %r" % index_or_name)
if index >= len(self.img_info):
raise ValueError("index out of range (%s, max %s)" % (index, len(self.img_info)))
offset = self.start_offset
for i in range(index):
offset += self.img_info[i].size
return self.data[offset:offset + self.img_info[index].size]
def extract_all(self, path):
"""extract_all(path)
Extracts all images to the provided path. The filenames are taken
from the image name, with '.img' appended.
"""
if not os.path.isdir(path):
raise ValueError("%r does not exist or is not a directory" % path)
for img in self.img_info:
imgpath = os.path.join(path, img.name + '.img')
with open(imgpath, 'wb+') as f:
data = self.extract(img.name)
f.write(data)
def __str__(self):
rv = []
rv.append("Bootloader")
rv.append(" Magic: %r" % self.magic)
rv.append(" Offset: %#x" % self.start_offset)
rv.append(" Size: %#x" % self.bootldr_size)
rv.append(" Images: %s" % self.num_images)
for img in self.img_info:
rv.append(" Name: %s" % img.name)
rv.append(" Size: %#x" % img.size)
rv.append(" Data: %r..." % self.extract(img.name)[:32])
return '\n'.join(rv)
def __getattr__(self, name):
value = getattr(self.header, name, None)
if value is not None:
return value
return getattr(super(BootImage, self), name)
if __name__ == '__main__':
# Easy sanity checking
b = BootloaderImage(open(sys.argv[1], 'rb').read())
print(b)
+3 -551
View File
@@ -1,553 +1,5 @@
"""
Implementation of the Android Debug Bridge (ADB) protocol, as far as Binjitsu needs it.
Documentation is available here:
https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
This file exists only for backward compatibility
"""
import functools
import stat
import time
from ..context import context
from ..log import Logger
from ..log import getLogger
from ..tubes.listen import listen
from ..tubes.process import process
from ..tubes.remote import remote
from ..util.lists import group
from ..util.misc import size
from ..util.packing import p32
from ..util.proc import pidof
from ..util.sh_string import sh_string
log = getLogger(__name__)
def pack(val):
return '%04x' % val
def unpack(val):
return int(val, 16)
OKAY = "OKAY"
FAIL = "FAIL"
class Message(object):
"""An ADB hex-length-prefixed message"""
def __init__(self, string):
self.string = string
def __str__(self):
return ('%04x' % len(self.string)) + self.string
def __flat__(self):
return str(self)
class Connection(remote):
"""Connection to the ADB server"""
def __init__(self, host, port, level=None, *a, **kw):
super(Connection, self).__init__(host, port, level=level, *a, **kw)
self._executable = None
self._argv = None
self._pid = None
self._cwd = None
self._env = None
def close(self):
with context.quiet:
super(Connection, self).close()
def adb_send(self, message):
self.send(str(Message(message)))
return self.recvn(4)
def adb_unpack(self):
return unpack(self.recvn(4))
def flat(self, *a, **kw):
kw.setdefault('word_size', 32)
return super(Connection, self).flat(*a, **kw)
class Process(Connection):
"""Duck-typed ``tubes.remote`` object to add properties of a ``tubes.process``"""
class Client(Logger):
"""ADB Client"""
def __init__(self, level=None):
super(Client, self).__init__()
if level is not None:
self.setLevel(level)
self.host = context.adb_host
self.port = context.adb_port
self._c = None
@property
def c(self):
"""Client's connection to the ADB server"""
if not self._c:
try:
self._c = Connection(self.host, self.port, level=self.level)
except Exception:
# If the connection fails, try starting a server on that port
# as long as it's the *default* port.
if self.host == context.defaults['adb_host'] \
and self.port == context.defaults['adb_port']:
log.warn("Could not connect to ADB server, trying to start it")
process(context.adb + ['start-server']).recvall()
else:
log.exception('Could not connect to ADB server')
# Final attempt...
if not self._c:
self._c = Connection(self.host, self.port, level=self.level)
return self._c
def _autoclose(fn):
"""Decorator which automatically closes the connection to the ADB server
after calling the decorated function."""
@functools.wraps(fn)
def wrapper(self, *a, **kw):
rv = fn(self, *a, **kw)
if self._c:
self._c.close()
self._c = None
return rv
return wrapper
def _with_transport(fn):
"""Decorator which automatically selects a device transport before calling
the decorated function, and closes the connection afterward."""
@functools.wraps(fn)
def wrapper(self, *a, **kw):
self.transport()
rv = fn(self, *a, **kw)
if self._c:
self._c.close()
self._c = None
return rv
return wrapper
def send(self, *a, **kw):
"""Sends data to the ADB server"""
return self.c.adb_send(*a, **kw)
def unpack(self, *a, **kw):
"""Receives a hex-ascii packed integer from the ADB server"""
return self.c.adb_unpack(*a, **kw)
def recvl(self):
"""Receives a length-prefixed data buffer from the ADB server"""
length = self.c.adb_unpack()
return self.c.recvn(length)
@_autoclose
def kill(self):
"""Kills the remote ADB server"
>>> c=adb.protocol.Client()
>>> c.kill()
The server is automatically re-started on the next request,
if the default host/port are used.
>>> c.version() > (4,0)
True
"""
try:
self.send('host:kill')
except EOFError:
pass
@_autoclose
def version(self):
"""
Returns:
Tuple containing the ``(major, minor)`` version from the ADB server
Example:
>>> adb.protocol.Client().version() # doctest: +SKIP
(4, 36)
"""
response = self.send('host:version')
if response == OKAY:
return (self.c.adb_unpack(), self.c.adb_unpack())
self.error("Could not fetch version")
@_autoclose
def devices(self, long=False):
"""
Arguments:
long(bool): If ``True``, fetch the long-format listing.
Returns:
String representation of all available devices.
"""
msg = 'host:devices'
if long:
msg += '-l'
response = self.send(msg)
if response == 'OKAY':
return self.recvl()
self.error("Could not enumerate devices")
@_autoclose
def track_devices(self):
"""
Returns:
Generator which returns a short-format listing of available
devices each time a device state changes.
"""
self.send('host:track-devices')
while True:
yield self.recvl()
def transport(self, serial=None):
"""Sets the Transport on the rmeote device.
Examples:
>>> adb.protocol.Client().transport()
"""
msg = 'host:transport:%s' % (serial or context.device)
if self.send(msg) == FAIL:
self.error("Could not set transport to %r" % serial)
@_autoclose
@_with_transport
def execute(self, argv):
r"""Executes a program on the device.
Returns:
A ``tube`` which is connected to the process.
Examples:
>>> adb.protocol.Client().execute(['echo','hello']).recvall()
'hello\n'
"""
self.transport(context.device)
if isinstance(argv, str):
argv = [argv]
argv = list(map(sh_string, argv))
cmd = 'exec:%s' % (' '.join(argv))
if OKAY == self.send(cmd):
rv = self._c
self._c = None
return rv
def _basic_wrapper(string):
@_autoclose
@_with_transport
def wrapper(self):
self.send(string)
return self.c.recvall()
return wrapper
@_autoclose
@_with_transport
def remount(self):
self.send('remount:')
return self.c.recvall()
@_autoclose
@_with_transport
def root(self):
self.send('root:')
return self.c.recvall()
@_autoclose
@_with_transport
def unroot(self):
self.send('unroot:')
return self.c.recvall()
@_autoclose
@_with_transport
def disable_verity(self):
self.send('disable-verity:')
return self.c.recvall()
@_autoclose
@_with_transport
def enable_verity(self):
self.send('enable-verity:')
return self.c.recvall()
@_autoclose
@_with_transport
def reconnect(self):
self.send('reconnect:')
return self.c.recvall()
@_autoclose
@_with_transport
def reboot(self):
self.send('reboot:')
return self.c.recvall()
@_autoclose
@_with_transport
def reboot_bootloader(self):
self.send('reboot:bootloader')
return self.c.recvall()
@_autoclose
def wait_for_device(self, serial=''):
response = self.send('host-serial:%s:wait-for-any-device' % serial)
# The first OKAY is that the command was understood
if response != 'OKAY':
self.error("An error occurred while waiting for device with serial %r" % serial)
# The second OKAY is that the device is available
response = self.c.recvn(4)
if response != 'OKAY':
self.error("An error occurred while waiting for device with serial %r" % serial)
def _sync(fn):
"""Decorator which enters 'sync:' mode to the selected transport,
then invokes the decorated funciton."""
@functools.wraps(fn)
def wrapper(self, *a, **kw):
rv = None
if FAIL != self.send('sync:'):
rv = fn(self, *a, **kw)
return rv
return wrapper
def list(self, path):
"""Execute the ``LIST`` command of the ``SYNC`` API.
Arguments:
path(str): Path of the directory to list.
Return:
A dictionary, where the keys are relative filenames,
and the values are a dictionary containing the same
values as ``stat()`` supplies.
Note:
In recent releases of Android (e.g. 7.0), the domain that
adbd executes from does not have access to everything that
the shell user does.
Because of this, while the shell user can get listings of
e.g. the root directory ('/'), adbd cannot.
The SYNC APIs are executed within the adbd context, not the
shell user context.
This issue is not a problem if the phone is rooted via
'adb root', since adbd then runs in the ``su`` domain.
Examples:
>>> pprint(adb.Client().list('/data/user'))
{'0': {'mode': 41471, 'size': 11, 'time': ...}}
>>> adb.Client().list('/does/not/exist')
Traceback (most recent call last):
...
PwnlibException: Cannot list directory '/does/not/exist': Does not exist
"""
st = self.stat(path)
if not st:
log.error("Cannot list directory %r: Does not exist" % path)
if not stat.S_ISDIR(st['mode']):
log.error("Cannot list directory %r: Path is not a directory" % path)
return self._list(path)
@_with_transport
@_sync
def _list(self, path):
self.c.flat('LIST', len(path), path)
files = {}
while True:
response = self.c.recvn(4)
if response == 'DONE':
break
if response != 'DENT':
self.error('Unexpected response: %r' % response)
mode = self.c.u32()
size = self.c.u32()
time = self.c.u32()
name = self.c.recvn(self.c.u32())
# Ignore the current directory and parent
if name in ('', '.', '..'):
continue
files[name] = {'mode': mode,
'size': size,
'time': time}
return files
@_with_transport
@_sync
def stat(self, path):
"""Execute the ``STAT`` command of the ``SYNC`` API.
Arguments:
path(str): Path to the file to stat.
Return:
On success, a dictionary mapping the values returned.
If the file cannot be ``stat()``ed, None is returned.
Example:
>>> expected = {'mode': 16749, 'size': 0, 'time': 0}
>>> adb.protocol.Client().stat('/proc') == expected
True
>>> adb.protocol.Client().stat('/does/not/exist') == None
True
"""
self.c.flat('STAT', len(path), path)
if self.c.recvn(4) != 'STAT':
self.error("An error occured while attempting to STAT a file.")
mode = self.c.u32()
size = self.c.u32()
time = self.c.u32()
if (mode,size,time) == (0,0,0):
return None
return {'mode': mode, 'size': size, 'time': time}
def write(self, path, data, mode=0o755, timestamp=None, callback=None):
"""Execute the ``WRITE`` command of the ``SYNC`` API.
Arguments:
path(str): Path to the file to write
data(str): Data to write to the file
mode(int): File mode to set (e.g. ``0o755``)
timestamp(int): Unix timestamp to set the file date to
callback(callable): Callback function invoked as data
is written. Arguments provided are:
- File path
- All data
- Expected size of all data
- Current chunk
- Expected size of chunk
"""
# We must ensure that 'path' is not a directory
# Writing to a directory is supported, but creates a temporary file
st = self.stat(path)
if st and stat.S_ISDIR(st['mode']):
log.error("Cannot write to %r: Path is a directory" % path)
return self._write(path, data, mode=0o755, timestamp=None, callback=None)
@_with_transport
@_sync
def _write(self, path, data, mode=0o755, timestamp=None, callback=None):
path += ',' + str(mode)
self.c.flat('SEND', len(path), path)
sent = 0
# Data needs to be broken up into chunks!
for chunk in group(0x10000, data):
self.c.flat('DATA', len(chunk), chunk)
if callback:
callback(path, data[:sent], len(data), chunk, len(chunk))
sent += len(chunk)
# Send completion notification and timestamp
if timestamp is None:
timestamp = int(time.time())
self.c.flat('DONE', timestamp)
result = self.c.recvn(4)
if result != 'OKAY':
log.error("Sync write failed: %r (expected OKAY)" % result)
return
@_with_transport
@_sync
def read(self, path, filesize=0, callback=lambda *a: True):
"""Execute the ``READ`` command of the ``SYNC`` API.
Arguments:
path(str): Path to the file to read
filesize(int): Size of the file, in bytes. Optional.
callback(callable): Callback function invoked as data
becomes available. Arguments provided are:
- File path
- All data
- Expected size of all data
- Current chunk
- Expected size of chunk
Return:
The data received as a string.
"""
self.c.send('RECV' + p32(len(path)) + path)
# Accumulate all data here
all_data = ''
while True:
magic = self.c.recvn(4)
# adbd says there is no more data to send
if magic == 'DONE':
break
if magic == 'FAIL':
self.error('Could not read file %r: Got FAIL.' % path)
# did we expect to be done?
if magic != 'DATA':
self.error('Error after file read: %r (expected DATA)' % magic)
# receive all of the data in the chunk
chunk_size = self.c.u32()
chunk_data = ''
while len(chunk_data) != chunk_size:
chunk_data += self.c.recv(chunk_size - len(chunk_data))
if callback:
callback(path,
all_data,
filesize,
chunk_data,
chunk_size)
# add the chunk onto what we have
all_data += chunk_data
zero = self.c.u32()
if zero != 0:
self.error('Error after file read: %r (expected ZERO)' % zero)
return all_data
@_with_transport
def forward(self, device, host_proto, host_port, device_proto, device_port):
self.send('host:forward:%s:%s;%s:%s' % (host_proto, host_port, device_proto, device_port))
self.c.recvall()
def __enter__(self, *a, **kw):
return self
@_autoclose
def __exit__(self, *a, **kw): pass
def proxy(port=9999):
"""Starts an ADB proxy on the specified port, for debugging purposes."""
l = listen(port)
l.wait_for_connection()
r = remote(context.adb_host, context.adb_port, level='debug')
l <> r
from pwnlib.protocols.adb import AdbClient
Client = AdbClient
+38 -9
View File
@@ -1,3 +1,4 @@
#!/usr/bin/env python2
"""
Pwntools exposes several magic command-line arguments and environment
@@ -16,13 +17,13 @@ The easiest example is to enable more verbose debugging. Just set ``DEBUG``.
$ python exploit.py DEBUG
These arguments are automatically extracted, regardless of their name, and
exposed via ``pwnlib.args.args``, which is exposed as the global variable
``args``. Arguments which ``pwntools`` reserves internally are not exposed
exposed via :mod:`pwnlib.args.args`, which is exposed as the global variable
:data:`args`. Arguments which ``pwntools`` reserves internally are not exposed
this way.
.. code-block:: bash
$ python -c 'from pwn import *; print args' A=1 B=Hello HOST=1.2.3.4 DEBUG
$ python -c 'from pwn import *; print(args)' A=1 B=Hello HOST=1.2.3.4 DEBUG
defaultdict(<type 'str'>, {'A': '1', 'HOST': '1.2.3.4', 'B': 'Hello'})
This is very useful for conditional code, for example determining whether to
@@ -36,28 +37,56 @@ not specified evaluate to an empty string.
else:
io = process('./pwnable')
Arguments can also be accessed directly with the dot operator, e.g.:
.. code-block:: python
if args.REMOTE:
...
Any undefined arguments evaluate to an empty string, ``''``.
The full list of supported "magic arguments" and their effects are listed
below.
"""
from __future__ import absolute_import
from __future__ import division
import collections
import logging
import os
import string
import sys
from . import term
from .context import context
from pwnlib import term
from pwnlib.context import context
class PwnlibArgs(collections.defaultdict):
def __getattr__(self, attr):
return self[attr]
args = PwnlibArgs(str)
term_mode = True
args = collections.defaultdict(str)
env_prefix = 'PWNLIB_'
free_form = True
# Check to see if we were invoked as one of the 'pwn xxx' scripts.
# If so, we don't want to remove e.g. "SYS_" from the end of the command
# line, as this breaks things like constgrep.
import pwnlib.commandline
basename = os.path.basename(sys.argv[0])
if basename == 'pwn' or basename in pwnlib.commandline.__all__:
free_form = False
def isident(s):
"""
Helper function to check whether a string is a valid identifier,
as passed in on the command-line.
"""
first = string.uppercase + '_'
first = string.ascii_uppercase + '_'
body = string.digits + first
if not s:
return False
@@ -166,13 +195,13 @@ def initialize():
value = 'True'
if '=' in arg:
arg, value = arg.split('=')
arg, value = arg.split('=', 1)
if arg in hooks:
sys.argv.remove(orig)
hooks[arg](value)
elif isident(arg):
elif free_form and isident(arg):
sys.argv.remove(orig)
args[arg] = value
+196 -122
View File
@@ -16,48 +16,49 @@ Assembly
To assemble code, simply invoke :func:`asm` on the code to assemble.
>>> asm('mov eax, 0')
'\xb8\x00\x00\x00\x00'
b'\xb8\x00\x00\x00\x00'
Additionally, you can use constants as defined in the :mod:`pwnlib.constants`
module.
>>> asm('mov eax, SYS_execve')
'\xb8\x0b\x00\x00\x00'
b'\xb8\x0b\x00\x00\x00'
Finally, :func:`asm` is used to assemble shellcode provided by ``pwntools``
in the :mod:`shellcraft` module.
>>> asm(shellcraft.nop())
'\x90'
b'\x90'
Disassembly
------------------------
To disassemble code, simply invoke :func:`disasm` on the bytes to disassemble.
>>> disasm('\xb8\x0b\x00\x00\x00')
' 0: b8 0b 00 00 00 mov eax,0xb'
>>> disasm(b'\xb8\x0b\x00\x00\x00')
' 0: b8 0b 00 00 00 mov eax, 0xb'
"""
from __future__ import absolute_import
from __future__ import division
import errno
import os
import platform
import re
import shutil
import string
import subprocess
import sys
import tempfile
from collections import defaultdict
from glob import glob
from os import environ
from os import path
from . import atexit
from . import shellcraft
from .context import LocalContext
from .context import context
from .log import getLogger
from pwnlib import atexit
from pwnlib import shellcraft
from pwnlib.context import LocalContext
from pwnlib.context import context
from pwnlib.log import getLogger
log = getLogger(__name__)
@@ -71,6 +72,11 @@ def dpkg_search_for_binutils(arch, util):
Returns:
A list of candidate package names.
::
>>> pwnlib.asm.dpkg_search_for_binutils('aarch64', 'as')
['binutils-aarch64-linux-gnu']
"""
# Example output:
@@ -83,7 +89,7 @@ def dpkg_search_for_binutils(arch, util):
try:
filename = 'bin/%s*linux*-%s' % (arch, util)
output = subprocess.check_output(['dpkg','-S',filename])
output = subprocess.check_output(['dpkg','-S',filename], universal_newlines = True)
for line in output.strip().splitlines():
package, path = line.split(':', 1)
packages.append(package)
@@ -97,6 +103,16 @@ def dpkg_search_for_binutils(arch, util):
def print_binutils_instructions(util, context):
"""On failure to find a binutils utility, inform the user of a way
they can get it easily.
Doctest:
>>> context.clear(arch = 'amd64')
>>> pwnlib.asm.print_binutils_instructions('as', context)
Traceback (most recent call last):
...
PwnlibException: Could not find 'as' installed for ContextType(arch = 'amd64', bits = 64, endian = 'little')
Try installing binutils for this architecture:
$ sudo apt-get install binutils
"""
# This links to our instructions on how to manually install binutils
# for several architectures.
@@ -129,8 +145,9 @@ def which_binutils(util):
Examples:
>>> import platform
>>> which_binutils = pwnlib.asm.which_binutils
>>> which_binutils('as', arch=platform.machine())
'.../bin/as'
'.../bin/...as'
>>> which_binutils('as', arch='arm') #doctest: +ELLIPSIS
'.../bin/arm-...-as'
>>> which_binutils('as', arch='powerpc') #doctest: +ELLIPSIS
@@ -142,7 +159,6 @@ def which_binutils(util):
Exception: Could not find 'as' installed for ContextType(arch = 'msp430')
"""
arch = context.arch
bits = context.bits
# Fix up pwntools vs Debian triplet naming, and account
# for 'thumb' being its own pwntools architecture.
@@ -173,10 +189,12 @@ def which_binutils(util):
for arch in arches:
for gutil in utils:
# e.g. objdump
if arch is None: pattern = gutil
if arch is None:
pattern = gutil
# e.g. aarch64-linux-gnu-objdump
else: pattern = '%s*linux*-%s' % (arch,gutil)
else:
pattern = '%s*linux*-%s' % (arch,gutil)
for dir in environ['PATH'].split(':'):
res = sorted(glob(path.join(dir, pattern)))
@@ -224,7 +242,7 @@ def _assembler():
if not checked_assembler_version[gas]:
checked_assembler_version[gas] = True
result = subprocess.check_output([gas, '--version','/dev/null'],
stderr=subprocess.STDOUT)
stderr=subprocess.STDOUT, universal_newlines=True)
version = re.search(r' (\d\.\d+)', result).group(1)
if version < '2.19':
log.warn_once('Your binutils version is too old and may not work!\n' + \
@@ -344,7 +362,8 @@ def _run(cmd, stdin = None):
cmd,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
stderr = subprocess.PIPE,
universal_newlines = True
)
stdout, stderr = proc.communicate(stdin)
exitcode = proc.wait()
@@ -380,19 +399,15 @@ def cpp(shellcode):
Examples:
.. doctest::
>>> cpp("mov al, SYS_setresuid", arch = "i386", os = "linux")
'mov al, 164\n'
>>> cpp("weee SYS_setresuid", arch = "arm", os = "linux")
'weee (0+164)\n'
>>> cpp("SYS_setresuid", arch = "thumb", os = "linux")
'(0+164)\n'
>>> cpp("SYS_setresuid", os = "freebsd")
'311\n'
>>> cpp("mov al, SYS_setresuid", arch = "i386", os = "linux")
'mov al, 164\n'
>>> cpp("weee SYS_setresuid", arch = "arm", os = "linux")
'weee (0+164)\n'
>>> cpp("SYS_setresuid", arch = "thumb", os = "linux")
'(0+164)\n'
>>> cpp("SYS_setresuid", os = "freebsd")
'311\n'
"""
arch = context.arch
os = context.os
code = _include_header() + shellcode
cmd = [
'cpp',
@@ -406,17 +421,39 @@ def cpp(shellcode):
return _run(cmd, code).strip('\n').rstrip() + '\n'
@LocalContext
def make_elf_from_assembly(assembly, vma = None, extract=False, shared = False):
r"""
Builds an ELF file with the specified assembly as its
executable code.
def make_elf_from_assembly(assembly,
vma=None,
extract=False,
shared=False,
strip=False,
**kwargs):
r"""make_elf_from_assembly(assembly, vma=None, extract=None, shared=False, strip=False, **kwargs) -> str
Builds an ELF file with the specified assembly as its executable code.
This differs from :func:`.make_elf` in that all ELF symbols are preserved,
such as labels and local variables. Use :func:`.make_elf` if size matters.
Additionally, the default value for ``extract`` in :func:`.make_elf` is
different.
Note:
This is effectively a wrapper around :func:`.asm`. with setting
``extract=False``, ``vma=0x10000000``, and marking the resulting
file as executable (``chmod +x``).
Note:
ELF files created with `arch=thumb` will prepend an ARM stub
which switches to Thumb mode.
Arguments:
assembly(str): Assembly
assembly(str): Assembly code to build into an ELF
vma(int): Load address of the binary
extract(bool): Whether to return the data extracted from the file created,
or the path to it.
(Default: ``0x10000000``, or ``0`` if ``shared=True``)
extract(bool): Extract the full ELF data from the file.
(Default: ``False``)
shared(bool): Create a shared library
(Default: ``False``)
kwargs(dict): Arguments to pass to :func:`.asm`.
Returns:
@@ -425,14 +462,29 @@ def make_elf_from_assembly(assembly, vma = None, extract=False, shared = False):
Example:
This example shows how to create a shared library, and load it via
``LD_PRELOAD``.
>>> context.clear()
>>> context.arch = 'amd64'
>>> sc = 'push rbp; mov rbp, rsp;'
>>> sc += shellcraft.echo('Hello\n')
>>> sc += 'mov rsp, rbp; pop rbp; ret'
>>> solib = make_elf_from_assembly(sc, shared=1)
>>> subprocess.check_output(['echo', 'World'], env={'LD_PRELOAD': solib})
>>> subprocess.check_output(['echo', 'World'], env={'LD_PRELOAD': solib}, universal_newlines = True)
'Hello\nWorld\n'
The same thing can be done with :func:`.make_elf`, though the sizes
are different. They both
>>> file_a = make_elf(asm('nop'), extract=True)
>>> file_b = make_elf_from_assembly('nop', extract=True)
>>> file_a[:4] == file_b[:4]
True
>>> len(file_a) < 0x200
True
>>> len(file_b) > 0x1000
True
"""
if shared and vma:
log.error("Cannot specify a VMA for a shared library.")
@@ -449,42 +501,48 @@ def make_elf_from_assembly(assembly, vma = None, extract=False, shared = False):
if not assembly.startswith(to_thumb):
assembly = to_thumb + assembly
path = asm(assembly, vma = vma, extract = extract, shared = shared)
result = asm(assembly, vma = vma, shared = shared, extract = False, **kwargs)
if not extract:
os.chmod(path, 0755)
os.chmod(result, 0o755)
else:
with open(result, 'rb') as io:
result = io.read()
return path
return result
@LocalContext
def make_elf(data, vma = None, strip=True, extract=True, shared=False):
r"""
Builds an ELF file with the specified binary data as its
executable code.
def make_elf(data,
vma=None,
strip=True,
extract=True,
shared=False):
r"""make_elf(data, vma=None, strip=True, extract=True, shared=False, **kwargs) -> str
Builds an ELF file with the specified binary data as its executable code.
Arguments:
data(str): Assembled code
vma(int): Load address for the ELF file
strip(bool): Strip the resulting ELF file. Only matters if ``extract=False``.
(Default: ``True``)
extract(bool): Extract the assembly from the ELF file.
If ``False``, the path of the ELF file is returned.
(Default: ``True``)
shared(bool): Create a Dynamic Shared Object (DSO, i.e. a ``.so``)
which can be loaded via ``dlopen`` or ``LD_PRELOAD``.
Examples:
This example creates an i386 ELF that just does
execve('/bin/sh',...).
>>> context.clear()
>>> context.arch = 'i386'
>>> context.bits = 32
>>> filename = tempfile.mktemp()
>>> bin_sh = '6a68682f2f2f73682f62696e89e331c96a0b5899cd80'.decode('hex')
>>> data = make_elf(bin_sh)
>>> with open(filename,'wb+') as f:
... f.write(data)
... f.flush()
>>> os.chmod(filename,0777)
>>> context.clear(arch='i386')
>>> bin_sh = unhex('6a68682f2f2f73682f62696e89e331c96a0b5899cd80')
>>> filename = make_elf(bin_sh, extract=False)
>>> p = process(filename)
>>> p.sendline('echo Hello; exit')
>>> p.sendline(b'echo Hello; exit')
>>> p.recvline()
'Hello\n'
b'Hello\n'
"""
retval = None
@@ -501,7 +559,7 @@ def make_elf(data, vma = None, strip=True, extract=True, shared=False):
assembler = _assembler()
linker = _linker()
code = _arch_header()
code += '.string "%s"' % ''.join('\\x%02x' % ord(c) for c in data)
code += '.string "%s"' % ''.join('\\x%02x' % c for c in bytearray(data))
code += '\n'
log.debug("Building ELF:\n" + code)
@@ -512,7 +570,7 @@ def make_elf(data, vma = None, strip=True, extract=True, shared=False):
step3 = path.join(tmpdir, 'step3-elf')
try:
with open(step1, 'wb+') as f:
with open(step1, 'w') as f:
f.write(code)
_run(assembler + ['-o', step2, step1])
@@ -533,11 +591,11 @@ def make_elf(data, vma = None, strip=True, extract=True, shared=False):
_run([which_binutils('strip'), '--strip-unneeded', step3])
if not extract:
os.chmod(step3, 0755)
os.chmod(step3, 0o755)
retval = step3
else:
with open(step3, 'r') as f:
with open(step3, 'rb') as f:
retval = f.read()
except Exception:
log.exception("An error occurred while building an ELF:\n%s" % code)
@@ -548,38 +606,37 @@ def make_elf(data, vma = None, strip=True, extract=True, shared=False):
@LocalContext
def asm(shellcode, vma = 0, extract = True, shared = False):
r"""asm(code, vma = 0, extract = True, ...) -> str
r"""asm(code, vma = 0, extract = True, shared = False, ...) -> str
Runs :func:`cpp` over a given shellcode and then assembles it into bytes.
To see which architectures or operating systems are supported,
look in :mod:`pwnlib.contex`.
look in :mod:`pwnlib.context`.
To support all these architecture, we bundle the GNU assembler
and objcopy with pwntools.
Assembling shellcode requires that the GNU assembler is installed
for the target architecture.
See :doc:`Installing Binutils </install/binutils>` for more information.
Arguments:
shellcode(str): Assembler code to assemble.
vma(int): Virtual memory address of the beginning of assembly
extract(bool): Extract the raw assembly bytes from the assembled
file. If ``False``, returns the path to an ELF file
with the assembly embedded.
Kwargs:
Any arguments/properties that can be set on ``context``
shellcode(str): Assembler code to assemble.
vma(int): Virtual memory address of the beginning of assembly
extract(bool): Extract the raw assembly bytes from the assembled
file. If :const:`False`, returns the path to an ELF file
with the assembly embedded.
shared(bool): Create a shared object.
kwargs(dict): Any attributes on :data:`.context` can be set, e.g.set
``arch='arm'``.
Examples:
.. doctest::
>>> asm("mov eax, SYS_select", arch = 'i386', os = 'freebsd')
'\xb8]\x00\x00\x00'
>>> asm("mov eax, SYS_select", arch = 'amd64', os = 'linux')
'\xb8\x17\x00\x00\x00'
>>> asm("mov rax, SYS_select", arch = 'amd64', os = 'linux')
'H\xc7\xc0\x17\x00\x00\x00'
>>> asm("mov r0, #SYS_select", arch = 'arm', os = 'linux', bits=32)
'R\x00\xa0\xe3'
>>> asm("mov eax, SYS_select", arch = 'i386', os = 'freebsd')
b'\xb8]\x00\x00\x00'
>>> asm("mov eax, SYS_select", arch = 'amd64', os = 'linux')
b'\xb8\x17\x00\x00\x00'
>>> asm("mov rax, SYS_select", arch = 'amd64', os = 'linux')
b'H\xc7\xc0\x17\x00\x00\x00'
>>> asm("mov r0, #SYS_select", arch = 'arm', os = 'linux', bits=32)
b'R\x00\xa0\xe3'
"""
result = ''
@@ -611,17 +668,27 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
ldflags = ['-z', 'execstack', '-o', step3, step2]
if vma:
ldflags += ['--section-start=.shellcode=%#x' % vma,
'--entry=%#x' % vma,
'-z', 'max-page-size=4096',
'-z', 'common-page-size=4096']
'--entry=%#x' % vma]
elif shared:
ldflags += ['-shared', '-init=_start']
# In order to ensure that we generate ELF files with 4k pages,
# and not e.g. 65KB pages (AArch64), force the page size.
# This is a result of GNU Gold being silly.
#
# Introduced in commit dd58f409 without supporting evidence,
# this shouldn't do anything except keep consistent page granularity
# across architectures.
ldflags += ['-z', 'max-page-size=4096',
'-z', 'common-page-size=4096']
_run(linker + ldflags)
elif file(step2,'rb').read(4) == '\x7fELF':
elif open(step2,'rb').read(4) == b'\x7fELF':
# Sanity check for seeing if the output has relocations
relocs = subprocess.check_output(
[which_binutils('readelf'), '-r', step2]
[which_binutils('readelf'), '-r', step2],
universal_newlines = True
).strip()
if extract and len(relocs.split('\n')) > 1:
log.error('Shellcode contains relocations:\n%s' % relocs)
@@ -633,7 +700,7 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
_run(objcopy + [step3, step4])
with open(step4) as fd:
with open(step4, 'rb') as fd:
result = fd.read()
except Exception:
@@ -653,9 +720,6 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
To see which architectures are supported,
look in :mod:`pwnlib.contex`.
To support all these architecture, we bundle the GNU objcopy
and objdump with pwntools.
Arguments:
data(str): Bytestring to disassemble.
vma(int): Passed through to the --adjust-vma argument of objdump
@@ -667,29 +731,28 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
Examples:
.. doctest::
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386')
0: b8 5d 00 00 00 mov eax,0x5d
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386', byte = 0)
0: mov eax,0x5d
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386', byte = 0, offset = 0)
mov eax,0x5d
>>> print disasm('b817000000'.decode('hex'), arch = 'amd64')
0: b8 17 00 00 00 mov eax,0x17
>>> print disasm('48c7c017000000'.decode('hex'), arch = 'amd64')
0: 48 c7 c0 17 00 00 00 mov rax,0x17
>>> print disasm('04001fe552009000'.decode('hex'), arch = 'arm')
0: e51f0004 ldr r0, [pc, #-4] ; 0x4
4: 00900052 addseq r0, r0, r2, asr r0
>>> print disasm('4ff00500'.decode('hex'), arch = 'thumb', bits=32)
0: f04f 0005 mov.w r0, #5
>>>
>>> print(disasm(unhex('b85d000000'), arch = 'i386'))
0: b8 5d 00 00 00 mov eax, 0x5d
>>> print(disasm(unhex('b85d000000'), arch = 'i386', byte = 0))
0: mov eax, 0x5d
>>> print(disasm(unhex('b85d000000'), arch = 'i386', byte = 0, offset = 0))
mov eax, 0x5d
>>> print(disasm(unhex('b817000000'), arch = 'amd64'))
0: b8 17 00 00 00 mov eax, 0x17
>>> print(disasm(unhex('48c7c017000000'), arch = 'amd64'))
0: 48 c7 c0 17 00 00 00 mov rax, 0x17
>>> print(disasm(unhex('04001fe552009000'), arch = 'arm'))
0: e51f0004 ldr r0, [pc, #-4] ; 0x4
4: 00900052 addseq r0, r0, r2, asr r0
>>> print(disasm(unhex('4ff00500'), arch = 'thumb', bits=32))
0: f04f 0005 mov.w r0, #5
>>> print(disasm(unhex('656664676665400F18A4000000000051'), byte=0, arch='amd64'))
0: gs data16 fs data16 rex nop/reserved BYTE PTR gs:[eax+eax*1+0x0]
f: push rcx
"""
result = ''
arch = context.arch
os = context.os
tmpdir = tempfile.mkdtemp(prefix = 'pwn-disasm-')
step1 = path.join(tmpdir, 'step1')
@@ -706,6 +769,9 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
'--rename-section', '.data=.text',
]
if not byte:
objdump += ['--no-show-raw-insn']
if arch == 'thumb':
objcopy += ['--prefix-symbol=$t.']
else:
@@ -713,12 +779,12 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
try:
with open(step1, 'w') as fd:
with open(step1, 'wb') as fd:
fd.write(data)
res = _run(objcopy + [step1, step2])
_run(objcopy + [step1, step2])
output0 = subprocess.check_output(objdump + [step2])
output0 = _run(objdump + [step2])
output1 = output0.split('<.text>:\n')
if len(output1) != 2:
@@ -732,14 +798,22 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
lines = []
pattern = '^( *[0-9a-f]+: *)((?:[0-9a-f]+ )+ *)(.*)'
pattern = '^( *[0-9a-f]+: *)', '((?:[0-9a-f]+ )+ *)', '(.*)'
if not byte:
pattern = pattern[::2]
pattern = ''.join(pattern)
for line in result.splitlines():
try:
o, b, i = re.search(pattern, line).groups()
except:
match = re.search(pattern, line)
if not match:
lines.append(line)
continue
groups = match.groups()
if byte:
o, b, i = groups
else:
o, i = groups
line = ''
if offset:
@@ -750,4 +824,4 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
line += i
lines.append(line)
return '\n'.join(lines)
return re.sub(',([^ ])', r', \1', '\n'.join(lines))
+3 -1
View File
@@ -2,12 +2,14 @@
Analogous to atexit, this module allows the programmer to register functions to
be run if an unhandled exception occurs.
"""
from __future__ import absolute_import
from __future__ import division
import sys
import threading
import traceback
from .context import context
from pwnlib.context import context
__all__ = ['register', 'unregister']
+3 -1
View File
@@ -7,12 +7,14 @@ this replacement module also defines :func:`unregister`.
This module also fixes a the issue that exceptions raised by an exit handler is
printed twice when the standard :mod:`atexit` is used.
"""
from __future__ import absolute_import
from __future__ import division
import sys
import threading
import traceback
from .context import context
from pwnlib.context import context
__all__ = ['register', 'unregister']
+21
View File
@@ -1 +1,22 @@
#!/usr/bin/env python2
__all__ = [
'asm',
'checksec',
'common',
'constgrep',
'cyclic',
'debug',
'disasm',
'disablenx',
'elfdiff',
'elfpatch',
'errno',
'hex',
'main',
'phd',
'pwnstrip',
'scramble',
'shellcraft',
'unhex',
'update'
]
+24 -14
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
from pwn import *
from . import common
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'asm',
@@ -28,8 +30,8 @@ parser.add_argument(
"-o","--output",
metavar='file',
help="Output file (defaults to stdout)",
type=argparse.FileType('w'),
default=sys.stdout
type=argparse.FileType('wb'),
default=getattr(sys.stdout, 'buffer', sys.stdout)
)
parser.add_argument(
@@ -44,14 +46,14 @@ parser.add_argument(
parser.add_argument(
'-v', '--avoid',
action='append',
help = 'Encode the shellcode to avoid the listed bytes (provided as hex; default: 000a)'
help = 'Encode the shellcode to avoid the listed bytes (provided as hex)'
)
parser.add_argument(
'-n', '--newline',
dest='avoid',
action='append_const',
const='\n',
const='0a',
help = 'Encode the shellcode to avoid newlines'
)
@@ -59,7 +61,7 @@ parser.add_argument(
'-z', '--zero',
dest='avoid',
action='append_const',
const='\x00',
const='00',
help = 'Encode the shellcode to avoid NULL bytes'
)
@@ -82,7 +84,7 @@ parser.add_argument(
'--infile',
help="Specify input file",
default=sys.stdin,
type=file
type=argparse.FileType('r')
)
parser.add_argument(
@@ -95,13 +97,18 @@ parser.add_argument(
def main(args):
tty = args.output.isatty()
if args.infile.isatty() and not args.lines:
parser.print_usage()
sys.exit(1)
data = '\n'.join(args.lines) or args.infile.read()
output = asm(data.replace(';', '\n'))
fmt = args.format or ('hex' if tty else 'raw')
formatters = {'r':str, 'h':enhex, 's':repr}
formatters = {'r':bytes, 'h':enhex, 's':repr}
if args.avoid:
output = encode(output, args.avoid)
avoid = unhex(''.join(args.avoid))
output = encode(output, avoid)
if args.debug:
proc = gdb.debug_shellcode(output, arch=context.arch)
@@ -115,13 +122,16 @@ def main(args):
if fmt[0] == 'e':
args.output.write(make_elf(output))
try: os.fchmod(args.output.fileno(), 0700)
try: os.fchmod(args.output.fileno(), 0o700)
except OSError: pass
else:
args.output.write(formatters[fmt[0]](output))
output = formatters[fmt[0]](output)
if not hasattr(output, 'decode'):
output = output.encode('ascii')
args.output.write(output)
if tty and fmt is not 'raw':
args.output.write('\n')
args.output.write(b'\n')
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+7 -5
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
from pwn import *
from . import common
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'checksec',
@@ -13,7 +15,7 @@ parser = common.parser_commands.add_parser(
parser.add_argument(
'elf',
nargs='*',
type=file,
type=argparse.FileType('rb'),
help='Files to check'
)
parser.add_argument(
@@ -21,7 +23,7 @@ parser.add_argument(
nargs='*',
dest='elf2',
metavar='elf',
type=file,
type=argparse.FileType('rb'),
help='File to check (for compatibility with checksec.sh)'
)
@@ -36,4 +38,4 @@ def main(args):
e = ELF(f.name)
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+1 -1
View File
@@ -5,7 +5,7 @@ import sys
import pwnlib
from pwnlib.context import context
choices = map(str, [16,32,64])
choices = list(map(str, [16,32,64]))
choices += list(context.oses)
choices += list(context.architectures)
choices += list(context.endiannesses)
+14 -8
View File
@@ -1,12 +1,17 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import functools
import os
import re
from pwn import *
import pwnlib
pwnlib.args.free_form = False
from . import common
from pwn import *
from pwnlib.commandline import common
p = common.parser_commands.add_parser(
'constgrep',
@@ -60,7 +65,7 @@ p.add_argument(
def main(args):
if args.exact:
# This is the simple case
print cpp(args.exact).strip()
print(cpp(args.exact).strip())
else:
# New we search in the right module.
# But first: We find the right module
@@ -75,6 +80,7 @@ def main(args):
else:
matcher = re.compile(args.regex)
# Evaluate the given constant
if args.constant:
try:
@@ -113,7 +119,7 @@ def main(args):
# Output all matching constants
for _, k in sorted(out):
print '#define %s %s' % (k.ljust(maxlen), cpp(k).strip())
print('#define %s %s' % (k.ljust(maxlen), cpp(k).strip()))
# If we are in match_mode, then try to find a combination of
# constants that yield the exact given value
@@ -130,9 +136,9 @@ def main(args):
out = [(v, k) for v, k in out if mask & v == v]
if reduce(lambda x, cur: x | cur[0], good, 0) == constant:
print
print '(%s) == %s' % (' | '.join(k for v, k in good), args.constant)
if functools.reduce(lambda x, cur: x | cur[0], good, 0) == constant:
print('')
print('(%s) == %s' % (' | '.join(k for v, k in good), args.constant))
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+9 -4
View File
@@ -1,11 +1,16 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import string
import sys
from pwn import *
import pwnlib
pwnlib.args.free_form = False
from . import common
from pwn import *
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'cyclic',
@@ -77,7 +82,7 @@ def main(args):
log.critical('Given pattern does not exist in cyclic pattern')
sys.exit(1)
else:
print offset
print(offset)
else:
want = args.count
result = cyclic(want, alphabet, subsize)
@@ -91,4 +96,4 @@ def main(args):
sys.stdout.write('\n')
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
from pwn import *
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'debug',
help = 'Debug a binary in GDB'
)
parser.add_argument(
'-x', metavar='GDBSCRIPT',
type=argparse.FileType('r'),
help='Execute GDB commands from this file.'
)
parser.add_argument(
'--pid',
type=int,
help="PID to attach to"
)
parser.add_argument(
'-c', '--context',
metavar = 'context',
action = 'append',
type = common.context_arg,
choices = common.choices,
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
)
parser.add_argument(
'--exec',
# NOTE: Type cannot be "file" because we may be referring to a remote
# file, or a file on an Android device.
type=str,
dest='executable',
help='File to debug'
)
parser.add_argument(
'--process', metavar='PROCESS_NAME',
help='Name of the process to attach to (e.g. "bash")'
)
parser.add_argument(
'--sysroot', metavar='SYSROOT',
type=str,
default='',
help="GDB sysroot path"
)
def main(args):
gdbscript = ''
if args.x:
gdbscript = args.x.read()
if context.os == 'android':
context.device = adb.wait_for_device()
if args.executable:
if os.path.exists(args.executable):
context.binary = ELF(args.executable)
target = context.binary.path
# This path does nothing, but avoids the "print_usage()"
# path below.
elif context.os == 'android':
target = args.executable
elif args.pid:
target = int(args.pid)
elif args.process:
if context.os == 'android':
target = adb.pidof(args.process)
else:
target = pidof(args.process)
# pidof() returns a list
if not target:
log.error("Could not find a PID for %r", args.process)
target = target[0]
# pidof will sometimes return all PIDs, including init
if target == 1:
log.error("Got PID 1 from pidof. Check the process name, or use --pid 1 to debug init")
else:
parser.print_usage()
return 1
if args.pid or args.process:
pid = gdb.attach(target, gdbscript=gdbscript, sysroot=args.sysroot)
# Since we spawned the gdbserver process, and process registers an
# atexit handler to close itself, gdbserver will be terminated when
# we exit. This will manifest as a "remote connected ended" or
# similar error message. Hold it open for the user.
log.info("GDB connection forwarding will terminate when you press enter")
pause()
else:
gdb.debug(target, gdbscript=gdbscript, sysroot=args.sysroot).interactive()
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
from pwn import *
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'disablenx',
help = 'Disable NX for an ELF binary'
)
parser.add_argument(
'elf',
nargs='+',
type=argparse.FileType('rb'),
help='Files to check'
)
def main(args):
for f in args.elf:
e = ELF(f.name)
e.disable_nx()
ELF(e.path)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+19 -14
View File
@@ -1,11 +1,17 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import string
import sys
from pwn import *
import pwnlib
pwnlib.args.free_form = False
from . import common
from pwn import *
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'disasm',
@@ -16,7 +22,7 @@ parser.add_argument(
'hex',
metavar = 'hex',
nargs = '*',
help = 'Hex-string to disasemble. If none are supplied, then it uses stdin in non-hex mode.'
help = 'Hex-string to disassemble. If none are supplied, then it uses stdin in non-hex mode.'
)
parser.add_argument(
@@ -55,14 +61,14 @@ parser.add_argument(
def main(args):
if len(args.hex) > 0:
dat = ''.join(args.hex)
dat = dat.translate(None, string.whitespace)
if not set(string.hexdigits) >= set(dat):
print "This is not a hex string"
dat = ''.join(args.hex).encode('utf-8', 'surrogateescape')
dat = dat.translate(None, string.whitespace.encode('ascii'))
if not set(string.hexdigits.encode('ascii')) >= set(dat):
print("This is not a hex string")
exit(-1)
dat = dat.decode('hex')
dat = unhex(dat)
else:
dat = sys.stdin.read()
dat = getattr(sys.stdin, 'buffer', sys.stdin).read()
if args.color:
@@ -75,17 +81,16 @@ def main(args):
instrs = disasm(dat, vma=safeeval.const(args.address), byte=False, offset=False)
# instrs = highlight(instrs, PwntoolsLexer(), TerminalFormatter())
split = lambda x: x.splitlines()
for o,b,i in zip(*list(map(split, (offsets, bytes, instrs)))):
for o,b,i in zip(*map(str.splitlines, (offsets, bytes, instrs))):
b = b.replace('00', text.red('00'))
b = b.replace('0a', text.red('0a'))
i = highlight(i.strip(), PwntoolsLexer(), TerminalFormatter()).strip()
i = i.replace(',',', ')
print o,b,i
print(o,b,i)
return
print disasm(dat, vma=safeeval.const(args.address))
print(disasm(dat, vma=safeeval.const(args.address)))
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+10 -5
View File
@@ -1,13 +1,18 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import shutil
from argparse import ArgumentParser
from subprocess import CalledProcessError
from subprocess import check_output
from tempfile import NamedTemporaryFile
from pwn import *
import pwnlib
pwnlib.args.free_form = False
from . import common
from pwn import *
from pwnlib.commandline import common
def dump(objdump, path):
@@ -18,7 +23,7 @@ def dump(objdump, path):
return n.name
def diff(a,b):
try: return check_output(['diff',a,b])
try: return check_output(['diff',a,b], universal_newlines=True)
except CalledProcessError as e:
return e.output
@@ -51,7 +56,7 @@ def main(a):
shutil.copy(y.path, name)
y = dump(objdump, name)
print diff(x, y)
print(diff(x, y))
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+9 -6
View File
@@ -1,17 +1,20 @@
#!/usr/bin/env python2
import argparse
from __future__ import absolute_import
from __future__ import division
import sys
from pwn import *
import pwnlib
pwnlib.args.free_form = False
from . import common
from pwn import *
from pwnlib.commandline import common
p = common.parser_commands.add_parser(
'elfpatch',
help = 'Patch an ELF file'
)
p = argparse.ArgumentParser()
p.add_argument('elf',help="File to patch")
p.add_argument('offset',help="Offset to patch in virtual address (hex encoded)")
p.add_argument('bytes',help='Bytes to patch (hex encoded)')
@@ -28,7 +31,7 @@ def main(a):
elf = ELF(a.elf)
elf.write(offset, bytes)
sys.stdout.write(elf.get_data())
getattr(sys.stdout, 'buffer', sys.stdout).write(elf.get_data())
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+13 -10
View File
@@ -1,7 +1,10 @@
from __future__ import absolute_import, print_function
import argparse
import os
import errno
from . import common
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'errno',
@@ -22,24 +25,24 @@ def main(args):
if 0x100000000 - value < 0x200:
value = 0x100000000 - value
if value not in os.errno.errorcode:
print "No errno for %s" % value
if value not in errno.errorcode:
print("No errno for %s" % value)
return
name = os.errno.errorcode[value]
name = errno.errorcode[value]
except ValueError:
name = args.error.upper()
if not hasattr(os.errno, name):
print "No errno for %s" % name
if not hasattr(errno, name):
print("No errno for %s" % name)
return
value = getattr(os.errno, name)
value = getattr(errno, name)
print '#define', name, value
print os.strerror(value)
print('#define', name, value)
print(os.strerror(value))
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+11 -4
View File
@@ -1,8 +1,12 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
from . import common
from pwnlib.commandline import common
from pwnlib.util.fiddling import enhex
parser = common.parser_commands.add_parser(
'hex',
@@ -14,9 +18,12 @@ parser.add_argument('data', nargs='*',
def main(args):
if not args.data:
print sys.stdin.read().encode('hex')
print(enhex(getattr(sys.stdin, 'buffer', sys.stdin).read()))
else:
print ' '.join(args.data).encode('hex')
data = ' '.join(args.data)
if not hasattr(data, 'decode'):
data = data.encode('utf-8', 'surrogateescape')
print(enhex(data))
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+29 -18
View File
@@ -1,30 +1,37 @@
from __future__ import absolute_import
import sys
from . import asm
from . import checksec
from . import common
from . import constgrep
from . import cyclic
from . import disasm
from . import elfdiff
from . import elfpatch
from . import errno
from . import hex
from . import phd
from . import pwnstrip
from . import scramble
from . import shellcraft
from . import unhex
from . import update
from .common import parser
from ..context import context
from pwnlib.commandline import asm
from pwnlib.commandline import checksec
from pwnlib.commandline import common
from pwnlib.commandline import constgrep
from pwnlib.commandline import cyclic
from pwnlib.commandline import debug
from pwnlib.commandline import disasm
from pwnlib.commandline import disablenx
from pwnlib.commandline import elfdiff
from pwnlib.commandline import elfpatch
from pwnlib.commandline import errno
from pwnlib.commandline import hex
from pwnlib.commandline import phd
from pwnlib.commandline import pwnstrip
from pwnlib.commandline import scramble
from pwnlib.commandline import shellcraft
from pwnlib.commandline import template
from pwnlib.commandline import unhex
from pwnlib.commandline import update
from pwnlib.commandline.common import parser
from pwnlib.context import context
commands = {
'asm': asm.main,
'checksec': checksec.main,
'constgrep': constgrep.main,
'cyclic': cyclic.main,
'debug': debug.main,
'disasm': disasm.main,
'disablenx': disablenx.main,
'elfdiff': elfdiff.main,
'elfpatch': elfpatch.main,
'errno': errno.main,
@@ -33,11 +40,15 @@ commands = {
'pwnstrip': pwnstrip.main,
'scramble': scramble.main,
'shellcraft': shellcraft.main,
'template': template.main,
'unhex': unhex.main,
'update': update.main,
}
def main():
if len(sys.argv) < 2:
parser.print_usage()
sys.exit()
args = parser.parse_args()
with context.local(log_console = sys.stderr):
commands[args.command](args)
+15 -6
View File
@@ -1,11 +1,17 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import os
import sys
import io
import pwnlib
pwnlib.args.free_form = False
from pwn import *
from . import common
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'phd',
@@ -17,8 +23,8 @@ parser.add_argument(
metavar='file',
nargs='?',
help='File to hexdump. Reads from stdin if missing.',
type=argparse.FileType('r'),
default=sys.stdin
type=argparse.FileType('rb'),
default=getattr(sys.stdin, 'buffer', sys.stdin)
)
parser.add_argument(
@@ -84,6 +90,9 @@ def main(args):
else:
infile.seek(skip, os.SEEK_CUR)
if count:
infile = io.BytesIO(infile.read(count))
hl = []
if args.highlight:
for hs in args.highlight:
@@ -92,9 +101,9 @@ def main(args):
try:
for line in hexdump_iter(infile, width, highlight = hl, begin = offset + skip):
print line
print(line)
except (KeyboardInterrupt, IOError):
pass
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
+12 -7
View File
@@ -1,8 +1,13 @@
from __future__ import absolute_import
from __future__ import division
import argparse
from pwn import *
import pwnlib
pwnlib.args.free_form = False
from . import common
from pwn import *
from pwnlib.commandline import common
p = common.parser_commands.add_parser(
'pwnstrip',
@@ -12,8 +17,8 @@ p = common.parser_commands.add_parser(
g = p.add_argument_group("actions")
g.add_argument('-b', '--build-id', help="Strip build ID", action='store_true')
g.add_argument('-p', '--patch', metavar='FUNCTION', help="Patch function", action='append')
p.add_argument('-o', '--output', type=file, default=sys.stdout)
p.add_argument('file', type=file)
p.add_argument('-o', '--output', type=argparse.FileType('wb'), default=getattr(sys.stdout, 'buffer', sys.stdout))
p.add_argument('file', type=argparse.FileType('rb'))
def main(args):
if not (args.patch or args.build_id):
@@ -28,7 +33,7 @@ def main(args):
for offset in pwnlib.libcdb.get_build_id_offsets():
data = elf.read(elf.address + offset + 0xC, 4)
if data == 'GNU\x00':
elf.write(elf.address + offset + 0x10, read('/dev/urandom', 20))
elf.write(elf.address + offset + 0x10, os.urandom(20))
for function in args.patch:
if function not in elf.symbols:
@@ -42,9 +47,9 @@ def main(args):
result = elf.data
if args.output.isatty():
result = enhex(result)
result = enhex(result).encode('ascii')
args.output.write(result)
if __name__ == '__main__':
pwnlib.common.main(__file__)
pwnlib.commandline.common.main(__file__)
Loaded 100 of 3773 files, more files were not shown because too many files have changed in this diff. Show more