Advertisement
Stranck

c++ custom debugger to steal register's data

Feb 6th, 2020
360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.73 KB | None | 0 0
  1. #include <windows.h>
  2. #include <tlhelp32.h>
  3. #include <tchar.h>
  4. #include <stdio.h>
  5. #include <stdint.h>
  6. #include <string>
  7. #include <Winnt.h>
  8.  
  9. //#define MA2P_NAME "gma2onpc.exe"
  10. //#define MA2P_NAME "calculator.exe"
  11. #define MA2P_NAME "debugThis.exe"
  12.  
  13. struct BreakpointList {
  14.     char *version;
  15.     DWORD64 address;
  16. };
  17. #define SUPPORTED_VERSION_NO 2
  18. const BreakpointList SUPPORTED_VERSION[] = {
  19.     {"3.3.4.3", 0x14016ade4},
  20.     {"c:\\Users\\Luca\\Desktop\\shit\\programming\\java\\grandMhAck2\\hack\\grandMhAck2", 0x4015cd} //0x4015AD
  21. };
  22.  
  23. struct ThreadInfo {
  24.     DWORD tid;
  25.     CONTEXT ctx;
  26.     HANDLE hThread;
  27.     BOOL stillValid;
  28. };
  29. BOOL doActionsOnThreads(DWORD dwOwnerPID, void (*action)(DWORD));
  30. DWORD64 getBreakpointAddr(char *version);
  31. ThreadInfo getThreadInfo(DWORD tid);
  32. DWORD getPidByPName(LPCSTR name);
  33. DWORD getPid(LPCSTR name);
  34. BOOL setPermissions(BOOL enable);
  35. void printError(TCHAR *msg);
  36. void printDWORD(DWORD n);
  37. void countThreads(DWORD tid);
  38. void createThreadObj(DWORD tid);
  39. void addBreakPoint(ThreadInfo ti, DWORD address);
  40. void realoadPointer(char *version);
  41. void addBreakPoint(ThreadInfo ti, DWORD64 address);
  42. void removeBreakPoint(ThreadInfo ti);
  43. void debugMainLoop(DWORD64 address);
  44. void printDbgEvent(DEBUG_EVENT dbgEvent);
  45. void elaborateBreakpointData(CONTEXT ctx);
  46.  
  47. //BOOL firstRun = TRUE;
  48. uint16_t threadsNo;
  49. ThreadInfo *threads;
  50.  
  51. int main(int argc, char *argv[]) {
  52.     if(argc < 2){
  53.         printf("arg[0] should be the grandma version!\n");
  54.         //DWORD64 asd = 0x14016ade4;
  55.         //printf("0x%llx\n%llu", asd, asd);
  56.         //return 1;
  57.     }
  58.     printf("grandMhAck2 is starting\n");
  59.     if(!setPermissions(true))
  60.         return 1;
  61.     realoadPointer(argv[0]);
  62.     printf("end");
  63.     return 0;
  64. }
  65.  
  66. void realoadPointer(char *version){
  67.     printf("Reloading dmx buffer pointer\n");
  68.     DWORD pID = getPidByPName(MA2P_NAME);
  69.     printf("\tPid obtained: %lu\n", pID);
  70.     printf("Attaching debugger to process\n");
  71.     DebugActiveProcess(pID);
  72.     DebugSetProcessKillOnExit(false);
  73.     threadsNo = 0;
  74.     doActionsOnThreads(pID, countThreads);
  75.     printf("Total threads found: %u\nObtaining thread info\n", threadsNo);
  76.     //if(!firstRun)
  77.     //  free(threads);
  78.     threads = (ThreadInfo *) malloc(threadsNo * sizeof(ThreadInfo));
  79.     uint16_t tmp = threadsNo;
  80.     doActionsOnThreads(pID, createThreadObj);
  81.     threadsNo = tmp;
  82.     printf("\nGetting correct breakpoint address for version: '%s'\n", version);
  83.     DWORD64 address = getBreakpointAddr(version);
  84.     printf("Setting breakpoint at *0x%llx for threads:", address);
  85.     for(uint16_t i = 0; i < threadsNo; i++)
  86.         if(threads[i].stillValid)
  87.             addBreakPoint(threads[i], address);
  88.     printf("\nEntering debug main loop, waiting breakpoint to be hitted\n");
  89.     debugMainLoop(address);
  90.     printf("Removing breakpoint *0x%llx for threads:", address);
  91.     for(uint16_t i = 0; i < threadsNo; i++)
  92.         if(threads[i].stillValid)
  93.             removeBreakPoint(threads[i]);
  94.     free(threads);
  95.     printf("\nDetaching debugger from process\n");
  96.     DebugActiveProcessStop(pID);
  97.     //firstRun = FALSE;
  98. }
  99.  
  100. void elaborateBreakpointData(CONTEXT ctx){
  101.     printf("RAX: %d\n", ctx.Rax); // eax get
  102. }
  103.  
  104. void debugMainLoop(DWORD64 address){
  105.     DEBUG_EVENT dbgEvent;
  106.     BOOL run = TRUE;
  107.     while (run){
  108.         fflush(stdout);
  109.         if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0) {
  110.             printf("\tWaitForDebugEvent returned 0\n");
  111.             break;
  112.         }
  113.         if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT){
  114.             DWORD tid = dbgEvent.dwThreadId;
  115.             ThreadInfo ti = getThreadInfo(tid);
  116.             //printf("Doneasd\n");
  117.             //fflush(stdout);
  118.             if (dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) {
  119.                 if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)address){
  120.                     printf("Breakpoint *0x%llx has been hitted by thread 0x%06X!\n", address, tid);
  121.                     ti.ctx.ContextFlags = CONTEXT_INTEGER;
  122.                     GetThreadContext(ti.hThread, &ti.ctx);
  123.                     elaborateBreakpointData(ti.ctx);
  124.                     removeBreakPoint(ti);
  125.                     printf(" removed from main loop to prevent other breakpoint hits and debugee's death\n");
  126.                     run = FALSE;
  127.                 } else printf("\tNot correct address (*0x%llx)\n", address);
  128.             } else if (dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION){
  129.                 printf("EXCEPTION_ACCESS_VIOLATION: removing thread 0x%06X\n", tid);
  130.                 removeBreakPoint(ti);
  131.                 printf(" removed\n");
  132.             } else printf("\tDebugged not SINGLE_STEP or ACCESS_VIOLATION event\n");
  133.         } else printf("\tDebugged not EXCEPTION event\n");
  134.         //printDbgEvent(dbgEvent);
  135.         ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
  136.     }
  137. }
  138.  
  139. DWORD64 getBreakpointAddr(char *version){
  140.     //DWORD64 addr = NULL;
  141.     DWORD64 addr = 0x4015af; //0x4015cd
  142.     uint16_t i = 0;
  143.     while(i < SUPPORTED_VERSION_NO && !addr){
  144.         if(!stricmp(version, SUPPORTED_VERSION[i].version))
  145.             addr = SUPPORTED_VERSION[i].address;
  146.         i++;
  147.     }
  148.     return addr;
  149. }
  150.  
  151. void addBreakPoint(ThreadInfo ti, DWORD64 address){
  152.     printf(" 0x%06X", ti.tid);
  153.     ti.ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
  154.     ti.ctx.Dr0 = address;
  155.     ti.ctx.Dr7 = 0x00000401;
  156.     if(!SetThreadContext(ti.hThread, &ti.ctx))
  157.         printError(TEXT("Error while setting breakpoint\n"));
  158. }
  159. void removeBreakPoint(ThreadInfo ti){
  160.     printf(" 0x%06X", ti.tid);
  161.     ti.stillValid = FALSE;
  162.     ti.ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
  163.     ti.ctx.Dr0 = 0;
  164.     ti.ctx.Dr7 = 0;
  165.     SetThreadContext(ti.hThread, &ti.ctx);
  166. }
  167.  
  168. DWORD getPidByPName(LPCSTR name){
  169.     DWORD pid = 0;
  170.     BOOL alreadyRunning = TRUE;
  171.     pid = getPid(name);
  172.     while(!pid) {
  173.         pid = getPid(name);
  174.         fflush(stdout); //Sleep is shit and I hate this programming language
  175.         alreadyRunning = FALSE;
  176.         Sleep(1000);
  177.     }
  178.     if(!alreadyRunning){
  179.         printf("%s started after this process. Waiting 2000ms, so it will load threads 'n stuff\n", name);
  180.         fflush(stdout);
  181.         Sleep(2000);
  182.     }
  183.     return pid;
  184. }
  185. DWORD getPid(LPCSTR name){
  186.     printf("Trying to obtain pid for '%s'\n", name);
  187.     PROCESSENTRY32 entry;
  188.     entry.dwSize = sizeof(PROCESSENTRY32);
  189.     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  190.     DWORD pid = 0;
  191.  
  192.     if(Process32First(snapshot, &entry))
  193.         while(Process32Next(snapshot, &entry) && !pid)
  194.             if(!stricmp(entry.szExeFile, name))
  195.                 pid = entry.th32ProcessID;
  196.  
  197.     CloseHandle(snapshot);
  198.     return pid;
  199. }
  200.  
  201. BOOL doActionsOnThreads(DWORD dwOwnerPID, void (*action)(DWORD)){
  202.     HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
  203.     THREADENTRY32 te32;
  204.     hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  205.     if(hThreadSnap == INVALID_HANDLE_VALUE) return FALSE;
  206.     te32.dwSize = sizeof(THREADENTRY32);
  207.     if(!Thread32First(hThreadSnap, &te32)){
  208.         printError(TEXT("Thread32First"));
  209.         CloseHandle(hThreadSnap);
  210.         return FALSE;
  211.     }
  212.     printf("Running action 0x%08X on all threads\n\t", action);
  213.     do {
  214.         if(te32.th32OwnerProcessID == dwOwnerPID){
  215.             DWORD tId = te32.th32ThreadID;
  216.             if(action)
  217.                 action(tId);
  218.         }
  219.     } while(Thread32Next(hThreadSnap, &te32));
  220.     //printf("\n");
  221.     CloseHandle(hThreadSnap);
  222.     return TRUE;
  223. }
  224.  
  225. void printError(TCHAR *msg){
  226.     DWORD eNum;
  227.     TCHAR sysMsg[256];
  228.     TCHAR *p;
  229.     eNum = GetLastError();
  230.     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  231.                   NULL, eNum,
  232.                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  233.                   sysMsg, 256, NULL);
  234.     p = sysMsg;
  235.     while((*p > 31) || (*p == 9)) ++p;
  236.     do{
  237.         *p-- = 0;
  238.     } while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));
  239.     _tprintf(TEXT("\n  WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg);
  240. }
  241.  
  242. ThreadInfo getThreadInfo(DWORD tid){
  243.     printf("Getting threadinfo obj for 0x%06X\n", tid);
  244.     uint16_t i = 0, result = 0xffff;
  245.     while(i < threadsNo && result == 0xffff){
  246.         //printf("%lu %lu\n", threads[i].tid, tid);
  247.         if(threads[i].tid == tid)
  248.             result = i;
  249.         i++;
  250.     }
  251.     //printf("Done %u < %u\n", result, threadsNo);
  252.     return threads[result];
  253. }
  254. void createThreadObj(DWORD tid){ //ik it's not an object lol
  255.     printf("0x%06X ", tid);
  256.     threads[--threadsNo] = {
  257.         tid,
  258.         {0},
  259.         OpenThread(THREAD_ALL_ACCESS, FALSE, tid),
  260.         TRUE
  261.     };
  262. }
  263. void countThreads(DWORD tid){
  264.     threadsNo++;
  265. }
  266. void printDWORD(DWORD n){
  267.     printf("%lu\n", n);
  268. }
  269.  
  270. void printDbgEvent(DEBUG_EVENT dbgEvent){
  271.     printf("Tid: 0x%06X\n", dbgEvent.dwThreadId);
  272.     printf("Code: %lu\t%B\n", dbgEvent.dwDebugEventCode, dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT);
  273.     printf("Exception: %llx\n", dbgEvent.u.Exception.ExceptionRecord.ExceptionCode);
  274.     printf("Record: %llx\n", dbgEvent.u.Exception.ExceptionRecord.ExceptionRecord);
  275.     printf("Flags: %lu\n", dbgEvent.u.Exception.ExceptionRecord.ExceptionFlags);
  276.     printf("Address: %llx\n", dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress);
  277.     printf("Parameters NO: %lu\n", dbgEvent.u.Exception.ExceptionRecord.NumberParameters);
  278.     for(DWORD i = 0; i < 3; i++)
  279.         printf("ExceptionInformation[%lu]: 0x%lx\n", i, dbgEvent.u.Exception.ExceptionRecord.ExceptionInformation[i]);
  280.     printf("\n");
  281. }
  282.  
  283. BOOL setPermissions(BOOL enable){
  284.     printf("Obtaining permissions\n");
  285.     HANDLE hToken;
  286.     if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
  287.         printError(TEXT("Error opening current process"));
  288.         return FALSE;
  289.     }
  290.     TOKEN_PRIVILEGES tp;
  291.     LUID luid;
  292.     if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)){
  293.         printf("LookupPrivilegeValue error: %u\n", GetLastError());
  294.         return FALSE;
  295.     }
  296.     tp.PrivilegeCount = 1;
  297.     tp.Privileges[0].Luid = luid;
  298.     if(enable)
  299.         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  300.     else
  301.         tp.Privileges[0].Attributes = 0;
  302.     if(!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)){
  303.         printError(TEXT("AdjustTokenPrivileges error\n"));
  304.         return FALSE;
  305.     }
  306.     if(GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
  307.         printf("ERROR: The token does not have the specified privilege.\n");
  308.         return FALSE;
  309.     }
  310.     CloseHandle(hToken);
  311.     return TRUE;
  312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement