[Question] Hook EndScene

Posts 16–30 of 31 · Page 2 of 3
Quote Originally Posted by Departure View Post
Actually Apoc91 is correct. This is exactly What I had in mind to get the PTC method working.. Difference is I will be using inline assembly in hooked EndScene Callback, As much as I would like to create DX device I wont be doing it as I dont want to even deal with DX9(not in Delphi anyway) thus I will not have any of the DX9 headers and units. I did'nt even want to hook from the start but after some info supplyed by freedompeace and other members I now relize you can'nt call the PTC method from your own thread, it must be called from a context of d3d9 thus the reason why I want to hook the simplest dx function(EndScene) as it only requires a pointer for arguments and will be passed straight to the original EndScene...


My idea...

Hook(d3d9Base + EndSceneOffset, @NewEndScene, @OriginalEndScene)

Then in my NewEndScene Callback...
Code:
function NewEndScene(const Self: Pointer): HResult; stdcall;
const
 FogOn = 'FogEnable 0';
 FogOff = 'FogEnable 1';
begin

  Result := OriginalEndScene(Self); <-- forward on to original

//PTC console Method, I disassembled some working C++ hacks and ripped the assembly)
  asm
      cmp dword ptr [bFogOnOff],0 <--- Check our Boolean
      jle @FogON
      push FogOff
      mov edx,$00485e10
      call edx
      jmp @Finish

     @FogON:

       push FogOn
       mov eax,$00485e10
       call eax

     @Finish:

       add esp, $00000004
    end;
end;
I have not tested this but now I think you get the what my mind set is to get PTC method working...

Once I get PTC working I will go further and start using the DX9 Types and classes(there is a delphi implementation I seen on the net for the DX9). But for now I just want to be able to use PushToConsole.


//Edit

I got rapped up in what I want to do that I forgot to tell you guys why I want to find out about the Vtables...

I dont understand why people are using a sig scanner on d3d9.dll to get the pointer to the vTable, Because in my head the Vtable address should always be the same offset from the d3d9 base address, As should the EndScene scene address, The only reason I can think why it would be different is because a different version of d3d9.dll for different OS's... And freedompeace even said some people get the pointer to the pointer of the pointer to the Vtable from Engine.exe, this in my mind makes no sense, why go through all that trouble? you should be only calculating from the base address of d3d9.dll when its loaded... So my question is what is the reason behind this because I lot of source I seen do this, So im guessing there must be a reason.... even if you wanted multiple d3d9 functions wouldn't it be easyer just to do something like d3d9base + OffsetToVTable which would land you on the first Vtable entry?

This Vtable is just DB pointers to function addresses, so im not sure why this is even used unless it changes which would make the d3d9.dll polymorphic code(which it is not)
There are two critical things you need to know here:
- DirectX is completely independent of the Console - you can push commands to the console without messig to touch DirectX
- I never said it was a pointer to a pointer to a pointer (and so on) - that was Mr Magician on another post. The signature scan gets the pointer to the current DirectX device. Add an offset to get the virtual function table, and then hook your functions from the pointers to functions pointed by that table.

Quote Originally Posted by Crash View Post
Apparently calling from endscene works as opposed to calling from your thread.
Apparently it doesn't matter (I wwas still calling console commands from an independent thread yesterday).
Quote Originally Posted by freedompeace View Post
There are two critical things you need to know here:
- DirectX is completely independent of the Console - you can push commands to the console without messig to touch DirectX
- I never said it was a pointer to a pointer to a pointer (and so on) - that was Mr Magician on another post. The signature scan gets the pointer to the current DirectX device. Add an offset to get the virtual function table, and then hook your functions from the pointers to functions pointed by that table.



Apparently it doesn't matter (I wwas still calling console commands from an independent thread yesterday).
Oh wow, I couldn't get it to call from my thread when I first started with CA, (I was using the 0x485E10 pointer). After I added in a hook for DirectX though, it ran fine from Present.
@freedompeace
Yeas I understand all of that, and sorry I thought it was you who informed me about the pointer to a pointer ect.. which is irrelevant, Even the Vtable is irrelevent because I know the address of EndScene.. But you say you can call PTC outside of DX9, Im sorry I have tried this so many times and failed to call it, So just as Apoc91 has done I am thinking of doing the same thing after being told about the dx function needed to be hooked to call the PTC method. Are you saying you called the PTC command without any hooking of the Directx? if this is the case is there any chance I could look over your code, because I would much prefer NOT to hook any DirectX functions...

