Skip to content

Commit

Permalink
Add more API and fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
HongThatCong committed Mar 24, 2023
1 parent 93ae0c1 commit 528fc6f
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 14 deletions.
2 changes: 1 addition & 1 deletion speakeasy/windows/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
# Blank header used for a 64-bit PE header
EMPTY_PE_64 = DOS_HEADER + b'PE\x00\x00d\x86\x00\x00ABCD\x00\x00\x00\x00\x00\x00\x00\x00' \
b'\xf0\x00\x03\x10\x0b\x02\x08\x00\x04\x00\x00\x00\x00\x00\x00' \
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@' \
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@' \
b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x06\x00' \
b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xb8' \
b'\x01\x00\x00\x00\x00\x00\x00AAAA\x02\x00\x00\x04\x00\x00\x10' \
Expand Down
10 changes: 6 additions & 4 deletions speakeasy/windows/win32.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,15 @@ def add_vectored_exception_handler(self, first, handler):
"""
Add a vectored exception handler that will be executed on an exception
"""
self.veh_handlers.append(handler)
if handler not in self.veh_handlers:
self.veh_handlers.append(handler)

def remove_vectored_exception_handler(self, handler):
"""
Remove a vectored exception handler
"""
self.veh_handlers.remove(handler)
if handler in self.veh_handlers:
self.veh_handlers.remove(handler)

def get_processes(self):
if len(self.processes) <= 1:
Expand Down Expand Up @@ -232,7 +234,7 @@ def load_module(self, path=None, data=None, first_time_setup=True):
pass

self.mem_map(pe.image_size, base=base,
tag='emu.module.%s' % (self.mod_name))
tag='emu.module.%s' % (self.mod_name))

self.modules.append((pe, ranges, emu_path))
self.mem_write(pe.base, pe.mapped_image)
Expand Down Expand Up @@ -392,7 +394,7 @@ def run_module(self, module, all_entrypoints=False, emulate_children=False):
child = self.child_processes.pop(0)

child.pe = self.load_module(data=child.pe_data,
first_time_setup=False)
first_time_setup=False)
self.prepare_module_for_emulation(child.pe, all_entrypoints)

self.command_line = child.cmdline
Expand Down
6 changes: 3 additions & 3 deletions speakeasy/winenv/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def mem_copy(self, dst, src, n):
return self.emu.mem_copy(dst, src, n)

def read_mem_string(self, addr, width, max_chars=0):
string = self.emu.read_mem_string(addr, width=width)
string = self.emu.read_mem_string(addr, width=width, max_chars=max_chars)
return string

def mem_string_len(self, addr, width):
Expand All @@ -165,14 +165,14 @@ def read_ansi_string(self, addr):
ans = ntos.STRING(self.emu.get_ptr_size())
ans = self.mem_cast(ans, addr)

string = self.emu.read_mem_string(ans.Buffer, width=1)
string = self.emu.read_mem_string(ans.Buffer, width=1, max_chars=ans.Length)
return string

def read_unicode_string(self, addr):
us = ntos.UNICODE_STRING(self.emu.get_ptr_size())
us = self.mem_cast(us, addr)

