Register for your free account! | Forgot your password?

Go Back   elitepvpers > Popular Games > Silkroad Online
You last visited: Today at 04:25

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Inside GameGuard

Discussion on Inside GameGuard within the Silkroad Online forum part of the Popular Games category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
In this topic I will post my findings about GameGuard ( nProtect ) as I research into it. Everything I know, you will know, and at the end of it all I will post tools to monitor and/or disable or bypass the tool using correct methods rather than hack-and-slash unsafe methods many others have used. Also, note that my investigation into nProtect will be done solely with the silkroad implementation. There may be differences in the nProtect accompanying SilkRoad and that of other games.

First, to break something you need to understand its roots.

The company that develops gameguard is called INCA Internet Co. Ltd. The company developed the nProtect technology as an antivirus solution in Korea several years ago. nProtect works by utilizing common strategies viruses use to protect vital system processes and access, in theory allowing the system to prevent any virus from taking any viable root in the system. INCA's idea is horrible. The antivirus is a huge flop, and doesn't succeed in much anything but being annoying as hell to those who use it ( try closing a protected process with ctrl+alt+delete and you get an annoying access denied prompt etc ). As a result, INCA noticed that the technology could be implemented into a semi-anticheat technology. Thus GameGuard was born. GameGuard began rather simply, just disallowing any IPC win32 APIs access to the protected process ( we all remember when you couldn't close gunbound with ctrl+alt+del.. and when it hung, you were fucked ). Now it takes full use of its driver capabilities, completely masking the game from win32 API ( apparently they aren't good at making rootkits either because the taskmanager still shows the window ). Now, you can't even get the handle to the process you want to inject into ( unless you get the handle of the window and use win32 API to perform the operations ).

Back when GameGuard just came out for gunbound, myself and friends of mine were making simple money hacks for the game. At the time we were semi-annoyed because we did most of our research with TSearch and other memory editing tools. That night, I decided since this company is new and their software has been known to be useless, that I would break GameGuard. Five minutes later and GameGuard no longer had any effect on my game. I had noticed with a simple process logger that the game loaded its launcher, logged in, and proceeded to run the GameGuard executable ( gameguard.des ). Then, either the loader or the GameGuard executable loaded the actual game executable, and GameGuard continued to check for updates then initiate the hiding process before resuming execution of the game executable ( the actual game may have initiated GameGuard, I will find this out when I begin my research ). I noticed since GameGuard, like any other code, must first load and then perform actions to take effect, that possibly by freezing GameGuard's executable that I could make a window in which I could modify the actual game. Sure enough, a simple process freeze on gameguard.des as soon as it loaded yeilded a vulnerable gunbound. Soon after our bots and hacks worked perfectly, not a day later than GameGuard began running. I remember the combination lock image in the center of my screen frozen as my debugger worked flawlessly inside the game.

Since then I have yet to bother messing with GameGuard, but now, as I play SilkRoad, I will attempt to remove its effects once again. I am annoyed to no end by GameGuard, and sometimes I'd like to bot as much as anyone else does. So stick around, keep this page bookmarked as it'll be your insight to breaking GameGuard.

The product page can be found at the following URL:
jMerliN is offline  
Old 02/14/2006, 05:01   #2
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
- Part 1 -
- Unpacking -

One quick look at silkroad files and I immediately came to a conclusion that the files were packed. Gameguard files are named '.des' rather than '.exe' or '.sys,' indicating foul play. Also, opening sro_client.exe in a disassembler yeilds a very noticeable packed output. The first step into understanding and breaking Gameguard is to unpack all sensitive code. We all know that packed code == useless code. Packing is the quick-and-dirty and often times sloppy way of protecting code. There is no need to pack code using commercial packers if it is secure and compiled with the correct directives ( they used MSVC 6.0/7.0 so I know for a fact that optimizing the compiler options would yeild file sizes competing with packed ones ). I quickly opened up my copy of PEiD ( ) and ran a scan on the directory. Note that you should have your scan mode set to 'Hardcore' or it pretty much picks up nothing unless it has not been modified at all. Here's what I found:

Code:
C:\Program Files\Silkroad\dbghelp.dll	::	Microsoft Visual C++ 7.0 DLL Method 3
C:\Program Files\Silkroad\gameguard.des	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GFXFileManager.dll	::	Microsoft Visual C++ 6.0 DLL [Debug]
C:\Program Files\Silkroad\msvcp60.dll	::	Microsoft Visual C++ 6.0 DLL [Debug]
C:\Program Files\Silkroad\Remove.Exe	::	Microsoft Visual C++ 6.0 [Overlay]
C:\Program Files\Silkroad\replacer.exe	::	Microsoft Visual C++ 6.0
C:\Program Files\Silkroad\SilkErrSender.exe	::	Microsoft Visual C++ 6.0
C:\Program Files\Silkroad\silkroad.exe	::	Microsoft Visual C++ 6.0
C:\Program Files\Silkroad\sro_client.exe	::	ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov
C:\Program Files\Silkroad\GameGuard\GameMon.des	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GameGuard\npgg9x.des	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GameGuard\npggNT.des	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GameGuard\npgmup.des	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GameGuard\npgmup.des.new	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GameGuard\npsc.des	::	UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo [Overlay]
C:\Program Files\Silkroad\GameGuard\NPSCAN.DES	::	UPX 0.80 - 1.24 DLL -> Markus & Laszlo [Overlay]
If you will read down a few posts you can see where I explain about these UPX packed files. The following is the reversal of the auto-unpacking code. Note this is preliminary reversing as it's not in any language with which you can compile. I will eventually post a compileable C++ source-code using this simple reversal that will unpack any files packed with this UPX variant.

