Jump to content

WMI Registry Monitor


 Share

Recommended Posts

First post =)

I found out how to monitor the registry with RegistryKeyChangeEvent with the help of MSDN and XxXFaNtA's example script, only problem is, this class doesn't support HKEY_CURRENT_USER. I found an article about defining a registry class (here) and I was wondering whether this is possible with AutoIt (to create a class for the HKEY_CURRENT_USER hive).

Example:

;~ Credits must go to XxXFaNtA =)

Global $o_WMI, $o_Sink, $s_Query
$o_Sink = ObjCreate("WbemScripting.SWbemSink")
ObjEvent($o_Sink , "SINK_")

$s_Query = 'Select * FROM RegistryKeyChangeEvent WHERE Hive="HKEY_CURRENT_USER" AND KeyPath="Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"'

$o_WMI = ObjGet('winmgmts:\\' & @ComputerName & '\root\default')

If Not @error Then
    $o_WMI.ExecNotificationQueryAsync($o_Sink, $s_Query, Default, Default, Default)
    ConsoleWrite("Ready and waiting for changes")
EndIf

While 1
    Sleep(100)
WEnd

Func SINK_OnObjectReady($objLatestEvent, $objAsyncContext)
    ConsoleWrite($objLatestEvent.GetObjectText_())
EndFunc   ;==>SINK_OnObjectReady

If you run this, it produces:

C:\Documents and Settings\Dennis\Mijn documenten\AutoIt\Test2.au3 (10) : ==> The requested action with this object has failed.:
$o_WMI.ExecNotificationQueryAsync($o_Sink, $s_Query, Default, Default, Default)
$o_WMI.ExecNotificationQueryAsync($o_Sink, $s_Query, Default, Default, Default)^ ERROR

If all this is just not possible, is there a way to monitor HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall and HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall without WMI in a not too resource-wasting manner?

Regards, Dennis =)

Edited by Denny577
Link to comment
Share on other sites

$strComputer = "."

$objWMIServices = ObjGet( _
    "winmgmts:{impersonationLevel=impersonate}!\\" & _ 
    $strComputer & "\root\default")

$objSink = ObjCreate( _
    "WbemScripting.SWbemSink")
$oMyEvent = ObjEvent($objSink,"SINK")
if IsObj($oMyEvent) Then MsgBox(0,"","OK")
$objWMIServices.ExecNotificationQueryAsync ($objSink, _ 
    "SELECT * FROM RegistryKeyChangeEvent " _
    & "WHERE Hive='HKEY_LOCAL_MACHINE' AND " _
    & "KeyPath='Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall'" )

While(True) 
    Sleep(1000)
Wend 
Func SINK_OnObjectReady($wmiObject, $wmiAsyncContext) 
    MsgBox(0,"", "Received Registry Change Event" _
        & @CRLF & $wmiObject.GetObjectText_())
EndFunc

Edited by wolf9228

صرح السماء كان هنا

 

Link to comment
Share on other sites

I already use the example I posted, only with Hive="HKEY_LOCAL_MACHINE". The HKEY_CURRENT_USER part was the problem. :)

http://msdn.microsoft.com/en-us/library/aa393040(VS.85).aspx

Name of the hive (subtree) that contains the key (or keys) that is changed. For example, HKEY_LOCAL_MACHINE. Changes to the HKEY_CLASSES_ROOT and HKEY_CURRENT_USER hives are not supported by RegistryEvent or classes derived from it, such as RegistryKeyChangeEvent.

صرح السماء كان هنا

 

Link to comment
Share on other sites

HKEY_CURRENT_USER is actually just a mapped location under HKEY_LOCAL_MACHINE\System\ControlSet00X, where the ControlSet00X is whichever it is mapped to. Read the value from HKEY_LOCAL_MACHINE\System\Select\Current to get which control set to look in. It is possible to do what you want, just in a round about way.

Link to comment
Share on other sites

http://msdn.microsoft.com/en-us/library/aa393040(VS.85).aspx

Name of the hive (subtree) that contains the key (or keys) that is changed. For example, HKEY_LOCAL_MACHINE. Changes to the HKEY_CLASSES_ROOT and HKEY_CURRENT_USER hives are not supported by RegistryEvent or classes derived from it, such as RegistryKeyChangeEvent.

