Конференция "Сети" » Перехват Сокетов [D7, WinXP]
 
  • @dimon (25.01.07 08:23) [0]
    В своей программе мне необходимо перехватить функцию Send библиотеки WinSock. Использую глобальный Хук, но почему -то приложение вызывающее WinSock выдает ошибку: "Приложение выполнело недопустимую операцию и будет закрыто". Для других API перехват происходи нормально. В чем может быть причина? Приведу процедуру перехвата.

    function MySock(s:TSocket; var Buf; len, flags: Integer): Integer; stdcall;
    begin
     result:=Send(s,Buf,len,flags);
     MessageBoxA(0, PChar(Buf), 'my hook', 0);
    end;

    procedure ProcessImports(PImports:PImageImportDescriptor);
       Var
           PImport:PImageImportDescriptor;
           PRVA_Import:LPDWORD;
           ProcAddress:pointer;
           Temp_Cardinal:cardinal;
       begin
         ProcAddress:=GetProcAddress(GetModuleHandle('WINSOCK.DLL'), 'Send');
         PImport:=PImports;
         while PImport.Name<>0 do
           begin
             PRVA_Import:=LPDWORD(pImport.FirstThunk+ImageBase);
             while PRVA_Import^<>0 do
             begin
               if PPointer(PRVA_Import)^=ProcAddress
                  then
                    begin
                      VirtualProtect(PPointer(PRVA_Import),4,PAGE_READWRITE,Temp_Cardinal);
                      PPointer(PRVA_Import)^:=@MySock;  
                     VirtualProtect(PPointer(PRVA_Import),4,Temp_Cardinal,Temp_Cardinal);
                    end;
               Inc(PRVA_Import);
             end;
          Inc(PImport);
      end;
    end;


    Примерно так.
  • Сергей М. © (25.01.07 09:36) [1]

    > function MySock(s:TSocket; var Buf; len, flags: Integer):
    >  Integer; stdcall;
    > begin
    >  result:=Send(s,Buf,len,flags);
    >  MessageBoxA(0, PChar(Buf), 'my hook', 0); //<- здесь брейкпойнт ловишь ?
    > end;
    >
  • @dimon (25.01.07 16:00) [2]

    > Сергей М. ©

    Я пытаюсь посмотреть текст проходящий через Сокет. Для эксперимента ставлю
    MessageBoxA. Возможно на нем и происходит ошибка, по крайней мере окно MessageBox не появляется.
  • Сергей М. © (25.01.07 16:08) [3]

    > @dimon   (25.01.07 16:00) [2]


    тебе профому, а ты все про ерему)

    Вопрос поставлен - жду ответа ...
  • Сергей М. © (25.01.07 16:09) [4]

    > текст проходящий через Сокет


    Это тебе Gушкин сказал. что там "проходит" именно текст ?
  • @dimon (25.01.07 17:32) [5]

    > что там "проходит" именно текст ?

    Да проходит именно тект. А вообще на счет MessageBox возникли сомнения. Почему - то не проходит динамическая загрузка библиотеки WinSock. Т.е. код:

    Type
    T=function (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;
    var
     Msg:T;
     h:THandle;
    begin
       h:=LoadLibrary('WinSock.dll');
       @Msg:=GetProcAddress(H,'Send');
       if @Msg=nil then
        ShowMessage('');
    end;



    Выдает ошибку :Библиотека WinSock не является образом программы для Windows NT
  • Сергей М. © (26.01.07 08:15) [6]
    Грузи ws2_32.dll
  • @dimon (26.01.07 08:28) [7]

    > Грузи ws2_32.dll


    Вызов
    @Msg:=GetProcAddress(H,'Send');

    Возвращает
    nil

  • @dimon (26.01.07 08:40) [8]

    > Вызов @Msg:=GetProcAddress(H,'Send'); Возвращает nil

    C этим разобрался (Send = SendTo).Что за библиотека ws2_32.dll? Почему WinSock не грузится?
  • Сергей М. © (26.01.07 08:41) [9]

    > Вызов @Msg:=GetProcAddress(H,'Send'); Возвращает nil


    потому что ф-ция называется "send", а не "Send".
    Прочувствуй разницу)

    p.s. Коль уж ты занялся нетривиальной задачей - перехватом, стыдно не знать такие элементарные вещи, как регистрочувствительность сист.загрузчика к именам экспортируемых символов.
  • @dimon (26.01.07 09:06) [10]
    потому что ф-ция называется "send", а не "Send".


    Вопрос не в этом. Интересно почему не грузится библиотека Winsock.dll. И существует ли другие способы отправки сообщений в сеть, кроме функции send?
  • Сергей М. © (26.01.07 09:32) [11]

    > почему не грузится библиотека Winsock.dll


    Потому что этот модуль не является PE-модулем


    > существует ли другие способы отправки сообщений в сеть,
    > кроме функции send?


    SendTo, WSASend
  • @dimon (26.01.07 09:38) [12]
    На сколько я знаю WSASend из другой версии Winsock. В какой библиотеки она находится? Можно ли получить IP - адрес получателя сообщения посланного функцией send, не перехватывая подключение к серверу?
  • Сергей М. © (26.01.07 09:52) [13]

    > WSASend из другой версии Winsock. В какой библиотеки она
    > находится?


    ws2_32.dll


    > Можно ли получить IP - адрес получателя сообщения посланного
    > функцией send, не перехватывая подключение к серверу?


    Можно, но зачем ?
    Гораздо проще перехватить [WSA]Connect
  • @dimon (26.01.07 10:00) [14]

    > Можно, но зачем ?


    Просто нужно одновременно получить и текст сообщения и кому он предназначен, при том, что функция отправки сообщения неизвестна.
  • Сергей М. © (26.01.07 10:08) [15]

    > функция отправки сообщения неизвестна



    > функция отправки сообщения неизвестна


    Их не так уж и много, всего-то 4 - send, sendto, WSASend, WSASendTo.
    Перехватывай все.


    > нужно одновременно получить и текст сообщения и кому он
    > предназначен


    Это возможно только для connectionless-протоколов и ф-ции [WSA]SendTo - там в параметре фигурирует адресат.
  • Verg © (26.01.07 10:20) [16]
    Либо прилож. делает [WSA]sendto, либо можно узнать via getpeername.
  • @dimon (26.01.07 10:35) [17]

    > либо можно узнать via getpeername

    Можно подробнее?
  • @dimon (26.01.07 10:39) [18]
    Вообще перехватывать необходимо сообщение от Proxy cервера Web Браузеру. Может ли в таком случае использоваться [WSA]send?
  • Сергей М. © (26.01.07 10:52) [19]

    > перехватывать необходимо сообщение от Proxy cервера Web
    > Браузеру


    Прокси - это сервер.
    А сервер никогда не вызывает [WSA]Connect.

    И если уж дело обстоит именно так (т.е. задача - перехватить прикладной траффик между прокси-сервером и его клиентом), то перехват WinsockAPI тут нафиг не нужен - пишется свой прокси-сервер и подключается в цепочку прокси-каскадирования:

    Было:
    Клиент <-> Имеющийся прокси <-> Тырнет

    Стало:
    Клиент <-> Имеющийся прокси <-> Твой прокси <-> Тырнет

    И все ! И незачем все эти выкрутасы с "перехватом")
  • Verg © (26.01.07 11:07) [20]
    int getpeername(
     SOCKET s,
     struct sockaddr* name,
     int* namelen
    );

    The getpeername function retrieves the name of the peer to which a socket is connected.
  • @dimon (26.01.07 11:18) [21]

    > Имеющийся прокси <-> Твой прокси

    И все это на одной машине?
  • Verg © (26.01.07 11:23) [22]

    > Сергей М. ©   (26.01.07 10:52) [19]
    >
    > > перехватывать необходимо сообщение от Proxy cервера Web
    >
    > > Браузеру
    >
    >
    > Прокси - это сервер.
    > А сервер никогда не вызывает [WSA]Connect.


    Ой ли?

    Если сервер - это прокси , то connect-ов там будет.
    На то он и proxy.
  • Сергей М. © (26.01.07 11:29) [23]

    > @dimon   (26.01.07 11:18) [21]
    > И все это на одной машине?


    На любой)
    Как браузер и прокси настроишь, так и оно будет.


    > Verg ©   (26.01.07 11:23) [22]


    Имелась ввиду серверная ипостась прокси-приложения. Разумеется, прокси-приложение в другой его ипостаси само выступает клиентом для других серверов, об этом речь пока не идет.
  • @dimon (26.01.07 16:12) [24]
    Снова проблема! Код
       
     ProcAddress:=GetProcAddress(GetModuleHandle('ws2_32.DLL'), 'send');

    возвращает nil. Вообще Handle библиотеки (GetModuleHandle('ws2_32.DLL')) возвращяется 0, хотя loadlibrary работает.
  • Сергей М. © (26.01.07 16:55) [25]

    > @dimon   (26.01.07 16:12) [24]


    ну ты и упертый мужик, однако)

    ты порло прокси-какскад проинтуичил ? Или об стенку горох ?
  • @dimon (28.01.07 09:14) [26]

    > Сергей М. ©  

    Уже просто интересно как это делается (перехват соектов). Может есть рабочий пример?
  • Сергей М. © (29.01.07 08:20) [27]

    > @dimon   (28.01.07 09:14) [26]


    Ну ты же сделал перехват, и , сам говоришь, успешно)
    Что ж тебе еще надобно, старче ?)
  • @dimon (29.01.07 16:57) [28]

    > Сергей М. ©


    Перехват я сделал, но тестировал его на других функциях. Работало. Переделал его по сокет ( библиотека ws2_32.dll функция send), есть программа (тестовая),которая явно вызывает send, перехватывающая програмка при тестирование ничего не выдает. Приведу полный текст своей Dll, посмотри пожалуйста, что не так.

    library MSock;

    uses
     sysutils,
     windows,
     winsock,
     messages;

    type
      TImageImportDescriptor=packed record
       OriginalFirstThunk    : DWORD;
       TimeDateStamp         : DWORD;
       ForwarderChain        : DWORD;
       Name                  : DWORD;
       FirstThunk            : DWORD;
     end;
     PImageImportDescriptor=^TImageImportDescriptor;

    var filename:array[0..max_path-1] of char;
       hook:HHook=0;
       PEHeader:PImageNtHeaders;
       ImageBase:cardinal;

    function Mysend(s: TSocket; var Buf; len, flags: Integer): Integer;
    stdcall;
    begin
     MessageBox(0,PAnsiChar(Buf),'Перехват сокета',0);
     result:=   Send(s,Buf,Len,flags);
     //Но уже через нашу табл. импорта
    end;
    function MyGetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC;
    stdcall;
    begin
    if lpProcName= 'send' then
     result:=@MySend
     else
     result:=GetProcAddress(hModule,lpProcName);
     //Но уже через нашу табл. импорта
    end;

    procedure ProcessImports(PImports:PImageImportDescriptor);
       Var
           PImport:PImageImportDescriptor;
           PRVA_Import:LPDWORD;
           ProcAddress:pointer;
           GetAdr:pointer;
           Temp_Cardinal:cardinal;
       begin{1}
         ProcAddress:=GetProcAddress(Loadlibrary('ws2_32.DLL'), 'send');
         MessageBox(0,'','',0);
         GetAdr:=GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'GetProcAddress');

         PImport:=PImports;
         while PImport.Name<>0 do
           begin{2}
             PRVA_Import:=LPDWORD(pImport.FirstThunk+ImageBase);
             while PRVA_Import^<>0 do
             begin{3}
               if PPointer(PRVA_Import)^=ProcAddress
                  then
                    begin{4}
                      VirtualProtect(PPointer(PRVA_Import),4,PAGE_READWRITE,Temp_Cardinal);
                      PPointer(PRVA_Import)^:=@MySend; //пишем свою...
                      VirtualProtect(PPointer(PRVA_Import),4,Temp_Cardinal,Temp_Cardinal);
                    end;{1}
                if PPointer(PRVA_Import)^=GetAdr
                  then
                    begin{4}
                      VirtualProtect(PPointer(PRVA_Import),4,PAGE_READWRITE,Temp_Cardinal);
                      PPointer(PRVA_Import)^:=@MyGetProcAddress; //пишем свою...
                      VirtualProtect(PPointer(PRVA_Import),4,Temp_Cardinal,Temp_Cardinal);
                    end;{1}
               Inc(PRVA_Import);
             end;{2}
          Inc(PImport);
      end;{3}
    end;{4}

    procedure DllEntryPoint(reson:longint);stdcall;
    begin
    case reson of
     DLL_PROCESS_ATTACH:
        begin
         DisableThreadLibraryCalls(hInstance);
         ZeroMemory(@FileName, SizeOf(FileName));
         GetModuleFileName(GetModuleHandle(nil), @FileName, SizeOf(FileName));
         ImageBase:=GetModuleHandle(nil);
         PEHeader:=pointer(int64(ImageBase)+PImageDosHeader(ImageBase)._lfanew);//pe header
         ProcessImports(pointer(PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENT RY_IMPORT].VirtualAddress+ImageBase));
         end;
     end;
    end;

    function nexthook(code:integer;wParam,lParam:longint):longint;stdcall;
    begin
     result:=callnexthookex(hook,code,wParam,lParam);
    end;

    procedure sethook(flag:bool);export; stdcall;
    begin
    if flag then
       hook:=setwindowshookex(wh_getmessage,@nexthook,hInstance,0)
    else
      begin
       unhookwindowshookex(hook);
       hook:=0;
      end;
    end;

    exports sethook;

    begin
     DLLProc:=@DllEntryPoint;
     DllEntryPoint(DLL_PROCESS_ATTACH)
    end.
     

  • Сергей М. © (29.01.07 17:07) [29]
    Что говорит отладчик ?
  • @dimon (30.01.07 08:45) [30]
    Отладчик ничего не говорит, но странно:
    GetProcAddress(Loadlibrary('ws2_32.DLL'), 'send');


    возвращает nil. Что на счет рабочего примера?
  • Сергей М. © (30.01.07 09:11) [31]

    > @dimon   (30.01.07 08:45) [30]


    > возвращает nil


    Пробуй так:

    hLib := Loadlibrary('ws2_32.DLL');
    Win32Check(hLib <> 0);
    ProcAddress := GetProcAddress(hLib, 'send');
    Win32Check(Assigned(ProcAddress));

    Какие сообщения показывает этот код ?
  • @dimon (31.01.07 11:12) [32]

    > Какие сообщения показывает этот код ?

    Перехватывающая программа по прежнему ничего не выдает.
  • Сергей М. © (31.01.07 11:34) [33]

    > Перехватывающая программа по прежнему ничего не выдает.
    >


    Раз не выдает, значит твое утверждение в [30] насчет nil заведомо ложное.
  • @dimon (31.01.07 11:44) [34]
    И что делать?
  • Сергей М. © (31.01.07 11:56) [35]
    Как что ? Трассировать дальше ..
  • имя (08.08.07 20:35) [36]
    Удалено модератором
  • имя (08.08.07 20:35) [37]
    Удалено модератором
  • имя (27.11.07 05:18) [38]
    Удалено модератором
  • имя (04.05.08 02:43) [39]
    Удалено модератором
 
Конференция "Сети" » Перехват Сокетов [D7, WinXP]
Есть новые Нет новых   [134431   +15][b:0][p:0.004]