Code:
.rdata:00426C30         xor   edi, edi
//EDI = 0

.rdata:00426C32         jz   short loc_426C3A
//jump condition always true

//UNREACHABLE CODE BEGIN ====
.rdata:00426C34         popa
.rdata:00426C35         jmp   near ptr 3092B984h
//==== UNREACHABLE CODE END

.rdata:00426C3A loc_426C3A:           &#59; CODE XREF: .rdata:00426C32j
.rdata:00426C3A         pop   edx
//POP

.rdata:00426C3B         mov   edx, 7Dh
//edx = 7Dh

.rdata:00426C40         cmp   byte ptr [esp+8], 1
//unused comparison statement, result never checked

.rdata:00426C45         jmp   $+5
//standard skip jump, jump statement jumps to next instruction

.rdata:00426C4A         pusha
//PUSHA - PUSHA LEVEL 1

.rdata:00426C4B         mov   esi, offset dword_419000
//ESI = base of DWORD data

.rdata:00426C50         xor   edi, edi
//EDI = 0

.rdata:00426C52         jz   short loc_426C5A
//jump condition always true

//UNREACHABLE CODE BEGIN ====
.rdata:00426C54         popa
.rdata:00426C55         jmp   near ptr 3092B9A4h
//==== UNREACHABLE CODE END

.rdata:00426C5A loc_426C5A:           &#59; CODE XREF: .rdata:00426C52j
.rdata:00426C5A         lea   edi, [esi-18000h]
//EDI = base of .text section

.rdata:00426C60         xor   ecx, ecx
//ECX = 0

.rdata:00426C62         jz   short loc_426C6A
//condition of jump always true

//UNREACHABLE CODE BEGIN ====
.rdata:00426C64         popa
.rdata:00426C65         jmp   near ptr 3092B9B4h
//==== UNREACHABLE CODE END

.rdata:00426C6A loc_426C6A:           &#59; CODE XREF: .rdata:00426C62j
.rdata:00426C6A         mov   eax, 7Dh
//EAX = 7Dh

.rdata:00426C6F         cmp   edx, eax
//EDX ( 7Dh ) == EAX ( 7Dh ), result is 0 ( zero flag set )

.rdata:00426C71         mov   eax, 4Ch
//EAX = 4Ch

.rdata:00426C76         not   eax
//EAX = 0FFFFFFB3h

.rdata:00426C78         jnz   short loc_426CB9
//jump condition always false

.rdata:00426C7A         mov   eax, large fs:30h
//EAX = _PEB

.rdata:00426C80         test  eax, eax
.rdata:00426C82         js   short loc_426CA7
//condition true if OS is 9x, false if NT

.rdata:00426C84         mov   eax, [eax+0Ch]
//EAX = _PEB->Ldr <<MODULE LIST HEAD>>

.rdata:00426C87         mov   eax, [eax+0Ch]
//EAX = _PEB->Ldr->InLoadOrderModuleList->Flink

.rdata:00426C8A         mov   dword ptr [eax+20h], 1000h
//(*_LDR_MODULE)( _PEB->Ldr->InLoadOrderModuleList->Flink )->SizeOfImage = 1000h

//THE FOLLOWING APPEARS TO BE DEBUGGER DETECTION CODE

.rdata:00426C91         mov   eax, large fs:18h
//EAX = _TEB

.rdata:00426C97         mov   eax, [eax+30h]
//EAX = _TEB->ProcessEnvironmentBlock

.rdata:00426C9A         movzx  eax, byte ptr [eax+2]
//EAX = _TEB->ProcessEnvironmentBlock->BeingDebugged ( TRUE IF DEBUGGER IS ACTIVE, NT VERSION ONLY )

.rdata:00426C9E         test  eax, eax
.rdata:00426CA0         jnz   short loc_426CB8
//condition is true if a debugger is active ( if debugger flag is set in TEB/PEB )

.rdata:00426CA2         jmp   loc_426CB9
//called if debugger is not active ( if debugger is not set in TEB/PEB )

.rdata:00426CA7 loc_426CA7:           &#59; CODE XREF: .rdata:00426C82j
.rdata:00426CA7         xor   eax, eax
//EAX = 0

.rdata:00426CA9         mov   al, large fs:20h
//EAX = TIB->DebugContext

.rdata:00426CAF         test  eax, eax
.rdata:00426CB1         jnz   short loc_426CB8
//condition is true if a debugger is active ( if debug context is true, 9X check! )

.rdata:00426CB3         jmp   loc_426CB9
//called if debugger is not active ( if debug context is false )

