├── LICENSE.md ├── README.md └── windows-exploit-suggester.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DESCRIPTION 2 | =========== 3 | This tool compares a targets patch levels against the Microsoft vulnerability 4 | database in order to detect potential missing patches on the target. It also 5 | notifies the user if there are public exploits and Metasploit modules 6 | available for the missing bulletins. 7 | 8 | It requires the 'systeminfo' command output from a Windows host in order to 9 | compare that the Microsoft security bulletin database and determine the 10 | patch level of the host. 11 | 12 | It has the ability to automatically download the security bulletin database 13 | from Microsoft with the --update flag, and saves it as an Excel spreadsheet. 14 | 15 | When looking at the command output, it is important to note that it assumes 16 | all vulnerabilities and then selectively removes them based upon the hotfix 17 | data. This can result in many false-positives, and it is key to know what 18 | software is actually running on the target host. For example, if there are 19 | known IIS exploits it will flag them even if IIS is not running on the 20 | target host. 21 | 22 | The output shows either public exploits (E), or Metasploit modules (M) as 23 | indicated by the character value. 24 | 25 | It was heavily inspired by Linux_Exploit_Suggester by Pentura. 26 | 27 | Blog Post: "Introducing Windows Exploit Suggester", https://blog.gdssecurity.com/labs/2014/7/11/introducing-windows-exploit-suggester.html 28 | 29 | USAGE 30 | ===== 31 | update the database 32 | ``` 33 | $ ./windows-exploit-suggester.py --update 34 | [*] initiating... 35 | [*] successfully requested base url 36 | [*] scraped ms download url 37 | [+] writing to file 2014-06-06-mssb.xlsx 38 | [*] done 39 | ``` 40 | install dependencies 41 | 42 | (install python-xlrd, $ pip install xlrd --upgrade) 43 | 44 | feed it "systeminfo" input, and point it to the microsoft database 45 | ``` 46 | $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --systeminfo win7sp1-systeminfo.txt 47 | [*] initiating... 48 | [*] database file detected as xls or xlsx based on extension 49 | [*] reading from the systeminfo input file 50 | [*] querying database file for potential vulnerabilities 51 | [*] comparing the 15 hotfix(es) against the 173 potential bulletins(s) 52 | [*] there are now 168 remaining vulns 53 | [+] windows version identified as 'Windows 7 SP1 32-bit' 54 | [*] 55 | [M] MS14-012: Cumulative Security Update for Internet Explorer (2925418) - Critical 56 | [E] MS13-101: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (2880430) - Important 57 | [M] MS13-090: Cumulative Security Update of ActiveX Kill Bits (2900986) - Critical 58 | [M] MS13-080: Cumulative Security Update for Internet Explorer (2879017) - Critical 59 | [M] MS13-069: Cumulative Security Update for Internet Explorer (2870699) - Critical 60 | [M] MS13-059: Cumulative Security Update for Internet Explorer (2862772) - Critical 61 | [M] MS13-055: Cumulative Security Update for Internet Explorer (2846071) - Critical 62 | [M] MS13-053: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Remote Code Execution (2850851) - Critical 63 | [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 64 | [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 65 | [*] done 66 | ``` 67 | 68 | possible exploits for an operating system can be used without hotfix data 69 | ``` 70 | $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --ostext 'windows server 2008 r2' 71 | [*] initiating... 72 | [*] database file detected as xls or xlsx based on extension 73 | [*] getting OS information from command line text 74 | [*] querying database file for potential vulnerabilities 75 | [*] comparing the 0 hotfix(es) against the 196 potential bulletins(s) 76 | [*] there are now 196 remaining vulns 77 | [+] windows version identified as 'Windows 2008 R2 64-bit' 78 | [*] 79 | [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 80 | [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 81 | [E] MS11-011: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (2393802) - Important 82 | [M] MS10-073: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (981957) - Important 83 | [M] MS10-061: Vulnerability in Print Spooler Service Could Allow Remote Code Execution (2347290) - Critical 84 | [E] MS10-059: Vulnerabilities in the Tracing Feature for Services Could Allow Elevation of Privilege (982799) - Important 85 | [E] MS10-047: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (981852) - Important 86 | [M] MS10-002: Cumulative Security Update for Internet Explorer (978207) - Critical 87 | [M] MS09-072: Cumulative Security Update for Internet Explorer (976325) - Critical 88 | ``` 89 | 90 | LIMITATIONS 91 | =========== 92 | Currently, if the 'systeminfo' command reveals 'File 1' as the output for 93 | the hotfixes, it will not be able to determine which are installed on 94 | the target. If this occurs, the list of hotfixes will need to be 95 | retrieved from the target host and passed in using the --hotfixes flag 96 | 97 | It currently does not seperate 'editions' of the Windows OS such as 98 | 'Tablet' or 'Media Center' for example, or different architectures, such as 99 | Itanium-based only 100 | 101 | False positives also occur where it assumes EVERYTHING is installed 102 | on the target Windows operating system. If you receive the 'File 1' 103 | output, try executing 'wmic qfe list full' and feed that as input 104 | with the --hotfixes flag, along with the 'systeminfo' 105 | 106 | LICENSE 107 | ======= 108 | This program is free software: you can redistribute it and/or modify 109 | it under the terms of the GNU General Public License as published by 110 | the Free Software Foundation, either version 3 of the License, or 111 | (at your option) any later version. 112 | 113 | This program is distributed in the hope that it will be useful, 114 | but WITHOUT ANY WARRANTY; without even the implied warranty of 115 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 116 | GNU General Public License for more details. 117 | 118 | You should have received a copy of the GNU General Public License 119 | along with this program. If not, see . 120 | 121 | -------------------------------------------------------------------------------- /windows-exploit-suggester.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Windows Exploit Suggester for Python 3 5 | # revision 3.3, 2017-02-13 6 | # 7 | # original WES author: Sam Bertram, Gotham Digital Science 8 | # ported to python3 and supported libraries by: Conor Rynne 9 | # contact: pwnistry@gmail.com 10 | # blog post: "Modernising Windows Exploit Suggester", http://blog.pwnistry.com/ 11 | # 12 | # DESCRIPTION 13 | # 14 | # The purpose of this project is to port the original Windows Exploit Suggester 15 | # to Python 3 and openpyxl (since xlrd dropped support for .xlsx files a while 16 | # ago) 17 | # 18 | # This tool compares a targets patch levels against the Microsoft vulnerability 19 | # database in order to detect potential missing patches on the target. It also 20 | # notifies the user if there are public exploits and Metasploit modules 21 | # available for the missing bulletins. 22 | # 23 | # It requires the 'systeminfo' command output from a Windows host in order to 24 | # compare that the Microsoft security bulletin database and determine the 25 | # patch level of the host. 26 | # 27 | # It has the ability to automatically download the security bulletin database 28 | # from Microsoft with the --update flag, and saves it as an Excel spreadsheet. 29 | # 30 | # When looking at the command output, it is important to note that it assumes 31 | # all vulnerabilities and then selectively removes them based upon the hotfix 32 | # data. This can result in many false-positives, and it is key to know what 33 | # software is actually running on the target host. For example, if there are 34 | # known IIS exploits it will flag them even if IIS is not running on the 35 | # target host. 36 | # 37 | # The output shows either public exploits (E), or Metasploit modules (M) as 38 | # indicated by the character value. 39 | # 40 | # It was heavily inspired by Linux_Exploit_Suggester by Pentura. 41 | # 42 | # Blog Post: "Introducing Windows Exploit Suggester", https://blog.gdssecurity.com/labs/2014/7/11/introducing-windows-exploit-suggester.html 43 | # 44 | # USAGE 45 | # 46 | # update the database 47 | # 48 | # $ ./windows-exploit-suggester.py --update 49 | # [*] initiating... 50 | # [*] successfully requested base url 51 | # [*] scraped ms download url 52 | # [+] writing to file 2014-06-06-mssb.xlsx 53 | # [*] done 54 | # 55 | # install dependencies 56 | # 57 | # (install python-xlrd, $ pip install xlrd --upgrade) 58 | # 59 | # feed it "systeminfo" input, and point it to the microsoft database 60 | # 61 | # $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --systeminfo win7sp1-systeminfo.txt 62 | # [*] initiating... 63 | # [*] database file detected as xls or xlsx based on extension 64 | # [*] reading from the systeminfo input file 65 | # [*] querying database file for potential vulnerabilities 66 | # [*] comparing the 15 hotfix(es) against the 173 potential bulletins(s) 67 | # [*] there are now 168 remaining vulns 68 | # [+] windows version identified as 'Windows 7 SP1 32-bit' 69 | # [*] 70 | # [M] MS14-012: Cumulative Security Update for Internet Explorer (2925418) - Critical 71 | # [E] MS13-101: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (2880430) - Important 72 | # [M] MS13-090: Cumulative Security Update of ActiveX Kill Bits (2900986) - Critical 73 | # [M] MS13-080: Cumulative Security Update for Internet Explorer (2879017) - Critical 74 | # [M] MS13-069: Cumulative Security Update for Internet Explorer (2870699) - Critical 75 | # [M] MS13-059: Cumulative Security Update for Internet Explorer (2862772) - Critical 76 | # [M] MS13-055: Cumulative Security Update for Internet Explorer (2846071) - Critical 77 | # [M] MS13-053: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Remote Code Execution (2850851) - Critical 78 | # [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 79 | # [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 80 | # [*] done 81 | # 82 | # possible exploits for an operating system can be used without hotfix data 83 | # $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --ostext 'windows server 2008 r2' 84 | # [*] initiating... 85 | # [*] database file detected as xls or xlsx based on extension 86 | # [*] getting OS information from command line text 87 | # [*] querying database file for potential vulnerabilities 88 | # [*] comparing the 0 hotfix(es) against the 196 potential bulletins(s) 89 | # [*] there are now 196 remaining vulns 90 | # [+] windows version identified as 'Windows 2008 R2 64-bit' 91 | # [*] 92 | # [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 93 | # [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 94 | # [E] MS11-011: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (2393802) - Important 95 | # [M] MS10-073: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (981957) - Important 96 | # [M] MS10-061: Vulnerability in Print Spooler Service Could Allow Remote Code Execution (2347290) - Critical 97 | # [E] MS10-059: Vulnerabilities in the Tracing Feature for Services Could Allow Elevation of Privilege (982799) - Important 98 | # [E] MS10-047: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (981852) - Important 99 | # [M] MS10-002: Cumulative Security Update for Internet Explorer (978207) - Critical 100 | # [M] MS09-072: Cumulative Security Update for Internet Explorer (976325) - Critical 101 | # 102 | # LIMITATIONS 103 | # 104 | # Currently, if the 'systeminfo' command reveals 'File 1' as the output for 105 | # the hotfixes, it will not be able to determine which are installed on 106 | # the target. If this occurs, the list of hotfixes will need to be 107 | # retrieved from the target host and passed in using the --hotfixes flag 108 | # 109 | # It currently does not seperate 'editions' of the Windows OS such as 110 | # 'Tablet' or 'Media Center' for example, or different architectures, such as 111 | # Itanium-based only 112 | # 113 | # False positives also occur where it assumes EVERYTHING is installed 114 | # on the target Windows operating system. If you receive the 'File 1' 115 | # output, try executing 'wmic qfe list full' and feed that as input 116 | # with the --hotfixes flag, along with the 'systeminfo' 117 | # 118 | # LICENSE 119 | # 120 | # This program is free software: you can redistribute it and/or modify 121 | # it under the terms of the GNU General Public License as published by 122 | # the Free Software Foundation, either version 3 of the License, or 123 | # (at your option) any later version. 124 | # 125 | # This program is distributed in the hope that it will be useful, 126 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 127 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 128 | # GNU General Public License for more details. 129 | # 130 | # You should have received a copy of the GNU General Public License 131 | # along with this program. If not, see . 132 | # 133 | # TODOLIST 134 | # 135 | # TODO better if/then/case when detecting OS. more flexibility with parsing 136 | # different systeminfo output 137 | # TODO seperate by editions? may result in false positives 138 | # TODO count the number of exploits in the summary prior to outputting it? 139 | # TODO finish -s --search function so that all info on an MS number can be 140 | # returned 141 | # TODO add titles to exploit list so that it is more portable 142 | # TODO test for Windows RT systeminfo output 143 | # TODO improved msf/poc output? perhaps adding details on each MS number? 144 | # TODO if it's running on windows, then try and execute the systeminfo command? 145 | # TODO SPEED. this is now way too slow... somewhat improved! 146 | # TODO automatically install python module? xlrd. 147 | # TODO manually override MS11-011 for Non-Affected Products. The bulletin 148 | # database is wrong. 149 | # Windows 7 for 32-bit Systems Service Pack 1 150 | # Windows 7 for x64-based Systems Service Pack 1 151 | # Windows Server 2008 R2 for x64-based Systems Service Pack 1 152 | # Windows Server 2008 R2 for Itanium-based Systems Service Pack 1 153 | # 154 | # CHANGE LOG 155 | # v33 2017-02-13 156 | # - added links to exploits and resources for each bulletins. can be ignored with the -q/--quiet flag 157 | # - hard coded ms11-011 to ignore false positives 158 | # - added additional resources 159 | # 160 | # v31 2016-02-10 161 | # - changed bulletin url, microsoft 404'd it 162 | # 163 | # v30 2016-01-04 164 | # - added exploits and bulletins from the past six months 165 | # 166 | # v29 2015-09-16 167 | # - adding support for windows 10 168 | # 169 | # v28 2015-07-30 170 | # - added bulletin scraping for xlsx and xls files using regex. thanks to 171 | # edebernis for reporting the bug 172 | # - added ms15-022, ms15-015 update to msf 173 | # 174 | # v27 2015-06-18 175 | # - added new bulletin url that is only xls and not xlsx. thanks to bstork for 176 | # reporting the bug 177 | # - added ms15-010, ms15-051, and ms15-052 178 | # 179 | # v26 2015-06-02 180 | # - small bug fix with linked output 181 | # - added duplicates flag that can allow for bulletins to be displayed 182 | # multiple times. this will allow for greater analysis on linked bulletins 183 | # 184 | # v25 2015-05-18 185 | # - added ms15-051 local priv 186 | # 187 | # v24 2015-01-30 188 | # - added --sub/-s command in order to display output of msids as linked 189 | # this aides in demonstrating what patches need to be applied precisely. 190 | # this change was implemented in v23, but only followed the depth to level 191 | # 1 instead of the entire way. 192 | # - fixed a bug that know allows for multiple supercedes msids in the db 193 | # - allowed for getarchitecture to be recursive, and reduced redunancy when 194 | # it is called throughout the program 195 | # - added ms14-070 196 | # 197 | # v23 2015-01-26 198 | # - typo in --local flag case (pontential vs potential). issue #5 closed. 199 | # 200 | # v22 2015-01-23 201 | # - speed optimisations! it was too slow beforehand. realised i could easily 202 | # make it a bit more efficient 203 | # 204 | # v21 2015-01-22 205 | # - changed display formatting to include nested/linked MS numbers. makes it 206 | # easier to determine the dependencies 207 | # - made args global 208 | # - changed some code formatting, including double-space instead of \t 209 | # - added some additional comments 210 | # - disable ANSI output if on windows platform 211 | # - added recent exploits 212 | # 213 | # v20 2014-12-16 214 | # - added ms14-068,ms14-064,ms14-060, and ms14-058 to the internal vuln list 215 | # 216 | # v19 2014-10-08 217 | # - added support for windows server 2012, this includes ignoring the 218 | # architecture for 2012, and forcing from 32-bit to 64-bit 219 | # 220 | # v18 2014-09-02 221 | # - added ms14-029 poc 222 | # 223 | # v17 2014-08-05 224 | # - fixed a bug where it would not detect OS version when a unicode char comes 225 | # before search string 226 | # 227 | # v16 2014-07-28 228 | # - improved reading of various file encodings for systeminfo. now attempts to 229 | # detect the file first, otherwise loops through common encodings 230 | # - improved OS, service pack, architecture, and release detection. this is now 231 | # not English-dependent as it was previously 232 | # - better architecture detection of systeminfo input (look for -based string) 233 | # - added /usr/bin/env python 234 | # - added ms14-035 poc 235 | # 236 | # v15 2014-07-15 237 | # - changed file open to io, and attempt to decode as utf-8; otherwise attempt 238 | # utf-16 239 | # 240 | # v14 2014-07-13 241 | # - allowed for --ostext flag to properly supersede OS detection of systeminfo 242 | # input 243 | # 244 | # v13a 2014-07-01 245 | # - added new msf flags for ms13-097, and ms14-009 246 | # 247 | # v12a 2014-06-06 248 | # - quick cleanup for release 249 | # 250 | # v11a 2014-05-02 251 | # - fixed the bulletin scrape regex for the update command. ms changed it 252 | # 253 | # v10a 2014-03-24 254 | # - added a hotfixes argument, that can be used to supplement the list 255 | # of hotfixes detected in the systeminfo input 256 | # - added severity at the end of the output when reporting bulletins 257 | # - added a 'patches' argument, that can be used to determine any 258 | # of the hotfixes for a specific bulletin. this is good for debugging. 259 | # 260 | # v09a 2014-03-18 261 | # - again, another massive bug on the linked kb searching function 262 | # getlinkedms(). should be fixed now 263 | # - also checks columns 11 and 12 for superseded, i think it has to 264 | # do with dos and *nix output 265 | # 266 | # v08a 2014-02-14 267 | # - bug where the superseded column wasn't being checked 268 | # this may be because it's only xlsx and it parsed differently in csv 269 | # - added some new exploits from edb 270 | # 271 | # v07a 2014-02-12 272 | # - added indicator for os version, and in green 273 | # - better parsing of architecture for itanium based support 274 | # 275 | # v06a 2014-01-19 276 | # - added 'ostext' or 'o' option, when don't have any patch information 277 | # but just know the OS 278 | # 279 | # v05a 280 | # - added a check for "Kernel version" column, as well as "OS version" 281 | # 282 | # v04a 283 | # - added support for XLSX files directly with the updated XLRD library, this 284 | # requires the python-xlrd library to be installed and upgraded with: 285 | # $ pip install xlrd --upgrade 286 | # - changed MS13-101 to E, as there isn't a metasploit module (yet!) 287 | # 288 | # v03a 289 | # - fixed an issue where component KB wasn't being checked 290 | # 291 | # FUNCTIONS 292 | # 293 | # def main(): 294 | # def run(database): 295 | # def detect_encoding(filename): 296 | # def trace(database): 297 | # def patches(database): 298 | # def getversion(name, release, servicepack, architecture): 299 | # def getname(ostext): 300 | # def getrelease(ostext): 301 | # def getservicepack(ostext): 302 | # def getarchitecture(ostext): 303 | # def getitanium(ostext): 304 | # def getpatch(ostext): 305 | # def getbulletinids(haystack): 306 | # def isaffected(name, release, servicepack, architecture, haystack): 307 | # def getlinkedms(msids, database): 308 | # def getexploit(msid = 0): 309 | # def update(): 310 | # def merge_list(li): 311 | # 312 | import re 313 | import platform 314 | import argparse 315 | import subprocess 316 | import csv 317 | from io import StringIO 318 | import os 319 | import datetime 320 | import urllib.request 321 | import urllib.error 322 | import io 323 | from random import randint 324 | from time import sleep 325 | from tempfile import NamedTemporaryFile 326 | from sys import exit 327 | 328 | # constants/globals 329 | MSSB_URL = 'http://www.microsoft.com/en-gb/download/confirmation.aspx?id=36982' 330 | BULLETIN_URL = 'http://download.microsoft.com/download/6/7/3/673E4349-1CA5-40B9-8879-095C72D5B49D/BulletinSearch.xlsx' 331 | VERSION = "3.4" 332 | 333 | # global parser 334 | parser = argparse.ArgumentParser(description="search microsoft security bulletins for exploits based upon the patch level of the machine by feeding in systeminfo command") 335 | parser.add_argument("-v", "--verbose", help="verbose output", action="store_true") 336 | parser.add_argument("-i", "--systeminfo", help="feed in an input file that contains the 'systeminfo' command") 337 | parser.add_argument("-d", "--database", help="the file that contains the microsoft security bulletin database") 338 | parser.add_argument("-u", "--update", help="required flag to even run the script", action="store_true") 339 | parser.add_argument("-a", "--audit", help="show all entries, not only exploits", action="store_true") 340 | parser.add_argument("-t", "--trace", help="used to determine linked ms bulletins") 341 | parser.add_argument("-p", "--patches", help="used to determine specific patches for a ms bulletin") 342 | parser.add_argument("-o", "--ostext", help="a loose text representation of the windows OS (ex: \"windows xp home edition sp2\")") 343 | parser.add_argument("-s", "--sub", help="generate output using linked/sub bulletins. WARNING: SLOW!", action="store_true") 344 | parser.add_argument("-2", "--duplicates", help="allow duplicate ms bulletin output within the results. this will produce a lot of output, but is useful when determining linked ms bulletins", action="store_true") 345 | parser.add_argument("-q", "--quiet", help="don't show exploit information. shorter output", action="store_true") 346 | # hotfixes 347 | # used to parse "wmic qfe list full" input, and to solve the 'File 1' errors 348 | parser.add_argument("-H", "--hotfixes", help="a loose list of hotfixes to be added, for use with the following command: 'wmic qfe list full'") 349 | 350 | # search by exploit type only 351 | exptypegroup = parser.add_mutually_exclusive_group() 352 | exptypegroup.add_argument("-r", "--remote", help="search remote exploits only", action="store_true") 353 | exptypegroup.add_argument("-l", "--local", help="search local exploits only", action="store_true") 354 | 355 | # global args parsed 356 | ARGS = parser.parse_args() 357 | 358 | def main(): 359 | ALERT("initiating winsploit version %s..." % VERSION) 360 | 361 | database = '' 362 | 363 | # if there is a database switch 364 | if ARGS.database: 365 | 366 | # split name and extension 367 | name, extension = os.path.splitext(ARGS.database) 368 | 369 | # csv 370 | if 'csv' in extension: 371 | 372 | ALERT("database file detected as csv based on extension", ALERT.NORMAL) 373 | 374 | # attempt to open the file 375 | try: 376 | dbfile = open(ARGS.database, 'r') 377 | 378 | except IOError as e: 379 | ALERT("could not open the file %s" % filename, ALERT.BAD) 380 | exit(1) 381 | 382 | data = '' 383 | for line in dbfile: 384 | data += line 385 | database = data 386 | 387 | dbfile.close() 388 | 389 | # xslx 390 | elif 'xlsx' in extension: 391 | 392 | ALERT("database file detected as xlsx based on extension", ALERT.NORMAL) 393 | 394 | try: 395 | import openpyxl 396 | except ImportError as e: 397 | ALERT("please install and upgrade the openpyxl library", ALERT.BAD) 398 | exit(1) 399 | 400 | # open the xls file 401 | try: 402 | wb = openpyxl.load_workbook(ARGS.database) 403 | except IOError as e: 404 | ALERT("no such file or directory '%s'. ensure you have the correct database file passed in --database/-d" % ARGS.database, ALERT.BAD) 405 | exit(1) 406 | #sh = wb.sheet_by_name('Export Bulletin Search Spreadsh') 407 | shlist=wb.sheetnames 408 | sh = wb[shlist[0]] 409 | 410 | # read the spreadsheet into a temp file 411 | f = NamedTemporaryFile(mode='wb') 412 | wr = csv.writer(f, quoting=csv.QUOTE_NONE, delimiter=',') 413 | 414 | data = '' 415 | 416 | # loop through xls 417 | rowcount=0 418 | for row in sh: 419 | rowcount+=1 420 | for rownum in range(1, rowcount+1): 421 | 422 | values = [] 423 | rowObjs=sh[rownum] 424 | for rowobj in rowObjs: 425 | values.append(rowobj.value) 426 | 427 | # loop through row values, and process input 428 | for i in range(len(values)): 429 | values[i] = str(values[i]) 430 | values[i] = values[i].replace('\n',' ') 431 | values[i] = values[i].replace(',','') 432 | values[i] = values[i].replace('.0','') 433 | 434 | data += ",".join(values) 435 | data += '\n' 436 | 437 | # set the database to the csv data 438 | database = data 439 | 440 | #xls 441 | elif 'xls' in extension: 442 | 443 | ALERT("database file detected as xls or xlsx based on extension", ALERT.NORMAL) 444 | 445 | try: 446 | import xlrd 447 | except ImportError as e: 448 | ALERT("please install and upgrade the python-xlrd library", ALERT.BAD) 449 | exit(1) 450 | 451 | # open the xls file 452 | try: 453 | wb = xlrd.open_workbook(ARGS.database) 454 | except IOError as e: 455 | ALERT("no such file or directory '%s'. ensure you have the correct database file passed in --database/-d" % ARGS.database, ALERT.BAD) 456 | exit(1) 457 | #sh = wb.sheet_by_name('Export Bulletin Search Spreadsh') 458 | sh = wb.sheet_by_index(0) 459 | 460 | # read the spreadsheet into a temp file 461 | f = NamedTemporaryFile(mode='wb') 462 | wr = csv.writer(f, quoting=csv.QUOTE_NONE, delimiter=',') 463 | 464 | data = '' 465 | 466 | # loop through xls 467 | for rownum in range(sh.nrows): 468 | 469 | values = sh.row_values(rownum) 470 | 471 | # loop through row values, and process input 472 | for i in range(len(values)): 473 | values[i] = str(values[i]) 474 | values[i] = values[i].replace('\n',' ') 475 | values[i] = values[i].replace(',','') 476 | values[i] = values[i].replace('.0','') 477 | 478 | data += ",".join(values) 479 | data += '\n' 480 | 481 | # set the database to the csv data 482 | database = data 483 | 484 | 485 | # unknown filetype, error 486 | else: 487 | ALERT("unknown filetype. change file extension to indicate csv or xls/xlsx", ALERT.BAD) 488 | exit(1) 489 | 490 | if ARGS.trace: trace(database) 491 | elif ARGS.systeminfo or ARGS.ostext: run(database) 492 | elif ARGS.update: update() 493 | elif ARGS.patches: patches(database) 494 | 495 | # error 496 | else: 497 | ALERT("an error occured while running, not enough arguments", ALERT.BAD) 498 | exit(1) 499 | 500 | ALERT("done") 501 | # end main() 502 | 503 | def run(database): 504 | 505 | # variables used 506 | ostext=None 507 | name=None 508 | release=None 509 | servicepack=None 510 | 511 | # will default to 32-bit, but can be 64 bit or itanium 512 | architecture=None 513 | 514 | hotfixes=set([]) 515 | bulletinids=set([]) 516 | 517 | potential=[] 518 | 519 | vulns={} 520 | ids=set([]) 521 | 522 | cmdoutput = [] 523 | 524 | # test for database 525 | if not ARGS.database: 526 | ALERT("please supply a MSSB database file with the --database or -d flag, this can be downloaded using the --update command", ALERT.BAD) 527 | exit(1) 528 | 529 | # read from ostext first 530 | if ARGS.ostext: 531 | ALERT("getting OS information from command line text") 532 | 533 | name=getname(ARGS.ostext) 534 | release=getrelease(ARGS.ostext) 535 | servicepack=getservicepack(ARGS.ostext) 536 | architecture=getarchitecture(ARGS.ostext) 537 | 538 | # the os name at least has to be identified 539 | if not name: 540 | ALERT("unable to determine the windows version command line text from '%s'" % ARGS.ostext, ALERT.BAD) 541 | exit(1) 542 | 543 | # get the systeminfo information from the input file 544 | if ARGS.systeminfo: 545 | 546 | ALERT("attempting to read from the systeminfo input file") 547 | 548 | # when reading the systeminfo file, we want to attempt to detect it using chardet 549 | # if this doesn't work, we will loop through a list of common encodings and try them all 550 | encodings = ['utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', 'iso-8859-2'] 551 | 552 | detected_encoding = detect_encoding(ARGS.systeminfo) 553 | 554 | # insert detected encoding to the front of the list 555 | if detected_encoding: 556 | if ARGS.verbose: ALERT("detected encoding of file as '%s'" % detected_encoding) 557 | encodings.insert(0, detected_encoding) 558 | 559 | cmdfile = None 560 | cmdoutput = None 561 | 562 | # now loop through all encodings, with the detected one first (if it was possible) 563 | for encoding in encodings: 564 | 565 | if ARGS.verbose: ALERT(" attempting to read with '%s' encoding" % encoding) 566 | 567 | # if we can read the file, and read the command output, we are done with the loop 568 | try: 569 | cmdfile = io.open(ARGS.systeminfo, "r", encoding=encoding) # throws UnicodeDecodeError 570 | cmdoutput = cmdfile.readlines() # throws UnicodeError 571 | break 572 | 573 | except (UnicodeError, UnicodeDecodeError) as e: 574 | ALERT("could not read file using '%s' encoding: %s" % (encoding, e), ALERT.BAD) 575 | 576 | # file might not exist 577 | except: 578 | ALERT("could not read from input file specified: %s" % ARGS.systeminfo, ALERT.BAD) 579 | exit(1) 580 | 581 | # general catchall if somehow it was able to keep processing 582 | if not cmdfile or not cmdoutput: 583 | ALERT("could not read from input file, or could not detect encoding", ALERT.BAD) 584 | exit(1) 585 | 586 | # file read successfully 587 | ALERT("systeminfo input file read successfully (%s)" % encoding, ALERT.GOOD) 588 | 589 | # error 590 | if not ARGS.systeminfo and not ARGS.ostext and platform.system() != 'Windows': 591 | ALERT("please run from a Windows machine, or provide an input file using --systeminfo, or use the --ostext option to get data with no patch information", ALERT.BAD) 592 | exit(1) 593 | 594 | # parse the systeminfo information 595 | hotfix=False 596 | 597 | # loop through the systeminfo input 598 | for haystack in cmdoutput: 599 | 600 | # only attempt to set the version, arch, service pack if there is no 601 | # ostext flag 602 | if not ARGS.ostext: 603 | 604 | # when detecting the operating system version, every line (independent of language) 605 | # appears to have Microsoft Windows in it, sometimes with (R) 606 | if "Microsoft" in haystack and "Windows" in haystack and not name: 607 | name = getname(haystack) 608 | 609 | # the windows release is similar to the above and has the text 'Microsoft Windows' in the text 610 | if "Microsoft" in haystack and "Windows" in haystack and not release: 611 | release = getrelease(haystack) 612 | 613 | # similar to OS, there is the words 'Service Pack' 614 | if "Service Pack" in haystack and not servicepack: 615 | servicepack = getservicepack(haystack) 616 | 617 | # get architecture only if -based is in the line, and --ostext hasn't been used 618 | if "-based" in haystack and not architecture: 619 | architecture=getarchitecture(haystack) 620 | 621 | # look for kbs 622 | if ("KB" in haystack or "]: " in haystack): 623 | patch=getpatch(haystack) 624 | 625 | # if a patch was parsed 626 | if patch: 627 | if ARGS.verbose: ALERT("found hotfix %s" % patch) 628 | hotfixes.add(patch) 629 | 630 | # now process the hotfixes argument input 631 | if ARGS.hotfixes: 632 | 633 | encodings = ['utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', 'iso-8859-2'] 634 | 635 | detected_encoding = detect_encoding(ARGS.systeminfo) 636 | 637 | # insert detected encoding to the front of the list 638 | if detected_encoding: 639 | if ARGS.verbose: ALERT("detected encoding of file as '%s'" % detected_encoding) 640 | encodings.insert(0, detected_encoding) 641 | 642 | cmdfile = None 643 | hotfixesfile = None 644 | 645 | # now loop through all encodings, with the detected one first (if it was possible) 646 | for encoding in encodings: 647 | 648 | if ARGS.verbose: ALERT(" attempting to read with '%s' encoding" % encoding) 649 | 650 | # if we can read the file, and read the command output, we are done with the loop 651 | try: 652 | cmdfile = io.open(ARGS.hotfixes, "r", encoding=encoding) # throws UnicodeDecodeError 653 | hotfixesfile = cmdfile.readlines() # throws UnicodeError 654 | break 655 | 656 | except (UnicodeError, UnicodeDecodeError) as e: 657 | if ARGS.verbose: ALERT("could not read file using '%s' encoding: %s" % (encoding, e), ALERT.BAD) 658 | 659 | # file might not exist 660 | except: 661 | ALERT("could not read from input file specified: %s" % ARGS.hotfixes, ALERT.BAD) 662 | exit(1) 663 | 664 | # general catchall if somehow it was able to keep processing 665 | if not cmdfile or not hotfixesfile: 666 | ALERT("could not read from input file, or could not detect encoding", ALERT.BAD) 667 | exit(1) 668 | 669 | # file read successfully 670 | ALERT("hotfixes input file read successfully (%s)" % encoding, ALERT.GOOD) 671 | 672 | # loop through hotfixes file input 673 | for haystack in hotfixesfile: 674 | # look for kbs 675 | if ("KB" in haystack or "]: " in haystack): 676 | patch=getpatch(haystack) 677 | 678 | # if a patch was parsed 679 | if patch: 680 | if ARGS.verbose: ALERT("found hotfix %s" % patch) 681 | hotfixes.add(patch) 682 | 683 | if ARGS.verbose: 684 | ALERT("name: %s; release: %s; servicepack: %s; architecture: %s" % (name, release, servicepack, architecture)) 685 | 686 | # verify that a windows os was at least able to be parsed 687 | if not name: 688 | if ARGS.systeminfo: 689 | ALERT("unable to determine the windows versions from the input file specified. consider using --ostext option to force detection (example: --ostext 'windows 7 sp1 64-bit')", ALERT.BAD) 690 | exit(1) 691 | 692 | if ARGS.verbose: 693 | ALERT("name: %s" % name) 694 | ALERT("release: %s" % release) 695 | ALERT("service pack: %s" % servicepack) 696 | ALERT("architecture: %s" % architecture) 697 | 698 | ALERT("querying database file for potential vulnerabilities") 699 | 700 | # potential, all matches within the CSV database for the name,release,sp,arch 701 | # bulletinds, set of the above with MSIDs (good to keep count) 702 | 703 | # get the potential bulletins 704 | try: 705 | for row in csv.reader(StringIO(database)): 706 | bulletinid=row[1] 707 | affected=row[6] 708 | 709 | if isaffected(name, release, servicepack, architecture, affected): 710 | 711 | # only add the bulletin if it's not already in the list 712 | if bulletinid not in bulletinids: 713 | potential.append(row) 714 | bulletinids.add(bulletinid) 715 | 716 | if ARGS.verbose: 717 | ALERT("%s has been added to potential list '%s'" % (bulletinid, affected)) 718 | 719 | except csv.Error as e: 720 | ALERT('could not parse database file, make sure it is in the proper format', ALERT.BAD) 721 | exit(1) 722 | 723 | # there should always be some potential vulns, because of the amount of windows software and false positives 724 | if len(bulletinid) == 0: 725 | ALERT("there are no potential vulnerabilities for, ensure you're searching a valid windows OS", ALERT.BAD) 726 | exit(1) 727 | 728 | ALERT("comparing the %s hotfix(es) against the %s potential bulletins(s) with a database of %s known exploits" % (len(hotfixes), len(bulletinids), getexploit())) 729 | 730 | # start removing the vulns because of hotfixes 731 | for row in list(potential): 732 | 733 | # ms bulletin 734 | bulletinid=row[1] 735 | kb=row[2] 736 | componentkb=row[7] 737 | 738 | for hotfix in hotfixes: 739 | 740 | # if either the hotfixes match the kb or componentkb columns, and the bulletin is in the list 741 | # of potential bulletins 742 | if (hotfix == kb or hotfix == componentkb) and bulletinid in bulletinids: 743 | 744 | if ARGS.verbose: 745 | ALERT(" %s hotfix triggered a removal of %skb and the %s bulletin; componentkb is %s" % (hotfix,kb,bulletinid,componentkb)) 746 | 747 | # get the linked ms, this will automatically calculate the superseded by as well 748 | linkedms = getlinkedms([bulletinid], csv.reader(StringIO(database))) 749 | linkedmsstr = '' 750 | 751 | # calculate the pretty string, only care when verbose 752 | if len(linkedms) > 0: 753 | for m in linkedms: 754 | linkedmsstr += ' ' + m 755 | 756 | if ARGS.verbose: 757 | 758 | if hotfix == kb: 759 | ALERT(" due to presence of KB%s (Bulletin KB) removing%s bulletin(s)" % (kb, linkedmsstr)) 760 | 761 | elif componentkb == kb: 762 | ALERT(" due to presence of KB%s (Component KB) removing%s bulletin(s)" % (componentkb, linkedmsstr)) 763 | 764 | bulletinids = bulletinids.difference(linkedms) 765 | potential.remove(row) 766 | 767 | ALERT("there are now %s remaining vulns" % len(bulletinids)) 768 | 769 | # search local exploits only 770 | if ARGS.local: 771 | ALERT("searching for local exploits only") 772 | for row in list(potential): 773 | bulletinid = row[1] 774 | impact = row[4] 775 | 776 | if bulletinid in bulletinids and not "elevation of privilege" in impact.lower(): 777 | 778 | remove = getlinkedms([bulletinid], csv.reader(StringIO(database))) 779 | 780 | if ARGS.verbose: 781 | ALERT(" removing %s (total of %s MS ids), because of its impact %s" % (bulletinid, len(remove), impact)) 782 | 783 | bulletinids = bulletinids.difference(remove) 784 | potential.remove(row) 785 | 786 | # search remote exploits only 787 | if ARGS.remote: 788 | ALERT("searching for remote exploits only") 789 | for row in list(potential): 790 | bulletinid = row[1] 791 | impact = row[4] 792 | 793 | if bulletinid in bulletinids and not "remote code execution" in impact.lower(): 794 | 795 | remove = getlinkedms([bulletinid], csv.reader(StringIO(database))) 796 | 797 | if ARGS.verbose: 798 | ALERT(" removing %s (total of %s MS ids), because of its impact %s" % (bulletinid, len(remove), impact)) 799 | 800 | bulletinids = bulletinids.difference(remove) 801 | potential.remove(row) 802 | 803 | # print windows version 804 | version=getversion(name, release, servicepack, architecture) 805 | 806 | ALERT("[E] exploitdb PoC, [M] Metasploit module, [*] missing bulletin", ALERT.GOOD) 807 | ALERT("windows version identified as '%s'" % version, ALERT.GOOD) 808 | 809 | # spacer 810 | ALERT("") 811 | 812 | # vulns, the dictionary of the bulletins based off of the potential bulletins 813 | # also, a good opportunity to remove false-positives due to the 814 | # differences in the technet post and bulletin 815 | for row in potential: 816 | id = row[1] 817 | 818 | # start removing vulns because of false-positives 819 | # Manual override for MS11-011 to reduce false positives. The article was updated, but the bulletin database wasn't (https://technet.microsoft.com/en-us/library/security/ms11-011.aspx) 820 | # V1.2 (March 18, 2011): Added Windows 7 for 32-bit Systems Service Pack 1, Windows 7 for x64-based Systems Service Pack 1, Windows Server 2008 R2 for x64-based Systems Service Pack 1, and Windows Server 2008 R2 for Itanium-based Systems Service Pack 1 to Non-Affected Software. This is an informational change only. There were no changes to the security update files or detection logic. 821 | if id == 'MS11-011': 822 | ms11_011 = ['Windows 7 for 32-bit Systems Service Pack 1', 'Windows 7 for x64-based Systems Service Pack 1', 'Windows Server 2008 R2 for x64-based Systems Service Pack 1','Windows Server 2008 R2 for Itanium-based Systems Service Pack 1'] 823 | for not_affected in ms11_011: 824 | compare_version = getversion(getname(not_affected),getrelease(not_affected),getservicepack(not_affected),getarchitecture(not_affected)) 825 | if version == compare_version: 826 | if ARGS.verbose: ALERT("Ignoring MS11-011 false positive due to it not affecting '%s'" % compare_version) 827 | id = False 828 | 829 | for bulletinid in bulletinids: 830 | if bulletinid == id: 831 | title = row[5] 832 | kb = row[2] 833 | severity = row[3] 834 | if id not in ids: 835 | vulns[id] = [title,kb,severity] 836 | ids.add(id) 837 | 838 | # alerted, if a bulletin has been alerted to the user so that it doesn't appear twice 839 | # this occurs when a bulletin has multiple parents 840 | # msids, the actual data for all of the relevant msids (the row from the CSV) 841 | alerted = set() 842 | msids = sorted(vulns, reverse=True) 843 | 844 | # loop through the bulletinids which is the set of the actual bulletins that are to 845 | # be alerted 846 | for msid in msids: 847 | 848 | ## don't alert twice, no matter the case 849 | if msid not in alerted: 850 | 851 | # get the msid, exploitability alert rating, and resources 852 | m,exploit,resources = getexploit(msid) 853 | 854 | # only display the message, if the exploit flag isn't used 855 | # or if it is used, and the alert level is MSF or EXP 856 | if ARGS.audit or (exploit == ALERT.MSF or exploit == ALERT.EXP): 857 | 858 | alert = ALERT.NORMAL 859 | if exploit: alert = exploit 860 | 861 | ALERT("%s: %s (%s) - %s" % (msid, vulns[msid][0], vulns[msid][1], vulns[msid][2]), alert) 862 | if resources and not ARGS.quiet: 863 | for resource in resources: 864 | ALERT(" %s" % resource) 865 | ALERT("") 866 | 867 | alerted.add(msid) 868 | 869 | # only attempt to display linked/sub msids based on cli arguments 870 | if ARGS.sub: 871 | 872 | # linked ms, the children of this msid 873 | linked = set(getlinkedms([msid], csv.reader(StringIO(database)))) 874 | linked = linked.intersection(msids) 875 | 876 | # loop through the linked msids, and only display those that qualify and 877 | # those that have not been alerted yet 878 | for lmsid in sorted(linked, reverse=True): 879 | if lmsid in msids and lmsid not in alerted: 880 | lexploit = getexploit(lmsid) 881 | lalert = ALERT.NORMAL 882 | if ARGS.audit or (lexploit == ALERT.MSF or lexploit == ALERT.EXP): 883 | if lexploit: lalert = lexploit 884 | ALERT("|_%s: %s (%s) - %s" % (lmsid, vulns[lmsid][0], vulns[lmsid][1], vulns[lmsid][2]), lalert) 885 | 886 | # only allow duplicate events to be displayed when command-line args passed 887 | if not ARGS.duplicates: alerted.add(lmsid) 888 | 889 | # end run() 890 | 891 | 892 | # attempt to detect character encoding of a file 893 | # otherwise return None 894 | # https://stackoverflow.com/questions/3323770/character-detection-in-a-text-file-in-python-using-the-universal-encoding-detect 895 | def detect_encoding(filename): 896 | try: 897 | import chardet 898 | data = open(filename, "r").read() 899 | result = chardet.detect(data) 900 | encoding = result['encoding'] 901 | return encoding 902 | except: 903 | return None 904 | 905 | # the trace command is used to determine linked MS bulletins 906 | # TODO much of this is duplicated from run(). should be merged 907 | def trace(database): 908 | 909 | # convert to upper 910 | bulletinid = ARGS.trace.upper() 911 | ALERT("searching for bulletin id %s" % bulletinid) 912 | 913 | # get linked msids 914 | lmsids = getlinkedms([bulletinid], csv.reader(StringIO(database))) 915 | 916 | msids = [] 917 | 918 | if ARGS.ostext: 919 | ALERT("getting OS information from command line text") 920 | 921 | name=getname(ARGS.ostext) 922 | release=getrelease(ARGS.ostext) 923 | servicepack=getservicepack(ARGS.ostext) 924 | architecture=getarchitecture(ARGS.ostext) 925 | 926 | if ARGS.verbose: 927 | ALERT("name: %s" % name) 928 | ALERT("release: %s" % release) 929 | ALERT("service pack: %s" % servicepack) 930 | ALERT("architecture: %s" % architecture) 931 | 932 | # the os name at least has to be identified 933 | if not name: 934 | ALERT("unable to determine the windows version command line text from '%s'" % ARGS.ostext, ALERT.BAD) 935 | exit(1) 936 | 937 | # get linked msids, loop through the row 938 | for row in csv.reader(StringIO(database)): 939 | msid = row[1] 940 | affected = row[6] 941 | 942 | if msid in lmsids: 943 | # debug 944 | #print ("%s,%s,%s,%s,%s,%s" % (msid, name, release, servicepack, architecture, affected)) 945 | 946 | if isaffected(name, release, servicepack, architecture, affected) and msid not in msids: msids.append(msid) 947 | 948 | 949 | else: msids = lmsids 950 | 951 | ALERT("linked msids %s" % msids, ALERT.GOOD) 952 | 953 | 954 | def patches(database): 955 | 956 | kbs = [] 957 | 958 | # convert to upper 959 | bulletinid = ARGS.patches.upper() 960 | ALERT("searching all kb's for bulletin id %s" % bulletinid) 961 | 962 | # get linked msids, loop through the row 963 | for row in csv.reader(StringIO(database)): 964 | 965 | bulletinkb=row[2] 966 | componentkb=row[7] 967 | 968 | # if there's a match 969 | if bulletinid in row[1]: 970 | kbs.append(bulletinkb) 971 | kbs.append(componentkb) 972 | 973 | ALERT("relevant kbs %s" % (sorted(set(kbs), reverse=True)), ALERT.GOOD) 974 | 975 | def getversion(name, release, servicepack, architecture): 976 | 977 | version = "Windows " + name 978 | 979 | # append release first 980 | if release: version += " R" + release 981 | 982 | # then service pack 983 | if servicepack: version += " SP" + servicepack 984 | 985 | # architecture 986 | if architecture == "Itanium": version += " Itanium-based" 987 | else: version += " %s-bit" % architecture 988 | 989 | return version 990 | 991 | 992 | def getname(ostext): 993 | 994 | if ostext == False: 995 | return False 996 | 997 | osname=False 998 | 999 | osnamearray=[["xp","XP"], 1000 | ["2000","2000"], 1001 | ["2003","2003"], 1002 | ["vista","Vista"], 1003 | ["2008","2008"], 1004 | [" 7","7"], 1005 | [" 8","8"], 1006 | ["2012","2012"], 1007 | ["8.1","8.1"], 1008 | [" 10","10"]] 1009 | 1010 | for needle in osnamearray: 1011 | ostext = ostext.lower() 1012 | if "windows" + needle[0] in ostext or "windows " + needle[0] in ostext or "server" + needle[0] in ostext or "server " + needle[0] in ostext: 1013 | osname = needle[1] 1014 | 1015 | # the first loop is a more restrictive detection of the OS name, but it does not detect the following 1016 | # > Microsoft Windows\xFF7 Entreprise 1017 | # so if there is no detection from the first attempt, then search on a more loosely based string of 1018 | # needle and space 1019 | if not osname: 1020 | for needle in osnamearray: 1021 | if needle[0] + " " in ostext.lower(): 1022 | osname = needle[1] 1023 | 1024 | return osname 1025 | 1026 | 1027 | def getrelease(ostext): 1028 | 1029 | if ostext == False: 1030 | return False 1031 | 1032 | osrelease=False 1033 | 1034 | regex="( r| rc|release|rel)[ ]*(\d)" 1035 | m=re.search(regex, ostext.lower()) 1036 | 1037 | if m and m.group(2): 1038 | osrelease=m.group(2) 1039 | 1040 | return osrelease 1041 | 1042 | def getservicepack(ostext): 1043 | 1044 | if ostext == False: 1045 | return False 1046 | 1047 | servicepack=False 1048 | 1049 | regex="(sp|pack|pack:)[ ]*(\d)" 1050 | m=re.search(regex, ostext.lower()) 1051 | if m and m.group(2): 1052 | servicepack=m.group(2) 1053 | 1054 | return servicepack 1055 | 1056 | 1057 | # architecture defaults to 32, but can be 64-bit 1058 | # or itanium based 1059 | def getarchitecture(ostext): 1060 | 1061 | # default to 32-bit 1062 | architecture="32" 1063 | 1064 | # haystack 1065 | s = ostext.lower() 1066 | 1067 | # attempt to be as flexible as possible 1068 | # matching '64-based', 'x64', ' 64', 'i64', '64bit', '64 bit', '64-bit' 1069 | if ("64-based" in s) or ("x64" in s) or (" 64" in s) or ("i64" in s) or ("64bit" in s) or ("64 bit" in s) or ("64-bit" in s): architecture="64" 1070 | 1071 | # target Itanium with a simple search for 'tani' 1072 | if "tani" in s: architecture="Itanium" 1073 | 1074 | if getname(ostext) == "2008" and getrelease(ostext) == "2" and architecture == "32": 1075 | if ARGS.verbose: 1076 | ALERT("forcing unidentified architecture to 64-bit because OS identified as Windows 2008 R2 (although could be Itanium and wasn't detected?)") 1077 | architecture = "64" 1078 | 1079 | # windows server 2012 is only 64-bit arch 1080 | if getname(ostext) == "2012" and architecture == "32": 1081 | if ARGS.verbose: 1082 | ALERT("forcing unidentified architecture to 64-bit because OS identified as Windows Server 2012 does not support 32-bit") 1083 | architecture = "64" 1084 | 1085 | return architecture 1086 | 1087 | # itanium build search string 1088 | def getitanium(ostext): 1089 | 1090 | if ostext == False: 1091 | return False 1092 | 1093 | regex="(tanium)" 1094 | m=re.search(regex, ostext.lower()) 1095 | 1096 | if m: 1097 | return True 1098 | 1099 | return False 1100 | 1101 | def getpatch(ostext): 1102 | 1103 | patch=False 1104 | 1105 | regex="(\d){5,10}" 1106 | m=re.search(regex, ostext.lower()) 1107 | if m and m.group(): 1108 | patch=m.group() 1109 | 1110 | return patch 1111 | 1112 | # get the bulletin ids from the haystack 1113 | # these are typically in the form of: 1114 | # MS14-009[2898860] 1115 | # MS13-052[2833940],MS14-009[2898856] 1116 | # will return a list if found, otherwise false 1117 | def getbulletinids(haystack): 1118 | regex="MS[\d]{2,3}-[\d]{2,3}" 1119 | m = re.findall(regex, haystack) 1120 | if len(m) > 0: return m 1121 | return False 1122 | 1123 | def isaffected(name, release, servicepack, architecture, haystack): 1124 | 1125 | if name == getname(haystack): 1126 | 1127 | # ensure None are set to False 1128 | # example, if getservicepack() does not get called in the systeminfo parsing 1129 | # then servicepack will be None. this will then fail when comparing to False. 1130 | if release == None: release = False 1131 | if servicepack == None: servicepack = False 1132 | if architecture == None: architecture = False 1133 | 1134 | # print "%s,%s,%s,%s" % (name, release, servicepack, architecture) 1135 | # print "%s,%s,%s,%s" % (getname(haystack),getrelease(haystack),getservicepack(haystack),getarchitecture(haystack)) 1136 | 1137 | n = (name == getname(haystack)) 1138 | r = (release == getrelease(haystack)) 1139 | s = (servicepack == getservicepack(haystack)) 1140 | a = (architecture == getarchitecture(haystack)) 1141 | 1142 | # we ignore the architecture for 2012 servers, as there is only 64-bit 1143 | if name == "2012": return r and s 1144 | 1145 | # print "%s,%s,%s,%s,%s" % (name, release, servicepack, architecture, (a and r and s)) 1146 | 1147 | return a and r and s 1148 | 1149 | # search entire database for linked msids 1150 | # this will also search the superseded column (11) 1151 | def getlinkedms(msids, database): 1152 | 1153 | lmsids = [] 1154 | 1155 | # go through each row in the database 1156 | for row in database: 1157 | 1158 | # base MS-XX 1159 | rowid=row[1] 1160 | 1161 | # superseded MS-XX 1162 | 1163 | # first try row 12, and then row 11 for the supercedes column due to 1164 | # differences in csv and xlrd parsing. this was a bug that might be 1165 | # fixed now 1166 | rowidsuper = getbulletinids(row[12]) 1167 | if rowidsuper == False: rowidsuper=getbulletinids(row[11]) 1168 | 1169 | rowidsuper = merge_list(rowidsuper) 1170 | 1171 | # loop through each msid for each row 1172 | for msid in msids: 1173 | 1174 | # debug output, what we're working with 1175 | #print "%s,%s,%s" % (msid, rowid, rowidsuper) 1176 | # MS14-053,MS14-053,['MS13-052', 'MS14-009'] 1177 | # MS14-053,MS14-053,['MS13-004'] 1178 | # MS14-053,MS14-053,['MS13-004'] 1179 | # MS14-053,MS14-053,['MS13-004'] 1180 | # MS14-053,MS14-053,['MS13-004'] 1181 | # MS14-053,MS14-053,[] 1182 | 1183 | # if the msid matches the row, get the supercedes column (which is a list) 1184 | if msid == rowid or rowid in lmsids: 1185 | #print "%s,%s,%s" % (msid, rowid, rowidsuper) 1186 | lmsids.append(msid) 1187 | lmsids = lmsids + rowidsuper 1188 | 1189 | return sorted(set(lmsids), reverse=True) 1190 | 1191 | # determines whether or not an msid is in a list of exploits. if msid = 0 1192 | # then it will just return the count 1193 | def getexploit(msid = 0): 1194 | # search using searchsploit 1195 | #MS Windows (ListBox/ComboBox Control) Local Exploit (MS03-045) /windows/local/122.c 1196 | #MS Windows Utility Manager Local SYSTEM Exploit (MS04-011) /windows/local/271.c 1197 | #MS Windows 2000 Utility Manager Privilege Elevation Exploit (MS04-019) /windows/local/350.c 1198 | #MS Windows 2K POSIX Subsystem Privilege Escalation Exploit (MS04-020) /windows/local/351.c 1199 | #MS Windows 2000 Universal Language Utility Manager Exploit (MS04-019) /windows/local/352.c 1200 | #MS Windows 2K/XP Task Scheduler .job Exploit (MS04-022) /windows/local/353.c 1201 | #MS Windows 2k Utility Manager (All-In-One) Exploit (MS04-019) /windows/local/355.c 1202 | #MS Windows XP Task Scheduler (.job) Universal Exploit (MS04-022) /windows/local/368.c 1203 | #MS Windows (HTA) Script Execution Exploit (MS05-016) /windows/local/938.cpp 1204 | #MS Windows COM Structured Storage Local Exploit (MS05-012) /windows/local/1019.c 1205 | #MS Windows CSRSS Local Privilege Escalation Exploit (MS05-018) /windows/local/1198.c 1206 | #MS Windows 2k Kernel APC Data-Free Local Escalation Exploit (MS05-055) /windows/local/1407.c 1207 | #MS Windows Telephony Service Command Execution Exploit (MS05-040) /windows/local/1584.cpp 1208 | #MS Windows (NtClose DeadLock) Vulnerability PoC (MS06-030) /windows/local/1910.c 1209 | #MS Windows XP/2K (Mrxsmb.sys) Privilege Escalation PoC (MS06-030) /windows/local/1911.c 1210 | #Microsoft IIS ASP Stack Overflow Exploit (MS06-034) /windows/local/2056.c 1211 | #MS Windows (Windows Kernel) Privilege Escalation Exploit (MS06-049) /windows/local/2412.c 1212 | #MS Windows GDI Local Privilege Escalation Exploit (MS07-017) /windows/local/3688.c 1213 | #MS Windows GDI Local Privilege Escalation Exploit (MS07-017) 2 /windows/local/3755.c 1214 | #Kodak Image Viewer TIF/TIFF Code Execution Exploit PoC (MS07-055) /windows/local/4584.c 1215 | #Microsoft Office .WPS File Stack Overflow Exploit (MS08-011) /windows/local/5107.c 1216 | #Microsoft Office Excel Code Execution Exploit (MS08-014) /windows/local/5287.txt 1217 | #Microsoft Office XP SP3 PPT File Buffer Overflow Exploit (ms08-016) /windows/local/5320.txt 1218 | #MS Windows GDI Image Parsing Stack Overflow Exploit (MS08-021) /windows/local/5442.cpp 1219 | 1220 | #MS Word Record Parsing Buffer Overflow (MS09-027) /windows/local/14693.py 1221 | #MS Excel Malformed FEATHEADER Record Exploit (MS09-067) /windows/local/14706.py 1222 | #MS Word Record Parsing Buffer Overflow MS09-027 (meta) /windows/local/17177.rb 1223 | #MS Internet Explorer Object Tag Exploit (MS03-020) /windows/remote/37.pl 1224 | #MS Windows Media Services Remote Exploit (MS03-022) /windows/remote/48.c 1225 | #Microsoft WordPerfect Document Converter Exploit (MS03-036) /windows/remote/92.c 1226 | #MS Windows (RPC DCOM) Scanner (MS03-039) /windows/remote/97.c 1227 | #MS Windows (RPC DCOM) Long Filename Overflow Exploit (MS03-026) /windows/remote/100.c 1228 | #MS Windows (RPC DCOM2) Remote Exploit (MS03-039) /windows/remote/103.c 1229 | #MS Windows (RPC2) Universal Exploit & DoS (RPC3) (MS03-039) /windows/remote/109.c 1230 | #MS Windows 2000/XP Workstation Service Overflow (MS03-049) /windows/remote/119.c 1231 | #MS Frontpage Server Extensions fp30reg.dll Exploit (MS03-051) /windows/remote/121.c 1232 | #MS Windows Workstation Service WKSSVC Remote Exploit (MS03-049) /windows/remote/123.c 1233 | #MS Windows XP Workstation Service Remote Exploit (MS03-049) /windows/remote/130.c 1234 | #MS Windows Messenger Service Remote Exploit FR (MS03-043) /windows/remote/135.c 1235 | #MS Internet Explorer URL Injection in History List (MS04-004) /windows/remote/151.txt 1236 | #MS Windows IIS 5.0 SSL Remote buffer overflow Exploit (MS04-011) /windows/remote/275.c 1237 | #MS Windows Lsasrv.dll RPC Remote Buffer Overflow Exploit (MS04-011) /windows/remote/293.c 1238 | #MS Windows XP/2K Lsasrv.dll Remote Universal Exploit (MS04-011) /windows/remote/295.c 1239 | #MS Windows JPEG GDI+ Overflow Administrator Exploit (MS04-028) /windows/remote/475.sh 1240 | #MS Windows JPEG GDI+ Overflow Download Shellcode Exploit (MS04-028) /windows/remote/478.c 1241 | #MS Windows JPEG GDI+ Remote Heap Overflow Exploit (MS04-028) /windows/remote/480.c 1242 | #MS Windows Metafile (.emf) Heap Overflow Exploit (MS04-032) /windows/remote/584.c 1243 | #MS Windows Compressed Zipped Folders Exploit (MS04-034) /windows/remote/640.c 1244 | #MS Windows NetDDE Remote Buffer Overflow Exploit (MS04-031) /windows/remote/734.c 1245 | #MS Internet Explorer .ANI files handling Universal Exploit (MS05-002) /windows/remote/765.c 1246 | #MS Internet Explorer .ANI files handling Downloader Exploit (MS05-002) /windows/remote/771.cpp 1247 | #MS Exchange Server Remote Code Execution Exploit (MS05-021) /windows/remote/947.pl 1248 | #MS Outlook Express NNTP Buffer Overflow Exploit (MS05-030) /windows/remote/1066.cpp 1249 | #MS Windows Message Queuing BoF Universal Exploit (MS05-017) (v.0.3) /windows/remote/1075.c 1250 | #MS Internet Explorer (blnmgr.dll) COM Object Remote Exploit (MS05-038) /windows/remote/1144.html 1251 | #MS Windows Plug-and-Play Service Remote Overflow (MS05-039) /windows/remote/1146.c 1252 | #MS Windows Plug-and-Play Service Remote Universal Exploit (MS05-039) /windows/remote/1149.c 1253 | #Microsoft Windows DTC Remote Exploit (PoC) (MS05-051) (updated) /windows/remote/1352.cpp 1254 | #Windows Media Player 7.1 <= 10 BMP Heap Overflow PoC (MS06-005) (2) /windows/remote/1502.py 1255 | #MS Windows Media Player 9 Plugin Overflow Exploit (MS06-006) (meta) /windows/remote/1504.pm 1256 | #MS Windows Media Player 10 Plugin Overflow Exploit (MS06-006) /windows/remote/1505.html 1257 | #MS Windows Color Management Module Overflow Exploit (MS05-036) (2) /windows/remote/1506.c 1258 | #MS Windows Media Player Plugin Overflow Exploit (MS06-006)(3) /windows/remote/1520.pl 1259 | #MS Windows RRAS Remote Stack Overflow Exploit (MS06-025) /windows/remote/1940.pm 1260 | #MS Windows RRAS RASMAN Registry Stack Overflow Exploit (MS06-025) /windows/remote/1965.pm 1261 | #MS Internet Explorer (MDAC) Remote Code Execution Exploit (MS06-014) /windows/remote/2052.sh 1262 | #MS Windows DHCP Client Broadcast Attack Exploit (MS06-036) /windows/remote/2054.txt 1263 | #MS Windows NetpIsRemote() Remote Overflow Exploit (MS06-040) /windows/remote/2162.pm 1264 | #Internet Explorer (MDAC) Remote Code Execution Exploit (MS06-014) (2) /windows/remote/2164.pm 1265 | #MS Windows CanonicalizePathName() Remote Exploit (MS06-040) /windows/remote/2223.c 1266 | #MS Windows NetpIsRemote() Remote Overflow Exploit (MS06-040) (2) /windows/remote/2265.c 1267 | #MS Windows NetpIsRemote() Remote Overflow Exploit (MS06-040) (2k3) /windows/remote/2355.pm 1268 | #MS Windows NetpManageIPCConnect Stack Overflow Exploit (MS06-070) /windows/remote/2789.cpp 1269 | #MS Windows Wkssvc NetrJoinDomain2 Stack Overflow Exploit (MS06-070) /windows/remote/2800.cpp 1270 | #MS Windows ASN.1 Remote Exploit (MS04-007) /windows/remote/3022.txt 1271 | #MS Internet Explorer VML Remote Buffer Overflow Exploit (MS07-004) /windows/remote/3137.html 1272 | #MS Internet Explorer VML Download and Execute Exploit (MS07-004) /windows/remote/3148.pl 1273 | #MS Internet Explorer Recordset Double Free Memory Exploit (MS07-009) /windows/remote/3577.html 1274 | #MS Windows (.ANI) GDI Remote Elevation of Privilege Exploit (MS07-017) /windows/remote/3804.txt 1275 | #MS Internet Explorer <= 7 Remote Arbitrary File Rewrite PoC (MS07-027) /windows/remote/3892.html 1276 | #Microsoft Internet Explorer TIF/TIFF Code Execution (MS07-055) /windows/remote/4616.pl 1277 | #MS Windows Message Queuing Service RPC BOF Exploit (MS07-065) /windows/remote/4745.cpp 1278 | #MS Windows 2000 AS SP4 Message Queue Exploit (MS07-065) /windows/remote/4760.txt 1279 | #Windows Media Encoder wmex.dll ActiveX BOF Exploit (MS08-053) /windows/remote/6454.html 1280 | #MS Windows GDI (EMR_COLORMATCHTOTARGETW) Exploit MS08-021 /windows/remote/6656.txt 1281 | #MS Windows Server Service Code Execution Exploit (MS08-067) (Univ) /windows/remote/6841.txt 1282 | #MS Windows Server Service Code Execution Exploit (MS08-067) /windows/remote/7104.c 1283 | #SmbRelay3 NTLM Replay Attack Tool/Exploit (MS08-068) /windows/remote/7125.txt 1284 | #MS Windows Server Service Code Execution Exploit (MS08-067) (2k/2k3) /windows/remote/7132.py 1285 | #Microsoft XML Core Services DTD Cross-Domain Scripting PoC MS08-069 /windows/remote/7196.html 1286 | #MS Internet Explorer 7 Memory Corruption Exploit (MS09-002) (xp sp2) /windows/remote/8079.html 1287 | #MS Internet Explorer 7 Memory Corruption Exploit (MS09-002) (py) /windows/remote/8080.py 1288 | #MS Internet Explorer 7 Memory Corruption PoC (MS09-002) (win2k3sp2) /windows/remote/8082.html 1289 | #MS Internet Explorer 7 Memory Corruption Exploit (MS09-002) (fast) /windows/remote/8152.py 1290 | #Microsoft SRV2.SYS SMB Negotiate ProcessID Function Table Dereference (MS09-050) /windows/remote/14674.txt 1291 | #Microsoft Services MS06-066 nwwks.dll /windows/remote/16369.rb 1292 | #Microsoft Services MS06-066 nwapi32.dll /windows/remote/16373.rb 1293 | #MS03-020 Internet Explorer Object Type /windows/remote/16581.rb 1294 | #MS03-046 Exchange 2000 XEXCH50 Heap Overflow /windows/remote/16820.rb 1295 | 1296 | # no ms number yet? 1297 | #MS??-???,http://www.exploit-db.com/exploits/30014/,P,??2914486 1298 | # bulletin, type, details 1299 | exploits = [ 1300 | 1301 | ['MS16-135', ALERT.EXP, [ # CVE-2016-7255 1302 | "https://www.exploit-db.com/exploits/40745/ -- Microsoft Windows Kernel - win32k Denial of Service (MS16-135)", 1303 | "https://www.exploit-db.com/exploits/41015/ -- Microsoft Windows Kernel - 'win32k.sys' 'NtSetWindowLongPtr' Privilege Escalation (MS16-135) (2)", 1304 | "https://github.com/tinysec/public/tree/master/CVE-2016-7255"]], 1305 | 1306 | ['MS16-129', ALERT.EXP, [ # CVE 2016-7200, CVE-2016-7201 1307 | "https://www.exploit-db.com/exploits/40990/ -- Microsoft Edge (Windows 10) - 'chakra.dll' Info Leak / Type Confusion Remote Code Execution", 1308 | "https://github.com/theori-io/chakra-2016-11"]], 1309 | 1310 | ['MS16-098', ALERT.EXP, [ 1311 | "https://www.exploit-db.com/exploits/41020/ -- Microsoft Windows 8.1 (x64) - RGNOBJ Integer Overflow (MS16-098)"]], 1312 | 1313 | ['MS16-075', ALERT.MSF, [ 1314 | "https://github.com/foxglovesec/RottenPotato", 1315 | "https://github.com/Kevin-Robertson/Tater", 1316 | "https://bugs.chromium.org/p/project-zero/issues/detail?id=222 -- Windows: Local WebDAV NTLM Reflection Elevation of Privilege", 1317 | "https://foxglovesecurity.com/2016/01/16/hot-potato/ -- Hot Potato - Windows Privilege Escalation"]], 1318 | 1319 | ['MS16-074', ALERT.EXP, [ # CVE 2016-3216 1320 | "https://www.exploit-db.com/exploits/39990/ -- Windows - gdi32.dll Multiple DIB-Related EMF Record Handlers Heap-Based Out-of-Bounds Reads/Memory Disclosure (MS16-074), PoC", 1321 | "https://www.exploit-db.com/exploits/39991/ -- Windows Kernel - ATMFD.DLL NamedEscape 0x250C Pool Corruption (MS16-074), PoC"]], # CVE 2016-3220 1322 | 1323 | ['MS16-063', ALERT.EXP, [ # CVE 2016-0199 1324 | "https://www.exploit-db.com/exploits/39994/ -- Internet Explorer 11 - Garbage Collector Attribute Type Confusion (MS16-063), PoC"]], 1325 | 1326 | ['MS16-042', ALERT.EXP, [ # CVE 2016-0122 1327 | "https://www.exploit-db.com/exploits/39694/ -- Microsoft Office Excel Out-of-Bounds Read Remote Code Execution (MS16-042), PoC"]], 1328 | 1329 | ['MS16-059', ALERT.EXP, [ # CVE 2016-0185 1330 | "https://www.exploit-db.com/exploits/39805/ -- Microsoft Windows Media Center - .MCL File Processing Remote Code Execution (MS16-059), PoC"]], 1331 | 1332 | ['MS16-056', ALERT.EXP, [ # CVE-2015-1730 1333 | "https://www.exploit-db.com/exploits/40881/ -- Microsoft Internet Explorer - jscript9 Java­Script­Stack­Walker Memory Corruption (MS15-056)", 1334 | "http://blog.skylined.nl/20161206001.html -- MSIE jscript9 Java­Script­Stack­Walker memory corruption"]], 1335 | 1336 | ['MS16-032', ALERT.EXP, [ # CVE 2016-0099 1337 | "https://www.exploit-db.com/exploits/40107/ -- MS16-032 Secondary Logon Handle Privilege Escalation, MSF", 1338 | "https://www.exploit-db.com/exploits/39574/ -- Microsoft Windows 8.1/10 - Secondary Logon Standard Handles Missing Sanitization Privilege Escalation (MS16-032), PoC", 1339 | "https://www.exploit-db.com/exploits/39719/ -- Microsoft Windows 7-10 & Server 2008-2012 (x32/x64) - Local Privilege Escalation (MS16-032) (PowerShell), PoC", 1340 | "https://www.exploit-db.com/exploits/39809/ -- Microsoft Windows 7-10 & Server 2008-2012 (x32/x64) - Local Privilege Escalation (MS16-032) (C#)"]], 1341 | 1342 | ['MS16-016', ALERT.MSF, [ # CVE 2016-0051 1343 | "https://www.exploit-db.com/exploits/40085/ -- MS16-016 mrxdav.sys WebDav Local Privilege Escalation, MSF", 1344 | "https://www.exploit-db.com/exploits/39788/ -- Microsoft Windows 7 - WebDAV Privilege Escalation Exploit (MS16-016) (2), PoC", 1345 | "https://www.exploit-db.com/exploits/39432/ -- Microsoft Windows 7 SP1 x86 - WebDAV Privilege Escalation (MS16-016) (1), PoC"]], 1346 | 1347 | ['MS16-014', ALERT.EXP, [ # CVE 2016-0400 1348 | "Windows 7 SP1 x86 - Privilege Escalation (MS16-014), https://www.exploit-db.com/exploits/40039/, PoC"]], 1349 | 1350 | ['MS16-007', ALERT.EXP, [ # CVE 2016-0015, CVE 2016-0016 1351 | "https://www.exploit-db.com/exploits/39232/ -- Microsoft Windows devenum.dll!DeviceMoniker::Load() - Heap Corruption Buffer Underflow (MS16-007), PoC", 1352 | "https://www.exploit-db.com/exploits/39233/ -- Microsoft Office / COM Object DLL Planting with WMALFXGFXDSP.dll (MS-16-007), PoC"]], 1353 | 1354 | ['MS15-134', ALERT.EXP, [ # CVE 2015-6131 1355 | "https://www.exploit-db.com/exploits/38911/ -- Microsoft Windows Media Center Library Parsing RCE Vulnerability aka self-executing' MCL File, PoC", 1356 | "https://www.exploit-db.com/exploits/38912/ -- Microsoft Windows Media Center Link File Incorrectly Resolved Reference, PoC", 1357 | "https://www.exploit-db.com/exploits/38918/ -- Microsoft Office / COM Object - 'els.dll' DLL Planting (MS15-134)", 1358 | "https://code.google.com/p/google-security-research/issues/detail?id=514 -- Microsoft Office / COM Object DLL Planting with els.dll"]], 1359 | 1360 | ['MS15-132', ALERT.EXP, [ # CVE 2015-6132, CVE 2015-6128 1361 | "https://www.exploit-db.com/exploits/38968/ -- Microsoft Office / COM Object DLL Planting with comsvcs.dll Delay Load of mqrt.dll (MS15-132), PoC", 1362 | "https://www.exploit-db.com/exploits/38918/ -- Microsoft Office / COM Object els.dll DLL Planting (MS15-134), PoC"]], 1363 | 1364 | ['MS15-112', ALERT.EXP, [ # CVE 2015-6086 1365 | "https://www.exploit-db.com/exploits/39698/ -- Internet Explorer 9/10/11 - CDOMStringDataList::InitFromString Out-of-Bounds Read (MS15-112)"]], 1366 | 1367 | ['MS15-111', ALERT.EXP, [ # CVE 2015-2553 1368 | "https://www.exploit-db.com/exploits/38474/ -- Windows 10 Sandboxed Mount Reparse Point Creation Mitigation Bypass (MS15-111), PoC"]], 1369 | 1370 | ['MS15-102', ALERT.EXP, [ # CVE 2015-2524, CVE 2015-2525, CVE 2015-2528 1371 | "https://www.exploit-db.com/exploits/38202/ -- Windows CreateObjectTask SettingsSyncDiagnostics Privilege Escalation, PoC", 1372 | "https://www.exploit-db.com/exploits/38200/ -- Windows Task Scheduler DeleteExpiredTaskAfter File Deletion Privilege Escalation, PoC", 1373 | "https://www.exploit-db.com/exploits/38201/ -- Windows CreateObjectTask TileUserBroker Privilege Escalation, PoC"]], 1374 | 1375 | ['MS15-100', ALERT.MSF, [ # CVE 2015-2509 1376 | "https://www.exploit-db.com/exploits/38195/ -- MS15-100 Microsoft Windows Media Center MCL Vulnerability, MSF", 1377 | "https://www.exploit-db.com/exploits/38151/ -- Windows Media Center - Command Execution (MS15-100), PoC"]], 1378 | 1379 | ['MS15-097', ALERT.EXP, [ # CVE 2015-2508, CVE 2015-2527 1380 | "https://www.exploit-db.com/exploits/38198/ -- Windows 10 Build 10130 - User Mode Font Driver Thread Permissions Privilege Escalation, PoC", 1381 | "https://www.exploit-db.com/exploits/38199/ -- Windows NtUserGetClipboardAccessToken Token Leak, PoC"]], 1382 | 1383 | ['MS15-078', ALERT.MSF, [ # CVE 2015-2426, CVE 2015-2433 1384 | "https://www.exploit-db.com/exploits/38222/ -- MS15-078 Microsoft Windows Font Driver Buffer Overflow"]], 1385 | 1386 | ['MS15-052', ALERT.EXP, [ # CVE 2015-1674 1387 | "https://www.exploit-db.com/exploits/37052/ -- Windows - CNG.SYS Kernel Security Feature Bypass PoC (MS15-052), PoC"]], 1388 | 1389 | ['MS15-051', ALERT.MSF, [ # CVE 2015-1701 1390 | "https://github.com/hfiref0x/CVE-2015-1701, Win32k Elevation of Privilege Vulnerability, PoC", 1391 | "https://www.exploit-db.com/exploits/37367/ -- Windows ClientCopyImage Win32k Exploit, MSF"]], 1392 | 1393 | ['MS15-022', ALERT.EXP, [ # CVE 2015-0097 1394 | "https://www.exploit-db.com/exploits/37657/ -- Microsoft Word Local Machine Zone Remote Code Execution Vulnerability, PoC", 1395 | "https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/37657.zip"]], 1396 | 1397 | ['MS15-010', ALERT.EXP, [ # CVE 2015-0057 1398 | "https://www.exploit-db.com/exploits/39035/ -- Microsoft Windows 8.1 - win32k Local Privilege Escalation (MS15-010), PoC", 1399 | "https://www.exploit-db.com/exploits/37098/ -- Microsoft Windows - Local Privilege Escalation (MS15-010), PoC", 1400 | "https://www.exploit-db.com/exploits/39035/ -- Microsoft Windows win32k Local Privilege Escalation (MS15-010), PoC"]], 1401 | 1402 | ['MS15-001', ALERT.EXP, [ # CVE 2015-0002 1403 | "http://www.exploit-db.com/exploits/35661/ -- Windows 8.1 (32/64 bit) - Privilege Escalation (ahcache.sys/NtApphelpCacheControl), PoC"]], 1404 | 1405 | ['MS14-070', ALERT.EXP, [ # CVE 2014 4076 1406 | "http://www.exploit-db.com/exploits/35936/ -- Microsoft Windows Server 2003 SP2 - Privilege Escalation, PoC"]], 1407 | 1408 | ['MS14-068', ALERT.EXP, [ # CVE 2014-6324 1409 | "http://www.exploit-db.com/exploits/35474/ -- Windows Kerberos - Elevation of Privilege (MS14-068), PoC"]], 1410 | 1411 | ['MS14-064', ALERT.MSF, [ # CVE 2014-6332 1412 | "https://www.exploit-db.com/exploits/37800// -- Microsoft Windows HTA (HTML Application) - Remote Code Execution (MS14-064), PoC", 1413 | "http://www.exploit-db.com/exploits/35308/ -- Internet Explorer OLE Pre-IE11 - Automation Array Remote Code Execution / Powershell VirtualAlloc (MS14-064), PoC", 1414 | "http://www.exploit-db.com/exploits/35229/ -- Internet Explorer <= 11 - OLE Automation Array Remote Code Execution (#1), PoC", 1415 | "http://www.exploit-db.com/exploits/35230/ -- Internet Explorer < 11 - OLE Automation Array Remote Code Execution (MSF), MSF", 1416 | "http://www.exploit-db.com/exploits/35235/ -- MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python, MSF", 1417 | "http://www.exploit-db.com/exploits/35236/ -- MS14-064 Microsoft Windows OLE Package Manager Code Execution, MSF"]], 1418 | 1419 | ['MS14-062', ALERT.MSF, [ # CVE 2014-4971 1420 | "http://www.exploit-db.com/exploits/34112/ -- Microsoft Windows XP SP3 MQAC.sys - Arbitrary Write Privilege Escalation, PoC", 1421 | "http://www.exploit-db.com/exploits/34982/ -- Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation"]], 1422 | 1423 | ['MS14-060', ALERT.MSF, [ # CVE 2014-4114 1424 | "http://www.exploit-db.com/exploits/35055/ -- Windows OLE - Remote Code Execution 'Sandworm' Exploit (MS14-060), PoC", 1425 | "http://www.exploit-db.com/exploits/35020/ -- MS14-060 Microsoft Windows OLE Package Manager Code Execution, MSF"]], 1426 | 1427 | ['MS14-058', ALERT.MSF, [ # CVE 2014-4113 1428 | "http://www.exploit-db.com/exploits/35101/ -- Windows TrackPopupMenu Win32k NULL Pointer Dereference, MSF"]], 1429 | 1430 | ['MS14-040', ALERT.EXP, [ # CVE 2014-1767 1431 | "https://www.exploit-db.com/exploits/39525/ -- Microsoft Windows 7 x64 - afd.sys Privilege Escalation (MS14-040), PoC", 1432 | "https://www.exploit-db.com/exploits/39446/ -- Microsoft Windows - afd.sys Dangling Pointer Privilege Escalation (MS14-040), PoC"]], 1433 | 1434 | ['MS14-035', ALERT.EXP], 1435 | ['MS14-029', ALERT.EXP, [ 1436 | "http://www.exploit-db.com/exploits/34458/"]], 1437 | 1438 | ['MS14-026', ALERT.EXP, [ # CVE 2014-1806 1439 | "http://www.exploit-db.com/exploits/35280/, -- .NET Remoting Services Remote Command Execution, PoC"]], 1440 | 1441 | ['MS14-017', ALERT.MSF], 1442 | ['MS14-012', ALERT.MSF], 1443 | ['MS14-009', ALERT.MSF], 1444 | ['MS14-002', ALERT.EXP], 1445 | ['MS13-101', ALERT.EXP], 1446 | ['MS13-097', ALERT.MSF], 1447 | ['MS13-096', ALERT.MSF], 1448 | ['MS13-090', ALERT.MSF], 1449 | ['MS13-080', ALERT.MSF], 1450 | ['MS13-071', ALERT.MSF], 1451 | ['MS13-069', ALERT.MSF], 1452 | ['MS13-067', ALERT.EXP], 1453 | ['MS13-059', ALERT.MSF], 1454 | ['MS13-055', ALERT.MSF], 1455 | ['MS13-053', ALERT.MSF], 1456 | ['MS13-009', ALERT.MSF], 1457 | ['MS13-005', ALERT.MSF], 1458 | ['MS12-037', ALERT.EXP, [ # CVE 2012-1876 1459 | "http://www.exploit-db.com/exploits/35273/ -- Internet Explorer 8 - Fixed Col Span ID Full ASLR, DEP & EMET 5., PoC", 1460 | "http://www.exploit-db.com/exploits/34815/ -- Internet Explorer 8 - Fixed Col Span ID Full ASLR, DEP & EMET 5.0 Bypass (MS12-037), PoC"]], 1461 | 1462 | ['MS12-022', ALERT.MSF], 1463 | ['MS11-080', ALERT.MSF], 1464 | ['MS11-011', ALERT.EXP], 1465 | ['MS10-073', ALERT.MSF], 1466 | ['MS10-061', ALERT.MSF], 1467 | ['MS10-059', ALERT.EXP], 1468 | ['MS10-047', ALERT.EXP], 1469 | ['MS10-015', ALERT.MSF], 1470 | ['MS10-002', ALERT.MSF], 1471 | ['MS09-072', ALERT.MSF], 1472 | ['MS09-067', ALERT.MSF], 1473 | ['MS09-065', ALERT.MSF], 1474 | ['MS09-053', ALERT.MSF], 1475 | ['MS09-050', ALERT.MSF, [ 1476 | "https://www.rapid7.com/db/modules/exploit/windows/smb/ms09_050_smb2_negotiate_func_index -- MS09-050 Microsoft SRV2.SYS SMB Negotiate ProcessID Function Table Dereference"]], 1477 | 1478 | ['MS09-050', ALERT.MSF], 1479 | ['MS09-043', ALERT.MSF], 1480 | ['MS09-020', ALERT.MSF], 1481 | ['MS09-004', ALERT.MSF], 1482 | ['MS09-002', ALERT.MSF], 1483 | ['MS09-001', ALERT.MSF], 1484 | ['MS08-078', ALERT.MSF], 1485 | ['MS08-070', ALERT.MSF], 1486 | ['MS08-067', ALERT.MSF], 1487 | ['MS08-067', ALERT.MSF], 1488 | ['MS08-053', ALERT.MSF], 1489 | ['MS08-041', ALERT.MSF], 1490 | ['MS08-025', ALERT.EXP], 1491 | ['MS07-065', ALERT.MSF], 1492 | ['MS07-065', ALERT.MSF], 1493 | ['MS07-064', ALERT.MSF], 1494 | ['MS07-029', ALERT.MSF], 1495 | ['MS07-029', ALERT.MSF], 1496 | ['MS07-017', ALERT.MSF], 1497 | ['MS06-071', ALERT.MSF], 1498 | ['MS06-070', ALERT.MSF], 1499 | ['MS06-070', ALERT.MSF], 1500 | ['MS06-067', ALERT.MSF], 1501 | ['MS06-066', ALERT.MSF], 1502 | ['MS06-066', ALERT.MSF], 1503 | ['MS06-063', ALERT.MSF], 1504 | ['MS06-057', ALERT.MSF], 1505 | ['MS06-055', ALERT.MSF], 1506 | ['MS06-049', ALERT.EXP], 1507 | ['MS06-040', ALERT.MSF], 1508 | ['MS06-040', ALERT.MSF], 1509 | ['MS06-035', ALERT.MSF], 1510 | ['MS06-025', ALERT.MSF], 1511 | ['MS06-025', ALERT.MSF], 1512 | ['MS06-019', ALERT.MSF], 1513 | ['MS06-013', ALERT.MSF], 1514 | ['MS06-001', ALERT.MSF], 1515 | ['MS05-054', ALERT.MSF], 1516 | ['MS05-047', ALERT.MSF], 1517 | ['MS05-039', ALERT.MSF], 1518 | ['MS05-039', ALERT.MSF], 1519 | ['MS05-030', ALERT.MSF], 1520 | ['MS05-017', ALERT.MSF], 1521 | ['MS05-017', ALERT.MSF], 1522 | ['MS04-045', ALERT.MSF], 1523 | ['MS04-031', ALERT.MSF], 1524 | ['MS04-031', ALERT.MSF], 1525 | ['MS04-011', ALERT.MSF], 1526 | ['MS04-011', ALERT.MSF], 1527 | ['MS04-007', ALERT.MSF], 1528 | ['MS04-007', ALERT.MSF], 1529 | ['MS03-051', ALERT.MSF], 1530 | ['MS03-049', ALERT.MSF], 1531 | ['MS03-049', ALERT.MSF], 1532 | ['MS03-046', ALERT.MSF], 1533 | ['MS03-026', ALERT.MSF], 1534 | ['MS03-026', ALERT.MSF], 1535 | ['MS03-022', ALERT.MSF], 1536 | ['MS03-020', ALERT.MSF], 1537 | ['MS03-007', ALERT.MSF], 1538 | ['MS02-065', ALERT.MSF], 1539 | ['MS02-063', ALERT.MSF], 1540 | ['MS02-056', ALERT.MSF], 1541 | ['MS02-039', ALERT.MSF], 1542 | ['MS02-018', ALERT.MSF], 1543 | ['MS01-033', ALERT.MSF], 1544 | ['MS01-026', ALERT.MSF], 1545 | ['MS01-023', ALERT.MSF], 1546 | ['MS00-094', ALERT.MSF] 1547 | ] 1548 | 1549 | # return the count of exploits 1550 | if msid == 0: return len(exploits) 1551 | 1552 | for exploit in exploits: 1553 | if msid == exploit[0]: 1554 | # need 3 values to unpack, in case there are resources 1555 | if len(exploit) == 2: 1556 | exploit.append(None) 1557 | return exploit 1558 | 1559 | # otherwise there are 3 values 1560 | return exploit 1561 | 1562 | return [False,False,False] 1563 | 1564 | # the update function 1565 | def update(): 1566 | 1567 | # compute the filenames to be used 1568 | filenames = '%s-mssb' % datetime.datetime.now().strftime('%Y-%m-%d') 1569 | xlsFile = '%s.%s' % (filenames, 'xlsx') #MS now puts out XLSX files, not XLS 1570 | csvFile = '%s.%s' % (filenames, 'csv') 1571 | 1572 | # url request opener with user-agent 1573 | opener = urllib.request.build_opener() 1574 | opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36')] 1575 | 1576 | # grab the new data from ms and scrape the site 1577 | #try: 1578 | # response = opener.open(MSSB_URL) 1579 | #except urllib2.URLError, e: 1580 | # ALERT("error getting url %s" % MSSB_URL, ALERT.BAD) 1581 | # exit(1) 1582 | # 1583 | #ALERT("successfully requested base url") 1584 | 1585 | # 2016-02-10, ms changed link to http://download.microsoft.com/download/6/7/3/673E4349-1CA5-40B9-8879-095C72D5B49D/BulletinSearch.xlsx 1586 | # 1587 | # now parse the data, ensure we have an mssb link 1588 | # BulletinSearch_20131111_151603.xlsx (recommended) 1589 | #html = response.read() 1590 | #m = re.findall('url=(.*BulletinSearch.*.xls[x]*)', html) 1591 | # m = re.findall('href="(.*BulletinSearch.*.xlsx)"', html) # old bulletin request url, 20140502 1592 | 1593 | # ensure we get the bulletin search 1594 | #if m and m[0]: 1595 | bulletinUrl = BULLETIN_URL 1596 | # ALERT("scraped ms download url") 1597 | # if the file was xlsx, add an x to the extension 1598 | # if "xlsx" in bulletinUrl: xlsFile += "x" 1599 | #else: 1600 | # ALERT("error finding the ms download url from previous response", ALERT.BAD) 1601 | # exit(1) 1602 | 1603 | # now download the mssb file, with a random sleep 1604 | try: 1605 | #sleep(randint(1,3)) 1606 | response = opener.open(bulletinUrl) 1607 | except urllib.error.URLError as e: 1608 | ALERT("error getting ms sb url %s" % bulletinUrl, ALERT.BAD) 1609 | exit(1) 1610 | 1611 | bulletinData = response.read() 1612 | 1613 | ALERT("writing to file %s" % xlsFile, ALERT.GOOD) 1614 | f = open(xlsFile, 'wb') 1615 | f.write(bulletinData) 1616 | f.close 1617 | 1618 | # modified ALERT class for exploit and metasploit level logging 1619 | class ALERT(object): 1620 | 1621 | def __init__(self, message, level=0, ansi=True): 1622 | 1623 | # default to ansi alerting, if it's detected as windows platform then disable 1624 | if platform.system() == "Windows": ansi = False 1625 | 1626 | good = '[+]' 1627 | bad = '[-]' 1628 | normal = '[*]' 1629 | 1630 | msf = '[M]' 1631 | exploit = '[E]' 1632 | 1633 | if ansi == True: 1634 | if level == ALERT.GOOD: print("%s%s%s" % ('\033[1;32m',good,"\033[0;0m")), 1635 | elif level == ALERT.BAD: print("%s%s%s" % ('\033[1;31m',bad,"\033[0;0m")), 1636 | elif level == ALERT.MSF: print("%s%s%s" % ('\033[1;32m',msf,"\033[0;0m")), 1637 | elif level == ALERT.EXP: print("%s%s%s" % ('\033[1;32m',exploit,"\033[0;0m")), 1638 | else: print("%s%s%s" % ('\033[1;34m',normal,"\033[0;0m")), 1639 | 1640 | else: 1641 | if level == ALERT.GOOD: print('%s' % good), 1642 | elif level == ALERT.BAD: print('%s' % bad), 1643 | elif level == ALERT.MSF: print('%s' % msf), 1644 | elif level == ALERT.EXP: print('%s' % exploit), 1645 | else: print('%s' % normal), 1646 | 1647 | print(message) 1648 | 1649 | @staticmethod 1650 | @property 1651 | def BAD(self): return -1 1652 | 1653 | @staticmethod 1654 | @property 1655 | def NORMAL(self): return 0 1656 | 1657 | @staticmethod 1658 | @property 1659 | def GOOD(self): return 1 1660 | 1661 | @staticmethod 1662 | @property 1663 | def MSF(self): return 2 1664 | 1665 | @staticmethod 1666 | @property 1667 | def EXP(self): return 3 1668 | 1669 | # this helper function will merge a list of lists into one sorted set 1670 | def merge_list(li): 1671 | s = [] 1672 | if li: 1673 | for l in li: 1674 | if isinstance(l, list): s = s + l 1675 | else: s.append(l) 1676 | return s 1677 | 1678 | if __name__ == '__main__': 1679 | main() 1680 | 1681 | --------------------------------------------------------------------------------