|
The Edge of Nowhere Don't worry, Search is still broken!
|
|
|
| Author |
Message |
R1CH Blizzhacker

Joined: 23 Apr 2004 My Posts
Location: England
|
Posted: Wed May 02, 2007 7:59 pm Post subject: [Program] TCP/IP Join Game Delay Reducer |
|
|
Same deal as ftjfix... I don't see why the delay for joining a TCP/IP game was so long, so I patched it. It seems the delay is some horrible method of synchronizing the network, so if you're on a slow connection this may or may not cause a problem; I didn't look into it further as it 'works for me'.
Usage:
Download and extract to your D2/plugin/ folder and run D2 using loader.
1.12 compatible.
Download: http://r-1.ch/tcpipfix-1.1.zip
Last edited by R1CH on Thu Jun 19, 2008 6:47 pm; edited 2 times in total |
|
| Back to top |
|
 |
Blood_SpIkE Banned

Joined: 01 Dec 2001 My Posts
|
Posted: Wed May 02, 2007 8:46 pm Post subject: |
|
|
| i don't trust u |
|
| Back to top |
|
 |
a.d.r User

Joined: 03 Dec 2004 My Posts
Location: O.o ! o.O
|
Posted: Wed May 02, 2007 8:53 pm Post subject: |
|
|
| Blood_SpIkE wrote: | | i don't trust u |
LOL |
|
| Back to top |
|
 |
Gary13579 User

Joined: 09 Oct 2006 My Posts
|
Posted: Wed May 02, 2007 9:05 pm Post subject: |
|
|
Great to see you're still around R1CH  |
|
| Back to top |
|
 |
EJO9876 Retired Mod

Joined: 11 Apr 2004 My Posts
Location: Awesomeville
|
Posted: Wed May 02, 2007 9:42 pm Post subject: |
|
|
i haven't scanned this, but seeing as it's you i don't think i need to.
nice to see you again  |
|
| Back to top |
|
 |
I_EAT_YOU User

Joined: 30 Apr 2006 My Posts
|
Posted: Wed May 02, 2007 10:53 pm Post subject: |
|
|
welcome back r1ch  |
|
| Back to top |
|
 |
R1CH Blizzhacker

Joined: 23 Apr 2004 My Posts
Location: England
|
Posted: Wed May 02, 2007 11:05 pm Post subject: |
|
|
I was never really gone, but OK .
Here's the source (MASM32), although there is more to be learned from finding the correct address than this code...
http://r-1.ch/tcpipfix.asm |
|
| Back to top |
|
 |
ApacheChief User

Joined: 22 Jan 2004 My Posts
|
Posted: Thu May 03, 2007 12:59 am Post subject: |
|
|
How did you find the correct addresses, if you don't mind explaining?
EDIT: If anyone else is trying to make sense of the ASM, this little guide helped me try to understand it: http://www.woodmann.com/crackz/Tutorials/Drme2.htm
What I think I understand:
| Code: | .code
szD2Client db "D2CLIENT",0 | Not sure, creates a variable some how pointing to diablo.exe?
| Code: | LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
xor eax,eax
inc eax
ret
LibMain Endp | This looks like a function, but I have no idea where it's called (main?) or rather how it links to QueryInterface proc. However, the code inside is setting eax to 0, incrementing it by 1, and returning it. So it's just like C++'s int main () { return 1; }?
| Code: | QueryInterface proc
LOCAL oldProt :DWORD
LOCAL dummy :DWORD
invoke GetModuleHandle,ADDR szD2Client
test eax, eax
jne short loadOK
invoke LoadLibrary,ADDR szD2Client
test eax, eax
je short nullRet | Not sure what the oldProt/dummy part is about, and I don't understand much about the rest
You're calling GetModuleHandle and it's returning a bool to the eax register. If GetModuleHandle returns true (0?) it jumps to loadOK, otherwise if that fails it skips the jump and tries to LoadLibrary instead?
Yikes, I have to get to bed--thanks for posting the source R1CH. If you get any free time, throw me some terms I should wiki/research please
[will work on this a bit tomorrow, loadOK looks a bit more simple] |
|
| Back to top |
|
 |
R1CH Blizzhacker

