Can't get IAT Thunk data (functions) from certain processes (PE32) - c

I have made a tool to parse the IAT out of PEs (IAT hooking also desirable). It works great for almost everything I've tried. There's one process however that I am completely failing to parse; I can iterate through the import descriptors and get the libraries (all with the correct data) but then my code for parsing the functions seems to just produce nonsense or crash. Here is my code:
// hMod is just the process module pointer thingy
LPBYTE pImageBase = (LPBYTE)hMod;
PIMAGE_DOS_HEADER pImgDosHeaders = (PIMAGE_DOS_HEADER)hMod;
PIMAGE_NT_HEADERS pImgNTHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pImgDosHeaders + pImgDosHeaders->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR pImgImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)pImgDosHeaders + pImgNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if (pImgDosHeaders->e_magic != IMAGE_DOS_SIGNATURE)
// This doesn't happen
LogError("Signature in the PE header wrong!");
for (; pImgImportDesc->Name != 0; pImgImportDesc++) {
libraryName = (LPCSTR)(pImageBase + pImgImportDesc->Name);
// This is all good...
LogDebug("Lib name: %s, RVA: %p", libraryName, pImgImportDesc->Name);
// This is NOT good. pImgImportDesc->OriginalFirstThunk is zero.
if (!pImgImportDesc->OriginalFirstThunk || !pImgImportDesc->FirstThunk) {
LogWarn("Thunk data missing for %s (%d, %d)", libraryName, pImgImportDesc->OriginalFirstThunk, pImgImportDesc->FirstThunk);
}
pOrigThunk = (PIMAGE_THUNK_DATA)(pImageBase + pImgImportDesc->OriginalFirstThunk);
pThunk = (PIMAGE_THUNK_DATA)(pImageBase + pImgImportDesc->FirstThunk);
for (; pOrigThunk->u1.AddressOfData != 0; pOrigThunk++, pThunk++) {
if (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) {
LogDebug("Non-string entry at RVA: %p", pOrigThunk->u1.AddressOfData);
}
else {
// here we just get nonsense data. also the wrong number of functions. so we're parsing it all wrong
functionName = (PIMAGE_IMPORT_BY_NAME)(pImageBase + pOrigThunk->u1.AddressOfData);
LogDebug("Function name: %s, RVA: %p", functionName->Name, pOrigThunk->u1.AddressOfData);
// Then we can do something with &pThunk->u1.Function if we so desire
}
}
}
The good folks at NTCore have a 32bit CFF explorer which works well on the process I am trying to read, however that's only from reading the file not the process. I have googled a lot and tried using other people's code but their code is always very similar to the above and also fails (sometimes crashing instead).
Important detail: this code is running injected inside the process, I am not reading a file.
EDIT: It seems I can sort of parse the file itself but this doesn't work in memory, so the real issue is that the IAT is getting obfuscated or something.
Here is the redacted output: https://textsaver.flap.tv/lists/4jsn
(Generated using this code)
Anyone got any suggestions for workarounds or am I at a dead end?

Related

GetModuleHandleW / A - not working. Returning null every call excluding empty string

#include <Windows.h>
int main(){
printf("Enter name of program. \n");
char prog[300];
scanf("%s", prog);
HMODULE hModule = GetModuleHandleW((LPCWSTR)prog);
if (hModule){
IMAGE_DOS_HEADER* pIDH = (IMAGE_DOS_HEADER*)hModule;
IMAGE_NT_HEADERS* pNTH =(IMAGE_NT_HEADERS*)((BYTE*)pIDH + pIDH->e_lfanew);
IMAGE_OPTIONAL_HEADER pOPH = (IMAGE_OPTIONAL_HEADER)pNTH->OptionalHeader;
IMAGE_DATA_DIRECTORY* pIDD = (IMAGE_DATA_DIRECTORY*)pOPH.DataDirectory;
printf("%x", pIDD->VirtualAddress);
}
else {
printf("Error");
}
return 0;
}
That's my basic script for now only to check if I get into the IMAGE_DATA_DIRECTORY.
My goal is to print every dll and all of it's imported functions of a certain running process - GetModuleHandleA / W.
Every call its returning null - printing "Error" as I checked, excluding the empty call in which it prints '0' for some reason..
Besides the obvious (LPCWSTR)prog casting bug, GetModuleHandle is never going to work because it only handles modules in the current process.
Call CreateToolhelp32Snapshot to get a list of all processes and then call CreateToolhelp32Snapshot again to get the modules of a specific process. Note that you cannot read the DOS/NT headers of a remote process directly, you would have to use ReadProcessMemory.
DataDirectory is an array, you have to specify the directory you are interested in (resource, import, export etc.).

