This small overview describes reading of unhandled RO client exceptions (also known as 'Gravity Error'). You are required to have certain knowledge of the Assembly language and be able to work with a debugger (for example OllyDbg, which will be used in this overview). You should have some knowledge of the structure and terms related to the Portable Executable format. Before you continue reading, read the disclaimer first. If you find a mistake or have a suggestion, please post it in the bbs.
When you work with RO exceptions, it is the best, to view them with a fixed-width font, inside a text editor. If you post it in a board, put it into [code] tags, because they make it more readable.
Module Name: C:\PATH\TO\YOUR\RO\091013RE.EXE Time Stamp: 0x4ad4401b - Tue Oct 13 10:53:47 2009 Exception Type: 0xc0000005 0x0042553b 091013RE.EXE 0x004364cc 091013RE.EXE 0x00449374 091013RE.EXE 0x0047bc23 091013RE.EXE 0x004e5460 091013RE.EXE 0x004f5b9c 091013RE.EXE 0x005f086f 091013RE.EXE 0x005efd89 091013RE.EXE 0x00517524 091013RE.EXE 0x006e22d0 091013RE.EXE 0x006f6b4c 091013RE.EXE 0xbff8b560 KERNEL32.DLL 0xbff8b412 KERNEL32.DLL 0xbff89dd5 KERNEL32.DLL 0x22220000 eax: 0x00000000 ebx: 0x00000000 ecx: 0x00000000 edx: 0x00000012 esi: 0x00000012 edi: 0x00a9f7e8 ebp: 0x00a9f714 esp: 0x00a9f710 stack 00a9f710 - 00a9fb10 00A9F710 : 80 1B E8 03 24 F7 A9 00 CC 64 43 00 12 00 00 00 00A9F720 : 02 00 00 00 68 F7 A9 00 74 93 44 00 12 00 00 00 00A9F730 : 02 00 00 00 54 F7 A9 00 50 F7 A9 00 4C F7 A9 00 00A9F740 : B0 08 E8 03 00 00 00 00 80 1B E8 03 E8 F7 A9 00 00A9F750 : B0 08 E8 03 58 1C 6F 00 9C 00 00 00 3C F8 A9 00 00A9F760 : 68 6A 70 00 00 00 00 00 48 F8 A9 00 23 BC 47 00 00A9F770 : 78 00 00 00 B0 08 E8 03 18 01 00 00 00 00 00 00 00A9F780 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A9F790 : 00 00 00 00 00 00 00 00 00 00 00 00 00 08 E8 03 00A9F7A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 08 E8 03 00A9F7B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 3A 40 00 00A9F7C0 : 00 00 00 00 00 00 00 00 00 00 00 00 40 60 74 00 00A9F7D0 : 48 60 74 00 54 60 74 00 14 60 74 00 04 60 74 00 00A9F7E0 : F4 5F 74 00 BD 00 00 00 60 00 00 00 EA 00 00 00 00A9F7F0 : 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A9F800 : 00 00 00 00 79 00 00 00 7A 00 00 00 00 00 00 00 Launch Info 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 Job : Novice
Module Name: C:\PATH\TO\YOUR\RO\091013RE.EXE
This line shows you, where the affected client is located and how it is called. It aids finding the issue, because certain paths can have restrictions on certain operating systems. It can also give you certain clue, if the client was renamed for whatever reason.
Time Stamp: 0x4ad4401b - Tue Oct 13 10:53:47 2009
This line represents the time and date, when the client was built (linked). It is not the last modification or creation date of the client. This information is hard-coded into the client and helps to find out, what client version this is supposed to be. The first part (0x4ad4401b) is the raw representation of the time-stamp in seconds since 1.1.1970 00:00:00 UTC (Unix time-stamp), the second part (Tue Oct 13 10:53:47 2009) is the human-readable representation of the time-stamp. In this case, it indicates the use of 2009-10-13RagexeRE client. Since there are sometimes multiple clients with the same date, you have to check the exact time-stamp of the client. To see the time-stamp you have to load the client into a PE editor/analyser; LordPE and PEiD are capable of displaying those for example. Note, that the time stamp can be easily changed, so do not depend on it too much, when the executable is encrypted or otherwise protected.
Exception Type: 0xc0000005
This line indicates, what actually went wrong with the client. The most common exception is, like in this example, 0xc0000005 (EXCEPTION_ACCESS_VIOLATION), which means, that the client attempted to read from, write to or execute an invalid memory position (for example accessing members of a NULL pointer) or a memory location, which is not enabled for such access (for example writing in executable-only memory). Execution attempts (ex. malformed JMPs) are usually caught by the Data Execution Prevention in recent operating systems. All other exception codes can be looked up in winbase.h (if you have Windows SDK installed) and/or google for 'exception <exception code>' to get more information about the exception.
0x0042553b 091013RE.EXE 0x004364cc 091013RE.EXE 0x00449374 091013RE.EXE 0x0047bc23 091013RE.EXE 0x004e5460 091013RE.EXE 0x004f5b9c 091013RE.EXE 0x005f086f 091013RE.EXE 0x005efd89 091013RE.EXE 0x00517524 091013RE.EXE 0x006e22d0 091013RE.EXE 0x006f6b4c 091013RE.EXE 0xbff8b560 KERNEL32.DLL 0xbff8b412 KERNEL32.DLL 0xbff89dd5 KERNEL32.DLL 0x22220000
This block is the call stack, which shows the path from the execution begin down (actually 'up' in this representation) to the function where the exception took place. The top-most entry is where the exception occurred, the last entry before KERNEL32.DLL or NTDLL.DLL is the first call after the module entry point of the module, or thread entry point in case of additional threads. If there is no module name next to the address, it means the address is bogus. If there is no KERNEL32.DLL or NTDLL.DLL module listed or no module names at all, the stack was most probably corrupt. You can locate the addresses by simply jumping inside your debugger to given offset.
eax: 0x00000000 ebx: 0x00000000 ecx: 0x00000000 edx: 0x00000012 esi: 0x00000012 edi: 0x00a9f7e8 ebp: 0x00a9f714 esp: 0x00a9f710
This block lists the processor register state at the point of the exception. When you have located the point, where the exception occurred, they help to figure out, what the client attempted to do. Here the client attempted to read from memory from position 0x00000114, which is obviously invalid (NULL pointer access):
MOV EAX,DWORD PTR DS:[ECX+114] ; ECX = 0x00000000Since there is no further clue in the current function, how ECX became 0, you have to go back in the call stack.
stack 00a9f710 - 00a9fb10 00A9F710 : 80 1B E8 03 24 F7 A9 00 CC 64 43 00 12 00 00 00 00A9F720 : 02 00 00 00 68 F7 A9 00 74 93 44 00 12 00 00 00 00A9F730 : 02 00 00 00 54 F7 A9 00 50 F7 A9 00 4C F7 A9 00 00A9F740 : B0 08 E8 03 00 00 00 00 80 1B E8 03 E8 F7 A9 00 00A9F750 : B0 08 E8 03 58 1C 6F 00 9C 00 00 00 3C F8 A9 00 00A9F760 : 68 6A 70 00 00 00 00 00 48 F8 A9 00 23 BC 47 00 00A9F770 : 78 00 00 00 B0 08 E8 03 18 01 00 00 00 00 00 00 00A9F780 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A9F790 : 00 00 00 00 00 00 00 00 00 00 00 00 00 08 E8 03 00A9F7A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 08 E8 03 00A9F7B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 3A 40 00 00A9F7C0 : 00 00 00 00 00 00 00 00 00 00 00 00 40 60 74 00 00A9F7D0 : 48 60 74 00 54 60 74 00 14 60 74 00 04 60 74 00 00A9F7E0 : F4 5F 74 00 BD 00 00 00 60 00 00 00 EA 00 00 00 00A9F7F0 : 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00A9F800 : 00 00 00 00 79 00 00 00 7A 00 00 00 00 00 00 00
This block represents the stack at the point of the exception, with the top most line being the stack top. The contents are usually return addresses and function parameters. Typically you are not required to use this.
Launch Info 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
This block is a history of recently displayed visual effects (g_recentEffectId), starting with the most recent effect id. Each block of 4 digits represents one effect id. Typically you are not required to use this.
Job : Novice
This line indicates the last selected character job class. If the exception occurs before selecting a character, the value is, like in this case 'Novice'.
As seen in registers, the cause is not obvious after examining the function (CBitmapRes::GetColor), where the exception occured. When you examine the caller function (CSkinMgr::GetColorChipColor), you find out, that ECX is set to a return value of a function (CResMgr::Get) called before the function call, where the exception occurs. Digging in that function further gives you the clue, that the function does something with files, so you can bet on missing (or corrupt) files. In this case, you receive an error message right before the exception occurs, stating:
ResourceError : Can't find file À¯ÀúÀÎÅÍÆäÀ̽º\colorchip.bmpThese messages are almost always shown, if the exception is file related, so if you ever run into such problem, but are not the one, who experienced it, ask for the presence of this message; it will make debuggung easier. Note, that all the function names in this document can be found inside the 'Highpriest' client found on kRO FTP, because it includes debugging symbols. When you are able to match the code position in both clients, the function labels will help you figure out, what a function in question is for.
As of kRO 2011-08-23aRagexeRE and 2011-08-31aRagexe the client supports the in-game command /buildinfo
that reports the client's build date, version and serial number:
build : Jul 2 2012 - 17:48:44 ver : 14.2.9 s/n : G3RX8UT-Z7EWZAS-TFXCLRK-T3YH8UT-5KHQDN8
Thanks to evilpuncker for making aware of this command.
This document is supposed to serve for general educational purposes and is provided AS IS, without warranty of ANY KIND, either expressed or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. The author cannot be made liable for actions, that can arise from the direct or indirect use of this document, including but not limited to modifications of the RO client or running private RO servers. The author cannot be made liable for ANY KIND of damages on software or hardware, that may arise from, including but not limited to use of this document, the mentioned software or websites contents this document links to.