Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple function implementations #227

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
81 changes: 80 additions & 1 deletion speakeasy/winenv/api/kernelmode/ntoskrnl.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import speakeasy.winenv.defs.registry.reg as regdefs
import speakeasy.winenv.defs.windows.windows as windefs
import speakeasy.winenv.defs.nt.ntoskrnl as ntos
import speakeasy.windows.objman as objman
from speakeasy.const import FILE_OPEN, FILE_WRITE, FILE_READ, MEM_WRITE
from speakeasy.errors import ApiEmuError
from speakeasy.winenv.api import api
Expand Down Expand Up @@ -2658,7 +2659,7 @@ def ZwOpenKey(self, emu, argv, ctx={}):

hnd = self.reg_open_key(name, create=False)
if not hnd:
rv = ddk.STATUS_INVALID_HANDLE
return ddk.STATUS_INVALID_HANDLE

if phnd:
self.mem_write(phnd, hnd.to_bytes(self.get_ptr_size(), 'little'))
Expand Down Expand Up @@ -3232,3 +3233,81 @@ def RtlFreeHeap(self, emu, argv, ctx={}):

self.mem_free(lpMem)
return rv

@apihook('ZwTerminateProcess', argc=2)
def ZwTerminateProcess(self, emu, argv, ctx={}):
'''
NTSYSAPI NTSTATUS ZwTerminateProcess(
[in, optional] HANDLE ProcessHandle,
[in] NTSTATUS ExitStatus
);
'''
#Copied from TerminateProcess
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#Copied from TerminateProcess
# Copied from TerminateProcess

hProcess, uExitCode = argv
rv = 0

proc = emu.get_object_from_handle(hProcess)
if not proc:
return rv

emu.kill_process(proc)
rv = ddk.STATUS_SUCCESS

