Compare commits

...
12 Commits
28 changed files with 179 additions and 108 deletions

No files matched your search

+1
View File
@@ -8,3 +8,4 @@
build
MANIFEST
dist
pwntools.egg-info
+2 -3
View File
@@ -1,7 +1,6 @@
TL;DR version:
As far as we can tell, everything in pwntools is open source. Most is
under an MIT license, but a few pieces are under GPL or a BSD 2-clause
licence.
Everything in pwntools is open source. Most is under an MIT license, but a
few pieces are under GPL or a BSD 2-clause licence.
This license covers everything within this project, except for a few pieces
of code that we either did not write ourselves or which we derived from code
+1
View File
@@ -0,0 +1 @@
include *.txt
+2 -2
View File
@@ -1,6 +1,6 @@
# Introduction
This is the CTF framework used by pwnies in every CTF.
This is the CTF framework used by Gallopsled in every CTF.
Most code is inside the pwnlib folder with some functionality inside pwn or bin. It is typically used as:
@@ -24,7 +24,7 @@ We also have the following tools, not dependent on the pwnlib:
* `hex`/`unhex`: Command line tools for doing common hexing/unhexing operations
# Documentation
Our documentation is available on
Our documentation is available on http://pwntools.readthedocs.org/
# Installation
Pwntools is available as a pip package. You can install it by running
+4 -4
View File
@@ -71,9 +71,9 @@ copyright = u'2014, Gallopsled et al'
# built documents.
#
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
release = '2.0'
import pwnlib
release = pwnlib.__version__
version = release.rsplit('.', 1)[0]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -307,4 +307,4 @@ def linkcode_resolve(domain, info):
filename += '#L%d-%d' % (first, first + len(lines) - 1)
except IOError:
pass
return "https://github.com/pwnies/pwntools/blob/master/%s" % filename
return "https://github.com/Gallopsled/pwntools/blob/%s/%s" % (release, filename)
+8
View File
@@ -0,0 +1,8 @@
.. testsetup:: *
from pwnlib import context, constants
:mod:`pwnlib.constants` --- Easy access to header file constants
================================================================
.. automodule:: pwnlib.constants
+5
View File
@@ -0,0 +1,5 @@
:mod:`pwnlib.dynelf` --- Resolving remote functions using leaks
===============================================================
.. automodule:: pwnlib.dynelf
:members:
+2
View File
@@ -9,7 +9,9 @@ Contents:
intro
asm
constants
context
dynelf
exception
log
memleak
+11 -5
View File
@@ -1,14 +1,20 @@
.. testsetup:: *
from pwnlib import shellcraft
:mod:`pwnlib.shellcraft` --- Shellcode generation
=================================================
.. automodule:: pwnlib.shellcraft
.. TODO:
Write a guide to adding more shellcode.
Submodules
----------
.. toctree::
:glob:
shellcraft/*
Writing shellcode
-----------------
Foo bar
+9
View File
@@ -1,11 +1,20 @@
:mod:`pwnlib.shellcraft.i386` --- Shellcode for Intel 80386
===========================================================
:mod:`pwnlib.shellcraft.i386`
-----------------------------
.. automodule:: pwnlib.shellcraft.i386
:members:
:mod:`pwnlib.shellcraft.i386.linux`
-----------------------------------
.. automodule:: pwnlib.shellcraft.i386.linux
:members:
:mod:`pwnlib.shellcraft.i386.freebsd`
-------------------------------------
.. automodule:: pwnlib.shellcraft.i386.freebsd
:members:
+4
View File
@@ -0,0 +1,4 @@
import pwn
pwn.splash()
pwn.pause()
+7 -6
View File
@@ -3,6 +3,13 @@ from pwnlib import *
# Promote functions from these modules to toplevel
from pwnlib.asm import *
from pwnlib.dynelf import DynELF
from pwnlib.elf import ELF, load
from pwnlib.log_levels import *
from pwnlib.memleak import MemLeak
from pwnlib.tubes.listen import *
from pwnlib.tubes.process import *
from pwnlib.tubes.remote import *
from pwnlib.ui import *
from pwnlib.util import crc, proc
from pwnlib.util.cyclic import *
@@ -13,12 +20,6 @@ from pwnlib.util.misc import *
from pwnlib.util.packing import *
from pwnlib.util.proc import pidof
from pwnlib.util.splash import *
from pwnlib.tubes.remote import *
from pwnlib.tubes.listen import *
from pwnlib.tubes.process import *
from pwnlib.memleak import MemLeak
from pwnlib.elf import ELF, load
from pwnlib.dynelf import DynELF
# Promote these modules, so that "from pwn import *" will let you access them
import pwn, pwnlib, re, time, sys, os, string, threading, subprocess, struct
+8 -6
View File
@@ -1,10 +1,12 @@
__all__ = [
'asm', 'constants', 'context', 'dynelf',
'elf', 'exception', 'log', 'memleak',
'shellcraft', 'term', 'tubes', 'ui',
'util'
'elf', 'exception', 'log_levels', 'log',
'memleak', 'shellcraft', 'term', 'tubes',
'ui', 'util'
]
from . import asm, constants, context, dynelf
from . import elf, exception, log, memleak
from . import shellcraft, term, tubes, ui
from . import util
from . import elf, exception, log_levels, log
from . import memleak, shellcraft, term, tubes
from . import ui, util
from version import __version__
+35
View File
@@ -1,3 +1,37 @@
"""Module containing constants extracted from header files.
The purpose of this module is to provide quick access to constants from
different architectures and operating systems.
Example:
>>> print constants.freebsd.SYS_stat
188
>>> print constants.linux.i386.SYS_stat
106
>>> print constants.linux.amd64.SYS_stat
4
The submodule ``freebsd`` contains all constants for FreeBSD, while the
constants for Linux have been split up by architecture.
The variables of the submodules will be "lifted up" by setting the
:data:`pwnlib.context.arch` or :data:`pwnlib.context.os` in a manner similar to
what happens in :mod:`pwnlib.shellcraft`.
Example:
>>> with context.local(os = 'freebsd'):
... print constants.SYS_stat
188
>>> with context.local(os = 'linux', arch = 'i386'):
... print constants.SYS_stat
106
>>> with context.local(os = 'linux', arch = 'amd64'):
... print constants.SYS_stat
4
"""
from types import ModuleType
import importlib, sys
from .. import context
@@ -8,6 +42,7 @@ class module(ModuleType):
# Insert nice properties
self.__dict__.update({
'__doc__': __doc__,
'__file__': __file__,
'__package__': __package__,
'__path__': __path__,
+9 -4
View File
@@ -17,18 +17,23 @@ class module(ModuleType):
# Save the shellcode directory
self._dir = directory
# Find the absolute path of the directory
self._absdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', self._dir)
# Get the docstring
with open(os.path.join(self._absdir, "__doc__")) as fd:
self.__doc__ = fd.read()
# Insert into the module list
sys.modules[self.__name__] = self
def __lazyinit__(self):
# Find the absolute path of the directory
absdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', self._dir)
# Create a dictionary of submodules
self._submodules = {}
self._shellcodes = {}
for name in os.listdir(absdir):
path = os.path.join(absdir, name)
for name in os.listdir(self._absdir):
path = os.path.join(self._absdir, name)
if os.path.isdir(path):
self._submodules[name] = module(self.__name__ + '.' + name, os.path.join(self._dir, name))
elif os.path.isfile(path) and name != '__doc__':
+15 -2
View File
@@ -1,2 +1,15 @@
Shellcraft is a module structure containing functions for generating
shellcode (in assembler format) for various architectures.
The shellcode module.
This module contains functions for generating shellcode.
It is organized first by architecture and then by operating system.
Example:
>>> print shellcraft.i386.nop()
nop
>>> print shellcraft.i386.linux.sh()
;; Clear eax, ecx, edx
xor ecx, ecx
imul ecx
...
@@ -1,19 +1,16 @@
<% from pwnlib.shellcraft import common %>
<% from socket import htons %>
<%page args="port, os = None"/>
<%page args="port"/>
<%docstring>
Args: port
Waits for a connection. Leaves socket in EBP.
os is either linux or freebsd. ipv4 only
ipv4 only
</%docstring>
<% acceptloop = common.label("acceptloop")
<% acceptloop = common.label("acceptloop")
accept = common.label("accept")
parent = common.label("parent")
%>
${acceptloop}:
;; Listens for and accepts a connection on ${int(port)}d forever
;; Socket file descriptor is placed in EBP
@@ -72,9 +69,3 @@ ${parent}:
pop ecx
test ecx, ecx
jnz ${accept}
@@ -1,18 +1,15 @@
<% from pwnlib.shellcraft import common %>
<% from socket import htons %>
<%page args="port, os = None"/>
<%page args="port"/>
<%docstring>
Args: port
Waits for a connection. Leaves socket in EBP.
os is either linux or freebsd. ipv4 only
ipv4 only
</%docstring>
<% acceptloop = common.label("acceptloop")
<% acceptloop = common.label("acceptloop")
looplabel = common.label("loop")
%>
${acceptloop}:
;; Listens for and accepts a connection on ${int(port)}d forever
;; Socket file descriptor is placed in EBP
@@ -75,6 +72,3 @@ ${looplabel}:
test edi, edi
jnz ${looplabel}
@@ -1,16 +1,13 @@
<% from pwnlib.shellcraft import common %>
<%page args="sock = None, os=None"/>
<%page args="sock = 'ebp'"/>
<%docstring>
Args: [sock (imm/reg) = ebp]
Duplicates sock to stdin, stdout and stderr
</%docstring>
<% dup = common.label("dup")
looplabel = common.label("loop")
<%
dup = common.label("dup")
looplabel = common.label("loop")
%>
${dup}:
mov ebx, ${sock}
push 3
@@ -22,4 +19,3 @@ ${looplabel}:
pop eax
int 0x80
jnz ${looplabel}
@@ -1,20 +1,15 @@
<% from pwnlib.shellcraft import common %>
<% from socket import htons %>
<%page args="port = None, os = None"/>
<%page args="port = None"/>
<%docstring>
Args: port (defaults to any port)
Finds a socket, which is connected to the specified port.
Leaves socket in ESI.
</%docstring>
<%
findpeer = common.label("findpeer")
looplabel = common.label("loop")
<%
findpeer = common.label("findpeer")
looplabel = common.label("loop")
%>
${findpeer}:
push -1
push SYS_socketcall_getpeername
@@ -22,7 +17,6 @@ ${findpeer}:
pop ebx
pop esi
${looplabel}:
push SYS_socketcall
pop eax
@@ -34,7 +28,7 @@ ${looplabel}:
pushad
int 0x80
% if port==None:
% if port == None:
test eax, eax
popad
pop edx
@@ -45,9 +39,4 @@ ${looplabel}:
shr eax, 16
cmp ax, ${htons(int(port))}
jne ${looplabel}
%endif
@@ -1,9 +1,9 @@
<% from pwnlib.shellcraft import i386 %>
<%page args="in_fd=0, size=255, allocate_stack=True"/>
<%page args="in_fd = 'ebp', size = 255, allocate_stack = True"/>
<%docstring> Reads to the stack from a directory.
Args:
in_fd (int/str): Directory to be read from. Defaults to `STDIN_FILENO`.
in_fd (int/str): File descriptor to be read from.
size (int): Buffer size.
allocate_stack (bool): allocate 'size' bytes on the stack.
@@ -1,6 +1,8 @@
<% from pwnlib.shellcraft import common %>
<%page args="cookie = 0x7afceb58"/>
<%docstring>
stackhunter(cookie = 0x7afceb58)
Returns an an egghunter, which searches from esp and upwards
for a cookie. However to save bytes, it only looks at a single
4-byte alignment. Use the function stackhunter_helper to
@@ -9,29 +11,16 @@
The default cookie has been chosen, because it makes it possible
to shave a single byte, but other cookies can be used too.
</%docstring>
<% stackhunter = common.label("stackhunter") %>
%if (cookie & 0xffffff) == 0xfceb58:
${stackhunter}:
cmp dword eax, ${hex(cookie)}
jne ${stackhunter}+1
jmp esp
%else:
${stackhunter}:
pop eax
cmp dword eax, ${hex(cookie)}
jne ${stackhunter}
jmp esp
%endif
+1 -1
View File
@@ -51,4 +51,4 @@ def pause(n = None):
time.sleep(1)
log.done_success('Done', h)
else:
raise ValueError('options(): n must be a number or None')
raise ValueError('pause(): n must be a number or None')
+2 -2
View File
@@ -1,7 +1,7 @@
__all__ = [
'crc', 'cyclic', 'fiddling', 'hashes', 'lists',
'misc', 'packing', 'proc', 'safeeval', 'net'
'misc', 'net', 'packing', 'proc', 'safeeval'
]
from . import crc, cyclic, fiddling, hashes, lists
from . import misc, packing, proc, safeeval, net
from . import misc, net, packing, proc, safeeval
+1 -1
View File
@@ -78,7 +78,7 @@ def read(path):
Examples:
>>> read('pwnlib/util/misc.py').split('\\n')[0]
'import socket, subprocess, re, os'
'import socket, subprocess, re, os, stat'
"""
path = os.path.expanduser(os.path.expandvars(path))
with open(path) as fd:
+12 -6
View File
@@ -29,15 +29,21 @@ def splash():
colors = [
text.blue, text.magenta, text.red,
text.yellow, text.green, text.cyan
text.yellow, text.green, text.cyan,
]
h = log.indented('\n', frozen = False)
lines = _banner.lstrip('\n')
lines = _banner.strip('\n').split('\n')
hs = [log.indented('', frozen = False) for _ in range(len(lines))]
ndx = 0
while sys:
h.update(colors[ndx](lines))
ndx = (ndx + 1) % len(colors)
import sys as _sys
while _sys:
for i, (l, h) in enumerate(zip(lines, hs)):
l = ''.join(colors[((ndx + i + j) / 3) % len(colors)](l[j]) \
for j in range(len(l))
)
h.update(l)
ndx += 1
time.sleep(0.15)
if term.term_mode:
+1
View File
@@ -0,0 +1 @@
__version__ = '2.1.1'
+20 -6
View File
@@ -1,32 +1,46 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
from distutils.util import convert_path
from distutils.command.install import INSTALL_SCHEMES
import os, sys, glob
# Get all template files
templates = []
for dirpath, dirnames, filenames in os.walk(os.path.join('pwnlib', 'shellcraft', 'templates')):
for dirpath, dirnames, filenames in os.walk(convert_path('pwnlib/shellcraft/templates')):
for f in filenames:
templates.append(os.path.relpath(os.path.join(dirpath, f), 'pwnlib'))
# Get the version
ns = {}
with open(convert_path('pwnlib/version.py')) as fd:
exec fd.read() in ns
version = ns['__version__']
# This makes pwntools-LICENSE.txt appear with the package folders
for scheme in INSTALL_SCHEMES.values():
scheme['data'] = scheme['purelib']
setup(
name = 'pwntools',
packages = find_packages(),
version = '2.1.0',
version = version,
data_files = [('', ['LICENSE-pwntools.txt'])],
package_data = {
'pwnlib': [
'data/crcsums.txt',
'data/binutils/*',
'data/includes/*.h',
'data/includes/*/*.h',
] + templates
] + templates,
},
scripts = glob.glob("bin/*"),
description = "This is the CTF framework used by Gallopsled in every CTF.",
author = "Gallopsled et al.",
author_email = "#gallopsled @ freenode.net",
url = 'https://github.com/pwnies/pwntools/', # use the URL to the github repo
download_url = "https://github.com/pwnies/pwntools/tarball/master",
url = 'https://github.com/Gallopsled/pwntools/',
download_url = "https://github.com/Gallopsled/pwntools/tarball/%s" % version,
install_requires = ['paramiko','argparse', 'mako'],
license = "MIT",
license = "Mostly MIT, some GPL/BSD, see LICENSE-pwntools.txt",
classifiers = [
'Topic :: Security',
'Environment :: Console',