Search code examples
windowsassemblyparametersstackmasm

How to set a value in the Windows registry in assembly language?


Ok. So I have this program that attempts to create a value in the Windows registry. Unfortunately, nothing happens. I have been trying to figure out if any of the parameters are wrong. Here is the code:

 includelib \Masm64\Lib\Kernel32.lib
 includelib \Masm64\Lib\Advapi32.lib
 extern RegOpenKeyExA : proc
 extern RegSetValueExA : proc
 extern ExitProcess : proc

 dseg       segment     para 'DATA'
 vlnm       db          'Startup', 0
 sbky       db          'Software\Microsoft\Windows\CurrentVersion\Run', 0
 phkr       dd          0
 path       db          'C:\Users\School\AppData\Roaming\Startups.exe', 0
 dseg       ends

 cseg       segment     para 'CODE'
 start      proc
            lea         rdx, [phkr]
            push        rdx
            sub         rsp, 28h
            mov         r9d, 2
            xor         r8d, r8d
            lea         rdx, [sbky]
            mov         ecx, 80000001h
            call        RegOpenKeyExA

            add         rsp, 28h
            push        45
            lea         rbx, [path]
            push        rbx
            sub         rsp, 28h
            mov         r9d, 1
            xor         r8d, r8d
            lea         rdx, [vlnm]
            mov         ecx, phkr
            call        RegSetValueExA

            call        ExitProcess
start       endp
cseg        ends
            end

Any suggestions?


Solution

  • Allow me to answer my own question. The problem does not truly concern incorrect parameters, but a mistake that I made allocating stack space. Whereas I was expected to allocate 20h of stack space for rcx, rdx, r8, and r9, and align the return address on a 16-byte boundary, I had mistakenly created a template as follows:

    *empty*         (rsp-8)
    param2          (rsp-16)
    param1          (rsp-24)
    *empty*         (rsp-32... causes incorrect parameters and convention!)
    space for r9    (rsp-40)
    space for r8    (rsp-48)
    space for rdx   (rsp-56)
    space for rcx   (rsp-64)
    return address  (rsp-72... not on a 16-byte boundary!)
    

    The correct template would be

    *empty*         (rsp-8)
    param2          (rsp-16)
    param1          (rsp-24)
    space for r9    (rsp-32)
    space for r8    (rsp-40)
    space for rdx   (rsp-48)
    space for rcx   (rsp-56)
    return address  (rsp-64)
    

    I had unintentionally allocated an extra 8 bytes between the stack parameters and register parameters, before the RegSetValueEx call, thus supplying an incorrect parameter. Here is the correct code:

    includelib \Masm64\Lib\Kernel32.lib
    includelib \Masm64\Lib\Advapi32.lib
    extern RegOpenKeyExA : proc
    extern RegSetValueExA : proc
    extern ExitProcess : proc
    
    dseg        segment     para 'DATA'
    vlnm        db          'Startup', 0
    sbky        db          'Software\Microsoft\Windows\CurrentVersion\Run', 0
    phkr        dd          0
    path        db          'C:\Users\Games\AppData\Roaming\Startups.exe', 0
    dseg        ends
    
    cseg        segment     para 'CODE'
    start       proc
                lea         rdx, [phky]
                push        rdx
                sub         rsp, 20h
                mov         r9d, 2
                xor         r8d, r8d
                lea         rdx, [sbky]
                mov         ecx, 80000001h
                call        RegOpenKeyExA
    
                add         rsp, 20h
                push        44
                lea         rbx, [path]
                push        rbx
                sub         rsp, 20h
                mov         r9d, 1
                xor         r8, r8
                lea         rdx, [vlnm]
                mov         ecx, phkr
                call        RegSetValueExA
    
    fini:       call        ExitProcess
    start       endp
    cseg        ends
                end
    

    Cheers!