Jump to content
Moopler
Sign in to follow this  
hackbotmaple

Help C++ Dereferencing multi layer pointer address

Recommended Posts

Hello guys, I've been stuck for a few days now before I decided to post here. Not sure which part is wrong... 

I'm trying to get the value from the pointer address for Current HP, 02B0B7E0 with 2 offsets 1FC and 1268. I'd checked a couple of times by restarting MapleStory to see if I obtained the wrong value. So far it was able to read my HP every time. I tried tons of solutions online but none seems to work. This was the latest one that I tried but it crashed maple upon injection. While other solutions would return no value...Does it have something to do with VirtualProtect?

int HP = 0;
ULONG_PTR hpBase = 0x02B0B7E0;

void hpHook()
{
    for (;;)
    {
        HP = (*(ULONG_PTR*)(*(ULONG_PTR*)(*(ULONG_PTR*)hpBase) + 0x1FC) + 0x1268);
    }
}
	

 

   CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)hpHook, NULL, 0, NULL);
   for (;;)
    {
        MessageBox::Show("The Address is : " + String::Format("{0:X}", HP));
	        Sleep(5000);
    }
	

 

Please guide me, thanks! :)

Edited by hackbotmaple

Share this post


Link to post

You have no checks if the memory is valid, reading an invalid pointer will raise an exception, which will then crash because it is unhandled.

  • Like 1

Share this post


Link to post
2 minutes ago, Erotica said:

You have no checks if the memory is valid, reading an invalid pointer will raise an exception, which will then crash because it is unhandled.

I see... I didn't bother to add exception because I was trying to see if it reads something. But does that mean my address is wrong now?

Share this post


Link to post
15 minutes ago, hackbotmaple said:

I see... I didn't bother to add exception because I was trying to see if it reads something. But does that mean my address is wrong now?

Nope. Lets assume you're reading the local character's data in a loop, and you change channel. Upon changing channel, the character structure is deleted and the first pointer will basically point to null (0). When you've entered a map, the character will again be reinitialized, but you will have already attempted to read data out of 0, which will crash you.

  • Like 1

Share this post


Link to post

I can throw in a little example from a previous project, dunno if it's good code at all but w/e it worked for me

void DataThread()
{
	Sleep(2000);

	for (;; Sleep(20000))
	{
		iMapID = ReadPointer(MapBase, MapIdOff);
		if (!iMapID) continue;
		
		/* this is what you're looking for, just don't cast it to a char* */
		lpzIGN = ReadStringPointer2(TSingleton_CWvsContext, IgnOff1, IgnOff2);
		if (!strlen(lpzIGN)) continue;
		
		iMesos = CWvsContext__GetMoney(*ms_pInstance_TSingleton_CWvsContext, NULL);
		iWorld = ReadPointer(TSingleton_CWvsContext, WorldOff);
		iChannel = ReadPointer(TSingleton_CWvsContext, ChannelOff);
		SendShit(lpzIGN, iMapID, GetLevel(), iMesos, iWorld, iChannel);
	}
}

Functions:

Spoiler

/* this shit is from benny */
inline bool is_readable(void* address)
{
	if (!address)
	{
		return false;
	}

	MEMORY_BASIC_INFORMATION mbi;
	memset(&mbi, 0, sizeof(MEMORY_BASIC_INFORMATION));

	if (VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION))
	{
		if (!mbi.Protect || (mbi.Protect & PAGE_GUARD))
		{
			return false;
		}

		if ((mbi.Protect & PAGE_EXECUTE_READ) || (mbi.Protect & PAGE_EXECUTE_READWRITE) ||
			(mbi.Protect & PAGE_READONLY) || (mbi.Protect & PAGE_READWRITE))
		{
			return true;
		}
	}

	return false;
}

DWORD ReadPointer(DWORD dwBase, DWORD dwOffset)
{
	if(!is_readable((void*)dwBase))
		return 0;

	unsigned char* pointer = *reinterpret_cast<unsigned char**>(dwBase) + dwOffset;
	if(!is_readable(pointer))
		return 0;

	__try { return *(PDWORD)(*(PDWORD)dwBase + dwOffset); }
	__except (EXCEPTION_EXECUTE_HANDLER) { return 0; }
}

LPCSTR ReadStringPointer2(DWORD dwBase, DWORD dwOffset, DWORD dwOffset2)
{
	if (!is_readable((void*)dwBase))
		return "";

	unsigned char* pointer = *reinterpret_cast<unsigned char**>(dwBase) + dwOffset;
	if (!is_readable(pointer))
		return "";

	dwBase = (*(ULONG_PTR*)dwBase) + dwOffset;

	__try { return (LPCSTR)(*(ULONG*)dwBase + dwOffset2); }
	__except (EXCEPTION_EXECUTE_HANDLER) {
		return "";
	}
}

 

 

  • Like 1