@apihook('ZwOpenProcess', argc=4)
def ZwOpenProcess(self, emu, argv, ctx={}):
'''
NTSYSAPI NTSTATUS ZwOpenProcess(
[out] PHANDLE ProcessHandle,
[in] ACCESS_MASK DesiredAccess,
[in] POBJECT_ATTRIBUTES ObjectAttributes,
[in, optional] PCLIENT_ID ClientId

);
'''
(hnd, desAccess, pObject, cid) = argv
if not cid:
return ddk.STATUS_INVALID_PARAMETER
cid_obj = self.win.CLIENT_ID(emu.get_ptr_size())
cid_obj = emu.mem_cast(cid_obj, cid)
oProc = emu.get_object_from_id(cid_obj.UniqueProcess)
hProc = emu.get_object_handle(oProc)
if hProc:
emu.mem_write(hnd,(hProc).to_bytes(4, "little"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
emu.mem_write(hnd,(hProc).to_bytes(4, "little"))
emu.mem_write(hnd, (hProc).to_bytes(4, "little"))

rv = ddk.STATUS_SUCCESS
else:
emu.mem_write(hnd,(0).to_bytes(4, "little"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
emu.mem_write(hnd,(0).to_bytes(4, "little"))
emu.mem_write(hnd, (0).to_bytes(4, "little"))

rv = ddk.STATUS_INVALID_PARAMETER
return rv

@apihook('ZwDuplicateObject', argc=7)
def ZwDuplicateObject (self, emu, argv, ctx={}):
'''
NTSYSAPI NTSTATUS ZwDuplicateObject(
[in] HANDLE SourceProcessHandle,
[in] HANDLE SourceHandle,
[in, optional] HANDLE TargetProcessHandle,
[out, optional] PHANDLE TargetHandle,
[in] ACCESS_MASK DesiredAccess,
[in] ULONG HandleAttributes,
[in] ULONG Options
);
'''
#Based on DublicateTokenEx
(hsProccessHandle, hsHandle, htProcessHandle,htHandle, mask, attr, opt) = argv
rv = 0

obj = self.get_object_from_handle(hsHandle)

if obj:

new_token = emu.new_object(objman.Token)
hnd_new_token = new_token.get_handle()

if hnd_new_token:
hnd = (htHandle).to_bytes(self.get_ptr_size(), 'little')
self.mem_write(htHandle, hnd)
rv = ddk.STATUS_SUCCESS
else:
rv = ddk.STATUS_INVALID_PARAMETER

return rv
71 changes: 70 additions & 1 deletion speakeasy/winenv/api/usermode/ntdll.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import speakeasy.winenv.defs.nt.ddk as ddk
import speakeasy.winenv.defs.nt.ntoskrnl as ntos
import speakeasy.windows.common as winemu

import speakeasy.winenv.arch as e_arch

class Ntdll(api.ApiHandler):

Expand Down Expand Up @@ -333,4 +333,73 @@ def LdrAccessResource(self, emu, argv, ctx={}):
self.mem_write(Resource, offset.to_bytes(4, 'little'))

return 0

@apihook('wcsstr', argc=2,conv=e_arch.CALL_CONV_CDECL)
def wcsstr(self, emu, argv, ctx={}):
"""
wchar_t *wcsstr(
const wchar_t *str,
const wchar_t *strSearch
);
"""
#Copied from msvcrt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than copying the implementation, could we reuse the one in msvcrt somehow?

hay, needle = argv

if hay:
_hay = self.read_mem_string(hay, 2)
argv[0] = _hay

if needle:
needle = self.read_mem_string(needle, 2)
argv[1] = needle

ret = _hay.find(needle)
if ret != -1:
ret = hay + ret
else:
ret = 0
return ret

@apihook('towlower', argc=1,conv=e_arch.CALL_CONV_CDECL)
def towlower(self, emu, argv, ctx={}):
"""
int tolower ( int c );
"""
#Copied from msvcrt
c, = argv
return c | 0x20

@apihook('tolower', argc=1,conv=e_arch.CALL_CONV_CDECL)
def tolower(self, emu, argv, ctx={}):
"""
int tolower ( int c );
"""
#Copied from msvcrt
c, = argv
return c | 0x20

@apihook('strstr', argc=2, conv=e_arch.CALL_CONV_CDECL)
def strstr(self, emu, argv, ctx={}):
"""
char *strstr(
const char *str,
const char *strSearch
);
"""
#Copied from msvcrt
hay, needle = argv
if hay:
_hay = self.read_mem_string(hay, 1)
argv[0] = _hay

if needle:
needle = self.read_mem_string(needle, 1)
argv[1] = needle

ret = _hay.find(needle)
if ret != -1:
ret = hay + ret
else:
ret = 0
return ret

42 changes: 42 additions & 0 deletions speakeasy/winenv/api/usermode/shell32.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,45 @@ def SHGetFolderPath(self, emu, argv, ctx={}):

emu.write_mem_string(path, pszPath, self.get_char_width(ctx))
return 0


@apihook('ShellExecuteExW', argc=1)
def ShellExecuteExW(self, emu, argv, ctx={}):
'''
BOOL ShellExecuteExW(
[in, out] SHELLEXECUTEINFOW *pExecInfo
);
'''
#Based on ShellExecute
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#Based on ShellExecute
# Based on ShellExecute

pExecInfo, = argv

cw = self.get_char_width(ctx)

fn = ''
param = ''
dn = ''

p_op = int.from_bytes(self.mem_read(pExecInfo + 0xC, 4), "little")
if p_op:
op = self.read_mem_string(p_op, cw)
print(op)
p_fn = int.from_bytes(self.mem_read(pExecInfo + 0x10, 4), "little")
if p_fn:
fn = self.read_mem_string(p_fn, cw)
print(fn)
p_param = int.from_bytes(self.mem_read(pExecInfo + 0x14, 4),"little")
if p_param:
param = self.read_mem_string(p_param, cw)
print(param)
p_dn = int.from_bytes(self.mem_read(pExecInfo + 0x18,4), "little")
if p_dn:
dn = self.read_mem_string(p_dn, cw)
print(dn)
Comment on lines +285 to +297
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these old debugging statements?


if dn and fn:
fn = '%s\\%s' % (dn, fn)

proc = emu.create_process(path=fn, cmdline=param)
self.log_process_event(proc, PROC_CREATE)

return 33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this return value mean? maybe its left over from testing?