mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-08 08:06:05 -10:00
Compare commits
992
Commits
2.3.0
...
3.2.0beta0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
548e033e7e | ||
|
|
fc097f3446 | ||
|
|
eb92a95134 | ||
|
|
c706461f10 | ||
|
|
b0ad5eb915 | ||
|
|
94f88cc8ba | ||
|
|
1e414afbeb | ||
|
|
869ec42082 | ||
|
|
4893819b4c | ||
|
|
fb1b952769 | ||
|
|
859380285f | ||
|
|
2af55c9bc3 | ||
|
|
4725b1be96 | ||
|
|
5af5f0c55d | ||
|
|
e84f395c97 | ||
|
|
fbf51ad96e | ||
|
|
52433339ec | ||
|
|
f277d5502f | ||
|
|
794122ec13 | ||
|
|
65b266e9b3 | ||
|
|
ca6eddc235 | ||
|
|
8793decd1c | ||
|
|
628aaabd04 | ||
|
|
3544167f26 | ||
|
|
9cca9c989b | ||
|
|
f42c291fef | ||
|
|
dacdd397ab | ||
|
|
c0f02d453a | ||
|
|
627ed5cbd5 | ||
|
|
3fb64f9fe0 | ||
|
|
254958bae9 | ||
|
|
1cb47220f1 | ||
|
|
d9be4f9ce0 | ||
|
|
2cd5aadf9d | ||
|
|
6ebcc6f3a2 | ||
|
|
21ce572dd6 | ||
|
|
1c47a30446 | ||
|
|
5b8ccb60a6 | ||
|
|
89fc74facf | ||
|
|
5a79a5e609 | ||
|
|
c92f9bed42 | ||
|
|
bfb534378b | ||
|
|
0ddcf8b129 | ||
|
|
a66376b8a0 | ||
|
|
9cb53d90fe | ||
|
|
a31cec5e81 | ||
|
|
5367a3528d | ||
|
|
669e7295c6 | ||
|
|
a7f32d1b0f | ||
|
|
efc531a2a9 | ||
|
|
8b959c9ede | ||
|
|
68051f9987 | ||
|
|
3636657ca0 | ||
|
|
f282ef8bbc | ||
|
|
d5fbb21f72 | ||
|
|
57e9bf58a5 | ||
|
|
0ce21d9b45 | ||
|
|
89649fbeb0 | ||
|
|
5924c0f340 | ||
|
|
2f9f10c182 | ||
|
|
d7c98c4819 | ||
|
|
cd0ba369b8 | ||
|
|
bebc84522d | ||
|
|
e7875c78bc | ||
|
|
0a37694436 | ||
|
|
742a11bfdc | ||
|
|
1e7262ce31 | ||
|
|
d733cf6560 | ||
|
|
3818dda9d9 | ||
|
|
18c4a49aa3 | ||
|
|
77f7a362d0 | ||
|
|
738fadc016 | ||
|
|
b97f30f36f | ||
|
|
de05e7a4b8 | ||
|
|
5fe024838b | ||
|
|
8b07fe12e6 | ||
|
|
cd828d6bca | ||
|
|
b60103b839 | ||
|
|
684e9f6791 | ||
|
|
5acc4c8ec3 | ||
|
|
a5c2b9276a | ||
|
|
8d15fceb92 | ||
|
|
913a3eba9e | ||
|
|
041e62bf0b | ||
|
|
e61f571f7c | ||
|
|
36d00b615d | ||
|
|
25d340b5c5 | ||
|
|
8f06c1f90f | ||
|
|
ae6a0745ff | ||
|
|
1d924af9d2 | ||
|
|
fed432877c | ||
|
|
46261091dd | ||
|
|
c356b69a13 | ||
|
|
6cff484b8c | ||
|
|
8314dff386 | ||
|
|
dc40ac1117 | ||
|
|
288b9668b7 | ||
|
|
3c0697b81e | ||
|
|
6e4e46386f | ||
|
|
9b179567da | ||
|
|
b20e17dd13 | ||
|
|
3dcfafc0de | ||
|
|
348bcac0ff | ||
|
|
a43c3b4967 | ||
|
|
40bf991153 | ||
|
|
8f98c01b77 | ||
|
|
18a8cfb88d | ||
|
|
2acdeef320 | ||
|
|
23c09b4b1b | ||
|
|
84c71d6b07 | ||
|
|
c6aa6bccb8 | ||
|
|
041c665185 | ||
|
|
70f9c0305d | ||
|
|
66e41bd862 | ||
|
|
5140d03b4d | ||
|
|
b016179ccc | ||
|
|
efaea581a1 | ||
|
|
24dfaa0ff7 | ||
|
|
f4a72da40e | ||
|
|
6376d07266 | ||
|
|
ea94ee4ca5 | ||
|
|
452605e854 | ||
|
|
dea8f00c01 | ||
|
|
b9d6b27b4e | ||
|
|
300ef0b462 | ||
|
|
6e79272e8d | ||
|
|
d65991d402 | ||
|
|
de94449a87 | ||
|
|
faeb57b35c | ||
|
|
e1332d277c | ||
|
|
e4c2a48696 | ||
|
|
6415367f15 | ||
|
|
fcf2842d87 | ||
|
|
422dccd8da | ||
|
|
abd08a94ea | ||
|
|
e877f7455a | ||
|
|
70c224f429 | ||
|
|
5f7c525023 | ||
|
|
16de5ec22c | ||
|
|
e635bcfea7 | ||
|
|
12b60447da | ||
|
|
5c804d49d0 | ||
|
|
cde19135eb | ||
|
|
77da84c5a8 | ||
|
|
2663762a9a | ||
|
|
7aa9605629 | ||
|
|
757d7fe2c6 | ||
|
|
9e724203b9 | ||
|
|
72207cf914 | ||
|
|
824852bf33 | ||
|
|
b382849671 | ||
|
|
0e814c91cc | ||
|
|
d55a47a8fc | ||
|
|
3b65f8775a | ||
|
|
fce5081c30 | ||
|
|
39afc7998a | ||
|
|
1bfc56daa0 | ||
|
|
2d08e7cd99 | ||
|
|
f7696f0388 | ||
|
|
2947fb16dd | ||
|
|
9e57328d1b | ||
|
|
2198df5ea5 | ||
|
|
40cc12ba95 | ||
|
|
13f1815b7d | ||
|
|
16846a80c6 | ||
|
|
b29467dab6 | ||
|
|
969a9fe754 | ||
|
|
23b0a019da | ||
|
|
99f9c80f15 | ||
|
|
3d5f859dd0 | ||
|
|
5c5e797cbf | ||
|
|
b2698f5513 | ||
|
|
2baebf9e51 | ||
|
|
640051d41c | ||
|
|
2f8de42cd8 | ||
|
|
ac8e053ca0 | ||
|
|
741dffb47d | ||
|
|
ee77289111 | ||
|
|
01cda51e3e | ||
|
|
2d72ccc30c | ||
|
|
eee6ce3521 | ||
|
|
7f933d3ffc | ||
|
|
8680f2eeb6 | ||
|
|
06b81a3279 | ||
|
|
33cdabf0ab | ||
|
|
c32ae58811 | ||
|
|
d4e42f86d0 | ||
|
|
bd6ef3f45e | ||
|
|
a613d75abb | ||
|
|
2d8c8593de | ||
|
|
054e3d50d5 | ||
|
|
b06b544323 | ||
|
|
18d9646498 | ||
|
|
e8d8f4c4cc | ||
|
|
e18eef7fae | ||
|
|
396efcf71a | ||
|
|
ee485a68d5 | ||
|
|
c0bc668450 | ||
|
|
7c8806950b | ||
|
|
ba5815bba5 | ||
|
|
25016264e7 | ||
|
|
4d83a0d017 | ||
|
|
67fd986360 | ||
|
|
fc1a7e2d11 | ||
|
|
112a246881 | ||
|
|
c0c91841a7 | ||
|
|
70df2fa5f3 | ||
|
|
aedbafd9d6 | ||
|
|
51f62206f6 | ||
|
|
a9ac751b89 | ||
|
|
ab31b3091c | ||
|
|
322942f2d3 | ||
|
|
9967347d70 | ||
|
|
01ec1328f9 | ||
|
|
020469788a | ||
|
|
348456e290 | ||
|
|
01e5057b05 | ||
|
|
c97da1524c | ||
|
|
ec506414ee | ||
|
|
10eb718058 | ||
|
|
c575c66895 | ||
|
|
a30ab0ca80 | ||
|
|
a598103ca9 | ||
|
|
d2a377cfbc | ||
|
|
3ab9063d43 | ||
|
|
8958123e3e | ||
|
|
c57aa1a507 | ||
|
|
ffe2e7cf1f | ||
|
|
fdbd19fdd2 | ||
|
|
30bfc92037 | ||
|
|
d84a1073d7 | ||
|
|
8d934d65e1 | ||
|
|
a77aa1be73 | ||
|
|
176b0af30b | ||
|
|
03e9546127 | ||
|
|
05672c3e14 | ||
|
|
7a5760cd39 | ||
|
|
78584929d7 | ||
|
|
56ad2276f4 | ||
|
|
d76b6c5560 | ||
|
|
e59a44d8b3 | ||
|
|
2f11018a1e | ||
|
|
21fc7759e0 | ||
|
|
d2933acba2 | ||
|
|
efa9c26842 | ||
|
|
b61941835a | ||
|
|
c75bf4ad75 | ||
|
|
8138315fa6 | ||
|
|
f1e7715e6f | ||
|
|
544342b9fe | ||
|
|
430bee44b7 | ||
|
|
31c1070ac8 | ||
|
|
59102739f5 | ||
|
|
a02d3277ce | ||
|
|
2f75eb6c3a | ||
|
|
22c97ee762 | ||
|
|
500a2720a5 | ||
|
|
2fc9a83a50 | ||
|
|
b572a9da4a | ||
|
|
3db45f46e4 | ||
|
|
41383b3330 | ||
|
|
1a3d81f8f1 | ||
|
|
4e04c8bfb3 | ||
|
|
94abecce80 | ||
|
|
7f733aa63b | ||
|
|
b26a2f21fc | ||
|
|
d91b05b43a | ||
|
|
9aff300cee | ||
|
|
806d506510 | ||
|
|
f0010e4413 | ||
|
|
58c61897ba | ||
|
|
dc083ae7b9 | ||
|
|
7029b38cce | ||
|
|
cf19d35d14 | ||
|
|
c498ddcb6d | ||
|
|
7253234fba | ||
|
|
7925b44582 | ||
|
|
494a078be9 | ||
|
|
8ef546bc34 | ||
|
|
64416909bb | ||
|
|
1c6689eca4 | ||
|
|
4dfc571702 | ||
|
|
cb40e4b883 | ||
|
|
12564a7e0d | ||
|
|
d51ad7f989 | ||
|
|
bbc91d6211 | ||
|
|
21c10be67e | ||
|
|
ca43832880 | ||
|
|
c9dabb8606 | ||
|
|
eb8f905449 | ||
|
|
1b9a4ca123 | ||
|
|
02e0c3804c | ||
|
|
50624322c4 | ||
|
|
63d564810b | ||
|
|
03d8efaba2 | ||
|
|
c47538da1f | ||
|
|
3192839ff8 | ||
|
|
abc646511a | ||
|
|
d3ab88364c | ||
|
|
3d61ba339a | ||
|
|
84a1a540b0 | ||
|
|
efa8c77d3c | ||
|
|
734d3a17e6 | ||
|
|
378a32b390 | ||
|
|
6bf0989e2f | ||
|
|
158f6d7758 | ||
|
|
38047c15c6 | ||
|
|
56fbd583e6 | ||
|
|
2d8e5f0050 | ||
|
|
1b865681fc | ||
|
|
bcc57b3138 | ||
|
|
87a612282d | ||
|
|
215ddafc65 | ||
|
|
474d96eb52 | ||
|
|
b868c12d63 | ||
|
|
d9f120e617 | ||
|
|
2c788f4f55 | ||
|
|
2d3eb7204d | ||
|
|
4e2d5f096a | ||
|
|
b60218a4d7 | ||
|
|
51dd430ad0 | ||
|
|
60e5a80790 | ||
|
|
d4f10b0d6e | ||
|
|
95d4b8e09d | ||
|
|
0af33f3a6f | ||
|
|
68207adbe4 | ||
|
|
999ad63200 | ||
|
|
b45ef8dfbd | ||
|
|
320e0dd80b | ||
|
|
c1e3d26d29 | ||
|
|
73ddedebb4 | ||
|
|
7f236f5064 | ||
|
|
80ebf7109a | ||
|
|
36ccc2bc81 | ||
|
|
72416c4705 | ||
|
|
8f2878d0ab | ||
|
|
10487c23ac | ||
|
|
a18c23cf2d | ||
|
|
714f27fee9 | ||
|
|
9942ae157f | ||
|
|
36ead5ac57 | ||
|
|
18049ddddb | ||
|
|
6f74c7f13e | ||
|
|
17b48f7186 | ||
|
|
a518a60388 | ||
|
|
78e394bd6d | ||
|
|
282b853c2a | ||
|
|
aa64f71075 | ||
|
|
354213c475 | ||
|
|
d22f6c457f | ||
|
|
03baaa3807 | ||
|
|
a5df5ee6a0 | ||
|
|
c5b3d343ad | ||
|
|
1413caf401 | ||
|
|
09a637eabe | ||
|
|
bb95c6fbbd | ||
|
|
b0cb09ae67 | ||
|
|
669c963290 | ||
|
|
0e0cb7c0e3 | ||
|
|
bc20216579 | ||
|
|
0ce1ebbd81 | ||
|
|
d3074011d6 | ||
|
|
03b8eb8694 | ||
|
|
3b383ece1c | ||
|
|
524a76b925 | ||
|
|
541734a097 | ||
|
|
cf203cc91e | ||
|
|
b52b970a28 | ||
|
|
b36c78805f | ||
|
|
54584e09c0 | ||
|
|
2314322369 | ||
|
|
0ef6a9a383 | ||
|
|
131eefaf05 | ||
|
|
63ca4f51b1 | ||
|
|
e806bf73f6 | ||
|
|
2cf84db4ca | ||
|
|
cb5f04de6b | ||
|
|
c8228729f1 | ||
|
|
098888da2f | ||
|
|
c250f00abe | ||
|
|
02ffc4034e | ||
|
|
00047af206 | ||
|
|
5a60b591be | ||
|
|
e54cd0ddf7 | ||
|
|
8eec3e2d12 | ||
|
|
1738218f81 | ||
|
|
e3c1aad702 | ||
|
|
df7f08a5ed | ||
|
|
44548b0a72 | ||
|
|
5512ecf450 | ||
|
|
8b969da149 | ||
|
|
176e45d9f6 | ||
|
|
594f35e4f7 | ||
|
|
ea2493bd56 | ||
|
|
3ef1e1a7d5 | ||
|
|
e978986a84 | ||
|
|
faf3e42861 | ||
|
|
32cff88c56 | ||
|
|
f32069589d | ||
|
|
926231b4ed | ||
|
|
f08e2c8731 | ||
|
|
ee1ca61d37 | ||
|
|
42d08b43fc | ||
|
|
ab692c1569 | ||
|
|
7640c3fa9f | ||
|
|
3db5c4d0ce | ||
|
|
3bcf57bcd3 | ||
|
|
714bc320c4 | ||
|
|
24c32f541d | ||
|
|
f8753f2f5b | ||
|
|
507deae10f | ||
|
|
d4dbdb58df | ||
|
|
59ae1a999a | ||
|
|
1582064bed | ||
|
|
506be041b7 | ||
|
|
8699c98a6f | ||
|
|
1bcc4626e3 | ||
|
|
d6e4c7d76d | ||
|
|
ee8a96c39d | ||
|
|
49dd666026 | ||
|
|
675155abc8 | ||
|
|
8d4b1f84f8 | ||
|
|
8ffb0dfacf | ||
|
|
aff7b8e3a3 | ||
|
|
438c9a303b | ||
|
|
f0f4180fd4 | ||
|
|
aad6e9ae9b | ||
|
|
bc6cc93537 | ||
|
|
89a60e71b8 | ||
|
|
6c6b16bb16 | ||
|
|
b1575e6a0f | ||
|
|
4c38d29ac3 | ||
|
|
232ebd5e6d | ||
|
|
f79b447378 | ||
|
|
45ea91fa8e | ||
|
|
55a47c95b9 | ||
|
|
dbd334673d | ||
|
|
73d8e06a4b | ||
|
|
6f248e8a5e | ||
|
|
d90566d30a | ||
|
|
6db7b8cfbf | ||
|
|
aa323a40df | ||
|
|
8fc7e64ff5 | ||
|
|
2264290a6f | ||
|
|
170d4999eb | ||
|
|
3520393b62 | ||
|
|
88ff1f3533 | ||
|
|
e5223e4bd1 | ||
|
|
afdb7a4449 | ||
|
|
d3814a3d39 | ||
|
|
515af41f85 | ||
|
|
c66b809006 | ||
|
|
c2339b62f1 | ||
|
|
e7a72e086b | ||
|
|
1bed4850b0 | ||
|
|
4993b4ada7 | ||
|
|
2c8652bf91 | ||
|
|
2219f183c2 | ||
|
|
278ebee345 | ||
|
|
81de47c025 | ||
|
|
e1b93c77f5 | ||
|
|
77383048fb | ||
|
|
fb3c55af06 | ||
|
|
d7a0bafc5f | ||
|
|
11fa0d8d6d | ||
|
|
768b24e192 | ||
|
|
42d8f59e11 | ||
|
|
c734802900 | ||
|
|
b4945667c7 | ||
|
|
442873e5be | ||
|
|
29eefaac2b | ||
|
|
c5a92cdfb6 | ||
|
|
4c61ed3b0b | ||
|
|
88d1643804 | ||
|
|
f12253e34d | ||
|
|
783cc096a6 | ||
|
|
549541b6ea | ||
|
|
a2916b7d01 | ||
|
|
a6a5cfeb9c | ||
|
|
c18f8a202d | ||
|
|
59a309d6ac | ||
|
|
a676adbc52 | ||
|
|
e08aebe9fd | ||
|
|
f968120997 | ||
|
|
b03d83dfe7 | ||
|
|
f9c7ea87fa | ||
|
|
1a389ca2b8 | ||
|
|
ecbe0e9fa9 | ||
|
|
76d78a0e7e | ||
|
|
3f8d4cc37c | ||
|
|
e7ef1c1029 | ||
|
|
e6752fbd30 | ||
|
|
de393e4afa | ||
|
|
f92ea95299 | ||
|
|
ee4028c10a | ||
|
|
69ee58343e | ||
|
|
dca6232d97 | ||
|
|
8c1565ae3e | ||
|
|
d1a70dc0fb | ||
|
|
48a1cc72b0 | ||
|
|
c29aebdb77 | ||
|
|
ae888803b6 | ||
|
|
4386b8d82a | ||
|
|
a44ba4fa16 | ||
|
|
9ac4e8d9cb | ||
|
|
9559a99854 | ||
|
|
1897045707 | ||
|
|
973efff68b | ||
|
|
dd58f40991 | ||
|
|
0f710677d3 | ||
|
|
6d2ccdcf93 | ||
|
|
5d1e3500f0 | ||
|
|
37c55233ed | ||
|
|
1f289e3dbd | ||
|
|
d66c273e60 | ||
|
|
ed7b459be9 | ||
|
|
e544cd43b8 | ||
|
|
cfdfaff37e | ||
|
|
38e9f4274d | ||
|
|
88d79af9c9 | ||
|
|
e675c2068e | ||
|
|
4cecbac380 | ||
|
|
b4f8877660 | ||
|
|
1f5fde3302 | ||
|
|
9e17e76054 | ||
|
|
4f5be7144b | ||
|
|
51d8a89d4b | ||
|
|
523344b64e | ||
|
|
7486c79a67 | ||
|
|
3a565a8171 | ||
|
|
6b82b6b7dc | ||
|
|
c4dd91c5de | ||
|
|
4b33859132 | ||
|
|
6aff977171 | ||
|
|
6141e7d465 | ||
|
|
71845f6198 | ||
|
|
d00cae41a6 | ||
|
|
1327f2b33b | ||
|
|
b6ea53696b | ||
|
|
be1e13389a | ||
|
|
6e562b2bdb | ||
|
|
dd7c0acae1 | ||
|
|
b10f109967 | ||
|
|
63da39ea18 | ||
|
|
8b459a066e | ||
|
|
1187e544de | ||
|
|
49e2c52b0b | ||
|
|
fc0c7a0f69 | ||
|
|
d7b957c9c1 | ||
|
|
dad217f9ed | ||
|
|
ba6eba4b13 | ||
|
|
4f1745fbdf | ||
|
|
b218776573 | ||
|
|
e867643192 | ||
|
|
275a3a09d4 | ||
|
|
6f0a62e751 | ||
|
|
70645b432b | ||
|
|
4ea3a4932e | ||
|
|
8d1f57a345 | ||
|
|
c00e2b1863 | ||
|
|
2aac79c9ad | ||
|
|
8121a95bc5 | ||
|
|
797d416a47 | ||
|
|
4ad2cb87a9 | ||
|
|
400f208ca2 | ||
|
|
800f85fe7a | ||
|
|
30dcc6af05 | ||
|
|
2078c1dca6 | ||
|
|
966cc482fd | ||
|
|
98f27f80d8 | ||
|
|
3c2b2b22c9 | ||
|
|
c03c90c204 | ||
|
|
4265424956 | ||
|
|
085efbc6b4 | ||
|
|
1d5fe92e04 | ||
|
|
8ba3d52955 | ||
|
|
24c1f2d04a | ||
|
|
1e59b54c4e | ||
|
|
e21f8a0a24 | ||
|
|
58b6ce5ec4 | ||
|
|
e54c16c5e9 | ||
|
|
ac4524607a | ||
|
|
757f60acb0 | ||
|
|
b57beda046 | ||
|
|
1ac87052c2 | ||
|
|
502de0c92f | ||
|
|
2093ca4632 | ||
|
|
86e422de0c | ||
|
|
af5ba55325 | ||
|
|
405d9cc2af | ||
|
|
1631d2265e | ||
|
|
77cc76769c | ||
|
|
31f05f4c7f | ||
|
|
24f49a46cf | ||
|
|
28307ec699 | ||
|
|
c50f224b6b | ||
|
|
3a63c0804d | ||
|
|
1d5825c844 | ||
|
|
709d834945 | ||
|
|
f3b0645568 | ||
|
|
640d0261fd | ||
|
|
89dd56a2a3 | ||
|
|
e45ee3053e | ||
|
|
65a60a6170 | ||
|
|
63c5d4fb60 | ||
|
|
6c27af5e16 | ||
|
|
931d18f836 | ||
|
|
41350f51cf | ||
|
|
75b230c052 | ||
|
|
24a70eb8ff | ||
|
|
918115302c | ||
|
|
af92658f42 | ||
|
|
ee35d10303 | ||
|
|
3b0cf3cbaf | ||
|
|
7292806e08 | ||
|
|
f263f9e10d | ||
|
|
cfa0d50339 | ||
|
|
7cf6360dbb | ||
|
|
32fef0cf05 | ||
|
|
95b1adebbf | ||
|
|
df3a746768 | ||
|
|
11bfb24506 | ||
|
|
ddaa95d6dd | ||
|
|
77e8ab1d84 | ||
|
|
e9497169f1 | ||
|
|
9f552c94cb | ||
|
|
0cdb715e7c | ||
|
|
9a5b4e09af | ||
|
|
bac6a9f543 | ||
|
|
b901ff3b1e | ||
|
|
de47ac9cf5 | ||
|
|
72e9b3135e | ||
|
|
7413dffac7 | ||
|
|
7b4a415a90 | ||
|
|
465f5875b7 | ||
|
|
a50cd85791 | ||
|
|
1541b20c19 | ||
|
|
54551eb072 | ||
|
|
a45da211db | ||
|
|
5bfde777bf | ||
|
|
6e0ee86cb9 | ||
|
|
b78b91180f | ||
|
|
77326199e4 | ||
|
|
287bcae4c4 | ||
|
|
6148801e95 | ||
|
|
f23c297d7b | ||
|
|
a4c5492772 | ||
|
|
01365128dc | ||
|
|
cbcf23c70d | ||
|
|
1bc94ccc58 | ||
|
|
347ab75af5 | ||
|
|
72768d8b4a | ||
|
|
d3a3359c77 | ||
|
|
c3b006ef50 | ||
|
|
14093c2d54 | ||
|
|
c21426e3a0 | ||
|
|
6034b2b312 | ||
|
|
ff5f634a76 | ||
|
|
af9fe4c0d2 | ||
|
|
9b9ae29a71 | ||
|
|
62b3964225 | ||
|
|
cec172ee9b | ||
|
|
b349eaff6f | ||
|
|
dfa96abb09 | ||
|
|
8922d369e9 | ||
|
|
043232336f | ||
|
|
ffa321103b | ||
|
|
4ac5bce80e | ||
|
|
9cf7e8f7e7 | ||
|
|
b7731b32e5 | ||
|
|
eec0b68b52 | ||
|
|
e1331055ae | ||
|
|
2b909824b8 | ||
|
|
f9d080141f | ||
|
|
00d9460422 | ||
|
|
525f35c143 | ||
|
|
b36bd7ace5 | ||
|
|
ce458c7fc0 | ||
|
|
329ef332b4 | ||
|
|
5c0d5132e2 | ||
|
|
06fc1eecd5 | ||
|
|
79c718aa43 | ||
|
|
d99f7160bf | ||
|
|
de4f14c5d2 | ||
|
|
b064c45d5e | ||
|
|
5064a75f1f | ||
|
|
2e4692ff22 | ||
|
|
3b9614a535 | ||
|
|
4acd9bc928 | ||
|
|
da475754fe | ||
|
|
e2ddcf2471 | ||
|
|
40dae903cc | ||
|
|
eecafc6ed6 | ||
|
|
32e85f5791 | ||
|
|
e58a661375 | ||
|
|
9eadd74bed | ||
|
|
525650bc5b | ||
|
|
d3e73d231b | ||
|
|
d7933badf2 | ||
|
|
e4d44c54d8 | ||
|
|
c5ec095b7f | ||
|
|
476e8991ca | ||
|
|
6e4f616c44 | ||
|
|
ffc44ece88 | ||
|
|
40db24653c | ||
|
|
9908afd495 | ||
|
|
f81993c303 | ||
|
|
3b9e9bf3a0 | ||
|
|
ebef41df05 | ||
|
|
9f5c2e77b8 | ||
|
|
116491c54c | ||
|
|
285a370378 | ||
|
|
9da1c64513 | ||
|
|
8845115b1f | ||
|
|
6f22a11559 | ||
|
|
b7ce1b4ccd | ||
|
|
19f4009b6e | ||
|
|
17b0d4efe6 | ||
|
|
2077846087 | ||
|
|
b43be94aaa | ||
|
|
8a671ac1a7 | ||
|
|
c503c9c7d5 | ||
|
|
ad05fda608 | ||
|
|
402e324725 | ||
|
|
d81e63f03d | ||
|
|
fcd04a5c91 | ||
|
|
9d9b880954 | ||
|
|
38097d724f | ||
|
|
230cdafe31 | ||
|
|
27b7f15c9c | ||
|
|
33ca18f931 | ||
|
|
5f8ae0ef2d | ||
|
|
821b08240a | ||
|
|
40ea374001 | ||
|
|
7399918a54 | ||
|
|
367af48420 | ||
|
|
3745f6fd03 | ||
|
|
f643bf8722 | ||
|
|
580b16230e | ||
|
|
ee9ffb7491 | ||
|
|
2aa6c1f015 | ||
|
|
90b8e50d07 | ||
|
|
2faeefeaf0 | ||
|
|
24e70378ca | ||
|
|
b7364fe8ac | ||
|
|
475c1d407f | ||
|
|
c9f0ec84d1 | ||
|
|
8b1a3e73a1 | ||
|
|
c472d573f7 | ||
|
|
10ed1a2a68 | ||
|
|
8ec7faf879 | ||
|
|
6278f9a94e | ||
|
|
25900adf72 | ||
|
|
09d053be0f | ||
|
|
9536b17e5a | ||
|
|
2aeda2c993 | ||
|
|
17c3a27861 | ||
|
|
36f1fc32e0 | ||
|
|
0a6f1e540e | ||
|
|
2caafc879f | ||
|
|
f30f2093b0 | ||
|
|
fadfa11214 | ||
|
|
030407d8e7 | ||
|
|
0c513cb06b | ||
|
|
2e0d7b8671 | ||
|
|
5004787cb9 | ||
|
|
1a55837bff | ||
|
|
c8c9e5d1ea | ||
|
|
989e7694d8 | ||
|
|
f753382a4d | ||
|
|
e5b3baae84 | ||
|
|
1e8bf3e0e9 | ||
|
|
3fe3502b30 | ||
|
|
9905ba6605 | ||
|
|
827d4e5f09 | ||
|
|
f8a64a69c1 | ||
|
|
50451ceda6 | ||
|
|
1aff50166a | ||
|
|
a8d02b5108 | ||
|
|
a46e7fdc06 | ||
|
|
50ac72d8eb | ||
|
|
eb8a166659 | ||
|
|
16c7954e0a | ||
|
|
f0c4d5814a | ||
|
|
d2f0cec56d | ||
|
|
2b163fb7fb | ||
|
|
b9c581b78c | ||
|
|
290f17a408 | ||
|
|
f22537027f | ||
|
|
9e2901e70f | ||
|
|
d38deb5ae7 | ||
|
|
8e14c3d488 | ||
|
|
19fb739d24 | ||
|
|
7a1d62f2fb | ||
|
|
6d806cede3 | ||
|
|
1fc1406895 | ||
|
|
008b013542 | ||
|
|
e485e5bc93 | ||
|
|
4fa6cc0649 | ||
|
|
c825e43ff2 | ||
|
|
506815533a | ||
|
|
b9951de394 | ||
|
|
ca8f0b2f80 | ||
|
|
a39b9ef25b | ||
|
|
3cfbf0793d | ||
|
|
fced987465 | ||
|
|
2530b1c586 | ||
|
|
477d0f54bf | ||
|
|
acc4f64a4b | ||
|
|
f7c3dae4e1 | ||
|
|
38e4ada7ce | ||
|
|
8afb2b6d89 | ||
|
|
81c9565e4c | ||
|
|
15f1aeaafe | ||
|
|
820936ccbd | ||
|
|
6499a63bfb | ||
|
|
c2c3aec1c8 | ||
|
|
70c34aab2a | ||
|
|
3be0ee96a7 | ||
|
|
1e062ac52b | ||
|
|
fb6b046d8d | ||
|
|
0874e1908f | ||
|
|
cbe13129db | ||
|
|
980d391b1f | ||
|
|
9d1756e99b | ||
|
|
cb163e7662 | ||
|
|
fdae85c991 | ||
|
|
f171539d83 | ||
|
|
44f881b742 | ||
|
|
cc6ca79a45 | ||
|
|
9332812af1 | ||
|
|
3f23a8a63a | ||
|
|
35ef86b189 | ||
|
|
5962bca201 | ||
|
|
0c8935fc8c | ||
|
|
5e1447f8b4 | ||
|
|
9ec1ea0852 | ||
|
|
b54d2dfa47 | ||
|
|
547e8df98a | ||
|
|
ef74b64e86 | ||
|
|
886e49bd1c | ||
|
|
42486c7a76 | ||
|
|
57eaede85b | ||
|
|
0ad8649599 | ||
|
|
8c183ac0e3 | ||
|
|
c0002895c8 | ||
|
|
a92260d9e5 | ||
|
|
b7743546b6 | ||
|
|
75d260cd77 | ||
|
|
fc4abbf395 | ||
|
|
a5c8aa31a5 | ||
|
|
9e90e0485c | ||
|
|
1a1afabb23 | ||
|
|
37ea0e8882 | ||
|
|
f3237586a5 | ||
|
|
324ef12b29 | ||
|
|
3b659cc8ec | ||
|
|
99aa19f332 | ||
|
|
c623661f06 | ||
|
|
1d165fbde4 | ||
|
|
a7816bde40 | ||
|
|
de8de2d187 | ||
|
|
3df64b6c80 | ||
|
|
84fc6a37e3 | ||
|
|
a2fb187c2a | ||
|
|
8a915a59e7 | ||
|
|
ea88f746a1 | ||
|
|
33c47c159c | ||
|
|
0d544d96c8 | ||
|
|
b9ac583e8a | ||
|
|
7e46c36965 | ||
|
|
0c9d345c37 | ||
|
|
b28299a96e | ||
|
|
f6dab8cb94 | ||
|
|
ab3e58be59 | ||
|
|
068a5915b8 | ||
|
|
48ccd3dbe6 | ||
|
|
4f1bae8748 | ||
|
|
5ed9d4e2a9 | ||
|
|
87d12970f6 | ||
|
|
131e669246 | ||
|
|
41f003464b | ||
|
|
b436d4a99a | ||
|
|
b689dc6141 | ||
|
|
9047360dd6 | ||
|
|
339c71abbd | ||
|
|
c1308f454f | ||
|
|
2ec8647d10 | ||
|
|
96f07f950c | ||
|
|
acaaf2bf98 | ||
|
|
5e4fa7c03d | ||
|
|
1a69412209 | ||
|
|
d194dfd8ce | ||
|
|
2c5ea17ddb | ||
|
|
9d25c526e9 | ||
|
|
34c4843bbf | ||
|
|
4616f9f107 | ||
|
|
12fe3d310a | ||
|
|
24661aa6e7 | ||
|
|
1b5c6162d1 | ||
|
|
e17e9c8b43 | ||
|
|
a9e535eef6 | ||
|
|
dfe78552c3 | ||
|
|
16dadb3376 | ||
|
|
054b7a5b17 | ||
|
|
3eccae29d8 | ||
|
|
37e29db87a | ||
|
|
dc84e7150a | ||
|
|
f6e90df62a | ||
|
|
a96ffc80a2 | ||
|
|
dae43bb581 | ||
|
|
b399f2a439 | ||
|
|
6730a63432 | ||
|
|
8bbaa14afe | ||
|
|
7bc5a9cc31 | ||
|
|
1844b85ae6 | ||
|
|
ff19108e02 | ||
|
|
5e58b94d7a | ||
|
|
9a5bccd837 | ||
|
|
7865ec93b0 | ||
|
|
de68ff6734 | ||
|
|
d26a5a7012 | ||
|
|
5f167c657f | ||
|
|
67faf896f1 | ||
|
|
073a179d29 | ||
|
|
65847258fd | ||
|
|
b6a98274c0 | ||
|
|
da9ee7bd9d | ||
|
|
47160d7398 | ||
|
|
5974be5c01 | ||
|
|
edf68d3ffb | ||
|
|
dddc0ee163 | ||
|
|
27e96868b8 | ||
|
|
efce85666d | ||
|
|
cdbba52548 | ||
|
|
2cc92df291 | ||
|
|
f3a0a4f781 | ||
|
|
b5d33ff064 | ||
|
|
7e829db170 | ||
|
|
504c502c22 | ||
|
|
3324062013 | ||
|
|
3a767b45dd | ||
|
|
ebb349c700 | ||
|
|
9991348963 | ||
|
|
b010daa438 | ||
|
|
73a494cfd0 | ||
|
|
3c2074cdeb | ||
|
|
16f7021065 | ||
|
|
bd137c7a4c | ||
|
|
4137fac99b | ||
|
|
57de045db5 | ||
|
|
5046f18b90 | ||
|
|
dcd3df3f10 | ||
|
|
ceec814588 | ||
|
|
a4860f3167 | ||
|
|
c762eec46c | ||
|
|
380eda7234 | ||
|
|
f02cc65624 | ||
|
|
32ecc909a3 | ||
|
|
ec64ebe3c7 | ||
|
|
fb7d604927 | ||
|
|
93a95d16f1 | ||
|
|
9de8211e58 | ||
|
|
33d7e4ea30 | ||
|
|
99acaf7471 | ||
|
|
e48c08baa4 | ||
|
|
b4e89ab373 | ||
|
|
806f2a3e7d | ||
|
|
c709e7e753 | ||
|
|
88a83cad71 | ||
|
|
b41a4057c3 | ||
|
|
49244fe1dc | ||
|
|
1c06dca971 | ||
|
|
85379b292d | ||
|
|
88195d8c56 | ||
|
|
1c52cd0390 | ||
|
|
bc270113b6 | ||
|
|
139937114b | ||
|
|
2f22025cea | ||
|
|
8f13445b73 | ||
|
|
f297cf60ba | ||
|
|
19866979bc | ||
|
|
372490b4e9 | ||
|
|
9f244268ca | ||
|
|
d3929505c4 | ||
|
|
a4f21971d1 | ||
|
|
4d31a89a67 | ||
|
|
ca47f5ce27 | ||
|
|
7e02110bc5 | ||
|
|
69073530fd | ||
|
|
8943102479 | ||
|
|
37a46e052a |
No files matched your search
@@ -0,0 +1,8 @@
|
||||
[run]
|
||||
branch = True
|
||||
omit =
|
||||
*/constants/*
|
||||
source =
|
||||
pwn
|
||||
pwnlib
|
||||
~/.pwntools-cache/
|
||||
+5
-1
@@ -3,6 +3,7 @@
|
||||
*.pyc
|
||||
*~
|
||||
*.swp
|
||||
.ropeproject
|
||||
*.pdf
|
||||
*/auto/*
|
||||
*/bin/*
|
||||
@@ -10,4 +11,7 @@ docs/build
|
||||
build
|
||||
MANIFEST
|
||||
dist
|
||||
pwntools.egg-info
|
||||
*.egg-info
|
||||
*.core
|
||||
.coverage
|
||||
.tox
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"default_encoding": "UTF-8",
|
||||
"ensure_newline_at_eof_on_save": true,
|
||||
"tab_size": 4,
|
||||
"translate_tabs_to_spaces": true,
|
||||
"trim_trailing_white_space_on_save": true
|
||||
}
|
||||
+26
-10
@@ -1,5 +1,18 @@
|
||||
sudo: false
|
||||
language: python
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
- gcc-4.6-arm-linux-gnueabihf
|
||||
- lib32stdc++6
|
||||
- ash
|
||||
- bash
|
||||
- dash
|
||||
- ksh
|
||||
- mksh
|
||||
- zsh
|
||||
- pandoc
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
@@ -9,15 +22,18 @@ cache:
|
||||
python:
|
||||
- "2.7"
|
||||
before_install:
|
||||
- source .travis_ssh_setup.sh
|
||||
- source .travis_install.sh
|
||||
- source travis/install.sh
|
||||
- source travis/ssh_setup.sh
|
||||
install:
|
||||
- pip install -e .
|
||||
- pip install -r docs/requirements.txt
|
||||
- pip install --upgrade --editable .
|
||||
- pip install --requirement docs/requirements.txt
|
||||
before_script:
|
||||
- python -c 'from pwn import *; print pwnlib.term.term_mode' NOTERM
|
||||
- python -c 'from pwn import *; print pwnlib.term.term_mode' NOTERM
|
||||
- python -c 'from pwn import *; print pwnlib.term.term_mode' NOTERM
|
||||
- python -c 'from pwn import *; print pwnlib.term.term_mode' NOTERM
|
||||
script: PWNLIB_NOTERM=1 make -C docs doctest
|
||||
|
||||
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
|
||||
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
|
||||
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
|
||||
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
|
||||
script:
|
||||
- PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest
|
||||
after_success:
|
||||
- coveralls
|
||||
- source travis/update_demo.sh
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
local_deb_extract()
|
||||
{
|
||||
wget $1
|
||||
ar vx *.deb
|
||||
tar xvf data.tar.gz
|
||||
rm -f *.tar.gz *deb*
|
||||
}
|
||||
|
||||
get_binutils()
|
||||
{
|
||||
BINUTILS_PREFIX='https://launchpad.net/~pwntools/+archive/ubuntu/binutils/+files/binutils-'
|
||||
BINUTILS_SUFFIX='-linux-gnu_2.22-6ubuntu1.1cross0.11pwntools12~precise_amd64.deb'
|
||||
local_deb_extract "${BINUTILS_PREFIX}${1}${BINUTILS_SUFFIX}"
|
||||
}
|
||||
|
||||
setup_travis()
|
||||
{
|
||||
export PATH=$PWD/usr/bin:$PATH
|
||||
export LD_LIBRARY_PATH=$PWD/usr/lib
|
||||
|
||||
if [ ! -d usr/bin ];
|
||||
then
|
||||
which arm-linux-as || get_binutils arm
|
||||
which mips-linux-as || get_binutils mips
|
||||
which powerpc-linux-as || get_binutils powerpc
|
||||
local_deb_extract http://mirrors.mit.edu/ubuntu/ubuntu/pool/universe/b/binutils/binutils-multiarch_2.22-6ubuntu1_amd64.deb
|
||||
rm -rf usr/share
|
||||
fi
|
||||
|
||||
pushd usr/lib
|
||||
ln -sf libbfd-2.22-multiarch.so libbfd-2.22.so
|
||||
ln -sf libopcodes-2.22-multiarch.so libopcodes-2.22.so
|
||||
popd
|
||||
|
||||
which arm-linux-gnu-as
|
||||
which mips-linux-gnu-as
|
||||
which powerpc-linux-gnu-as
|
||||
}
|
||||
|
||||
setup_linux()
|
||||
{
|
||||
sudo apt-get install software-properties-common pwgen
|
||||
sudo apt-add-repository --yes ppa:pwntools/binutils
|
||||
sudo apt-get update
|
||||
sudo apt-get install binutils-arm-linux-gnu binutils-mips-linux-gnu binutils-powerpc-linux-gnu
|
||||
}
|
||||
|
||||
setup_osx()
|
||||
{
|
||||
brew update
|
||||
brew install binutils
|
||||
brew install capstone
|
||||
}
|
||||
|
||||
if [[ "$TRAVIS" ]]; then
|
||||
setup_travis
|
||||
elif [[ "$(uname)" == "Darwin" ]]; then
|
||||
setup_osx
|
||||
elif [[ "$(uname)" == "Linux" ]]; then
|
||||
setup_linux
|
||||
fi
|
||||
+186
@@ -3,6 +3,192 @@
|
||||
This changelog only includes added major features and changes. Bugfixes and
|
||||
minor changes are omitted.
|
||||
|
||||
## Release History
|
||||
|
||||
The table below shows which release corresponds to each branch, and what date the version was released.
|
||||
|
||||
| Version | Branch | Release Date |
|
||||
| ---------------- | -------- | ---------------------- |
|
||||
| [3.3.0](#330) | `dev` | Dec 24, 2016 (planned)
|
||||
| [3.2.0](#320) | `beta` | Nov 12, 2016 (planned)
|
||||
| [3.1.0](#310) | `stable` | Oct 2, 2016
|
||||
| [3.0.4](#304) | | Sept 19, 2016
|
||||
| [3.0.3](#303) | | Sept 18, 2016
|
||||
| [3.0.2](#302) | | Sept 6, 2016
|
||||
| [3.0.1](#301) | | Aug 20, 2016
|
||||
| [3.0.0](#300) | | Aug 20, 2016
|
||||
| [2.2.0](#220) | | Jan 5, 2015
|
||||
|
||||
## 3.2.0
|
||||
|
||||
- [#695][695] Fixed a performance regression in `phd`.
|
||||
- [#700][700] Added missing MIPS shellcode documentation to readthedocs, and enabled unit tests
|
||||
- [#701][701] Command line tools refactored to have a common `pwn` entry point.
|
||||
+ Added an option to *not* install the traditional `asm`, `disasm`, `checksec`, etc scripts
|
||||
+ All existing tools can be accessed from the `pwn` command (e.g. `pwn asm nop`).
|
||||
- [#704][704] The `process` object has a new, optional argument `alarm` for setting a `SIGALRM` timeout for processes.
|
||||
- [#705][705] Added the Android Emulator to the test suite and Travis CI.
|
||||
+ Android Emulator is now required for the full test suite
|
||||
+ Android Emulator tests are skipped if no Android-related changes are detected
|
||||
- [#711][711] `DynELF` has a new attribute, `heap`, which leaks the current `brk` address (heap base). This is useful for finding heap allocations with dlmalloc-derived allocators like those used by Glibc.
|
||||
- [#717][717] `sh_string` was rewritten to emit more compact and compatible strings
|
||||
+ This was achieved by embedding single-quoted non-printable literals
|
||||
+ Much more testing was added
|
||||
+ Emitted strings are no longer copy-paste compatible, but work fine with e.g. `tubes` module and the default `subprocess` module
|
||||
- [#709][709] The `adb` module now directly talks to the `adb` server process via a new module, `adb.protocol`
|
||||
+ Removes the need to shell out to `adb`
|
||||
+ Avoids version-compatibility issues with `adb` server vs. client
|
||||
- [#703][703] Added new methods to `adb`
|
||||
+ `install` - Installs an APK
|
||||
+ `uninstall` - Uninstalls a package
|
||||
+ `packages` - Lists installed packages
|
||||
- [4893819][4893819] Modified `shellcraft.sh` on all platforms to provide `argv[0]` and set `argc==1`
|
||||
+ This is needed for systems which have Busybox or other minimal shell for `/bin/sh` which does not behave well with `argc==0` or `argv[0]==NULL`.
|
||||
- [1e414af][1e414af] Added `connect()` alias for `remote()`
|
||||
+ For example, `io=connect('google.com', 80)`
|
||||
+ This also works with `tcp(...)` and `udp(...)` aliases
|
||||
- [869ec42][869ec42] Added `ssh.read()` and `ssh.write()` aiases
|
||||
- [2af55c9][2af55c9] `AdbDevice` objects exposed via e.g. `adb.devices()` now offer scoped access to all `adb` module properties
|
||||
+ It is now possible to e.g. `map(lambda d: d.process(['id']).recvall(), adb.devices())`
|
||||
|
||||
[695]: https://github.com/Gallopsled/pwntools/pull/695
|
||||
[700]: https://github.com/Gallopsled/pwntools/pull/700
|
||||
[701]: https://github.com/Gallopsled/pwntools/pull/701
|
||||
[704]: https://github.com/Gallopsled/pwntools/pull/704
|
||||
[711]: https://github.com/Gallopsled/pwntools/pull/711
|
||||
[717]: https://github.com/Gallopsled/pwntools/pull/717
|
||||
[709]: https://github.com/Gallopsled/pwntools/pull/709
|
||||
[705]: https://github.com/Gallopsled/pwntools/pull/705
|
||||
[703]: https://github.com/Gallopsled/pwntools/pull/703
|
||||
[1e414af]: https://github.com/Gallopsled/pwntools/commit/1e414afbeb3a01242f4918f111febaa63b640eb7
|
||||
[869ec42]: https://github.com/Gallopsled/pwntools/commit/869ec42082b4b98958dfe85103da9b101dde7daa
|
||||
[4893819]: https://github.com/Gallopsled/pwntools/commit/4893819b4c23182da570e2f4ea4c14d73af2c0df
|
||||
[2af55c9]: https://github.com/Gallopsled/pwntools/commit/2af55c9bc382eca23f89bc0abc7a07c075521f94
|
||||
|
||||
## 3.1.0
|
||||
|
||||
A number of smaller bugfixes and documentation tweaks.
|
||||
|
||||
## 3.0.4
|
||||
|
||||
- Fixed a bug that made 3.0.3 uninstallable (Issue: #751, PR: #752)
|
||||
|
||||
## 3.0.3
|
||||
|
||||
- Fixed some performance and usability problems with the update system (Issues:
|
||||
#723, #724, #736. PRs: #729, #738, #747).
|
||||
- Fixed a bug related to internals in pyelftools (PRs: #730, #746).
|
||||
- Fixed an issue with travis (Issue: #741, PRs: #743, #744, #745).
|
||||
|
||||
## 3.0.2
|
||||
|
||||
- Cherry-pick #695, as this was a regression-fix.
|
||||
- Added a fix for the update checker, as it would suggest prereleases as updates to stable releases.
|
||||
- Various documentation fixes.
|
||||
|
||||
## 3.0.1
|
||||
|
||||
A small bugfix release. There were a lot of references to the `master`-branch, however after 3.0.0 we use the names `stable`, `beta` and `dev` for our branches.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
This was a large release (1305 commits since 2.2.0) with a lot of bugfixes and changes. The Binjitsu project, a fork of Pwntools, was merged back into Pwntools. As such, its features are now available here.
|
||||
|
||||
As always, the best source of information on specific features is the comprehensive docs at https://pwntools.readthedocs.org.
|
||||
|
||||
This list of changes is non-complete, but covers all of the significant changes which were appropriately documented.
|
||||
|
||||
#### Android
|
||||
|
||||
Android support via a new `adb` module, `context.device`, `context.adb_host`, and `context.adb_port`.
|
||||
|
||||
#### Assembly and Shellcode
|
||||
|
||||
- Assembly module enhancements for making ELF modules from assembly or pre-assembled shellcode. See `asm.make_elf` and `asm.make_elf_from_assembly`.
|
||||
- `asm` and `shellcraft` command-line tools support flags for the new shellcode encoders
|
||||
- `asm` and `shellcraft` command-line tools support `--debug` flag for automatically launching GDB on the result
|
||||
- Added MIPS, PowerPC, and AArch64 support to the `shellcraft` module
|
||||
- Added Cyber Grand Challenge (CGC) support to the `shellcraft` module
|
||||
- Added syscall wrappers for every Linux syscall for all supported architectures to the `shellcraft` module
|
||||
+ e.g. `shellcraft.<arch>.gettimeofday`
|
||||
- (e.g. `shellcraft.i386.linux.`)
|
||||
- Added in-memory ELF loaders for most supported architectures
|
||||
+ Only supports statically-linked binaries
|
||||
+ `shellcraft.<arch>.linux.loader`
|
||||
|
||||
#### Context Module
|
||||
|
||||
- Added `context.aslr` which controls ASLR on launched processes. This works with both `process()` and `ssh.process()`, and can be specified per-process with the `aslr=` keyword argument.
|
||||
- Added `context.binary` which automatically sets all `context` variables from an ELF file.
|
||||
- Added `context.device`, `context.adb`, `context.adb_port`, and `context.adb_host` for connecting to Android devices.
|
||||
- Added `context.kernel` setting for SigReturn-Oriented-Programming (SROP).
|
||||
- Added `context.log_file` setting for sending logs to a file. This can be set with the `LOG_FILE` magic command-line option.
|
||||
- Added `context.noptrace` setting for disabling actions which require `ptrace` support. This is useful for turning all `gdb.debug` and `gdb.attach` options into no-ops, and can be set via the `NOPTRACE` magic command-line option.
|
||||
- Added `context.proxy` which hooks all connections and sends them to a SOCKS4/SOCKS5. This can be set via the `PROXY` magic command-line option.
|
||||
- Added `context.randomize` to control randommization of settings like XOR keys and register ordering (default off).
|
||||
- Added `context.terminal` for setting how to launch commands in a new terminal.
|
||||
|
||||
#### DynELF and MemLeak Module
|
||||
|
||||
- Added a `DynELF().libc` property which attempt to find the remote libc and download the ELF from LibcDB.
|
||||
- Added a `DynELF().stack` property which leaks the `__environ` pointer from libc, making it easy to leak stack addresses.
|
||||
- Added `MemLeak.String` and `MemLeak.NoNewlines` and other related helpers for handling special leakers which cannot e.g. handle newlines in the leaked addresses and which leak a C string (e.g. auto-append a `'\x00'`).
|
||||
- Enhancements for leaking speed via `MemLeak.compare` to avoid leaking an entire field if we can tell from a partial leak that it does not match what we are searching for.
|
||||
|
||||
#### Encoders Module
|
||||
|
||||
- Added a `pwnlib.encoders` module for assembled-shellcode encoders/decoders
|
||||
- Includes position-indepentent basic XOR encoders
|
||||
- Includes position-independent delta encoders
|
||||
- Includes non-position-independent alphanumeric encoders for Intel
|
||||
- Includes position-independent alphanumeric encoders for ARM/Thumb
|
||||
|
||||
#### ELF Module
|
||||
|
||||
- Added a `Core` object which can parse core-files, in order to extract / search for memory contents, and extract register states (e.g. `Core('./corefile').eax`).
|
||||
|
||||
#### Format Strings
|
||||
|
||||
- Added a basic `fmtstr` module for assisting with Format String exploitation
|
||||
|
||||
#### GDB Module
|
||||
|
||||
- Added support for debugging Android devices when `context.os=='android'`
|
||||
- Added helpers for debugging shellcode snippets with `gdb.debug_assembly()` and `gdb.debug_shellcode()`
|
||||
|
||||
#### ROP Module
|
||||
|
||||
- Added support for SigReturn via `pwnlib.rop.srop`
|
||||
+ Occurs automatically when syscalls are invoked and a function cannot be found
|
||||
+ SigReturn frames can be constructed manually with `SigreturnFrame()` objects
|
||||
- Added functional doctests for ROP and SROP
|
||||
|
||||
#### Tubes Process Module
|
||||
|
||||
- `process()` has many new options, check out the documentation
|
||||
+ `aslr` controls ASLR
|
||||
+ `setuid` can disable the effect of setuid, allowing core dumps (useful for extracting crash state via the new `Core()` object)
|
||||
+ TTY echo and control characters can be enabled via `raw` argument
|
||||
- `stdout` and `stderr` are now PTYs by default
|
||||
+ `stdin` can be set to a PTY also via setting `stdin=process.PTY`
|
||||
|
||||
#### Tubes SSH Module
|
||||
|
||||
- Massive enhancements all over
|
||||
- `ssh` objects now have a `ssh.process()` method which avoids the need to handle shell expansion via the old `ssh.run()` method
|
||||
- Files are downloaded via SFTP if available
|
||||
- New `download` and `upload` methods auto-detect whether the target is a file or directory and acts accordingly
|
||||
- Added `listen()` method alias for `listen_remote()`
|
||||
- Added `remote()` method alias for `connect_remote()`
|
||||
|
||||
#### Utilities
|
||||
|
||||
- Added `fit()` method to combine the functionality of `flat()` with the functionality of `cyclic()`
|
||||
- Added `negative()` method to negate the value of an integer via two's complement, with respect to the current integer size (`context.bytes`).
|
||||
- Added `xor_key()` method to generate an XOR key which avoids undesirable bytes over a given input.
|
||||
- Added a multi-threaded `bruteforce()` implementation, `mbruteforce()`.
|
||||
- Added `dealarm_shell()` helper to remove the effects of `alarm()` after you've popped a shell.
|
||||
|
||||
## 2.2.0
|
||||
|
||||
This was a large release with a lot of bugfixes and changes. Only the most significant
|
||||
|
||||
+10
-13
@@ -1,7 +1,5 @@
|
||||
# Contributing
|
||||
|
||||
We love pull requests!
|
||||
|
||||
Github has a great guide for contributing to open source projects:
|
||||
|
||||
- [Contributing to a project](https://guides.github.com/activities/forking/)
|
||||
@@ -11,7 +9,7 @@ Github has a great guide for contributing to open source projects:
|
||||
- [Making a Pull Request](https://guides.github.com/activities/forking/#making-a-pull-request)
|
||||
- [Huzzah!](https://guides.github.com/activities/forking/#huzzah)
|
||||
|
||||
## Pwntools Specifics
|
||||
## pwntools Specifics
|
||||
|
||||
In general, we like to keep things documented. You should add documentation to any new functionality, and update it for any changed functionality. Our docstrings use the [Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.org/en/latest/example_google.html#example-google).
|
||||
|
||||
@@ -21,18 +19,17 @@ Finally, it is probably a good idea to run the test suite locally before doing
|
||||
the pull-request to make sure everything works, however this is not a
|
||||
requirement.
|
||||
|
||||
Once you are ready to do a pull-request, you should figure out if your changes
|
||||
constitutes a new feature or a bugfix in stable or beta. If it is a bugfix in
|
||||
stable or beta, you should do the pull-request against the branch in question,
|
||||
and otherwise your pull-request should be against the dev branch.
|
||||
|
||||
Once you do the pull-request Travis CI will run the test-suite on it. Once it
|
||||
passes one of the core developers will look at your pull request, possibly
|
||||
comment on it and then hopefully merge it into master.
|
||||
comment on it and then hopefully merge it into the branch in question.
|
||||
|
||||
## Test Suite
|
||||
## Automated Testing
|
||||
|
||||
To run the test suite, you should be running Ubuntu 12.04 or 14.04, and run the following commands. **Be aware** that this will add a user to your machine, and create a public key for SSH login!
|
||||
Pull requests against Pwntools require at a minimum that no tests have been broken, and ideally each pull request will include new tests to ensure that all of the functionality works as intended.
|
||||
|
||||
```sh
|
||||
bash .travis_install.sh
|
||||
bash .travis_ssh_setup.sh
|
||||
cd docs
|
||||
pip install -r requirements.txt
|
||||
make doctest
|
||||
```
|
||||
You can find more information on testing in [TESTING.md](TESTING.md).
|
||||
@@ -0,0 +1,9 @@
|
||||
# Pwntools Issue Template
|
||||
|
||||
Thanks for contributing to Pwntools!
|
||||
|
||||
When reporting an issue, be sure that you are running the latest released version of pwntools (`pip install --upgrade pwntools`).
|
||||
|
||||
Please verify that your issue occurs on 64-bit Ubuntu 14.04. You can use the Dockerfile in `extra/docker/Dockerfile` to save time.
|
||||
|
||||
If possible, provide a proof-of-concept which demonstrates the problem. Include any binaries or scripts necessary to reproduce the issue.
|
||||
@@ -13,7 +13,7 @@ directories:
|
||||
- pwnlib/data/
|
||||
|
||||
|
||||
Copyright (c) 2015 Gallopsled and Zach Riggle
|
||||
Copyright (c) 2015 Gallopsled et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+7
-1
@@ -1 +1,7 @@
|
||||
include *.txt
|
||||
graft examples
|
||||
graft extra
|
||||
include *.md *.txt *.sh *.yml MANIFEST.in
|
||||
recursive-include docs *.rst *.png Makefile *.py *.txt
|
||||
recursive-include pwnlib *.py *.asm *.rst *.md *.txt *.sh
|
||||
recursive-include pwn *.py *.asm *.rst *.md *.txt *.sh
|
||||
recursive-exclude *.pyc
|
||||
@@ -0,0 +1,27 @@
|
||||
# Pwntools Pull Request
|
||||
|
||||
Thanks for contributing to Pwntools! Take a moment to look at [`CONTRIBUTING.md`][contributing] to make sure you're familiar with Pwntools development.
|
||||
|
||||
Please provide a high-level explanation of what this pull request is for.
|
||||
|
||||
## Testing
|
||||
|
||||
Pull Requests that introduce new code should try to add doctests for that code. See [`TESTING.md`][testing] for more information.
|
||||
|
||||
## Target Branch
|
||||
|
||||
Depending on what the PR is for, it needs to target a different branch.
|
||||
|
||||
You can always [change the branch][change] after you create the PR if it's against the wrong branch.
|
||||
|
||||
| Branch | Type of PR |
|
||||
| -------- | ---------------------------------------------------------------- |
|
||||
| `dev` | New features, and enhancements
|
||||
| `dev` | Documentation fixes and new tests
|
||||
| `stable` | Bug fixes that affect the current `stable` branch
|
||||
| `beta` | Bug fixes that affect the current `beta` branch, but not `stable`
|
||||
| `dev` | Bug fixes for code that has never been released
|
||||
|
||||
[contributing]: https://github.com/Gallopsled/pwntools/blob/dev/CONTRIBUTING.md
|
||||
[testing]: https://github.com/Gallopsled/pwntools/blob/dev/TESTING.md
|
||||
[change]: https://github.com/blog/2224-change-the-base-branch-of-a-pull-request
|
||||
@@ -1,14 +1,14 @@
|
||||

|
||||
# pwntools - CTF toolkit
|
||||

|
||||
|
||||
[](https://pwntools.readthedocs.org/en/latest)
|
||||
[](https://pwntools.readthedocs.org/en/2.2.0)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://www.gittip.com/gallopsled/)
|
||||
[](https://docs.pwntools.com/)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||
[](https://twitter.com/Gallopsled)
|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
|
||||
[](https://twitter.com/pwntools)
|
||||
[](http://choosealicense.com/licenses/mit/)
|
||||
|
||||
This is the CTF framework used by Gallopsled in every CTF.
|
||||
pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
|
||||
|
||||
```python
|
||||
from pwn import *
|
||||
@@ -20,32 +20,29 @@ r.send(asm(shellcraft.sh()))
|
||||
r.interactive()
|
||||
```
|
||||
|
||||
However we have made command-line frontends for some of the functionality
|
||||
in `pwnlib`. These are:
|
||||
# Try It Now!
|
||||
|
||||
* `asm`/`disasm`: Small wrapper for various assemblers.
|
||||
* `constgrep`: Tool for finding constants defined in header files.
|
||||
* `cyclic`: De Bruijn sequence generator and lookup tool.
|
||||
* `hex`/`unhex`: Command line tools for doing common hexing/unhexing operations.
|
||||
* `shellcraft`: Frontend to our shellcode.
|
||||
* `phd`: Replacement for `hexdump` with colors.
|
||||
You can now do a live demo of Pwntools, [right in your browser](https://demo.pwntools.com).
|
||||
|
||||
# Documentation
|
||||
Our documentation is available at [pwntools.readthedocs.org](https://pwntools.readthedocs.org/en/latest/)
|
||||
|
||||
Our documentation is available at [docs.pwntools.com](https://docs.pwntools.com/)
|
||||
|
||||
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 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 12.04 and 14.04, but most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python 2.7 is required.
|
||||
|
||||
Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
|
||||
|
||||
```sh
|
||||
pip install pwntools
|
||||
apt-get update
|
||||
apt-get install python2.7 python-pip python-dev git libssl-dev
|
||||
pip install --upgrade pwntools
|
||||
```
|
||||
|
||||
However, some of the features (ROP generation and assembling/disassembling foreign architectures) require non-Python dependencies. For more information, see the [complete installation instructions here](https://pwntools.readthedocs.org/en/latest/install.html).
|
||||
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).
|
||||
|
||||
|
||||
# Contribution
|
||||
@@ -53,7 +50,7 @@ However, some of the features (ROP generation and assembling/disassembling forei
|
||||
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 join us
|
||||
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.
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
# Testing
|
||||
|
||||
Pwntools makes extensive use of unit tests and integration tests to ensure everything is in working order, and no regressions occur.
|
||||
|
||||
## Test Suite
|
||||
|
||||
|
||||
To run the test suite, it is beste to use Ubuntu 12.04 or 14.04, and run the following commands. **Be aware** that this will add a user to the machine, and create a public key for SSH login!
|
||||
|
||||
```sh
|
||||
bash travis/install.sh
|
||||
bash travis/ssh_setup.sh
|
||||
pip install --upgrade --editable .
|
||||
PWNLIB_NOTERM=1 make -C docs doctest
|
||||
```
|
||||
|
||||
## New Tests
|
||||
|
||||
To add a new test to an existing module, just add an inline doctest. If the test needs access to an external module, add the import statement to the `testsetup` block in the corresponding file in `docs/source/<module>.rst`.
|
||||
|
||||
To add an entirely new module, create a new `module.rst` and add it to the list in `index.rst`. The best way to see if your tests are actually being run is to add an intentionally-failing test like:
|
||||
|
||||
```py
|
||||
>>> assert False
|
||||
```
|
||||
|
||||
## Example Test Module
|
||||
|
||||
The module `pwnlib.testexample` exists to demonstrate how everything is tied together. The only files which were modified to add this example module and run its tests automatically are:
|
||||
|
||||
- `pwnlib/testexample.py`
|
||||
- `docs/source/testexample.rst`
|
||||
- `docs/source/index.rst`
|
||||
|
||||
## Shellcode and ROP
|
||||
|
||||
These are both less easy to test, as they require actually executing code, or loading real binaries. In order to make the process simpler, the `runner` library was created to wrap common tasks. For an example of testing shellcode with these helpers, see [exit.asm](pwnlib/shellcraft/templates/i386/linux/exit.asm).
|
||||
|
||||
Additionally, for loading ELF files on-the-fly, the helpers `ELF.from_bytes` and `ELF.from_assembly` are available.
|
||||
@@ -44,6 +44,10 @@ help:
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
-rm -rf /tmp/user/pwn*
|
||||
-rm -rf $(HOME)/.pwntools-cache
|
||||
-rm -rf /tmp/pwn* 2>/dev/null || true
|
||||
-rm -rf build
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
||||
+54
-54
@@ -26,68 +26,68 @@ sys.path.append(os.path.abspath(os.path.join('..', 'pwnlib')))
|
||||
import version
|
||||
|
||||
def main(args):
|
||||
"""Generate a Dash docset from Sphinx source files."""
|
||||
"""Generate a Dash docset from Sphinx source files."""
|
||||
|
||||
srcdir = args.srcdir
|
||||
dstdir = args.dstdir
|
||||
name = args.name
|
||||
srcdir = args.srcdir
|
||||
dstdir = args.dstdir
|
||||
name = args.name
|
||||
|
||||
if not os.path.exists(dstdir):
|
||||
os.makedirs(dstdir)
|
||||
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") ])
|
||||
# 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,e:
|
||||
pass
|
||||
# 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,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()
|
||||
# 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 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()
|
||||
# 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
|
||||
return 0
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--name", help="docset name", default="pwntools")
|
||||
|
||||
+12
-4
@@ -1,8 +1,16 @@
|
||||
paramiko
|
||||
argparse
|
||||
mako
|
||||
pyelftools
|
||||
sphinxcontrib-napoleon
|
||||
sphinxcontrib-autoprogram
|
||||
isort
|
||||
paramiko>=1.15.2
|
||||
mako>=1.0.0
|
||||
pyelftools>=0.2.3
|
||||
capstone
|
||||
ropgadget>=5.3
|
||||
pyserial>=2.7
|
||||
requests>=2.5.1
|
||||
pip>=6.0.8
|
||||
tox>=1.8.1
|
||||
pygments>=2.0
|
||||
sphinx_rtd_theme
|
||||
doc2dash
|
||||
coveralls
|
||||
@@ -0,0 +1,13 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
adb = pwnlib.adb
|
||||
|
||||
:mod:`pwnlib.adb` --- Android Debug Bridge
|
||||
=====================================================
|
||||
|
||||
.. automodule:: pwnlib.adb.adb
|
||||
:members:
|
||||
|
||||
.. automodule:: pwnlib.adb.protocol
|
||||
:members:
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
import tempfile
|
||||
import os
|
||||
import subprocess
|
||||
from pwnlib.context import context
|
||||
from pwnlib.asm import *
|
||||
from pwnlib import shellcraft
|
||||
|
||||
@@ -14,33 +14,5 @@ pwntools comes with a handful of useful command-line utilities which serve as wr
|
||||
|
||||
.. toctree::
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.asm:parser
|
||||
:prog: asm
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.constgrep:p
|
||||
:prog: constgrep
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.cyclic:parser
|
||||
:prog: cyclic
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.disasm:parser
|
||||
:prog: disasm
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.elfdiff:p
|
||||
:prog: elfdiff
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.elfpatch:p
|
||||
:prog: elfpatch
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.hex:parser
|
||||
:prog: hex
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.phd:parser
|
||||
:prog: phd
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.shellcraft:p
|
||||
:prog: shellcraft
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.unhex:parser
|
||||
:prog: unhex
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.main:parser
|
||||
:prog: pwn
|
||||
+12
-7
@@ -22,6 +22,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
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
@@ -43,12 +45,16 @@ extensions = [
|
||||
]
|
||||
|
||||
doctest_global_setup = '''
|
||||
import pwnlib, sys
|
||||
import sys, os
|
||||
os.environ['PWNLIB_NOTERM'] = '1'
|
||||
os.environ['PWNLIB_RANDOMIZE'] = '0'
|
||||
import pwnlib
|
||||
pwnlib.context.context.reset_local()
|
||||
pwnlib.context.ContextType.defaults['log_level'] = 'ERROR'
|
||||
pwnlib.context.ContextType.defaults['randomize'] = False
|
||||
pwnlib.term.text.when = 'never'
|
||||
pwnlib.log.install_default_handler()
|
||||
pwnlib.log.console.stream = sys.stdout
|
||||
pwnlib.log.rootlogger.setLevel(1)
|
||||
'''
|
||||
|
||||
autodoc_member_order = 'alphabetical'
|
||||
@@ -69,14 +75,13 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'pwntools'
|
||||
copyright = u'2014, Gallopsled et al'
|
||||
copyright = u'2016, Gallopsled et al.'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
import pwnlib
|
||||
release = pwnlib.__version__
|
||||
version = release.rsplit('.', 1)[0]
|
||||
|
||||
@@ -212,7 +217,7 @@ latex_elements = {
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'pwntools.tex', u'pwntools Documentation',
|
||||
u'Gallopsled et al', 'manual'),
|
||||
u'2016, Gallopsled et al.', 'manual'),
|
||||
]
|
||||
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/2.7', None),
|
||||
@@ -245,7 +250,7 @@ intersphinx_mapping = {'python': ('https://docs.python.org/2.7', None),
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'pwntools', u'pwntools Documentation',
|
||||
[u'Gallopsled et al'], 1)
|
||||
[u'2016, Gallopsled et al.'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
@@ -259,7 +264,7 @@ man_pages = [
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'pwntools', u'pwntools Documentation',
|
||||
u'Gallopsled et al', 'pwntools', 'One line description of project.',
|
||||
u'', 'pwntools', 'CTF exploit writing toolkit.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
.. testsetup:: *
|
||||
|
||||
import pwnlib
|
||||
from pwnlib.context import context
|
||||
import threading, logging
|
||||
|
||||
from pwn import *
|
||||
import logging
|
||||
log = pwnlib.log.getLogger('pwnlib.context')
|
||||
|
||||
:mod:`pwnlib.context` --- Setting runtime variables
|
||||
=====================================================
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.encoders` --- Encoding Shellcode
|
||||
===============================================
|
||||
|
||||
.. automodule:: pwnlib.encoders
|
||||
:members:
|
||||
|
||||
.. automodule:: pwnlib.encoders.encoder
|
||||
:members:
|
||||
|
||||
|
||||
.. automodule:: pwnlib.encoders.amd64
|
||||
:members:
|
||||
|
||||
.. automodule:: pwnlib.encoders.arm
|
||||
:members:
|
||||
|
||||
.. automodule:: pwnlib.encoders.i386
|
||||
:members:
|
||||
|
||||
.. automodule:: pwnlib.encoders.i386.xor
|
||||
:members:
|
||||
@@ -0,0 +1,10 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
|
||||
:mod:`pwnlib.flag` --- CTF Flag Management
|
||||
==========================================
|
||||
|
||||
.. automodule:: pwnlib.flag
|
||||
:members:
|
||||
@@ -0,0 +1,10 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
import tempfile
|
||||
|
||||
:mod:`pwnlib.fmtstr` --- Format string bug exploitation tools
|
||||
=============================================================
|
||||
|
||||
.. automodule:: pwnlib.fmtstr
|
||||
:members:
|
||||
@@ -5,6 +5,20 @@ pwntools
|
||||
Written in Python, it is designed for rapid prototyping and development,
|
||||
and intended to make exploit writing as simple as possible.
|
||||
|
||||
The primary location for this documentation is at docs.pwntools.com_, which uses
|
||||
readthedocs_. It comes in three primary flavors:
|
||||
|
||||
- Stable_
|
||||
- Beta_
|
||||
- Dev_
|
||||
|
||||
.. _readthedocs: https://readthedocs.org
|
||||
.. _docs.pwntools.com: https://docs.pwntools.com
|
||||
.. _Stable: https://docs.pwntools.com/en/stable
|
||||
.. _Beta: https://docs.pwntools.com/en/beta
|
||||
.. _Dev: https://docs.pwntools.com/en/dev
|
||||
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
@@ -28,19 +42,25 @@ Each of the ``pwntools`` modules is documented here.
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
adb
|
||||
asm
|
||||
atexception
|
||||
atexit
|
||||
constants
|
||||
context
|
||||
dynelf
|
||||
encoders
|
||||
elf
|
||||
exception
|
||||
flag
|
||||
fmtstr
|
||||
gdb
|
||||
log
|
||||
memleak
|
||||
replacements
|
||||
rop
|
||||
rop/*
|
||||
runner
|
||||
shellcraft
|
||||
shellcraft/*
|
||||
term
|
||||
@@ -48,9 +68,15 @@ Each of the ``pwntools`` modules is documented here.
|
||||
tubes
|
||||
tubes/*
|
||||
ui
|
||||
update
|
||||
useragents
|
||||
util/*
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
testexample
|
||||
|
||||
.. only:: not dash
|
||||
|
||||
Indices and tables
|
||||
|
||||
@@ -20,21 +20,21 @@ following system libraries installed.
|
||||
Released Version
|
||||
-----------------
|
||||
|
||||
Pwntools is available as a ``pip`` package.
|
||||
pwntools is available as a ``pip`` package.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ apt-get install python2.7 python2.7-dev python-pip
|
||||
$ pip install pwntools
|
||||
$ pip install --upgrade pwntools
|
||||
|
||||
Latest Version
|
||||
Development
|
||||
--------------
|
||||
|
||||
Alternatively if you prefer to use the latest version from the
|
||||
repository, pip can install directly from github.
|
||||
If you are hacking on Pwntools locally, you'll want to do something like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install git+https://github.com/Gallopsled/pwntools#egg=pwntools
|
||||
$ git clone https://github.com/Gallopsled/pwntools
|
||||
$ pip install --upgrade --editable ./pwntools
|
||||
|
||||
.. _Ubuntu: https://launchpad.net/~pwntools/+archive/ubuntu/binutils
|
||||
@@ -11,7 +11,10 @@ Building `binutils` from source takes about 60 seconds on a modern 8-core machin
|
||||
|
||||
Ubuntu
|
||||
^^^^^^^^^^^^^^^^
|
||||
First, add our `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 <http://binutils.pwntools.com>`__.
|
||||
|
||||
Ubuntu Xenial (16.04) has official packages for most architectures, and does not require this step.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -58,8 +61,6 @@ OSes, ``binutils`` is simple to build by hand.
|
||||
gpg --keyserver keys.gnupg.net --recv-keys 4AE55E93
|
||||
gpg --verify binutils-$V.tar.gz.sig
|
||||
|
||||
rm -rf binutils-*
|
||||
|
||||
tar xf binutils-$V.tar.gz
|
||||
|
||||
mkdir binutils-build
|
||||
@@ -79,6 +80,6 @@ OSes, ``binutils`` is simple to build by hand.
|
||||
MAKE=gmake
|
||||
hash gmake || MAKE=make
|
||||
|
||||
$MAKE -j
|
||||
$MAKE -j clean all
|
||||
sudo $MAKE install
|
||||
|
||||
@@ -67,7 +67,7 @@ actually **interact** with processes.
|
||||
|
||||
There's even an SSH module for when you've got to SSH into a box to perform
|
||||
a local/setuid exploit with :mod:`pwnlib.tubes.ssh`. You can quickly spawn
|
||||
processes and grab the output, or spawn a process and interact iwth it like
|
||||
processes and grab the output, or spawn a process and interact with it like
|
||||
a ``process`` tube.
|
||||
|
||||
::
|
||||
@@ -170,14 +170,14 @@ But if you do, it's easy to suss out!
|
||||
5: eb f9 jmp 0x0
|
||||
|
||||
However, you shouldn't even need to write your own shellcode most of the
|
||||
time! Pwntools comes with the :mod:`pwnlib.shellcraft` module, which is
|
||||
time! pwntools comes with the :mod:`pwnlib.shellcraft` module, which is
|
||||
loaded with useful time-saving shellcodes.
|
||||
|
||||
Let's say that we want to `setreuid(getuid(), getuid())` followed by `dup`ing
|
||||
file descriptor 4 to `stdin`, `stdout`, and `stderr`, and then pop a shell!
|
||||
|
||||
>>> asm(shellcraft.setreuid() + shellcraft.dupsh(4)).encode('hex')
|
||||
'6a3158cd8089c389d96a4658cd806a045b6a0359496a3f58cd8075f86a68682f2f2f73682f62696e89e331c96a0b5899cd80'
|
||||
>>> asm(shellcraft.setreuid() + shellcraft.dupsh(4)).encode('hex') # doctest: +ELLIPSIS
|
||||
'6a3158cd80...'
|
||||
|
||||
|
||||
Misc Tools
|
||||
|
||||
+8
-5
@@ -1,11 +1,14 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwnlib.elf import *
|
||||
from pwnlib.rop import *
|
||||
from pwnlib.util.misc import which
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.rop` --- Return Oriented Programming
|
||||
=================================================
|
||||
|
||||
.. automodule:: pwnlib.rop
|
||||
:members:
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
|
||||
rop/*
|
||||
@@ -0,0 +1,9 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.rop.rop` --- Return Oriented Programming
|
||||
==========================================================
|
||||
|
||||
.. automodule:: pwnlib.rop.rop
|
||||
:members:
|
||||
@@ -0,0 +1,9 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.rop.srop` --- Sigreturn Oriented Programming
|
||||
==========================================================
|
||||
|
||||
.. automodule:: pwnlib.rop.srop
|
||||
:members:
|
||||
@@ -0,0 +1,9 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.runner` --- Running Shellcode
|
||||
===========================================
|
||||
|
||||
.. automodule:: pwnlib.runner
|
||||
:members:
|
||||
@@ -1,6 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
context.clear(arch='amd64')
|
||||
|
||||
:mod:`pwnlib.shellcraft.amd64` --- Shellcode for AMD64
|
||||
===========================================================
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
context.clear(arch='arm')
|
||||
|
||||
:mod:`pwnlib.shellcraft.arm` --- Shellcode for ARM
|
||||
===========================================================
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
context.clear(arch='i386')
|
||||
|
||||
:mod:`pwnlib.shellcraft.i386` --- Shellcode for Intel 80386
|
||||
===========================================================
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
context.clear(arch='mips')
|
||||
|
||||
:mod:`pwnlib.shellcraft.mips` --- Shellcode for MIPS
|
||||
===========================================================
|
||||
|
||||
:mod:`pwnlib.shellcraft.mips`
|
||||
-----------------------------
|
||||
|
||||
.. automodule:: pwnlib.shellcraft.mips
|
||||
:members:
|
||||
|
||||
:mod:`pwnlib.shellcraft.mips.linux`
|
||||
-----------------------------------
|
||||
|
||||
.. automodule:: pwnlib.shellcraft.mips.linux
|
||||
:members:
|
||||
@@ -1,6 +1,7 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
context.clear(arch='thumb')
|
||||
|
||||
:mod:`pwnlib.shellcraft.thumb` --- Shellcode for Thumb Mode
|
||||
===========================================================
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
.. testsetup:: *
|
||||
|
||||
import os
|
||||
from pwnlib.testexample import add
|
||||
|
||||
:mod:`pwnlib.testexample` --- Example Test Module
|
||||
==================================================
|
||||
|
||||
.. automodule:: pwnlib.testexample
|
||||
:members:
|
||||
@@ -5,7 +5,7 @@
|
||||
import time
|
||||
|
||||
:mod:`pwnlib.timeout` --- Timeout handling
|
||||
========================================
|
||||
============================================
|
||||
|
||||
.. automodule:: pwnlib.timeout
|
||||
:members:
|
||||
@@ -8,5 +8,5 @@
|
||||
.. automodule:: pwnlib.tubes.process
|
||||
|
||||
.. autoclass:: pwnlib.tubes.process.process
|
||||
:members: kill, poll, communicate
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,10 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.update import *
|
||||
|
||||
:mod:`pwnlib.update` --- Updating Pwntools
|
||||
===================================================
|
||||
|
||||
.. automodule:: pwnlib.update
|
||||
:members:
|
||||
@@ -0,0 +1,10 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
test = pwnlib.util.sh_string.test
|
||||
|
||||
:mod:`pwnlib.util.sh_string` --- Shell Expansion is Hard
|
||||
===============================================================
|
||||
|
||||
.. automodule:: pwnlib.util.sh_string
|
||||
:members:
|
||||
+1
-1
@@ -4,7 +4,7 @@ the pwntools project.
|
||||
|
||||
We have a plan to create a separate repository with examples, primarily
|
||||
exploits. Until we do so, we recommend new users to look at
|
||||
https://pwntools.readthedocs.org, as this is a better overview of our features.
|
||||
https://docs.pwntools.com, as this is a better overview of our features.
|
||||
|
||||
In no particular order the docstrings for each example:
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
from pwn import *
|
||||
|
||||
# Tell pwntools that the target is an Android device
|
||||
context.os='android'
|
||||
context.arch='aarch64' # or 'arm'
|
||||
|
||||
# Optionally, set the remote ADB server address
|
||||
context.adb_host='172.16.110.1'
|
||||
|
||||
# Wait for a device to become available
|
||||
print adb.wait_for_device()
|
||||
|
||||
# Who am I?
|
||||
print adb.process('id').recvall().strip()
|
||||
|
||||
# Interactive sessions!
|
||||
io = adb.shell()
|
||||
io.sendline('echo Hello, world; exit')
|
||||
print io.recvall().replace('\r\n', '\n').strip()
|
||||
|
||||
# Debugging!
|
||||
gdb.debug('sh').interactive()
|
||||
@@ -3,6 +3,7 @@ Example showing the interface to `pwnlib.asm.asm` and `pwnlib.shellcraft`.
|
||||
"""
|
||||
|
||||
from pwn import *
|
||||
|
||||
context(arch='i386', os='linux')
|
||||
|
||||
shellcode = shellcraft.i386_to_amd64()
|
||||
|
||||
@@ -26,4 +26,3 @@ atexit.register(r.clean_and_log)
|
||||
while True:
|
||||
line = r.recvline()
|
||||
print re.findall('^prefix (\S+)$', line)[0]
|
||||
|
||||
@@ -4,13 +4,14 @@ Script to generate README.md
|
||||
|
||||
from pwn import *
|
||||
|
||||
|
||||
out = '''# Examples
|
||||
While these examples should all work, they are not very representative of
|
||||
the pwntools project.
|
||||
|
||||
We have a plan to create a separate repository with examples, primarily
|
||||
exploits. Until we do so, we recommend new users to look at
|
||||
https://pwntools.readthedocs.org, as this is a better overview of our features.
|
||||
https://docs.pwntools.com, as this is a better overview of our features.
|
||||
|
||||
In no particular order the docstrings for each example:
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ off some proof-of-concepts.
|
||||
"""
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.term.completer import LongestPrefixCompleter, \
|
||||
PathCompleter
|
||||
from pwnlib.term.completer import LongestPrefixCompleter
|
||||
from pwnlib.term.completer import PathCompleter
|
||||
|
||||
c1 = LongestPrefixCompleter([
|
||||
'foobar',
|
||||
|
||||
@@ -3,9 +3,10 @@ Simple example showing how to use the remote
|
||||
gdb debugging features available in pwntools.
|
||||
"""
|
||||
|
||||
from pwn import *
|
||||
import getpass
|
||||
|
||||
from pwn import *
|
||||
|
||||
s = ssh(getpass.getuser(), '127.0.0.1', port = 22, keyfile = "~/.ssh/id_rsa")
|
||||
c = gdb.ssh_gdb(s, '/bin/sh', execute = '''
|
||||
p/x $pc
|
||||
|
||||
@@ -43,4 +43,4 @@ _shellcraft()
|
||||
COMPREPLY=( $(compgen -W "${_shellcraft_shellcodes}" -- ${cur}) )
|
||||
}
|
||||
|
||||
complete -F _shellcraft shellcraft
|
||||
complete -F _shellcraft pwn shellcraft
|
||||
@@ -0,0 +1,58 @@
|
||||
############################################################
|
||||
# Dockerfile to build Pwntools container
|
||||
# Based on Ubuntu
|
||||
############################################################
|
||||
|
||||
FROM ubuntu:trusty
|
||||
MAINTAINER Maintainer Gallopsled et al.
|
||||
|
||||
RUN apt-get update && apt-get install -y software-properties-common
|
||||
RUN apt-add-repository --yes ppa:pwntools/binutils
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y \
|
||||
binutils \
|
||||
binutils-aarch64-linux-gnu \
|
||||
binutils-arm-linux-gnueabihf \
|
||||
curl \
|
||||
gdb \
|
||||
gdbserver \
|
||||
gdb-multiarch \
|
||||
git \
|
||||
libc6-i386 \
|
||||
libc6-arm64-cross \
|
||||
libc6-armhf-cross \
|
||||
libc6-dev-i386 \
|
||||
libffi-dev \
|
||||
libglib2.0-dev \
|
||||
libncurses5-dev \
|
||||
libncursesw5-dev \
|
||||
ltrace \
|
||||
python-dev \
|
||||
python-pip \
|
||||
python3-pip \
|
||||
python2.7 \
|
||||
qemu \
|
||||
qemu-user-static \
|
||||
strace \
|
||||
tmux \
|
||||
wget
|
||||
RUN pip install --upgrade ipython
|
||||
RUN useradd -m zerocool
|
||||
RUN usermod -U zerocool
|
||||
|
||||
RUN mkdir -p /etc/qemu-binfmt
|
||||
RUN ln -s /usr/aarch64-linux-gnu /etc/qemu-binfmt/aarch64
|
||||
RUN ln -s /usr/arm-linux-gnueabihf /etc/qemu-binfmt/arm
|
||||
|
||||
RUN pip install --upgrade pip pycparser psutil python-ptrace
|
||||
RUN pip3 install --upgrade pip pycparser psutil python-ptrace
|
||||
|
||||
RUN pip install --upgrade git+https://github.com/Gallopsled/pwntools.git
|
||||
|
||||
RUN locale-gen en_US.UTF-8
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LANGUAGE en_US:en
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
|
||||
RUN chown -R zerocool.zerocool /home/zerocool
|
||||
RUN chsh -s /bin/bash zerocool
|
||||
@@ -0,0 +1,19 @@
|
||||
# Pwntools Mako Assembly Syntax Highlighting
|
||||
|
||||
This should work for TextMate and anything that's compatible (e.g. Sublime Text).
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
### Sublime Text
|
||||
|
||||
Copy the `tmLanguage` files into the `Packages/User` folder in your Sublime Text configuration folder.
|
||||
|
||||
These folders are located at the paths shown below. Replace `2` with `3` if you're a ST3 user.
|
||||
|
||||
- OS X: `~/Library/Application Support/Sublime Text 2`
|
||||
- Windows: `%APPDATA%\Sublime Text 2`
|
||||
- Linux: `~/.config/sublime-text-2`
|
||||
|
||||
Open a `.asm` file, and choose `View > Syntax > Open All ... > Pwntools ...`.
|
||||
@@ -0,0 +1,209 @@
|
||||
# [PackageDev] target_format: plist, ext: tmLanguage
|
||||
---
|
||||
name: Pwntools Mako ASM
|
||||
scopeName: source.pwntools
|
||||
fileTypes: ['.asm']
|
||||
uuid: 19bbf78d-4ad8-4385-bb20-5bde8df453bf
|
||||
|
||||
patterns:
|
||||
- comment: x86 instruction
|
||||
name: support.function.mnemonic.x86.all
|
||||
match: \b(?i)(v)?(aaa|aad|aam|aas|adc|add|addpd|addps|addsd|addss|addsubpd|addsubps|aesdec|aesdeclast|aesenc|aesenclast|aesimc|aeskeygenassist|and|andpd|andps|andnpd|andnps|arpl|blendpd|bmi|blendps|blendvpd|blendvps|bound|bsf|bsr|bswap|bt|btc|btr|bts|cbw|cwde|cdqe|clc|cld|cflush|clts|cmc|cmov(n?e|ge?|ae?|le?|be?|n?o|n?z)|cmp|cmppd|cmpps|cmps|cnpsb|cmpsw|cmpsd|cmpsq|cmpss|cmpxchg|cmpxchg8b|cmpxchg16b|comisd|comiss|cpuid|crc32|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtpi2ps|cvtps2dq|cvtps2pd|cvtps2pi|cvtsd2si|cvtsd2ss|cvts2sd|cvtsi2ss|cvtss2sd|cvtss2si|cvttpd2dq|cvtpd2pi|cvttps2dq|cvttps2pi|cvttps2dq|cvttps2pi|cvttsd2si|cvttss2si|cwd|cdq|cqo|daa|das|dec|div|divpd|divps|divsd|divss|dppd|dpps|emms|enter|extractps|f2xm1|fabs|fadd|faddp|fiadd|fbld|fbstp|fchs|fclex|fnclex|fcmov(n?e|ge?|ae?|le?|be?|n?o|n?z)|fcom|fcmop|fcompp|fcomi|fcomip|fucomi|fucomip|fcos|fdecstp|fdiv|fdivp|fidiv|fdivr|fdivrp|fidivr|ffree|ficom|ficomp|fild|fincstp|finit|fnint|fist|fistp|fisttp|fld|fld1|fldl2t|fldl2e|fldpi|fldlg2|fldln2|fldz|fldcw|fldenv|fmul|fmulp|fimul|fnop|fpatan|fprem|fprem1|fptan|frndint|frstor|fsave|fnsave|fscale|fsin|fsincos|fsqrt|fst|fstp|fstcw|fnstcw|fstenv|fnstenv|fsts(w?)|fnstsw|fsub|fsubp|fisub|fsubr|fsubrp|fisubr|ftst|fucom|fucomp|fucompp|fxam|fxch|fxrstor|fxsave|fxtract|fyl2x|fyl2xp1|haddpd|haddps|husbpd|hsubps|idiv|imul|in|inc|ins|insb|insw|insd|insertps|int|into|invd|invplg|invpcid|iret|iretd|iretq|lahf|lar|lddqu|ldmxcsr|lds|les|lfs|lgs|lss|lea|leave|lfence|lgdt|lidt|llgdt|lmsw|lock|lods|lodsb|lodsw|lodsd|lodsq|lsl|ltr|maskmovdqu|maskmovq|maxpd|maxps|maxsd|maxss|mfence|minpd|minps|minsd|minss|monitor|mov|movapd|movaps|movbe|movd|movq|movddup|movdqa|movdqu|movq2q|movhlps|movhpd|movhps|movlhps|movlpd|movlps|movmskpd|movmskps|movntdqa|movntdq|movnti|movntpd|movntps|movntq|movq|movq2dq|movs|movsb|movsw|movsd|movsq|movsd|movshdup|movsldup|movss|movsx|movsxd|movupd|movups|movzx|mpsadbw|mul|mulpd|mulps|mulsd|mulss|mwait|neg|not|or|orpd|orps|out|outs|outsb|outsw|outsd|pabsb|pabsw|pabsd|packsswb|packssdw|packusdw|packuswbpaddb|paddw|paddd|paddq|paddsb|paddsw|paddusb|paddusw|palignr|pand|pandn|pause|pavgb|pavgw|pblendvb|pblendw|pclmulqdq|pcmpeqb|pcmpeqw|pcmpeqd|pcmpeqq|pcmpestri|pcmpestrm|pcmptb|pcmptgw|pcmpgtd|pcmpgtq|pcmpistri|pcmpisrm|pdep|pext|pextrb|pextrd|pextrq|pextrw|phaddw|phaddd|phaddsw|phinposuw|phsubw|phsubd|phsubsw|pinsrb|pinsrd|pinsrq|pinsrw|pmaddubsw|pmadddwd|pmaxsb|pmaxsd|pmaxsw|pmaxsw|pmaxub|pmaxud|pmaxuw|pminsb|pminsd|pminsw|pminub|pminud|pminuw|pmovmskb|pmovsx|pmovzx|pmuldq|pmulhrsw|pmulhuw|pmulhw|pmulld|pmullw|pmuludw|pop|popa|popad|popcnt|popf|popfd|popfq|por|prefetch|psadbw|pshufb|pshufd|pshufhw|pshuflw|pshufw|psignb|psignw|psignd|pslldq|psllw|pslld|psllq|psraw|psrad|psrldq|psrlw|psrld|psrlq|psubb|psubw|psubd|psubq|psubsb|psubsw|psubusb|psubusw|test|ptest|punpckhbw|punpckhwd|punpckhdq|punpckhddq|punpcklbw|punpcklwd|punpckldq|punpckldqd|push|pusha|pushad|pushf|pushfd|pxor|prcl|rcr|rol|ror|rcpps|rcpss|rdfsbase|rdgsbase|rdmsr|rdpmc|rdrand|rdtsc|rdtscp|rep|repe|repz|repne|repnz|roundpd|roundps|roundsd|roundss|rsm|rsqrps|rsqrtss|sahf|sal|sar|shl|shr|sbb|scas|scasb|scasw|scasd|set(n?e|ge?|ae?|le?|be?|n?o|n?z)|sfence|sgdt|shld|shrd|shufpd|shufps|sidt|sldt|smsw|sqrtpd|sqrtps|sqrtsd|sqrtss|stc|std|stmxcsr|stos|stosb|stosw|stosd|stosq|str|sub|subpd|subps|subsd|subss|swapgs|syscall|sysenter|sysexit|sysret|teset|ucomisd|ucomiss|ud2|unpckhpd|unpckhps|unpcklpd|unpcklps|vbroadcast|vcvtph2ps|vcvtp2sph|verr|verw|vextractf128|vinsertf128|vmaskmov|vpermilpd|vpermilps|vperm2f128|vtestpd|vzeroall|vzeroupper|wait|fwait|wbinvd|wrfsbase|wrgsbase|wrmsr|xadd|xchg|xgetbv|xlat|xlatb|xor|xorpd|xorps|xrstor|xsave|xsaveopt|xsetbv|lzcnt|extrq|insertq|movntsd|movntss|vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubbpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubpd|vfnmusbps|vfnmusbsd|vfnmusbss|vbroadcastss|vbroadcastsd|vbroadcastf128|vmaskmovps|vmaskmovpd|cvt|xor|cli|sti|hlt|nop|lock|wait|enter|leave|ret|loop(n?e|n?z)?|call|j(mp|n?e|n?ge?|n?ae?|le?|be?|n?o|n?z|n?c|n?p|n?b))\b
|
||||
- comment: ARM instruction
|
||||
name: support.function.mnemonic.arm.arithmetic
|
||||
match: >
|
||||
(?x)\b((?i)
|
||||
( (bf(c|i)|(u|s)bfx|(u|s)xta?(h|b)?)
|
||||
| (v(add|cvt|sub|mov|trn|cmp|div|qdmulh|mrs|mul|ld1|qadd|qshrun|st[1234]|addw|mull|mlal|rshrn|swp|qmovun)|qmovun)(\.([isup]?8|[isupf]?16|[isuf]?32|[isu]?64))*
|
||||
| (mul|mla|mull|smlabb)
|
||||
| (mov(w|t))
|
||||
| rev(8|16)?
|
||||
| (pld|adr|adrl|vswp)
|
||||
| bkpt
|
||||
)?(?-i))?\b
|
||||
- comment: ARM instruction
|
||||
name: support.function.mnemonic.arm.memory
|
||||
match: >
|
||||
(?x)\b((?i)(
|
||||
swi|svc|wfi|
|
||||
dmb | clrex | dsb | isb |
|
||||
v(ldr|str|push|pop) |
|
||||
(push|pop) |
|
||||
(st|ld)(
|
||||
p |
|
||||
r(ex|s?(h|b)|d)? |
|
||||
m(
|
||||
(f|e)(d|a) |
|
||||
(d|i)(b|a)
|
||||
)?
|
||||
) |
|
||||
b(l|x|lx|lr|r)? |
|
||||
(i|e)?ret|
|
||||
b\.(eq|ne|hs|cs|lo|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|nv)+ |
|
||||
(c|t)?bn?z|
|
||||
)+(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))\b
|
||||
- comment: ARM instruction
|
||||
name: meta.preprocessor.c.include
|
||||
match: >
|
||||
\b((?i)(def(b|w|s)|equ|(include|get)(\s+([a-zA-Z_]+[0-9a-zA-Z_]*|[0-9]+[a-zA-Z_]+[0-9a-zA-Z_]*?)\.s)?)?(?-i))\b
|
||||
- comment: ARM instruction
|
||||
name: comment.nop
|
||||
match: >
|
||||
\b((?i)nop(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))?\b
|
||||
- comment: Comment Block
|
||||
begin: /\*
|
||||
end: \*/
|
||||
name: comment.block
|
||||
- comment: Directive
|
||||
name: keyword.control.directive
|
||||
match: \.(?i)(globl|global|macro|endm|purgem|if|elseif|else|endif|section|text|arm|align|balign|irp|rept|endr|req|unreq|error|short|func|endfunc|hidden|type|fpu|arch|code|altmacro|object_arch|word|int|string)(?-i)\b
|
||||
- comment: ARM register
|
||||
name: storage.other.register.arm
|
||||
match: \b((?i)\$?([xw][0-9]|[xw]1[0-9]||[xw]2[0-9]|[wx]30|wzr|xzr|wsp|fpsr|fpcr|[rcp]1[0-5]|[rcp][0-9]|a[1-4]|v[1-8]|sl|sb|fp|ip|sp|lr|(c|s)psr(_c)?|pc|[sd]3[0-1]|[sd][12][0-9]|[sd][0-9]|fpsid|fpscr|fpexc|q3[0-1]|q2[0-9]|q1[0-9]|q[0-9]|APSR_nzcv|sy)!?(?-i))?\b
|
||||
- comment: x86 register
|
||||
name: storage.other.register.x86
|
||||
match: \b((?i)(al|ah|ax|eax|rax|bl|bh|bx|ebx|rbx|cl|ch|cx|ecx|rcx|dl|dh|dx|edx|rdx|sil|si|esi|rsi|di|di|edi|rdi|bpl|bp|ebp|rbp|sp|esp|rsp|cs|ds|ss|es|fs|gs|ip|eip|rip|flags|eflags|rflags|r8|r9|r10|r11|r12|r13|r14|r15|r8d|r9d|r10d|r11d|r12d|r13d|r14d|r15d|r8w|r9w|r10w|r11w|r12w|r13w|r14w|r15w|r8l|r9l|r10l|r11l|r12l|r13l|r14l|r15l|st0|st1|st2|st3|st4|st5|st6|st7|mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15|xmm16|xmm17|xmm18|xmm19|xmm20|xmm21|xmm22|xmm23|xmm24|xmm25|xmm26|xmm27|xmm28|xmm29|xmm30|xmm31|ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15|ymm16|ymm17|ymm18|ymm19|ymm20|ymm21|ymm22|ymm23|ymm24|ymm25|ymm26|ymm27|ymm28|ymm29|ymm30|ymm31|zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31|cr0|cr2|cr3|cr4|gdtr|ldtr|idtr|dr0|dr1|dr2|dr3|dr4|dr5|dr6|dr7|msr)!?(?-i))?\b
|
||||
- comment: SPARC register
|
||||
name: storage.other.register.sparc
|
||||
match: \b((?i)\$?([gloi][0-9])!?(?-i))?\b
|
||||
- comment: MIPS register
|
||||
name: storage.other.register.mips
|
||||
match: \b((?i)\$?(r[0-3][0-9]|v[0-2]|a[0-4]|t[0-8]|s[0-9]|t([89]|10|k[0-2]))!?(?-i))?\b
|
||||
- comment: Numeric Hex
|
||||
name: constant.numeric.hex
|
||||
match: (\b|\s+)(\#)?-?(0x|&)[0-9a-fA-F_]+\b
|
||||
- comment: Numeric Literal
|
||||
name: constant.numeric.literal
|
||||
match: (\b|\s+)\#-?[0-9a-zA-Z_]+\b
|
||||
- comment: Numeric Decimal
|
||||
name: constant.numeric.dec
|
||||
match: (\b|\s+)[0-9]+\b
|
||||
- comment: Label
|
||||
name: entity.name.tag
|
||||
match: ([\w${}]+[:])
|
||||
- comment: Inline Python
|
||||
name: pwntools.raw.block.python
|
||||
begin: (<%\s)
|
||||
end: (%>)
|
||||
beginCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
endCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
patterns:
|
||||
- {include: source.python}
|
||||
- comment: Inline Docstring
|
||||
begin: (<%(\S+)>)
|
||||
end: (</%(\2)>)
|
||||
beginCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
endCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
patterns:
|
||||
- {include: comment.block}
|
||||
- comment: Mako Tag
|
||||
name: source.mako.tag
|
||||
begin: (<%\w+\s)
|
||||
end: (/>)
|
||||
beginCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
endCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
patterns:
|
||||
- {include: comment.block}
|
||||
- comment: Mako Substitution
|
||||
name: source.mako.expression
|
||||
begin: (\${)
|
||||
end: (})
|
||||
beginCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
endCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
patterns:
|
||||
- {include: source.python}
|
||||
- comment: Mako Comment
|
||||
match: (^##(.*)$)
|
||||
name: comment.line.mako
|
||||
- comment: Mako Directive
|
||||
begin: ^\s*(%)(\s*((endfor)|(endif)|(endwhile)))?
|
||||
end: $
|
||||
beginCaptures:
|
||||
'1': {name: 'keyword.control'}
|
||||
'2': {name: 'keyword.control'}
|
||||
patterns:
|
||||
- {include: source.python}
|
||||
name: source.doc.python.mako.controlline
|
||||
|
||||
# <key>begin</key>
|
||||
# <string>^(#)</string>
|
||||
# <key>beginCaptures</key>
|
||||
# <dict>
|
||||
# <key>1</key>
|
||||
# <dict>
|
||||
# <key>name</key>
|
||||
# <string>keyword.control</string>
|
||||
# </dict>
|
||||
# </dict>
|
||||
# <key>end</key>
|
||||
# <string>$</string>
|
||||
# <key>name</key>
|
||||
# <string>source.python.mako.line</string>
|
||||
# <key>patterns</key>
|
||||
# <array>
|
||||
# <dict>
|
||||
# <key>include</key>
|
||||
# <string>comment.block</string>
|
||||
# </dict>
|
||||
# </array>
|
||||
# </dict>
|
||||
|
||||
# <key>begin</key>
|
||||
# <string>^\s*(%)(\s*((endfor)|(endif)|(endwhile)))?</string>
|
||||
# <key>beginCaptures</key>
|
||||
# <dict>
|
||||
# <key>1</key>
|
||||
# <dict>
|
||||
# <key>name</key>
|
||||
# <string>keyword.control</string>
|
||||
# </dict>
|
||||
# <key>2</key>
|
||||
# <dict>
|
||||
# <key>name</key>
|
||||
# <string>keyword.control</string>
|
||||
# </dict>
|
||||
# </dict>
|
||||
|
||||
|
||||
# <key>begin</key>
|
||||
# <string>(<%\s)</string>
|
||||
# <key>captures</key>
|
||||
# <dict>
|
||||
# <key>1</key>
|
||||
# <dict>
|
||||
# <key>name</key>
|
||||
# <string>keyword.control</string>
|
||||
# </dict>
|
||||
# </dict>
|
||||
# <key>end</key>
|
||||
# <string>(%>)</string>
|
||||
# <key>name</key>
|
||||
# <string>source.mako.substitution</string>
|
||||
# <key>patterns</key>
|
||||
# <array>
|
||||
# <dict>
|
||||
# <key>include</key>
|
||||
# <string>source.python</string>
|
||||
# </dict>
|
||||
# </array>
|
||||
|
||||
# match: "(
|
||||
# (bf(c|i)|(u|s)bfx|(u|s)xta?(h|b)?) |
|
||||
# (v(add|cvt|sub|mov|trn|cmp|div|qdmulh|mrs|mul|ld1|qadd|qshrun|st[1234]|addw|mull|mlal|rshrn|swp|qmovun)|qmovun)(\.([isup]?8|[isupf]?16|[isuf]?32|[isu]?64))* |
|
||||
# (and|m(rs|sr)|eor|sub|rsb|add|adc|sbc|rsc|tst|teq|cmp|cmn|orr|mov|bic|mvn |
|
||||
# (neg) |
|
||||
# (lsr|lsl|ror|asr)
|
||||
# )s? |
|
||||
# (mul|mla|mull|smlabb) |
|
||||
# (mov(w|t)) |
|
||||
# rev(8|16)? |
|
||||
# (pld|adr|adrl|vswp)
|
||||
# )
|
||||
@@ -0,0 +1,337 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>.asm</string>
|
||||
</array>
|
||||
<key>name</key>
|
||||
<string>Pwntools Mako ASM</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>x86 instruction</string>
|
||||
<key>match</key>
|
||||
<string>\b(?i)(v)?(aaa|aad|aam|aas|adc|add|addpd|addps|addsd|addss|addsubpd|addsubps|aesdec|aesdeclast|aesenc|aesenclast|aesimc|aeskeygenassist|and|andpd|andps|andnpd|andnps|arpl|blendpd|bmi|blendps|blendvpd|blendvps|bound|bsf|bsr|bswap|bt|btc|btr|bts|cbw|cwde|cdqe|clc|cld|cflush|clts|cmc|cmov(n?e|ge?|ae?|le?|be?|n?o|n?z)|cmp|cmppd|cmpps|cmps|cnpsb|cmpsw|cmpsd|cmpsq|cmpss|cmpxchg|cmpxchg8b|cmpxchg16b|comisd|comiss|cpuid|crc32|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtpi2ps|cvtps2dq|cvtps2pd|cvtps2pi|cvtsd2si|cvtsd2ss|cvts2sd|cvtsi2ss|cvtss2sd|cvtss2si|cvttpd2dq|cvtpd2pi|cvttps2dq|cvttps2pi|cvttps2dq|cvttps2pi|cvttsd2si|cvttss2si|cwd|cdq|cqo|daa|das|dec|div|divpd|divps|divsd|divss|dppd|dpps|emms|enter|extractps|f2xm1|fabs|fadd|faddp|fiadd|fbld|fbstp|fchs|fclex|fnclex|fcmov(n?e|ge?|ae?|le?|be?|n?o|n?z)|fcom|fcmop|fcompp|fcomi|fcomip|fucomi|fucomip|fcos|fdecstp|fdiv|fdivp|fidiv|fdivr|fdivrp|fidivr|ffree|ficom|ficomp|fild|fincstp|finit|fnint|fist|fistp|fisttp|fld|fld1|fldl2t|fldl2e|fldpi|fldlg2|fldln2|fldz|fldcw|fldenv|fmul|fmulp|fimul|fnop|fpatan|fprem|fprem1|fptan|frndint|frstor|fsave|fnsave|fscale|fsin|fsincos|fsqrt|fst|fstp|fstcw|fnstcw|fstenv|fnstenv|fsts(w?)|fnstsw|fsub|fsubp|fisub|fsubr|fsubrp|fisubr|ftst|fucom|fucomp|fucompp|fxam|fxch|fxrstor|fxsave|fxtract|fyl2x|fyl2xp1|haddpd|haddps|husbpd|hsubps|idiv|imul|in|inc|ins|insb|insw|insd|insertps|int|into|invd|invplg|invpcid|iret|iretd|iretq|lahf|lar|lddqu|ldmxcsr|lds|les|lfs|lgs|lss|lea|leave|lfence|lgdt|lidt|llgdt|lmsw|lock|lods|lodsb|lodsw|lodsd|lodsq|lsl|ltr|maskmovdqu|maskmovq|maxpd|maxps|maxsd|maxss|mfence|minpd|minps|minsd|minss|monitor|mov|movapd|movaps|movbe|movd|movq|movddup|movdqa|movdqu|movq2q|movhlps|movhpd|movhps|movlhps|movlpd|movlps|movmskpd|movmskps|movntdqa|movntdq|movnti|movntpd|movntps|movntq|movq|movq2dq|movs|movsb|movsw|movsd|movsq|movsd|movshdup|movsldup|movss|movsx|movsxd|movupd|movups|movzx|mpsadbw|mul|mulpd|mulps|mulsd|mulss|mwait|neg|not|or|orpd|orps|out|outs|outsb|outsw|outsd|pabsb|pabsw|pabsd|packsswb|packssdw|packusdw|packuswbpaddb|paddw|paddd|paddq|paddsb|paddsw|paddusb|paddusw|palignr|pand|pandn|pause|pavgb|pavgw|pblendvb|pblendw|pclmulqdq|pcmpeqb|pcmpeqw|pcmpeqd|pcmpeqq|pcmpestri|pcmpestrm|pcmptb|pcmptgw|pcmpgtd|pcmpgtq|pcmpistri|pcmpisrm|pdep|pext|pextrb|pextrd|pextrq|pextrw|phaddw|phaddd|phaddsw|phinposuw|phsubw|phsubd|phsubsw|pinsrb|pinsrd|pinsrq|pinsrw|pmaddubsw|pmadddwd|pmaxsb|pmaxsd|pmaxsw|pmaxsw|pmaxub|pmaxud|pmaxuw|pminsb|pminsd|pminsw|pminub|pminud|pminuw|pmovmskb|pmovsx|pmovzx|pmuldq|pmulhrsw|pmulhuw|pmulhw|pmulld|pmullw|pmuludw|pop|popa|popad|popcnt|popf|popfd|popfq|por|prefetch|psadbw|pshufb|pshufd|pshufhw|pshuflw|pshufw|psignb|psignw|psignd|pslldq|psllw|pslld|psllq|psraw|psrad|psrldq|psrlw|psrld|psrlq|psubb|psubw|psubd|psubq|psubsb|psubsw|psubusb|psubusw|test|ptest|punpckhbw|punpckhwd|punpckhdq|punpckhddq|punpcklbw|punpcklwd|punpckldq|punpckldqd|push|pusha|pushad|pushf|pushfd|pxor|prcl|rcr|rol|ror|rcpps|rcpss|rdfsbase|rdgsbase|rdmsr|rdpmc|rdrand|rdtsc|rdtscp|rep|repe|repz|repne|repnz|roundpd|roundps|roundsd|roundss|rsm|rsqrps|rsqrtss|sahf|sal|sar|shl|shr|sbb|scas|scasb|scasw|scasd|set(n?e|ge?|ae?|le?|be?|n?o|n?z)|sfence|sgdt|shld|shrd|shufpd|shufps|sidt|sldt|smsw|sqrtpd|sqrtps|sqrtsd|sqrtss|stc|std|stmxcsr|stos|stosb|stosw|stosd|stosq|str|sub|subpd|subps|subsd|subss|swapgs|syscall|sysenter|sysexit|sysret|teset|ucomisd|ucomiss|ud2|unpckhpd|unpckhps|unpcklpd|unpcklps|vbroadcast|vcvtph2ps|vcvtp2sph|verr|verw|vextractf128|vinsertf128|vmaskmov|vpermilpd|vpermilps|vperm2f128|vtestpd|vzeroall|vzeroupper|wait|fwait|wbinvd|wrfsbase|wrgsbase|wrmsr|xadd|xchg|xgetbv|xlat|xlatb|xor|xorpd|xorps|xrstor|xsave|xsaveopt|xsetbv|lzcnt|extrq|insertq|movntsd|movntss|vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubbpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubpd|vfnmusbps|vfnmusbsd|vfnmusbss|vbroadcastss|vbroadcastsd|vbroadcastf128|vmaskmovps|vmaskmovpd|cvt|xor|cli|sti|hlt|nop|lock|wait|enter|leave|ret|loop(n?e|n?z)?|call|j(mp|n?e|n?ge?|n?ae?|le?|be?|n?o|n?z|n?c|n?p|n?b))\b</string>
|
||||
<key>name</key>
|
||||
<string>support.function.mnemonic.x86.all</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>ARM instruction</string>
|
||||
<key>match</key>
|
||||
<string>(?x)\b((?i) ( (bf(c|i)|(u|s)bfx|(u|s)xta?(h|b)?)
|
||||
| (v(add|cvt|sub|mov|trn|cmp|div|qdmulh|mrs|mul|ld1|qadd|qshrun|st[1234]|addw|mull|mlal|rshrn|swp|qmovun)|qmovun)(\.([isup]?8|[isupf]?16|[isuf]?32|[isu]?64))*
|
||||
| (mul|mla|mull|smlabb)
|
||||
| (mov(w|t))
|
||||
| rev(8|16)?
|
||||
| (pld|adr|adrl|vswp)
|
||||
| bkpt
|
||||
)?(?-i))?\b
|
||||
</string>
|
||||
<key>name</key>
|
||||
<string>support.function.mnemonic.arm.arithmetic</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>ARM instruction</string>
|
||||
<key>match</key>
|
||||
<string>(?x)\b((?i)(
|
||||
swi|svc|wfi|
|
||||
dmb | clrex | dsb | isb |
|
||||
v(ldr|str|push|pop) |
|
||||
(push|pop) |
|
||||
(st|ld)(
|
||||
p |
|
||||
r(ex|s?(h|b)|d)? |
|
||||
m(
|
||||
(f|e)(d|a) |
|
||||
(d|i)(b|a)
|
||||
)?
|
||||
) |
|
||||
b(l|x|lx|lr|r)? |
|
||||
(i|e)?ret|
|
||||
b\.(eq|ne|hs|cs|lo|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|nv)+ |
|
||||
(c|t)?bn?z|
|
||||
)+(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))\b
|
||||
</string>
|
||||
<key>name</key>
|
||||
<string>support.function.mnemonic.arm.memory</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>ARM instruction</string>
|
||||
<key>match</key>
|
||||
<string>\b((?i)(def(b|w|s)|equ|(include|get)(\s+([a-zA-Z_]+[0-9a-zA-Z_]*|[0-9]+[a-zA-Z_]+[0-9a-zA-Z_]*?)\.s)?)?(?-i))\b
|
||||
</string>
|
||||
<key>name</key>
|
||||
<string>meta.preprocessor.c.include</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>ARM instruction</string>
|
||||
<key>match</key>
|
||||
<string>\b((?i)nop(ne|eq|cs|hs|cc|lo|mi|pl|vs|vc|hi|ls|lt|le|gt|ge|al)?(?-i))?\b
|
||||
</string>
|
||||
<key>name</key>
|
||||
<string>comment.nop</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>/\*</string>
|
||||
<key>comment</key>
|
||||
<string>Comment Block</string>
|
||||
<key>end</key>
|
||||
<string>\*/</string>
|
||||
<key>name</key>
|
||||
<string>comment.block</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Directive</string>
|
||||
<key>match</key>
|
||||
<string>\.(?i)(globl|global|macro|endm|purgem|if|elseif|else|endif|section|text|arm|align|balign|irp|rept|endr|req|unreq|error|short|func|endfunc|hidden|type|fpu|arch|code|altmacro|object_arch|word|int|string)(?-i)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.control.directive</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>ARM register</string>
|
||||
<key>match</key>
|
||||
<string>\b((?i)\$?([xw][0-9]|[xw]1[0-9]||[xw]2[0-9]|[wx]30|wzr|xzr|wsp|fpsr|fpcr|[rcp]1[0-5]|[rcp][0-9]|a[1-4]|v[1-8]|sl|sb|fp|ip|sp|lr|(c|s)psr(_c)?|pc|[sd]3[0-1]|[sd][12][0-9]|[sd][0-9]|fpsid|fpscr|fpexc|q3[0-1]|q2[0-9]|q1[0-9]|q[0-9]|APSR_nzcv|sy)!?(?-i))?\b</string>
|
||||
<key>name</key>
|
||||
<string>storage.other.register.arm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>x86 register</string>
|
||||
<key>match</key>
|
||||
<string>\b((?i)(al|ah|ax|eax|rax|bl|bh|bx|ebx|rbx|cl|ch|cx|ecx|rcx|dl|dh|dx|edx|rdx|sil|si|esi|rsi|di|di|edi|rdi|bpl|bp|ebp|rbp|sp|esp|rsp|cs|ds|ss|es|fs|gs|ip|eip|rip|flags|eflags|rflags|r8|r9|r10|r11|r12|r13|r14|r15|r8d|r9d|r10d|r11d|r12d|r13d|r14d|r15d|r8w|r9w|r10w|r11w|r12w|r13w|r14w|r15w|r8l|r9l|r10l|r11l|r12l|r13l|r14l|r15l|st0|st1|st2|st3|st4|st5|st6|st7|mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15|xmm16|xmm17|xmm18|xmm19|xmm20|xmm21|xmm22|xmm23|xmm24|xmm25|xmm26|xmm27|xmm28|xmm29|xmm30|xmm31|ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15|ymm16|ymm17|ymm18|ymm19|ymm20|ymm21|ymm22|ymm23|ymm24|ymm25|ymm26|ymm27|ymm28|ymm29|ymm30|ymm31|zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31|cr0|cr2|cr3|cr4|gdtr|ldtr|idtr|dr0|dr1|dr2|dr3|dr4|dr5|dr6|dr7|msr)!?(?-i))?\b</string>
|
||||
<key>name</key>
|
||||
<string>storage.other.register.x86</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>SPARC register</string>
|
||||
<key>match</key>
|
||||
<string>\b((?i)\$?([gloi][0-9])!?(?-i))?\b</string>
|
||||
<key>name</key>
|
||||
<string>storage.other.register.sparc</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>MIPS register</string>
|
||||
<key>match</key>
|
||||
<string>\b((?i)\$?(r[0-3][0-9]|v[0-2]|a[0-4]|t[0-8]|s[0-9]|t([89]|10|k[0-2]))!?(?-i))?\b</string>
|
||||
<key>name</key>
|
||||
<string>storage.other.register.mips</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Numeric Hex</string>
|
||||
<key>match</key>
|
||||
<string>(\b|\s+)(\#)?-?(0x|&amp;)[0-9a-fA-F_]+\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.hex</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Numeric Literal</string>
|
||||
<key>match</key>
|
||||
<string>(\b|\s+)\#-?[0-9a-zA-Z_]+\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.literal</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Numeric Decimal</string>
|
||||
<key>match</key>
|
||||
<string>(\b|\s+)[0-9]+\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.dec</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Label</string>
|
||||
<key>match</key>
|
||||
<string>([\w${}]+[:])</string>
|
||||
<key>name</key>
|
||||
<string>entity.name.tag</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(<%\s)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>Inline Python</string>
|
||||
<key>end</key>
|
||||
<string>(%>)</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>pwntools.raw.block.python</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>source.python</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(<%(\S+)>)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>Inline Docstring</string>
|
||||
<key>end</key>
|
||||
<string>(</%(\2)>)</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>comment.block</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(<%\w+\s)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>Mako Tag</string>
|
||||
<key>end</key>
|
||||
<string>(/>)</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>source.mako.tag</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>comment.block</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(\${)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>Mako Substitution</string>
|
||||
<key>end</key>
|
||||
<string>(})</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>source.mako.expression</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>source.python</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Mako Comment</string>
|
||||
<key>match</key>
|
||||
<string>(^##(.*)$)</string>
|
||||
<key>name</key>
|
||||
<string>comment.line.mako</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>^\s*(%)(\s*((endfor)|(endif)|(endwhile)))?</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>Mako Directive</string>
|
||||
<key>end</key>
|
||||
<string>$</string>
|
||||
<key>name</key>
|
||||
<string>source.doc.python.mako.controlline</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>source.python</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>source.pwntools</string>
|
||||
<key>uuid</key>
|
||||
<string>19bbf78d-4ad8-4385-bb20-5bde8df453bf</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
+10
-113
@@ -1,119 +1,16 @@
|
||||
# Promote useful stuff to toplevel
|
||||
from .toplevel import *
|
||||
|
||||
pwnlib.args.initialize()
|
||||
pwnlib.log.install_default_handler()
|
||||
|
||||
# look for special args in argv
|
||||
def closure():
|
||||
term_mode = True
|
||||
import sys
|
||||
if not hasattr(sys, 'argv'):
|
||||
return
|
||||
import string, collections
|
||||
global args
|
||||
args = collections.defaultdict(str)
|
||||
def isident(s):
|
||||
first = string.uppercase + '_'
|
||||
body = string.digits + first
|
||||
if not s:
|
||||
return False
|
||||
if s[0] not in first:
|
||||
return False
|
||||
if not all(c in body for c in s[1:]):
|
||||
return False
|
||||
return True
|
||||
def asbool(s):
|
||||
if s.lower() == 'true':
|
||||
return True
|
||||
elif s.lower() == 'false':
|
||||
return False
|
||||
elif s.isdigit():
|
||||
return bool(int(s))
|
||||
else:
|
||||
raise ValueError('must be integer or boolean')
|
||||
# parse environtment variables
|
||||
for k, v in os.environ.items():
|
||||
if not k.startswith('PWNLIB_'):
|
||||
continue
|
||||
k = k[7:]
|
||||
if k == 'DEBUG':
|
||||
if asbool(v):
|
||||
context.log_level = 'DEBUG'
|
||||
elif k == 'SILENT':
|
||||
if asbool(v):
|
||||
context.log_level = 'ERROR'
|
||||
elif k == 'NOTERM':
|
||||
if asbool(v):
|
||||
term_mode = False
|
||||
elif isident(k):
|
||||
args[k] = v
|
||||
# parse command line
|
||||
# save a copy of argv for the log file header (see below)
|
||||
argv = sys.argv[:]
|
||||
for arg in argv:
|
||||
if arg == 'DEBUG':
|
||||
sys.argv.remove(arg)
|
||||
context.log_level = 'DEBUG'
|
||||
elif arg == 'SILENT':
|
||||
sys.argv.remove(arg)
|
||||
context.log_level = 'ERROR'
|
||||
elif arg == 'NOTERM':
|
||||
term_mode = False
|
||||
elif arg.find('=') > 0:
|
||||
k, v = arg.split('=', 1)
|
||||
if not isident(k):
|
||||
continue
|
||||
sys.argv.remove(arg)
|
||||
args[k] = v
|
||||
if 'LOG_LEVEL' in args:
|
||||
context.log_level = args['LOG_LEVEL']
|
||||
if 'LOG_FILE' in args:
|
||||
# install a file logger
|
||||
import logging, time
|
||||
modes = ('w', 'wb', 'a', 'ab')
|
||||
filename = args['LOG_FILE']
|
||||
mode = 'a'
|
||||
# check if mode was specified as "[filename],[mode]"
|
||||
if ',' in filename:
|
||||
filename_, mode_ = filename.rsplit(',', 1)
|
||||
if mode in modes:
|
||||
filename = filename_
|
||||
mode = mode_
|
||||
# ISO 8601
|
||||
dfmt = '%Y-%m-%dT%H:%M:%S'
|
||||
# write a "header" to the file, which makes it easier to find the start
|
||||
# of a session
|
||||
with open(filename, mode) as fd:
|
||||
lines = [
|
||||
'=' * 78,
|
||||
' Started at %s ' % time.strftime(dfmt),
|
||||
' sys.argv = [',
|
||||
]
|
||||
for arg in argv:
|
||||
lines.append(' %r,' % arg)
|
||||
lines.append(' ]')
|
||||
lines.append('=' * 78)
|
||||
for line in lines:
|
||||
fd.write('=%s=\n' % line.ljust(78))
|
||||
# if the mode was 'w' or 'wb' we need to change it to 'a'/'ab' now so
|
||||
# the logging module wont overwrite the header
|
||||
mode = mode.replace('w', 'a')
|
||||
# create a formatter and a handler and install them for the pwnlib root
|
||||
# logger (i.e. 'pwnlib')
|
||||
handler = logging.FileHandler(filename, mode)
|
||||
fmt = '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
|
||||
formatter = logging.Formatter(fmt, dfmt)
|
||||
handler.setFormatter(formatter)
|
||||
logging.root.addHandler(handler)
|
||||
# put the terminal in rawmode unless NOTERM was specified
|
||||
if term_mode:
|
||||
term.init()
|
||||
# install a log handler and turn logging all the way up
|
||||
import pwnlib.log as log
|
||||
import logging
|
||||
log.rootlogger.setLevel(logging.DEBUG)
|
||||
log.install_default_handler()
|
||||
log = pwnlib.log.getLogger('pwnlib.exploit')
|
||||
args = pwnlib.args.args
|
||||
|
||||
closure()
|
||||
del closure
|
||||
if not platform.architecture()[0].startswith('64'):
|
||||
"""Determines if the current Python interpreter is supported by Pwntools.
|
||||
|
||||
log = getLogger('pwnlib.exploit')
|
||||
See Gallopsled/pwntools#518 for more information."""
|
||||
log.warn_once('Pwntools does not support 32-bit Python. Use a 64-bit release.')
|
||||
|
||||
pwnlib.update.check_automatically()
|
||||
+26
-10
@@ -1,9 +1,12 @@
|
||||
# Promote these modules, so that "from pwn import *" will let you access them
|
||||
# Get all the modules from pwnlib
|
||||
import collections
|
||||
import logging
|
||||
import math
|
||||
import operator
|
||||
import os
|
||||
import re
|
||||
import socks
|
||||
import signal
|
||||
import string
|
||||
import struct
|
||||
import subprocess
|
||||
@@ -12,31 +15,33 @@ import tempfile
|
||||
import threading
|
||||
import time
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
import pwnlib
|
||||
|
||||
# Get all the modules from pwnlib
|
||||
from pwnlib import *
|
||||
|
||||
# Promote functions from these modules to toplevel
|
||||
from pwnlib.asm import asm
|
||||
from pwnlib.asm import cpp
|
||||
from pwnlib.asm import disasm
|
||||
from pwnlib.asm import *
|
||||
from pwnlib.context import Thread
|
||||
from pwnlib.context import context
|
||||
from pwnlib.dynelf import DynELF
|
||||
from pwnlib.encoders import *
|
||||
from pwnlib.elf import Core
|
||||
from pwnlib.elf import ELF
|
||||
from pwnlib.elf import load
|
||||
from pwnlib.encoders import *
|
||||
from pwnlib.exception import PwnlibException
|
||||
from pwnlib.fmtstr import FmtStr
|
||||
from pwnlib.flag import *
|
||||
from pwnlib.fmtstr import FmtStr, fmtstr_payload
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.memleak import MemLeak
|
||||
from pwnlib.regsort import *
|
||||
from pwnlib.replacements import *
|
||||
from pwnlib.rop import ROP
|
||||
from pwnlib.rop.srop import SigreturnFrame
|
||||
from pwnlib.runner import *
|
||||
from pwnlib.timeout import Timeout
|
||||
from pwnlib.tubes.listen import listen
|
||||
from pwnlib.tubes.process import process
|
||||
from pwnlib.tubes.remote import remote
|
||||
from pwnlib.tubes.remote import remote, tcp, udp, connect
|
||||
from pwnlib.tubes.serialtube import serialtube
|
||||
from pwnlib.tubes.ssh import ssh
|
||||
from pwnlib.tubes.tube import tube
|
||||
@@ -48,14 +53,18 @@ from pwnlib.util import proc
|
||||
from pwnlib.util import safeeval
|
||||
from pwnlib.util.cyclic import *
|
||||
from pwnlib.util.fiddling import *
|
||||
from pwnlib.util.getdents import *
|
||||
from pwnlib.util.hashes import *
|
||||
from pwnlib.util.lists import *
|
||||
from pwnlib.util.misc import *
|
||||
from pwnlib.util.packing import *
|
||||
from pwnlib.util.proc import pidof
|
||||
from pwnlib.util.sh_string import sh_string, sh_prepare, sh_command_with
|
||||
from pwnlib.util.splash import *
|
||||
from pwnlib.util.web import *
|
||||
|
||||
# Promote these modules, so that "from pwn import *" will let you access them
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
@@ -65,3 +74,10 @@ try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
|
||||
error = log.error
|
||||
warning = log.warning
|
||||
warn = log.warning
|
||||
info = log.info
|
||||
debug = log.debug
|
||||
success = log.success
|
||||
+6
-1
@@ -5,6 +5,7 @@ from .version import __version__
|
||||
version = __version__
|
||||
|
||||
__all__ = [
|
||||
'args',
|
||||
'asm',
|
||||
'atexception',
|
||||
'atexit',
|
||||
@@ -12,6 +13,7 @@ __all__ = [
|
||||
'constants',
|
||||
'context',
|
||||
'dynelf',
|
||||
'encoders',
|
||||
'elf',
|
||||
'exception',
|
||||
'fmtstr',
|
||||
@@ -23,12 +25,15 @@ __all__ = [
|
||||
'regsort',
|
||||
'replacements',
|
||||
'rop',
|
||||
'runner',
|
||||
'shellcraft',
|
||||
'term',
|
||||
'tubes',
|
||||
'ui',
|
||||
'useragents',
|
||||
'util'
|
||||
'util',
|
||||
'adb',
|
||||
'update',
|
||||
]
|
||||
|
||||
for module in __all__:
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from .context import LocalContext
|
||||
from .context import context
|
||||
|
||||
|
||||
class ABI(object):
|
||||
"""
|
||||
Encapsulates information about a calling convention.
|
||||
"""
|
||||
#: List or registers which should be filled with arguments before
|
||||
#: spilling onto the stack.
|
||||
register_arguments = []
|
||||
|
||||
#: Minimum alignment of the stack.
|
||||
#: The value used is min(context.bytes, stack_alignment)
|
||||
#: This is necessary as Windows x64 frames must be 32-byte aligned.
|
||||
#: "Alignment" is considered with respect to the last argument on the stack.
|
||||
arg_alignment = 1
|
||||
|
||||
#: Minimum number of stack slots used by a function call
|
||||
#: This is necessary as Windows x64 requires using 4 slots on the stack
|
||||
stack_minimum = 0
|
||||
|
||||
#: Indicates that this ABI returns to the next address on the slot
|
||||
returns = True
|
||||
|
||||
def __init__(self, regs, align, minimum):
|
||||
self.register_arguments = regs
|
||||
self.arg_alignment = align
|
||||
self.stack_minimum = minimum
|
||||
|
||||
@staticmethod
|
||||
@LocalContext
|
||||
def default():
|
||||
return {
|
||||
(32, 'i386', 'linux'): linux_i386,
|
||||
(64, 'amd64', 'linux'): linux_amd64,
|
||||
(32, 'arm', 'linux'): linux_arm,
|
||||
(32, 'thumb', 'linux'): linux_arm,
|
||||
(32, 'mips', 'linux'): linux_mips,
|
||||
(32, 'i386', 'windows'): windows_i386,
|
||||
(64, 'amd64', 'windows'): windows_amd64,
|
||||
}[(context.bits, context.arch, context.os)]
|
||||
|
||||
@staticmethod
|
||||
@LocalContext
|
||||
def syscall():
|
||||
return {
|
||||
(32, 'i386', 'linux'): linux_i386_syscall,
|
||||
(64, 'amd64', 'linux'): linux_amd64_syscall,
|
||||
(32, 'arm', 'linux'): linux_arm_syscall,
|
||||
(32, 'thumb', 'linux'): linux_arm_syscall,
|
||||
(32, 'mips', 'linux'): linux_mips_syscall,
|
||||
}[(context.bits, context.arch, context.os)]
|
||||
|
||||
@staticmethod
|
||||
@LocalContext
|
||||
def sigreturn():
|
||||
return {
|
||||
(32, 'i386', 'linux'): linux_i386_sigreturn,
|
||||
(64, 'amd64', 'linux'): linux_amd64_sigreturn,
|
||||
(32, 'arm', 'linux'): linux_arm_sigreturn,
|
||||
(32, 'thumb', 'linux'): linux_arm_sigreturn,
|
||||
}[(context.bits, context.arch, context.os)]
|
||||
|
||||
class SyscallABI(ABI):
|
||||
"""
|
||||
The syscall ABI treats the syscall number as the zeroth argument,
|
||||
which must be loaded into the specified register.
|
||||
"""
|
||||
def __init__(self, register_arguments, *a, **kw):
|
||||
super(SyscallABI, self).__init__(register_arguments, *a, **kw)
|
||||
self.syscall_register = register_arguments[0]
|
||||
|
||||
class SigreturnABI(SyscallABI):
|
||||
"""
|
||||
The sigreturn ABI is similar to the syscall ABI, except that
|
||||
both PC and SP are loaded from the stack. Because of this, there
|
||||
is no 'return' slot necessary on the stack.
|
||||
"""
|
||||
returns = False
|
||||
|
||||
|
||||
linux_i386 = ABI([], 4, 0)
|
||||
linux_amd64 = ABI(['rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
|
||||
linux_arm = ABI(['r0', 'r1', 'r2', 'r3'], 8, 0)
|
||||
linux_aarch64 = ABI(['x0', 'x1', 'x2', 'x3'], 16, 0)
|
||||
linux_mips = ABI(['$a0','$a1','$a2','$a3'], 4, 0)
|
||||
|
||||
linux_i386_syscall = SyscallABI(['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp'], 4, 0)
|
||||
linux_amd64_syscall = SyscallABI(['rax','rdi', 'rsi', 'rdx', 'r10', 'r8', 'r9'], 8, 0)
|
||||
linux_arm_syscall = SyscallABI(['r7', 'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6'], 4, 0)
|
||||
linux_aarch64_syscall = SyscallABI(['x8', 'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6'], 16, 0)
|
||||
linux_mips_syscall = ABI(['$v0', '$a0','$a1','$a2','$a3'], 4, 0)
|
||||
|
||||
linux_i386_sigreturn = SigreturnABI(['eax'], 4, 0)
|
||||
linux_amd64_sigreturn = SigreturnABI(['rax'], 4, 0)
|
||||
linux_arm_sigreturn = SigreturnABI(['r7'], 4, 0)
|
||||
|
||||
windows_i386 = ABI([], 4, 0)
|
||||
windows_amd64 = ABI(['rcx','rdx','r8','r9'], 32, 32)
|
||||
|
||||
# Fake ABIs used by SROP
|
||||
linux_i386_srop = ABI(['eax'], 4, 0)
|
||||
linux_amd64_srop = ABI(['rax'], 4, 0)
|
||||
linux_arm_srop = ABI(['r7'], 4, 0)
|
||||
@@ -0,0 +1,2 @@
|
||||
from .adb import *
|
||||
from .protocol import Client
|
||||
+1047
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,495 @@
|
||||
"""
|
||||
Implementation of the Android Debug Bridge (ADB) protocol, as far as Binjitsu needs it.
|
||||
|
||||
Documentation is available here:
|
||||
https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
|
||||
"""
|
||||
import functools
|
||||
import time
|
||||
|
||||
from ..context import context
|
||||
from ..log import Logger
|
||||
from ..log import getLogger
|
||||
from ..tubes.listen import listen
|
||||
from ..tubes.process import process
|
||||
from ..tubes.remote import remote
|
||||
from ..util.lists import group
|
||||
from ..util.misc import size
|
||||
from ..util.packing import p32
|
||||
from ..util.proc import pidof
|
||||
from ..util.sh_string import sh_string
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
def pack(val):
|
||||
return '%04x' % val
|
||||
|
||||
def unpack(val):
|
||||
return int(val, 16)
|
||||
|
||||
OKAY = "OKAY"
|
||||
FAIL = "FAIL"
|
||||
|
||||
class Message(object):
|
||||
"""An ADB hex-length-prefixed message"""
|
||||
def __init__(self, string):
|
||||
self.string = string
|
||||
def __str__(self):
|
||||
return ('%04x' % len(self.string)) + self.string
|
||||
def __flat__(self):
|
||||
return str(self)
|
||||
|
||||
class Connection(remote):
|
||||
"""Connection to the ADB server"""
|
||||
def __init__(self, host, port, level=None, *a, **kw):
|
||||
|
||||
# Try to make sure ADB is running if it's on the default host and port.
|
||||
if host == context.defaults['adb_host'] \
|
||||
and port == context.defaults['adb_port']:
|
||||
process(context.adb + ['start-server'], level='error').wait_for_close()
|
||||
|
||||
with context.quiet:
|
||||
super(Connection, self).__init__(host, port, level=level, *a, **kw)
|
||||
|
||||
self._executable = None
|
||||
self._argv = None
|
||||
self._pid = None
|
||||
self._cwd = None
|
||||
self._env = None
|
||||
|
||||
def close(self):
|
||||
with context.quiet:
|
||||
super(Connection, self).close()
|
||||
|
||||
def adb_send(self, message):
|
||||
self.send(str(Message(message)))
|
||||
return self.recvn(4)
|
||||
|
||||
def adb_unpack(self):
|
||||
return unpack(self.recvn(4))
|
||||
|
||||
def flat(self, *a, **kw):
|
||||
kw.setdefault('word_size', 32)
|
||||
return super(Connection, self).flat(*a, **kw)
|
||||
|
||||
class Process(Connection):
|
||||
"""Duck-typed ``tubes.remote`` object to add properties of a ``tubes.process``"""
|
||||
|
||||
class Client(Logger):
|
||||
"""ADB Client"""
|
||||
def __init__(self, level=None):
|
||||
super(Client, self).__init__()
|
||||
|
||||
if level is not None:
|
||||
self.setLevel(level)
|
||||
|
||||
self.host = context.adb_host
|
||||
self.port = context.adb_port
|
||||
self._c = None
|
||||
|
||||
@property
|
||||
def c(self):
|
||||
"""Client's connection to the ADB server"""
|
||||
if not self._c:
|
||||
self._c = Connection(self.host, self.port, level=self.level)
|
||||
return self._c
|
||||
|
||||
def _autoclose(fn):
|
||||
"""Decorator which automatically closes the connection to the ADB server
|
||||
after calling the decorated function."""
|
||||
@functools.wraps(fn)
|
||||
def wrapper(self, *a, **kw):
|
||||
rv = fn(self, *a, **kw)
|
||||
if self._c:
|
||||
self._c.close()
|
||||
self._c = None
|
||||
return rv
|
||||
return wrapper
|
||||
|
||||
def _with_transport(fn):
|
||||
"""Decorator which automatically selects a device transport before calling
|
||||
the decorated function, and closes the connection afterward."""
|
||||
@functools.wraps(fn)
|
||||
def wrapper(self, *a, **kw):
|
||||
self.transport()
|
||||
rv = fn(self, *a, **kw)
|
||||
if self._c:
|
||||
self._c.close()
|
||||
self._c = None
|
||||
return rv
|
||||
return wrapper
|
||||
|
||||
def send(self, *a, **kw):
|
||||
"""Sends data to the ADB server"""
|
||||
return self.c.adb_send(*a, **kw)
|
||||
|
||||
def unpack(self, *a, **kw):
|
||||
"""Receives a hex-ascii packed integer from the ADB server"""
|
||||
return self.c.adb_unpack(*a, **kw)
|
||||
|
||||
def recvl(self):
|
||||
"""Receives a length-prefixed data buffer from the ADB server"""
|
||||
length = self.c.adb_unpack()
|
||||
return self.c.recvn(length)
|
||||
|
||||
@_autoclose
|
||||
def kill(self):
|
||||
"""Kills the remote ADB server"""
|
||||
try:
|
||||
self.send('host:kill')
|
||||
except EOFError:
|
||||
pass
|
||||
|
||||
def version(self):
|
||||
"""
|
||||
Returns:
|
||||
Tuple containing the ``(major, minor)`` version from the ADB server
|
||||
|
||||
Example:
|
||||
|
||||
>>> adb.protocol.Client().version() # doctest: +SKIP
|
||||
(4, 36)
|
||||
"""
|
||||
response = self.send('host:version')
|
||||
if response == OKAY:
|
||||
return (self.c.adb_unpack(), self.c.adb_unpack())
|
||||
self.error("Could not fetch version")
|
||||
|
||||
@_autoclose
|
||||
def devices(self, long=False):
|
||||
"""
|
||||
Arguments:
|
||||
long(bool): If ``True``, fetch the long-format listing.
|
||||
Returns:
|
||||
String representation of all available devices.
|
||||
"""
|
||||
msg = 'host:devices'
|
||||
if long:
|
||||
msg += '-l'
|
||||
response = self.send(msg)
|
||||
if response == 'OKAY':
|
||||
return self.recvl()
|
||||
self.error("Could not enumerate devices")
|
||||
|
||||
@_autoclose
|
||||
def track_devices(self):
|
||||
"""
|
||||
Returns:
|
||||
Generator which returns a short-format listing of available
|
||||
devices each time a device state changes.
|
||||
"""
|
||||
self.send('host:track-devices')
|
||||
while True:
|
||||
yield self.recvl()
|
||||
|
||||
def transport(self, serial=None):
|
||||
"""Sets the Transport on the rmeote device.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> adb.protocol.Client().transport()
|
||||
"""
|
||||
msg = 'host:transport:%s' % (serial or context.device)
|
||||
if self.send(msg) == FAIL:
|
||||
self.error("Could not set transport to %r" % serial)
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def execute(self, argv):
|
||||
r"""Executes a program on the device.
|
||||
|
||||
Returns:
|
||||
A ``tube`` which is connected to the process.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> adb.protocol.Client().execute(['echo','hello']).recvall()
|
||||
'hello\n'
|
||||
"""
|
||||
self.transport(context.device)
|
||||
if isinstance(argv, str):
|
||||
argv = [argv]
|
||||
argv = list(map(sh_string, argv))
|
||||
cmd = 'exec:%s' % (' '.join(argv))
|
||||
if OKAY == self.send(cmd):
|
||||
rv = self._c
|
||||
self._c = None
|
||||
return rv
|
||||
|
||||
def _basic_wrapper(string):
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def wrapper(self):
|
||||
self.send(string)
|
||||
return self.c.recvall()
|
||||
return wrapper
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def remount(self):
|
||||
self.send('remount:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def root(self):
|
||||
self.send('root:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def unroot(self):
|
||||
self.send('unroot:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def disable_verity(self):
|
||||
self.send('disable-verity:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def enable_verity(self):
|
||||
self.send('enable-verity:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def reconnect(self):
|
||||
self.send('reconnect:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def reboot(self):
|
||||
self.send('reboot:')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
@_with_transport
|
||||
def reboot_bootloader(self):
|
||||
self.send('reboot:bootloader')
|
||||
return self.c.recvall()
|
||||
|
||||
@_autoclose
|
||||
def wait_for_device(self, serial=''):
|
||||
response = self.send('host-serial:%s:wait-for-any-device' % serial)
|
||||
|
||||
# The first OKAY is that the command was understood
|
||||
if response != 'OKAY':
|
||||
self.error("An error occurred while waiting for device with serial %r" % serial)
|
||||
|
||||
# The second OKAY is that the device is available
|
||||
response = self.c.recvn(4)
|
||||
if response != 'OKAY':
|
||||
self.error("An error occurred while waiting for device with serial %r" % serial)
|
||||
|
||||
def _sync(fn):
|
||||
"""Decorator which enters 'sync:' mode to the selected transport,
|
||||
then invokes the decorated funciton."""
|
||||
@functools.wraps(fn)
|
||||
def wrapper(self, *a, **kw):
|
||||
rv = None
|
||||
if FAIL != self.send('sync:'):
|
||||
rv = fn(self, *a, **kw)
|
||||
return rv
|
||||
return wrapper
|
||||
|
||||
@_with_transport
|
||||
@_sync
|
||||
def list(self, path):
|
||||
"""Execute the ``LIST`` command of the ``SYNC`` API.
|
||||
|
||||
Arguments:
|
||||
path(str): Path of the directory to list.
|
||||
|
||||
Return:
|
||||
A dictionary, where the keys are relative filenames,
|
||||
and the values are a dictionary containing the same
|
||||
values as ``stat()`` supplies.
|
||||
|
||||
Note:
|
||||
In recent releases of Android (e.g. 7.0), the domain that
|
||||
adbd executes from does not have access to everything that
|
||||
the shell user does.
|
||||
|
||||
Because of this, while the shell user can get listings of
|
||||
e.g. the root directory ('/'), adbd cannot.
|
||||
|
||||
The SYNC APIs are executed within the adbd context, not the
|
||||
shell user context.
|
||||
|
||||
This issue is not a problem if the phone is rooted via
|
||||
'adb root', since adbd then runs in the ``su`` domain.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> pprint(adb.Client().list('/data/user'))
|
||||
{'0': {'mode': 41471, 'size': 11, 'time': ...}}
|
||||
>>> adb.Client().list('/does/not/exist')
|
||||
{}
|
||||
"""
|
||||
self.c.flat('LIST', len(path), path)
|
||||
files = {}
|
||||
while True:
|
||||
response = self.c.recvn(4)
|
||||
|
||||
if response == 'DONE':
|
||||
break
|
||||
|
||||
if response != 'DENT':
|
||||
self.error('Unexpected response: %r' % response)
|
||||
|
||||
mode = self.c.u32()
|
||||
size = self.c.u32()
|
||||
time = self.c.u32()
|
||||
name = self.c.recvn(self.c.u32())
|
||||
|
||||
# Ignore the current directory and parent
|
||||
if name in ('', '.', '..'):
|
||||
continue
|
||||
|
||||
files[name] = {'mode': mode,
|
||||
'size': size,
|
||||
'time': time}
|
||||
|
||||
return files
|
||||
|
||||
@_with_transport
|
||||
@_sync
|
||||
def stat(self, path):
|
||||
"""Execute the ``STAT`` command of the ``SYNC`` API.
|
||||
|
||||
Arguments:
|
||||
path(str): Path to the file to stat.
|
||||
|
||||
Return:
|
||||
On success, a dictionary mapping the values returned.
|
||||
If the file cannot be ``stat()``ed, None is returned.
|
||||
|
||||
Example:
|
||||
|
||||
>>> expected = {'mode': 16749, 'size': 0, 'time': 0}
|
||||
>>> adb.protocol.Client().stat('/proc') == expected
|
||||
True
|
||||
>>> adb.protocol.Client().stat('/does/not/exist') == None
|
||||
True
|
||||
"""
|
||||
self.c.flat('STAT', len(path), path)
|
||||
if self.c.recvn(4) != 'STAT':
|
||||
self.error("An error occured while attempting to STAT a file.")
|
||||
|
||||
mode = self.c.u32()
|
||||
size = self.c.u32()
|
||||
time = self.c.u32()
|
||||
|
||||
if (mode,size,time) == (0,0,0):
|
||||
return None
|
||||
|
||||
return {'mode': mode, 'size': size, 'time': time}
|
||||
|
||||
@_with_transport
|
||||
@_sync
|
||||
def write(self, path, data, mode=0o755, timestamp=None, callback=None):
|
||||
path += ',' + str(mode)
|
||||
self.c.flat('SEND', len(path), path)
|
||||
|
||||
sent = 0
|
||||
|
||||
# Data needs to be broken up into chunks!
|
||||
for chunk in group(0x10000, data):
|
||||
self.c.flat('DATA', len(chunk), chunk)
|
||||
if callback:
|
||||
callback(path, data[:sent], len(data), chunk, len(chunk))
|
||||
sent += len(chunk)
|
||||
|
||||
# Send completion notification and timestamp
|
||||
if timestamp is None:
|
||||
timestamp = int(time.time())
|
||||
self.c.flat('DONE', timestamp)
|
||||
|
||||
result = self.c.recvn(4)
|
||||
if result != 'OKAY':
|
||||
log.error("Sync write failed: %r (expected OKAY)" % result)
|
||||
|
||||
return
|
||||
|
||||
@_with_transport
|
||||
@_sync
|
||||
def read(self, path, filesize=0, callback=lambda *a: True):
|
||||
"""Execute the ``READ`` command of the ``SYNC`` API.
|
||||
|
||||
Arguments:
|
||||
path(str): Path to the file to read
|
||||
filesize(int): Size of the file, in bytes. Optional.
|
||||
callback(callable): Callback function invoked as data
|
||||
becomes available. Arguments provided are:
|
||||
|
||||
- File path
|
||||
- All data
|
||||
- Expected size of all data
|
||||
- Current chunk
|
||||
- Expected size of chunk
|
||||
|
||||
Return:
|
||||
The data received as a string.
|
||||
"""
|
||||
self.c.send('RECV' + p32(len(path)) + path)
|
||||
|
||||
# Accumulate all data here
|
||||
all_data = ''
|
||||
|
||||
while True:
|
||||
magic = self.c.recvn(4)
|
||||
|
||||
# adbd says there is no more data to send
|
||||
if magic == 'DONE':
|
||||
break
|
||||
|
||||
if magic == 'FAIL':
|
||||
self.error('Could not read file %r: Got FAIL.' % path)
|
||||
|
||||
# did we expect to be done?
|
||||
if magic != 'DATA':
|
||||
self.error('Error after file read: %r (expected DATA)' % magic)
|
||||
|
||||
# receive all of the data in the chunk
|
||||
chunk_size = self.c.u32()
|
||||
chunk_data = ''
|
||||
while len(chunk_data) != chunk_size:
|
||||
chunk_data += self.c.recv(chunk_size - len(chunk_data))
|
||||
|
||||
if callback:
|
||||
callback(path,
|
||||
all_data,
|
||||
filesize,
|
||||
chunk_data,
|
||||
chunk_size)
|
||||
|
||||
# add the chunk onto what we have
|
||||
all_data += chunk_data
|
||||
|
||||
zero = self.c.u32()
|
||||
if zero != 0:
|
||||
self.error('Error after file read: %r (expected ZERO)' % zero)
|
||||
|
||||
return all_data
|
||||
|
||||
@_with_transport
|
||||
def forward(self, device, host_proto, host_port, device_proto, device_port):
|
||||
self.send('host:forward:%s:%s;%s:%s' % (host_proto, host_port, device_proto, device_port))
|
||||
self.c.recvall()
|
||||
|
||||
def __enter__(self, *a, **kw):
|
||||
return self
|
||||
|
||||
@_autoclose
|
||||
def __exit__(self, *a, **kw): pass
|
||||
|
||||
def proxy(port=9999):
|
||||
"""Starts an ADB proxy on the specified port, for debugging purposes."""
|
||||
l = listen(port)
|
||||
l.wait_for_connection()
|
||||
r = remote(context.adb_host, context.adb_port, level='debug')
|
||||
l <> r
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python2
|
||||
"""
|
||||
"""
|
||||
import collections
|
||||
import logging
|
||||
import os
|
||||
import string
|
||||
import sys
|
||||
|
||||
from . import term
|
||||
from .context import context
|
||||
|
||||
term_mode = True
|
||||
args = collections.defaultdict(str)
|
||||
env_prefix = 'PWNLIB_'
|
||||
|
||||
def isident(s):
|
||||
"""
|
||||
Helper function to check whether a string is a valid identifier,
|
||||
as passed in on the command-line.
|
||||
"""
|
||||
first = string.uppercase + '_'
|
||||
body = string.digits + first
|
||||
if not s:
|
||||
return False
|
||||
if s[0] not in first:
|
||||
return False
|
||||
if not all(c in body for c in s[1:]):
|
||||
return False
|
||||
return True
|
||||
|
||||
def asbool(s):
|
||||
"""
|
||||
Convert a string to its boolean value
|
||||
"""
|
||||
if s.lower() == 'true':
|
||||
return True
|
||||
elif s.lower() == 'false':
|
||||
return False
|
||||
elif s.isdigit():
|
||||
return bool(int(s))
|
||||
else:
|
||||
raise ValueError('must be integer or boolean: %r' % s)
|
||||
|
||||
def set_log_level(x):
|
||||
with context.local(log_level=x):
|
||||
context.defaults['log_level']=context.log_level
|
||||
|
||||
def set_log_file(x):
|
||||
context.log_file=x
|
||||
|
||||
def set_log_level_error(x):
|
||||
set_log_level('error')
|
||||
|
||||
def set_log_level_debug(x):
|
||||
set_log_level('debug')
|
||||
|
||||
def set_noterm(v):
|
||||
if asbool(v):
|
||||
global term_mode
|
||||
term_mode = False
|
||||
|
||||
def set_timeout(v):
|
||||
context.defaults['timeout'] = int(v)
|
||||
|
||||
def set_randomize(v):
|
||||
context.defaults['randomize'] = asbool(v)
|
||||
|
||||
def set_aslr(v):
|
||||
context.defaults['aslr'] = not asbool(v)
|
||||
|
||||
def set_noptrace(v):
|
||||
context.defaults['noptrace'] = asbool(v)
|
||||
|
||||
hooks = {
|
||||
'LOG_LEVEL': set_log_level,
|
||||
'LOG_FILE': set_log_file,
|
||||
'DEBUG': set_log_level_debug,
|
||||
'NOTERM': set_noterm,
|
||||
'SILENT': set_log_level_error,
|
||||
'RANDOMIZE': set_randomize,
|
||||
'TIMEOUT': set_timeout,
|
||||
'NOASLR': set_aslr,
|
||||
'NOPTRACE': set_noptrace,
|
||||
}
|
||||
|
||||
def initialize():
|
||||
global args, term_mode
|
||||
|
||||
# Hack for readthedocs.org
|
||||
if 'READTHEDOCS' in os.environ:
|
||||
os.environ['PWNLIB_NOTERM'] = '1'
|
||||
|
||||
for k, v in os.environ.items():
|
||||
if not k.startswith(env_prefix):
|
||||
continue
|
||||
k = k[len(env_prefix):]
|
||||
|
||||
if k in hooks:
|
||||
hooks[k](v)
|
||||
elif isident(k):
|
||||
args[k] = v
|
||||
|
||||
argv = sys.argv[:]
|
||||
for arg in sys.argv[:]:
|
||||
orig = arg
|
||||
value = 'True'
|
||||
|
||||
if '=' in arg:
|
||||
arg, value = arg.split('=')
|
||||
|
||||
if arg in hooks:
|
||||
sys.argv.remove(orig)
|
||||
hooks[arg](value)
|
||||
|
||||
elif isident(arg):
|
||||
sys.argv.remove(orig)
|
||||
args[arg] = value
|
||||
|
||||
if term_mode:
|
||||
term.init()
|
||||
+327
-181
@@ -27,8 +27,8 @@ Assembly
|
||||
Finally, :func:`asm` is used to assemble shellcode provided by ``pwntools``
|
||||
in the :mod:`shellcraft` module.
|
||||
|
||||
>>> asm(shellcraft.sh())
|
||||
'jhh///sh/bin\x89\xe31\xc9j\x0bX\x99\xcd\x80'
|
||||
>>> asm(shellcraft.nop())
|
||||
'\x90'
|
||||
|
||||
Disassembly
|
||||
------------------------
|
||||
@@ -53,17 +53,75 @@ from glob import glob
|
||||
from os import environ
|
||||
from os import path
|
||||
|
||||
from . import atexit
|
||||
from . import shellcraft
|
||||
from .context import LocalContext
|
||||
from .context import context
|
||||
from .log import getLogger
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
__all__ = ['asm', 'cpp', 'disasm', 'make_elf']
|
||||
__all__ = ['asm', 'cpp', 'disasm', 'make_elf', 'make_elf_from_assembly']
|
||||
|
||||
_basedir = path.split(__file__)[0]
|
||||
_incdir = path.join(_basedir, 'data', 'includes')
|
||||
|
||||
def which_binutils(util, **kwargs):
|
||||
def dpkg_search_for_binutils(arch, util):
|
||||
"""Use dpkg to search for any available assemblers which will work.
|
||||
|
||||
Returns:
|
||||
A list of candidate package names.
|
||||
"""
|
||||
|
||||
# Example output:
|
||||
# $ dpkg -S 'arm*linux*-as'
|
||||
# binutils-arm-linux-gnu: /usr/bin/arm-linux-gnu-as
|
||||
# binutils-arm-linux-gnueabihf: /usr/bin/arm-linux-gnueabihf-as
|
||||
# binutils-arm-linux-gnueabihf: /usr/x86_64-linux-gnu/arm-linux-gnueabihf/include/dis-asm.h
|
||||
# binutils-arm-linux-gnu: /usr/x86_64-linux-gnu/arm-linux-gnu/include/dis-asm.h
|
||||
packages = []
|
||||
|
||||
try:
|
||||
filename = 'bin/%s*linux*-%s' % (arch, util)
|
||||
output = subprocess.check_output(['dpkg','-S',filename])
|
||||
for line in output.strip().splitlines():
|
||||
package, path = line.split(':', 1)
|
||||
packages.append(package)
|
||||
except OSError:
|
||||
pass
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
|
||||
return packages
|
||||
|
||||
def print_binutils_instructions(util, context):
|
||||
"""On failure to find a binutils utility, inform the user of a way
|
||||
they can get it easily.
|
||||
"""
|
||||
# This links to our instructions on how to manually install binutils
|
||||
# for several architectures.
|
||||
instructions = 'https://docs.pwntools.com/en/stable/install/binutils.html'
|
||||
|
||||
# However, if we can directly provide a useful command, go for it.
|
||||
binutils_arch = {
|
||||
'amd64': 'x86_64',
|
||||
'arm': 'armeabi',
|
||||
'thumb': 'armeabi',
|
||||
}.get(context.arch, context.arch)
|
||||
|
||||
packages = dpkg_search_for_binutils(binutils_arch, util)
|
||||
|
||||
if packages:
|
||||
instructions = '$ sudo apt-get install %s' % packages[0]
|
||||
|
||||
log.error("""
|
||||
Could not find %(util)r installed for %(context)s
|
||||
Try installing binutils for this architecture:
|
||||
%(instructions)s
|
||||
""".strip() % locals())
|
||||
|
||||
@LocalContext
|
||||
def which_binutils(util):
|
||||
"""
|
||||
Finds a binutils in the PATH somewhere.
|
||||
Expects that the utility is prefixed with the architecture name.
|
||||
@@ -83,49 +141,50 @@ def which_binutils(util, **kwargs):
|
||||
...
|
||||
Exception: Could not find 'as' installed for ContextType(arch = 'msp430')
|
||||
"""
|
||||
with context.local(**kwargs):
|
||||
arch = context.arch
|
||||
bits = context.bits
|
||||
arch = context.arch
|
||||
bits = context.bits
|
||||
|
||||
# Fix up pwntools vs Debian triplet naming, and account
|
||||
# for 'thumb' being its own pwntools architecture.
|
||||
arches = [arch] + {
|
||||
'thumb': ['arm', 'aarch64'],
|
||||
'i386': ['x86_64', 'amd64'],
|
||||
'amd64': ['x86_64', 'i386'],
|
||||
}.get(arch, [])
|
||||
# Fix up pwntools vs Debian triplet naming, and account
|
||||
# for 'thumb' being its own pwntools architecture.
|
||||
arches = [arch] + {
|
||||
'thumb': ['arm', 'aarch64'],
|
||||
'i386': ['x86_64', 'amd64'],
|
||||
'i686': ['x86_64', 'amd64'],
|
||||
'amd64': ['x86_64', 'i386'],
|
||||
}.get(arch, [])
|
||||
|
||||
# If one of the candidate architectures matches the native
|
||||
# architecture, use that as a last resort.
|
||||
machine = platform.machine()
|
||||
try:
|
||||
with context.local(arch = machine):
|
||||
if context.arch in arches:
|
||||
arches.append(None)
|
||||
except AttributeError:
|
||||
log.warn_once("Your local binutils won't be used because architecture %r is not supported." % machine)
|
||||
# If one of the candidate architectures matches the native
|
||||
# architecture, use that as a last resort.
|
||||
machine = platform.machine()
|
||||
machine = 'i386' if machine == 'i686' else machine
|
||||
try:
|
||||
with context.local(arch = machine):
|
||||
if context.arch in arches:
|
||||
arches.append(None)
|
||||
except AttributeError:
|
||||
log.warn_once("Your local binutils won't be used because architecture %r is not supported." % machine)
|
||||
|
||||
for arch in arches:
|
||||
# hack for homebrew-installed binutils on mac
|
||||
for gutil in ['g'+util, util]:
|
||||
# e.g. objdump
|
||||
if arch is None: pattern = gutil
|
||||
utils = [util]
|
||||
|
||||
# e.g. aarch64-linux-gnu-objdump
|
||||
else: pattern = '%s*linux*-%s' % (arch,gutil)
|
||||
# hack for homebrew-installed binutils on mac
|
||||
if platform.system() == 'Darwin':
|
||||
utils = ['g'+util, util]
|
||||
|
||||
for dir in environ['PATH'].split(':'):
|
||||
res = sorted(glob(path.join(dir, pattern)))
|
||||
if res:
|
||||
return res[0]
|
||||
for arch in arches:
|
||||
for gutil in utils:
|
||||
# e.g. objdump
|
||||
if arch is None: pattern = gutil
|
||||
|
||||
locals()['context'] = context
|
||||
log.warning("""
|
||||
Could not find %(util)r installed for %(context)s
|
||||
Try installing binutils for this architecture:
|
||||
https://pwntools.readthedocs.org/en/latest/install/binutils.html
|
||||
""".strip() % locals())
|
||||
raise Exception('Could not find %(util)r installed for %(context)s' % locals())
|
||||
# e.g. aarch64-linux-gnu-objdump
|
||||
else: pattern = '%s*linux*-%s' % (arch,gutil)
|
||||
|
||||
for dir in environ['PATH'].split(':'):
|
||||
res = sorted(glob(path.join(dir, pattern)))
|
||||
if res:
|
||||
return res[0]
|
||||
|
||||
# No dice!
|
||||
print_binutils_instructions(util, context)
|
||||
|
||||
checked_assembler_version = defaultdict(lambda: False)
|
||||
|
||||
@@ -169,7 +228,7 @@ def _assembler():
|
||||
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://pwntools.readthedocs.org/en/latest/install/binutils.html\n' + \
|
||||
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n' + \
|
||||
'Reported Version: %r' % result.strip())
|
||||
|
||||
|
||||
@@ -204,11 +263,7 @@ def _objdump():
|
||||
def _include_header():
|
||||
os = context.os
|
||||
arch = context.arch
|
||||
|
||||
if os == 'freebsd':
|
||||
include = 'freebsd.h'
|
||||
elif os == 'linux':
|
||||
include = 'linux/%s.h' % arch
|
||||
include = '%s/%s.h' % (os, arch)
|
||||
|
||||
if not include or not path.exists(path.join(_incdir, include)):
|
||||
log.warn_once("Could not find system include headers for %s-%s" % (arch,os))
|
||||
@@ -218,7 +273,11 @@ def _include_header():
|
||||
|
||||
|
||||
def _arch_header():
|
||||
prefix = ['.section .shellcode,"ax"']
|
||||
prefix = ['.section .shellcode,"awx"',
|
||||
'.global _start',
|
||||
'.global __start',
|
||||
'_start:',
|
||||
'__start:']
|
||||
headers = {
|
||||
'i386' : ['.intel_syntax noprefix'],
|
||||
'amd64' : ['.intel_syntax noprefix'],
|
||||
@@ -229,7 +288,8 @@ def _arch_header():
|
||||
'.arch armv7-a',
|
||||
'.thumb'],
|
||||
'mips' : ['.set mips2',
|
||||
'.set noreorder'],
|
||||
'.set noreorder',
|
||||
],
|
||||
}
|
||||
|
||||
return '\n'.join(prefix + headers.get(context.arch, [])) + '\n'
|
||||
@@ -304,7 +364,8 @@ def _run(cmd, stdin = None):
|
||||
|
||||
return stdout
|
||||
|
||||
def cpp(shellcode, **kwargs):
|
||||
@LocalContext
|
||||
def cpp(shellcode):
|
||||
r"""cpp(shellcode, ...) -> str
|
||||
|
||||
Runs CPP over the given shellcode.
|
||||
@@ -324,37 +385,79 @@ def cpp(shellcode, **kwargs):
|
||||
>>> cpp("mov al, SYS_setresuid", arch = "i386", os = "linux")
|
||||
'mov al, 164\n'
|
||||
>>> cpp("weee SYS_setresuid", arch = "arm", os = "linux")
|
||||
'weee (0x900000+164)\n'
|
||||
'weee (0+164)\n'
|
||||
>>> cpp("SYS_setresuid", arch = "thumb", os = "linux")
|
||||
'(0+164)\n'
|
||||
>>> cpp("SYS_setresuid", os = "freebsd")
|
||||
'311\n'
|
||||
"""
|
||||
arch = context.arch
|
||||
os = context.os
|
||||
code = _include_header() + shellcode
|
||||
cmd = [
|
||||
'cpp',
|
||||
'-C',
|
||||
'-nostdinc',
|
||||
'-undef',
|
||||
'-P',
|
||||
'-I' + _incdir,
|
||||
'/dev/stdin'
|
||||
]
|
||||
return _run(cmd, code).strip('\n').rstrip() + '\n'
|
||||
|
||||
with context.local(**kwargs):
|
||||
arch = context.arch
|
||||
os = context.os
|
||||
code = _include_header() + shellcode
|
||||
cmd = [
|
||||
'cpp',
|
||||
'-C',
|
||||
'-nostdinc',
|
||||
'-undef',
|
||||
'-P',
|
||||
'-I' + _incdir,
|
||||
'/dev/stdin'
|
||||
]
|
||||
return _run(cmd, code).strip('\n').rstrip() + '\n'
|
||||
@LocalContext
|
||||
def make_elf_from_assembly(assembly, vma = None, extract=False, shared = False):
|
||||
r"""
|
||||
Builds an ELF file with the specified assembly as its
|
||||
executable code.
|
||||
|
||||
elf_template = '''
|
||||
.global _start
|
||||
.global __start
|
||||
.text
|
||||
_start:
|
||||
__start:
|
||||
'''
|
||||
Arguments:
|
||||
|
||||
def make_elf(data, vma = None, strip=True, **kwargs):
|
||||
assembly(str): Assembly
|
||||
vma(int): Load address of the binary
|
||||
extract(bool): Whether to return the data extracted from the file created,
|
||||
or the path to it.
|
||||
|
||||
Returns:
|
||||
|
||||
The path to the assembled ELF (extract=False), or the data
|
||||
of the assembled ELF.
|
||||
|
||||
Example:
|
||||
|
||||
>>> context.clear()
|
||||
>>> context.arch = 'amd64'
|
||||
>>> sc = 'push rbp; mov rbp, rsp;'
|
||||
>>> sc += shellcraft.echo('Hello\n')
|
||||
>>> sc += 'mov rsp, rbp; pop rbp; ret'
|
||||
>>> solib = make_elf_from_assembly(sc, shared=1)
|
||||
>>> subprocess.check_output(['echo', 'World'], env={'LD_PRELOAD': solib})
|
||||
'Hello\nWorld\n'
|
||||
"""
|
||||
if shared and vma:
|
||||
log.error("Cannot specify a VMA for a shared library.")
|
||||
|
||||
if vma is None:
|
||||
if shared:
|
||||
vma = 0
|
||||
else:
|
||||
vma = 0x10000000
|
||||
|
||||
if context.arch == 'thumb':
|
||||
to_thumb = shellcraft.arm.to_thumb()
|
||||
|
||||
if not assembly.startswith(to_thumb):
|
||||
assembly = to_thumb + assembly
|
||||
|
||||
path = asm(assembly, vma = vma, extract = extract, shared = shared)
|
||||
|
||||
if not extract:
|
||||
os.chmod(path, 0755)
|
||||
|
||||
return path
|
||||
|
||||
@LocalContext
|
||||
def make_elf(data, vma = None, strip=True, extract=True, shared=False):
|
||||
r"""
|
||||
Builds an ELF file with the specified binary data as its
|
||||
executable code.
|
||||
@@ -383,45 +486,69 @@ def make_elf(data, vma = None, strip=True, **kwargs):
|
||||
>>> p.recvline()
|
||||
'Hello\n'
|
||||
"""
|
||||
with context.local(**kwargs):
|
||||
assembler = _assembler()
|
||||
linker = _linker()
|
||||
code = elf_template
|
||||
code += '.string "%s"' % ''.join('\\x%02x' % c for c in bytearray(data))
|
||||
code += '\n'
|
||||
retval = None
|
||||
|
||||
log.debug(code)
|
||||
if shared and vma:
|
||||
log.error("Cannot specify a VMA for a shared library.")
|
||||
|
||||
tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-')
|
||||
step1 = path.join(tmpdir, 'step1-asm')
|
||||
step2 = path.join(tmpdir, 'step2-obj')
|
||||
step3 = path.join(tmpdir, 'step3-elf')
|
||||
if context.arch == 'thumb':
|
||||
to_thumb = asm(shellcraft.arm.to_thumb(), arch='arm')
|
||||
|
||||
try:
|
||||
with open(step1, 'wb+') as f:
|
||||
f.write(code)
|
||||
if not data.startswith(to_thumb):
|
||||
data = to_thumb + data
|
||||
|
||||
_run(assembler + ['-o', step2, step1])
|
||||
|
||||
load_addr = []
|
||||
if vma is not None:
|
||||
load_addr = ['-Ttext-segment=%#x' % vma]
|
||||
assembler = _assembler()
|
||||
linker = _linker()
|
||||
code = _arch_header()
|
||||
code += '.string "%s"' % ''.join('\\x%02x' % ord(c) for c in data)
|
||||
code += '\n'
|
||||
|
||||
_run(linker + load_addr + ['-N', '-o', step3, step2])
|
||||
log.debug("Building ELF:\n" + code)
|
||||
|
||||
if strip:
|
||||
_run([which_binutils('objcopy'), '-Sg', step3])
|
||||
_run([which_binutils('strip'), '--strip-unneeded', step3])
|
||||
tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-')
|
||||
step1 = path.join(tmpdir, 'step1-asm')
|
||||
step2 = path.join(tmpdir, 'step2-obj')
|
||||
step3 = path.join(tmpdir, 'step3-elf')
|
||||
|
||||
try:
|
||||
with open(step1, 'wb+') as f:
|
||||
f.write(code)
|
||||
|
||||
_run(assembler + ['-o', step2, step1])
|
||||
|
||||
linker_options = ['-z', 'execstack']
|
||||
if vma:
|
||||
linker_options += ['--section-start=.shellcode=%#x' % vma,
|
||||
'--entry=%#x' % vma]
|
||||
elif shared:
|
||||
linker_options += ['-shared', '-init=_start']
|
||||
|
||||
linker_options += ['-o', step3, step2]
|
||||
|
||||
_run(linker + linker_options)
|
||||
|
||||
if strip:
|
||||
_run([which_binutils('objcopy'), '-Sg', step3])
|
||||
_run([which_binutils('strip'), '--strip-unneeded', step3])
|
||||
|
||||
if not extract:
|
||||
os.chmod(step3, 0755)
|
||||
retval = step3
|
||||
|
||||
with open(step3, 'r') as f:
|
||||
return f.read()
|
||||
except Exception:
|
||||
log.exception("An error occurred while building an ELF:\n%s" % code)
|
||||
else:
|
||||
shutil.rmtree(tmpdir)
|
||||
with open(step3, 'r') as f:
|
||||
retval = f.read()
|
||||
except Exception:
|
||||
log.exception("An error occurred while building an ELF:\n%s" % code)
|
||||
else:
|
||||
atexit.register(lambda: shutil.rmtree(tmpdir))
|
||||
|
||||
def asm(shellcode, vma = 0, **kwargs):
|
||||
r"""asm(code, vma = 0, ...) -> str
|
||||
return retval
|
||||
|
||||
@LocalContext
|
||||
def asm(shellcode, vma = 0, extract = True, shared = False):
|
||||
r"""asm(code, vma = 0, extract = True, ...) -> str
|
||||
|
||||
Runs :func:`cpp` over a given shellcode and then assembles it into bytes.
|
||||
|
||||
@@ -434,6 +561,9 @@ def asm(shellcode, vma = 0, **kwargs):
|
||||
Arguments:
|
||||
shellcode(str): Assembler code to assemble.
|
||||
vma(int): Virtual memory address of the beginning of assembly
|
||||
extract(bool): Extract the raw assembly bytes from the assembled
|
||||
file. If ``False``, returns the path to an ELF file
|
||||
with the assembly embedded.
|
||||
|
||||
Kwargs:
|
||||
Any arguments/properties that can be set on ``context``
|
||||
@@ -448,63 +578,74 @@ def asm(shellcode, vma = 0, **kwargs):
|
||||
'\xb8\x17\x00\x00\x00'
|
||||
>>> asm("mov rax, SYS_select", arch = 'amd64', os = 'linux')
|
||||
'H\xc7\xc0\x17\x00\x00\x00'
|
||||
>>> asm("ldr r0, =SYS_select", arch = 'arm', os = 'linux', bits=32)
|
||||
'\x04\x00\x1f\xe5R\x00\x90\x00'
|
||||
>>> asm("mov r0, #SYS_select", arch = 'arm', os = 'linux', bits=32)
|
||||
'R\x00\xa0\xe3'
|
||||
"""
|
||||
result = ''
|
||||
|
||||
with context.local(**kwargs):
|
||||
assembler = _assembler()
|
||||
linker = _linker()
|
||||
objcopy = _objcopy() + ['-j', '.shellcode', '-Obinary']
|
||||
code = ''
|
||||
code += _arch_header()
|
||||
code += cpp(shellcode)
|
||||
assembler = _assembler()
|
||||
linker = _linker()
|
||||
objcopy = _objcopy() + ['-j', '.shellcode', '-Obinary']
|
||||
code = ''
|
||||
code += _arch_header()
|
||||
code += cpp(shellcode)
|
||||
|
||||
log.debug('Assembling\n%s' % code)
|
||||
log.debug('Assembling\n%s' % code)
|
||||
|
||||
tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-')
|
||||
step1 = path.join(tmpdir, 'step1')
|
||||
step2 = path.join(tmpdir, 'step2')
|
||||
step3 = path.join(tmpdir, 'step3')
|
||||
step4 = path.join(tmpdir, 'step4')
|
||||
tmpdir = tempfile.mkdtemp(prefix = 'pwn-asm-')
|
||||
step1 = path.join(tmpdir, 'step1')
|
||||
step2 = path.join(tmpdir, 'step2')
|
||||
step3 = path.join(tmpdir, 'step3')
|
||||
step4 = path.join(tmpdir, 'step4')
|
||||
|
||||
try:
|
||||
with open(step1, 'w') as fd:
|
||||
fd.write(code)
|
||||
try:
|
||||
with open(step1, 'w') as fd:
|
||||
fd.write(code)
|
||||
|
||||
_run(assembler + ['-o', step2, step1])
|
||||
_run(assembler + ['-o', step2, step1])
|
||||
|
||||
if not vma:
|
||||
shutil.copy(step2, step3)
|
||||
if not vma:
|
||||
shutil.copy(step2, step3)
|
||||
|
||||
if vma or not extract:
|
||||
ldflags = ['-z', 'execstack', '-o', step3, step2]
|
||||
if vma:
|
||||
_run(linker + ['--section-start=.shellcode=%#x' % vma,
|
||||
'--entry=%#x' % vma,
|
||||
'-o', step3, step2])
|
||||
ldflags += ['--section-start=.shellcode=%#x' % vma,
|
||||
'--entry=%#x' % vma,
|
||||
'-z', 'max-page-size=4096',
|
||||
'-z', 'common-page-size=4096']
|
||||
elif shared:
|
||||
ldflags += ['-shared', '-init=_start']
|
||||
_run(linker + ldflags)
|
||||
|
||||
elif file(step2,'rb').read(4) == '\x7fELF':
|
||||
# Sanity check for seeing if the output has relocations
|
||||
relocs = subprocess.check_output(
|
||||
[which_binutils('readelf'), '-r', step2]
|
||||
).strip()
|
||||
if len(relocs.split('\n')) > 1:
|
||||
log.error('Shellcode contains relocations:\n%s' % relocs)
|
||||
else:
|
||||
shutil.copy(step2, step3)
|
||||
|
||||
_run(objcopy + [step3, step4])
|
||||
|
||||
with open(step4) as fd:
|
||||
result = fd.read()
|
||||
|
||||
except Exception:
|
||||
log.exception("An error occurred while assembling:\n%s" % code)
|
||||
elif file(step2,'rb').read(4) == '\x7fELF':
|
||||
# Sanity check for seeing if the output has relocations
|
||||
relocs = subprocess.check_output(
|
||||
[which_binutils('readelf'), '-r', step2]
|
||||
).strip()
|
||||
if extract and len(relocs.split('\n')) > 1:
|
||||
log.error('Shellcode contains relocations:\n%s' % relocs)
|
||||
else:
|
||||
shutil.rmtree(tmpdir)
|
||||
return result
|
||||
shutil.copy(step2, step3)
|
||||
|
||||
def disasm(data, vma = 0, byte = True, offset = True, **kwargs):
|
||||
if not extract:
|
||||
return step3
|
||||
|
||||
_run(objcopy + [step3, step4])
|
||||
|
||||
with open(step4) as fd:
|
||||
result = fd.read()
|
||||
|
||||
except Exception:
|
||||
lines = '\n'.join('%4i: %s' % (i+1,line) for (i,line) in enumerate(code.splitlines()))
|
||||
log.exception("An error occurred while assembling:\n%s" % lines)
|
||||
else:
|
||||
atexit.register(lambda: shutil.rmtree(tmpdir))
|
||||
|
||||
return result
|
||||
|
||||
@LocalContext
|
||||
def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
|
||||
"""disasm(data, ...) -> str
|
||||
|
||||
Disassembles a bytestring into human readable assembler.
|
||||
@@ -547,53 +688,57 @@ def disasm(data, vma = 0, byte = True, offset = True, **kwargs):
|
||||
"""
|
||||
result = ''
|
||||
|
||||
with context.local(**kwargs):
|
||||
arch = context.arch
|
||||
os = context.os
|
||||
arch = context.arch
|
||||
os = context.os
|
||||
|
||||
tmpdir = tempfile.mkdtemp(prefix = 'pwn-disasm-')
|
||||
step1 = path.join(tmpdir, 'step1')
|
||||
step2 = path.join(tmpdir, 'step2')
|
||||
tmpdir = tempfile.mkdtemp(prefix = 'pwn-disasm-')
|
||||
step1 = path.join(tmpdir, 'step1')
|
||||
step2 = path.join(tmpdir, 'step2')
|
||||
|
||||
bfdarch = _bfdarch()
|
||||
bfdname = _bfdname()
|
||||
objdump = _objdump() + ['-d', '--adjust-vma', str(vma), '-b', bfdname]
|
||||
objcopy = _objcopy() + [
|
||||
'-I', 'binary',
|
||||
'-O', bfdname,
|
||||
'-B', bfdarch,
|
||||
'--set-section-flags', '.data=code',
|
||||
'--rename-section', '.data=.text',
|
||||
]
|
||||
bfdarch = _bfdarch()
|
||||
bfdname = _bfdname()
|
||||
objdump = _objdump() + ['-d', '--adjust-vma', str(vma), '-b', bfdname]
|
||||
objcopy = _objcopy() + [
|
||||
'-I', 'binary',
|
||||
'-O', bfdname,
|
||||
'-B', bfdarch,
|
||||
'--set-section-flags', '.data=code',
|
||||
'--rename-section', '.data=.text',
|
||||
]
|
||||
|
||||
if arch == 'thumb':
|
||||
objcopy += ['--prefix-symbol=$t.']
|
||||
else:
|
||||
objcopy += ['-w', '-N', '*']
|
||||
if arch == 'thumb':
|
||||
objcopy += ['--prefix-symbol=$t.']
|
||||
else:
|
||||
objcopy += ['-w', '-N', '*']
|
||||
|
||||
try:
|
||||
try:
|
||||
|
||||
with open(step1, 'w') as fd:
|
||||
fd.write(data)
|
||||
with open(step1, 'w') as fd:
|
||||
fd.write(data)
|
||||
|
||||
res = _run(objcopy + [step1, step2])
|
||||
res = _run(objcopy + [step1, step2])
|
||||
|
||||
output0 = subprocess.check_output(objdump + [step2])
|
||||
output1 = output0.split('<.text>:\n')
|
||||
output0 = subprocess.check_output(objdump + [step2])
|
||||
output1 = output0.split('<.text>:\n')
|
||||
|
||||
if len(output1) != 2:
|
||||
log.error('Could not find .text in objdump output:\n%s' % output0)
|
||||
if len(output1) != 2:
|
||||
log.error('Could not find .text in objdump output:\n%s' % output0)
|
||||
|
||||
result = output1[1].strip('\n').rstrip().expandtabs()
|
||||
except Exception:
|
||||
log.exception("An error occurred while disassembling:\n%s" % data)
|
||||
else:
|
||||
atexit.register(lambda: shutil.rmtree(tmpdir))
|
||||
|
||||
result = output1[1].strip('\n').rstrip().expandtabs()
|
||||
except Exception:
|
||||
log.exception("An error occurred while disassembling:\n%s" % data)
|
||||
else:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
lines = []
|
||||
pattern = '^( *[0-9a-f]+: *)((?:[0-9a-f]+ )+ *)(.*)'
|
||||
for line in result.splitlines():
|
||||
o, b, i = re.search(pattern, line).groups()
|
||||
try:
|
||||
o, b, i = re.search(pattern, line).groups()
|
||||
except:
|
||||
lines.append(line)
|
||||
continue
|
||||
|
||||
line = ''
|
||||
|
||||
@@ -601,7 +746,8 @@ def disasm(data, vma = 0, byte = True, offset = True, **kwargs):
|
||||
line += o
|
||||
if byte:
|
||||
line += b
|
||||
line += i
|
||||
if instructions:
|
||||
line += i
|
||||
lines.append(line)
|
||||
|
||||
return '\n'.join(lines)
|
||||
@@ -71,25 +71,23 @@ def _run_handlers():
|
||||
If a handler raises an exception, it will be printed but nothing else
|
||||
happens, i.e. other handlers will be run.
|
||||
"""
|
||||
context.clear()
|
||||
for _ident, (func, args, kwargs, ctx) in \
|
||||
sorted(_handlers.items(), reverse = True):
|
||||
try:
|
||||
with context.local(**ctx):
|
||||
with context.local():
|
||||
context.clear()
|
||||
context.update(**ctx)
|
||||
func(*args, **kwargs)
|
||||
except SystemExit:
|
||||
pass
|
||||
except:
|
||||
except Exception:
|
||||
# extract the current exception and rewind the traceback to where it
|
||||
# originated
|
||||
typ, val, tb = sys.exc_info()
|
||||
traceback.print_exception(typ, val, tb.tb_next)
|
||||
|
||||
# we rely on the existing excepthook to print exceptions
|
||||
if hasattr(sys, 'excepthook'):
|
||||
_oldhook = sys.excepthook
|
||||
else:
|
||||
_oldhook = None
|
||||
_oldhook = getattr(sys, 'excepthook', None)
|
||||
|
||||
def _newhook(typ, val, tb):
|
||||
"""_newhook(typ, val, tb)
|
||||
@@ -99,6 +97,7 @@ def _newhook(typ, val, tb):
|
||||
"""
|
||||
if _oldhook:
|
||||
_oldhook(typ, val, tb)
|
||||
_run_handlers()
|
||||
if _run_handlers:
|
||||
_run_handlers()
|
||||
|
||||
sys.excepthook = _newhook
|
||||
+1
-1
@@ -83,7 +83,7 @@ def _run_handlers():
|
||||
func(*args, **kwargs)
|
||||
except SystemExit:
|
||||
pass
|
||||
except:
|
||||
except Exception:
|
||||
# extract the current exception and rewind the traceback to where it
|
||||
# originated
|
||||
typ, val, tb = sys.exc_info()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#!/usr/bin/env python2
|
||||
@@ -6,8 +6,9 @@ from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Assemble shellcode into bytes'
|
||||
parser = common.parser_commands.add_parser(
|
||||
'asm',
|
||||
help = 'Assemble shellcode into bytes'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -20,7 +21,7 @@ parser.add_argument(
|
||||
parser.add_argument(
|
||||
"-f", "--format",
|
||||
help="Output format (defaults to hex for ttys, otherwise raw)",
|
||||
choices=['raw', 'hex', 'string']
|
||||
choices=['raw', 'hex', 'string', 'elf']
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -40,6 +41,28 @@ parser.add_argument(
|
||||
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-v', '--avoid',
|
||||
action='append',
|
||||
help = 'Encode the shellcode to avoid the listed bytes (provided as hex; default: 000a)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-n', '--newline',
|
||||
dest='avoid',
|
||||
action='append_const',
|
||||
const='\n',
|
||||
help = 'Encode the shellcode to avoid newlines'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-z', '--zero',
|
||||
dest='avoid',
|
||||
action='append_const',
|
||||
const='\x00',
|
||||
help = 'Encode the shellcode to avoid NULL bytes'
|
||||
)
|
||||
|
||||
|
||||
parser.add_argument(
|
||||
'-d',
|
||||
@@ -48,23 +71,57 @@ parser.add_argument(
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
parser.add_argument(
|
||||
'-e',
|
||||
'--encoder',
|
||||
help="Specific encoder to use"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-i',
|
||||
'--infile',
|
||||
help="Specify input file",
|
||||
default=sys.stdin,
|
||||
type=file
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-r',
|
||||
'--run',
|
||||
help="Run output",
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
def main(args):
|
||||
tty = args.output.isatty()
|
||||
|
||||
data = '\n'.join(args.lines) or sys.stdin.read()
|
||||
data = '\n'.join(args.lines) or args.infile.read()
|
||||
output = asm(data.replace(';', '\n'))
|
||||
fmt = args.format or ('hex' if tty else 'raw')
|
||||
formatters = {'r':str, 'h':enhex, 's':repr}
|
||||
|
||||
if args.avoid:
|
||||
output = encode(output, args.avoid)
|
||||
|
||||
if args.debug:
|
||||
proc = gdb.debug_shellcode(output, arch=context.arch)
|
||||
proc.interactive()
|
||||
sys.exit(0)
|
||||
|
||||
args.output.write(formatters[fmt[0]](output))
|
||||
if args.run:
|
||||
proc = run_shellcode(output)
|
||||
proc.interactive()
|
||||
sys.exit(0)
|
||||
|
||||
if fmt[0] == 'e':
|
||||
args.output.write(make_elf(output))
|
||||
try: os.fchmod(args.output.fileno(), 0700)
|
||||
except OSError: pass
|
||||
else:
|
||||
args.output.write(formatters[fmt[0]](output))
|
||||
|
||||
if tty and fmt is not 'raw':
|
||||
args.output.write('\n')
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -6,20 +6,34 @@ from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Check binary security settings'
|
||||
parser = common.parser_commands.add_parser(
|
||||
'checksec',
|
||||
help = 'Check binary security settings'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'elf',
|
||||
nargs='+',
|
||||
nargs='*',
|
||||
type=file,
|
||||
help='Files to check'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--file',
|
||||
nargs='*',
|
||||
dest='elf2',
|
||||
metavar='elf',
|
||||
type=file,
|
||||
help='File to check (for compatibility with checksec.sh)'
|
||||
)
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
for f in args.elf:
|
||||
def main(args):
|
||||
files = args.elf or args.elf2 or []
|
||||
|
||||
if not files:
|
||||
parser.print_usage()
|
||||
return
|
||||
|
||||
for f in files:
|
||||
e = ELF(f.name)
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -1,4 +1,9 @@
|
||||
from pwn import *
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
from pwnlib.context import context
|
||||
|
||||
pwnlib.log.console.stream = sys.stderr
|
||||
|
||||
@@ -17,3 +22,13 @@ def context_arg(arg):
|
||||
try: context.endian = arg
|
||||
except Exception: pass
|
||||
return arg
|
||||
|
||||
parser = argparse.ArgumentParser(description='Pwntools Command-line Interface',
|
||||
prog='pwn')
|
||||
parser_commands = parser.add_subparsers(dest='command')
|
||||
|
||||
def main(file=sys.argv[0]):
|
||||
import pwnlib.commandline.main
|
||||
name = os.path.splitext(os.path.basename(file))[0]
|
||||
sys.argv.insert(1, name)
|
||||
pwnlib.commandline.main.main()
|
||||
@@ -4,23 +4,20 @@ import argparse
|
||||
import os
|
||||
import re
|
||||
|
||||
import pwnlib.log
|
||||
from pwnlib import asm
|
||||
from pwnlib import constants
|
||||
from pwnlib.context import context
|
||||
from pwnlib.util import safeeval
|
||||
from pwn import *
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from . import common
|
||||
|
||||
p = argparse.ArgumentParser(
|
||||
description = "Looking up constants from header files.\n\nExample: constgrep -c freebsd -m ^PROT_ '3 + 4'",
|
||||
p = common.parser_commands.add_parser(
|
||||
'constgrep',
|
||||
help = "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(
|
||||
'-e', '--exact',
|
||||
metavar = '<constant name>',
|
||||
metavar = 'constant',
|
||||
# nargs = 1,
|
||||
default = None,
|
||||
help = 'Do an exact match for a constant instead of searching for a regex',
|
||||
@@ -53,33 +50,24 @@ p.add_argument(
|
||||
|
||||
p.add_argument(
|
||||
'-c', '--context',
|
||||
metavar = '<opt>',
|
||||
choices = context.oses + list(context.architectures),
|
||||
default = ['i386','linux'],
|
||||
metavar = 'arch_or_os',
|
||||
action = 'append',
|
||||
help = 'The os/architecture to find constants for (default: linux/i386), choose from: %s' % \
|
||||
', '.join(sorted(context.oses + context.architectures.keys()))
|
||||
type = common.context_arg,
|
||||
choices = common.choices,
|
||||
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
|
||||
)
|
||||
|
||||
def main():
|
||||
args = p.parse_args()
|
||||
|
||||
# Find the architecture and os from the list of contexts
|
||||
for arch in args.context[::-1]:
|
||||
if arch in context.architectures: break
|
||||
for os in args.context[::-1]:
|
||||
if os in context.oses: break
|
||||
|
||||
def main(args):
|
||||
if args.exact:
|
||||
# This is the simple case
|
||||
print asm.cpp(args.exact, os = os, arch = arch).strip()
|
||||
print cpp(args.exact).strip()
|
||||
else:
|
||||
# New we search in the right module.
|
||||
# But first: We find the right module
|
||||
if os == 'freebsd':
|
||||
if context.os == 'freebsd':
|
||||
mod = constants.freebsd
|
||||
else:
|
||||
mod = getattr(getattr(constants, os), arch)
|
||||
mod = getattr(getattr(constants, context.os), context.arch)
|
||||
|
||||
# Compile the given regex, for optimized lookup
|
||||
if args.case_insensitive:
|
||||
@@ -89,7 +77,10 @@ def main():
|
||||
|
||||
# Evaluate the given constant
|
||||
if args.constant:
|
||||
constant = safeeval.expr(args.constant)
|
||||
try:
|
||||
constant = safeeval.expr(args.constant)
|
||||
except:
|
||||
log.error("Could not evaluate constant %r" % args.constant)
|
||||
else:
|
||||
constant = None
|
||||
|
||||
@@ -122,7 +113,7 @@ def main():
|
||||
|
||||
# Output all matching constants
|
||||
for _, k in sorted(out):
|
||||
print '#define %s %s' % (k.ljust(maxlen), asm.cpp(k, os = os, arch = arch).strip())
|
||||
print '#define %s %s' % (k.ljust(maxlen), cpp(k).strip())
|
||||
|
||||
# If we are in match_mode, then try to find a combination of
|
||||
# constants that yield the exact given value
|
||||
@@ -143,4 +134,5 @@ def main():
|
||||
print
|
||||
print '(%s) == %s' % (' | '.join(k for v, k in good), args.constant)
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -3,17 +3,13 @@ import argparse
|
||||
import string
|
||||
import sys
|
||||
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.log import install_default_handler
|
||||
from pwnlib.util import cyclic
|
||||
from pwnlib.util import packing
|
||||
from pwn import *
|
||||
|
||||
install_default_handler()
|
||||
from . import common
|
||||
|
||||
log = getLogger('pwnlib.commandline.cyclic')
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = "Cyclic pattern creator/finder"
|
||||
parser = common.parser_commands.add_parser(
|
||||
'cyclic',
|
||||
help = "Cyclic pattern creator/finder"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -31,11 +27,20 @@ parser.add_argument(
|
||||
help = 'Size of the unique subsequences (defaults to 4).'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--context',
|
||||
metavar = 'context',
|
||||
action = 'append',
|
||||
type = common.context_arg,
|
||||
choices = common.choices,
|
||||
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
|
||||
)
|
||||
|
||||
group = parser.add_mutually_exclusive_group(required = True)
|
||||
group.add_argument(
|
||||
'-l', '-o', '--offset', '--lookup',
|
||||
dest = 'lookup',
|
||||
metavar = '<lookup value>',
|
||||
metavar = 'lookup_value',
|
||||
help = 'Do a lookup instead printing the alphabet',
|
||||
)
|
||||
|
||||
@@ -46,18 +51,17 @@ group.add_argument(
|
||||
help = 'Number of characters to print'
|
||||
)
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
def main(args):
|
||||
alphabet = args.alphabet
|
||||
subsize = args.length
|
||||
|
||||
if args.lookup:
|
||||
pat = args.lookup
|
||||
|
||||
if pat.startswith('0x'):
|
||||
pat = packing.pack(int(pat[2:], 16), subsize*8, 'little', False)
|
||||
elif pat.isdigit():
|
||||
pat = packing.pack(int(pat, 10), subsize*8, 'little', False)
|
||||
try:
|
||||
pat = packing.pack(int(pat, 0), subsize*8)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if len(pat) != subsize:
|
||||
log.critical('Subpattern must be %d bytes' % subsize)
|
||||
@@ -67,7 +71,7 @@ def main():
|
||||
log.critical('Pattern contains characters not present in the alphabet')
|
||||
sys.exit(1)
|
||||
|
||||
offset = cyclic.cyclic_find(pat, alphabet, subsize)
|
||||
offset = cyclic_find(pat, alphabet, subsize)
|
||||
|
||||
if offset == -1:
|
||||
log.critical('Given pattern does not exist in cyclic pattern')
|
||||
@@ -76,7 +80,7 @@ def main():
|
||||
print offset
|
||||
else:
|
||||
want = args.count
|
||||
result = cyclic.cyclic(want, alphabet, subsize)
|
||||
result = cyclic(want, alphabet, subsize)
|
||||
got = len(result)
|
||||
if got < want:
|
||||
log.failure("Alphabet too small (max length = %i)" % got)
|
||||
@@ -86,4 +90,5 @@ def main():
|
||||
if sys.stdout.isatty():
|
||||
sys.stdout.write('\n')
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -1,17 +1,15 @@
|
||||
#!/usr/bin/env python2
|
||||
import argparse
|
||||
import string
|
||||
import sys
|
||||
from string import hexdigits
|
||||
from string import whitespace
|
||||
|
||||
import pwnlib.log
|
||||
from pwnlib import asm
|
||||
from pwnlib.context import context
|
||||
from pwn import *
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from . import common
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Disassemble bytes into text format'
|
||||
parser = common.parser_commands.add_parser(
|
||||
'disasm',
|
||||
help = 'Disassemble bytes into text format'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -23,25 +21,71 @@ parser.add_argument(
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--context',
|
||||
metavar = '<opt>',
|
||||
choices = context.architectures,
|
||||
default = 'i386',
|
||||
help = 'The architecture of the shellcode (default: i386), choose from:\n%s' % ', '.join(context.architectures)
|
||||
metavar = 'arch_or_os',
|
||||
action = 'append',
|
||||
type = common.context_arg,
|
||||
choices = common.choices,
|
||||
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
|
||||
)
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
parser.add_argument(
|
||||
"-a","--address",
|
||||
metavar='address',
|
||||
help="Base address",
|
||||
type=str,
|
||||
default='0'
|
||||
)
|
||||
|
||||
|
||||
parser.add_argument(
|
||||
'--color',
|
||||
help="Color output",
|
||||
action='store_true',
|
||||
default=sys.stdout.isatty()
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--no-color',
|
||||
help="Disable color output",
|
||||
action='store_false',
|
||||
dest='color'
|
||||
)
|
||||
|
||||
|
||||
def main(args):
|
||||
if len(args.hex) > 0:
|
||||
dat = ''.join(args.hex)
|
||||
dat = dat.translate(None, whitespace)
|
||||
if not set(hexdigits) >= set(dat):
|
||||
dat = dat.translate(None, string.whitespace)
|
||||
if not set(string.hexdigits) >= set(dat):
|
||||
print "This is not a hex string"
|
||||
exit(-1)
|
||||
dat = dat.decode('hex')
|
||||
else:
|
||||
dat = sys.stdin.read()
|
||||
|
||||
print asm.disasm(dat, arch = args.context)
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if args.color:
|
||||
from pygments import highlight
|
||||
from pygments.formatters import TerminalFormatter
|
||||
from pwnlib.lexer import PwntoolsLexer
|
||||
|
||||
offsets = disasm(dat, vma=safeeval.const(args.address), instructions=False, byte=False)
|
||||
bytes = disasm(dat, vma=safeeval.const(args.address), instructions=False, offset=False)
|
||||
instrs = disasm(dat, vma=safeeval.const(args.address), byte=False, offset=False)
|
||||
# instrs = highlight(instrs, PwntoolsLexer(), TerminalFormatter())
|
||||
|
||||
split = lambda x: x.splitlines()
|
||||
for o,b,i in zip(*list(map(split, (offsets, bytes, instrs)))):
|
||||
b = b.replace('00', text.red('00'))
|
||||
b = b.replace('0a', text.red('0a'))
|
||||
i = highlight(i.strip(), PwntoolsLexer(), TerminalFormatter()).strip()
|
||||
i = i.replace(',',', ')
|
||||
|
||||
print o,b,i
|
||||
return
|
||||
|
||||
print disasm(dat, vma=safeeval.const(args.address))
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -1,13 +1,18 @@
|
||||
#!/usr/bin/env python2
|
||||
import shutil
|
||||
from argparse import ArgumentParser
|
||||
from subprocess import CalledProcessError
|
||||
from subprocess import check_output
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from pwn import *
|
||||
|
||||
def dump(x):
|
||||
from . import common
|
||||
|
||||
|
||||
def dump(objdump, path):
|
||||
n = NamedTemporaryFile(delete=False)
|
||||
o = check_output(['objdump','-d','-x','-s',x])
|
||||
o = check_output([objdump,'-d','-x','-s',path])
|
||||
n.write(o)
|
||||
n.flush()
|
||||
return n.name
|
||||
@@ -17,13 +22,36 @@ def diff(a,b):
|
||||
except CalledProcessError as e:
|
||||
return e.output
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'elfdiff',
|
||||
help = 'Compare two ELF files'
|
||||
)
|
||||
|
||||
p = ArgumentParser()
|
||||
p.add_argument('a')
|
||||
p.add_argument('b')
|
||||
|
||||
def main():
|
||||
a = p.parse_args()
|
||||
print diff(dump(a.a), dump(a.b))
|
||||
def main(a):
|
||||
with context.silent:
|
||||
x = ELF(a.a)
|
||||
y = ELF(a.b)
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if x.arch != y.arch:
|
||||
log.error("Architectures are not the same: %s vs %s" % (x.arch, y.arch))
|
||||
|
||||
context.arch = x.arch
|
||||
|
||||
objdump = pwnlib.asm.which_binutils('objdump')
|
||||
|
||||
tmp = NamedTemporaryFile()
|
||||
name = tmp.name
|
||||
|
||||
shutil.copy(x.path, name)
|
||||
x = dump(objdump, name)
|
||||
|
||||
shutil.copy(y.path, name)
|
||||
y = dump(objdump, name)
|
||||
|
||||
print diff(x, y)
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -2,11 +2,14 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import pwnlib.log
|
||||
from pwnlib.elf import ELF
|
||||
from pwnlib.util.fiddling import unhex
|
||||
from pwn import *
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from . import common
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'elfpatch',
|
||||
help = 'Patch an ELF file'
|
||||
)
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('elf',help="File to patch")
|
||||
@@ -14,17 +17,18 @@ p.add_argument('offset',help="Offset to patch in virtual address (hex encoded)")
|
||||
p.add_argument('bytes',help='Bytes to patch (hex encoded)')
|
||||
|
||||
|
||||
def main():
|
||||
a = p.parse_args()
|
||||
|
||||
def main(a):
|
||||
if not a.offset.startswith('0x'):
|
||||
a.offset = '0x' + a.offset
|
||||
|
||||
offset = int(a.offset, 16)
|
||||
bytes = unhex(a.bytes)
|
||||
elf = ELF(a.elf)
|
||||
|
||||
with context.silent:
|
||||
elf = ELF(a.elf)
|
||||
|
||||
elf.write(offset, bytes)
|
||||
sys.stdout.write(elf.get_data())
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -0,0 +1,45 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
from . import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'errno',
|
||||
help = 'Prints out error messages'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'error', help='Error message or value', type=str
|
||||
)
|
||||
|
||||
def main(args):
|
||||
try:
|
||||
value = int(args.error, 0)
|
||||
|
||||
if value < 0:
|
||||
value = -value
|
||||
|
||||
if 0x100000000 - value < 0x200:
|
||||
value = 0x100000000 - value
|
||||
|
||||
if value not in os.errno.errorcode:
|
||||
print "No errno for %s" % value
|
||||
return
|
||||
|
||||
name = os.errno.errorcode[value]
|
||||
|
||||
except ValueError:
|
||||
name = args.error.upper()
|
||||
|
||||
if not hasattr(os.errno, name):
|
||||
print "No errno for %s" % name
|
||||
return
|
||||
|
||||
value = getattr(os.errno, name)
|
||||
|
||||
|
||||
print '#define', name, value
|
||||
print os.strerror(value)
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -2,17 +2,21 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
parser = argparse.ArgumentParser(description='''
|
||||
Hex-encodes data provided on the command line or via stdin.
|
||||
from . import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'hex',
|
||||
help = '''
|
||||
Hex-encodes data provided on the command line or stdin
|
||||
''')
|
||||
parser.add_argument('data', nargs='*',
|
||||
help='Data to convert into hex')
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
def main(args):
|
||||
if not args.data:
|
||||
print sys.stdin.read().encode('hex')
|
||||
else:
|
||||
print ' '.join(args.data).encode('hex')
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -0,0 +1,42 @@
|
||||
from . import asm
|
||||
from . import checksec
|
||||
from . import common
|
||||
from . import constgrep
|
||||
from . import cyclic
|
||||
from . import disasm
|
||||
from . import elfdiff
|
||||
from . import elfpatch
|
||||
from . import errno
|
||||
from . import hex
|
||||
from . import phd
|
||||
from . import pwnstrip
|
||||
from . import scramble
|
||||
from . import shellcraft
|
||||
from . import unhex
|
||||
from . import update
|
||||
from .common import parser
|
||||
|
||||
commands = {
|
||||
'asm': asm.main,
|
||||
'checksec': checksec.main,
|
||||
'constgrep': constgrep.main,
|
||||
'cyclic': cyclic.main,
|
||||
'disasm': disasm.main,
|
||||
'elfdiff': elfdiff.main,
|
||||
'elfpatch': elfpatch.main,
|
||||
'errno': errno.main,
|
||||
'hex': hex.main,
|
||||
'phd': phd.main,
|
||||
'pwnstrip': pwnstrip.main,
|
||||
'scramble': scramble.main,
|
||||
'shellcraft': shellcraft.main,
|
||||
'unhex': unhex.main,
|
||||
'update': update.main,
|
||||
}
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
commands[args.command](args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+14
-44
@@ -1,17 +1,15 @@
|
||||
#!/usr/bin/env python2
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
import pwnlib.log
|
||||
import pwnlib.term.text as text
|
||||
from pwnlib.util.fiddling import hexdump_iter
|
||||
from pwn import *
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from . import common
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Pwnlib HexDump'
|
||||
parser = common.parser_commands.add_parser(
|
||||
'phd',
|
||||
help = 'Pwnlib HexDump'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -31,9 +29,7 @@ parser.add_argument(
|
||||
|
||||
parser.add_argument(
|
||||
"-l", "--highlight",
|
||||
help="Byte sequence to highlight. Use '?' to match arbitrary bytes and "\
|
||||
"'\\?' to match an actual question mark. Use '\\xXX' for non-"\
|
||||
"printable bytes.",
|
||||
help="Byte to highlight.",
|
||||
nargs="*",
|
||||
)
|
||||
|
||||
@@ -71,9 +67,7 @@ def asint(s):
|
||||
else:
|
||||
return int(s, 10)
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
def main(args):
|
||||
infile = args.file
|
||||
width = asint(args.width)
|
||||
skip = asint(args.skip)
|
||||
@@ -90,41 +84,17 @@ def main():
|
||||
else:
|
||||
infile.seek(skip, os.SEEK_CUR)
|
||||
|
||||
hl = []
|
||||
if args.highlight:
|
||||
def canon(hl):
|
||||
out = []
|
||||
i = 0
|
||||
while i < len(hl):
|
||||
c = hl[i]
|
||||
if c == '\\' and len(hl) > i + 1:
|
||||
c2 = hl[i + 1]
|
||||
if c2 == 'x':
|
||||
try:
|
||||
b = chr(int(hl[i + 2: i + 4], 16))
|
||||
except:
|
||||
print 'Bad escape sequence:', hl[i:]
|
||||
sys.exit(1)
|
||||
out.append(b)
|
||||
i += 3
|
||||
elif c2 in '\\?':
|
||||
out.append(c2)
|
||||
i += 1
|
||||
else:
|
||||
out.append(c)
|
||||
elif c == '?':
|
||||
out.append(None)
|
||||
else:
|
||||
out.append(c)
|
||||
i += 1
|
||||
return out
|
||||
highlight = map(canon, args.highlight)
|
||||
else:
|
||||
highlight = []
|
||||
for hs in args.highlight:
|
||||
for h in hs.split(','):
|
||||
hl.append(asint(h))
|
||||
|
||||
try:
|
||||
for line in hexdump_iter(infile, width, highlight = highlight, begin = offset + skip):
|
||||
for line in hexdump_iter(infile, width, highlight = hl, begin = offset + skip):
|
||||
print line
|
||||
except (KeyboardInterrupt, IOError):
|
||||
pass
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -0,0 +1,50 @@
|
||||
import argparse
|
||||
|
||||
from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'pwnstrip',
|
||||
help = 'Strip binaries for CTF usage',
|
||||
)
|
||||
|
||||
g = p.add_argument_group("actions")
|
||||
g.add_argument('-b', '--build-id', help="Strip build ID", action='store_true')
|
||||
g.add_argument('-p', '--patch', metavar='FUNCTION', help="Patch function", action='append')
|
||||
p.add_argument('-o', '--output', type=file, default=sys.stdout)
|
||||
p.add_argument('file', type=file)
|
||||
|
||||
def main(args):
|
||||
if not (args.patch or args.build_id):
|
||||
sys.stderr.write("Must specify at least one action\n")
|
||||
sys.stderr.write(p.format_usage())
|
||||
sys.exit(0)
|
||||
|
||||
elf = ELF(args.file.name)
|
||||
context.clear(arch=elf.arch)
|
||||
|
||||
if args.build_id:
|
||||
for offset in pwnlib.libcdb.get_build_id_offsets():
|
||||
data = elf.read(elf.address + offset + 0xC, 4)
|
||||
if data == 'GNU\x00':
|
||||
elf.write(elf.address + offset + 0x10, read('/dev/urandom', 20))
|
||||
|
||||
for function in args.patch:
|
||||
if function not in elf.symbols:
|
||||
log.error("Could not find function %r" % function)
|
||||
|
||||
trap = asm(shellcraft.trap())
|
||||
offset = elf.symbols[function]
|
||||
|
||||
elf.write(elf.address + offset, trap)
|
||||
|
||||
result = elf.data
|
||||
|
||||
if args.output.isatty():
|
||||
result = enhex(result)
|
||||
|
||||
args.output.write(result)
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -0,0 +1,104 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'scramble',
|
||||
help = 'Shellcode encoder'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-f", "--format",
|
||||
help="Output format (defaults to hex for ttys, otherwise raw)",
|
||||
choices=['raw', 'hex', 'string', 'elf']
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-o","--output",
|
||||
metavar='file',
|
||||
help="Output file (defaults to stdout)",
|
||||
type=argparse.FileType('w'),
|
||||
default=sys.stdout
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-c', '--context',
|
||||
metavar = 'context',
|
||||
action = 'append',
|
||||
type = common.context_arg,
|
||||
choices = common.choices,
|
||||
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-p', '--alphanumeric',
|
||||
action='store_true',
|
||||
help = 'Encode the shellcode with an alphanumeric encoder'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-v', '--avoid',
|
||||
action='append',
|
||||
help = 'Encode the shellcode to avoid the listed bytes'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-n', '--newline',
|
||||
dest='avoid',
|
||||
action='append_const',
|
||||
const='\n',
|
||||
help = 'Encode the shellcode to avoid newlines'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-z', '--zero',
|
||||
dest='avoid',
|
||||
action='append_const',
|
||||
const='\x00',
|
||||
help = 'Encode the shellcode to avoid NULL bytes'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-d',
|
||||
'--debug',
|
||||
help='Debug the shellcode with GDB',
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
def main(args):
|
||||
tty = args.output.isatty()
|
||||
|
||||
if sys.stdin.isatty():
|
||||
parser.print_usage()
|
||||
sys.exit(0)
|
||||
|
||||
data = sys.stdin.read()
|
||||
output = data
|
||||
fmt = args.format or ('hex' if tty else 'raw')
|
||||
formatters = {'r':str, 'h':enhex, 's':repr}
|
||||
|
||||
if args.alphanumeric:
|
||||
output = alphanumeric(output)
|
||||
|
||||
if args.avoid:
|
||||
output = avoid(output, ''.join(args.avoid))
|
||||
|
||||
if args.debug:
|
||||
proc = gdb.debug_shellcode(output, arch=context.arch)
|
||||
proc.interactive()
|
||||
sys.exit(0)
|
||||
|
||||
if fmt[0] == 'e':
|
||||
sys.stdout.write(make_elf(output))
|
||||
else:
|
||||
args.output.write(formatters[fmt[0]](output))
|
||||
|
||||
if tty and fmt is not 'raw':
|
||||
args.output.write('\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -8,18 +8,6 @@ from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
r = text.red
|
||||
g = text.green
|
||||
b = text.blue
|
||||
|
||||
banner = '\n'.join([' ' + r('____') + ' ' + g('_') + ' ' + r('_') + ' ' + g('_') + ' ' + b('__') + ' ' + r('_'),
|
||||
' ' + r('/ ___|') + g('| |__') + ' ' + b('___') + r('| |') + ' ' + g('|') + ' ' + b('___') + ' ' + r('_ __') + ' ' + g('__ _') + ' ' + b('/ _|') + ' ' + r('|_'),
|
||||
' ' + r('\___ \\') + g('| \'_ \\') + ' ' + b('/ _ \\') + ' ' + r('|') + ' ' + g('|') + b('/ __|') + ' ' + r('\'__/') + ' ' + g('_` |') + ' ' + b('|_') + r('| __|'),
|
||||
' ' + r('___) |') + ' ' + g('| | |') + ' ' + b('__/') + ' ' + r('|') + ' ' + g('|') + ' ' + b('(__') + r('| |') + ' ' + g('| (_| |') + ' ' + b('_|') + ' ' + r('|_'),
|
||||
' ' + r('|____/') + g('|_| |_|') + b('\\___|') + r('_|') + g('_|') + b('\\___|') + r('_|') + ' ' + g('\\__,_|') + b('_|') + ' ' + r('\\__|'),
|
||||
'\n'
|
||||
])
|
||||
|
||||
|
||||
# ____ _ _ _ __ _
|
||||
# / ___|| |__ ___| | | ___ _ __ __ _ / _| |_
|
||||
@@ -37,9 +25,10 @@ def _string(s):
|
||||
out.append('\\x%02x' % co)
|
||||
return '"' + ''.join(out) + '"\n'
|
||||
|
||||
p = argparse.ArgumentParser(
|
||||
description = 'Microwave shellcode -- Easy, fast and delicious',
|
||||
formatter_class = argparse.RawDescriptionHelpFormatter,
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'shellcraft',
|
||||
help = 'Microwave shellcode -- Easy, fast and delicious',
|
||||
)
|
||||
|
||||
|
||||
@@ -67,6 +56,7 @@ p.add_argument(
|
||||
'a', 'asm', 'assembly',
|
||||
'p',
|
||||
'i', 'hexii',
|
||||
'e', 'elf',
|
||||
'default'],
|
||||
default = 'default',
|
||||
help = 'Output format (default: hex), choose from {r}aw, {s}tring, {c}-style array, {h}ex string, hex{i}i, {a}ssembly code, {p}reprocssed code',
|
||||
@@ -75,13 +65,10 @@ p.add_argument(
|
||||
p.add_argument(
|
||||
'shellcode',
|
||||
nargs = '?',
|
||||
choices = shellcraft.templates,
|
||||
metavar = 'shellcode',
|
||||
help = 'The shellcode you want',
|
||||
type = str
|
||||
)
|
||||
|
||||
p.epilog = 'Available shellcodes are:\n' + '\n'.join(shellcraft.templates)
|
||||
|
||||
p.add_argument(
|
||||
'args',
|
||||
nargs = '*',
|
||||
@@ -97,25 +84,111 @@ p.add_argument(
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
def main():
|
||||
# Banner must be added here so that it doesn't appear in the autodoc
|
||||
# generation for command line tools
|
||||
p.description = banner + p.description
|
||||
args = p.parse_args()
|
||||
p.add_argument(
|
||||
'-b',
|
||||
'--before',
|
||||
help='Insert a debug trap before the code',
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
if not args.shellcode:
|
||||
print '\n'.join(shellcraft.templates)
|
||||
p.add_argument(
|
||||
'-a',
|
||||
'--after',
|
||||
help='Insert a debug trap after the code',
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'-v', '--avoid',
|
||||
action='append',
|
||||
help = 'Encode the shellcode to avoid the listed bytes'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'-n', '--newline',
|
||||
dest='avoid',
|
||||
action='append_const',
|
||||
const='\n',
|
||||
help = 'Encode the shellcode to avoid newlines'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'-z', '--zero',
|
||||
dest='avoid',
|
||||
action='append_const',
|
||||
const='\x00',
|
||||
help = 'Encode the shellcode to avoid NULL bytes'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'-r',
|
||||
'--run',
|
||||
help="Run output",
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'--color',
|
||||
help="Color output",
|
||||
action='store_true',
|
||||
default=sys.stdout.isatty()
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'--no-color',
|
||||
help="Disable color output",
|
||||
action='store_false',
|
||||
dest='color'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'--syscalls',
|
||||
help="List syscalls",
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'--address',
|
||||
help="Load address",
|
||||
default=None
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'-l', '--list',
|
||||
action='store_true',
|
||||
help='List available shellcodes, optionally provide a filter'
|
||||
)
|
||||
|
||||
def get_template(name):
|
||||
func = shellcraft
|
||||
for attr in name.split('.'):
|
||||
func = getattr(func, attr)
|
||||
return func
|
||||
|
||||
def is_not_a_syscall_template(name):
|
||||
template_src = shellcraft._get_source(name)
|
||||
return 'man 2' not in read(template_src)
|
||||
|
||||
def main(args):
|
||||
if args.list:
|
||||
templates = shellcraft.templates
|
||||
|
||||
if args.shellcode:
|
||||
templates = filter(lambda a: args.shellcode in a, templates)
|
||||
elif not args.syscalls:
|
||||
templates = filter(is_not_a_syscall_template, templates)
|
||||
|
||||
print '\n'.join(templates)
|
||||
exit()
|
||||
|
||||
if args.format == 'default':
|
||||
if sys.stdout.isatty():
|
||||
args.format = 'hex'
|
||||
else:
|
||||
args.format = 'raw'
|
||||
if not args.shellcode:
|
||||
common.parser.print_usage()
|
||||
exit()
|
||||
|
||||
func = shellcraft
|
||||
for attr in args.shellcode.split('.'):
|
||||
func = getattr(func, attr)
|
||||
if args.shellcode not in shellcraft.templates:
|
||||
log.error("Unknown shellcraft template %r. Use --list to see available shellcodes." % args.shellcode)
|
||||
|
||||
func = get_template(args.shellcode)
|
||||
|
||||
if args.show:
|
||||
# remove doctests
|
||||
@@ -184,18 +257,67 @@ def main():
|
||||
map(common.context_arg, args.shellcode.split('.'))
|
||||
code = func(*args.args)
|
||||
|
||||
|
||||
if args.before:
|
||||
code = shellcraft.trap() + code
|
||||
if args.after:
|
||||
code = code + shellcraft.trap()
|
||||
|
||||
|
||||
if args.format in ['a', 'asm', 'assembly']:
|
||||
if args.color:
|
||||
from pygments import highlight
|
||||
from pygments.formatters import TerminalFormatter
|
||||
from pwnlib.lexer import PwntoolsLexer
|
||||
|
||||
code = highlight(code, PwntoolsLexer(), TerminalFormatter())
|
||||
|
||||
print code
|
||||
exit()
|
||||
if args.format == 'p':
|
||||
print cpp(code)
|
||||
exit()
|
||||
|
||||
code = asm(code)
|
||||
assembly = code
|
||||
|
||||
vma = args.address
|
||||
if vma:
|
||||
vma = eval(vma)
|
||||
|
||||
if args.format in ['e','elf']:
|
||||
args.format = 'default'
|
||||
try: os.fchmod(args.out.fileno(), 0700)
|
||||
except OSError: pass
|
||||
|
||||
|
||||
if not args.avoid:
|
||||
code = read(make_elf_from_assembly(assembly, vma=vma))
|
||||
else:
|
||||
code = asm(assembly)
|
||||
code = encode(code, args.avoid)
|
||||
code = make_elf(code, vma=vma)
|
||||
# code = read(make_elf(encode(asm(code), args.avoid)))
|
||||
else:
|
||||
code = encode(asm(assembly), args.avoid)
|
||||
|
||||
if args.format == 'default':
|
||||
if args.out.isatty():
|
||||
args.format = 'hex'
|
||||
else:
|
||||
args.format = 'raw'
|
||||
|
||||
arch = args.shellcode.split('.')[0]
|
||||
|
||||
if args.debug:
|
||||
arch = args.shellcode.split('.')[0]
|
||||
proc = gdb.debug_shellcode(code, arch=arch)
|
||||
if not args.avoid:
|
||||
proc = gdb.debug_assembly(assembly, arch=arch, vma=vma)
|
||||
else:
|
||||
proc = gdb.debug_shellcode(code, arch=arch, vma=vma)
|
||||
proc.interactive()
|
||||
sys.exit(0)
|
||||
|
||||
if args.run:
|
||||
proc = run_shellcode(code, arch=arch)
|
||||
proc.interactive()
|
||||
sys.exit(0)
|
||||
|
||||
@@ -209,8 +331,9 @@ def main():
|
||||
code = hexii(code) + '\n'
|
||||
|
||||
if not sys.stdin.isatty():
|
||||
sys.stdout.write(sys.stdin.read())
|
||||
args.out.write(sys.stdin.read())
|
||||
|
||||
sys.stdout.write(code)
|
||||
args.out.write(code)
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -3,14 +3,18 @@ import argparse
|
||||
import sys
|
||||
from string import whitespace
|
||||
|
||||
parser = argparse.ArgumentParser(description='''
|
||||
from . import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'unhex',
|
||||
help = '''
|
||||
Decodes hex-encoded data provided on the command line or via stdin.
|
||||
''')
|
||||
|
||||
parser.add_argument('hex', nargs='*',
|
||||
help='Hex bytes to decode')
|
||||
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
def main(args):
|
||||
try:
|
||||
if not args.hex:
|
||||
s = sys.stdin.read().translate(None, whitespace)
|
||||
@@ -20,4 +24,5 @@ def main():
|
||||
except TypeError, e:
|
||||
sys.stderr.write(str(e) + '\n')
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python2
|
||||
import subprocess
|
||||
|
||||
from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
p = common.parser_commands.add_parser(
|
||||
'update',
|
||||
help = 'Check for pwntools updates'
|
||||
)
|
||||
|
||||
p.add_argument('--install', action='store_true', help='''
|
||||
Install the update automatically.
|
||||
''')
|
||||
|
||||
p.add_argument('--pre', action='store_true', help='''
|
||||
Check for pre-releases.
|
||||
''')
|
||||
|
||||
def main(a):
|
||||
result = pwnlib.update.perform_check(prerelease=a.pre)
|
||||
if a.install:
|
||||
subprocess.check_call(result, shell=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.common.main(__file__)
|
||||
@@ -46,6 +46,7 @@ from types import ModuleType
|
||||
|
||||
from ..context import context
|
||||
from ..util import safeeval
|
||||
from .constant import Constant
|
||||
|
||||
|
||||
class ConstantsModule(ModuleType):
|
||||
@@ -67,6 +68,8 @@ class ConstantsModule(ModuleType):
|
||||
True
|
||||
|
||||
"""
|
||||
Constant = Constant
|
||||
|
||||
possible_submodules = set(context.oses) | set(context.architectures)
|
||||
|
||||
def __init__(self, name, module):
|
||||
@@ -122,14 +125,14 @@ class ConstantsModule(ModuleType):
|
||||
Example:
|
||||
|
||||
>>> with context.local(arch = 'i386', os = 'linux'):
|
||||
... print constants.eval('SYS_execve + PROT_WRITE')
|
||||
13
|
||||
... print 13 == constants.eval('SYS_execve + PROT_WRITE')
|
||||
True
|
||||
>>> with context.local(arch = 'amd64', os = 'linux'):
|
||||
... print constants.eval('SYS_execve + PROT_WRITE')
|
||||
61
|
||||
... print 61 == constants.eval('SYS_execve + PROT_WRITE')
|
||||
True
|
||||
>>> with context.local(arch = 'amd64', os = 'linux'):
|
||||
... print constants.eval('SYS_execve + PROT_WRITE')
|
||||
61
|
||||
... print 61 == constants.eval('SYS_execve + PROT_WRITE')
|
||||
True
|
||||
"""
|
||||
if not isinstance(string, str):
|
||||
return string
|
||||
@@ -138,7 +141,7 @@ class ConstantsModule(ModuleType):
|
||||
if key not in self._env_store:
|
||||
self._env_store[key] = {key: getattr(self, key) for key in dir(self) if not key.endswith('__')}
|
||||
|
||||
return safeeval.values(string, self._env_store[key])
|
||||
return Constant('(%s)' % string, safeeval.values(string, self._env_store[key]))
|
||||
|
||||
|
||||
# To prevent garbage collection
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
linux
|
||||
Whitespace-only changes.
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
thumb.py
|
||||
Loaded 100 of 3374 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user