I don't know what something wrong with my code. i already put condition when the handle is invalid. it will CloseHandle. but it seems not work. this code trying to get processName. when i input exist PID. it return the processName. opposite when i input doesn't exist PID like 10000. it return handle is invalid. and Error Exception throw. but in my code i already put condition when invalid. it will Close Handle.
std::wstring GetProcessNameById(DWORD i_processId)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
if (hProcess != NULL)
{
wchar_t processFilePath[MAX_PATH];
if (GetModuleFileNameExW(hProcess, NULL, processFilePath, MAX_PATH))
{
CloseHandle(hProcess);
wchar_t *processFileName = PathFindFileNameW(processFilePath);
return processFileName;
}
else
{
CloseHandle(hProcess);
SystemErrorMessage();
}
}
else
{
CloseHandle(hProcess);
SystemErrorMessage();
}
}
int main()
{
std::wcout << GetProcessNameById(10000);
return 0;
}
A compact version of your code makes the bug obvious:
if (hProcess != NULL)
{
// Left out for brevity
}
else
{
// Here, hProcess is NULL
CloseHandle(hProcess);
SystemErrorMessage();
}
In essence, this is calling CloseHandle(NULL);, presumably setting the thread's last error code to ERROR_INVALID_HANDLE. SystemErrorMessage() probably blindly calls GetLastError (without evaluating whether it should), and throws an exception if the value returned is anything other than ERROR_SUCCESS.
To fix this, you need to fix the logic bug (remove the call to CloseHandle in the else branch, in which you know hProcess to be invalid). When done, rework your entire error handling. It won't work reliably. You cannot blindly call GetLastError, anytime an API call failed. When done with that, study the RAII idiom, so that you won't have to write manual cleanup code, like you would have to do with C.
Related
I have created a folder with CreateDirectoryW to which I haven't got access. I used nullptr as a security descriptor, but for some reason it didn't copy the parent folder's ACLs, but instead made the folder inaccessible.
I can't view or change the owner. takeown, icacls, SetNamedSecurityInfoW, all from elevated processes or command prompts, fail with ERROR_ACCESS_DENIED.
Do I have any chance of deleting this folder in Windows (Shell or C++) before trying a Linux live CD which hopefully doesn't care about the ACLs?
You just need to enable backup (or restore) privilege:
#include <Windows.h>
#include <stdio.h>
int wmain(int argc, wchar_t ** argv)
{
// argv[1] must contain the directory to remove
HANDLE hToken;
struct
{
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[1];
} tkp;
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE,
(PTOKEN_PRIVILEGES)&tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
{
printf("AdjustTokenPrivileges: %u\n", GetLastError());
return 1;
}
if (GetLastError() != ERROR_SUCCESS)
{
// This happens if you don't have the privilege
printf("AdjustTokenPrivileges: %u\n", GetLastError());
return 1;
}
CloseHandle(hToken);
}
if (!RemoveDirectory(argv[1]))
{
printf("RemoveDirectory: %u\n", GetLastError());
return 1;
}
printf("OK\n");
return 0;
}
Note that in the interests of conciseness, some error handling has been omitted. Also note that AdjustTokenPrivileges() is one of the few special cases where calling GetLastError() is meaningful even though the call succeeded; it will return ERROR_SUCCESS or ERROR_NOT_ALL_ASSIGNED depending on whether you actually have all of the privileges you were attempting to enable.
This is a fairly general solution for bypassing security permissions on files. It works for most API calls, although in some cases (most notably CreateFile) you must provide a special flag in order to make use of backup privilege. As well as deleting files or removing directories that you don't have permission to, you can change attributes, change permissions, and even assign ownership to somebody else, which is not otherwise permitted.
assume that file not open with incompatible to delete share flags and no section on file.
for delete file enough 2 things - we have FILE_DELETE_CHILD on parent folder. and file is not read only. in this case call ZwDeleteFile (but not DeleteFile or RemoveDirectory - both this api will fail if file have empty DACL) is enough. in case file have read-only attribute - ZwDeleteFile fail with code STATUS_CANNOT_DELETE. in this case we need first remove read only. for this need open file with FILE_WRITE_ATTRIBUTES access. we can do this if we have SE_RESTORE_PRIVILEGE and set FILE_OPEN_FOR_BACKUP_INTENT option in call to ZwOpenFile. so code for delete file can be next:
NTSTATUS DeleteEx(POBJECT_ATTRIBUTES poa)
{
NTSTATUS status = ZwDeleteFile(poa);
if (status == STATUS_CANNOT_DELETE)
{
BOOLEAN b;
RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &b);
HANDLE hFile;
IO_STATUS_BLOCK iosb;
if (0 <= (status = NtOpenFile(&hFile, FILE_WRITE_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT)))
{
static FILE_BASIC_INFORMATION fbi = {{},{},{},{}, FILE_ATTRIBUTE_NORMAL};
status = ZwSetInformationFile(hFile, &iosb, &fbi, sizeof(fbi), FileBasicInformation);
NtClose(hFile);
if (0 <= status)
{
status = ZwDeleteFile(poa);
}
}
}
return status;
}
I'll try to explain my problem the best I can.
I'm trying to access to a memory-protected process memory (Minesweeper).
I'll put my code first and then I'll explain what's the thing I want to archieve. (If you read everything and know another way to do this, please post it).
First, the getProcessHandle, a function that returns a open handle to the process with name procName.
It works perfectly, and I can list all the processes.
HANDLE getProcessHandle(const wchar_t *procName){
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 procEnt;
procEnt.dwSize = sizeof(PROCESSENTRY32);
Process32First(snap, &procEnt);
printf("--Listando procesos...\n");
do{
printf("Process name: %S \n", procEnt.szExeFile);
if (!wcscmp(procName, procEnt.szExeFile)){
printf("Encontrado %S.\n\n", procName);
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEnt.th32ProcessID);
}
} while (Process32Next(snap, &procEnt));
printf("No se ha encontrado el proceso.");
CloseHandle(snap);
return NULL;
Second, the getModule function. Its work should be finding and enumerating all the modules in the process passed as a HANDLE.
HMODULE getHModule(HANDLE procHandle, const wchar_t *procName){
HMODULE moduleHandle[1024];
DWORD bytesNeeded;
unsigned int i = 0;
if (EnumProcessModulesEx(procHandle, moduleHandle, sizeof(moduleHandle), &bytesNeeded, LIST_MODULES_ALL)){
printf("--Modulos del proceso:\n");
for (i = 0; i < (bytesNeeded / sizeof(HMODULE)); i++){
TCHAR pathModule[1024];
GetModuleBaseName(procHandle, moduleHandle[i], pathModule, sizeof(pathModule) / sizeof(TCHAR));
if (!wcscmp(procName, pathModule)){
printf("Encontrado modulo %S.", procName);
return moduleHandle[i];
}
printf("Module %d: %S \n", i + 1, pathModule);
}
printf("No se ha encontrado el modulo.");
return NULL;
}
else {
printf("Error en EnumProcessModulesEx n: %ls", GetLastError());
}
return NULL;
And the problem comes here. When I try to enumerate all the modules in the process, if the process is a normal process, I mean, a not-memory-protected process, it works perfectly.
The problem is when the process is memory-protected.
At this point, I decided to search, and I discovered the Privilege Tokens. It's said that if I get the SE_DEBUG_NAME token activated, my process could surpass the protection, so, I've done that function:
int privileges(){
HANDLE token;
TOKEN_PRIVILEGES tp;
DWORD siz = sizeof(TOKEN_PRIVILEGES);
if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &token) != 0){
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(token, 0, &tp, siz, NULL ,NULL) != 0){
cout << "--Conseguido acceso debug.\n";
return TRUE;
}
else {
cout << "fail adjust\n";
return FALSE;
}
}
else {
cout << "fail if: " << GetLastError() << endl;
cin.get();
return FALSE;
}
And the "main" function:
int _tmain(int argc, _TCHAR* argv[])
{
privileges();
wchar_t *processName = _T("calc.exe");
HANDLE hProc = getProcessHandle(processName);
if (hProc){
HMODULE hMod = getHModule(hProc, processName);
cout << hMod;
}
cin.get();
return 0;
}
The problem I have right now is, when I execute this function, privileges(), it returns the ERROR_NO_TOKEN code number.
Someone here said me to change the OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &token) for an OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token), and that causes no problem, neither result, with that fix, I have the same problem as if privileges() is not executed.
Thanks for reading all the text, and, if is there another way to do this, please tell me, I'm trying to learn.
The documentation for EnumProcessModulesEx says:
This function is intended primarily for 64-bit applications. If the function is called by a 32-bit application running under WOW64, the dwFilterFlag option is ignored and the function provides the same results as the EnumProcessModules function.
Going to the documentation for EnumProcessModules, we find:
If this function is called from a 32-bit application running on WOW64, it can only enumerate the modules of a 32-bit process.
So to work on a 64-bit process, your code will have to be 64-bit itself.
The documentation continues:
If the process is a 64-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
It seems that this may be incorrect, since you were receiving a access violation exception instead.
Write ImpersonateSelf(SecurityImpersonation); like here:
ImpersonateSelf(SecurityImpersonation);
OpenThreadToken
(
GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&token
);
The ImpersonateSelf makes function obtains an access token that impersonates the security context of the calling process. The token is assigned to the calling thread.
To see all the SECURITY_IMPERSONATION_LEVELs click here
Program below is a synchronization between two threads using a Mutex.
It compiles, works and prints what I want in order(alternating R/W for the 2 threads), but it crashes after it's done. Any idea why?
I think it has to do with closing TName handle, if I comment that part it doesn't crash, but I'd like to close opened handles.
HANDLE hMutex, hWriteDone, hReadDone;
int num, state;
void Writer()
{
for(int x=10; x>=0; x--)
{
while (true)
{
if (WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
{
std::cout<<"In writing loop, no mutex!\n";
ExitThread(0);
}
if (state == 0)
{
ReleaseMutex(hMutex);
WaitForSingleObject(hReadDone, INFINITE);
continue;
}
break;
}
std::cout<<"Write done\n";
num= x;
state= 0;
ReleaseMutex(hMutex);
PulseEvent(hWriteDone);
}
}
void Reader()
{
while(true)
{
if (WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
{
std::cout<<"In reader, no mutex!\n";
ExitThread(0);
}
if (state == 1)
{
ReleaseMutex(hMutex);
WaitForSingleObject(hWriteDone, INFINITE);
continue;
}
if (num == 0)
{
std::cout<<"End of data\n";
ReleaseMutex(hMutex);
ExitThread(0);
}
else {
std::cout<<"Read done\n";
state=1;
ReleaseMutex(hMutex);
PulseEvent(hReadDone);
}
}
}
void main()
{
HANDLE TName[2];
DWORD ThreadID;
state= 1;
hMutex= CreateMutex(NULL, FALSE, NULL);
hWriteDone= CreateEvent(NULL, TRUE, FALSE, NULL);
hReadDone= CreateEvent(NULL, TRUE, FALSE, NULL);
TName[0]= CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)Writer,
NULL, 0, &ThreadID);
TName[1]= CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)Reader,
NULL, 0, &ThreadID);
WaitForMultipleObjects(2, TName, TRUE, INFINITE);
CloseHandle(TName);
getchar();
}
You should never cast a function pointer. Remove the (LPTHREAD_START_ROUTINE) casts from your code, fix the compiler errors, and try again. Never use casts to quell compiler errors.
The lpStartAddress parameter of CreateThread is of type LPTHREAD_START_ROUTINE. Which is a function pointer compatible with this signature:
DWORD WINAPI ThreadProc(LPVOID lpParameter);
So you need to supply what the function expects. Your function Reader does not fit the bill. Change its signature to be like this:
DWORD WINAPI Reader(LPVOID lpParameter)
{
....
}
And likewise for Writer.
Every time you cast something to suppress a compiler warning you are trading an easy to diagnose compile time error for a hard to diagnose run time error. That's a very bad trade. So, as a general rule, don't use casts. Sometimes you'll need to break that rule, but do so in full understanding of what you are doing.
Your main function also has a somewhat bogus signature. If you don't want to process arguments, then you should declare it like this:
int main()
Since you ignore the thread ID, you may as well pass NULL for the final parameter of CreateThread.
This also is wrong:
CloseHandle(TName);
The parameter of CloseHandle is of type HANDLE. You are passing a pointer to an array. You need to do this:
CloseHandle(TName[0]);
CloseHandle(TName[1]);
The Writer function does not return a value. The compiler warns you about that, if you enable sufficient warnings. You should certainly do so.
Error message is: The instruction at "0x7c810eac" referenced memory at "0x00000000". The memory could not be "written".
If I remove the destructor everything is fine. But I do not understand what is happening here. Everywhere I read that I should close handles, but here code won't let me. (Yes I know that I can do it manually... but that is a unnecessary line in client code that I think should be handled by object.)
#include <windows.h>
#include <iostream>
#include <string>
struct fileHandle {
HANDLE hFile;
fileHandle(std::string path) {
hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("error: INVALID_HANDLE_VALUE");
}
}
~fileHandle() {
CloseHandle(hFile);
}
void save(std::string data) {
if (!WriteFile(hFile, data.c_str(), data.size(), NULL, NULL)) {
printf("WriteFile failed: ", GetLastError());
}
}
};
int main() {
fileHandle my_handle("test_file.txt");
my_handle.save("some text");
}
Update: this happens when file doesn't exist. When file do exist program print errors, but this is intended. I'm here asking co cover only this case when file is created (I know how to rewrite handle creating to cover existing file.)
compiler: http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev7.7z
Update 2: I didn't mention that this code works and writes to file. Memory error is triggered at the very end.
Please compile all your code with -Wall. Saves a whole lot amount of time.
In your code printf which has an invalid format string. Correct solution for printf would be (notice the %lu):
void save(std::string data) {
if (!WriteFile(hFile, data.c_str(), data.size(), NULL, NULL)) {
printf("WriteFile failed: %lu", GetLastError());
}
}
If you would have compiled with -Wall, your code would have given the warning:
filehandle.cpp: In member function 'void fileHandle::save(std::string)':
filehandle.cpp:18:50: warning: too many arguments for format [-Wformat-extra-args]
Also you should print errors to stderr as it is unbuffered. printf uses buffers and that's why you did not get any output. Also a good idea to add a \n after the errors.
Also read the other answers to improve your code. Use the rule of three.
After reading the comment I realized that this is not the segfault reason indeed. (Also look at Ron Burk's solution to see what went wrong.)
According to the Windows API documentation, lpNumberOfBytesWritten parameter can be NULL only when the lpOverlapped parameter is not NULL.
So you have to give a pointer to a DWORD where WriteFile can store how many bytes it actually read. The final save would be:
void save(std::string data) {
DWORD writtenBytes;
if (!WriteFile(hFile, data.c_str(), data.size(), &writtenBytes, NULL)) {
printf("WriteFile failed: %lu", GetLastError());
}
}
If the file exists, the error does not pop up, because passing INVALID_HANDLE_VALUE to WriteFile seems to make WriteFile return earlier than it uses your pointer.
Wrong args to WriteFile(). 2nd to last argument can't be NULL. Change it to address of DWORD that you've set to 0 and all will work. It was dying in the kernel in WriteFile() as it tried to write back the # of bytes written.
The documentation for CloseHandle makes it clear why this happens:
If the application is running under a debugger, the function will throw an exception if it receives either a handle value that is not valid or a pseudo-handle value.
So, when your call to CreateFile fails, the subsequent call to CloseHandle will raise an SEH exception.
The solution is that your code must only call CloseHandle if the call to CreateFile succeeded.
As others point out, your use of WriteFile is wrong. I won't repeat the details here.
~fileHandle() {
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
You need to check that the file was correctly opened.
if (hFile != INVALID_HANDLE_VALUE) CloseFile(hFile);
You're not following the rule of three - so ownership of hFile is shared between copies of fileHandle because of the shallow, compiler generated copy-constructor and copy-assignment operator.
For example:
fileHandle my_handle("test_file.txt");
fileHandle my_second_handle = my_handle;
Which one of these should actually close the handle on destruction? The first? What will happen when the second one goes out of scope and calls the destructor?
In this case, I'd say you should disallow copying or assignment, or pinpoint ownership.
EDIT: In your snippet, the problem is probably the one pointed out by Ron, but this is still an important point.
That's not how I'd treat it though. I think if the file couldn't be opened, fileHandle shouldn't exist. What's the point of having an invalid object? I'd simply throw an exception in the constructor to disallow invalid objects, as opposed to doing the check in the destructor.
fileHandle(std::string path) {
hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
throw std::exception("file not found");
}
}
to be on the safe side, use
~fileHandle()
{
if (hfile != INVALID_HANDLE_VALUE)
{
CloseHandle(hfile);
hfile = INVALID_HANDLE_VALUE;
}
}
I've been searching examples for the Win32 API C++ function TerminateProcess() but couldn't find any.
I'm not that familiar with the Win32 API in general and so I wanted to ask if someone here who is better in it than me could show me an example for,
Retrieving a process handle by its PID required to terminate it and then call TerminateProcess with it.
If you aren't familiar with C++ a C# equivalent would help too.
To answer the original question, in order to retrieve a process handle by its PID and call TerminateProcess, you need code like the following:
BOOL TerminateProcessEx(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (hProcess == NULL)
return FALSE;
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
Keep in mind that TerminateProcess does not allow its target to clean up and exit in a valid state. Think twice before using it.