:)

I believe I clearly stated the fact that I found out that HKEY_CURRENT_USER wasn't supported, and was asking whether there might be an other way to do the same?

I found out how to monitor the registry with RegistryKeyChangeEvent with the help of MSDN and XxXFaNtA's example script, only problem is, this class doesn't support HKEY_CURRENT_USER.

Ring any bells?

@SkinnyWhiteGuy, Thank you very much, I will try it right now.

EDIT: I just tried, but...

HKEY_LOCAL_MACHINE\System\Select\Current = 1

HKEY_LOCAL_MACHINE\System\ControlSet001 doesn't quite look like HKEY_CURRENT_USER.

I did find that HKEY_LOCAL_MACHINE\System\ControlSet001\HardwareProfiles\Current and HKEY_LOCAL_MACHINE\System\CurrentControlSet\HardwareProfiles\Current both look like HKEY_CURRENT_CONFIG :lmao:

But nothing seems to look like HKEY_CURRENT_USER.

Am I on the right track?

EDIT: I found that HKEY_USERS\S-1-5-21-1935655697-1960408961-1547161642-1004 is HKEY_CURRENT_USER and HKEY_USERS\S-1-5-21-1935655697-1960408961-1547161642-1004_Classes is HKEY_CLASSES_ROOT.

I found this snippet on the Hey, Scripting Guy page:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
           
Set objAccount = objWMIService.Get _
        ("Win32_UserAccount.Name='kenmyer',Domain='atl-ws-01'")
Wscript.Echo objAccount.SID</span>

From which I managed to create this function:

Func _GetSID($s_User = @UserName, $s_Domain = @LogonDomain)
    Local $o_WMI = ObjGet("winmgmts:\\.\root\cimv2")
    If Not IsObj($o_WMI) Then Return SetError(1, 0, -1)
    
    Local $s_SID = $o_WMI.Get("Win32_UserAccount.Name='" & $s_User & "',Domain='" & $s_Domain & "'")
    
    Return $s_SID.SID
