Writing to multilevel pointer crashes .exe - c++

I'm trying to edit pointer's value with dll but it crashes the program. Pointer is 100% correct (checked and tested with cheat engine). My goal is to change its value to 1 (I can do it via cheat engine, but I need to convert it to code).
typedef void(__fastcall* _wh)(int val);
_wh wh;
uintptr_t FinalAddress(uintptr_t ptr, std::vector<DWORD> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
addr = *(uintptr_t*)addr;
addr += offsets[i];
}
return addr; // returns the main pointer from needed assets
}
DWORD WINAPI HackThread(HMODULE hModule)
{
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
std::cout << "dll injected\n" << std::endl;
uintptr_t moduleBase = (uintptr_t)GetModuleHandle(L"Soria2.pl.exe");
uintptr_t adres = FinalAddress(moduleBase + 0x267D94, {0xC, 0x66C});
wh = (_wh)adres; // access the pointer's pointer to edit the value;
std::cout << wh;
while (true)
{
if (GetAsyncKeyState(VK_SHIFT) & 1)
{
wh(1);
}
Sleep(10);
}
fclose(f);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
return 0;
}

Ok I've figured it out. It turned out that the thing I wanted was just a variable and I wanted to call the function. This part was problematic:
wh = (_wh)adres; // access the pointer's pointer to edit the value;
I changed it to:
int* wallHack = (int*)adres
and simply changed the value to:
*wallhack = 1

Related

Memory leak when using IShellItem2.GetString()

