← Back to DevelopmentAging & Mixing viewer.dll generatorProgramsClan filesInternet Information ServiceOllyDbg tutorialsMiscellaneousSkinsLinks / Files

level_up_fix

← Back to Miscellaneous
If you have added levels to your experience table (and I mean added it correctly: correct pointers, correct checksums), you might have noticed that after a certain level, the character just refuses to level up unless you relog.

That's because of a comparison made with your level in the client. If the level isn't too high, the character will level up, otherwise it wont.
It's right here:

OllyDbg - Client side

00447F5E  |> \83FE 78       CMP ESI,78


0x78 is equal to 120. So we just need to increase the value and problem solved right ?

Well not really. If you look the comparison instruction code, it's 83.
I don't know how all of this really works, but apparently, a comparison code of 83 expects a 8bit signed constant.
That's where the problem is : a signed 8 bit value can go from -127 to +127. If we compare the level to, let's say 149 (= 0x95), it will actually compare it to -107 (don't ask me why, that's how it works :P).

In order to solve our problem, we need to use the comparison instruction code 81. The problem is that this instruction needs more space than 83. It requires 3 more bytes.
We could use a jump and relocate the whole procedure further in the program. But we can also use one dirty hack.

Here's the code after the CMP instruction :

OllyDbg - Client side