How do I read OpenVINO IR models from memory with the OpenVINO C API

I am having trouble reading OpenVINO IR networks (XML and bin) from memory using ie_core_read_network_from_memory() in the OpenVINO 2021.4 C API ie_c_api.h.
I suspect that I am creating the network weight blob wrong, but I cannot find any information on how to create weight blobs correctly for networks.
I have read the OpenVINO C API docs but cannot deduce from docs what I am doing wrong. The OpenVINO code repo contains some C code samples, but none of the samples seem to use ie_core_read_network_from_memory().
Below is a cut out of the code I am having trouble with.
// void* dmem->data - network memory buffer (float32)
// size_t dmem->size - size of network memory buffer (bytes)
ie_core_t* ov_core = NULL;
IEStatusCode status = ie_core_create("", &ov_core);
if (status != OK)
{
// error handling
}
const dimensions_t weights_tensor_dims =
{ 4, { 1, 1, 1, dmem->size/sizeof(float) } };
tensor_desc_t weights_tensor_desc = { OIHW, weights_tensor_dims, FP32 };
ie_blob_t* ov_model_weight_blob = NULL;
status = ie_blob_make_memory_from_preallocated(
&weights_tensor_desc, dmem->data, dmem->size, &ov_model_weight_blob);
if (status != OK)
{
// error handling
}
// char* model_xml_desc - the model's XML string
uint8_t* ov_model_xml_content = (uint8_t*)model_xml_desc;
ie_network_t* ov_network = NULL;
size_t xml_sz = strlen(ov_model_xml_content);
status = ie_core_read_network_from_memory(
ov_core, ov_model_xml_content, xml_sz, ov_model_weight_blob, &ov_network);
if (status != OK)
{
// Always get "GENERAL_ERROR (-1)"
}
The code works fine down to the ie_core_read_network_from_memory() call which results in "GENERAL_ERROR".
I have tried two models that were converted from Tensorflow. One is a simple [X] -> [Y] regression model (single input value, single output value). The other is also a regression model [X_1, X_2, ..., X_9] -> [Y] (nine input values, single output value). They work fine when reading them from file with ie_core_read_network(), but for my use case I must provide the network as a binary memory buffer and XML string.
I would appreciate any help, either by pointing out what I am getting wrong or directing me to some code samples that use ie_core_read_network_from_memory().
System information:
Windows 10
OpenVINO v2021.4.689
Microsoft Visual Studio 2019
UPDATE: An Intel employee reached out to me in another forum and pointed out that there is a unit test for ie_core_read_network_from_memory(). The unit test successfully reads a network from memory and made clear that I was in fact using a faulty tensor description to produce the weight blob, just as I suspected. Apparently the weight blob descriptor should be one dimensional, have memory layout ANY and datatype U8 even though the model weights are fp32.
From the unit test:
std::string bin_std = TestDataHelpers::generate_model_path("test_model", "test_model_fp32.bin");
const char* bin = bin_std.c_str();
//...
std::vector<uint8_t> weights_content(content_from_file(bin, true));
tensor_desc_t weights_desc { ANY, { 1, { weights_content.size() } }, U8 };
However, simply changing the tensor descriptor was not enough to get my code to work so it remains for me to properly translate the C++ code from the unit test to my C environment before the issue to can be considered solved.
Thanks
Refer to tensor_desc struct and standard layout format.
Apart from that, it is recommended to use the Benchmark_app tool to test the inference performance.

Code (C) won't work when I remove junk code?