I'm using the following code to enumerate the contents of the Recyclebin Shell folder and get the file type of each item.
The code gives the expected results but if I call the function in a loop it looks like there's some memory leak when using the IshellItem2 GetString function (see attached screenshot at the end).
Am I cleaning up everything properly?
Am I misinterpreting the results?
void Test1()
{
// Get recyclebin ishellitem
IShellItem* psiRecycleBin;
if (SUCCEEDED(SHGetKnownFolderItem(FOLDERID_RecycleBinFolder, KF_FLAG_DEFAULT,
NULL, IID_PPV_ARGS(&psiRecycleBin))))
{
// Get ishellitem contents enumerator
IEnumShellItems* pesi;
if (SUCCEEDED(psiRecycleBin->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&pesi))))
{
IShellItem* psi;
while (pesi->Next(1, &psi, NULL) == S_OK)
{
// Get ishellitem2 from ishellitem
IShellItem2* psi2;
if (SUCCEEDED(psi->QueryInterface(IID_PPV_ARGS(&psi2))))
{
// Get the item file type string
LPWSTR fileType = NULL;
if (SUCCEEDED(psi2->GetString(PKEY_ItemTypeText, &fileType)))
{
CoTaskMemFree(fileType);
}
psi2->Release();
}
psi->Release();
}
pesi->Release();
}
psiRecycleBin->Release();
}
}
And I'm calling it in loop like this:
#define STRICT_TYPED_ITEMIDS
#include <shlobj.h>
#include <propkey.h>
#include <iostream>
void Test1();
int main()
{
(void)CoInitialize(NULL);
std::cout << "Enumerating recyclebin items..\n";
for (int ii = 0; ii < 5000; ii++)
{
Test1();
}
CoUninitialize();
return 0;
}
When debugging this console program in VS in the memory diagnostics window this is what I get:
Thanks for the help
yes, here really exist memory leak, related to HIDDENRECYCLEBINDATAV2 structure from shell32.dll
partial definition of it:
struct HIDDENRECYCLEBINDATAV2
{
//... some mebers
FILETIME time;
PWSTR pszLocationBeforeDelete = 0; // !!! not released
PWSTR pszLocationInRecycleBin = 0; // !!! not released
HRESULT Serialize(PBYTE *, PUSHORT);
static HRESULT Deserialize(
_In_reads_bytes_opt_(cbStream) const BYTE *pbStream ,
_In_ USHORT cbStream,
_Out_ HIDDENRECYCLEBINDATAV2 ** pphrbd);
static HRESULT Initialize(HIDDENRECYCLEBINDATAV1 const *, HIDDENRECYCLEBINDATAV2**);
};
this structure hold 2 strings - file path from where it deleted ( pszLocationBeforeDelete - this is my name, i don't know original) and current file path in Recycle Bin ( pszLocationInRecycleBin - again my name)
this names allocated inside Deserialize method, by call IStream_ReadStrLong and must be freed with CoTaskMemFree. but how i found - CoTaskMemFree never called for this two strings.
pseudo code for Deserialize :
static HRESULT HIDDENRECYCLEBINDATAV2::Deserialize(
_In_reads_bytes_opt_(cbInit) const BYTE *pbStream ,
_In_ USHORT cbStream,
_Out_ HIDDENRECYCLEBINDATAV2 ** pphrbd)
{
HRESULT hr = E_FAIL;
if (HIDDENRECYCLEBINDATAV2 *phrbd = new HIDDENRECYCLEBINDATAV2)
{
if (IStream *pStream = SHCreateMemStream(pbStream, cbStream))
{
if (0 <= (hr = IStream_ReadStrLong(pStream, &phrbd->pszLocationBeforeDelete)) &&
0 <= (hr = IStream_ReadStrLong(pStream, &phrbd->pszLocationInRecycleBin)))
{
*pphrbd = phrbd, phrbd = 0;
}
pStream->Release();
}
CoTaskMemFree(phrbd); // !! error, need delete phrbd
}
return hr;
}
and it called from CBitBucket::_ValidateItem :
HRESULT InitDeletedItem(PCWSTR pszLocationBeforeDelete, PCWSTR pszLocationBeforeDelete, DELETEDITEM *);
static HRESULT CBitBucket::_ValidateItem(_ITEMIDLIST_RELATIVE const *, DELETEDITEM ** ppdi)
{
HIDDENRECYCLEBINDATAV2 * phrbd;
if (0 <= HIDDENRECYCLEBINDATAV2::Deserialize(pbStream, cbStream, &phrbd))
{
if (DELETEDITEM * pdi = new DELETEDITEM)
{
if (0 <= InitDeletedItem( phrbd->pszLocationBeforeDelete,
phrbd->pszLocationInRecycleBin, pdi))
{
*ppdi = pdi, pdi = 0;
}
if (pdi) delete pdi;
}
CoTaskMemFree(phrbd); // !! error, need delete phrbd
}
}
in both functions - memory for HIDDENRECYCLEBINDATAV2 simply released with CoTaskMemFree api, but memory for strings inside this structure not released. i think need add
HIDDENRECYCLEBINDATAV2::~HIDDENRECYCLEBINDATAV2()
{
CoTaskMemFree(pszLocationInRecycleBin);
CoTaskMemFree(pszLocationBeforeDelete);
}
to this structure and call delete instead CoTaskMemFree
how possible found this ? i hook RtlAllocateHeap and RtlFreeHeap before second call to Test1() (important do this not on first call, because during first call may be additional libs load, some differed initialization, etc.. - all this can distort the real result)and log all alloc/free calls in current thread. also i replace while (pesi->Next..) to if (pesi->Next..) (usually one iteration is enough ). and i found that count of alloc on 2 more than count of free. so i easy found from where this 2 allocations- inside IStream_ReadStrLong. then i set breakpoint here and easy view from where this called :
CBitBucket::_ValidateItem
HIDDENRECYCLEBINDATAV2::Deserialize
IStream_ReadStrLong
CoTaskMemAlloc
partial demo code for log:
struct AI
{
PVOID BaseAddress;
PVOID From;
ULONG Size;
ULONG Flags;
};
struct TID
{
AI *pi;
ULONG nAlloc, nFree, nCells, MaxAllocDelta;
BOOL bNotLog;
TID()
{
RtlZeroMemory(this, sizeof(*this));
}
};
BOOLEAN NTAPI hook_RtlFreeHeap(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress )
{
TID* p = RTL_FRAME<TID>::get();
if (!p || p->bNotLog)
{
return RtlFreeHeap(HeapHandle, Flags, BaseAddress) != 0;
}
p->bNotLog = TRUE;
if (!RtlFreeHeap(HeapHandle, Flags, BaseAddress))
{
__debugbreak();
}
if (BaseAddress)
{
AI* pi = p->pi;
ULONG n = p->nCells;
do
{
if (pi->BaseAddress == BaseAddress)
{
pi->BaseAddress = 0;
p->nFree++;
break;
}
} while (pi++, --n);
if (!n)
{
__debugbreak();
}
}
p->bNotLog = FALSE;
return TRUE;
}
PVOID NTAPI hook_RtlAllocateHeap( PVOID HeapHandle, ULONG Flags, SIZE_T Size )
{
TID* p = RTL_FRAME<TID>::get();
if (!p || p->bNotLog)
{
return RtlAllocateHeap(HeapHandle, Flags, Size);
}
p->bNotLog = TRUE;
if (PVOID BaseAddress = RtlAllocateHeap(HeapHandle, Flags, Size))
{
AI* pi = p->pi;
ULONG n = p->nCells;
do
{
if (!pi->BaseAddress)
{
pi->BaseAddress = BaseAddress;
pi->From = _ReturnAddress();
pi->Size = (ULONG)Size;
pi->Flags = Flags;
p->nAlloc++;
ULONG k = p->nAlloc - p->nFree;
if (k > p->MaxAllocDelta)
{
p->MaxAllocDelta = k;
}
break;
}
} while (pi++, --n);
if (!n)
{
__debugbreak();
}
p->bNotLog = FALSE;
return BaseAddress;
}
return 0;
}
void TestEx()
{
enum { cell_count = 0x1000 };
if (AI* pi = new AI[cell_count])
{
Test1();// first call
// hook RtlAllocateHeap + RtlFreeHeap
{
RtlZeroMemory(pi, cell_count * sizeof(AI));
RTL_FRAME<TID> f;
f.pi = pi;
f.nCells = cell_count;
Test1();// second call
DbgPrint("%x(%x) %x\n", f.nAlloc, f.nFree, f.MaxAllocDelta);
if (f.nAlloc - f.nFree)
{
ULONG n = cell_count;
AI* qi = pi;
do
{
if (qi->BaseAddress)
{
DbgPrint("%p> %x %x\n", qi->From, qi->Size, qi->Flags);
}
} while (qi++, --n);
}
}
delete [] pi;
}
}

How to write process memory with multilevel pointer with c++?

I'm trying to make a cheat for RE2. I found memory's with pointer-scan with cheat engine. My code is not working :(
#include <iostream>
#include <windows.h>
using namespace std;
int main() {
int newValue = 10 ;
HWND hwnd = FindWindowA(NULL, "RESIDENT EVIL 2");
if ( hwnd == NULL )
{
cout << endl << "Process handle not found !" << endl;
return 0 ;
} else {
DWORD pId;
GetWindowThreadProcessId(hwnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if(!hProc) {
cerr << "Cannot open process !" << endl ;
} else {
int c = WriteProcessMemory(hProc, (LPVOID)0x707B6D0 + 0x80 + 0x78 + 0x98 + 0x50 + 0x18, &newValue, (DWORD)sizeof(newValue), NULL);
if (c>0) {
clog << "yes" << endl ;
} else {
clog << "no" << endl ;
}
CloseHandle(hProc);
}
}
return 0;
}
You are misinterpreting what Cheat Engine is showing you.
In your code, 0x707B6D0 + 0x80 + 0x78 + 0x98 + 0x50 + 0x18 equals 0x707B8C8, which is NOWHERE even close to the value of 0x0EC1A3F0 that you are trying to reach.
What you need to do instead is:
First, read a pointer that is stored at the base address 0x707B6D0 (the value read is 0x128BFBB0).
Then, add 0x18 to that pointer (0x128BFBB0 + 0x18 = 0x128BFBC8) and read a new pointer at that address (the value read is 0x128564D0).
Then, add 0x50 to that pointer (0x128564D0 + 0x50 = 0x12856520) and read a new pointer at that address (the value read is 0x0F2EC940).
Then, add 0x98 to that pointer (0x0F2EC940 + 0x98 = 0x0F2EC9D8) and read a new pointer at that address (the value read is 0x0F2EB2B0).
Then, add 0x78 to that pointer (0x0F2EB2B0 + 0x78 = 0x0F2EB328) and read a new pointer at that address (the value read is 0x0EC1A370).
Then, add 0x80 to that pointer (0x0EC1A370 + 0x80 = 0x0EC1A3F0), and write your data to that address.
Try something more like this:
#include <iostream>
#include <stdexcept>
#include <memory>
#include <windows.h>
DWORD_PTR readPointerFromProc(HANDLE hProc, DWORD_PTR baseAddr)
{
DWORD ptr;
if (!ReadProcessMemory(hProc, reinterpret_cast<LPVOID>(baseAddr), &ptr, sizeof(ptr), NULL);
throw std::runtime_error("Cannot read from process !");
return ptr;
}
void WriteIntToProc(HANDLE hProc, DWORD_PTR baseAddr, int value)
{
if (!WriteProcessMemory(hProc, reinterpret_cast<LPVOID>(baseAddr), &value, sizeof(value), NULL);
throw std::runtime_error("Cannot write to process !");
}
struct HandleDeleter
{
typedef HANDLE pointer;
void operator()(HANDLE handle) const { CloseHandle(handle); }
};
int main()
{
int newValue = 10;
try
{
HWND hwnd = FindWindowA(NULL, "RESIDENT EVIL 2");
if (!hwnd)
throw std::runtime_error("Process window not found !");
DWORD pId = 0;
GetWindowThreadProcessId(hwnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pId);
if (!hProc)
throw std::runtime_error("Cannot open process !");
std::unique_ptr<HANDLE, HandleDeleter> hProc_deleter(hProc);
DWORD_PTR ptr = readPointerFromProc(hProc, 0x707B6D0);
ptr = readPointerFromProc(hProc, ptr + 0x18);
ptr = readPointerFromProc(hProc, ptr + 0x50);
ptr = readPointerFromProc(hProc, ptr + 0x98);
ptr = readPointerFromProc(hProc, ptr + 0x78);
writeIntToProc(hProc, ptr + 0x80, newValue);
}
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 0;
}
std::cout << "Success !" << std::endl;
return 0;
}
You need to de-reference between each offset so that you are following the pointer chain. Just adding the offsets is not enough.
Here is a function that does this for you, please keep in mind there is no error checking:
uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}
Calling the function would look like:
uintptr_t ammoAddr = FindDMAAddy(hProcess, dynamicPtrBaseAddr, { 0x374, 0x14, 0x0 });
It does not de-reference the last offset, which is ideal.
After that, call WriteProcessMemory using the return from that function as the lpBaseAddress argument.

self-mutating issues at the moment of change permisions

I am creating a self-mutation under Windows, but when I try to change my permissions page boundaries, it works under Dev C++, but the same code doesn't work under Visual Studio 2017. Once I compile it works, but it always return me original function result 1, mutation 1 when it should be 42.
Dev C++
int change_page_permissions_of_address(void *addr) {
// Move the pointer to the page boundary
int page_size = getpagesize();
DWORD dwOldProtect;
addr -= (unsigned uintptr_t)addr % page_size; // it works under dev c++
if(VirtualProtect(addr, page_size, PAGE_EXECUTE_READWRITE,&dwOldProtect) == -1) {
return -1;
}
return 0;
}
Visual Studio 2017
int change_page_permissions_of_address(void* address) {
// Move the pointer to the page boundary
unsigned char* addr = reinterpret_cast<unsigned char *>(address); // cast before operation
int page_size = getpagesize();
DWORD dwOldProtect;
addr -= (uintptr_t)addr % page_size; // doesnt work under visual studio
if (VirtualProtect(addr, page_size, PAGE_EXECUTE_READWRITE, &dwOldProtect) == -1) {
return -1;
}
return 0;
}
main
int main(){
void *foo_addr = (void*)foo;
if(change_page_permissions_of_address(foo_addr) == -1) {
fprintf(stderr, "Error while changing page permissions of foo(): %s\n", strerror(errno));
return 1;
}
// Call the unmodified foo()
puts("Calling foo...");
foo();
// Change the immediate value in the addl instruction in foo() to 42
unsigned char *instruction = (unsigned char*)foo_addr + 18;
*instruction = 0x2A;
// Call the modified foo()
puts("Calling foo..., but I am the self-modifying");
foo();
return 0;
}
self-mutation_visual

self-modifying under windows issue overwrite

I am writting a self-mutation code , and its original value before overwrite is 1,but after the overwrite should be 42. I think I am missing some aspecs because I got 1 on both original and mutation overwrite. my complete code looks like this gist link , but the original source was written under *unix https://shanetully.com/2013/12/writing-a-self-mutating-x86_64-c-program/
#include <windows.h>
#include <iostream>
using namespace std;
int getpagesize();
void foo(void);
int change_page_permissions_of_address(void *addr);
int getpagesize() {
SYSTEM_INFO si;
GetSystemInfo(&si);
return unsigned(si.dwPageSize);
}
void foo(void) {
int i = 0;
i++;
printf("i: %d\n", i);
}
int change_page_permissions_of_address(void *addr) {
// Get total function size
int page_size = getpagesize();
DWORD dwOldProtect;
// Obtain the addresses for the functions so we can calculate size.
uintptr_t tmp = (uintptr_t)addr-(uintptr_t)addr%page_size;
addr = (void*)tmp;
// We need to give ourselves access to modifify data at the given address
if (VirtualProtect(addr, page_size, PAGE_EXECUTE_READWRITE, &dwOldProtect) == -1) {
return -1;
}
return 0;
}
int main() {
void *foo_addr = (void*)foo;
if (change_page_permissions_of_address(foo_addr) == -1) {
printf("Error while changing page permissions of foo(): %s\n");
return 1;
}
// Call the unmodified foo()
puts("Calling foo...");
foo();
// Change the immediate value in the addl instruction in foo() to 42
unsigned char *instruction = (unsigned char*)foo_addr + 18;
*instruction = 0x2A;
puts("Calling foo..., but I am the self-modifying");
foo();
cin.get();
return 0;
}
Check of VirtualProtect is incorrect as it returns FALSE, not -1 in case of an error. Also I suspect that you will need to obtain a pointer to a starting page of the region of pages that foo belongs to and it is not clear where did you get offset 18 from.

InternetReadFile not getting entire file

I have the following code to download some rss files from servers, but so far I'm just getting incomplete version of my rss file.(?) The code is as follows -
#include<iostream>
#include<conio.h>
#include<stdio.h>
#include<string>
#include<cstring>
#include<wininet.h>
using namespace std;
const int _SIZE = 307200;
int WEB_GET_DATA(char* WEB_URL){
HINTERNET WEB_CONNECT = InternetOpen("Default_User_Agent",INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
if(!WEB_CONNECT){
cout<<"Connection Failed or Syntax error";
return 0;
}
HINTERNET WEB_ADDRESS = InternetOpenUrl(WEB_CONNECT,WEB_URL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, 0);
if(!WEB_ADDRESS){
cout<<"ERROR...\n";
return 0;
}
char _DATA_RECIEVED[_SIZE];
DWORD NO_BYTES_READ = 0;
while(InternetReadFile(WEB_ADDRESS,_DATA_RECIEVED,_SIZE,&NO_BYTES_READ)&&(NO_BYTES_READ)){
cout<<_DATA_RECIEVED;
}
InternetCloseHandle(WEB_ADDRESS);
InternetCloseHandle(WEB_CONNECT);
return 0;
}
int main(){
WEB_GET_DATA("http://themoneyconverter.com/rss-feed/AED/rss.xml");
getch();
return 0;
}
I'm getting only almost half of my file and not from start but my output is seeming to be starting from somewhere in between the file and then to it's end.
So where I'm going wrong? I checked that my rss file is at least gonna be 30kb large. So I have given the _SIZE const 307200 (300kb) and still it is not working? Please help me.
Try this instead:
int WEB_GET_DATA(char* WEB_URL)
{
HINTERNET WEB_CONNECT = InternetOpen("Default_User_Agent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!WEB_CONNECT)
{
cout << "Connection Failed or Syntax error" << endl;
return 0;
}
HINTERNET WEB_ADDRESS = InternetOpenUrl(WEB_CONNECT, WEB_URL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, 0);
if (!WEB_ADDRESS)
{
cout << "ERROR..." << endl;
InternetCloseHandle(WEB_CONNECT);
return 0;
}
DWORD DATA_SIZE = _SIZE;
char *_DATA_RECIEVED = new char[DATA_SIZE];
DWORD NO_BYTES_READ = 0;
do
{
if (InternetReadFile(WEB_ADDRESS, _DATA_RECIEVED, DATA_SIZE, &NO_BYTES_READ))
{
if (NO_BYTES_READ == 0)
break;
cout << string(_DATA_RECIEVED, NO_BYTES_READ);
}
else
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
cout << "Read error" << endl;
break;
}
delete[] _DATA_RECIEVED;
DATA_SIZE += _SIZE;
_DATA_RECIEVED = new char[DATA_SIZE];
}
}
while (true);
InternetCloseHandle(WEB_ADDRESS);
InternetCloseHandle(WEB_CONNECT);
return 0;
}
char buffer[200000];
DWORD bytes_read = 0;
DWORD currbytes_read;
do
{
bRead = InternetReadFile(file_handle, buffer + bytes_read, 200000 - bytes_read, &currbytes_read);
bytes_read += currbytes_read;
} while (bRead && currbytes_read);
buffer[bytes_read] = 0;
First of all, the problem you are having is that you are overwriting the same buffer and you are not clearing the data before each call of InternetReadFile. You also have not cleared the buffer before your first call. You are then throwing a potentially garbled mess of string and memory into a cout. This is very bad.
A quick fix would be to do this:
BYTE _DATA_RECIEVED[_SIZE]; // BYTE is a char, but its clearer now its not guaranteed to be a string!
BOOL ret = TRUE;
DWORD NO_BYTES_READ = 0;
while(ret){
memset(_DATA_RECIEVED, 0, _SIZE); // clear the buffer
ret = InternetReadFile(WEB_ADDRESS,_DATA_RECIEVED,_SIZE,&NO_BYTES_READ);
if(NO_BYTES_READ > 0)
cout<<_DATA_RECIEVED;
}
This is not the most elegant way of doing it (far from it), but at least you should get the data you expect back.
Remember, InternetReadFile passes back a buffer of data, not necessarily a string! It could be an image, junk, and even if it is a string, in your case, it wont have a null byte to close it off. InternetReadFile reads raw bytes, NOT text.
A more elegant solution might start like this:
std::string resultRss;
BYTE _DATA_RECIEVED[_SIZE];
DWORD NO_BYTES_READ = 0;
while(InternetReadFile(WEB_ADDRESS,_DATA_RECIEVED,_SIZE,&NO_BYTES_READ)){
resultRss.append((char*)_DATA_RECIEVED, NO_BYTES_READ); //doesn't matter about null-byte because we are defining the number of bytes to append. This also means we don't NEED to clear the memory, although you might want to.
}
//output final result
cout << resultRss;
Also, as a commenter added, you need to lay off the ALLCAPS for variables.
Hope this helps.