Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > advapihook


Автор: vtih 2.12.2006, 14:40
Хочу с помошью библиотеки advapihook (от ms-rem; wasm.ru, -- http://wasm.ru/pub/21/files/advapihook.rar) перехватить у определенной программы все входящие (recv, WSArecv, -- этого жостаточно будет? [tcp]) пакеты, с целью на лету модифицировать некоторые из них и отдать обратно в программу. Но что-то совсем глупый я, смотрел примеры из этой библиотеки; а именно пример с перехватом winapi, но там они перехватывают вызов из самой библиотеки api, мне же нужно перехватить вызов только в нужной программе. Как это сделать?

Например:
...
  HookProc('user32.dll', 'MessageBoxA', @NewMessageBoxA, @TrueMessageBoxA);
...

Попытки глупо использовать вместо user32.dll, например имя своего же ехе, ни к чему хорошему ни привели.

Автор: W4FhLF 3.12.2006, 10:38
vtih, что за бред ты несёшь? Ты внимательно прочёл статью о перехвате? Что значит из самой библиотеки? А твоя программа при вызове recv думаешь не к библиотеке обращается? 
Ты вызываешь recv и программа через таблицу импорта вызывает процедуру из библиотеки, которая подгружена в адресное пространство твоего процесса, вот именно вначале этой функции и ставится переходник на функцию перехвата. Чтобы перехватывать только в своём процессе достаточно вызвать InjectDll или CreateProcessWithDll из advapihook, далее установится перехват на нужную тебе функцию только лишь в одном процессе.

Автор: vtih 3.12.2006, 11:54
Да, сидел разбирался, вроде чуток понял.

Сделал dll для инжекта в требуемый экзэшник, но к сожалению не понимаю, почему не работает. Для примера не срабатывает ShowMessage на перехваченном Recv. Да и вообще программа отказывается работать с сетью, ну т.е. видимо connect делает, а при первом recv уже начинаются заморочки.

Код

type 
  TwsRecv = function (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;

var 
  OldRecv: TwsRecv;

function NewRecv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; 
begin
  ShowMessage('NewRecv!');
  OldRecv(s, buf, len, flags);
end;

procedure DLLEntryPoint(dwReason: DWord); 
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
    begin
//        StopThreads;
        HookProc('WS2_32.dll', 'recv', @NewRecv, @OldRecv);
        HookProc('WSock32.dll', 'recv', @NewRecv, @OldRecv);
//        RunThreads;
    end;
    DLL_PROCESS_DETACH:
    begin
      UnhookCode(@OldRecv);
    end;
  end;
end;

begin 
  DllProc := @DLLEntryPoint;
  DLLEntryPoint(DLL_PROCESS_ATTACH); 
end.


Заталкиваю dll через CreateProcessWithDll.

Автор: W4FhLF 3.12.2006, 12:15
Вот так попробуй:

Код

var
TwsRecv: function (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;

function NewRecv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; 
begin
asm
pushad
end;
  ShowMessage('NewRecv!');
asm
popad
end;
  Result := TwsRecv(s, buf, len, flags);
end;

procedure DLLEntryPoint(dwReason: DWord); 
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
    begin
        HookProc('WS2_32.dll', 'recv', @NewRecv, @TwsRecv);
    end;
    DLL_PROCESS_DETACH:
    begin
      UnhookCode(@TwsRecv);
    end;
  end;
end;



PS Устанавливать перехват на recv из WSock32.dll смысла нет, ибо она обращается к WS2_32.dll


Автор: vtih 3.12.2006, 12:39
W4FhLF, увы, не помогло это, теперь просто сама программа отлично коннектится и принимает/отправляет данные...

Автор: W4FhLF 3.12.2006, 13:19
Цитата

теперь просто сама программа отлично коннектится и принимает/отправляет данные...


Ну а в чём тогда проблема?

Автор: vtih 3.12.2006, 13:25
Цитата

Ну а в чём тогда проблема?

Ну получается, что не перехватывается Recv, ибо я не вижу результат выполнения SendMessage.

Автор: W4FhLF 3.12.2006, 13:42
Ты уверен, что именно с помощью recv программа получает данные? Попробуй поставить перехват на WSARecv, так же было бы хорошо запустить программу под отладчиком и поставить бряк на recv, дабы посмотреть устаналивается ли переходник или нет.

Автор: vtih 3.12.2006, 14:30
Спасибо! Добавил WSARecv, на нём срабатывает. Но при применении есть маленький недостаток, при выходе из приложение случается AV: инструкция по адресу ... обратилась к памяти по пдресу ... память не может быть read.

Ну и ещё образовались вопросы такие: зачем "экранировать" вызов ShowMessage, pushad - popad'ом?

Например при перехватывании recv оказывается в буфере у меня пакет принятый, необходимо его проверить, переработать чуток (вплоть до изменения размера пакета) и отдать в программу, какие тут могут быть рекомендации?

Автор: W4FhLF 3.12.2006, 14:39
Цитата

инструкция по адресу ... обратилась к памяти по пдресу ... память не может быть read.


Ну тут уже надо анализировать конкретную ситуацию, ничего однозначного сказать невозможно.

Код

Ну и ещё образовались вопросы такие: зачем "экранировать" вызов ShowMessage, pushad - popad'ом?


Это как доп. перестраховка, можешь убрать в прицнипе, команды pushad и popad соответственно сохраняют и восстаналивают значения всех регистров в/из стека.

Цитата

Например при перехватывании recv оказывается в буфере у меня пакет принятый, необходимо его проверить, переработать чуток (вплоть до изменения размера пакета) и отдать в программу, какие тут могут быть рекомендации?


Ну прежде всего при изменении размера не забывай про параметр len функции recv, это важно. Во-вторых я бы посоветовал при изменении размера(а если он будет изменяться в большую сторону, то это вообще незибежно) выделять новый буфер под даннеые и работать с ним, при это не забывай переписывать указатель в параметре Buf.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)