News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Loop trough registry (recursive call)

Started by r.gabor, February 03, 2010, 09:05:55 PM

Previous topic - Next topic

r.gabor

Hi All,

I am new in this forum, and I would like to get help on a small sample project what I am doing to learn masm32

What I would like to accomplish is:

- Open HKLM root registry then loop trough every single subkey and list it.
I am able to do the first hive (root) but I cannot go further. Somehow I need to memorize the key was open previously, so when I call my proc again with args (Previous key + new subkey) I can get a new handle.

This is what I have so far:

;«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
      .486                                     
      .model flat, stdcall                           
      option casemap :none                     
      include c:\masm32\include\windows.inc     
      include c:\masm32\include\masm32.inc       
      include c:\masm32\include\kernel32.inc
      include c:\masm32\include\advapi32.inc
      includelib c:\masm32\lib\masm32.lib       
      includelib c:\masm32\lib\kernel32.lib
      includelib c:\masm32\lib\advapi32.lib
      include c:\masm32\macros\macros.asm
;«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

.data
    szHKLM                  db         "HKEY_LOCAL_MACHINE",0

.data?

    regStart                db         ?
    regSubKeyBuffer         db         256 dup(?)
    szLength                dd         ?

.const

.code

GetSubKey proto :DWORD,:DWORD

start:
    ;Call proc for the first time with a NULL string
    invoke GetSubKey, offset regStart, 0
       
Exit:
   
    invoke ExitProcess, NULL


;#####################################################################################################
GetSubKey proc argSubKey:DWORD, argIndex:DWORD

LOCAL hKey :HANDLE

    ;Open key requested in SubKey argument
    invoke  RegOpenKeyExA, HKEY_LOCAL_MACHINE, argSubKey, 0, KEY_ENUMERATE_SUB_KEYS, addr hKey
    .if eax == ERROR_SUCCESS
        .while TRUE
            mov szLength, 512
            ;Enumerate subkeys in the opened reg handle
            invoke RegEnumKeyEx, hKey, argIndex, offset regSubKeyBuffer, offset szLength, NULL, NULL, NULL, NULL   
            .if eax == ERROR_NO_MORE_ITEMS
                ;No more subkey has been found
                ret
            .else
                print [argSubKey]               ;This should print the key which called the proc
                print offset regSubKeyBuffer    ;This is the retrieved subkey
                print chr$(13,10)
               
                inc argIndex                    ;Increment the index to get the next subkey

                ;This is where I need help
                ;Now I have to use lstrcat to put actual argSubKey and regSubKeyBuffer separated with \
                ;This is to call this proc again with the new value and check subkeys under another opened key
               
                ;invoke GetSubKey, ?????????, 0
            .endif
        .endw
    .else
        ret
    .endif
    ret         
GetSubKey endp
;#####################################################################################################

end start

I am stuck with this for few days now, so that is why I am looking for any help.

Any help, hint will be appreciated.

Thanks,
Gabor

dedndave

you probably need to establish a stack frame and store it there
each recursion will have it's own frame

        push    ebp
        mov     ebp,esp
        sub     esp,4*number_of_dword_parms

then you can access the parms with [ebp-4], [ebp-8], and so on
at the end of the proc....

        leave               ;same as mov esp,ebp - pop ebp

if you like, you can return the key in EAX, ECX, or EDX
ESI, EDI, EBX, and EBP should be preserved

the way you have it now, the proc creates a frame for the local variable
but, for recursion, i would use OPTION PROLOGUE:NONE and OPTION EPILOGUE:NONE
and take control of the stack frame with my own code as shown above
after the end of the proc, OPTION PROLOGUE:PrologueDef and OPTION EPILOGUE:EpilogueDef to set it back to default

Gunner

I don't think I would call your proc recursevly. here is how I would do it.. it is not tested but it will give you an idea


LOCAL ParentKey[50]:BYTE
LOCAL lpcBuffer:DWORD
LOCAL hKey:DWORD
LOCAL hSubKey:DWORD
LOCAL lpcSubKeys:DWORD


invoke RegOpenKeyEx, HKEY_LOCAL_MACHINE, addr TestKey, NULL, KEY_ENUMERATE_SUB_KEYS, addr hKey

xor ebx, ebx
GetNextKey:
    lea     esi, ParentKey
invoke  memfill, esi, 50, NULL

mov     lpcBuffer, 50
; Enumerate each key
invoke  RegEnumKeyEx, hKey, ebx, esi, addr lpcBuffer, NULL, NULL, NULL, NULL
cmp     eax, ERROR_NO_MORE_ITEMS
je EnumDone

; See if current key has subkeys
invoke RegOpenKeyEx, hKey, esi, NULL, KEY_ENUMERATE_SUB_KEYS, addr hSubKey
invoke RegQueryInfoKey, hSubKey, NULL, NULL, NULL, addr lpcSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL
mov eax, lpcSubKeys
test eax, eax
jz NextKey

; We have subkeys so something here
; Enum each one and display em

NextKey:
invoke RegCloseKey, hSubKey
inc     ebx
jmp     GetNextKey

