Handle leaking in WinAPI CreateFile? - c++

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.

Related

Unload dll from process

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.

Readprocessmemory in C++ won't read

I have been coding for a few years now, but in 2016 I took a couple years off. Now I decided to come back, so I wanted to play around with some reverse engineering.
I played around with a game called Black Ops 1: Zombies. I found the memory addresses, then I went into C++ to code a simple cheat for unlimited ammo (This is offline), but it didn't work, so tried using ReadProcessMemory instead to see if it gives the correct ammo. The console started printing out "0". I thought there might been something with the code so I looked up some of my older source code, and the code was the same, tried installing VS 2015 instead in case the compiler is the problem, still nothing, tried GNCC compiler, still nothing. Tried using it on my second computer and it worked. I tried disabling Anti-Virus and windows defender but still nothing.
Here is the source code if it means anything:
#include <iostream>
#include <Windows.h>
using namespace std;
DWORD Address = 0x180A6C8;
DWORD pID;
int points;
int main()
{
while (true)
{
HWND hWnd = FindWindowA(0, ("Call of Duty®: BlackOps"));
GetWindowThreadProcessId(hWnd, &pID);
HANDLE pHandle = OpenProcess(PROCESS_VM_READ, FALSE, pID);
ReadProcessMemory(pHandle, (LPVOID)Address, &points, sizeof(points), 0);
cout << points << endl;
Sleep(100);
}
}
A.) Can you read the Address in Cheat Engine etc
B.) Does it require a base address (e.g "client.dll")? If so get the module base address of the required module.

C++ Unable to Read Memory Address

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.

How Do I Get mciSendString to Work With Both Variables and Spaces?

I have created a program that plays music in my music directory and supports spaces, thanks to the help of Google. However, I don't want to keep hard-coding the song names, so I'm wondering if I can replace the file name with a variable, and std::cin the variable when my program is run. However, I also want to be able play songs that have spaces in their names. I made a wrapper function (I think that this would count as one?) for mciSendString, and I'm trying to be able to pass a "name" parameter to it for it to play. However, due to complications with LPCWSTR and std::string, among other things, I'm having difficulty implementing this.
Here's my current music function:
void Music(std::string strSongName,DWORD dwExtraFlag)
{
MCIERROR me =
mciSendString(TEXT("open \"D:\\Windows.old\\Users\\MyName\\Desktop\\Sounds\\Music\\song name.mp3\""" type mpegvideo alias song1"),
NULL, 0, 0);
/*
note that I want to be able to play songs
with spaces in their name
*/
if (me == 0)
{
me = mciSendString(TEXT("play song1 wait repeat"), NULL, 0, 0);
mciSendString(TEXT("close song1"), NULL, 0, 0);
}
}
What I want it to be like:
void Music(std::string strName,DWORD dwExtraFlag)
{
MCIERROR me =
mciSendString(TEXT("open \"D:\\Windows.old\\Users\\MyName\\Desktop\\Sounds\\Music\\STRNAMEVARIABLEHERE.mp3\""" type mpegvideo alias song1"),
NULL, 0, 0);
/*
note that I want to be able to play songs
with spaces in their name
*/
if (me == 0)
{
me = mciSendString(TEXT("play song1 wait repeat"), NULL, 0, 0);
mciSendString(TEXT("close song1"), NULL, 0, 0);
}
}
I would then make a variable in main or some other function and std::cin into that variable.
std::string strNameOfSong = "";
std::cin >> strNameOfSong;
Then, I would call music like:
Music(strNameOfSong,0)
I would also like to mention that you can ignore the "dwExtraFlags" argument if you wish, it is something that I have yet to implement.
Anyways, I would really appreciate help implementing this as I am new to C++. However, I don't want to leave this project unfinished, and I wish to complete it before moving on.
I would greatly appreciate any solutions, help, or tips. If you want me to be more specific or provide any more information to help you formulate an answer, I would be glad to do so.
Thank you very much.
EDIT: I implemented Ethan's suggestion. After adding some things in and adding his suggestion, my program stops working shortly after typing in the name of the song I want. I've tried debugging and it reports:
"Exception thrown at 0x00047430 in Program.exe: 0xC0000005: Access violation writing location 0x6563696E."
Here's what I added into my main function (aside from Ethan's suggestion):
static std::string strSongName = "";
std::cin >> strSongName;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&Music, &strSongName, 0, 0);
// The above is to createthread so I can play music while doing other things
Debugging, the values seem to be correct. However, I suddenly get that exception and the application stops working. How can I have an access violation?
Another small change that I made to Ethan's suggestion:
MCIERROR me =
mciSendString((LPCWSTR)(songFile.c_str()), NULL, 0, 0);
(I typecasted SongFile as it was giving me errors)
I also changed the example of the path back to normal.
EDIT2:
Fixed the exception! It was because I (in a silly manner), forgot to dereference the pointer to "strSongName". However, anything after the space still isn't recognized, it seems, as I debugged it. It also doesn't seem to play songs even when they do not have a space, and yes I am adding .mp3 too.
How about this one?
void Music(std::string strName,DWORD dwExtraFlag)
{
std::string songFile = "open \"D:\\Windows.old\\Users\\MyName\\Desktop\\Sounds\\Music\\";
songFile += strName + "\" type mpegvideo alias song1";
MCIERROR me =
mciSendString(songFile.c_str(), NULL, 0, 0);
/*
note that I want to be able to play songs
with spaces in their name
*/
if (me == 0)
{
me = mciSendString(TEXT("play song1 wait repeat"), NULL, 0, 0);
mciSendString(TEXT("close song1"), NULL, 0, 0);
}
}

