Pages

Monday, May 18, 2015

[C/C++] From kernel32!GetLastError to pTEB->LastErrorValue

Code snippet: 
#include <windows.h>
#include <stdio.h>
#include <ntdll.h>

int WINAPI iWinMain() {
#ifdef _WIN64
    PTEB_7 pTEB = (PTEB_7)__readgsqword(0x30);
    LPWSTR captionMsg = L"64-bit Application";
#else
    PTEB_7 pTEB = (PTEB_7)__readfsdword(0x18);
    LPWSTR captionMsg = L"32-bit Application";
#endif

    ULONG_PTR lastError;
    WCHAR mainMsg[MAX_PATH] = {0};

    LoadLibraryW(L"target.dll");

    lastError = GetLastError();

    _snwprintf(
        mainMsg,
        MAX_PATH,
        L"LastError: 0x%p",
        lastError);

    MessageBoxW(
        NULL,
        mainMsg,
        captionMsg,
        MB_ICONINFORMATION);

    return 0;
}
Inside debugger:
........
........
004010A5 PUSH main.00401068                            ; UNICODE "target.dll"
004010AA CALL DWORD PTR DS:[<&KERNEL32.LoadLibraryW>]  ; kernel32.LoadLibraryW
004010B0 CALL DWORD PTR DS:[<&KERNEL32.GetLastError>]  ; kernel32.GetLastError
........
........
GetLastError  MOV EAX,DWORD PTR FS:[18]
751F680C      MOV EAX,DWORD PTR DS:[EAX+34]
751F680F      RET
........
........
Retrieve the LastErrorValue directly from the information stored in the current TEB (Thread Environment Block)
typedef struct _TEB_7
{
 NT_TIB     NtTib;
 PVOID                   EnvironmentPointer;
 CLIENT_ID               Cid;
 PVOID                   ActiveRpcInfo;
 PVOID                   ThreadLocalStoragePointer;
 PPEB_VISTA_7            Peb;
 ULONG                   LastErrorValue;

#include <windows.h>
#include <stdio.h>
#include <ntdll.h>

#define GET_LAST_ERROR_FROM_TEB

int WINAPI iWinMain() {
#ifdef _WIN64
    PTEB_7 pTEB = (PTEB_7)__readgsqword(0x30);
    LPWSTR captionMsg = L"64-bit Application";
#else
    PTEB_7 pTEB = (PTEB_7)__readfsdword(0x18);
    LPWSTR captionMsg = L"32-bit Application";
#endif

    ULONG_PTR lastError;
    WCHAR mainMsg[MAX_PATH] = {0};

    LoadLibraryW(L"target.dll");

#ifdef GET_LAST_ERROR_FROM_TEB
    lastError = pTEB->LastErrorValue;
#else
    lastError = GetLastError();
#endif

    _snwprintf(
        mainMsg,
        MAX_PATH,
        L"LastError: 0x%p",
        lastError);

    MessageBoxW(
        NULL,
        mainMsg,
        captionMsg,
        MB_ICONINFORMATION);

    return 0;
}

Source:
http://www.mediafire.com/download/dobcx2s4v0tm5zv/GetLastError.rar