> For the complete documentation index, see [llms.txt](https://open-advanced-windows-exploitati.gitbook.io/open-advanced-windows-exploitation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://open-advanced-windows-exploitati.gitbook.io/open-advanced-windows-exploitation/custom-shellcode/writing-shellcode/getlasterror.md).

# GetLastError

Sometimes when we are calling Win32 APIs from shellcode we need to understand why the function has not carried out the tasks we expected. The Win32 APIs have a really useful function called `GetLastError`. We can make this one of the first functions we resolve and use it later in subsequent assembly code.

Resolving the function is the same as any other:

{% code overflow="wrap" lineNumbers="true" %}

```nasm
call_getprocaddress_getlasterror:
    mov [rbp-0x28], rbx             ; [RBP-0x28] = Kernel32 base address
    mov rcx, [rbp-0x28]             ; RCX = hModule = Kernel32 base address
    mov rax, 0x726f7272             ;
    push rax                        ;
    mov rax, 0x457473614c746547     ;
    push rax                        ;
    mov rdx, rsp                    ; RDX = lpProcName = GetLastError  
    sub rsp, 0x2c                   ; Allocate stack space for the function call 
                                    ; (+ alignment)
    call [rbp-0x18]                 ; CALL GetProcAddress
    add rsp, 0x2c                   ; Clean up allocated space
    add rsp, 0x10                   ; Clean up GetLastError on stack
    mov [rbp-0x8], rax              ; [RBP-0x8] = *GetLastError
```

{% endcode %}

Now, if we are not seeing the results we expect from Win32 APIs, we can call `GetLastError` and the error code will be in `rax` after the call:

{% code overflow="wrap" lineNumbers="true" %}

```nasm
sub rsp, 0x2c                   ; Allocate stack space for the function call (+         
                                ; alignment)
call [rbp-0x8]                  ; Call GetLastError
int3                            ; Break to examine error in rax
```

{% endcode %}

Once your shellcode is working as intended you can remove the `GetLastError` code.

## Example

The following example uses a the `WinHttp` APIs to download some malicious shellcode, with the intention of injectiing it in to memory (this could be a basic stager):

<figure><img src="/files/IaHQHUZg6nRjpiSx7p33" alt=""><figcaption><p>Using GetLastError</p></figcaption></figure>

The flow on the left shows the order in which the calls should be made. The flow on the right shows what happens if we forget to call `WinHttpReceiveResponse`.

`WinHttpQueryDataAvailable` will return `0` instead of the number of bytes in the shellcode. This is because it has failed. If we find this during debugging our mistake might not be that obvious.

During the different calls the `HINTERNET` handle is used to track the request. If we use the `GetLastError` call imediately after our mistake we can get an insight in to why it failed.

The `12019` error is the `ERROR_INTERNET_INCORRECT_HANDLE_STATE`, which should help us diagnose the problem.
