diff --git a/samples/wincli.py b/samples/wincli.py index 361aa0a..0734193 100644 --- a/samples/wincli.py +++ b/samples/wincli.py @@ -1,5 +1,7 @@ import argparse import os.path +import code + import windows import windows.generated_def as gdef @@ -27,7 +29,7 @@ def find_one_process_from_kwargs(pid=None, name=None, **kwargs): print("Multiple process with name {0}, please choose:".format(name)) for i, proc in enumerate(targets): print(" {0}) {1}".format(i, proc)) - choice = raw_input("Number > ") + choice = int(raw_input("Number > "), 0) try: return targets[choice] except IndexError: @@ -135,6 +137,18 @@ def proc_command_addr(**kwargs): if res[1] != "NOTFOUND": print(" * {0}!{1}+{2:#x}".format(mod.name, res[1], dist)) +def proc_find_modules(**kwargs): + targets = find_processes_from_kwargs(**kwargs) + for target in targets: + mod_name = kwargs["modname"] + try: + mods = [m.name for m in target.peb.modules if mod_name.lower() in m.name.lower()] + if mods: + print(target) + print(mods) + except Exception as e: + print(e) + # Services def find_services_from_kwargs(name=None, **kwargs): @@ -164,12 +178,20 @@ def serv_command_list(**kwargs): for serv in find_services_from_kwargs(**kwargs): print (serv) +def serv_command_get(**kwargs): + print("Listing services") + servs = find_services_from_kwargs(**kwargs) + code.InteractiveConsole(locals()).interact() + def serv_command_start(**kwargs): serv = find_one_service_from_kwargs(**kwargs) serv.start() serv = find_one_service_from_kwargs(**kwargs) print(serv) + + + parser = argparse.ArgumentParser(prog=__file__) subparsers = parser.add_subparsers(description='valid subcommands',) @@ -187,7 +209,7 @@ proc_list_parser_ = proc_subparsers.add_parser('list') proc_list_parser_.set_defaults(func=proc_command_list) proc_inject_parser = proc_subparsers.add_parser('shell') -proc_inject_parser.set_defaults(func=proc_command_shell) + proc_inject_parser = proc_subparsers.add_parser('kill') proc_inject_parser.set_defaults(func=proc_command_kill) @@ -199,6 +221,10 @@ proc_addr_parser = proc_subparsers.add_parser('addr') proc_addr_parser.set_defaults(func=proc_command_addr) proc_addr_parser.add_argument('addresses', type=lambda x: int(x, 0), nargs="+", help='The addresses to explore') +proc_findmod_parser = proc_subparsers.add_parser('findmod') +proc_findmod_parser.set_defaults(func=proc_find_modules) +proc_findmod_parser.add_argument('modname', help='The name of the module to find') + # Services commandes serv_parser = subparsers.add_parser('serv') serv_parser.set_defaults(func=proc_command_list) @@ -214,6 +240,10 @@ serv_list_parser_.set_defaults(func=serv_command_list) serv_list_parser_ = serv_subparsers.add_parser('start') serv_list_parser_.set_defaults(func=serv_command_start) +serv_list_parser_ = serv_subparsers.add_parser('get') +serv_list_parser_.set_defaults(func=serv_command_get) + + if __name__ == "__main__": res = parser.parse_args() res.func(**res.__dict__) \ No newline at end of file diff --git a/windows/hooks.py b/windows/hooks.py index 80cf523..a3e5df3 100644 --- a/windows/hooks.py +++ b/windows/hooks.py @@ -104,10 +104,8 @@ class IATHook(object): ## New simple hook API based on winproxy - def setup_hook(target, hook, dll_to_hook): "TODO: Test and doc :D" - dll_to_hook = "python27.dll" dll_name, api_name = windows.winproxy.get_target(target) prototype = target.prototype hook._types_info = (prototype._restype_,) + prototype._argtypes_ diff --git a/windows/rpc/__init__.py b/windows/rpc/__init__.py index 8e832fc..369f7e1 100644 --- a/windows/rpc/__init__.py +++ b/windows/rpc/__init__.py @@ -1,5 +1,4 @@ import ndr -from client import (RPC_SYNTAX_IDENTIFIER, RPCClient, - REQUEST_TYPE_CALL, REQUEST_TYPE_BIND, - RESPONSE_TYPE_BIND_OK, RESPONSE_TYPE_FAIL, RESPONSE_TYPE_SUCESS) +from client import RPCClient, RPC_IF_ID + from epmapper import find_alpc_endpoint_and_connect, endpoint_map_alpc, construct_alpc_tower \ No newline at end of file diff --git a/windows/rpc/client.py b/windows/rpc/client.py index 892b163..f5c83df 100644 --- a/windows/rpc/client.py +++ b/windows/rpc/client.py @@ -1,77 +1,62 @@ -import windows.alpc2 as alpc -import windows.com -from windows.generated_def import USHORT, DWORD, CHAR import ctypes import struct +import windows.alpc as alpc +import windows.com +import windows.generated_def as gdef -class _RPC_SYNTAX_IDENTIFIER(ctypes.Structure): + +class _RPC_IF_ID(ctypes.Structure): _fields_ = [ - ("SyntaxGUID", windows.com.IID), - ("MajorVersion", USHORT), - ("MinorVersion", USHORT), + ("Uuid", gdef.IID), + ("MajorVersion", gdef.USHORT), + ("MinorVersion", gdef.USHORT), ] def __repr__(self): - return ''.format(self.SyntaxGUID.to_string(), self.MajorVersion, self.MinorVersion) -RPC_SYNTAX_IDENTIFIER = _RPC_SYNTAX_IDENTIFIER + return ''.format(self.Uuid.to_string(), self.MajorVersion, self.MinorVersion) -# DEFINES - -REQUEST_TYPE_CALL = 0 -REQUEST_TYPE_BIND = 1 - -KNOW_REQUEST_TYPE = { - REQUEST_TYPE_CALL : "REQUEST_CALL", - REQUEST_TYPE_BIND : "REQUEST_BIND", - } +RPC_IF_ID = _RPC_IF_ID -RESPONSE_TYPE_BIND_OK = 1 -RESPONSE_TYPE_FAIL = 2 -RESPONSE_TYPE_SUCESS = 3 +KNOW_REQUEST_TYPE = {x:x for x in [gdef.RPC_REQUEST_TYPE_CALL, gdef.RPC_REQUEST_TYPE_BIND]} -KNOW_RESPONSE_TYPE = { - RESPONSE_TYPE_FAIL : "RESPONSE_FAIL", - RESPONSE_TYPE_SUCESS : "RESPONSE_SUCESS", - RESPONSE_TYPE_BIND_OK: "RESPONSE_BIND_OK", - } +KNOW_RESPONSE_TYPE = {x:x for x in [gdef.RPC_RESPONSE_TYPE_FAIL, gdef.RPC_RESPONSE_TYPE_SUCESS, gdef.RPC_RESPONSE_TYPE_SUCESS]} -KNOWN_RPC_ERROR_CODE = { - 1783 : "RPC_X_BAD_STUB_DATA", - 1717 : "RPC_S_UNKNOWN_IF", - 1728 : "RPC_S_PROTOCOL_ERROR", - 1730 : "RPC_S_UNSUPPORTED_TRANS_SYN", - 1745 : "RPC_S_PROCNUM_OUT_OF_RANGE", -} +KNOWN_RPC_ERROR_CODE = {x:x for x in [ + gdef.ERROR_INVALID_HANDLE, + gdef.RPC_X_BAD_STUB_DATA, + gdef.RPC_S_UNKNOWN_IF, + gdef.RPC_S_PROTOCOL_ERROR, + gdef.RPC_S_UNSUPPORTED_TRANS_SYN, + gdef.RPC_S_PROCNUM_OUT_OF_RANGE, + ]} -BIND_IF_SYNTAX_NDR32 = 1 -BIND_IF_SYNTAX_NDR64 = 2 -BIND_IF_SYNTAX_UNKNOWN = 4 NOT_USED = 0xBAADF00D + class ALPC_RPC_BIND(ctypes.Structure): _pack_ = 1 _fields_ = [ - ("request_type", DWORD), - ("UNK1", DWORD), - ("UNK2", DWORD), - ("target", RPC_SYNTAX_IDENTIFIER), - ("flags", DWORD), - ("if_nb_ndr32", USHORT), - ("if_nb_ndr64", USHORT), - ("if_nb_unkn", USHORT), - ("PAD", USHORT), - ("register_multiple_syntax", DWORD), - ("use_flow", DWORD), - ("UNK5", DWORD), - ("maybe_flow_id", DWORD), - ("UNK7", DWORD), - ("some_context_id", DWORD), - ("UNK9", DWORD), + ("request_type", gdef.DWORD), + ("UNK1", gdef.DWORD), + ("UNK2", gdef.DWORD), + ("target", RPC_IF_ID), + ("flags", gdef.DWORD), + ("if_nb_ndr32", gdef.USHORT), + ("if_nb_ndr64", gdef.USHORT), + ("if_nb_unkn", gdef.USHORT), + ("PAD", gdef.USHORT), + ("register_multiple_syntax", gdef.DWORD), + ("use_flow", gdef.DWORD), + ("UNK5", gdef.DWORD), + ("maybe_flow_id", gdef.DWORD), + ("UNK7", gdef.DWORD), + ("some_context_id", gdef.DWORD), + ("UNK9", gdef.DWORD), ] @@ -88,7 +73,7 @@ class RPCClient(object): response = self._send_request(request) # Parse reponse request_type = self._get_request_type(response) - if request_type != RESPONSE_TYPE_BIND_OK: + if request_type != gdef.RPC_RESPONSE_TYPE_BIND_OK: raise ValueError("Unexpected reponse type. Expected RESPONSE_TYPE_BIND_OK got {0}".format(KNOW_RESPONSE_TYPE.get(request_type, request_type))) iid_hash = hash(buffer(IID)[:]) # TODO: add __hash__ to IID self.if_bind_number[iid_hash] = self.number_of_bind_if @@ -103,7 +88,7 @@ class RPCClient(object): response = self._send_request(request) # Parse reponse request_type = self._get_request_type(response) - if request_type != RESPONSE_TYPE_SUCESS: + if request_type != gdef.RPC_RESPONSE_TYPE_SUCESS: raise ValueError("Unexpected reponse type. Expected RESPONSE_SUCESS got {0}".format(KNOW_RESPONSE_TYPE.get(request_type, request_type))) data = struct.unpack("<6I", response[:6 * 4]) @@ -117,18 +102,16 @@ class RPCClient(object): def _forge_call_request(self, interface_nb, method_offset, params): # TODO: differents REQUEST_IDENTIFIER for each req ? # TODO: what is this '0' ? (1 is also accepted) (flags ?) - request = struct.pack("<16I", REQUEST_TYPE_CALL, NOT_USED, 1, self.REQUEST_IDENTIFIER, interface_nb, method_offset, *[NOT_USED] * 10) + request = struct.pack("<16I", gdef.RPC_REQUEST_TYPE_CALL, NOT_USED, 1, self.REQUEST_IDENTIFIER, interface_nb, method_offset, *[NOT_USED] * 10) request += params return request def _forge_bind_request(self, uuid, syntaxversion, requested_if_nb): - # if syntaxversion == (1, 0): - # requested_if_nb = 0x10000 version_major, version_minor = syntaxversion req = ALPC_RPC_BIND() - req.request_type = REQUEST_TYPE_BIND - req.target = RPC_SYNTAX_IDENTIFIER(uuid, *syntaxversion) - req.flags = BIND_IF_SYNTAX_NDR32 + req.request_type = gdef.RPC_REQUEST_TYPE_BIND + req.target = RPC_IF_ID(uuid, *syntaxversion) + req.flags = gdef.BIND_IF_SYNTAX_NDR32 req.if_nb_ndr32 = requested_if_nb req.if_nb_ndr64 = 0 req.if_nb_unkn = 0 @@ -139,15 +122,7 @@ class RPCClient(object): def _get_request_type(self, response): "raise if request_type == RESPONSE_TYPE_FAIL" request_type = struct.unpack("