EnumDone:
invoke RegCloseKey, hKey
ret
~Rob (Gunner)
- IE Zone Editor
- Gunners File Type Editor
http://www.gunnerinc.com

Slugsnack

include \masm32\include\masm32rt.inc
include \masm32\include\shlwapi.inc
includelib \masm32\lib\shlwapi.lib

.data?

hkResult            DWORD           ?
szName              BYTE 1024 DUP  (?)
chName              DWORD       ?

.code
Start:

xor ebx, ebx
xor edi, edi
mov esi, HKEY_CLASSES_ROOT

  @@:

mov chName, sizeof szName
  invoke SHEnumKeyEx, esi, edi, addr szName, addr chName
inc edi
push eax

    print addr szName, 13, 10

pop eax
test eax, eax
jz @b

    @@:

    invoke Sleep, 100
    invoke crt__kbhit
test eax, eax
jz @b

  invoke ExitProcess, ebx

end Start


is that what you are trying to do ?

//edit : oh i see what you want to do now..

include \masm32\include\masm32rt.inc
include \masm32\include\advapi32.inc
include \masm32\include\shlwapi.inc
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\shlwapi.lib

enumfunc proto :DWORD

.data?

szName              BYTE 1024 DUP  (?)
chName              DWORD       ?

.code
Start:

xor ebx, ebx

  invoke enumfunc, HKEY_CLASSES_ROOT

    @@:

    invoke Sleep, 100
    invoke crt__kbhit
test eax, eax
jz @b

  invoke ExitProcess, ebx

enumfunc proc uses edi _hkResult:DWORD
LOCAL hkResult:DWORD
LOCAL cSubKeys:DWORD

xor edi, edi

  @@:

mov chName, sizeof szName
  invoke SHEnumKeyEx, _hkResult, edi, addr szName, addr chName
inc edi
push eax

    print addr szName, 13, 10

  invoke RegQueryInfoKey, _hkResult, ebx, ebx, ebx, addr cSubKeys, ebx, ebx, ebx, ebx, ebx, ebx, ebx

  .IF cSubKeys
    invoke RegOpenKeyEx, HKEY_CLASSES_ROOT, addr szName, ebx, KEY_ALL_ACCESS, addr hkResult
    .IF eax
      invoke enumfunc, hkResult
      invoke RegCloseKey, hkResult
    .ENDIF
  .ENDIF

pop eax
test eax, eax
jz @b

ret
enumfunc endp

end Start


that is halfway done. it still needs some work but i really need to sleep.. will finish tomorrow if i get the time

donkey

Wrote a small registry browser a while back, it might help though it is in GoAsm syntax, its quite easy to follow all the same...

http://www.quickersoft.com/donkey/files/RegBrowser.zip
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

r.gabor

Dear All,

Thank you for the quick reply and for all the advise.

I will try to check if I can do this :)

I love MASM but for sure, not easy :)

Thanks again.

dedndave

#6
it gets easier - and then it gets harder - lol

i never thought about trying a recursive approach with the registry - that is an interesting idea

r.gabor

yes , it is :)

What I want to accomplish is:

print every key from a given hive like:

Start is the root of HKLM, so prints would be:

HKEY_LOCAL_MACHINE
HKEY_LOCAL_MACHINE\HARDWARE
HKEY_LOCAL_MACHINE\HARDWARE\ACPI
.......
HKEY_LOCAL_MACHINE\SAM
.......
HKEY_LOCAL_MACHINE\SECURITY

and so on, until the end of HKLM

Why I need this? Actually when I found the solution to recursive list of registry subkeys, I can also evaluate all values in a given subkey.
Then I want to check the length of the key to see if is more than 255 or not. If yes, that mean, hidden from user.

So yes, I just want to scan registry to find "hidden" entries :)

I know that there are some tools available to do that already, but I think, this is also a good way to learn assembler.





r.gabor


r.gabor

Hello donkey,

Thank you for the link.

Yes, I saw your code and it is great. It even show a key which is hidden from normal regedit.

However, manually I can also parse the given key, and I can enumerate all values.

My issue is that let say, what If I just want to dump to a text file every keys subkeys of HKLM. (At this point no matter the values)



I

donkey

Regedit has a command line interface that allows you to export the registry keys:

regedit.exe /e myfile.reg HKEY_LOCAL_MACHINE

You can use CreateProcess to do this.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

redskull

If you are just dumping them to a text file, try the built in program

reg export HKLM c:\out.txt
Strange women, lying in ponds, distributing swords, is no basis for a system of government

r.gabor

Hello redskull,

I think you did not got my point.

I am posting this question to learn. Not to use other already made solutions.

I know how to dump it, but I want to learn how to do it with MASM :)


r.gabor

Hello donkey,

For you I can say the same as in my previous post.

Once again.

My question in this forum was related to MASM ( assembler ) and not about any other application like regedit or so on.

I would like to see comments on MASM. Why? Because to have a small project like that, will help me and anyone else here to learn.

At this point I believe that you do not know either how to do that except using regedit :)

So yes, as this forum is about MASM, I still keep the subject related to assembler even if there are other solution the accomplish the same task  :)