I have a function that iterates through modules and compares module size to main module and module address != main module address then its assuming that its shadow module address but its not correct way to do it I guess because When I uninject my dll and try to inject and retrieve shadow module address again this function fails cannot find shadow module because I think shadow module size changes.I tried to log main module size its same.
[2023-01-22 13:56:32] ----------------- MFX.dll injected in to the League process -----------------
[2023-01-22 13:56:32] MinHook Initalized!...
[2023-01-22 13:56:32] WndProc Hook...
[2023-01-22 13:56:32] MAIN MODULE SIZE
[2023-01-22 13:56:32] 52838400[2023-01-22 13:56:32]
[2023-01-22 14:20:39] ----------------- MFX.dll injected in to the League process -----------------
This is the function I'm using for retrieve shadow module address.
bool MEM::GetShadowModule(std::uintptr_t& base_address)
{
/* The `shadow module` has the same size as the `league` module, but has a different base */
/* Get base address of `League of Legends.exe` */
/* Check if `League of Legends.exe` is loaded */
if (!LeagueBase)
return false;
/* Get Module information */
MODULEINFO module_info = { 0 };
if (!GetModuleInformation(GetCurrentProcess(), (HMODULE)LeagueBase, &module_info, sizeof(MODULEINFO)))
return false;
/* Get module size */
std::uintptr_t module_size = (std::uintptr_t)module_info.SizeOfImage;
MEMORY_BASIC_INFORMATION memory_info = { 0 };
/* Start at end of league base */
std::uintptr_t current_address = LeagueBase + module_size;
/* Loop until we find the shadow module */
while (VirtualQuery((LPCVOID)current_address, &memory_info, sizeof(MEMORY_BASIC_INFORMATION32)))
{
/* Check if the size is the same as the league module */
if (memory_info.RegionSize == module_size && memory_info.BaseAddress != (LPVOID)LeagueBase)
{
/*We found shadow module base address Set the base address*/
base_address = current_address;
return true;
}
/* Move to the next region */
current_address += memory_info.RegionSize;
}
return false;
}
I'm just making some memory allocations/memcpy like that in my DLL.I suspect these are changing shadow module size & sinking my function ?
auto GateWay = VirtualAlloc(NULL, ByteSize + 5, MEM_RESERVE | MEM_COMMIT, //Create a Gateway
PAGE_EXECUTE_READWRITE);
memcpy(GateWay, (PVOID)HookAddress, ByteSize); // Copy Original Bytes to GateWay
I'm looking for a better way to find shadow module address rather than comparing its size.If it's a duplicate question then I'm sorry.I couldn't find any similiar question regarding shadow module.
Related
Our program has a piece of code that calculates the list of computers on our local network. It uses the Windows Networking API (WNetOpenEnum/WNetEnumResource) to unwind the network. For many years, the resulting list was identical to the one that can be seen in Windows Explorer under the "Network" entry. However, recently we have noticed that the same code returns an empty list. During debugging I found that WNetOpenEnum returns error 1231 (ERROR_NETWORK_UNREACHABLE) when it is called for the "Microsoft Windows Network" under the root node.
I have to mention, though I'm pretty sure it has nothing to do with the matter, that the network unwinding is done multithreaded, to avoid possible delays in the main GUI thread. Each time a node of type RESOURCEUSAGE_CONTAINER is encountered, a new worker thread is launched. The thread function calls the following procedure:
DWORD WINAPI EnumNetwork(NETRESOURCE_M* lpNR)
{
const int BUF_SIZE = 16384; // 16K is a good size.
HANDLE hEnum;
DWORD Result;
// Call the WNetOpenEnum function to begin the enumeration.
Result = ::WNetOpenEnum(RESOURCE_GLOBALNET, // all network
RESOURCETYPE_ANY, // all resource types
0, // enumerate all
(LPNETRESOURCE)lpNR,// parent resource
&hEnum); // enumeration handle
if (Result != NO_ERROR) // -> for "Microsoft Windows Network" Result = 1231
return Result;
std::vector<std::wstring> SrvList;
// Allocate buffer for enumeration.
LPNETRESOURCE lpEnumNR = (LPNETRESOURCE)new char[BUF_SIZE];
if (lpEnumNR == 0)
Result = ERROR_OUTOFMEMORY;
else
{
while (1)
{
::ZeroMemory(lpEnumNR, BUF_SIZE); // Initialize the buffer.
DWORD NumEntries = -1; // Enumerate all entries.
DWORD BufSize = BUF_SIZE;
// Call WNetEnumResource to continue the enumeration.
Result = ::WNetEnumResource(hEnum, // enumeration handle
&NumEntries,// number of entries to enumerate
lpEnumNR, // array of resources to return
&BufSize); // buffer size
if (Result == NO_ERROR)
{
// If the call succeeds, loop through the array.
for (unsigned i = 0; i < NumEntries; ++i)
{
if (lpEnumNR[i].dwDisplayType == RESOURCEDISPLAYTYPE_SERVER)
{
// Collect servers.
LPCWSTR SrvName = lpEnumNR[i].lpRemoteName;
if (PathHelpers::IsFullPath(SrvName))
SrvList.push_back(SrvName);
}
else if ((lpEnumNR[i].dwUsage & RESOURCEUSAGE_CONTAINER) &&
lpEnumNR[i].lpRemoteName != 0)
{
TCHAR PathBuf[1024] = {0};
if (lpNR && lpNR->Path)
{
_tcscpy(PathBuf, lpNR->Path);
::PathAddBackslash(PathBuf);
}
_tcscat(PathBuf, lpEnumNR[i].lpRemoteName);
if (RegisterServer(PathBuf))
{
// Start new thread for recursive enumeration.
NETRESOURCE_M* lpChildNR = DeepCopyNR(&lpEnumNR[i], PathBuf);
ExploreNetwork(lpChildNR); // -> this starts a worker thread
}
else
{
GetLogger().LogMessage(
_T("Cycles found while unwinding network: %s"), PathBuf);
}
}
}
}
else
{
if (Result == ERROR_NO_MORE_ITEMS)
Result = NO_ERROR;
break;
}
} // end while
delete [] (char*)lpEnumNR;
} // end if
::WNetCloseEnum(hEnum);
if (!SrvList.empty())
NotifyServerAdded(SrvList);
return Result;
}
where NETRESOURCE_M is the structure
struct NETRESOURCE_M
{
NETRESOURCE NR;
LPTSTR Path;
};
Trying to figure out what could have caused such a sudden change in behavior, I found in Google that a few years ago Microsoft disabled the SMB1 protocol, which could affect Network Discovery. However, I can't believe they could have damaged their own API without saying a word in the documentation.
EDIT: At the same time, Windows Explorer has a bunch of computers under its "Network" node. In the network settings, the network type is "Domain", and the network discovery is ON. Services "Function Discovery Provider Host" and "Function Discovery Resources Publication" are running. Windows OS build is 19042.685.
Edit 2: The Sysinternals' "ShareEnum" tool also fails with the error: "No domains or workgroups where found on your network". Because of this, and also because some time ago our company moved all of its computers to a different network, I got the feeling that the problem is in the network configuration. Such as though the network is declared as "Domain", the computers were not enrolled to this domain. I do not understand much in that, but something like this.
I'm trying to create a mod loader for an 18 year old game to help me get better at c++. Right now I'm just trying to inject a dll into the same process of the mod loader. The sample dll just prints some text to the command window but doesn't. I think that the code that I have loading the entry point of the dll is not working because everything works up until I call the entry point function of my sample dll within my ModLoader.exe, and Visual Studio just throws an Access Violation. I poked through the memory viewer in debug mode within visual studio to try and see where my ModLoader program thinks the dll entry point is located within the dll but the address just points to a bunch of zeros. I recently learned the PE file format and tried to understand all the code that I wrote when I was following a tutorial on Youtube on how to do this, so forgive me for my inexperience I'm just trying to learn. The other code that I do not show is me locating and finding the target process, reading the dll binary, getting the headers from the dll, me allocating space on the target process for the dll, and finally me writing all of the section header data into the target process. I can provide any other code that y'all would like to see!
Injector.h
using ModLoader_LoadLibrary = HINSTANCE(WINAPI*)(const char* filename);
using ModLoader_GetProcAddress = UINT_PTR(WINAPI*)(HINSTANCE module, const char* procName);
using ModLoader_DllEntry = BOOL(WINAPI*)(HINSTANCE dll, DWORD reason, LPVOID reserved);
struct ModLoader_ManualMapping_Data
{
ModLoader_LoadLibrary ML_LoadLibrary; //Function pointer to the windows load library function
ModLoader_GetProcAddress ML_ProcAddress; //Function pointer to a function to be called
HINSTANCE ML_Module; //dll instance
};
Injector.cpp : Shellcode function that'll run alongside the target executable
void __stdcall Shellcode(ModLoader_ManualMapping_Data* data)
{
if (!data)
return;
BYTE* pData = reinterpret_cast<BYTE*>(data);
IMAGE_OPTIONAL_HEADER& optHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pData + reinterpret_cast<IMAGE_DOS_HEADER*>(pData)->e_lfanew)->OptionalHeader;
auto loadLibrary = data->ML_LoadLibrary;
auto procAddress = data->ML_ProcAddress;
auto dllLoad = reinterpret_cast<ModLoader_DllEntry>(pData + optHeader.AddressOfEntryPoint); //Loads entry point func from dll
BYTE* locationDelta = pData - optHeader.ImageBase; //pData = the new address | ImageBase = preferred address -> Get the difference between the two to add to every address in the relocation table
if (locationDelta) //THIS DOES NOT GET RAN
{
//Adds the delta value to all addresses within the base relocation table
}
//Import table
if (optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
{
IMAGE_IMPORT_DESCRIPTOR* imgImport = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(pData
+ optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (imgImport->Name) //THIS DOES NOT GET RAN B\C imgImport is all zeros.
{
//Loops through import table
}
}
if (optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) //THIS DOES NOT GET RAN
{
//Calls the callback functions within dll
}
dllLoad(reinterpret_cast<HINSTANCE>(pData), DLL_PROCESS_ATTACH, nullptr); //PROBLEM: ACCESS VIOLATION
}
Injector.cpp : bool ManualMapping(HANDLE process, const char* dllFilepath)
-- This function is called in main.cpp.
The srcData variable is just the binary contents of the dll
ModLoader_ManualMapping_Data loadData = { 0 };
loadData.ML_LoadLibrary = LoadLibraryA;
loadData.ML_ProcAddress = reinterpret_cast<ModLoader_GetProcAddress>(GetProcAddress);
memcpy(srcData, &loadData, sizeof(loadData));
WriteProcessMemory(process, locOfDll, srcData, 0x1000, nullptr);
void* shellCodeBase = VirtualAllocEx(process, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //Allocates 0x1000 bytes in the process memory for the shellcode
WriteProcessMemory(process, shellCodeBase, Shellcode, 0x1000, nullptr); //Injects the Shellcode function into the process
HANDLE thread = nullptr;
thread = CreateRemoteThread(process, nullptr, 0, reinterpret_cast<PTHREAD_START_ROUTINE>(shellCodeBase), locOfDll, 0, nullptr); //Runs
Finally the sample dll code
#include <Windows.h>
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD reason_for_call, LPVOID lpReserved)
{
switch (reason_for_call)
{
case DLL_PROCESS_ATTACH:
OutputDebugStringA("Injected!");
break;
}
return TRUE;
}
EDIT
After rewriting all the code and looking at it all day I finally figured it out. I just had to make sure that the parameters were right when I called dllLoad!
I'm trying to load a signed DLL into a VBS enclave and LoadEnclaveImage is returning A device attached to the system is not functioning.
Hyper-V, Secure Boot, & TPM 2.0 are all functioning, so I'm not quite sure as to what the error is referring to.
Sample Code:
if (IsEnclaveTypeSupported(ENCLAVE_TYPE_VBS))
{
DWORD lpError = 0;
ENCLAVE_CREATE_INFO_VBS vci = { 0 };
vci.Flags = 1;
PVOID enclave = CreateEnclave(GetCurrentProcess(),
NULL,
1024 * 1024 * 2,
NULL,
ENCLAVE_TYPE_VBS,
&vci,
sizeof(ENCLAVE_CREATE_INFO_VBS),
&lpError);
if (enclave != NULL)
{
auto lib = LoadLibrary(L"kernelbase.dll");
auto addr = (__LoadEnclaveImage)GetProcAddress(lib, "LoadEnclaveImageW");
if (addr(enclave, L"...\testme.dll"))
{
printf("Worked!\n");
}
else {
printf("Failed to load image\n");
printf(GetLastErrorAsString().c_str());
}
}
else
{
printf(GetLastErrorAsString().c_str());
}
}
else {
printf("VBS not supported\n");
}
I got the same general error when loading a signed DLL, so I looked for usages of LoadEnclaveImageW in other system binaries using Static Import Finder, and found it in SgrmBroker.exe where it loads "SgrmEnclave_secure.dll". Attempting to use LoadEnclaveImageW with that DLL was successful.
Digging deeper into the PE structure of the "SgrmEnclave_secure.dll" file, we can see that a value is defined for EnclaveConfigurationPointer in the IMAGE_LOAD_CONFIG_DIRECTORY64 structure (see screenshot from PE-bear).
This pointer points to an IMAGE_ENCLAVE_CONFIG64 structure and this screenshot shows what it looks like when parsed in Ghidra. The ImportList member is an RVA for a series of IMAGE_ENCLAVE_IMPORT structures.
So it looks like these structures need to be defined in the PE. This can be done using the /ENCLAVE option in the linker. Not sure if there are additional requirements. Should you get further with this, I'd be interested to know.
I am trying to use CreateFileMapping for the first time and it is giving me this error when I use GetLastError():
ERROR_INVALID_HANDLE: The handle is invalid.
Here is my code:
// create the name of our file-mapping object
nTry++; // Ensures a unique string is used in case user closes and reopens
wsprintfA(szName, FS6IPC_MSGNAME1 ":%X:%X", GetCurrentProcessId(), nTry);
// stuff the name into a global atom
m_atom = GlobalAddAtomA(szName);
if (m_atom == 0)
{ *pdwResult = ERR_ATOM;
return FALSE;
}
// create the file-mapping object
m_hMap = CreateFileMappingA(
(HANDLE)0xFFFFFFFF, // use system paging file
NULL, // security
PAGE_READWRITE, // protection
0, MAX_SIZE+256, // size
szName); //
EDIT:
The first issue was resolved, but now my program crashes somewhere else.
#define FS6IPC_MESSAGE_SUCCESS 1
#define FS6IPC_MESSAGE_FAILURE 0
// IPC message types
#define FS6IPC_READSTATEDATA_ID 1
#define FS6IPC_WRITESTATEDATA_ID 2
// read request structure
typedef struct tagFS6IPC_READSTATEDATA_HDR
{
DWORD dwId; // FS6IPC_READSTATEDATA_ID
DWORD dwOffset; // state table offset
DWORD nBytes; // number of bytes of state data to read
void* pDest; // destination buffer for data (client use only)
} FS6IPC_READSTATEDATA_HDR;
// write request structure
typedef struct tagFS6IPC_WRITESTATEDATA_HDR
{
DWORD dwId; // FS6IPC_WRITESTATEDATA_ID
DWORD dwOffset; // state table offset
DWORD nBytes; // number of bytes of state data to write
} FS6IPC_WRITESTATEDATA_HDR;
while (*pdw)
{ switch (*pdw)
{ case FS6IPC_READSTATEDATA_ID:
pHdrR = (FS6IPC_READSTATEDATA_HDR *) pdw;
m_pNext += sizeof(FS6IPC_READSTATEDATA_HDR);
if (pHdrR->pDest && pHdrR->nBytes)
CopyMemory(pHdrR->pDest, m_pNext, pHdrR->nBytes);
m_pNext += pHdrR->nBytes; // Debugger says the issue is here
break;
case FS6IPC_WRITESTATEDATA_ID:
// This is a write, so there's no returned data to store
pHdrW = (FS6IPC_WRITESTATEDATA_HDR *) pdw;
m_pNext += sizeof(FS6IPC_WRITESTATEDATA_HDR) + pHdrW->nBytes;
break;
default:
// Error! So terminate the scan
*pdw = 0;
break;
}
pdw = (DWORD *) m_pNext;
}
I'm guessing you're running on a 64-bit system, on which HANDLEs are 64 bits. The OS is quite right—the handle value 0x00000000FFFFFFFF is an invalid handle value for your process.
What exactly are you trying to do? If you want to create a file mapping backed by an actual file, pass in the handle for that file. If you want to a create a file mapping backed by the paging file instead, pass in INVALID_HANDLE_VALUE. INVALID_HANDLE_VALUE happens to be (HANDLE)-1, which is 0xFFFFFFFF on 32-bit systems but 0xFFFFFFFFFFFFFFFF on 64-bit systems, but that doesn't really matter since you should just use the symbolic value INVALID_HANDLE_VALUE in any case.
If your application is crashing when you pass in INVALID_HANDLE_VALUE, it's not because the call to CreateFileMapping is failing, it's for some other reason, and you should debug that.
I've created project using CMake in VS. Later I've add boost and gmock usage. GMock forced me to set /MT flag on all project in solution (main exe, plugins, dll, UT).
Now I'm facing strange problem. Log4Qt is my logging library. During startup when loggers are created deep inside this library
mpTextStream = new QTextStream(stdout);
where 'stdout' during runtime goes to
/* These functions are for enabling STATIC_CPPLIB functionality */
_CRTIMP FILE * __cdecl __iob_func(void)
{
return _iob;
}
which returns NULL (only first item in this _iob array isn't NULL). Ok, I see that those entries seems to be valid as initialization of this table is
FILE _iob[_IOB_ENTRIES] = {
/* _ptr, _cnt, _base, _flag, _file, _charbuf, _bufsiz */
/* stdin (_iob[0]) */
{ _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
/* stdout (_iob[1]) */
{ NULL, 0, NULL, _IOWRT, 1, 0, 0 },
...
So in the result when
void __cdecl _lock_file (
FILE *pf
)
{
/*
* The way the FILE (pointed to by pf) is locked depends on whether
* it is part of _iob[] or not
*/
if ( (pf >= _iob) && (pf <= (&_iob[_IOB_ENTRIES-1])) )
{
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
*/
_lock( _STREAM_LOCKS + (int)(pf - _iob) );
/* We set _IOLOCKED to indicate we locked the stream */
pf->_flag |= _IOLOCKED;
}
else
/*
* Not part of _iob[]. Therefore, *pf is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
EnterCriticalSection( &(((_FILEX *)pf)->lock) );
}
stdout isn't recognized as part of _iob array and standard EnterCriticalSection is run which result in 'Unhandled exception at 0x77E58DC9 (ntdll.dll) in ComputerConfShop.exe: 0xC0000005: Access violation writing location 0x00000014.'
Should I add some specific building flag? Or gmock can be easily change from /MT to /MD library? Or something other?