.rdata:00426CB8 loc_426CB8:           &#59; CODE XREF: .rdata:00426CA0j
.rdata:00426CB8                 &#59; .rdata:00426CB1j
.rdata:00426CB8         popa
//POPA - PUSHA LEVEL 0 ( clear ) ( ONLY EXECUTED IF A DEBUGGER IS FOUND )

.rdata:00426CB9 loc_426CB9:           &#59; CODE XREF: .rdata:00426C78j
.rdata:00426CB9                 &#59; .rdata:00426CA2j ...
.rdata:00426CB9         push  edi
//push the .text section base on the stack

.rdata:00426CBA         or   ebp, 0FFFFFFFFh
//EBP == 0FFFFFFFFh

.rdata:00426CBD         jmp   short loc_426CCA
.rdata:00426CBD; ---------------------------------------------------------------------------
.rdata:00426CBF         align 4
//jmp + NOP x4

.rdata:00426CC0 loc_426CC0:           &#59; CODE XREF: .rdata:00426CD1j
.rdata:00426CC0         mov   al, [esi]
//AL = first byte of the second dword

.rdata:00426CC2         inc   esi
//ESI points to next byte

.rdata:00426CC3         mov   [edi], al
//first byte in the text section now equals the first byte in the second dword

.rdata:00426CC5         inc   edi
//edi points to the second byte in the text section

.rdata:00426CC6 loc_426CC6:           &#59; CODE XREF: .rdata:00426D5Ej
.rdata:00426CC6                 &#59; .rdata:00426D75j
.rdata:00426CC6         add   ebx, ebx
//0 extension left shift in ebx when the zero flag is set, the carry flag will be cleared here when ebx is less than 0EFFFFFFFh

.rdata:00426CC8         jnz   short loc_426CD1
//condition is true if ebx is not 0

.rdata:00426CCA loc_426CCA:           &#59; CODE XREF: .rdata:00426CBDj
.rdata:00426CCA         mov   ebx, [esi]
//EBX = first dword in DWORD data

.rdata:00426CCC         sub   esi, 0FFFFFFFCh
//ESI is now 4 bytes bigger and carry flag has been set

.rdata:00426CCF         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426CD1 loc_426CD1:           &#59; CODE XREF: .rdata:00426CC8j
.rdata:00426CD1         jb   short loc_426CC0
//condition true until carry flag cleared

.rdata:00426CD3         mov   eax, 1
//EAX = 1

.rdata:00426CD8 loc_426CD8:           &#59; CODE XREF: .rdata:00426CE7j
.rdata:00426CD8                 &#59; .rdata:00426CF2j
.rdata:00426CD8         add   ebx, ebx
//0 extension left shift in ebx

.rdata:00426CDA         jnz   short loc_426CE3
//jumps if ebx is 0

.rdata:00426CDC         mov   ebx, [esi]
//if ebx is greater than 0 ( but carry flag was cleared previously ), ebx becomes the next dword in the table pointed to by esi

.rdata:00426CDE         sub   esi, 0FFFFFFFCh
//carry flag set, esi incremented 4 bytes

.rdata:00426CE1         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426CE3 loc_426CE3:           &#59; CODE XREF: .rdata:00426CDAj
.rdata:00426CE3         adc   eax, eax
//1 extension left shift in eax ( 1 becomes 3 )

.rdata:00426CE5         add   ebx, ebx
//0 extension left shift in ebx

.rdata:00426CE7         jnb   short loc_426CD8
//jump if the carry flag is not set

.rdata:00426CE9         jnz   short loc_426CF4
//jump if the carry flag is set and ebx is not zero ( ebx == 0 - 0EFFFFFFFh )
//if the carry flag is set and ebx is zero, the following code will execute

.rdata:00426CEB         mov   ebx, [esi]
//ebx becomes the next dword

.rdata:00426CED         sub   esi, 0FFFFFFFCh
//esi is incremented and carry flag is set

.rdata:00426CF0         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426CF2         jnb   short loc_426CD8
//jump if the carry flag is not set

.rdata:00426CF4 loc_426CF4:           &#59; CODE XREF: .rdata:00426CE9j
.rdata:00426CF4         xor   ecx, ecx
//ECX = 0

.rdata:00426CF6         sub   eax, 3
.rdata:00426CF9         jb   short loc_426D08
//jump if carry flag is set

.rdata:00426CFB         shl   eax, 8
//0 extension left shift in eax 8 bits

.rdata:00426CFE         mov   al, [esi]
//the cleared bits in al become the byte pointed to by esi in the data table

.rdata:00426D00         inc   esi
//esi is incremented to the next byte in the table

.rdata:00426D01         xor   eax, 0FFFFFFFFh
.rdata:00426D04         jz   short loc_426D7A
//jump if eax is zero

.rdata:00426D06         mov   ebp, eax
//EBP = EAX

.rdata:00426D08 loc_426D08:           &#59; CODE XREF: .rdata:00426CF9j
.rdata:00426D08         add   ebx, ebx
//0 extension left shift in ebx

.rdata:00426D0A         jnz   short loc_426D13
//jump if ebx is 0

.rdata:00426D0C         mov   ebx, [esi]
//ebx becomes the next dword

.rdata:00426D0E         sub   esi, 0FFFFFFFCh
//data pointer incremented by 4 and carry flag set

