Hello I want to unload this dll from the process it is injected to, how can I do this? this is how I inject the dll to process:
this is just me showing how i inject my dll into a process, but how do i UNLOAD / UNINJECT this dll from the process if my inject method is this
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, GetProcessIdByName("csgo.exe"));
if (h)
{
LPVOID LoadLibAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
//cout << "[!] Initialized Library\n";
LPVOID dereercomp = VirtualAllocEx(h, NULL, strlen(dllName), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//cout << "[!] Initialized memory allocation\n";
WriteProcessMemory(h, dereercomp, dllName, strlen(dllName), NULL);
//cout << "[!] Wrote dll name to memory: " << strlen(dllName) << " byte(s)\n";
HANDLE asdc = CreateRemoteThread(h, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, dereercomp, 0, NULL);
//cout << "[!] Created remote thread: " << asdc << endl;
//cout << "[!] Waiting for Dll exit...\n";
WaitForSingleObject(asdc, INFINITE);
VirtualFreeEx(h, dereercomp, strlen(dllName), MEM_RELEASE);
//cout << "[!] Freeing memory\n";
CloseHandle(asdc);
CloseHandle(h);
//cout << "[!] Closed all handles\n";
//cout << "[!] Complete!\n";
}
You’re using CreateRemoteThread to launch a thread in your target process that runs “LoadLibraryA”.
I have no idea why commenters didn't like your injection code. Looks OK to me. I think you’re correctly closing that thread, however I recommend adding GetExitCodeThread call after WaitForSingleObject, this will give you the return code from LoadLibrary so you can check for errors. You can't call FreeLibrary on that handle because different processes. GetLastError won't work either. But at least you can compare with nullptr to detect a fail.
The reason why DLL stays loaded is no one has called FreeLibrary.
One pattern here, in DllMain of your DLL, under DLL_PROCESS_ATTACH case, create one more remote thread. This time no need to use CreateRemoteThread, just call normal CreateThread because that code already runs in the target process. Call CloseHandle at once on the returned handle (this won't kill the new thread just release the handle). Now in that second remote thread, do whatever you want to do in the target process, and when finished, call FreeLibraryAndExitThread API. This will exit the second remote thread, at the same time unloading your DLL from your target process.
More info: DllMain entry point For DLLs, HINSTANCE is same as HMODULE, just cast the first argument to HMODULE and keep that argument in some variable to pass into FreeLibraryAndExitThread.
Update: As said by the commenter, ideally you need to allocate, and copy, one extra character. Just replace strlen(dllName) with strlen(dllName)+1 in both cases.
Update 2: BTW it's often a good idea to call DisableThreadLibraryCalls first thing in DLL_PROCESS_ATTACH handler. Especially if you then launch new threads from your DllMain.
Related
I'm attempting to debug some very opaque issues with DLLs in Unreal on a CI machine (see Unreal: Diagnosing why Windows cannot load a DLL for more information). glu32.dll seems to be the DLL at which the Unreal process falls over, and as Windows Server doesn't contain all the graphics-related DLLs that normal Windows 10 does, I was recommended to upload certain DLLs from my machine/Microsoft redistributables in order to make sure the Unreal build process could run.
For sanity purposes, I've written a small utility program to test whether glu32.dll on my machine can be dynamically loaded and can have its functions called correctly. I'm planning to run this executable on the troublesome CI machine soon to see what happens.
The code for the program is below:
#include <windows.h>
#include <iostream>
#include <GL/gl.h>
extern "C"
{
typedef const GLubyte* (__stdcall *ErrorStringFunc)(GLenum error);
}
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage: GLU32Loader.exe <path to glu32.dll>" << std::endl;
return 1;
}
const char* path = argv[1];
std::cout << "Attempting to load: " << path << std::endl;
HMODULE dllHandle = LoadLibraryA(path);
if (!dllHandle)
{
std::cerr << "Could not load " << path << std::endl;
return 1;
}
std::cout << "Successfully loaded DLL: 0x" << dllHandle << std::endl;
const char* funcName = "gluErrorString";
std::cout << "Looking up function: " << funcName << std::endl;
ErrorStringFunc func = reinterpret_cast<ErrorStringFunc>(GetProcAddress(dllHandle, funcName));
if (func)
{
std::cout << "Successfully loaded function: 0x" << func << std::endl;
const GLubyte* str = (*func)(100902);
std::cout << "Error string for value 100902: \"" << str << "\" (0x" << static_cast<const void*>(str) << ")" << std::endl;
}
else
{
std::cerr << "Failed to load function " << funcName << std::endl;
}
FreeLibrary(dllHandle);
return 0;
}
When I run the executable and point it to glu32.dll in the System32 folder, I get expected output:
> GLU32Loader.exe "C:\Windows\System32\glu32.dll"
Attempting to load: C:\Windows\System32\glu32.dll
Successfully loaded DLL: 0x00007FFC7A350000
Looking up function: gluErrorString
Successfully loaded function: 0x00007FFC7A35C650
Error string for value 100902: "out of memory" (0x000001E5757F51D0)
However, if I copy the DLL to my desktop and run the program again, although the DLL and function appear to be loaded, the string returned from the function is empty:
> GLU32Loader.exe "C:\Users\Jonathan\Desktop\glu32.dll"
Attempting to load: C:\Users\Jonathan\Desktop\glu32.dll
Successfully loaded DLL: 0x00007FFC8DDB0000
Looking up function: gluErrorString
Successfully loaded function: 0x00007FFC8DDBC650
Error string for value 100902: "" (0x0000025C5236E520)
Why would this be? It's exactly the same DLL, just in a different folder, and I would have thought that any other dependent DLLs that it references should still be available because they're all in System32. Is there some mystical property of Windows DLLs that I'm not familiar with that might cause this to happen?
This is an example of why one shall not mess around with system DLLs.
The DLL in question, like many Microsoft DLLs, uses MUI (Multilingual User Interface).
If you look at its resources, it has no resources except a MUI type resource, pointing to a folder containing the corresponding .mui file, which contains its actual (internationalized) resources.
So, if you still want to copy it, at least also copy the corresponding .mui file:
System32\glu32.dll → <my_files>\glu32.dll
System32\en-US\glu32.dll.mui → <my_files>\en-US\glu32.dll.mui
The en-US part may be different on your system depending on the default locale.
EDIT: I saw only now from your log that you didn't rename the file. Then I'm not sure what it can be. I'll leave this explanation up anyway because it would also be what happens if one were to rename that file, so maybe it is helpful to someone else...
It seems to me as if you renamed the DLL file (not just loaded it from another location but with another filename as well).
glu32.dll doesn't like to be renamed, because in some places code like GetModuleHandle("glu32.dll") is used instead of saving the hInstance received in DllMain into a global variable and using that handle (which is what should have been done, but unfortunately it isn't what Microsoft did). If you rename the DLL, this call will return NULL. Now unfortunately there also isn't much error handling going on in glu32 in that case.
The error strings are stored in global arrays of some sort, but they are lazy-loaded there from string table resources. The first time you call gluErrorString, the error strings are loaded using LoadString which takes the hInstance of the DLL. With the renamed DLL, this will be the bogus NULL handle, and calling LoadString(NULL, ...) will return 0, indicating an error. Normally the number returned is the length of the string. glu32 doesn't handle the zero case in any special way and just copies the zero characters to the array and happily returns an empty string to you at the end.
fork() creates a new process by duplicating the calling process in the separate memory space. The execution of the forked process can be checked by checking the pid_t returned value by fork() function.
I used fork() to create some concurrent processes from a single parent. These processes are commands in a shell that no need to be executed.
I'm wondering how I can check whether the command is a valid command that can be executed or not without using the system functions and/or execute them.
#include <iostream>
#include <unistd.h>
#include <string>
int main(){
std::string command = "/bin/ls";
//std::string invalidCommand = "/bin/123";
pid_t pid = fork();
if(pid == -1 || `here I want to check if the command is executable without execution`){
std::cout << "Error in forking or Command is not executable" << std::endl;
}
else if (pid == 0){
std::cout << "Process has been forked and valid to execute" << std::endl;
}
return 0;
}
These processes are commands in a shell that no need to be executed.
I don't fully understand what you want to say with this sentence. However, I think you are not aware how fork() works and how system() is related to fork():
As you already found out, fork() duplicates a running process; this means that the program is now running twice and all variables exist twice (just like if you run your program twice).
system() internally uses fork() to create a copy of the process; in the newly created process it uses one of the exec() variants (such as execvp()) to replace the program in the new process by another program.
Then it uses one of the wait() variants (such as waitpid()) to wait for the new process to finish:
fflush(stdout);
fflush(stderr);
int newpid = fork();
if(newpid == 0)
{
execlp("ls", "ls", "./subdirectory", NULL);
std::cerr << "Could not start \"ls\".\n";
fflush(stderr);
_exit(1);
}
if(newpid < 0)
{
std::cerr << "Not enough memory.\n";
}
else
{
int code;
waitpid(newpid, &code, 0);
if(code == 0) std::cout << "\"ls\" was successful.";
else std::cout << "\"ls\" was not successful.";
}
If you want to have "special" behaviour (such as re-directing stdout to a file), you typically don't use the system() function but you will implement the program the way it is shown above.
I'm wondering how I can check whether the command is a valid command ...
Without running the program it is nearly impossible to find out if some command is executable:
It is possible to find out if a program with some name (e.g. "/usr/bin/ls") is existing and marked as executable using the access() function (this is what command -v or test -x do).
However, this test will not detect if a file mistakenly has the x flag set although the file is a document file and not a program. (This is often the case for files on Windows-formatted media.)
If wait() returns the value passed to the _exit() function, it is also difficult to check if the reason is that exec() failed (this means that the program could not be executed) or if the program that has been started returned the same code that we use in our _exit() function.
You can send some information from the new process to the original process if the exec() function has returned. The exec() function will never return on success. However, sending this information is not that easy: Just setting a variable will not work:
int ls_failed = 0;
int pid = fork();
if(pid == 0)
{
execlp("ls", "ls", "./subdirectory", NULL);
ls_failed = 1;
_exit(1);
}
wait(pid, NULL, 0);
if(ls_failed > 0) std::cout << "Starting \"ls\" failed.";
The two processes behave like you started the programs twice; therefore both processes have their own variables, so the variable ls_failed in the newly started process is not identical to the variable ls_failed in the original process.
std::cout << ...
Please note that std::cout probably internally performs an fwrite(...,stdout). This function will not write directly to the terminal but it will write to some buffer. When the buffer is full, all data is written at once.
When calling fork() the buffer is duplicated; when using _exit() or exec(), the data in the buffer is lost.
This may lead to weird effects:
std::cout << "We are doing some fork() now.";
int pid = fork();
if(pid == 0)
{
std::cout << "\nNow the child process is running().";
_exit(0);
}
waitpid(pid, NULL, 0);
std::cout << "\nThe child process has finished.\n";
Depending on the buffer size we could get the following output:
We are doing some fork() now.
Now the chi ng some fork() now.
The child process has finished.
Therefore, we should perform a fflush(stdout) and a fflush(stderr) before using fork(), an exec() variant or _exit() unless you know that the corresponding buffer (stdout for std::cout and stderr for std::cin) is empty.
you can use the system call wait and check the return value of the command that you attempted to execute, other than that fork would really help you. try reading the man page of wait.
https://www.man7.org/linux/man-pages/man2/wait.2.html
I'm creating a simple HACK for educational purpose only. A simple Triggerbot that reads from memory the value of player aiming to enemy YES = 1 or NO = 0. I have made some other similar HACKS however I never found this problem .. in Rainbow Six Siege I have the memory address both static or dynamic however cheat engine read it well but when I try to read it from my C++ Program it does't work. Not sure why if it had work with other games. I'm new to this and maybe I did something wrong.
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#define F6Key 0x75
using namespace std ;
int value ;
int main()
{
cout << "Open Game .." << endl ;
system("Pause") ;
LPCWSTR gameone = L"Rainbow Six";
HWND hwnd = FindWindow(0, gameone);
if (gameone == 0)
{
cout << "Not Found." << endl ;
system("Pause") ;
}
else
{
cout << "Success finding game." << endl;
DWORD processid ;
GetWindowThreadProcessId(hwnd, &processid) ;
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid) ;
cout << processid ;
if (!ReadProcessMemory(process, (void *)0x25421AD9D6C, (void *)&value, sizeof(value), NULL)) {
cout << "Unable to read memory proccess";
}
else {
cout << "\n Read: " << value;
}
system("Pause");
}
return 0 ;
}
Here is the code simple Find the Window by name, gets its PID fine no problem. OpenProcess then when I call the method ReadProcessMemory with the process, address pointer value by parameter is unable to read it print the if condition and never the else of value read.
If I remove the function from the If condition just for testing if at least points to something it gives some random values... is weird that I'm unable to read memory It always work ::(
Can someone help me out? It is some king of security software or something?
First of all, you have to check OpenProcess return value. If your process does not have sufficient rights, it will return NULL and any attempts to use this handle will fail. Use GetLastError function to determine error reason.
Most likely it will be ERROR_ACCESS_DENIED.
Secondary, to successfully access external process memory space, you should open its handle with PROCESS_VM_READ right or enable seDebugPrivilege for you process token. Example how to do that you could see in the MSDN.
And lastly. If memory address (0x25421AD9D6C in your case) is invalid, ReadProcessMemory will fail. In that case value variable would not be initialized and any attempts to use it is an undefined behavior.
Also, if you managed to get process handle, it should be closed using CloseHandle function when you finish using it.
Upd: If ReadProcessMemory returns FALSE and GetLastError - ERROR_PARTIAL_COPY that means that a page fault has occured, you are trying to read from a buffer and at least part of it is not assigned to the physical memory. If you know your value offset, get module load address using PSAPI GetModuleInformation function and add offset to the lpBaseOfDll field of the MODULEINFO structure.
I'm trying to implement OpenCV into my application but every time I call a function there is a memory leak. I guess it has something to do with how I have used the library with Visual Studio but I tested it with a blank project and it seemed to work fine with the same settings.
The code I'm trying to implement into:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize Microsoft Foundation Classes, and print an error if failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// Application starts here...
// Time the application's execution time.
TIMER start;
// CODE TO GO HERE!
TIMER end;
TIMER elapsed;
elapsed = end - start;
__int64 ticks_per_second = start.get_frequency();
// Display the resulting time...
double elapsed_seconds = (double)elapsed.get_time() / (double)ticks_per_second;
cout << "Elapsed time (seconds): " << elapsed_seconds;
cout << endl;
cout << "Press a key to continue" << endl;
char c;
cin >> c;
}
return nRetCode;
}
If I implement something as simple as:
cv::Mat aVar;
in the space where I have put "CODE TO GO HERE!" Visual Studio says there is a memory leak once the program has terminated. Any ideas what the problem could be?
Like I said in your last post, the details are important. The non-MFC dll loads before MFC dll and if there is any data not freed before MFC exits, MFC falsely reports this as a memory leak. This is a known issue which is a problem when using opencv with mfc. The solution is to:
Static link MFC library (most common way)
Try the workaround to force mfc dll to be loaded first in the link above
Delay loading dlls as seen in this question.
I've noticed in the debug version that the combination of MFC and OpenCV can also result in strange behavior when you additionally use fopen and fread. fread might return error 9 (The storage control block address is invalid).
Again, delayed loading the OpenCV dlls might solve the problem.
CreateFile allocates 2(!!) handles and CloseHandle closes only one handle when trying to get the low-level access to cd-rom device. OS Windows XP SP3, 5 of 7 tested computers works the same.
When trying to access hdd drive letter CreateFiles works OK and allocate only one handle.
Here is the sample code:
HANDLE m_driveHandle = CreateFileW("\\\\.\\E", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(m_driveHandle);
What is the possible reason or it's just a microsoft bug?
Upd. The drive name was'nt cut&pasted.. The right string is L"\\.\E:". Bug still persists.
Upd2. Problem solved! See the answer below from me (omega).
There seem to be a few bugs in your sample code. If it was in fact copy & pasted from your program, then there would have to be something else going on.
First, you're calling a Unicode function with a MBCS string: the first argument should either be prepended with L or surrounded with _T().
Second, and perhaps more importantly, "\\\\.\\E" is not a valid name. You're missing a trailing colon: for opening a volume, it needs to be of the form \\.\X:, or in your case "\\\\.\\E:".
After fixing those two bugs (the first preventing compilation, the second required to get anything other than INVALID_HANDLE_VALUE back), everything seemed to be working as expected. I used GetProcessHandleCount to count the number of open handles, and it was the same before and after:
HANDLE m_driveHandle = NULL;
HANDLE m_process = GetCurrentProcess();
DWORD handleCount;
GetProcessHandleCount(m_process, &handleCount);
cout << "Currently held handles: " << handleCount << endl;
for (int i = 0; i < 10; ++i) {
m_driveHandle = CreateFileW(L"\\\\.\\E:",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (INVALID_HANDLE_VALUE == m_driveHandle) {
cout << "Invalid handle" << endl;
} else {
CloseHandle(m_driveHandle);
}
GetProcessHandleCount(m_process, &handleCount);
cout << "Currently held handles: " << handleCount << endl;
}
Commenting out the CloseHandle call causes handleCount to increment as expected, as well.
The problem was in the Kaspersky Antivirus software. KAV 6.0 was installed on all tested machines. After removing the software it is needed to clear the UpperFilters and LowerFilters for the cd-driver in the registry:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}
Only after this steps handles stop leaking..
A newest version of the software, Kaspersky Internet Security, also works without leaking.
Suggestion:
Put log begin at call CreateFileW, this confirm how many times it is executed;
Have you tried SysInternals' "Handle" tool ? It can show you every handle opened by your program, not just a count. Hence, you'll know which handle remains open.