Basically am trying to iterate through function address's from a running process which is a dummy program that I have created so what I do is this
IMAGE_THUNK_DATA first_thunk = { 0 };
if(!ReadProcessMemory(handle,process_base_address + import_desc.FirstThunk,&first_thunk,sizeof(first_thunk),0))
return false;
std::cout << "Function address :" << std::hex << "0x" << first_thunk.u1.Function << '\n';
Now everything you see is correct and I read it from the target process without a problem but now
when I try to print first_thunk.u1.Function I get an address that will land inside MessageBoxA function.
But I want the address of it and not an address inside that function anyways if I do this auto address = process_base_address + import_desc.FirstThunk; I get what I want which is the address of MessageBoxA
So I am so confused. Why doing process_base_address + import_desc.FirstThunk works and using the struct that I read doesn't which is my big problem regarding this question when I try to read the sizeof(IMAGE_THUNK_DATA) I read 8 bytes which is understandable since its inside a union which shares the address space for 4 variables inside there but how would I get each variable address or access each var address or rva using ReadProcessMemory since its only reading 8 bytes I can't do that.
Which you mean is ReadProcessMemory with auto address = process_base_address + import_desc.FirstThunk works for you but doesn't work with process_base_address + import_desc.FirstThunk directly, I recommend to use (PBYTE) Conversion.
According to your description sizeof(IMAGE_THUNK_DATA) = 8, I assume you use the x64 version.
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString; // PBYTE
ULONGLONG Function; // PDWORD
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;
When the highest value of IMAGE_THUNK_DATA is 1, it means that the function is imported in the form of a serial number, otherwise, the function is imported in the form of a function name, and it is an RVA, pointing to an IMAGE_IMPORT_BY_NAME structure. We can use constant IMAGE_ORDINAL_FLAG to test whether the highest bit is 1.
The following sample work for me:
#include <Windows.h>
#include <iostream>
#include <psapi.h>
#pragma warning(disable : 4996)
using namespace std;
void main()
{
int i;
HMODULE hModule;
DWORD dwOffset, cbneeded;
SIZE_T dwRet;
DWORD dwPid = 8752; // PID of process to be hooked
TCHAR szModName[MAX_PATH];
TCHAR szHookModName[MAX_PATH] = { "user32.dll" };
TCHAR szFuncName[MAX_PATH] = { "MessageBoxA" };
IMAGE_DOS_HEADER DOSHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
IMAGE_DATA_DIRECTORY DataDirectory;
IMAGE_IMPORT_DESCRIPTOR ImportDesc;
IMAGE_THUNK_DATA OrigThunkData;
IMAGE_THUNK_DATA RealThunkData;
PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)malloc(255); //function name length;
MEMORY_BASIC_INFORMATION mbi;
LPVOID lpBaseAddress;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid);
if (hProcess == NULL)
{
printf("Fail to open process!\n");
return;
}
if (!EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbneeded))
{
printf("Fail to enum process modules!\n");
return;
}
if (!ReadProcessMemory(hProcess, hModule, (void*)&DOSHeader, sizeof(IMAGE_DOS_HEADER), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
dwOffset = DOSHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + dwOffset, (void*)&OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
DataDirectory = OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
i = 0;
do
{
dwOffset = DataDirectory.VirtualAddress + sizeof(IMAGE_IMPORT_DESCRIPTOR) * i;
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + dwOffset, (void*)&ImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + ImportDesc.Name, (void*)szModName, MAX_PATH, &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (stricmp(szModName, szHookModName) == 0)
break;
i++;
} while (ImportDesc.Name);
i = 0;
do
{
lpBaseAddress = (PBYTE)hModule + ImportDesc.OriginalFirstThunk + sizeof(IMAGE_THUNK_DATA) * i;
if (!ReadProcessMemory(hProcess, lpBaseAddress, (void*)&OrigThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + ImportDesc.FirstThunk + sizeof(IMAGE_THUNK_DATA) * i, (void*)&RealThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
std::cout << "Function address :" << std::hex << "0x" << RealThunkData.u1.Function << '\n';
lpBaseAddress = (PBYTE)hModule + ImportDesc.FirstThunk + sizeof(IMAGE_THUNK_DATA) * i;
if (!ReadProcessMemory(hProcess, lpBaseAddress, (void*)&RealThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
std::cout << "Function address :" << std::hex << "0x" << RealThunkData.u1.Function << '\n';
if ((OrigThunkData.u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + OrigThunkData.u1.AddressOfData, (void*)pImportByName, sizeof(WORD) + strlen(szFuncName) + 1, &dwRet))
{
if (GetLastError() == ERROR_PARTIAL_COPY)
{
i++;
continue;
}
else
{
printf("Fail to read memory in remote process!\n");
return;
}
}
if (pImportByName->Name[0] == '\0')
{
printf("Function not located!\n");
break;
}
if (strcmpi((char*)pImportByName->Name, szFuncName) == 0)
{
printf("Function: %s \n ", pImportByName->Name);
break;
}
}
i++;
} while (OrigThunkData.u1.Function);
free(pImportByName);
}
It should be noted that the contents pointed to by OriginalFirstThunk and FirstThunk in the PE file are exactly the same, but when the file is loaded into memory, the difference appears: the contents of OriginalFirstThunk will not change, but the data in FirstThunk will change to the entry address of the function.
target process:
#include <windows.h>
#include <iostream>
int main()
{
printf("child\n");
VOID *p = (VOID*)MessageBoxA;
MessageBoxA(NULL,"TEST","TEST",0);
getchar();
return 0;
}
Result:
Related
So I have been trying to get into memory reading in C++ and I thought a cool project would be to read all addresses a process is using (similar to how Cheat Engine works).
I started by reading
Link1: Read Memory of Process C++
Link2: Read memory of 64bit process address
Link3: http://www.cplusplus.com/forum/general/42132/
And I also watched a tutorial on youtube where he explained how a process (game) worked with addresses. Link to youtube video: https://www.youtube.com/watch?v=wiX5LmdD5yk
This resulted in me making three different methods:
DWORD GetProcId(const wchar_t* procName) {
DWORD pid = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnap != INVALID_HANDLE_VALUE) {
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if(Process32First(hSnap, &procEntry)) {
do {
if(!_wcsicmp(procEntry.szExeFile, procName)) {
pid = procEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return pid;
}
This method is to get the process-id which I could also just type manually by finding the same PID in task-manager (which gave me the same baseaddress later on).
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName) {
uintptr_t modBaseAddr = 0;
//I use 0x10 instead of TH32CS_SNAPMODULE32 since it didnt work and according to documentation
// this is the value it should have.
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | 0x10, procId);
if(hSnap != INVALID_HANDLE_VALUE) {
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if(Module32First(hSnap, &modEntry)) {
do {
if(!_wcsicmp(modEntry.szModule, modName)) {
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while(Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
This method (I assume) will return the base address of the process. Which for example in my code I tried to find the base address of the discord.exe process. When discord.exe wasn't running I got 0 and when it was running I got an address (which I believe is the correct base address, correct me if I am wrong).
And my main method:
int main() {
DWORD procId = GetProcId(L"Discord.exe");
uintptr_t moduleBase = GetModuleBaseAddress(procId, L"Discord.exe");
HANDLE hProcess = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);
uintptr_t dynamicPtrBaseAddr = moduleBase;
std::cout << "Dynamic: " << dynamicPtrBaseAddr << std::endl;
int value = 0;
int arr [10000] = {};
for (int i = 0; i < 100000; i++) {
ReadProcessMemory(hProcess, (BYTE*)dynamicPtrBaseAddr, &value, sizeof(value),0);
dynamicPtrBaseAddr += 1;
arr[i] = value;
}
}
Where I try to put all the values of all 100000 addresses in an array.
So my questions are:
Have I retrieved the base address of the process correctly?
For reading the other addresses I just increase dynamicPtrBaseAddr by 1, is there a better way to implement an offset? Or is this the correct way?
Now I increase the base address by 100000. Can I find the last address of the process instead?
I compile with g++ main.cpp -o test -lpsapi -DUNICODE (MinGW).
You must run as administrator and you must compile for the same bitness as the target process.
You should not be reading 1 byte at a time, especially in an external hack.
You should be using VirtualQueryEx() to properly loop through only proper memory regions:
DWORD procid = GetProcId("ac_client.exe");
unsigned char* addr = 0;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid);
MEMORY_BASIC_INFORMATION mbi;
while (VirtualQueryEx(hProc, addr, &mbi, sizeof(mbi)))
{
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && mbi.Protect != PAGE_GUARD)
{
std::cout << "base : 0x" << std::hex << mbi.BaseAddress << " end : 0x" << std::hex << (uintptr_t)mbi.BaseAddress + mbi.RegionSize << "\n";
}
addr += mbi.RegionSize;
}
This ensures you're only reading proper memory. Next you would reach each region into a local buffer in one go, this will increase speed dramatically as you won't have the overhead of calling the API for each byte.
What you're looks like you're trying to do is pattern scanning. You can find our pattern scanning tutorials in the same place you found the original tutorial you were following.
I'm trying to implement some anti-debugging/anti-reversing techinques in order to prevent my (python) executable to be debugged/reversed, but when I try to launch it from x32dbg or python -m pdb they don't work, letting x32gdb/pdb to access my code and execute the executable/script.
The techniques I'm using are written in c++; I import the c++ code in my python code through a dll generated thorugh Visual Studio 2019, and everything works fine, meaning that I can call the functions in my dll from the executable/python without any error/exception.
I found the techniques online, I didn't wrote them, but also the simplest technique (isDebuggerPresent() function from debugapi.h windows library) does not work, and this is only a call to a function.
Here are the techniques I implemented in my dll
int isThereADebugger()
{
if (IsDebuggerPresent())
{
cout << "Stop debugging program!" << endl;
exit(-1);
}
return 0;
}
// Current PEB for 64bit and 32bit processes accordingly
PVOID GetPEB()
{
#ifdef _WIN64
return (PVOID)__readgsqword(0x0C * sizeof(PVOID));
#else
return (PVOID)__readfsdword(0x0C * sizeof(PVOID));
#endif
}
// Get PEB for WOW64 Process
PVOID GetPEB64()
{
PVOID pPeb = 0;
#ifndef _WIN64
BOOL isWow64 = FALSE;
typedef BOOL(WINAPI* pfnIsWow64Process)(HANDLE hProcess, PBOOL isWow64);
pfnIsWow64Process fnIsWow64Process = (pfnIsWow64Process)
GetProcAddress(GetModuleHandleA("Kernel32.dll"), "IsWow64Process");
if (fnIsWow64Process(GetCurrentProcess(), &isWow64))
{
if (isWow64)
{
pPeb = (PVOID)__readfsdword(0x0C * sizeof(PVOID));
pPeb = (PVOID)((PBYTE)pPeb + 0x1000);
}
}
#endif
return pPeb;
}
#define FLG_HEAP_ENABLE_TAIL_CHECK 0x10
#define FLG_HEAP_ENABLE_FREE_CHECK 0x20
#define FLG_HEAP_VALIDATE_PARAMETERS 0x40
#define NT_GLOBAL_FLAG_DEBUGGED (FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS)
void CheckNtGlobalFlag()
{
PVOID pPeb = GetPEB();
PVOID pPeb64 = GetPEB64();
DWORD offsetNtGlobalFlag = 0;
#ifdef _WIN64
offsetNtGlobalFlag = 0xBC;
#else
offsetNtGlobalFlag = 0x68;
#endif
DWORD NtGlobalFlag = *(PDWORD)((PBYTE)pPeb + offsetNtGlobalFlag);
if (NtGlobalFlag & NT_GLOBAL_FLAG_DEBUGGED)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
if (pPeb64)
{
DWORD NtGlobalFlagWow64 = *(PDWORD)((PBYTE)pPeb64 + 0xBC);
if (NtGlobalFlagWow64 & NT_GLOBAL_FLAG_DEBUGGED)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
}
PIMAGE_NT_HEADERS GetImageNtHeaders(PBYTE pImageBase)
{
PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)pImageBase;
return (PIMAGE_NT_HEADERS)(pImageBase + pImageDosHeader->e_lfanew);
}
PIMAGE_SECTION_HEADER FindRDataSection(PBYTE pImageBase)
{
static const std::string rdata = ".rdata";
PIMAGE_NT_HEADERS pImageNtHeaders = GetImageNtHeaders(pImageBase);
PIMAGE_SECTION_HEADER pImageSectionHeader = IMAGE_FIRST_SECTION(pImageNtHeaders);
int n = 0;
for (; n < pImageNtHeaders->FileHeader.NumberOfSections; ++n)
{
if (rdata == (char*)pImageSectionHeader[n].Name)
{
break;
}
}
return &pImageSectionHeader[n];
}
void CheckGlobalFlagsClearInProcess()
{
PBYTE pImageBase = (PBYTE)GetModuleHandle(NULL);
PIMAGE_NT_HEADERS pImageNtHeaders = GetImageNtHeaders(pImageBase);
PIMAGE_LOAD_CONFIG_DIRECTORY pImageLoadConfigDirectory = (PIMAGE_LOAD_CONFIG_DIRECTORY)(pImageBase
+ pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress);
if (pImageLoadConfigDirectory->GlobalFlagsClear != 0)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
void CheckGlobalFlagsClearInFile()
{
HANDLE hExecutable = INVALID_HANDLE_VALUE;
HANDLE hExecutableMapping = NULL;
PBYTE pMappedImageBase = NULL;
__try
{
PBYTE pImageBase = (PBYTE)GetModuleHandle(NULL);
PIMAGE_SECTION_HEADER pImageSectionHeader = FindRDataSection(pImageBase);
TCHAR pszExecutablePath[MAX_PATH];
DWORD dwPathLength = GetModuleFileName(NULL, pszExecutablePath, MAX_PATH);
if (0 == dwPathLength) __leave;
hExecutable = CreateFile(pszExecutablePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hExecutable) __leave;
hExecutableMapping = CreateFileMapping(hExecutable, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL == hExecutableMapping) __leave;
pMappedImageBase = (PBYTE)MapViewOfFile(hExecutableMapping, FILE_MAP_READ, 0, 0,
pImageSectionHeader->PointerToRawData + pImageSectionHeader->SizeOfRawData);
if (NULL == pMappedImageBase) __leave;
PIMAGE_NT_HEADERS pImageNtHeaders = GetImageNtHeaders(pMappedImageBase);
PIMAGE_LOAD_CONFIG_DIRECTORY pImageLoadConfigDirectory = (PIMAGE_LOAD_CONFIG_DIRECTORY)(pMappedImageBase
+ (pImageSectionHeader->PointerToRawData
+ (pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress - pImageSectionHeader->VirtualAddress)));
if (pImageLoadConfigDirectory->GlobalFlagsClear != 0)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
__finally
{
if (NULL != pMappedImageBase)
UnmapViewOfFile(pMappedImageBase);
if (NULL != hExecutableMapping)
CloseHandle(hExecutableMapping);
if (INVALID_HANDLE_VALUE != hExecutable)
CloseHandle(hExecutable);
}
}
int GetHeapFlagsOffset(bool x64)
{
return x64 ?
TRUE ? 0x70 : 0x14 : //x64 offsets
TRUE ? 0x40 : 0x0C; //x86 offsets
}
int GetHeapForceFlagsOffset(bool x64)
{
return x64 ?
TRUE ? 0x74 : 0x18 : //x64 offsets
TRUE ? 0x44 : 0x10; //x86 offsets
}
void CheckHeap()
{
PVOID pPeb = GetPEB();
PVOID pPeb64 = GetPEB64();
PVOID heap = 0;
DWORD offsetProcessHeap = 0;
PDWORD heapFlagsPtr = 0, heapForceFlagsPtr = 0;
BOOL x64 = FALSE;
#ifdef _WIN64
x64 = TRUE;
offsetProcessHeap = 0x30;
#else
offsetProcessHeap = 0x18;
#endif
heap = (PVOID) * (PDWORD_PTR)((PBYTE)pPeb + offsetProcessHeap);
heapFlagsPtr = (PDWORD)((PBYTE)heap + GetHeapFlagsOffset(x64));
heapForceFlagsPtr = (PDWORD)((PBYTE)heap + GetHeapForceFlagsOffset(x64));
if (*heapFlagsPtr & ~HEAP_GROWABLE || *heapForceFlagsPtr != 0)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
if (pPeb64)
{
heap = (PVOID) * (PDWORD_PTR)((PBYTE)pPeb64 + 0x30);
heapFlagsPtr = (PDWORD)((PBYTE)heap + GetHeapFlagsOffset(true));
heapForceFlagsPtr = (PDWORD)((PBYTE)heap + GetHeapForceFlagsOffset(true));
if (*heapFlagsPtr & ~HEAP_GROWABLE || *heapForceFlagsPtr != 0)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
}
void trapCheckFlag() {
BOOL isDebugged = TRUE;
__try
{
__asm
{
pushfd
or dword ptr[esp], 0x100 // set the Trap Flag
popfd // Load the value into EFLAGS register
nop
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// If an exception has been raised – debugger is not present
isDebugged = FALSE;
}
if (isDebugged)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
int isRemoteDebuggerPresent() {
BOOL isDebuggerPresent = FALSE;
if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &isDebuggerPresent))
{
if (isDebuggerPresent)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
return 0;
}
typedef NTSTATUS(NTAPI* pfnNtQueryInformationProcess)(
_In_ HANDLE ProcessHandle,
_In_ UINT ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
//const UINT ProcessDebugPort = 7;
int ntQueryInfoProc()
{
pfnNtQueryInformationProcess NtQueryInformationProcess = NULL;
NTSTATUS status;
DWORD isDebuggerPresent = 0;
HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
if (NULL != hNtDll)
{
NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformationProcess");
if (NULL != NtQueryInformationProcess)
{
status = NtQueryInformationProcess(
GetCurrentProcess(),
7,
&isDebuggerPresent,
sizeof(DWORD),
NULL);
if (status == 0x00000000 && isDebuggerPresent != 0)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
}
}
return 0;
}
typedef NTSTATUS(NTAPI* pfnNtSetInformationThread)(
_In_ HANDLE ThreadHandle,
_In_ ULONG ThreadInformationClass,
_In_ PVOID ThreadInformation,
_In_ ULONG ThreadInformationLength
);
const ULONG ThreadHideFromDebugger = 0x11;
void HideFromDebugger()
{
HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
pfnNtSetInformationThread NtSetInformationThread = (pfnNtSetInformationThread)
GetProcAddress(hNtDll, "NtSetInformationThread");
NTSTATUS status = NtSetInformationThread(GetCurrentThread(),
ThreadHideFromDebugger, NULL, 0);
}
EXCEPTION_DISPOSITION ExceptionRoutine(
PEXCEPTION_RECORD ExceptionRecord,
PVOID EstablisherFrame,
PCONTEXT ContextRecord,
PVOID DispatcherContext)
{
if (EXCEPTION_INVALID_HANDLE == ExceptionRecord->ExceptionCode)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
return ExceptionContinueExecution;
}
int handleTracing() {
__asm
{
// set SEH handler
push ExceptionRoutine
push dword ptr fs : [0]
mov dword ptr fs : [0] , esp
}
CloseHandle((HANDLE)0xBAAD);
__asm
{
// return original SEH handler
mov eax, [esp]
mov dword ptr fs : [0] , eax
add esp, 8
}
return 0;
}
#define DBG_PRINTEXCEPTION_WIDE_C 0x4001000A
void dbgMessages() {
WCHAR* outputString = (WCHAR*)L"Any text";
ULONG_PTR args[4] = { 0 };
args[0] = (ULONG_PTR)wcslen(outputString) + 1;
args[1] = (ULONG_PTR)outputString;
__try
{
RaiseException(DBG_PRINTEXCEPTION_WIDE_C, 0, 4, args);
printf("Debugger detected");
exit(-1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("Debugger NOT detected");
}
}
void DoSmth()
{
Sleep(1000);
}
int timeApproach() {
const int g_doSmthExecutionTime = 1050;
SYSTEMTIME sysTimeStart;
SYSTEMTIME sysTimeEnd;
FILETIME timeStart, timeEnd;
GetSystemTime(&sysTimeStart);
DoSmth();
GetSystemTime(&sysTimeEnd);
SystemTimeToFileTime(&sysTimeStart, &timeStart);
SystemTimeToFileTime(&sysTimeEnd, &timeEnd);
double timeExecution = (timeEnd.dwLowDateTime - timeStart.dwLowDateTime) / 10000.0;
if (timeExecution < g_doSmthExecutionTime)
{
std::cout << "Debugger not present";
}
else
{
std::cout << "Debugger present";
}
return 0;
}
In my python script I call those function sequentially at the entry point, like
if __name__ == "__main__":
antiDebugger = ctypes.CDLL('C:\\absolute\\path\\to\\antiDebugger.dll')
antiDebugger.isThereADebugger()
antiDebugger.CheckNtGlobalFlag()
antiDebugger.CheckGlobalFlagsClearInProcess()
antiDebugger.CheckGlobalFlagsClearInFile()
antiDebugger.CheckHeap()
antiDebugger.trapCheckFlag()
antiDebugger.isRemoteDebuggerPresent()
antiDebugger.ntQueryInfoProc()
antiDebugger.timeApproach()
antiDebugger.handleTracing()
antiDebugger.HideFromDebugger()
antiDebugger.dbgMessages()
customFunction()
Actually, I also tried to put them at the beginning of every function in my python script, but also that didn't work.
I generate the executable with pyarmor combined with pyinstaller using the --onefile option
My windows version is the x64 windows 10 Pro, while my python version is 3.8.2
I know that all those techniques might be too much, but I just want them to work in order to try to break them, specifically the executable side.
Can anyone tell me how to make this techniques work?
Hello I am creating a file encryption code I read a file and I need to turn the file that I am reading to BYTE* I tried searching but every single time I got "CL.exit". This is how I read the file.
HANDLE getFile = createFile();
DWORD reciveBytes = 0;
//If it's byte or kilobyte the size of the buffer will be 1024.
//If it's megabytes or gigabyte the size of the buffer will be 4096.
const DWORD Buffersize = 66232; // gave me warning for 1024
DWORD buffer[Buffersize];
string fileInput;
if (ReadFile(
getFile,
buffer,
Buffersize,
&reciveBytes,
NULL
)) {
}
else {
cout << "Faild!" << endl;
cout << GetLastError() << endl;
}
/*
for (unsigned int i = 0; i < reciveBytes; i++) {
if (buffer[i] != '\0') {
fileInput = fileInput + buffer[i];
}
}
*/
return buffer[reciveBytes];
now, what I need to do is to turn the return type to BYTE* so I could do something like this: BYTE* protect = (BYTE*)"Hello world!";
This is createFile():
HANDLE getFile = CreateFileA(
fileName,
GENERIC_READ,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
#include <windows.h>
#include <iostream>
HANDLE createFile()
{
HANDLE getFile = CreateFileA(
"xxx.txt",
GENERIC_READ,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
return getFile;
}
BYTE* memoryfromfile()
{
HANDLE getFile = createFile();
DWORD reciveBytes = 0;
//If it's byte or kilobyte the size of the buffer will be 1024.
//If it's megabytes or gigabyte the size of the buffer will be 4096.
const DWORD Buffersize = 66232; // gave me warning for 1024
BYTE* memory = new BYTE[Buffersize];
memset(memory, 0, Buffersize);
std::string fileInput;
if (ReadFile(
getFile,
memory,
Buffersize,
&reciveBytes,
NULL
)) {
}
else {
std::cout << GetLastError() << std::endl;
std::cout << "Faild!" << std::endl;
}
/*
for (unsigned int i = 0; i < reciveBytes; i++) {
if (buffer[i] != '\0') {
fileInput = fileInput + buffer[i];
}
}
*/
return memory;
}
int main()
{
BYTE * temp = memoryfromfile();
std::cout << "temp = " << temp << std::endl;
delete temp;
system("pause");
return 0;
}
I am trying to fiddle around with CounterStrike in order to learn something about memory editing in C++. I used an offset dumper in order to obtain the static pointers and offsets that will lead to the temporary adresses of the dw_LocalPlayer, m_fFlags and dw_ForceJump. I am not using any memory editing classes like VAMemory.dll, just ReadProcessMemory. I found out that when the player is in the air, the value of m_fFlags is "256". When he is on the ground it is "257". However, I am not able to read these to values once I obtained a temporary adress. Here is the code:
// ConsoleApplication1.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <cstdint>
#define dwLocalPlayer 0xAB06EC
#define dwForceJump 0x4D6A684
#define fFlags 0x100
int main()
{
HWND hwnd = FindWindowA(NULL, "Counter-Strike: Global Offensive");
if (hwnd == NULL)
{
std::cout << "Error!" << std::endl;
exit(-1);
system("PAUSE");
}
else
{
DWORD pid = GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
DWORD tempadress;
ReadProcessMemory(pHandle, (PBYTE*)dwLocalPlayer, &tempadress, sizeof(tempadress), NULL);
DWORD fl_Onground = tempadress + fFlags;
std::cout << fl_Onground << "\n" << &fl_Onground << std::endl;
system("PAUSE");
}
return 0;
}
I would really appreciate some help and suggestions to the code since Im stuck on this since a few days. I am only trying to gain knowledge on C++ here, I do not want to code any cheats or whatnot...
You are not using the offsets correctly. The offsets that are supplied by the dumper need to be added to other addresses, such as the base address of the module.
dwLocalPlayer is not a pointer to the local player, it's an offset. You have to add it to the address of client_panorama.dll.
Secondly:
DWORD fl_Onground = tempadress + fFlags;
This gives you the address of fl_Onground but you never read it's value, your subsequent std::cout will print the address not the value.
Fixed code here:
#include <iostream>
#include <Windows.h>
#include <cstdint>
#include <TlHelp32.h>
#define dwLocalPlayer 0xD30B94
#define dwForceJump 0x51EE680
#define m_fFlags 0x104
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
int main()
{
HWND hwnd = FindWindowA(NULL, "Counter-Strike: Global Offensive");
if (hwnd == NULL)
{
std::cout << "Error!\n" << std::endl;
exit(-1);
system("PAUSE");
}
else
{
DWORD pid = GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
uintptr_t dllBaseAddress = 0;
dllBaseAddress = GetModuleBaseAddress(pid, L"client_panorama.dll");
DWORD tempadress;
ReadProcessMemory(pHandle, (BYTE*)(dllBaseAddress + dwLocalPlayer), &tempadress, sizeof(tempadress), NULL);
BYTE fl_Onground = 0;
ReadProcessMemory(pHandle, (BYTE*)(tempadress + m_fFlags), &fl_Onground, sizeof(fl_Onground), NULL);
std::cout << fl_Onground << "\n" << &fl_Onground << std::endl;
getchar();
}
return 0;
}
i'm trying to read the memory of a game called: "Prison Architect",
but i always have this value: "Money :-858993460"
I lost 2 days without have found any solutions.
I hope you can help me.
Pointer Info:
BaseAddress: "prison architect.exe"+00075140
Pointer1: 300
Pointer2: 88
Pointer3: 26c
Pointer4: 70
Pointer5: 328
int FindPointer(int offset, HANDLE pHandle, int baseaddr, int offsets[])
{
int Address = baseaddr;
int total = offset;
for (int i = 0; i < total; i++) //Loop trough the offsets
{
ReadProcessMemory(pHandle, (LPCVOID)Address, &Address, 4, NULL);
Address += offsets[i];
}
return Address;
}
int main()
{
int value = 0; // This will store our value. In my case, its an integer, which is the timer
DWORD pid; //This will store our Process ID, used to read/write into the memory
HWND hwnd; //Finally a handle to our window
hwnd = FindWindow(NULL, L"Prison Architect"); //Finds the Window
if (!hwnd) //If none, display an error
{
cout << "Window not found!\n";
cin.get();
}
GetWindowThreadProcessId(hwnd, &pid); //Get the process id and place it in pid
HANDLE phandle = OpenProcess(PROCESS_VM_READ, 0, pid); //Get permission to read
if (!phandle) //Once again, if it fails, tell us
{
cout << "Could not get handle!\n";
cin.get();
}
int baseAddress = 0x00197BE8;
int offsets[] = { 0x300, 0x88, 0x26c, 0x70, 0x328 };
while (1) {
int moneyRead = FindPointer(5, phandle, baseAddress, offsets); //number of offsets, HANDLE, base address, offsets
//reading
int money;
ReadProcessMemory(phandle, (LPVOID)moneyRead, &money, sizeof(money), 0);
cout << "\nMoney :" << money;
Sleep(3000);
}
return 0;
}
int baseAddress = 0x00197BE8;
You're using a hard coded address, which is bad practice because it may only work for this one instance of running the game process. When you re-open the game it probably will change.
The pointer must begin with an address that has a relative offset from a module. You then add the relative offset to the address of the module which you have calculated at run time. This will make it so your final address that is calculated always works correctly, regardless of ASLR.
You can use this function to find the base address of a module
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
Add the relative offset to the return value and use this as the base address of the pointer you pass into your FindPointer() function.