EndFuncoÝ÷ Ù*&Èr`%DCSQ!²Úâ(­¹^Â+aEè"²Úò)ì©àxKÞÜ(ºW[y«­¢+ØÌäí!-e}UMILÀäÈìÌäìµÀì}ÑM% ¤µÀìÌäìÀäÈíM½ÑÝÉÀäÈí5¥É½Í½ÐÀäÈí]¥¹½ÝÌÀäÈí
ÕÉɹÑYÉÍ¥½¸ÀäÈíU¹¥¹Íѱ°Ìäì

Problem solved.

@SkinnyWhiteGuy, Thanks again :think:

Regards =)

Edited by Denny577
Link to comment
Share on other sites

#Include <EventLog.au3>
#Include <WinAPI.au3>
#Include <Array.au3>
Const $HKEY_CLASSES_ROOT = 0x80000000
Const $HKEY_CURRENT_USER = 0x80000001
Const $HKEY_LOCAL_MACHINE = 0x80000002
Const $HKEY_USERS = 0x80000003
Const $HKEY_CURRENT_CONFIG = 0x80000005
Const $READ_CONTROL = 0x20000
Const $STANDARD_RIGHTS_READ = ($READ_CONTROL)
Const $KEY_QUERY_VALUE = 0x1
Const $KEY_ENUMERATE_SUB_KEYS = 0x8
Const $KEY_NOTIFY = 0x10
Const $REG_NOTIFY_CHANGE_NAME = 0x1   
Const $REG_NOTIFY_CHANGE_ATTRIBUTES = 0x2
Const $REG_NOTIFY_CHANGE_LAST_SET = 0x4   
Const $REG_NOTIFY_CHANGE_SECURITY = 0x8
Const $KEY_READ = BitOR($STANDARD_RIGHTS_READ, $KEY_QUERY_VALUE, $KEY_ENUMERATE_SUB_KEYS, $KEY_NOTIFY)
Dim $dwFilter = BitOR($REG_NOTIFY_CHANGE_NAME, $REG_NOTIFY_CHANGE_ATTRIBUTES, $REG_NOTIFY_CHANGE_LAST_SET, $REG_NOTIFY_CHANGE_SECURITY)
Global $Func ,$hEvent,$hEventLog

;RegNotifyChangeKeyValue Function
;http://msdn.microsoft.com/en-us/library/ms724892.aspx

;RegOpenKeyEx Function
;http://msdn.microsoft.com/en-us/library/ms724897.aspx



RegistryChange()


While 1
WEnd


Func RegistryChange($STR_KEY = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wbem", _
$REG_NOTIFY_CHANGE = $dwFilter , $bWatchSubtree = True , $ReturnFunc = "myFunc")
$Func = $ReturnFunc 
Local $lpSubKey ,$phkResult , $ulOptions = 0 , $samDesired = $KEY_READ _
,$dwNotifyFilter = $REG_NOTIFY_CHANGE , $fAsynchronous = True
$hEventLog = _EventLog__Open ("", "RegistryChange")
$hEvent = _WinAPI_CreateEvent (0, False, False, "")
_EventLog__Notify ($hEventLog, $hEvent)

$StringSplit = StringSplit($STR_KEY, "\")
$CaseStr = StringUpper($StringSplit[1])
Select
Case $CaseStr = "HKLM" Or $CaseStr = "HKEY_LOCAL_MACHINE"
$Long_KEY = $HKEY_LOCAL_MACHINE 
Case $CaseStr = "HKCU" Or $CaseStr = "HKEY_CURRENT_USER"
$Long_KEY = $HKEY_CURRENT_USER
Case $CaseStr = "HKCR" Or $CaseStr = "HKEY_CLASSES_ROOT"
$Long_KEY = $HKEY_CLASSES_ROOT
Case $CaseStr = "HKU"  Or $CaseStr = "HKEY_USERS"
$Long_KEY = $HKEY_USERS
Case $CaseStr = "HKCC" Or $CaseStr = "HKEY_CURRENT_CONFIG"
$Long_KEY =  $HKEY_CURRENT_CONFIG
EndSelect
$STR_KEY2 = $STR_KEY
Do
$STR_KEY2 = StringTrimLeft($STR_KEY2,1)
Until StringLeft($STR_KEY2 , 1) = "\" or $STR_KEY2 = ""
$lpSubKey = StringTrimLeft($STR_KEY2 , 1)
$Structhar = DllStructCreate("char[" & StringLen($lpSubKey) + 1 & "]")
DllStructSetData($Structhar, 1, $lpSubKey)
$phkResult = DllStructCreate("int")
$DllCall = DllCall("Advapi32.dll","long","RegOpenKeyEx","int",$Long_KEY,"ptr", _
DllStructGetPtr($Structhar),"int",$ulOptions,"long",$samDesired,"ptr",DllStructGetPtr($phkResult))
If @error Then Return 0
$hKey = DllStructGetData($phkResult, 1)
$DllCall = DllCall("Advapi32.dll","long","RegNotifyChangeKeyValue","int",$hKey,"int", _
$bWatchSubtree,"int",$dwNotifyFilter,"int",$hEvent,"int",$fAsynchronous)
If @error Then Return 0
AdlibEnable("ChkeRegistryChange")
Return 1
EndFunc


Func ChkeRegistryChange()
$iResult = _WinAPI_WaitForSingleObject ($hEvent,0)
if $iResult = 0 Then 
AdlibDisable ( )
$aEvent = _EventLog__Read($hEventLog)
Call ($Func,$aEvent)
EndIf
EndFunc


Func myFunc($DATA)
_ArrayDisplay($DATA, "EventLog__Read")
EndFunc

صرح السماء كان هنا

 

Link to comment
Share on other sites

  • 1 year later...

Great, it works. But please do you have an idea how to get more info then just GetObjectText_() from it? For example which process did that registry change. Of course I am talking about malware hunting ;-) But probably this information is just not available this way. Although sysinternals Process Monitor somehow does it...

technet scripting guy - read the last paragraph

so it seems it really is not possible by this method. So I wonder how does the process monitor do it?

Edited by LoWang
Link to comment
Share on other sites

  • 2 weeks later...
  • 8 years later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...