Solved Whats wrong with my Mid function hook? Getting the wrong JMP address

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

ranseier

Jr.Coder
Full Member
Nobleman
Sep 26, 2015
53
538
3
Hi,

this is my approach for a mid function hook in C#/ASM.

The problem is, that the JMP address to my function is always wrong. But the JMP address back to the original function works!?

Some codes:

call
C#:
IntPtr playerBaseAddrs = sig.FindPattern(new byte[] { 0x8b, 0x56, 0x00, 0x89, 0x46, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x89, 0x4e }, "xx?xx?x????xx", 0x0);
HookedMethodDelegate hookedMethodDel = new HookedMethodDelegate(HookedMethod);
IntPtr hookedMethodAddrs = Marshal.GetFunctionPointerForDelegate(hookedMethodDel);
IntPtr trampo = SetHook2(playerBaseAddrs, hookedMethodAddrs, 6);
function I will jump to
C#:
        delegate void HookedMethodDelegate(IntPtr playerBase);

        public static void HookedMethod(IntPtr playerBase)
        {
            //do somthing later
        }
the setHook function.
C#:
public static IntPtr SetHook2(IntPtr OriginalAddress, IntPtr TrampolineAddress, uint SIZE)
{
	try
	{
		byte[] TrampJMP = new byte[5];
		byte[] OldBytes = new byte[SIZE];
		uint OldProtection = 0;
		byte[] JMP = { 0xE9, 0x90, 0x90, 0x90, 0x90 };
		IntPtr Trampoline = IntPtr.Zero;

		if (VirtualProtect(OriginalAddress, SIZE, 0x40, out OldProtection))
		{
			for (int i = 0; i < SIZE; i++)
			{
				//store old op codes for later use
				OldBytes[i] = Marshal.ReadByte(OriginalAddress + i);
				//fill original address with NOPs
				Marshal.WriteByte(OriginalAddress + i, 0x90);
			}

			//construct JMP op code address
			Array.Copy(BitConverter.GetBytes(IntPtr.Subtract(TrampolineAddress, OriginalAddress.ToInt32()).ToInt32() - 5), 0, JMP, 1, Marshal.SizeOf(typeof(uint)));

			//write jMP code to original address
			// !!!!!!!!!!!!!!!!!!!The JMP jumps to a wrong address!!!!!!!!!!!!!!!!!!!
			for (int i = 0; i < 5; i++)
				Marshal.WriteByte((IntPtr)(OriginalAddress.ToInt32() + i), JMP[i]);

			Trampoline = VirtualAlloc(UIntPtr.Zero, new UIntPtr(SIZE) + 5, AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.EXECUTE_READWRITE);

			if (Trampoline != IntPtr.Zero)
			{
				for (int i = 0; i < SIZE; i++)
					Marshal.WriteByte(new IntPtr(Trampoline.ToInt32()) + i, OldBytes[i]);   //Write old bytes to trampoline

				//create JMP back to original address
				Array.Copy(BitConverter.GetBytes(OriginalAddress.ToInt32() - (5 + Trampoline.ToInt32())), 0, TrampJMP, 1, Marshal.SizeOf(typeof(uint)));

				TrampJMP[0] = 0xE9;

				//write jMP code to original address
				//this works
				for (int i = 0; i < 5; i++)
					Marshal.WriteByte((IntPtr)(Trampoline.ToInt32() + SIZE + i), TrampJMP[i]);
			}
		}

		//restore old protection
		uint bakProtection = 0;
		VirtualProtect(OriginalAddress, SIZE, OldProtection, out bakProtection);

		return Trampoline;

	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.ToString());
	}
	return IntPtr.Zero;
}
I have commented the position where I get the wrong address.
Whats really confusing is, that the line "Trampoline = VirtualAlloc(UIntPtr.Zero, new UIntPtr(SIZE) + 5, AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.EXECUTE_READWRITE);" returns the correct position of the JMP address I want!?

Thanks for your help
 

ranseier

Jr.Coder
Full Member
Nobleman
Sep 26, 2015
53
538
3
Hey,

thanks for all the help you provide :)

I just realized that my complete approach of mid function hooking entirely in C#/ASM cannot work since it is impossible to do something like in C#:

C++:
__declspec(naked) void GetPlayerYaxis()
{
    __asm MOV ECX, [ESI+0x3C]
    __asm MOV YaxisRegister, ESI // This is not possible in C#
    __asm MOV [ESI+0x08],EDX
    __asm jmp [FlyingJmpBack]
}
You can write ASM into a process in C#, but you cannot do things like "__asm MOV YaxisRegister, ESI". Saving the value of a stack register and use it in your program.

The whole sample code I found and posted in my first post was about hooking a MessageBox function. Took me A WAY TO LONG to realize this... :FeelsBadMan:
 

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,298
37,938
269
You don't ToInt32() your Trampoline address in the subtract, could be the source of your issue, though i'm not sure how C# handles that data type.
 

ranseier

Jr.Coder
Full Member
Nobleman
Sep 26, 2015
53
538
3
Instead of this
C#:
Array.Copy(BitConverter.GetBytes(IntPtr.Subtract(TrampolineAddress, OriginalAddress.ToInt32()).ToInt32() - 5), 0, JMP, 1, Marshal.SizeOf(typeof(uint)));
I also tried this, without success
C#:
Array.Copy(BitConverter.GetBytes(TrampolineAddress.ToInt32() - OriginalAddress.ToInt32() - 5), 0, JMP, 1, Marshal.SizeOf(typeof(uint)));
the JMP address always points to the wrong address.


EDIT: What I also tried:
Create trampoline first, get Trampoline address by "Trampoline = VirtualAlloc(UIntPtr.Zero, new UIntPtr(SIZE) + 5, AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.EXECUTE_READWRITE);", write a JMP that points to Trampoline address.
Trampoline = VirtualAlloc(...) returns the correct address to the trampoline (i checked it via cheat engine) but after creating the JMP to the trampoline address, cheat engine shows a wrong address which doesn't point to the trampoline...
 
Last edited:

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,298
37,938
269
Well time to check your calculations yourself

make 2 variables of type Int32
store trampoline address
store source address

subtract them yourselv in windows calculator and subtract 5, if that works think about the rest of the line, is the address right but with the wrong endianness ( the way the bytes are written in memory ), if so you'd probably want to flip that, i highly doubt thats the issue though.

Set some breakpoints and show a picture of the variables, that usually helps
 

Alex

Sober linux neb
Dank Tier Donator
Nobleman
Nov 26, 2015
150
828
1
ranseier But you can still make your asm funcs in C++ DLLs and export the them for you to use in C#
 

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,298
37,938
269
You can't put register values into your own variables? That's some cold stuff lmao. you could always push the register and call a function and use then save the parameter value

You have to write shellcode into the process then
 
Last edited by a moderator:
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Similar threads

Community Mods