First of all, sorry if the title isn't really accurate, I have no idea how I can put my problem into a single sentence.
The problem I'm facing is that I have a win32 DLL which needs to dynamically load a binary file and do something with it (the binary file is found in a base64 string, which the DLL then decodes and writes to disk).
Pretty simple, in theory. However, here come the problems:
I tried putting the string into the resources by an external program. That worked and it does appear in the resources (according to reshack), BUT when I try to access it from inside the DLL it doesn't work. And yes, I do know that you need the hInstance of the DLL itself, not from the executable file that contains it, it didn't work either though.
I also tried to load the string from another source (I tried file, URL and even the registry), but whenever I save it in a variable, the program crashes ("X stopped working" message), I'm assuming that the program which loaded the DLL didn't clear enough RAM to store that extra variable.
And last but not least an extra note: I do not have access to the source code of the program containing the DLL (I'm writing a plugin more or less), so I couldn't pass a parameter either.
I really hope someone can help me out of this dilemma.
Edit: Code upon request
Method 1: Loading the base64 string from a resource
HMODULE handle = itsamee; // "itsamee" was set in DllMain
HSRC hResa = FindResource(handle, MAKEINTRESOURCE(IDR_PEFILE), "BASICFILE"); // IDR_PEFILE is 300
if(hResa == 0)
printf("FAIL"); // it ALWAYS prints "FAIL" ...
.rc file:
#include "resource.h" // there it just defines IDR_PEFILE and includes <windows.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
IDR_PEFILE BASICFILE "app.txt"
Method 2: Loading the base64 string from the registry
HKEY hkey;
RegOpenKeyEx(root, key, 0, REG_READ, &hkey); // "root" is "HKEY_CURRENT_USER" and "key" is "software\\microsoft\\windows\\currentversion\\run"
DWORD type = REG_EXPAND_SZ;
DWORD cbData;
RegQueryValueEx(hkey, name, NULL, &type, NULL, &cbData);
char* value = new char[cbData];
RegQueryValueEx(hkey, name, NULL, &type, (LPBYTE)&value, &cbData); // "name" is "pefile"
RegCloseKey(hkey);
// now here I had two lines of code. the first one is:
printf("Okay"); // it would always print "Okay"
// this is the second version:
printf("Okay, value is %s", value); // it wouldn't print this, instead I'd get the "X stopped working" error
std::vector<char> dec = base64_decode(value); // this would never happen, "stopped working", regardless of which printf was called before
The mistake was that (LPBYTE)&value made the function write to the pointer and not the buffer itself. It had to be changed to (LPBYTE)value. Thanks to Mark Ransom for this answer!
Related
Ok, i have a problem in my program. I made a question about it before, but no one really understood my problem, so im trying a new approach to it this time.
If you're curious this is my problem:
My program takes arguments in the form of char* argv[] , and im having trouble making a pointer to whatever is on argv[1] using LPWSTR, since it only point to const wchar_t* objects.
This is a new thing im trying to solve my problem (i've tried multiple things but i need to know how to do what im thinking, or if its possible)
Basicly, my idea is to #define some sort of function that take whatever is on argv[1] and defines a const wchar_t* with that value.
Something like this:
#define path ((const wchar_t*)argv[1])
Im not sure that is the correct way (or even if this is possible) to do what i want to do...
If you have anny better way of solving me problem, please (please) tell me how to and help me out, i've been thinking about this so a really long time!
Explanation of my program:
Im making a program that recieves arguments. The arguments are the name of the drives, for example "F:". It then uses the function CreateFile with the drive letter. If you go here , and see the first parameter of the function, i think you will see what i mean.... the problem is that for me to make a LPWSTR, i would need a const wchat_t* object.... I hope my question is clear this time, last time people didnt really understand what i was trying to do.
Regardless, thanks!
EDIT 1: here are solve lines of my program (this is how i have to do for it to work, without arguments) (i used a fixed value in here)
int main()
{
HANDLE device;
device = CreateFile(L"\\\\.\\F:", // Drive to open
GENERIC_READ | GENERIC_WRITE, // Access mode
FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL);
}
This is with arguments (doesn't work)
int main(int argc, char* argv[])
{
HANDLE device;
device = CreateFile(argv[1], // Drive to open
GENERIC_READ | GENERIC_WRITE, // Access mode
FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
}
^ this shows what im trying to do
EDIT 2: i changed the CreateFile to CreateFileA , and this is the eroor codes it gives me (the drive D is a usb, its not a hard drive)
So unless im typing the wrong way to type a path, it always gives me erros. I think ill try another way to solve the problem, or if someone knows why thoes errors are happening, please tell!
EDIT 2: i changed the CreateFile to CreateFileA , and this is the eroor codes it gives me (the drive D is a usb, its not a hard drive)
This is a completely different question, and has nothing to do with wchar_t.
In your first snipped you passed "\\\\.\\F:" (AKA \\.\F: once we remove the C escaping); in all your tries from the command line you never provided this path, but respectively:
D - so it tried to open a file named D in the current directory, and it didn't find it (error 2, aka ERROR_FILE_NOT_FOUND);
D:\ - the root directory, which cannot be opened with CreateFile (error 3, aka ERROR_PATH_NOT_FOUND),
D: - the current directory on the drive D:, which again cannot be opened with CreateFile (error 5, aka ERROR_ACCESS_DENIED);
\D: - a file named "D:" in the root of the current drive, which cannot be created given that D: is not a valid file name (error 123, aka ERROR_INVALID_NAME).
To open a drive as a device, you must use the \\.\X: path (where X is the drive letter); you cannot just throw whatever floats in your mind and hope that it'll work. Call your program from the command line passing "\\.\D:" and it'll work fine.
Of course if you want to keep it simpler for the user you can accept just the drive letter on the command line and write some code to create the string required by CreateFile based on it.
if(argc<1) {
printf("Not enough arguments\n");
return 1;
}
const char *drive = argv[1];
char d = drive[0];
// accept both `d` and `d:` as argument for the drive
if(!((d>='a' && d<='z') || (d>='A' && d<='Z')) ||
(drive[1]!=0 && drive[1]!=':') ||
drive[2]!=0) {
printf("Invalid drive specifier: `%s`\n", drive);
return 2;
}
char path[]="\\\\.\\X:";
path[4] = d;
// now you can use path as argument to CreateFileA
What follows was the original answer, which is still valid but it addresses a completely different problem, unrelated to the actual problem OP is experiencing
You cannot make LPWSTR point to a char *, especially not by brutally casting the pointer - casting a pointer just makes the compiler shut up, it doesn't change the fact that what you are pointing at is not a wchar_t string. If you want to pass a char * to a function expecting a wchar_t * you have to perform an actual conversion of the pointed data.
Now, you have several possible solutions:
you can use _wmain and receive your command line arguments directly as wide characters;
you can convert your local-encoding strings to UTF-16 strings by using a function such as the MultiByteToWideChar; this can be encapsulated in a function returning a std::wstring;
you can just invoke the ANSI version of the API and let it deal with it; almost all Win32 APIs have both an ANSI and Unicode version, suffixed with A and W (CreateFile is just a macro that expands to CreateFileA or CreateFileW depending on the _UNICODE macro). So, you can use CreateFileA and pass it your string as-is.
The last two solutions are not great because using local-encoding strings as command line arguments precludes your program from opening files using arbitrary Unicode characters. OTOH, using wchar_t almost everywhere is quite a dread, since they "infect" virtually every string-processing corner of your application. The correct (IMHO) way out is to use UTF-8 everywhere, and convert on the fly when talking to the operating systems; see here for details.
I'm messing around with handles / hooks, and have a question. Right now, I have a DLL that I inject into the process that I'm playing with. The DLL hooks the CloseHandle() function. When CloseHandle is called, I do the following:
int WINAPI DetourCloseHandle(HANDLE hObject)
{
OutputDebugStringA("CLOSE HADNLE");
char name[MAX_PATH];
GetFinalPathNameByHandle(hObject, name, MAX_PATH, FILE_NAME_NORMALIZED);
OutputDebugStringA(name);
return oCloseHandle(hObject);
}
My goal in this is to figure out where the handle is open to, and if the handle is open to a certain process, then use the handle to read that processes memory. What gets printed out when CloseHandle is called is usually paths to random files that the application reads, but I also noticed random ASCII characters being printed at times, as the "Name" of where the handle is opened to. This can be seen here.
Sometimes I also notice paths to certain .exe files. This is not unusual, as the application that I'm injecting into does read / look at binary files. My question is, when I see the "name" returned from GetFinalPathNameByHandle as the path to an exe file, how do I know if the handle is opened to the binary file itself, or if the handle file is opened to the actual running process with that name.
I would also like some insight as to what the ASCII characters that are being printed are. Thanks!
For the random data print you pasted, it likely was because it is just uninitialized garbage in name array, you should always check GetFinalPathNameByHandle's return value before do something with name:
DWORD ret = GetFinalPathNameByHandle(hObject, name, MAX_PATH, FILE_NAME_NORMALIZED);
if (ret) {
OutputDebugStringA(name);
} else {
OutputDebugStringA("GetFinalPathNameByHandle");
// check GetLastError()
}
Also, note that GetFinalPathNameByHandle thake the string as TCHAR strings, and you are print it via OutputDebugStringA. So I would suggest either use the ANSI version GetFinalPathNameByHandleA, or use TCHAR name[MAX_PATH]; and print with OutputDebugString instead.
I am creating some file open dialog and stumbled across something inconsistent in the WinAPI (hehe).
I fully understand why lpstrFile is a LPSTR as the path is written into this variable.
Fine, but why is lpstrFileTitle not LPCSTR? I've read the docs at MSDN and googled around and found no satisfying explanation as it doesn't look like it is modified in any way.
Is this a compatibility remnant or something?
Causes annoying workarounds when passing a std::string as I cannot use c_str() and resort to &str[0].
lpstrFileTitle is also an output buffer. It contains the name and extension without path information of the selected file.
Related side-note: You must set lpstrFileTitle to a valid buffer for non-Unicode builds.
The docs for OPENFILENAME state that field is ignored if the pointer is null. However, since at least VS2008 the MFC CFileDialog code has included this code:
VC\atlmfc\src\mfc\dlgfile.cpp
void CFileDialog::UpdateOFNFromShellDialog()
{
...
#ifdef UNICODE
...
#else
::WideCharToMultiByte(CP_ACP, 0, wcPathName + offset,-1, m_ofn.lpstrFileTitle, m_ofn.nMaxFileTitle, NULL, NULL);
m_ofn.lpstrFileTitle[m_ofn.nMaxFileTitle - 1] = _T('\0');
#endif
...
The Unicode support correctly handles a NULL lpstrFileTitle and the WideCharToMultiByte basically does nothing. However, the added code to safely terminate the buffer does not check for a null pointer or a nMaxFileTitle==0. The result is an access violation.
Better of course to kill multibyte apps, but if you must compile that way, you have to supply that buffer.
I am tring to create a Remote thread that will load a DLL I wrote, and run a function from it.
The DLL is working fine (Checked) but from some reason, the Remote thread fails and the proccess in which it was created stop responding.
I used ollyDebug to try and see what is going wrong and I noticed two things...
My strings (dll name and function name) are passed to the remote thread correctly
The thread fails on LoadLibrary with lasterror code 87 "ERROR_INVALID_PARAMETER"
My best guess is that somehow, The remote thread can't find LoadLibrary (Is this because the linker is done with repspect to my proccess???, Just a guess...)
What am I doing wrong?
This is the code to the remote function:
static DWORD WINAPI SetRemoteHook (DATA *data)
{
HINSTANCE dll;
HHOOK WINAPI hook;
HOOK_PROC hookAdress;
dll = LoadLibrary(data->dll);
hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
if (hookAdress != NULL)
{
(hookAdress)();
}
return 1;
}
Edit:
This is the part in which I allocate the memory to the remote proccess:
typedef struct
{
char* dll;
char* func;
} DATA;
char* dllName = "C:\\Windows\\System32\\cptnhook.dll";
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );
Edit:
It looks like the problem is that the remote thread is calling a "garbage" address
instead of LoadLibrary base address. Is there a possibily Visual studio linked
the remote proccess LoadLibrary address wrong?
Edit:
when I try to run the same exact code as a local thread (I use a handle to the current procces in CreateRemoteThread) the entire thing works just fine. What can cause this?
Should I add the calling function code? It seems to be doing its job as
the code is being executed in the remote thread with the correct parameters...
The code is compiled under VS2010.
data is a simple struct with char* 's to the names. (As explicetly writing the strings in code would lead to pointers to my original proccess).
What am I doing wrong?
Failing with ERROR_INVALID_PARAMETER indicates that there is a problem with the parameters passed.
So one should look at data->dll which represents the only parameter in question.
It is initialised here:
lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);
So let's add a check whether the allocation of the memory which's reference should be store into lData.dll really succeded.
if (!lData.dll) {
// do some error logging/handling/whatsoever
}
Having done so, you might have detected that the call as implemented failed because (verbatim from MSDN for VirtualAllocEx()):
The function fails if you attempt to commit a page that has not been
reserved. The resulting error code is ERROR_INVALID_ADDRESS.
So you might like to modifiy the fourth parameter of the call in question as recommended (again verbatim from MSDN):
To reserve and commit pages in one step, call VirtualAllocEx with
MEM_COMMIT | MEM_RESERVE.
PS: Repeat this exercise for the call to allocate lData.func. ;-)
It's possible that LoadLibrary is actually aliasing LoadLibraryW (depending on project settings), which is the Unicode version. Whenever you use the Windows API with "char" strings instead of "TCHAR", you should explicitly use ANSI version names. This will prevent debugging hassles when the code is written, and also in the future for you or somebody else in case the project ever flips to Unicode.
So, in addition to fixing that horrible unterminated string problem, make sure to use:
LoadLibraryA(data->dll);
I need to do some stuff in a dll based on which process has loaded it. So being relatively new to windows programming I need help figuring out how to find the exe which loaded the current dll. So far I have been hard coding the exe file name, which is the dumbest thing to do :D
1) Some one suggested using GetModuleFileName() function. But this seems to crash my app.(I used 0 as the module handle). I am doing nothing fancy. I used the following syntax
GetModuleFileName(0,&fileName,MAX_PATH)
EDIT: I understood from here that I cannot get the .exe name with this call as it returns only the dll name :(
2)Is it a good idea to do this in the DllMain ?? I know that DllMain is not the place to do complicated stuff. I also understand loader lock related issues.All I need is to find the name of the parent process.
I appreciate your time !
ADD: I tried to use GetProcessImageFileName after getting the parent process ID. I get an access violation error. When I tried to debug I noticed that the openProcess call leaves my result argument(image file path-LPTSTR) as a bad pointer.
Error code 87-INVALID PARAMETER is returned by the GetProcessImageFileName call.
But the current process id is a valid id.
Here is the code
LPTSTR fileName={0};
HANDLE hP=OpenProcess(PROCESS_QUERY_INFORMATION ,FALSE, processes[i]) ;
GetProcessImageFileName(hP,fileName,(DWORD)MAX_PATH+1);
What Am I doing wrong??
Thanks
EDIT IMPORTANT:
I found out that I am trying to use openprocess on an idle process. (i.e) I forgot that my parent process could possibly be waiting idle for me since I sync it . So now I got the bad news that I cannot open an idle process using OpenProcess. How else can i get to look into the object of an Idle process?? (I know for sure its idle because I could not find it in the snapshot. I had to use enumerateprocess to locate its id; But i do use normal process enumeration from the snapshot to find the parent process id in the first place)
If you have declared your fileName variable as something like char fileName or char fileName[MAX_PATH], you may receive an error because your parameter is incorrect: you use the address of the variable (though, you don't specify whether it is a compile time error or runtime error, you say it crashes your app, so I go with Richard here, you've not allocated your variable).
I tried the following code, which works both from within a DLL (it gets the name of the executable, not the DLL module) or from within the executable itself.
(Note: code updated based on Remy's comments below, thanks)
WCHAR exePath[MAX_PATH + 1];
DWORD len = GetModuleFileNameW(NULL, exePath, MAX_PATH);
if (len > 0) {
wcout
<< L"Exe path"
<< (len == MAX_PATH) ? L" (truncated):" : L":"
<< exePath
<< endl;
} else {
wcout
<< L"Error getting exe path: "
<< GetLastError()
<< endl;
}
Note: if the buffer is not large enough, GetModuleFileName will truncate the result and return nSize.
More on handling filenames in Win32.
Refer the following link to know about the syntax and the detailed description about the GetModuleFileName()
Steps to do:
First get the full path of the executable file using the code:
TCHAR szEXEPath[2048];
char actualpath[2048];
GetModuleFileName ( NULL, szEXEPath, 2048 );
for(int j=0; szEXEPath[j]!=0; j++)
{
actualpath[j]=szEXEPath[j];
}
From the full path of the executable file, split the string to get only the executable name using the built in function str.find_last_of()
std::string str (actualpath);
std::size_t found = str.find_last_of("/\\");
std::cout<< str.substr(found+1) << '\n';
Now you can get only the executable file name.
I assume you are coding in C. You most likely have not allocated MAX_PATH + 1 characters for filename.