I want to change the permissions of a memory segment at run time (the memory section contains a function that I want to change its code at run time).
My first thought was to change the permissions to write - read, make the changes, return the permissions to execute only.
The thing is that I need to get the base address of my page, not the address of my function and only then I can tweak the permissions.
Here is the code, where I tried to execute it:
void encrypt_function()
{
PBYTE start_addr = (PBYTE)&function_to_hide1; // get location of function (can get some time jmp stub instead of actual function - need to find better approach).
DWORD size = (UINT_PTR)&empty_staub - (UINT_PTR)&function_to_hide1;
// try to get the base address of my function page - failed
_MEMORY_BASIC_INFORMATION lpBuffer;
VirtualQuery(start_addr, &lpBuffer, size);
DWORD old_flags = 0;
if (!VirtualProtect(start_addr, size, PAGE_EXECUTE_READWRITE, &old_flags)) // ERROR_INVALID_ADDRESS - it's not the base address
{
printf("went rung %d", GetLastError());
}// make function page read write execute permission
// can't be done - i dont have permission
for (DWORD i = 0; i < size; i++)
{
start_addr[i] ^= 0x55;
}
VirtualProtect(start_addr, size, old_flags, NULL);
}
For some reason, I cannot get the base address (the linker will not compile this code for some reason).
Does anyone know a better way to do this (modify permissions and perform function modification)?
To get the base address of the page in which your function resides you can use VirtualQuery(), then you pass mbi.BaseAddress to the VirtualProtect() call.
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(start_addr, &mbi, sizeof(mbi));
DWORD oldprotect;
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect);
As was discussed in the comments you should use VirtualAlloc() to get a new memory space and decrypt your function there,and do a simple detour to jump to it rather than doing the decryption in place.
Related
As the title suggests, I am trying to read memory from another process in C++ in order to check if the values from the other process reach a certain level. Since I don't know anything about this, I decided to consult GitHub Copilot for help. On a normal basis, I would search the docs, but Github seems to disagree. Since I have access to GitHub Copilot, and since the front page advertisement clearly encourages users to trust Copilot's programming ability, I chose to let Copilot make this function.
So I gave it a prompt in the form of a comment: //A function that can grab an address from the memory of another process and store it as a double value
What it gave me seemed pretty good, but I will never take a function that copilot makes and blindly use it unless I know for sure it will work (because I don't trust that everything Copilot makes is never going to cause issues, especially when dealing with pointers and such). I wanted to see if someone who had experience with memory in C++ could tell me if this function will work and why it would or wouldn't work as I know nothing about getting memory from another process.
There are three main reasons why I am not just searching the docs anyway despite GitHub's statement:
Since this is a complicated and real-world use case, this will really test Copilot's programming ability and it will give me insight into how much I can trust Copilot in the future for stuff I don't know how to do (Obviously I wouldn't let this get out of hand, but it would be good to know I can trust Copilot a little more than I do right now).
Searching the docs anyways despite the statement that GitHub made on their website is quite the opposite of what Copilot is supposed to help users with, and while I understand that it's a public beta and it's not complete yet, it should at least be good enough for real-world use cases rather than simple coding cases. An answer from someone experienced will really show if it is good enough for real-world coding cases.
The docs only tell me what a function does and what to put as its parameters, it doesn't tell me how to use it. If I really wanted to know how to use it, I would have to search the web. Searching the web will most likely get me complicated examples that don't pertain to my issue and defer me from what I am actually trying to accomplish. Not only that, but it is the opposite of what Copilot is supposed to help users with, as stated in reason #2.
Here is the code that Copilot generated for me:
DWORD GetAddress(DWORD dwProcessId, LPCWSTR szModuleName, const char* szProcName)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (hProcess == NULL)
return 0;
MODULEINFO modinfo;
GetModuleInformation(hProcess, GetModuleHandle(szModuleName), &modinfo, sizeof(MODULEINFO));
DWORD dwAddress = (DWORD)modinfo.lpBaseOfDll;
DWORD dwSize = (DWORD)modinfo.SizeOfImage;
MEMORY_BASIC_INFORMATION mbi;
while (dwSize > 0)
{
VirtualQueryEx(hProcess, (LPVOID)dwAddress, &mbi, sizeof(mbi));
if (mbi.State == MEM_COMMIT && !(mbi.Protect & PAGE_GUARD) && mbi.Protect & PAGE_EXECUTE_READWRITE)
{
DWORD dwOldProtect;
VirtualProtectEx(hProcess, (LPVOID)dwAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
char* szBuffer = new char[mbi.RegionSize];
ReadProcessMemory(hProcess, (LPVOID)dwAddress, szBuffer, mbi.RegionSize, NULL);
for (DWORD dwIndex = 0; dwIndex < mbi.RegionSize - 4; dwIndex++)
{
if (szBuffer[dwIndex] == '\x55' && szBuffer[dwIndex + 1] == '\x8B' && szBuffer[dwIndex + 2] == 'E' && szBuffer[dwIndex + 3] == 'A')
{
DWORD dwAddress2 = dwAddress + dwIndex + 7;
DWORD dwAddress3 = dwAddress2 + *(DWORD*)(dwAddress2);
if (strcmp((char*)dwAddress3, szProcName) == 0)
{
delete[] szBuffer;
CloseHandle(hProcess);
return dwAddress2 + 4;
}
}
}
delete[] szBuffer;
VirtualProtectEx(hProcess, (LPVOID)dwAddress, mbi.RegionSize, dwOldProtect, &dwOldProtect);
}
dwAddress += mbi.RegionSize;
dwSize -= mbi.RegionSize;
}
CloseHandle(hProcess);
return 0;
}
You may point out an immediately noticeable error: The function returns DWORD rather than double, which is what I asked Copilot to return. I saw that error but from examples that I have seen (Yes, I have done at least some searching), returning DWORD works as well. I could have seen those examples wrong, and if I am correct me.
The function returns double but it only returns the value that is stored in the memory, not actually double-typed data. If you do a casting to double, you get back your original data.
You can't search in memory with anything other than a byte pointer on 64-bit systems: http://msdn.microsoft.com/en-us/library/aa746449%28v=vs.85%29.aspx
There are different ways to search for a string in memory, depending on what you are looking for: http://www.catatonicsoft.com/blog/need-to-read-and-write-strings-and-data-in-a-processs-memory/
(Read more here: https://github.com/MicrosoftArchiveOrgMember/copilot)
Memory Scraper
This program uses several techniques to obtain information from processes and memory as it runs so that it can be added to the evidence file when Cofactor terminates the target process (by default) or when you terminate the program manually (with CTRL+C).
This code was mostly cobbled together from various examples at http://www.codeproject.com and https://forums.hak5.org, with some heavy modifications made to get the output in a useful format.
The process memory usage is checked continuously and added to the log file when it changes. This is done by getting a pointer to the process' memory region, then checking all of its pages as they are referenced. When they are changed, the contents of that page will be read and added to the log file as evidence. If a process goes in and out of sleep mode or is stopped for some other reason, this program will detect that and add it to the log file accordingly.
The current DLLs loaded by processes are recorded every 5 seconds so that if a DLL gets loaded after Cofactor terminates its target, it will still be included in the log file as evidence. A process is also checked every 5 seconds for new threads being spawned so that child processes are also included in our evidence files.
We could extend this program by having it check for two modules:
1) A module containing functions that correspond to debug breakpoints (which would detect whether a debugger was attached).
2) A module containing crash signatures - integers that would trigger an alert if they were found written to memory in any of our processes (like stack smashing protections might provide).
In order to do this without complicating things too much, I'd probably use CreateRemoteThread with an address within each module to continue execution from that thread into your own code where you can check for the breakpoint or crash signature and act accordingly.
Conclusion
If you need to debug a process and can't get it to stop for any reason, this program will still be able to grab the process memory at any time so that you can search for whatever you need.
You'll have to do some extra work in order to use the log file that is created, like parsing it with a parser of your choice and searching it (using regexes or something) which I assume is outside of the scope of what Copilot is designed to do.
If you end up using this program, please let me know! I'm curious to see how many people find this program useful.
Interesting Techniques I Learned From Other Programs
Finding DLLs Loaded by a Process
The C++ code below uses the Windows API GetModuleFileNameW() to get the full path of loaded DLLs and parses it with split() to extract just the filename and not the whole path. The rest of that code just tries to avoid duplicates while being simple enough that it doesn't get too confused between different processes and file system cases (hopefully).
// Code Example: Finding DLLs Loaded by a Process
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#define BUFF_SIZE 200
// Find the full path to a loaded DLL by process ID (PID) and its filename (first 8 characters)
void GetModuleFileNameEx(int pid, const char* szName, char* buff, int buffSize)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess == NULL) { return; }
HMODULE hMods[1024];
DWORD cbNeeded;
if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) { return; }
for (int i = 0; i < (int)(cbNeeded / sizeof(HMODULE)); i++) {
TCHAR szModName[MAX_PATH];
if (!GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName))) { continue; }
strcat_s((char*)buff, buffSize - 1 , (char*)szModName);
// Check if the first 8 characters of the filename in the process matches
// with what we are looking for and avoid adding duplicates
char* chPtr = strchr((char*)buff, '\\');
if (chPtr != NULL) {
*chPtr = 0;
strcat_s((char*)buff, buffSize - 1 , "\\");
strcat_s((char*)buff, buffSize - 1 , szName);
HANDLE hFile = CreateFileA((LPCSTR)buff, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); return; }
} else { break; }
}
}
int main() {
char szDllName[8]; // Maximum length of a module name is MAXPATH - 1 bytes including the NULL terminator. However we only need 8 characters to store the DLL name so use this limit to save memory.
int pid; scanf("%d", &pid);
if (pid == 0) { return 0; }
char buff[BUFF_SIZE];
GetModuleFileNameEx(pid, szDllName, buff, BUFF_SIZE);
char* chPtr = strchr(buff, '\\');
// Change the path separator character to a null terminator so we can split it
if (chPtr != NULL) { *chPtr = 0; }
chPtr = strtok(buff, "\\");
while (chPtr != NULL) {
printf("%s\n", chPtr);
chPtr = strtok(NULL, "\\");
}
return 0;
}
Now, I know questions similar to this may have been asked before, and trust me, for the past couple days I've been looking around the internet for an already-answered situation, however I still can't get this to work and to be honest, not sure why it isn't working. What I am attempting to do is get the ammo value in a game. readMemory, which is an int, is supposed to contain this value, however it's simply outputting 0.
ReadProcessMemory(handle, (PBYTE*)(base_adr), &pAddress1, sizeof(pAddress1), 0);
ReadProcessMemory(handle, (PBYTE*)(pAddress1 + offset_1), &pAddress2, sizeof(pAddress2), 0);
ReadProcessMemory(handle, (PBYTE*)(pAddress2 + offset_2), &pAddress3, sizeof(pAddress3), 0);
ReadProcessMemory(handle, (PBYTE*)(pAddress3 + offset_3), &pAddress4, sizeof(pAddress4), 0);
ReadProcessMemory(handle, (PBYTE*)(pAddress4 + offset_4), &pAddress5, sizeof(pAddress5), 0);
while (1)
{
ReadProcessMemory(handle, (PBYTE*)(pAddress5 + offset_5), &readMemory, sizeof(readMemory), 0);
cout << readMemory << endl;
}
Obviously, this isn't an efficient way of adding the pointers (nor is it a working way, I guess), and I'm looking for someone who can point me into the right direction. Thanks, and once again sorry for the (most likely in your eyes) a basic question.
DWORD base_adr = 0xCC8408;
const DWORD offset_1 = 0x23C;
const DWORD offset_2 = 0x7A4;
const DWORD offset_3 = 0x34C;
const DWORD offset_4 = 0x5B0;
const DWORD offset_5 = 0x2D8;
DWORD pAddress1;
DWORD pAddress2;
DWORD pAddress3;
DWORD pAddress4;
DWORD pAddress5;
Reading the MSDN article on function ReadProcessMemory the first thing I notice is this:
The entire area to be read must be accessible or the operation fails.
First thing I'd suggest is you check the return value of those calls. I'm pretty sure they all return 0 for "failed" so next thing you do is you call GetLastError to find out why exactly did it fail.
Once you figure that out you'll be able to fix it. More likely than not the problem is that your program doesn't have sufficient privileges to access another process's memory.
Quick search pops this OS article on how to properly access other process's memory: How is it possible to access memory of other processes?
I wonder why this code doesn't work:
#include <iostream>
using namespace std;
int main()
{
int *pointer = (int*)0x02F70BCC;
cout<<*pointer;
return 0;
}
In my opinion it should write on the screen value of 0x02F70BCC,
instead of this my programm crashes.
I know that memory with adress 0x02F70BCC stores value of 20.
But like I said no matter what it just doesn't want to show correct number.
Please help me guys, detailed explanation would be very nice of you.
It doesn't work, because you won't get access to every location in memory you want. Not every location in memory is valid, you may want to read about Virtual Address Space.
Some addresses are reserved for device drivers and kernel mode operations. Another range of addresses (for example 0xCCCCCCCC and higher) may be reserved for uninitialized pointers.
Even if some location is valid, operating system may still deny access to write to/read from certain location, if that would cause undefined behaviour or violate system safety.
EDIT
I think you might be interested in creating some kind of "GameHack", that allows you to modify amount of resources, number of units, experience level, attributes or anything.
Memory access is not a simple topic. Different OSes use different strategies to prevent security violations. But many thing can be done here, after all there is a lot software for doing such things.
First of all, do you really need to write your own tool? If you just want some cheating, use ArtMoney - it is a great memory editor, that I have been using for years.
But if you really have to write it manually, you need to do some research first.
On Windows, for example, I would start from these:
ReadProcessMemory
WriteProcessMemory
Also, I am quite certain, that one of possible techniques is to pretend, that you are a debugger:
DebugActiveProcess.
EDIT 2
I have done some research and it looks, that on Windows (I assume this is your platform, since you mentioned gaming; can't imagine playing anything on crappy Linux), steps required to write another process' memory are:
1. Enumerate processes: (EnumProcesses)
const size_t MAX_PROC_NUM = 512;
DWORD procIDs[MAX_PROC_NUM] = { 0 };
DWORD idsNum = 0;
if(!EnumProcesses(procIDs, sizeof(DWORD) * MAX_PROC_NUM, &idsNum))
//handle error here
idsNum /= sizeof(DWORD); //After EnumProcesses(), idsNum contains number of BYTES!
2. Open required process. (OpenProcess,GetModuleFileNameEx)
const char* game_exe_path = "E:\\Games\\Spellforce\\Spellforce.exe"; //Example
HANDLE game_proc_handle = nullptr;
DWORD proc_access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE; //read & write memory, query info needed to get .exe name
const DWORD MAX_EXE_PATH_LEN = 1024;
for(DWORD n = 0 ; n < idsNum ; ++idsNum)
{
DWORD current_id = procIDs[n];
HANDLE current_handle = OpenProcess(proc_access, false, current_id);
if(!current_handle)
{
//handle error here
continue;
}
char current_path[MAX_EXE_PATH_LEN];
DWORD length = GetModuleFileNameEx(current_handle, nullptr, current_path, MAX_EXE_PATH_LEN);
if(length > 0)
{
if(strcmp(current_path, game_exe_path) == 0) //that's our game!
{
game_proc_handle = current_handle;
break;
}
}
CloseHandle(current_handle); //don't forget this!
}
if(!game_proc_handle)
//sorry, game not found
3. Write memory (WriteProcessMemory)
void* pointer = reinterpret_cast<void*>(0x02F70BCC);
int new_value = 5000; //value to be written
BOOL success = WriteProcessMemory(game_proc_handle, pointer, &new_value, sizeof(int), nullptr);
if(success)
//data successfully written!
else
//well, that's... em...
This code is written just 'as is', but I see no errors, so you can use it as your starting point. I also provided links for all functions I used, so with some additional research (if necessary), you can achieve what you are trying to.
Cheers.
When you use,
cout<<*pointer;
the program tries to dereference the value of the pointer and writes the value at the address.
If you want to print just the pointer, use:
cout << pointer;
Example:
int main()
{
int i = 20;
int* p = &i;
std::cout << *p << std::endl; // print the value stored at the address
// pointed to by p. In this case, it will
// print the value of i, which is 20
std::cout << p << std::endl; // print the address that p points to
// It will print the address of i.
}
I've been trying to get this call to cooperate, but to no success.
I'm trying to get the SID value for the current user in order to get the User's account rights (using LsaEnumerateAccountRights). Although I'm lost as to why My call to GetTokenInformation is returning false. No error in retrieving the process token.
Here is my work so far on the subject:
HANDLE h_Process;
HANDLE h_Token;
HANDLE h_retToken;
TOKEN_USER tp;
DWORD cb = sizeof(TOKEN_USER);
PDWORD ret;
DWORD dw_TokenLength;
h_Process = GetCurrentProcess();
if (OpenProcessToken(h_Process, TOKEN_READ, &h_Token) == FALSE)
{
printf("Error: Couldn't open the process token\n");
return -1;
}
if (GetTokenInformation(h_Token, TokenUser, &tp, cb, &dw_TokenLength) == FALSE)
{
printf("Error: Could not retrieve Token User information");
return -1;
}
And along with it, I might as well ask a follow up question that I have not yet encountered, how to retrieve the SID from the formed TOKEN_USER structure?
I apologize ahead of time for such a simple question, I'm just stumped and would like some help to continue. All the questions related to this one are far more complicated and give little insight to my current problem.
Thanks in advance,
Jon
According to the documentation For GetTokenInformation, if the function fails you can retrieve more information via a call to GetLastError.
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
So you need to implement some checking for the extended error:
if (!GetTokenInformation(h_Token, TokenUser, &tp, cb, &dw_TokenLength))
{
int lastError = GetLastError();
// Should be a switch, of course. Omitted for brevity
if (lastError == ERROR_INSUFFICIENT_BUFFER)
{
//
}
}
As a general rule of thumb when using WinAPI functions that have varying buffer requirements, you typically
Call the function with a NULL buffer to determine the buffer size needed (in this case, returned in the ReturnLength parameter)
Allocate a buffer of the indicated size
Call the function again, passing the allocated buffer, to obtain the information
The first thing to understand is that Win32 UM (user mode) APIs that result into system calls generally require that you provide the buffer up front. This has to do with the fact that the kernel can access UM heap allocations, and UM cannot access KM allocations.
These calls typically follow a convention where you call once to get the required buffer size, and then call again with an allocated buffer that is large enough. It is even better though if you can create a reasonably sized buffer upfront. System calls can be expensive because of the context switching that it causes, so going from 2 calls to 1 can be a big performance improvement if it is a hot path.
Here is a sample of what you need. This has a loop that will try forever, but it is also common to just try twice. If the needed buffer is <= 128, it will only call once.
DWORD bytesReturned = 128;
LPVOID tokenUser = nullptr;
auto cleanup = ScopeExit([&]()
{
LocalFree(tokenUser);
});
for (;;) {
tokenUser = LocalAlloc(LMEM_FIXED, bytesReturned);
THROW_HR_IF_NULL(E_OUTOFMEMORY, tokenUser);
if (!GetTokenInformation(token.get(), TokenUser, &tokenUser, bytesReturned, &bytesReturned))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
LocalFree(tokenUser);
tokenUser = nullptr;
continue;
}
THROW_HR(HRESULT_FROM_WIN32(GetLastError()));
}
break;
}
The other big problem with your code is that you are passing in a reference to TOKEN_USER tp. The API actually just takes a PVOID. The SID's buffer will just be in tokenUser's buffer. You will need to cast it to a TOKEN_USER* to correctly access the memory.
I'd like to access a spawned process's TIB (I created the process with CreateProcessW successfully).
I have obtained a pointer to the spawned process's TIB through:
GetThreadContext (with permissions set of course)
Accessing pContext.SegFs
Formatting this value like so: (ldtSel.HighWord.Bits.BaseHi << 24 ) | ( ldtSel.HighWord.Bits.BaseMid << 16 ) | ( ldtSel.BaseLow ); (I don't think this is necessary).
The value I am left with after the format is a 10 digit pointer.
How am I to use this variable in place of the fs register to access the threads information block?
The conventional way I would access it generally would be as so:
__asm
{
mov eax, fs:[0x30] // PEB
mov dwPebBase, eax
}
However, replacing the "fs" with the pointer variable of course wouldn't work, and removing the semi-colon had unexpected results.
So how can I access the members of the TIB through this pointer value, I feel as if I am accessing memory that isn't supposed to be accessed (or attempting to anyway :P).
Thank you for the help.
You are taking the wrong approach for this. Use NtQueryInformationProcess() instead of GetThreadContext() to access the spawned process's PEB, eg:
PROCESS_INFORMATION pi = {0};
...
PROCESS_BASIC_INFORMATION pbi = {0};
ULONG pbi_len = 0;
if (NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &pbi_len) >= 0)
{
if (pbi.PebBaseAddress)
{
PEB peb = {0};
SIZE_T peb_len = 0;
if (ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), &peb_len))
{
// use peb as needed...
}
}
}
Refer to the following article for more info:
Get Process Info with NtQueryInformationProcess
a simple trick is call ntdll!RtlGetCurrentPeb() in your local process, this routine return a pointer to PEB, this pointer is in fact valid, and also point to PEB in remote process, then you can use ReadProcessMemory() to read what you need.