.rdata:00426D11         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426D13 loc_426D13:           &#59; CODE XREF: .rdata:00426D0Aj
.rdata:00426D13         adc   ecx, ecx
//if carry flag is set, 1 extension left shift in ecx, otherwise 0 extension left shift

.rdata:00426D15         add   ebx, ebx
//0 extension left shift in ebx

.rdata:00426D17         jnz   short loc_426D20
//jump if ebx is not 0

.rdata:00426D19         mov   ebx, [esi]
//ebx becomes the next dword

.rdata:00426D1B         sub   esi, 0FFFFFFFCh
//carry flag set, esi incremented 4 bytes

.rdata:00426D1E         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426D20 loc_426D20:           &#59; CODE XREF: .rdata:00426D17j
.rdata:00426D20         adc   ecx, ecx
//if carry flag is set, 1 extension left shift in ecx, otherwise 0 extension left shift

.rdata:00426D22         jnz   short loc_426D44
//jump if ecx is not zero

.rdata:00426D24         inc   ecx
//ECX += 1

.rdata:00426D25 loc_426D25:           &#59; CODE XREF: .rdata:00426D34j
.rdata:00426D25                 &#59; .rdata:00426D3Fj
.rdata:00426D25         add   ebx, ebx
//0 extension left shift in ebx

.rdata:00426D27         jnz   short loc_426D30
//jump if ebx is not zero

.rdata:00426D29         mov   ebx, [esi]
//ebx becomes the next dword

.rdata:00426D2B         sub   esi, 0FFFFFFFCh
//carry flag set, esi incremented 4 bytes

.rdata:00426D2E         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426D30 loc_426D30:           &#59; CODE XREF: .rdata:00426D27j
.rdata:00426D30         adc   ecx, ecx
//if carry flag is set, 1 extension left shift in ecx, otherwise 0 extension left shift

.rdata:00426D32         add   ebx, ebx
//0 extension left shift in ebx

.rdata:00426D34         jnb   short loc_426D25
//jump if carry flag is not set

.rdata:00426D36         jnz   short loc_426D41
//jump if carry flag is set and ebx is not 0
//the following code will be executed if the carry flag is set and ebx is 0

.rdata:00426D38         mov   ebx, [esi]
//ebx becomes the next dword

.rdata:00426D3A         sub   esi, 0FFFFFFFCh
//carry flag is set and esi is incremented 4 bytes

.rdata:00426D3D         adc   ebx, ebx
//1 extension left shift in ebx

.rdata:00426D3F         jnb   short loc_426D25
//jump is carry flag is cleared


.rdata:00426D41 loc_426D41:           &#59; CODE XREF: .rdata:00426D36j
.rdata:00426D41         add   ecx, 2

.rdata:00426D44 loc_426D44:           &#59; CODE XREF: .rdata:00426D22j
.rdata:00426D44         cmp   ebp, 0FFFFF300h
//ebp - 0FFFFF300h implied

.rdata:00426D4A         adc   ecx, 1
//if ebp is less than the compared value, ecx is incremented by 2, otherwise just 1

.rdata:00426D4D         lea   edx, [edi+ebp]
//edx becomes the the value stored in memory at edi+ebp

.rdata:00426D50         cmp   ebp, 0FFFFFFFCh
//ebp - 0FFFFFFFCh implied

.rdata:00426D53         jbe   short loc_426D64
//jump if the carry flag or zero flag is set ( if ebp is less than or equal to the operand )

.rdata:00426D55 loc_426D55:           &#59; CODE XREF: .rdata:00426D5Cj
.rdata:00426D55         mov   al, [edx]
//al becomes the byte pointed to by edx

.rdata:00426D57         inc   edx
//edx points to the next byte

.rdata:00426D58         mov   [edi], al
//value at edi becomes the value moved into al

.rdata:00426D5A         inc   edi
//edi points to next value

.rdata:00426D5B         dec   ecx
//ecx is decremented

.rdata:00426D5C         jnz   short loc_426D55
//jump if ecx is not zero

.rdata:00426D5E         jmp   loc_426CC6
//otherwise jump here

.rdata:00426D5E; ---------------------------------------------------------------------------
.rdata:00426D63         align 4
//NOP x4

.rdata:00426D64 loc_426D64:           &#59; CODE XREF: .rdata:00426D53j
.rdata:00426D64                 &#59; .rdata:00426D71j
.rdata:00426D64         mov   eax, [edx]
//eax becomes the dword pointed to by edx

.rdata:00426D66         add   edx, 4
//edx is incremented to the next dword

.rdata:00426D69         mov   [edi], eax
//the value pointed to by edi is set to the value moved into eax

.rdata:00426D6B         add   edi, 4
//edi is incremented to the next dest. dword

.rdata:00426D6E         sub   ecx, 4
//ecx is decremented by 4

.rdata:00426D71         ja   short loc_426D64
//jump if carry flag and zero flag are set

.rdata:00426D73         add   edi, ecx
//edi incremented by ecx

.rdata:00426D75         jmp   loc_426CC6
.rdata:00426D7A; ---------------------------------------------------------------------------


