搜索
 找回密码
 加入

[1.298] Patching a trade dupe Fix

Twisted 2011-12-20 21:22:27 1444
To make the lives of cheaters more difficult (especially to decrease the likelihood of duping stackable items [without serials] - 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

  1. 004ABBCA  |. 66:83BF 408100>CMP WORD PTR DS:[EDI+8140],0FFFF
复制代码
If 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!
  1. 004ABBD2  |. 0F85 B8000000  JNZ 004ABC90
复制代码
.. with:
(AFTER)

Compare this->m_sExchangeUser to -1
  1. 004ABBCA         66:81BE 408100>CMP WORD PTR DS:[ESI+8140],0FFFF
复制代码
Jump to our code-cave! Yay!
  1. 004ABBD3         E9 89010000    JMP 004ABD61
复制代码
Now 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().
  1. 004ABD61         75 14            JNZ SHORT 004ABD77
复制代码
Compare pUser->m_sExchangeUser to -1

  1. 004ABD63         66:81BF 408100>CMP WORD PTR DS:[EDI+8140],0FFFF
复制代码
If 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!

  1. 004ABD6C        ^0F85 1EFFFFFF  JNZ 004ABC90
复制代码
All 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!

  1. 004ABD72        ^E9 61FEFFFF    JMP 004ABBD8
复制代码
This 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.

  1. 004ABD77         8BCE              MOV ECX,ESI
复制代码
Call CUser::ExchangeCancel() to handle cancelling trade.

  1. 004ABD79         E8 0B79F5FF    CALL 00403689
复制代码
Jump back to the end of the function - don't need to send any packets, so we're jumping back to code straight after that.
  1. 004ABD7E        ^E9 2DFFFFFF    JMP 004ABCB0
复制代码
...and voila! That dupe is effectively patched!

2 回复

28085279
2011-10-22 22:55:21
点击查看详情
没看明白
天剑风小流
2011-12-20 21:22:27
進來花了我2金幣還錢················
高级模式
游客