mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-09 01:59:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47c9cfe4eb | ||
|
|
642fcb0b29 | ||
|
|
89d73c8047 | ||
|
|
e8b4f0b07f | ||
|
|
c0202f9c65 | ||
|
|
ddab95e5cb | ||
|
|
f4ab2d2700 | ||
|
|
aad7eb9241 | ||
|
|
2f9f759839 | ||
|
|
3934a04536 | ||
|
|
3d76872a28 | ||
|
|
92aa3d3c16 | ||
|
|
f36bbecc6e | ||
|
|
1a66766c30 | ||
|
|
74560c80e6 |
No files matched your search
@@ -25,3 +25,8 @@ You can always [change the branch][change] after you create the PR if it's again
|
||||
[contributing]: https://github.com/Gallopsled/pwntools/blob/dev/CONTRIBUTING.md
|
||||
[testing]: https://github.com/Gallopsled/pwntools/blob/dev/TESTING.md
|
||||
[change]: https://github.com/blog/2224-change-the-base-branch-of-a-pull-request
|
||||
|
||||
## Changelog
|
||||
|
||||
After creating your Pull Request, please add and push a commit that updates the changelog for the appropriate branch.
|
||||
You can look at the existing changelog for examples of how to do this.
|
||||
@@ -0,0 +1,20 @@
|
||||
name: Changelog
|
||||
on: [pull_request]
|
||||
env:
|
||||
GITHUB_BASE: origin/${{ github.event.pull_request.base.ref }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check changelog for updates
|
||||
run: |
|
||||
git log --stat ${GITHUB_BASE}..HEAD | grep CHANGELOG.md
|
||||
+35
-11
@@ -8,6 +8,7 @@ jobs:
|
||||
python-version: [2.7, 3.8]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -28,11 +29,18 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Lint
|
||||
- name: Verify tag against version
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
env:
|
||||
GITHUB_REF: ${{ github.event.ref }}
|
||||
run: |
|
||||
pip install flake8
|
||||
flake8 . --count --select=E9,F63,F7 --show-source --statistics --exclude=android-?dk # TODO: Add F82
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=pwnlib/constants,android-?dk,.git,__pycache__
|
||||
set -x
|
||||
GITHUB_TAG=${GITHUB_REF#refs/tags/}
|
||||
echo "$GITHUB_TAG" | grep -E '^[0-9.]*(beta[0-9])?$'
|
||||
vsetup=$(grep -o "version\\s*=\\s*[\"'].*[\"'],$" setup.py | grep -o "[0-9][^\"']*")
|
||||
vpwnlib=$(grep -o "__version__\\s*=\\s*[\"'].*[\"']$" pwnlib/version.py | grep -o "[0-9][^\"']*")
|
||||
[ "$vsetup" = "$vpwnlib" ]
|
||||
[ "$GITHUB_TAG" = "$vsetup" ]
|
||||
|
||||
- name: Detect whether java is needed
|
||||
id: java-needed
|
||||
@@ -67,10 +75,8 @@ jobs:
|
||||
binutils-mips-linux-gnu \
|
||||
binutils-powerpc-linux-gnu \
|
||||
gcc-multilib \
|
||||
libc6-dbg \
|
||||
$ANDROID_JRE
|
||||
sudo apt-get install -y -o Acquire::Retries=3 \
|
||||
gcc-aarch64-linux-gnu \
|
||||
gcc-arm-linux-gnueabihf
|
||||
|
||||
- name: Install android avd
|
||||
if: steps.java-needed.outputs.need
|
||||
@@ -98,7 +104,6 @@ jobs:
|
||||
- name: Disable broken tests
|
||||
run: |
|
||||
rm -f docs/source/elf/corefile.rst
|
||||
rm -f docs/source/ui.rst
|
||||
|
||||
- name: Manually install non-broken Unicorn
|
||||
run: pip install unicorn==1.0.2rc3
|
||||
@@ -123,26 +128,45 @@ jobs:
|
||||
- name: Coverage running commandline tools
|
||||
run: |
|
||||
export TERM=linux
|
||||
pwn() { coverage run -m pwnlib.commandline.main "$@"; }
|
||||
pwn() { ( set +x; cmd=$1; shift; PYTHONUNBUFFERED=1 exec coverage run -m pwnlib.commandline."$cmd" "$@" ) }
|
||||
set -x
|
||||
|
||||
pwn cyclic 32
|
||||
pwn cyclic -l 0x62616161
|
||||
pwn cyclic -a ab
|
||||
echo
|
||||
|
||||
pwn shellcraft --list |tail
|
||||
pwn shellcraft -l --syscalls |tail
|
||||
pwn shellcraft -l execve
|
||||
pwn shellcraft --show i386.linux.loader_append
|
||||
pwn shellcraft -f asm --color amd64.linux.sh
|
||||
pwn shellcraft -f elf amd64.linux.syscalls.exit 0 </dev/null |pwn hex
|
||||
pwn shellcraft -f i --color amd64.linux.cat /etc/passwd </dev/null
|
||||
pwn shellcraft -f c amd64.linux.syscalls.exit 0 </dev/null
|
||||
pwn shellcraft -f str aarch64.linux.sh </dev/null
|
||||
pwn shellcraft -abr -f elf -o /dev/null amd64.linux.cat /etc/passwd </dev/null
|
||||
pwn shellcraft -nzr thumb.linux.syscalls.execve /bin/cat '["/bin/cat", "/etc/os-release"]' </dev/null
|
||||
pwn shellcraft -fp aarch64.trap
|
||||
|
||||
pwn disasm --color ff3424c3ebfe
|
||||
pwn asm -f hex nop
|
||||
|
||||
pwn hex abcd
|
||||
pwn unhex 4141 4141
|
||||
|
||||
head -c256 /dev/urandom | pwn phd
|
||||
cat /dev/urandom | pwn phd --color -c 256 -s 2
|
||||
pwn phd -l 0x3d --color=always /etc/os-release
|
||||
|
||||
pwn checksec /bin/bash
|
||||
|
||||
pwn errno 2
|
||||
pwn errno -1
|
||||
pwn errno EADDRINUSE
|
||||
|
||||
pwn constgrep -c freebsd -m ^PROT_ '3 + 4'
|
||||
pwn constgrep ^MAP_ 0
|
||||
pwn constgrep ^O_
|
||||
pwn constgrep -e O_RDWR
|
||||
|
||||
- name: Build source and wheel distributions
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Lint
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.8]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache for pip
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ matrix.os }}-cache-pip
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
pip install flake8
|
||||
flake8 . --count --select=E9,F63,F7 --show-source --statistics --exclude=android-?dk # TODO: Add F82
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=pwnlib/constants,android-?dk,.git,__pycache__
|
||||
@@ -20,10 +20,7 @@ addons:
|
||||
- binutils-arm-linux-gnueabihf
|
||||
- binutils-mips-linux-gnu
|
||||
- binutils-powerpc-linux-gnu
|
||||
- gcc-aarch64-linux-gnu
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- bash-static
|
||||
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
|
||||
+14
-1
@@ -66,7 +66,20 @@ To be released on Jun 5, 2020.
|
||||
[fecf9f]: http://github.com/Gallopsled/pwntools/commit/fecf9f
|
||||
[1454]: https://github.com/Gallopsled/pwntools/pull/1454
|
||||
|
||||
## 4.1.1 (`stable`)
|
||||
## 4.1.3 (`stable`)
|
||||
|
||||
- [#1590][1590] Fix `gdb.attach()` for `remote`, `listen`, `ssh` tubes
|
||||
- Also fix `run_in_new_terminal` for Py2 unicode strings
|
||||
- [#1595][1595] Fix ssh.process(timeout=)
|
||||
|
||||
[1590]: https://github.com/Gallopsled/pwntools/pull/1590
|
||||
[1595]: https://github.com/Gallopsled/pwntools/pull/1595
|
||||
|
||||
## 4.1.2
|
||||
|
||||
- Pwntools requires `six` v.1.12.0 or higher
|
||||
|
||||
## 4.1.1
|
||||
|
||||
- Fix PLT resolution by locking unicorn <1.0.2rc4 (#1538)
|
||||
- Fix wrong ELF/context unpack handling (c4c11a37)
|
||||
|
||||
@@ -5,6 +5,9 @@ from __future__ import division
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.commandline import common
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ parser.add_argument(
|
||||
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
|
||||
)
|
||||
|
||||
group = parser.add_mutually_exclusive_group(required = True)
|
||||
group = parser.add_mutually_exclusive_group(required=False)
|
||||
group.add_argument(
|
||||
'-l', '-o', '--offset', '--lookup',
|
||||
dest = 'lookup',
|
||||
@@ -53,9 +53,10 @@ group.add_argument(
|
||||
|
||||
group.add_argument(
|
||||
'count',
|
||||
type = int,
|
||||
nargs = '?',
|
||||
help = 'Number of characters to print'
|
||||
type=int,
|
||||
nargs='?',
|
||||
default=None,
|
||||
help='Number of characters to print'
|
||||
)
|
||||
|
||||
def main(args):
|
||||
@@ -90,7 +91,7 @@ def main(args):
|
||||
want = args.count
|
||||
result = cyclic(want, alphabet, subsize)
|
||||
got = len(result)
|
||||
if got < want:
|
||||
if want is not None and got < want:
|
||||
log.failure("Alphabet too small (max length = %i)" % got)
|
||||
|
||||
out = getattr(sys.stdout, 'buffer', sys.stdout)
|
||||
|
||||
@@ -45,4 +45,4 @@ def main(args):
|
||||
print(os.strerror(value))
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.commandline.common.main(__file__)
|
||||
common.main(__file__)
|
||||
@@ -26,4 +26,4 @@ def main(args):
|
||||
print(enhex(data))
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.commandline.common.main(__file__)
|
||||
common.main(__file__)
|
||||
@@ -85,12 +85,12 @@ def main(args):
|
||||
text.when = color
|
||||
|
||||
if skip:
|
||||
if infile == sys.stdin:
|
||||
infile.read(skip)
|
||||
else:
|
||||
try:
|
||||
infile.seek(skip, os.SEEK_CUR)
|
||||
except IOError:
|
||||
infile.read(skip)
|
||||
|
||||
if count:
|
||||
if count != -1:
|
||||
infile = io.BytesIO(infile.read(count))
|
||||
|
||||
hl = []
|
||||
|
||||
@@ -30,4 +30,4 @@ def main(args):
|
||||
sys.stderr.write(str(e) + '\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.commandline.common.main(__file__)
|
||||
common.main(__file__)
|
||||
@@ -1,4 +1,5 @@
|
||||
from __future__ import absolute_import
|
||||
from pwnlib.data.elf import fmtstr
|
||||
from pwnlib.data.elf import relro
|
||||
|
||||
import os
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
all: i386
|
||||
|
||||
i386: vuln.c
|
||||
gcc "$^" -fno-stack-protector -no-pie -m32 -o $@
|
||||
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
def get(x):
|
||||
return os.path.join(path, x)
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#define MEMORY_ADDRESS ((void*)0x11111000)
|
||||
#define MEMORY_SIZE 1024
|
||||
#define TARGET ((int *) 0x11111110)
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
char buff[1024];
|
||||
void *ptr = NULL;
|
||||
int *my_var = TARGET;
|
||||
ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
|
||||
if(ptr != MEMORY_ADDRESS)
|
||||
{
|
||||
perror("mmap");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
*my_var = 0x41414141;
|
||||
write(1, &my_var, sizeof(int *));
|
||||
scanf("%s", buff);
|
||||
dprintf(2, buff);
|
||||
write(1, my_var, sizeof(int));
|
||||
return 0;
|
||||
}
|
||||
+32
-32
@@ -1,39 +1,39 @@
|
||||
r"""
|
||||
Provide some tools to exploit format string bug
|
||||
|
||||
Examples:
|
||||
Let's use this program as an example:
|
||||
|
||||
>>> program = tempfile.mktemp()
|
||||
>>> source = program + ".c"
|
||||
>>> write(source, '''
|
||||
... #include <stdio.h>
|
||||
... #include <stdlib.h>
|
||||
... #include <unistd.h>
|
||||
... #include <sys/mman.h>
|
||||
... #define MEMORY_ADDRESS ((void*)0x11111000)
|
||||
... #define MEMORY_SIZE 1024
|
||||
... #define TARGET ((int *) 0x11111110)
|
||||
... int main(int argc, char const *argv[])
|
||||
... {
|
||||
... char buff[1024];
|
||||
... void *ptr = NULL;
|
||||
... int *my_var = TARGET;
|
||||
... ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
|
||||
... if(ptr != MEMORY_ADDRESS)
|
||||
... {
|
||||
... perror("mmap");
|
||||
... return EXIT_FAILURE;
|
||||
... }
|
||||
... *my_var = 0x41414141;
|
||||
... write(1, &my_var, sizeof(int *));
|
||||
... scanf("%s", buff);
|
||||
... dprintf(2, buff);
|
||||
... write(1, my_var, sizeof(int));
|
||||
... return 0;
|
||||
... }''')
|
||||
>>> gcc = process(["gcc", source, "-Wno-format-security", "-m32", "-o", program])
|
||||
>>> gcc.poll(True) and gcc.recvall()
|
||||
0
|
||||
::
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#define MEMORY_ADDRESS ((void*)0x11111000)
|
||||
#define MEMORY_SIZE 1024
|
||||
#define TARGET ((int *) 0x11111110)
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
char buff[1024];
|
||||
void *ptr = NULL;
|
||||
int *my_var = TARGET;
|
||||
ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
|
||||
if(ptr != MEMORY_ADDRESS)
|
||||
{
|
||||
perror("mmap");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
*my_var = 0x41414141;
|
||||
write(1, &my_var, sizeof(int *));
|
||||
scanf("%s", buff);
|
||||
dprintf(2, buff);
|
||||
write(1, my_var, sizeof(int));
|
||||
return 0;
|
||||
}
|
||||
|
||||
We can automate the exploitation of the process like so:
|
||||
|
||||
>>> program = pwnlib.data.elf.fmtstr.get('i386')
|
||||
>>> def exec_fmt(payload):
|
||||
... p = process(program)
|
||||
... p.sendline(payload)
|
||||
|
||||
+77
-64
@@ -110,6 +110,7 @@ from pwnlib.asm import make_elf_from_assembly
|
||||
from pwnlib.context import LocalContext
|
||||
from pwnlib.context import context
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.timeout import Timeout
|
||||
from pwnlib.util import misc
|
||||
from pwnlib.util import proc
|
||||
|
||||
@@ -545,68 +546,63 @@ def attach(target, gdbscript = '', exe = None, need_ptrace_scope = True, gdb_arg
|
||||
|
||||
Examples:
|
||||
|
||||
>>> # Attach directly to pid 1234
|
||||
>>> gdb.attach(1234) # doctest: +SKIP
|
||||
|
||||
Attach to a process by PID
|
||||
|
||||
>>> # Attach to the youngest "bash" process
|
||||
>>> gdb.attach('bash') # doctest: +SKIP
|
||||
>>> pid = gdb.attach(1234) # doctest: +SKIP
|
||||
|
||||
Attach to the youngest process by name
|
||||
|
||||
>>> # Start a process
|
||||
>>> bash = process('bash')
|
||||
>>> pid = gdb.attach('bash') # doctest: +SKIP
|
||||
|
||||
>>> # Attach the debugger
|
||||
>>> pid = gdb.attach(bash, '''
|
||||
... set follow-fork-mode child
|
||||
... break execve
|
||||
... continue
|
||||
... ''')
|
||||
Attach a debugger to a :class:`.process` tube and automate interaction
|
||||
|
||||
>>> # Interact with the process
|
||||
>>> bash.sendline("/bin/echo hello")
|
||||
>>> bash.recvline()
|
||||
b'hello\n'
|
||||
>>> bash.close()
|
||||
>>> io = process('bash')
|
||||
>>> pid = gdb.attach(io, gdbscript='''
|
||||
... call puts("Hello from process debugger!")
|
||||
... detach
|
||||
... quit
|
||||
... ''')
|
||||
>>> io.recvline()
|
||||
b'Hello from process debugger!\n'
|
||||
>>> io.sendline('echo Hello from bash && exit')
|
||||
>>> io.recvall()
|
||||
b'Hello from bash\n'
|
||||
|
||||
>>> # Start a forking server
|
||||
>>> server = process(['socat', 'tcp-listen:12345,fork,reuseaddr', 'exec:/bin/bash,nofork'])
|
||||
>>> sleep(1)
|
||||
Attach to the remote process from a :class:`.remote` or :class:`.listen` tube,
|
||||
as long as it is running on the same machine.
|
||||
|
||||
>>> # Connect to the server
|
||||
>>> io = remote('127.0.0.1', 12345)
|
||||
>>> server = process(['socat', 'tcp-listen:12345,reuseaddr,fork', 'exec:/bin/bash,nofork'])
|
||||
>>> sleep(1) # Wait for socat to start
|
||||
>>> io = remote('127.0.0.1', 12345)
|
||||
>>> sleep(1) # Wait for process to fork
|
||||
>>> pid = gdb.attach(io, gdbscript='''
|
||||
... call puts("Hello from remote debugger!")
|
||||
... detach
|
||||
... quit
|
||||
... ''')
|
||||
>>> io.recvline()
|
||||
b'Hello from remote debugger!\n'
|
||||
>>> io.sendline('echo Hello from bash && exit')
|
||||
>>> io.recvall()
|
||||
b'Hello from bash\n'
|
||||
|
||||
>>> # Connect the debugger to the server-spawned process
|
||||
>>> pid = gdb.attach(io, '''
|
||||
... break exit
|
||||
... continue
|
||||
... ''', exe = '/bin/bash')
|
||||
|
||||
>>> # Talk to the spawned 'sh'
|
||||
>>> io.sendline("echo hello")
|
||||
>>> io.recvline()
|
||||
b'hello\n'
|
||||
>>> io.sendline("exit")
|
||||
|
||||
>>> io.close()
|
||||
|
||||
>>> # Connect to the SSH server
|
||||
>>> shell = ssh('travis', 'example.pwnme', password='demopass')
|
||||
|
||||
>>> # Start a process on the server
|
||||
>>> cat = shell.process(['cat'])
|
||||
|
||||
>>> # Attach a debugger to it
|
||||
>>> gdb.attach(cat, '''
|
||||
... break exit
|
||||
... continue
|
||||
... ''')
|
||||
|
||||
>>> cat.sendline("hello")
|
||||
>>> cat.recvline()
|
||||
b'hello\n'
|
||||
>>> # Cause `cat` to exit
|
||||
>>> cat.close()
|
||||
Attach to processes running on a remote machine via an SSH :class:`.ssh` process
|
||||
|
||||
>>> shell = ssh('travis', 'example.pwnme', password='demopass')
|
||||
>>> io = shell.process(['cat'])
|
||||
>>> pid = gdb.attach(io, gdbscript='''
|
||||
... call sleep(5)
|
||||
... call puts("Hello from ssh debugger!")
|
||||
... detach
|
||||
... quit
|
||||
... ''')
|
||||
>>> io.recvline(timeout=5) # doctest: +SKIP
|
||||
b'Hello from ssh debugger!\n'
|
||||
>>> io.sendline('This will be echoed back')
|
||||
>>> io.recvline()
|
||||
b'This will be echoed back\n'
|
||||
>>> io.close()
|
||||
"""
|
||||
if context.noptrace:
|
||||
log.warn_once("Skipping debug attach since context.noptrace==True")
|
||||
@@ -687,17 +683,24 @@ def attach(target, gdbscript = '', exe = None, need_ptrace_scope = True, gdb_arg
|
||||
elif isinstance(target, tubes.sock.sock):
|
||||
pids = proc.pidof(target)
|
||||
if not pids:
|
||||
log.error('could not find remote process (%s:%d) on this machine' %
|
||||
log.error('Could not find remote process (%s:%d) on this machine' %
|
||||
target.sock.getpeername())
|
||||
waiting = True
|
||||
if exe:
|
||||
while waiting:
|
||||
for pid in pids:
|
||||
if proc.exe(pid) == exe:
|
||||
waiting = False
|
||||
break
|
||||
else:
|
||||
time.sleep(0.01)
|
||||
pid = pids[0]
|
||||
|
||||
# Specifically check for socat, since it has an intermediary process
|
||||
# if you do not specify "nofork" to the EXEC: argument
|
||||
# python(2640)───socat(2642)───socat(2643)───bash(2644)
|
||||
if proc.exe(pid).endswith('/socat') and time.sleep(0.1) and proc.children(pid):
|
||||
pid = proc.children(pid)[0]
|
||||
|
||||
# We may attach to the remote process after the fork but before it performs an exec.
|
||||
# If an exe is provided, wait until the process is actually running the expected exe
|
||||
# before we attach the debugger.
|
||||
t = Timeout()
|
||||
with t.countdown(2):
|
||||
while exe and os.realpath(proc.exe(pid)) != os.realpath(exe) and t.timeout:
|
||||
time.sleep(0.1)
|
||||
|
||||
elif isinstance(target, tubes.process.process):
|
||||
pid = proc.pidof(target)[0]
|
||||
exe = exe or target.executable
|
||||
@@ -945,13 +948,23 @@ def find_module_addresses(binary, ssh=None, ulimit=False):
|
||||
return rv
|
||||
|
||||
def corefile(process):
|
||||
r"""Drops a core file for the process.
|
||||
r"""Drops a core file for a running local process.
|
||||
|
||||
Note:
|
||||
You should use :meth:`.process.corefile` instead of using this method directly.
|
||||
|
||||
Arguments:
|
||||
process: Process to dump
|
||||
|
||||
Returns:
|
||||
:class:`.Core`: The generated core file
|
||||
|
||||
Example:
|
||||
|
||||
>>> io = process('bash')
|
||||
>>> core = gdb.corefile(io)
|
||||
>>> core.exe.name
|
||||
'/bin/bash'
|
||||
"""
|
||||
|
||||
if context.noptrace:
|
||||
|
||||
@@ -3,7 +3,10 @@ from pwnlib.tubes.process import process
|
||||
from time import sleep
|
||||
from sys import argv
|
||||
sleep(1)
|
||||
sh = process(argv[1], shell=True)
|
||||
if len(argv) == 2:
|
||||
sh = process(argv[1], shell=True)
|
||||
else:
|
||||
sh = process(argv[1:])
|
||||
sh.sendline('set prompt (gdb)')
|
||||
res = sh.sendlineafter('(gdb)', 'c')
|
||||
while b'The program is not being run.' not in res:
|
||||
|
||||
@@ -17,18 +17,11 @@ Example:
|
||||
The following doctest is commented out because it doesn't work on Travis
|
||||
for reasons I cannot diagnose. However, it should work just fine :-)
|
||||
|
||||
>>> gcc = process(['aarch64-linux-gnu-gcc','-xc','-static','-Wl,-Ttext-segment=0x20000000','-'])
|
||||
>>> gcc.write(b'''
|
||||
... #include <stdio.h>
|
||||
... int main() {
|
||||
... printf("Hello, %s!\\n", "world");
|
||||
... }
|
||||
... ''')
|
||||
>>> gcc.shutdown('send')
|
||||
>>> gcc.poll(True) and gcc.recvall()
|
||||
0
|
||||
>>> sc = shellcraft.loader_append('a.out')
|
||||
>>> run_assembly(sc).recvline()
|
||||
>>> payload = shellcraft.echo(b'Hello, world!\n') + shellcraft.exit(0)
|
||||
>>> payloadELF = ELF.from_assembly(payload)
|
||||
>>> loader = shellcraft.loader_append(payloadELF.data)
|
||||
>>> loaderELF = ELF.from_assembly(loader, vma=0, shared=True)
|
||||
>>> loaderELF.process().recvall()
|
||||
b'Hello, world!\n'
|
||||
|
||||
</%docstring>
|
||||
@@ -47,7 +40,7 @@ ${there}:
|
||||
<%
|
||||
import os
|
||||
|
||||
if os.path.isfile(data):
|
||||
if b'\x00' not in data and os.path.isfile(data):
|
||||
with open(data, 'rb') as f:
|
||||
data = f.read()
|
||||
%>
|
||||
|
||||
@@ -14,23 +14,15 @@ Arguments:
|
||||
|
||||
Example:
|
||||
|
||||
>>> gcc = process(['gcc','-m64','-xc','-static','-Wl,-Ttext-segment=0x20000000','-'])
|
||||
>>> gcc.write(b'''
|
||||
... #include <stdio.h>
|
||||
... int main() {
|
||||
... printf("Hello, %s!\\n", "amd64");
|
||||
... }
|
||||
... ''')
|
||||
>>> gcc.shutdown('send')
|
||||
>>> gcc.poll(True) and gcc.recvall()
|
||||
0
|
||||
>>> sc = shellcraft.loader_append('a.out')
|
||||
>>> payload = shellcraft.echo(b'Hello, world!\n') + shellcraft.exit(0)
|
||||
>>> payloadELF = ELF.from_assembly(payload)
|
||||
>>> payloadELF.arch
|
||||
'amd64'
|
||||
>>> loader = shellcraft.loader_append(payloadELF.data)
|
||||
>>> loaderELF = ELF.from_assembly(loader, vma=0, shared=True)
|
||||
>>> loaderELF.process().recvall()
|
||||
b'Hello, world!\n'
|
||||
|
||||
The following doctest is commented out because it doesn't work on Travis
|
||||
for reasons I cannot diagnose. However, it should work just fine :-)
|
||||
|
||||
>>> run_assembly(sc).recvline() == b'Hello, amd64!\n'
|
||||
True
|
||||
|
||||
</%docstring>
|
||||
<%page args="data = None"/>
|
||||
@@ -48,7 +40,7 @@ ${elf_data}:
|
||||
<%
|
||||
import os
|
||||
|
||||
if os.path.isfile(data):
|
||||
if b'\x00' not in data and os.path.isfile(data):
|
||||
with open(data, 'rb') as f:
|
||||
data = f.read()
|
||||
%>
|
||||
|
||||
@@ -14,23 +14,14 @@ Arguments:
|
||||
|
||||
Example:
|
||||
|
||||
>>> gcc = process(['gcc','-m32','-xc','-static','-Wl,-Ttext-segment=0x20000000','-'])
|
||||
>>> gcc.write(b'''
|
||||
... #include <stdio.h>
|
||||
... int main() {
|
||||
... printf("Hello, %s!\\n", "i386");
|
||||
... }
|
||||
... ''')
|
||||
>>> gcc.shutdown('send')
|
||||
>>> gcc.poll(True) and gcc.recvall()
|
||||
0
|
||||
>>> sc = shellcraft.loader_append('a.out')
|
||||
|
||||
The following doctest is commented out because it doesn't work on Travis
|
||||
for reasons I cannot diagnose. However, it should work just fine :-)
|
||||
|
||||
>>> run_assembly(sc).recvline()
|
||||
b'Hello, i386!\n'
|
||||
>>> payload = shellcraft.echo(b'Hello, world!\n') + shellcraft.exit(0)
|
||||
>>> payloadELF = ELF.from_assembly(payload)
|
||||
>>> payloadELF.arch
|
||||
'i386'
|
||||
>>> loader = shellcraft.loader_append(payloadELF.data)
|
||||
>>> loaderELF = ELF.from_assembly(loader, vma=0, shared=True)
|
||||
>>> loaderELF.process().recvall()
|
||||
b'Hello, world!\n'
|
||||
|
||||
</%docstring>
|
||||
<%page args="data = None"/>
|
||||
@@ -48,7 +39,7 @@ ${elf_data}:
|
||||
<%
|
||||
import os
|
||||
|
||||
if os.path.isfile(data):
|
||||
if b'\x00' not in data and os.path.isfile(data):
|
||||
with open(data, 'rb') as f:
|
||||
data = f.read()
|
||||
%>
|
||||
|
||||
@@ -17,20 +17,16 @@ Example:
|
||||
The following doctest is commented out because it doesn't work on Travis
|
||||
for reasons I cannot diagnose. However, it should work just fine :-)
|
||||
|
||||
>>> gcc = process(['arm-linux-gnueabihf-gcc','-xc','-static','-Wl,-Ttext-segment=0x20000000','-'])
|
||||
>>> gcc.write(b'''
|
||||
... #include <stdio.h>
|
||||
... int main() {
|
||||
... printf("Hello, %s!\\n", "world");
|
||||
... }
|
||||
... ''')
|
||||
>>> gcc.shutdown('send')
|
||||
>>> gcc.poll(True) and gcc.recvall()
|
||||
0
|
||||
>>> sc = shellcraft.loader_append('a.out')
|
||||
>>> run_assembly(sc).recvline()
|
||||
>>> payload = shellcraft.echo(b'Hello, world!\n') + shellcraft.exit(0)
|
||||
>>> payloadELF = ELF.from_assembly(payload)
|
||||
>>> payloadELF.arch
|
||||
'arm'
|
||||
>>> loader = shellcraft.loader_append(payloadELF.data)
|
||||
>>> loaderELF = ELF.from_assembly(loader, vma=0, shared=True)
|
||||
>>> loaderELF.process().recvall()
|
||||
b'Hello, world!\n'
|
||||
|
||||
|
||||
</%docstring>
|
||||
<%page args="data = None"/>
|
||||
<%
|
||||
@@ -45,7 +41,7 @@ ${there}:
|
||||
<%
|
||||
import os
|
||||
|
||||
if os.path.isfile(data):
|
||||
if b'\x00' not in data and os.path.isfile(data):
|
||||
with open(data, 'rb') as f:
|
||||
data = f.read()
|
||||
%>
|
||||
|
||||
+9
-2
@@ -832,6 +832,10 @@ class ssh(Timeout, Logger):
|
||||
|
||||
>>> s.process('echo hello', shell=True).recvall()
|
||||
b'hello\n'
|
||||
|
||||
>>> io = s.process(['cat'], timeout=5)
|
||||
>>> io.recvline()
|
||||
b''
|
||||
"""
|
||||
if not argv and not executable:
|
||||
self.error("Must specify argv or executable")
|
||||
@@ -1044,11 +1048,14 @@ os.execve(exe, argv, env)
|
||||
|
||||
msg = 'Starting remote process %s on %s' % (execve_repr, self.host)
|
||||
|
||||
if timeout == Timeout.default:
|
||||
timeout = self.timeout
|
||||
|
||||
with self.progress(msg) as h:
|
||||
|
||||
script = 'for py in python2.7 python2 python; do test -x "$(which $py 2>&1)" && exec $py -c %s check; done; echo 2' % sh_string(script)
|
||||
with context.local(log_level='error'):
|
||||
python = ssh_process(self, script, tty=True, raw=True, level=self.level, timeout=self.timeout)
|
||||
with context.quiet:
|
||||
python = ssh_process(self, script, tty=True, raw=True, level=self.level, timeout=timeout)
|
||||
|
||||
try:
|
||||
result = safeeval.const(python.recvline())
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ import errno
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import six
|
||||
import socket
|
||||
import stat
|
||||
import string
|
||||
@@ -238,7 +239,7 @@ def run_in_new_terminal(command, terminal = None, args = None):
|
||||
|
||||
argv = [which(terminal)] + args
|
||||
|
||||
if isinstance(command, str):
|
||||
if isinstance(command, six.string_types):
|
||||
if ';' in command:
|
||||
log.error("Cannot use commands with semicolon. Create a script and invoke that directly.")
|
||||
argv += [command]
|
||||
|
||||
+15
-1
@@ -33,6 +33,7 @@ Examples:
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import collections
|
||||
import six
|
||||
import struct
|
||||
import sys
|
||||
@@ -548,6 +549,7 @@ def _flat(args, preprocessor, packer, filler):
|
||||
elif isinstance(arg, (list, tuple)):
|
||||
val = _flat(arg, preprocessor, packer, filler)
|
||||
elif isinstance(arg, dict):
|
||||
arg = collections.OrderedDict(((k,v) for k,v in sorted(arg.items())))
|
||||
filler, val = _fit(arg, preprocessor, packer, filler)
|
||||
elif isinstance(arg, bytes):
|
||||
val = arg
|
||||
@@ -614,6 +616,8 @@ def flat(*args, **kwargs):
|
||||
sign (str): Signedness of the converted integer (False/True)
|
||||
|
||||
Examples:
|
||||
|
||||
>>> context.clear()
|
||||
>>> flat(1, "test", [[["AB"]*2]*3], endianness = 'little', word_size = 16, sign = False)
|
||||
b'\x01\x00testABABABABABAB'
|
||||
>>> flat([1, [2, 3]], preprocessor = lambda x: str(x+1))
|
||||
@@ -633,7 +637,17 @@ def flat(*args, **kwargs):
|
||||
b'aaaaX'
|
||||
>>> flat({4: {0: 'X', 4: 'Y'}})
|
||||
b'aaaaXaaaY'
|
||||
|
||||
>>> flat({0x61616161:'x', 0x61616162:'y'})
|
||||
b'xaaay'
|
||||
>>> flat({0x61616162:'y', 0x61616161:'x'})
|
||||
b'xaaay'
|
||||
>>> fit({
|
||||
... 0x61616161: 'a',
|
||||
... 1: 'b',
|
||||
... 0x61616161+2: 'c',
|
||||
... 3: 'd',
|
||||
... })
|
||||
b'abadbaaac'
|
||||
"""
|
||||
# HACK: To avoid circular imports we need to delay the import of `cyclic`
|
||||
from pwnlib.util import cyclic
|
||||
|
||||
+20
-13
@@ -9,6 +9,7 @@ import psutil
|
||||
|
||||
from pwnlib import tubes
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.timeout import Timeout
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
@@ -337,17 +338,23 @@ def wait_for_debugger(pid, debugger_pid=None):
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
with log.waitfor('Waiting for debugger') as l:
|
||||
if debugger_pid:
|
||||
debugger = psutil.Process(debugger_pid)
|
||||
while tracer(pid) is None:
|
||||
try:
|
||||
debugger.wait(0.01)
|
||||
except psutil.TimeoutExpired:
|
||||
pass
|
||||
else:
|
||||
l.error("debugger exited! (maybe check /proc/sys/kernel/yama/ptrace_scope)")
|
||||
t = Timeout()
|
||||
with t.countdown(timeout=15):
|
||||
with log.waitfor('Waiting for debugger') as l:
|
||||
if debugger_pid:
|
||||
debugger = psutil.Process(debugger_pid)
|
||||
while t.timeout and tracer(pid) is None:
|
||||
try:
|
||||
debugger.wait(0.01)
|
||||
except psutil.TimeoutExpired:
|
||||
pass
|
||||
else:
|
||||
l.failure("debugger exited! (maybe check /proc/sys/kernel/yama/ptrace_scope)")
|
||||
else:
|
||||
while t.timeout and tracer(pid) is None:
|
||||
time.sleep(0.01)
|
||||
|
||||
if tracer(pid):
|
||||
l.success()
|
||||
else:
|
||||
while tracer(pid) is None:
|
||||
time.sleep(0.01)
|
||||
l.success()
|
||||
l.failure('Debugger did not attach to pid %d within 15 seconds', pid)
|
||||
+1
-1
@@ -1 +1 @@
|
||||
__version__ = '4.1.2'
|
||||
__version__ = '4.1.3'
|
||||
@@ -83,7 +83,7 @@ setup(
|
||||
name = 'pwntools',
|
||||
python_requires = '>=2.7',
|
||||
packages = find_packages(),
|
||||
version = '4.1.2',
|
||||
version = '4.1.3',
|
||||
data_files = [('',
|
||||
glob.glob('*.md') + glob.glob('*.txt')),
|
||||
],
|
||||
|
||||
@@ -64,6 +64,11 @@ setup_travis()
|
||||
rm -rf usr/share
|
||||
}
|
||||
|
||||
setup_ipv6()
|
||||
{
|
||||
echo 0 | sudo tee /proc/sys/net/ipv6/conf/all/disable_ipv6
|
||||
}
|
||||
|
||||
setup_gdbserver()
|
||||
{
|
||||
# https://docs.improbable.io/reference/14.3/shared/debug-cloud-workers#common-issues
|
||||
@@ -186,6 +191,7 @@ setup_osx()
|
||||
|
||||
if [[ "$USER" == "travis" ]]; then
|
||||
# setup_travis
|
||||
setup_ipv6
|
||||
setup_gdbserver
|
||||
setup_android_emulator
|
||||
elif [[ "$USER" == "shippable" ]]; then
|
||||
|
||||
Reference in new issue
Block a user