搜索
 找回密码
 加入

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

Twisted 2011-10-16 09:05:26 1400
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 handler
  1. 00490995   . E9 16400300        JMP Ebenezer.004C49B0; Replace the kill-switch checks with a jump to our code-cave
  2. 0049099A         90                      NOP; Rest of it is nopped out.
  3. 0049099B         90                      NOP
  4. 0049099C         90                      NOP
  5. 0049099D         90                      NOP
  6. 0049099E         90                      NOP
  7. 0049099F         90                      NOP
  8. 004909A0         90                      NOP
  9. 004909A1         90                      NOP
  10. 004909A2         90                      NOP
  11. 004909A3         90                      NOP

  12. ; In our code-cave
  13. 004C49B0   > 83FA 2B            CMP EDX,2B                                                        ;  Check for version packet
  14. 004C49B3   . 74 17                JE SHORT Ebenezer.004C49CC                      ;  If version packet, jump back to switch (no account ID set yet)
  15. 004C49B5   . 83FA 01            CMP EDX,1                                                          ;  Check for login packet
  16. 004C49B8         74 17            JE SHORT Ebenezer.004C49D1                      ;  If login packet, set the Authority to 1 [default before it's retrieved from the database] and jump back to switch (it's set in this packet's handler)
  17. 004C49BA   . 52                  PUSH EDX                                                               ;  Push EDX/opcode onto the stack
  18. 004C49BB   . 8A96 9C800000  MOV DL,BYTE PTR DS:[ESI+809C]                  ;  Store first byte of account name in DL
  19. 004C49C1   . 80FA 00            CMP DL,0                                                                ;  Compare first byte of account name to 0x00/NULL
  20. 004C49C4   . 5A                  POP EDX                                                                 ;  Pop EDX/opcode off the stack
  21. 004C49C5   . 75 05                JNZ SHORT Ebenezer.004C49CC                    ;  Byte isn't NULL, jump to packet handler!
  22. 004C49C7   . BA FFFFFFFF        MOV EDX,-1                                                        ;  Byte is NULL, set the opcode to -1 (so it's not handled)
  23. 004C49CC   >^E9 D3BFFCFF        JMP Ebenezer.004909A4                              ;  Back to the packet handler we go!
  24. 004C49D1         50                      PUSH EAX                                                               ;  Push EAX (used in the CUser::Parsing func we jumped from for something [not relevant]) onto the stack
  25. 004C49D2         8B86 98800000  MOV EAX,DWORD PTR DS:[ESI+8098]          ;  Store the pointer to the user's struct in eax
  26. 004C49D8         C640 71 01      MOV BYTE PTR DS:[EAX+71],1                       ;  Set the user's Authority to 1
  27. 004C49DC         58                      POP EAX                                                                 ;  Pop eax off the stack
  28. 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. ;)

0 回复

高级模式
游客