@Apoc91
Thats is exactly why im going to hook the DirectX, Maybe I should be looking at hooking "Present" function instead of EmdScene?, saying that if Freedompeace can call the PTC command without hooking then I would rather go down that path

Thanks to both of you guys for your input and infomation it is very much appreciated..
Sorry for the delayed reply, just finished dinner x]

Well, I've just about completed the core functions of my hack rewrite, so I'm just about to add the console functions into it now (on another thread, obviously) and trying it out in a moment.

I'll inform you if I get PTC working via. a non-EndScene thread.




Now, to the reason why the DirectX thread may be the only way to use your PushToConsole functions is that (apparently), HackShield checks the calling address of every command. If your call resides in (or an address that resolves to) one of the game's internal functions - such as a rendering function, your call will pass the test and be allowed to continue.

This means that in theory, you could just NOP the check and be good to go.
Quote Originally Posted by freedompeace View Post
Sorry for the delayed reply, just finished dinner x]

Well, I've just about completed the core functions of my hack rewrite, so I'm just about to add the console functions into it now (on another thread, obviously) and trying it out in a moment.

I'll inform you if I get PTC working via. a non-EndScene thread.




Now, to the reason why the DirectX thread may be the only way to use your PushToConsole functions is that (apparently), HackShield checks the calling address of every command. If your call resides in (or an address that resolves to) one of the game's internal functions - such as a rendering function, your call will pass the test and be allowed to continue.

This means that in theory, you could just NOP the check and be good to go.
Yea, there's definately a check (at least it looks as if it's checking if it's coming from CShell.dll) at *LTClient + 0x208:

Code:
0046FA40   A1 3C001037      MOV EAX,DWORD PTR DS:[3710003C]
0046FA45   8B88 2C001037    MOV ECX,DWORD PTR DS:[EAX+3710002C]
0046FA4B   8B1424           MOV EDX,DWORD PTR SS:[ESP]
0046FA4E   05 00001037      ADD EAX,37100000                      
0046FA53   81C1 00001037    ADD ECX,37100000                   ; CShell.dll codebase
0046FA59   3BD1             CMP EDX,ECX                        ; Check if called before CShell base
0046FA5B   72 0E            JB SHORT Engine.0046FA6B           ; If so, return
0046FA5D   8B40 50          MOV EAX,DWORD PTR DS:[EAX+50]      ; size of CShell
0046FA60   03C1             ADD EAX,ECX                        ; add size and base
0046FA62   3BD0             CMP EDX,EAX                        ; Check if called afer CShell.dll
0046FA64   73 05            JNB SHORT Engine.0046FA6B          ; If so, return
0046FA66   E9 A5630100      JMP Engine.00485E10                ; All's well -- execute the code
0046FA6B   C3               RETN
Sadly, even called 00485E10 directly, I couldn't get the RCC to run.
Quote Originally Posted by Apoc91 View Post
Yea, there's definately a check (at least it looks as if it's checking if it's coming from CShell.dll) at *LTClient + 0x208:

Code:
0046FA40   A1 3C001037      MOV EAX,DWORD PTR DS:[3710003C]
0046FA45   8B88 2C001037    MOV ECX,DWORD PTR DS:[EAX+3710002C]
0046FA4B   8B1424           MOV EDX,DWORD PTR SS:[ESP]
0046FA4E   05 00001037      ADD EAX,37100000                      
0046FA53   81C1 00001037    ADD ECX,37100000                   ; CShell.dll codebase
0046FA59   3BD1             CMP EDX,ECX                        ; Check if called before CShell base
0046FA5B   72 0E            JB SHORT Engine.0046FA6B           ; If so, return
0046FA5D   8B40 50          MOV EAX,DWORD PTR DS:[EAX+50]      ; size of CShell
0046FA60   03C1             ADD EAX,ECX                        ; add size and base
0046FA62   3BD0             CMP EDX,EAX                        ; Check if called afer CShell.dll
0046FA64   73 05            JNB SHORT Engine.0046FA6B          ; If so, return
0046FA66   E9 A5630100      JMP Engine.00485E10                ; All's well -- execute the code
0046FA6B   C3               RETN
Sadly, even called 00485E10 directly, I couldn't get the RCC to run.
Woah D:

I need you on MSN >:}

And sorries Departure, as you might (not) know, I don't have Combat Arms personally (due to financial, and therefore internet) limitations and I'm too young to legally work <.<), so I kinda rely on a trusted tester who I ping my works in progress to for testing, who then pongs be back the results =P

Unfortunately he wasn't here as he normally would be today, so couldn't test. Better luck next time, but you pretty much have a possible solution there :)
resolved long ago just use the internal console.

http://www.mpgh.net/forum/207-combat...ml#post3030792


or you could vtable hook consolecommand in your hook set it to how it use to be and then you can calll it.

the one after the jump

typedef void (__cdecl *lpSetConsoleVariable)(unsigned long console,char* szVal);
lpSetConsoleVariable SetConsoleVariable;


SetConsoleVariable = (lpSetConsoleVariable)(0x0484BC0);
SetConsoleVariable(0x8003F0,"SkelModelStencil -1");
Yeap I also seen this while looking through Engine.exe, Thats why I was originally trying to call $00485E10 Directly and thought that would have done the trick, maybe by setting EDX and EAX the same values as what this routine sets it as, before calling $00485E10 might just do the trick, only problem is break pointing on this address while the game is running to get those values...

Still though it makes no sense that d3d9 function can call this address directly??\


//Edit
Just read SNal2F post

Code:
00484BC0   8B4424 08        MOV EAX,DWORD PTR SS:[ESP+8]
00484BC4   8B4C24 04        MOV ECX,DWORD PTR SS:[ESP+4]
00484BC8   6A 00            PUSH 0
00484BCA   6A 00            PUSH 0
00484BCC   50               PUSH EAX
00484BCD   51               PUSH ECX
00484BCE   E8 2DF8FFFF      CALL Engine.00484400(unsigned long,szcommand,int,int) //can do here
00484BD3   83C4 10          ADD ESP,10
00484BD6   C3               RETN
Unsigned long , Pchar , integer, integer
What are the 2 Integer arguments? is it 0 from the Push 0, Push 0 ????
The unsigned Long is "0x8003F0"???

so if the above is true then ....

asm
pushad
mov eax, pCharNoFog
mov ecx, 008003F0
Push 0
Push 0
Push eax <--- "EnableFog 0"
Push ecx <--- "008003F0"
Call 00484400
add esp, 10
popad
end

that should work called from any thread???
Quote Originally Posted by Departure View Post
Yeap I also seen this while looking through Engine.exe, Thats why I was originally trying to call $00485E10 Directly and thought that would have done the trick, maybe by setting EDX and EAX the same values as what this routine sets it as, before calling $00485E10 might just do the trick, only problem is break pointing on this address while the game is running to get those values...

Still though it makes no sense that d3d9 function can call this address directly??\


//Edit
Just read SNal2F post

Code:
00484BC0   8B4424 08        MOV EAX,DWORD PTR SS:[ESP+8]
00484BC4   8B4C24 04        MOV ECX,DWORD PTR SS:[ESP+4]
00484BC8   6A 00            PUSH 0
00484BCA   6A 00            PUSH 0
00484BCC   50               PUSH EAX
00484BCD   51               PUSH ECX
00484BCE   E8 2DF8FFFF      CALL Engine.00484400(unsigned long,szcommand,int,int) //can do here
00484BD3   83C4 10          ADD ESP,10
00484BD6   C3               RETN
Unsigned long , Pchar , integer, integer
What are the 2 Integer arguments? is it 0 from the Push 0, Push 0 ????
The unsigned Long is "0x8003F0"???

so if the above is true then ....

asm
pushad
mov eax, pCharNoFog
mov ecx, 008003F0
Push 0
Push 0
Push eax <--- "EnableFog 0"
Push ecx <--- "008003F0"
Call 00484400
add esp, 10
popad
end

that should work called from any thread???
that one would be

typedef void (__cdecl *lpSetConsoleVariable)(unsigned long console,char* szVal,int unk,int unk2);
lpSetConsoleVariable SetConsoleVariable;

yes it should
Quote Originally Posted by SNal2F View Post
that one would be

typedef void (__cdecl *lpSetConsoleVariable)(unsigned long console,char* szVal,int unk,int unk2);
lpSetConsoleVariable SetConsoleVariable;

yes it should
I may be doing something wrong, but I still don't have it working even using that. Although, I'm not really interested in not hooking DirectX (Since I draw shit etc), but I figured I'd make a quick hackup to see if I could get it to work. If you see something I did wrong just point it out and I'll retry.

Code:
typedef void (__cdecl *SetConsoleVariable_T)(DWORD console, LPSTR szVal, int, int);
SetConsoleVariable_T SetConsoleVariable = (SetConsoleVariable_T) 0x00484400;

static const DWORD dwConsole = 0x008013F0;

DWORD WINAPI InitDll(LPVOID lpVoid)
{
	UNREFERENCED_PARAMETER(lpVoid);

	while(GetModuleHandle(L"cshell.dll") == NULL) Sleep(100);

	while(true)
	{
		SetConsoleVariable(dwConsole, "ShowFps 1", 0, 0);

		Sleep(100);
	}
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  dwReason,
                       LPVOID lpReserved
					 )
{
	UNREFERENCED_PARAMETER(hModule);
	UNREFERENCED_PARAMETER(lpReserved);

	if(dwReason == DLL_PROCESS_ATTACH)
	{
		DisableThreadLibraryCalls(hModule);
		CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InitDll, NULL, 0, NULL);
	}

	return TRUE;
}
maybe you do have to call it in a game function :S
Some tested results come as follows:
- Yes, you will need to call SetConsoleVariable or pRunConsoleCommand from within the game (drawing) loop - EndScene or Present. I did so through Present(). Doing so outside will cause an instant crash.
- Obviously, but for those who are reading this who don't know, you will need to call the console commands from within your re-routed DirectX function, not by calling another function that will push back your command to the console.

This means that if you have pre-existing frameworks for your GameConsole (such as I do), just prefix your functions with __inline, plus a few other adjustments depending on your code.
K finally got a working PTC method with Delphi, doing what we have talked about I Hooked EndScene function from the d3d9.dll by using base address + offset, Only problem is it only worked for about 3 or 4 minutes before CA just shut down

So here comes a new lot of questions... What causes CA to shut down? is it the hook detection? is it because it uses PTC EVERY SINGLE time the hooked EndScene Callback is called?

for example here is my EndScene, and im thinking it might be shutting down for 1 of 2 reasons..

Here I have ported the PTC C++
Code:
type
  lpSetConsoleVariable = procedure (console: cardinal; szVal: PAnsiChar); cdecl;
  RunConsoleCommand_t = function(cmd: PAnsiChar): integer; cdecl;

var
  SetConsoleVariable: lpSetConsoleVariable = nil;
  pRunConsoleCommand: RunConsoleCommand_t = nil; // assign later
First it detects hotkey if its on or off
Code:
if (GetAsyncKeyState(VK_NUMPAD5) <> 0) then
    begin
     bFps:= NOT bFps;
     Sleep(10);
     OffOn(bFps);
    end;
Now in my hooked EndScene
Code:
function EndSceneCallback(const Self: Pointer): HResult; stdcall;
begin
  asm
   pushad
   pushfd
  end;

  @SetConsoleVariable:= pointer($00484400);

  if(bFps = False) then
   SetConsoleVariable($008013F0,'ShowFps 0')
   else
   SetConsoleVariable($008013F0,'ShowFps 1');

  asm
   popfd
   popad
  end;

  Result := EndSceneNext(Self);
end;
Now im thinking because PTC method get called EVERY time the endScene gets called and maybe this is why its crashing, or it might be because they detect my hook, Im not sure how they go about hook detection and maybe thats why people hook the vTable instead? or maybe its just my PTC within the EndScene thats causing it to crash after 3 or 4 minutes?

Any help will be appreciated....

It amazing how you over come one problem only to find your self with a heap of new ones.....
K I worked out it must be the hook thats getting detected and not the PTC function
So I ask you guys if you would explain the way you guys hook EndScene?

I think SNal2F might have something with his info about hooking the Vtable instead of EndScene Direct... or anyone with suggestions are welcome
Quote Originally Posted by Departure View Post
K I worked out it must be the hook thats getting detected and not the PTC function
So I ask you guys if you would explain the way you guys hook EndScene?

I think SNal2F might have something with his info about hooking the Vtable instead of EndScene Direct... or anyone with suggestions are welcome
a lot of ways to do it
this is for halo but it also work with ca
halo-devkit - Project Hosting on Google Code

am using Gordon's atm which also bypasses the detection from hackshield
if you want it pm me
Posts 16–30 of 31 · Page 2 of 3

Post a Reply

Tags for this Thread

None

Talk with us