mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-08 01:58:16 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c804d49d0 | ||
|
|
cde19135eb | ||
|
|
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/
|
||||
+4
-1
@@ -3,6 +3,7 @@
|
||||
*.pyc
|
||||
*~
|
||||
*.swp
|
||||
.ropeproject
|
||||
*.pdf
|
||||
*/auto/*
|
||||
*/bin/*
|
||||
@@ -10,4 +11,6 @@ docs/build
|
||||
build
|
||||
MANIFEST
|
||||
dist
|
||||
pwntools.egg-info
|
||||
*.egg-info
|
||||
*.core
|
||||
.coverage
|
||||
@@ -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
|
||||
}
|
||||
+14
-7
@@ -1,5 +1,10 @@
|
||||
sudo: false
|
||||
language: python
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
- gcc-4.6-arm-linux-gnueabihf
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
@@ -8,16 +13,18 @@ cache:
|
||||
- /home/travis/virtualenv/python2.7.9/bin/
|
||||
python:
|
||||
- "2.7"
|
||||
after_success:
|
||||
- coveralls
|
||||
before_install:
|
||||
- source .travis_ssh_setup.sh
|
||||
- source .travis_install.sh
|
||||
- source .travis_ssh_setup.sh
|
||||
install:
|
||||
- pip install -e .
|
||||
- pip install -r 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
|
||||
+33
-7
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env bash -e
|
||||
local_deb_extract()
|
||||
{
|
||||
wget $1
|
||||
ar vx *.deb
|
||||
tar xvf data.tar.gz
|
||||
rm -f *.tar.gz *deb*
|
||||
tar xvf data.tar.*
|
||||
rm -f *.tar.* *deb*
|
||||
}
|
||||
|
||||
get_binutils()
|
||||
@@ -14,20 +14,37 @@ get_binutils()
|
||||
local_deb_extract "${BINUTILS_PREFIX}${1}${BINUTILS_SUFFIX}"
|
||||
}
|
||||
|
||||
get_qemu()
|
||||
{
|
||||
echo "Installing qemu"
|
||||
QEMU_URL='https://mirrors.kernel.org/ubuntu/pool/universe/q/qemu/qemu-user-static_2.6%2bdfsg-3ubuntu1_amd64.deb'
|
||||
local_deb_extract "$QEMU_URL"
|
||||
}
|
||||
|
||||
setup_travis()
|
||||
{
|
||||
export PATH=$PWD/usr/bin:$PATH
|
||||
export LD_LIBRARY_PATH=$PWD/usr/lib
|
||||
|
||||
if [ ! -d usr/bin ];
|
||||
if [ ! -d usr/bin ];
|
||||
then
|
||||
# Install our custom binutils
|
||||
which arm-linux-as || get_binutils arm
|
||||
which mips-linux-as || get_binutils mips
|
||||
which powerpc-linux-as || get_binutils powerpc
|
||||
which aarch64-linux-as || get_binutils aarch64
|
||||
|
||||
# Install the multiarch binutils
|
||||
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
|
||||
|
||||
if ! (which qemu-arm-static && qemu-arm-static -version | grep 2.6.0); then
|
||||
get_qemu
|
||||
fi
|
||||
|
||||
# Get rid of files we don't want cached
|
||||
rm -rf usr/share
|
||||
|
||||
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
|
||||
@@ -36,11 +53,13 @@ setup_travis()
|
||||
which arm-linux-gnu-as
|
||||
which mips-linux-gnu-as
|
||||
which powerpc-linux-gnu-as
|
||||
which aarch64-linux-gnu-as
|
||||
which qemu-arm-static
|
||||
}
|
||||
|
||||
setup_linux()
|
||||
{
|
||||
sudo apt-get install software-properties-common pwgen
|
||||
sudo apt-get install -y software-properties-common openssh-server libncurses5-dev libncursesw5-dev
|
||||
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
|
||||
@@ -53,10 +72,17 @@ setup_osx()
|
||||
brew install capstone
|
||||
}
|
||||
|
||||
if [[ "$TRAVIS" ]]; then
|
||||
if [[ "$USER" == "travis" ]]; then
|
||||
setup_travis
|
||||
elif [[ "$USER" == "shippable" ]]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install openssh-server gcc-multilib
|
||||
sudo /usr/sbin/sshd -f /etc/ssh/sshd_config &
|
||||
setup_travis
|
||||
elif [[ "$(uname)" == "Darwin" ]]; then
|
||||
setup_osx
|
||||
elif [[ "$(uname)" == "Linux" ]]; then
|
||||
setup_linux
|
||||
fi
|
||||
|
||||
dpkg -l
|
||||
@@ -2,12 +2,14 @@
|
||||
#
|
||||
# Install a demo user for SSH purposes
|
||||
#
|
||||
# All of the "conditional sudo" is to do container-based builds on
|
||||
# Travis which are much, much faster.
|
||||
U=travis
|
||||
H=/home/$U
|
||||
|
||||
USUDO()
|
||||
{
|
||||
if [ "$TRAVIS" ];
|
||||
if [[ "$USER" == "travis" ]];
|
||||
then
|
||||
$*
|
||||
else
|
||||
@@ -16,7 +18,7 @@ fi
|
||||
}
|
||||
|
||||
|
||||
if [ "$TRAVIS" ];
|
||||
if [[ "$USER" == "travis" ]];
|
||||
then
|
||||
rm -f ~/.ssh/*
|
||||
else
|
||||
@@ -44,10 +46,9 @@ EOF
|
||||
cat >> ~/.ssh/config <<EOF
|
||||
|
||||
Host example.pwnme
|
||||
User travis
|
||||
User $U
|
||||
HostName 127.0.0.1
|
||||
IdentityFile ~/.ssh/$U
|
||||
EOF
|
||||
|
||||
ssh-keyscan -t rsa example.pwnme >>~/.ssh/known_hosts
|
||||
ssh -o "StrictHostKeyChecking no" -v [email protected] id
|
||||
ssh -o "StrictHostKeyChecking no" -vvvv [email protected] id
|
||||
+103
@@ -3,6 +3,109 @@
|
||||
This changelog only includes added major features and changes. Bugfixes and
|
||||
minor changes are omitted.
|
||||
|
||||
## 3.0.1 (August 20 2016)
|
||||
|
||||
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 (August 20 2016)
|
||||
|
||||
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.termianl` 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).
|
||||
@@ -1,14 +1,16 @@
|
||||

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

|
||||
|
||||
[](https://pwntools.readthedocs.org/en/latest)
|
||||
[](https://pwntools.readthedocs.org/)
|
||||
[](https://pwntools.readthedocs.org/en/2.2.0)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://www.gittip.com/gallopsled/)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||
[](https://twitter.com/Gallopsled)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=stable)
|
||||
[](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 +22,32 @@ 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](http://demo.pwntools.com). Alternately, you can SSH to the same host, and log in as user `zerocool` with [this private key][key] (password `i_promise_not_to_be_evil`).
|
||||
|
||||
It will drop you into a clean, Docker-ized container. There is nothing of value on the VPS, so please don't be evil.
|
||||
|
||||
[key]: https://gist.githubusercontent.com/zachriggle/efa2e0080ae6de2e8344/raw/4b503e9db54f009d97477d03d4ba5678471f8ff0/id_rsa
|
||||
|
||||
# Documentation
|
||||
Our documentation is available at [pwntools.readthedocs.org](https://pwntools.readthedocs.org/en/latest/)
|
||||
Our documentation is available at [pwntools.readthedocs.org](https://pwntools.readthedocs.org/)
|
||||
|
||||
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 git+https://github.com/Gallopsled/pwntools.git
|
||||
```
|
||||
|
||||
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://pwntools.readthedocs.org/en/latest/install.html).
|
||||
|
||||
|
||||
# Contribution
|
||||
@@ -53,7 +55,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.
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
# 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 -e .
|
||||
pip install -r docs/requirements.txt
|
||||
cd docs
|
||||
PWNLIB_NOTERM=1 make clean 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,9 @@
|
||||
.. testsetup:: *
|
||||
|
||||
from pwn import *
|
||||
|
||||
:mod:`pwnlib.adb` --- Android Debug Bridge
|
||||
=====================================================
|
||||
|
||||
.. automodule:: pwnlib.adb
|
||||
: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
|
||||
|
||||
@@ -17,6 +17,9 @@ pwntools comes with a handful of useful command-line utilities which serve as wr
|
||||
.. autoprogram:: pwnlib.commandline.asm:parser
|
||||
:prog: asm
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.checksec:parser
|
||||
:prog: checksec
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.constgrep:p
|
||||
:prog: constgrep
|
||||
|
||||
@@ -32,12 +35,21 @@ pwntools comes with a handful of useful command-line utilities which serve as wr
|
||||
.. autoprogram:: pwnlib.commandline.elfpatch:p
|
||||
:prog: elfpatch
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.errno:parser
|
||||
:prog: errno
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.hex:parser
|
||||
:prog: hex
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.phd:parser
|
||||
:prog: phd
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.pwnstrip:p
|
||||
:prog: pwnstrip
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.scramble:parser
|
||||
:prog: scramble
|
||||
|
||||
.. autoprogram:: pwnlib.commandline.shellcraft:p
|
||||
:prog: shellcraft
|
||||
|
||||
|
||||
+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'2015, Zach Riggle'
|
||||
|
||||
# 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'2015, Zach Riggle', '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'2015, Zach Riggle'], 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 *
|
||||
import tempfile
|
||||
|
||||
:mod:`pwnlib.fmtstr` --- Format string bug exploitation tools
|
||||
=============================================================
|
||||
|
||||
.. automodule:: pwnlib.fmtstr
|
||||
:members:
|
||||
@@ -28,19 +28,24 @@ Each of the ``pwntools`` modules is documented here.
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
adb
|
||||
asm
|
||||
atexception
|
||||
atexit
|
||||
constants
|
||||
context
|
||||
dynelf
|
||||
encoders
|
||||
elf
|
||||
exception
|
||||
fmtstr
|
||||
gdb
|
||||
log
|
||||
memleak
|
||||
replacements
|
||||
rop
|
||||
rop/*
|
||||
runner
|
||||
shellcraft
|
||||
shellcraft/*
|
||||
term
|
||||
@@ -51,6 +56,11 @@ Each of the ``pwntools`` modules is documented here.
|
||||
useragents
|
||||
util/*
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
testexample
|
||||
|
||||
.. only:: not dash
|
||||
|
||||
Indices and tables
|
||||
|
||||
@@ -20,21 +20,22 @@ 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 git+https://github.com/Gallopsled/pwntools.git
|
||||
|
||||
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
|
||||
$ cd pwntools
|
||||
$ pip install -e .
|
||||
|
||||
.. _Ubuntu: https://launchpad.net/~pwntools/+archive/ubuntu/binutils
|
||||
@@ -58,8 +58,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 +77,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'
|
||||
'6a3158cd8089c36a465889d9cd806a045b6a0359496a3f58cd8075f86a68682f2f2f73682f62696e6a0b5889e331c999cd80'
|
||||
|
||||
|
||||
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
|
||||
===========================================================
|
||||
|
||||
@@ -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,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,6 +4,7 @@ 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
############################################################
|
||||
# Dockerfile to build Pwntools container
|
||||
# Based on Ubuntu
|
||||
############################################################
|
||||
|
||||
FROM ubuntu:trusty
|
||||
MAINTAINER Maintainer Zach Riggle
|
||||
|
||||
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()
|
||||
+21
-10
@@ -1,9 +1,11 @@
|
||||
# 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 string
|
||||
import struct
|
||||
import subprocess
|
||||
@@ -13,30 +15,29 @@ import threading
|
||||
import time
|
||||
|
||||
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.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
|
||||
from pwnlib.tubes.serialtube import serialtube
|
||||
from pwnlib.tubes.ssh import ssh
|
||||
from pwnlib.tubes.tube import tube
|
||||
@@ -48,6 +49,7 @@ 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 *
|
||||
@@ -56,6 +58,8 @@ from pwnlib.util.proc import pidof
|
||||
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 +69,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)
|
||||
+723
@@ -0,0 +1,723 @@
|
||||
"""Provides utilities for interacting with Android devices via the Android Debug Bridge.
|
||||
"""
|
||||
import glob
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import dateutil.parser
|
||||
|
||||
from . import atexit
|
||||
from . import tubes
|
||||
from .context import context
|
||||
from .context import LocalContext
|
||||
from .device import Device
|
||||
from .log import getLogger
|
||||
from .util import misc
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
def adb(argv, *a, **kw):
|
||||
"""Returns the output of an ADB subcommand."""
|
||||
if isinstance(argv, (str, unicode)):
|
||||
argv = [argv]
|
||||
|
||||
log.debug("$ " + ' '.join(context.adb + argv))
|
||||
|
||||
return tubes.process.process(context.adb + argv, *a, **kw).recvall()
|
||||
|
||||
def root():
|
||||
"""Restarts adbd as root."""
|
||||
log.info("Enabling root on %s" % context.device)
|
||||
|
||||
with context.quiet:
|
||||
reply = adb('root')
|
||||
|
||||
if 'already running as root' in reply:
|
||||
return
|
||||
|
||||
elif not reply or 'restarting adbd as root' in reply:
|
||||
with context.quiet:
|
||||
wait_for_device()
|
||||
|
||||
else:
|
||||
log.error("Could not run as root:\n%s" % reply)
|
||||
|
||||
|
||||
def reboot(wait=True):
|
||||
"""Reboots the device."""
|
||||
log.info('Rebooting device %s' % context.device)
|
||||
|
||||
with context.quiet:
|
||||
adb('reboot')
|
||||
|
||||
if wait:
|
||||
wait_for_device()
|
||||
|
||||
def reboot_bootloader():
|
||||
"""Reboots the device to the bootloader."""
|
||||
log.info('Rebooting %s to bootloader' % context.device)
|
||||
|
||||
with context.quiet:
|
||||
adb('reboot-bootloader')
|
||||
|
||||
class AdbDevice(Device):
|
||||
"""Encapsulates information about a connected device."""
|
||||
def __init__(self, serial, type, port, product='unknown', model='unknown', device='unknown'):
|
||||
self.serial = serial
|
||||
self.type = type
|
||||
self.port = port
|
||||
self.product = product
|
||||
self.model = model.replace('_', ' ')
|
||||
self.device = device
|
||||
|
||||
if product == 'unknown':
|
||||
return
|
||||
|
||||
with context.local(device=serial):
|
||||
abi = str(properties.ro.product.cpu.abi)
|
||||
context.clear()
|
||||
context.arch = str(abi)
|
||||
self.arch = context.arch
|
||||
self.bits = context.bits
|
||||
self.endian = context.endian
|
||||
|
||||
def __str__(self):
|
||||
return self.serial
|
||||
|
||||
def __repr__(self):
|
||||
fields = ['serial', 'type', 'port', 'product', 'model', 'device']
|
||||
return '%s(%s)' % (self.__class__.__name__,
|
||||
', '.join(('%s=%r' % (field, getattr(self, field)) for field in fields)))
|
||||
|
||||
@staticmethod
|
||||
def from_adb_output(line):
|
||||
fields = line.split()
|
||||
|
||||
"""
|
||||
Example output:
|
||||
ZX1G22LM7G device usb:336789504X product:shamu model:Nexus_6 device:shamu features:cmd,shell_v2
|
||||
84B5T15A29020449 device usb:336855040X product:angler model:Nexus_6P device:angler
|
||||
0062741b0e54b353 unauthorized usb:337641472X
|
||||
"""
|
||||
|
||||
# The last few fields need to be split at colons.
|
||||
split = lambda x: x.split(':')[-1]
|
||||
fields[3:] = list(map(split, fields[3:]))
|
||||
|
||||
return AdbDevice(*fields[:6])
|
||||
|
||||
@context.quiet
|
||||
def devices(serial=None):
|
||||
"""Returns a list of ``Device`` objects corresponding to the connected devices."""
|
||||
lines = adb(['devices', '-l'])
|
||||
result = []
|
||||
|
||||
for line in lines.splitlines():
|
||||
# Skip the first 'List of devices attached' line, and the final empty line.
|
||||
if 'List of devices' in line or not line.strip():
|
||||
continue
|
||||
device = AdbDevice.from_adb_output(line)
|
||||
if device.serial == serial:
|
||||
return device
|
||||
result.append(device)
|
||||
|
||||
return tuple(result)
|
||||
|
||||
@LocalContext
|
||||
def wait_for_device(kick=False):
|
||||
"""Waits for a device to be connected."""
|
||||
with log.waitfor("Waiting for device to come online") as w:
|
||||
with context.quiet:
|
||||
if kick:
|
||||
try:
|
||||
adb(['reconnect'])
|
||||
except Exception:
|
||||
pass
|
||||
adb('wait-for-device')
|
||||
|
||||
for device in devices():
|
||||
if context.device == device:
|
||||
return device
|
||||
break
|
||||
else:
|
||||
log.error("Could not find any devices")
|
||||
|
||||
with context.local(device=device):
|
||||
# There may be multiple devices, so context.device is
|
||||
# insufficient. Pick the first device reported.
|
||||
w.success('%s (%s %s %s)' % (device,
|
||||
product(),
|
||||
build(),
|
||||
_build_date()))
|
||||
|
||||
return context.device
|
||||
|
||||
def disable_verity():
|
||||
"""Disables dm-verity on the device."""
|
||||
with log.waitfor("Disabling dm-verity on %s" % context.device) as w:
|
||||
root()
|
||||
|
||||
with context.quiet:
|
||||
reply = adb('disable-verity')
|
||||
|
||||
if 'Verity already disabled' in reply:
|
||||
return
|
||||
elif 'Now reboot your device' in reply:
|
||||
reboot(wait=True)
|
||||
else:
|
||||
log.error("Could not disable verity:\n%s" % reply)
|
||||
|
||||
|
||||
def remount():
|
||||
"""Remounts the filesystem as writable."""
|
||||
with log.waitfor("Remounting filesystem on %s" % context.device) as w:
|
||||
disable_verity()
|
||||
root()
|
||||
|
||||
with context.quiet:
|
||||
reply = adb('remount')
|
||||
|
||||
if 'remount succeeded' not in reply:
|
||||
log.error("Could not remount filesystem:\n%s" % reply)
|
||||
|
||||
def unroot():
|
||||
"""Restarts adbd as AID_SHELL."""
|
||||
log.info("Unrooting %s" % context.device)
|
||||
with context.quiet:
|
||||
reply = adb('unroot')
|
||||
|
||||
if 'restarting adbd as non root' not in reply:
|
||||
log.error("Could not run as root:\n%s" % reply)
|
||||
|
||||
def pull(remote_path, local_path=None):
|
||||
"""Download a file from the device.
|
||||
|
||||
Arguments:
|
||||
remote_path(str): Path or directory of the file on the device.
|
||||
local_path(str): Path to save the file to.
|
||||
Uses the file's name by default.
|
||||
"""
|
||||
if local_path is None:
|
||||
local_path = os.path.basename(remote_path)
|
||||
|
||||
msg = "Pulling %r from %r" % (remote_path, local_path)
|
||||
|
||||
if context.log_level == 'debug':
|
||||
msg += ' (%s)' % context.device
|
||||
|
||||
result = ''
|
||||
with log.waitfor(msg) as w:
|
||||
with context.quiet:
|
||||
args = context.adb + ['pull', remote_path, local_path]
|
||||
io = tubes.process.process(args)
|
||||
result = io.recvall()
|
||||
|
||||
if 0 != io.poll(block=True):
|
||||
log.error(result)
|
||||
|
||||
return result
|
||||
|
||||
def push(local_path, remote_path):
|
||||
"""Upload a file to the device.
|
||||
|
||||
Arguments:
|
||||
local_path(str): Path to the local file to push.
|
||||
remote_path(str): Path or directory to store the file on the device.
|
||||
"""
|
||||
msg = "Pushing %r to %r" % (local_path, remote_path)
|
||||
|
||||
if context.log_level == 'debug':
|
||||
msg += ' (%s)' % context.device
|
||||
|
||||
with log.waitfor(msg) as w:
|
||||
with context.quiet:
|
||||
args = context.adb + ['push', local_path, remote_path]
|
||||
io = tubes.process.process(args)
|
||||
result = io.recvall()
|
||||
|
||||
if 0 != io.poll(block=True):
|
||||
log.error(result)
|
||||
|
||||
return result
|
||||
|
||||
@context.quiet
|
||||
def read(path, target=None):
|
||||
"""Download a file from the device, and extract its contents.
|
||||
|
||||
Arguments:
|
||||
path(str): Path to the file on the device.
|
||||
target(str): Optional, location to store the file.
|
||||
Uses a temporary file by default.
|
||||
"""
|
||||
with tempfile.NamedTemporaryFile() as temp:
|
||||
target = target or temp.name
|
||||
pull(path, target)
|
||||
result = misc.read(target)
|
||||
return result
|
||||
|
||||
@context.quiet
|
||||
def write(path, data=''):
|
||||
"""Create a file on the device with the provided contents.
|
||||
|
||||
Arguments:
|
||||
path(str): Path to the file on the device
|
||||
data(str): Contents to store in the file
|
||||
"""
|
||||
with tempfile.NamedTemporaryFile() as temp:
|
||||
misc.write(temp.name, data)
|
||||
push(temp.name, path)
|
||||
|
||||
def process(argv, *a, **kw):
|
||||
"""Execute a process on the device.
|
||||
|
||||
See ``pwnlib.tubes.process.process`` documentation for more info.
|
||||
|
||||
Returns:
|
||||
A ``process`` tube.
|
||||
"""
|
||||
argv = argv or []
|
||||
if isinstance(argv, (str, unicode)):
|
||||
argv = [argv]
|
||||
|
||||
display = argv
|
||||
argv = context.adb + ['shell'] + argv
|
||||
|
||||
kw.setdefault('display', display)
|
||||
kw.setdefault('where', 'Android')
|
||||
|
||||
return tubes.process.process(argv, *a, **kw)
|
||||
|
||||
def interactive(**kw):
|
||||
"""Spawns an interactive shell."""
|
||||
return shell(**kw).interactive()
|
||||
|
||||
def shell(**kw):
|
||||
"""Returns an interactive shell."""
|
||||
return process([], **kw)
|
||||
|
||||
@context.quiet
|
||||
def which(name):
|
||||
"""Retrieves the full path to a binary in ``PATH`` on the device"""
|
||||
return process(['which', name]).recvall().strip()
|
||||
|
||||
def whoami():
|
||||
return process(['whoami']).recvall().strip()
|
||||
|
||||
def forward(port):
|
||||
"""Sets up a port to forward to the device."""
|
||||
tcp_port = 'tcp:%s' % port
|
||||
start_forwarding = adb(['forward', tcp_port, tcp_port])
|
||||
atexit.register(lambda: adb(['forward', '--remove', tcp_port]))
|
||||
|
||||
@context.quiet
|
||||
def logcat(stream=False):
|
||||
"""Reads the system log file.
|
||||
|
||||
By default, causes logcat to exit after reading the file.
|
||||
|
||||
Arguments:
|
||||
stream(bool): If ``True``, the contents are streamed rather than
|
||||
read in a one-shot manner. Default is ``False``.
|
||||
|
||||
Returns:
|
||||
If ``stream`` is ``False``, returns a string containing the log data.
|
||||
Otherwise, it returns a ``tube`` connected to the log output.
|
||||
"""
|
||||
|
||||
if stream:
|
||||
return process(['logcat'])
|
||||
else:
|
||||
return adb(['logcat', '-d'])
|
||||
|
||||
def pidof(name):
|
||||
"""Returns a list of PIDs for the named process."""
|
||||
with context.quiet:
|
||||
io = process(['pidof', name])
|
||||
data = io.recvall().split()
|
||||
return list(map(int, data))
|
||||
|
||||
def proc_exe(pid):
|
||||
"""Returns the full path of the executable for the provided PID."""
|
||||
with context.quiet:
|
||||
io = process(['readlink','-e','/proc/%d/exe' % pid])
|
||||
data = io.recvall().strip()
|
||||
return data
|
||||
|
||||
def getprop(name=None):
|
||||
"""Reads a properties from the system property store.
|
||||
|
||||
Arguments:
|
||||
name(str): Optional, read a single property.
|
||||
|
||||
Returns:
|
||||
If ``name`` is not specified, a ``dict`` of all properties is returned.
|
||||
Otherwise, a string is returned with the contents of the named property.
|
||||
"""
|
||||
with context.quiet:
|
||||
if name:
|
||||
return process(['getprop', name]).recvall().strip()
|
||||
|
||||
|
||||
result = process(['getprop']).recvall()
|
||||
|
||||
expr = r'\[([^\]]+)\]: \[(.*)\]'
|
||||
|
||||
props = {}
|
||||
|
||||
for line in result.splitlines():
|
||||
if not line.startswith('['):
|
||||
continue
|
||||
|
||||
name, value = re.search(expr, line).groups()
|
||||
|
||||
if value.isdigit():
|
||||
value = int(value)
|
||||
|
||||
props[name] = value
|
||||
|
||||
return props
|
||||
|
||||
def setprop(name, value):
|
||||
"""Writes a property to the system property store."""
|
||||
return process(['setprop', name, value]).recvall().strip()
|
||||
|
||||
def listdir(directory='/'):
|
||||
"""Returns a list containing the entries in the provided directory.
|
||||
|
||||
Note:
|
||||
Because ``adb shell`` is used to retrieve the listing, shell
|
||||
environment variable expansion and globbing are in effect.
|
||||
"""
|
||||
io = process(['find', directory, '-maxdepth', '1', '-print0'])
|
||||
data = io.recvall()
|
||||
paths = filter(len, data.split('\x00'))
|
||||
relpaths = [os.path.relpath(path, directory) for path in paths]
|
||||
if '.' in relpaths:
|
||||
relpaths.remove('.')
|
||||
return relpaths
|
||||
|
||||
def fastboot(args, *a, **kw):
|
||||
"""Executes a fastboot command.
|
||||
|
||||
Returns:
|
||||
The command output.
|
||||
"""
|
||||
serial = context.device
|
||||
if not serial:
|
||||
log.error("Unknown device")
|
||||
return tubes.process.process(['fastboot', '-s', serial] + list(args), **kw).recvall()
|
||||
|
||||
def fingerprint():
|
||||
"""Returns the device build fingerprint."""
|
||||
return str(properties.ro.build.fingerprint)
|
||||
|
||||
def product():
|
||||
"""Returns the device product identifier."""
|
||||
return str(properties.ro.build.product)
|
||||
|
||||
def build():
|
||||
"""Returns the Build ID of the device."""
|
||||
return str(properties.ro.build.id)
|
||||
|
||||
def unlock_bootloader():
|
||||
"""Unlocks the bootloader of the device.
|
||||
|
||||
Note:
|
||||
This requires physical interaction with the device.
|
||||
"""
|
||||
adb(['reboot-bootloader'])
|
||||
fastboot(['oem', 'unlock'])
|
||||
fastboot(['continue'])
|
||||
|
||||
class Kernel(object):
|
||||
_kallsyms = None
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.symbols['_text']
|
||||
|
||||
@property
|
||||
@context.quiet
|
||||
def symbols(self):
|
||||
"""Returns a dictionary of kernel symbols"""
|
||||
result = {}
|
||||
for line in self.kallsyms.splitlines():
|
||||
fields = line.split()
|
||||
address = int(fields[0], 16)
|
||||
name = fields[-1]
|
||||
result[name] = address
|
||||
return result
|
||||
|
||||
@property
|
||||
@context.quiet
|
||||
def kallsyms(self):
|
||||
"""Returns the raw output of kallsyms"""
|
||||
if not self._kallsyms:
|
||||
self._kallsyms = {}
|
||||
root()
|
||||
write('/proc/sys/kernel/kptr_restrict', '1')
|
||||
self._kallsyms = read('/proc/kallsyms')
|
||||
return self._kallsyms
|
||||
|
||||
@property
|
||||
@context.quiet
|
||||
def version(self):
|
||||
"""Returns the kernel version of the device."""
|
||||
root()
|
||||
return read('/proc/version').strip()
|
||||
|
||||
@property
|
||||
@context.quiet
|
||||
def cmdline(self):
|
||||
root()
|
||||
return read('/proc/cmdline').strip()
|
||||
|
||||
@property
|
||||
@context.quiet
|
||||
def lastmsg(self):
|
||||
root()
|
||||
if 'last_kmsg' in listdir('/proc'):
|
||||
return read('/proc/last_kmsg')
|
||||
|
||||
if 'console-ramoops' in listdir('/sys/fs/pstore/'):
|
||||
return read('/sys/fs/pstore/console-ramoops')
|
||||
|
||||
def enable_uart(self):
|
||||
"""Reboots the device with kernel logging to the UART enabled."""
|
||||
model = str(properties.ro.product.model)
|
||||
|
||||
known_commands = {
|
||||
'Nexus 4': None,
|
||||
'Nexus 5': None,
|
||||
'Nexus 6': 'oem config console enable',
|
||||
'Nexus 5X': None,
|
||||
'Nexus 6P': 'oem uart enable',
|
||||
'Nexus 7': 'oem uart-on',
|
||||
}
|
||||
|
||||
with log.waitfor('Enabling kernel UART') as w:
|
||||
|
||||
if model not in known_commands:
|
||||
log.error("Device UART is unsupported.")
|
||||
|
||||
command = known_commands[model]
|
||||
|
||||
if command is None:
|
||||
w.success('Always enabled')
|
||||
return
|
||||
|
||||
# Check the current commandline, it may already be enabled.
|
||||
if any(s.startswith('console=tty') for s in self.cmdline.split()):
|
||||
w.success("Already enabled")
|
||||
return
|
||||
|
||||
# Need to be root
|
||||
with context.local(device=context.device):
|
||||
# Save off the command line before rebooting to the bootloader
|
||||
cmdline = kernel.cmdline
|
||||
|
||||
reboot_bootloader()
|
||||
|
||||
# Wait for device to come online
|
||||
while context.device not in fastboot(['devices',' -l']):
|
||||
time.sleep(0.5)
|
||||
|
||||
# Try the 'new' way
|
||||
fastboot(command.split())
|
||||
fastboot(['continue'])
|
||||
wait_for_device()
|
||||
|
||||
|
||||
kernel = Kernel()
|
||||
|
||||
class Property(object):
|
||||
def __init__(self, name=None):
|
||||
self.__dict__['_name'] = name
|
||||
|
||||
def __str__(self):
|
||||
return getprop(self._name).strip()
|
||||
|
||||
def __repr__(self):
|
||||
return repr(str(self))
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if self._name:
|
||||
attr = '%s.%s' % (self._name, attr)
|
||||
return Property(attr)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
if attr in self.__dict__:
|
||||
return super(Property, self).__setattr__(attr, value)
|
||||
|
||||
if self._name:
|
||||
attr = '%s.%s' % (self._name, attr)
|
||||
setprop(attr, value)
|
||||
|
||||
properties = Property()
|
||||
|
||||
def _build_date():
|
||||
"""Returns the build date in the form YYYY-MM-DD as a string"""
|
||||
as_string = getprop('ro.build.date')
|
||||
as_datetime = dateutil.parser.parse(as_string)
|
||||
return as_datetime.strftime('%Y-%b-%d')
|
||||
|
||||
def find_ndk_project_root(source):
|
||||
'''Given a directory path, find the topmost project root.
|
||||
|
||||
tl;dr "foo/bar/jni/baz.cpp" ==> "foo/bar"
|
||||
'''
|
||||
ndk_directory = os.path.abspath(source)
|
||||
while ndk_directory != '/':
|
||||
if os.path.exists(os.path.join(ndk_directory, 'jni')):
|
||||
break
|
||||
ndk_directory = os.path.dirname(ndk_directory)
|
||||
else:
|
||||
return None
|
||||
|
||||
return ndk_directory
|
||||
|
||||
_android_mk_template = '''
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := poc
|
||||
LOCAL_SRC_FILES := %(local_src_files)s
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
'''.lstrip()
|
||||
|
||||
_application_mk_template = '''
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
APP_ABI:= %(app_abi)s
|
||||
APP_PLATFORM:=%(app_platform)s
|
||||
'''.lstrip()
|
||||
|
||||
def _generate_ndk_project(file_list, abi='arm-v7a', platform_version=21):
|
||||
# Create our project root
|
||||
root = tempfile.mkdtemp()
|
||||
|
||||
if not isinstance(file_list, (list, tuple)):
|
||||
file_list = [file_list]
|
||||
|
||||
# Copy over the source file(s)
|
||||
jni_directory = os.path.join(root, 'jni')
|
||||
os.mkdir(jni_directory)
|
||||
for file in file_list:
|
||||
shutil.copy(file, jni_directory)
|
||||
|
||||
# Create the directories
|
||||
|
||||
# Populate Android.mk
|
||||
local_src_files = ' '.join(list(map(os.path.basename, file_list)))
|
||||
Android_mk = os.path.join(jni_directory, 'Android.mk')
|
||||
with open(Android_mk, 'w+') as f:
|
||||
f.write(_android_mk_template % locals())
|
||||
|
||||
# Populate Application.mk
|
||||
app_abi = abi
|
||||
app_platform = 'android-%s' % platform_version
|
||||
Application_mk = os.path.join(jni_directory, 'Application.mk')
|
||||
with open(Application_mk, 'w+') as f:
|
||||
f.write(_application_mk_template % locals())
|
||||
|
||||
return root
|
||||
|
||||
def compile(source):
|
||||
"""Compile a source file or project with the Android NDK."""
|
||||
|
||||
# Ensure that we can find the NDK.
|
||||
ndk = os.environ.get('NDK', None)
|
||||
if ndk is None:
|
||||
log.error('$NDK must be set to the Android NDK directory')
|
||||
ndk_build = os.path.join(ndk, 'ndk-build')
|
||||
|
||||
# Determine whether the source is an NDK project or a single source file.
|
||||
project = find_ndk_project_root(source)
|
||||
|
||||
if not project:
|
||||
project = _generate_ndk_project(source,
|
||||
str(properties.ro.product.cpu.abi),
|
||||
str(properties.ro.build.version.sdk))
|
||||
|
||||
# Remove any output files
|
||||
lib = os.path.join(project, 'libs')
|
||||
if os.path.exists(lib):
|
||||
shutil.rmtree(lib)
|
||||
|
||||
# Build the project
|
||||
io = tubes.process.process(ndk_build, cwd=os.path.join(project, 'jni'))
|
||||
|
||||
result = io.recvall()
|
||||
|
||||
if 0 != io.poll():
|
||||
log.error("Build failed:\n%s" % result)
|
||||
|
||||
# Find all of the output files
|
||||
output = glob.glob(os.path.join(lib, '*', '*'))
|
||||
|
||||
return output[0]
|
||||
|
||||
class Partition(object):
|
||||
def __init__(self, path, name, blocks=0):
|
||||
self.path = path
|
||||
self.name = name
|
||||
self.blocks = blocks
|
||||
self.size = blocks * 1024
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
with log.waitfor('Fetching %r partition (%s)' % (self.name, self.path)):
|
||||
return read(self.path)
|
||||
|
||||
class Partitions(object):
|
||||
@property
|
||||
@context.quiet
|
||||
def by_name_dir(self):
|
||||
cmd = ['shell','find /dev/block/platform -type d -name by-name']
|
||||
return adb(cmd).strip()
|
||||
|
||||
@context.quiet
|
||||
def __dir__(self):
|
||||
return list(self)
|
||||
|
||||
@context.quiet
|
||||
def __iter__(self):
|
||||
root()
|
||||
|
||||
# Find all named partitions
|
||||
for name in listdir(self.by_name_dir):
|
||||
yield name
|
||||
|
||||
@context.quiet
|
||||
def __getattr__(self, attr):
|
||||
for name in self:
|
||||
if name == attr:
|
||||
break
|
||||
else:
|
||||
raise AttributeError("No partition %r" % attr)
|
||||
|
||||
path = os.path.join(self.by_name_dir, name)
|
||||
|
||||
# Find the actual path of the device
|
||||
devpath = process(['readlink', '-n', path]).recvall()
|
||||
devname = os.path.basename(devpath)
|
||||
|
||||
# Get the size of the partition
|
||||
for line in read('/proc/partitions').splitlines():
|
||||
if not line.strip():
|
||||
continue
|
||||
major, minor, blocks, name = line.split(None, 4)
|
||||
if devname == name:
|
||||
break
|
||||
else:
|
||||
log.error("Could not find size of partition %r" % name)
|
||||
|
||||
return Partition(devpath, attr, int(blocks))
|
||||
|
||||
partitions = Partitions()
|
||||
+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()
|
||||
+273
-176
@@ -28,7 +28,7 @@ Assembly
|
||||
in the :mod:`shellcraft` module.
|
||||
|
||||
>>> asm(shellcraft.sh())
|
||||
'jhh///sh/bin\x89\xe31\xc9j\x0bX\x99\xcd\x80'
|
||||
'jhh///sh/binj\x0bX\x89\xe31\xc9\x99\xcd\x80'
|
||||
|
||||
Disassembly
|
||||
------------------------
|
||||
@@ -53,17 +53,21 @@ 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):
|
||||
@LocalContext
|
||||
def which_binutils(util):
|
||||
"""
|
||||
Finds a binutils in the PATH somewhere.
|
||||
Expects that the utility is prefixed with the architecture name.
|
||||
@@ -83,49 +87,55 @@ 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("""
|
||||
# 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]
|
||||
|
||||
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
|
||||
https://pwntools.readthedocs.org/en/latest/install/binutils.html
|
||||
""".strip() % locals())
|
||||
raise Exception('Could not find %(util)r installed for %(context)s' % locals())
|
||||
raise Exception('Could not find %(util)r installed for %(context)s' % locals())
|
||||
|
||||
checked_assembler_version = defaultdict(lambda: False)
|
||||
|
||||
@@ -204,11 +214,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 +224,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 +239,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 +315,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 +336,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 +437,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 +512,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 +529,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 +639,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 +697,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 @@
|
||||
# empty
|
||||
@@ -20,7 +20,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 +40,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,21 +70,55 @@ parser.add_argument(
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
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 = parser.parse_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')
|
||||
|
||||
@@ -10,16 +10,31 @@ parser = argparse.ArgumentParser(
|
||||
description = '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:
|
||||
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()
|
||||
@@ -1,4 +1,7 @@
|
||||
from pwn import *
|
||||
import sys
|
||||
|
||||
import pwnlib
|
||||
from pwnlib.context import context
|
||||
|
||||
pwnlib.log.console.stream = sys.stderr
|
||||
|
||||
|
||||
@@ -4,13 +4,8 @@ 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
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from pwn import *
|
||||
from . import common
|
||||
|
||||
p = argparse.ArgumentParser(
|
||||
description = "Looking up constants from header files.\n\nExample: constgrep -c freebsd -m ^PROT_ '3 + 4'",
|
||||
@@ -20,7 +15,7 @@ p = argparse.ArgumentParser(
|
||||
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 +48,26 @@ 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
|
||||
|
||||
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
|
||||
|
||||
@@ -3,14 +3,9 @@ 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()
|
||||
|
||||
log = getLogger('pwnlib.commandline.cyclic')
|
||||
from . import common
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = "Cyclic pattern creator/finder"
|
||||
@@ -31,11 +26,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',
|
||||
)
|
||||
|
||||
@@ -54,10 +58,10 @@ def main():
|
||||
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)
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
#!/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'
|
||||
@@ -23,25 +20,72 @@ 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,
|
||||
)
|
||||
|
||||
|
||||
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 = parser.parse_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 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__': main()
|
||||
@@ -1,13 +1,16 @@
|
||||
#!/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):
|
||||
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 +20,33 @@ def diff(a,b):
|
||||
except CalledProcessError as e:
|
||||
return e.output
|
||||
|
||||
|
||||
p = ArgumentParser()
|
||||
p.add_argument('a')
|
||||
p.add_argument('b')
|
||||
|
||||
def main():
|
||||
a = p.parse_args()
|
||||
print diff(dump(a.a), dump(a.b))
|
||||
|
||||
with context.silent:
|
||||
x = ELF(a.a)
|
||||
y = ELF(a.b)
|
||||
|
||||
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__': main()
|
||||
@@ -2,11 +2,7 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import pwnlib.log
|
||||
from pwnlib.elf import ELF
|
||||
from pwnlib.util.fiddling import unhex
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from pwn import *
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('elf',help="File to patch")
|
||||
@@ -22,7 +18,9 @@ def main():
|
||||
|
||||
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())
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import argparse
|
||||
import os
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Prints out error messages'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'error', help='Error message or value', type=str
|
||||
)
|
||||
|
||||
def main():
|
||||
args, unknown = parser.parse_known_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__': main()
|
||||
@@ -1,14 +1,9 @@
|
||||
#!/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
|
||||
|
||||
pwnlib.log.install_default_handler()
|
||||
from pwn import *
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Pwnlib HexDump'
|
||||
@@ -31,9 +26,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="*",
|
||||
)
|
||||
|
||||
@@ -90,39 +83,16 @@ def main():
|
||||
else:
|
||||
infile.seek(skip, os.SEEK_CUR)
|
||||
|
||||
data = infile.read(count)
|
||||
|
||||
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(data, width, highlight = hl, begin = offset + skip):
|
||||
print line
|
||||
except (KeyboardInterrupt, IOError):
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import argparse
|
||||
|
||||
from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
p = argparse.ArgumentParser(
|
||||
description = 'Strip binaries for CTF usage',
|
||||
formatter_class = argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
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 = p.parse_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__':
|
||||
main()
|
||||
@@ -0,0 +1,103 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from pwn import *
|
||||
|
||||
from . import common
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = '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 = parser.parse_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__': main()
|
||||
@@ -67,6 +67,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',
|
||||
@@ -97,6 +98,85 @@ p.add_argument(
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'-b',
|
||||
'--before',
|
||||
help='Insert a debug trap before the code',
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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():
|
||||
# Banner must be added here so that it doesn't appear in the autodoc
|
||||
# generation for command line tools
|
||||
@@ -104,18 +184,15 @@ def main():
|
||||
args = p.parse_args()
|
||||
|
||||
if not args.shellcode:
|
||||
print '\n'.join(shellcraft.templates)
|
||||
templates = shellcraft.templates
|
||||
|
||||
if 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'
|
||||
|
||||
func = shellcraft
|
||||
for attr in args.shellcode.split('.'):
|
||||
func = getattr(func, attr)
|
||||
func = get_template(args.shellcode)
|
||||
|
||||
if args.show:
|
||||
# remove doctests
|
||||
@@ -184,23 +261,72 @@ 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)
|
||||
|
||||
if args.format in ['s', 'str', 'string']:
|
||||
code = _string(code)
|
||||
code = _string(code) + '"\n'
|
||||
elif args.format == 'c':
|
||||
code = '{' + ', '.join(map(hex, bytearray(code))) + '}' + '\n'
|
||||
elif args.format in ['h', 'hex']:
|
||||
@@ -209,8 +335,8 @@ 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()
|
||||
@@ -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
|
||||
@@ -0,0 +1,29 @@
|
||||
from pwnlib.constants.constant import Constant
|
||||
|
||||
terminate = Constant('terminate', 1)
|
||||
SYS_terminate = Constant('SYS_terminate', 1)
|
||||
__NR_terminate = Constant('__NR_terminate', 1)
|
||||
|
||||
transmit = Constant('transmit', 2)
|
||||
SYS_transmit = Constant('SYS_transmit', 2)
|
||||
__NR_transmit = Constant('__NR_transmit', 2)
|
||||
|
||||
receive = Constant('receive', 3)
|
||||
SYS_receive = Constant('SYS_receive', 3)
|
||||
__NR_receive = Constant('__NR_receive', 3)
|
||||
|
||||
fdwait = Constant('fdwait', 4)
|
||||
SYS_fdwait = Constant('SYS_fdwait', 4)
|
||||
__NR_fdwait = Constant('__NR_fdwait', 4)
|
||||
|
||||
allocate = Constant('allocate', 5)
|
||||
SYS_allocate = Constant('SYS_allocate', 5)
|
||||
__NR_allocate = Constant('__NR_allocate', 5)
|
||||
|
||||
deallocate = Constant('deallocate', 6)
|
||||
SYS_deallocate = Constant('SYS_deallocate', 6)
|
||||
__NR_deallocate = Constant('__NR_deallocate', 6)
|
||||
|
||||
random = Constant('random', 7)
|
||||
SYS_random = Constant('SYS_random', 7)
|
||||
__NR_random = Constant('__NR_random', 7)
|
||||
+648
-646
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+333
-19
@@ -5,12 +5,30 @@ Implements context management so that nested/scoped contexts and threaded
|
||||
contexts work properly and as expected.
|
||||
"""
|
||||
import collections
|
||||
import functools
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
import socket
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
import socks
|
||||
|
||||
from ..device import Device
|
||||
from ..timeout import Timeout
|
||||
|
||||
_original_socket = socket.socket
|
||||
|
||||
class _devnull(object):
|
||||
name = None
|
||||
def write(self, *a, **kw): pass
|
||||
def read(self, *a, **kw): return ''
|
||||
def flush(self, *a, **kw): pass
|
||||
def close(self, *a, **kw): pass
|
||||
|
||||
class _defaultdict(dict):
|
||||
"""
|
||||
@@ -305,20 +323,29 @@ class ContextType(object):
|
||||
|
||||
#: Default values for :class:`pwnlib.context.ContextType`
|
||||
defaults = {
|
||||
'adb_host': 'localhost',
|
||||
'adb_port': 5037,
|
||||
'arch': 'i386',
|
||||
'aslr': True,
|
||||
'binary': None,
|
||||
'bits': 32,
|
||||
'device': os.getenv('ANDROID_SERIAL', None) or None,
|
||||
'endian': 'little',
|
||||
'kernel': None,
|
||||
'log_level': logging.INFO,
|
||||
'log_file': _devnull(),
|
||||
'randomize': False,
|
||||
'newline': '\n',
|
||||
'noptrace': False,
|
||||
'os': 'linux',
|
||||
'proxy': None,
|
||||
'signed': False,
|
||||
'timeout': Timeout.maximum,
|
||||
'terminal': None,
|
||||
'timeout': Timeout.maximum,
|
||||
}
|
||||
|
||||
#: Valid values for :meth:`pwnlib.context.ContextType.os`
|
||||
oses = sorted(('linux','freebsd','windows'))
|
||||
oses = sorted(('linux','freebsd','windows','cgc','android'))
|
||||
|
||||
big_32 = {'endian': 'big', 'bits': 32}
|
||||
big_64 = {'endian': 'big', 'bits': 64}
|
||||
@@ -440,7 +467,7 @@ class ContextType(object):
|
||||
v = sorted("%s = %r" % (k,v) for k,v in self._tls._current.items())
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(v))
|
||||
|
||||
def local(self, **kwargs):
|
||||
def local(self, function=None, **kwargs):
|
||||
"""local(**kwargs) -> context manager
|
||||
|
||||
Create a context manager for use with the ``with`` statement.
|
||||
@@ -479,13 +506,46 @@ class ContextType(object):
|
||||
def __exit__(a, *b, **c):
|
||||
self._tls.pop()
|
||||
|
||||
def __call__(self, function, *a, **kw):
|
||||
@functools.wraps(function)
|
||||
def inner(*a, **kw):
|
||||
with self:
|
||||
return function(*a, **kw)
|
||||
return inner
|
||||
|
||||
return LocalContext()
|
||||
|
||||
def clear(self):
|
||||
@property
|
||||
def silent(self, function=None):
|
||||
"""Disable all non-error logging within the enclosed scope.
|
||||
"""
|
||||
return self.local(function, log_level='error')
|
||||
|
||||
@property
|
||||
def quiet(self, function=None):
|
||||
"""Disables all non-error logging within the enclosed scope,
|
||||
*unless* the debugging level is set to 'debug' or lower."""
|
||||
level = 'error'
|
||||
if context.log_level <= logging.DEBUG:
|
||||
level = None
|
||||
return self.local(function, log_level=level)
|
||||
|
||||
@property
|
||||
def verbose(self):
|
||||
"""Enable all logging within the enclosed scope.
|
||||
"""
|
||||
return self.local(log_level='debug')
|
||||
|
||||
def clear(self, *a, **kw):
|
||||
"""
|
||||
Clears the contents of the context.
|
||||
All values are set to their defaults.
|
||||
|
||||
Arguments:
|
||||
|
||||
a: Arguments passed to ``update``
|
||||
kw: Arguments passed to ``update``
|
||||
|
||||
Examples:
|
||||
|
||||
>>> # Default value
|
||||
@@ -500,10 +560,27 @@ class ContextType(object):
|
||||
"""
|
||||
self._tls._current.clear()
|
||||
|
||||
if a or kw:
|
||||
self.update(*a, **kw)
|
||||
|
||||
@property
|
||||
def native(self):
|
||||
if context.os in ('android', 'cgc'):
|
||||
return False
|
||||
|
||||
arch = context.arch
|
||||
with context.local(arch = platform.machine()):
|
||||
platform_arch = context.arch
|
||||
|
||||
if arch in ('i386', 'amd64') and platform_arch in ('i386', 'amd64'):
|
||||
return True
|
||||
|
||||
return arch == platform_arch
|
||||
|
||||
@_validator
|
||||
def arch(self, arch):
|
||||
"""
|
||||
Target machine architecture.
|
||||
Target binary architecture.
|
||||
|
||||
Allowed values are listed in :attr:`pwnlib.context.ContextType.architectures`.
|
||||
|
||||
@@ -565,17 +642,22 @@ class ContextType(object):
|
||||
>>> vars(context) == {'arch': 'powerpc64', 'bits': 64, 'endian': 'big'}
|
||||
True
|
||||
"""
|
||||
|
||||
# Lowercase
|
||||
arch = arch.lower()
|
||||
|
||||
# Attempt to perform convenience and legacy compatibility
|
||||
# transformations.
|
||||
# Attempt to perform convenience and legacy compatibility transformations.
|
||||
# We have to make sure that x86_64 appears before x86 for this to work correctly.
|
||||
transform = [('ppc', 'powerpc'), ('x86_64', 'amd64'), ('x86', 'i386')]
|
||||
transform = [('ppc64', 'powerpc64'),
|
||||
('ppc', 'powerpc'),
|
||||
('x86_64', 'amd64'),
|
||||
('x86', 'i386'),
|
||||
('i686', 'i386'),
|
||||
('armeabi', 'arm'),
|
||||
('arm64', 'aarch64')]
|
||||
for k, v in transform:
|
||||
if arch.startswith(k):
|
||||
arch = arch.replace(k,v,1)
|
||||
arch = v
|
||||
break
|
||||
|
||||
try:
|
||||
defaults = ContextType.architectures[arch]
|
||||
@@ -588,6 +670,33 @@ class ContextType(object):
|
||||
|
||||
return arch
|
||||
|
||||
@_validator
|
||||
def aslr(self, aslr):
|
||||
"""
|
||||
ASLR settings for new processes.
|
||||
|
||||
If ``False``, attempt to disable ASLR in all processes which are
|
||||
created via ``personality`` (``setarch -R``) and ``setrlimit``
|
||||
(``ulimit -s unlimited``).
|
||||
|
||||
The ``setarch`` changes are lost if a ``setuid`` binary is executed.
|
||||
"""
|
||||
return bool(aslr)
|
||||
|
||||
@_validator
|
||||
def kernel(self, arch):
|
||||
"""
|
||||
Target machine's kernel architecture.
|
||||
|
||||
Usually, this is the same as ``arch``, except when
|
||||
running a 32-bit binary on a 64-bit kernel (e.g. i386-on-amd64).
|
||||
|
||||
Even then, this doesn't matter much -- only when the the segment
|
||||
registers need to be known
|
||||
"""
|
||||
with context.local(arch=arch):
|
||||
return context.arch
|
||||
|
||||
@_validator
|
||||
def bits(self, bits):
|
||||
"""
|
||||
@@ -635,13 +744,14 @@ class ContextType(object):
|
||||
# Cyclic imports... sorry Idolf.
|
||||
from ..elf import ELF
|
||||
|
||||
e = ELF(binary)
|
||||
if not isinstance(binary, ELF):
|
||||
binary = ELF(binary)
|
||||
|
||||
self.arch = e.arch
|
||||
self.bits = e.bits
|
||||
self.endian = e.endian
|
||||
self.arch = binary.arch
|
||||
self.bits = binary.bits
|
||||
self.endian = binary.endian
|
||||
|
||||
return e
|
||||
return binary
|
||||
|
||||
@property
|
||||
def bytes(self):
|
||||
@@ -666,7 +776,6 @@ class ContextType(object):
|
||||
def bytes(self, value):
|
||||
self.bits = value*8
|
||||
|
||||
|
||||
@_validator
|
||||
def endian(self, endianness):
|
||||
"""
|
||||
@@ -741,6 +850,70 @@ class ContextType(object):
|
||||
permitted = sorted(level_names)
|
||||
raise AttributeError('log_level must be an integer or one of %r' % permitted)
|
||||
|
||||
@_validator
|
||||
def log_file(self, value):
|
||||
r"""
|
||||
Sets the target file for all logging output.
|
||||
|
||||
Works in a similar fashion to :attr:`log_level`.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
>>> context.log_file = 'foo.txt' #doctest: +ELLIPSIS
|
||||
>>> log.debug('Hello!') #doctest: +ELLIPSIS
|
||||
>>> with context.local(log_level='ERROR'): #doctest: +ELLIPSIS
|
||||
... log.info('Hello again!')
|
||||
>>> with context.local(log_file='bar.txt'):
|
||||
... log.debug('Hello from bar!')
|
||||
>>> log.info('Hello from foo!')
|
||||
>>> file('foo.txt').readlines()[-3] #doctest: +ELLIPSIS
|
||||
'...:DEBUG:...:Hello!\n'
|
||||
>>> file('foo.txt').readlines()[-2] #doctest: +ELLIPSIS
|
||||
'...:INFO:...:Hello again!\n'
|
||||
>>> file('foo.txt').readlines()[-1] #doctest: +ELLIPSIS
|
||||
'...:INFO:...:Hello from foo!\n'
|
||||
>>> file('bar.txt').readlines()[-1] #doctest: +ELLIPSIS
|
||||
'...:DEBUG:...:Hello from bar!\n'
|
||||
"""
|
||||
if isinstance(value, (str,unicode)):
|
||||
modes = ('w', 'wb', 'a', 'ab')
|
||||
# check if mode was specified as "[value],[mode]"
|
||||
if ',' not in value:
|
||||
value += ',a'
|
||||
filename, mode = value.rsplit(',', 1)
|
||||
value = open(filename, mode)
|
||||
|
||||
elif not isinstance(value, (file)):
|
||||
raise AttributeError('log_file must be a file')
|
||||
|
||||
# Is this the same file we already have open?
|
||||
# If so, don't re-print the banner.
|
||||
if self.log_file and not isinstance(self.log_file, _devnull):
|
||||
a = os.fstat(value.fileno()).st_ino
|
||||
b = os.fstat(self.log_file.fileno()).st_ino
|
||||
|
||||
if a == b:
|
||||
return self.log_file
|
||||
|
||||
iso_8601 = '%Y-%m-%dT%H:%M:%S'
|
||||
lines = [
|
||||
'=' * 78,
|
||||
' Started at %s ' % time.strftime(iso_8601),
|
||||
' sys.argv = [',
|
||||
]
|
||||
for arg in sys.argv:
|
||||
lines.append(' %r,' % arg)
|
||||
lines.append(' ]')
|
||||
lines.append('=' * 78)
|
||||
for line in lines:
|
||||
value.write('=%-78s=\n' % line)
|
||||
value.flush()
|
||||
return value
|
||||
|
||||
@property
|
||||
def mask(self):
|
||||
return (1 << self.bits) - 1
|
||||
|
||||
@_validator
|
||||
def os(self, os):
|
||||
@@ -757,16 +930,21 @@ class ContextType(object):
|
||||
>>> context.os = 'foobar' #doctest: +ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: os must be one of ['freebsd', 'linux', 'windows']
|
||||
AttributeError: os must be one of ['android', 'cgc', 'freebsd', 'linux', 'windows']
|
||||
"""
|
||||
os = os.lower()
|
||||
|
||||
if os not in ContextType.oses:
|
||||
raise AttributeError("os must be one of %r" % sorted(ContextType.oses))
|
||||
raise AttributeError("os must be one of %r" % ContextType.oses)
|
||||
|
||||
return os
|
||||
|
||||
|
||||
@_validator
|
||||
def randomize(self, r):
|
||||
"""
|
||||
Global flag that lots of things should be randomized.
|
||||
"""
|
||||
return bool(r)
|
||||
|
||||
@_validator
|
||||
def signed(self, signed):
|
||||
@@ -827,6 +1005,111 @@ class ContextType(object):
|
||||
return [value]
|
||||
return value
|
||||
|
||||
@property
|
||||
def abi(self):
|
||||
return self._abi
|
||||
|
||||
@_validator
|
||||
def proxy(self, proxy):
|
||||
"""
|
||||
Default proxy for all socket connections.
|
||||
|
||||
Accepts either a string (hostname or IP address) for a SOCKS5 proxy on
|
||||
the default port, **or** a ``tuple`` passed to ``socks.set_default_proxy``,
|
||||
e.g. ``(socks.SOCKS4, 'localhost', 1234)``.
|
||||
|
||||
>>> context.proxy = 'localhost' #doctest: +ELLIPSIS
|
||||
>>> r=remote('google.com', 80)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ProxyConnectionError: Error connecting to SOCKS5 proxy localhost:1080: [Errno 111] Connection refused
|
||||
|
||||
>>> context.proxy = None
|
||||
>>> r=remote('google.com', 80, level='error')
|
||||
"""
|
||||
|
||||
if not proxy:
|
||||
socket.socket = _original_socket
|
||||
return None
|
||||
|
||||
if isinstance(proxy, str):
|
||||
proxy = (socks.SOCKS5, proxy)
|
||||
|
||||
if not isinstance(proxy, collections.Iterable):
|
||||
raise AttributeError('proxy must be a string hostname, or tuple of arguments for socks.set_default_proxy')
|
||||
|
||||
socks.set_default_proxy(*proxy)
|
||||
socket.socket = socks.socksocket
|
||||
|
||||
return proxy
|
||||
|
||||
@_validator
|
||||
def noptrace(self, value):
|
||||
"""Disable all actions which rely on ptrace.
|
||||
|
||||
This is useful for switching between local exploitation with a debugger,
|
||||
and remote exploitation (without a debugger).
|
||||
|
||||
This option can be set with the ``NOPTRACE`` command-line argument.
|
||||
"""
|
||||
return bool(value)
|
||||
|
||||
|
||||
@_validator
|
||||
def adb_host(self, value):
|
||||
"""Sets the target host which is used for ADB.
|
||||
|
||||
This is useful for Android exploitation.
|
||||
|
||||
The default value is inherited from ANDROID_ADB_SERVER_HOST, or set
|
||||
to the default 'localhost'.
|
||||
"""
|
||||
return str(value)
|
||||
|
||||
|
||||
@_validator
|
||||
def adb_port(self, value):
|
||||
"""Sets the target port which is used for ADB.
|
||||
|
||||
This is useful for Android exploitation.
|
||||
|
||||
The default value is inherited from ANDROID_ADB_SERVER_PORT, or set
|
||||
to the default 5037.
|
||||
"""
|
||||
return int(value)
|
||||
|
||||
@_validator
|
||||
def device(self, device):
|
||||
"""Sets the device being operated on.
|
||||
"""
|
||||
if isinstance(device, Device):
|
||||
self.arch = device.arch or self.arch
|
||||
self.bits = device.bits or self.bits
|
||||
self.endian = device.endian or self.endian
|
||||
elif isinstance(device, str):
|
||||
device = Device(device)
|
||||
else:
|
||||
raise AttributeError("device must be either a Device object or a serial number as a string")
|
||||
|
||||
return device
|
||||
|
||||
@property
|
||||
def adb(self):
|
||||
"""Returns an argument array for connecting to adb."""
|
||||
command = ['adb']
|
||||
|
||||
if self.adb_host != self.defaults['adb_host']:
|
||||
command += ['-H', self.adb_host]
|
||||
|
||||
if self.adb_port != self.defaults['adb_port']:
|
||||
command += ['-P', str(self.adb_port)]
|
||||
|
||||
if self.device:
|
||||
command += ['-s', str(self.device)]
|
||||
|
||||
return command
|
||||
|
||||
|
||||
#*************************************************************************
|
||||
# ALIASES
|
||||
#*************************************************************************
|
||||
@@ -909,3 +1192,34 @@ class ContextType(object):
|
||||
#: Consider it a shorthand to passing ``os=`` and ``arch=`` to every single
|
||||
#: function call.
|
||||
context = ContextType()
|
||||
|
||||
# Inherit default ADB values
|
||||
if 'ANDROID_ADB_SERVER_HOST' in os.environ:
|
||||
context.adb_host = os.environ.get('ANDROID_ADB_SERVER_HOST')
|
||||
|
||||
if 'ANDROID_ADB_SERVER_PORT' in os.environ:
|
||||
context.adb_port = int(os.getenv('ANDROID_ADB_SERVER_PORT'))
|
||||
|
||||
def LocalContext(function):
|
||||
"""
|
||||
Wraps the specied function on a context.local() block, using kwargs.
|
||||
|
||||
Example:
|
||||
|
||||
>>> @LocalContext
|
||||
... def printArch():
|
||||
... print(context.arch)
|
||||
>>> printArch()
|
||||
i386
|
||||
>>> printArch(arch='arm')
|
||||
arm
|
||||
"""
|
||||
@functools.wraps(function)
|
||||
def setter(*a, **kw):
|
||||
# Fast path to skip adding a Context frame
|
||||
if not kw:
|
||||
return function(*a)
|
||||
|
||||
with context.local(**{k:kw.pop(k) for k,v in kw.items() if isinstance(getattr(ContextType, k, None), property)}):
|
||||
return function(*a, **kw)
|
||||
return setter
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
linux
|
||||
+1
@@ -0,0 +1 @@
|
||||
arm.h
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
arm.h
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
arm.h
|
||||
@@ -0,0 +1,21 @@
|
||||
#define allocate 5
|
||||
#define SYS_allocate 5
|
||||
#define __NR_allocate 5
|
||||
#define deallocate 6
|
||||
#define SYS_deallocate 6
|
||||
#define __NR_deallocate 6
|
||||
#define fdwait 4
|
||||
#define SYS_fdwait 4
|
||||
#define __NR_fdwait 4
|
||||
#define random 7
|
||||
#define SYS_random 7
|
||||
#define __NR_random 7
|
||||
#define receive 3
|
||||
#define SYS_receive 3
|
||||
#define __NR_receive 3
|
||||
#define terminate 1
|
||||
#define SYS_terminate 1
|
||||
#define __NR_terminate 1
|
||||
#define transmit 2
|
||||
#define SYS_transmit 2
|
||||
#define __NR_transmit 2
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
arm.h
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
arm.h
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
arm.h
|
||||
Loaded 100 of 3348 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user