Programmatically Setting Breakpoints on Multi-threaded 64-bit Applications - c++

I have adapted some code from other sources (primarily here) and had no avail in my circumstance. I am attaching to a 64-bit application that has upwards of 100 threads at any given time. There are two issues I have, somewhat unrelated:
Whenever the code hits DebugActiveProcess(pid), the attached application freezes.
The code I have only sets a breakpoint on the main thread, but I need it on more than one - ideally all.
I have confirmed that when the code hits SetThreadContext(hThread, &ctx) the dr0 and dr7 registers change as intended, so that much is fine. The only issues I can see right now are the process freezing and setting more than one breakpoint (I thought of iterating for every single thread which would be fine one-time, but when it gets into the while loop that would obviously be problematic and very resource-consuming). I should also note that I can attach the CheatEngine debugger to the application, and breakpoints work fine with no issues. Below is the code I'm using:
DWORD GetProcessThreadID(DWORD dwProcessID)
{
THREADENTRY32 te = { sizeof(THREADENTRY32) };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (Thread32First(hSnapshot, &te))
while (Thread32Next(hSnapshot, &te))
if (te.th32OwnerProcessID == dwProcessID)
return te.th32ThreadID;
return NULL;
}
BOOL SetDebugPrivilege(BOOL State)
{
HANDLE hToken;
TOKEN_PRIVILEGES token_privileges;
DWORD dwSize;
ZeroMemory(&token_privileges, sizeof(token_privileges));
token_privileges.PrivilegeCount = 1;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
return FALSE;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &token_privileges.Privileges[0].Luid))
{
CloseHandle(hToken);
return FALSE;
}
if (State)
token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
if (!AdjustTokenPrivileges(hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
{
CloseHandle(hToken);
return FALSE;
}
return CloseHandle(hToken);
}
void CreateBreakpoint(DWORD pid, DWORD64 addr) {
DebugActiveProcess(pid);
DebugSetProcessKillOnExit(false);
DWORD_PTR dwThreadID = GetProcessThreadID(pid);
std::cout << std::hex << dwThreadID << std::endl;
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
SetDebugPrivilege(true);
CONTEXT ctx = { 0 };
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_INTEGER;
ctx.Dr0 = addr;
ctx.Dr7 = 0x00000001;
SetThreadContext(hThread, &ctx);
DEBUG_EVENT dbgEvent;
while (true) {
if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
break;
if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) // EXCEPTION_BREAKPOINT
{
if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)addr)
{
GetThreadContext(hThread, &ctx);
std::cout << ctx.Rax << "\n";
ctx.Dr7 = 0;
SetThreadContext(hThread, &ctx);
}
}
ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
}
}
It may be worth noting that this is a C++ extension to a python script, but that shouldn't really be relevant, and even if I run the code standalone it runs into the same issues. Also, I'm not an expert in C++ so I apologize if there are any misunderstandings.

I agree with Taekahn, unless you give more information on what you are trying to do, why not use a normal debugger? if you just want to read the registers, any debugger can do that. You can even set breakpoints in disassembly or random addresses, or set data breakpoints.
IDK about gdb, but even in visual studio you can set conditions and actions on breakpoints. It's not as powerfull as c++ code but again, without more informations...
If you want to modify the behavior of the application, that's not how we do it, and using a debugger can actually cause issues.

Related

Logoff remote system using c++