string = self.emu.read_mem_string(us.Buffer, width=2)
string = self.emu.read_mem_string(us.Buffer, width=2, max_chars=us.Length // 2)
return string

def read_wide_string(self, addr, max_chars=0):
Expand Down
6 changes: 3 additions & 3 deletions speakeasy/winenv/api/kernelmode/ntoskrnl.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def get_current_irql(self):

def set_current_irql(self, irql):
return self.emu.set_current_irql(irql)

def win_perms_to_emu_perms(self, win_perms):
"""
Maps Windows permissions to emulator engine permissions
Expand Down Expand Up @@ -600,14 +600,14 @@ def ZwQuerySystemInformation(self, emu, argv, ctx={}):
size = len(out)
self.mem_write(sysinfo, out)
nts = ddk.STATUS_SUCCESS

elif sysclass == ddk.SYSTEM_INFORMATION_CLASS.SystemCodeIntegrityInformation:
if sysinfo and syslen >= 8:
class_len = (8).to_bytes(4, "little")
flags = (1).to_bytes(4, "little")
self.mem_write(sysinfo, class_len + flags)
nts = ddk.STATUS_SUCCESS

elif sysclass == ddk.SYSTEM_INFORMATION_CLASS.SystemProcessInformation:
procs = emu.get_processes()
for proc in procs:
Expand Down
13 changes: 13 additions & 0 deletions speakeasy/winenv/api/usermode/advapi32.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,19 @@ def RegisterServiceCtrlHandler(self, emu, argv, ctx={}):

return self.service_status_handle

@apihook('RegisterServiceCtrlHandlerEx', argc=3)
def RegisterServiceCtrlHandlerEx(self, emu, argv, ctx={}):
'''
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerExA(
LPCSTR lpServiceName,
LPHANDLER_FUNCTION_EX lpHandlerProc,
LPVOID lpContext
);
'''
lpServiceName, lpHandlerProc, lpContext = argv

return self.RegisterServiceCtrlHandler(self, emu, [lpServiceName, lpHandlerProc], ctx)

@apihook('SetServiceStatus', argc=2)
def SetServiceStatus(self, emu, argv, ctx={}):
'''
Expand Down
32 changes: 30 additions & 2 deletions speakeasy/winenv/api/usermode/kernel32.py
Original file line number Diff line number Diff line change
Expand Up @@ -5248,6 +5248,15 @@ def RtlZeroMemory(self, emu, argv, ctx={}):
buf = b'\x00' * length
self.mem_write(dest, buf)

@apihook('RtlMoveMemory', argc=3)
def RtlMoveMemory(self, emu, argv, ctx={}):
"""
void RtlMoveMemory(void* pvDest, const void *pSrc, size_t Length);
"""
dest, source, length = argv
buf = self.mem_read(source, length)
self.mem_write(dest, buf)

@apihook('QueryPerformanceFrequency', argc=1)
def QueryPerformanceFrequency(self, emu, argv, ctx={}):
"""
Expand Down Expand Up @@ -5832,6 +5841,16 @@ def AddVectoredExceptionHandler(self, emu, argv, ctx={}):

return Handler

@apihook('RemoveVectoredExceptionHandler', argc=1)
def RemoveVectoredExceptionHandler(self, emu, argv, ctx={}):
'''
ULONG RemoveVectoredExceptionHandler(
PVOID Handle);
'''
Handler = argv
emu.remove_vectored_exception_handler(Handler)
return 1

@apihook("GetSystemDefaultUILanguage", argc=0)
def GetSystemDefaultUILanguage(self, emu, argv, ctx={}):
'''
Expand Down Expand Up @@ -5942,8 +5961,8 @@ def _lclose(self, emu, argv, ctx={}):
def GetConsoleTitle(self, emu, argv, ctx={}):
'''
DWORD WINAPI GetConsoleTitle(
_Out_ LPTSTR lpConsoleTitle,
_In_  DWORD  nSize
_Out_ LPTSTR lpConsoleTitle,
_In_ DWORD nSize
);
'''
lpConsoleTitle, nSize = argv
Expand Down Expand Up @@ -6036,3 +6055,12 @@ def GetPhysicallyInstalledSystemMemory(self, emu, argv, ctx={}):
@apihook('WTSGetActiveConsoleSessionId', argc=0)
def WTSGetActiveConsoleSessionId(self, emu, argv, ctx={}):
return emu.get_current_process().get_session_id()

@apihook('WaitForSingleObjectEx', argc=3)
def WaitForSingleObjectEx(self, emu, argv, ctx={}):
return 0 # = WAIT_OBJECT_0

@apihook('GetProfileInt', argc=3)
def GetProfileInt(self, emu, argv, ctx={}):
_, _, nDefault = argv
return nDefault
16 changes: 15 additions & 1 deletion speakeasy/winenv/api/usermode/ntdll.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ def RtlGetLastWin32Error(self, emu, argv, ctx={}):

return emu.get_last_error()

@apihook('RtlNtStatusToDosError', argc=1)
def RtlNtStatusToDosError(self, emu, argv, ctx={}):
'''ULONG RtlNtStatusToDosError(NTSTATUS Status);'''
return 0

@apihook('RtlFlushSecureMemoryCache', argc=2)
def RtlFlushSecureMemoryCache(self, emu, argv, ctx={}):
'''DWORD RtlFlushSecureMemoryCache(PVOID arg0, PVOID arg1);'''
Expand Down Expand Up @@ -146,7 +151,7 @@ def LdrGetProcedureAddress(self, emu, argv, ctx={}):
fn = ntos.STRING(emu.get_ptr_size())
fn = self.mem_cast(fn, proc_name)

proc = self.read_mem_string(fn.Buffer, 1)
proc = self.read_mem_string(fn.Buffer, 1, max_chars=fn.Length)
argv[1] = proc

elif ordinal:
Expand Down Expand Up @@ -175,6 +180,15 @@ def RtlZeroMemory(self, emu, argv, ctx={}):
buf = b'\x00' * length
self.mem_write(dest, buf)

@apihook('RtlMoveMemory', argc=3)
def RtlMoveMemory(self, emu, argv, ctx={}):
"""
void RtlMoveMemory(void* pvDest, const void *pSrc, size_t Length);
"""
dest, source, length = argv
buf = self.mem_read(source, length)
self.mem_write(dest, buf)

@apihook('NtSetInformationProcess', argc=4)
def NtSetInformationProcess(self, emu, argv, ctx={}):
"""
Expand Down
20 changes: 20 additions & 0 deletions speakeasy/winenv/api/usermode/sfc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from .. import api

import time

class sfc(api.ApiHandler):
"""
Emulates functions from sfc.dll
"""

name = 'sfc'
apihook = api.ApiHandler.apihook
impdata = api.ApiHandler.impdata

def __init__(self, emu):
super(sfc, self).__init__(emu)
super(sfc, self).__get_hook_attrs__(self)

@apihook('SfcIsFileProtected', argc=2)
def SfcIsFileProtected(self, emu, argv, ctx={}):
return False
63 changes: 63 additions & 0 deletions speakeasy/winenv/api/usermode/shlwapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from .. import api
import speakeasy.winenv.arch as e_arch

MAX_PATH = 260


class Shlwapi(api.ApiHandler):

Expand Down Expand Up @@ -306,3 +308,64 @@ def PathCanonicalize(self, emu, argv, ctx={}):
path = self.read_wide_string(pszPath)
self.write_wide_string(path, pszBuf)
return 1

@apihook('PathRemoveFileSpec', argc=1)
def PathRemoveFileSpec(self, emu, argv, ctx={}):
"""
BOOL PathRemoveFileSpec(LPTSTR pszPath);
"""
pszPath, = argv
cw = self.get_char_width(ctx)
s = self.read_mem_string(pszPath, cw)
idx = s.rfind('\\')
if idx == -1:
return 0

s = s[:idx]
self.write_mem_string(s, pszPath, cw)
return 1

@apihook('PathAddBackslash', argc=1)
def PathAddBackslash(self, emu, argv, ctx={}):
"""
LPTSTR PathAddBackslash(LPTSTR pszPath);
"""
pszPath, = argv
cw = self.get_char_width(ctx)
s = self.read_mem_string(pszPath, cw)
if not s.endswith('\\'):
s += '\\'
if len(s) > MAX_PATH:
return 0

self.write_mem_string(s, pszPath, cw)
return pszPath

@apihook('PathRenameExtension', argc=2)
def PathRenameExtension(self, emu, argv, ctx={}):
"""
BOOL PathRenameExtension(
[in, out] LPSTR pszPath,
[in] LPCSTR pszExt
);
"""
pszPath, pszExt = argv

cw = self.get_char_width(ctx)
path = self.read_mem_string(pszPath, cw)

ext = self.read_mem_string(pszExt, cw)
if not ext.startswith('.'):
return 0

i = path.rfind('.')
if i == -1:
path += ext
else:
path = path[:i] + ext

if len(path) > MAX_PATH:
return 0

self.write_mem_string(path, pszPath, cw)
return 1

0 comments on commit 528fc6f

Please sign in to comment.