I have the following code. The code reads a string from a PHP webpage, then converts the code using the MultiByteToWideChar-function. Then it splits the string using the comma-delimiter. It then removes the "xxx=" before the value (for example, "cid={abcd-1234-5678},tid=AAD23HKJD23KVAAAHN23") and attaches the splitted substrings to an array. Then it displays the parameters one by one in a textbox.
I had it working, however I reinstalled my system 2 days ago and since then I cannot seem to get it working again (even though I backed up the working project before reinstalling, which leaves me wondering how this could ever be possible).
So I have been trying for hours and hours and hours the past day, changing every setting in the compiler and project properties I could think of, reinstalling Visual Studio, trying other versions of Visual Studio, installing extra SDK packages... Nothing helped. Then I added some junk code to test whether the wcstok function was even working (it seems that the project died there) and then randomly the entire project worked and the array I talked about before got properly returned. However, if I remove this junkcode or the code after the splitting/returning of the string (which should have no influence on the code above it, leaving me as confused as I could possibly be) it stops working again and seems to die at the "wcstok"-function.
This is my code:
BOOL Commands(LPBYTE command, DWORD size)
{
unsigned int sizeint;
sizeint = (unsigned int)size;
wchar_t params[MAXCHAR];
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, (LPCCH)command, sizeint, (LPWSTR)params, size);
MessageBoxW(0, params, 0, 0);
//wchar_t input[100] = L"A bird came down the walk";
//wchar_t* buffer;
//wchar_t* token = std::wcstok(input, L" ", &buffer);
wchar_t buf2[MAXCHAR], *ptr;
int i;
for (ptr = wcstok(params, L","); ptr != NULL; ptr = wcstok(NULL, L","))
{
CWA(lstrcpyW, kernel32, buf2, ptr);
for (i = 0; i < lstrlenW(buf2); i++)
{
if (buf2[i] == '=' )
{
wchar_t *a[1000];
wcscpy(a[0] + i, buf2 + i + 1);
MessageBoxW(0, a[0] + i, 0, 0);
}
else
{
}
}
}
//HRESULT hr;
//LPCTSTR Url = _T("http://cplusplus.com/img/cpp-logo.png"), File = _T("C:\\Users\\Public\\file.exe");
//////hr = URLDownloadToFile(0, Url, File, 0, 0);
//switch (hr)
//{
// PROCESS_INFORMATION *piinfo; //size = 0x10
// STARTUPINFO *siinfo; //size = 0x44
// CWA(CreateProcessW, kernel32, 0, File, 0, 0, 0, DETACHED_PROCESS, 0, 0, siinfo, piinfo);
//}
CWA(Sleep, kernel32, 100);
return 1;
}
It doesn't work properly when I use the code above, but when I uncomment the junk-code that is commented above, it randomly does work. The first "MessageBoxW" seems to always return the string from the PHP page properly, however once I remove the junkcode, the program gets terminated once the wcstok in the splitting function is reached.
It worked before exactly like this and I am honestly clueless, I hope anyone has an idea what could cause this because it is honestly driving me nuts..
Thanks a lot in advance!
Millie Smith was the one who gave me the place where the code was bugged.
Instead of defining "a" as a wchar_t*, I had to define it as a normal w_char.
So it became "wchar_t a[MAXCHAR]". Then I had to change the "wcscpy(a[0] + i, buf2 + i + 1);" inside the splitting function into "wcscpy(a + i, buf2 + i + 1);".
Learned something new again, undefined behaviour can be a tricky thing.
Thanks for the help and have a nice day!

