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;
}
Related
I am trying to add a new section to a portable executable, where I need to write some data, in this case an entire file.
The second file is able to parse itself and read the data from the section I created inside of it, but for some reason, it gets corrupted when I modify it using the code below.
The Imgur links are below: I'm sorry for the bad formatting :(
This messagebox should appear.
But I get this error message instead: "This app cannot run on your pc."
The new section gets added properly inside the PE:
The data inside the new section:
I can't really tell what is wrong here.
#include <iostream>
#include <Windows.h>
#include <ShlObj.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Shlwapi.lib")
DWORD align(DWORD size, DWORD align, DWORD addr) {
if (!(size % align))
return addr + size;
return addr + (size / align + 1) * align;
}
int main(int argc, char* argv[])
{
if (argc < 3)
{
std::cout << "Argomenti insufficienti.\n";
return 0;
}
char PathToSave[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, PathToSave)))
{
PathAppendA(PathToSave, "Bind.exe");
}
HANDLE fOutput = CreateFileA(PathToSave, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL); // Unused
HANDLE FirstFile = CreateFileA(argv[5], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); // File to read data from
if (FirstFile == INVALID_HANDLE_VALUE)
{
std::cout << "Impossibile aprire il file passato come primo argomento.\n";
return 0;
}
HANDLE SecFile = CreateFileA(argv[5], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); // File to write the read data in
if (SecFile == INVALID_HANDLE_VALUE)
{
std::cout << "Impossibile aprire il file passato come secondo argomento.\n";
return 0;
}
DWORD FirstFS = GetFileSize(FirstFile, 0); // First file dimension
DWORD SecondFS = GetFileSize(SecFile, 0); // Second file dimension
BYTE* FirstFB = (BYTE*)VirtualAlloc(NULL, FirstFS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Allocates memory for the first file
BYTE* SecondFB = (BYTE*)VirtualAlloc(NULL, SecondFS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Allocates memory for the second file
DWORD BytesRead = 0;
DWORD BytesWritten = 0;
if (bool Read = ReadFile(FirstFile, FirstFB, FirstFS, &BytesRead, NULL) == FALSE) // Reads the first file
{
std::cout << "Impossibile leggere primo file.\n";
return 0;
}
else
{
std::cout << "Letti " << BytesRead << " dal primo file.\n";
BytesRead = 0;
}
if (bool Read = ReadFile(SecFile, SecondFB, SecondFS, &BytesRead, NULL) == FALSE) // Reads the second file
{
std::cout << "Impossibile leggere secondo file.\n";
return 0;
}
else
{
std::cout << "Letti " << BytesRead << " bytes dal secondo file.\n";
BytesRead = 0;
}
/*
*
* The code is problematic beyond this point!
*
* SecondFB = Pointer to the second file's data buffer that needs to be modified by adding the new section.
* FirstFB = Pointer to the first file's data buffer that will be written inside the ".sdata" section.
* Both of them have been loaded in memory using VirtualAlloc.
*
* Ask me anything for further info and many, many thanks :D
*/
// Here I add a new section to the second file.
PIMAGE_DOS_HEADER sIDH = (IMAGE_DOS_HEADER*)SecondFB;
PIMAGE_NT_HEADERS sINH = (IMAGE_NT_HEADERS*)(SecondFB + sIDH->e_lfanew);
PIMAGE_FILE_HEADER sIFH = (PIMAGE_FILE_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD));
PIMAGE_OPTIONAL_HEADER sIOH = (PIMAGE_OPTIONAL_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
PIMAGE_SECTION_HEADER sISH = (PIMAGE_SECTION_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS));
// Here I name the new section inside the file
ZeroMemory(sISH, sizeof(IMAGE_SECTION_HEADER));
CopyMemory(sISH[sIFH->NumberOfSections].Name, ".scode", 8);
/*
0xE00000E0 = IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_CNT_CODE |
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ
*/
// Here all the required information gets filled in
sISH[sIFH->NumberOfSections].VirtualAddress = align(sISH[sIFH->NumberOfSections - 1].Misc.VirtualSize, sIOH->SectionAlignment, sISH[sIFH->NumberOfSections - 1].VirtualAddress);
sISH[sIFH->NumberOfSections].SizeOfRawData = align(FirstFS, sIOH->SectionAlignment, 0);
sISH[sIFH->NumberOfSections].Misc.VirtualSize = align(FirstFS, sIOH->SectionAlignment, 0);
sISH[sIFH->NumberOfSections].PointerToRawData = align(sISH[sIFH->NumberOfSections - 1].SizeOfRawData, sIOH->FileAlignment, sISH[sIFH->NumberOfSections - 1].PointerToRawData);
sISH[sIFH->NumberOfSections].Characteristics = 0xE00000E0;
// Here the changes are written to the second file
SetFilePointer(SecFile, sISH[sIFH->NumberOfSections].PointerToRawData + sISH[sIFH->NumberOfSections].SizeOfRawData, NULL, FILE_BEGIN);
SetEndOfFile(SecFile);
sIOH->SizeOfImage = sISH[sIFH->NumberOfSections].VirtualAddress + sISH[sIFH->NumberOfSections].Misc.VirtualSize;
sIFH->NumberOfSections += 1;
SetFilePointer(SecFile, 0, NULL, FILE_BEGIN);
BytesWritten = 0;
bool W = WriteFile(SecFile, SecondFB, SecondFS, &BytesWritten, NULL);
if (W == FALSE)
{
std::cout << "Impossibile aggiungere sezione alla stub.\n";
return 0;
}
else
{
std::cout << "Scritti " << BytesWritten << " bytes nella stub. (Aggiunta nuova sezione.)\n";
BytesWritten = 0;
}
// Here I write the data inside the new section
SetFilePointer(SecFile, sISH[sIFH->NumberOfSections - 1].PointerToRawData, 0, FILE_BEGIN);
if (bool Write = WriteFile(SecFile, FirstFB, FirstFS, &BytesWritten, NULL) == FALSE)
{
std::cout << "Impossibile aggiungere sezione alla stub.\n";
}
else
{
std::cout << "Scritti " << BytesWritten << " bytes nella stub.\n";
BytesWritten = 0;
}
// Here I close all the handles
VirtualFree(FirstFB, FirstFS, MEM_RELEASE);
CloseHandle(FirstFile);
VirtualFree(SecondFB, SecondFS, MEM_RELEASE);
CloseHandle(SecFile);
std::cout << "Binding completato.\n";
return 0;
}
The problem is in ZeroMemory(sISH, sizeof(IMAGE_SECTION_HEADER));
You removed the memory of the first section, which caused problems with the section structure of the exe. This is why the exe cannot run.
Solution:
=> ZeroMemory(&sISH[sIFH->NumberOfSections], sizeof(IMAGE_SECTION_HEADER)); //Clear the memory behind the last section
Don't forget to add FILE_SHARE_WRITE for the first CreateFileA, otherwise it will cause the second CreateFileA to fail to write.
=> HANDLE FirstFile = CreateFileA(argv[5], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); // File to read data from
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:
The codes are as follows. I want to enumerate all the ips. Part of the codes are used to my GUI, i am sure that the error has no relevance with them.
void udpchat1::getNameAndIp() {
struct hostent *host;
struct in_addr *ptr;
DWORD dwScope = RESOURCE_CONTEXT;
NETRESOURCE *NetResource = NULL;
HANDLE hEnum;
WNetOpenEnum(dwScope, NULL, NULL, NULL, &hEnum);
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
ui.IpListWidget->clear();
names.clear();
ui.chatIpLabel->setText("1111111111111");
sendAble = false;
// flag = false;
if (hEnum)
{
DWORD Count = 0xFFFFFFFF;
DWORD BufferSize = 10240;
LPVOID Buffer = new char[10240];
WNetEnumResource(hEnum, &Count, Buffer, &BufferSize);
NetResource = (NETRESOURCE*)Buffer;
char szHostName[200];
for (unsigned int i = 0; i < BufferSize / sizeof(NETRESOURCE); i++, NetResource++)
{
if (NetResource->dwUsage == RESOURCEUSAGE_CONTAINER && NetResource->dwType == RESOURCETYPE_ANY)
{
if (NetResource->lpRemoteName)
{
CString strFullName = NetResource->lpRemoteName;
if (0 == strFullName.Left(2).Compare(_T("\\\\")))
strFullName = strFullName.Right(strFullName.GetLength() - 2);
gethostname(szHostName, strlen(szHostName));
USES_CONVERSION;
char *pchar = T2A(strFullName);
host = gethostbyname(pchar);
if (host == NULL) continue;
ptr = (struct in_addr *) host->h_addr_list[0];
std::string str = "";
for (int n = 0; n < 4; n++)
{
CString addr;
if (n > 0)
{
str += ".";
}
int value = (unsigned int)((unsigned char*)host->h_addr_list[0])[n];
char p[20];
sprintf(p, "%d", value);
str.append(p);
}
names.insert(std::pair<std::string, std::string>(host->h_name, str));
ui.IpListWidget->addItem(QString::fromStdString(host->h_name));
//std::cout << "IP:" << str << " Name:" << host->h_name << std::endl;
}
}
}
delete Buffer;
WNetCloseEnum(hEnum);
}
WSACleanup();
}
I used debugging, and i found the program can not get in to this if statement.
if (NetResource->lpRemoteName)
Here is a screenshot of the debug inspector.
I have a PLC connected to one of my laptop's COM Ports and I've trying to send it a default command that returns a default response. Currently WriteFile successfully sends the 20 bit command but ReadFile doesn't read anything though there's no error.
int main(){
HANDLE hCom = CreateFile("\\\\.\\COM4",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hCom == INVALID_HANDLE_VALUE)
{
DWORD err=GetLastError();
std::cout << "Failed\n";
return 0;
}
DCB dcbConfig;
if(GetCommState(hCom, &dcbConfig))
{
dcbConfig.BaudRate = CBR_115200;
dcbConfig.ByteSize = 8;
dcbConfig.Parity = NOPARITY;
dcbConfig.StopBits = ONESTOPBIT;
dcbConfig.fBinary = TRUE;
dcbConfig.fParity = FALSE;
}
if(!SetCommState(hCom, &dcbConfig))
{
CloseHandle(hCom);
return 0;
}
COMMTIMEOUTS commTimeout;
if(GetCommTimeouts(hCom, &commTimeout))
{
commTimeout.ReadIntervalTimeout = 1;
commTimeout.ReadTotalTimeoutConstant = 1;
commTimeout.ReadTotalTimeoutMultiplier = 1;
commTimeout.WriteTotalTimeoutConstant = 1;
commTimeout.WriteTotalTimeoutMultiplier = 1;
}
if(!SetCommTimeouts(hCom, &commTimeout))
//Handle Error Condition
CloseHandle(hCom);
// Write to the COM
static char data[22]="%01#RDD0010000107**\n";
int size = strlen(data);
DWORD dwWritten, dwReading;
int j;
WriteFile(hCom,data,(DWORD)size,&dwWritten,NULL);
DWORD err=GetLastError();
std::cout << err;
char datarecv[22];
ReadFile(hCom,&datarecv,1,&dwReading,NULL);
err = GetLastError();
std::cout << err;
std::cout << datarecv << "\n";
CloseHandle(hCom);
std::cin>>j;
return 0;
}
I'd like to have a function that allows me to read the memory of another process.
I was thinking about something like this (pseudo code):
staticAddress = 0x026E0DC4
processId = GetProcessIdByName(processName)
processHandle = GetProcessHandle(processId)
processBaseAddress = GetBaseAddress(processHandle)
addressToRead = processBaseAddress+staticAddress
readValueAsInt = ReadMemoryInt(processHandle, addressToRead)
readValueAsFloat = ReadMemoryFloat(processHandle, addressToRead)
readValueAsString = ReadMemoryString(processHandle, addressToRead)
Would that even be possible?
Here is what I got so far:
#include <Windows.h>
#include <conio.h>
#include <tlhelp32.h>
#include <string>
#include <psapi.h>
#pragma comment( lib, "psapi" )
int GetProcessId(char* ProcName) {
PROCESSENTRY32 pe32;
HANDLE hSnapshot = NULL;
pe32.dwSize = sizeof( PROCESSENTRY32 );
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( Process32First( hSnapshot, &pe32 ) ) {
do {
if( strcmp( pe32.szExeFile, ProcName ) == 0 )
break;
} while( Process32Next( hSnapshot, &pe32 ) );
}
if( hSnapshot != INVALID_HANDLE_VALUE )
CloseHandle( hSnapshot );
return pe32.th32ProcessID;
}
int GetModuleBase(HANDLE processHandle, string &sModuleName)
{
HMODULE *hModules;
char szBuf[50];
DWORD cModules;
DWORD dwBase = -1;
//------
EnumProcessModules(processHandle, hModules, 0, &cModules);
hModules = new HMODULE[cModules/sizeof(HMODULE)];
if(EnumProcessModules(processHandle, hModules, cModules/sizeof(HMODULE), &cModules)) {
for(int i = 0; i < cModules/sizeof(HMODULE); i++) {
if(GetModuleBaseName(processHandle, hModules[i], szBuf, sizeof(szBuf))) {
if(sModuleName.compare(szBuf) == 0) {
dwBase = (DWORD)hModules[i];
break;
}
}
}
}
delete[] hModules;
return dwBase;
}
int ReadMemoryInt(HANDLE processHandle, LPCVOID address) {
//LPVOID buffer = ??;
//SIZE_T size = ??;
SIZE_T NumberOfBytesToRead = 4; //??
ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
return buffer; //??
}
int ReadMemoryFloat(HANDLE processHandle, LPCVOID address) {
//LPVOID buffer = ??;
//SIZE_T size = ??;
SIZE_T NumberOfBytesToRead = 8; //??
ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
return buffer; //??
}
int ReadMemoryString(HANDLE processHandle, LPCVOID address) {
//LPVOID buffer = ??;
//SIZE_T size = ??;
SIZE_T NumberOfBytesToRead = 999; //??
ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
return buffer; //??
}
int main()
{
//read an integer from "Program.exe"+0x05D8A3C4
int address = 0x05D8A3C4;
char* processName = "Program.exe";
int processId = GetProcessId(processName);
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
int processBaseAddress = GetModuleBase(processHandle, (string)"Program.exe";
LPCVOID actualAddress = processBaseAddress+address;
int readValue = ReadMemory(processHandle, actualAddress);
std::cout << readValue << std::endl;
CloseHandle(processHandle);
return 0;
}
As you can see form the question marks in the code I'm really unsure about the "buffer" and "size" parameters of ReadProcessMemory. I'd really appreciate it if someone could help me figuring this out.
https://github.com/T-vK/Memory-Hacking-Class
Is a pretty simple class to do all that and even more.
Here is a list with all the methods it supports:
GetProcessId()
GetModuleBase()
SetPrivilege()
GetDebugPrivileges()
ReadInt()
GetPointerAddress()
ReadPointerInt()
ReadFloat()
ReadPointerFloat()
ReadText()
ReadPointerText()
Example usage:
#include "Memory.hpp"
using std::string;
int main() {
char* TARGET_PROCESS_NAME = "League of Legends.exe";
int GAME_VERSION_MODULE_OFFSET = 0x2A1D738; // [Base address of 'League of Legends.exe']+0x2A1D738 (address of a string containing a version number)
Memory Memory;
Memory.GetDebugPrivileges();
int processId = Memory.GetProcessId(TARGET_PROCESS_NAME);
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
int baseAddress = Memory.GetModuleBase(processHandle, (string)TARGET_PROCESS_NAME);
int gameVersionAddress = baseAddress + GAME_VERSION_MODULE_OFFSET;
string gameVersion = Memory.ReadText(processHandle, gameVersionAddress);
std::cout << "Game version: " << gameVersionAddress << std::endl;
cin.get();
return 0;
}
In case you were wondering, yes, I'm the author.
Here is an example for your ReadMemoryInt() function:
int ReadMemoryInt(HANDLE processHandle, LPCVOID address) {
int buffer = 0;
SIZE_T NumberOfBytesToRead = sizeof(buffer); //this is equal to 4
SIZE_T NumberOfBytesActuallyRead;
BOOL err = ReadProcessMemory(processHandle, address, &buffer, NumberOfBytesToRead, &NumberOfBytesActuallyRead);
if (err || NumberOfBytesActuallyRead != NumberOfBytesToRead)
/*an error occured*/ ;
return buffer;
}
The & mean that the address of the variable is passed instead its value.
And in ReadMemoryString() you cannot know the actual size you need to read, you could either read a big block (size 999) or read many little blocks till you get one containing \0.
And if you want to know if it works, you can start it in a debugger and look if the values you expect are returned.