change remote_calc sample to use notepad + add demo of test_code sample + Stos[BWD] in simple_x86 +

This commit is contained in:
Clement Rouault
2017-04-13 11:14:09 +02:00
parent 344678de02
commit 654e6bff71
7 changed files with 266 additions and 170 deletions
+140 -44
View File
@@ -1,10 +1,13 @@
Samples of code
===============
Processes
"""""""""
.. _sample_current_process:
``windows.current_process``
"""""""""""""""""""""""""""
'''''''''''''''''''''''''''
.. literalinclude:: ..\..\samples\current_process.py
@@ -26,34 +29,34 @@ Output::
.. _sample_remote_process:
Remote process : :class:`WinProcess`
""""""""""""""""""""""""""""""""""""
''''''''''''''''''''''''''''''''''''
.. literalinclude:: ..\..\samples\remote_calc.py
.. literalinclude:: ..\..\samples\remote_process.py
Output::
(cmd λ) python.exe remote_calc.py
Creating a calc
Looking for calcs in the processes
They are currently <1> calcs running on the system
Let's play with our calc: <<WinProcess "calc.exe" pid 8052 at 0x27bd5d0>>
Our calc pid is 8052
Our calc is a <32> bits process
Our calc is a SysWow64 process ? <True>
Our calc have threads ! <[<WinThread 8552 owner "calc.exe" at 0x27f7f30>, <WinThread 3464 owner "calc.exe" at 0x27f7f80>, <WinThread 3840 owner "calc.exe" at 0x27fa030>]>
Exploring our calc PEB ! <windows.winobject.RemotePEB object at 0x026DDD00>
Command line is <RemoteWinUnicodeString ""C:\windows\system32\calc.exe"" at 0x26ddee0>
Here are 3 loaded modules: [<RemoteLoadedModule "calc.exe" at 0x26dde40>, <RemoteLoadedModule "ntdll.dll" at 0x26ddf30>, <RemoteLoadedModule "kernel32.dll" at 0x26ddc60>]
Allocating memory in our calc
Allocated memory is at <0x5c90000>
(cmd λ) python.exe remote_process.py
Creating a notepad
Looking for notepads in the processes
They are currently <1> notepads running on the system
Let's play with our notepad: <<WinProcess "notepad.exe" pid 2044 at 0x40ce850>>
Our notepad pid is 2044
Our notepad is a <32> bits process
Our notepad is a SysWow64 process ? <True>
Our notepad have threads ! <[<WinThread 7700 owner "notepad.exe" at 0x41faee0>, <WinThread 7264 owner "notepad.exe" at 0x41faf30>, ...]>
Exploring our notepad PEB ! <windows.winobject.process.RemotePEB object at 0x03F6CDA0>
Command line is <RemoteWinUnicodeString ""C:\windows\system32\notepad.exe"" at 0x3f6cf80>
Here are 3 loaded modules: [<RemoteLoadedModule "notepad.exe" at 0x3f6cf30>, <RemoteLoadedModule "ntdll.dll" at 0x3f6ce40>, <RemoteLoadedModule "kernel32.dll" at 0x3f6cee0>]
Allocating memory in our notepad
Allocated memory is at <0x6f80000>
Writing 'SOME STUFF' in allocated memory
Reading allocated memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
Execution some native code in our calc (write 0x424242 at allocated address + return 0x1337
Execution some native code in our notepad (write 0x424242 at allocated address + return 0x1337)
Executing native code !
Return code = 0x1337L
Reading allocated memory : <'BBBB STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
Executing python code !
Reading allocated memory : <'HELLO FROM CALC\x00\x00\x00\x00\x00'>
Reading allocated memory : <'HELLO FROM notepad\x00\x00'>
Trying to import in remote module 'FAKE_MODULE'
Remote ERROR !
Traceback (most recent call last):
@@ -61,13 +64,13 @@ Output::
File "<string>", line 2, in func
ImportError: No module named FAKE_MODULE
That's all ! killing the calc
That's all ! killing the notepad
.. _sample_peb_exploration:
:class:`PEB` exploration
""""""""""""""""""""""""
''''''''''''''''''''''''
.. literalinclude:: ..\..\samples\peb.py
@@ -97,7 +100,30 @@ Output::
IAT Entry for ntdll!NtCreateFile = <IATEntry "NtCreateFile" ordinal 253> | addr = 0x77541128L
Sections: [<PESection ".text">, <PESection ".rdata">, <PESection ".data">, <PESection ".rsrc">, <PESection ".reloc">]
.. _sample_iat_hook:
IAT hooking
'''''''''''
.. literalinclude:: ..\..\samples\iat_hook.py
Output::
(cmd λ) python iat_hook.py
Asking for <MY_SECRET_KEY>
<in hook> Hook called | hKey = 0x12d687 | lpSubKey = <MY_SECRET_KEY>
<in hook> Secret key asked, returning magic handle 0x12345678
Result = 0x12345678
Asking for <MY_FAIL_KEY>
<in hook> Hook called | hKey = 0x12d687 | lpSubKey = <MY_FAIL_KEY>
<in hook> Asked for a failing key: returning 0x2a
WindowsError(42, 'Windows Error 0x2A')
Asking for <HKEY_CURRENT_USER/Software>
<in hook> Hook called | hKey = 0x80000001L | lpSubKey = <Software>
<in hook> Non-secret key : calling normal function
Result = 0x108
.. _sample_system:
@@ -149,30 +175,7 @@ Output::
Handle is <Handle value=<0x4> in process pid=14340>
Name is <\Device\ConDrv>
.. _sample_iat_hook:
IAT hooking
"""""""""""
.. literalinclude:: ..\..\samples\iat_hook.py
Output::
(cmd λ) python iat_hook.py
Asking for <MY_SECRET_KEY>
<in hook> Hook called | hKey = 0x12d687 | lpSubKey = <MY_SECRET_KEY>
<in hook> Secret key asked, returning magic handle 0x12345678
Result = 0x12345678
Asking for <MY_FAIL_KEY>
<in hook> Hook called | hKey = 0x12d687 | lpSubKey = <MY_FAIL_KEY>
<in hook> Asked for a failing key: returning 0x2a
WindowsError(42, 'Windows Error 0x2A')
Asking for <HKEY_CURRENT_USER/Software>
<in hook> Hook called | hKey = 0x80000001L | lpSubKey = <Software>
<in hook> Non-secret key : calling normal function
Result = 0x108
.. _sample_network_exploration:
@@ -401,6 +404,99 @@ Ouput::
Exiting process
Native code tester
~~~~~~~~~~~~~~~~~~
.. literalinclude:: ..\..\samples\test_code.py
Ouput::
(cmd λ) python.exe .\samples\test_code.py "mov eax, 0x42424242" "eax=0x11223344"
Testing x86 code
Startup context is:
Eip -> 0x3f0000L
Esp -> 0x3bfae4L
Eax -> 0x11223344L
Ebx -> 0x5a6000L
Ecx -> 0x0L
Edx -> 0x0L
Ebp -> 0x0L
Edi -> 0x0L
Esi -> 0x0L
EFlags -> 0x202L
EEflags(0x202L:IF)
==Post-exec context==
Eip -> 0x3f0007L
Esp -> 0x3bfae4L
Eax -> 0x42424242L
Ebx -> 0x5a6000L
Ecx -> 0x0L
Edx -> 0x0L
Ebp -> 0x0L
Edi -> 0x0L
Esi -> 0x0L
EFlags -> 0x202L
EEflags(0x202L:IF)
<Normal terminaison>
==DIFF==
Eip: 0x3f0000 -> 0x3f0007 (+0x7)
Eax: 0x11223344 -> 0x42424242 (+0x31200efe)
(cmd λ) python64 .\samples\test_code.py --x64 "mov r15, 0x11223344; push r14; call r15" "rcx=1; r14=0x4242424243434343"
Testing x64 code
Startup context is:
Rip -> 0x205a1d60000L
Rsp -> 0xe24a88fa88L
Rax -> 0x0L
Rbx -> 0x0L
Rcx -> 0x1L
Rdx -> 0xe24aaf9000L
Rbp -> 0x0L
Rdi -> 0x0L
Rsi -> 0x0L
R8 -> 0x0L
R9 -> 0x0L
R10 -> 0x0L
R11 -> 0x0L
R12 -> 0x0L
R13 -> 0x0L
R14 -> 0x4242424243434343L
R15 -> 0x0L
EFlags -> 0x200L
EEflags(0x200L:IF)
==Post-exec context==
Rip -> 0x11223344L
Rsp -> 0xe24a88fa78L
Rax -> 0x0L
Rbx -> 0x0L
Rcx -> 0x1L
Rdx -> 0xe24aaf9000L
Rbp -> 0x0L
Rdi -> 0x0L
Rsi -> 0x0L
R8 -> 0x0L
R9 -> 0x0L
R10 -> 0x0L
R11 -> 0x0L
R12 -> 0x0L
R13 -> 0x0L
R14 -> 0x4242424243434343L
R15 -> 0x11223344L
EFlags -> 0x10202L
EEflags(0x10202L:IF|RF)
<EXCEPTION_ACCESS_VIOLATION(0xc0000005L)> at <0x11223344>
==DIFF==
Rip: 0x205a1d60000 -> 0x11223344 (-0x20590b3ccbc)
Rsp: 0xe24a88fa88 -> 0xe24a88fa78 (-0x10)
R15: 0x0 -> 0x11223344 (+0x11223344)
EFlags: 0x200 -> 0x10202 (+0x10002)
Negative Stack: dumping:
E24A88FA88 0C 00 D6 A1 05 02 00 00 43 43 43 43 42 42 42 42 ........CCCCBBBB
.. _sample_local_debugger:
+1 -1
View File
@@ -80,7 +80,7 @@ def genkeys(common_name, pfxpassword, outname, **kwargs):
prov = HCRYPTPROV()
winproxy.CryptAcquireContextW(prov, PFW_TMP_KEY_CONTAINER, None, PROV_RSA_FULL, CRYPT_DELETEKEYSET)
parser = argparse.ArgumentParser(prog='PROG')
parser = argparse.ArgumentParser(prog=__file__)
subparsers = parser.add_subparsers(description='valid subcommands',)
cryptparse = subparsers.add_parser('crypt')
-92
View File
@@ -1,92 +0,0 @@
import sys
import os.path
sys.path.append(os.path.abspath(__file__ + "\..\.."))
import windows
import windows.native_exec.simple_x86 as x86
import windows.native_exec.simple_x64 as x64
print("Creating a calc")
calc = windows.utils.create_process(r"C:\windows\system32\calc.exe")
# You don't need to do that in our case, but it's useful to now
print("Looking for calcs in the processes")
all_calcs = [proc for proc in windows.system.processes if proc.name == "calc.exe"]
print("They are currently <{0}> calcs running on the system".format(len(all_calcs)))
print("Let's play with our calc: <{calc}>".format(calc=calc))
print("Our calc pid is {calc.pid}".format(calc=calc))
print("Our calc is a <{calc.bitness}> bits process".format(calc=calc))
print("Our calc is a SysWow64 process ? <{calc.is_wow_64}>".format(calc=calc))
print("Our calc have threads ! <{calc.threads}>".format(calc=calc))
# PEB STUFF
peb = calc.peb
print("Exploring our calc PEB ! {peb}".format(peb=peb))
print("Command line is {peb.commandline}".format(peb=peb))
modules = peb.modules
print("Here are 3 loaded modules: {0}".format(modules[:3]))
# See iat_hook.py for module exploration
# Remote alloc / read / write
print("Allocating memory in our calc")
addr = calc.virtual_alloc(0x1000)
print("Allocated memory is at <{0}>".format(hex(addr)))
print("Writing 'SOME STUFF' in allocated memory")
calc.write_memory(addr, "SOME STUFF")
print("Reading allocated memory : <{0}>".format(repr(calc.read_memory(addr, 20))))
# Remote Execution
print("Execution some native code in our calc (write 0x424242 at allocated address + return 0x1337)")
if calc.bitness == 32:
# Let's generate some native code
code = x86.MultipleInstr()
code += x86.Mov(x86.deref(addr), 0x42424242)
code += x86.Mov("EAX", 0x1337)
code += x86.Ret()
else:
code = x64.MultipleInstr()
code += x64.Mov('RAX', addr)
code += x64.Mov(x64.mem("[RAX]"), 0x42424242)
code += x64.Mov("RAX", 0x1337)
code += x64.Ret()
print("Executing native code !")
t = calc.execute(code.get_code())
t.wait()
print("Return code = {0}".format(hex(t.exit_code)))
print("Reading allocated memory : <{0}>".format(repr(calc.read_memory(addr, 20))))
print("Executing python code !")
# Make 'windows' importable in remote python
calc.execute_python("import sys; sys.path.append(r'{0}')".format(sys.path[-1]))
calc.execute_python("import windows")
# Let's write in the calc 'current_process' memory :)
calc.execute_python("addr = {addr}; windows.current_process.write_memory(addr, 'HELLO FROM CALC')".format(addr=addr))
print("Reading allocated memory : <{0}>".format(repr(calc.read_memory(addr, 20))))
# python_execute is 'safe':
# - it waits for the thread completion
# - it raise an error if remote code raised some
try:
print("Trying to import in remote module 'FAKE_MODULE'")
calc.execute_python("def func():\n import FAKE_MODULE\nfunc()")
except windows.injection.RemotePythonError as e:
print("Remote ERROR !")
print(e)
print("That's all ! killing the calc")
calc.exit()
+92
View File
@@ -0,0 +1,92 @@
import sys
import os.path
sys.path.append(os.path.abspath(__file__ + "\..\.."))
import windows
import windows.native_exec.simple_x86 as x86
import windows.native_exec.simple_x64 as x64
print("Creating a notepad") ## Replaced calc.exe by notepad.exe cause of windows 10.
notepad = windows.utils.create_process(r"C:\windows\system32\notepad.exe")
# You don't need to do that in our case, but it's useful to now
print("Looking for notepads in the processes")
all_notepads = [proc for proc in windows.system.processes if proc.name == "notepad.exe"]
print("They are currently <{0}> notepads running on the system".format(len(all_notepads)))
print("Let's play with our notepad: <{notepad}>".format(notepad=notepad))
print("Our notepad pid is {notepad.pid}".format(notepad=notepad))
print("Our notepad is a <{notepad.bitness}> bits process".format(notepad=notepad))
print("Our notepad is a SysWow64 process ? <{notepad.is_wow_64}>".format(notepad=notepad))
print("Our notepad have threads ! <{notepad.threads}>".format(notepad=notepad))
# PEB STUFF
peb = notepad.peb
print("Exploring our notepad PEB ! {peb}".format(peb=peb))
print("Command line is {peb.commandline}".format(peb=peb))
modules = peb.modules
print("Here are 3 loaded modules: {0}".format(modules[:3]))
# See iat_hook.py for module exploration
# Remote alloc / read / write
print("Allocating memory in our notepad")
addr = notepad.virtual_alloc(0x1000)
print("Allocated memory is at <{0}>".format(hex(addr)))
print("Writing 'SOME STUFF' in allocated memory")
notepad.write_memory(addr, "SOME STUFF")
print("Reading allocated memory : <{0}>".format(repr(notepad.read_memory(addr, 20))))
# Remote Execution
print("Execution some native code in our notepad (write 0x424242 at allocated address + return 0x1337)")
if notepad.bitness == 32:
# Let's generate some native code
code = x86.MultipleInstr()
code += x86.Mov(x86.deref(addr), 0x42424242)
code += x86.Mov("EAX", 0x1337)
code += x86.Ret()
else:
code = x64.MultipleInstr()
code += x64.Mov('RAX', addr)
code += x64.Mov(x64.mem("[RAX]"), 0x42424242)
code += x64.Mov("RAX", 0x1337)
code += x64.Ret()
print("Executing native code !")
t = notepad.execute(code.get_code())
t.wait()
print("Return code = {0}".format(hex(t.exit_code)))
print("Reading allocated memory : <{0}>".format(repr(notepad.read_memory(addr, 20))))
print("Executing python code !")
# Make 'windows' importable in remote python
notepad.execute_python("import sys; sys.path.append(r'{0}')".format(sys.path[-1]))
notepad.execute_python("import windows")
# Let's write in the notepad 'current_process' memory :)
notepad.execute_python("addr = {addr}; windows.current_process.write_memory(addr, 'HELLO FROM notepad')".format(addr=addr))
print("Reading allocated memory : <{0}>".format(repr(notepad.read_memory(addr, 20))))
# python_execute is 'safe':
# - it waits for the thread completion
# - it raise an error if remote code raised some
try:
print("Trying to import in remote module 'FAKE_MODULE'")
notepad.execute_python("def func():\n import FAKE_MODULE\nfunc()")
except windows.injection.RemotePythonError as e:
print("Remote ERROR !")
print(e)
print("That's all ! killing the notepad")
notepad.exit()
+19 -30
View File
@@ -1,4 +1,5 @@
import sys
import argparse
import windows
import windows.test
@@ -7,6 +8,7 @@ import windows.native_exec.simple_x86 as x86
import windows.native_exec.simple_x64 as x64
from windows.generated_def import *
def hexdump(string, start_addr=0):
result = ""
if len(string) == 0:
@@ -112,17 +114,17 @@ class CodeTesteur(dbg.Debugger):
print(hexdump(data, start.sp))
def test_code_x86(raw=False):
def test_code_x86(code, regs=None, raw=False, **kwargs):
print("Testing x86 code")
process = windows.test.pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
if raw:
code = sys.argv[1].replace(" ", "").decode('hex')
code = code.replace(" ", "").decode('hex')
else:
code = x86.assemble(sys.argv[1])
code = x86.assemble(code)
start_register = {}
if len(sys.argv) > 2:
for name_value in sys.argv[2].split(";"):
if regs:
for name_value in regs.split(";"):
name, value = name_value.split("=")
name = name.strip().capitalize()
if name == "Eflags":
@@ -134,19 +136,19 @@ def test_code_x86(raw=False):
x = CodeTesteur(process, code, start_register)
x.loop()
def test_code_x64(raw=False):
def test_code_x64(code, regs=None, raw=False, **kwargs):
print("Testing x64 code")
if windows.current_process.bitness == 32:
raise ValueError("Cannot debug a 64b process from 32b python")
process = windows.test.pop_calc_64(dwCreationFlags=DEBUG_PROCESS)
if raw:
code = sys.argv[1].replace(" ", "").decode('hex')
code = code.replace(" ", "").decode('hex')
else:
code = x64.assemble(sys.argv[1])
code = x64.assemble(code)
start_register = {}
if len(sys.argv) > 2:
for name_value in sys.argv[2].split(";"):
if regs:
for name_value in regs.split(";"):
name, value = name_value.split("=")
name = name.strip().capitalize()
if name == "Eflags":
@@ -158,27 +160,14 @@ def test_code_x64(raw=False):
x = CodeTesteur(process, code, start_register)
x.loop()
import sys
if len(sys.argv) < 2:
print("Need x86 code to exec as first argument")
exit(1)
if sys.argv[1] == "-x64":
sys.argv.remove("-x64")
test_code_x64()
elif sys.argv[1] == "--raw":
sys.argv.remove("--raw")
test_code_x86(raw=True)
elif sys.argv[1] == "--raw64":
sys.argv.remove("--raw64")
test_code_x64(raw=True)
else:
test_code_x86()
parser = argparse.ArgumentParser(prog=__file__)
parser.add_argument('--x64', action='store_const', dest="func", const=test_code_x64, default=test_code_x86, help='Code is x64')
parser.add_argument('--raw', action='store_true', help='argument is raw assembled code (in hex)')
parser.add_argument('code', help='The code to execute')
parser.add_argument('regs', nargs="?", help='The default values of the registers')
res = parser.parse_args()
#test_code(c, "\xcc")
res.func(**res.__dict__)
+10
View File
@@ -779,6 +779,16 @@ class ScasD(Instruction):
encoding = [(RawBits.from_int(8, 0xAF),)]
class StosB(Instruction):
encoding = [(RawBits.from_int(8, 0xAA),)]
class StosW(Instruction):
encoding = [(RawBits.from_int(16, 0x66AB),)]
class StosD(Instruction):
encoding = [(RawBits.from_int(8, 0xAB),)]
class CmpsB(Instruction):
default_32_bits = True
encoding = [(RawBits.from_int(8, 0xa6),)]
+4 -3
View File
@@ -54,9 +54,10 @@ DgMCGgQU70h/rEXLQOberGvgJenggoWU5poEFCfdE1wNK1M38Yp3+qfjEqNIJGCPAgIH0A==
class CryptoTestCase(unittest.TestCase):
def setUp(self):
self.raw_cert = TEST_CERT.decode("base64")
self.raw_pfx = TEST_PFX.decode("base64")
@classmethod
def setUpClass(cls):
cls.raw_cert = TEST_CERT.decode("base64")
cls.raw_pfx = TEST_PFX.decode("base64")
def test_certificate(self):
cert = windows.crypto.CertificateContext.from_buffer(self.raw_cert)