Writing / updating some doc

This commit is contained in:
hakril
2016-03-29 23:41:54 +02:00
parent 4c1192bf75
commit 53e131831d
10 changed files with 256 additions and 69 deletions
+16 -12
View File
@@ -1,7 +1,7 @@
TODO:
- Documentation
- Pass 0.2 when doc is done <3
- ProcessMemory object ? (metasm like)
- Extend Registry feature (write)
- remove pe_parse.transform_ctypes_fields (use utils.transform_ctypes_fields)
- DBG
@@ -10,7 +10,6 @@ TODO:
- Test !! (bp, BP_HX, bp on only on process, bp_hx on only one thread..)
- test breakpoint with specific target
- Threading
- Quid IAT hook stub ? just einit threads and remove this ?
@@ -25,36 +24,41 @@ TODO:
- rethink OptionalExport ? not useful with lazy resolution (or we need to force resolution..)
- Readme
- Debugger ? Veh ?
- TransparentApiProxy
double name (params and args) for same info..
- 32 <-> 64
* What about ``NtWow64QueryVirtualMemory64`` ?
- Parse .IDL file for more COM NAME->IID
CHANGELOG:
* NEW REGISTRY -> change examples and documentation
* WinProcess is not a PROCESSENTRY32 anymore (change doc)
FIXME:
- WMI
- COM initialisation when injected in another process
- The CoInitialize might be already called
- Fix that
Documentation
* Debugger
* LocalDebugger
* volumes
* system.version stuff
* windows.com
* windows.wintrust
* New stuff in exception ?
* system.firewall.network
* system.services
* New stuff in WMI ?(think not just change in internal)
* windows.utils
* verif samples
FIXME:
- setup.py build seems to raise an error
- winutils.create_process : use WinProcess._from_handle
- Push("[ECX]") in simple_x64 as a "H" rex and i think it should not..
RESSOURCE
* read http://www.codeproject.com/Articles/18975/Listing-Used-Files
+12 -4
View File
@@ -1,19 +1,27 @@
Network
=======
.. module:: windows.network
.. module:: windows.winobject.network
.. note::
See sample :ref:`sample_network_exploration`
.. autoclass:: windows.network.Network
.. autoclass:: Network
Connections
"""""""""""
.. autoclass:: windows.network.TCP4Connection
.. autoclass:: TCP4Connection
.. autoclass:: windows.network.TCP6Connection
.. autoclass:: TCP6Connection
Firewall
""""""""
.. autoclass:: Firewall
.. autoclass:: FirewallRule
+1 -1
View File
@@ -1,7 +1,7 @@
Processes and Threads
"""""""""""""""""""""
.. module:: windows.winobject
.. module:: windows.winobject.process
CurrentProcess
''''''''''''''
+1 -1
View File
@@ -1,7 +1,7 @@
Registry
========
.. module:: windows.registry
.. module:: windows.winobject.registry
.. note::
+1
View File
@@ -13,4 +13,5 @@ This sections describes them by group of relation.
exception.rst
registry.rst
network.rst
service.rst
com.rst
+5 -13
View File
@@ -7,14 +7,15 @@ This module exports some objects representing the current state of the system.
It also offers some submodules aimed to help the interfacing with ``Windows`` and native code execution.
The defaults objects accessible in ``windows`` are:
* ``system`` of type :class:`windows.winobject.System`
* ``current_process`` of type :class:`windows.winobject.CurrentProcess`
* ``current_thread`` of type :class:`windows.winobject.CurrentThread`
* ``system`` of type :class:`windows.winobject.system.System`
* ``current_process`` of type :class:`windows.winobject.process.CurrentProcess`
* ``current_thread`` of type :class:`windows.winobject.process.CurrentThread`
The submodules that you might use by themself are:
* :mod:`windows.native_exec`
* :mod:`windows.winproxy`
* :mod:`windows.utils`
* :mod:`windows.com`
.. _object_system:
@@ -23,15 +24,6 @@ The ``system`` object
.. currentmodule:: windows.winobject
.. autoclass:: windows.winobject.System
.. autoclass:: windows.winobject.system.System
:no-show-inheritance:
.. autoattribute:: windows.winobject.System.registry
:annotation:
Object of class :class:`windows.registry.Registry`
.. autoattribute:: windows.winobject.System.network
:annotation:
Object of class :class:`windows.network.Network`
+96 -5
View File
@@ -11,7 +11,7 @@ from windows.generated_def.windef import *
class TCP4Connection(MIB_TCPROW_OWNER_PID):
"""A TCP4 socket (connected or listening)"""
@property
def established(self):
"""``True`` if connection is established else it's a listening socket"""
@@ -87,6 +87,7 @@ class TCP4Connection(MIB_TCPROW_OWNER_PID):
class TCP6Connection(MIB_TCP6ROW_OWNER_PID):
"""A TCP6 socket (connected or listening)"""
@staticmethod
def _str_ipv6_addr(addr):
return ":".join(c.encode('hex') for c in addr)
@@ -170,8 +171,13 @@ def get_MIB_TCP6TABLE_OWNER_PID_from_buffer(buffer):
return _GENERATED_MIB_TCP6TABLE_OWNER_PID.from_buffer(buffer)
class Firewall(cominterfaces.INetFwPolicy2):
"""The windows firewall"""
@property
def rules(self):
"""The rules of the firewall
:type: [:class:`FirewallRule`] -- A list of rule
"""
ifw_rules = cominterfaces.INetFwRules()
self.get_Rules(ifw_rules)
@@ -200,102 +206,183 @@ class Firewall(cominterfaces.INetFwPolicy2):
@property
def current_profile_types(self):
"""Mask of the profiles currently enabled
:type: :class:`long`
"""
cpt = gdef.LONG()
self.get_CurrentProfileTypes(cpt)
return cpt.value
@property
def enabled(self):
"""A maping of the active firewall profiles
{
``NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_DOMAIN(0x1L)``: ``True`` or ``False``,
``NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE(0x2L)``: ``True`` or ``False``,
``NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC(0x4L)``: ``True`` or ``False``,
}
:type: :class:`dict`
"""
profiles = [gdef.NET_FW_PROFILE2_DOMAIN, gdef.NET_FW_PROFILE2_PRIVATE, gdef.NET_FW_PROFILE2_PUBLIC]
return {prof: self.enabled_for_profile_type(prof) for prof in profiles}
def enabled_for_profile_type(self, profile_type):
enabled = gdef.VARIANT_BOOL()
self.get_FirewallEnabled(profile_type, enabled)
return enabled.value
@property
def enabled(self):
profiles = [gdef.NET_FW_PROFILE2_DOMAIN, gdef.NET_FW_PROFILE2_PRIVATE, gdef.NET_FW_PROFILE2_PUBLIC]
return {prof: self.enabled_for_profile_type(prof) for prof in profiles}
class FirewallRule(cominterfaces.INetFwRule):
"""A rule of the firewall"""
@property
def name(self):
"""Name of the rule
:type: :class:`unicode`
"""
name = gdef.BSTR()
self.get_Name(name)
return name.value
@property
def description(self):
"""Description of the rule
:type: :class:`unicode`
"""
description = gdef.BSTR()
self.get_Description(description)
return description.value
@property
def application_name(self):
"""Name of the application to which apply the rule
:type: :class:`unicode`
"""
applicationname = gdef.BSTR()
self.get_ApplicationName(applicationname)
return applicationname.value
@property
def service_name(self):
"""Name of the service to which apply the rule
:type: :class:`unicode`
"""
servicename = gdef.BSTR()
self.get_ServiceName(servicename)
return servicename.value
@property
def protocol(self):
"""Protocol to which apply the rule
:type: :class:`long`
"""
protocol = gdef.LONG()
self.get_Protocol(protocol)
return protocol.value
@property
def local_address(self):
"""Local address of the rule
:type: :class:`unicode`
"""
local_address = gdef.BSTR()
self.get_LocalAddresses(local_address)
return local_address.value
@property
def remote_address(self):
"""Remote address of the rule
:type: :class:`unicode`
"""
remote_address = gdef.BSTR()
self.get_RemoteAddresses(remote_address)
return remote_address.value
@property
def direction(self):
"""Direction of the rule, values might be:
* ``NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN(0x1L)``
* ``NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT(0x2L)``
subclass of :class:`long`
"""
direction = gdef.NET_FW_RULE_DIRECTION()
self.get_Direction(direction)
return direction.value
@property
def interface_types(self):
"""Types of interface of the rule
:type: :class:`unicode`
"""
interface_type = gdef.BSTR()
self.get_InterfaceTypes(interface_type)
return interface_type.value
@property
def local_port(self):
"""Local port of the rule
:type: :class:`unicode`
"""
local_port = gdef.BSTR()
self.get_LocalPorts(local_port)
return local_port.value
@property
def remote_port(self):
"""Remote port of the rule
:type: :class:`unicode`
"""
remote_port = gdef.BSTR()
self.get_RemotePorts(remote_port)
return remote_port.value
@property
def action(self):
"""Action of the rule, values might be:
* ``NET_FW_ACTION_.NET_FW_ACTION_BLOCK(0x0L)``
* ``NET_FW_ACTION_.NET_FW_ACTION_ALLOW(0x1L)``
subclass of :class:`long`
"""
action = gdef.NET_FW_ACTION()
self.get_Action(action)
return action.value
@property
def enabled(self):
"""``True`` if rule is enabled"""
enabled = gdef.VARIANT_BOOL()
self.get_Enabled(enabled)
return enabled.value
@property
def grouping(self):
"""Grouping of the rule
:type: :class:`unicode`
"""
grouping = gdef.BSTR()
self.get_RemotePorts(grouping)
return grouping.value
@@ -314,6 +401,10 @@ class Network(object):
@property
def firewall(self):
"""The firewall of the system
:type: :class:`Firewall`
"""
windows.com.init()
firewall = Firewall()
windows.com.create_instance(self.NetFwPolicy2, firewall)
+44 -2
View File
@@ -13,7 +13,32 @@ SERVICE_CONTROLE_ACCEPTED = {x:x for x in []}
SERVICE_FLAGS = {x:x for x in [SERVICE_RUNS_IN_SYSTEM_PROCESS]}
service_status = namedtuple("ServiceStatus", ["type", "state", "control_accepted", "flags"])
ServiceStatus = namedtuple("ServiceStatus", ["type", "state", "control_accepted", "flags"])
"""
``type`` might be one of:
* ``SERVICE_KERNEL_DRIVER(0x1L)``
* ``SERVICE_FILE_SYSTEM_DRIVER(0x2L)``
* ``SERVICE_WIN32_OWN_PROCESS(0x10L)``
* ``SERVICE_WIN32_SHARE_PROCESS(0x20L)``
* ``SERVICE_INTERACTIVE_PROCESS(0x100L)``
``state`` might be on of:
* ``SERVICE_STOPPED(0x1L)``
* ``SERVICE_START_PENDING(0x2L)``
* ``SERVICE_STOP_PENDING(0x3L)``
* ``SERVICE_RUNNING(0x4L)``
* ``SERVICE_CONTINUE_PENDING(0x5L)``
* ``SERVICE_PAUSE_PENDING(0x6L)``
* ``SERVICE_PAUSED(0x7L)``
``flags`` might be one of:
* ``0``
* ``SERVICE_RUNS_IN_SYSTEM_PROCESS(0x1L)``
"""
class Service(object):
def __repr__(self):
@@ -21,23 +46,39 @@ class Service(object):
@utils.fixedpropety
def name(self):
"""The name of the service
:type: :class:`str`
"""
return self.lpServiceName
@utils.fixedpropety
def description(self):
"""The description of the service
:type: :class:`str`
"""
return self.lpDisplayName
@utils.fixedpropety
def status(self):
"""The status of the service
:type: :class:`ServiceStatus`
"""
status = self.ServiceStatusProcess
stype = SERVICE_TYPE.get(status.dwServiceType, status.dwServiceType)
sstate = SERVICE_STATE.get(status.dwCurrentState, status.dwCurrentState)
scontrol = status.dwControlsAccepted
sflags = SERVICE_FLAGS.get(status.dwServiceFlags, status.dwServiceFlags)
return service_status(stype, sstate, scontrol, sflags)
return ServiceStatus(stype, sstate, scontrol, sflags)
@utils.fixedpropety
def process(self):
"""The process running the service (if any)
:type: :class:`WinProcess <windows.winobject.process.WinProcess>` or ``None``
"""
pid = self.ServiceStatusProcess.dwProcessId
if not pid:
return None
@@ -48,6 +89,7 @@ class Service(object):
class ServiceA(Service, ENUM_SERVICE_STATUS_PROCESSA):
"""A Service object with ascii data"""
pass
def enumerate_services():
+79 -30
View File
@@ -21,14 +21,16 @@ from windows.generated_def.winstructs import *
class System(object):
"""Represent the current ``Windows`` system ``Python`` is running on"""
network = network.Network() # Object of class :class:`windows.network.Network`
registry = registry.Registry() # Object of class :class:`windows.registry.Registry`
network = network.Network()
"""Object of class :class:`windows.winobject.network.Network`"""
registry = registry.Registry()
"""Object of class :class:`windows.winobject.registry.Registry`"""
@property
def processes(self):
"""The list of running processes
:type: [:class:`WinProcess`] -- A list of Process
:type: [:class:`process.WinProcess`] -- A list of Process
"""
return self.enumerate_processes()
@@ -36,17 +38,23 @@ class System(object):
def threads(self):
"""The list of running threads
:type: [:class:`WinThread`] -- A list of Thread
:type: [:class:`process.WinThread`] -- A list of Thread
"""
return self.enumerate_threads()
@property
def logicaldrives(self):
"""List of logical drives [C:\, ...]
:type: [:class:`volume.LogicalDrive`] -- A list of LogicalDrive
"""
return volume.enum_logical_drive()
@property
def services(self):
"""The list of services (TODO: BETTER DOC)"""
"""The list of services
:type: [:class:`service.ServiceA`] -- A list of Service"""
return service.enumerate_services()
#@property
@@ -87,42 +95,29 @@ class System(object):
@utils.fixedpropety
def wmi(self):
r"""An object to perform wmi request to "root\\cimv2"
:type: :class:`wmi.WmiRequester`"""
return wmi.WmiRequester()
#TODO: use GetComputerNameExA ? and recover other names ?
@utils.fixedpropety
def computer_name(self):
"""The name of the computer
:type: :class:`str`
"""
size = DWORD(0x1000)
buf = ctypes.c_buffer(size.value)
winproxy.GetComputerNameA(buf, ctypes.byref(size))
return buf[:size.value]
@staticmethod
def enumerate_processes():
process_entry = PROCESSENTRY32()
process_entry.dwSize = ctypes.sizeof(process_entry)
snap = winproxy.CreateToolhelp32Snapshot(windef.TH32CS_SNAPPROCESS, 0)
winproxy.Process32First(snap, process_entry)
res = []
res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
while winproxy.Process32Next(snap, process_entry):
res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
return res
@staticmethod
def enumerate_threads():
thread_entry = process.WinThread()
thread_entry.dwSize = ctypes.sizeof(thread_entry)
snap = winproxy.CreateToolhelp32Snapshot(windef.TH32CS_SNAPTHREAD, 0)
threads = []
winproxy.Thread32First(snap, thread_entry)
threads.append(copy.copy(thread_entry))
while winproxy.Thread32Next(snap, thread_entry):
threads.append(copy.copy(thread_entry))
return threads
@utils.fixedpropety
def version(self):
"""The version of the system
:type: (:class:`int`, :class:`int`) -- (Major, Minor)
"""
data = self.get_version()
result = data.dwMajorVersion, data.dwMinorVersion
if result == (6,2):
@@ -133,6 +128,28 @@ class System(object):
@utils.fixedpropety
def version_name(self):
"""The name of the system version, values are:
* Windows Server 2016
* Windows 10
* Windows Server 2012 R2
* Windows 8.1
* Windows Server 2012
* Windows 8
* Windows Server 2008
* Windows 7
* Windows Server 2008
* Windows Vista
* Windows XP Professional x64 Edition
* TODO: version (5.2) + is_workstation + bitness == 32 (don't even know if possible..)
* Windows Server 2003 R2
* Windows Server 2003
* Windows XP
* Windows 2000
* "Unknow Windows <version={0} | is_workstation={1}>".format(version, is_workstation)
:type: :class:`str`
"""
version = self.version
is_workstation = self.product_type == VER_NT_WORKSTATION
if version == (10, 0):
@@ -165,6 +182,14 @@ class System(object):
@utils.fixedpropety
def product_type(self):
"""The product type, value might be:
* VER_NT_WORKSTATION(0x1L)
* VER_NT_DOMAIN_CONTROLLER(0x2L)
* VER_NT_SERVER(0x3L)
:type: :class:`long` or :class:`int` (or subclass)
"""
version_map = {x:x for x in [VER_NT_WORKSTATION, VER_NT_DOMAIN_CONTROLLER, VER_NT_SERVER]}
version = self.get_version()
return version_map.get(version.wProductType, version.wProductType)
@@ -188,4 +213,28 @@ class System(object):
req = "{0:04x}{1:04x}".format(*tup)
winproxy.VerQueryValueA(buf, "\\StringFileInfo\\{0}\\ProductVersion".format(req), ctypes.byref(bufptr), ctypes.byref(bufsize))
bufstr = ctypes.cast(bufptr, LPCSTR)
return bufstr.value
return bufstr.value
@staticmethod
def enumerate_processes():
process_entry = PROCESSENTRY32()
process_entry.dwSize = ctypes.sizeof(process_entry)
snap = winproxy.CreateToolhelp32Snapshot(windef.TH32CS_SNAPPROCESS, 0)
winproxy.Process32First(snap, process_entry)
res = []
res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
while winproxy.Process32Next(snap, process_entry):
res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
return res
@staticmethod
def enumerate_threads():
thread_entry = process.WinThread()
thread_entry.dwSize = ctypes.sizeof(thread_entry)
snap = winproxy.CreateToolhelp32Snapshot(windef.TH32CS_SNAPTHREAD, 0)
threads = []
winproxy.Thread32First(snap, thread_entry)
threads.append(copy.copy(thread_entry))
while winproxy.Thread32Next(snap, thread_entry):
threads.append(copy.copy(thread_entry))
return threads
+1 -1
View File
@@ -11,7 +11,7 @@ from windows.generated_def.interfaces import IWbemLocator, IWbemServices, IEnumW
class WmiRequester(object):
"""Perform WMI request: NOT STABLE"""
"""Perform WMI request"""
INSTANCE = None