Properties file reading in C (no C# or C++) compiled with minGW

I need to say that i am Newbie at C and i only wrote about 100-150 lines of code in C.
I need to read a .properties file with entries like the following:
Value1 = Hello
Value2 = Bye
I would like to get to the Values like this:
bla.getValue("Value1");
So i can work with it like this:
foo = bla.getValue("Value1");
bar = bla.getValue("Value2");
printf("%s - %s",foo,bar);
I don't need them for anything else, than printing them to the screen.
I found two questions here, which went into the right direction, but they couldn't help me in my task:
How to read configuration/properties file in C?
Properties file library for C (or C++)
I tried multiple of the answers of the thread above, but either way my compiler(minGW) doesn't like one of these lines:
using foo::bar;
or
using namespace foo;
When i try to compile my code, i get an error saying:
error: unknown type name 'using'
This is the code where i tried to implement the given solution of the thread above:
#include <windows.h>
#include <stdio.h>
#include <string.h>
using platformstl::properties_file;
int WINAPI WinMain(HINSTANCE a,HINSTANCE b,LPSTR c,int d)
{
char *tPath, *tWindow;
char *search = " ";
tWindow = strtok(c, search);
tPath = strtok(NULL, search);
properties_file properties("%s",tPath);
properties::value_type value1 = properties["Value1"];
properties::value_type value2 = properties["Value2"];
printf("Window: %s; Path: %s; %s %s",tWindow,tPath,value0,value1);
}
I use a WinMain, because the programm is about finding an open Window. I haven't included those parts of the code, because they are irrelevant for my question and worked completely fine. The strtok(); parts are working fine for me too. I need them, because the title of the window to find and the Path of the properties file are both given as commandline arguments:
programm.exe windowtitle path/to/properties/file
As i tried with other answers, which told me to load some libraries, i got to a point, where the needed libraries didn't contain the needed header files. Some of the libraries are even for c++, which i have a restriction on, so i can't use it.
I hope that made things a little clearer, as you may know that i am not used to ask questions here. :)
I solved my Problem with a big Workaround.
This is my final code:
if(vn != NULL){
for(i = 0; i < 1; i++){
if(fgets(temp, BUF, vn) == NULL){
printf("Line is empty");
return 2;
}
}
if(fgets(puffer, BUF, vn) == NULL){
printf("Line is empty");
return 2;
}
tVariable = strtok(puffer, find);
tValue = strtok(NULL, find);
}else {
printf("Unable to read File");
return 2;
}
I just read the second Line of the given file and cut it at the = sign.
I know, that i need to read the second line, because the Property i need is always found in the second line of the .properties file.
I now have my wanted Value in tValue, so i can use it to print it out with printf("%s", tValue).

Using VirtualQueryEx to enumerate modules at remote process doesn't return all modules

I am trying to get a list of DLLs that a given process is using, I am trying to achieve that through VirtualQueryEx. My problem is that it return to me just a partial list of DLLs and not all of them (i can see the list using Process Explorer or using VirtualQuery on the given process).
Here's the code:
char szBuf[MAX_PATH * 100] = { 0 };
PBYTE pb = NULL;
MEMORY_BASIC_INFORMATION mbi;
HANDLE h_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, iPID);
while (VirtualQueryEx(h_process, pb, &mbi, sizeof(mbi)) == sizeof(mbi)) {
int nLen;
char szModName[MAX_PATH];
if (mbi.State == MEM_FREE)
mbi.AllocationBase = mbi.BaseAddress;
if ((mbi.AllocationBase == hInstDll) ||
(mbi.AllocationBase != mbi.BaseAddress) ||
(mbi.AllocationBase == NULL)) {
// Do not add the module name to the list
// if any of the following is true:
// 1. If this region contains this DLL
// 2. If this block is NOT the beginning of a region
// 3. If the address is NULL
nLen = 0;
} else {
nLen = GetModuleFileNameA((HINSTANCE) mbi.AllocationBase,
szModName, _countof(szModName));
}
if (nLen > 0) {
wsprintfA(strchr(szBuf, 0), "\n%p-%s",
mbi.AllocationBase, szModName);
}
pb += mbi.RegionSize;
}
I am getting the result on szBuf.
This function is part of a DLL file so that it is harder for me to debug.
Right now the DLL is compiled as x64 binary and i am using it against x64 processes.
P.S i know about EnumProcessModules and i am not using it with a reason (too long:).
GetModuleFileName() only gives you the name for modules loaded in your process, not the other process. It will give you a few hits by accident, the Windows operating system DLLs will get loaded at the same address and will thus have the same module handle value.
You will need to use GetModuleFileNameEx() so you can pass the process handle.
Do note the fundamental flaw with your code as posted, you are not doing anything to ensure that you can safely use VirtualQueryEx() on another process. Which requires that you suspend all its threads so it cannot allocate memory while you are iterating it, the kind of thing a debugger does. Also required for EnumProcessModules. The failure mode is nasty, it is random and it can easily get your loop stuck, iterating the same addresses over and over again. Which is why the CreateToolHelp32Snapshot() function exists, emphasis on "snapshot".

Resources