I am trying to get the image base of my process once it is loaded in memory. From my understanding, you can call GetModuleHandle to get the image base. My question is, does the handle returned essentially point to the IMAGE_DOS_HEADER struct such that you could do the following:
PIMAGE_DOS_HEADER DosHeader;
DosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
If this is not correct, what other method could you use?
This is correct, though if you want the module handle of of a dll you need to specify its path. Otherwise you will get the handle to the process exe. You should also check the returned HMODULE first to see that its valid.
An example of how to get the virtual size of the module:
std::size_t GetModuleSize(const char* szModule)
{
HMODULE hModule = GetModuleHandle(szModule);
if(hModule == NULL) return 0;
IMAGE_DOS_HEADER* pDOSHeader = (IMAGE_DOS_HEADER*)hModule;
IMAGE_NT_HEADERS* pNTHeaders =(IMAGE_NT_HEADERS*)((BYTE*)pDOSHeader + pDOSHeader->e_lfanew);
return pNTHeaders->OptionalHeader.SizeOfImage;
}
you'll notice I use IMAGE_DOS_HEADER* and not PIMAGE_DOS_HEADER as I find that more readable and clear.
With Microsoft's compiler and linker, you can use
extern "C" IMAGE_DOS_HEADER __ImageBase;
Related
I am trying to get the image base of my process once it is loaded in memory. From my understanding, you can call GetModuleHandle to get the image base. My question is, does the handle returned essentially point to the IMAGE_DOS_HEADER struct such that you could do the following:
PIMAGE_DOS_HEADER DosHeader;
DosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
If this is not correct, what other method could you use?
This is correct, though if you want the module handle of of a dll you need to specify its path. Otherwise you will get the handle to the process exe. You should also check the returned HMODULE first to see that its valid.
An example of how to get the virtual size of the module:
std::size_t GetModuleSize(const char* szModule)
{
HMODULE hModule = GetModuleHandle(szModule);
if(hModule == NULL) return 0;
IMAGE_DOS_HEADER* pDOSHeader = (IMAGE_DOS_HEADER*)hModule;
IMAGE_NT_HEADERS* pNTHeaders =(IMAGE_NT_HEADERS*)((BYTE*)pDOSHeader + pDOSHeader->e_lfanew);
return pNTHeaders->OptionalHeader.SizeOfImage;
}
you'll notice I use IMAGE_DOS_HEADER* and not PIMAGE_DOS_HEADER as I find that more readable and clear.
With Microsoft's compiler and linker, you can use
extern "C" IMAGE_DOS_HEADER __ImageBase;
Winapi's ReadDirectoryChanges uses FILE_NOTIFY_INFORMATION to present it's results. The struct looks like this:
typedef struct _FILE_NOTIFY_INFORMATION {
DWORD NextEntryOffset;
DWORD Action;
DWORD FileNameLength;
WCHAR FileName[1];
} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION;
If I get this struct filled by winapi, how do I correctly delete the FileName WCHAR*? Do I have to delete it?
None of the examples (not that there are many examples) of the ReadDirectoryChanges mention deleting anything. Microsoft of course does not provide any examples at all.
If you use malloc you need call free after you finish using the object.
For example:
DWORD FileNameLength = 100;
PFILE_NOTIFY_INFORMATION file_notify_info = (PFILE_NOTIFY_INFORMATION)malloc(FIELD_OFFSET(FILE_NOTIFY_INFORMATION, FileName[FileNameLength]));
free(file_notify_info);
Refer to "Why do some structures end with an array of size 1?".
I want to read binary of loader DLL of my DLL. But there is an exe and 2 DLL that I use first one (X DLL) for loadind second one (Y DLL). When I load Y dll from X DLL via exe, GetModuleFileNameA(NULL, szEXEPath, 2048); function give me just exe path. I want to get X DLL path. I could use GetModuleFileNameA("X DLL Name", szEXEPath, 2048); but I dont know name of X DLL.
When I read MSDN help for GetModuleFileName I saw the description that in below about first parameter of function.
A handle to the loaded module whose path is being requested. If this
parameter is NULL, GetModuleFileName retrieves the path of the
executable file of the current process.
I dont want to get path of executable, I just want to determine which DLL load my current DLL. Is there a way to find loader path DLL?
To get the "parent" dll's name, you can create a function as part of the API that is required to be called, that passes in the HMODULE handle of the parent dll.
Creating the get_current_module_handle() function below as inline and wrapping it up into a macro of some sort would simplify the process for the client code.
//... control header
inline HMODULE get_current_module_handle() {/*...*/}
#define PARENT_MODULE get_current_module_handle()
void SetControlParent(HMODULE parent);
//... client code to initialise the "parent"
SetControlParent(PARENT_MODULE);
To get the dll name (in the child), you can use a combination of the GetModuleFileNameEx and GetModuleHandleEx functions. The trick is in the GetModuleHandleEx function that allows for the module handle to be obtain via a pointer to a function (i.e. a function in the dll); particularly the use of the flag GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS.
What follows is a snippet from some code that should do the trick;
HMODULE get_current_module_handle()
{
HMODULE moduleHandle = NULL;
if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)get_current_module_handle, &moduleHandle))
throw std::runtime_error("unable to get the module handle");
return moduleHandle;
}
std::basic_string<TCHAR> get_module_name(HMODULE moduleHandle)
{
std::vector<TCHAR> filename(2048, _T('?')); // allocate some space
DWORD filenameLength = ::GetModuleFileNameEx(::GetCurrentProcess(), moduleHandle, &filename.front(), filename.size());
if (filenameLength && filenameLength < filename.size()) {
return std::basic_string<TCHAR>(&filename.front(), filenameLength);
}
return std::basic_string<TCHAR>(_T("unknown"));
}
//...
std::basic_string<TCHAR> dllname = get_module_name(get_current_module_handle()); // current dll
std::basic_string<TCHAR> parentdllname = get_module_name(parentHModule); // for "parent" dll
Note, a simplified version is reproduced above (based on the 2048 length in the OP). A recursive implementation to account for long file name is also presented (check the edits).
The dllname will be the fully qualified path of the module, hence to get the base file name, functions such as _splitpath. Alternatively, you can use GetModuleBaseName directly in the code above.
std::basic_string<TCHAR> get_module_name(HMODULE moduleHandle)
{
std::vector<TCHAR> filename(MAX_PATH, _T('?')); // MAX_PATH is 260
DWORD filenameLength = ::GetModuleBaseName(::GetCurrentProcess(), moduleHandle, &filename.front(), filename.size());
if (filenameLength && filenameLength < filename.size()) {
return std::basic_string<TCHAR>(&filename.front(), filenameLength);
}
return std::basic_string<TCHAR>(_T("unknown"));
}
You can use the dllpath function to define its own path and pass it as a paramater to the linked one.
I'm using GetProcAddress to gain access to a standard Isapi Filter DLL method - the GetFilterVersion method which takes a pointer to a HTTP_FILTER_VERSION structure.
https://msdn.microsoft.com/en-us/library/ms525822(v=vs.90).aspx
https://msdn.microsoft.com/en-us/library/ms525465(v=vs.90).aspx
I've tested the code against a working Isapi filter that I've written and it works fine. I debug the code against an Isapi filter from a vendor (I don't have access to the source code or anything beyond the dll itself) and I get the exception, "access violation writing location". What could be the issue? (Both Isapi filters work in IIS.)
//Attempted to define function ptr several ways
typedef BOOL(__cdecl * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);
//typedef BOOL( * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);
//typedef BOOL(WINAPI * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);
void arbitraryMethod()
{
HINSTANCE hDLL; // Handle to DLL
TRIRIGAISAPIV lpfnDllFunc2; // Function pointer
DWORD lastError;
BOOL uReturnVal2;
hDLL = LoadLibrary(L"iisWASPlugin_http.dll"); //vendor's dll
//hDLL = LoadLibrary(L"KLTWebIsapi.dll //my dll
if (hDLL != NULL)
{
lpfnDllFunc2 = (TRIRIGAISAPIV)GetProcAddress(hDLL, "GetFilterVersion");
if (!lpfnDllFunc2)
{
lastError = GetLastError();
// handle the error
FreeLibrary(hDLL);
//return 1;
}
else
{
HTTP_FILTER_VERSION pVer = { 6 };
//Call the function via pointer; Works with my dll, fails with vendor's
uReturnVal2 = lpfnDllFunc2(&pVer);
//................ HELP!!!!!!!!!!!!!
}
}
}
One issue that I see is that your function pointer declaration is incorrect.
According to the Microsoft documentation, GetFilterVersion is prototyped as:
BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer);
The WINAPI is a Windows macro that is actually defined as __stdcall, thus you are declaring the function pointer incorrectly when you used __cdecl.
What does WINAPI mean?
Thus, your declaration should be:
typedef BOOL(__stdcall * TRIRIGAISAPIV)(PHTTP_FILTER_VERSION);
It could be that there are actually some additional structure fields filled by the custom filter.
You can try to increase the size of the structure to see if that will work, like for example:
struct HTTP_FILTER_VERSION_EXTRA {
HTTP_FILTER_VERSION v;
char[1024] extra;
};
HTTP_FILTER_VERSION_EXTRA ver;
ver.v.dwServerFilterVersion = 6;
uReturnVal2 = lpfnDllFunc2(&ver.v);
It is sometimes the case with the WinAPI structures that they allow versioning, so adding fields is possible. If the function doesn't then check (or doesn't know) the actual structure version, it might try to use an extended one which might be different than the one supplied - if the size of the supplied struct is then lesser than the structure version the func tries to use, bad things can happen.
Also check if the DLL is 64-bit or 32-bit. You cannot use 64-bit DLL by 32-bit app and vice versa (but I expect that would already fail during the LoadLibrary call).
I have written a hooking dll using the mhook library. In a spezial case the NtOpenFile() fails when a std::wstring is defined as stack var. Defining it on the heap the code is working.
The code is working without problems except when a certain win32 application (lets call it nuisance.exe) tries to open an existing testfile (like c:\temp\anyfile.log) the access fails. Mostly STATUS_INVALID_ACL (0xC0000077) is returned then.
I have reduced my code line by line and finally found that the error happens when in a called function a std::wstring is defined (this example below). The error happens every time an on different OS's
NTSTATUS NtOpenFileApiHook::NtOpenFileHook(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG ShareAccess,
ULONG OpenOptions
)
{
NTSTATUS Status = STATUS_SUCCESS;
// using this function the call will fail
AfterThis_NtOpenFile_WillFail();
// using this function INSTEAD the call will work
AfterThis_NtOpenFile_WillWork();
// calling the real NtOpenFile using a pointer
// nothing was changed hier, the original parameters are passed
Status = RealNtOpenFile(FileHandle, ...);
return Status;
}
int AfterThis_NtOpenFile_WillFail()
{
std::wstring String = L"";
return 0;
}
int AfterThis_NtOpenFile_WillWork()
{
std::wstring * pString = new std::wstring();
pString->assign(L"");
delete pString;
return 0;
}
I have fixed it this way for this call. But I'm afraid that other functions in other circumstainces could fail so I'm looking for the reason and (probably) for a solution.
Nuisance.exe is a C# application with default stacksize callling a win32 dll about which I know nothing.
If Nuisance.exe was a C++ application, I would imagine that it calls NtOpenFile in a way similar to this, allocating one of pointer parameters on overwritten stack:
POBJECT_ATTRIBUTES MakeObjectAttributes()
{
POBJECT_ATTRIBUTES oa = {...};
return &oa; // Pointer to stack variable - UB
}
...
NtOpenFile(..., MakeObjectAttributes(), ...)
STATUS_INVALID_ACL (0xC0000077) error might suggest that SecurityDescriptor within OBJECT_ATTRIBUTES is allocated this way.
Then it matters how much stack is used by AfterThis_NtOpenFile_WillFail, and it is more than AfterThis_NtOpenFile_WillWork, since std::wstring would be larger than just a couple of pointers due to small string optimization.
If the call chain is always the same, the corruption may be deterministic.
I don't know if code equivalent of returning address of temporary is possible in C#. But the DLL may be in C/C++ or similar language that allows dandling pointers.
To prove/disprove the role of stack, try to allocate other data on stack that has std::wstring size. More precise proof could be checking passed pointer to see if they point to stack area that is about to be overwritten.