Share this post


Link to post
7 minutes ago, NewSprux2.0? said:

Nope. Lets assume you're reading the local character's data in a loop, and you change channel. Upon changing channel, the character structure is deleted and the first pointer will basically point to null (0). When you've entered a map, the character will again be reinitialized, but you will have already attempted to read data out of 0, which will crash you.

I assume it has something to do with MSCRC...?

 

6 minutes ago, Erotica said:

I can throw in a little example from a previous project, dunno if it's good code at all but w/e it worked for me


void DataThread()
{
	Sleep(2000);

	for (;; Sleep(20000))
	{
		iMapID = ReadPointer(MapBase, MapIdOff);
		if (!iMapID) continue;
		
		/* this is what you're looking for, just don't cast it to a char* */
		lpzIGN = ReadStringPointer2(TSingleton_CWvsContext, IgnOff1, IgnOff2);
		if (!strlen(lpzIGN)) continue;
		
		iMesos = CWvsContext__GetMoney(*ms_pInstance_TSingleton_CWvsContext, NULL);
		iWorld = ReadPointer(TSingleton_CWvsContext, WorldOff);
		iChannel = ReadPointer(TSingleton_CWvsContext, ChannelOff);
		SendShit(lpzIGN, iMapID, GetLevel(), iMesos, iWorld, iChannel);
	}
}

Functions:

  Hide contents


/* this shit is from benny */
inline bool is_readable(void* address)
{
	if (!address)
	{
		return false;
	}

	MEMORY_BASIC_INFORMATION mbi;
	memset(&mbi, 0, sizeof(MEMORY_BASIC_INFORMATION));

	if (VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION))
	{
		if (!mbi.Protect || (mbi.Protect & PAGE_GUARD))
		{
			return false;
		}

		if ((mbi.Protect & PAGE_EXECUTE_READ) || (mbi.Protect & PAGE_EXECUTE_READWRITE) ||
			(mbi.Protect & PAGE_READONLY) || (mbi.Protect & PAGE_READWRITE))
		{
			return true;
		}
	}

	return false;
}

DWORD ReadPointer(DWORD dwBase, DWORD dwOffset)
{
	if(!is_readable((void*)dwBase))
		return 0;

	unsigned char* pointer = *reinterpret_cast<unsigned char**>(dwBase) + dwOffset;
	if(!is_readable(pointer))
		return 0;

	__try { return *(PDWORD)(*(PDWORD)dwBase + dwOffset); }
	__except (EXCEPTION_EXECUTE_HANDLER) { return 0; }
}

LPCSTR ReadStringPointer2(DWORD dwBase, DWORD dwOffset, DWORD dwOffset2)
{
	if (!is_readable((void*)dwBase))
		return "";

	unsigned char* pointer = *reinterpret_cast<unsigned char**>(dwBase) + dwOffset;
	if (!is_readable(pointer))
		return "";

	dwBase = (*(ULONG_PTR*)dwBase) + dwOffset;

	__try { return (LPCSTR)(*(ULONG*)dwBase + dwOffset2); }
	__except (EXCEPTION_EXECUTE_HANDLER) {
		return "";
	}
}

 

 

Thanks for the codes! I'll see if I can use it to make them work. What's TSingleton_CWvsContext btw?

Share this post


Link to post
5 minutes ago, hackbotmaple said:

I assume it has something to do with MSCRC...?

No. Nothing at all to do with MSCRC. It has to do with you reading something that isn't there (yet? not available? just wrong?).

5 minutes ago, hackbotmaple said:

What's TSingleton_CWvsContext btw?

Bruh

Edited by Erotica
  • Like 1

Share this post


Link to post
On 1/19/2018 at 16:56, hackbotmaple said:

I assume it has something to do with MSCRC...?

 

Thanks for the codes! I'll see if I can use it to make them work. What's TSingleton_CWvsContext btw?

Every time you change channel the allocated variable "structure" is destroyed and created again. trying to read "TSingleton_CWvsContext" (name of basepointer) returns value (memory location) 0 since its not yet allocated (created) then you try to read the value of 0+offset will throw you into a unallocated memory location and crash the game

 

To prevent crashes you need to make sure the value of TSingleton_CWvsContext != 0 before reading the memory location [TSingleton_CWvsContext] + offset

Edited by Chubbylitooo
  • Like 2

Share this post


Link to post
3 hours ago, Chubbylitooo said:

Every time you change channel the allocated variable "structure" is destroyed and created again. trying to read "TSingleton_CWvsContext" (name of basepointer) returns value (memory location) 0 since its not yet allocated (created) then you try to read the value of 0+offset will throw you into a unallocated memory location and crash the game

 

To prevent crashes you need to make sure the value of TSingleton_CWvsContext != 0 before reading the memory location [TSingleton_CWvsContext] + offset

Thanks for making it clearer! :yay:

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×