Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ on:
pull_request:
branches: [master]

permissions: read-all

jobs:
lint:
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions speakeasy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@
{"name": "wkscli", "base_addr": "0x5fc00000", "path": "C:\\Windows\\system32\\wkscli.dll"},
{"name": "iphlpapi", "base_addr": "0x5fd00000", "path": "C:\\Windows\\system32\\iphlpapi.dll"},
{"name": "sfc_os", "base_addr": "0x5fe00000", "path": "C:\\Windows\\system32\\sfc_os.dll"},
{"name": "winmm", "base_addr": "0x5ff00000", "path": "C:\\Windows\\system32\\winmm.dll"},
{
"name": "bcryptprimitives",
"base_addr": "0x60000000",
"path": "C:\\Windows\\system32\\bcryptprimitives.dll",
},
],
},
}
Expand Down
2 changes: 1 addition & 1 deletion speakeasy/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.0.0a1"
__version__ = "2.0.0b1"
2 changes: 2 additions & 0 deletions speakeasy/windows/objman.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ def get_std_handle(self, dev):
STD_OUTPUT_HANDLE = 0xFFFFFFF5
STD_ERROR_HANDLE = 0xFFFFFFF4

dev = dev & 0xFFFFFFFF

for k, v in (
(STD_INPUT_HANDLE, self.stdin),
(STD_OUTPUT_HANDLE, self.stdout),
Expand Down
30 changes: 30 additions & 0 deletions speakeasy/windows/winemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,36 @@ def setup_user_shared_data(self):
# This is a read-only address for KUSER_SHARED_DATA,
# and this is the same address for 32-bit and 64-bit.
self.mem_map(self.page_size, base=0x7FFE0000, tag="emu.struct.KUSER_SHARED_DATA")
self._populate_user_shared_data(0x7FFE0000)

def _populate_user_shared_data(self, base):
import struct
import time

now_100ns = int(time.time() * 10_000_000) + 116444736000000000
tick_ms = int(time.monotonic() * 1000) & 0xFFFFFFFF

data = bytearray(0x400)

# InterruptTime (offset 0x008): KSYSTEM_TIME {LowPart, High1Time, High2Time}
interrupt_100ns = int(time.monotonic() * 10_000_000)
struct.pack_into(
"<IiI", data, 0x008, interrupt_100ns & 0xFFFFFFFF, interrupt_100ns >> 32, interrupt_100ns >> 32
)
# SystemTime (offset 0x014): KSYSTEM_TIME
struct.pack_into("<IiI", data, 0x014, now_100ns & 0xFFFFFFFF, now_100ns >> 32, now_100ns >> 32)
# NtMajorVersion (offset 0x260)
struct.pack_into("<I", data, 0x260, self.config.os_ver.major or 0)
# NtMinorVersion (offset 0x264)
struct.pack_into("<I", data, 0x264, self.config.os_ver.minor or 0)
# NtBuildNumber (offset 0x268)
struct.pack_into("<I", data, 0x268, self.config.os_ver.build or 0)
# TickCount (offset 0x320): KSYSTEM_TIME
struct.pack_into("<IiI", data, 0x320, tick_ms, 0, 0)
# QpcFrequency (offset 0x3B8)
struct.pack_into("<q", data, 0x3B8, 10_000_000)

self.mem_write(base, bytes(data))

def resume(self, addr, count=-1):
"""
Expand Down
29 changes: 29 additions & 0 deletions speakeasy/winenv/api/usermode/bcryptprimitives.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os

from .. import api


class Bcryptprimitives(api.ApiHandler):
"""
Implements exported functions from bcryptprimitives.dll
"""

name = "bcryptprimitives"
apihook = api.ApiHandler.apihook
impdata = api.ApiHandler.impdata

def __init__(self, emu):
super().__init__(emu)
self.funcs = {}
self.data = {}
super().__get_hook_attrs__(self)

@apihook("ProcessPrng", argc=2)
def ProcessPrng(self, emu, argv, ctx={}):
"""
BOOL ProcessPrng(PBYTE pbData, SIZE_T cbData);
"""
pbData, cbData = argv
rand_bytes = os.urandom(cbData)
self.mem_write(pbData, rand_bytes)
return 1
96 changes: 96 additions & 0 deletions speakeasy/winenv/api/usermode/kernel32.py
Original file line number Diff line number Diff line change
Expand Up @@ -1999,6 +1999,11 @@ def Sleep(self, emu, argv, ctx={}):

return

@apihook("SwitchToThread", argc=0)
def SwitchToThread(self, emu, argv, ctx={}):
"""BOOL SwitchToThread();"""
return 0

@apihook("SleepEx", argc=2)
def SleepEx(self, emu, argv, ctx={}):
"""DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable);"""
Expand Down Expand Up @@ -4428,6 +4433,30 @@ def SetErrorMode(self, emu, argv, ctx={}):
"""
return 0

@apihook("GetErrorMode", argc=0)
def GetErrorMode(self, emu, argv, ctx={}):
"""
UINT GetErrorMode();
"""
return 0

@apihook("WerGetFlags", argc=2)
def WerGetFlags(self, emu, argv, ctx={}):
"""
HRESULT WerGetFlags(HANDLE hProcess, DWORD *pdwFlags);
"""
hProcess, pdwFlags = argv
if pdwFlags:
self.mem_write(pdwFlags, (0).to_bytes(4, "little"))
return 0 # S_OK

@apihook("WerSetFlags", argc=1)
def WerSetFlags(self, emu, argv, ctx={}):
"""
HRESULT WerSetFlags(DWORD dwFlags);
"""
return 0 # S_OK