.rdata:00426D7A loc_426D7A:           &#59; CODE XREF: .rdata:00426D04j
.rdata:00426D7A         pop   esi
//POP

.rdata:00426D7B         mov   edi, esi
//edi becomes the popped value

.rdata:00426D7D         mov   ecx, 636h
//ecx becomes 636

.rdata:00426D82 loc_426D82:           &#59; CODE XREF: .rdata:00426D89j
.rdata:00426D82                 &#59; .rdata:00426D8Ej
.rdata:00426D82         mov   al, [edi]
//al becomes the byte pointed to by edi

.rdata:00426D84         inc   edi
//edi points to the next byte

.rdata:00426D85         sub   al, 0E8h
//al is decremented by 0E8h

.rdata:00426D87 loc_426D87:           &#59; CODE XREF: .rdata:00426DACj
.rdata:00426D87         cmp   al, 1
.rdata:00426D89         ja   short loc_426D82
//jump if al is greater than 1
//the following code is executed if al is 0 or 1

.rdata:00426D8B         cmp   byte ptr [edi], 13h
.rdata:00426D8E         jnz   short loc_426D82
//jump if the byte pointed to by edi is not equal to 13h

.rdata:00426D90         mov   eax, [edi]
//eax becomes the dword pointed to by edi

.rdata:00426D92         mov   bl, [edi+4]
//bl becomes the first byte in the next dword

.rdata:00426D95         shr   ax, 8
//0 extension right shift in ax 8 bytes

.rdata:00426D99         rol   eax, 10h
//left rotation in eax 16 bits

.rdata:00426D9C         xchg  al, ah
//al and ah are exchanged

.rdata:00426D9E         sub   eax, edi
//eax decremented by edi

.rdata:00426DA0         sub   bl, 0E8h
//bl decremented by 0E8h

.rdata:00426DA3         add   eax, esi
//eax incremented by esi

.rdata:00426DA5         mov   [edi], eax
//value pointed to by edi becomes eax

.rdata:00426DA7         add   edi, 5
//edi incremented by 5

.rdata:00426DAA         mov   eax, ebx
//eax becomes ebx

.rdata:00426DAC         loop  loc_426D87
//loop the last code ecx times

.rdata:00426DAE         lea   edi, [esi+24000h]
//edi becomes the value pointed to by esi+24000h

.rdata:00426DB4 loc_426DB4:           &#59; CODE XREF: .rdata:00426DD6j
.rdata:00426DB4         mov   eax, [edi]
//eax becomes the value pointed to by edi

.rdata:00426DB6         or   eax, eax
.rdata:00426DB8         jz   short loc_426DFF
//jump if eax is zero

.rdata:00426DBA         mov   ebx, [edi+4]
//ebx becomes dword at edi+4

.rdata:00426DBD         lea   eax, [eax+esi+26B90h]
//eax becomes the value pointed to by eax+esi+26B90h

.rdata:00426DC4         add   ebx, esi
//ebx incremented by esi

.rdata:00426DC6         push  eax
//eax pushed onto stack

.rdata:00426DC7         add   edi, 8
//edi incremented by 8

.rdata:00426DCA         call  dword ptr [esi+26C08h]
//code at esi+26C08 called

.rdata:00426DD0         xchg  eax, ebp
//eax becomes ebp, ebp becomes eax

.rdata:00426DD1 loc_426DD1:           &#59; CODE XREF: .rdata:00426DF7j
.rdata:00426DD1         mov   al, [edi]
//al becomes the byte pointed to by edi

.rdata:00426DD3         inc   edi
//edi points to the next byte

.rdata:00426DD4         or   al, al
.rdata:00426DD6         jz   short loc_426DB4
//jump if the byte is 0

.rdata:00426DD8         mov   ecx, edi
//ecx becomes edi

.rdata:00426DDA         jns   short near ptr loc_426DE2+1
//jump if the sign flag is cleared

.rdata:00426DDC         movzx  eax, word ptr [edi]
//eax becomes the word pointed to by edi

.rdata:00426DDF         inc   edi
//edi points to the next byte

.rdata:00426DE0         push  eax
//eax is pushed

.rdata:00426DE1         inc   edi
//edi points to the next byte

.rdata:00426DE2 loc_426DE2:           &#59; CODE XREF: .rdata:00426DDAj
.rdata:00426DE2         mov   ecx, 0AEF24857h
//ecx becomes this weird-ass number

.rdata:00426DE7         push  ebp
//push the base pointer onto the stack

.rdata:00426DE8         call  dword ptr [esi+26C0Ch]
//call this code

.rdata:00426DEE         or   eax, eax
.rdata:00426DF0         jz   short loc_426DF9
//jump if eax is zero

.rdata:00426DF2         mov   [ebx], eax
//the value pointed to by ebx becomes eax if it's not zero

.rdata:00426DF4         add   ebx, 4
//ebx incremented by 4 bytes

.rdata:00426DF7         jmp   short loc_426DD1

.rdata:00426DF9 loc_426DF9:           &#59; CODE XREF: .rdata:00426DF0j
.rdata:00426DF9         call  dword ptr [esi+26C10h]
//call this code.. 

