Twisted 发表于 2011-10-17 07:48:12

[1.298] Patching a trade dupe Fix

To make the lives of cheaters more difficult (especially to decrease the likelihood of duping stackable items - which dupe scanners cannot pick up) I decided to try to patch the only dupe I know (thanks Vision). If you know any dupe methods you'd like to see patched, PLEASE PM me them! I would love to have a go at patching them!

The dupe itself is quite easy, it requires 3 characters:
- Player A
- Player B
- Player C

I won't go into all of the dupe method, but we will need to understand where the problem lies - so here's most of it:
- Player A trades Player C
- Player C accepts
- Player A types /trade (Player C is already selected) - and the trade window will be cancelled... for Player A only!

Player C's trade window remains up, meaning the Player C thinks they're still trading. In this time, Player A can then trade Player B, and perform the rest of the dupe.

The problem I see here, as you may have noticed from me highlighting it, is that both trade windows DO NOT CLOSE!

Looking into CUser::ExchangeReq() (exchange request) I see that it isn't calling CUser::ExchangeCancel() at all! Instead, it's just sending the cancel packet to the local session - which isn't good at all as you will soon find out.

What CUser::ExchangeCancel() does, is it resets the coins being traded and then calls CUser::InitExchange() to revert the items being traded as well as resets the variable m_sExchangeUser - which stores the session ID of the player they're trading.
Once that's done, CUser::ExchangeCancel() will then, if the session ID of the other player is valid, call ExchangeCancel() for their session (so that it will repeat the above process for the other session) and then send a cancel packet to the other player.

As CUser::ExchangeReq() is only sending the packet to the local session, we're:
a. Not reverting the exchanged items list,
b. Not reverting the coins being transferred,
c. Not sending the packet to the other client!

So, what we clearly need to do is call CUser::ExchangeCancel() instead (of course, only in the instance where the user is trying to perform the dupe).

To do this, we'll need extra code - so we'll use a code-cave. The code-cave I will use starts at 004ABD60, however I will start it at 004ABD61, just to separate it from the main function a little bit. :P

Note:
ESI is a pointer to the current instance of CUser (I'll refer to it as "this" to emphasise the fact it is the current instance),
EDI is a pointer to the other player's instance of CUser (I'll refer to it as pUser, as it is referred to in the old source).

In CUser::ExchangeReq() you will need to patch over the follow lines:
(BEFORE)

Compare pUser->m_sExchangeUser to -1
004ABBCA|. 66:83BF 408100>CMP WORD PTR DS:,0FFFFIf pUser->m_sExchangeUser is not equal to -1 (if it's set to -1, it means they are not trading anyone), jump to 004ABC90 - which sends the cancels packet and returns the function!004ABBD2|. 0F85 B8000000JNZ 004ABC90.. with:
(AFTER)

Compare this->m_sExchangeUser to -1004ABBCA         66:81BE 408100>CMP WORD PTR DS:,0FFFFJump to our code-cave! Yay!004ABBD3         E9 89010000    JMP 004ABD61Now in our code-cave (you'll see a whole lot of INT3s which we'll just assemble over), we'll begin our new code.

Continuing from the above, if this->m_sExchangeUser not equal to -1, that means they are trading someone already - so we'll jump to some more of our own code which will then cancel both trade windows properly with CUser::ExchangeCancel().004ABD61         75 14            JNZ SHORT 004ABD77Compare pUser->m_sExchangeUser to -1
004ABD63         66:81BF 408100>CMP WORD PTR DS:,0FFFFIf pUser->m_sExchangeUser is not equal to -1, then it means that the other player is already trading, so we will cancel the local trade window (as we're doing already). This is our patched over code. We DON'T want to close both windows here, because the other player is already trading SOMEONE ELSE!
004ABD6C      ^0F85 1EFFFFFFJNZ 004ABC90All of the above checks are fine, so we'll jump back to the main function and follow the rest of the code following that which we patched over!
004ABD72      ^E9 61FEFFFF    JMP 004ABBD8This line probably isn't needed, but I was just making sure that the ECX register is set to the pointer of our current session - CUser::ExchangeCancel() requires it, so I was just being careful.
004ABD77         8BCE            MOV ECX,ESICall CUser::ExchangeCancel() to handle cancelling trade.
004ABD79         E8 0B79F5FF    CALL 00403689Jump back to the end of the function - don't need to send any packets, so we're jumping back to code straight after that.004ABD7E      ^E9 2DFFFFFF    JMP 004ABCB0...and voila! That dupe is effectively patched!

28085279 发表于 2011-10-22 22:55:21

{:2_227:}{:2_235:}没看明白

天剑风小流 发表于 2011-12-20 21:22:27

{:1_203:}進來花了我2金幣還錢················
页: [1]
查看完整版本: [1.298] Patching a trade dupe Fix