mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Lot of small py3 compat fix
This commit is contained in:
+9
-6
@@ -5,6 +5,7 @@ from collections import namedtuple
|
||||
import windows
|
||||
from windows import winproxy
|
||||
from windows import generated_def as gdef
|
||||
import windows.pycompat
|
||||
|
||||
|
||||
## For 64b python
|
||||
@@ -21,7 +22,7 @@ class AlpcMessage(object):
|
||||
# PORT_MESSAGE + MessageAttribute
|
||||
def __init__(self, msg_or_size=0x1000, attributes=None):
|
||||
# Init the PORT_MESSAGE
|
||||
if isinstance(msg_or_size, (long, int)):
|
||||
if isinstance(msg_or_size, windows.pycompat.int_types):
|
||||
self.port_message_buffer_size = msg_or_size
|
||||
self.port_message_raw_buffer = ctypes.c_buffer(msg_or_size)
|
||||
self.port_message = AlpcMessagePort.from_buffer(self.port_message_raw_buffer)
|
||||
@@ -301,9 +302,11 @@ class AlpcTransportBase(object):
|
||||
:type receive_msg: AlpcMessage or None
|
||||
:param int flags: The flags for :func:`NtAlpcSendWaitReceivePort`
|
||||
"""
|
||||
if isinstance(alpc_message, basestring):
|
||||
if isinstance(alpc_message, windows.pycompat.anybuff):
|
||||
raw_alpc_message = alpc_message
|
||||
alpc_message = AlpcMessage(max(0x1000, len(alpc_message)))
|
||||
if len(alpc_message) > 0x1000:
|
||||
import pdb;pdb.set_trace()
|
||||
alpc_message = AlpcMessage(max(0x1000, len(alpc_message) + 0x200))
|
||||
alpc_message.port_message.data = raw_alpc_message
|
||||
|
||||
if receive_msg is None:
|
||||
@@ -319,7 +322,7 @@ class AlpcTransportBase(object):
|
||||
:type alpc_message: AlpcMessage or str
|
||||
:param int flags: The flags for :func:`NtAlpcSendWaitReceivePort`
|
||||
"""
|
||||
if isinstance(alpc_message, basestring):
|
||||
if isinstance(alpc_message, windows.pycompat.anybuff):
|
||||
raw_alpc_message = alpc_message
|
||||
alpc_message = AlpcMessage(max(0x1000, len(alpc_message)))
|
||||
alpc_message.port_message.data = raw_alpc_message
|
||||
@@ -346,7 +349,7 @@ class AlpcTransportBase(object):
|
||||
|
||||
class AlpcClient(AlpcTransportBase):
|
||||
"An ALPC client able to connect to a port and send/receive messages"
|
||||
DEFAULT_MAX_MESSAGE_LENGTH = 0x1000
|
||||
DEFAULT_MAX_MESSAGE_LENGTH = 0x9000
|
||||
|
||||
def __init__(self, port_name=None):
|
||||
"""Init the :class:`AlpcClient` automatically connect to ``port_name`` using default values if given"""
|
||||
@@ -396,7 +399,7 @@ class AlpcClient(AlpcTransportBase):
|
||||
send_msg = None
|
||||
send_msg_attr = None
|
||||
buffersize = None
|
||||
elif isinstance(connect_message, basestring):
|
||||
elif isinstance(connect_message, windows.pycompat.anybuff):
|
||||
buffersize = gdef.DWORD(len(connect_message) + 0x1000)
|
||||
send_msg = AlpcMessagePort.from_buffer_size(buffersize.value)
|
||||
send_msg.data = connect_message
|
||||
|
||||
+6
-3
@@ -1,3 +1,4 @@
|
||||
import sys
|
||||
import struct
|
||||
import ctypes
|
||||
import functools
|
||||
@@ -12,6 +13,8 @@ from windows.generated_def import RPC_C_IMP_LEVEL_IMPERSONATE, CLSCTX_INPROC_SER
|
||||
from windows.generated_def import interfaces
|
||||
from windows.generated_def.interfaces import generate_IID, IID
|
||||
|
||||
from windows.pycompat import int_types, basestring
|
||||
|
||||
# We have windows.com.COMImplementation
|
||||
# So we need windows.com.COMInterface
|
||||
COMInterface = interfaces.COMInterface
|
||||
@@ -109,11 +112,11 @@ def check_type_null(value):
|
||||
|
||||
def check_type_i4(value):
|
||||
# 31 ? as we may want to keep sign :)
|
||||
return isinstance(value, (int, long)) and (value).bit_length() <= 32
|
||||
return isinstance(value, int_types) and (value).bit_length() <= 32
|
||||
|
||||
def check_type_i8(value):
|
||||
# 63 ? as we may want to keep sign :)
|
||||
return isinstance(value, (int, long)) and (value).bit_length() <= 64
|
||||
return isinstance(value, int_types) and (value).bit_length() <= 64
|
||||
|
||||
def check_type_bstr(value):
|
||||
return isinstance(value, basestring)
|
||||
@@ -299,7 +302,7 @@ class COMImplementation(object):
|
||||
|
||||
def QueryInterface(self, this, piid, result):
|
||||
"""Default ``QueryInterface`` implementation that returns ``self`` if piid is the implemented interface"""
|
||||
if piid[0] in (IUnknown.IID, self.IMPLEMENT.IID):
|
||||
if piid[0] in (gdef.IUnknown.IID, self.IMPLEMENT.IID):
|
||||
result[0] = this
|
||||
return 1
|
||||
return E_NOINTERFACE
|
||||
|
||||
@@ -98,7 +98,7 @@ class CryptObject(object):
|
||||
return list(self._signers_and_certs_generator())
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0} "{1}" content_type={2}>'.format(type(self).__name__, self.filename, self.content_type)
|
||||
return '<{0} "{1}" content_type={2!r}>'.format(type(self).__name__, self.filename, self.content_type)
|
||||
|
||||
|
||||
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa382037(v=vs.85).aspx
|
||||
@@ -176,6 +176,9 @@ class CertificateStore(gdef.HCERTSTORE):
|
||||
return None
|
||||
return Certificate.from_pointer(rawcertcontext)
|
||||
|
||||
def __del__(self):
|
||||
return winproxy.CertCloseStore(self, 0)
|
||||
|
||||
|
||||
# PKCS12_NO_PERSIST_KEY -> do not save it in a key container on disk
|
||||
# Without it, a key container is created at 'C:\Users\USERNAME\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-3241049326-165485355-1070449050-1001'
|
||||
@@ -189,6 +192,7 @@ class CertificateStore(gdef.HCERTSTORE):
|
||||
# By forcing PKCS12_ALWAYS_CNG_KSP we remove this as the key are directly linked to the correct CNG_KSP in the CertStore
|
||||
# Look like it's based on this part of the PFX:
|
||||
# Microsoft CSP Name: Microsoft Enhanced Cryptographic Provider v1.0
|
||||
# BUT this will not allow to decrypt RSA_RC4 ?
|
||||
|
||||
def import_pfx(pfx, password=None, flags=gdef.CRYPT_USER_KEYSET | gdef.PKCS12_NO_PERSIST_KEY | gdef.PKCS12_ALWAYS_CNG_KSP):
|
||||
"""Import the file ``pfx`` with the ``password``.
|
||||
@@ -199,7 +203,7 @@ def import_pfx(pfx, password=None, flags=gdef.CRYPT_USER_KEYSET | gdef.PKCS12_NO
|
||||
|
||||
:return: :class:`CertificateStore`
|
||||
"""
|
||||
if isinstance(pfx, (basestring, bytearray)):
|
||||
if isinstance(pfx, windows.pycompat.anybuff) or isinstance(pfx, bytearray):
|
||||
pfx = gdef.CRYPT_DATA_BLOB.from_string(pfx)
|
||||
cert_store = winproxy.PFXImportCertStore(pfx, password, flags)
|
||||
return CertificateStore(cert_store)
|
||||
@@ -483,6 +487,8 @@ class Certificate(gdef.CERT_CONTEXT):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# class CertficateChain(object):
|
||||
# def __init__(self, pc_chain_context):
|
||||
# self.chain = pc_chain_context[0]
|
||||
|
||||
@@ -127,3 +127,6 @@ class CryptMessage(gdef.HCRYPTMSG):
|
||||
newmsg = CryptMessage(hmsg)
|
||||
newmsg.update(data, final=True)
|
||||
return newmsg
|
||||
|
||||
def __del__(self):
|
||||
return winproxy.CryptMsgClose(self)
|
||||
|
||||
@@ -48,7 +48,7 @@ def encrypt(cert_or_certlist, msg, algo=szOID_NIST_AES256_CBC, initvector=genini
|
||||
:return: :class:`bytearray`: The encrypted message
|
||||
"""
|
||||
alg_ident = CRYPT_ALGORITHM_IDENTIFIER()
|
||||
alg_ident.pszObjId = algo
|
||||
alg_ident.pszObjId = algo.encode("ascii")
|
||||
# We want to have automatique translation of Certificate -> PCERT_CONTEXT
|
||||
# In order to simple create the 'PCERT_CONTEXT[] certs'
|
||||
# For that we need a tuple of X * 1-item-tuple
|
||||
@@ -114,6 +114,6 @@ def decrypt(cert_store, encrypted):
|
||||
dcryptsize = DWORD()
|
||||
winproxy.CryptDecryptMessage(dparam, buf, ctypes.sizeof(buf), None, dcryptsize, None)
|
||||
#Decrypt the msg
|
||||
dcryptbuff = (BYTE * dcryptsize.value)()
|
||||
dcryptbuff = (BYTE * (dcryptsize.value + 0x1000))()
|
||||
winproxy.CryptDecryptMessage(dparam, buf, ctypes.sizeof(buf), dcryptbuff, dcryptsize, None)
|
||||
return str(bytearray(dcryptbuff[:dcryptsize.value]))
|
||||
return bytes(bytearray(dcryptbuff[:dcryptsize.value]))
|
||||
|
||||
@@ -208,6 +208,7 @@ def generate_python_exec_shellcode_32(target, PyDll):
|
||||
code += x86.Jnz(":DO_ENSURE")
|
||||
code += x86.Mov('EAX', Py_Initialize)
|
||||
code += x86.Call('EAX')
|
||||
# https://docs.python.org/3/c-api/init.html#c.PyEval_InitThreads
|
||||
code += x86.Mov('EAX', PyEval_InitThreads)
|
||||
code += x86.Call('EAX')
|
||||
code += x86.Label(":DO_ENSURE")
|
||||
@@ -272,6 +273,7 @@ def generate_python_exec_shellcode_64(target, PyDll):
|
||||
code += x64.Jnz(":DO_ENSURE")
|
||||
code += x64.Mov('RAX', Py_Initialize)
|
||||
code += x64.Call('RAX')
|
||||
# https://docs.python.org/3/c-api/init.html#c.PyEval_InitThreads
|
||||
code += x64.Mov('RAX', PyEval_InitThreads)
|
||||
code += x64.Call('RAX')
|
||||
code += x64.Label(":DO_ENSURE")
|
||||
@@ -398,7 +400,7 @@ import ctypes
|
||||
size = ctypes.c_uint.from_address(addr)
|
||||
size.value = len(txt)
|
||||
buff = (ctypes.c_char * len(txt)).from_address(addr + ctypes.sizeof(ctypes.c_uint))
|
||||
buff[:] = txt
|
||||
buff[:] = txt.encode()
|
||||
"""
|
||||
|
||||
def retrieve_last_exception_data(process):
|
||||
|
||||
+12
-5
@@ -1,17 +1,24 @@
|
||||
import windows
|
||||
from windows import winproxy
|
||||
import windows.generated_def as gdef
|
||||
|
||||
import _multiprocessing
|
||||
import ctypes
|
||||
|
||||
from windows.pycompat import is_py3
|
||||
|
||||
if is_py3:
|
||||
from multiprocessing.connection import PipeConnection as native_PipeConnection
|
||||
else:
|
||||
from _multiprocessing import PipeConnection as native_PipeConnection
|
||||
|
||||
# Inspired from 'multiprocessing\connection.py'
|
||||
|
||||
def full_pipe_address(addr):
|
||||
"""Return the full address of the pipe `addr`"""
|
||||
if addr.startswith("\\\\"):
|
||||
if not isinstance(addr, bytes):
|
||||
addr = addr.encode("ascii")
|
||||
if addr.startswith(b"\\\\"):
|
||||
return addr
|
||||
return r"\\.\pipe\{addr}".format(addr=addr)
|
||||
return br"\\.\pipe" + "\\".encode() + addr
|
||||
|
||||
class PipeConnection(object): # Cannot inherit: crash the interpreter
|
||||
"""A wrapper arround :class:`_multiprocessing.PipeConnection` able to work as a ContextManager"""
|
||||
@@ -26,7 +33,7 @@ class PipeConnection(object): # Cannot inherit: crash the interpreter
|
||||
@classmethod
|
||||
def from_handle(cls, phandle, *args, **kwargs):
|
||||
"""Create a :class:`PipeConnection` from pipe handle `phandle`"""
|
||||
connection = _multiprocessing.PipeConnection(phandle)
|
||||
connection = native_PipeConnection(phandle)
|
||||
return cls(connection, *args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -10,6 +10,16 @@ if is_py3:
|
||||
basestring = str
|
||||
anybuff = (str, bytes)
|
||||
|
||||
def raw_encode(s):
|
||||
if isinstance(s, str):
|
||||
return s.encode("latin1")
|
||||
return s
|
||||
|
||||
def raw_decode(s):
|
||||
if isinstance(s, bytes):
|
||||
return s.decode("latin1")
|
||||
return s
|
||||
|
||||
else: # py2.7
|
||||
def str_from_ascii_function(s):
|
||||
return s
|
||||
@@ -17,3 +27,12 @@ else: # py2.7
|
||||
int_types = (int, long)
|
||||
basestring = basestring
|
||||
anybuff = basestring
|
||||
|
||||
def raw_encode(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode("latin1")
|
||||
return s
|
||||
|
||||
def raw_decode(s):
|
||||
# No unicode for now on py2
|
||||
return s
|
||||
|
||||
@@ -7,6 +7,14 @@ import ctypes.wintypes
|
||||
import itertools
|
||||
from _ctypes import _SimpleCData
|
||||
|
||||
# No PFW deps in this file
|
||||
import sys
|
||||
is_py3 = (sys.version_info.major >= 3)
|
||||
if is_py3:
|
||||
int_types = int
|
||||
else:
|
||||
int_types = (int, long)
|
||||
|
||||
|
||||
# ## Utils ### #
|
||||
def is_pointer(x):
|
||||
@@ -168,7 +176,7 @@ def create_remote_array(subtype, len):
|
||||
|
||||
def __getitem__(self, slice):
|
||||
# import pdb;pdb.set_trace()
|
||||
if not isinstance(slice, (int, long)):
|
||||
if not isinstance(slice, int_types):
|
||||
raise NotImplementedError("RemoteArray slice __getitem__")
|
||||
if slice >= len:
|
||||
raise IndexError("Access to {0} for a RemoteArray of size {1}".format(slice, len))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import ndr
|
||||
from client import RPCClient
|
||||
|
||||
from epmapper import find_alpc_endpoint_and_connect, find_alpc_endpoints, construct_alpc_tower
|
||||
from . import ndr
|
||||
from .client import RPCClient
|
||||
from .epmapper import find_alpc_endpoint_and_connect, find_alpc_endpoints, construct_alpc_tower
|
||||
+44
-12
@@ -5,6 +5,9 @@ import windows.alpc as alpc
|
||||
import windows.com
|
||||
import windows.generated_def as gdef
|
||||
|
||||
if windows.pycompat.is_py3:
|
||||
buffer = bytes
|
||||
|
||||
|
||||
KNOW_REQUEST_TYPE = gdef.FlagMapper(gdef.RPC_REQUEST_TYPE_CALL, gdef.RPC_REQUEST_TYPE_BIND)
|
||||
KNOW_RESPONSE_TYPE = gdef.FlagMapper(gdef.RPC_RESPONSE_TYPE_FAIL, gdef.RPC_RESPONSE_TYPE_SUCCESS, gdef.RPC_RESPONSE_TYPE_BIND_OK)
|
||||
@@ -54,10 +57,7 @@ class ALPC_RPC_CALL(ctypes.Structure):
|
||||
("UNK5", gdef.DWORD),
|
||||
("UNK6", gdef.DWORD),
|
||||
("UNK7", gdef.DWORD),
|
||||
("UNK8", gdef.DWORD),
|
||||
("UNK9", gdef.DWORD),
|
||||
("UNK10", gdef.DWORD),
|
||||
("UNK11", gdef.DWORD),
|
||||
("ORPC_IPID", gdef.GUID)
|
||||
]
|
||||
|
||||
class RPCClient(object):
|
||||
@@ -86,7 +86,20 @@ class RPCClient(object):
|
||||
#TODO: attach version information to IID
|
||||
return IID
|
||||
|
||||
def call(self, IID, method_offset, params):
|
||||
def forge_alpc_request(self, IID, method_offset, params, ipid=None):
|
||||
"""Craft an ALPC message containing an RPC request to call ``method_offset`` of interface ``IID`
|
||||
with ``params``.
|
||||
Can be used to craft request without directly sending it
|
||||
"""
|
||||
iid_hash = hash(buffer(IID)[:])
|
||||
interface_nb = self.if_bind_number[iid_hash] # TODO: add __hash__ to IID
|
||||
if len(params) > 0x900: # 0x1000 - size of meta-data
|
||||
request = self._forge_call_request_in_view(interface_nb, method_offset, params, ipid=ipid)
|
||||
else:
|
||||
request = self._forge_call_request(interface_nb, method_offset, params, ipid=ipid)
|
||||
return request
|
||||
|
||||
def call(self, IID, method_offset, params, ipid=None):
|
||||
"""Call method number ``method_offset`` of interface ``IID`` with mashalled ``params``
|
||||
|
||||
:param IID IID: An IID previously returned by :func:`bind`
|
||||
@@ -94,15 +107,14 @@ class RPCClient(object):
|
||||
:param str params: The mashalled parameters (NDR32)
|
||||
:returns: :class:`str`
|
||||
"""
|
||||
iid_hash = hash(buffer(IID)[:])
|
||||
interface_nb = self.if_bind_number[iid_hash] # TODO: add __hash__ to IID
|
||||
request = self._forge_call_request(interface_nb, method_offset, params)
|
||||
request = self.forge_alpc_request(IID, method_offset, params, ipid=ipid)
|
||||
response = self._send_request(request)
|
||||
# Parse reponse
|
||||
request_type = self._get_request_type(response)
|
||||
if request_type != gdef.RPC_RESPONSE_TYPE_SUCCESS:
|
||||
raise ValueError("Unexpected reponse type. Expected RESPONSE_SUCCESS got {0}".format(KNOW_RESPONSE_TYPE[request_type]))
|
||||
|
||||
# windows.utils.sprint(ALPC_RPC_CALL.from_buffer_copy(response + "\x00" * 12))
|
||||
data = struct.unpack("<6I", response[:6 * 4])
|
||||
assert data[3] == self.REQUEST_IDENTIFIER
|
||||
return response[4 * 6:] # Should be the return value (not completly verified)
|
||||
@@ -111,7 +123,7 @@ class RPCClient(object):
|
||||
response = self.alpc_client.send_receive(request)
|
||||
return response.data
|
||||
|
||||
def _forge_call_request(self, interface_nb, method_offset, params):
|
||||
def _forge_call_request(self, interface_nb, method_offset, params, ipid=None):
|
||||
# TODO: differents REQUEST_IDENTIFIER for each req ?
|
||||
# TODO: what is this '0' ? (1 is also accepted) (flags ?)
|
||||
# request = struct.pack("<16I", gdef.RPC_REQUEST_TYPE_CALL, NOT_USED, 1, self.REQUEST_IDENTIFIER, interface_nb, method_offset, *[NOT_USED] * 10)
|
||||
@@ -121,19 +133,39 @@ class RPCClient(object):
|
||||
req.request_id = self.REQUEST_IDENTIFIER
|
||||
req.if_nb = interface_nb
|
||||
req.method_offset = method_offset
|
||||
|
||||
if ipid:
|
||||
req.ORPC_IPID = ipid
|
||||
this = gdef.ORPCTHIS()
|
||||
this.version = (5,7)
|
||||
this.flags = 1
|
||||
lthis = gdef.LOCALTHIS()
|
||||
return buffer(req)[:] + buffer(this)[:] + buffer(lthis)[:] + params
|
||||
return buffer(req)[:] + params
|
||||
|
||||
def _forge_call_request_in_view(self, interface_nb, method_offset, params, ipid=None):
|
||||
# import pdb;pdb.set_trace()
|
||||
# Version crade qui clean rien pour POC. GROS DOUTES :D
|
||||
raw_request = self._forge_call_request(interface_nb, method_offset, "")
|
||||
p = windows.alpc.AlpcMessage(0x2000)
|
||||
section = self.alpc_client.create_port_section(0x40000, 0, len(params))
|
||||
view = self.alpc_client.map_section(section[0], len(params))
|
||||
p.port_message.data = raw_request + windows.rpc.ndr.NdrLong.pack(len(params) + 0x200) + "\x00" * 40
|
||||
p.attributes.ValidAttributes |= gdef.ALPC_MESSAGE_VIEW_ATTRIBUTE
|
||||
p.view_attribute.Flags = 0x40000
|
||||
p.view_attribute.ViewBase = view.ViewBase
|
||||
p.view_attribute.SectionHandle = view.SectionHandle
|
||||
p.view_attribute.ViewSize = len(params)
|
||||
windows.current_process.write_memory(view.ViewBase, params) # Write NDR to view
|
||||
return p
|
||||
|
||||
def _forge_bind_request(self, uuid, syntaxversion, requested_if_nb):
|
||||
version_major, version_minor = syntaxversion
|
||||
req = ALPC_RPC_BIND()
|
||||
req.request_type = gdef.RPC_REQUEST_TYPE_BIND
|
||||
req.target = gdef.RPC_IF_ID(uuid, *syntaxversion)
|
||||
req.flags = gdef.BIND_IF_SYNTAX_NDR32
|
||||
# req.flags = gdef.BIND_IF_SYNTAX_NDR64
|
||||
req.if_nb_ndr32 = requested_if_nb
|
||||
req.if_nb_ndr64 = 0
|
||||
req.if_nb_ndr64 = requested_if_nb
|
||||
req.if_nb_unkn = 0
|
||||
req.register_multiple_syntax = False
|
||||
req.some_context_id = 0xB00B00B
|
||||
|
||||
+11
-9
@@ -5,6 +5,7 @@ import windows
|
||||
import windows.generated_def as gdef
|
||||
from windows.rpc import ndr
|
||||
from windows.dbgprint import dbgprint
|
||||
from windows.pycompat import basestring
|
||||
|
||||
|
||||
|
||||
@@ -85,14 +86,15 @@ def explode_alpc_tower(tower):
|
||||
|
||||
lhs, rhs = parse_floor(stream)
|
||||
if not (rhs[-1] == 0):
|
||||
raise ValueError("ALPC Port name doest not end by \\x00")
|
||||
return UnpackTower("ncalrpc", rhs[:-1], None, object, syntax)
|
||||
rhs = rhs[:rhs.find("\x00")]
|
||||
# raise ValueError("ALPC Port name doest not end by \\x00")
|
||||
return UnpackTower("ncalrpc", bytes(rhs[:-1]), None, object, syntax)
|
||||
|
||||
# http://pubs.opengroup.org/onlinepubs/9629399/apdxi.htm#tagcjh_28
|
||||
# Octet 0 contains the hexadecimal value 0d. This is a reserved protocol identifier prefix that indicates that the protocol ID is UUID derived
|
||||
TOWER_PROTOCOL_IS_UUID = "\x0d"
|
||||
TOWER_EMPTY_RHS = "\x00\x00"
|
||||
TOWER_PROTOCOL_ID_ALPC = "\x0c" # From RE
|
||||
TOWER_PROTOCOL_IS_UUID = b"\x0d"
|
||||
TOWER_EMPTY_RHS = b"\x00\x00"
|
||||
TOWER_PROTOCOL_ID_ALPC = b"\x0c" # From RE
|
||||
|
||||
def construct_alpc_tower(object, syntax, protseq, endpoint, address):
|
||||
if address is not None:
|
||||
@@ -113,11 +115,11 @@ def construct_alpc_tower(object, syntax, protseq, endpoint, address):
|
||||
floor_2 = craft_floor(floor_2_lsh, floor_2_rsh)
|
||||
# Floor 3
|
||||
if endpoint is None:
|
||||
floor_3_lsh = "\xff"
|
||||
floor_3_lsh = b"\xff"
|
||||
floor_3_rsh = TOWER_EMPTY_RHS
|
||||
floor_3 = craft_floor(floor_3_lsh, floor_3_rsh)
|
||||
else:
|
||||
floor_3_lsh = "\x10"
|
||||
floor_3_lsh = b"\x10"
|
||||
floor_3_rsh = endpoint
|
||||
floor_3 = craft_floor(floor_3_lsh, floor_3_rsh)
|
||||
towerarray = struct.pack("<H", 4) + floor_0 + floor_1 + floor_2 + floor_3
|
||||
@@ -147,7 +149,7 @@ def find_alpc_endpoints(targetiid, version=(1,0), nb_response=1, sid=gdef.WinLoc
|
||||
syntax_iid = gdef.IID.from_string("8a885d04-1ceb-11c9-9fe8-08002b104860")
|
||||
rpc_syntax = gdef.RPC_IF_ID(syntax_iid, 2, 0)
|
||||
## Forge tower
|
||||
tower_array_size, towerarray = construct_alpc_tower(rpc_object, rpc_syntax, "ncalrpc", "", None)
|
||||
tower_array_size, towerarray = construct_alpc_tower(rpc_object, rpc_syntax, "ncalrpc", b"", None)
|
||||
|
||||
# parameters
|
||||
local_system_psid = windows.utils.get_known_sid(sid)
|
||||
@@ -183,7 +185,7 @@ def find_alpc_endpoint_and_connect(targetiid, version=(1,0), sid=gdef.WinLocalSy
|
||||
dbgprint("ALPC endpoints list: <{0}>".format(alpctowers), "RPC")
|
||||
for tower in alpctowers:
|
||||
dbgprint("Trying to connect to endpoint <{0}>".format(tower.endpoint), "RPC")
|
||||
alpc_port = r"\RPC Control\{0}".format(tower.endpoint)
|
||||
alpc_port = r"\RPC Control\{0}".format(tower.endpoint.decode())
|
||||
try:
|
||||
client = windows.rpc.RPCClient(alpc_port)
|
||||
except Exception as e:
|
||||
|
||||
+52
-11
@@ -24,7 +24,7 @@ def pack_dword(x):
|
||||
def dword_pad(s):
|
||||
if (len(s) % 4) == 0:
|
||||
return s
|
||||
return s + ("P" * (4 - len(s) % 4))
|
||||
return s + (b"P" * (4 - len(s) % 4))
|
||||
|
||||
|
||||
class NdrUniquePTR(object):
|
||||
@@ -55,7 +55,7 @@ class NdrUniquePTR(object):
|
||||
def unpack_in_struct(self, stream):
|
||||
ptr = NdrLong.unpack(stream)
|
||||
if not ptr:
|
||||
return 0, None
|
||||
return 0, NdrUnpackNone
|
||||
return ptr, self.subcls
|
||||
|
||||
def parse(self, stream):
|
||||
@@ -64,6 +64,22 @@ class NdrUniquePTR(object):
|
||||
return None
|
||||
return self.subcls.parse(stream)
|
||||
|
||||
class NdrUnpackNone(object):
|
||||
@classmethod
|
||||
def unpack(cls, stream):
|
||||
return None
|
||||
|
||||
class NdrRef(object):
|
||||
# TESTING
|
||||
def __init__(self, subcls):
|
||||
self.subcls = subcls
|
||||
|
||||
def unpack(self, stream):
|
||||
ptr = NdrLong.unpack(stream)
|
||||
if not ptr:
|
||||
raise ValueError("Ndr REF cannot be NULL")
|
||||
return self.subcls.unpack(stream)
|
||||
|
||||
class NdrFixedArray(object):
|
||||
def __init__(self, subcls, size):
|
||||
self.subcls = subcls
|
||||
@@ -72,7 +88,7 @@ class NdrFixedArray(object):
|
||||
def pack(self, data):
|
||||
data = list(data)
|
||||
assert len(data) == self.size
|
||||
return dword_pad("".join([self.subcls.pack(elt) for elt in data]))
|
||||
return dword_pad(b"".join([self.subcls.pack(elt) for elt in data]))
|
||||
|
||||
|
||||
def unpack(self, stream):
|
||||
@@ -119,7 +135,7 @@ class NdrWString(object):
|
||||
if not data.endswith('\x00'):
|
||||
data += '\x00'
|
||||
data = data.encode("utf-16-le")
|
||||
l = (len(data) / 2)
|
||||
l = (len(data) // 2)
|
||||
result = struct.pack("<3I", l, 0, l)
|
||||
result += data
|
||||
return dword_pad(result)
|
||||
@@ -249,7 +265,7 @@ class NdrStructure(object):
|
||||
else:
|
||||
packed_member = member.pack(memberdata)
|
||||
res.append(packed_member)
|
||||
return dword_pad("".join(conformant_size)) + dword_pad("".join(res)) + dword_pad("".join(pointed))
|
||||
return dword_pad(b"".join(conformant_size)) + dword_pad(b"".join(res)) + dword_pad(b"".join(pointed))
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, stream):
|
||||
@@ -257,7 +273,6 @@ class NdrStructure(object):
|
||||
conformant_members = [hasattr(m, "pack_conformant") for m in cls.MEMBERS]
|
||||
is_conformant = any(conformant_members)
|
||||
assert(conformant_members.count(True) <= 1), "Unpack conformant struct with more that one conformant MEMBER not implem"
|
||||
|
||||
data = []
|
||||
if is_conformant:
|
||||
conformant_size = NdrLong.unpack(stream)
|
||||
@@ -279,7 +294,11 @@ class NdrStructure(object):
|
||||
data.append(member.unpack(stream))
|
||||
# print("Applying deref unpack")
|
||||
for i, entry in post_subcls:
|
||||
data[i] = entry.unpack(stream)
|
||||
new_data = entry.unpack(stream)
|
||||
if getattr(entry, "post_unpack", None):
|
||||
new_data = entry.post_unpack(new_data)
|
||||
data[i] = new_data
|
||||
|
||||
return cls.post_unpack(data)
|
||||
|
||||
@classmethod
|
||||
@@ -305,7 +324,7 @@ class NdrParameters(object):
|
||||
for (member, memberdata) in zip(cls.MEMBERS, data):
|
||||
packed_member = member.pack(memberdata)
|
||||
res.append(packed_member)
|
||||
return "".join(dword_pad(elt) for elt in res)
|
||||
return b"".join(dword_pad(elt) for elt in res)
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, stream):
|
||||
@@ -321,14 +340,24 @@ class NdrConformantArray(object):
|
||||
@classmethod
|
||||
def pack(cls, data):
|
||||
ndrsize = NdrLong.pack(len(data))
|
||||
return dword_pad(ndrsize + "".join([cls.MEMBER_TYPE.pack(memberdata) for memberdata in data]))
|
||||
return dword_pad(ndrsize + b"".join([cls.MEMBER_TYPE.pack(memberdata) for memberdata in data]))
|
||||
|
||||
@classmethod
|
||||
def pack_conformant(cls, data):
|
||||
ndrsize = NdrLong.pack(len(data))
|
||||
ndrdata = dword_pad("".join([cls.MEMBER_TYPE.pack(memberdata) for memberdata in data]))
|
||||
ndrdata = dword_pad(b"".join([cls.MEMBER_TYPE.pack(memberdata) for memberdata in data]))
|
||||
return ndrsize, ndrdata
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, stream):
|
||||
nbelt = NdrLong.unpack(stream)
|
||||
result = cls.unpack_conformant(stream, nbelt)
|
||||
return cls._post_unpack(result)
|
||||
|
||||
@classmethod
|
||||
def _post_unpack(cls, result):
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def unpack_conformant(cls, stream, size):
|
||||
res = [cls.MEMBER_TYPE.unpack(stream) for i in range(size)]
|
||||
@@ -342,7 +371,7 @@ class NdrConformantVaryingArrays(object):
|
||||
def pack(cls, data):
|
||||
ndrsize = NdrLong.pack(len(data))
|
||||
offset = NdrLong.pack(0)
|
||||
return dword_pad(ndrsize + offset + ndrsize + "".join([cls.MEMBER_TYPE.pack(memberdata) for memberdata in data]))
|
||||
return dword_pad(ndrsize + offset + ndrsize + b"".join([cls.MEMBER_TYPE.pack(memberdata) for memberdata in data]))
|
||||
|
||||
@classmethod
|
||||
def unpack(cls, stream):
|
||||
@@ -385,6 +414,8 @@ class NdrWcharConformantVaryingArrays(NdrConformantVaryingArrays):
|
||||
def _post_unpack(self, result):
|
||||
return u"".join(unichr(c) for c in result)
|
||||
|
||||
class NdrCharConformantVaryingArrays(NdrConformantVaryingArrays):
|
||||
MEMBER_TYPE = NdrByte
|
||||
|
||||
class NdrHyperConformantVaryingArrays(NdrConformantVaryingArrays):
|
||||
MEMBER_TYPE = NdrHyper
|
||||
@@ -405,6 +436,13 @@ class NdrByteConformantArray(NdrConformantArray):
|
||||
def _post_unpack(self, result):
|
||||
return bytearray(result)
|
||||
|
||||
class NdrWcharConformantArray(NdrConformantArray):
|
||||
MEMBER_TYPE = NdrShort
|
||||
|
||||
@classmethod
|
||||
def _post_unpack(self, result):
|
||||
return bytearray(result)
|
||||
|
||||
class NdrGuidConformantArray(NdrConformantArray):
|
||||
MEMBER_TYPE = NdrGuid
|
||||
|
||||
@@ -438,12 +476,15 @@ class NdrStream(object):
|
||||
|
||||
def align(self, size):
|
||||
"""Discard some bytes to align the remaining stream on ``size``"""
|
||||
|
||||
already_read = len(self.fulldata) - len(self.data)
|
||||
if already_read % size:
|
||||
# Realign
|
||||
size_to_align = (size - (already_read % size))
|
||||
self.data = self.data[size_to_align:]
|
||||
# print("align {0}: {1}".format(size, size_to_align))
|
||||
return size_to_align
|
||||
# print("align {0}: 0".format(size))
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -8,18 +8,18 @@ DEFAULT_CREATION_FLAGS = gdef.CREATE_NEW_CONSOLE
|
||||
|
||||
if windows.system.bitness == 32:
|
||||
def pop_proc_32(dwCreationFlags=DEFAULT_CREATION_FLAGS):
|
||||
return create_process(r"C:\Windows\system32\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
return create_process(r"C:\Windows\system32\{0}".format(test_binary_name).encode(), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
|
||||
def pop_proc_64(dwCreationFlags=DEFAULT_CREATION_FLAGS):
|
||||
raise WindowsError("Cannot create calc64 in 32bits system")
|
||||
else:
|
||||
def pop_proc_32(dwCreationFlags=DEFAULT_CREATION_FLAGS):
|
||||
return create_process(r"C:\Windows\syswow64\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
return create_process(r"C:\Windows\syswow64\{0}".format(test_binary_name).encode(), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
|
||||
if windows.current_process.bitness == 32:
|
||||
def pop_proc_64(dwCreationFlags=DEFAULT_CREATION_FLAGS):
|
||||
with DisableWow64FsRedirection():
|
||||
return create_process(r"C:\Windows\system32\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
return create_process(r"C:\Windows\system32\{0}".format(test_binary_name).encode(), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
else:
|
||||
def pop_proc_64(dwCreationFlags=DEFAULT_CREATION_FLAGS):
|
||||
return create_process(r"C:\Windows\system32\{0}".format(test_binary_name), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
return create_process(r"C:\Windows\system32\{0}".format(test_binary_name).encode(), dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
@@ -80,13 +80,13 @@ class PartialBufferType(object):
|
||||
def from_buffer(self, buffer): # size as kwargs ?
|
||||
if len(buffer) % ctypes.sizeof(self.type):
|
||||
raise NotImplementedError("Buffer size of not a multiple of sizeof({0})".format(self.type.__name__))
|
||||
nbelt = len(buffer) / ctypes.sizeof(self.type)
|
||||
nbelt = int(len(buffer) / ctypes.sizeof(self.type))
|
||||
return self.create_real_implem(self.type, nbelt).from_buffer(buffer)
|
||||
|
||||
def from_buffer_copy(self, buffer): # size as kwargs ?
|
||||
if len(buffer) % ctypes.sizeof(self.type):
|
||||
raise NotImplementedError("Buffer size of not a multiple of sizeof({0})".format(self.type.__name__))
|
||||
nbelt = len(buffer) / ctypes.sizeof(self.type)
|
||||
nbelt = int(len(buffer) / ctypes.sizeof(self.type))
|
||||
return self.create_real_implem(self.type, nbelt).from_buffer_copy(buffer)
|
||||
|
||||
def create(self, nbelt):
|
||||
|
||||
+35
-20
@@ -51,7 +51,15 @@ def create_file_from_handle(handle, mode="r"):
|
||||
"""Return a Python :class:`file` around a ``Windows`` HANDLE"""
|
||||
flags = os.O_BINARY if "b" in mode else os.O_TEXT
|
||||
fd = msvcrt.open_osfhandle(handle, flags)
|
||||
return os.fdopen(fd, mode, 0)
|
||||
kwargs = {}
|
||||
if windows.pycompat.is_py3 and flags == os.O_TEXT:
|
||||
# Buffering, encoding
|
||||
args = (100, "ascii")
|
||||
else:
|
||||
# Buffering
|
||||
args = (0,)
|
||||
# In py2 os.fdopen do not accept kwargs
|
||||
return os.fdopen(fd, mode, *args)
|
||||
|
||||
|
||||
def get_handle_from_file(f):
|
||||
@@ -68,7 +76,7 @@ def create_console():
|
||||
sys.stdout = console_stdout
|
||||
|
||||
stdin_handle = winproxy.GetStdHandle(gdef.STD_INPUT_HANDLE)
|
||||
console_stdin = create_file_from_handle(stdin_handle, "r+")
|
||||
console_stdin = create_file_from_handle(stdin_handle, "r")
|
||||
sys.stdin = console_stdin
|
||||
|
||||
stderr_handle = winproxy.GetStdHandle(gdef.STD_ERROR_HANDLE)
|
||||
@@ -87,7 +95,7 @@ def create_process(path, args=None, dwCreationFlags=0, show_windows=True):
|
||||
lpStartupInfo = ctypes.byref(StartupInfo)
|
||||
lpCommandLine = None
|
||||
if args:
|
||||
lpCommandLine = (" ".join([str(a) for a in args]))
|
||||
lpCommandLine = (b" ".join([a for a in args]))
|
||||
windows.winproxy.CreateProcessA(path, lpCommandLine=lpCommandLine, dwCreationFlags=dwCreationFlags, lpProcessInformation=ctypes.byref(proc_info), lpStartupInfo=lpStartupInfo)
|
||||
dbgprint("CreateProcessA new process handle {:#x}".format(proc_info.hProcess), "HANDLE")
|
||||
dbgprint("CreateProcessA new thread handle {:#x}".format(proc_info.hThread), "HANDLE")
|
||||
@@ -213,13 +221,29 @@ WIN_TO_UNIX_EPOCH_WIN_TICKS = WIN_TO_UNIX_EPOCH_SECOND * WIN_TICK_PER_SECOND_INT
|
||||
|
||||
def unix_timestamp_from_filetime(filetime):
|
||||
# Round the filetime
|
||||
round_win_ticks = ((filetime / 10) + int(round((filetime % 10) / 10.0))) * 10
|
||||
last_number = (filetime % 10)
|
||||
# We do some sort of "manual rounding cause of py2 vs py3
|
||||
# PY2: round(0.5) == 1
|
||||
# PY3: round(0.5) == 0
|
||||
if last_number == 5:
|
||||
rounding = 1
|
||||
else:
|
||||
rounding = round(last_number / 10.0)
|
||||
round_win_ticks = ((filetime // 10) + int(rounding)) * 10
|
||||
return round((round_win_ticks - WIN_TO_UNIX_EPOCH_WIN_TICKS) / WIN_TICK_PER_SECOND_FLOAT, 7)
|
||||
|
||||
def datetime_from_filetime(filetime):
|
||||
"""return a :class:`datetime.datetime` from a ``windows`` FILETIME int"""
|
||||
# Manual non-approx rounding as filetime will not have a perfect representation as Python float
|
||||
round_microsecond = (filetime / 10) + int(round((filetime % 10) / 10.0))
|
||||
# We do some sort of "manual rounding cause of py2 vs py3
|
||||
# PY2: round(0.5) == 1
|
||||
# PY3: round(0.5) == 0
|
||||
last_number = (filetime % 10)
|
||||
if last_number == 5:
|
||||
rounding = 1
|
||||
else:
|
||||
rounding = round(last_number / 10.0)
|
||||
round_microsecond = (filetime // 10) + int(rounding)
|
||||
return WINDOWS_EPOCH + datetime.timedelta(microseconds=round_microsecond)
|
||||
|
||||
def filetime_from_datetime(dtime):
|
||||
@@ -303,7 +327,7 @@ ntqueryinformationfile_info_structs = {
|
||||
}
|
||||
|
||||
def query_file_information(file_or_handle, file_info_class):
|
||||
if isinstance(file_or_handle, file):
|
||||
if not isinstance(file_or_handle, windows.pycompat.int_types):
|
||||
file_or_handle = windows.utils.get_handle_from_file(file_or_handle)
|
||||
handle = file_or_handle
|
||||
io_status = gdef.IO_STATUS_BLOCK()
|
||||
@@ -313,7 +337,6 @@ def query_file_information(file_or_handle, file_info_class):
|
||||
try:
|
||||
windows.winproxy.NtQueryInformationFile(handle, io_status, pinfo, ctypes.sizeof(info), FileInformationClass=file_info_class)
|
||||
except Exception as e:
|
||||
# import pdb;pdb.set_trace()
|
||||
if not (e.winerror & 0xffffffff) == gdef.STATUS_BUFFER_OVERFLOW:
|
||||
raise
|
||||
# STATUS_BUFFER_OVERFLOW -> Guess we have a FILE_NAME_INFORMATION somewhere that need a bigger buffer
|
||||
@@ -407,7 +430,7 @@ ntqueryvolumeinformationfile_info_structs = {
|
||||
# TODO: FileFsDriverPathInformation
|
||||
# TODO: Extended FILE_FS_VOLUME_INFORMATION that can read the real value of 'VolumeLabel'
|
||||
def query_volume_information(file_or_handle, volume_info_class):
|
||||
if isinstance(file_or_handle, file):
|
||||
if not isinstance(file_or_handle, windows.pycompat.int_types):
|
||||
file_or_handle = get_handle_from_file(file_or_handle)
|
||||
handle = file_or_handle
|
||||
io_status = gdef.IO_STATUS_BLOCK()
|
||||
@@ -460,12 +483,8 @@ def get_long_path(path):
|
||||
:returns: :class:`str` | :obj:`unicode` -- same type as ``path`` parameter
|
||||
"""
|
||||
size = 0x1000
|
||||
if isinstance(path, unicode):
|
||||
buffer = ctypes.create_unicode_buffer(size)
|
||||
rsize = winproxy.GetLongPathNameW(path, buffer, size)
|
||||
else:
|
||||
buffer = ctypes.c_buffer(size)
|
||||
rsize = winproxy.GetLongPathNameA(path, buffer, size)
|
||||
buffer = ctypes.create_unicode_buffer(size)
|
||||
rsize = winproxy.GetLongPathNameW(path, buffer, size)
|
||||
return buffer[:rsize]
|
||||
|
||||
|
||||
@@ -478,12 +497,8 @@ def get_short_path(path):
|
||||
:returns: :class:`str` | :obj:`unicode` -- same type as ``path`` parameter
|
||||
"""
|
||||
size = 0x1000
|
||||
if isinstance(path, unicode):
|
||||
buffer = ctypes.create_unicode_buffer(size)
|
||||
rsize = winproxy.GetShortPathNameW(path, buffer, size)
|
||||
else:
|
||||
buffer = ctypes.c_buffer(size)
|
||||
rsize = winproxy.GetShortPathNameA(path, buffer, size)
|
||||
buffer = ctypes.create_unicode_buffer(size)
|
||||
rsize = winproxy.GetShortPathNameW(path, buffer, size)
|
||||
return buffer[:rsize]
|
||||
|
||||
def dospath_to_ntpath(dospath):
|
||||
|
||||
@@ -191,7 +191,7 @@ class BitsCopyJob(IBackgroundCopyJob):
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0} iid="{1}" at {2:#08x}>'.format(type(self).__name__, self.iid.to_string(), id(self))
|
||||
return '<{0} iid="{1}" at {2:#08x}>'.format(type(self).__name__, self.iid, id(self))
|
||||
|
||||
|
||||
class BitsCopyJob2(gdef.IBackgroundCopyJob2, BitsCopyJob):
|
||||
|
||||
@@ -18,7 +18,7 @@ def query_link(linkpath):
|
||||
obj_attr.SecurityQualityOfService = 0
|
||||
res = gdef.HANDLE()
|
||||
x = winproxy.NtOpenSymbolicLinkObject(res, gdef.DIRECTORY_QUERY | gdef.READ_CONTROL , obj_attr)
|
||||
v = gdef.LSA_UNICODE_STRING.from_string("\x00" * 1000)
|
||||
v = gdef.LSA_UNICODE_STRING.from_size(1000)
|
||||
s = gdef.ULONG()
|
||||
winproxy.NtQuerySymbolicLinkObject(res, v, s) # Handle Buffer-too-small ?
|
||||
return v.str
|
||||
|
||||
@@ -378,7 +378,7 @@ class Process(utils.AutoHandle):
|
||||
# handle read_wstring at end of page
|
||||
# Of read failed: read only the half of size
|
||||
# read_size must remain a multiple of 2
|
||||
read_size = read_size / 2
|
||||
read_size = int(read_size / 2)
|
||||
continue
|
||||
readden += read_size
|
||||
# Bytearray will work on py2 & py3
|
||||
|
||||
@@ -8,6 +8,7 @@ import windows
|
||||
from windows.dbgprint import dbgprint
|
||||
import windows.generated_def as gdef
|
||||
from windows import winproxy
|
||||
from windows.pycompat import basestring, int_types, is_py3
|
||||
|
||||
WENCODING = "utf-16-le"
|
||||
|
||||
@@ -61,9 +62,10 @@ def Py2Reg_DWORD_BIG_ENDIAN(obj):
|
||||
|
||||
|
||||
def Reg2Py_BINARY(buffer, size):
|
||||
return str(bytearray(buffer[:size]))
|
||||
return bytes(bytearray(buffer[:size]))
|
||||
|
||||
def Py2Reg_BINARY(obj):
|
||||
# latin-1 encoding if py3 & type is str ?
|
||||
return obj
|
||||
|
||||
|
||||
@@ -75,7 +77,8 @@ def Reg2Py_SZ(buffer, size):
|
||||
# NULL TERMINATED: EASY
|
||||
return buffer.as_wstring()
|
||||
# Not null terminated: keep last byte
|
||||
return (gdef.WCHAR * (size / 2)).from_buffer(buffer)[:]
|
||||
assert not size % 2
|
||||
return (gdef.WCHAR * (size // 2)).from_buffer(buffer)[:]
|
||||
|
||||
def Py2Reg_SZ(obj):
|
||||
return obj.encode(WENCODING)
|
||||
@@ -84,7 +87,10 @@ def Reg2Py_Multi_SZ(buffer, size):
|
||||
if not size:
|
||||
return []
|
||||
# Simple path
|
||||
rawstr = "".join([chr(c) for c in buffer[:size]])
|
||||
if is_py3:
|
||||
rawstr = bytes(buffer)
|
||||
else:
|
||||
rawstr = "".join([chr(c) for c in buffer[:size]])
|
||||
try:
|
||||
unistr = rawstr.decode(WENCODING)
|
||||
return unistr.rstrip(u"\x00").split(u"\x00")
|
||||
@@ -93,16 +99,16 @@ def Reg2Py_Multi_SZ(buffer, size):
|
||||
# Complexe-path
|
||||
# This is not some valide UTF-16
|
||||
# Try our best to extract some stuff from raw
|
||||
return rawstr.rstrip("\x00").split("\x00")
|
||||
return rawstr.rstrip(b"\x00").split(b"\x00")
|
||||
|
||||
|
||||
def Py2Reg_Multi_SZ(obj):
|
||||
# Work on encoded values (to prevent str/unicode errors)
|
||||
uni_list = [s.encode(WENCODING) for s in obj]
|
||||
# Separate by UTF-16 NULL BYTE (2 \x00)
|
||||
uni_str = "\x00\x00".join(uni_list)
|
||||
uni_str = b"\x00\x00".join(uni_list)
|
||||
# Add UTF-16 NULL byte for final string + final UTF-16 \x00 (4 \x00)
|
||||
return uni_str + "\x00\x00\x00\x00"
|
||||
return uni_str + b"\x00\x00\x00\x00"
|
||||
|
||||
DECODE_METHOD = 0
|
||||
ENCODE_METHOD = 1
|
||||
@@ -293,7 +299,7 @@ class PyHKey(object):
|
||||
def _guess_value_type(self, value):
|
||||
if isinstance(value, basestring):
|
||||
return gdef.REG_SZ
|
||||
elif isinstance(value, (int, long)):
|
||||
elif isinstance(value, int_types):
|
||||
return gdef.REG_DWORD
|
||||
# elif isinstance(value, (list, tuple)):
|
||||
# if all(isinstance(v, basestring) in value):
|
||||
@@ -308,7 +314,7 @@ class PyHKey(object):
|
||||
|
||||
|
||||
buffer = ENCODE_DECODE_METHODS[type][ENCODE_METHOD](value)
|
||||
if isinstance(buffer, str): # Should not be unicode at this point
|
||||
if isinstance(buffer, bytes): # Should not be unicode at this point
|
||||
buffer = windows.utils.BUFFER(gdef.BYTE).from_buffer_copy(buffer)
|
||||
return winproxy.RegSetValueExW(self.phkey, name, 0, type, buffer, len(buffer))
|
||||
|
||||
@@ -357,7 +363,7 @@ class PyHKey(object):
|
||||
|
||||
def __setitem__(self, name, value):
|
||||
rtype = None
|
||||
if not isinstance(value, (int, long, basestring)):
|
||||
if not (isinstance(value, basestring) or isinstance(value, int_types)):
|
||||
value, rtype = value
|
||||
return self.set(name, value, rtype)
|
||||
|
||||
|
||||
@@ -147,8 +147,13 @@ class System(object):
|
||||
:type: :class:`str`
|
||||
"""
|
||||
size = gdef.DWORD(0x1000)
|
||||
buf = ctypes.c_buffer(size.value)
|
||||
winproxy.GetComputerNameA(buf, ctypes.byref(size))
|
||||
# For now I don't know what is best as A vs W APIs...
|
||||
if windows.pycompat.is_py3:
|
||||
buf = ctypes.create_unicode_buffer(size.value)
|
||||
winproxy.GetComputerNameW(buf, ctypes.byref(size))
|
||||
else:
|
||||
buf = ctypes.create_string_buffer(size.value)
|
||||
winproxy.GetComputerNameA(buf, ctypes.byref(size))
|
||||
return buf[:size.value]
|
||||
|
||||
@utils.fixedpropety
|
||||
@@ -372,12 +377,30 @@ class System(object):
|
||||
|
||||
@utils.fixedpropety
|
||||
def build_number(self):
|
||||
# This returns the last version where ntdll was updated
|
||||
# Should look at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
|
||||
# values: CurrentBuild + UBR
|
||||
# windows.system.registry(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion")["CurrentBuild"].value
|
||||
# windows.system.registry(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion")["UBR"].value
|
||||
return self.get_file_version("comctl32")
|
||||
# Best effort. use get_file_version if registry code fails
|
||||
try:
|
||||
# Does not works on Win7..
|
||||
# Missing CurrentMajorVersionNumber/CurrentMinorVersionNumber/UBR
|
||||
# We have CurrentVersion instead
|
||||
# Use this code and get_file_version as a backup ?
|
||||
curver_key = windows.system.registry(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion")
|
||||
try:
|
||||
major = curver_key["CurrentMajorVersionNumber"].value
|
||||
minor = curver_key["CurrentMinorVersionNumber"].value
|
||||
except WindowsError as e:
|
||||
version = curver_key["CurrentVersion"].value
|
||||
# May raise ValueError if no "."
|
||||
major, minor = version.split(".")
|
||||
build = curver_key["CurrentBuildNumber"].value
|
||||
# Update Build Revision
|
||||
try:
|
||||
ubr = curver_key["UBR"].value
|
||||
except WindowsError as e:
|
||||
ubr = 0 # Not present on Win7
|
||||
return "{0}.{1}.{2}.{3}".format(major, minor, build, ubr)
|
||||
except (WindowsError, ValueError):
|
||||
return self.get_file_version("ntdll")
|
||||
|
||||
|
||||
@staticmethod
|
||||
def enumerate_processes():
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import ctypes
|
||||
import functools
|
||||
from __builtin__ import type as bltn_type
|
||||
|
||||
import windows
|
||||
from windows import utils
|
||||
from windows import winproxy
|
||||
import windows.generated_def as gdef
|
||||
|
||||
bltn_type = type
|
||||
|
||||
KNOW_INTEGRITY_LEVEL = gdef.FlagMapper(
|
||||
gdef.SECURITY_MANDATORY_UNTRUSTED_RID,
|
||||
@@ -465,7 +465,8 @@ class Token(utils.AutoHandle):
|
||||
"""
|
||||
mandatory_label = gdef.TOKEN_MANDATORY_LABEL()
|
||||
mandatory_label.Label.Attributes = 0x60
|
||||
mandatory_label.Label.Sid = gdef.PSID.from_string("S-1-16-{0}".format(integrity))
|
||||
# cast integrity to int to accept SECURITY_MANDATORY_LOW_RID & other Flags
|
||||
mandatory_label.Label.Sid = gdef.PSID.from_string("S-1-16-{0}".format(int(integrity)))
|
||||
return self.set_informations(gdef.TokenIntegrityLevel, mandatory_label)
|
||||
|
||||
_INTEGRITY_PROPERTY_DOC = """The integrity of the token as an int (extracted from integrity PSID)
|
||||
|
||||
@@ -71,7 +71,7 @@ def get_logical_drive_names():
|
||||
size = 0x100
|
||||
buffer = ctypes.c_buffer(size)
|
||||
rsize = winproxy.GetLogicalDriveStringsA(0x1000, buffer)
|
||||
return buffer[:rsize].rstrip("\x00").split("\x00")
|
||||
return buffer[:rsize].rstrip(b"\x00").split(b"\x00")
|
||||
|
||||
def get_info(drivename):
|
||||
size = 0x1000
|
||||
@@ -85,4 +85,4 @@ def query_dos_device(name):
|
||||
size = 0x1000
|
||||
buffer = ctypes.c_buffer(size)
|
||||
rsize = winproxy.QueryDosDeviceA(name, buffer, size)
|
||||
return buffer[:rsize].rstrip("\x00").split("\x00")
|
||||
return buffer[:rsize].rstrip(b"\x00").split(b"\x00")
|
||||
@@ -4,6 +4,9 @@ import windows.generated_def as gdef
|
||||
from ..apiproxy import ApiProxy, NeededParameter
|
||||
from ..error import no_error_check, fail_on_zero
|
||||
|
||||
import windows.pycompat
|
||||
from windows.pycompat import int_types
|
||||
|
||||
class Crypt32Proxy(ApiProxy):
|
||||
APIDLL = "crypt32"
|
||||
default_error_check = staticmethod(fail_on_zero)
|
||||
@@ -74,7 +77,7 @@ def CryptHashCertificate(hCryptProv, Algid, dwFlags, pbEncoded, cbEncoded, pbCom
|
||||
|
||||
@Crypt32Proxy()
|
||||
def CertOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara):
|
||||
if isinstance(lpszStoreProvider, (long, int)):
|
||||
if isinstance(lpszStoreProvider, int_types):
|
||||
lpszStoreProvider = gdef.LPCSTR(lpszStoreProvider)
|
||||
return CertOpenStore.ctypes_function(lpszStoreProvider, dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara)
|
||||
|
||||
@@ -119,7 +122,7 @@ def CryptAcquireCertificatePrivateKey(pCert, dwFlags, pvParameters, phCryptProvO
|
||||
|
||||
@Crypt32Proxy()
|
||||
def CryptEncryptMessage(pEncryptPara, cRecipientCert, rgpRecipientCert, pbToBeEncrypted, cbToBeEncrypted, pbEncryptedBlob, pcbEncryptedBlob):
|
||||
if isinstance(pbToBeEncrypted, basestring):
|
||||
if isinstance(pbToBeEncrypted, windows.pycompat.anybuff):
|
||||
# Transform string to array of byte
|
||||
pbToBeEncrypted = (gdef.BYTE * len(pbToBeEncrypted))(*bytearray(pbToBeEncrypted))
|
||||
if cbToBeEncrypted is None and pbToBeEncrypted is not None:
|
||||
@@ -161,7 +164,7 @@ def CryptVerifyMessageHash(pHashPara, pbHashedBlob, cbHashedBlob, pbToBeHashed,
|
||||
|
||||
@Crypt32Proxy()
|
||||
def CryptEncodeObjectEx(dwCertEncodingType, lpszStructType, pvStructInfo, dwFlags, pEncodePara, pvEncoded, pcbEncoded):
|
||||
lpszStructType = gdef.LPCSTR(lpszStructType) if isinstance(lpszStructType, (int, long)) else lpszStructType
|
||||
lpszStructType = gdef.LPCSTR(lpszStructType) if isinstance(lpszStructType, int_types) else lpszStructType
|
||||
return CryptEncodeObjectEx.ctypes_function(dwCertEncodingType, lpszStructType, pvStructInfo, dwFlags, pEncodePara, pvEncoded, pcbEncoded)
|
||||
|
||||
@Crypt32Proxy()
|
||||
|
||||
Reference in New Issue
Block a user