Twisted 发表于 2011-10-16 09:05:26

[1.298] Add a logged in check to game server packets

So... a hack was released that made a highlight of a very important Ebenezer flaw.
Basically, it was able to send GM commands through the chat packet - without having to even be logged in.

But how does the exploit actually work?

Well...
As the hack doesn't login, the character also hasn't been selected, and well, the character's Authority hasn't been set in Ebenezer.
This means that the Authority stays as it is - 0. We all should know that the 0 Authority indicates that a user is a Game Master!

So, because of this, when the hack sends the chat packet, Ebenezer goes "hey, they have the Authority 0 - that means I can pass it on to my dear friend CEbenezerDlg::OperationMessage, where they'll (hopefully!) handle it with care". CEbenezerDlg::OperationMessage then handles the command itself, and does whatever it needs to do.

With that said, the question then is how do we fix the problem?

Quite simply, we need to set the default Authority to something other than 0. I use 1, but you could also use 2 (muted) or 255 (banned). Either way, they don't have access to execute any GM commands.

Now, another big flaw is that Ebenezer does not at all check if a user is logged in throughout the many packet handlers it has.
This means that if you send a packet to Ebenezer, if you are logged in or not, it will heed the request, and carry it out (depending on the packet) - even though you're not actually logged in!

This is just a problem waiting to happen - if we checked to see if the user was logged in before going ahead with handling packets (that is, all except the first two - version & login request), the Authority issue for one would be nearly completely removed. The released hack would not work any longer, however if you hooked the client's send function and sent the GM command/s at the character selection screen, the hack would still be effective, as the login check would say you've logged in - but the Authority has yet to be set (it is set when you select a character).

So, instead of doing one or the other, I have combined the two into one relatively large-sized patch which I really have to thank mgame for.
I suppose you could say this patch also patches the kill-switch exploit... I decided to use the kill-switch's check (before the packet handler), and also its function for my code-cave.

Well, here's the patch - each line is commented, so you know what's going on).

; Above the packet handler00490995   . E9 16400300      JMP Ebenezer.004C49B0; Replace the kill-switch checks with a jump to our code-cave
0049099A         90                      NOP; Rest of it is nopped out.
0049099B         90                      NOP
0049099C         90                      NOP
0049099D         90                      NOP
0049099E         90                      NOP
0049099F         90                      NOP
004909A0         90                      NOP
004909A1         90                      NOP
004909A2         90                      NOP
004909A3         90                      NOP

; In our code-cave
004C49B0   > 83FA 2B            CMP EDX,2B                                                      ;Check for version packet
004C49B3   . 74 17                JE SHORT Ebenezer.004C49CC                      ;If version packet, jump back to switch (no account ID set yet)
004C49B5   . 83FA 01            CMP EDX,1                                                          ;Check for login packet
004C49B8         74 17            JE SHORT Ebenezer.004C49D1                      ;If login packet, set the Authority to 1 and jump back to switch (it's set in this packet's handler)
004C49BA   . 52                  PUSH EDX                                                               ;Push EDX/opcode onto the stack
004C49BB   . 8A96 9C800000MOV DL,BYTE PTR DS:                  ;Store first byte of account name in DL
004C49C1   . 80FA 00            CMP DL,0                                                                ;Compare first byte of account name to 0x00/NULL
004C49C4   . 5A                  POP EDX                                                               ;Pop EDX/opcode off the stack
004C49C5   . 75 05                JNZ SHORT Ebenezer.004C49CC                  ;Byte isn't NULL, jump to packet handler!
004C49C7   . BA FFFFFFFF      MOV EDX,-1                                                      ;Byte is NULL, set the opcode to -1 (so it's not handled)
004C49CC   >^E9 D3BFFCFF      JMP Ebenezer.004909A4                              ;Back to the packet handler we go!
004C49D1         50                      PUSH EAX                                                               ;Push EAX (used in the CUser::Parsing func we jumped from for something ) onto the stack
004C49D2         8B86 98800000MOV EAX,DWORD PTR DS:          ;Store the pointer to the user's struct in eax
004C49D8         C640 71 01      MOV BYTE PTR DS:,1                     ;Set the user's Authority to 1
004C49DC         58                      POP EAX                                                               ;Pop eax off the stack
004C49DD      ^EB ED            JMP SHORT Ebenezer.004C49CC                  ;Jump back to CUser::Parsing

You can use OllyDbg to patch this one up, or just use my updated version of the Ebenezer/Client Editor - which will be released very soon. ;)
页: [1]
查看完整版本: [1.298] Add a logged in check to game server packets