Arguments being passed to CreateProcess aren't being parsed as I expected

I'm trying to use devcon.exe to check the status of various pieces of hardware. In the example I'm trying to check my SATA HBA status but devcon is whining about it. Here's the code:
int main(int argc, char** argv) {
std::string cmdLine("\"C:\\Users\\afalanga\\Documents\\Visual Studio 2010\\Projects\\PlayGround\\Debug\\devcon.exe\" status PCI\\VEN_8086^&DEV_3A22^&SUBSYS_75201462^&REV_00");
char* pCmdLine(new char[cmdLine.length() + 10]);
memset(pCmdLine, 0, cmdLine.length() + 10);
for(int i(0); i < cmdLine.length(); i++)
pCmdLine[i] = cmdLine.at(i);
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi = {0};
if(!CreateProcess(NULL, pCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
std::cout << "Create child process failed. Error code: "
<< GetLastError() << std::endl;
return 1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
The problem is that when the above executes, devcon complains that, "No matching devices were found." However, if I copy/paste that command line from the debugger into my command prompt and hit the enter key (or course deleting the all encompassing quotes that the debugger puts around it), the command executes perfectly as expected.
What am I getting wrong in my handing of the string? What's above is the result of reading the CreateProcess() docs on MSDN (found out that the first argument isn't necessarily needed and the cmd args shouldn't go there at all). The reason I'm allocating 10 extra bytes of memory to copy the string into is so that "whatever" may change down in the guts of the CreateProcess() function can do so without stomping on other memory. At least, that was my thought when I did that.
Command line metacharacters are parsed by the command processor. In particular you are using the ^ to prevent CMD.EXE from breaking the command at the ampersand. But you are executing the program directly, bypassing CMD.EXE. Therefore, the ^ passes through to devcon.exe who gets confused by them.
Solution: Remove the ^ characters.
Your problem is actually the opposite of your title. The command line you passed to CreateProcess is being passed directly to the application exactly as you specified it.
std::string cmdLine("\"C:\\Users\\afalanga\\Documents\\Visual Studio 2010\\Projects\\PlayGround\\Debug\\devcon.exe\" status PCI\\VEN_8086^&DEV_3A22^&SUBSYS_75201462^&REV_00
Presumably the ^ carets in there are residues from a command entered in the command line interpreter, where they serve to turn off the special meaning of &.
Simply remove the carets.
Also note that your current code leaks memory.
To avoid that, do e.g.
string commandLineArg = cmdLine + '\0';
... CreateProcess( 0, &commandLineArg[0], ... )
Can you try like this:
CreateProcess(NULL, pCmdLine.c_str(), ...);
I used:
TCHAR var[] = _T(" C:\\filepathe\\foo");
CreateProcess(NULL, var,...);