 |
madshi.net high quality low level programming
|
| View previous topic :: View next topic |
| Author |
Message |
mutantc0der
Joined: 17 Jun 2004 Posts: 11
|
Posted: Thu Jun 17, 2004 1:59 pm Post subject: winsock example code |
|
|
hi
i'v been working on a winsock demo project (orginally made by Aphex, but heavly modified) but i some things still goes wrong.. I attempt to intercept send/recv data and log it back to the base application using IPC. The problem is that IE/MSN act very unstable on this code. IE crashes after ~30 page requests, I suspect that a few bytes are lost in the send/recv events but im unable to find any thing wrong. The reason i think this is because MSN traffic is shown perfectly in the base logapp but it still says that there is a problem while connecting. Can somebody please look at it, so when its fixed u can give this thread url as refrence for a winsock demo .. (i'v seen the request for this alot of times). note: this code also tries to log the remote ip of the socket, i commented that code first, but had no effect.
btw, sorry for the sloppy coding, but just hacking on it for a few hours and the last thing on my mind was to clean up the code a bit
thanks for all the work madshi!
| Code: |
library Project1;
uses
Windows,
Winsock,
SysUtils,
madRemote,
madCodeHook;
{$R *.RES}
var
connectNextHook: function (s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
sendNextHook: function(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
recvNextHook: function(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
DataSocket: TSocket;
LastDataSocket : Tsocket;
var
strAppExe: string;
strSockIP : String;
function GetModuleFileName: string;
var
pid : dword;
Buffer: array[0..MAX_PATH] of Char;
begin
{ SetString(Result, Buffer, Windows.GetModuleFileName(HInstance,
Buffer, SizeOf(Buffer)));}
ProcessIdToFilename(ProcessHandleToId (GetCurrentProcess()),Buffer);
Result := StrPas(Buffer);
end;
function GetPeerAddr: string;
var
saddr : TSockAddrIn;
saddrlen : integer;
szAddr : PChar;
begin
Result := 'error';
if GetPeerName(DataSocket, TSockAddr(saddr), saddrlen) = 0 then begin
szAddr := Inet_ntoa(saddr.sin_addr);
Result := StrPas(szAddr);
end;
end;
procedure CheckIP();
begin
if (LastDataSocket = 0) OR ( DataSocket <> LastDataSocket) then
begin
LastDataSocket := DataSocket;
strSockIP := GetPeerAddr();
end
end;
procedure IPCLog(strWhat : String);
var
Result : Integer;
begin
strWhat := '[' + strAppExe + ' (' + strSockIP + ')] ' + strWhat;
SendIpcMessage('whooklib', pchar(strWhat), Length(strWhat), @result, sizeOf(result));
end;
function ConvertDataToAscii(Buffer: pointer; Length: Word): string;
var
Iterator: integer;
AsciiBuffer: string;
begin
AsciiBuffer := '';
for Iterator := 0 to Length - 1 do
begin
if char(pointer(integer(Buffer) + Iterator)^) in [#32..#127] then
AsciiBuffer := AsciiBuffer + ' ' + char(pointer(integer(Buffer) + Iterator)^) + ' '
else
AsciiBuffer := AsciiBuffer + ' . ';
end;
Result := AsciiBuffer;
end;
function ConvertDataToHex(Buffer: pointer; Length: Word): string;
var
Iterator: integer;
HexBuffer: string;
begin
HexBuffer := '';
for Iterator := 0 to Length - 1 do
begin
HexBuffer := HexBuffer + IntToHex(Ord(char(pointer(integer(Buffer) + Iterator)^)), 2) + ' ';
end;
Result := HexBuffer;
end;
function connectHookProc (s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
begin
Result := connectNextHook(s,name,namelen);
if Result = 0 then
begin
DataSocket := s;
CheckIP();
end;
end;
function recvHookProc(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
var
AsciiBuffer: string;
HexBuffer: string;
DataBuffer: pchar;
begin
//call the real winsock function
Result := recvNextHook(s, Buf, len, flags);
//allocate memory for our copy of the data
GetMem(DataBuffer, Result);
try
//get our copy of the data
CopyMemory(DataBuffer, @Buf, Result);
IPCLog( 'recv: ' + DataBuffer);
finally
FreeMem(DataBuffer);
end;
end;
function sendHookProc(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
var
AsciiBuffer: string;
HexBuffer: string;
DataBuffer: pchar;
begin
{ DataSocket := s;
CheckIP();}
//allocate memory for our copy of the data
GetMem(DataBuffer, len);
try
//get our copy of the data
CopyMemory(DataBuffer, @Buf, len);
IPCLog( 'send: ' + DataBuffer);
finally
FreeMem(DataBuffer);
end;
//call the real winsock function
Result := sendNextHook(s, Buf, len, flags);
end;
begin
strAppExe := GetModuleFileName();
strSockIP := 'undefined';
DataSocket := 0;
LastDataSocket := 0;
hookapi('ws2_32.dll','send', @sendHookProc, @sendNextHook);
hookapi('wsock32.dll','send', @sendHookProc, @sendNextHook);
hookapi('ws2_32.dll','recv', @recvHookProc, @recvNextHook);
hookapi('wsock32.dll','recv', @recvHookProc, @recvNextHook);
hookapi('ws2_32.dll','connect', @connectHookProc, @connectNextHook);
hookapi('wsock32.dll','connect', @connectHookProc, @connectNextHook);
end.
|
for the interested ppl, the base log app:
| Code: |
unit injecter;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, madCodeHook,
StdCtrls;
type
// this is how you get notified about incoming ipc messages
// you have to write a function which fits to this type definition
// and then you give it into "CreateIpcQueue"
TIpcCallback = procedure (name : pchar;
messageBuf : pointer;
messageLen : dword;
answerBuf : pointer;
answerLen : dword); stdcall;
type
TForm1 = class(TForm)
log: TMemo;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
{procedure RecvIPCmsg(name: pchar; messageBuf: pointer;
messageLen: dword; answerBuf: pointer; answerLen: dword);stdcall;}
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure RecvIPCmsg(name: pchar; messageBuf: pointer;
messageLen: dword; answerBuf: pointer; answerLen: dword);stdcall;
begin
//wassap
Form1.log.Lines.Add(StrPas(messageBuf));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateIpcQueue('whooklib', RecvIPCmsg);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
DestroyIpcQueue('whooklib');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
log.Lines.Add('injecting');
InjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'Project1.dll');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
log.Lines.Add('uninjecting');
UnInjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'Project1.dll');
end;
end.
|
|
|
| Back to top |
|
 |
madshi Site Admin
Joined: 21 Mar 2004 Posts: 5844
|
Posted: Fri Jun 18, 2004 8:00 am Post subject: |
|
|
I've not the time to check your code out in detail. Just two comments:
(1) When calling GetPeerName I think you need to initialize "saddrlen".
(2) Storing sockets in global variables is not really good for thread stuff. What happens if IE calls winsock functions at the "same" time from different threads?
I suggest that you comment out your code piece by piece until the hook dll is stable. This way you should be able to locate the guilty code. |
|
| Back to top |
|
 |
nildo
Joined: 22 Mar 2004 Posts: 246
|
Posted: Fri Jun 18, 2004 2:06 pm Post subject: |
|
|
just a Tip:
Do not call GetPeerAddr at the Recv hook because I've experienced with this error and was not able to fix.... |
|
| Back to top |
|
 |
mutantc0der
Joined: 17 Jun 2004 Posts: 11
|
Posted: Fri Jun 25, 2004 8:35 pm Post subject: |
|
|
ok, i got it working with another piece of code
now my question is, when do i get the remote IP of the connected socket ? i can retrieve it successfully with the following code BUT the socket gets disconnected after the function completes :
| Code: |
....
function GetPeerAddr(DataSocket : TSocket): string;
var
saddr : TSockAddrIn;
saddrlen : integer;
szAddr : PChar;
begin
Result := 'error';
saddrlen := sizeof(TSockAddrIn);
if GetPeerName(DataSocket, TSockAddr(saddr), saddrlen) = 0 then
begin
szAddr := Inet_ntoa(saddr.sin_addr);
Result := StrPas(szAddr);
end;
end;
....
function connectHookProc (s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
begin
Result := connectNextHook(s,name,namelen);
if Result = -1 then
begin
LogWithIPC('connect() to ' + GetPeerAddr(s));
//socket is now disconnected here
end;
LogWithIPC('connect() retcode : ' + IntToStr(Result));
end;
.........
|
nildo, u said u couldnt retrieve it in recv() , did you already find another suitable event to retrieve the remote ip/port and more info ??
thanks |
|
| Back to top |
|
 |
nildo
Joined: 22 Mar 2004 Posts: 246
|
Posted: Sat Jun 26, 2004 3:16 am Post subject: |
|
|
| mutantc0der wrote: | nildo, u said u couldnt retrieve it in recv() , did you already find another suitable event to retrieve the remote ip/port and more info ??
thanks |
No. What I did on my program was a Timer that keeps checking for those SocketIDs from my target application. To retreve the information you need to OpenProcess then DuplicateHandle on the SocketID. But I am trying a new way. Do you know NETSTAT? I'am adapting some code to my Delphi applacition that can read exatly what Netstat reads. So I will search for the SocketID on that list and then display the Remote and Local IP and port. |
|
| Back to top |
|
 |
mutantc0der
Joined: 17 Jun 2004 Posts: 11
|
Posted: Sat Jun 26, 2004 2:53 pm Post subject: |
|
|
do you want to pipe stdout from netstat.exe and read the information ? which parameters allows you to print the socket handles ? or are u using API's to retrieve a list
can you explain why we cannot retrieve the remote peer ip? i mean, we just intercept the recv() call, we directly call the real recv() , and then we perform some functions on the socket . the recv() is blocking for the app anyway, so why cant we let it wait and do our own things and then return from the call. very weird |
|
| Back to top |
|
 |
mic
Joined: 31 May 2004 Posts: 11
|
Posted: Sat Jul 03, 2004 8:56 am Post subject: |
|
|
mutant, that code looks nice
what i was wondering was how would u send data using it? |
|
| Back to top |
|
 |
nildo
Joined: 22 Mar 2004 Posts: 246
|
Posted: Mon Jul 12, 2004 11:16 am Post subject: |
|
|
mutantc0der, I was wrong, theres no way to retrieve sockets handle from netstat...  |
|
| Back to top |
|
 |
mutantc0der
Joined: 17 Jun 2004 Posts: 11
|
Posted: Mon Jul 12, 2004 12:16 pm Post subject: |
|
|
too bad nildo !!!
mic, thanx , but what do you mean with 'how do you send data?' , the DLL will process every send() call from the injected process, is that what you mean ? |
|
| Back to top |
|
 |
mic
Joined: 31 May 2004 Posts: 11
|
Posted: Mon Jul 12, 2004 12:27 pm Post subject: |
|
|
i was wondering how u would send like a byte array like from the loader
do u just call the dll send function from the loader and if so how i am crass at delphi |
|
| Back to top |
|
 |
mutantc0der
Joined: 17 Jun 2004 Posts: 11
|
Posted: Mon Jul 12, 2004 2:50 pm Post subject: |
|
|
| you'll need to use sendNextHook() if you want to send data in the DLL yourself, if i'v understood your question correctly |
|
| Back to top |
|
 |
iridium
Joined: 19 Aug 2004 Posts: 9
|
Posted: Fri Aug 20, 2004 9:05 am Post subject: |
|
|
| mutantc0der wrote: | | ok, i got it working with another piece of code |
mutant, would you mind sending me the "new" code? I'm working on a similar project.
Thanks a lot! |
|
| Back to top |
|
 |
jlist
Joined: 29 Aug 2004 Posts: 9
|
Posted: Sun Aug 29, 2004 1:07 am Post subject: |
|
|
It's an interesting topic.
I tried mutantc0der's code. Issues are:
- not getting connects. (mutantc0der mentioned this) Actually, I was surprised that recv and send worked. My impression is that MS will use WinSock2 functions as opposed to BSD sockets. And BSD sockets will be translated to WinSock2 calls. If IE calls WinSock2 functions directly, there would be no chance that recv, send or connect got called. I'm quite confused. I suppose hooking winsock2 functions could be the solution to connect?
- there are often garbage characters shown in the log. What are they? Below is the beginning part of a session accessing whatismyip.com
- sometimes, IE just can not access internet. Need to uninject, close the host app, start it again.
| Quote: | injecting
[IEXPLORE.EXE (undefined)] recv:
[IEXPLORE.EXE (undefined)] recv: ¤´E
[IEXPLORE.EXE (undefined)] recv: À´ v:R
[IEXPLORE.EXE (undefined)] recv: À´
[IEXPLORE.EXE (undefined)] send: GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: www.whatismyip.com
Connection: Keep-Alive
ibŽ
[IEXPLORE.EXE (undefined)] recv: ¤´ü
[IEXPLORE.EXE (undefined)] send: !´
[IEXPLORE.EXE (undefined)] recv: !´
[IEXPLORE.EXE (undefined)] recv: HTTP/1.1 200 OK
Date: Sun, 29 Aug 2004 00:54:35 GMT
Server: Microsoft-IIS/6.0
...
uninjecting |
|
|
| Back to top |
|
 |
zamolx32
Joined: 16 Sep 2004 Posts: 31
|
Posted: Thu Sep 16, 2004 10:33 am Post subject: What trick have solved your problem |
|
|
I'm having the same problems with this sample.
After a random period of time, iexplorer (or myie in my case) is crashing.
I have no ideea what could cause this problem.
mutantc0der, could you please share with us the trick you have used to solve this problem.
Thanks, |
|
| Back to top |
|
 |
nildo
Joined: 22 Mar 2004 Posts: 246
|
Posted: Thu Sep 16, 2004 11:19 am Post subject: |
|
|
I had no problem with my hook. I had not used MutantCoder's example but works perfectly. Some things that I've learned when doing my hook: Do not use GetPeerName and others like it, inside the callback of Send, Recv, WSASend and WSARec. Other things: You need to know what is making your IE to crash, so you do this: First of all, hook only the SEND without anything else. If works well then you hook Send and Recv. Then you keep going till you find where the error is...  |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|