.rdata:00426DFF loc_426DFF:           &#59; CODE XREF: .rdata:00426DB8j
.rdata:00426DFF         popa
.rdata:00426E00         jmp   near ptr dword_40BCB7
//popa and jump to the original entrypoint
Yeah.. that's some fun stuff. I'll be working on the unpacker.

Also, the win32 executables are packed with the same exact variant and the device drivers ( npgg9x.des and npggNT.des ) are packed with a very slightly different variant ( the last 15-20 lines of code are different ), but we don't need to unpack the drivers as they will never be loaded in the final patched version =).
jMerliN is offline  
Old 02/18/2006, 17:45   #3
 
elite*gold: 0
Join Date: Feb 2006
Posts: 1
Received Thanks: 0
Very nice. Written in a flawless and coherent way. I applaud you for your effort. By any chance, do you know how to bypass Maple Story's Gameguard? >_>
Lahe is offline  
Old 02/18/2006, 18:00   #4
 
elite*gold: 0
Join Date: Jan 2006
Posts: 4
Received Thanks: 0
I have already tried to unpack the files with Unaspacker and a number of other unpackers, and it didn't work, so if you have a good unpacker that could actually unpack those files, please post a link.
also in order for the files to work again you need to repack them, so in addition to the unpackers for each pack method you'll need the packer.
SpiritCrusha is offline  
Old 02/19/2006, 05:00   #5
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
Lahe: one bypass should be a universal bypass =)

SpiritCrusha:

I've been busy playing sro ( lol ) so I've been messing with it while I'm bored of grinding. When I get the stuff unpacked I'll update that post and move onto the next step. You can't just 'unpack' the files. They look like UPX but if you analyze them in a disassembler you can easily see they're heavily modified from UPX's traditional packing style ( UPX is open source so making a variant is very simple ).

The packer they used for this is semi-custom. It includes polymorphism and CRC checking. It also messes with TEB and PEB structures ( i'm still reversing it ). There's a bit of white noise in the code that is never reached including jumps to bogus values ( obvious use of polymorphism to prevent hacking ). No known unpacker can unpack them for several reasons. You need an unpacker that can unpack the file without executing it. Generic unpackers will usually only unpack .exe's that they can execute. gameguard.des ( you can rename it to .exe because that's what it is ) when executed will automatically end itself if it is not started by the game client ( sro_client.exe in this case ). Also, as you stated, the app CRC ( or md5, not sure yet ) checksums itself to make sure it hasn't been modified ( this is where polymorphism can be used ). If it has been modified it gives you that little message that I'm sure everyone has seen.

Basically what I'm doing is reversing the auto-unpacking code included in the UPX variant packed files ( all of gameguard's files ). It's identical in each, showing they were all packed with the same upx variant. This unpacker will unpack the files on hard-disk and allow me to see the actual code. Once I can get that far I can easily move on with cracking the CRC/MD5 checking and let me use modified gameguard files and from there a simple patch that lets you run the game of choice without gameguard. I've reversed about half of the auto-unpacking code. I'll go ahead and post it here so people can take a look at it and anyone who cares to can make their own unpacker using the reversal.
jMerliN is offline  
Old 02/19/2006, 17:43   #6
 
