Solved

Rlibby's Win32Hook

Posted on 2006-11-21
14
611 Views
Last Modified: 2011-09-20
////////////////////////////////////////////////////////////////////////////////
//
//   Library        :  Hook
//   Author         :  Russell Libby
//   Date           :  05.19.2006
//   Description    :  Hooking dll that updates the import address table for
//                     CreateFileA and displays a message box when the function
//                     is called.
//
////////////////////////////////////////////////////////////////////////////////
library Hook;

////////////////////////////////////////////////////////////////////////////////
//   Include units
////////////////////////////////////////////////////////////////////////////////
uses
  Windows,
  SysUtils,
  Win32Hook,Winsock;

////////////////////////////////////////////////////////////////////////////////
//   Resources
////////////////////////////////////////////////////////////////////////////////
{$R *.RES}

////////////////////////////////////////////////////////////////////////////////
//   Library defines
////////////////////////////////////////////////////////////////////////////////
type
  TCreateFileA      =  function(lpFileName: PChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
  TCreateFileW      =  function(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
  TCreateConnect  =    function(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;


////////////////////////////////////////////////////////////////////////////////
//   Library variables
////////////////////////////////////////////////////////////////////////////////
var
  lpCreateFileA:    TCreateFileA   =  nil;
  lpCreateFileW:    TCreateFileW   =  nil;
  Lpconnect:   TCreateConnect = Nil;
////////////////////////////////////////////////////////////////////////////////
//   Library hook callback
////////////////////////////////////////////////////////////////////////////////

function Hook_connect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
Begin
MessageBox(0, 'API Connect', 'Connect ', MB_OK);
 if Assigned(@Lpconnect) then
     // Leave the file name alone and pass on
     result:=Lpconnect(S,Name,namelen)
  else
     // Original function pointer is not assigned
     result:=$FFEE;
End;

function HookCreateFileA(lpFileName: PChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
begin

  // Display message of the file to create / open
  MessageBox(0, lpFileName, 'HookCreateFileA', MB_OK);

  // Check the old function pointer (sanity check)
  if Assigned(@lpCreateFileA) then
     // Leave the file name alone and pass on
     result:=lpCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
  else
     // Original function pointer is not assigned
     result:=INVALID_HANDLE_VALUE;

end;

function HookCreateFileW(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
begin

  // Display message of the file to create / open
  MessageBox(0, PChar(String(WideString(lpFileName))), 'HookCreateFileW', MB_OK);

  // Check the old function pointer (sanity check)
  if Assigned(@lpCreateFileW) then
     // Leave the file name alone and pass on
     result:=lpCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
  else
     // Original function pointer is not assigned
     result:=INVALID_HANDLE_VALUE;

end;

////////////////////////////////////////////////////////////////////////////////
//   DllMain
////////////////////////////////////////////////////////////////////////////////
procedure DllMain(Reason: Integer);
begin

  // We only care about the process attach
  if (Reason = DLL_PROCESS_ATTACH) then
  begin
     // Display message box
     MessageBox(0, 'Process Attach', nil, MB_OK);
     // Create import address update object
     with TImportAddress.Create do
     begin
        // Resource protection
        try
           // Don't unpatch on free
           UnpatchOnFree:=False;
           // Patch the CreateFileA/W functions
           Patch('WSock32','Connect', @Hook_connect, @Lpconnect);
           Patch('kernel32', 'CreateFileA', @HookCreateFileA, @lpCreateFileA);
           Patch('kernel32', 'CreateFileW', @HookCreateFileW, @lpCreateFileW);
        finally
           // Free the object                  // lpCreateFileW:    TCreateFileW   =  nil;
           Free;                               // Lpconnect:   TCreateConnect = Nil;
        end;
     end;
  end;

end;

////////////////////////////////////////////////////////////////////////////////
//   Library entry point
////////////////////////////////////////////////////////////////////////////////
begin

  // Set the entry point for the library
  DLLProc:=@DllMain;

  // We must call with process attach now, cause this is our cue
  DllMain(DLL_PROCESS_ATTACH)

end.
 

 Patch('WSock32','Connect', @Hook_connect, @Lpconnect);

I know it finds the library, anyone have any idea why it's not hooking the connect?...

What my intention is, (what i originally tried) was to hook
gethostbyname (which failed) so i tried Connect, and i failed at that as well lol

gethostbyname - the intention, to redirect yahoo messenger from connecting to yahoo but instead point it to lto local host (127.0.0.1) and feed the packets into my own program which (proxies it) and spits them out to yahoo... but  well yeah that's another story lol, if i can't even get it to inject properly...

RLibby, I know you're probably getting sick of me but seriously if you help i promise to leave you alone for a while <grins>

Thanks :)
0
Comment
Question by:tobjectpascal
  • 7
  • 6
14 Comments
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17992541

If you have the library injected (should see the message box),  then it could be that yahoo msgr uses dynamic binding on wsock32 vs static binding. IAT patching is only useful if static binding is used. You might want to try using the TCodeRewrite class  instead (which will overwrite the address contents for Connect)

Russell

0
 
LVL 4

Author Comment

by:tobjectpascal
ID: 17992596
Actually, i tried it on my own little program..

Program getcookieprog;

uses
  Windows,
  Messages,
  Winsock;

Var
  hWin: Integer;
  WindowHandle: HWND;
  BH,EH,Eh2,Eh3: Integer;
  Cookie,S: String;
  Len: Integer;
  UserName,PassWord: String;

const
  CrLf = #$0d+#$0a;
  MULTIEDIT1 = 1;
  EditBox2 = 2;
  Button = 3;

Function Display(Hnd: Hwnd; S: String): Boolean;
Begin
 SendMessage(Hnd,wm_settext,0,Integer(Pchar(S)));
End;

Function GetText(Hnd: Hwnd): String;
Var
 L: Integer;
 S: String;
Begin
 L:=SendMessage(hnd,wm_gettextlength,0,0);
 SetLength(S,L+1);
 SendMessage(Hnd,wm_Gettext,L+1,Integer(Pchar(S)));
 Result:=S;
End;

Function Trim(S: String): String;
Begin
 If Length(S)>0 Then
  While (S[1]=' ') Do
   If S[1]=' ' Then
     Delete(S,1,1)
      else
     Break;

 If Length(S)>0 Then
  While (S[Length(S)]=' ') Do
   If S[Length(S)]=' ' Then
     Delete(S,Length(S),1)
      else
     Break;
End;

Function IntToStr(Val2: Longint): String;
Begin
 Str(Val2,Result);
End;

Function StrToInt(Val2: String): Integer;
Var
 Err: Integer;
Begin
 Val(Val2,Result,Err);
 If Err<>0 Then
   Result:=Err;
End;

Function LowerCase(S: String): String;
Var
 N: Integer;
Begin
 For N:=1 to Length(S) Do
  Begin
   if S[N] in['A'..'Z'] then
      S[N] := chr(ord(S[N]) + 32);
  End;
 Result:=S;
end;

Function UpperCase(S: String) : String;
Var
 N: Integer;
Begin
 For N:=1 to Length(S) Do
  Begin
   if S[N] in['a'..'z'] then
      S[N] := chr(ord(S[N]) - 32);
  End;
  Result:=S;
end;

Procedure SendText(SH: Tsocket; S: String);
Begin
 Send(Sh,S[1],Length(s),0);
End;


Function PArseOutCookie(Data: String): String;
Var
   Cookie1,Cookie2,Tmp,Tmp2: String;
begin
  Tmp:=Data;
  Tmp2:=Tmp;
  Delete(Tmp2,1,Pos('Set-Cookie:',Tmp)+11);
  Tmp2:=Copy(Tmp2,1,Pos('expires',Tmp2)-2);
  Delete(Tmp,1,Pos('Set-Cookie',Tmp));
  Delete(Tmp,1,Pos('Y=v',Tmp)-1);
  Cookie1:=Copy(Tmp,1,pos(';',Tmp));
  Delete(Tmp,1,Length(Cookie1));
  Delete(Tmp,1,Pos('Set-Cookie',Tmp));
  Delete(Tmp,1,Pos('T=z',Tmp)-1);
  Cookie2:=Copy(Tmp,1,pos(';',Tmp));
  Delete(Tmp,1,Length(Cookie2));
  Cookie:=Tmp2+' '+Cookie1+' '+Cookie2;
  If (Cookie<>'') and (Pos('Y=v',Cookie)>0) Then
   Begin
    Display(Eh,'Cookie Success! '+Cookie);
    Result:=Cookie;
   End
     else
   Begin
     Display(Eh,'Cookie Authentication Failed..');
     Cookie:='';
   End;
End;

Function GetCookie(P: Pointer): Longint; Stdcall;
Var
  mysock : TSocket;
  hp : phostent;
  a : tsockaddr;
  WSAData: TWSAData;
  Strbuffer : String;
  Buffer: Array[0..2048] of Char;
  st, tt : longint;
  ParamStr,SearchStr,ipaddress:string;
  i: integer;
Begin
  UserName:=Copy(GetText(Eh2),1,pos(#0,GetText(Eh2))-1);
  Password:=Copy(GetText(Eh3),1,pos(#0,GetText(Eh3))-1);
  WSAStartup($0101, WSAData);
  mysock := socket(AF_INET, SOCK_stream, ipproto_tcp);
  hp := gethostbyname('edit.yahoo.com');
    if hp = nil then
      begin
        Display(Eh,'Could Not Resolve Name...');
        exit;
      end
    else
      begin
        for i := 0 to hp^.h_length - 1 do
          IPAddress:=IpAddress+IntToStr(Ord(Hp.h_addr_list^[i]))+'.';
          SetLength(IPAddress,Length(IPaddress)-1);
        end;
  a.sin_family := AF_INET;
  a.sin_port := htons(80);
  A.sin_addr.S_addr:=inet_addr(Pchar(IpAddress));
  I:=connect(mysock, a, sizeof(a));

 //this is where i was expecting the hook

  If I<>0 Then Exit;
  ParamStr:='GET /config/login?.tries=1&.src=chat&.last=&promo='
  +'&lg=us&.intl=us&.bypass=&.chkP=Y&.done=http%3A%2F%2'
  +'Fchat.yahoo.com%2F%3Froom%3D30%2527s%253a%253a1600326617&login'
  +'='+UserName+'&passwd='+Password+' HTTP/1.1'+CrLf+'Accept: */*'+CrLf+'Accept-Language: en-us'+CrLf+'User-Agent: Mozilla/4.0'
  +'(compatible; MSIE 6.0; Windows NT 5.1)'+CrLf+'Host: login.yahoo.com'+CrLf+'Connection:'
  +' Keep-Alive'+CrLf+CrLf+'';
  Move(ParamStr[1],Buffer,Length(ParamStr));
  Display(Eh,'Requesting Cookie...');
  Sleep(300);
  SendText(MySock,ParamStr);
  Repeat
   I:=recv(mysock, buffer, sizeof(buffer),0);
  Until I=0;
  Cookie:=ParseOutCookie(Buffer);
  Display(Eh,Cookie);
  closesocket(mysock);
End;


function WinProc(hWnd,uMsg,wPar,lPar:Integer):Integer; stdcall;
Var
  Th: THandle;
begin
 //Writeln(Umsg,'  ',wpar,'  ',lpar);
case uMsg of
 WM_Command:
   Begin
    If Lpar=Integer(BH) Then
     Begin
      // PostQuitMessage(0);
      CreateThread(Nil,0,@GetCookie,Nil,0,Th);
     End;
//    Writeln(Umsg,'  ',wpar,'  ',lpar);
   End;
 WM_CLOSE:
   begin
    PostQuitMessage(0);
    Result:=0;
   End;
    else Result:=DefWindowProc(hWnd,uMsg,wPar,lPar);
  end;
end;

 var
  Msg: TMsg;
  wClass: TWndClass;
  Active: Boolean=True;
  Font: HFONT;
begin
 with wClass do
   begin
     style:=0;
     lpfnWndProc:=@WinProc;
     cbClsExtra:=0;
     cbWndExtra:=0;
     hInstance:=hInstance;
     hIcon:=LoadIcon(hInstance,'MAINICON');
     hCursor:=LoadCursor(0,IDC_ARROW);
     hbrBackground:=COLOR_BTNFACE+1;
     lpszMenuName:=nil;
     lpszClassName:='someclass';
end;

  RegisterClass(wClass);
  hWin:=CreateWindow('someclass','Tobject''s Cookie Extractor ;-)',
  WS_VISIBLE or WS_THICKFRAME or WS_OVERLAPPED or WS_SYSMENU,
  0,0,400,123,0,0,hInstance,nil);

 EH:=CreateWindow('EDIT','', ES_AUTOHSCROLL or WS_Border or WS_Child or WS_Visible,1,1,389,20,Hwin,EditBox2,Hinstance,Nil);
 BH:=CreateWindow('BUTTON','GetCookie',BS_PUSHBUTTON Or WS_VISIBLE OR WS_CHILD, 1,22,389,20, Hwin, Button, 0,Nil);

 EH2:=CreateWindow('EDIT','', ES_AUTOHSCROLL or WS_Border or WS_Child or WS_Visible,1,47,389,20,Hwin,EditBox2,Hinstance,Nil);
 EH3:=CreateWindow('EDIT','', ES_AUTOHSCROLL or WS_Border or WS_Child or WS_Visible,1,73,389,20,Hwin,EditBox2,Hinstance,Nil);
  SendMessage(Eh,wm_SetFont,Integer(Font),Longint(True));
  SendMessage(Bh,wm_SetFont,Integer(Font),Longint(True));

  Display(Eh,'***Cookie Displays Here*****');
  Display(Eh2,'UserName');
  Display(Eh3,'Password');
//  Display(Eh,GetText(Eh3));


 while Active do
  begin
  if PeekMessage(Msg,hWin,0,0,PM_NOREMOVE) then
   begin
     Active:=Longint(GetMessage(Msg,hWin,0,0))<>0;
     TranslateMessage(Msg);
     DispatchMessage(Msg);
//     Sleep(580);
  end else WaitMessage;
end;

end.

since it failed on my own program i never tried it on anything else.
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17992624

And where is the hook in that code? or are you injecting a dll (first example shows 'hook.dll') from another process?....

Little more info would be helpful...



0
 
LVL 4

Author Comment

by:tobjectpascal
ID: 17992642
i thought all i needed to do was alter the dll, the program that injects dll need not be changed...

I changed your console inject for a prettier VCL version, but it's identical

unit spypro;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls,Win32Hook;

const
  SZ_HOOKDLL        =  '\hook.dll';

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;



var
  Form1: TForm1;
  lpPI:             TProcessInformation;
  lpSA:             TSecurityAttributes;
  lpSI:             TStartupInfo;
  szFilePath:       String;
  dwSize:           Integer;


implementation

{$R *.DFM}


procedure InitializeSecurity(var SA: TSecurityAttributes);
var  sd:            PSecurityDescriptor;
begin

  // Allocate memory for the security descriptor
  sd:=AllocMem(SECURITY_DESCRIPTOR_MIN_LENGTH);

  // Initialise the new security descriptor
  if InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION) then
  begin
     // Add a NULL descriptor ACL to the security descriptor
     if SetSecurityDescriptorDacl(sd, True, nil, False) then
     begin
        // Set up the security attributes structure
        with SA do
        begin
           nLength:=SizeOf(TSecurityAttributes);
           lpSecurityDescriptor:=sd;
           bInheritHandle:=True;
        end;
     end
     else
        // Failed to init the sec descriptor
        RaiseLastWin32Error;
  end
  else
     // Failed to init the sec descriptor
     RaiseLastWin32Error;
end;

procedure FinalizeSecurity(var SA: TSecurityAttributes);
begin
  // Release memory that was assigned to security descriptor
  if Assigned(SA.lpSecurityDescriptor) then
  begin
     // Free memory
     FreeMem(SA.lpSecurityDescriptor);
     // Clear pointer
     SA.lpSecurityDescriptor:=nil;
  end;
end;

Procedure InjectProcess(Fn: String);
Begin
 // Set buffer size
  SetLength(szFilePath, Succ(MAX_PATH));
  // Get application filename
  dwSize:=GetModuleFileName(0, Pointer(szFilePath), MAX_PATH);
  // Reset to actual string size
  SetLength(szFilePath, dwSize);
  // Extract file path from the application name
  szFilePath:=ExcludeTrailingBackslash(ExtractFilePath(szFilePath));
  // Initialize a null security descriptor
  InitializeSecurity(lpSA);
  // Clear startup structures
  FillChar(lpPI, SizeOf(lpPI), #0);
  FillChar(lpSI, SizeOf(lpSI), #0);

  // Set default flags
  lpSI.cb:=SizeOf(lpSI);
  lpSI.dwFlags:=STARTF_USESHOWWINDOW;
  lpSI.wShowWindow:=SW_SHOW;

  // Resource protection
  try
     // Attempt to create the notepad process
     if CreateProcess(nil, Pchar(Fn), @lpSA, @lpSA, True, NORMAL_PRIORITY_CLASS, nil, PChar(szFilePath), lpSI, lpPI) then
     begin
        // Process was created
        try
           // Wait for input idle so we are sure the app is in a state where we can inject
           WaitForInputIdle(lpPI.hProcess, 2000);
           // Inject the library into the
           with TLibraryInject.Create do
           begin
              // Resource protection
              try
                 // Don't want to unload on free
                 UnloadOnFree:=False;
                 // Inject the hook library into the target process
                 Add(lpPI.dwProcessId, szFilePath+SZ_HOOKDLL);
              finally
                 // Free the injection class
                 Free;
              end;
           end;
        finally
           // Need to close the handles we got back
           CloseHandle(lpPI.hThread);
           CloseHandle(lpPI.hProcess);
        end;
     end;
  finally
     // Finalize the security descriptor
     FinalizeSecurity(lpSA);
  end;
End;


procedure TForm1.Button1Click(Sender: TObject);
Var
 Fn: String;
begin
 OpenDialog1.Execute;
 Fn:=OpenDialog1.FileName;
 If Fn<>'' Then
   InjectProcess(FN);
end;

end.


This works perfectly fine when it comes to

function HookCreateFileW(lpFileName: PWideChar;

It's interesting to watch yahoo messenger load up with this hook....

But when i try and hook wsock32 of any app, there's no errors, it just don't display a message box to show me it's working... kinda odd, am i missing something?
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17992805
>> thought all i needed to do was alter the dll, the program that injects dll need not be changed...

It helps to post all the related code, especially when your taking parts of my code to come up with an example. I need some sort of context as to what you are doing in order to be of any help to you.

As to the problem, the code is not hooking. As to the why:

It is NOT 'Connect'... its 'connect'. ALL lowercase. GetProcAddress is case sensitive and is failing to resolve the function name, thus no hooking.

Russell
0
 
LVL 4

Author Comment

by:tobjectpascal
ID: 17992911
AH.and then he tried "connect" and yet he still gets no message box...

what i've ruled out, wsock32 is fine, it returns a handle when loading the dll, getproc address returns a pointer to connect fine.

rlibby, have you ever tried hooking winsock? is it even possible ?...

i have no firewall (just AVG) my modem/router take care of the firewall for me, so when it's all internal, there's nothing left to prevent anything from working..

i'm on 2K.

for now i'm hooking a simple program i wrote ,or at least trying...

I know i'm a pain in the behind :)

0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17992957

Yes, I have already tried it and it works fine. Are you now talking about your own app now or ym?

First, determine where the issue resides:

- Do you get a message box on the inject? If not then the injection is failing. If yes, then the process attach is firing and the import address table is being scanned and patched. Add debug code (message boxes) if you are unsure of something working or not. The Patch function also returns a boolean result, what is the result from that?
- If the patch is NOT going through ok (should not be the case for your app, as using WinSock will static bind to wsock32) and ym msgr is not firing the connect then try using the TCodeRewrite. This works regardless if the app is using static / dynamic binding.

If I had 5 minutes, I'd rip a demo, but I don't have the time right now... If your still having problems then I will put together a demo app in a day or 3 (T-Day coming up you know, no time @ the moment).

And yes, you tend to be <g>

Russell
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 4

Expert Comment

by:David_Ward
ID: 18006645
have you ever tried hooking winsock? is it even possible ?...

I would think so; it is certainly possible to monitor any-and-all  traffic ...

"Mr L Erwan" has provided the perfect vehicle for this with his "Promiscuous IP Sniffer" - available here:
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=7&txtCodeId=962

(You will need to create an account here, if, you have not got one)
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 18023205
Downloaded and tested on YM. As I suggested, the TCodeRewrite works just fine (YM uses dynamic binding on wsock32).

Russell

--

////////////////////////////////////////////////////////////////////////////////
//
//   Library        :  Hook
//   Author         :  rllibby
//   Date           :  11.27.
//   Description    :  Hooking dll that rewrites the code for the connect function,
//                     allowing the library to catch all calls to connect.
//
////////////////////////////////////////////////////////////////////////////////
library Hook;

////////////////////////////////////////////////////////////////////////////////
//   Include units
////////////////////////////////////////////////////////////////////////////////
uses
  Windows,
  SysUtils,
  WinSock,
  Win32Hook;

////////////////////////////////////////////////////////////////////////////////
//   Resources
////////////////////////////////////////////////////////////////////////////////
{$R *.RES}

////////////////////////////////////////////////////////////////////////////////
//   Library defines
////////////////////////////////////////////////////////////////////////////////
type
  TConnect             =  function(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;

////////////////////////////////////////////////////////////////////////////////
//   Library variables
////////////////////////////////////////////////////////////////////////////////
var
  lpConnect:        TConnect       =  nil;

////////////////////////////////////////////////////////////////////////////////
//   Library hook callbacks
////////////////////////////////////////////////////////////////////////////////
function HookConnect(s: TSocket; var name: TSockAddr; namelen: Integer): Integer; stdcall;
begin

  // Display message indicating the connect is occurring
  MessageBox(0, 'connect has been called', nil, MB_OK);

  // Check the old function pointer (sanity check)
  if Assigned(@lpConnect) then
     // Call the original function
     result:=lpConnect(s, name, namelen)
  else
     // Original function pointer is not assigned
     result:=SOCKET_ERROR;

end;

////////////////////////////////////////////////////////////////////////////////
//   DllMain
////////////////////////////////////////////////////////////////////////////////
procedure DllMain(Reason: Integer);
begin

  // We only care about the process attach
  if (Reason = DLL_PROCESS_ATTACH) then
  begin
     // Display message box
     MessageBox(0, 'Injected library has attached to Yahoo Messenger!', nil, MB_OK);
     // Create code rewrite object
     with TCodeRewrite.Create do
     begin
        // Resource protection
        try
           // Don't unlink on free
           UnlinkOnFree:=False;
           // Hook the connect method
           if not(Link(GetProcAddress(GetModuleHandle('wsock32.dll'), 'connect'), @HookConnect, @lpConnect)) then
              MessageBox(0, 'Failed to rewrite the "connect" function', nil, MB_OK or MB_ICONERROR)
           else
              MessageBox(0, 'Code written for the "connect" function', nil, MB_OK or MB_ICONINFORMATION);
        finally
           // Free the object
           Free;
        end;
     end;
  end;

end;

////////////////////////////////////////////////////////////////////////////////
//   Library entry point
////////////////////////////////////////////////////////////////////////////////
begin

  // Set the entry point for the library
  DLLProc:=@DllMain;

  // We must call with process attach now, cause this is our cue
  DllMain(DLL_PROCESS_ATTACH)

end.
0
 
LVL 4

Author Comment

by:tobjectpascal
ID: 18024116
unit spypro;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls,Win32Hook;

const
  SZ_HOOKDLL        =  '\hook.dll';

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;



var
  Form1: TForm1;
  lpPI:             TProcessInformation;
  lpSA:             TSecurityAttributes;
  lpSI:             TStartupInfo;
  szFilePath:       String;
  dwSize:           Integer;


implementation

{$R *.DFM}


procedure InitializeSecurity(var SA: TSecurityAttributes);
var  sd:            PSecurityDescriptor;
begin

  // Allocate memory for the security descriptor
  sd:=AllocMem(SECURITY_DESCRIPTOR_MIN_LENGTH);

  // Initialise the new security descriptor
  if InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION) then
  begin
     // Add a NULL descriptor ACL to the security descriptor
     if SetSecurityDescriptorDacl(sd, True, nil, False) then
     begin
        // Set up the security attributes structure
        with SA do
        begin
           nLength:=SizeOf(TSecurityAttributes);
           lpSecurityDescriptor:=sd;
           bInheritHandle:=True;
        end;
     end
     else
        // Failed to init the sec descriptor
        RaiseLastWin32Error;
  end
  else
     // Failed to init the sec descriptor
     RaiseLastWin32Error;
end;

procedure FinalizeSecurity(var SA: TSecurityAttributes);
begin
  // Release memory that was assigned to security descriptor
  if Assigned(SA.lpSecurityDescriptor) then
  begin
     // Free memory
     FreeMem(SA.lpSecurityDescriptor);
     // Clear pointer
     SA.lpSecurityDescriptor:=nil;
  end;
end;

Procedure InjectProcess(Fn: String);
Begin
 // Set buffer size
  SetLength(szFilePath, Succ(MAX_PATH));
  // Get application filename
  dwSize:=GetModuleFileName(0, Pointer(szFilePath), MAX_PATH);
  // Reset to actual string size
  SetLength(szFilePath, dwSize);
  // Extract file path from the application name
  szFilePath:=ExcludeTrailingBackslash(ExtractFilePath(szFilePath));
  // Initialize a null security descriptor
  InitializeSecurity(lpSA);
  // Clear startup structures
  FillChar(lpPI, SizeOf(lpPI), #0);
  FillChar(lpSI, SizeOf(lpSI), #0);

  // Set default flags
  lpSI.cb:=SizeOf(lpSI);
  lpSI.dwFlags:=STARTF_USESHOWWINDOW;
  lpSI.wShowWindow:=SW_SHOW;

  // Resource protection
  try
     // Attempt to create the notepad process
     if CreateProcess(nil, Pchar(Fn), @lpSA, @lpSA, True, NORMAL_PRIORITY_CLASS, nil, PChar(szFilePath), lpSI, lpPI) then
     begin
        // Process was created
        try
           // Wait for input idle so we are sure the app is in a state where we can inject
           WaitForInputIdle(lpPI.hProcess, 2000);
           // Inject the library into the
           with TLibraryInject.Create do
           begin
              // Resource protection
              try
                 // Don't want to unload on free
                 UnloadOnFree:=False;
                 // Inject the hook library into the target process
                 Add(lpPI.dwProcessId, szFilePath+SZ_HOOKDLL);
              finally
                 // Free the injection class
                 Free;
              end;
           end;
        finally
           // Need to close the handles we got back
           CloseHandle(lpPI.hThread);
           CloseHandle(lpPI.hProcess);
        end;
     end;
  finally
     // Finalize the security descriptor
     FinalizeSecurity(lpSA);
  end;
End;


procedure TForm1.Button1Click(Sender: TObject);
Var
 Fn: String;
begin
 OpenDialog1.Execute;
 Fn:=OpenDialog1.FileName;
 If Fn<>'' Then
   InjectProcess(FN);
end;

end.

Is there anything i have to modify for the application that injects the dll? because it seems to be doing nothing for me...

But thanks for all your effort :)
0
 
LVL 26

Accepted Solution

by:
Russell Libby earned 50 total points
ID: 18024420
Define "does nothing"... Is the library being injected or not?

If no - ensure that the hook library is in the same path as your loader application, because thats what the example code you are using is expecting. If the hook dll location is correct, where does the Add(...) function bail out when single stepping through?

function TLibraryInject.Add(ProcessID: DWORD; LibraryName: String): Integer;
var  hKernel:       HMODULE;
     hProcess:      THandle;
     hThread:       THandle;
     dwNull:        Cardinal;
     lpRemote:      PLibRemote;
     lpLibRemote:   PChar;
begin

  // Enter critical section
  EnterCriticalSection(FLock);

  // Resource protection
  try
     // Set default result of (-1), which means the injection failed
     result:=(-1);
     // Check library name and version of OS we are running on
     if (Length(LibraryName) > 0) and ((GetVersion and $80000000) = 0)then
     begin
        // Attempt to open the process
        hProcess:=OpenProcess(PROCESS_ALL_ACCESS, False, ProcessID);
        // Check process handle
        if (hProcess <> 0) then
        begin
           // Resource protection
           try
              // Get module handle for kernel32
              hKernel:=GetModuleHandle('kernel32');
              // Check handle
              if (hKernel <> 0) then
              begin
                 // Allocate memory in other process
                 lpLibRemote:=VirtualAllocEx(hProcess, nil, Succ(Length(LibraryName)), MEM_COMMIT, PAGE_READWRITE);
                 // Check memory pointer
                 if Assigned(lpLibRemote) then
                 begin
                    // Resource protection
                    try
                       // Write the library name to the memory in other process
                       WriteProcessMemory(hProcess, lpLibRemote, PChar(LibraryName), Length(LibraryName), dwNull);
                       // Create the remote thread
                       hThread:=CreateRemoteThread(hProcess, nil, 0, GetProcAddress(hKernel, 'LoadLibraryA'), lpLibRemote, 0, dwNull);
                       // Check the thread handle
                       if (hThread <> 0) then
                       begin
                          // Resource protection
                          try
                             // Allocate a new remote injection record
                             lpRemote:=AllocMem(SizeOf(TLibRemote));
                             // Set process id
                             lpRemote^.ProcessID:=ProcessID;
                             // Copy library name
                             StrPLCopy(lpRemote^.LibraryName, LibraryName, MAX_LIBRARYNAME);
                             // Wait for the thread to complete
                             WaitForSingleObject(hThread, INFINITE);
                             // Fill in the library handle
                             GetExitCodeThread(hThread, DWORD(lpRemote^.LibraryHandle));
                             // Add to list
                             result:=FInjectList.Add(lpRemote);
                          finally
                             // Close the thread handle
                             CloseHandle(hThread);
                          end;
                       end;
                    finally
                       // Free allocated memory
                       VirtualFree(lpLibRemote, 0, MEM_RELEASE);
                    end;
                 end;
              end;
           finally
              // Close the process handle
              CloseHandle(hProcess);
           end;
        end;
     end;
  finally
     // Leave critical section
     LeaveCriticalSection(FLock);
  end;

end;

---

If yes - You should be seeing 2 dialogs, one to indicate the injection and the other to verify the hook install/failure to install. I need to know if you see either one of these, and which ones.

---

As for what I did:
- I installed YahooMessenger
- modified the loader app to load / inject into YahooMessenger.exe
- compiled the hook code I gave you above, hook.dll exists in same location as hook loader app.
- ran the loader
- got message box indicating injection
- got message box indicating code mod
- got 5 messages generated from the connect hook.



0
 
LVL 4

Author Comment

by:tobjectpascal
ID: 18197756
ooooooooooppppppsssssssss


1. sorry i thought for some reason i closed this thread.
2. i was right, it was not connecting for me but then i'm a moron lol, i was using Yahoo Messenger 6, 8 works great with the code...

Again, I am sorry for all that trouble.


Thank You :).
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 18405891
Btw, this Q is still not closed

Russell


0
 
LVL 4

Author Comment

by:tobjectpascal
ID: 18409987
lol


i honeslty did think i closed it lol.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now