00447F5E     \83FE 78       CMP ESI,78
00447F61  |.  7D 7D         JGE SHORT 00447FE0
00447F63  |.  E8 D899FFFF   CALL 00441940
00447F68  |.  8B0D B8105F00 MOV ECX,DWORD PTR DS:[5F10B8]
00447F6E  |.  3BC8          CMP ECX,EAX
00447F70  |.  75 6E         JNE SHORT 00447FE0
00447F72  |.  A1 BC105F00   MOV EAX,DWORD PTR DS:[5F10BC]
00447F77  |.  3BC2          CMP EAX,EDX
00447F79  |.  75 65         JNE SHORT 00447FE0
00447F7B  |.  8D4E 01       LEA ECX,[ESI+1]
00447F7E  |.  898D 44390000 MOV DWORD PTR SS:[EBP+3944],ECX
00447F84  |.  8B14F5 F80C5F MOV EDX,DWORD PTR DS:[ESI*8+5F0CF8]
00447F8B  |.  A1 28AE8E00   MOV EAX,DWORD PTR DS:[8EAE28]
00447F90  |.  8990 CC390000 MOV DWORD PTR DS:[EAX+39CC],EDX
00447F96  |.  A1 28AE8E00   MOV EAX,DWORD PTR DS:[8EAE28]
00447F9B  |.  8B88 54010000 MOV ECX,DWORD PTR DS:[EAX+154]
00447FA1  |.  8B90 50010000 MOV EDX,DWORD PTR DS:[EAX+150]
00447FA7  |.  8B80 4C010000 MOV EAX,DWORD PTR DS:[EAX+14C]
00447FAD  |.  6A 01         PUSH 1                                   ; /Arg5 = 1
00447FAF  |.  68 2C010000   PUSH 12C                                 ; |Arg4 = 12C
00447FB4  |.  51            PUSH ECX                                 ; |Arg3
00447FB5  |.  81C2 00200000 ADD EDX,2000                             ; |
00447FBB  |.  52            PUSH EDX                                 ; |Arg2
00447FBC  |.  50            PUSH EAX                                 ; |Arg1
00447FBD  |.  E8 3EFA0B00   CALL 00507A00                            ; \1873_quantumfusion_local.00507A00
00447FC2  |.  68 90010000   PUSH 190                                 ; /Arg2 = 190
00447FC7  |.  6A 07         PUSH 7                                   ; |Arg1 = 7
00447FC9  |.  E8 F2650900   CALL 004DE5C0                            ; \1873_quantumfusion_local.004DE5C0
00447FCE  |.  83C4 1C       ADD ESP,1C
00447FD1  |.  E8 8ABCFFFF   CALL 00443C60                            ; [1873_quantumfusion_local.00443C60
00447FD6  |.  E8 65B71000   CALL 00553740                            ; [1873_quantumfusion_local.00553740
00447FDB  |.  E8 A0051100   CALL 00558580                            ; [1873_quantumfusion_local.00558580
00447FE0  |>  5E            POP ESI
00447FE1  |.  5D            POP EBP
00447FE2  |.  5F            POP EDI
00447FE3  |.  B8 01000000   MOV EAX,1
00447FE8  |.  5B            POP EBX
00447FE9  \.  C3            RETN
00447FEA      90            NOP
00447FEB      90            NOP
00447FEC      90            NOP
00447FED      90            NOP
00447FEE      90            NOP
00447FEF      90            NOP


As you can see, there's a few NOPs at the end before the next procedure. We could simply shift the code after the CMP instruction from 3 bytes. And the new CMP would fit.
In order to do that, you just need to select the code after the CMP and binary copy it :

01.jpg

After that we need to clean up a bit after the CMP to be able to select precisely. Select the JMP and the CALL instructions and fill it with NOPs.

02.jpg

Now make a new selection from 3 NOPs after the CMP to 3 NOPs after the RETN, and binary paste :

03.jpg

The code has been shifted, but it's not over yet.

04.jpg

When you moved the code, OllyDbg reajusted (did +3) the JMP addresses, which is cool, because the jumps will be made at the correct address.
But also did that for the call addresses...

OllyDbg - Client side

00447FC0      E8 3EFA0B00   CALL 00507A03
00447FC5      68 90010000   PUSH 190
00447FCA      6A 07         PUSH 7
00447FCC      E8 F2650900   CALL 004DE5C3
00447FD1      83C4 1C       ADD ESP,1C
00447FD4      E8 8ABCFFFF   CALL 00443C63
00447FD9      E8 65B71000   CALL 00553743
00447FDE      E8 A0051100   CALL 00558583


We need to remove 3 to each call if we don't want it to call an inapproriate address.

OllyDbg - Client side

00447FC0  |.  E8 3BFA0B00   CALL 00507A00
00447FC5  |.  68 90010000   PUSH 190
00447FCA  |.  6A 07         PUSH 7
00447FCC  |.  E8 EF650900   CALL 004DE5C0
00447FD1  |.  83C4 1C       ADD ESP,1C
00447FD4  |.  E8 87BCFFFF   CALL 00443C60
00447FD9  |.  E8 62B71000   CALL 00553740
00447FDE  |.  E8 9D051100   CALL 00558580


Also there's a few jumps before the CMP instruction that need to be readjusted. It's the ones that jump to 00447FE0.

OllyDbg - Client side

00447F3C  |. /0F8C 9E000000 JL 00447FE0
00447F42  |. |7F 08         JG SHORT 00447F4C
00447F44  |. |85C9          TEST ECX,ECX
00447F46  |. |0F82 94000000 JB 00447FE0
00447F4C  |> |3BF8          CMP EDI,EAX
00447F4E  |. |0F8C 8C000000 JL 00447FE0
00447F54  |. |7F 08         JG SHORT 00447F5E
00447F56  |. |3BD9          CMP EBX,ECX
00447F58  |. |0F82 82000000 JB 00447FE0


The new address is 00447FE3

OllyDbg - Client side

00447F3C  |. /0F8C A1000000 JL 00447FE3
00447F42  |. |7F 08         JG SHORT 00447F4C
00447F44  |. |85C9          TEST ECX,ECX
00447F46  |. |0F82 97000000 JB 00447FE3
00447F4C  |> |3BF8          CMP EDI,EAX
00447F4E  |. |0F8C 8F000000 JL 00447FE3
00447F54  |. |7F 08         JG SHORT 00447F5E
00447F56  |. |3BD9          CMP EBX,ECX
00447F58  |. |0F82 85000000 JB 00447FE3


Now we finally have enough space to convert our comparison.

OllyDbg - Client side

00447F5E     \83FE 78       CMP ESI,78
00447F61      90            NOP
00447F62      90            NOP
00447F63      90            NOP


Let's change the max value to 0x95 (= 149).

OllyDbg - Client side

00447F5E     \81FE 95000000 CMP ESI,95


And here's the complete portion of working code :

OllyDbg - Client side

00447F3C  |. /0F8C A1000000 JL 00447FE3
00447F42  |. |7F 08         JG SHORT 00447F4C
00447F44  |. |85C9          TEST ECX,ECX
00447F46  |. |0F82 97000000 JB 00447FE3
00447F4C  |> |3BF8          CMP EDI,EAX
00447F4E  |. |0F8C 8F000000 JL 00447FE3
00447F54  |. |7F 08         JG SHORT 00447F5E
00447F56  |. |3BD9          CMP EBX,ECX
00447F58  |. |0F82 85000000 JB 00447FE3
00447F5E  |> |81FE 95000000 CMP ESI,95
00447F64  |. |7D 7D         JGE SHORT 00447FE3
00447F66  |. |E8 D599FFFF   CALL 00441940
00447F6B      8B0D B8105F00 MOV ECX,DWORD PTR DS:[5F10B8]
00447F71      3BC8          CMP ECX,EAX
00447F73      75 6E         JNE SHORT 00447FE3
00447F75      A1 BC105F00   MOV EAX,DWORD PTR DS:[5F10BC]
00447F7A  |. |3BC2          CMP EAX,EDX
00447F7C  |. |75 65         JNE SHORT 00447FE3
00447F7E  |. |8D4E 01       LEA ECX,[ESI+1]
00447F81  |. |898D 44390000 MOV DWORD PTR SS:[EBP+3944],ECX
00447F87      8B14F5 F80C5F MOV EDX,DWORD PTR DS:[ESI*8+5F0CF8]
00447F8E  |. |A1 28AE8E00   MOV EAX,DWORD PTR DS:[8EAE28]
00447F93  |. |8990 CC390000 MOV DWORD PTR DS:[EAX+39CC],EDX
00447F99  |. |A1 28AE8E00   MOV EAX,DWORD PTR DS:[8EAE28]
00447F9E  |. |8B88 54010000 MOV ECX,DWORD PTR DS:[EAX+154]
00447FA4  |. |8B90 50010000 MOV EDX,DWORD PTR DS:[EAX+150]
00447FAA  |. |8B80 4C010000 MOV EAX,DWORD PTR DS:[EAX+14C]
00447FB0  |. |6A 01         PUSH 1                                   ; /Arg5 = 1
00447FB2  |. |68 2C010000   PUSH 12C                                 ; |Arg4 = 12C
00447FB7  |. |51            PUSH ECX                                 ; |Arg3
00447FB8  |. |81C2 00200000 ADD EDX,2000                             ; |
00447FBE  |. |52            PUSH EDX                                 ; |Arg2
00447FBF  |. |50            PUSH EAX                                 ; |Arg1
00447FC0  |. |E8 3BFA0B00   CALL 00507A00                            ; \xxxxxx.00507A00
00447FC5  |. |68 90010000   PUSH 190                                 ; /Arg2 = 190
00447FCA  |. |6A 07         PUSH 7                                   ; |Arg1 = 7
00447FCC  |. |E8 EF650900   CALL 004DE5C0                            ; \xxxxxx.004DE5C0
00447FD1  |. |83C4 1C       ADD ESP,1C
00447FD4  |. |E8 87BCFFFF   CALL 00443C60                            ; [xxxxxx.00443C60
00447FD9  |. |E8 62B71000   CALL 00553740                            ; [xxxxxx.00553740
00447FDE  |. |E8 9D051100   CALL 00558580                            ; [xxxxxx.00558580
00447FE3  |> \5E            POP ESI
00447FE4  |.  5D            POP EBP
00447FE5  |.  5F            POP EDI
00447FE6  |.  B8 01000000   MOV EAX,1
00447FEB  |.  5B            POP EBX
00447FEC  \.  C3            RETN