Jump to content
Sign in to follow this  
Denny577

WMI Registry Monitor

Recommended Posts

Denny577

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

Share this post


Link to post
Share on other sites
wolf9228

$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

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

 

Share this post


Link to post
Share on other sites
Denny577

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

Share this post


Link to post
Share on other sites
wolf9228

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.


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

 

Share this post


Link to post
Share on other sites
SkinnyWhiteGuy

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.

Share this post


Link to post
Share on other sites
Denny577

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

Share this post


Link to post
Share on other sites
wolf9228

#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


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

 

Share this post


Link to post
Share on other sites
Denny577

That might actually work, but it's constantly checking for changes. I prefer it being event-driven :) (which works now :lmao:)

Regards

Share this post


Link to post
Share on other sites
LoWang

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

Share this post


Link to post
Share on other sites
LoWang

Forums were down recently so I hope now somebody has a clue when it's back again :graduated:

Share this post


Link to post
Share on other sites
LoWang

bump

Share this post


Link to post
Share on other sites
LoWang

too bad :graduated: It seems I am destined to ask questions nobody knows the answer for :-]

  • Like 1

Share this post


Link to post
Share on other sites

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
Sign in to follow this  

×