Twisted 发表于 2011-10-16 08:59:17

[1.298] ban_knights exploit fix

The /ban_knights command is supposed to be used by the alliance leader to remove the selected clan leader's clan from the alliance.
However, mgame failed yet again - the command was actually open to anybody at all, so long as the selected clan leader was in a clan and an alliance. This means that anybody could remove any clan from an alliance!

What we'll do for this one is add a check to see if the player that is trying to remove the alliance is the alliance leader.

We'll start off in CKnightsManager::KnightsAlliancePunish(), the function that's called when /ban_knights is used.
We might as well use the pointer to the clan struct that's being retrieved, so pretty much straight after the checks, we'll add a jump to our code-cave.

We'll overwrite this line here:00457D53   . 68 80276800          PUSH 00682780                        ; /pCriticalSection = 00682780With a jump to our code-cave:
00457D53         E9 9E030000      JMP 004580F6In the following code, we'll have to mess with the registers a lot, which I'm sure the rest of CKnightsManager::KnightsAlliancePunish() will most certainly not like, so what we can do is "save" the state of the current registers and flags, which we'll use the following two lines for:004580F6         60                        PUSHAD
004580F7         9C                        PUSHFDOnce we're done we'll need to remember to restore the state we saved here.

Now, this bit gets tricky, as we have a pointer to the selected clan leader's clan... but we actually need a pointer to the alliance leader's clan.
So, to do this, I took a bit of a look through the memory dump until I found the main alliance's clan ID. It was located at EAX-46.004580F8         0FB740 BA            MOVZX EAX,WORD PTR DS:Now that we've got the main alliance's clan ID, it's just a matter of calling CEbenezerDlg::GetKnightsPtr(int clanid) to retrieve the pointer to the clan's struct (which we need to get the alliance leader's name!).

In CEbenezerDlg::GetKnightsPtr() we'll refer to ECX - this is the pointer to the instance of the class CEbenezerDlg. We need to pass this, so that anything in that function can still access what it needs in the instance of CEbenzerDlg.004580FD         8B4F 04                  MOV ECX,DWORD PTR DS:Here we push EAX (that's the main alliance's clan ID!) onto the stack, which CEbenezerDlg::GetKnightsPtr() will use.004580FC         50                        PUSH EAXCall CEbenezerDlg::GetKnightsPtr() to get the pointer to the main alliance's clan.00458100         E8 5F94FAFF      CALL 00401564EAX will now be the return value of 00401564 (CEbenezerDlg::GetKnightsPtr()), which is the clan pointer.
We'll need to check to make sure that the pointer is actually valid (make sure that the clan was found).
00458105         85C0                  TEST EAX,EAXIf the pointer (EAX) is 0, the pointer is obviously invalid, so we'll jump to a case I'll call "fail_return". We jump here in any case that something's wrong, and it will then as you will find out later, restore the registers & flags, and jump back to the end of CKnightsManager::KnightsAlliancePunish() - so it doesn't do anything.00458107         74 27                  JE SHORT 00458130We'll use EBX to store the pointer to the class of the player that's trying to use /ban_knights.00458109         3E:8B5D 08      MOV EBX,DWORD PTR DS:Now we'll use EBX again (as we don't need it for anything else) to store the pointer to the character's name (the one who is trying to use /ban_knights).0045810D         8B9B 98800000MOV EBX,DWORD PTR DS:Here we push EBX (pointer to the character's name) onto the stack, for use with our call to strcmp() (which we'll use to make sure that the two character's names - the alliance leader's and the player who is trying to use /ban_knights - match).00458113         53                        PUSH EBXSimply, we'll store the pointer to the alliance leader's name (EAX is the pointer to the clan struct, +26 is the offset from there to get to the clan leader's name) in EAX.00458114         8D40 26                  LEA EAX,DWORD PTR DS:Now push the alliance leader's name onto the stack also (so we have both character names on the stack at the moment - the player who is trying to use /ban_knights, and the alliance leader!).
00458117         50                        PUSH EAXNow that we've got all the data prepared, we can finally call strcmp() to compare the two character names!00458118         E8 339D0A00      CALL 00501E50Pop ECX (pointer to the instance of CEbenezerDlg) off the stack. (Clean-up)0045811D         59                        POP ECX
Test EAX (return value of strcmp). If it's 0, it's a match. Plainly, it's non-zero, it isn't a match.
0045811E         85C0                  TEST EAX,EAXMore clean-up.
00458120         59                        POP ECXAs I said before, if EAX is 0, it's a match. If it's non-zero, it isn't a match. JNZ = Jump Not Zero, so if it's not a match, we'll jump to "fail_return", preventing the user from removing a clan from an alliance illegitimately.
00458121         75 0D                  JNZ SHORT 00458130Restore the saved flags & registers from before. Put it all back the way we left it! :)
00458123         9D                        POPFD
00458124         61                        POPADThis is the code we patched over:00458125         BB 80276800      MOV EBX,00682780
0045812A         53                        PUSH EBXAll is well, so jump back and continue executing the code resuming from the point we left off.0045812B      ^E9 28FCFFFF      JMP 00457D58...and here is fail_return!

Restore the flags & registers from our saved state.00458130         9D                        POPFD
00458131         61                        POPADJump to the end of CKnightsManager::KnightsAlliancePunish(), so we skip doing anything like removing the clan from the alliance. :P00458132      ^EB A2                  JMP SHORT 004580D6Code recapCKnightsManager::KnightsAlliancePunish()

00457D53         E9 9E030000      JMP 004580F6Code-cave:
004580F6         60                        PUSHAD
004580F7         9C                        PUSHFD
004580F8         0FB740 BA            MOVZX EAX,WORD PTR DS:
004580FC         50                        PUSH EAX
004580FD         8B4F 04                  MOV ECX,DWORD PTR DS:
00458100         E8 5F94FAFF      CALL 00401564
00458105         85C0                  TEST EAX,EAX
00458107         74 27                  JE SHORT 00458130
00458109         3E:8B5D 08      MOV EBX,DWORD PTR DS:
0045810D         8B9B 98800000MOV EBX,DWORD PTR DS:
00458113         53                        PUSH EBX
00458114         8D40 26                  LEA EAX,DWORD PTR DS:
00458117         50                        PUSH EAX
00458118         E8 339D0A00      CALL 00501E50
0045811D         59                        POP ECX
0045811E         85C0                  TEST EAX,EAX
00458120         59                        POP ECX
00458121         75 0D                  JNZ SHORT 00458130
00458123         9D                        POPFD
00458124         61                        POPAD
00458125         BB 80276800      MOV EBX,00682780
0045812A         53                        PUSH EBX
0045812B      ^E9 28FCFFFF      JMP 00457D58
00458130         9D                        POPFD
00458131         61                        POPAD
00458132      ^EB A2                  JMP SHORT 004580D6
Have fun!
页: [1]
查看完整版本: [1.298] ban_knights exploit fix