mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-07 17:14:22 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f046fdd93e | ||
|
|
4c0e08c2c8 | ||
|
|
1b47ae1c20 | ||
|
|
2114692513 | ||
|
|
b5e4ff137a | ||
|
|
1b21f7a043 | ||
|
|
2e09b7dd91 | ||
|
|
d643a33233 | ||
|
|
8d6dc0b121 | ||
|
|
2f58fe7ae5 | ||
|
|
64d52b09f3 | ||
|
|
8cf3ecdc5b | ||
|
|
0c1121d32c | ||
|
|
dafd42b2c3 | ||
|
|
3ff37a8b7e | ||
|
|
e9f73bf440 | ||
|
|
045b8c2186 | ||
|
|
01e6970971 | ||
|
|
6aaaf84586 | ||
|
|
92cd96999f | ||
|
|
8b86cc3ba6 | ||
|
|
20f07795f0 | ||
|
|
d12d2ea78c | ||
|
|
2d998a4082 | ||
|
|
8be72238b0 | ||
|
|
d762fe0c31 | ||
|
|
e608a46490 | ||
|
|
fa2d47753b | ||
|
|
6ff74256d8 | ||
|
|
340b0bf0bc | ||
|
|
2e5a33cfea | ||
|
|
b8b29e1cc7 | ||
|
|
ff178aad6a | ||
|
|
8c8e49cc10 | ||
|
|
0b0f786002 | ||
|
|
9ba65eb414 | ||
|
|
cf53c4b219 | ||
|
|
a0c9da07ac | ||
|
|
5b783feabd | ||
|
|
5589e15051 | ||
|
|
40c1ef5890 | ||
|
|
e5af2bc3a3 | ||
|
|
6fa13de917 | ||
|
|
216e3edcde | ||
|
|
c334d46026 | ||
|
|
3e4e8b7055 | ||
|
|
0696c5cb4f | ||
|
|
ac855ab179 | ||
|
|
42c0798077 | ||
|
|
cc3b28b23c | ||
|
|
d69e294d54 | ||
|
|
d679252ba9 | ||
|
|
94fc5d2769 | ||
|
|
fbe88c06db | ||
|
|
dd1edaa6c9 | ||
|
|
b23251d05b | ||
|
|
83e19216ab | ||
|
|
1399c7a969 | ||
|
|
8d104851ad | ||
|
|
9c83fa1099 | ||
|
|
f1d5afe328 | ||
|
|
05783e98c9 | ||
|
|
d90cfd8b50 | ||
|
|
c397626530 | ||
|
|
9f072e3d0b | ||
|
|
7547518e7c | ||
|
|
edb93986ef | ||
|
|
8c62a58a18 | ||
|
|
96a8db0243 | ||
|
|
8b4cacf8b8 | ||
|
|
5f15b53ee6 | ||
|
|
7d4b80fc48 | ||
|
|
b73e74f1ff | ||
|
|
909d5833cd | ||
|
|
b9cc118a15 | ||
|
|
1f63615085 | ||
|
|
23ef84e45a | ||
|
|
91be8af121 | ||
|
|
61bce7f6cf | ||
|
|
c195c14b13 | ||
|
|
17fa832443 | ||
|
|
c72886a9b9 | ||
|
|
e09112b7d4 | ||
|
|
f8fd03c2c2 | ||
|
|
d590a0b77f | ||
|
|
f0ffaee217 | ||
|
|
9dfc4d7ee4 | ||
|
|
cb5b8af5f3 | ||
|
|
78196db658 | ||
|
|
d76c9fc704 | ||
|
|
8f122c3e00 | ||
|
|
123f68f096 | ||
|
|
5a84bbf775 | ||
|
|
60af3a26d0 | ||
|
|
060746e274 | ||
|
|
0499631429 | ||
|
|
74c37037e2 | ||
|
|
58222ccf8b | ||
|
|
1998ff0920 | ||
|
|
ab60471266 | ||
|
|
d16da4f8a8 | ||
|
|
731f4a9219 | ||
|
|
83e3b5bbaa | ||
|
|
c1ed0e6f10 | ||
|
|
ef3bb56be9 | ||
|
|
1a1124cf46 | ||
|
|
fbf2727ac6 | ||
|
|
a51a06a36f | ||
|
|
aa48227781 | ||
|
|
1461b486ab | ||
|
|
98778d2277 | ||
|
|
ba7c7e5545 | ||
|
|
60e91b7fd6 | ||
|
|
36ad53b4ff | ||
|
|
44d514119e | ||
|
|
55c304328a | ||
|
|
39ef958bfe | ||
|
|
082c55dd78 | ||
|
|
c45e92d78b | ||
|
|
7673ce8ea2 | ||
|
|
6a9f78ac46 | ||
|
|
48d76ed0af | ||
|
|
838e9ec947 | ||
|
|
826f4f39da | ||
|
|
188632cd96 | ||
|
|
e5407603f0 | ||
|
|
f1693e3005 | ||
|
|
4d81cb5d3f | ||
|
|
fa08f5a7bf | ||
|
|
69132c66e3 | ||
|
|
74cf13eb58 | ||
|
|
448914a5aa | ||
|
|
2f21f1bedb | ||
|
|
165452a0ab | ||
|
|
b771fc560b | ||
|
|
21131bd5e8 | ||
|
|
a76c7b0ca1 | ||
|
|
b8fad78d3e | ||
|
|
8f42bef2b1 | ||
|
|
020143f0f9 | ||
|
|
416c33ed00 | ||
|
|
3884d606b7 | ||
|
|
4628627943 | ||
|
|
d86ae5794a | ||
|
|
9e065adae8 | ||
|
|
0a7c0b62a7 | ||
|
|
67d49a693d | ||
|
|
4ddb702ba7 | ||
|
|
30f55d33f4 | ||
|
|
a7cb54931c | ||
|
|
dc4108d6f2 | ||
|
|
7d1dae1071 | ||
|
|
302a4ef4ed | ||
|
|
6457c33280 | ||
|
|
87e37ee121 | ||
|
|
e53c7f7350 | ||
|
|
a5c0809f38 | ||
|
|
01df19d360 | ||
|
|
e63e685bc7 | ||
|
|
002ac9e03e | ||
|
|
b825e977f3 | ||
|
|
0533ba01c8 | ||
|
|
f084699341 | ||
|
|
955b6d4cbd | ||
|
|
1b5a00cad9 | ||
|
|
a7b362e1c0 | ||
|
|
eb67d55f0d | ||
|
|
807f534c24 | ||
|
|
11f34c3bc5 | ||
|
|
dbf066b89c | ||
|
|
45551f4bc4 | ||
|
|
7f5866ab8d | ||
|
|
e450f6c247 | ||
|
|
493a3e3d92 | ||
|
|
3e4d4a2115 | ||
|
|
b3b6d52bdd | ||
|
|
6ba46d4eec | ||
|
|
5af2d92100 | ||
|
|
3fadc67327 | ||
|
|
91c1b20c7b | ||
|
|
0351219903 | ||
|
|
4b067d2ec5 | ||
|
|
d9f9e7ca6f | ||
|
|
9e55d8f4c8 | ||
|
|
97a760a0dd | ||
|
|
f491bc6a22 | ||
|
|
cde1b89615 | ||
|
|
17fc0aeaad | ||
|
|
c93bdfeed8 | ||
|
|
4fd08b0b00 | ||
|
|
8dd566b9e9 | ||
|
|
fca2929de0 | ||
|
|
d67bdbc550 | ||
|
|
c3894c24de | ||
|
|
208b11df69 | ||
|
|
0a860bd964 | ||
|
|
15efc3f1dc | ||
|
|
2d0f03b66c | ||
|
|
d7e9d313a2 | ||
|
|
7a246e7887 | ||
|
|
c04dbdb9e9 | ||
|
|
fc372d17a2 | ||
|
|
79986d8262 | ||
|
|
ef698d4562 | ||
|
|
1238fc359e | ||
|
|
79d150061c | ||
|
|
2198b74df9 | ||
|
|
bf37947a99 | ||
|
|
1fe9b3e693 | ||
|
|
762591bf35 | ||
|
|
04f401c70e | ||
|
|
84b51fc1a5 | ||
|
|
1573957cc8 | ||
|
|
038e50fa0c | ||
|
|
58d6aea217 | ||
|
|
4c78e188ce | ||
|
|
9d8060496c | ||
|
|
67b28491a4 | ||
|
|
7ea1f1d492 | ||
|
|
1b86e89efb | ||
|
|
0c769bdba9 | ||
|
|
e80a6978ec | ||
|
|
da8bf2667d | ||
|
|
a37bce2bdc | ||
|
|
3dd0b24cc3 | ||
|
|
a8c8c28f00 | ||
|
|
315a462603 | ||
|
|
ddeddd455e | ||
|
|
d3140ed983 | ||
|
|
fc250a33a1 | ||
|
|
92911cbabd | ||
|
|
a9715d8c74 | ||
|
|
bd12d1874f | ||
|
|
11b8537d17 | ||
|
|
f7283bf2eb | ||
|
|
d5d7b8385c | ||
|
|
d8abd074df | ||
|
|
56d43680f1 | ||
|
|
03df22a4c5 | ||
|
|
bbdb5dbb23 | ||
|
|
6b2cdbb74d | ||
|
|
90930e2bb8 | ||
|
|
35260c4c31 | ||
|
|
684f06b760 | ||
|
|
1e34fb4a4f | ||
|
|
e2ec6d0381 | ||
|
|
78c6b8c2a9 | ||
|
|
d7139997dd | ||
|
|
5b0bec0c09 | ||
|
|
e3a5ac5818 | ||
|
|
12af84f19f | ||
|
|
2d460e5738 | ||
|
|
dff64e2366 | ||
|
|
0aa1a231c3 | ||
|
|
d991c898ac | ||
|
|
ca4eeaa196 | ||
|
|
ef37e991d8 | ||
|
|
9426df0095 | ||
|
|
29fd2fe1c1 | ||
|
|
3c85afdbf5 | ||
|
|
7893e6124d | ||
|
|
fcf008b4fd | ||
|
|
b2c83a7cd0 | ||
|
|
2d1e0616a7 | ||
|
|
6b25687454 | ||
|
|
882fd6a926 | ||
|
|
cdc36a8597 | ||
|
|
f16cead9d7 | ||
|
|
d7e7ecce3f | ||
|
|
3914b212ae | ||
|
|
8af69b3261 | ||
|
|
21d1cd0519 | ||
|
|
c7119c7bc5 | ||
|
|
6780c890cd | ||
|
|
9241ea80f8 | ||
|
|
bf023053fc | ||
|
|
c8681de1ee | ||
|
|
34bcb02a3f | ||
|
|
4b8cac5557 | ||
|
|
8926425aed | ||
|
|
e27209469e | ||
|
|
797c3ee178 | ||
|
|
e3bd4212de | ||
|
|
a7b34f7d79 | ||
|
|
4b196c7d96 | ||
|
|
ad251a8285 | ||
|
|
603e5ba0f1 | ||
|
|
cb24f376ce | ||
|
|
f3b08ed289 | ||
|
|
21da0e1c46 | ||
|
|
9e9531ff0d | ||
|
|
835bc6ad56 | ||
|
|
2b71971821 | ||
|
|
084890f739 | ||
|
|
3121f68e39 | ||
|
|
9066a68879 | ||
|
|
7e03bfd5a6 | ||
|
|
cf7ee859c9 | ||
|
|
7ececc6bce | ||
|
|
b3fe1eb6ed | ||
|
|
5d54e0d66d | ||
|
|
3e0e0a5833 | ||
|
|
3d5ca378ec | ||
|
|
c6fd41b733 | ||
|
|
faba1351fc | ||
|
|
d07a86d556 | ||
|
|
ec9dfe108b | ||
|
|
d20ceacd7b | ||
|
|
3bfb3ff135 | ||
|
|
2114708210 | ||
|
|
e8c03edebf | ||
|
|
216d24875d | ||
|
|
e8979928d6 | ||
|
|
efce48cddf | ||
|
|
19cf23b3ac | ||
|
|
d98d82d664 | ||
|
|
639be2dc82 | ||
|
|
082de2cc7e | ||
|
|
95200fc351 | ||
|
|
b2274da946 | ||
|
|
5ff4375c7b | ||
|
|
2f094b74e5 | ||
|
|
8f8adf7b71 | ||
|
|
cc4210041b | ||
|
|
93316b724d | ||
|
|
8a6383a55d | ||
|
|
aa7b6f77a5 | ||
|
|
a3870d3ede | ||
|
|
f716b4e9ff | ||
|
|
559543984f | ||
|
|
3acbd0596b | ||
|
|
4e6ccb0da1 | ||
|
|
15f85de4d8 | ||
|
|
3b909651aa | ||
|
|
7cc55d039d | ||
|
|
c978ad0668 | ||
|
|
08a96ff859 | ||
|
|
4cf71b4593 | ||
|
|
ea1301806d | ||
|
|
2086a31954 | ||
|
|
747d30a3a6 | ||
|
|
4c390c04d6 | ||
|
|
153b35ba68 | ||
|
|
2f4c5cbf48 | ||
|
|
fd280b266b | ||
|
|
281b64bb96 | ||
|
|
af80848208 | ||
|
|
9de743810e | ||
|
|
f4237d9b7d | ||
|
|
52ba4b8a17 | ||
|
|
db8df476b2 | ||
|
|
d796cc7dc0 | ||
|
|
679463220f | ||
|
|
145b606a06 | ||
|
|
b76d045a40 | ||
|
|
957a5a5835 | ||
|
|
2efb5a0a73 | ||
|
|
442fedeef0 | ||
|
|
138188eb1c | ||
|
|
5dfcb53964 | ||
|
|
d466fa9017 | ||
|
|
0b1f430935 | ||
|
|
9e76e50c9a | ||
|
|
42b060e48a | ||
|
|
d98e60e4e5 | ||
|
|
4572f8711a | ||
|
|
b6bb1ea17e | ||
|
|
681be1284c | ||
|
|
40b01582b8 | ||
|
|
031b3cbadf | ||
|
|
545f8dddd4 | ||
|
|
7aa22dd6f5 | ||
|
|
447aa551f6 | ||
|
|
e004aa6566 | ||
|
|
5db149adc2 | ||
|
|
23f5075d93 | ||
|
|
ddb5798b8c | ||
|
|
cde51065bf | ||
|
|
e47c65c6fc | ||
|
|
d6859eb744 | ||
|
|
79cd784383 | ||
|
|
1c0ca55627 | ||
|
|
1d6aa2e276 | ||
|
|
a0b3b24984 | ||
|
|
26ccb97f63 | ||
|
|
23ac852023 | ||
|
|
bcb6e066aa | ||
|
|
2a5aac1101 | ||
|
|
dc8d0e310c | ||
|
|
72ca730f4b | ||
|
|
6b7c3d99c4 | ||
|
|
4dec08b4bd | ||
|
|
9ccf404dde | ||
|
|
4b5969f582 | ||
|
|
fb2bf934ac | ||
|
|
df76e24e7c | ||
|
|
f98c4fbe2a | ||
|
|
9e0aa3200c | ||
|
|
8080af8866 | ||
|
|
f227796a09 | ||
|
|
b6fc0f3536 | ||
|
|
556685e150 | ||
|
|
eb60b5d6b6 | ||
|
|
84a139f55b | ||
|
|
70f3b6fa79 | ||
|
|
2d45903ee3 | ||
|
|
baa4fc5a9f | ||
|
|
a8d34166c4 | ||
|
|
a6edf2689d | ||
|
|
3940631e21 | ||
|
|
7141e93243 | ||
|
|
53ecb27948 | ||
|
|
f1d8d5b8fe | ||
|
|
48a482df24 | ||
|
|
08ab1b6adf | ||
|
|
2c33601a86 | ||
|
|
55552cd6a2 | ||
|
|
7e0e644564 | ||
|
|
8b1c25f441 | ||
|
|
ca06098649 | ||
|
|
d2b0a5913b | ||
|
|
2fafbfb291 | ||
|
|
08d900994d | ||
|
|
427066d937 | ||
|
|
db0312e0fe | ||
|
|
0337387f97 | ||
|
|
6afccefb01 | ||
|
|
db7312b43f | ||
|
|
89e3f2bee0 | ||
|
|
7b130aec79 | ||
|
|
13960bac08 | ||
|
|
230a42ffc0 | ||
|
|
31465d7570 | ||
|
|
07c7dd6242 | ||
|
|
6f8319519b | ||
|
|
3469f4a4f7 | ||
|
|
b22e3e611d | ||
|
|
3be97b7ab5 | ||
|
|
1a9dce025f | ||
|
|
cbb57c0148 | ||
|
|
92810cbeb2 | ||
|
|
039f2439b5 | ||
|
|
a190726caf | ||
|
|
745f8e7716 | ||
|
|
a3bf833a9a | ||
|
|
f2cb7babcf | ||
|
|
ce0966d186 | ||
|
|
d143af398e | ||
|
|
a1b0ff6b29 | ||
|
|
1b130cfe5d | ||
|
|
c3e39f57f8 | ||
|
|
ede4ed13e0 | ||
|
|
316cf359c1 | ||
|
|
343dff5c51 | ||
|
|
a0d61dcea5 | ||
|
|
f02e5b5e45 | ||
|
|
c293318cbd | ||
|
|
ddf5cdcb3f | ||
|
|
761d446fa3 | ||
|
|
5e012ebf95 | ||
|
|
7d6cb3f61f | ||
|
|
a414d788fe | ||
|
|
4134e60c8d | ||
|
|
88084975ad | ||
|
|
4b14e27523 | ||
|
|
45eb8bcc81 | ||
|
|
8b6e6ed67d | ||
|
|
18a7a9458c | ||
|
|
3cca881881 | ||
|
|
2a68da3dad | ||
|
|
9f5b24d889 | ||
|
|
e9b24a6159 | ||
|
|
39a3b2e8ff | ||
|
|
09caa4ba63 | ||
|
|
a0eeb30e0b | ||
|
|
f1628b80fe | ||
|
|
5c65b8a03e | ||
|
|
c2a61b30db | ||
|
|
82a7074d86 | ||
|
|
8a21b0306d | ||
|
|
c0afb8ef29 | ||
|
|
baed2d5bbc | ||
|
|
cccbc4555c | ||
|
|
df3835a611 | ||
|
|
758b86c4b0 | ||
|
|
16f8c419bc | ||
|
|
1eca50e421 | ||
|
|
d2e84c1a30 | ||
|
|
1c1615da2f | ||
|
|
cb4e01b4df | ||
|
|
00f65f2c53 | ||
|
|
ac2522fe91 | ||
|
|
82f20b28cf | ||
|
|
fd8ed5883e | ||
|
|
5fea8d25a8 | ||
|
|
01fb378320 | ||
|
|
3f8c92b233 | ||
|
|
c846f94c8e | ||
|
|
a5bf7c50f4 | ||
|
|
8066b2353b | ||
|
|
b81c61cae4 | ||
|
|
54d3f674e1 | ||
|
|
14f5ab6b90 | ||
|
|
555dec78d9 | ||
|
|
267879c91a | ||
|
|
2d48220165 | ||
|
|
4d9242ae89 | ||
|
|
fae86c3dec | ||
|
|
24211219d8 | ||
|
|
2c0d63b569 | ||
|
|
e254c5fa62 | ||
|
|
aba16247b4 | ||
|
|
6fc0914dc0 | ||
|
|
8137494932 | ||
|
|
baad3927b9 | ||
|
|
94647d6c10 | ||
|
|
e1aedff092 | ||
|
|
8a2b77131e | ||
|
|
b5dd858897 | ||
|
|
70d42fb076 | ||
|
|
9ede4b8eea | ||
|
|
d944a9ec68 | ||
|
|
bbd82ac6fe | ||
|
|
4439849d66 | ||
|
|
061d0fd953 | ||
|
|
43c4eef53b | ||
|
|
ef40a31ac8 | ||
|
|
59ce329431 |
No files matched your search
-11
@@ -1,11 +0,0 @@
|
||||
[run]
|
||||
branch = True
|
||||
parallel = True
|
||||
concurrency = thread,multiprocessing
|
||||
omit =
|
||||
*/constants/*
|
||||
source =
|
||||
pwn
|
||||
pwnlib
|
||||
~/.pwntools-cache-2.7/
|
||||
~/.pwntools-cache-3.8/
|
||||
@@ -12,7 +12,7 @@ Thanks for contributing to Pwntools! Ideas from the community help make Pwntoo
|
||||
If you've got an idea for a new feature, please provide information about:
|
||||
|
||||
* What the feature does
|
||||
* Why the feature should exit
|
||||
* Why the feature should exist
|
||||
* What tests should be included
|
||||
|
||||
If you think you can write the feature yourself, please submit a Pull Request and we can review your changes!
|
||||
@@ -0,0 +1,8 @@
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every week
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Android Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
android-test:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.8]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache for pip
|
||||
uses: actions/cache@v3
|
||||
id: cache-pip
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ matrix.os }}-cache-pip
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends -o Acquire::Retries=3 \
|
||||
gdb gdbserver socat \
|
||||
qemu-user-static \
|
||||
binutils-aarch64-linux-gnu \
|
||||
binutils-arm-linux-gnueabihf \
|
||||
libc6-dbg
|
||||
|
||||
- name: Install Android AVD
|
||||
run: |
|
||||
source travis/setup_avd_fast.sh
|
||||
sed -i 's/skip_android = True/skip_android = False/' docs/source/conf.py
|
||||
set | grep ^PATH >.android.env
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
python setup.py egg_info
|
||||
pip install --upgrade --editable .
|
||||
|
||||
- name: Sanity checks
|
||||
run: PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
|
||||
|
||||
- name: Install documentation dependencies
|
||||
run: pip install -r docs/requirements.txt
|
||||
|
||||
- name: Coverage Doctests (Android Only)
|
||||
run: |
|
||||
source .android.env
|
||||
PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest docs/source/adb.rst
|
||||
@@ -1,17 +1,21 @@
|
||||
name: Changelog
|
||||
on: [pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- pwnlib/**
|
||||
- pwn/**
|
||||
env:
|
||||
GITHUB_BASE: origin/${{ github.event.pull_request.base.ref }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -20,7 +24,7 @@ jobs:
|
||||
if git log --stat ${GITHUB_BASE}..HEAD | grep CHANGELOG.md; then
|
||||
echo 'Changelog updated :D'
|
||||
else
|
||||
if git log --stat ${GITHUB_BASE}..HEAD | grep '++\|--'; then
|
||||
if git log --stat ${GITHUB_BASE}..HEAD pwnlib pwn | grep '++\|--'; then
|
||||
echo 'Major changes detected, changelog required!'
|
||||
false
|
||||
else
|
||||
|
||||
+99
-65
@@ -5,29 +5,44 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.8]
|
||||
python_version: ['2.7', '3.10']
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-depth: 20
|
||||
|
||||
- name: Git History 2
|
||||
run: git log --oneline --graph -10
|
||||
- name: Git History
|
||||
run: |
|
||||
git fetch origin
|
||||
git log --oneline --graph -10
|
||||
|
||||
- name: Cache for pip
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v3
|
||||
id: cache-pip
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ matrix.os }}-cache-pip
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
- name: Set up Python ${{ matrix.python_version }}
|
||||
if: matrix.python_version != '2.7'
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
python-version: ${{ matrix.python_version }}
|
||||
|
||||
- name: Set up Python 2.7
|
||||
if: matrix.python_version == '2.7'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
python2.7 python2.7-dev python2-pip-whl
|
||||
sudo ln -sf python2.7 /usr/bin/python
|
||||
export PYTHONPATH=`echo /usr/share/python-wheels/pip-*py2*.whl`
|
||||
sudo --preserve-env=PYTHONPATH python -m pip install --upgrade pip setuptools wheel
|
||||
sudo chown -R $USER /usr/local/lib/python2.7
|
||||
|
||||
|
||||
- name: Verify tag against version
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
@@ -42,47 +57,33 @@ jobs:
|
||||
[ "$vsetup" = "$vpwnlib" ]
|
||||
[ "$GITHUB_TAG" = "$vsetup" ]
|
||||
|
||||
- name: Detect whether java is needed
|
||||
id: java-needed
|
||||
env:
|
||||
GITHUB_REF: ${{ github.event.ref }}
|
||||
GITHUB_COMMIT_RANGE: ${{ github.event.before }}...${{ github.event.after }}
|
||||
run: |
|
||||
if echo "$GITHUB_REF" | grep -Eq 'staging|tags'; then
|
||||
echo "Found release or important branch ($GITHUB_REF), forcing tests."
|
||||
elif ! git show "$GITHUB_COMMIT_RANGE" >/dev/null; then
|
||||
echo 'Incorrect commit range, forcing android tests.'
|
||||
elif git log --stat "$GITHUB_COMMIT_RANGE" | grep -iE 'android|\<adb\>'; then
|
||||
echo 'Found Android-related commits, forcing tests.'
|
||||
else
|
||||
# clear files that cause Android doctests
|
||||
: > docs/source/adb.rst > docs/source/protocols/adb.rst
|
||||
exit 0
|
||||
fi
|
||||
echo ::set-output name=need::openjdk-8-jre-headless
|
||||
|
||||
- name: Install Linux dependencies
|
||||
env:
|
||||
ANDROID_JRE: ${{ steps.java-needed.outputs.need }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends -o Acquire::Retries=3 \
|
||||
ash bash-static dash ksh mksh zsh \
|
||||
pandoc gdb gdbserver socat sshpass \
|
||||
python3-rpyc \
|
||||
gdb gdbserver socat \
|
||||
binutils-multiarch qemu-user-static \
|
||||
binutils-aarch64-linux-gnu \
|
||||
binutils-arm-linux-gnueabihf \
|
||||
binutils-mips-linux-gnu \
|
||||
binutils-msp430 \
|
||||
binutils-powerpc-linux-gnu \
|
||||
binutils-s390x-linux-gnu \
|
||||
binutils-sparc64-linux-gnu \
|
||||
gcc-multilib \
|
||||
libc6-dbg \
|
||||
$ANDROID_JRE
|
||||
|
||||
- name: Install android avd
|
||||
if: steps.java-needed.outputs.need
|
||||
elfutils \
|
||||
patchelf
|
||||
|
||||
- name: Testing Corefiles
|
||||
run: |
|
||||
USER=travis source travis/install.sh
|
||||
set | egrep '^(ANDROID|PATH)' >.android.env
|
||||
ulimit -a
|
||||
ulimit -c unlimited
|
||||
cat /proc/sys/kernel/core_pattern
|
||||
cat /proc/sys/kernel/core_uses_pid
|
||||
( cd $(mktemp -d); sh -c 'kill -11 $$' || true; ls -la ./*core* /var/crash/*.crash /var/lib/apport/coredump/core*) || true
|
||||
|
||||
- name: Set up SSH
|
||||
run: |
|
||||
@@ -91,44 +92,43 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install --upgrade wheel build
|
||||
pip install --upgrade flake8 appdirs
|
||||
python setup.py egg_info
|
||||
pip install --upgrade --editable .
|
||||
|
||||
- name: Sanity checks
|
||||
run: PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
|
||||
run: PWNLIB_NOTERM=1 python -bb -c 'from pwn import *; print(pwnlib.term.term_mode)'
|
||||
|
||||
- name: Install documentation dependencies
|
||||
run: pip install -r docs/requirements.txt
|
||||
|
||||
- name: Disable broken tests
|
||||
run: |
|
||||
rm -f docs/source/elf/corefile.rst
|
||||
run: pip install -r docs/requirements.txt
|
||||
|
||||
- name: Manually install non-broken Unicorn
|
||||
run: pip install unicorn==1.0.2rc3
|
||||
if: matrix.python_version == '2.7'
|
||||
run: pip install unicorn==2.0.0rc7
|
||||
|
||||
- name: Disable yama ptrace_scope
|
||||
run: |
|
||||
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # required by some gdb doctests
|
||||
|
||||
- name: Coverage doctests
|
||||
run: |
|
||||
source .android.env || :
|
||||
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # required by some gdb doctests
|
||||
PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest
|
||||
PWNLIB_NOTERM=1 python -bb -m coverage run -m sphinx -b doctest docs/source docs/build/doctest
|
||||
|
||||
- name: Coverage running examples
|
||||
run: |
|
||||
export TERM=linux
|
||||
set -x
|
||||
python travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit.py
|
||||
python travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit2.py || : # can fail randomly?
|
||||
coverage run examples/asm.py
|
||||
coverage run examples/asm.py
|
||||
coverage run examples/text.py
|
||||
python -bb travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit.py
|
||||
python -bb travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit2.py || : # can fail randomly?
|
||||
python -bb -m coverage run examples/asm.py
|
||||
python -bb -m coverage run examples/asm.py
|
||||
python -bb -m coverage run examples/text.py
|
||||
# for f in examples/sigreturn_corefile_*.py; do coverage run "$f"; done # XXX something is wrong
|
||||
|
||||
- name: Coverage running commandline tools
|
||||
run: |
|
||||
export TERM=linux
|
||||
pwn() { ( set +x; cmd=$1; shift; PYTHONUNBUFFERED=1 exec coverage run -m pwnlib.commandline."$cmd" "$@" ) }
|
||||
pwn() { ( set +x; cmd=$1; shift; PYTHONUNBUFFERED=1 exec python -bb -m coverage run -m pwnlib.commandline."$cmd" "$@" ) }
|
||||
set -x
|
||||
|
||||
pwn cyclic 32
|
||||
@@ -152,6 +152,11 @@ jobs:
|
||||
pwn disasm --color ff3424c3ebfe
|
||||
pwn asm -f hex nop
|
||||
|
||||
pwn hex ABCD
|
||||
pwn hex ABCD --separator ' '
|
||||
pwn hex ABCD --prefix '\x'
|
||||
pwn hex ABCD -p '0x' -s ' '
|
||||
|
||||
pwn hex abcd
|
||||
pwn unhex 4141 4141
|
||||
|
||||
@@ -168,27 +173,55 @@ jobs:
|
||||
pwn constgrep ^MAP_ 0
|
||||
pwn constgrep -e O_RDWR
|
||||
|
||||
- name: Build source and wheel distributions
|
||||
run: |
|
||||
python setup.py sdist
|
||||
python setup.py bdist_wheel --universal
|
||||
pwn libcdb file /lib/x86_64-linux-gnu/libc.so.6
|
||||
pwn libcdb lookup puts 5f0 __libc_start_main_ret d0a
|
||||
pwn libcdb hash b229d1da1e161f95e839cf90cded5f719e5de308
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
- name: Build source and wheel distributions
|
||||
if: matrix.python_version > '2.7'
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: packages
|
||||
path: dist/
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage
|
||||
path: .coverage*
|
||||
|
||||
|
||||
upload-coverage:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 20
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: coverage
|
||||
path: .
|
||||
|
||||
- name: Install coveralls
|
||||
run: |
|
||||
pip install tomli coveralls
|
||||
|
||||
- name: Upload coverage to coveralls.io
|
||||
run: |
|
||||
coverage combine
|
||||
COVERALLS_REPO_TOKEN=PP20MEgztXIQJJTguQwe2jeCh6Bm4lkbv coveralls
|
||||
|
||||
|
||||
staging-merge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'Gallopsled' && github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/') && endsWith(github.event.ref, '-staging')
|
||||
needs: test
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 20
|
||||
- name: Push changes to protected branch
|
||||
@@ -199,23 +232,24 @@ jobs:
|
||||
TARGET=${BRANCH%-staging}
|
||||
git branch -f "$TARGET"
|
||||
git push origin "$TARGET"
|
||||
git push origin --delete "$BRANCH"
|
||||
|
||||
|
||||
pypi:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
permissions:
|
||||
id-token: write
|
||||
needs: test
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: packages
|
||||
path: dist
|
||||
|
||||
- name: Publish package
|
||||
uses: pypa/gh-action-pypi-publish@v1.1.0
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_password }}
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
|
||||
- if: failure()
|
||||
run: ls -R
|
||||
@@ -0,0 +1,64 @@
|
||||
name: Publish Docker images
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- beta
|
||||
- stable
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'Gallopsled'
|
||||
steps:
|
||||
# Required for subdirectories in Git context
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build and push base image
|
||||
uses: docker/build-push-action@v4
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
context: "{{defaultContext}}:extra/docker/base"
|
||||
push: true
|
||||
tags: pwntools/pwntools:base
|
||||
|
||||
- name: Build and push stable image
|
||||
uses: docker/build-push-action@v4
|
||||
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/stable')
|
||||
with:
|
||||
context: "{{defaultContext}}:extra/docker/stable"
|
||||
push: true
|
||||
tags: pwntools/pwntools:stable
|
||||
|
||||
- name: Build and push beta image
|
||||
uses: docker/build-push-action@v4
|
||||
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/beta')
|
||||
with:
|
||||
context: "{{defaultContext}}:extra/docker/beta"
|
||||
push: true
|
||||
tags: pwntools/pwntools:beta
|
||||
|
||||
- name: Build and push dev image
|
||||
uses: docker/build-push-action@v4
|
||||
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/dev')
|
||||
with:
|
||||
context: "{{defaultContext}}:extra/docker/dev"
|
||||
push: true
|
||||
tags: |
|
||||
pwntools/pwntools:dev
|
||||
pwntools/pwntools:latest
|
||||
|
||||
- name: Build and push ci image
|
||||
uses: docker/build-push-action@v4
|
||||
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/dev')
|
||||
with:
|
||||
context: "{{defaultContext}}:travis/docker"
|
||||
push: true
|
||||
tags: pwntools/pwntools:ci
|
||||
@@ -10,24 +10,26 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache for pip
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v3
|
||||
id: cache-pip
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ matrix.os }}-cache-pip
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Lint
|
||||
- name: Critical 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__
|
||||
flake8 . --count --select=E9,F63,F7,E71 --show-source --statistics --exclude=android-?dk # TODO: Add F82
|
||||
|
||||
- name: Style lint
|
||||
run: |
|
||||
flake8 pwnlib setup.py docs travis --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
flake8 examples --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --ignore='F403,F405'
|
||||
flake8 pwn --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --ignore='F401,F403,F405'
|
||||
@@ -1,5 +1,7 @@
|
||||
name: Check for merge markers
|
||||
on: [pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
types: [synchronize]
|
||||
env:
|
||||
GITHUB_BASE: origin/${{ github.event.pull_request.base.ref }}
|
||||
|
||||
@@ -11,7 +13,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
name: PyLint
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.8]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache for pip
|
||||
uses: actions/cache@v3
|
||||
id: cache-pip
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ matrix.os }}-cache-pip
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: PyLint
|
||||
run: |
|
||||
set -x
|
||||
pip install pylint
|
||||
pip install --upgrade -e .
|
||||
pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- > current.txt
|
||||
git fetch origin
|
||||
git checkout origin/"$GITHUB_BASE_REF"
|
||||
pylint --exit-zero --errors-only pwnlib -f parseable | cut -d ' ' -f2- > base.txt
|
||||
if diff base.txt current.txt | grep '>'; then
|
||||
false
|
||||
fi
|
||||
@@ -13,7 +13,12 @@ MANIFEST
|
||||
dist
|
||||
venv
|
||||
.vscode
|
||||
.idea
|
||||
*.egg-info
|
||||
*.core
|
||||
.coverage
|
||||
.coverage.*
|
||||
.idea
|
||||
__pycache__
|
||||
!.github
|
||||
.DS_Store
|
||||
@@ -0,0 +1,12 @@
|
||||
# https://docs.readthedocs.io/en/stable/config-file/v2.html
|
||||
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3"
|
||||
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
language: python
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- lib32stdc++6
|
||||
- ash
|
||||
- bash
|
||||
- dash
|
||||
- ksh
|
||||
- mksh
|
||||
- zsh
|
||||
- pandoc
|
||||
- gdb
|
||||
- socat
|
||||
- sshpass
|
||||
- binutils
|
||||
- qemu-user-static
|
||||
- binutils-multiarch
|
||||
- binutils-aarch64-linux-gnu
|
||||
- binutils-arm-linux-gnueabihf
|
||||
- binutils-mips-linux-gnu
|
||||
- binutils-powerpc-linux-gnu
|
||||
- bash-static
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
- usr
|
||||
- /home/travis/virtualenv/python2.7.15/lib/python2.7/site-packages/
|
||||
- /home/travis/virtualenv/python2.7.15/bin/
|
||||
- /home/travis/virtualenv/python3.8.*/lib/python3.8/site-packages/
|
||||
- /home/travis/virtualenv/python3.8.*/bin/
|
||||
- docs/build/doctest/.doctrees
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.8"
|
||||
before_install:
|
||||
- echo $-
|
||||
- source travis/install.sh
|
||||
- source travis/ssh_setup.sh
|
||||
- echo $-
|
||||
install:
|
||||
- pip install --upgrade pip
|
||||
- pip install --upgrade flake8 appdirs # https://github.com/ActiveState/appdirs/issues/89#issuecomment-282326570
|
||||
- python setup.py egg_info # pypa/pip#6275
|
||||
- pip install --upgrade --editable .
|
||||
- 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)'
|
||||
- sudo sh -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
|
||||
script:
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
- flake8 . --count --select=E9,F63,F7 --show-source --statistics --exclude=android-?dk # TODO: Add F82
|
||||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||
- PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest
|
||||
- coverage combine
|
||||
after_success:
|
||||
- coveralls
|
||||
- source travis/update_demo.sh
|
||||
+346
-7
@@ -9,9 +9,23 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
|
||||
| Version | Branch | Release Date |
|
||||
| ---------------- | -------- | ---------------------- |
|
||||
| [4.4.0](#440) | `dev` | Sep 1, 2020 (planned)
|
||||
| [4.3.0](#430) | `beta` | Aug 1, 2020 (planned)
|
||||
| [4.2.0](#420) | `stable` | Jul 3, 2020 (planned)
|
||||
| [4.14.0](#4140-dev) | `dev` |
|
||||
| [4.13.0](#4130-beta) | `beta` |
|
||||
| [4.12.0](#4120-stable) | `stable` | Feb 22, 2024
|
||||
| [4.11.1](#4111) | | Nov 14, 2023
|
||||
| [4.11.0](#4110) | | Sep 15, 2023
|
||||
| [4.10.0](#4100) | | May 21, 2023
|
||||
| [4.9.0](#490) | | Dec 29, 2022
|
||||
| [4.8.0](#480) | | Apr 21, 2022
|
||||
| [4.7.1](#471) | | Apr 20, 2022
|
||||
| [4.7.0](#470) | | Nov 15, 2021
|
||||
| [4.6.0](#460) | | Jul 12, 2021
|
||||
| [4.5.1](#451) | | May 30, 2021
|
||||
| [4.5.0](#450) | | Apr 30, 2021
|
||||
| [4.4.0](#440) | | Mar 29, 2021
|
||||
| [4.3.1](#431) | | Nov 29, 2020
|
||||
| [4.3.0](#430) | | Oct 20, 2020
|
||||
| [4.2.0](#420) | | Jul 3, 2020
|
||||
| [4.1.7](#417) | | Jun 30, 2020
|
||||
| [4.1.5](#415) | | Jun 27, 2020
|
||||
| [4.1.4](#414) | | Jun 26, 2020
|
||||
@@ -55,13 +69,336 @@ 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.4.0 (`dev`)
|
||||
## 4.14.0 (`dev`)
|
||||
|
||||
|
||||
## 4.13.0 (`beta`)
|
||||
|
||||
- [#2242][2242] Term module revamp: activating special handling of terminal only when necessary
|
||||
- [#2277][2277] elf: Resolve more relocations into GOT entries
|
||||
- [#2281][2281] FIX: Getting right amount of data for search fix
|
||||
- [#2293][2293] Add x86 CET status to checksec output
|
||||
- [#1763][1763] Allow to add to the existing environment in `process` instead of replacing it
|
||||
- [#2307][2307] Fix `pwn libcdb file` crashing if "/bin/sh" string was not found
|
||||
- [#2309][2309] Detect challenge binary and libc in `pwn template`
|
||||
- [#2308][2308] Fix WinExec shellcraft to make sure it's 16 byte aligned
|
||||
- [#2279][2279] Make `pwn template` always set context.binary
|
||||
- [#2310][2310] Add support to start a process on Windows
|
||||
- [#2335][2335] Add lookup optimizations in DynELF
|
||||
- [#2334][2334] Speed up disasm commandline tool with colored output
|
||||
- [#2328][2328] Lookup using $PATHEXT file extensions in `which` on Windows
|
||||
- [#2189][2189] Explicitly define p64/u64 functions for IDE support
|
||||
- [#2339][2339] Fix: Allow setting attributes on gdb Breakpoints
|
||||
- [#2323][2323] Retry failed lookups after one week in libcdb
|
||||
- [#2325][2325] Match against local system libc first in libcdb
|
||||
- [#2336][2336] Add `ELF.stripped` and `ELF.debuginfo` properties
|
||||
- [#2161][2161] Add basic support for darwin shellcraft/asm/disasm/run_shellcode/run_assembly
|
||||
- [#2161][2161] Fix freebsd amd64 SyscallABI
|
||||
- [#2160][2161] Fix invalid shellcraft.mov on arm64
|
||||
- [#2284][2161] Fix invalid shellcraft.pushstr_array on arm64
|
||||
- [#2345][2345] Fix pwn constgrep when it matches a non-constant type
|
||||
- [#2338][2338] Fix: follow symlink for libs on ssh connection
|
||||
- [#2341][2341] Launch GDB correctly in iTerm on Mac
|
||||
- [#2268][2268] Add a `flatten` argument to `ssh.libs`
|
||||
- [#2347][2347] Fix/workaround Unicorn Engine 1GB limit that calls exit()
|
||||
- [#2233][2233] Fix gdb.debug: exe parameter now respected, allow empty argv
|
||||
|
||||
[2242]: https://github.com/Gallopsled/pwntools/pull/2242
|
||||
[2277]: https://github.com/Gallopsled/pwntools/pull/2277
|
||||
[2281]: https://github.com/Gallopsled/pwntools/pull/2281
|
||||
[2293]: https://github.com/Gallopsled/pwntools/pull/2293
|
||||
[1763]: https://github.com/Gallopsled/pwntools/pull/1763
|
||||
[2307]: https://github.com/Gallopsled/pwntools/pull/2307
|
||||
[2309]: https://github.com/Gallopsled/pwntools/pull/2309
|
||||
[2308]: https://github.com/Gallopsled/pwntools/pull/2308
|
||||
[2279]: https://github.com/Gallopsled/pwntools/pull/2279
|
||||
[2310]: https://github.com/Gallopsled/pwntools/pull/2310
|
||||
[2335]: https://github.com/Gallopsled/pwntools/pull/2335
|
||||
[2334]: https://github.com/Gallopsled/pwntools/pull/2334
|
||||
[2328]: https://github.com/Gallopsled/pwntools/pull/2328
|
||||
[2189]: https://github.com/Gallopsled/pwntools/pull/2189
|
||||
[2339]: https://github.com/Gallopsled/pwntools/pull/2339
|
||||
[2323]: https://github.com/Gallopsled/pwntools/pull/2323
|
||||
[2325]: https://github.com/Gallopsled/pwntools/pull/2325
|
||||
[2336]: https://github.com/Gallopsled/pwntools/pull/2336
|
||||
[2161]: https://github.com/Gallopsled/pwntools/pull/2161
|
||||
[2345]: https://github.com/Gallopsled/pwntools/pull/2345
|
||||
[2338]: https://github.com/Gallopsled/pwntools/pull/2338
|
||||
[2341]: https://github.com/Gallopsled/pwntools/pull/2341
|
||||
[2268]: https://github.com/Gallopsled/pwntools/pull/2268
|
||||
[2347]: https://github.com/Gallopsled/pwntools/pull/2347
|
||||
[2233]: https://github.com/Gallopsled/pwntools/pull/2233
|
||||
|
||||
## 4.12.0 (`stable`)
|
||||
|
||||
- [#2202][2202] Fix `remote` and `listen` in sagemath
|
||||
- [#2117][2117] Add -p (--prefix) and -s (--separator) arguments to `hex` command
|
||||
- [#2221][2221] Add shellcraft.sleep template wrapping SYS_nanosleep
|
||||
- [#2219][2219] Fix passing arguments on the stack in shellcraft syscall template
|
||||
- [#2212][2212] Add `--libc libc.so` argument to `pwn template` command
|
||||
- [#2257][2257] Allow creation of custom templates for `pwn template` command
|
||||
- [#2225][2225] Allow empty argv in ssh.process()
|
||||
- [#2349][2349] Fix term.readline omitting a trailing \n
|
||||
- [#2352][2352] add `RETURN_CONST` as an allowed `_const_code` in safeeval
|
||||
|
||||
[2202]: https://github.com/Gallopsled/pwntools/pull/2202
|
||||
[2117]: https://github.com/Gallopsled/pwntools/pull/2117
|
||||
[2221]: https://github.com/Gallopsled/pwntools/pull/2221
|
||||
[2219]: https://github.com/Gallopsled/pwntools/pull/2219
|
||||
[2212]: https://github.com/Gallopsled/pwntools/pull/2212
|
||||
[2257]: https://github.com/Gallopsled/pwntools/pull/2257
|
||||
[2225]: https://github.com/Gallopsled/pwntools/pull/2225
|
||||
[2349]: https://github.com/Gallopsled/pwntools/pull/2349
|
||||
[2352]: https://github.com/Gallopsled/pwntools/pull/2352
|
||||
|
||||
## 4.11.1
|
||||
|
||||
- [#2271][2271] FIX: Generated shebang with path to python invalid if path contains spaces
|
||||
- [#2272][2272] Fix `tube.clean_and_log` not logging buffered data
|
||||
- [#2281][2281] FIX: Getting right amount of data for search fix
|
||||
- [#2287][2287] Fix `_countdown_handler` not invoking `timeout_change`
|
||||
- [#2294][2294] Fix atexit SEGV in aarch64 loader
|
||||
|
||||
[2271]: https://github.com/Gallopsled/pwntools/pull/2271
|
||||
[2272]: https://github.com/Gallopsled/pwntools/pull/2272
|
||||
[2281]: https://github.com/Gallopsled/pwntools/pull/2281
|
||||
[2287]: https://github.com/Gallopsled/pwntools/pull/2287
|
||||
[2294]: https://github.com/Gallopsled/pwntools/pull/2294
|
||||
|
||||
## 4.11.0
|
||||
|
||||
- [#2185][2185] make fmtstr module able to create payload without $ notation
|
||||
- [#2103][2103] Add search for libc binary by leaked function addresses `libcdb.search_by_symbol_offsets()`
|
||||
- [#2177][2177] Support for RISC-V 64-bit architecture
|
||||
- [#2186][2186] Enhance `ELF.nx` and `ELF.execstack`
|
||||
- [#2129][2129] Handle `context.newline` correctly when typing in `tube.interactive()`
|
||||
- [#2214][2214] Fix bug at ssh.py:`download` and `download_file` with relative paths
|
||||
- [#2241][2241] Fix ssh.process not setting ssh_process.cwd attribute
|
||||
- [#2261][2261] Fix corefile module after pyelftools update
|
||||
|
||||
[2185]: https://github.com/Gallopsled/pwntools/pull/2185
|
||||
[2103]: https://github.com/Gallopsled/pwntools/pull/2103
|
||||
[2177]: https://github.com/Gallopsled/pwntools/pull/2177
|
||||
[2186]: https://github.com/Gallopsled/pwntools/pull/2186
|
||||
[2129]: https://github.com/Gallopsled/pwntools/pull/2129
|
||||
[2214]: https://github.com/Gallopsled/pwntools/pull/2214
|
||||
[2241]: https://github.com/Gallopsled/pwntools/pull/2241
|
||||
[2261]: https://github.com/Gallopsled/pwntools/pull/2261
|
||||
|
||||
## 4.10.0
|
||||
|
||||
In memoriam — [Zach Riggle][zach] — long time contributor and maintainer of Pwntools.
|
||||
|
||||
- [#2062][2062] make pwn cyclic -l work with entry larger than 4 bytes
|
||||
- [#2092][2092] shellcraft: dup() is now called dupio() consistently across all supported arches
|
||||
- [#2093][2093] setresuid() in shellcraft uses current euid by default
|
||||
- [#2125][2125] Allow tube.recvregex to return capture groups
|
||||
- [#2144][2144] Removes `p2align 2` `asm()` headers from `x86-32`, `x86-64` and `mips` architectures to avoid inconsistent instruction length when patching binaries
|
||||
|
||||
[2062]: https://github.com/Gallopsled/pwntools/pull/2062
|
||||
[2092]: https://github.com/Gallopsled/pwntools/pull/2092
|
||||
[2093]: https://github.com/Gallopsled/pwntools/pull/2093
|
||||
[2125]: https://github.com/Gallopsled/pwntools/pull/2125
|
||||
[2144]: https://github.com/Gallopsled/pwntools/pull/2144
|
||||
[zach]: https://github.com/zachriggle
|
||||
|
||||
## 4.9.0
|
||||
|
||||
- [#1975][1975] Add libcdb commandline tool
|
||||
- [#1979][1979] Add `js_escape()` and `js_unescape()` to `util.fiddling`
|
||||
- [#2011][2011] Fix tube's debug output of same byte compression
|
||||
- [#2023][2023] Support KDE Konsole in run_in_new_terminal function
|
||||
- [#2027][2027] Fix ELF.libc_start_main_return with glibc 2.34
|
||||
- [#2033][2033] Quote file and core path in generated GDB script
|
||||
- [#2035][2035] Change Buffer's parent class to object
|
||||
- [#2037][2037] Allow SSH tunnel to be treated like a TCP socket (with 'raw=True')
|
||||
- [#2123][2123] Fix ROP without a writeable cache directory
|
||||
- [#2124][2124] Fix `tube.recvpred()` timeout argument
|
||||
|
||||
[1975]: https://github.com/Gallopsled/pwntools/pull/1975
|
||||
[1979]: https://github.com/Gallopsled/pwntools/pull/1979
|
||||
[2011]: https://github.com/Gallopsled/pwntools/pull/2011
|
||||
[2023]: https://github.com/Gallopsled/pwntools/pull/2023
|
||||
[2027]: https://github.com/Gallopsled/pwntools/pull/2027
|
||||
[2033]: https://github.com/Gallopsled/pwntools/pull/2033
|
||||
[2035]: https://github.com/Gallopsled/pwntools/pull/2035
|
||||
[2037]: https://github.com/Gallopsled/pwntools/pull/2037
|
||||
[2123]: https://github.com/Gallopsled/pwntools/pull/2123
|
||||
[2124]: https://github.com/Gallopsled/pwntools/pull/2124
|
||||
|
||||
## 4.8.0
|
||||
|
||||
- [#1922][1922] Fix logic in `wait_for_debugger`
|
||||
- [#1828][1828] libcdb: Load debug info and unstrip libc binary
|
||||
- [#1939][1939] Fix error in validating log levels
|
||||
- [#1981][1981] Fix `cyclic_find()` to make it work with large int values
|
||||
|
||||
[1922]: https://github.com/Gallopsled/pwntools/pull/1922
|
||||
[1828]: https://github.com/Gallopsled/pwntools/pull/1828
|
||||
[1939]: https://github.com/Gallopsled/pwntools/pull/1939
|
||||
[1981]: https://github.com/Gallopsled/pwntools/pull/1981
|
||||
|
||||
## 4.7.1
|
||||
|
||||
- [#1784][1784] Use temporary cache directory when persistent cache cannot be used
|
||||
- [#1973][1973] ELF symbols can be looked up by bytes values
|
||||
- several bugfixes ([#2012][2012], [#2031][2031], [#1912][1912], [#1961][1961],
|
||||
[#2007][2007], [#2040][2040], [#2051][2051])
|
||||
|
||||
[1784]: https://github.com/Gallopsled/pwntools/pull/1784
|
||||
[1912]: https://github.com/Gallopsled/pwntools/pull/1912
|
||||
[1961]: https://github.com/Gallopsled/pwntools/pull/1961
|
||||
[1973]: https://github.com/Gallopsled/pwntools/pull/1973
|
||||
[2007]: https://github.com/Gallopsled/pwntools/pull/2007
|
||||
[2012]: https://github.com/Gallopsled/pwntools/pull/2012
|
||||
[2031]: https://github.com/Gallopsled/pwntools/pull/2031
|
||||
[2040]: https://github.com/Gallopsled/pwntools/pull/2040
|
||||
[2051]: https://github.com/Gallopsled/pwntools/pull/2051
|
||||
|
||||
## 4.7.0
|
||||
|
||||
- [#1733][1733] Update libc headers -> more syscalls available!
|
||||
- [#1876][1876] add `self.message` and change `sys.exc_type` to `sys.exec_info()` in PwnlibException
|
||||
- [#1877][1877] encoders error message handles when `avoid` is bytes in python3
|
||||
- [#1891][1891] Keep ROP gadgets when setting registers via setattr/call
|
||||
- [#1892][1892] Silence SIGPIPE error for "pwn phd"
|
||||
- [#1893][1893] Fix bytes warning in "pwn cyclic"
|
||||
- [#1897][1897] Add basic support for RISC-V
|
||||
- [#1903][1903] Add zsh completion script
|
||||
- [#1904][1904] Add bash completion script
|
||||
- [#1906][1906] Defer import of several modules to save on startup time
|
||||
- [#1921][1921] Add basic support for the bare-metal ARM specific toolchain
|
||||
- [#1995][1995] Add `shellcraft.*.linux.cat2`, which uses alloc+read+write instead of sendfile
|
||||
|
||||
[1733]: https://github.com/Gallopsled/pwntools/pull/1733
|
||||
[1876]: https://github.com/Gallopsled/pwntools/pull/1876
|
||||
[1877]: https://github.com/Gallopsled/pwntools/pull/1877
|
||||
[1891]: https://github.com/Gallopsled/pwntools/pull/1891
|
||||
[1892]: https://github.com/Gallopsled/pwntools/pull/1892
|
||||
[1893]: https://github.com/Gallopsled/pwntools/pull/1893
|
||||
[1897]: https://github.com/Gallopsled/pwntools/pull/1897
|
||||
[1903]: https://github.com/Gallopsled/pwntools/pull/1903
|
||||
[1904]: https://github.com/Gallopsled/pwntools/pull/1904
|
||||
[1906]: https://github.com/Gallopsled/pwntools/pull/1906
|
||||
[1921]: https://github.com/Gallopsled/pwntools/pull/1921
|
||||
[1995]: https://github.com/Gallopsled/pwntools/pull/1995
|
||||
|
||||
## 4.6.0
|
||||
|
||||
- [#1429][1429] Add a mechanism for ret2csu (originally #1138)
|
||||
- [#1566][1566] Add `ignore_config` argument to `pwnlib.tubes.ssh` and improve `allow_agent` implementation
|
||||
- [#1652][1652] Add `process.readmem` and `process.writemem`
|
||||
- [#1739][1739] Add/fix shellcraft.linux.kill() / shellcraft.linux.killparent()
|
||||
- [#1746][1746] Prefer Python3 over Python2 for spawning remote processes over SSH
|
||||
- [#1751][1751] Fix process() with executable relative to cwd
|
||||
- [#1753][1753] major change: less unconditional imports in pwnlib
|
||||
- [#1776][1776] mips: do not use $t0 temporary variable in dupio
|
||||
- [#1846][1846] support launching GDB in more different terminals
|
||||
|
||||
[1429]: https://github.com/Gallopsled/pwntools/pull/1429
|
||||
[1566]: https://github.com/Gallopsled/pwntools/pull/1566
|
||||
[1652]: https://github.com/Gallopsled/pwntools/pull/1652
|
||||
[1739]: https://github.com/Gallopsled/pwntools/pull/1739
|
||||
[1746]: https://github.com/Gallopsled/pwntools/pull/1746
|
||||
[1751]: https://github.com/Gallopsled/pwntools/pull/1751
|
||||
[1753]: https://github.com/Gallopsled/pwntools/pull/1753
|
||||
[1776]: https://github.com/Gallopsled/pwntools/pull/1776
|
||||
[1846]: https://github.com/Gallopsled/pwntools/pull/1846
|
||||
|
||||
## 4.5.1
|
||||
|
||||
- [#1902][1902] Always specify -F and -P for tmux in `run_in_new_terminal`
|
||||
|
||||
[1902]: https://github.com/Gallopsled/pwntools/pull/1902
|
||||
|
||||
## 4.5.0
|
||||
|
||||
- [#1261][1261] Misc `run_in_new_terminal` improvements (notably gdb terminated by default)
|
||||
- [#1695][1695] Allow using GDB Python API
|
||||
- [#1735][1735] Python 3.9 support in safeeval
|
||||
- [#1738][1738] Which function support custom search path
|
||||
- process also looks now at `env['PATH']` to find the path for the executable
|
||||
- [#1742][1742] New `baremetal` os to debug binaries executed with qemu-system-$(arch)
|
||||
- [#1757][1757] update cache directories
|
||||
- [#1758][1758] Remove eval from cli
|
||||
- [#1780][1780] Re-add Python2 to the official Dockerfile
|
||||
- [#1941][1941] Disable all Android tests, `pwnlib.adb` is no longer supported in CI
|
||||
- [#1811][1811] Remove unnecessary `pwn.toplevel.__all__`
|
||||
- [#1827][1827] Support `$XDG_CONFIG_HOME` dir for `pwn.conf`
|
||||
- [#1841][1841] Add colored_traceback
|
||||
- [#1839][1839] run_in_new_terminal now creates a runner script if given a list or tuple
|
||||
- [#1833][1833] Add pwnlib.filesystem module
|
||||
- [#1852][1852] Fix `atexit` on Python 3
|
||||
- [#1883][1883] ROP gadget verifier accounts for 2 character registers
|
||||
|
||||
[1261]: https://github.com/Gallopsled/pwntools/pull/1261
|
||||
[1695]: https://github.com/Gallopsled/pwntools/pull/1695
|
||||
[1735]: https://github.com/Gallopsled/pwntools/pull/1735
|
||||
[1738]: https://github.com/Gallopsled/pwntools/pull/1738
|
||||
[1742]: https://github.com/Gallopsled/pwntools/pull/1742
|
||||
[1757]: https://github.com/Gallopsled/pwntools/pull/1757
|
||||
[1758]: https://github.com/Gallopsled/pwntools/pull/1758
|
||||
[1780]: https://github.com/Gallopsled/pwntools/pull/1780
|
||||
[1941]: https://github.com/Gallopsled/pwntools/pull/1941
|
||||
[1811]: https://github.com/Gallopsled/pwntools/pull/1811
|
||||
[1827]: https://github.com/Gallopsled/pwntools/pull/1827
|
||||
[1841]: https://github.com/Gallopsled/pwntools/pull/1841
|
||||
[1839]: https://github.com/Gallopsled/pwntools/pull/1839
|
||||
[1833]: https://github.com/Gallopsled/pwntools/pull/1833
|
||||
[1852]: https://github.com/Gallopsled/pwntools/pull/1852
|
||||
[1883]: https://github.com/Gallopsled/pwntools/pull/1883
|
||||
|
||||
## 4.4.0
|
||||
|
||||
- [#1541][1541] Use `context.newline` for tubes by default
|
||||
- [#1602][1602] Fix bytes handling in ssh tubes
|
||||
- [#1606][1606] Fix `asm()` and `disasm()` for MSP430, S390
|
||||
- [#1616][1616] Fix `cyclic` cli for 64 bit integers
|
||||
- [#1632][1632] Enable usage of Pwntools in jupyter
|
||||
- [#1633][1633] Open a shell if `pwn template` cannot download the remote file
|
||||
- [#1644][1644] Enable and support SNI for SSL-wrapped tubes
|
||||
- [#1651][1651] Make `pwn shellcraft` faster
|
||||
- [#1654][1654] Docker images (`pwntools/pwntools:stable` etc) now use Python3 by default, and includes assemblers for a few common architectures
|
||||
- [#1667][1667] Add i386 encoder `ascii_shellcode` (Fixed docs in #1693)
|
||||
- Fix syscall instruction lists for SROP on `i386` and `amd64`
|
||||
- Fix migration to another ROP
|
||||
- [#1673][1673] Add `base=` argument to `ROP.chain()` and `ROP.dump()`
|
||||
- [#1675][1675] Gdbserver now correctly accepts multiple libraries in `LD_PRELOAD` and `LD_LIBRARY_PATH`
|
||||
- [#1678][1678] ROPGadget multibr
|
||||
- [#1682][1682] ROPGadget multibr fix
|
||||
- [#1687][1687] Actually import `requests` when doing `from pwn import *`
|
||||
- [#1688][1688] Add `__setattr__` and `__call__` interfaces to `ROP` for setting registers
|
||||
- [#1692][1692] Remove python2 shebangs where appropriate
|
||||
- [#1703][1703] Update libcdb buildid offsets for amd64 and i386
|
||||
- [#1704][1704] Try https://libc.rip/ for libcdb lookup
|
||||
|
||||
[1541]: https://github.com/Gallopsled/pwntools/pull/1541
|
||||
[1602]: https://github.com/Gallopsled/pwntools/pull/1602
|
||||
[1606]: https://github.com/Gallopsled/pwntools/pull/1606
|
||||
[1616]: https://github.com/Gallopsled/pwntools/pull/1616
|
||||
[1632]: https://github.com/Gallopsled/pwntools/pull/1632
|
||||
[1633]: https://github.com/Gallopsled/pwntools/pull/1633
|
||||
[1644]: https://github.com/Gallopsled/pwntools/pull/1644
|
||||
[1651]: https://github.com/Gallopsled/pwntools/pull/1651
|
||||
[1654]: https://github.com/Gallopsled/pwntools/pull/1654
|
||||
[1667]: https://github.com/Gallopsled/pwntools/pull/1667
|
||||
[1673]: https://github.com/Gallopsled/pwntools/pull/1673
|
||||
[1675]: https://github.com/Gallopsled/pwntools/pull/1675
|
||||
[1678]: https://github.com/Gallopsled/pwntools/pull/1678
|
||||
[1682]: https://github.com/Gallopsled/pwntools/pull/1679
|
||||
[1687]: https://github.com/Gallopsled/pwntools/pull/1687
|
||||
[1688]: https://github.com/Gallopsled/pwntools/pull/1688
|
||||
[1692]: https://github.com/Gallopsled/pwntools/pull/1692
|
||||
[1703]: https://github.com/Gallopsled/pwntools/pull/1703
|
||||
[1704]: https://github.com/Gallopsled/pwntools/pull/1704
|
||||
|
||||
## 4.3.0 (`beta`)
|
||||
## 4.3.1
|
||||
|
||||
- [#1732][1732] Fix shellcraft SSTI vulnerability (first major pwntools vuln!)
|
||||
|
||||
[1732]: https://github.com/Gallopsled/pwntools/pull/1732
|
||||
|
||||
## 4.3.0
|
||||
|
||||
- [#1576][1576] Add `executable=` argument to `ELF.search`
|
||||
- [#1584][1584] Add `jmp_esp`/`jmp_rsp` attribute to `ROP`
|
||||
@@ -70,6 +407,7 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
- [#1601][1601] Add `pwn version` command line tool
|
||||
- [#1605][1605] Add to `fiddling.hexdump` a way to suppress the total at the end
|
||||
- [#1613][1613] Permit `--password` for `pwn template`
|
||||
- [#1616][1616] Fix `cyclic` cli for 64 bit integers
|
||||
- [#1564][1564] Fix `asm()` and `disasm()` for PowerPC64, MIPS64, Sparc64
|
||||
- [#1621][1621] Permit negative values in flat() and fit()
|
||||
|
||||
@@ -80,10 +418,11 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
[1601]: https://github.com/Gallopsled/pwntools/pull/1601
|
||||
[1605]: https://github.com/Gallopsled/pwntools/pull/1605
|
||||
[1613]: https://github.com/Gallopsled/pwntools/pull/1613
|
||||
[1616]: https://github.com/Gallopsled/pwntools/pull/1616
|
||||
[1564]: https://github.com/Gallopsled/pwntools/pull/1564
|
||||
[1621]: https://github.com/Gallopsled/pwntools/pull/1621
|
||||
|
||||
## 4.2.1 (`stable`)
|
||||
## 4.2.1
|
||||
|
||||
- [#1625][1625] GDB now properly loads executables with QEMU
|
||||
- [#1663][1663] Change lookup algorithm of `adb.which`
|
||||
@@ -157,7 +496,7 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
[1001]: https://github.com/Gallopsled/pwntools/pull/1001
|
||||
[1389]: https://github.com/Gallopsled/pwntools/pull/1389
|
||||
[1241]: https://github.com/Gallopsled/pwntools/pull/1241
|
||||
[1218]: https://github.com/Gallopsled/pwntools/pull/1218
|
||||
[1218]: https://github.com/Gallopsled/pwntools/pull/1218
|
||||
|
||||
## 4.0.1
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# Using Pwntools with Docker
|
||||
|
||||
Sometimes it's annoying to set up Pwntools on your workstation, and you want something that Just Works (TM).
|
||||
|
||||
[Docker](https://www.docker.com/) is here to the rescue! Using Docker means that you get a nice, standardized Linux environment and don't need to worry about pip or installing dependencies.
|
||||
|
||||
## Quick Start
|
||||
|
||||
First, install Docker for your OS, which you can find on their [Getting Started](https://www.docker.com/get-started) page.
|
||||
|
||||
Next, download and run the Pwntools stable docker image.
|
||||
|
||||
```sh
|
||||
$ docker run -it pwntools/pwntools:stable
|
||||
```
|
||||
|
||||
## Recommended Settings
|
||||
|
||||
In order to get the most from your docker image, we need to enable debugging of processes (`--privileged`) and expose the network ports from the guest to the host (`--net=host`).
|
||||
|
||||
```sh
|
||||
$ docker run -it \
|
||||
--privileged \
|
||||
--net=host \
|
||||
--hostname localhost \
|
||||
--ulimit core=-1:-1 \
|
||||
pwntools/pwntools:stable
|
||||
```
|
||||
|
||||
## Sharing a Folder
|
||||
|
||||
It's really nice to be able to use your preferred native editor, and have the changes show up live inside your Docker image. This is easy to add, thanks to Docker's bind mounts (`--mount type=bind`).
|
||||
|
||||
With the command below, your `~/exploits` directory will magically show up inside the Docker image at `/home/pwntools/exploits` so that you can easily run them (from Docker) and edit them (from outside Docker).
|
||||
|
||||
```sh
|
||||
$ mkdir $HOME/exploits
|
||||
|
||||
$ vim $HOME/exploits/my_exploit.py
|
||||
|
||||
$ docker run -it \
|
||||
--privileged \
|
||||
--net=host \
|
||||
--hostname localhost \
|
||||
--ulimit core=-1:-1 \
|
||||
--mount type=bind,source="$HOME/exploits",target=/home/pwntools/exploits \
|
||||
pwntools/pwntools:stable
|
||||
|
||||
$ python3 exploits/my_exploit.py
|
||||
```
|
||||
|
||||
### Windows User Bind Mounts
|
||||
|
||||
If you're a Windows user `$HOME` doesn't exist in the same way as on Linux, instead it is `%UserProfile%`. The command from above would look like this, assuming your editor is Visual Studio Code and you have code.exe in your `%PATH%`.
|
||||
|
||||
```sh
|
||||
C:\Users\user> mkdir Desktop\exploits
|
||||
|
||||
C:\Users\user> code Desktop\exploits\my_exploit.py
|
||||
|
||||
C:\Users\user> docker run -it \
|
||||
--privileged \
|
||||
--net=host \
|
||||
--hostname localhost \
|
||||
--ulimit core=-1:-1 \
|
||||
--mount type=bind,source="%UserProfile%\Desktop\exploits",target=/home/pwntools/exploits \
|
||||
pwntools/pwntools:stable
|
||||
|
||||
$ python3 exploits/my_exploit.py
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+3
-1
@@ -1,7 +1,9 @@
|
||||
graft build
|
||||
graft examples
|
||||
graft extra
|
||||
graft travis
|
||||
include *.md *.txt *.sh *.yml MANIFEST.in
|
||||
recursive-include docs *.rst *.png Makefile *.py *.txt
|
||||
recursive-include pwnlib *.py *.asm *.rst *.md *.txt *.sh __doc__ *.mako
|
||||
recursive-include pwn *.py *.asm *.rst *.md *.txt *.sh
|
||||
recursive-exclude *.pyc
|
||||
global-exclude *.pyc
|
||||
@@ -1,12 +1,14 @@
|
||||
# pwntools - CTF toolkit
|
||||

|
||||
|
||||
[](https://docs.pwntools.com/)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
|
||||
[](https://twitter.com/pwntools)
|
||||
[](https://docs.pwntools.com/)
|
||||
[](https://github.com/Gallopsled/pwntools/actions/workflows/ci.yml?query=branch%3Adev)
|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
|
||||
[](http://choosealicense.com/licenses/mit/)
|
||||
[](https://repology.org/project/python:pwntools/versions)
|
||||
[](https://discord.gg/96VA2zvjCB)
|
||||
[](https://twitter.com/pwntools)
|
||||
|
||||
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.
|
||||
|
||||
@@ -20,29 +22,28 @@ r.send(asm(shellcraft.sh()))
|
||||
r.interactive()
|
||||
```
|
||||
|
||||
# Try It Now!
|
||||
|
||||
You can now do a live demo of Pwntools, [right in your browser](https://demo.pwntools.com).
|
||||
|
||||
# Documentation
|
||||
|
||||
Our documentation is available at [docs.pwntools.com](https://docs.pwntools.com/)
|
||||
|
||||
A series of tutorials is also [available online](https://github.com/Gallopsled/pwntools-tutorial#readme)
|
||||
|
||||
To get you started, we've provided some example solutions for past CTF challenges in our [write-ups repository](https://github.com/Gallopsled/pwntools-write-ups).
|
||||
|
||||
# Installation
|
||||
|
||||
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).
|
||||
Pwntools is best supported on 64-bit Ubuntu LTS releases (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.).
|
||||
|
||||
Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
|
||||
Python3 is suggested, but Pwntools still works with Python 2.7. 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 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@dev
|
||||
python3 -m pip install --upgrade pwntools
|
||||
```
|
||||
|
||||
|
||||
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).
|
||||
|
||||
|
||||
@@ -50,8 +51,5 @@ However, some of the features (assembling/disassembling foreign architectures) r
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
# Contact
|
||||
If you have any questions not worthy of a [bug report](https://github.com/Gallopsled/pwntools/issues), feel free to ping us
|
||||
at [`#pwntools` on Freenode](irc://irc.freenode.net/pwntools) and ask away.
|
||||
Click [here](https://kiwiirc.com/client/irc.freenode.net/pwntools) to connect.
|
||||
There is also a [mailing list](https://groups.google.com/forum/#!forum/pwntools-users) for higher latency discussion.
|
||||
# Contact and Community
|
||||
If you have any questions not worthy of a [bug report](https://github.com/Gallopsled/pwntools/issues), join the Discord server at https://discord.gg/96VA2zvjCB
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------------- | ------------------ |
|
||||
| latest dev | :white_check_mark: |
|
||||
| latest beta | :white_check_mark: |
|
||||
| latest stable | :white_check_mark: |
|
||||
| anything else | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
The aim of pwntools is exploiting software vulnerabilities, which is an unusual position, but it nevertheless can have its own security issues.
|
||||
Especially that an attacker (=re-victim) is usually not prepared to be attacked back (by the re-attacker).
|
||||
|
||||
The first question to ask yourself is: is this an actual vulnerability?
|
||||
- can it be triggered by a re-attacker (malicious honeypot pretending to be a vulnerable service)?
|
||||
- does it impact the attacker (=re-victim)?
|
||||
- is it serious?
|
||||
* *availability: medium* means *at least* exhausting RAM or disk space of the attacker (=re-victim)
|
||||
* *confidentiality: medium* means *at least* reading the filesystem of the attacker (=re-victim)
|
||||
* *integrity: medium* means *at least* performing uncontrolled actions or data corruption on behalf of the attacker (=re-victim)
|
||||
* if crucial for some sophisticated exploit chain, it is always serious
|
||||
* `safe_eval` bypasses **are** serious.
|
||||
* an example of what was **kind of** serious: [#1732](https://github.com/Gallopsled/pwntools/pull/1732)
|
||||
- can it be fixed without compromising on Pwntools' usability?
|
||||
|
||||
If at least one of the answers is no, then this is NOT a vulnerability, so just file a bug report or feature request, without the weird confidential disclosure dance.
|
||||
|
||||
Just e-mail the maintainers. Arusekk is the one that is currently the most excited to fix vulnerabilities.
|
||||
Or create a CTF task! Prove a point the good old hacker way!
|
||||
+3
-4
@@ -6,7 +6,6 @@ SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
DASHBUILD = ./dashbuild.py
|
||||
TAR = tar
|
||||
|
||||
# Internal variables.
|
||||
@@ -45,7 +44,7 @@ help:
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
-rm -rf /tmp/user/pwn*
|
||||
-rm -rf $(HOME)/.pwntools-cache
|
||||
-rm -rf $(HOME)/.cache/.pwntools-cache
|
||||
-rm -rf /tmp/pwn* 2>/dev/null || true
|
||||
-rm -rf build
|
||||
|
||||
@@ -145,8 +144,8 @@ gettext:
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
dash:
|
||||
$(DASHBUILD) source $(BUILDDIR)/dash
|
||||
$(TAR) --exclude='.DS_Store' -cvzf $(BUILDDIR)/dash/pwntools.tgz -C $(BUILDDIR)/dash pwntools.docset
|
||||
$(SPHINXBUILD) -b html -d $(BUILDDIR)/doctrees -t dash source $(BUILDDIR)/html
|
||||
doc2dash $(BUILDDIR)/html -d $(BUILDDIR)/dash -n pwntools -f -I index.html
|
||||
@echo "Build finished. The Dash docset is in $(BUILDDIR)/dash."
|
||||
|
||||
changes:
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Helper to build Dash docset from sphinx source files.
|
||||
#
|
||||
# Dash docsets can be read by various applications:
|
||||
#
|
||||
# Dash OS X, iOS https://kapeli.com
|
||||
# Zeal Linux, Windows https://zealdocs.org
|
||||
# Velocity Windows http://velocity.silverlakesoftware.com
|
||||
# LovelyDocs Android http://lovelydocs.io
|
||||
# dasht POSIX https://github.com/sunaku/dasht
|
||||
# Helm Dash emacs https://github.com/areina/helm-dash
|
||||
#
|
||||
|
||||
import argparse
|
||||
import doc2dash.__main__
|
||||
import os, os.path
|
||||
import sphinx
|
||||
import sqlite3
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.abspath(os.path.join('..', 'pwnlib')))
|
||||
import version
|
||||
|
||||
def main(args):
|
||||
"""Generate a Dash docset from Sphinx source files."""
|
||||
|
||||
srcdir = args.srcdir
|
||||
dstdir = args.dstdir
|
||||
name = args.name
|
||||
|
||||
if not os.path.exists(dstdir):
|
||||
os.makedirs(dstdir)
|
||||
|
||||
# Generate HTML without indices.
|
||||
sphinx.build_main([ "sphinx-build", "-b", "html", "-d", os.path.join(dstdir, "doctrees"), \
|
||||
"-t", "dash", srcdir, os.path.join(dstdir, "html") ])
|
||||
|
||||
# Convert to docset.
|
||||
try:
|
||||
doc2dash.__main__.main.main( \
|
||||
[ os.path.join(dstdir, "html"), "-d", dstdir, "-n", name, \
|
||||
"-f", "-I", "index.html"], "doc2dash", False)
|
||||
except SystemExit as e:
|
||||
pass
|
||||
|
||||
# Insert a link to the online version.
|
||||
online = args.online
|
||||
if online is not None and online != "":
|
||||
url = online.replace("@VERSION", args.version)
|
||||
with open(os.path.join(dstdir, name+".docset", "Contents", "Info.plist"), "r+") as f_info:
|
||||
pl = f_info.read()
|
||||
pl = pl.replace("</dict>", \
|
||||
"\t<key>DashDocSetFallbackURL</key>\n\t<string>%s</string>\n</dict>" % url)
|
||||
f_info.seek(0)
|
||||
f_info.write(pl)
|
||||
f_info.truncate()
|
||||
|
||||
# Modify the CSS to hide the menu included in the HTML.
|
||||
with open(os.path.join(dstdir, name+".docset", "Contents", "Resources", "Documents", "_static", "css", "theme.css"), "r+") as f_css:
|
||||
css = f_css.read()
|
||||
css = css.replace( \
|
||||
'@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}',\
|
||||
'@media screen {.wy-body-for-nav{background:#fcfcfc}' )
|
||||
css = css.replace( \
|
||||
'@media screen and (max-width: 480px)', \
|
||||
'@media screen ')
|
||||
f_css.seek(0)
|
||||
f_css.write(css)
|
||||
f_css.truncate()
|
||||
|
||||
# Modify the index
|
||||
db_conn = sqlite3.connect(os.path.join(dstdir, name+".docset", "Contents", "Resources", "docSet.dsidx"))
|
||||
try:
|
||||
db_conn.execute('INSERT INTO "searchIndex" ("name","type","path") VALUES ' \
|
||||
'("1 Contents", "Guide", "index.html"), ' \
|
||||
'("2 About pwntools", "Guide", "about.html"), ' \
|
||||
'("3 Installation", "Guide", "install.html"), ' \
|
||||
'("4 Getting Started", "Guide", "intro.html"), ' \
|
||||
'("5 Globals (pwn)", "Guide", "globals.html"), ' \
|
||||
'("6 Command Line Tools", "Guide", "commandline.html")')
|
||||
db_conn.execute('DELETE FROM "searchIndex" WHERE "type" = "Module" AND ("name" = "pwn" OR "name" = "pwnlib")')
|
||||
db_conn.commit()
|
||||
finally:
|
||||
db_conn.close()
|
||||
|
||||
return 0
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--name", help="docset name", default="pwntools")
|
||||
parser.add_argument("--online", help="URL for online docs", default="https://pwntools.readthedocs.org/en/@VERSION/")
|
||||
parser.add_argument("--version", help="pwntools version", default=version.__version__)
|
||||
parser.add_argument("srcdir", help="Source directory containing .rst files")
|
||||
parser.add_argument("dstdir", help="Destination and working directory")
|
||||
|
||||
main(parser.parse_args())
|
||||
@@ -1,6 +1,9 @@
|
||||
capstone
|
||||
coveralls
|
||||
coverage[toml]
|
||||
python-dateutil
|
||||
doc2dash
|
||||
docutils<0.18
|
||||
intervaltree
|
||||
isort
|
||||
mako>=1.0.0
|
||||
paramiko>=1.15.2
|
||||
@@ -9,9 +12,11 @@ pyelftools>=0.2.3
|
||||
pygments>=2.0
|
||||
pypandoc
|
||||
pyserial>=2.7
|
||||
pysocks
|
||||
psutil
|
||||
requests>=2.5.1
|
||||
ropgadget>=5.3
|
||||
sphinx
|
||||
sphinx==1.8.6; python_version<'3'
|
||||
sphinx>=4.5.0; python_version>='3'
|
||||
sphinx_rtd_theme
|
||||
sphinxcontrib-napoleon
|
||||
sphinxcontrib-autoprogram
|
||||
sphinxcontrib-autoprogram<=0.1.5
|
||||
+1
-6
@@ -2,12 +2,7 @@
|
||||
|
||||
import tempfile
|
||||
import subprocess
|
||||
from pwnlib.context import context
|
||||
from pwnlib.asm import *
|
||||
from pwnlib import shellcraft
|
||||
from pwnlib.tubes.process import process
|
||||
from pwnlib.util.fiddling import unhex
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.asm` --- Assembler functions
|
||||
=========================================
|
||||
|
||||
@@ -12,6 +12,8 @@ Command Line Tools
|
||||
|
||||
pwntools comes with a handful of useful command-line utilities which serve as wrappers for some of the internal functionality.
|
||||
|
||||
If these tools do not appear to be installed, make sure that you have added ``~/.local/bin`` to your ``$PATH`` environment variable.
|
||||
|
||||
.. toctree::
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.main:parser
|
||||
|
||||
+41
-18
@@ -25,7 +25,8 @@ build_dash = tags.has('dash')
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.update
|
||||
pwnlib.update.disabled = True
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
@@ -41,8 +42,8 @@ extensions = [
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinxcontrib.autoprogram',
|
||||
'sphinxcontrib.napoleon'
|
||||
]
|
||||
|
||||
# Disable "info" logging directly to stdout by Sphinx
|
||||
@@ -70,10 +71,14 @@ doctest_global_setup = '''
|
||||
import sys, os
|
||||
os.environ['PWNLIB_NOTERM'] = '1'
|
||||
os.environ['PWNLIB_RANDOMIZE'] = '0'
|
||||
import pwnlib, logging
|
||||
import pwnlib.update
|
||||
import pwnlib.util.fiddling
|
||||
import logging
|
||||
pwnlib.update.disabled = True
|
||||
pwnlib.context.context.reset_local()
|
||||
pwnlib.context.ContextType.defaults['log_level'] = logging.ERROR
|
||||
pwnlib.context.ContextType.defaults['randomize'] = False
|
||||
# pwnlib.context.ContextType.defaults['terminal'] = ['sh', '-c']
|
||||
pwnlib.util.fiddling.default_style = {}
|
||||
pwnlib.term.text.when = 'never'
|
||||
pwnlib.log.install_default_handler()
|
||||
@@ -91,6 +96,9 @@ pwnlib.context.ContextType.defaults['log_console'] = stdout()
|
||||
|
||||
github_actions = os.environ.get('USER') == 'runner'
|
||||
travis_ci = os.environ.get('USER') == 'travis'
|
||||
local_doctest = os.environ.get('USER') == 'pwntools'
|
||||
branch_dev = os.environ.get('GITHUB_BASE_REF') == 'dev'
|
||||
skip_android = True
|
||||
'''
|
||||
|
||||
autoclass_content = 'both'
|
||||
@@ -257,7 +265,7 @@ latex_documents = [
|
||||
u'2016, Gallopsled et al.', 'manual'),
|
||||
]
|
||||
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/2.7', None),
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.8', 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
|
||||
@@ -340,7 +348,7 @@ def linkcode_resolve(domain, info):
|
||||
val = mod
|
||||
for k in info['fullname'].split('.'):
|
||||
val = getattr(val, k, None)
|
||||
if val == None:
|
||||
if val is None:
|
||||
break
|
||||
|
||||
# Special case for shellcraft
|
||||
@@ -369,9 +377,10 @@ if build_dash:
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
import alabaster
|
||||
html_theme = 'alabaster'
|
||||
html_theme_path = [alabaster.get_path()]
|
||||
html_theme_options = { 'nosidebar' : True }
|
||||
|
||||
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
|
||||
|
||||
@@ -381,7 +390,9 @@ import sphinx.ext.autodoc
|
||||
|
||||
# Test hidden members (e.g. def _foo(...))
|
||||
def dont_skip_any_doctests(app, what, name, obj, skip, options):
|
||||
return False
|
||||
return None
|
||||
|
||||
autodoc_default_options = {'special-members': None, 'private-members': None}
|
||||
|
||||
class _DummyClass(object): pass
|
||||
|
||||
@@ -403,24 +414,36 @@ class Py2OutputChecker(_DummyClass, doctest.OutputChecker):
|
||||
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)
|
||||
if sup(rly_want, got, optionflags):
|
||||
return True
|
||||
for wantl, gotl in six.moves.zip_longest(want.splitlines(), got.splitlines(), fillvalue=''):
|
||||
rly_want1 = '['.join(x[:2].replace('b"','"').replace("b'","'")+x[2:] for x in wantl.split('['))
|
||||
rly_want2 = ' '.join(x[:2].replace('b"',' "').replace("b'"," '")+x[2:] for x in wantl.split(' '))
|
||||
if not sup(rly_want1, gotl, optionflags) and not sup(rly_want2, gotl, optionflags):
|
||||
return False
|
||||
return True
|
||||
|
||||
def py2_doctest_init(self, checker=None, verbose=None, optionflags=0):
|
||||
if checker is None:
|
||||
checker = Py2OutputChecker()
|
||||
doctest.DocTestRunner.__init__(self, checker, verbose, optionflags)
|
||||
|
||||
class EndlessLoop(Exception): pass
|
||||
def alrm_handler(sig, frame):
|
||||
signal.alarm(180) # three minutes
|
||||
raise EndlessLoop()
|
||||
signal.signal(signal.SIGALRM, alrm_handler)
|
||||
signal.alarm(600) # ten minutes
|
||||
|
||||
if 'doctest' in sys.argv:
|
||||
def setup(app):
|
||||
app.connect('autodoc-skip-member', dont_skip_any_doctests)
|
||||
pass # 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
|
||||
else:
|
||||
# monkey patching paramiko due to https://github.com/paramiko/paramiko/pull/1661
|
||||
import paramiko.client
|
||||
import binascii
|
||||
paramiko.client.hexlify = lambda x: binascii.hexlify(x).decode()
|
||||
paramiko.util.safe_string = lambda x: '' # function result never *actually used*
|
||||
class EndlessLoop(Exception): pass
|
||||
def alrm_handler(sig, frame):
|
||||
signal.alarm(180) # three minutes
|
||||
raise EndlessLoop()
|
||||
signal.signal(signal.SIGALRM, alrm_handler)
|
||||
signal.alarm(600) # ten minutes
|
||||
@@ -3,6 +3,22 @@
|
||||
from glob import glob
|
||||
from pwn import *
|
||||
|
||||
# The Linux kernel won't overwrite an existing corefile, so in case
|
||||
# some other part of the doctests caused a segfault and core dump,
|
||||
# we need to get rid of it before our tests run.
|
||||
#
|
||||
# We DONT need to worry about e.g. ./core existing when using Corefile()
|
||||
# because we always move and rename the corefile to prevent this situation.
|
||||
if os.path.exists('core'):
|
||||
os.unlink('core')
|
||||
|
||||
# bash-static is a statically linked version of bash, but if $SHELL is not
|
||||
# set to anything, it decides to up and load ld.so and libc.so which breaks
|
||||
# our example of showing `corefile.libc == None` for a statically linked bin.
|
||||
# Set the environment here so it's not in the middle of our tests.
|
||||
os.environ.setdefault('SHELL', '/bin/sh')
|
||||
|
||||
|
||||
:mod:`pwnlib.elf.corefile` --- Core Files
|
||||
===========================================================
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from pwn import *
|
||||
from glob import glob
|
||||
from pwnlib.elf.maps import CAT_PROC_MAPS_EXIT
|
||||
import shutil
|
||||
|
||||
:mod:`pwnlib.elf.elf` --- ELF Files
|
||||
===========================================================
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
|
||||
:mod:`pwnlib.encoders` --- Encoding Shellcode
|
||||
===============================================
|
||||
|
||||
.. automodule:: pwnlib.encoders.encoder
|
||||
:members:
|
||||
|
||||
.. automodule:: pwnlib.encoders.i386.ascii_shellcode
|
||||
:members:
|
||||
:special-members:
|
||||
:exclude-members: __init__
|
||||
|
||||
.. automodule:: pwnlib.encoders.i386.xor
|
||||
:members:
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
.. testsetup:: *
|
||||
|
||||
import time
|
||||
import six
|
||||
from pwnlib.context import context
|
||||
from pwnlib.tubes.ssh import ssh
|
||||
from pwnlib.filesystem import *
|
||||
|
||||
:mod:`pwnlib.filesystem` --- Manipulating Files Locally and Over SSH
|
||||
====================================================================
|
||||
|
||||
Provides a Python2-compatible :py:mod:`pathlib` interface for paths
|
||||
on the local filesystem (`.Path`) as well as on remote filesystems,
|
||||
via SSH (`.SSHPath`).
|
||||
|
||||
.. automodule:: pwnlib.filesystem
|
||||
:members:
|
||||
+13
-3
@@ -13,7 +13,7 @@ readthedocs_. It comes in three primary flavors:
|
||||
- Dev_
|
||||
|
||||
.. _readthedocs: https://readthedocs.org
|
||||
.. _docs.pwntools.com: https://docs.pwntools.com
|
||||
.. _docs.pwntools.com: https://docs.pwntools.com/en/latest
|
||||
.. _Stable: https://docs.pwntools.com/en/stable
|
||||
.. _Beta: https://docs.pwntools.com/en/beta
|
||||
.. _Dev: https://docs.pwntools.com/en/dev
|
||||
@@ -52,9 +52,10 @@ Each of the ``pwntools`` modules is documented here.
|
||||
context
|
||||
dynelf
|
||||
encoders
|
||||
elf
|
||||
elf/*
|
||||
exception
|
||||
filepointer
|
||||
filesystem
|
||||
flag
|
||||
fmtstr
|
||||
gdb
|
||||
@@ -64,7 +65,6 @@ Each of the ``pwntools`` modules is documented here.
|
||||
protocols
|
||||
qemu
|
||||
replacements
|
||||
rop
|
||||
rop/*
|
||||
runner
|
||||
shellcraft
|
||||
@@ -82,6 +82,7 @@ Each of the ``pwntools`` modules is documented here.
|
||||
:hidden:
|
||||
|
||||
testexample
|
||||
rop/call
|
||||
|
||||
.. only:: not dash
|
||||
|
||||
@@ -91,3 +92,12 @@ Each of the ``pwntools`` modules is documented here.
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
Bytes
|
||||
-----
|
||||
|
||||
The bytes vs text distinction is so important that it even made it to this main page.
|
||||
See the pwntools-tutorial_ repo for the latest tutorial finally
|
||||
explaining the difference once and for all (hopefully).
|
||||
|
||||
.. _pwntools-tutorial: https://github.com/Gallopsled/pwntools-tutorial/blob/master/bytes.md
|
||||
+36
-4
@@ -1,9 +1,7 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
pwntools is best supported on Ubuntu 12.04 and 14.04, but most
|
||||
functionality should work on any Posix-like distribution (Debian, Arch,
|
||||
FreeBSD, OSX, etc.).
|
||||
Pwntools is best supported on 64-bit Ubuntu LTS releases (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.).
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
@@ -20,7 +18,10 @@ following system libraries installed.
|
||||
Released Version
|
||||
-----------------
|
||||
|
||||
pwntools is available as a ``pip`` package.
|
||||
pwntools is available as a ``pip`` package for both Python2 and Python3.
|
||||
|
||||
Python3
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -29,6 +30,37 @@ pwntools is available as a ``pip`` package.
|
||||
$ python3 -m pip install --upgrade pip
|
||||
$ python3 -m pip install --upgrade pwntools
|
||||
|
||||
|
||||
Python2 (Deprecated)
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
NOTE: Pwntools maintainers STRONGLY recommend using Python3 for all future Pwntools-based scripts and projects.
|
||||
|
||||
Additionally, due to `pip` dropping support for Python2, a specfic version of `pip` must be installed.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ apt-get update
|
||||
$ apt-get install python python-pip python-dev git libssl-dev libffi-dev build-essential
|
||||
$ python2 -m pip install --upgrade pip==20.3.4
|
||||
$ python2 -m pip install --upgrade pwntools
|
||||
|
||||
|
||||
Command-Line Tools
|
||||
------------------
|
||||
|
||||
When installed with ``sudo`` the above commands will install Pwntools' command-line tools to somewhere like ``/usr/bin``.
|
||||
|
||||
However, if you run as an unprivileged user, you may see a warning message that looks like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
WARNING: The scripts asm, checksec, common, constgrep, cyclic, debug, disablenx, disasm,
|
||||
elfdiff, elfpatch, errno, hex, main, phd, pwn, pwnstrip, scramble, shellcraft, template,
|
||||
unhex, update and version are installed in '/home/user/.local/bin' which is not on PATH.
|
||||
|
||||
Follow the instructions listed and add ``~/.local/bin`` to your ``$PATH`` environment variable.
|
||||
|
||||
Development
|
||||
--------------
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@ Assembly of foreign architectures (e.g. assembling Sparc shellcode on
|
||||
Mac OS X) requires cross-compiled versions of ``binutils`` to be
|
||||
installed. We've made this process as smooth as we can.
|
||||
|
||||
In these examples, replace ``$ARCH`` with your target architecture (e.g., arm, mips64, vax, etc.).
|
||||
In these examples, replace ``$ARCH`` with your target architecture (e.g., arm, aarch64, mips64, vax, etc.).
|
||||
|
||||
Building `binutils` from source takes about 60 seconds on a modern 8-core machine.
|
||||
|
||||
Ubuntu
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
For Ubuntu 12.04 through 15.10, you must first add the pwntools `Personal Package Archive repository <http://binutils.pwntools.com>`__.
|
||||
For Ubuntu 12.04 through 15.10, you must first add the pwntools `Personal Package Archive repository <https://launchpad.net/~pwntools/+archive/ubuntu/binutils>`__.
|
||||
|
||||
Ubuntu Xenial (16.04) has official packages for most architectures, and does not require this step.
|
||||
|
||||
@@ -33,7 +33,7 @@ Mac OS X
|
||||
|
||||
Mac OS X is just as easy, but requires building binutils from source.
|
||||
However, we've made ``homebrew`` recipes to make this a single command.
|
||||
After installing `brew <http://brew.sh>`__, grab the appropriate
|
||||
After installing `brew <https://brew.sh>`__, grab the appropriate
|
||||
recipe from our `binutils
|
||||
repo <https://github.com/Gallopsled/pwntools-binutils/>`__.
|
||||
|
||||
@@ -51,10 +51,10 @@ OSes, ``binutils`` is simple to build by hand.
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
V=2.25 # Binutils Version
|
||||
V=2.38 # Binutils Version
|
||||
ARCH=arm # Target architecture
|
||||
|
||||
cd /tmp
|
||||
cd ${TMPDIR:-/tmp}
|
||||
wget -nc https://ftp.gnu.org/gnu/binutils/binutils-$V.tar.gz
|
||||
wget -nc https://ftp.gnu.org/gnu/binutils/binutils-$V.tar.gz.sig
|
||||
|
||||
@@ -70,7 +70,7 @@ OSes, ``binutils`` is simple to build by hand.
|
||||
export AS=as
|
||||
|
||||
../binutils-$V/configure \
|
||||
--prefix=/usr/local \
|
||||
--prefix=${PREFIX:-/usr/local} \
|
||||
--target=$ARCH-unknown-linux-gnu \
|
||||
--disable-static \
|
||||
--disable-multilib \
|
||||
|
||||
+10
-3
@@ -17,6 +17,13 @@ assemble, disassemble, pack, unpack, and many other things with a single functio
|
||||
A full list of everything that is imported is available on :doc:`globals`.
|
||||
|
||||
|
||||
Tutorials
|
||||
---------
|
||||
|
||||
A series of tutorials for Pwntools exists online, at
|
||||
https://github.com/Gallopsled/pwntools-tutorial#readme
|
||||
|
||||
|
||||
Making Connections
|
||||
------------------
|
||||
|
||||
@@ -188,10 +195,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).decode())
|
||||
aaaabaaacaaadaaaeaaa
|
||||
>>> cyclic(20)
|
||||
b'aaaabaaacaaadaaaeaaa'
|
||||
>>> # Assume EIP = 0x62616166 (b'faab' which is pack(0x62616166)) at crash time
|
||||
>>> print(cyclic_find(b'faab'))
|
||||
>>> cyclic_find(b'faab')
|
||||
120
|
||||
|
||||
ELF Manipulation
|
||||
|
||||
@@ -1,15 +1 @@
|
||||
:mod:`pwnlib.protocols` --- Wire Protocols
|
||||
=============================================
|
||||
|
||||
.. automodule:: pwnlib.protocols
|
||||
|
||||
|
||||
Supported Protocols
|
||||
-------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:glob:
|
||||
|
||||
protocols/*
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.protocols.adb import AdbClient
|
||||
AdbClient().wait_for_device()
|
||||
|
||||
:mod:`pwnlib.protocols.adb` --- ADB Protocol Implementation
|
||||
===========================================================
|
||||
|
||||
.. automodule:: pwnlib.protocols.adb
|
||||
:members:
|
||||
File renamed without changes.
@@ -1,7 +1,3 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.rop` --- Return Oriented Programming
|
||||
=================================================
|
||||
|
||||
|
||||
+19
-1
@@ -1,6 +1,24 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
import time
|
||||
from glob import glob
|
||||
|
||||
from pwnlib.asm import asm
|
||||
from pwnlib import constants
|
||||
from pwnlib.context import context
|
||||
from pwnlib.elf import ELF
|
||||
from pwnlib.rop import ROP
|
||||
from pwnlib.rop.call import Call, AppendedArgument
|
||||
from pwnlib.elf.maps import CAT_PROC_MAPS_EXIT
|
||||
from pwnlib.util.packing import *
|
||||
from pwnlib.util.fiddling import *
|
||||
from pwnlib.tubes.process import process
|
||||
from pwnlib import shellcraft
|
||||
from pwnlib.util.misc import which
|
||||
import pwnlib.data
|
||||
|
||||
context.clear()
|
||||
|
||||
|
||||
:mod:`pwnlib.rop.rop` --- Return Oriented Programming
|
||||
==========================================================
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.rop.srop import *
|
||||
|
||||
from pwnlib import constants
|
||||
from pwnlib import shellcraft
|
||||
from pwnlib.elf import ELF
|
||||
from pwnlib.tubes.process import process
|
||||
|
||||
:mod:`pwnlib.rop.srop` --- Sigreturn Oriented Programming
|
||||
==========================================================
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.runner import *
|
||||
from pwnlib.asm import asm
|
||||
|
||||
:mod:`pwnlib.runner` --- Running Shellcode
|
||||
===========================================
|
||||
|
||||
@@ -17,3 +17,9 @@
|
||||
|
||||
.. automodule:: pwnlib.shellcraft.amd64.linux
|
||||
:members:
|
||||
|
||||
:mod:`pwnlib.shellcraft.amd64.windows`
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: pwnlib.shellcraft.amd64.windows
|
||||
:members:
|
||||
@@ -1,6 +1,15 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
import tempfile
|
||||
|
||||
from pwnlib import shellcraft
|
||||
|
||||
from pwnlib.asm import asm
|
||||
from pwnlib.context import context
|
||||
from pwnlib.runner import run_assembly
|
||||
from pwnlib.util.fiddling import enhex
|
||||
from pwnlib.util.misc import write
|
||||
|
||||
context.clear(arch='mips')
|
||||
|
||||
:mod:`pwnlib.shellcraft.mips` --- Shellcode for MIPS
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
:members: kill, poll, interactive
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pwnlib.tubes.ssh.ssh_process
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pwnlib.tubes.ssh.ssh_connecter()
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
+16
-16
@@ -17,19 +17,19 @@
|
||||
count ,
|
||||
cycle ,
|
||||
dropwhile ,
|
||||
filter ,
|
||||
filterfalse ,
|
||||
groupby ,
|
||||
ifilter ,
|
||||
ifilterfalse ,
|
||||
imap ,
|
||||
islice ,
|
||||
izip ,
|
||||
izip_longest ,
|
||||
map ,
|
||||
permutations ,
|
||||
product ,
|
||||
repeat ,
|
||||
starmap ,
|
||||
takewhile ,
|
||||
tee
|
||||
tee ,
|
||||
zip ,
|
||||
zip_longest
|
||||
|
||||
.. function:: chain
|
||||
|
||||
@@ -63,29 +63,29 @@
|
||||
|
||||
Alias for :func:`itertools.groupby`
|
||||
|
||||
.. function:: ifilter
|
||||
.. function:: filter
|
||||
|
||||
Alias for :func:`itertools.ifilter`
|
||||
Alias for python3-style :func:`filter`
|
||||
|
||||
.. function:: ifilterfalse
|
||||
.. function:: filterfalse
|
||||
|
||||
Alias for :func:`itertools.ifilterfalse`
|
||||
Alias for :func:`itertools.filterfalse`
|
||||
|
||||
.. function:: imap
|
||||
.. function:: map
|
||||
|
||||
Alias for :func:`itertools.imap`
|
||||
Alias for python3-style :func:`map`
|
||||
|
||||
.. function:: islice
|
||||
|
||||
Alias for :func:`itertools.islice`
|
||||
|
||||
.. function:: izip
|
||||
.. function:: zip
|
||||
|
||||
Alias for :func:`itertools.izip`
|
||||
Alias for python3-style :func:`zip`
|
||||
|
||||
.. function:: izip_longest
|
||||
.. function:: zip_longest
|
||||
|
||||
Alias for :func:`itertools.izip_longest`
|
||||
Alias for :func:`itertools.zip_longest`
|
||||
|
||||
.. function:: permutations
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from pprint import pprint
|
||||
from pwnlib.util.misc import *
|
||||
import os, subprocess
|
||||
os.chdir("..")
|
||||
|
||||
:mod:`pwnlib.util.misc` --- We could not fit it any other place
|
||||
===============================================================
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
from pwnlib.util.net import *
|
||||
|
||||
|
||||
:mod:`pwnlib.util.net` --- Networking interfaces
|
||||
===================================================
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
import tempfile
|
||||
|
||||
from pwnlib.context import context
|
||||
from pwnlib.util.web import *
|
||||
|
||||
|
||||
+18
-12
@@ -11,18 +11,24 @@ Solution:
|
||||
"""
|
||||
|
||||
from pwn import *
|
||||
from multiprocessing import Process
|
||||
|
||||
os.system('''((
|
||||
echo prefix sometext ;
|
||||
echo prefix someothertext ;
|
||||
echo here comes the flag ;
|
||||
echo LostInTheInterTubes
|
||||
) | nc -l 1337) &
|
||||
''')
|
||||
def submit_data():
|
||||
with context.quiet:
|
||||
with listen(1337) as io:
|
||||
io.wait_for_connection()
|
||||
io.sendline(b'prefix sometext')
|
||||
io.sendline(b'prefix someothertext')
|
||||
io.sendline(b'here comes the flag')
|
||||
io.sendline(b'LostInTheInterTubes')
|
||||
|
||||
r = remote('localhost', 1337)
|
||||
atexit.register(r.clean_and_log)
|
||||
if __name__ == '__main__':
|
||||
p = Process(target=submit_data)
|
||||
p.start()
|
||||
|
||||
while True:
|
||||
line = r.recvline()
|
||||
print(re.findall(r'^prefix (\S+)$', line)[0])
|
||||
r = remote('localhost', 1337)
|
||||
atexit.register(r.clean_and_log)
|
||||
|
||||
while True:
|
||||
line = r.recvline()
|
||||
print(re.findall(br'^prefix (\S+)$', line)[0])
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""An example of using GDB Python API with Pwntools."""
|
||||
from pwn import *
|
||||
|
||||
|
||||
def check_write(gdb, exp_buf):
|
||||
"""Check that write() was called with the expected arguments."""
|
||||
fd = gdb.parse_and_eval('$rdi').cast(gdb.lookup_type('int'))
|
||||
assert fd == 1, fd
|
||||
buf_addr = gdb.parse_and_eval('$rsi').cast(gdb.lookup_type('long'))
|
||||
count = gdb.parse_and_eval('$rdx').cast(gdb.lookup_type('long'))
|
||||
buf = gdb.selected_inferior().read_memory(buf_addr, count).tobytes()
|
||||
assert buf == exp_buf, buf
|
||||
|
||||
|
||||
def demo_sync_breakpoint(cat, gdb, txt):
|
||||
"""Demonstrate a synchronous breakpoint."""
|
||||
# set the synchronous breakpoint on ``write``
|
||||
gdb.Breakpoint('write', temporary=True)
|
||||
|
||||
# resume the program
|
||||
gdb.continue_nowait()
|
||||
|
||||
# send the line
|
||||
cat.sendline(txt)
|
||||
|
||||
# wait until we hit the breakpoint
|
||||
gdb.wait()
|
||||
|
||||
# inspect program state
|
||||
check_write(gdb, (txt + '\n').encode())
|
||||
|
||||
# resume the program
|
||||
gdb.continue_nowait()
|
||||
|
||||
# expect to observe the line we just sent
|
||||
cat.recvuntil(txt)
|
||||
|
||||
|
||||
def demo_async_breakpoint(cat, gdb, txt):
|
||||
"""Demonstrate asynchronous breakpoint."""
|
||||
# set the asynchronous breakpoint on ``write``
|
||||
class WriteBp(gdb.Breakpoint):
|
||||
def __init__(self):
|
||||
super().__init__('write')
|
||||
self.count = 0
|
||||
|
||||
def stop(self):
|
||||
# called in a separate thread
|
||||
check_write(gdb, (txt + '\n').encode())
|
||||
self.count += 1
|
||||
|
||||
bp = WriteBp()
|
||||
|
||||
# resume the program
|
||||
gdb.continue_nowait()
|
||||
|
||||
# send the line and immediately expect to observe it
|
||||
cat.sendline(txt)
|
||||
cat.recvuntil(txt)
|
||||
|
||||
# check that we hit the breakpoint
|
||||
assert bp.count == 1, bp.count
|
||||
|
||||
# interrupt the program
|
||||
gdb.interrupt_and_wait()
|
||||
|
||||
# delete the breakpoint
|
||||
bp.delete()
|
||||
|
||||
# resume the program
|
||||
gdb.continue_nowait()
|
||||
|
||||
|
||||
def main():
|
||||
# start ``cat`` under GDB
|
||||
with gdb.debug('cat', gdbscript='''
|
||||
set logging on
|
||||
set pagination off
|
||||
''', api=True) as cat:
|
||||
|
||||
# the process is stopped
|
||||
# set the synchronous breakpoint on ``read``
|
||||
cat.gdb.Breakpoint('read', temporary=True)
|
||||
|
||||
# resume and wait until we hit it
|
||||
cat.gdb.continue_and_wait()
|
||||
|
||||
# demonstrate a more interesting synchronous breakpoint
|
||||
demo_sync_breakpoint(cat, cat.gdb, 'foo')
|
||||
|
||||
# terminate GDB
|
||||
cat.gdb.quit()
|
||||
|
||||
# now start ``cat`` normally
|
||||
with process('cat') as cat:
|
||||
# attach GDB
|
||||
_, cat_gdb = gdb.attach(cat, gdbscript='''
|
||||
set logging on
|
||||
set pagination off
|
||||
''', api=True)
|
||||
|
||||
# the process is stopped
|
||||
# demonstrate asynchronous breakpoint
|
||||
demo_async_breakpoint(cat, cat_gdb, 'bar')
|
||||
|
||||
# terminate GDB
|
||||
cat_gdb.quit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -36,5 +36,14 @@ print(shell.echo("single string"))
|
||||
print(shell.echo(["list","of","strings"]))
|
||||
print(shell["echo single statement"])
|
||||
|
||||
# ssh.process() is the most flexible way to run a command)
|
||||
io = shell.process(['/bin/bash', '-c', 'echo Hello $FOO'],
|
||||
env={'FOO': 'World'}, # Set environment
|
||||
stderr='/dev/null', # Override file descriptors
|
||||
aslr=False, # Disable ASLR on processes
|
||||
setuid=False, # Disable setuid bit so processes can be debugged
|
||||
shell=False) # Enable or disable shell evaluation
|
||||
print(io.recvall())
|
||||
|
||||
# Show off the interactive shell
|
||||
shell.interactive()
|
||||
@@ -0,0 +1,12 @@
|
||||
# Bash Completion
|
||||
|
||||
To install the completion, add `. /path/to/bash_completion.d/pwn`to your e.g. `~/.bash_profile`.
|
||||
|
||||
The `./install.sh` script attempts to do this for you automatically.
|
||||
|
||||
### Shellcraft Autocomplete
|
||||
|
||||
The legacy autocompletion for `pwn shellcraft` is also available at `./shellcraft`.
|
||||
|
||||
It is unsupported, and slow (runs `pwn shellcraft -l` every time your shell starts).
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BASH_COMPLETION_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
|
||||
if grep "$BASH_COMPLETION_DIR" ~/.bash_profile; then
|
||||
>&2 echo "Already installed"
|
||||
exit
|
||||
fi >/dev/null
|
||||
|
||||
cat >> ~/.bash_profile <<EOF
|
||||
# Install autocompletion for Pwntools
|
||||
. "$BASH_COMPLETION_DIR/pwn"
|
||||
EOF
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env bash
|
||||
# AUTOMATCALLY GENERATED by `shtab`
|
||||
|
||||
_shtab_pwnlib_options_='-h --help'
|
||||
_shtab_pwnlib_commands_='asm checksec constgrep cyclic debug disablenx disasm elfdiff elfpatch errno hex phd pwnstrip scramble shellcraft template unhex update version'
|
||||
|
||||
_shtab_pwnlib_asm='-h --help -f --format -o --output -c --context -v --avoid -n --newline -z --zero -d --debug -e --encoder -i --infile -r --run'
|
||||
_shtab_pwnlib_checksec='-h --help --file'
|
||||
_shtab_pwnlib_constgrep='-h --help -e --exact -i --case-insensitive -m --mask-mode -c --context'
|
||||
_shtab_pwnlib_cyclic='-h --help -a --alphabet -n --length -c --context -l -o --offset --lookup'
|
||||
_shtab_pwnlib_debug='-h --help -x --pid -c --context --exec --process --sysroot'
|
||||
_shtab_pwnlib_disablenx='-h --help'
|
||||
_shtab_pwnlib_disasm='-h --help -c --context -a --address --color --no-color'
|
||||
_shtab_pwnlib_elfdiff='-h --help'
|
||||
_shtab_pwnlib_elfpatch='-h --help'
|
||||
_shtab_pwnlib_errno='-h --help'
|
||||
_shtab_pwnlib_hex='-h --help'
|
||||
_shtab_pwnlib_phd='-h --help -w --width -l --highlight -s --skip -c --count -o --offset --color'
|
||||
_shtab_pwnlib_pwnstrip='-h --help -b --build-id -p --patch -o --output'
|
||||
_shtab_pwnlib_scramble='-h --help -f --format -o --output -c --context -p --alphanumeric -v --avoid -n --newline -z --zero -d --debug'
|
||||
_shtab_pwnlib_shellcraft='-h --help -? --show -o --out -f --format -d --debug -b --before -a --after -v --avoid -n --newline -z --zero -r --run --color --no-color --syscalls --address -l --list -s --shared'
|
||||
_shtab_pwnlib_template='-h --help --host --port --user --pass --password --path --quiet --color'
|
||||
_shtab_pwnlib_unhex='-h --help'
|
||||
_shtab_pwnlib_update='-h --help --install --pre'
|
||||
_shtab_pwnlib_version='-h --help'
|
||||
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_compgen_files() {
|
||||
compgen -f -- $1 # files
|
||||
compgen -d -S '/' -- $1 # recurse into subdirs
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_compgen_dirs() {
|
||||
compgen -d -S '/' -- $1 # recurse into subdirs
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_replace_hyphen() {
|
||||
echo $1 | sed 's/-/_/g'
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_replace_nonword() {
|
||||
echo "${1//[^[:word:]]/_}"
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_pwnlib_compgen_root_() {
|
||||
local args_gen="_shtab_pwnlib_COMPGEN"
|
||||
case "$word" in
|
||||
-*) COMPREPLY=( $(compgen -W "$_shtab_pwnlib_options_" -- "$word"; [ -n "${!args_gen}" ] && ${!args_gen} "$word") ) ;;
|
||||
*) COMPREPLY=( $(compgen -W "$_shtab_pwnlib_commands_" -- "$word"; [ -n "${!args_gen}" ] && ${!args_gen} "$word") ) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_pwnlib_compgen_command_() {
|
||||
local flags_list="_shtab_pwnlib_$(_shtab_replace_nonword $1)"
|
||||
local args_gen="${flags_list}_COMPGEN"
|
||||
COMPREPLY=( $(compgen -W "${!flags_list}" -- "$word"; [ -n "${!args_gen}" ] && ${!args_gen} "$word") )
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
# $2=COMP_WORDS[2]
|
||||
_shtab_pwnlib_compgen_subcommand_() {
|
||||
local flags_list="_shtab_pwnlib_$(_shtab_replace_nonword "${1}_${2}")"
|
||||
local args_gen="${flags_list}_COMPGEN"
|
||||
[ -n "${!args_gen}" ] && local opts_more="$(${!args_gen} "$word")"
|
||||
local opts="${!flags_list}"
|
||||
if [ -z "$opts$opts_more" ]; then
|
||||
_shtab_pwnlib_compgen_command_ $1
|
||||
else
|
||||
COMPREPLY=( $(compgen -W "$opts" -- "$word"; [ -n "$opts_more" ] && echo "$opts_more") )
|
||||
fi
|
||||
}
|
||||
|
||||
# Notes:
|
||||
# `COMPREPLY` contains what will be rendered after completion is triggered
|
||||
# `word` refers to the current typed word
|
||||
# `${!var}` is to evaluate the content of `var`
|
||||
# and expand its content as a variable
|
||||
# hello="world"
|
||||
# x="hello"
|
||||
# ${!x} -> ${hello} -> "world"
|
||||
_shtab_pwnlib() {
|
||||
local word="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "${COMP_CWORD}" -eq 1 ]; then
|
||||
_shtab_pwnlib_compgen_root_ ${COMP_WORDS[1]}
|
||||
elif [ "${COMP_CWORD}" -eq 2 ]; then
|
||||
_shtab_pwnlib_compgen_command_ ${COMP_WORDS[1]}
|
||||
elif [ "${COMP_CWORD}" -ge 3 ]; then
|
||||
_shtab_pwnlib_compgen_subcommand_ ${COMP_WORDS[1]} ${COMP_WORDS[2]}
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o nospace -F _shtab_pwnlib pwn
|
||||
+33
-7
@@ -1,13 +1,39 @@
|
||||
subdirs=xenial stable $(wildcard */)
|
||||
makefiles=$(wildcard */Makefile)
|
||||
subdirs=$(shell find . -mindepth 1 -maxdepth 1 -type d | xargs -n1 basename)
|
||||
tags=base stable beta dev
|
||||
ROOT=$(shell git rev-parse --show-toplevel)
|
||||
CMD ?= zsh
|
||||
|
||||
all: $(makefiles) $(subdirs)
|
||||
ifneq ($(HISTFILE),)
|
||||
MOUNT_HISTFILE=--mount type=bind,source="$(HISTFILE)",target=/home/pwntools/.history
|
||||
endif
|
||||
|
||||
$(subdirs):
|
||||
all: $(tags) $(subdirs)
|
||||
|
||||
tags: $(tags)
|
||||
|
||||
$(subdirs)::
|
||||
@echo "Building $@"
|
||||
docker build -t pwntools/pwntools:$(shell basename $(@)) "$@"
|
||||
|
||||
$(makefiles):
|
||||
make -C $(shell dirname $@)
|
||||
develop::
|
||||
docker run -it \
|
||||
--privileged \
|
||||
--net=host \
|
||||
--hostname localhost \
|
||||
--ulimit core=-1:-1 \
|
||||
$(MOUNT_HISTFILE) \
|
||||
--mount type=bind,source="$(ROOT)",target=/home/pwntools/pwntools \
|
||||
pwntools/pwntools:$(shell basename $(@)) \
|
||||
$(CMD)
|
||||
|
||||
.PHONY: all $(subdirs) $(makefiles)
|
||||
debug:
|
||||
@echo "Subdirs $(subdirs)"
|
||||
@echo "Tags $(tags)"
|
||||
|
||||
clean:
|
||||
docker container prune
|
||||
docker
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all $(subdirs) $(makefiles) $(tags)
|
||||
@@ -0,0 +1,53 @@
|
||||
# Pwntools Docker Images
|
||||
|
||||
This directory contains some Docker images with various versions of Pwntools pre-installed.
|
||||
|
||||
## Getting Images
|
||||
|
||||
You can either make them yourself, or pull from Docker Hub.
|
||||
|
||||
### Docker Hub
|
||||
|
||||
To pull an image from Docker hub, just run the command:
|
||||
|
||||
```sh
|
||||
$ docker pull pwntools/pwntools:stable
|
||||
```
|
||||
|
||||
Replace `stable` with `beta` or `dev` as desired.
|
||||
|
||||
### Building Locally
|
||||
|
||||
To build the images locally, just invoke the `Makefile` with the desired branch target.
|
||||
|
||||
```sh
|
||||
$ make -C extra/docker dev
|
||||
```
|
||||
|
||||
## Running Images
|
||||
|
||||
To run the `stable`, `beta`, or `dev` image, we recommend the following command line, in this example it is the `dev` image.
|
||||
|
||||
```sh
|
||||
$ docker run -it \
|
||||
--privileged \
|
||||
--net=host \
|
||||
--ulimit core=-1:-1 \
|
||||
pwntools/pwntools:dev
|
||||
```
|
||||
|
||||
The `--privileged` option is needed to perform any debugging with GDB.
|
||||
|
||||
The `--ulimit` option is needed for any corefiles to drop when a program crashes.
|
||||
|
||||
The `--net=host` allows you to easily connect to services hosted inside the container from outside the container.
|
||||
|
||||
## Development Dockerfile
|
||||
|
||||
In addition to `stable`, `beta`, and `dev` Dockerfiles, there is also a `develop` dockerfile which mounts your Pwntools installation inside the VM so you can develop seamlessly while editing on your host.
|
||||
|
||||
```sh
|
||||
$ make -C extra/docker develop
|
||||
```
|
||||
|
||||
You will be dropped into a shell, and any changes you make to your local Pwntools checkout will be immediately reflected inside the Docker container. This is useful for e.g. editing on a macOS host, but testing your changes on Ubuntu without needing to copy files around.
|
||||
@@ -1 +0,0 @@
|
||||
xenial
|
||||
@@ -0,0 +1,51 @@
|
||||
############################################################
|
||||
# Dockerfile to build Pwntools container
|
||||
# Based on Ubuntu
|
||||
############################################################
|
||||
|
||||
FROM ubuntu:jammy
|
||||
MAINTAINER Maintainer Gallopsled et al.
|
||||
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LANGUAGE en_US:en
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
sudo \
|
||||
locales \
|
||||
build-essential \
|
||||
elfutils \
|
||||
git \
|
||||
libssl-dev \
|
||||
libffi-dev \
|
||||
python2.7 \
|
||||
python2.7-dev \
|
||||
python2-pip-whl \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-dev \
|
||||
python-is-python3 \
|
||||
qemu-user-static \
|
||||
binutils-arm-linux-gnueabihf \
|
||||
binutils-aarch64-linux-gnu \
|
||||
binutils-mips-linux-gnu \
|
||||
binutils-mipsel-linux-gnu \
|
||||
binutils-powerpc-linux-gnu \
|
||||
binutils-powerpc64-linux-gnu \
|
||||
binutils-sparc64-linux-gnu \
|
||||
binutils-riscv64-linux-gnu \
|
||||
tmux \
|
||||
patchelf \
|
||||
&& locale-gen en_US.UTF-8 \
|
||||
&& update-locale LANG=en_US.UTF-8 \
|
||||
&& PYTHONPATH=`echo /usr/share/python-wheels/pip-*.whl` python2.7 -m pip install --upgrade pip setuptools wheel \
|
||||
&& python2.7 -m pip install --upgrade pwntools \
|
||||
&& python3 -m pip install --upgrade pip \
|
||||
&& python3 -m pip install --upgrade pwntools \
|
||||
&& PWNLIB_NOTERM=1 pwn update \
|
||||
&& useradd -m pwntools \
|
||||
&& passwd --delete --unlock pwntools \
|
||||
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
|
||||
USER pwntools
|
||||
@@ -1,6 +1,7 @@
|
||||
FROM pwntools/pwntools:stable
|
||||
|
||||
USER root
|
||||
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools@beta
|
||||
RUN python2.7 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools@beta \
|
||||
&& python3 -m pip install --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@beta
|
||||
RUN PWNLIB_NOTERM=1 pwn update
|
||||
USER pwntools
|
||||
@@ -0,0 +1,8 @@
|
||||
from debian:buster
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get -y dist-upgrade
|
||||
RUN apt-get -y install python3 python3-pip
|
||||
RUN apt-get -y install git wget unzip
|
||||
|
||||
RUN pip3 install --upgrade git+https://github.com/Gallopsled/pwntools@dev
|
||||
@@ -1,6 +1,7 @@
|
||||
FROM pwntools/pwntools:stable
|
||||
|
||||
USER root
|
||||
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools@dev
|
||||
RUN python2.7 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools@dev \
|
||||
&& python3 -m pip install --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@dev
|
||||
RUN PWNLIB_NOTERM=1 pwn update
|
||||
USER pwntools
|
||||
@@ -0,0 +1,5 @@
|
||||
try:
|
||||
from pwn import *
|
||||
except Exception:
|
||||
print("Could not import pwntools")
|
||||
import os, re, sys, time, random, urllib, datetime, itertools, subprocess, multiprocessing
|
||||
@@ -0,0 +1,86 @@
|
||||
FROM pwntools/pwntools:base
|
||||
|
||||
# Support sharing history with the develop Dockerfile
|
||||
ENV HISTFILE=/home/pwntools/.history
|
||||
|
||||
# Uninstall existing versions of pwntools
|
||||
USER root
|
||||
RUN python2.7 -m pip uninstall -q -y pwntools \
|
||||
&& python3 -m pip uninstall -q -y pwntools
|
||||
|
||||
# Switch back to the pwntools user from here forward
|
||||
USER pwntools
|
||||
WORKDIR /home/pwntools
|
||||
|
||||
# Since we are not installing Pwntools systemwide, the "pwn" binaries
|
||||
# etc will all end up in this path.
|
||||
ENV PATH="/home/pwntools/.local/bin:${PATH}"
|
||||
|
||||
# Install Pwntools to the home directory, make it an editable install
|
||||
RUN git clone https://github.com/Gallopsled/pwntools \
|
||||
&& python2.7 -m pip install --upgrade --editable pwntools \
|
||||
&& python3 -m pip install --upgrade --editable pwntools \
|
||||
&& PWNLIB_NOTERM=1 pwn version
|
||||
|
||||
# Requirements for running the tests
|
||||
RUN python2.7 -m pip install --upgrade --requirement pwntools/docs/requirements.txt \
|
||||
&& python3 -m pip install --upgrade --requirement pwntools/docs/requirements.txt
|
||||
|
||||
# Python niceties for debugging
|
||||
RUN python2.7 -m pip install -U ipython ipdb \
|
||||
&& python3 -m pip install -U ipython ipdb
|
||||
|
||||
# Dependencies from .travis.yml addons -> apt -> packages
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ="UTC"
|
||||
RUN sudo apt-get update && sudo -E apt-get install -y \
|
||||
tzdata \
|
||||
ash \
|
||||
bash \
|
||||
bash-static \
|
||||
binutils-msp430 \
|
||||
binutils-multiarch \
|
||||
binutils-s390x-linux-gnu \
|
||||
dash \
|
||||
gcc \
|
||||
gcc-multilib \
|
||||
gdb \
|
||||
ksh \
|
||||
lib32stdc++6 \
|
||||
libc6-dev-i386 \
|
||||
mksh \
|
||||
pandoc \
|
||||
qemu-user-static \
|
||||
socat \
|
||||
sshpass \
|
||||
vim \
|
||||
zsh \
|
||||
# Misc useful things when developing
|
||||
curl \
|
||||
ipython3 \
|
||||
lsb-release \
|
||||
ssh \
|
||||
unzip \
|
||||
wget
|
||||
|
||||
# Use zsh by default
|
||||
RUN sudo -E chsh -s /bin/zsh pwntools
|
||||
|
||||
# Get and install prezto
|
||||
RUN git clone --recursive https://github.com/sorin-ionescu/prezto.git .zprezto
|
||||
RUN bash -c 'for file in .zprezto/runcoms/z*; do ln -s $file .$(basename $file); done'
|
||||
|
||||
# Get and install pwndbg
|
||||
RUN git clone --recursive https://github.com/pwndbg/pwndbg
|
||||
RUN cd pwndbg && ./setup.sh
|
||||
|
||||
# Install autocompletion
|
||||
RUN ln -s /home/pwntools/pwntools/extra/zsh_completion/_pwn /home/pwntools/.zprezto/modules/completion/external/src
|
||||
|
||||
# Install ipython profile and auto-import
|
||||
RUN mkdir -p /home/pwntools/.ipython/profile_default/startup
|
||||
ADD 10-import.py /home/pwntools/.ipython/profile_default/startup
|
||||
ADD ipython_config.py /home/pwntools/.ipython/profile_default
|
||||
|
||||
# Do not require password for sudo
|
||||
RUN echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/travis
|
||||
@@ -0,0 +1,563 @@
|
||||
# Configuration file for ipython.
|
||||
|
||||
c = get_config()
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# InteractiveShellApp configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# A Mixin for applications that start InteractiveShell instances.
|
||||
#
|
||||
# Provides configurables for loading extensions and executing files as part of
|
||||
# configuring a Shell environment.
|
||||
#
|
||||
# The following methods should be called by the :meth:`initialize` method of the
|
||||
# subclass:
|
||||
#
|
||||
# - :meth:`init_path`
|
||||
# - :meth:`init_shell` (to be implemented by the subclass)
|
||||
# - :meth:`init_gui_pylab`
|
||||
# - :meth:`init_extensions`
|
||||
# - :meth:`init_code`
|
||||
|
||||
# Execute the given command string.
|
||||
# c.InteractiveShellApp.code_to_run = ''
|
||||
|
||||
# Run the file referenced by the PYTHONSTARTUP environment variable at IPython
|
||||
# startup.
|
||||
# c.InteractiveShellApp.exec_PYTHONSTARTUP = True
|
||||
|
||||
# lines of code to run at IPython startup.
|
||||
c.InteractiveShell.confirm_exit = False
|
||||
c.InteractiveShell.separate_in = ''
|
||||
c.InteractiveShell.separate_out = ''
|
||||
c.InteractiveShell.separate_out2 = ''
|
||||
|
||||
# c.PromptManager.in_template = '>>> '
|
||||
# c.PromptManager.in2_template = '..: '
|
||||
# c.PromptManager.out_template = ''
|
||||
# c.PromptManager.justify = False
|
||||
|
||||
c.TerminalIPythonApp.display_banner = False
|
||||
|
||||
from IPython.terminal.prompts import Prompts, Token
|
||||
|
||||
class ClassicPrompts(Prompts):
|
||||
def in_prompt_tokens(self, cli=None):
|
||||
return [
|
||||
(Token.Prompt, '>>> '),
|
||||
]
|
||||
|
||||
def continuation_prompt_tokens(self, cli=None, width=None):
|
||||
return [
|
||||
(Token.Prompt, '... ')
|
||||
]
|
||||
|
||||
def rewrite_prompt_tokens(self):
|
||||
return []
|
||||
|
||||
def out_prompt_tokens(self):
|
||||
return []
|
||||
|
||||
c.TerminalInteractiveShell.prompts_class = ClassicPrompts
|
||||
|
||||
# Enable GUI event loop integration with any of ('glut', 'gtk', 'gtk3', 'none',
|
||||
# 'osx', 'pyglet', 'qt', 'qt4', 'tk', 'wx').
|
||||
# c.InteractiveShellApp.gui = None
|
||||
|
||||
# Pre-load matplotlib and numpy for interactive use, selecting a particular
|
||||
# matplotlib backend and loop integration.
|
||||
# c.InteractiveShellApp.pylab = None
|
||||
|
||||
# Configure matplotlib for interactive use with the default matplotlib backend.
|
||||
# c.InteractiveShellApp.matplotlib = None
|
||||
|
||||
# If true, IPython will populate the user namespace with numpy, pylab, etc. and
|
||||
# an ``import *`` is done from numpy and pylab, when using pylab mode.
|
||||
#
|
||||
# When False, pylab mode should not import any names into the user namespace.
|
||||
# c.InteractiveShellApp.pylab_import_all = True
|
||||
|
||||
# A list of dotted module names of IPython extensions to load.
|
||||
# c.InteractiveShellApp.extensions = []
|
||||
|
||||
# Run the module as a script.
|
||||
# c.InteractiveShellApp.module_to_run = ''
|
||||
|
||||
# Should variables loaded at startup (by startup files, exec_lines, etc.) be
|
||||
# hidden from tools like %who?
|
||||
# c.InteractiveShellApp.hide_initial_ns = True
|
||||
|
||||
# dotted module name of an IPython extension to load.
|
||||
# c.InteractiveShellApp.extra_extension = ''
|
||||
|
||||
# List of files to run at IPython startup.
|
||||
# c.InteractiveShellApp.exec_files = []
|
||||
|
||||
# A file to be run
|
||||
# c.InteractiveShellApp.file_to_run = ''
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# TerminalIPythonApp configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# TerminalIPythonApp will inherit config from: BaseIPythonApplication,
|
||||
# Application, InteractiveShellApp
|
||||
|
||||
# Run the file referenced by the PYTHONSTARTUP environment variable at IPython
|
||||
# startup.
|
||||
# c.TerminalIPythonApp.exec_PYTHONSTARTUP = True
|
||||
|
||||
# Pre-load matplotlib and numpy for interactive use, selecting a particular
|
||||
# matplotlib backend and loop integration.
|
||||
# c.TerminalIPythonApp.pylab = None
|
||||
|
||||
# Create a massive crash report when IPython encounters what may be an internal
|
||||
# error. The default is to append a short message to the usual traceback
|
||||
# c.TerminalIPythonApp.verbose_crash = False
|
||||
|
||||
# Run the module as a script.
|
||||
# c.TerminalIPythonApp.module_to_run = ''
|
||||
|
||||
# The date format used by logging formatters for %(asctime)s
|
||||
# c.TerminalIPythonApp.log_datefmt = '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
# Whether to overwrite existing config files when copying
|
||||
# c.TerminalIPythonApp.overwrite = False
|
||||
|
||||
# Execute the given command string.
|
||||
# c.TerminalIPythonApp.code_to_run = ''
|
||||
|
||||
# Set the log level by value or name.
|
||||
# c.TerminalIPythonApp.log_level = 30
|
||||
|
||||
# lines of code to run at IPython startup.
|
||||
# c.TerminalIPythonApp.exec_lines = []
|
||||
|
||||
# Suppress warning messages about legacy config files
|
||||
# c.TerminalIPythonApp.ignore_old_config = False
|
||||
|
||||
# Path to an extra config file to load.
|
||||
#
|
||||
# If specified, load this config file in addition to any other IPython config.
|
||||
# c.TerminalIPythonApp.extra_config_file = u''
|
||||
|
||||
# Should variables loaded at startup (by startup files, exec_lines, etc.) be
|
||||
# hidden from tools like %who?
|
||||
# c.TerminalIPythonApp.hide_initial_ns = True
|
||||
|
||||
# dotted module name of an IPython extension to load.
|
||||
# c.TerminalIPythonApp.extra_extension = ''
|
||||
|
||||
# A file to be run
|
||||
# c.TerminalIPythonApp.file_to_run = ''
|
||||
|
||||
# The IPython profile to use.
|
||||
# c.TerminalIPythonApp.profile = u'default'
|
||||
|
||||
# Configure matplotlib for interactive use with the default matplotlib backend.
|
||||
# c.TerminalIPythonApp.matplotlib = None
|
||||
|
||||
# If a command or file is given via the command-line, e.g. 'ipython foo.py',
|
||||
# start an interactive shell after executing the file or command.
|
||||
# c.TerminalIPythonApp.force_interact = False
|
||||
|
||||
# If true, IPython will populate the user namespace with numpy, pylab, etc. and
|
||||
# an ``import *`` is done from numpy and pylab, when using pylab mode.
|
||||
#
|
||||
# When False, pylab mode should not import any names into the user namespace.
|
||||
# c.TerminalIPythonApp.pylab_import_all = True
|
||||
|
||||
# The name of the IPython directory. This directory is used for logging
|
||||
# configuration (through profiles), history storage, etc. The default is usually
|
||||
# $HOME/.ipython. This options can also be specified through the environment
|
||||
# variable IPYTHONDIR.
|
||||
# c.TerminalIPythonApp.ipython_dir = u''
|
||||
|
||||
# Whether to display a banner upon starting IPython.
|
||||
# c.TerminalIPythonApp.display_banner = True
|
||||
|
||||
# Whether to install the default config files into the profile dir. If a new
|
||||
# profile is being created, and IPython contains config files for that profile,
|
||||
# then they will be staged into the new directory. Otherwise, default config
|
||||
# files will be automatically generated.
|
||||
# c.TerminalIPythonApp.copy_config_files = False
|
||||
|
||||
# List of files to run at IPython startup.
|
||||
# c.TerminalIPythonApp.exec_files = []
|
||||
|
||||
# Enable GUI event loop integration with any of ('glut', 'gtk', 'gtk3', 'none',
|
||||
# 'osx', 'pyglet', 'qt', 'qt4', 'tk', 'wx').
|
||||
# c.TerminalIPythonApp.gui = None
|
||||
|
||||
# A list of dotted module names of IPython extensions to load.
|
||||
# c.TerminalIPythonApp.extensions = []
|
||||
|
||||
# Start IPython quickly by skipping the loading of config files.
|
||||
# c.TerminalIPythonApp.quick = False
|
||||
|
||||
# The Logging format template
|
||||
# c.TerminalIPythonApp.log_format = '[%(name)s]%(highlevel)s %(message)s'
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# TerminalInteractiveShell configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# TerminalInteractiveShell will inherit config from: InteractiveShell
|
||||
|
||||
# auto editing of files with syntax errors.
|
||||
# c.TerminalInteractiveShell.autoedit_syntax = False
|
||||
|
||||
# Use colors for displaying information about objects. Because this information
|
||||
# is passed through a pager (like 'less'), and some pagers get confused with
|
||||
# color codes, this capability can be turned off.
|
||||
# c.TerminalInteractiveShell.color_info = True
|
||||
|
||||
# A list of ast.NodeTransformer subclass instances, which will be applied to
|
||||
# user input before code is run.
|
||||
# c.TerminalInteractiveShell.ast_transformers = []
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.history_length = 10000
|
||||
|
||||
# Don't call post-execute functions that have failed in the past.
|
||||
# c.TerminalInteractiveShell.disable_failing_post_execute = False
|
||||
|
||||
# Show rewritten input, e.g. for autocall.
|
||||
# c.TerminalInteractiveShell.show_rewritten_input = True
|
||||
|
||||
# Set the color scheme (NoColor, Linux, or LightBG).
|
||||
# c.TerminalInteractiveShell.colors = 'Linux'
|
||||
|
||||
# Autoindent IPython code entered interactively.
|
||||
# c.TerminalInteractiveShell.autoindent = True
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.separate_in = '\n'
|
||||
|
||||
# Deprecated, use PromptManager.in2_template
|
||||
# c.TerminalInteractiveShell.prompt_in2 = ' .\\D.: '
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.separate_out = ''
|
||||
|
||||
# Deprecated, use PromptManager.in_template
|
||||
# c.TerminalInteractiveShell.prompt_in1 = 'In [\\#]: '
|
||||
|
||||
# Make IPython automatically call any callable object even if you didn't type
|
||||
# explicit parentheses. For example, 'str 43' becomes 'str(43)' automatically.
|
||||
# The value can be '0' to disable the feature, '1' for 'smart' autocall, where
|
||||
# it is not applied if there are no more arguments on the line, and '2' for
|
||||
# 'full' autocall, where all callable objects are automatically called (even if
|
||||
# no arguments are present).
|
||||
# c.TerminalInteractiveShell.autocall = 0
|
||||
|
||||
# Number of lines of your screen, used to control printing of very long strings.
|
||||
# Strings longer than this number of lines will be sent through a pager instead
|
||||
# of directly printed. The default value for this is 0, which means IPython
|
||||
# will auto-detect your screen size every time it needs to print certain
|
||||
# potentially long strings (this doesn't change the behavior of the 'print'
|
||||
# keyword, it's only triggered internally). If for some reason this isn't
|
||||
# working well (it needs curses support), specify it yourself. Otherwise don't
|
||||
# change the default.
|
||||
# c.TerminalInteractiveShell.screen_length = 0
|
||||
|
||||
# Set the editor used by IPython (default to $EDITOR/vi/notepad).
|
||||
# c.TerminalInteractiveShell.editor = u'nano'
|
||||
|
||||
# Deprecated, use PromptManager.justify
|
||||
# c.TerminalInteractiveShell.prompts_pad_left = True
|
||||
|
||||
# The part of the banner to be printed before the profile
|
||||
# c.TerminalInteractiveShell.banner1 = 'Python 2.7.6 (default, Apr 23 2014, 12:04:55) \nType "copyright", "credits" or "license" for more information.\n\nIPython 2.0.0 -- An enhanced Interactive Python.\n? -> Introduction and overview of IPython\'s features.\n%quickref -> Quick reference.\nhelp -> Python\'s own help system.\nobject? -> Details about \'object\', use \'object??\' for extra details.\n'
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.readline_parse_and_bind = ['tab: complete', '"\\C-l": clear-screen', 'set show-all-if-ambiguous on', '"\\C-o": tab-insert', '"\\C-r": reverse-search-history', '"\\C-s": forward-search-history', '"\\C-p": history-search-backward', '"\\C-n": history-search-forward', '"\\e[A": history-search-backward', '"\\e[B": history-search-forward', '"\\C-k": kill-line', '"\\C-u": unix-line-discard']
|
||||
|
||||
# The part of the banner to be printed after the profile
|
||||
# c.TerminalInteractiveShell.banner2 = ''
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.separate_out2 = ''
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.wildcards_case_sensitive = True
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.debug = False
|
||||
|
||||
# Set to confirm when you try to exit IPython with an EOF (Control-D in Unix,
|
||||
# Control-Z/Enter in Windows). By typing 'exit' or 'quit', you can force a
|
||||
# direct exit without any confirmation.
|
||||
# c.TerminalInteractiveShell.confirm_exit = True
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.ipython_dir = ''
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.readline_remove_delims = '-/~'
|
||||
|
||||
# Start logging to the default log file.
|
||||
# c.TerminalInteractiveShell.logstart = False
|
||||
|
||||
# The name of the logfile to use.
|
||||
# c.TerminalInteractiveShell.logfile = ''
|
||||
|
||||
# The shell program to be used for paging.
|
||||
# c.TerminalInteractiveShell.pager = 'less'
|
||||
|
||||
# Enable magic commands to be called without the leading %.
|
||||
# c.TerminalInteractiveShell.automagic = True
|
||||
|
||||
# Save multi-line entries as one entry in readline history
|
||||
# c.TerminalInteractiveShell.multiline_history = True
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.readline_use = True
|
||||
|
||||
# Enable deep (recursive) reloading by default. IPython can use the deep_reload
|
||||
# module which reloads changes in modules recursively (it replaces the reload()
|
||||
# function, so you don't need to change anything to use it). deep_reload()
|
||||
# forces a full reload of modules whose code may have changed, which the default
|
||||
# reload() function does not. When deep_reload is off, IPython will use the
|
||||
# normal reload(), but deep_reload will still be available as dreload().
|
||||
# c.TerminalInteractiveShell.deep_reload = False
|
||||
|
||||
# Start logging to the given file in append mode.
|
||||
# c.TerminalInteractiveShell.logappend = ''
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.xmode = 'Context'
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.quiet = False
|
||||
|
||||
# Enable auto setting the terminal title.
|
||||
# c.TerminalInteractiveShell.term_title = False
|
||||
|
||||
#
|
||||
# c.TerminalInteractiveShell.object_info_string_level = 0
|
||||
|
||||
# Deprecated, use PromptManager.out_template
|
||||
# c.TerminalInteractiveShell.prompt_out = 'Out[\\#]: '
|
||||
|
||||
# Set the size of the output cache. The default is 1000, you can change it
|
||||
# permanently in your config file. Setting it to 0 completely disables the
|
||||
# caching system, and the minimum value accepted is 20 (if you provide a value
|
||||
# less than 20, it is reset to 0 and a warning is issued). This limit is
|
||||
# defined because otherwise you'll spend more time re-flushing a too small cache
|
||||
# than working
|
||||
# c.TerminalInteractiveShell.cache_size = 1000
|
||||
|
||||
# 'all', 'last', 'last_expr' or 'none', specifying which nodes should be run
|
||||
# interactively (displaying output from expressions).
|
||||
# c.TerminalInteractiveShell.ast_node_interactivity = 'last_expr'
|
||||
|
||||
# Automatically call the pdb debugger after every exception.
|
||||
# c.TerminalInteractiveShell.pdb = False
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# PromptManager configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# This is the primary interface for producing IPython's prompts.
|
||||
|
||||
# Output prompt. '\#' will be transformed to the prompt number
|
||||
# c.PromptManager.out_template = 'Out[\\#]: '
|
||||
|
||||
# Continuation prompt.
|
||||
# c.PromptManager.in2_template = ' .\\D.: '
|
||||
|
||||
# If True (default), each prompt will be right-aligned with the preceding one.
|
||||
# c.PromptManager.justify = True
|
||||
|
||||
# Input prompt. '\#' will be transformed to the prompt number
|
||||
# c.PromptManager.in_template = 'In [\\#]: '
|
||||
|
||||
#
|
||||
# c.PromptManager.color_scheme = 'Linux'
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# HistoryManager configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# A class to organize all history-related functionality in one place.
|
||||
|
||||
# HistoryManager will inherit config from: HistoryAccessor
|
||||
|
||||
# Should the history database include output? (default: no)
|
||||
# c.HistoryManager.db_log_output = False
|
||||
|
||||
# Write to database every x commands (higher values save disk access & power).
|
||||
# Values of 1 or less effectively disable caching.
|
||||
# c.HistoryManager.db_cache_size = 0
|
||||
|
||||
# Path to file to use for SQLite history database.
|
||||
#
|
||||
# By default, IPython will put the history database in the IPython profile
|
||||
# directory. If you would rather share one history among profiles, you can set
|
||||
# this value in each, so that they are consistent.
|
||||
#
|
||||
# Due to an issue with fcntl, SQLite is known to misbehave on some NFS mounts.
|
||||
# If you see IPython hanging, try setting this to something on a local disk,
|
||||
# e.g::
|
||||
#
|
||||
# ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
|
||||
# c.HistoryManager.hist_file = u''
|
||||
|
||||
# Options for configuring the SQLite connection
|
||||
#
|
||||
# These options are passed as keyword args to sqlite3.connect when establishing
|
||||
# database conenctions.
|
||||
# c.HistoryManager.connection_options = {}
|
||||
|
||||
# enable the SQLite history
|
||||
#
|
||||
# set enabled=False to disable the SQLite history, in which case there will be
|
||||
# no stored history, no SQLite connection, and no background saving thread.
|
||||
# This may be necessary in some threaded environments where IPython is embedded.
|
||||
# c.HistoryManager.enabled = True
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# ProfileDir configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# An object to manage the profile directory and its resources.
|
||||
#
|
||||
# The profile directory is used by all IPython applications, to manage
|
||||
# configuration, logging and security.
|
||||
#
|
||||
# This object knows how to find, create and manage these directories. This
|
||||
# should be used by any code that wants to handle profiles.
|
||||
|
||||
# Set the profile location directly. This overrides the logic used by the
|
||||
# `profile` option.
|
||||
# c.ProfileDir.location = u''
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# PlainTextFormatter configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# The default pretty-printer.
|
||||
#
|
||||
# This uses :mod:`IPython.lib.pretty` to compute the format data of the object.
|
||||
# If the object cannot be pretty printed, :func:`repr` is used. See the
|
||||
# documentation of :mod:`IPython.lib.pretty` for details on how to write pretty
|
||||
# printers. Here is a simple example::
|
||||
#
|
||||
# def dtype_pprinter(obj, p, cycle):
|
||||
# if cycle:
|
||||
# return p.text('dtype(...)')
|
||||
# if hasattr(obj, 'fields'):
|
||||
# if obj.fields is None:
|
||||
# p.text(repr(obj))
|
||||
# else:
|
||||
# p.begin_group(7, 'dtype([')
|
||||
# for i, field in enumerate(obj.descr):
|
||||
# if i > 0:
|
||||
# p.text(',')
|
||||
# p.breakable()
|
||||
# p.pretty(field)
|
||||
# p.end_group(7, '])')
|
||||
|
||||
# PlainTextFormatter will inherit config from: BaseFormatter
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.type_printers = {}
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.newline = '\n'
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.float_precision = ''
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.verbose = False
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.deferred_printers = {}
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.pprint = True
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.max_width = 79
|
||||
|
||||
#
|
||||
# c.PlainTextFormatter.singleton_printers = {}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# IPCompleter configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Extension of the completer class with IPython-specific features
|
||||
|
||||
# IPCompleter will inherit config from: Completer
|
||||
|
||||
# Instruct the completer to omit private method names
|
||||
#
|
||||
# Specifically, when completing on ``object.<tab>``.
|
||||
#
|
||||
# When 2 [default]: all names that start with '_' will be excluded.
|
||||
#
|
||||
# When 1: all 'magic' names (``__foo__``) will be excluded.
|
||||
#
|
||||
# When 0: nothing will be excluded.
|
||||
# c.IPCompleter.omit__names = 2
|
||||
|
||||
# Whether to merge completion results into a single list
|
||||
#
|
||||
# If False, only the completion results from the first non-empty completer will
|
||||
# be returned.
|
||||
# c.IPCompleter.merge_completions = True
|
||||
|
||||
# Instruct the completer to use __all__ for the completion
|
||||
#
|
||||
# Specifically, when completing on ``object.<tab>``.
|
||||
#
|
||||
# When True: only those names in obj.__all__ will be included.
|
||||
#
|
||||
# When False [default]: the __all__ attribute is ignored
|
||||
# c.IPCompleter.limit_to__all__ = False
|
||||
|
||||
# Activate greedy completion
|
||||
#
|
||||
# This will enable completion on elements of lists, results of function calls,
|
||||
# etc., but can be unsafe because the code is actually evaluated on TAB.
|
||||
# c.IPCompleter.greedy = False
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# ScriptMagics configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Magics for talking to scripts
|
||||
#
|
||||
# This defines a base `%%script` cell magic for running a cell with a program in
|
||||
# a subprocess, and registers a few top-level magics that call %%script with
|
||||
# common interpreters.
|
||||
|
||||
# Extra script cell magics to define
|
||||
#
|
||||
# This generates simple wrappers of `%%script foo` as `%%foo`.
|
||||
#
|
||||
# If you want to add script magics that aren't on your path, specify them in
|
||||
# script_paths
|
||||
# c.ScriptMagics.script_magics = []
|
||||
|
||||
# Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
|
||||
#
|
||||
# Only necessary for items in script_magics where the default path will not find
|
||||
# the right interpreter.
|
||||
# c.ScriptMagics.script_paths = {}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# StoreMagics configuration
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Lightweight persistence for python variables.
|
||||
#
|
||||
# Provides the %store magic.
|
||||
|
||||
# If True, any %store-d variables will be automatically restored when IPython
|
||||
# starts.
|
||||
# c.StoreMagics.autorestore = False
|
||||
@@ -1,26 +0,0 @@
|
||||
############################################################
|
||||
# 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
|
||||
@@ -1,8 +0,0 @@
|
||||
all: Dockerfile
|
||||
|
||||
Dockerfile: ../xenial/Dockerfile FORCE
|
||||
sed "s|ubuntu:xenial|kalilinux/kali-linux-docker|" < "$<" > "$@"
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all
|
||||
@@ -1,26 +0,0 @@
|
||||
############################################################
|
||||
# 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
|
||||
@@ -1,8 +0,0 @@
|
||||
all: Dockerfile
|
||||
|
||||
Dockerfile: ../xenial/Dockerfile FORCE
|
||||
sed "s|ubuntu:xenial|ubuntu:precise|" < "$<" > "$@"
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all
|
||||
@@ -1,6 +1,7 @@
|
||||
FROM pwntools/pwntools:base
|
||||
|
||||
USER root
|
||||
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools@stable
|
||||
RUN python2.7 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools@stable \
|
||||
&& python3 -m pip install --force-reinstall --upgrade git+https://github.com/Gallopsled/pwntools@stable
|
||||
RUN PWNLIB_NOTERM=1 pwn update
|
||||
USER pwntools
|
||||
@@ -1,26 +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 \
|
||||
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
|
||||
@@ -1,8 +0,0 @@
|
||||
all: Dockerfile
|
||||
|
||||
Dockerfile: ../xenial/Dockerfile FORCE
|
||||
sed "s|ubuntu:xenial|ubuntu:trusty|" < "$<" > "$@"
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: all
|
||||
@@ -1,26 +0,0 @@
|
||||
############################################################
|
||||
# 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
|
||||
@@ -0,0 +1,5 @@
|
||||
# ZSH Completion
|
||||
|
||||
To install the completion, copy `_pwn` to somewhere in your `$fpath`.
|
||||
|
||||
The `./install.sh` script attempts to automate this, and advises an alternative method if that's unavailable.
|
||||
@@ -0,0 +1,197 @@
|
||||
#compdef pwn
|
||||
# ----------------------------------------------------------------------------------------
|
||||
# Zsh completion file for pwn
|
||||
#
|
||||
# Pwntools Command-line Interface
|
||||
#
|
||||
# This file was generated with help from Zargparse (https://github.com/ctil/zargparse)
|
||||
# ----------------------------------------------------------------------------------------
|
||||
|
||||
typeset -A opt_args
|
||||
|
||||
_pwn() {
|
||||
# Define the subcommands
|
||||
local -a commands
|
||||
commands=(
|
||||
'asm:Assemble shellcode into bytes'
|
||||
'checksec:Check binary security settings'
|
||||
'constgrep:Looking up constants from header files.'
|
||||
'cyclic:Cyclic pattern creator/finder'
|
||||
'debug:Debug a binary in GDB'
|
||||
'disasm:Disassemble bytes into text format'
|
||||
'disablenx:Disable NX for an ELF binary'
|
||||
'elfdiff:Compare two ELF files'
|
||||
'elfpatch:Patch an ELF file'
|
||||
'errno:Prints out error messages'
|
||||
'hex:Hex-encodes data provided on the command line or stdin'
|
||||
'phd:Pretty hex dump'
|
||||
'scramble:Strip binaries for CTF usage'
|
||||
'shellcraft:Shellcode encoder'
|
||||
'template:Microwave shellcode -- Easy, fast and delicious'
|
||||
'unhex:Generate an exploit template'
|
||||
'update:Decodes hex-encoded data provided on the command line or via stdin.'
|
||||
'version:Check for pwntools updates'
|
||||
)
|
||||
|
||||
# Global flags (i.e. ones not associated with a subcommand)
|
||||
_arguments \
|
||||
"1: :{_describe 'command' commands}" \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'*:: :->args'
|
||||
|
||||
# Flags for each subcommand
|
||||
case $state in
|
||||
args)
|
||||
case $words[1] in
|
||||
pwnstrip)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-b --build-id)'{-b,--build-id}'[Strip build ID]' \
|
||||
'(-p --patch)'{-p,--patch}'=[Patch function]:' \
|
||||
'(-o --output)'{-o,--output}'=[None]:' \
|
||||
;;
|
||||
asm)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-f --format)'{-f,--format}'=[Output format (defaults to hex for ttys, otherwise raw)]:-f :(raw hex string elf)' \
|
||||
'(-o --output)'{-o,--output}'=[Output file (defaults to stdout)]:' \
|
||||
'(-c --context)'{-c,--context}'=[The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: \["16", "32", "64", "android", "baremetal", "cgc", "freebsd", "linux", "windows", "powerpc64", "aarch64", "powerpc", "sparc64", "mips64", "msp430", "alpha", "amd64", "sparc", "thumb", "cris", "i386", "ia64", "m68k", "mips", "s390", "none", "avr", "arm", "vax", "little", "big", "be", "eb", "le", "el"\]]:-c :(16 32 64 android baremetal cgc freebsd linux windows powerpc64 aarch64 powerpc sparc64 mips64 msp430 alpha amd64 sparc thumb cris i386 ia64 m68k mips s390 none avr arm vax little big be eb le el)' \
|
||||
'(-v --avoid)'{-v,--avoid}'=[Encode the shellcode to avoid the listed bytes (provided as hex)]:' \
|
||||
'(-n --newline)'{-n,--newline}'[Encode the shellcode to avoid newlines]' \
|
||||
'(-z --zero)'{-z,--zero}'[Encode the shellcode to avoid NULL bytes]' \
|
||||
'(-d --debug)'{-d,--debug}'[Debug the shellcode with GDB]' \
|
||||
'(-e --encoder)'{-e,--encoder}'=[Specific encoder to use]:' \
|
||||
'(-i --infile)'{-i,--infile}'=[Specify input file]:' \
|
||||
'(-r --run)'{-r,--run}'[Run output]' \
|
||||
;;
|
||||
checksec)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'--file=[File to check (for compatibility with checksec.sh)]:' \
|
||||
;;
|
||||
constgrep)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-e --exact)'{-e,--exact}'[Do an exact match for a constant instead of searching for a regex]' \
|
||||
'(-i --case-insensitive)'{-i,--case-insensitive}'[Search case insensitive]' \
|
||||
'(-m --mask-mode)'{-m,--mask-mode}'[Instead of searching for a specific constant value, search for values not containing strictly less bits that the given value.]' \
|
||||
'(-c --context)'{-c,--context}'=[The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: \["16", "32", "64", "android", "baremetal", "cgc", "freebsd", "linux", "windows", "powerpc64", "aarch64", "powerpc", "sparc64", "mips64", "msp430", "alpha", "amd64", "sparc", "thumb", "cris", "i386", "ia64", "m68k", "mips", "s390", "none", "avr", "arm", "vax", "little", "big", "be", "eb", "le", "el"\]]:-c :(16 32 64 android baremetal cgc freebsd linux windows powerpc64 aarch64 powerpc sparc64 mips64 msp430 alpha amd64 sparc thumb cris i386 ia64 m68k mips s390 none avr arm vax little big be eb le el)' \
|
||||
;;
|
||||
cyclic)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-a --alphabet)'{-a,--alphabet}'=[The alphabet to use in the cyclic pattern (defaults to all lower case letters)]:' \
|
||||
'(-n --length)'{-n,--length}'=[Size of the unique subsequences (defaults to 4).]:' \
|
||||
'(-c --context)'{-c,--context}'=[The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: \["16", "32", "64", "android", "baremetal", "cgc", "freebsd", "linux", "windows", "powerpc64", "aarch64", "powerpc", "sparc64", "mips64", "msp430", "alpha", "amd64", "sparc", "thumb", "cris", "i386", "ia64", "m68k", "mips", "s390", "none", "avr", "arm", "vax", "little", "big", "be", "eb", "le", "el"\]]:-c :(16 32 64 android baremetal cgc freebsd linux windows powerpc64 aarch64 powerpc sparc64 mips64 msp430 alpha amd64 sparc thumb cris i386 ia64 m68k mips s390 none avr arm vax little big be eb le el)' \
|
||||
'(-l -o --offset --lookup)'{-l,-o,--offset,--lookup}'=[Do a lookup instead printing the alphabet]:' \
|
||||
;;
|
||||
debug)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'-x=[Execute GDB commands from this file.]:' \
|
||||
'--pid=[PID to attach to]:' \
|
||||
'(-c --context)'{-c,--context}'=[The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: \["16", "32", "64", "android", "baremetal", "cgc", "freebsd", "linux", "windows", "powerpc64", "aarch64", "powerpc", "sparc64", "mips64", "msp430", "alpha", "amd64", "sparc", "thumb", "cris", "i386", "ia64", "m68k", "mips", "s390", "none", "avr", "arm", "vax", "little", "big", "be", "eb", "le", "el"\]]:-c :(16 32 64 android baremetal cgc freebsd linux windows powerpc64 aarch64 powerpc sparc64 mips64 msp430 alpha amd64 sparc thumb cris i386 ia64 m68k mips s390 none avr arm vax little big be eb le el)' \
|
||||
'--exec=[File to debug]:' \
|
||||
'--process=[Name of the process to attach to (e.g. "bash")]:' \
|
||||
'--sysroot=[GDB sysroot path]:' \
|
||||
;;
|
||||
disasm)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-c --context)'{-c,--context}'=[The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: \["16", "32", "64", "android", "baremetal", "cgc", "freebsd", "linux", "windows", "powerpc64", "aarch64", "powerpc", "sparc64", "mips64", "msp430", "alpha", "amd64", "sparc", "thumb", "cris", "i386", "ia64", "m68k", "mips", "s390", "none", "avr", "arm", "vax", "little", "big", "be", "eb", "le", "el"\]]:-c :(16 32 64 android baremetal cgc freebsd linux windows powerpc64 aarch64 powerpc sparc64 mips64 msp430 alpha amd64 sparc thumb cris i386 ia64 m68k mips s390 none avr arm vax little big be eb le el)' \
|
||||
'(-a --address)'{-a,--address}'=[Base address]:' \
|
||||
'--color[Color output]' \
|
||||
'--no-color[Disable color output]' \
|
||||
;;
|
||||
disablenx)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
elfdiff)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
elfpatch)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
errno)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
hex)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
phd)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-w --width)'{-w,--width}'=[Number of bytes per line.]:' \
|
||||
'(-l --highlight)'{-l,--highlight}'=[Byte to highlight.]:' \
|
||||
'(-s --skip)'{-s,--skip}'=[Skip this many initial bytes.]:' \
|
||||
'(-c --count)'{-c,--count}'=[Only show this many bytes.]:' \
|
||||
'(-o --offset)'{-o,--offset}'=[Addresses in left hand column starts at this address.]:' \
|
||||
'--color=[Colorize the output. When "auto" output is colorized exactly when stdout is a TTY. Default is "auto".]:--color :(always never auto)' \
|
||||
;;
|
||||
scramble)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-f --format)'{-f,--format}'=[Output format (defaults to hex for ttys, otherwise raw)]:-f :(raw hex string elf)' \
|
||||
'(-o --output)'{-o,--output}'=[Output file (defaults to stdout)]:' \
|
||||
'(-c --context)'{-c,--context}'=[The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: \["16", "32", "64", "android", "baremetal", "cgc", "freebsd", "linux", "windows", "powerpc64", "aarch64", "powerpc", "sparc64", "mips64", "msp430", "alpha", "amd64", "sparc", "thumb", "cris", "i386", "ia64", "m68k", "mips", "s390", "none", "avr", "arm", "vax", "little", "big", "be", "eb", "le", "el"\]]:-c :(16 32 64 android baremetal cgc freebsd linux windows powerpc64 aarch64 powerpc sparc64 mips64 msp430 alpha amd64 sparc thumb cris i386 ia64 m68k mips s390 none avr arm vax little big be eb le el)' \
|
||||
'(-p --alphanumeric)'{-p,--alphanumeric}'[Encode the shellcode with an alphanumeric encoder]' \
|
||||
'(-v --avoid)'{-v,--avoid}'=[Encode the shellcode to avoid the listed bytes]:' \
|
||||
'(-n --newline)'{-n,--newline}'[Encode the shellcode to avoid newlines]' \
|
||||
'(-z --zero)'{-z,--zero}'[Encode the shellcode to avoid NULL bytes]' \
|
||||
'(-d --debug)'{-d,--debug}'[Debug the shellcode with GDB]' \
|
||||
;;
|
||||
shellcraft)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'(-? --show)'{-?,--show}'[Show shellcode documentation]' \
|
||||
'(-o --out)'{-o,--out}'=[Output file (default: stdout)]:' \
|
||||
'(-f --format)'{-f,--format}'=[Output format (default: hex), choose from {e}lf, {r}aw, {s}tring, {c}-style array, {h}ex string, hex{i}i, {a}ssembly code, {p}reprocssed code, escape{d} hex string]:-f :(r raw s str string c h hex a asm assembly p i hexii e elf d escaped default)' \
|
||||
'(-d --debug)'{-d,--debug}'[Debug the shellcode with GDB]' \
|
||||
'(-b --before)'{-b,--before}'[Insert a debug trap before the code]' \
|
||||
'(-a --after)'{-a,--after}'[Insert a debug trap after the code]' \
|
||||
'(-v --avoid)'{-v,--avoid}'=[Encode the shellcode to avoid the listed bytes]:' \
|
||||
'(-n --newline)'{-n,--newline}'[Encode the shellcode to avoid newlines]' \
|
||||
'(-z --zero)'{-z,--zero}'[Encode the shellcode to avoid NULL bytes]' \
|
||||
'(-r --run)'{-r,--run}'[Run output]' \
|
||||
'--color[Color output]' \
|
||||
'--no-color[Disable color output]' \
|
||||
'--syscalls[List syscalls]' \
|
||||
'--address=[Load address]:' \
|
||||
'(-l --list)'{-l,--list}'[List available shellcodes, optionally provide a filter]' \
|
||||
'(-s --shared)'{-s,--shared}'[Generated ELF is a shared library]' \
|
||||
;;
|
||||
template)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'--host=[Remote host / SSH server]:' \
|
||||
'--port=[Remote port / SSH port]:' \
|
||||
'--user=[SSH Username]:' \
|
||||
'(--pass --password)'{--pass,--password}'=[SSH Password]:' \
|
||||
'--path=[Remote path of file on SSH server]:' \
|
||||
'--quiet[Less verbose template comments]' \
|
||||
'--color=[Print the output in color]:--color :(never always auto)' \
|
||||
;;
|
||||
unhex)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
update)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
'--install[Install the update automatically.]' \
|
||||
'--pre[Check for pre-releases.]' \
|
||||
;;
|
||||
version)
|
||||
_arguments \
|
||||
'(-h --help)'{-h,--help}'[show this help message and exit]' \
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
_pwn
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Try to find a writable directory first, in reverse order
|
||||
for dir in "${(Oa)fpath[@]}"; do
|
||||
if [ -w "$dir" ]; then
|
||||
cp -f ${0:h}/_pwn "$dir"
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
Could not find a suitable directory to install the completion.
|
||||
|
||||
Try adding this line at the top of your ~/.zshrc, and start a new shell.
|
||||
|
||||
fpath=( ${0:A:h} \$fpath )
|
||||
|
||||
If completion does not work, add this to the bottom of your ~/.zshrc, and start a new shell.
|
||||
Users of prezto should enable the 'completion' module (enabled by default).
|
||||
|
||||
compinit -i
|
||||
|
||||
EOF
|
||||
@@ -7,7 +7,6 @@ pwnlib.args.initialize()
|
||||
pwnlib.log.install_default_handler()
|
||||
pwnlib.config.initialize()
|
||||
|
||||
log = pwnlib.log.getLogger('pwnlib.exploit')
|
||||
args = pwnlib.args.args
|
||||
|
||||
if not platform.architecture()[0].startswith('64'):
|
||||
|
||||
+14
-2
@@ -4,6 +4,7 @@ import logging
|
||||
import math
|
||||
import operator
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import socks
|
||||
import signal
|
||||
@@ -28,8 +29,9 @@ 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.gdb import attach, debug_assembly, debug_shellcode
|
||||
from pwnlib.filepointer import *
|
||||
from pwnlib.filesystem import *
|
||||
from pwnlib.flag import *
|
||||
from pwnlib.fmtstr import FmtStr, fmtstr_payload, fmtstr_split
|
||||
from pwnlib.log import getLogger
|
||||
@@ -37,6 +39,7 @@ from pwnlib.memleak import MemLeak, RelativeMemLeak
|
||||
from pwnlib.regsort import *
|
||||
from pwnlib.replacements import *
|
||||
from pwnlib.rop import ROP
|
||||
from pwnlib.rop.call import AppendedArgument
|
||||
from pwnlib.rop.srop import SigreturnFrame
|
||||
from pwnlib.rop.ret2dlresolve import Ret2dlresolvePayload
|
||||
from pwnlib.runner import *
|
||||
@@ -73,6 +76,7 @@ from pwnlib.util.web import *
|
||||
from six.moves import cPickle as pickle, cStringIO as StringIO
|
||||
from six import BytesIO
|
||||
|
||||
log = getLogger("pwnlib.exploit")
|
||||
error = log.error
|
||||
warning = log.warning
|
||||
warn = log.warning
|
||||
@@ -80,4 +84,12 @@ info = log.info
|
||||
debug = log.debug
|
||||
success = log.success
|
||||
|
||||
__all__ = [x for x in globals().keys() if x != '__name__']
|
||||
try:
|
||||
import colored_traceback
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
colored_traceback.add_hook()
|
||||
|
||||
# Equivalence with the default behavior of "from import *"
|
||||
# __all__ = [x for x in tuple(globals()) if not x.startswith('_')]
|
||||
+4
-6
@@ -1,12 +1,11 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import importlib
|
||||
|
||||
from pwnlib.version import __version__
|
||||
from .version import __version__
|
||||
|
||||
version = __version__
|
||||
|
||||
__all__ = [
|
||||
'adb',
|
||||
'args',
|
||||
'asm',
|
||||
'atexception',
|
||||
@@ -35,9 +34,8 @@ __all__ = [
|
||||
'ui',
|
||||
'useragents',
|
||||
'util',
|
||||
'adb',
|
||||
'update',
|
||||
'version',
|
||||
]
|
||||
|
||||
for module in __all__:
|
||||
importlib.import_module('.%s' % module, 'pwnlib')
|
||||
from . import args
|
||||
+125
-26
@@ -66,8 +66,10 @@ from pwnlib import tubes
|
||||
from pwnlib.context import LocalContext
|
||||
from pwnlib.context import context
|
||||
from pwnlib.device import Device
|
||||
from pwnlib.exception import PwnlibException
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.protocols.adb import AdbClient
|
||||
from pwnlib.util.packing import _decode
|
||||
from pwnlib.util import misc
|
||||
|
||||
log = getLogger(__name__)
|
||||
@@ -75,10 +77,13 @@ log = getLogger(__name__)
|
||||
def adb(argv, *a, **kw):
|
||||
r"""Returns the output of an ADB subcommand.
|
||||
|
||||
>>> adb.adb('get-serialno')
|
||||
b'emulator-5554\n'
|
||||
>>> adb.adb(['shell', 'uname']) # it is better to use adb.process
|
||||
b'Linux\n'
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.adb('get-serialno')
|
||||
b'emulator-5554\n'
|
||||
>>> adb.adb(['shell', 'uname']) # it is better to use adb.process
|
||||
b'Linux\n'
|
||||
"""
|
||||
if isinstance(argv, (bytes, six.text_type)):
|
||||
argv = [argv]
|
||||
@@ -113,11 +118,12 @@ def current_device(any=False):
|
||||
"""Returns an ``AdbDevice`` instance for the currently-selected device
|
||||
(via ``context.device``).
|
||||
|
||||
Example:
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> device = adb.current_device(any=True)
|
||||
>>> device
|
||||
AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_google_phone_armv7', model='sdk google phone armv7', device='generic')
|
||||
>>> device # doctest: +ELLIPSIS
|
||||
AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_...phone_...', model='...', device='generic...')
|
||||
>>> device.port
|
||||
'emulator'
|
||||
"""
|
||||
@@ -144,7 +150,10 @@ def with_device(f):
|
||||
def root():
|
||||
"""Restarts adbd as root.
|
||||
|
||||
>>> adb.root()
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.root()
|
||||
"""
|
||||
log.info("Enabling root on %s" % context.device)
|
||||
|
||||
@@ -202,6 +211,10 @@ def uptime():
|
||||
Uptime of the device, in seconds
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.uptime() > 3 # normally AVD takes ~7 seconds to boot
|
||||
True
|
||||
"""
|
||||
@@ -217,6 +230,10 @@ def boot_time():
|
||||
nearest second.
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> import time
|
||||
>>> adb.boot_time() < time.time()
|
||||
True
|
||||
@@ -231,15 +248,18 @@ class AdbDevice(Device):
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> device = adb.wait_for_device()
|
||||
>>> device.arch
|
||||
'arm'
|
||||
'amd64'
|
||||
>>> device.bits
|
||||
32
|
||||
64
|
||||
>>> device.os
|
||||
'android'
|
||||
>>> device.product
|
||||
'sdk_google_phone_armv7'
|
||||
>>> device.product # doctest: +ELLIPSIS
|
||||
'sdk_...phone_...'
|
||||
>>> device.serial
|
||||
'emulator-5554'
|
||||
"""
|
||||
@@ -357,11 +377,17 @@ class AdbDevice(Device):
|
||||
"""Provides scoped access to ``adb`` module propertise, in the context
|
||||
of this device.
|
||||
|
||||
>>> property = 'ro.build.fingerprint'
|
||||
>>> device = adb.wait_for_device()
|
||||
>>> adb.getprop(property) == device.getprop(property)
|
||||
True
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> property = 'ro.build.fingerprint'
|
||||
>>> device = adb.wait_for_device()
|
||||
>>> adb.getprop(property) == device.getprop(property)
|
||||
True
|
||||
"""
|
||||
if name.startswith('_'):
|
||||
raise AttributeError(name)
|
||||
|
||||
with context.local(device=self):
|
||||
g = globals()
|
||||
|
||||
@@ -387,6 +413,9 @@ def wait_for_device(kick=False):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> device = adb.wait_for_device()
|
||||
"""
|
||||
with log.waitfor("Waiting for device to come online") as w:
|
||||
@@ -496,6 +525,9 @@ def pull(remote_path, local_path=None):
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> _=adb.pull('/proc/version', './proc-version')
|
||||
>>> print(read('./proc-version').decode('utf-8')) # doctest: +ELLIPSIS
|
||||
Linux version ...
|
||||
@@ -527,6 +559,9 @@ def push(local_path, remote_path):
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> write('./filename', 'contents')
|
||||
>>> adb.push('./filename', '/data/local/tmp')
|
||||
'/data/local/tmp/filename'
|
||||
@@ -584,6 +619,9 @@ def read(path, target=None, callback=None):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> print(adb.read('/proc/version').decode('utf-8')) # doctest: +ELLIPSIS
|
||||
Linux version ...
|
||||
>>> adb.read('/does/not/exist')
|
||||
@@ -613,6 +651,9 @@ def write(path, data=b''):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.write('/dev/null', b'data')
|
||||
>>> adb.write('/data/local/tmp/')
|
||||
"""
|
||||
@@ -633,6 +674,9 @@ def mkdir(path):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.mkdir('/')
|
||||
|
||||
>>> path = '/data/local/tmp/mkdir_test'
|
||||
@@ -673,6 +717,9 @@ def makedirs(path):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.makedirs('/data/local/tmp/this/is/a/directory/hierarchy')
|
||||
>>> adb.listdir('/data/local/tmp/this/is/a/directory')
|
||||
['hierarchy']
|
||||
@@ -689,6 +736,9 @@ def exists(path):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.exists('/')
|
||||
True
|
||||
>>> adb.exists('/etc/hosts')
|
||||
@@ -706,6 +756,9 @@ def isdir(path):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.isdir('/')
|
||||
True
|
||||
>>> adb.isdir('/init')
|
||||
@@ -724,6 +777,9 @@ def unlink(path, recursive=False):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.unlink("/does/not/exist")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
@@ -775,6 +831,9 @@ def process(argv, *a, **kw):
|
||||
|
||||
Examples:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.root()
|
||||
>>> print(adb.process(['cat','/proc/version']).recvall().decode('utf-8')) # doctest: +ELLIPSIS
|
||||
Linux version ...
|
||||
@@ -815,6 +874,9 @@ def which(name, all = False, *a, **kw):
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.which('sh')
|
||||
'/system/bin/sh'
|
||||
>>> adb.which('sh', all=True)
|
||||
@@ -838,7 +900,7 @@ def which(name, all = False, *a, **kw):
|
||||
|
||||
which_cmd = which_cmd.strip()
|
||||
data = process(['sh','-c', which_cmd], *a, **kw).recvall()
|
||||
data = context._decode(data)
|
||||
data = _decode(data)
|
||||
result = []
|
||||
|
||||
for path in data.split('\x00'):
|
||||
@@ -864,6 +926,10 @@ def whoami():
|
||||
"""Returns current shell user
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.whoami()
|
||||
b'root'
|
||||
"""
|
||||
@@ -917,6 +983,10 @@ def proc_exe(pid):
|
||||
"""Returns the full path of the executable for the provided PID.
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.proc_exe(1)
|
||||
b'/init'
|
||||
"""
|
||||
@@ -937,18 +1007,22 @@ def getprop(name=None):
|
||||
Otherwise, a string is returned with the contents of the named property.
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.getprop() # doctest: +ELLIPSIS
|
||||
{...}
|
||||
"""
|
||||
with context.quiet:
|
||||
if name:
|
||||
result = process(['getprop', name]).recvall().strip()
|
||||
result = context._decode(result)
|
||||
result = _decode(result)
|
||||
return result
|
||||
|
||||
result = process(['getprop']).recvall()
|
||||
|
||||
result = context._decode(result)
|
||||
result = _decode(result)
|
||||
expr = r'\[([^\]]+)\]: \[(.*)\]'
|
||||
|
||||
props = {}
|
||||
@@ -1052,6 +1126,10 @@ class Kernel(object):
|
||||
def address(self):
|
||||
"""Returns kernel address
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> hex(adb.kernel.address) # doctest: +ELLIPSIS
|
||||
'0x...000'
|
||||
"""
|
||||
@@ -1178,6 +1256,10 @@ class Property(object):
|
||||
"""Allow simple comparison
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> adb.properties.ro.build.version.sdk == "24"
|
||||
True
|
||||
"""
|
||||
@@ -1266,6 +1348,10 @@ def compile(source):
|
||||
r"""Compile a source file or project with the Android NDK.
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> temp = tempfile.mktemp('.c')
|
||||
>>> write(temp, '''
|
||||
... #include <stdio.h>
|
||||
@@ -1279,14 +1365,18 @@ def compile(source):
|
||||
>>> filename = adb.compile(temp)
|
||||
>>> sent = adb.push(filename, "/data/local/tmp")
|
||||
>>> adb.process(sent).recvall() # doctest: +ELLIPSIS
|
||||
b'... /system/bin/linker\n...'
|
||||
b'... /system/lib64/libc.so\n...'
|
||||
"""
|
||||
|
||||
ndk_build = misc.which('ndk-build')
|
||||
if not ndk_build:
|
||||
# Ensure that we can find the NDK.
|
||||
ndk = os.environ.get('NDK', None)
|
||||
if ndk is None:
|
||||
for envvar in ('NDK', 'ANDROID_NDK', 'ANDROID_NDK_ROOT',
|
||||
'ANDROID_NDK_HOME', 'ANDROID_NDK_LATEST_HOME'):
|
||||
ndk = os.environ.get(envvar)
|
||||
if ndk is not None:
|
||||
break
|
||||
else:
|
||||
log.error('$NDK must be set to the Android NDK directory')
|
||||
ndk_build = os.path.join(ndk, 'ndk-build')
|
||||
|
||||
@@ -1390,6 +1480,10 @@ class Partitions(object):
|
||||
"""Enable access to partitions
|
||||
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
:skipif: skip_android
|
||||
|
||||
>>> hex(adb.partitions.vda.size) # doctest: +ELLIPSIS
|
||||
'0x...000'
|
||||
"""
|
||||
@@ -1397,8 +1491,9 @@ class Partitions(object):
|
||||
@context.quietfunc
|
||||
def by_name_dir(self):
|
||||
try:
|
||||
return next(find('/dev/block/platform','by-name'))
|
||||
except StopIteration:
|
||||
with context.local(log_level=logging.FATAL):
|
||||
return next(find('/dev/block/platform','by-name'))
|
||||
except (StopIteration, PwnlibException):
|
||||
return '/dev/block'
|
||||
|
||||
@context.quietfunc
|
||||
@@ -1427,7 +1522,7 @@ class Partitions(object):
|
||||
return iter(names)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr.startswith("_"):
|
||||
if attr.startswith('_'):
|
||||
raise AttributeError(attr)
|
||||
|
||||
for name in self:
|
||||
@@ -1498,7 +1593,10 @@ def uninstall(package, *arguments):
|
||||
@context.quietfunc
|
||||
def packages():
|
||||
"""Returns a list of packages installed on the system"""
|
||||
packages = process(['pm', 'list', 'packages']).recvall()
|
||||
# Decodes the received bytes as UTF-8 per:
|
||||
# https://developer.android.com/reference/java/nio/charset/Charset#defaultCharset()
|
||||
# where it is specified that UTF-8 is the default charset for Android.
|
||||
packages = process(['pm', 'list', 'packages']).recvall().decode('utf-8')
|
||||
return [line.split('package:', 1)[-1] for line in packages.splitlines()]
|
||||
|
||||
@context.quietfunc
|
||||
@@ -1506,3 +1604,4 @@ def version():
|
||||
"""Returns rthe platform version as a tuple."""
|
||||
prop = getprop('ro.build.version.release')
|
||||
return [int(v) for v in prop.split('.')]
|
||||
|
||||
@@ -46,7 +46,7 @@ class BootImage(object):
|
||||
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)
|
||||
if name.startswith('_'):
|
||||
raise AttributeError(name)
|
||||
|
||||
return getattr(self.header, name)
|
||||
@@ -4,6 +4,7 @@ from __future__ import division
|
||||
import ctypes
|
||||
import io
|
||||
import os
|
||||
import six
|
||||
import sys
|
||||
|
||||
from pwnlib.log import getLogger
|
||||
@@ -64,7 +65,7 @@ class BootloaderImage(object):
|
||||
Returns:
|
||||
Contents of the image.
|
||||
"""
|
||||
if isinstance(index_or_name, int):
|
||||
if isinstance(index_or_name, six.integer_types):
|
||||
index = index_or_name
|
||||
else:
|
||||
for i in range(len(self.img_info)):
|
||||
@@ -113,10 +114,11 @@ class BootloaderImage(object):
|
||||
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.startswith('_'):
|
||||
raise AttributeError(name)
|
||||
|
||||
return getattr(self.header, name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Easy sanity checking
|
||||
|
||||
+2
-2
@@ -1,5 +1,3 @@
|
||||
|
||||
#!/usr/bin/env python2
|
||||
"""
|
||||
Pwntools exposes several magic command-line arguments and environment
|
||||
variables when operating in `from pwn import *` mode.
|
||||
@@ -64,6 +62,8 @@ from pwnlib.context import context
|
||||
|
||||
class PwnlibArgs(collections.defaultdict):
|
||||
def __getattr__(self, attr):
|
||||
if attr.startswith('_'):
|
||||
raise AttributeError(attr)
|
||||
return self[attr]
|
||||
|
||||
args = PwnlibArgs(str)
|
||||
|
||||
+108
-46
@@ -136,8 +136,23 @@ Try installing binutils for this architecture:
|
||||
%(instructions)s
|
||||
""".strip() % locals())
|
||||
|
||||
|
||||
def check_binutils_version(util):
|
||||
if util_versions[util]:
|
||||
return util_versions[util]
|
||||
result = subprocess.check_output([util, '--version','/dev/null'],
|
||||
stderr=subprocess.STDOUT, universal_newlines=True)
|
||||
if 'clang' in result:
|
||||
log.warn_once('Your binutils is clang-based and may not work!\n'
|
||||
'Try installing with: https://docs.pwntools.com/en/stable/install/binutils.html\n'
|
||||
'Reported version: %r', result.strip())
|
||||
version = re.search(r' (\d+\.\d+)', result).group(1)
|
||||
util_versions[util] = version = tuple(map(int, version.split('.')))
|
||||
return version
|
||||
|
||||
|
||||
@LocalContext
|
||||
def which_binutils(util):
|
||||
def which_binutils(util, check_version=False):
|
||||
"""
|
||||
Finds a binutils in the PATH somewhere.
|
||||
Expects that the utility is prefixed with the architecture name.
|
||||
@@ -167,6 +182,11 @@ def which_binutils(util):
|
||||
'i386': ['x86_64', 'amd64'],
|
||||
'i686': ['x86_64', 'amd64'],
|
||||
'amd64': ['x86_64', 'i386'],
|
||||
'mips64': ['mips'],
|
||||
'powerpc64': ['powerpc'],
|
||||
'sparc64': ['sparc'],
|
||||
'riscv32': ['riscv32', 'riscv64', 'riscv'],
|
||||
'riscv64': ['riscv64', 'riscv32', 'riscv'],
|
||||
}.get(arch, [])
|
||||
|
||||
# If one of the candidate architectures matches the native
|
||||
@@ -190,24 +210,34 @@ def which_binutils(util):
|
||||
for gutil in utils:
|
||||
# e.g. objdump
|
||||
if arch is None:
|
||||
pattern = gutil
|
||||
patterns = [gutil]
|
||||
|
||||
# e.g. aarch64-linux-gnu-objdump
|
||||
# e.g. aarch64-linux-gnu-objdump, avr-objdump
|
||||
else:
|
||||
pattern = '%s*linux*-%s' % (arch,gutil)
|
||||
patterns = ['%s*linux*-%s' % (arch, gutil),
|
||||
'%s*-elf-%s' % (arch, gutil),
|
||||
'%s-none*-%s' % (arch, gutil),
|
||||
'%s-%s' % (arch, gutil)]
|
||||
|
||||
for dir in environ['PATH'].split(':'):
|
||||
res = sorted(glob(path.join(dir, pattern)))
|
||||
if res:
|
||||
return res[0]
|
||||
for pattern in patterns:
|
||||
for dir in environ['PATH'].split(':'):
|
||||
for res in sorted(glob(path.join(dir, pattern))):
|
||||
if check_version:
|
||||
ver = check_binutils_version(res)
|
||||
return res, ver
|
||||
return res
|
||||
|
||||
# No dice!
|
||||
print_binutils_instructions(util, context)
|
||||
|
||||
checked_assembler_version = defaultdict(lambda: False)
|
||||
util_versions = defaultdict(tuple)
|
||||
|
||||
def _assembler():
|
||||
gas = which_binutils('as')
|
||||
gas, version = which_binutils('as', check_version=True)
|
||||
if version < (2, 19):
|
||||
log.warn_once('Your binutils version is too old and may not work!\n'
|
||||
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n'
|
||||
'Reported version: %r', version)
|
||||
|
||||
E = {
|
||||
'big': '-EB',
|
||||
@@ -234,26 +264,19 @@ def _assembler():
|
||||
'powerpc64': [gas, '-m%s' % context.endianness, '-mppc%s' % context.bits],
|
||||
|
||||
# ia64 only accepts -mbe or -mle
|
||||
'ia64': [gas, '-m%ce' % context.endianness[0]]
|
||||
'ia64': [gas, '-m%ce' % context.endianness[0]],
|
||||
|
||||
# riscv64-unknown-elf-as supports riscv32 as well as riscv64
|
||||
'riscv32': [gas, '-march=rv32gc', '-mabi=ilp32'],
|
||||
'riscv64': [gas, '-march=rv64gc', '-mabi=lp64'],
|
||||
}
|
||||
|
||||
assembler = assemblers.get(context.arch, [gas])
|
||||
|
||||
if not checked_assembler_version[gas]:
|
||||
checked_assembler_version[gas] = True
|
||||
result = subprocess.check_output([gas, '--version','/dev/null'],
|
||||
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' + \
|
||||
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n' + \
|
||||
'Reported Version: %r' % result.strip())
|
||||
|
||||
|
||||
return assembler
|
||||
|
||||
def _linker():
|
||||
ld = [which_binutils('ld')]
|
||||
ld, _ = which_binutils('ld', check_version=True)
|
||||
bfd = ['--oformat=' + _bfdname()]
|
||||
|
||||
E = {
|
||||
@@ -265,7 +288,16 @@ def _linker():
|
||||
'i386': ['-m', 'elf_i386'],
|
||||
}.get(context.arch, [])
|
||||
|
||||
return ld + bfd + [E] + arguments
|
||||
return [ld] + bfd + [E] + arguments
|
||||
|
||||
|
||||
def _execstack(linker):
|
||||
ldflags = ['-z', 'execstack']
|
||||
version = util_versions[linker[0]]
|
||||
if version >= (2, 39):
|
||||
return ldflags + ['--no-warn-execstack', '--no-warn-rwx-segments']
|
||||
return ldflags
|
||||
|
||||
|
||||
def _objcopy():
|
||||
return [which_binutils('objcopy')]
|
||||
@@ -297,16 +329,20 @@ def _arch_header():
|
||||
'_start:',
|
||||
'__start:']
|
||||
headers = {
|
||||
'i386' : ['.intel_syntax noprefix'],
|
||||
'amd64' : ['.intel_syntax noprefix'],
|
||||
'i386' : ['.intel_syntax noprefix', '.p2align 0'],
|
||||
'amd64' : ['.intel_syntax noprefix', '.p2align 0'],
|
||||
'arm' : ['.syntax unified',
|
||||
'.arch armv7-a',
|
||||
'.arm'],
|
||||
'.arm',
|
||||
'.p2align 2'],
|
||||
'thumb' : ['.syntax unified',
|
||||
'.arch armv7-a',
|
||||
'.thumb'],
|
||||
'.thumb',
|
||||
'.p2align 2'
|
||||
],
|
||||
'mips' : ['.set mips2',
|
||||
'.set noreorder',
|
||||
'.p2align 2'
|
||||
],
|
||||
}
|
||||
|
||||
@@ -322,15 +358,20 @@ def _bfdname():
|
||||
'amd64' : 'elf64-x86-64',
|
||||
'arm' : 'elf32-%sarm' % E,
|
||||
'thumb' : 'elf32-%sarm' % E,
|
||||
'avr' : 'elf32-avr',
|
||||
'mips' : 'elf32-trad%smips' % E,
|
||||
'mips64' : 'elf64-trad%smips' % E,
|
||||
'alpha' : 'elf64-alpha',
|
||||
'cris' : 'elf32-cris',
|
||||
'ia64' : 'elf64-ia64-%s' % E,
|
||||
'm68k' : 'elf32-m68k',
|
||||
'msp430' : 'elf32-msp430',
|
||||
'powerpc' : 'elf32-powerpc',
|
||||
'powerpc64' : 'elf64-powerpc',
|
||||
'riscv32' : 'elf%d-%sriscv' % (context.bits, E),
|
||||
'riscv64' : 'elf%d-%sriscv' % (context.bits, E),
|
||||
'vax' : 'elf32-vax',
|
||||
's390' : 'elf%d-s390' % context.bits,
|
||||
'sparc' : 'elf32-sparc',
|
||||
'sparc64' : 'elf64-sparc',
|
||||
}
|
||||
@@ -344,10 +385,15 @@ def _bfdname():
|
||||
def _bfdarch():
|
||||
arch = context.arch
|
||||
convert = {
|
||||
'i386': 'i386',
|
||||
'amd64': 'i386:x86-64',
|
||||
'thumb': 'arm',
|
||||
'ia64': 'ia64-elf64'
|
||||
'amd64': 'i386:x86-64',
|
||||
'i386': 'i386',
|
||||
'ia64': 'ia64-elf64',
|
||||
'mips64': 'mips',
|
||||
'powerpc64': 'powerpc',
|
||||
'sparc64': 'sparc',
|
||||
'thumb': 'arm',
|
||||
'riscv32': 'riscv',
|
||||
'riscv64': 'riscv',
|
||||
}
|
||||
|
||||
if arch in convert:
|
||||
@@ -356,7 +402,7 @@ def _bfdarch():
|
||||
return arch
|
||||
|
||||
def _run(cmd, stdin = None):
|
||||
log.debug(subprocess.list2cmdline(cmd))
|
||||
log.debug('%s', subprocess.list2cmdline(cmd))
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
cmd,
|
||||
@@ -369,17 +415,20 @@ def _run(cmd, stdin = None):
|
||||
exitcode = proc.wait()
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
log.exception('Could not run %r the program' % cmd[0])
|
||||
log.exception('Could not run %r the program', cmd[0])
|
||||
else:
|
||||
raise
|
||||
|
||||
if (exitcode, stderr) != (0, ''):
|
||||
msg = 'There was an error running %s:\n' % repr(cmd)
|
||||
msg = 'There was an error running %r:\n'
|
||||
args = cmd,
|
||||
if exitcode != 0:
|
||||
msg += 'It had the exitcode %d.\n' % exitcode
|
||||
msg += 'It had the exitcode %d.\n'
|
||||
args += exitcode,
|
||||
if stderr != '':
|
||||
msg += 'It had this on stdout:\n%s\n' % stderr
|
||||
log.error(msg)
|
||||
msg += 'It had this on stdout:\n%s\n'
|
||||
args += stderr,
|
||||
log.error(msg, *args)
|
||||
|
||||
return stdout
|
||||
|
||||
@@ -481,9 +530,7 @@ def make_elf_from_assembly(assembly,
|
||||
>>> 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
|
||||
>>> len(file_a) < len(file_b)
|
||||
True
|
||||
"""
|
||||
if shared and vma:
|
||||
@@ -575,7 +622,7 @@ def make_elf(data,
|
||||
|
||||
_run(assembler + ['-o', step2, step1])
|
||||
|
||||
linker_options = ['-z', 'execstack']
|
||||
linker_options = _execstack(linker)
|
||||
if vma is not None:
|
||||
linker_options += ['--section-start=.shellcode=%#x' % vma,
|
||||
'--entry=%#x' % vma]
|
||||
@@ -637,6 +684,10 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
|
||||
b'H\xc7\xc0\x17\x00\x00\x00'
|
||||
>>> asm("mov r0, #SYS_select", arch = 'arm', os = 'linux', bits=32)
|
||||
b'R\x00\xa0\xe3'
|
||||
>>> asm("mov #42, r0", arch = 'msp430')
|
||||
b'0@*\x00'
|
||||
>>> asm("la %r0, 42", arch = 's390', bits=64)
|
||||
b'A\x00\x00*'
|
||||
"""
|
||||
result = ''
|
||||
|
||||
@@ -665,7 +716,7 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
|
||||
shutil.copy(step2, step3)
|
||||
|
||||
if vma or not extract:
|
||||
ldflags = ['-z', 'execstack', '-o', step3, step2]
|
||||
ldflags = _execstack(linker) + ['-o', step3, step2]
|
||||
if vma:
|
||||
ldflags += ['--section-start=.shellcode=%#x' % vma,
|
||||
'--entry=%#x' % vma]
|
||||
@@ -747,8 +798,19 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
|
||||
>>> 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]
|
||||
0: gs data16 fs rex nop WORD PTR gs:[eax+eax*1+0x0]
|
||||
f: push rcx
|
||||
>>> print(disasm(unhex('01000000'), arch='sparc64'))
|
||||
0: 01 00 00 00 nop
|
||||
>>> print(disasm(unhex('60000000'), arch='powerpc64'))
|
||||
0: 60 00 00 00 nop
|
||||
>>> print(disasm(unhex('00000000'), arch='mips64'))
|
||||
0: 00000000 nop
|
||||
>>> print(disasm(unhex('48b84141414141414100c3'), arch='amd64'))
|
||||
0: 48 b8 41 41 41 41 41 41 41 00 movabs rax, 0x41414141414141
|
||||
a: c3 ret
|
||||
>>> print(disasm(unhex('00000000'), vma=0x80000000, arch='mips'))
|
||||
80000000: 00000000 nop
|
||||
"""
|
||||
result = ''
|
||||
|
||||
@@ -760,7 +822,7 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
|
||||
|
||||
bfdarch = _bfdarch()
|
||||
bfdname = _bfdname()
|
||||
objdump = _objdump() + ['-d', '--adjust-vma', str(vma), '-b', bfdname]
|
||||
objdump = _objdump() + ['-w', '-d', '--adjust-vma', str(vma), '-b', bfdname]
|
||||
objcopy = _objcopy() + [
|
||||
'-I', 'binary',
|
||||
'-O', bfdname,
|
||||
@@ -785,7 +847,7 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
|
||||
_run(objcopy + [step1, step2])
|
||||
|
||||
output0 = _run(objdump + [step2])
|
||||
output1 = output0.split('<.text>:\n')
|
||||
output1 = re.split(r'<\.text(?:\+0x0)?>:\n', output0, flags=re.MULTILINE)
|
||||
|
||||
if len(output1) != 2:
|
||||
log.error('Could not find .text in objdump output:\n%s' % output0)
|
||||
|
||||
+6
-1
@@ -13,6 +13,7 @@ from __future__ import division
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
import atexit as std_atexit
|
||||
|
||||
from pwnlib.context import context
|
||||
|
||||
@@ -95,4 +96,8 @@ def _run_handlers():
|
||||
if hasattr(sys, "exitfunc"):
|
||||
register(sys.exitfunc)
|
||||
|
||||
sys.exitfunc = _run_handlers
|
||||
if sys.version_info[0] < 3:
|
||||
sys.exitfunc = _run_handlers
|
||||
else:
|
||||
std_atexit.register(_run_handlers)
|
||||
|
||||
@@ -18,5 +18,6 @@ __all__ = [
|
||||
'scramble',
|
||||
'shellcraft',
|
||||
'unhex',
|
||||
'update'
|
||||
'update',
|
||||
'version'
|
||||
]
|
||||
@@ -5,7 +5,7 @@ from __future__ import division
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -13,7 +13,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'asm',
|
||||
help = 'Assemble shellcode into bytes'
|
||||
help = 'Assemble shellcode into bytes',
|
||||
description = 'Assemble shellcode into bytes',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
|
||||
@@ -10,7 +10,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'checksec',
|
||||
help = 'Check binary security settings'
|
||||
help = 'Check binary security settings',
|
||||
description = 'Check binary security settings',
|
||||
)
|
||||
parser.add_argument(
|
||||
'elf',
|
||||
|
||||
Regular → Executable
+14
-25
@@ -4,10 +4,9 @@ from __future__ import division
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -16,28 +15,26 @@ from pwnlib.commandline import common
|
||||
p = common.parser_commands.add_parser(
|
||||
'constgrep',
|
||||
help = "Looking up constants from header files.\n\nExample: constgrep -c freebsd -m ^PROT_ '3 + 4'",
|
||||
description = "Looking up constants from header files.\n\nExample: constgrep -c freebsd -m ^PROT_ '3 + 4'",
|
||||
formatter_class = argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
group = p.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
p.add_argument(
|
||||
'-e', '--exact',
|
||||
metavar = 'constant',
|
||||
# nargs = 1,
|
||||
default = None,
|
||||
help = 'Do an exact match for a constant instead of searching for a regex',
|
||||
action='store_true',
|
||||
help='Do an exact match for a constant instead of searching for a regex',
|
||||
)
|
||||
group.add_argument(
|
||||
|
||||
p.add_argument(
|
||||
'regex',
|
||||
nargs = '?',
|
||||
default = '',
|
||||
help = 'The regex matching constant you want to find',
|
||||
help='The regex matching constant you want to find',
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'constant',
|
||||
nargs = '?',
|
||||
default = None,
|
||||
type = safeeval.expr,
|
||||
help = 'The constant to find',
|
||||
)
|
||||
|
||||
@@ -65,7 +62,7 @@ p.add_argument(
|
||||
def main(args):
|
||||
if args.exact:
|
||||
# This is the simple case
|
||||
print(cpp(args.exact).strip())
|
||||
print(cpp(args.regex).strip())
|
||||
else:
|
||||
# New we search in the right module.
|
||||
# But first: We find the right module
|
||||
@@ -80,20 +77,12 @@ def main(args):
|
||||
else:
|
||||
matcher = re.compile(args.regex)
|
||||
|
||||
|
||||
# Evaluate the given constant
|
||||
if args.constant:
|
||||
try:
|
||||
constant = safeeval.expr(args.constant)
|
||||
except:
|
||||
log.error("Could not evaluate constant %r" % args.constant)
|
||||
else:
|
||||
constant = None
|
||||
|
||||
# The found matching constants and the length of the longest string
|
||||
out = []
|
||||
maxlen = 0
|
||||
|
||||
constant = args.constant
|
||||
|
||||
for k in dir(mod):
|
||||
# No python stuff
|
||||
if k.endswith('__') and k.startswith('__'):
|
||||
@@ -104,7 +93,7 @@ def main(args):
|
||||
continue
|
||||
|
||||
# Check the constant
|
||||
if constant != None:
|
||||
if constant is not None:
|
||||
val = getattr(mod, k)
|
||||
if args.mask_mode:
|
||||
if constant & val != val:
|
||||
@@ -124,7 +113,7 @@ def main(args):
|
||||
# If we are in match_mode, then try to find a combination of
|
||||
# constants that yield the exact given value
|
||||
# We do not want to find combinations using the value 0.
|
||||
if not (constant == None or constant == 0) and args.mask_mode:
|
||||
if constant and args.mask_mode:
|
||||
mask = constant
|
||||
good = []
|
||||
out = [(v, k) for v, k in out if v != 0]
|
||||
|
||||
@@ -7,7 +7,7 @@ import six
|
||||
import string
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -15,14 +15,15 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'cyclic',
|
||||
help = "Cyclic pattern creator/finder"
|
||||
help = "Cyclic pattern creator/finder",
|
||||
description = "Cyclic pattern creator/finder"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-a', '--alphabet',
|
||||
metavar = 'alphabet',
|
||||
default = string.ascii_lowercase.encode(),
|
||||
type = six.ensure_binary,
|
||||
type = packing._encode,
|
||||
help = 'The alphabet to use in the cyclic pattern (defaults to all lower case letters)',
|
||||
)
|
||||
|
||||
@@ -66,15 +67,21 @@ def main(args):
|
||||
if args.lookup:
|
||||
pat = args.lookup
|
||||
|
||||
if six.PY3:
|
||||
pat = bytes(pat, encoding='utf-8')
|
||||
|
||||
try:
|
||||
pat = int(pat, 0)
|
||||
pat = pack(pat, 'all')
|
||||
except ValueError:
|
||||
pass
|
||||
pat = flat(pat)
|
||||
pat = flat(pat, bytes=args.length)
|
||||
|
||||
if len(pat) != subsize:
|
||||
log.critical('Subpattern must be %d bytes' % subsize)
|
||||
if len(pat) < subsize:
|
||||
log.critical('Subpattern must be at least %d bytes' % subsize)
|
||||
sys.exit(1)
|
||||
else:
|
||||
pat = pat[:subsize]
|
||||
|
||||
if not all(c in alphabet for c in pat):
|
||||
log.critical('Pattern contains characters not present in the alphabet')
|
||||
|
||||
@@ -10,7 +10,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'debug',
|
||||
help = 'Debug a binary in GDB'
|
||||
help = 'Debug a binary in GDB',
|
||||
description = 'Debug a binary in GDB'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-x', metavar='GDBSCRIPT',
|
||||
|
||||
@@ -8,7 +8,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'disablenx',
|
||||
help = 'Disable NX for an ELF binary'
|
||||
help = 'Disable NX for an ELF binary',
|
||||
description = 'Disable NX for an ELF binary'
|
||||
)
|
||||
parser.add_argument(
|
||||
'elf',
|
||||
|
||||
@@ -7,7 +7,7 @@ import argparse
|
||||
import string
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -15,7 +15,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'disasm',
|
||||
help = 'Disassemble bytes into text format'
|
||||
help = 'Disassemble bytes into text format',
|
||||
description = 'Disassemble bytes into text format'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -81,9 +82,9 @@ def main(args):
|
||||
instrs = disasm(dat, vma=safeeval.const(args.address), byte=False, offset=False)
|
||||
# instrs = highlight(instrs, PwntoolsLexer(), TerminalFormatter())
|
||||
|
||||
highlight_bytes = lambda t: ''.join(map(lambda x: x.replace('00', text.red('00')).replace('0a', text.red('0a')), group(2, t)))
|
||||
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'))
|
||||
b = ' '.join(highlight_bytes(bb) for bb in b.split(' '))
|
||||
i = highlight(i.strip(), PwntoolsLexer(), TerminalFormatter()).strip()
|
||||
i = i.replace(',',', ')
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from subprocess import CalledProcessError
|
||||
from subprocess import check_output
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -29,7 +29,8 @@ def diff(a,b):
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'elfdiff',
|
||||
help = 'Compare two ELF files'
|
||||
help = 'Compare two ELF files',
|
||||
description = 'Compare two ELF files'
|
||||
)
|
||||
|
||||
p.add_argument('a')
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import division
|
||||
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -12,7 +12,8 @@ from pwnlib.commandline import common
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'elfpatch',
|
||||
help = 'Patch an ELF file'
|
||||
help = 'Patch an ELF file',
|
||||
description = 'Patch an ELF file'
|
||||
)
|
||||
|
||||
p.add_argument('elf',help="File to patch")
|
||||
|
||||
@@ -8,7 +8,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'errno',
|
||||
help = 'Prints out error messages'
|
||||
help = 'Prints out error messages',
|
||||
description = 'Prints out error messages'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
|
||||
@@ -7,23 +7,48 @@ import sys
|
||||
|
||||
from pwnlib.commandline import common
|
||||
from pwnlib.util.fiddling import enhex
|
||||
from pwnlib.util.lists import group
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'hex',
|
||||
help = '''
|
||||
Hex-encodes data provided on the command line or stdin
|
||||
''')
|
||||
help = 'Hex-encodes data provided on the command line or stdin',
|
||||
description = 'Hex-encodes data provided on the command line or stdin')
|
||||
|
||||
parser.add_argument('data', nargs='*',
|
||||
help='Data to convert into hex')
|
||||
|
||||
parser.add_argument(
|
||||
'-p', '--prefix',
|
||||
metavar = 'prefix',
|
||||
type = str,
|
||||
default = '',
|
||||
help = 'Insert a prefix before each byte',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-s', '--separator',
|
||||
metavar = 'separator',
|
||||
type = str,
|
||||
default = '',
|
||||
help = 'Add a separator between each byte',
|
||||
)
|
||||
|
||||
def format_hex(hex_string, prefix, separator):
|
||||
return separator.join([prefix + x for x in group(2, hex_string)])
|
||||
|
||||
def main(args):
|
||||
if not args.data:
|
||||
print(enhex(getattr(sys.stdin, 'buffer', sys.stdin).read()))
|
||||
encoded = enhex(getattr(sys.stdin, 'buffer', sys.stdin).read())
|
||||
else:
|
||||
data = ' '.join(args.data)
|
||||
if not hasattr(data, 'decode'):
|
||||
data = data.encode('utf-8', 'surrogateescape')
|
||||
print(enhex(data))
|
||||
encoded = enhex(data)
|
||||
|
||||
if args.prefix or args.separator:
|
||||
encoded = format_hex(encoded, args.prefix, args.separator)
|
||||
|
||||
print(encoded)
|
||||
|
||||
if __name__ == '__main__':
|
||||
common.main(__file__)
|
||||
@@ -0,0 +1,247 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'libcdb',
|
||||
help = 'Print various information about a libc binary',
|
||||
description = 'Print various information about a libc binary'
|
||||
)
|
||||
|
||||
libc_commands = parser.add_subparsers(
|
||||
dest = 'libc_command'
|
||||
)
|
||||
|
||||
lookup_parser = libc_commands.add_parser(
|
||||
'lookup',
|
||||
help = 'Lookup a libc version by function offsets',
|
||||
description = 'Lookup a libc version by function offsets'
|
||||
)
|
||||
|
||||
lookup_parser.add_argument(
|
||||
'symbol_offset_pairs',
|
||||
metavar = 'symbol_offset_pairs',
|
||||
nargs = '+',
|
||||
help = 'Symbol and offset pairs to lookup matching libc version. Can be any number of pairs to narrow the search. Example: "read 3e0 write 520"'
|
||||
)
|
||||
|
||||
lookup_parser.add_argument(
|
||||
'--download-libc',
|
||||
action = 'store_true',
|
||||
default = False,
|
||||
help = 'Attempt to download the matching libc.so'
|
||||
)
|
||||
|
||||
lookup_parser.add_argument(
|
||||
'--unstrip',
|
||||
action = 'store_true',
|
||||
default = True,
|
||||
help = 'Attempt to unstrip the libc binary with debug symbols from a debuginfod server'
|
||||
)
|
||||
|
||||
lookup_parser.add_argument(
|
||||
'--no-unstrip',
|
||||
action = 'store_false',
|
||||
dest = 'unstrip',
|
||||
help = 'Do NOT attempt to unstrip the libc binary with debug symbols from a debuginfod server'
|
||||
)
|
||||
|
||||
hash_parser = libc_commands.add_parser(
|
||||
'hash',
|
||||
help = 'Display information of a libc version given an unique hash',
|
||||
description = 'Display information of a libc version given an unique hash'
|
||||
)
|
||||
|
||||
hash_parser.add_argument(
|
||||
'hash_value',
|
||||
metavar = 'hash_value',
|
||||
nargs = '+',
|
||||
help = 'Hex encoded hash value'
|
||||
)
|
||||
|
||||
hash_parser.add_argument(
|
||||
'-t', '--hash_type',
|
||||
nargs = '?',
|
||||
type = str,
|
||||
choices = ['id', 'buildid', 'md5', 'sha1', 'sha256'],
|
||||
default = 'buildid',
|
||||
help = 'The type of the provided hash value. Supported hashtypes: id, buildid, md5, sha1, sha256'
|
||||
)
|
||||
|
||||
hash_parser.add_argument(
|
||||
'--download-libc',
|
||||
action = 'store_true',
|
||||
default = False,
|
||||
help = 'Attempt to download the matching libc.so'
|
||||
)
|
||||
|
||||
hash_parser.add_argument(
|
||||
'--unstrip',
|
||||
action = 'store_true',
|
||||
default = True,
|
||||
help = 'Attempt to unstrip the libc binary with debug symbols from a debuginfod server'
|
||||
)
|
||||
|
||||
hash_parser.add_argument(
|
||||
'--no-unstrip',
|
||||
action = 'store_false',
|
||||
dest = 'unstrip',
|
||||
help = 'Do NOT attempt to unstrip the libc binary with debug symbols from a debuginfod server'
|
||||
)
|
||||
|
||||
file_parser = libc_commands.add_parser(
|
||||
'file',
|
||||
help = 'Dump information about a libc binary',
|
||||
description = 'Dump information about a libc binary'
|
||||
)
|
||||
|
||||
file_parser.add_argument(
|
||||
'files',
|
||||
metavar = 'files',
|
||||
nargs = '+',
|
||||
help = 'Libc binary to dump'
|
||||
)
|
||||
|
||||
file_parser.add_argument(
|
||||
'-s', '--symbols',
|
||||
metavar = 'symbols',
|
||||
nargs = '*',
|
||||
help = 'List of symbol offsets to dump in addition to the common ones'
|
||||
)
|
||||
|
||||
file_parser.add_argument(
|
||||
'-o', '--offset',
|
||||
metavar = 'offset',
|
||||
type = str,
|
||||
help = 'Display all offsets relative to this symbol'
|
||||
)
|
||||
|
||||
file_parser.add_argument(
|
||||
'--unstrip',
|
||||
action = 'store_true',
|
||||
default = False,
|
||||
help = 'Attempt to unstrip the libc binary inplace with debug symbols from a debuginfod server'
|
||||
)
|
||||
|
||||
common_symbols = ['dup2', 'printf', 'puts', 'read', 'system', 'write']
|
||||
|
||||
def find_libc(params):
|
||||
import requests
|
||||
url = "https://libc.rip/api/find"
|
||||
result = requests.post(url, json=params, timeout=20)
|
||||
log.debug('Request: %s', params)
|
||||
log.debug('Result: %s', result.json())
|
||||
if result.status_code != 200 or len(result.json()) == 0:
|
||||
log.failure("Could not find libc for %s on libc.rip", params)
|
||||
return []
|
||||
|
||||
return result.json()
|
||||
|
||||
def print_libc(libc):
|
||||
log.info('%s', text.red(libc['id']))
|
||||
log.indented('\t%-20s %s', text.green('BuildID:'), libc['buildid'])
|
||||
log.indented('\t%-20s %s', text.green('MD5:'), libc['md5'])
|
||||
log.indented('\t%-20s %s', text.green('SHA1:'), libc['sha1'])
|
||||
log.indented('\t%-20s %s', text.green('SHA256:'), libc['sha256'])
|
||||
log.indented('\t%s', text.green('Symbols:'))
|
||||
for symbol in libc['symbols'].items():
|
||||
log.indented('\t%25s = %s', symbol[0], symbol[1])
|
||||
|
||||
def handle_remote_libc(args, libc):
|
||||
print_libc(libc)
|
||||
if args.download_libc:
|
||||
path = libcdb.search_by_build_id(libc['buildid'], args.unstrip)
|
||||
if path:
|
||||
if args.unstrip:
|
||||
libcdb.unstrip_libc(path)
|
||||
shutil.copy(path, './{}.so'.format(libc['id']))
|
||||
|
||||
def translate_offset(offs, args, exe):
|
||||
if args.offset:
|
||||
if args.offset not in exe.symbols:
|
||||
log.info_once('offset symbol %s not found. ignoring.', args.offset)
|
||||
return offs
|
||||
return offs - exe.symbols[args.offset]
|
||||
return offs
|
||||
|
||||
def collect_synthetic_symbols(exe):
|
||||
available_symbols = ['str_bin_sh']
|
||||
exe.symbols['str_bin_sh'] = next(exe.search(b'/bin/sh\x00'))
|
||||
|
||||
libc_start_main_return = exe.libc_start_main_return
|
||||
if libc_start_main_return > 0:
|
||||
exe.symbols['__libc_start_main_ret'] = libc_start_main_return
|
||||
available_symbols.append('__libc_start_main_ret')
|
||||
|
||||
return available_symbols
|
||||
|
||||
def main(args):
|
||||
if len(sys.argv) < 3:
|
||||
parser.print_usage()
|
||||
sys.exit()
|
||||
|
||||
if args.libc_command == 'lookup':
|
||||
pairs = args.symbol_offset_pairs
|
||||
if len(pairs) % 2 != 0:
|
||||
log.failure('Uneven number of arguments. Please provide "symbol offset" pairs')
|
||||
return
|
||||
|
||||
symbols = {pairs[i]:pairs[i+1] for i in range(0, len(pairs), 2)}
|
||||
matched_libcs = find_libc({'symbols': symbols})
|
||||
for libc in matched_libcs:
|
||||
handle_remote_libc(args, libc)
|
||||
|
||||
elif args.libc_command == 'hash':
|
||||
for hash_value in args.hash_value:
|
||||
matched_libcs = find_libc({args.hash_type: hash_value})
|
||||
for libc in matched_libcs:
|
||||
handle_remote_libc(args, libc)
|
||||
|
||||
elif args.libc_command == 'file':
|
||||
from hashlib import md5, sha1, sha256
|
||||
for file in args.files:
|
||||
if not os.path.exists(file) or not os.path.isfile(file):
|
||||
log.failure('File does not exist %s', args.file)
|
||||
continue
|
||||
|
||||
if args.unstrip:
|
||||
libcdb.unstrip_libc(file)
|
||||
|
||||
exe = ELF(file, checksec=False)
|
||||
log.info('%s', text.red(os.path.basename(file)))
|
||||
|
||||
libc_version = re.search(b'libc[ -](\d+\.\d+)', exe.data)
|
||||
if libc_version:
|
||||
log.indented('%-20s %s', text.green('Version:'), libc_version.group(1).decode())
|
||||
|
||||
if exe.buildid:
|
||||
log.indented('%-20s %s', text.green('BuildID:'), enhex(exe.buildid))
|
||||
log.indented('%-20s %s', text.green('MD5:'), md5(exe.data).hexdigest())
|
||||
log.indented('%-20s %s', text.green('SHA1:'), sha1(exe.data).hexdigest())
|
||||
log.indented('%-20s %s', text.green('SHA256:'), sha256(exe.data).hexdigest())
|
||||
|
||||
# Always dump the basic list of common symbols
|
||||
log.indented('%s', text.green('Symbols:'))
|
||||
synthetic_symbols = collect_synthetic_symbols(exe)
|
||||
|
||||
symbols = common_symbols + (args.symbols or []) + synthetic_symbols
|
||||
symbols.sort()
|
||||
for symbol in symbols:
|
||||
if symbol not in exe.symbols:
|
||||
log.indented('%25s = %s', symbol, text.red('not found'))
|
||||
else:
|
||||
log.indented('%25s = %#x', symbol, translate_offset(exe.symbols[symbol], args, exe))
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.commandline.common.main(__file__)
|
||||
@@ -14,6 +14,7 @@ from pwnlib.commandline import elfdiff
|
||||
from pwnlib.commandline import elfpatch
|
||||
from pwnlib.commandline import errno
|
||||
from pwnlib.commandline import hex
|
||||
from pwnlib.commandline import libcdb
|
||||
from pwnlib.commandline import phd
|
||||
from pwnlib.commandline import pwnstrip
|
||||
from pwnlib.commandline import scramble
|
||||
@@ -21,6 +22,7 @@ from pwnlib.commandline import shellcraft
|
||||
from pwnlib.commandline import template
|
||||
from pwnlib.commandline import unhex
|
||||
from pwnlib.commandline import update
|
||||
from pwnlib.commandline import version
|
||||
from pwnlib.commandline.common import parser
|
||||
from pwnlib.context import context
|
||||
|
||||
@@ -36,6 +38,7 @@ commands = {
|
||||
'elfpatch': elfpatch.main,
|
||||
'errno': errno.main,
|
||||
'hex': hex.main,
|
||||
'libcdb': libcdb.main,
|
||||
'phd': phd.main,
|
||||
'pwnstrip': pwnstrip.main,
|
||||
'scramble': scramble.main,
|
||||
@@ -43,6 +46,7 @@ commands = {
|
||||
'template': template.main,
|
||||
'unhex': unhex.main,
|
||||
'update': update.main,
|
||||
'version': version.main,
|
||||
}
|
||||
|
||||
def main():
|
||||
|
||||
@@ -4,10 +4,11 @@ from __future__ import division
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import io
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -15,7 +16,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'phd',
|
||||
help = 'Pwnlib HexDump'
|
||||
help = 'Pretty hex dump',
|
||||
description = 'Pretty hex dump'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -99,6 +101,8 @@ def main(args):
|
||||
for h in hs.split(','):
|
||||
hl.append(asint(h))
|
||||
|
||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||
|
||||
try:
|
||||
for line in hexdump_iter(infile, width, highlight = hl, begin = offset + skip):
|
||||
print(line)
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import division
|
||||
|
||||
import argparse
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -12,6 +12,7 @@ from pwnlib.commandline import common
|
||||
p = common.parser_commands.add_parser(
|
||||
'pwnstrip',
|
||||
help = 'Strip binaries for CTF usage',
|
||||
description = 'Strip binaries for CTF usage'
|
||||
)
|
||||
|
||||
g = p.add_argument_group("actions")
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import division
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -12,7 +12,8 @@ from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'scramble',
|
||||
help = 'Shellcode encoder'
|
||||
help = 'Shellcode encoder',
|
||||
description = 'Shellcode encoder'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
|
||||
@@ -8,7 +8,7 @@ import six
|
||||
import sys
|
||||
import types
|
||||
|
||||
import pwnlib
|
||||
import pwnlib.args
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
@@ -35,6 +35,7 @@ def _string(s):
|
||||
p = common.parser_commands.add_parser(
|
||||
'shellcraft',
|
||||
help = 'Microwave shellcode -- Easy, fast and delicious',
|
||||
description = 'Microwave shellcode -- Easy, fast and delicious',
|
||||
)
|
||||
|
||||
|
||||
@@ -198,11 +199,11 @@ def main(args):
|
||||
common.parser.print_usage()
|
||||
exit()
|
||||
|
||||
if args.shellcode not in shellcraft.templates:
|
||||
try:
|
||||
func = get_template(args.shellcode)
|
||||
except AttributeError:
|
||||
log.error("Unknown shellcraft template %r. Use --list to see available shellcodes." % args.shellcode)
|
||||
|
||||
func = get_template(args.shellcode)
|
||||
|
||||
if args.show:
|
||||
# remove doctests
|
||||
doc = []
|
||||
@@ -295,7 +296,7 @@ def main(args):
|
||||
|
||||
vma = args.address
|
||||
if vma:
|
||||
vma = eval(vma)
|
||||
vma = pwnlib.util.safeeval.expr(vma)
|
||||
|
||||
if args.format in ['e','elf']:
|
||||
args.format = 'default'
|
||||
|
||||
Loaded 100 of 876 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user