Joined: 23 Apr 2004 My Posts
Location: England
|
Posted: Thu May 03, 2007 5:05 am Post subject: |
|
|
I figure I'll explain how this works then in the hope of helping someone .
To find the address is relatively simple, I fired up OllyDbg and ran D2 under it and joined a TCP/IP game. During the delay, I hit break in Olly and then followed the call stack until I found D2 calling Sleep (250) a whole lot. The patch simply replaces the 250 with 20, a 4 byte code change (really one byte but I use a DWORD for consistency ).
| Code: | | szD2Client db "D2CLIENT",0 |
That's declaring a null terminated string called szD2Client.
LibMain is essentially DllMain as you see in Win32 C and simply returns 1 to allow the DLL to load.
| Code: | QueryInterface proc
LOCAL oldProt :DWORD
LOCAL dummy :DWORD |
This is using MASM syntax to allow for easy local variable setup rather than messing with the stack pointer and such myself. It's exactly the same as DWORD oldProt, dummy in C.
| Code: | invoke GetModuleHandle,ADDR szD2Client
test eax, eax
jne short loadOK
invoke LoadLibrary,ADDR szD2Client
test eax, eax
je short nullRet |
invoke is again an MASM function, essentially instead of pushing all the parameters and using a call, you just use invoke and it does all the heavy lifting for you. GetModuleHandle ("D2CLIENT") in C. If GetModuleHandle returns NULL, the jump is not taken, and a LoadLibrary is attempted. If this fails, the function returns. We don't actually need the module handle (although in an ideal world we'd use it for relative offsets in the event D2Client.dll is rebased), so it's not actually copied anywhere.
After that it's just a case of changing the memory protection (VirtualProtect) to allow code changes, writing the new value, restoring protection and you're done.
Here's an approximation in C:
| Code: | #define OFFSET_D2CLIENT_SLEEPVAL 0x6FB0E7CE
LPPLUGIN_INTERFACE __stdcall QueryInterface(VOID)
{
DWORD oldProt;
DWORD dummy;
if (!GetModuleHandle ("D2CLIENT") && !LoadLibrary ("D2CLIENT"))
return NULL;
if (!VirtualProtect ((LPVOID)OFFSET_D2CLIENT_SLEEPVAL, 4, PAGE_EXECUTE_READWRITE, &oldProt))
return NULL;
*(DWORD *)OFFSET_D2CLIENT_SLEEPVAL = 20;
VirtualProtect ((LPVOID)OFFSET_D2CLIENT_SLEEPVAL, 4, oldprot, &dummy);
return NULL;
}
BOOL WINAPI DllMain(HINSTANCE hDll,DWORD dwReason,LPVOID lpReserved)
{
return TRUE;
} |
|
|
| Back to top |
|
 |
lolp1 User

Joined: 31 May 2006 My Posts
|
Posted: Thu May 03, 2007 5:27 am Post subject: |
|
|
I always wondered why they did this to, I never thought of opening olly and looking around for it though.
Looks good Nice to see a post from ya. |
|
| Back to top |
|
 |
lolp1 User

Joined: 31 May 2006 My Posts
|
Posted: Thu May 03, 2007 6:07 am Post subject: |
|
|
Well, I looked into this a bit more, and noticed I didn't like to have to be loading a DLL where it was not neccasery. (Regardless how innocent).
So I made something just to use writeprocesssmemory to patch it, it has the same effect
Also lets you change the delay, but it appeared to me that anything under 20 would show no faster.
If you want to use my version www.valvesupport.info/DelayReducer.rar
(Comes with a cool icon, and ini LOL)
EDIT: I also think my version will work with non-d2loader users, but this is not tested !
(Source)
| Code: | Func _MemRead($i_hProcess, $i_lpBaseAddress, $i_nSize, $v_lpNumberOfBytesRead = '')
Local $v_Struct = DllStructCreate ('byte[' & $i_nSize & ']')
DllCall('kernel32.dll', 'int', 'ReadProcessMemory', 'int', $i_hProcess, 'int', $i_lpBaseAddress, 'int', DllStructGetPtr ($v_Struct, 1), 'int', $i_nSize, 'int', $v_lpNumberOfBytesRead)
Local $v_Return = DllStructGetData ($v_Struct, 1)
$v_Struct=0
Return $v_Return
EndFunc ;==> _MemRead()
Func _MemWrite($i_hProcess, $i_lpBaseAddress, $v_Inject, $i_nSize, $v_lpNumberOfBytesRead = '')
Local $v_Struct = DllStructCreate ('byte[' & $i_nSize & ']')
DllStructSetData ($v_Struct, 1, $v_Inject)
$i_Call = DllCall('kernel32.dll', 'int', 'WriteProcessMemory', 'int', $i_hProcess, 'int', $i_lpBaseAddress, 'int', DllStructGetPtr ($v_Struct, 1), 'int', $i_nSize, 'int', $v_lpNumberOfBytesRead)
$v_Struct=0
Return $i_Call[0]
EndFunc ;==> _MemWrite()
Func _MemOpen($i_dwDesiredAccess, $i_bInheritHandle, $i_dwProcessId)
$ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $i_dwDesiredAccess, 'int', $i_bInheritHandle, 'int', $i_dwProcessId)
If @error Then
SetError(1)
Return 0
EndIf
Return $ai_Handle[0]
EndFunc ;==> _MemOpen()
Func _MemClose($i_hProcess)
$av_CloseHandle = DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $i_hProcess)
Return $av_CloseHandle[0]
EndFunc ;==> _MemClose() |
| Code: |
#include <mem.au3>
$Process = iniread("global.ini","global","process","Diablo II.exe") ;-> Target process
$PID = ProcessExists($Process) ;-> Get Process ID
$Address = 0x6FB0E7CE
$Value = iniread("global.ini","global","delay=","20") ;-> Target process
$OpenProcess = _MemOpen(0x38, False, $PID) ;-> Enable reading/writing to the process and get the handle
$v_Read = _MemRead($OpenProcess, $Address, 3) ;-> Read a 1 byte value from the defined address
$v_Read = _MemWrite($OpenProcess, $Address, $Value, 1);-> Write a new 1 byte value to the defined address
_MemClose($OpenProcess) ;-> Disable reading/writing to the process
MsgBox(0,"Patcher", "Addres is now patched...") |
|
|
| Back to top |
|
 |