elite*gold: 0
Join Date: Jan 2006
Posts: 4
Received Thanks: 0
I think I lost you at the second paragraph, My C level is only highschool level (I'm leraning it in highschool obviously) and I have learned some Java as well, and I know how polymorphism applies there(down/up casting), but I have no idea what polymorphism means in context of what you said, and my assembler knowhow is very basic, (too lazy to read tutorials), so can you explain in short the logic behind that algorithm? I would appreciate it.
SpiritCrusha is offline  
Old 02/19/2006, 19:22   #7
 
elite*gold: 0
Join Date: Jul 2005
Posts: 149
Received Thanks: 1
jMerlin u got my first karma that i ever gave Keep working on this! I wish i can help but im too dum lol
grishathebest is offline  
Old 02/21/2006, 10:38   #8
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
Well I was bored tonight and as I've been reversing around I've realized that yeah, they used UPX but they used a custom loader ( read into UPX's documentation to learn what those are ) and they corrupted the UPX pack header and changed the names of the sections to fool any would-be crackers.

Basically what I decided was that reading the UPX pack header and trying to repair it then renaming the sections so UPX would unpack it is a big hassle. I may do it in the future, however, to yeild a perfect unpack, but for the needs and the sake of a bypass to gameguard, there's really no need at all. Another idea ( which is a simple idea to a generic UPX unpacker ) is to make a simple program which will do the following ( this is my idea, and is what I will most likely do for myself to make a simple UPX unpacker that will unpack even corrupted UPX packed files ). Simply put, this is the same exact algorithm anyone would use by-hand to unpack a UPX packed file.

1. Because UPX decompresses the data into the first section before executing the OEP, you must wait for the decompressing loader to finish it's job before you can proceed to dump any useable code from this section.

2. You must reset the OEP once dumping the filled section with unpacked data.

3. Because UPX decompresses all sections into the same final section ( the win32 subsystem doesn't give a shit about sections, it just follows the code and as long as the code references these sections correctly who's the wiser ) you must then distinguish them ( imports/exports, data, rdata, etc.. with exception to relocs [ if file base address is less than 400000 ] and rsrc ) and add fields in the files PE to account for them.

4. You must repair the relocs / imports / etc so the executable runs correctly after the unpacking. This step can be omitted if the file will not be executed but simply studied.

5. You must remove both the loader stub and the packed data stub and remove their information from the PE header to complete the unpacking.

The result is a 100% unpacked file. This is exactly what UPX does ( read the source ) and because it's well-documented, unpacking it perfectly using code would require minimal effort ( since the code is provided.. a modified unpack function would suffice for this task ).

The concept I have is to simply load the executable in question into memory. The addresses in the loader stub will then be reset to point to the correct sections in memory ( the data section, the pack header, the destination or code / UPX0 section ) and then executed until it jmps into the new code section following a popad ( this is the OEP ), on which case the PE and subsequent sections will be rebuilt, the UPX loader and packed data sections will be removed and the OEP modified to suit the new load address, and the resulting file will be saved to u<filename>.<fileext> on the harddrive. This will yeild a 100% perfectly unpacked file on even protected/hacked/modified UPX files such as the gameguard ones.

I am impatient to say the least and because of this I have opted to unpack the file(s) and THEN make an application to create perfect unpacks. Because I choose this method, the unpacked files may be unstable and may not run correctly but contain all viable code intact ( which makes them perfect candidates for study ). When I get around to making this unpacking app, it will be posted here, source and all. For the time being let me tell you exactly how I unpacked these files ( note this method only works for executable files.. a modified approach must be taken to dump .dll files ):

First you need these programs:OllyDbg, OllyDmp ( a plugin for OllyDbg, google it ), and ImpREC

Once you have these you can unpack virtually any file ( lol ).

Starting off, we'll unpack gameguard.des ( this is the only file I'll walk you through ). Firstly copy gameguard.des to the folder you're using as your unpacking folder as to not interfere with the original file. Rename gameguard.des to gameguard.exe. Now open OllyDbg and drag gameguard.exe into it. The exe will load and halt at the EP, giving you a pre-emptive edge. You want to get the UPX loader stub ( that's the code I reversed above ) to fill the .text section of the gameguard file. To do so ( from code to imports.. and UPX does it in that order, imports last before jumping into the original code, the calls you see are to kernel functions such as GetProcAddress which will fill the IAT etc ), you need to get OllyDbg to breakpoint before it takes the final jmp. Scroll down until you see a 'popad' followed by a 'jmp gameguar.<some number>'. You need to put a HARDWARE BREAKPOINT here on execution ( right click on the jmp and go down to breakpoint ). Now that the breakpoint is set, we need to run the program, so click the blue right-facing triangle in the toolbar. Oops . The program generated an exception.. wtf.. not good. Hold shift and press F7, F8, and then F9. You'll see in red letters at the bottom right that the application terminated ( before the loading process even finished ). I want to give you a little lesson in why reversing protected loaders like this is essential to QUICKLY identifying and fixing a problem.

Normally if you were to just load up this exe and try this method ( which is the de-facto cracking method to breaking simple packers like UPX ) it would work great. If this packer was reinforced with protection like this, you would get a termination here. What you'd have to do then is find out WHY, and you'd trace the code piece by piece to find out why it faulted. I'll go ahead and tell you why it faulted. If you read up in the reversed code, near the top there's what I said was debugger detection code. I showed that there was a 'popad' statement that was ONLY CALLED IF A DEBUGGER WAS FOUND. Well guess what boys & girls, we're running a debugger. A debugger WAS found, and thus that popad was taken. This reset all of the registers ( thus ESI didn't point to the data anymore ) and when the mov statement was reached an exception was encountered. This was handled by simply terminating the process ( the default exception handling provided by the win32 subsystem loader ). This is a very VERY simple debugger protection system designed to stop NOOBS ( like most of you ) from getting a peek at the real code by preventing 1 byte from being unpacked if a debugger is loaded.

Now that you know this, repeat the steps up to the clicking the right-facing blue arrow again ( you do not need to repeat the setting of the hardware breakpoint.. it will stay in the debug registers stored in the system's context ). This time, instead of hitting the blue arrow, scroll up to the code that I show is debugger detection code in the semi-reversal. We're going to NOP out the culprit ( a common hack method of bypassing protection.. quick, dirty, and 100% effective .. just like we like it ). See that 'test eax,eax' statement? Double-click the jnz statement after it and make sure the checkbox next to "Fill with NOPs" is checked and type "NOP" in the drop box and hit Assemble. This will place 2 NOP operations in the jnz's place. Now hit the blue right-facing arrow and viola, the application pauses at our breakpoint. Congratz on your first protection crack boys & girls.

What you'll want to do ( I assume you installed OllyDmp before doing this.. ) is to hit 'F7' which will take the jump and poof we're at the OEP. Go to plugins->OllyDmp and click dump debugged process. Click 'Get EIP as OEP' and hit 'Dump'. Save the file as 'ugameguard.exe' and close OllyDbg. Run it through ImpREC and you're finished.

There you go, dumped gameguard.des file. Have fun people. The next section will be started soon, cracking the checksums to use modified files & then the actual patching GameGuard to run without the protection. If anyone has any comments or questions go ahead and ask. The perfect unpacker will be posted here when I get around do making it =).
jMerliN is offline  
Old 02/21/2006, 11:07   #9
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
And the images / final executable / tutorial:
jMerliN is offline  
Old 03/04/2006, 00:11   #10
 
