Click here to Skip to main content
15,886,072 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
So I have been working on learning the windows low end side of thing and I created some asm to access the peb without using any library's. This is because my project has /NODEFAULTLIB on and no inputs in Visual Studio

So my project is about using the PEB to import thing dynamically without the need of dependency. thought i needed to get the PEB first without the use of a library but thats were my problem comes in.

this is my code.asm file content
ASM
.code

PUBLIC GetPEB

GetPEB PROC
    mov rax, gs:[60h] ; TEB
    mov rax, [rax + 60h] ; PEB
    RET
GetPEB ENDP

END


Now i access this function with
C++
extern "C" PPEB GetPEB();

but it just returns null

after debugging for awhile I found that after my asm code gets the TEB address and the next line is run it shows that RAX is null? witch made no sense because the TEB address was in there.

So if you know what could be coursing the problem let me know

this the current project code
Function.h
C++
<pre>#include <Windows.h>
#include <winternl.h>

extern "C" PPEB GetPEB();

namespace Function
{

	typedef LPVOID(WINAPI* tVirtualAlloc)(
		LPVOID lpAddress,
		SIZE_T dwSize,
		DWORD  flAllocationType,
		DWORD  flProtect
	);
	typedef BOOL(WINAPI* tVirtualProtect)(
		LPVOID lpAddress,
		SIZE_T dwSize,
		DWORD  flNewProtect,
		PDWORD lpflOldProtect
	);
	typedef BOOL(WINAPI* tBeep)(
		DWORD dwFreq,
		DWORD dwDuration
	);

	int _strcmp(const char* str1, const char* str2);
	int wstrcmp(const wchar_t* str1, const wchar_t* str2);
	void* pGetProcAddress(void* moduleHandle, const char* functionName);
	void* pGetModuleHandle(const wchar_t* moduleName);
};


and this is the rest just in case you see if something else would course this error

Function.cpp
ASM
#include "Function.h"

int Function::_strcmp(const char* str1, const char* str2)
{
    while (*str1 && *str2)
    {
        if (*str1 != *str2)
        {
            break;
        }
        str1++;
        str2++;
    }

    return *str1 - *str2;
}

int Function::wstrcmp(const wchar_t* str1, const wchar_t* str2)
{
    while (*str1 && *str2)
    {
        if (*str1 != *str2)
        {
            break;
        }
        str1++;
        str2++;
    }

    return *str1 - *str2;
}

void* Function::pGetProcAddress(void* moduleHandle, const char* functionName)
{
    PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)moduleHandle;
    PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)((char*)(moduleHandle) + dos_header->e_lfanew);

    if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
        return 0;
    }
    if (nt_header->Signature != IMAGE_NT_SIGNATURE) {
        return 0;
    }

    PIMAGE_DATA_DIRECTORY exports = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    if (exports->Size) {
        PIMAGE_EXPORT_DIRECTORY export_dir = (PIMAGE_EXPORT_DIRECTORY)((char*)(moduleHandle) + exports->VirtualAddress);
        DWORD* name_rvas = (DWORD*)((char*)(moduleHandle) + export_dir->AddressOfNames);
        DWORD* func_addrs = (DWORD*)((char*)(moduleHandle) + export_dir->AddressOfFunctions);
        WORD* ordinals = (WORD*)((char*)(moduleHandle) + export_dir->AddressOfNameOrdinals);
        for (DWORD i = 0; i < export_dir->NumberOfNames; i++)
        {
            const char* name = (const char*)((char*)(moduleHandle) + name_rvas[i]);
            if (Function::_strcmp(name, functionName) == 0)
            {
                DWORD ordinal = ordinals[i];
                DWORD func_addr = func_addrs[ordinal];
                return (void*)((char*)moduleHandle + func_addr);
            }
        }
    }

    return 0;
}

void* Function::pGetModuleHandle(const wchar_t* moduleName)
{
    PPEB pebPtr = GetPEB();
    PPEB_LDR_DATA ldr = (PPEB_LDR_DATA)pebPtr->Ldr;
    
    PLIST_ENTRY list_head = &(ldr->InMemoryOrderModuleList);
    PLIST_ENTRY list_entry = list_head->Flink;

    while (list_entry != list_head) {
        LDR_DATA_TABLE_ENTRY* module_entry = CONTAINING_RECORD(list_entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

        if (!Function::wstrcmp(module_entry->FullDllName.Buffer, moduleName)) {
            return module_entry->DllBase;
        }

        list_entry = list_entry->Flink;
    }

    return nullptr;
}


I welcome any help at all with my problem and thanks you for it too

What I have tried:

I have tried making a function return the TEB witch worked but as soon as i try to access the PEB it goes to NULL, I have been searching the internet for sometime looking for an answer but I can't find any reason this should not work. i have also tried with /NODEFAULTLIB off and with default input setting and the same problem happens. I am not new to C++ but this is part of my learning journey.
Posted
Updated 7-May-23 7:21am
v2

As Richard already pointed out, there are quite a few Windows system calls in the rest of the code and it would certainly be possible to get the pointer without assembler, but if you really want to, you can do it with VisualStudio and assembler.

Since rax registers are used this is 64 bit Intel assembler code.

Where and with which parameter the function Function::pGetModuleHandle(txt) is called was not specified, but at least the return value is expected in rax. The second assembler line always returns the value 0, because the access is faulty and rax has the value 0 afterwards. The call should therefore look more like the following:
ASM
;mov  rax, gs:[60h] ; TEB
;mov  rax, [rax + 60h] ; PEB
mov rax, qword ptr gs:[00000060h]
 
Share this answer
 
Comments
WOLF 2018 7-May-23 14:09pm    
Thank you for your answer. But does this not just return the TEB? Because i thought the TEB was at offset gs:[00000060h]. But the peb is 0x60 after the TEB hence why i did mov rax, [rax + 60h]

But Im using Windows headers but I dont call any functions. Because if i did i would have got an linker error because i removed all librarys with /NODEFAULTLIB and removed everything from Input from my linker setting in Visual Studio
merano99 7-May-23 17:32pm    
Your function works with my suggestion. Have you tested it? You can get the TEB with gs:[00000030h].
WOLF 2018 7-May-23 17:36pm    
Yes your suggestion worked perfectly and thanks for clearing that up about the access fault. I guess im still learning. Tho thanks for letting me know that the TEB is at 30h i always thought from things i read it was 60h
 
Share this answer
 
Comments
WOLF 2018 7-May-23 3:53am    
Because I don't have librarys, so I don't have access to api to get the NtQueryInformationProcess
Richard MacCutchan 7-May-23 3:55am    
Then install Visual Studio 2022 Community Edition, or the Windows SDK, which is free, and you get everything.
WOLF 2018 7-May-23 3:57am    
Well as stated in the question my plain was to have no dependency
Richard MacCutchan 7-May-23 3:58am    
Well you will probably be on your own then, as most people use the libraries provided by Microsoft.
Richard MacCutchan 7-May-23 3:59am    
And I notice your code uses plenty of Windows headers and library calls, so how exactly does this work with out the libraries?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900