¹³³7 User

Joined: 29 Apr 2006 My Posts
|
Posted: Thu May 03, 2007 6:35 am Post subject: |
|
|
| nice work ty |
|
| Back to top |
|
 |
R1CH Blizzhacker

Joined: 23 Apr 2004 My Posts
Location: England
|
Posted: Thu May 03, 2007 6:54 am Post subject: |
|
|
| lolp1 wrote: | | Well, I looked into this a bit more, and noticed I didn't like to have to be loading a DLL where it was not neccasery. (Regardless how innocent). |
Keep in mind that as with ftjfix and dropprotect, returning NULL to QueryInterface causes D2Loader to unload the DLL, so this is just as safe as an external WriteProcessMemory. For simple code patches, a D2Loader DLL which returns NULL is just a convenient way to apply it on startup. |
|
| Back to top |
|
 |
lolp1 User

Joined: 31 May 2006 My Posts
|
Posted: Thu May 03, 2007 7:15 am Post subject: |
|
|
| R1CH wrote: | | lolp1 wrote: | | Well, I looked into this a bit more, and noticed I didn't like to have to be loading a DLL where it was not neccasery. (Regardless how innocent). |
Keep in mind that as with ftjfix and dropprotect, returning NULL to QueryInterface causes D2Loader to unload the DLL, so this is just as safe as an external WriteProcessMemory. For simple code patches, a D2Loader DLL which returns NULL is just a convenient way to apply it on startup. |
Ahh, I did not know that. I agree, it is a nice way to load at start up. Well then, nice job. |
|
| Back to top |
|
 |
ApacheChief User

Joined: 22 Jan 2004 My Posts
|
Posted: Thu May 03, 2007 5:55 pm Post subject: |
|
|
| R1CH wrote: | I figure I'll explain how this works then in the hope of helping someone .
To find the address is relatively simple, I fired up OllyDbg and ran D2 under it and joined a TCP/IP game. During the delay, I hit break in Olly and then followed the call stack until I found D2 calling Sleep (250) a whole lot. The patch simply replaces the 250 with 20, a 4 byte code change (really one byte but I use a DWORD for consistency ). | Thanks a lot for explaining that in detail AND posting a C equivalent. I really appreciate it.
However, looking at the C vs MASM, why did you use MASM? For fun? The C looks so much more simple  |
|
| Back to top |
|
 |
|
Donations this month: $120 Server cost this month: $120 Surplus Donations: $243 (2 months)
Donators this month: BenOwns, m3flow, crazyguy2005, TriiT, mbundy, pcgamer4life, parajumper, HEMULI, Alister, fallore, ZepherX, iLikeDixLOL, dsa, fobic, wootie, fbu, KaRdOoShI, youngstar2, ByTeMe, jj!, zonic, cruciform, Ninjai, Dr.Duck
|