Last active
August 29, 2015 14:27
-
-
Save juntalis/7b23959196cc756e62e7 to your computer and use it in GitHub Desktop.
Using 7 bytes of preassembled shellcode, determine if the current 32-bit process is running in the WOW64 subsystem (as is the case when running 32-bit Python on 64-bit Windows) or if it's running from a 32-bit Windows OS.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
""" | |
iswow64.py | |
Using 7 bytes of preassembled shellcode, determine if the current | |
32-bit process is running in the WOW64 subsystem (as is the case | |
when running 32-bit Python on 64-bit Windows) or if it's running | |
from a 32-bit Windows OS. | |
This program is free software. It comes without any warranty, to | |
the extent permitted by applicable law. You can redistribute it | |
and/or modify it under the terms of the Do What The Fuck You Want | |
To Public License, Version 2, as published by Sam Hocevar. See | |
http://sam.zoy.org/wtfpl/COPYING for more details. | |
""" | |
from _ctypes import _SimpleCData as _SimpleCData | |
from ctypes.wintypes import LPVOID, DWORD, INT, BOOLEAN, HANDLE | |
from ctypes import WinDLL, POINTER, WinError, c_size_t as SIZE_T, sizeof as SIZEOF, \ | |
cast as CAST, byref as BYREF, create_string_buffer as STRALLOC, \ | |
WINFUNCTYPE as WINAPI, CFUNCTYPE as CDECL | |
# Verify we're working on a 32-bit version of Python | |
assert(SIZEOF(LPVOID) == SIZEOF(DWORD)) | |
# Kernel32 DLL | |
_kernel32 = WinDLL('kernel32.dll') | |
# Custom Types | |
class BOOL(INT): | |
""" Just a 32-bit integer interpreted as a boolean. """ | |
def from_param(self, value): | |
if value is None: | |
return INT(0) | |
elif isinstance(value, _SimpleCData): | |
return value | |
else: | |
return INT(value) | |
def __eq__(self, other): | |
value = self.value | |
if isinstance(other, bool): | |
return value == other | |
elif isinstance(other, _SimpleCData): | |
return value == bool(other.value) | |
else: | |
return value == bool(other) | |
def __hash__(self): | |
return hash(self._as_parameter_) | |
# Typedefs | |
LPCVOID = LPVOID | |
PDWORD = POINTER(DWORD) | |
PSIZE_T = POINTER(SIZE_T) | |
# Constants | |
NULL = LPVOID(0) | |
NULL_PDWORD = CAST(NULL, PDWORD) | |
NULL_PSIZE_T = CAST(NULL, PSIZE_T) | |
## Param values for flAllocationType & dwFreeType | |
MEM_RESERVE = DWORD(0x00002000) | |
MEM_COMMIT = DWORD(0x00001000) | |
MEM_RELEASE = DWORD(0x8000) | |
## Param values for flProtect & flNewProtect | |
PAGE_READWRITE = DWORD(0x04) | |
PAGE_EXECUTE_READWRITE = DWORD(0x40) | |
## Param flags Constants | |
_In = 1 | |
_Out = 2 | |
_InOpt = 3 | |
_InOutOpt = _InOpt | _Out | |
# Win32 API Function Prototypes | |
""" HANDLE WINAPI GetCurrentProcess(void); """ | |
GetCurrentProcess = WINAPI(HANDLE)(('GetCurrentProcess', _kernel32)) | |
hCurrentProcess = GetCurrentProcess() | |
""" LPVOID WINAPI VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) """ | |
VirtualAlloc = WINAPI(LPVOID, LPVOID, SIZE_T, DWORD, DWORD)( | |
_kernel32.VirtualAlloc | |
) | |
""" BOOL VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) """ | |
VirtualFree = WINAPI(BOOL, LPVOID, SIZE_T, DWORD)( | |
_kernel32.VirtualFree | |
) | |
""" BOOL VirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect) """ | |
VirtualProtect = WINAPI(BOOL, LPVOID, SIZE_T, DWORD, PDWORD)( | |
_kernel32.VirtualProtect | |
) | |
""" BOOL WINAPI WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumofBytesWritten) """ | |
WriteProcessMemory = WINAPI(BOOL, HANDLE, LPVOID, LPCVOID, SIZE_T, PSIZE_T)( | |
_kernel32.WriteProcessMemory | |
) | |
""" BOOL WINAPI FlushInstructionCache(HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize) """ | |
FlushInstructionCache = WINAPI(BOOL, HANDLE, LPCVOID, SIZE_T)( | |
_kernel32.FlushInstructionCache | |
) | |
def destroy_cfunc(cfuncproc): | |
""" | |
:param cfuncproc:Stuff | |
:type cfuncproc:ctypes.CFUNCTYPE | |
:return:Success | |
:rtype:bool | |
""" | |
if isinstance(cfuncproc, LPVOID): | |
cptr = cfuncproc | |
csize = cfuncproc._allocsize | |
else: | |
cptr = cfuncproc._cptr | |
csize = cfuncproc._procsize | |
return bool(VirtualFree(cptr, csize, MEM_RELEASE)) | |
def create_cfunc(cfunctype, shellcode): | |
""" | |
:param cfunctype: The function prototype to use for creation. | |
:type cfunctype: ctypes.CFUNCTYPE | |
:param shellcode: List of bytes forming the shellcode | |
:type shellcode: list | |
:return:The callable function in memory. | |
:rtype:ctypes.CFUNCTYPE | |
""" | |
# Grab the size of the shellcode | |
shellcode_size = len(shellcode) | |
# Reserve memory for our shellcode bytes | |
lpAllocated = LPVOID(VirtualAlloc(NULL, shellcode_size, MEM_RESERVE, PAGE_EXECUTE_READWRITE)) | |
if not lpAllocated or (hasattr(lpAllocated, 'value') and lpAllocated.value is None): | |
raise WinError() | |
# Commit our allocation to obtain our allocated memory. | |
lpRes = VirtualAlloc(lpAllocated.value, shellcode_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE) | |
lpAllocated._allocsize = shellcode_size | |
# Alter protection flags on the memory region that will contain our code. | |
# if not VirtualProtect(lpAllocated.value, shellcode_size, PAGE_EXECUTE_READWRITE, NULL_PDWORD): | |
# destroy_cfunc(lpAllocated) | |
# raise WinError() | |
# Assemble our shellcode buffer, then copy it over to our allocated memory. | |
shellcode_buffer = STRALLOC(''.join(map(chr, shellcode)), shellcode_size) | |
WriteProcessMemory(hCurrentProcess, lpAllocated, CAST(shellcode_buffer, LPVOID).value, shellcode_size, NULL_PSIZE_T) | |
# Flush our instruction cache, and apply our prototype, then return the result. | |
FlushInstructionCache(hCurrentProcess, lpAllocated, shellcode_size) | |
cfuncproc = cfunctype(lpAllocated.value) | |
cfuncproc._cptr = lpAllocated | |
cfuncproc._procsize = shellcode_size | |
return cfuncproc | |
IsWow64ShellCode = [ # _IsWow64: | |
0x66, 0x8C, 0xC8, # mov ax, cs | |
0xC1, 0xE8, 0x05, # shr eax, 5 | |
0xC3 # ret | |
] | |
ISWOW64FUNCTYPE = CDECL(BOOLEAN) | |
IsWow64 = create_cfunc(ISWOW64FUNCTYPE, IsWow64ShellCode) | |
if IsWow64(): | |
print 'IsWow64 = True' | |
else: | |
print 'IsWow64 = False' | |
destroy_cfunc(IsWow64) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment