PDA

View Full Version : nProtect/GameGuard 101


Sirmabus
15th March 2006, 06:13
Seeing not much here yet, I did some research on nProtect/GameGuard and I'll share some details.

nProtect (as most protections are) is primarily a root kit.
It has 3 or 4 kernel table hooks, and it hides the target client (along with the external process GameMon.des it creates) by removing links from the kernel process list.
Also it also does userland hooks on serveral common API's like SendInput(), SendMessage(), GetPixel(), etc.

Obviously then it can intercept common macro programs (Like ACTOOL, AutoIt, etc.) calls like "SendInput()" and make it uses.

On startup and when new process are create it has some type of signiture checks to keep some programs (such as known bybpasses, etc.) from even running.

Additionaly on the game client (that it "protects") it does more checks. It has some kind of pattern check on the code layout of the client so that if code is hooked/patched it will detect it.
Also removes, and, or replaces EAT hooks.
It appears though since there are different versions of nProtect that client protections may be different from one game to the next.

Most of the time nProtect can just be simply removed from even starting in 2 to 4 code patches. But if the target game has the nProtect server challenge/responce packet setup then you can't just remove it (else you get a game server DC in around 10 minutes).

If the packet setup is there then you have to either emulate how nProtect works, and, or, some how coexist with it...

Opcode&H90
15th March 2006, 09:37
Some info on nProtect (Rev 641) hooked functions. I may have missed some out. Please post here if you know other functions have been hooked.

Kernel32.dll
ReadProcessMemory
WriteProcessMemory
GetProcAddress
VirtualProtect
VirtualProtectEx
LoadLibraryExW
CreateProcessInternalW
OpenProcess
DebugActiveProcess
MoveFileW
MapViewOfFile
MapViewOfFileEx

User32.dll
SendInput
keybd_event
mouse_event
PostMessageA
PostMessageW
77D448B80 (?)
SendMessageA
SendMessageW
GetWindowThreadProcessId

Gdi32.dll
GetPixel

ntdll.dll
ZwOpenProcess
ZwProtectVirtualMemory
ZwSuspendProcess
ZwSuspendThread
ZwTerminateThread
ZwQuerySystemInformation

Surprizingly, CreateRemoteThread is not on the list. Maybe since ZwOpenProcess is hooked, you may not even gain the handle to call it...

Most of the time nProtect can just be simply removed from even starting in 2 to 4 code patches.

The most simple method is to terminate GameGuard.des with exit code 1877.

1337mopar
15th March 2006, 21:29
You people must be elite h4x0rs or something o.O

Now to figure out what those code patches must be... or figure out what exit code 1877 is....

xD

Thanks for the info!

jackass003
19th March 2006, 20:34
kill game guard mu bots dont work anymore becuase of the new patch >.<

Sirmabus
22nd March 2006, 05:27
Surprizingly, CreateRemoteThread is not on the list. Maybe since ZwOpenProcess is hooked, you may not even gain the handle to call it...


I think "CreateRemoteThread" is, or at least "Create Thread" is at some level because an IPC system I was using breaks when it tries to create threads.

Not just "ZwOpenProcess" from ntdll.dll but a level deeper in the kernel SDT (service decriptor table) nProt hooks these known by thier ntddl.dll names:

1. "ZwOpenProcess"
2, "ZwReadVirtualMemory"
3. "ZwWriteVirtualMemory".

Looks like there is a 4th one in the SDT shadow table but I don't what it is, and not sure it even gets hit normaly.

You can restore all of these by putting the origional table entries back, at least temporary, but the nProt API hooks will be put back in the next time you call one of the higher levels of the API (I.E. OpenProcess() from kernel32.dll).

An anti-root-kit program like "IceSword" might stop the hooks too (not tired).

Seems like a pretty invasive root kit if you ask me. I've never seen a game's EULA (that uses nProtect) that says that they do this. Nor, ask for permission if it's okay from the user to hook/modify core components of the user's opperating system!

I guess they don't consider what happens if you are working on something else important at the same time you fire up a game with nProtect and it crashes your system and you loose your work, etc.

Plocploc
1st April 2006, 04:41
If SendInput is intercepted, is there a way to overcome the nprotect hook or not? In other words how can I overhook the keyboard & mouse or am I doomed? I suppose there is no lower level API than SendInput right...

Opcode&H90
1st April 2006, 05:16
If SendInput is intercepted, is there a way to overcome the nprotect hook or not? In other words how can I overhook the keyboard & mouse or am I doomed? I suppose there is no lower level API than SendInput right...

There is.


SendInput proc cInputs, nInputs, cbSize

push cbSize
push nInputs
push cInputs
call Tunnel
ret

Tunnel:

mov eax, 11F6h
mov edx, 7FFE0300h
call dword ptr [edx]
ret 0Ch

SendInput endp


Works for most hooked API except 3 kernel-hooked API mentioned above.

BlackHorse
1st April 2006, 19:19
Tell more about GG plz, is there a new way to bypass GG?

PeLuCHo
20th April 2006, 21:27
Kernel32.dll
ReadProcessMemory
WriteProcessMemory

Gdi32.dll
GetPixe

and GetDc

how this apis function hook?

number89757
2nd May 2006, 12:16
Erm... its plenty of info here...
But i suck in this kinda stuff. mebe u can jus upload a gamegaurd bypass?

MeLzAr
4th May 2006, 20:11
If you guys want to use SendInput() then all you need to do is rename your bot to "JoyToKey.exe" and then it will work.

Good luck!

Plocploc
4th May 2006, 23:01
Apparently it's not fully working. I used keyb_event from user32.dll to send the space char (to pick up items in Mu) and it worked once, then gets blocked. I wonder wheter it's blocked in the message queue. Maybe I must flush this queue but I don't know how to do it :(
Everytime I relaunch the bot, it will pick up once and only once :s

Sirmabus
5th May 2006, 13:32
Just renaming a program won't make the API calls like SendInput() work once nProt has loaded. Read up on root kits at rootkit.com, for more info.

Like Opcode says above you can just make your own stub. Also you can just copy the function before nProtect starts and call your copy of the function instead.

pouki
10th May 2006, 00:26
for gunbound were can we found the RB6runtime file and decrypted GB plz tell me i can't find those file and programs to hack in gunbound

MeLzAr
11th May 2006, 09:19
Just renaming a program won't make the API calls like SendInput() work once nProt has loaded. Read up on root kits at rootkit.com, for more info.

Like Opcode says above you can just make your own stub. Also you can just copy the function before nProtect starts and call your copy of the function instead.


Sirmabus dont be dull witted and try it out before saying anything. It works and if you dont try it, you will miss out!! I am not lieing... I am a moderator, why would I lie you you?


This goes for all autoit bots as well.

Plocploc
12th May 2006, 20:18
And I'd also add that some scripts language different from AutoIt will even allow to run through without the need of renaming into Joytokey!

Sirmabus
15th May 2006, 04:53
Why am I "dull witted" for starting this thread in the first place?.. well maybe it was a momentary laps of better judgment :-P
A moderator = smart = good programmer = skills? Ok if you say so, I guess I had better become one first..

Anyhow don't get defensive (or insulted), I don't talk about things I don't have direct experience in. Frankly I don't care what people think of me here, and there is no purpose to make a name for my self. Ban me, I loose nothing. I just won't post here anymore.

I directly saw exactly what I was saying. nProtect is both a user land and kernel mode root kit. I saw it was patching the first 5 bytes of some API calls with a JMP hook.
As a root kit one nProtect strategy apparently is to hook common interprocess, fake inputs, etc., API's like "SendInput()", mouse_event() (just a layer above SendInput()), SendMessage(), ReadProcessMemory(), etc.

You can test this easy your self by making a test appication with something like SendInput() in it. Look at the first 5 or 6 bytes of the function call address, before and after nProtect runs.
You will probably see an E9h, "jmp" patched in.

With a hook on these they can easily just disable them outside the nProtected'ed target.
IE. They can simply look where the HWND, or HANDLE, etc, is directed. Or in the case of SendInput() is to bypass the call completely.

Also they have low level hook that monitors process creation. If the signature of the process being created is on their black list it will do something about it. Such as bypassing the process from starting, and, or, terminate the game it was protecting.

So since they do a system-wide hook on these renaming any applications shouldn't do anything. Because it's still going to hook in every application these API calls.
Doesn’t matter what you rename the process too, and change the window title to be.
So if you take “tsearch” for example and rename it to “asearch” it probably will still not work for you on an nProtected game because it’s ReadProcessMemory() is hooked reguardless.

BUT, there are different variations of nProtect. I'm pretty sure (as I have seen it) that "GameMon.des" is different for each game. At least setups that have the challenge/response packet in it. You could have had a version of nProtect that was thwarted be just renaming a program, etc.

That's why I said you can copy the API function before nProtect starts. Because you will have a separate instance of the function this way. One that won't be hooked because it doesn’t exist in the DLL space anymore.

EDIT: I see what you are saying there. Prehaps "JoyToKey.exe" is on some exclusion list. In that case nProtect wouldn't bypass it's API calls for something like SendInput().

EDIT: Changed references to EAT hooks to "code hooks".

Opcode&H90
16th May 2006, 08:07
Well, first thing Im gonna say is that you did a good job on starting this thread. I knew some ppl who knows much a lot better on GameGuard and yet unwilling to share out their knowledge.

Another thing, I believe that is not called EAT hooking. It should be API entry overwriting or something similar. EAT hooking works by patching address on the export table. It works similar to IAT hooking.

Sirmabus
23rd May 2006, 23:02
Right not actually an export/import table, but the actual API function is patched with a customary 5 or 6 byte JMP hook.

It takes a little tricky work to even see this because you can't even normally get a PID and or open a handle to the process once nProtect starts (Hint, use a delayed thread in an injected DLL).

Hopefully a few people will actually experiment with these things to find out on their own. And thus make some way to handle nProtect privately.
Posting detailed ways of how I might know of working with (or bypassing, etc.) nProtect with be shooting my self in the foot wouldn't it?

If they are used in some public tool/hack they will probably get somehow counter measured with an nProtect patch/change.
That's simply why most(all?) public bypasses that worked in the past no longer do.

Again this only applies to nProtect that uses the challenge/response packet. If it doesn’t, one should find the offsets to just patch it (nProtect) out and all your problems are solved.

temp2
24th May 2006, 12:45
Right not actually an export/import table, but the actual API function is patched with a customary 5 or 6 byte JMP hook.

I'd refer to that as a simple detour.

ZwQuerySystemInformation
ZwOpenProcess
ZwProtectVirtualMemory
ZwReadVirtualMemory
ZwWriteVirtualMemory
ZwSuspendProcess
ZwSuspendThread
ZwTerminateThread

Mmm that’s pretty invasive hooking of the Service Descriptor Table.

ZwQuerySystemInformation will be to inhibit obtaining ProcessID and ZwOpenProcess getting a handle. ZwProtectVirtualMemory, ZwReadVirtualMemory, ZwWriteVirtualMemory cover any writing and reading from a processes memory and presumably ZwSuspendProcess ZwTerminateThread and ZwSuspendThread are used to stop people ****ing with GameGuard itself.

Here is an interesting *user mode* project to restore the SDT http://www.security.org.sg/code/sdtrestore.html :-) By the sound of it however there detouring of the user mode functions also? And have some kind of periodic re-hooking of the SDT. Sounds like the way to go is to get hold of the DDK write a service and call ntoskrnl.exe directly … if they want to run and hide in ring 0 it’s the worst place for them if they force us into ring 0.

Now does anyone know how GameGuard.des is packaged. It claims it is UPX 0.89.6 … 1.24 in PeiD but does not appear to unpack with an unpacker for that.


start of GameMon.des

.rdata:00426C30 ; ---------------------------------------------------------------------------
.rdata:00426C30
.rdata:00426C30 public start
.rdata:00426C30 start:
.rdata:00426C30 xor edi, edi
.rdata:00426C32 jz short EP_Zero
.rdata:00426C34 popa
.rdata:00426C35 jmp near ptr 3092B984h
.rdata:00426C3A ; ---------------------------------------------------------------------------
.rdata:00426C3A
.rdata:00426C3A EP_Zero: ; CODE XREF: .rdata:00426C32j
.rdata:00426C3A pop edx
.rdata:00426C3B mov edx, 7Dh
.rdata:00426C40 cmp byte ptr [esp+8], 1
.rdata:00426C45 jmp $+5
.rdata:00426C4A pusha
.rdata:00426C4B mov esi, offset rdata_Section2_start
.rdata:00426C50 xor edi, edi
.rdata:00426C52 jz short EP_One
.rdata:00426C54 popa
.rdata:00426C55 jmp near ptr 3092B9A4h
.rdata:00426C5A ; ---------------------------------------------------------------------------
.rdata:00426C5A
.rdata:00426C5A EP_One: ; CODE XREF: .rdata:00426C52j
.rdata:00426C5A lea edi, [esi-18000h]
.rdata:00426C60 xor ecx, ecx
.rdata:00426C62 jz short EP_Two
.rdata:00426C64 popa
.rdata:00426C65 jmp near ptr 3092B9B4h
.rdata:00426C6A ; ---------------------------------------------------------------------------
.rdata:00426C6A
.rdata:00426C6A EP_Two: ; CODE XREF: .rdata:00426C62j
.rdata:00426C6A mov eax, 7Dh
.rdata:00426C6F cmp edx, eax
.rdata:00426C71 mov eax, 4Ch
.rdata:00426C76 not eax
.rdata:00426C78 jnz short EP_Five
.rdata:00426C7A mov eax, large fs:30h ; // ProcessModuleInfo member of PEB - a pointer to a PEB_LDR_DATA structure
.rdata:00426C80 test eax, eax
.rdata:00426C82 js short EP_Three
.rdata:00426C84 mov eax, [eax+0Ch]
.rdata:00426C87 mov eax, [eax+0Ch]
.rdata:00426C8A mov dword ptr [eax+20h], 1000h
.rdata:00426C91 mov eax, large fs:18h ; // TEB
.rdata:00426C97 mov eax, [eax+30h] ; // PEB
.rdata:00426C9A movzx eax, byte ptr [eax+2] ; // PEB.BeingDebugged
.rdata:00426C9E test eax, eax
.rdata:00426CA0 jnz short EP_Four
.rdata:00426CA2 jmp EP_Five
.rdata:00426CA7 ; ---------------------------------------------------------------------------
.rdata:00426CA7
.rdata:00426CA7 EP_Three: ; CODE XREF: .rdata:00426C82j
.rdata:00426CA7 xor eax, eax
.rdata:00426CA9 mov al, large fs:20h ; // DebugContext if zero, we're not being debugged
.rdata:00426CAF test eax, eax
.rdata:00426CB1 jnz short EP_Four
.rdata:00426CB3 jmp EP_Five
.rdata:00426CB8 ; ---------------------------------------------------------------------------
.rdata:00426CB8
.rdata:00426CB8 EP_Four: ; CODE XREF: .rdata:00426CA0j
.rdata:00426CB8 ; .rdata:00426CB1j
.rdata:00426CB8 popa
.rdata:00426CB9
.rdata:00426CB9 EP_Five: ; CODE XREF: .rdata:00426C78j
.rdata:00426CB9 ; .rdata:00426CA2j ...
.rdata:00426CB9 push edi
.rdata:00426CBA or ebp, 0FFFFFFFFh
.rdata:00426CBD jmp short EP_Eight
.rdata:00426CBD ; ---------------------------------------------------------------------------
.rdata:00426CBF align 10h
.rdata:00426CC0
.rdata:00426CC0 EP_Six: ; CODE XREF: .rdata:EP_Ninej
.rdata:00426CC0 mov al, [esi]
.rdata:00426CC2 inc esi
.rdata:00426CC3 mov [edi], al
.rdata:00426CC5 inc edi
.rdata:00426CC6
.rdata:00426CC6 EP_Seven: ; CODE XREF: .rdata:00426D5Ej
.rdata:00426CC6 ; .rdata:00426D75j
.rdata:00426CC6 add ebx, ebx
.rdata:00426CC8 jnz short EP_Nine
.rdata:00426CCA
.rdata:00426CCA EP_Eight: ; CODE XREF: .rdata:00426CBDj
.rdata:00426CCA mov ebx, [esi]
.rdata:00426CCC sub esi, 0FFFFFFFCh
.rdata:00426CCF adc ebx, ebx
.rdata:00426CD1
.rdata:00426CD1 EP_Nine: ; CODE XREF: .rdata:00426CC8j
.rdata:00426CD1 jb short EP_Six
.rdata:00426CD3 mov eax, 1
.rdata:00426CD8
.rdata:00426CD8 EP_Ten: ; CODE XREF: .rdata:00426CE7j
.rdata:00426CD8 ; .rdata:00426CF2j
.rdata:00426CD8 add ebx, ebx
.rdata:00426CDA jnz short EP_Eleven
.rdata:00426CDC mov ebx, [esi]
.rdata:00426CDE sub esi, 0FFFFFFFCh
.rdata:00426CE1 adc ebx, ebx
.rdata:00426CE3
.rdata:00426CE3 EP_Eleven: ; CODE XREF: .rdata:00426CDAj
.rdata:00426CE3 adc eax, eax
.rdata:00426CE5 add ebx, ebx
.rdata:00426CE7 jnb short EP_Ten
.rdata:00426CE9 jnz short EP_Twelve
.rdata:00426CEB mov ebx, [esi]
.rdata:00426CED sub esi, 0FFFFFFFCh
.rdata:00426CF0 adc ebx, ebx
.rdata:00426CF2 jnb short EP_Ten
.rdata:00426CF4
.rdata:00426CF4 EP_Twelve: ; CODE XREF: .rdata:00426CE9j
.rdata:00426CF4 xor ecx, ecx
.rdata:00426CF6 sub eax, 3
.rdata:00426CF9 jb short EP_Thirteen
.rdata:00426CFB shl eax, 8
.rdata:00426CFE mov al, [esi]
.rdata:00426D00 inc esi
.rdata:00426D01 xor eax, 0FFFFFFFFh
.rdata:00426D04 jz short EP_TwentyTwo
.rdata:00426D06 mov ebp, eax
.rdata:00426D08
.rdata:00426D08 EP_Thirteen: ; CODE XREF: .rdata:00426CF9j
.rdata:00426D08 add ebx, ebx
.rdata:00426D0A jnz short EP_Fourteen
.rdata:00426D0C mov ebx, [esi]
.rdata:00426D0E sub esi, 0FFFFFFFCh
.rdata:00426D11 adc ebx, ebx
.rdata:00426D13
.rdata:00426D13 EP_Fourteen: ; CODE XREF: .rdata:00426D0Aj
.rdata:00426D13 adc ecx, ecx
.rdata:00426D15 add ebx, ebx
.rdata:00426D17 jnz short EP_Fifteen
.rdata:00426D19 mov ebx, [esi]
.rdata:00426D1B sub esi, 0FFFFFFFCh
.rdata:00426D1E adc ebx, ebx
.rdata:00426D20
.rdata:00426D20 EP_Fifteen: ; CODE XREF: .rdata:00426D17j
.rdata:00426D20 adc ecx, ecx
.rdata:00426D22 jnz short EP_Nineteen
.rdata:00426D24 inc ecx
.rdata:00426D25
.rdata:00426D25 EP_Sixteen: ; CODE XREF: .rdata:00426D34j
.rdata:00426D25 ; .rdata:00426D3Fj
.rdata:00426D25 add ebx, ebx
.rdata:00426D27 jnz short EP_Seventeen
.rdata:00426D29 mov ebx, [esi]
.rdata:00426D2B sub esi, 0FFFFFFFCh
.rdata:00426D2E adc ebx, ebx
.rdata:00426D30
.rdata:00426D30 EP_Seventeen: ; CODE XREF: .rdata:00426D27j
.rdata:00426D30 adc ecx, ecx
.rdata:00426D32 add ebx, ebx
.rdata:00426D34 jnb short EP_Sixteen
.rdata:00426D36 jnz short EP_Eighteen
.rdata:00426D38 mov ebx, [esi]
.rdata:00426D3A sub esi, 0FFFFFFFCh
.rdata:00426D3D adc ebx, ebx
.rdata:00426D3F jnb short EP_Sixteen
.rdata:00426D41
.rdata:00426D41 EP_Eighteen: ; CODE XREF: .rdata:00426D36j
.rdata:00426D41 add ecx, 2
.rdata:00426D44
.rdata:00426D44 EP_Nineteen: ; CODE XREF: .rdata:00426D22j
.rdata:00426D44 cmp ebp, 0FFFFF300h
.rdata:00426D4A adc ecx, 1
.rdata:00426D4D lea edx, [edi+ebp]
.rdata:00426D50 cmp ebp, 0FFFFFFFCh
.rdata:00426D53 jbe short EP_TwentyOne
.rdata:00426D55
.rdata:00426D55 EP_Twenty: ; CODE XREF: .rdata:00426D5Cj
.rdata:00426D55 mov al, [edx]
.rdata:00426D57 inc edx
.rdata:00426D58 mov [edi], al
.rdata:00426D5A inc edi
.rdata:00426D5B dec ecx
.rdata:00426D5C jnz short EP_Twenty
.rdata:00426D5E jmp EP_Seven
.rdata:00426D5E ; ---------------------------------------------------------------------------
.rdata:00426D63 align 4
.rdata:00426D64
.rdata:00426D64 EP_TwentyOne: ; CODE XREF: .rdata:00426D53j
.rdata:00426D64 ; .rdata:00426D71j
.rdata:00426D64 mov eax, [edx]
.rdata:00426D66 add edx, 4
.rdata:00426D69 mov [edi], eax
.rdata:00426D6B add edi, 4
.rdata:00426D6E sub ecx, 4
.rdata:00426D71 ja short EP_TwentyOne
.rdata:00426D73 add edi, ecx
.rdata:00426D75 jmp EP_Seven
.rdata:00426D7A ; ---------------------------------------------------------------------------
.rdata:00426D7A
.rdata:00426D7A EP_TwentyTwo: ; CODE XREF: .rdata:00426D04j
.rdata:00426D7A pop esi
.rdata:00426D7B mov edi, esi
.rdata:00426D7D mov ecx, 636h
.rdata:00426D82
.rdata:00426D82 EP_Twentythree: ; CODE XREF: .rdata:00426D89j
.rdata:00426D82 ; .rdata:00426D8Ej
.rdata:00426D82 mov al, [edi]
.rdata:00426D84 inc edi
.rdata:00426D85 sub al, 0E8h
.rdata:00426D87
.rdata:00426D87 EP_TwentyFour: ; CODE XREF: .rdata:00426DACj
.rdata:00426D87 cmp al, 1
.rdata:00426D89 ja short EP_Twentythree
.rdata:00426D8B cmp byte ptr [edi], 13h
.rdata:00426D8E jnz short EP_Twentythree
.rdata:00426D90 mov eax, [edi]
.rdata:00426D92 mov bl, [edi+4]
.rdata:00426D95 shr ax, 8
.rdata:00426D99 rol eax, 10h
.rdata:00426D9C xchg al, ah
.rdata:00426D9E sub eax, edi
.rdata:00426DA0 sub bl, 0E8h
.rdata:00426DA3 add eax, esi
.rdata:00426DA5 mov [edi], eax
.rdata:00426DA7 add edi, 5
.rdata:00426DAA mov eax, ebx
.rdata:00426DAC loop EP_TwentyFour
.rdata:00426DAE lea edi, [esi+24000h]
.rdata:00426DB4
.rdata:00426DB4 EP_TwentyFive: ; CODE XREF: .rdata:00426DD6j
.rdata:00426DB4 mov eax, [edi]
.rdata:00426DB6 or eax, eax
.rdata:00426DB8 jz short EP_TwentyNine
.rdata:00426DBA mov ebx, [edi+4]
.rdata:00426DBD lea eax, [eax+esi+26B90h]
.rdata:00426DC4 add ebx, esi
.rdata:00426DC6 push eax
.rdata:00426DC7 add edi, 8
.rdata:00426DCA call dword ptr [esi+26C08h]
.rdata:00426DD0 xchg eax, ebp
.rdata:00426DD1
.rdata:00426DD1 EP_TwentySix: ; CODE XREF: .rdata:00426DF7j
.rdata:00426DD1 mov al, [edi]
.rdata:00426DD3 inc edi
.rdata:00426DD4 or al, al
.rdata:00426DD6 jz short EP_TwentyFive
.rdata:00426DD8 mov ecx, edi
.rdata:00426DDA jns short near ptr EP_TwentySeven+1
.rdata:00426DDC movzx eax, word ptr [edi]
.rdata:00426DDF inc edi
.rdata:00426DE0 push eax
.rdata:00426DE1 inc edi
.rdata:00426DE2
.rdata:00426DE2 EP_TwentySeven: ; CODE XREF: .rdata:00426DDAj
.rdata:00426DE2 mov ecx, 0AEF24857h
.rdata:00426DE7 push ebp
.rdata:00426DE8 call dword ptr [esi+26C0Ch]
.rdata:00426DEE or eax, eax
.rdata:00426DF0 jz short EP_TwentyEight
.rdata:00426DF2 mov [ebx], eax
.rdata:00426DF4 add ebx, 4
.rdata:00426DF7 jmp short EP_TwentySix
.rdata:00426DF9 ; ---------------------------------------------------------------------------
.rdata:00426DF9
.rdata:00426DF9 EP_TwentyEight: ; CODE XREF: .rdata:00426DF0j
.rdata:00426DF9 call dword ptr [esi+26C10h]
.rdata:00426DFF
.rdata:00426DFF EP_TwentyNine: ; CODE XREF: .rdata:00426DB8j
.rdata:00426DFF popa
.rdata:00426E00 jmp near ptr byte_40BCB7
.rdata:00426E00 ; ---------------------------------------------------------------------------
.rdata:00426E05 align 200h
.rdata:00426E05 _rdata ends
.rdata:00426E05
.rdata:00426E05
.rdata:00426E05 end start

Opcode&H90
25th May 2006, 15:07
Well, this isnt the correct forum to post tools/bypasses since it helps nothing more than showing off and getting it patched. People should post information on the internal working of GameGuard. (eg. how its protection works, challenge/response mechanism, packing method) This will help people to learn and figure out a bypass themselves rather than using bunch of crudely made programs.


Sounds like the way to go is to get hold of the DDK write a service and call ntoskrnl.exe directly … if they want to run and hide in ring 0 it’s the worst place for them if they force us into ring 0.
Kernel driver usually solves all the problem, and yet the worst method since any error = OS crash.


Now does anyone know how GameGuard.des is packaged. It claims it is UPX 0.89.6 … 1.24 in PeiD but does not appear to unpack with an unpacker for that.
It is a modified UPX with some anti-debugging codes in it.

temp2
26th May 2006, 04:00
Well, this isnt the correct forum to post tools/bypasses since it helps nothing more than showing off and getting it patched.
.

Then where is? I'm more than happy to discuss stuff privately in email.


It is a modified UPX with some anti-debugging codes in it.

And anti dump by the looks of it. Any tips to unpacking it?

.rdata:00426C6A mov eax, 7Dh
.rdata:00426C6F cmp edx, eax
.rdata:00426C71 mov eax, 4Ch
.rdata:00426C76 not eax ; FFFFFFB3
.rdata:00426C78 jnz short EP_Five
.rdata:00426C7A mov eax, large fs:30h ; // PEB
.rdata:00426C80 test eax, eax
.rdata:00426C82 js short EP_Three
.rdata:00426C84 mov eax, [eax+0Ch] // pointer to loader data (PEB_LDR_DATA)
.rdata:00426C87 mov eax, [eax+0Ch] // pointer to first entry in InLoadOrderModuleList
.rdata:00426C8A mov dword ptr [eax+20h], 1000h // set SizeOfImage image size to 1000h :-)
.rdata:00426C91 mov eax, large fs:18h ; // TEB
.rdata:00426C97 mov eax, [eax+30h] ; // PEB
.rdata:00426C9A movzx eax, byte ptr [eax+2] ; // PEB.BeingDebugged
.rdata:00426C9E test eax, eax
.rdata:00426CA0 jnz short EP_Four
.rdata:00426CA2 jmp EP_Five
.rdata:00426CA7 ; ---------------------------------------------------------------------------
.rdata:00426CA7
.rdata:00426CA7 EP_Three: ; CODE XREF: .rdata:00426C82j
.rdata:00426CA7 xor eax, eax
.rdata:00426CA9 mov al, large fs:20h ; // DebugContext if zero, we're not being debugged
.rdata:00426CAF test eax, eax
.rdata:00426CB1 jnz short EP_Four
.rdata:00426CB3 jmp EP_Five

AsHiKa
30th May 2006, 04:45
More info:

nProtect terminates kernel32.dll and replaces it with a fake.
Ex:

nProtect: MUST KILL KERNEL!!!
kernel32.dll: argghhh Im dead (terminated)
nProtect: Good now put up fake kernel
Hack: Can I sendmessage?
Fake Kernel: **** no bitch

Opcode&H90
30th May 2006, 09:59
And anti dump by the looks of it. Any tips to unpacking it?
Take a look at the last jmp. Good luck dumping. ;)

temp2
3rd June 2006, 05:50
Take a look at the last jmp. Good luck dumping. ;)

Here is an unpacking tutorial from Thursday, January 12 2006 @ 08:34 PM CET

Unpacking UPX packed Gamemon.des
By: g3nuin3

http://www.reversing.be/article.php...060112203459247

I will be continuing the reversal on GameDeception's Anti-Cheat General forum

KizZamP-
3rd June 2006, 10:49
you didn't insert the link properly lol :)
click the HTTP symbol.

TiMBuS
9th June 2006, 04:40
g3n's still going strong ey.

What surprises me, is that even though the driver hooks a few SDT functions, it doesn't hook the SDT Shadow and disable things like GetDC, GetPixel, SendInput etc from the kernel..


Oh, and you mentioned Zw*** Functions are hooked..
Erm, only kernelmode applications can use Zw* functions. Nt equivalent functions are the ones located on the syscall table, and the syscall table is the entry point into ntoskrnl.exe

Usermode programs tell ntdll.dll to use the syscall table. To use the syscall table you just need to make a call to the gate:
mov [edx], 7FFE0300h
call edx

So I guess thats kind of ranting. My point is Zw* functions arent hooked, the ones on the table are hooked (Nt*)

tyrell444
9th June 2006, 07:46
yo does anyone know the new codes for ce or were i can find em kinda pissing me off lol

Opcode&H90
10th June 2006, 05:52
Nt* functions are just an alias for Zw* functions. They both points to the same code. If you hook it, so you are actually hooking both.

In kernel they dont have Nt* functions, so I guess it is just naming convention. Nt* meant for user modes and Zw* meant for kernel modes.

Edit: There are Nt* functions in ntoskrnl.exe. These exports are pointing to somewhere outside the image. I've made a big mistake lol.

Lets hope they are still idoit enough to think that user mode hooking will done their job. :P

Hehehe123
12th June 2006, 06:42
I admire you guys work on study a way to bypass the GG on its own game, creating another rootkit for the job :D. I just stop to say good work, good luck and keep it up, so when all the 'backdoors' on GG are removed (like the joytokey.exe), you will be the only ones with a unique low level GG bypass.

temp2
12th June 2006, 08:04
Nt* functions are just an alias for Zw* functions. They both points to the same code. If you hook it, so you are actually hooking both.

In kernel they dont have Nt* functions, so I guess it is just naming convention. Nt* meant for user modes and Zw* meant for kernel modes.

Lets hope they are still idoit enough to think that user mode hooking will done their job. :P

Are you sure about this?

If you look at ntoskrnl.exe for example in IDA Pro you see:

.text:0042FF00 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:0042FF00
.text:0042FF00
.text:0042FF00 ; NTSTATUS __stdcall ZwOpenProcess(PHANDLE ProcessHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId)
.text:0042FF00 public ZwOpenProcess
.text:0042FF00 ZwOpenProcess proc near ; CODE XREF: sub_5017D0+92p
.text:0042FF00
.text:0042FF00 ProcessHandle = dword ptr 4
.text:0042FF00 DesiredAccess = dword ptr 8
.text:0042FF00 ObjectAttributes= dword ptr 0Ch
.text:0042FF00 ClientId = dword ptr 10h
.text:0042FF00
.text:0042FF00 mov eax, 6Ah
.text:0042FF05 lea edx, [esp+ProcessHandle]
.text:0042FF09 int 2Eh ; DOS 2+ internal - EXECUTE COMMAND
.text:0042FF09 ; DS:SI -> counted CR-terminated command string
.text:0042FF0B retn 10h
.text:0042FF0B ZwOpenProcess endp
.text:0042FF0B
.text:0042FF0B ; ---------------------------------------------------------------------------

i.e. the standard mechanism for using an 2Eh interrupt (sysenter) for to get into ring 0 and call the corresponding Nt* function in ntoskrnl.exe via the SDT

and

PAGE:004DEB7A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
PAGE:004DEB7A
PAGE:004DEB7A ; Attributes: bp-based frame
PAGE:004DEB7A
PAGE:004DEB7A ; NTSTATUS __stdcall NtOpenProcess(PHANDLE ProcessHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,PCLIENT_ID ClientId)
PAGE:004DEB7A public NtOpenProcess
PAGE:004DEB7A NtOpenProcess proc near ; CODE XREF: sub_5278D4+38p
PAGE:004DEB7A ; sub_527870+BEj
PAGE:004DEB7A ; DATA XREF: ...
PAGE:004DEB7A
PAGE:004DEB7A var_CC = dword ptr -0CCh
PAGE:004DEB7A var_B4 = dword ptr -0B4h
PAGE:004DEB7A var_B0 = dword ptr -0B0h
PAGE:004DEB7A var_A0 = dword ptr -0A0h
PAGE:004DEB7A var_9C = dword ptr -9Ch
PAGE:004DEB7A var_3C = dword ptr -3Ch
PAGE:004DEB7A AccessMode = byte ptr -38h
PAGE:004DEB7A var_34 = byte ptr -34h
PAGE:004DEB7A var_30 = dword ptr -30h
PAGE:004DEB7A var_2C = dword ptr -2Ch
PAGE:004DEB7A var_28 = dword ptr -28h
PAGE:004DEB7A Object = dword ptr -24h
PAGE:004DEB7A var_20 = dword ptr -20h
PAGE:004DEB7A var_1C = byte ptr -1Ch
PAGE:004DEB7A var_18 = dword ptr -18h
PAGE:004DEB7A var_10 = dword ptr -10h
PAGE:004DEB7A var_4 = dword ptr -4
PAGE:004DEB7A ProcessHandle = dword ptr 8
PAGE:004DEB7A AccessMask = dword ptr 0Ch
PAGE:004DEB7A ObjectAttributes= dword ptr 10h
PAGE:004DEB7A ClientId = dword ptr 14h
PAGE:004DEB7A
PAGE:004DEB7A push ebp
PAGE:004DEB7B mov ebp, esp
PAGE:004DEB7D push 0FFFFFFFFh
PAGE:004DEB7F push offset dword_406250
PAGE:004DEB84 push offset _except_handler3
PAGE:004DEB89 mov eax, large fs:0
PAGE:004DEB8F push eax
PAGE:004DEB90 mov large fs:0, esp
PAGE:004DEB97 push ecx
PAGE:004DEB98 push ecx
PAGE:004DEB99 sub esp, 0BCh
PAGE:004DEB9F push ebx
PAGE:004DEBA0 push esi
PAGE:004DEBA1 push edi

In usermode Zw* and Nt* both point to the same code. In kernelmode the Nt* is the actual implementation while the Zw* is a stub that goes through the system-call mechanism. The reason why one would want to call a Zw* is to prove to the API being called that you are calling it from kernelmode. If you wouldn't do that the API might think it is called from usermode and will verify that all the parameters only contain usermode addresses. http://www.osronline.com/article.cfm?article=257

temp2
16th June 2006, 02:41
Unpacking UPX packed Gamemon.des
By: g3nuin3

I finally got round to following g3nuin3's excellent tutorial. It appears nProtect have introduced some anti-debug code into the packer. Thats no problem though ... just nop the mov dword ptr [eax+20h], 1000h and jnz short EP_Four code.


rdata:00426C6A mov eax, 7Dh
.rdata:00426C6F cmp edx, eax
.rdata:00426C71 mov eax, 4Ch
.rdata:00426C76 not eax ; FFFFFFB3
.rdata:00426C78 jnz short EP_Five
.rdata:00426C7A mov eax, large fs:30h ; // PEB
.rdata:00426C80 test eax, eax
.rdata:00426C82 js short EP_Three
.rdata:00426C84 mov eax, [eax+0Ch] // pointer to loader data (PEB_LDR_DATA)
.rdata:00426C87 mov eax, [eax+0Ch] // pointer to first entry in InLoadOrderModuleList
.rdata:00426C8A mov dword ptr [eax+20h], 1000h // set SizeOfImage image size to 1000h :-)
.rdata:00426C91 mov eax, large fs:18h ; // TEB
.rdata:00426C97 mov eax, [eax+30h] ; // PEB
.rdata:00426C9A movzx eax, byte ptr [eax+2] ; // PEB.BeingDebugged
.rdata:00426C9E test eax, eax
.rdata:00426CA0 jnz short EP_Four
.rdata:00426CA2 jmp EP_Five
.rdata:00426CA7 ; ---------------------------------------------------------------------------
.rdata:00426CA7
.rdata:00426CA7 EP_Three: ; CODE XREF: .rdata:00426C82j
.rdata:00426CA7 xor eax, eax
.rdata:00426CA9 mov al, large fs:20h ; // DebugContext if zero, we're not being debugged
.rdata:00426CAF test eax, eax
.rdata:00426CB1 jnz short EP_Four
.rdata:00426CB3 jmp EP_Five

Opcode&H90
16th June 2006, 17:43
Wouldnt it easier to just get a stealth plugin and bp at the oep? (the last jmp points to oep)

temp2
17th June 2006, 06:44
Wouldnt it easier to just get a stealth plugin and bp at the oep? (the last jmp points to oep)

How would said plugin know what the correct dump size was since it was changed to 0x1000 i.e. the size of the header LOL?

TiMBuS
21st June 2006, 17:50
How would said plugin know what the correct dump size was since it was changed to 0x1000 i.e. the size of the header LOL?

He gotcha there ;)

Temp, you mention that kernelmode API (Zw*) are hooked, this may be so as I've noticed that DBK32 avoids any Zw functions reported hooked.

Doesn't really matter as you can just grab the address from the SSDT (You call it an SDT but that incorrect :P as the SDT is just a stuct that contains a pointer to the SSDT among other things) Or you can grab the address of the function directly from the export table of Ntoskrnl.exe as it's a standard PE file..

Well thats your Zw* bypassing - ghetto style.
Or, you could just override these mythical hooks. You're in the kernel, after all.

I'd also like to note that as far as I can tell, there are no longer any SSDT hooks. Thats why current CE's work without using the DBK read/write (you need to have CE protect on tho, to stop the user hooks, of course.)

MapleCheater437
21st June 2006, 22:30
Does cheat engine 5.2 work????? if so can u guys hook me up with some codes u know addresses offsets and that stuff.....

temp2
22nd June 2006, 04:09
Doesn't really matter as you can just grab the address from the SSDT (You call it an SDT but that incorrect :P as the SDT is just a stuct that contains a pointer to the SSDT among other things)


I have a KeServiceDescriptorTable and KeServiceDescriptorTableShadow in my w2k source code ... what do you mean by SSDT? :-)

Or you can grab the address of the function directly from the export table of Ntoskrnl.exe as it's a standard PE file..


Exactly

I'd also like to note that as far as I can tell, there are no longer any SSDT hooks. Thats why current CE's work without using the DBK read/write (you need to have CE protect on tho, to stop the user hooks, of course.)

That appears correct for some games. The hidden driver has gone. Hacking nProtect is more of a hobby than a necessity for me.

TiMBuS
22nd June 2006, 04:33
If you have the source, then you should know that the KeServiceDescriptor is declared as follows:

typedef struct ServiceDescriptorTable {
SDE ServiceDescriptor[4];
} SDT;

typedef struct ServiceDescroptorEntry {
PDWORD KiServiceTable;
PDWORD CounterTableBase;
DWORD ServiceLimit;
PBYTE ArguementTable;
}SDE;

Does that look like a table of functions to you? No, but it's got a pointer to a table of functions; the SSDT, or System Service Dispatch Table (KiServiceTable). :squareeyed:

temp2
22nd June 2006, 07:41
If you have the source, then you should know that the KeServiceDescriptor is declared as follows:


ke.h

//
// System service table descriptor.
//
// N.B. A system service number has a 12-bit service table offset and a
// 3-bit service table number.
//
// N.B. Descriptor table entries must be a power of 2 in size. Currently
// this is 16 bytes on a 32-bit system and 32 bytes on a 64-bit
// system.
//

#define NUMBER_SERVICE_TABLES 4
#define SERVICE_NUMBER_MASK ((1 << 12) - 1)

#if defined(_WIN64)

#define SERVICE_TABLE_SHIFT (12 - 5)
#define SERVICE_TABLE_MASK (((1 << 2) - 1) << 5)
#define SERVICE_TABLE_TEST (WIN32K_SERVICE_INDEX << 5)

#else

#define SERVICE_TABLE_SHIFT (12 - 4)
#define SERVICE_TABLE_MASK (((1 << 2) - 1) << 4)
#define SERVICE_TABLE_TEST (WIN32K_SERVICE_INDEX << 4)

#endif

typedef struct _KSERVICE_TABLE_DESCRIPTOR {
PULONG_PTR Base;
PULONG Count;
ULONG Limit;
#if defined(_IA64_)
LONG TableBaseGpOffset;
#endif
PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
kinit.c

//
// KeServiceDescriptorTable - This is a table of descriptors for system
// service providers. Each entry in the table describes the base
// address of the dispatch table and the number of services provided.
//

KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[NUMBER_SERVICE_TABLES];
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow[NUMBER_SERVICE_TABLES];

Where is your source from?

Is the shadow for Win32.sys do you know? I have not really investigated that yet.

TiMBuS
27th June 2006, 08:05
The struct I printed has striking resemblance to yours. I got it from here. (www.security.org.sg/code/SIG2_DefeatingNativeAPIHookers.pdf)

I was working with knowledge from the www.rootkit.com book. Highly recommended.

In response to your question about the SDT Shadow. It does indeed point to Win32.sys.

sstevenn6t9
3rd July 2006, 03:14
OMG how do you know this stuff im trying to learn it but it wont work.. can someone plz help mee by sending me a msg - ghetto-steve-6t9 @ hotmail . com

[noo spaces]

hcong
23rd September 2006, 22:25
Like Opcode says above you can just make your own stub. Also you can just copy the function before nProtect starts and call your copy of the function instead.

i tried what you said before, but what i get is access violation!!
i call VirtualAlloc to allocate some space with PAGE_EXECUTE_READWRITE, then i call CopyMemory to copy the whole function of SendInput to the space i allocate, then i call the "SendInput" that already copied to my process, but i get access violation. izzit the function cant call from different address?

i also tried to backup the 1st 10 bytes of the SendInput function, then after the GameGuard loading, i try to write back the 10 bytes to the function entry, but failed, i think is because the GameGuard hook the VirtualProtect also.

got any other better way to use the "original" api functions

Sirmabus
24th September 2006, 06:42
You probably have a bug some place.
Are you sure you are calling the copy of the function?

Just point a breakpoint just before you call the copy as a test, (you can also put a __asm int 3; before it) then step though it with a debuger like OllyDbg and see where the call goes to.

hcong
24th September 2006, 19:52
i upload the the dll file, the export function name is NewSendInput, the parameters is same as the api SendInput, the function is i copy 15 bytes(the size of the SendInput is 15 bytes only) start from entry of SendInput function

i write this dll file in delphi, i don't know you know delphi or not, but i know you know you know C++, so i make simple translation, maybe got syntax error, coz i not familiar with c++

typedef UINT (*TSendInput)(UINT cInputs, LPINPUT *pInputs, int cbSize);
UINT NewSendInput(UINT cInputs, LPINPUT *pInputs, int cbSize)
{
LPVOID Proc = VirtualAlloc(NULL, 15, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
CopyMemory(Proc, GetProcAddress(GetModuleHandle("User32"), "SendInput"), 15);
TSendInput SendInput = (TSendInput)Proc;
return (*SendInput)(cInputs, pInputs, cbSize);
}

sorry for my poor grammer.

when i call the NewSendInput, i get "The instruction at "0x0000001c" referenced memory at "0x0000001c". The memory could not be "read"."

Sirmabus
25th September 2006, 05:46
If you just took my advise and steped through with it in a debugger you would have figured out the problem.
Even if nProtect is running you can still run a debugger on your OWN process.

Looks like you have the essence of it right. Again I would step through it in a debugger. See if the code get's copied over corretly, etc.

If you run user33.dll in IDA Pro you can see the function is the typical simple stub that calls the kernel service (XP Sp2):


.text:77D5F118 ; UINT __stdcall SendInput(UINT cInputs,LPINPUT pInputs,int cbSize)
.text:77D5F118 public SendInput
.text:77D5F118 SendInput proc near ; CODE XREF: mouse_event+36p
.text:77D5F118 ; keybd_event+37p
.text:77D5F118
.text:77D5F118 cInputs = dword ptr 4
.text:77D5F118 pInputs = dword ptr 8
.text:77D5F118 cbSize = dword ptr 0Ch
.text:77D5F118
.text:77D5F118 mov eax, 11F6h
.text:77D5F11D mov edx, 7FFE0300h
.text:77D5F122 call dword ptr [edx]
.text:77D5F124 retn 0Ch
.text:77D5F124 SendInput endp


So there are no relocations, etc., just those 9 bytes of code.

After you step through the copy part (in debugger) then
Put a break point on your
"(*SendInput)(cInputs, pInputs, cbSize);"

Maybe you code there is just an example, but realise it's supposed to be a two part process:
1. Before nProtect loads copy the function (like you code does).
2. Then after nProtect is loaded then you just want to call the stub. Like the "(*SendInput)(cInputs, pInputs, cbSize);"

There is no sense in make a copy of the function after nProect starts. It will already be hooked.

hcong
25th September 2006, 08:45
the allocation and the copy function part is actually put in DllMain, is just i want to simplify my code on forum,
and also i very new to debugger, but i would try advise

and another thing is the NewSendInput cannot work properly even the nProtect was not running

underling2000
26th September 2006, 03:17
The last update (about a week ago I guess) seems to have prevented some of these techniques. I was implmenting one myself the other day and noticed that when GG was running I couldn't launch the process with OllyDBG (my own process) and my "SafeSendInput" would stop funtioning.

The SafeSendInput and OllyDBG were tested without GG running and worked perfectly, but as soon as GG loaded they both stopped working.

Looks like the new release has some new tricks =).

Cheers,
Underling2k

hcong
26th September 2006, 10:19
http://www.geocities.com/hcong85/untitled.GIF
http://www.geocities.com/hcong85/untitled2.GIF

the function is copy correctly to the space i allocate, and the function call address also correct, but the function cannot work properly:disappointed:

hcong
27th September 2006, 23:04
i know where is my mistake already, thanks anyway!!:) :)

cloudkia
28th September 2006, 12:20
count you tell me how to use your "GameHack.dll"? I meant the NewSendInput function

hcong
28th September 2006, 15:24
count you tell me how to use your "GameHack.dll"? I meant the NewSendInput function

the NewSendInput is just an example, is useless, because it copy the function and call the copied function in same process.

this two should seperate, the function should copy before the original function hooked

the parameters is same as SendInput, but when call the NewSendInput, will get access violation, because when coding, i forgot to include stdcall.

this method is useless to nProtect, because nProtect hook function in both Kernel mode and User mode

unnamed_anonym
23rd October 2007, 00:03
sry! i am nobb
where copy gamehack.dll? or how to deactive gameguard or how to use gameguard+cheat engine 5.3 ? :]]]

Mazteraz9
31st October 2007, 15:39
lkjljkl

Sirmabus
1st November 2007, 22:20
Coping the functions is not a useless technique.
It depends on the function really. Like the last time I tried SendInput(), and SendMessage() worked great.
But functions like VirtualProtectEx() won't work because that one does get picked up in the kernel hook.

There is basically both a user and kernel mode rootkit.
A lot of API functions never reach the kernel, a lot of things are in process space only.

You got to reverse engineer it. Once you see how it works, the little tricks it does, etc., then you can make a bypass, emulator, etc..

S3NSA
3rd November 2007, 22:33
here ends the journey

Sirmabus
7th November 2007, 20:01
Guy Falk, it only ends where you want it to.

Unfortunately, a lot of people don't even want to start.
They want it handed to them.

Like I mentioned hardware break points, maybe people are doing that (w/DLL injection) but there is not much talk of it.

Well, I'm working on a new hook/detour engine I plan on releasing. It will have HWBP generically built in.
But then it might only work for a while before GG is updated to
block it..

L. Spiro
31st December 2007, 07:17
Because GameGuard is such a poorly coded piece of crap I refuse to install it on my own machine.
For that reason I can not study it myself.

I would like to borrow a bit of information from those who can get it so that I can work on an extensive bypass.

For the sake of clarity, a few terms should be defined.
- IAT (Import Address Table) Hook: To modify the import table of a module so it points from the real function to some other function made by the anti-cheat.
- EAT (Export Address Table) Hook: To modify the exported address of a function in a module so that when you look for it (using GetProcAddress()) it gives you a false address.
- Inlined Hooking: Overwriting some of the bytes of the actual function (usually at the very start) to JMP to a stub created by the anti-cheat.
- SSDT (Service System Dispatch Table): Modifies entries in KeServiceDescriptorTable->ServiceTable. These are used when you call usermode routines in ntdll.dll that in turn call their kernel-mode relatives (for example NtOpenProcess). If you are in kernel-mode already and you link your driver against NtOpenProcess (for example) then it does not use the SSDT (correct me if I am wrong) but links normally to the function using a JMP table (though the mechanism it uses to get the address of the function might be using the SSDT; once again someone may feel free to post information about this).



#1: It is easy to get a list of API routines that are hooked but I would like a bit more information:
- A: Which functions use which hooking methods?
The list of hooked functions should be made into a table that also shows how they are hooked. This would be much more useful than just a list.
- B: Are any kernel functions inlined hooked? This would actually be answered by doing the above, but it is important enough to ask again.

#2: If any functions are inline-hooked, could someone copy/paste the function, including its hooking code, here? I would like to see the hook for myself and how it fits into the original code (though I am sure it is like any other hook).

#3: What was mentioned about using a fake Kernel32.dll? Is this confirmed or conspiracy theory? And if so, what is different about it?


// ==== A BIG ONE ====
#4: What do these hooks actually DO? For example, the hook on NtOpenProcess. Does it just return FALSE if the process ID is the protected process, or does it modify the parameters of the function to remove some flags (the function succeeds but it does not have the requested access rights)?
Which functions are made to fail, and which functions are made to work but lie? And lie in what way?






All hooks are inlined (they may also be IAT or EAT).
The header of each function gets replaced with a stub that jumps to some code that is not viewable with ReadProcessMemory, and it is not clear yet what the hooks actually do, except that the hook on ReadProcessMemory() returns FALSE if some ares of memory is supposed to be protected.

The hooks on NtOpenProcess seem only to be used to detect known cheating programs. Unknown programs may open and hack games protected with nProtect Game Guard.

The spaces where the hooks are written is set to read/execute-only and may not be changed thanks to their hooks on NtProtectVirtualMemory in kernel.


Kernel functions are also inlined.
These can be removed by simply overwriting them.





L. Spiro

hcong
7th February 2008, 16:58
Coping the functions is not a useless technique.
It depends on the function really. Like the last time I tried SendInput(), and SendMessage() worked great.
But functions like VirtualProtectEx() won't work because that one does get picked up in the kernel hook.

There is basically both a user and kernel mode rootkit.
A lot of API functions never reach the kernel, a lot of things are in process space only.

You got to reverse engineer it. Once you see how it works, the little tricks it does, etc., then you can make a bypass, emulator, etc..

but i have tried before, copy the function before the nprotect loaded, but then after the nprotect loaded, the function i copied won't work anymore, i have tried the function that i copy before, it work perfect without nProtect.

Sirmabus
8th February 2008, 02:10
They could have changed something, like hooking something in the chain of APIs that wasn't hooked before.

Also since they do kernel hooks on some services, some APIs won't work reguardless if you do a user mode copy or not.
"VirtualQueryEx()" for example; even if you get by the user mode hook from making a copy, there is a kernel mode hook in the way..

L. Spiro
12th February 2008, 11:37
One issue deals with copying user-mode functions. You still run into the bridge that connects user-mode to kernel-mode and then you run into the kernel-mode hooks on the SDT functions (note the SDT table is not hooked as far as I have yet seen; rather the functions themselves are hooked).



The second issue deals with kernel-mode hooks.
NtOpenProcess(), PsLookupProcessByProcessId(), NtDebugActiveProcess(), etc., are NOT hooked.

They hook KeAttachProcess() 3 calls deep and KeStackAttachProcess() 3 calls deep.
These are hooked because they are used by all of the above functions and also by all custom implementations of ReadProcessMemory().
Also, KeAttachProcess() actually calls KeStackAttachProcess() at a depth of 23 calls, but this might not be a problem if it is using it to go into a system process rather than the target process (which would not trigger the alarms on nProtect Game Guard).



So if you are only copying the upper-most hooked function you will not bypass anything. You would have to copy that, plus all of the functions it calls, etc.


L. Spiro