Advertisement
CasualGamer

Threadstack Pointers

Oct 5th, 2019
1,721
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.54 KB | None | 0 0
  1. #include <Windows.h> //HWND, DWORD etc.
  2. #include<TlHelp32.h>
  3. #include <Psapi.h>
  4. #include <iostream> // cout
  5. //#include <tchar.h> // _tcscmp
  6. #include <vector> //vector ...
  7. #include "ntinfo.h"
  8.  
  9. std::vector<DWORD> threadList(DWORD pid) {
  10.     /* solution from http://stackoverflow.com/questions/1206878/enumerating-threads-in-windows */
  11.     std::vector<DWORD> vect = std::vector<DWORD>();
  12.     HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  13.     if (h == INVALID_HANDLE_VALUE)
  14.         return vect;
  15.  
  16.     THREADENTRY32 te;
  17.     te.dwSize = sizeof(te);
  18.     if (Thread32First(h, &te)) {
  19.         do {
  20.             if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
  21.                 sizeof(te.th32OwnerProcessID)) {
  22.  
  23.  
  24.                 if (te.th32OwnerProcessID == pid) {
  25.                     //printf("PID: %04d Thread ID: 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
  26.                     vect.push_back(te.th32ThreadID);
  27.                 }
  28.  
  29.             }
  30.             te.dwSize = sizeof(te);
  31.         } while (Thread32Next(h, &te));
  32.     }
  33.  
  34.     return vect;
  35. }
  36.  
  37. DWORD GetThreadStartAddress(HANDLE processHandle, HANDLE hThread) {
  38.     /* rewritten from https://github.com/cheat-engine/cheat-engine/blob/master/Cheat%20Engine/CEFuncProc.pas#L3080 */
  39.     DWORD used = 0, ret = 0;
  40.     DWORD stacktop = 0, result = 0;
  41.  
  42.     MODULEINFO mi;
  43.  
  44.     GetModuleInformation(processHandle, GetModuleHandle("kernel32.dll"), &mi, sizeof(mi));
  45.     stacktop = (DWORD)GetThreadStackTopAddress_x86(processHandle, hThread);
  46.  
  47.     CloseHandle(hThread);
  48.  
  49.     if (stacktop) {
  50.         //find the stack entry pointing to the function that calls "ExitXXXXXThread"
  51.         //Fun thing to note: It's the first entry that points to a address in kernel32
  52.  
  53.         DWORD* buf32 = new DWORD[4096];
  54.  
  55.         if (ReadProcessMemory(processHandle, (LPCVOID)(stacktop - 4096), buf32, 4096, NULL)) {
  56.             for (int i = 4096 / 4 - 1; i >= 0; --i) {
  57.                 if (buf32[i] >= (DWORD)mi.lpBaseOfDll && buf32[i] <= (DWORD)mi.lpBaseOfDll + mi.SizeOfImage) {
  58.                     result = stacktop - 4096 + i * 4;
  59.                     break;
  60.                 }
  61.  
  62.             }
  63.         }
  64.  
  65.         delete buf32;
  66.     }
  67.  
  68.     return result;
  69. }
  70.  
  71.  
  72.  
  73.  
  74. DWORD GetThreadstackStartAddress(int stackNumber, DWORD pID, HANDLE processHandle) {
  75.     std::vector<DWORD> threadId = threadList(pID);
  76.     int stackNum = 0;
  77.     for (auto it = threadId.begin(); it != threadId.end(); ++it) {
  78.         HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, *it);
  79.         DWORD threadStartAddress = GetThreadStartAddress(processHandle, threadHandle);
  80.         //printf("TID: 0x%04x = THREADSTACK%2d BASE ADDRESS: 0x%04x\n", *it, stackNum, threadStartAddress);
  81.         if (stackNum == stackNumber) return threadStartAddress;
  82.         stackNum++;
  83.     }
  84. }
  85.  
  86. int main() {
  87.  
  88.     HWND hGameWindow = FindWindow(NULL, "Zuma Deluxe 1.1.0.0");
  89.     if (hGameWindow == NULL) {
  90.         std::cout << "Start the game!" << std::endl;
  91.         return 0;
  92.     }
  93.     DWORD pID = NULL; // ID of our Game
  94.     GetWindowThreadProcessId(hGameWindow, &pID);
  95.     HANDLE processHandle = NULL;
  96.     processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
  97.     if (processHandle == INVALID_HANDLE_VALUE || processHandle == NULL) { // error handling
  98.         std::cout << "Failed to open process" << std::endl;
  99.         return 0;
  100.     }
  101.  
  102.     DWORD PointerBaseAddress = GetThreadstackStartAddress(0, pID, processHandle);
  103.     DWORD offsetGameToBaseAdress = -0x0000013C;
  104.     std::vector<DWORD> pointsOffsets{ 0xF0 };
  105.     DWORD baseAddress = NULL;
  106.     //Get value at gamebase+offset -> store it in baseAddress
  107.     ReadProcessMemory(processHandle, (LPVOID)(PointerBaseAddress + offsetGameToBaseAdress), &baseAddress, sizeof(baseAddress), NULL);
  108.     std::cout << "debugginfo: baseaddress = " << std::hex << baseAddress << std::endl;
  109.     DWORD pointsAddress = baseAddress; //the Adress we need -> change now while going through offsets
  110.     for (int i = 0; i < pointsOffsets.size() - 1; i++) // -1 because we dont want the value at the last offset
  111.     {
  112.         ReadProcessMemory(processHandle, (LPVOID)(pointsAddress + pointsOffsets.at(i)), &pointsAddress, sizeof(pointsAddress), NULL);
  113.         std::cout << "debugginfo: Value at offset = " << std::hex << pointsAddress << std::endl;
  114.     }
  115.     pointsAddress += pointsOffsets.at(pointsOffsets.size() - 1); //Add Last offset -> done!!
  116.  
  117.     //"UI"
  118.     std::cout << "Zuma Deluxe 1.1.0.0 H4CKs" << std::endl;
  119.     std::cout << "Press Numpad 0 to EXIT" << std::endl;
  120.     std::cout << "Press Numpad 1 to set lives" << std::endl;
  121.     while (true) {
  122.         Sleep(50);
  123.         if (GetAsyncKeyState(VK_NUMPAD0)) { // Exit
  124.             return 0;
  125.         }
  126.         if (GetAsyncKeyState(VK_NUMPAD1)) {//Mouseposition
  127.             std::cout << "How many lives you want?" << std::endl;
  128.             int newPoints = 0;
  129.             std::cin >> newPoints;
  130.             WriteProcessMemory(processHandle, (LPVOID)(pointsAddress), &newPoints, 4, 0);
  131.         }
  132.     }
  133.  
  134. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement