Jump to content

Read reg hive from memory?


Biatu
 Share

Recommended Posts

  • Moderators

Can you give an idea of why you would want to maintain a hive in memory, rather than simply reading from it in situ?

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

Well, mainly for Windows PE purposes. I need to be able to extract from an archive or download a hive, and then search/read keys and values from it. it is to be used for a dependency resolving program. And i need it to be in memory so that the file is not locked by the system, nor can it be written to the disk in cases where there is no physical disk. (ie; a ramdrive with limited space)

Edit: It does not need to be capable of write to the hive, as i would only be importing data into the current system if needed

Current Process Model:

  1.  Map network drive
  2.  Load SOFTWARE/SYSTEM/DEFAULT hives from previously extracted install.wim
  3.  Wait for Failed reg requests from ProcMon
  4.  Check if key/value exists
  5.  Copy Key/Value if it exists

 

Preferred Process Model:

  1. Map Network Drive
  2. Extract Hives from install.wim directly into memory using wimlib.
  3. then do 3 thru 4 as above.
Edited by Biatu

What is what? What is what.

Link to comment
Share on other sites

Link to comment
Share on other sites

Very interesting post !

Here is, I think, a start point :

Func _WinAPI_ORCloseKey($hKey)
    Local $aRet = DllCall("Offreg.dll", "dword", "ORCloseKey", "handle", $hKey)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return 1
EndFunc

Func _WinAPI_ORCloseHive($hHive)
    Local $aRet = DllCall("Offreg.dll", "dword", "ORCloseHive", "handle", $hHive)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return 1
EndFunc

Func _WinAPI_OREnumKey($hKey, $iIndex)
    Local $aRet = DllCall("Offreg.dll", "dword", "OREnumKey", "handle", $hKey, "dword", $iIndex, "wstr", "", "dword*", 256, "ptr", 0, "ptr", 0, 'ptr', 0)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return $aRet[3]
EndFunc

Func _WinAPI_OREnumValue($hKey, $iIndex)
    Local $aRet = DllCall("Offreg.dll", "dword", "OREnumValue", "handle", $hKey, "dword", $iIndex, "wstr", "", "dword*", 16384, "ptr", 0, "ptr", 0, 'ptr', 0)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return $aRet[3]
EndFunc

Func _WinAPI_OROpenHive($sHivePath)
    Local $aRet = DllCall("Offreg.dll", "dword", "OROpenHive", "wstr", $sHivePath, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aRet[0] Then Return SetError(10, $aRet[0], 0)
    Return $aRet[2]
EndFunc

Func _WinAPI_OROpenKey($hHive, $sSubKey)
    Local $aRet = DllCall("Offreg.dll", "dword", "OROpenKey", "handle", $hHive, "wstr", $sSubKey, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aRet[0] Then Return SetError(10, $aRet[0], 0)
    Return $aRet[3]
EndFunc

I did not manage to build the _WinAPI_ORGetValue function. I'm not quite comfortable with that yet.

Link to comment
Share on other sites

 

On 1/14/2017 at 4:40 PM, jguinch said:

Very interesting post !

Here is, I think, a start point :

Func _WinAPI_ORCloseKey($hKey)
    Local $aRet = DllCall("Offreg.dll", "dword", "ORCloseKey", "handle", $hKey)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return 1
EndFunc

Func _WinAPI_ORCloseHive($hHive)
    Local $aRet = DllCall("Offreg.dll", "dword", "ORCloseHive", "handle", $hHive)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return 1
EndFunc

Func _WinAPI_OREnumKey($hKey, $iIndex)
    Local $aRet = DllCall("Offreg.dll", "dword", "OREnumKey", "handle", $hKey, "dword", $iIndex, "wstr", "", "dword*", 256, "ptr", 0, "ptr", 0, 'ptr', 0)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return $aRet[3]
EndFunc

Func _WinAPI_OREnumValue($hKey, $iIndex)
    Local $aRet = DllCall("Offreg.dll", "dword", "OREnumValue", "handle", $hKey, "dword", $iIndex, "wstr", "", "dword*", 16384, "ptr", 0, "ptr", 0, 'ptr', 0)
    If @error Then Return SetError(@error, @extended, '')
    If $aRet[0] Then Return SetError(10, $aRet[0], '')
    Return $aRet[3]
EndFunc

Func _WinAPI_OROpenHive($sHivePath)
    Local $aRet = DllCall("Offreg.dll", "dword", "OROpenHive", "wstr", $sHivePath, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aRet[0] Then Return SetError(10, $aRet[0], 0)
    Return $aRet[2]
EndFunc

Func _WinAPI_OROpenKey($hHive, $sSubKey)
    Local $aRet = DllCall("Offreg.dll", "dword", "OROpenKey", "handle", $hHive, "wstr", $sSubKey, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aRet[0] Then Return SetError(10, $aRet[0], 0)
    Return $aRet[3]
EndFunc

I did not manage to build the _WinAPI_ORGetValue function. I'm not quite comfortable with that yet.

Nice! I tried PMing JFX as it seems he has moved to MSFN, but it looks like you beat him to it lol. Thank you very much. Ill look into ORGetCalue, and see if I can complete these funcs. What is disconcerting about ORGetValue btw?

Thank you!

 

Update:

On the MSDN, i see that you need to call ORGetValue first with pvData being null, then pcbBuffer gets filled with size needed to alloc the return data, then just exec again with a pvData buffer with the size return from the last call.

Edited by Biatu

What is what? What is what.

Link to comment
Share on other sites

I realize a problem with offreg, we need to have the hive on the disk in the first place in order to even open it. -.- Now i remember coming across some WinAPI funcs that allow one to make a virtual file per say, write the data to, then open with OPOpenHive. Another approach is to Create an empty hive, get the pointer to it, and then dump the memory-loaded hive into it before continuing, but that sounds a bit dangerous.

Update:  If Offreg will not suite my application, then there is a pure java implementation of reading the registry that we might be able to port to autoit, but non-the less the offreg APIs in autoit will still be useful to alot of devs, so I will continue looking into the possibility of all methods aforementioned.

Update 2: I also remember coming across a script that used a 3rd party sandbox-like dll that allows virtualization of registry, and/or the filesystem without writing to the disk, and possibly more, but I haven't been able to find it in the past years. If I could get my hands on that again, then we could use that to write the hives into, then process them.

Update 3: Bingo! However might be a bit of an overkill for this project lol :sweating:

Update 4: I might try using a Named Pipe instead, its volatile, in memory, and the DllCall should be able to access it, ill give it a whirl. :huh2:

Edited by Biatu

What is what? What is what.

Link to comment
Share on other sites

Currently working with NamePipes, and I cannot seem to write the file data to the Pipe. I tried the various examples, tried modifying NamedPIpe_Client/Server to read a file and write it to the pipe, it seemed that it would onyl take 4096 bytes so I set the WriteFile Bytes to write to 4096 which suceeds, but cannot get further. Even tried irritating through Hive with WinAPI_ReadFile/WinAPI_WriteFile, and no go

 

This is where im at...it just hangs

#include <WinAPI.au3>
#include <NamedPipes.au3>
#include <WinAPIFiles.au3>
#include <WinAPIDiag.au3>
Global $hPipe, $sPipeName="\\.\pipe\virtual"&Random(0,65535,1)
InitPipe(@ScriptDir&"\SYSTEM")
ClosePipe()

Func ClosePipe()
    _NamedPipes_DisconnectNamedPipe($hPipe)
    _NamedPipes_DisconnectNamedPipe($sPipeName)
EndFunc

Func InitPipe($bData)
    ConsoleWrite("sPipeName: "&$sPipeName&@CRLF)
    ConsoleWrite("sHive: "&$bData&@CRLF)
    Global $BUFFER_SIZE = 1024 ; 4k
    Global $TIMEOUT = 1000
    $hPipe = _NamedPipes_CreateNamedPipe( _
         $sPipeName, _ ; Pipe name
         2, _        ; The pipe is bi-directional
         2, _        ; Overlapped mode is enabled
         0, _        ; No security ACL flags
         0, _        ; Data is written to the pipe as a stream of messages
         0, _        ; Data is read from the pipe as a stream of messages
         0, _        ; Blocking mode is enabled
         1, _        ; Maximum number of instances
         $BUFFER_SIZE, _ ; Output buffer size
         $BUFFER_SIZE, _ ; Input buffer size
         0, _ ; Client time out
         0)          ; Default security attributes
    If $hPipe = -1 Then
        ConsoleWrite("CreatePipeFailed."&@CRLF)
        Exit
    EndIf
    ConsoleWrite("hPipe: "&$hPipe)
    ConsoleWrite(" ("&_WinAPI_GetLastErrorMessage()&")"&@CRLF)

    Global $OVERLAPPED_Struct=DllStructCreate($tagOVERLAPPED)
    $hFile=_WinAPI_CreateFile($sPipeName,2,7,7)
    ConsoleWrite("hPipeFile: "&$hFile)
    ConsoleWrite(" ("&_WinAPI_GetLastErrorMessage()&")"&@CRLF)
    If _WinAPI_GetLastError() Then
        ConsoleWrite("CreateFileFailed"&_WinAPI_GetLastError()&@CRLF)
        ClosePipe()
        Return False
    EndIf

    $hSrc=_WinAPI_CreateFile($bData,2,7,7)
    ConsoleWrite("hHive: "&$hSrc)
    ConsoleWrite(" ("&_WinAPI_GetLastErrorMessage()&")"&@CRLF)
    If _WinAPI_GetLastError() Then
        ConsoleWrite("CreateFileFailed"&_WinAPI_GetLastError()&@CRLF)
        ClosePipe()
        Return False
    EndIf
    $iSrcSize = _WinAPI_GetFileSizeEx($hSrc)
    ConsoleWrite("iHiveSize: "&$iSrcSize&@CRLF&@CRLF)
    _WinAPI_SetFilePointerEx($hFile, $iSrcSize)
    _WinAPI_SetEndOfFile($hFile)
    _WinAPI_FlushFileBuffers($hFile)
    _WinAPI_SetFilePointerEx($hFile,0)
    Local $nBytes
    For $i=0 To $iSrcSize Step $BUFFER_SIZE; Account for last Block
        $tBuffer=DllStructCreate("byte[" & $BUFFER_SIZE & "]")
        ConsoleWrite("iHiveRead: "&$i&"/"&$iSrcSize)
        _WinAPI_SetLastError(0)
        $iRead=_WinAPI_ReadFile($hSrc, DllStructGetPtr($tBuffer), $BUFFER_SIZE, $nBytes)
        ConsoleWrite(" (Read: "&$nBytes&" Return:"&_WinAPI_GetLastErrorMessage()&")"&@CRLF)
        If $iRead=0  then
            ConsoleWrite("Error reading hive block: " & $i & @crlf)
            _WinAPI_CloseHandle($hSrc)
            Return
        EndIf
        _WinAPI_SetLastError(0)
        ConsoleWrite("iPipeWrite: "&$i&"/"&$iSrcSize)
        $iWrite=_WinAPI_WriteFile($hFile, DllStructGetPtr($tBuffer), $BUFFER_SIZE, $nBytes)
        ConsoleWrite(" (Write: "&$nBytes&" Return:"&_WinAPI_GetLastErrorMessage()&")"&@CRLF)
        If $iWrite=0 Then
            ConsoleWrite("Error writing pipe block: " & $i & @crlf)
        EndIf
        If $i=$iSrcSize Then
            _WinAPI_FlushFileBuffers($hPipe)
            ExitLoop
        EndIf
        ;_WinAPI_FlushFileBuffers($hFile)
        _WinAPI_SetFilePointerEx($hSrc, $i)
        _WinAPI_SetFilePointerEx($hFile, $i)
    Next
    Return True
EndFunc

Update: If I change BUFFER_SIZE on the CreateNamedPipe to BUFFER_SIZE*8192, then it works, otherwise it hangs on 1024 offset.

Edited by Biatu

What is what? What is what.

Link to comment
Share on other sites

@Biatu : I don't understand what you explain in #8 about the problem with the offline registry. I understood that you wanted to extract the hive from a WIM image, so you will have access to the file on disk, right?

BTW, here is the full Offline Registry UDF :

 

 

 

 

 

Link to comment
Share on other sites

4 hours ago, jguinch said:

@Biatu : I don't understand what you explain in #8 about the problem with the offline registry. I understood that you wanted to extract the hive from a WIM image, so you will have access to the file on disk, right?

BTW, here is the full Offline Registry UDF :

 

 

 

 

 

In #3 I explain that this will be used in WinPE where there is a chance that there will be no physical disk, or small ramdisk. So it would be preferred that the Hive is not loaded into the system, and never put on the disk. But offreg will still work, just disk writes not preferred.

Edited by Biatu

What is what? What is what.

Link to comment
Share on other sites

11 minutes ago, Biatu said:

In #3 I explain that this will be used in WinPE where there is a chance that there will be no physical disk, or small ramdisk.

OK, I understand now. Do you now exactly where the hive file is stored into the WIM file ? Maybe you can extract it (just this file) to a ramdisk, without mounting the WIM file ?

 

Link to comment
Share on other sites

2 hours ago, jguinch said:

OK, I understand now. Do you now exactly where the hive file is stored into the WIM file ? Maybe you can extract it (just this file) to a ramdisk, without mounting the WIM file ?

 

yes, I can use wimlib to extract it to any location, including a ramdisk. However, ideally this should work without a ramdisk. In the future, I do intend on getting rid of the wrapper exe for wimlib, and using trancexx's subrogation for both offreg, and wimlib.

Update: I'm also working on porting Rejistry to AutoIt..lol not easy.

Edited by Biatu

What is what? What is what.

Link to comment
Share on other sites

  • 2 weeks 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...