elite*gold: 0
Join Date: Aug 2005
Posts: 27
Received Thanks: 0
Kudos to you for getting on top of kicking gameguard in the ***. I am not a cracker but I am a software developer and I have written some kick *** bots for CO and most recently SRO. I had just implimented my newest feature of other player avoidance and intelligent hunting via the radar mini map when they did the 2nd beta. Imagine my annoyance when my bot quit working. I like SRO but ill be damned if im gonna sit there and mindlessly kill 600 chakji warriors for a quest.

My bot completed that task in about 10 hours for me

I never gave any of my bots to anyone but my good friends and never released them to a board. However if you are successful in killing gameguard or can help me figure out how to get my bot working again Ill release it on this board.


My bot
1) AutoHunts
2) AutoPickups
3) Doesn't act like a bot like some of the other SRO bots ive seen
4) Can be scripted
5) Fights with random skill usage based on user defined thresholds
6) Auto Pots based on user defined thresholds ' Although not useful these days
7) Avoids other players based on mini map
8) Homes in on mobs base on mini map
9) Auto disconnects on durability for any item
10) Auto Revives
11) Can page you via smtp (i carry a pager for my bots lol) or Msg you via netbios
12) Auto Joins teams or avoids teams based on User defined thresholds
13) Any a few other honka honka awesome features.

Help me help the community, Death to gameguard!
shihanshin is offline  
Old 03/06/2006, 03:50   #11
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
Gameguard is no longer on SRO so there's no need =).
jMerliN is offline  
Old 03/06/2006, 07:08   #12
 
elite*gold: 0
Join Date: Mar 2006
Posts: 25
Received Thanks: 0
lol owned
simon4 is offline  
Old 03/06/2006, 10:50   #13
 
elite*gold: 0
Join Date: Jul 2005
Posts: 639
Received Thanks: 43
Quote:
Originally posted by jMerliN@Mar 6 2006, 03:50
Gameguard is no longer on SRO so there's no need =).
Its only temporary. You know this dont you? Dont let it halt your work.
Matt.dk is offline  
Old 03/07/2006, 07:08   #14
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
Quote:
Originally posted by Matt.dk+Mar 6 2006, 03:50--></span><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td>QUOTE (Matt.dk @ Mar 6 2006, 03:50)</td></tr><tr><td id='QUOTE'> <!--QuoteBegin--jMerliN@Mar 6 2006, 03:50
Gameguard is no longer on SRO so there's no need =).
Its only temporary. You know this dont you? Dont let it halt your work. [/b][/quote]
It's permenant, kSRO doesn't even use gameguard anymore. They figured botters will always find a way around it so they don't even bother. Plus, they allow the use of "autopotters" in korea but don't really punish if you use a hunting/leveling bot. Gameguard interferes with these autopotters and so they just don't use it anymore :&#092;.

Even if they do, in this latest patch the client is completely and totally naked, debug mode, and not packed with ASProtect or protected via gamegaurd which means I have the core ASM code here along with all netcode & packet information which means I can get offsets in the client if it DOES go back to gameguard and reference them to the code I have now to break encryption on packets ( if there is any ) and to make a more thorough packet bot.
jMerliN is offline  
Old 03/07/2006, 07:49   #15
 
elite*gold: 0
Join Date: Jun 2005
Posts: 99
Received Thanks: 0
Maybe I shouldn't keep jinxing myself =).

Soon as I made that post they patched gg back in -_-.

However, I did save the sro_client.exe =).
jMerliN is offline  
Reply


Similar Threads Similar Threads
SO.. there is no gameguard bypass? (i need old gameguard files)
07/28/2011 - Cabal Online - 16 Replies
i been reading around about how to bypass gameguard, it seems that emulating the http server is the best way, anyone have a copy of old cabal? i need gameguard.des and gameguard/ folder.
WTS SEG +9 [SS Inside] SIZ
09/07/2010 - Dekaron Trading - 5 Replies
Glove http://img831.imageshack.us/img831/1378/glove.jpg Pants http://img819.imageshack.us/img819/6958/pantsvx.j pg Boots http://img255.imageshack.us/img255/4936/bootsc.jp g Armor
Need help ( see pic inside )
02/10/2009 - SRO Private Server - 6 Replies
http://img152.imageshack.us/my.php?image=42739867l q2.png help =o http://img152.imageshack.us/my.php?image=42739867 lq2.png
GameGuard make a Problem/Gameguard macht probleme
07/21/2008 - Flyff - 9 Replies
Bin nicht der einzigste, der das problem hat, aber wenn ich Flyff starte kommt folgendes: Game guard update was not done. Scan the virus or make some changes in your pc magament programm. Weiß zufällig wer, was ich da machen kann ? Kann man den irgendwie überspringen oder so ? Am besten was legales ;) Hoffe auf schnelle Antwort. ------



All times are GMT +2. The time now is 04:25.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.