@apihook("InterlockedCompareExchange", argc=3)
def InterlockedCompareExchange(self, emu, argv, ctx={}):
"""
Expand Down Expand Up @@ -6306,6 +6335,17 @@ def AddVectoredExceptionHandler(self, emu, argv, ctx={}):

return Handler

@apihook("AddVectoredContinueHandler", argc=2)
def AddVectoredContinueHandler(self, emu, argv, ctx={}):
"""
PVOID AddVectoredContinueHandler(
ULONG First,
PVECTORED_EXCEPTION_HANDLER Handler
);
"""
First, Handler = argv
return Handler

@apihook("RemoveVectoredExceptionHandler", argc=1)
def RemoveVectoredExceptionHandler(self, emu, argv, ctx={}):
"""
Expand Down Expand Up @@ -6518,6 +6558,62 @@ def GetPhysicallyInstalledSystemMemory(self, emu, argv, ctx={}):
self.mem_write(TotalMemoryInKilobytes, (0x200000).to_bytes(8, "little"))
return 1

@apihook("CreateWaitableTimerExW", argc=4)
def CreateWaitableTimerExW(self, emu, argv, ctx={}):
"""
HANDLE CreateWaitableTimerExW(
LPSECURITY_ATTRIBUTES lpTimerAttributes,
LPCWSTR lpTimerName,
DWORD dwFlags,
DWORD dwDesiredAccess
);
"""
_attrs, name, _flags, _access = argv

timer_name = None
obj = None
if name:
timer_name = self.read_mem_string(name, 2)
argv[1] = timer_name
obj = self.get_object_from_name(timer_name)

if obj:
hnd = obj.get_handle()
emu.set_last_error(windefs.ERROR_ALREADY_EXISTS)
else:
hnd, _evt = emu.create_event(timer_name)
emu.set_last_error(windefs.ERROR_SUCCESS)

return hnd

@apihook("GetProcessAffinityMask", argc=3)
def GetProcessAffinityMask(self, emu, argv, ctx={}):
"""
BOOL GetProcessAffinityMask(
HANDLE hProcess,
PDWORD_PTR lpProcessAffinityMask,
PDWORD_PTR lpSystemAffinityMask
);
"""
hProcess, lpProcessAffinityMask, lpSystemAffinityMask = argv
ptr_size = emu.get_ptr_size()
mask = 0x1
if lpProcessAffinityMask:
self.mem_write(lpProcessAffinityMask, mask.to_bytes(ptr_size, "little"))
if lpSystemAffinityMask:
self.mem_write(lpSystemAffinityMask, mask.to_bytes(ptr_size, "little"))
return 1

@apihook("SetConsoleCtrlHandler", argc=2)
def SetConsoleCtrlHandler(self, emu, argv, ctx={}):
"""
BOOL SetConsoleCtrlHandler(
PHANDLER_ROUTINE HandlerRoutine,
BOOL Add
);
"""
return 1

@apihook("WTSGetActiveConsoleSessionId", argc=0)
def WTSGetActiveConsoleSessionId(self, emu, argv, ctx={}):
return emu.get_current_process().session
Expand Down
42 changes: 42 additions & 0 deletions speakeasy/winenv/api/usermode/ntdll.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,45 @@ def LdrAccessResource(self, emu, argv, ctx={}):
emu.write_ptr(Resource, BaseAddress + offset)

return ddk.STATUS_SUCCESS

@apihook("RtlGetNtVersionNumbers", argc=3)
def RtlGetNtVersionNumbers(self, emu, argv, ctx={}):
"""
void RtlGetNtVersionNumbers(
DWORD *pNtMajorVersion,
DWORD *pNtMinorVersion,
DWORD *pNtBuildNumber
);
"""
pMajor, pMinor, pBuild = argv
if pMajor:
self.mem_write(pMajor, (10).to_bytes(4, "little"))
if pMinor:
self.mem_write(pMinor, (0).to_bytes(4, "little"))
if pBuild:
self.mem_write(pBuild, (0xF0004A61).to_bytes(4, "little"))

@apihook("RtlGetCurrentPeb", argc=0)
def RtlGetCurrentPeb(self, emu, argv, ctx={}):
"""
PPEB RtlGetCurrentPeb();
"""
proc = emu.get_current_process()
if proc and proc.peb:
return proc.peb.address
return 0

@apihook("RtlGetVersion", argc=1)
def RtlGetVersion(self, emu, argv, ctx={}):
"""
NTSTATUS RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation);
"""
(lpVersionInformation,) = argv
# RTL_OSVERSIONINFOW: dwOSVersionInfoSize(4), dwMajorVersion(4),
# dwMinorVersion(4), dwBuildNumber(4), dwPlatformId(4), szCSDVersion(256)
import struct

info = struct.pack("<IIIII", 276, 10, 0, 19041, 2) # VER_PLATFORM_WIN32_NT=2
info += b"\x00" * (276 - len(info))
self.mem_write(lpVersionInformation, info)
return 0 # STATUS_SUCCESS
14 changes: 14 additions & 0 deletions speakeasy/winenv/api/usermode/winmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ def __init__(self, emu):
super().__init__(emu)
super().__get_hook_attrs__(self)

@apihook("timeBeginPeriod", argc=1)
def timeBeginPeriod(self, emu, argv, ctx={}):
"""
MMRESULT timeBeginPeriod(UINT uPeriod);
"""
return 0 # TIMERR_NOERROR

@apihook("timeEndPeriod", argc=1)
def timeEndPeriod(self, emu, argv, ctx={}):
"""
MMRESULT timeEndPeriod(UINT uPeriod);
"""
return 0 # TIMERR_NOERROR

@apihook("timeGetTime", argc=0)
def timeGetTime(self, emu, argv, ctx={}):
"""
Expand Down
Loading