More doc / sample

This commit is contained in:
Clement Rouault
2016-03-30 18:27:40 +02:00
parent 96c8d68297
commit 6c1b4cf5e6
12 changed files with 117 additions and 42 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
Exception and Context related structures
========================================
.. module:: windows.exception
.. module:: windows.winobject.exception
This module regroups all the Exception/Context related structures and functions.
+29 -1
View File
@@ -339,4 +339,32 @@ Ouput::
I AM LOADING <C:\Windows\SysWOW64\msxml6.dll>
I AM LOADING <C:\Windows\system32\shell32.dll>
I AM LOADING <C:\Windows\SYSTEM32\WINMM.dll>
I AM LOADING <C:\Windows\system32\ole32.dll>
I AM LOADING <C:\Windows\system32\ole32.dll>
.. _wmi_request:
Make WMI requests
'''''''''''''''''
.. literalinclude:: ..\..\samples\wmi_request.py
Ouput::
(cmd λ) python .\samples\wmi_request.py
WMI requester is <windows.winobject.wmi.WmiRequester object at 0x02CAA410>
Selecting * from 'Win32_Process'
They are <94> processes
Looking for ourself via pid
Some info about our process:
* Name -> python.exe
* ProcessId -> 7896
* OSName -> Microsoft Windows 8.1 Pro|C:\Windows|\Device\Harddisk0\Partition2
* UserModeTime -> 1406250
* WindowsVersion -> 6.3.9600
* CommandLine -> "C:\Python27\python.exe" .\wmi_request.py
<Select Caption,FileSystem,FreeSpace from Win32_LogicalDisk>:
* {'Caption': u'C:', 'FreeSpace': u'14729031680', 'FileSystem': u'NTFS'}
* {'Caption': u'D:', 'FreeSpace': u'243872890880', 'FileSystem': u'NTFS'}
* {'Caption': u'E:', 'FreeSpace': u'1073852416', 'FileSystem': u'FAT32'}
+3 -1
View File
@@ -14,4 +14,6 @@ This sections describes them by group of relation.
registry.rst
network.rst
service.rst
com.rst
volume.rst
com.rst
wmi.rst
+2
View File
@@ -0,0 +1,2 @@
Volume -- The logical drives
============================
+2 -1
View File
@@ -1,7 +1,7 @@
The ``windows`` module
**********************
The ``windows`` module is the module installed by :file:`setup.py` (that does not exists right now).
The ``windows`` module is the module installed by :file:`setup.py`.
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.
@@ -15,6 +15,7 @@ The submodules that you might use by themself are:
* :mod:`windows.native_exec`
* :mod:`windows.winproxy`
* :mod:`windows.utils`
* :mod:`windows.debug`
* :mod:`windows.com`
.. _object_system:
+1 -18
View File
@@ -3,21 +3,4 @@ Early Work In Progress
Here are some features that are still work in progress. Code might be unstable and/or ultra-ugly.
Wintrust -- Signature check
"""""""""""""""""""""""""""
Should it juste be part of :mod:`windows.utils` ?
.. module:: windows.wintrust
.. autofunction:: windows.wintrust.check_signature
.. module:: windows.wmi
WMI -- WMI request
""""""""""""""""""
Unstable code: not fully tested, ugly COM initialisation
.. autoclass:: windows.wmi.WmiRequester
<Nothing right now>
+12
View File
@@ -0,0 +1,12 @@
WMI -- Make request to WMI
==========================
.. module:: windows.winobject.wmi
.. note::
See sample :ref:`wmi_request`
.. autoclass:: WmiRequester
+31
View File
@@ -0,0 +1,31 @@
import sys
import os.path
import pprint
sys.path.append(os.path.abspath(__file__ + "\..\.."))
import windows
print("WMI requester is {0}".format(windows.system.wmi))
print("Selecting * from 'Win32_Process'")
result = windows.system.wmi.select("Win32_Process")
print("They are <{0}> processes".format(len(result)))
print("Looking for ourself via pid")
us = [p for p in result if int(p["ProcessId"]) == windows.current_process.pid][0]
print("Some info about our process:")
print(" * {0} -> {1}".format("Name", us["Name"]))
print(" * {0} -> {1}".format("ProcessId", us["ProcessId"]))
print(" * {0} -> {1}".format("OSName", us["OSName"]))
print(" * {0} -> {1}".format("UserModeTime", us["UserModeTime"]))
print(" * {0} -> {1}".format("WindowsVersion", us["WindowsVersion"]))
print(" * {0} -> {1}".format("CommandLine", us["CommandLine"]))
print("<Select Caption,FileSystem,FreeSpace from Win32_LogicalDisk>:")
for vol in windows.system.wmi.select("Win32_LogicalDisk", ["Caption", "FileSystem", "FreeSpace"]):
print(" * " + str(vol))
+7 -1
View File
@@ -96,7 +96,6 @@ class SystemTestCase(unittest.TestCase):
class WindowsTestCase(unittest.TestCase):
def setUp(self):
pass
@@ -409,6 +408,13 @@ class WindowsTestCase(unittest.TestCase):
calc.load_library(DLL)
self.assertIn(DLL, [m.name for m in calc.peb.modules])
def test_token_info(self):
token = windows.current_process.token
self.assertIsInstance(token.computername, basestring)
self.assertIsInstance(token.username, basestring)
self.assertIsInstance(token.integrity, (int, long))
self.assertIsInstance(token.is_elevated, (bool))
class WindowsAPITestCase(unittest.TestCase):
def test_createfileA_fail(self):
+24 -14
View File
@@ -51,7 +51,7 @@ class AutoHandle(object):
def __del__(self):
if hasattr(self, "_handle") and self._handle:
dbgprint("Closing Handle {0} for {1}".format(hex(self._handle), self), "HANDLE")
#dbgprint("Closing Handle {0} for {1}".format(hex(self._handle), self), "HANDLE")
self._close_function(self._handle)
@@ -82,7 +82,7 @@ class WinThread(THREADENTRY32, AutoHandle):
def context(self):
"""The context of the thread, type depend of the target process.
:type: :class:`windows.exception.ECONTEXT32` or :class:`windows.exception.ECONTEXT64` or :class:`windows.exception.ECONTEXTWOW64`
:type: :class:`windows.exception.ECONTEXT32` or :class:`windows.exception.ECONTEXT64` or :class:`windows.exception.ECONTEXTWOW64`
"""
if self.owner.bitness == 32 and windows.current_process.bitness == 64:
# Wow64
@@ -148,7 +148,7 @@ class WinThread(THREADENTRY32, AutoHandle):
@property
def is_exit(self):
"""Is ``True`` if the thread is terminated
"""``True`` if the thread is terminated
:type: :class:`bool`
"""
@@ -271,7 +271,7 @@ class Process(AutoHandle):
def allocated_memory(self, size):
"""ContextManager to allocate memory and free it
:type: :class:`int` -- the address of the allocated memory
:type: :class:`int` -- the address of the allocated memory
"""
addr = self.virtual_alloc(size)
try:
@@ -282,8 +282,8 @@ class Process(AutoHandle):
def execute(self, code, parameter=0):
"""Execute some native code in the context of the process
:return: The thread executing the code
:rtype: :class:`WinThread` or :class:`DeadThread`
:return: The thread executing the code
:rtype: :class:`WinThread` or :class:`DeadThread`
"""
x = self.virtual_alloc(len(code)) #Todo: free this ? when ? how ? reuse ?
self.write_memory(x, code)
@@ -292,7 +292,7 @@ class Process(AutoHandle):
def query_memory(self, addr):
"""Query the memory informations about page at ``addr``
:rtype: :class:`MEMORY_BASIC_INFORMATION`
:rtype: :class:`MEMORY_BASIC_INFORMATION`
"""
if windows.current_process.bitness == 32 and self.bitness == 64:
res = MEMORY_BASIC_INFORMATION64()
@@ -313,7 +313,7 @@ class Process(AutoHandle):
def memory_state(self):
"""Yield the memory information for the whole address space of the process
:yield: :class:`MEMORY_BASIC_INFORMATION`
:yield: :class:`MEMORY_BASIC_INFORMATION`
"""
addr = 0
res = []
@@ -328,7 +328,7 @@ class Process(AutoHandle):
def mapped_filename(self, addr):
"""The filename mapped at address ``addr`` or ``None``
:rtype: :class:`str` or ``None``
:rtype: :class:`str` or ``None``
"""
buffer = ctypes.c_buffer(0x1024)
try:
@@ -406,7 +406,7 @@ class Process(AutoHandle):
def token(self):
"""The token of the process
:type: :class:`Token`
:type: :class:`Token`
"""
token_handle = HANDLE()
winproxy.OpenProcessToken(self.handle, TOKEN_QUERY, byref(token_handle))
@@ -622,7 +622,9 @@ class WinProcess(Process):
:type: :class:`int`
"""
return self.th32ParentProcessID
# TODO: is there an API ?
pid = self.pid
return [p for p in windows.system.processes if p.pid == pid][0].th32ParentProcessID
def _get_handle(self):
return winproxy.OpenProcess(dwProcessId=self.pid)
@@ -771,7 +773,7 @@ class WinProcess(Process):
def peb_syswow(self):
"""The 64bits PEB of a SysWow64 process
:type: :class:`PEB`
:type: :class:`PEB`
"""
if not self.is_wow_64:
raise ValueError("Not a syswow process")
@@ -805,7 +807,7 @@ class Token(AutoHandle):
def integrity(self):
"""Return the integrity level of a process
:type: :class:`int`
:type: :class:`int`
"""
buffer_size = self.get_required_information_size(TokenIntegrityLevel)
buffer = ctypes.c_buffer(buffer_size)
@@ -830,10 +832,14 @@ class Token(AutoHandle):
self.get_informations(TokenUser, buffer)
return ctypes.cast(ctypes.byref(buffer), POINTER(TOKEN_USER))[0]
@property
def computername(self):
"""The computername of the token"""
return self._user_and_computer_name()[1]
@property
def username(self):
"""The username of the token"""
return self._user_and_computer_name()[0]
def _user_and_computer_name(self):
@@ -843,7 +849,7 @@ class Token(AutoHandle):
computernamesize = DWORD(0x1000)
username = ctypes.c_buffer(usernamesize.value)
computername = ctypes.c_buffer(computernamesize.value)
peUse = DWORD()
peUse = SID_NAME_USE()
winproxy.LookupAccountSidA(None, sid, username, byref(usernamesize), computername, byref(computernamesize), peUse)
return username[:usernamesize.value], computername[:computernamesize.value]
@@ -873,6 +879,10 @@ class WinUnicodeString(Structure):
@property
def str(self):
"""The python string of the LSA_UNICODE_STRING object
:type: :class:`unicode`
"""
if getattr(self, "_target", None) is not None: #remote ctypes :D -> TRICKS OF THE YEAR
raw_data = self._target.read_memory(self.Buffer, self.Length)
return raw_data.decode("utf16")
+2 -1
View File
@@ -15,6 +15,7 @@ from windows.winobject import exception
from windows.winobject import service
from windows.winobject import volume
from windows.winobject import wmi
from windows.winobject import kernobj
from windows.generated_def.winstructs import *
@@ -97,7 +98,7 @@ class System(object):
def wmi(self):
r"""An object to perform wmi request to "root\\cimv2"
:type: :class:`wmi.WmiRequester`"""
:type: :class:`windows.winobject.wmi.WmiRequester`"""
return wmi.WmiRequester()
#TODO: use GetComputerNameExA ? and recover other names ?
+3 -4
View File
@@ -11,10 +11,9 @@ from windows.generated_def.interfaces import IWbemLocator, IWbemServices, IEnumW
class WmiRequester(object):
"""Perform WMI request"""
r"""An object to perform wmi request to ``root\cimv2``"""
INSTANCE = None
def __new__(cls):
if cls.INSTANCE is not None:
return cls.INSTANCE
@@ -32,9 +31,9 @@ class WmiRequester(object):
self.service = service
def select(self, frm, attrs="*"):
"""Select `attrs` from ``frm``
"""Select ``attrs`` from ``frm``
:rtype: list of dict
:rtype: list of dict
"""
enumerator = IEnumWbemClassObject()
try: