Short version:
I am trying to open a process descriptor with debug privileges and determine a pointer that points to an object in debuggee memory.
Long version
I graduated from a computer science university in my last year of study and was given the task of creating an application that should be used for educational purposes for the next generation of students.
Why am I asking for help here, you ask? Well, the target platform is Windows, and I, unfortunately, do not know about WinAPI at all ...
Ok, here is the basic requirement:
- Programming Language : C ++
- Platform : Windows (7 Professional)
- IDE Used : Visual Studio 2012
- There are no additional libraries if they are not essential to facilitate development.
What will the application be used for?
Using this application, students must learn how to handle addresses, in this case static: the debuggee process will have some static pointers that lead to other pointers to form a multidimensional pointer. Students should find these base addresses using some debugging methods (which are not part of my work!) And try to find the values ββat the end of these pointers.
My application will be used by teachers to randomly change values ββand / or structures during the debuggee process.
Some searches gave the first answer: using ReadProcessMemory and WriteProcessMemory you can easily change the values ββin the memory of another process without having to obtain debug privileges.
However, my teachers want to be able to define pointers (let say unsigned int) that should point to the memory space of the debuggee process, effectively preserving the base addresses that I wrote about earlier. They really want it, and I couldn't even talk about it, so I was stuck to do it at the end ...
And what exactly should work?
Well, I would complete my task if the following (pseudo) code works:
grantThisProcessDebugPrivileges(); openAnotherProcessWhileItsRunning("targetProcess.exe"); unsigned int * targetValue = (unsigned int*) 0xDE123F00;
where the address 0xDE123F00 is in the targetProcess.exe memory space.
I know that this is possible, otherwise there would be no debuggers that could show this information.
What have I done so far (or tried ...)
Well, the thing is that I am really confused if I should activate debug privileges for my application before by opening the target process, doing it after opening, or rather by giving the target process these privileges.
So, I found an example on MSDN and tried to implement it:
BOOL SetPrivilege( HANDLE hToken, // token handle LPCTSTR Privilege, // Privilege to enable/disable BOOL bEnablePrivilege // TRUE to enable. FALSE to disable ) { TOKEN_PRIVILEGES tp; LUID luid; TOKEN_PRIVILEGES tpPrevious; DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES); if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; // // first pass. get current privilege setting // tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious ); if (GetLastError() != ERROR_SUCCESS) return FALSE; // // second pass. set privilege based on previous setting // tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid; if(bEnablePrivilege) { tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); } else { tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); } AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL ); if (GetLastError() != ERROR_SUCCESS) return FALSE; return TRUE; };
And basically:
HANDLE mainToken; // I really don't know what this block of code does :< if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &mainToken)) { if (GetLastError() == ERROR_NO_TOKEN) { if (!ImpersonateSelf(SecurityImpersonation)) return 1; if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &mainToken)){ cout << GetLastError(); return 1; } } else return 1; } if (!SetPrivilege(mainToken, SE_DEBUG_NAME, true)) { CloseHandle(mainToken); cout << "Couldn't set DEBUG MODE: " << GetLastError() << endl; return 1; }; unsigned int processID = getPID("targetProcess.exe"); HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID); if (hproc == NULL) { cout << "Couldn't open the process" << endl; return 1; }; unsigned int * theValue = (unsigned int*) 0xDE123F;
Well, this code works without any errors, SetPrivilege returns TRUE, so I think it really set SE_DEBUG_NAME , which I think is the flag I need to set.
But after - for example - the dereferenced value of theValue is output, the application crashes with an access violation message that indicates that my approach is not working. I especially drew attention to starting VisualStudio Debugger with administrator privileges (otherwise SetPrivilege failed).
I'm really shameless, the fact that I don't know if setting SE_DEBUG_NAME right approach adds to my general confusion.
I hope you can help me :) My hands are connected with specific requests of the application, if you have ideas for achieving my goal, using the whole tidy approach, you can tell me about it, but I will not be able to introduce it to the authorities so that it will only add as far as I know: D