//d2sniffer by mousepad //NOTE :- "Link incremently" must be disabled #include #include HANDLE diablo2_ph = 0; HANDLE GetProcessHandle(char *szClass, char *szTitle) { HWND hwnd = FindWindow(szClass, szTitle); DWORD pid = 0; GetWindowThreadProcessId(hwnd, &pid); return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); } DWORD VirtualProtectEx(HANDLE hProcess, DWORD lpAddress, DWORD dwSize, DWORD flNewProtect) { DWORD oldprot = 0; VirtualProtectEx(hProcess, (void *)lpAddress, dwSize, flNewProtect, &oldprot); return oldprot; } void WriteProcessBYTES(HANDLE hProcess, DWORD lpAddress, void *buf, int len) { DWORD oldprot = VirtualProtectEx(hProcess, lpAddress, len, PAGE_EXECUTE_READWRITE); WriteProcessMemory(hProcess, (void *)lpAddress, buf, len, 0); VirtualProtectEx(hProcess, lpAddress, len, oldprot); } void WriteProcessDWORD(HANDLE hProcess, DWORD lpAddress, DWORD val) { WriteProcessBYTES(hProcess, lpAddress, &val, 4); } void InterceptCode(HANDLE diablo2_ph, int inst, DWORD pOldCode, DWORD pNewCode, int nBytes = 5) { BYTE *buf1 = new BYTE[nBytes]; buf1[0] = inst; *(DWORD *)(buf1+1) = pNewCode-(pOldCode+5); memset(buf1+5, 0x90, nBytes-5); //nops WriteProcessBYTES(diablo2_ph, pOldCode, buf1, nBytes); delete buf1; } void DisplayBuffer(FILE *f, BYTE *buf, int len) { for (int i = 0; i < len; i++) fprintf(f, "%.2X ",buf[i]); fprintf(f, "\n"); } #define INST_NOP 0x90 #define INST_CALL 0xe8 #define INST_JMP 0xe9 #define INST_JMPR 0xeb #define INST_RET 0xc3 #define DB(x) __asm _emit (x) #define DW(x) __asm _emit (x)&0xff __asm _emit (x)>>8&0xff #define DD(x) __asm _emit (x)&0xff __asm _emit (x)>>8&0xff __asm _emit (x)>>16&0xff __asm _emit (x)>>24&0xff #define FUNCTLEN(func) ((DWORD)func##END-(DWORD)func) #define CMP_DWORD(addr,bval) DB(0x83) DB(0x3d) DD(addr) DB(bval) #define ADDR_MESSAGESHACK 0x00400f00 void __declspec(naked) MessagesHack_ASM() { __asm { jmp recvmessage //+0 jmp sentmessage //+2 DD(0) //+4 dest hwnd recvmessage: //ebp = ptr message //eax = length //bl = message no CMP_DWORD(ADDR_MESSAGESHACK+4,0) //dest hwnd je recvmessage3 cmp bl,0x07 je recvmessage2 cmp bl,0x08 je recvmessage2 // jmp recvmessage3 recvmessage2: push ebp push eax push 0 call sendcopydata recvmessage3: //orignal code and ebx,0xFF ret sentmessage: //[esp+0x0c] = ptr message //[esp+0x10] = length CMP_DWORD(ADDR_MESSAGESHACK+4,0) //dest hwnd je sentmessage3 mov eax,[esp+0x0c] mov al,[eax] cmp al,0x01 je sentmessage2 cmp al,0x03 je sentmessage2 // jmp sentmessage3 sentmessage2: push dword ptr [esp+0x0c] push dword ptr [esp+4+0x10] push 1 call sendcopydata sentmessage3: //orignal code push 0x6FC01A20 ret sendcopydata: //params 3 = type, length, ptr message pushad lea eax,[esp+0x20+4] //lParam, pcds push eax //lParam, pcds mov eax,0x6FB600CE //get hwnd (d2gfx 272b) call eax push eax //wParam, source hwnd push WM_COPYDATA //uMsg mov eax,ADDR_MESSAGESHACK+4 push dword ptr [eax] //dest hwnd mov eax,0x6FB6D0F4 //d2client's SendMessageA call [eax] popad ret 3*4 } } void __declspec(naked) MessagesHack_ASMEND() {} void MessagesHackStart(HWND hwnd) { WriteProcessBYTES(diablo2_ph, ADDR_MESSAGESHACK, MessagesHack_ASM, FUNCTLEN(MessagesHack_ASM)); InterceptCode(diablo2_ph, INST_CALL, 0x6FAB43EA, ADDR_MESSAGESHACK+0, 6); //recv (d2client) InterceptCode(diablo2_ph, INST_CALL, 0x6FC0178D, ADDR_MESSAGESHACK+2, 5); //send (d2net) WriteProcessDWORD(diablo2_ph, ADDR_MESSAGESHACK+4, (DWORD)hwnd); } void MessagesHackStop() { WriteProcessDWORD(diablo2_ph, ADDR_MESSAGESHACK+4, 0); } LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0); break; case WM_COPYDATA: { COPYDATASTRUCT *pcds = (COPYDATASTRUCT *)lParam; printf(pcds->dwData?"SENT ":"RECV "); DisplayBuffer(stdout, (BYTE *)pcds->lpData, pcds->cbData); break; } default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } void __cdecl main() { diablo2_ph = GetProcessHandle("Diablo II", "Diablo II"); if (diablo2_ph == 0) { printf("cant get d2 process handle\n"); return; } WNDCLASS wc = {0, TestWindowProc, 0, 0, GetModuleHandle(0), 0, 0, GetStockObject(BLACK_BRUSH), 0, "testwin"}; RegisterClass(&wc); HWND hwnd = CreateWindow("testwin", "testwin", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, GetModuleHandle(0), 0); MessagesHackStart(hwnd); MSG lpMsg; while (GetMessage(&lpMsg,0,0,0)) { TranslateMessage(&lpMsg); DispatchMessage(&lpMsg); } MessagesHackStop(); CloseHandle(diablo2_ph); }