I am looking for an API to logoff current user on remote computer. Two
functions ExitWindows and InitiateSystemShutdown seem not exactly what I
want. The first one doesn't accept computer name, the second one doesn't
have logoff option.is it possible to logoff current user
on remote computer ?. Can someone tell me how to achieve this in a
C++ program?
I knew that you want to shutdown system by using exitwindows function.
However, if you want to shut down the remote system in your own process, you need to use the exitwindowsEX function and write a program that specifies the process ID.
The relevant function references are as follows:
https://learn.microsoft.com/zh-cn/windows/win32/shutdown/how-to-shut-down-the-system
The following are specific codes:
#pragma region
#include<windows.h>
#pragma warning(disable:4996)
BOOL ReSetWindows(DWORD dwFlags, BOOL bForce)
{
if (dwFlags != EWX_LOGOFF && dwFlags != EWX_REBOOT && dwFlags != EWX_SHUTDOWN)
return FALSE;
OSVERSIONINFO osvi = { 0 };
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osvi))
{
return FALSE;
}
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
//EnableShutDownPriv();
}
dwFlags |= (bForce != FALSE) ? EWX_FORCE : EWX_FORCEIFHUNG;
return ExitWindowsEx(dwFlags, 0);
}
int main()
{
ReSetWindows(EWX_LOGOFF, false);//logoff
//ReSetWindows(EWX_REBOOT, true);//restart
//ReSetWindows(EWX_SHUTDOWN, true);//shutdown
}
=======================
Caution!!!Please save your important file before running or running in the virtual machine
WTSLogoffSession? but the concept of a current user on a remote machine does not really exist, you would have to inspect the sessions with WTSEnumerateSessions+WTSQuerySessionInformation if you want to find a specific user. This only makes sense in a environment where there is a NT domain so you can match against a domain SID. Without a domain, all you can do is match against the username which might be enough for you.
This is the program specifies the process ID:
DWORD GetProcessIDByName(LPCTSTR szProcessName)
{
STARTUPINFO st;
PROCESS_INFORMATION pi;
PROCESSENTRY32 ps;
HANDLE hSnapshot;
DWORD dwPID = 0;
ZeroMemory(&st, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
st.cb = sizeof(STARTUPINFO);
ZeroMemory(&ps, sizeof(PROCESSENTRY32));
ps.dwSize = sizeof(PROCESSENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)//
{
return dwPID;
}
if (!Process32First(hSnapshot, &ps))
{
return dwPID;
}
do
{
if (lstrcmpi(ps.szExeFile, szProcessName) == 0)
{
dwPID = ps.th32ProcessID;
}
} while (Process32Next(hSnapshot, &ps));
CloseHandle(hSnapshot);
return dwPID;//
}
You need this line of code in your main function:
DWORD pId = GetProcessIDByName("\\\.exe");
Closing remote system by local machine is easy. Closing local machine by remote machine sounds like a virus. No offense, it is difficult to implement. Maybe you can try using socket to communicate local machine with virtual machine.

OpenProcess Failure (SeDebugPrivilege?)

I'm trying to use OpenProcess, for some reason it keeps failing.
HANDLE GetProcessPid()
{
DWORD pid = 0;
wchar_t ProcessName[] = L"notepad.exe";
// Create toolhelp snapshot.
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
// Walkthrough all processes.
if (Process32First(snapshot, &process))
{
do
{
if (wcscmp(process.szExeFile, ProcessName) == 0)
{
pid = process.th32ProcessID;
break;
}
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
if (pid != 0)
{
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}
return NULL;
}
This always returns 0xcccccccccccccccc or 0x0000000000000020 even when I've set the pid manually when calling OpenProcess.
I've tried running as admin outside of debugging inside visual studio and get the same results, after searching, I think I need to enable debug priviledges (SeDebugPrivilege), how do I do this in visual studio 2013?
Your code is fine, you just need to run your executable as administrator and it works, I just tested it.

CreateToolhelp32Snapshot: INVALID_HANDLE_VALUE (ERROR_PARTIAL_COPY)

This code is running in a 64-bit application. The target application is 32-bit.
Every time I run this code, CreateToolhelp32Snapshot() returns INVALID_HANDLE_VALUE and then GetLastError() returns ERROR_PARTIAL_COPY. So it skips the loop and returns false.
BOOL HookInjector::InjectIntoProcess(DWORD pID)
{
//Get Handle to Remote Process
HANDLE Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
....
//Check to see if 64-bit or 32-bit application
IsWow64Process(Proc, &isWow64);
size_t szCurProc = sizeof(void*); //returns 8
if (isWow64)
{
__debugbreak();
//Get list of all Modules associated with the Process
HANDLE hProc32Module;
do {
hProc32Module = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32, pID);
}
while ((hProc32Module == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_BAD_LENGTH));
if (hProc32Module == INVALID_HANDLE_VALUE) {
__debugbreak();
DWORD err = GetLastError(); //just to see the error code which is 0x12b
return false;
}
//Find the module for Kernel.dll and get the base address of it
MODULEENTRY32 entryModule;
entryModule.dwSize = sizeof(MODULEENTRY32);
BOOL isGetModuleSuccess = Module32First(hProc32Module, &entryModule);
DWORD errEndofList = GetLastError();
BOOL isSuccessful = false;
while (errEndofList != ERROR_NO_MORE_FILES && isGetModuleSuccess)
{
if (_tcscmp(entryModule.szModule, KERNEL32_DLL)){
isSuccessful = true;
break;
}
isGetModuleSuccess = Module32Next(hProc32Module, &entryModule);
errEndofList = GetLastError();
}
if (!isSuccessful)
{
__debugbreak();
CloseHandle(hProc32Module);
return false;
}
//Get handle for Kernel.dll module
hKernel32 = entryModule.hModule;
CloseHandle(hProc32Module);
}
else
{
....
According to the documentation, CreateToolhelp32Snapshot() only fails with ERROR_PARTIAL_COPY when CreateToolhelp32Snapshot() is called by a 32bit process trying to access a 64bit process:
If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
Make sure your app really is compiled for 64bit to begin with. TH32CS_SNAPMODULE32 only makes sense to use when CreateToolhelp32Snapshot() is being called in a 64bit process:
TH32CS_SNAPMODULE32
0x00000010
Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process.
You are also not taking into account that GetLastError() is only updated when API functions fail, unless documented otherwise. Your loops are assuming that GetLastError() is updated after every API call, that is simply not true.
Try something more like this instead:
BOOL HookInjector::InjectIntoProcess(DWORD pID)
{
//Get Handle to Remote Process
HANDLE Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
....
DWORD dwFlag;
#ifdef _WIN64
//Check if Remote Process is a 32-bit application
BOOL isWow64 = FALSE;
IsWow64Process(Proc, &isWow64);
if (!isWow64) return false;
// TH32CS_SNAPMODULE32 includes 32bit modules when used by a 64bit process...
dwFlag = TH32CS_SNAPMODULE32;
#else
// TH32CS_SNAPMODULE includes 32bit modules when used by a 32bit process...
dwFlag = TH32CS_SNAPMODULE;
#endif
__debugbreak();
//Get list of all Modules associated with the Process
HANDLE hProc32Module;
do {
hProc32Module = CreateToolhelp32Snapshot(dwFlag, pID);
}
while ((hProc32Module == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_BAD_LENGTH));
if (hProc32Module == INVALID_HANDLE_VALUE) {
__debugbreak();
return false;
}
//Find the module for Kernel.dll and get the base address of it
hKernel32 = NULL;
MODULEENTRY32 entryModule = {0};
entryModule.dwSize = sizeof(MODULEENTRY32);
BOOL isGetModuleSuccess = Module32First(hProc32Module, &entryModule);
while (isGetModuleSuccess) {
if (_tcscmp(entryModule.szModule, KERNEL32_DLL)) {
hKernel32 = entryModule.hModule;
break;
}
isGetModuleSuccess = Module32Next(hProc32Module, &entryModule);
}
if (!hKernel32) {
__debugbreak();
CloseHandle(hProc32Module);
return false;
}
CloseHandle(hProc32Module);
....
}
According to the documentation, CreateToolhelp32Snapshot() only fails with ERROR_PARTIAL_COPY when CreateToolhelp32Snapshot() is called by a 32bit process trying to access a 64bit process:
If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
This is plain wrong as you could have deduced from the excerpt you posted. Where does it say it ONLY fails with ERROR_PARTIAL_COPY (299) when the caller is 32bit trying to access 64bit? It doesn't.
If the documentation would be complete, which it is not, then you would be right to assume that the stated behaviour is the only way to generate an ERROR_PARTIAL_COPY error code. Sadly the documentation is not complete.
For example if you start a process with the CREATE_SUSPENDED flag the CreateToolhelp32Snapshot API will set the error code to ERROR_PARTIAL_COPY when queried for modules regardless of the bitness of the host or target application. The reason it fails is because the DLLs aren't loaded until after the main thread is resumed and therefore the PebLdr pointer in the PEB structure is NULL.
Basically anything which prevents read of process memory (missing address in PEB, unmapped segment, etc.) can cause ERROR_PARTIAL_COPY as its description states:
ERROR_PARTIAL_COPY 299 (0x12B)
Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

Write/Read a memory-protected process's memory

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

How to put the system to sleep & again resume from sleep automatically (programatically) without any manual "mouse click or keyboard hit

My question is in continuation to my previous question "SetSuspendState() API never returns in Win8"
I'm running my VC++ code on Win8/Win8.1 m/c.
My purpose is to put the system to sleep & again bring back the system
from sleep automatically without any manual "mouse click or keyboard
hit".
But I'm not able to achieve "taking the system to sleep and hence ofcourse not bringing the system back from sleep." With the below call SetSuspendState(), the system is going to hibernation always, instead of sleep.
I'm again pasting the code snippet for quick reference::
int wait = 100;
LARGE_INTEGER WaitTime;
WaitTime.QuadPart = wait;
WaitTime.QuadPart *= -10000000;
HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if(0 == SetWaitableTimer(hTimer, &WaitTime, 0, NULL, NULL, TRUE))
{
res = false;
return res;
}
if(0 == SetSuspendState(FALSE, FALSE, FALSE))
{
res = false;
return res;
}
Here I'm calling "SetSuspendState() API with the options to put the system to sleep & to get it back from sleep automatically but the system is just going to hibernation::
SetSuspendState(FALSE, FALSE, FALSE)
Can anyone kindly help me in solving this problem & how do i put my system to sleep "programatically & resume back from sleep automatically without manual "mouse click or keyboard hit".
Before performing sleep we should make sure that system supports the required sleep state and allow wake up timer should be enabled, use following code to do the same.
//Check support
SYSTEM_POWER_CAPABILITIES sysPowCab = {0};
if (CallNtPowerInformation(SystemPowerCapabilities, NULL, 0, &sysPowCab, sizeof(SYSTEM_POWER_CAPABILITIES)) != 0)
{
return false;
}
if (!sysPowCab.SystemS3)
{
return false;
}
return true;
//Enable allow wake up timer
GUID *pPwrGUID;
GUID subGUID = GUID_SLEEP_SUBGROUP;
GUID BriGUID = GUID_ALLOW_RTC_WAKE;
DWORD ret = PowerGetActiveScheme(NULL, &pPwrGUID);
if (ret != ERROR_SUCCESS)
{
return false;
}
ret = PowerWriteACValueIndex(NULL, pPwrGUID, &subGUID, &BriGUID, 1);
if (ret != ERROR_SUCCESS)
{
return false;
}
return true;