I had a working tool to debug network traffic for a network game written in purebasic (4.x), but meantime (windows 8.1 instead of xp, purebasic version 5+) it doesn't work anymore...DarkDragon wrote:Well I've done a hooking-code which works on Windows 7 x64 compiled with 64bit and 32bit. It is basic hooking and uses the disassembler of purebasic, which sometimes really works wrong. And you can't call the old method at the moment.
http://www.bradan.eu/files/hook.zip (Your antivirus will recognize it as a virus, sorry)
...so I try to find an alternative to write a log file showing the network data of the program. I tried to modify your code but I wasn't able to hook the winsock functions receive and send...
TestDll.dll:
Code: Select all
#HookMessages= 0
#HookWinsock= 1
; Define
Declare MessageBoxAHook(Parent.i,*Text,*Title,Type.i)
Declare WinsockSend(s.l,*buf,len.l,flags.l)
Declare WinsockRecv(s.l,*buf,len.l,flags.l)
Structure SFunction
*OldAddress
*NewAddress
*Buffer
BufferSize.i
OldProtect.i
EndStructure
Global NewList Functions.SFunction()
Global *WinsockSend
Global *WinsockRecv
Global Logging
Procedure.s Disassemble(*Buffer,Length)
Protected Result.s=""
If ExamineAssembly(*Buffer,*Buffer+Length)
Result=""
While NextInstruction()
If FindString(LCase(InstructionString()),"invalid",1) <= 0
Result+InstructionString()+#CRLF$
EndIf
Wend
EndIf
ProcedureReturn Result
EndProcedure
Procedure.s HexMemory(*Buffer,Length)
Protected k.i
Protected Result.s=""
For k=0 To Length-1
Result+RSet(Hex(PeekA(*Buffer+k),#PB_Ascii),2,"0")+" "
Next k
ProcedureReturn Result
EndProcedure
Procedure Hook(*OldAddress,*NewAddress)
Protected ProcessHandle.i
Protected MemoryInfo.MEMORY_BASIC_INFORMATION
Protected Length.i
Protected i.i
Protected Bytes.i
Protected Disassembly.s
Protected OldDisassembly.s
CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
Protected JMP.u=$E0FF
Protected MOV.u=$B848
CompilerElse
Protected JMP.u=$E0FF
Protected MOV.a=$B8
CompilerEndIf
Protected NOP.a=$90
Protected JumpAddress.i
ProcessHandle=OpenProcess_(#PROCESS_ALL_ACCESS,#False,GetCurrentProcessId_())
If ProcessHandle
AddElement(Functions())
Functions()\OldAddress=*OldAddress
Functions()\NewAddress=*NewAddress
Functions()\Buffer=AllocateMemory(64)
VirtualQuery_(Functions()\OldAddress,@MemoryInfo,SizeOf(MEMORY_BASIC_INFORMATION))
VirtualProtect_(MemoryInfo\BaseAddress,MemoryInfo\RegionSize,#PAGE_EXECUTE_READWRITE,@Functions()\OldProtect)
; read the memory block
Length=SizeOf(JumpAddress)+SizeOf(JMP)+SizeOf(MOV)-1
ReadProcessMemory_(ProcessHandle,Functions()\OldAddress,Functions()\Buffer,Length,@Bytes)
Disassembly=Disassemble(Functions()\Buffer,Length)
OldDisassembly=Disassembly
While Length <= MemorySize(Functions()\Buffer) And OldDisassembly=Disassembly
Length+1
ReadProcessMemory_(ProcessHandle,Functions()\OldAddress,Functions()\Buffer,Length,@Bytes)
OldDisassembly=Disassembly
Disassembly=Disassemble(Functions()\Buffer,Length)
Wend
Functions()\Buffer=ReAllocateMemory(Functions()\Buffer,Length)
Functions()\BufferSize=Length
; write our jump command to it
JumpAddress=Functions()\NewAddress
i=0
WriteProcessMemory_(ProcessHandle,Functions()\OldAddress,@MOV,SizeOf(MOV),@Bytes)
i+SizeOf(MOV)
WriteProcessMemory_(ProcessHandle,Functions()\OldAddress+i,@JumpAddress,SizeOf(JumpAddress),@Bytes)
i+SizeOf(JumpAddress)
WriteProcessMemory_(ProcessHandle,Functions()\OldAddress+i,@JMP,SizeOf(JMP),@Bytes)
i+SizeOf(JMP)
; fill the rest with NOP
While i < Functions()\BufferSize
WriteProcessMemory_(ProcessHandle,Functions()\OldAddress+i,@NOP,1,@Bytes)
i+1
Wend
; debug it
*Buffer=AllocateMemory(SizeOf(JumpAddress)+5)
ReadProcessMemory_(ProcessHandle,Functions()\OldAddress,*Buffer,SizeOf(JumpAddress)+5,@Bytes)
CloseHandle_(ProcessHandle)
EndIf
EndProcedure
Procedure Unhook(*NewAddress)
Protected Result=#False
Protected ProcessHandle.i
Protected MemoryInfo.MEMORY_BASIC_INFORMATION
Protected Protection.i
Protected Bytes.i
ForEach Functions()
If Functions()\NewAddress=*NewAddress
ProcessHandle=OpenProcess_(#PROCESS_ALL_ACCESS,#False,GetCurrentProcessId_())
If ProcessHandle <> 0
WriteProcessMemory_(ProcessHandle,Functions()\OldAddress,Functions()\Buffer,Functions()\BufferSize,@Bytes)
VirtualQuery_(Functions()\OldAddress,@MemoryInfo,SizeOf(MEMORY_BASIC_INFORMATION))
VirtualProtect_(MemoryInfo\BaseAddress,MemoryInfo\RegionSize,Functions()\OldProtect,@Protection)
DeleteElement(Functions())
Result=#True
CloseHandle_(ProcessHandle)
EndIf
Break
EndIf
Next
ProcedureReturn Result
EndProcedure
ProcedureDLL AttachProcess(Instance)
; MessageRequester("Start",Str(Instance))
Protected *OldAddress
Protected *NewAddress
CompilerIf #HookMessages
Library=OpenLibrary(#PB_Any,"user32.dll")
If Library
*OldAddress=GetFunction(Library,"MessageBoxA")
*NewAddress=@MessageBoxAHook()
If *OldAddress And *NewAddress
;MessageRequester("!","Message hooked")
Hook(*OldAddress,*NewAddress)
EndIf
CloseLibrary(Library)
EndIf
CompilerEndIf
CompilerIf #HookWinsock
Library=LoadLibrary_("wsock32.dll")
If Library
MessageRequester("...",Str(Library))
*WinsockSend=GetFunction(Library,"send")
*WinsockRecv=GetFunction(Library,"recv")
If *WinsockSend And *WinsockRecv
*NewAddress=@WinsockSend()
If *NewAddress
Hook(*WinsockSend,*NewAddress)
MessageRequester("Send hooked",Str(*WinsockSend)+#CR$+Str(*NewAddress))
EndIf
*NewAddress=@WinsockRecv()
If *NewAddress
Hook(*WinsockRecv,*NewAddress)
MessageRequester("Receive hooked",Str(*WinsockRecv)+#CR$+Str(*NewAddress))
EndIf
EndIf
EndIf
If OpenFile(0,"Sniffer.log")
Logging=#True
EndIf
CompilerEndIf
EndProcedure
ProcedureDLL DetachProcess(Instance)
Unhook(@MessageBoxAHook())
If Logging
CloseFile(0)
EndIf
EndProcedure
; EndDefine
ProcedureDLL WinsockSend(s.l,*buf,len.l,flags.l)
Result.l=CallFunctionFast(*WinsockSend,s.l,*buf,len.l,flags.l)
If Logging
WriteString(0,"> ")
WriteData(0,*buf,len)
WriteStringN(0,"")
EndIf
ProcedureReturn Result
EndProcedure
ProcedureDLL WinsockRecv(s.l,*buf,len.l,flags.l)
Result.l = CallFunctionFast(*WinsockRecv,s.l,*buf,len.l,flags.l)
If Logging
WriteStringN(0, "< ")
WriteData(0,*buf,len)
WriteStringN(0,"")
EndIf
ProcedureReturn Result
EndProcedure
ProcedureDLL MessageBoxAHook(Parent.i,*Text,*Title,Type.i)
Protected Window
Window=OpenWindow(#PB_Any,0,0,320,240,"Information",#PB_Window_SystemMenu | #PB_Window_TitleBar,Parent)
TextGadget(#PB_Any,10,10,300,220,"Hooked!")
Repeat : Until WaitWindowEvent(5)=#PB_Event_CloseWindow
CloseWindow(Window)
EndProcedure
Code: Select all
Procedure InjectLibary(ProcessID.i, Library.s)
Protected ProcessHandle.i = 0
Protected ThreadHandle.i = 0
Protected *FilenameExtern
Protected *FilenameIntern
Protected KernelLibrary.i = 0
Protected *LoadLibraryA = #Null
Protected Result.i = #False
ProcessHandle = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, ProcessID)
If ProcessHandle = 0
ProcedureReturn #False
EndIf
Size = StringByteLength(Library, #PB_Ascii) + 1
If Size <= 0
CloseHandle_(ProcessHandle)
ProcedureReturn #False
EndIf
*FilenameExtern = VirtualAllocEx_(ProcessHandle, #Null, Size, #MEM_COMMIT, #PAGE_READWRITE)
*FilenameIntern = AllocateMemory(Size)
If *FilenameIntern <> #Null And *FilenameExtern <> #Null
PokeS(*FilenameIntern, Library, -1, #PB_Ascii)
If WriteProcessMemory_(ProcessHandle, *FilenameExtern, *FilenameIntern, Size, #Null) <> 0
KernelLibrary = OpenLibrary(#PB_Any, "kernel32.dll")
If KernelLibrary
*LoadLibraryA = GetFunction(KernelLibrary, "LoadLibraryA")
CloseLibrary(KernelLibrary)
EndIf
If *LoadLibraryA <> #Null
ThreadHandle = CreateRemoteThread_(ProcessHandle, #Null, #Null, *LoadLibraryA, *FilenameExtern, #Null, #Null)
If ThreadHandle <> 0
WaitForSingleObject_(ThreadHandle, #INFINITE)
Result = #True
CloseHandle_(ThreadHandle)
ThreadHandle = 0
EndIf
EndIf
EndIf
EndIf
If *FilenameIntern <> #Null
FreeMemory(*FilenameIntern)
*FilenameIntern = #Null
EndIf
If *FilenameExtern <> #Null
VirtualFreeEx_(ProcessHandle, *FilenameExtern, 0, #MEM_RELEASE)
*FilenameExtern = #Null
EndIf
If ProcessHandle <> 0
CloseHandle_(ProcessHandle)
ProcessHandle = 0
EndIf
ProcedureReturn Result
EndProcedure
Process = RunProgram("TestEXE.exe", "", GetCurrentDirectory(), #PB_Program_Open)
If Process
InjectLibary(ProgramID(Process),GetCurrentDirectory()+"TestDLL.dll")
EndIf
Code: Select all
Delay(2000)
OpenWindow(0,0,0,500,500,"")
WebGadget(0,0,0,500,500,"http://www.purebasic.com")
MessageRequester("Information",": (")