Как сделать сетевой снифер, снифающий трафик в режиме обычного юзера?(в режиме админа и так удалось) Вот мой код: Code: procedure TForm1.Button1Click(Sender: TObject); var inaddrlist: PInAddrList; szHostName: array[0..127] of AnsiChar; phe:PHostEnt; sa:sockaddr_in; sock:TSocket; flag:Integer; buffer : Array[0..MaxPacketSize - 1] of byte; hdr : PIPHeader; outstr,tmpS: AnsiString; Len:Word; siz,ps:Integer; begin sock := socket(AF_INET, SOCK_RAW, IPPROTO_IP); if sock = INVALID_SOCKET then exit; if gethostname(szHostName, sizeof(szHostName)) <> 0 then Exit; phe:=gethostbyname(@szHostName); if phe = Nil then exit; ZeroMemory(@sa,sizeof(sa)); inaddrlist:=PInAddrList(phe.h_addr_list); // Привязываемся к нашему сокету :) sa.sin_family := AF_INET; sa.sin_addr.S_addr := inaddrlist^[0].S_addr; if (bind(sock, sa, sizeof(sa)) = SOCKET_ERROR) then Exit; flag:=1; if ioctlsocket(sock, SIO_RCVALL, flag) = SOCKET_ERROR then exit; work:=true; while work do begin // Ждем пакет :) siz:=recv(sock, Buffer, sizeof(Buffer), 0); if (siz = SOCKET_ERROR) then begin // Бывают же глюки :) flag := WSAGetLastError; break; end; // Если пакет имеет размер с заголовок или больше, то это - хорошо :) if (siz >= sizeof(TIPHeader)) then begin // Печатаем tmpS:=ByteToansiString(@Buffer[40],siz-40); Memo1.Text:=memo1.Text+tmpS+#13#10; Break; end; Application.ProcessMessages; end; end; closesocket(sock); end; Сырые сокеты не хотят создаватся в юзер режиме. Но Http Analyzer как-то же работает.
Да, ты прав. Для 3-ей версии сниффера библиотека называеться HookWinSockV3.dll. Важно заметить, что перехват пакетов от Google Chrome входящих и исходящих работает неправильно.
Прочитай для начала эту статью: http://www.codenet.ru/progr/delphi/stat/api-hook.php Если хочешь перехватывать траффик с помощью инжектирования своей библиотеки, ты должен перехватывать функции recv, send, WSARecv, WSASend (находяться в Ws2_32.dll).
есть winpcap.org там даже фильтр пакетов со слов компилирует нужный код. попробуй его - единственное что под вопросом - сможешь ли ты к нему OpenFile от юзера осуществить
Угу, у меня никогда не запускался, интерфейс Dial-up'а не перехватаывает, сколько не пробовал. А почти все поголовно сниферы через него работают, одно ток спасенье - HttpAnalyzerStd, а он не устраивает тем что только с порта 80 перехватывает HTTP трафик, а бывает что не по 80-ому(HTTP прокси к примеру).
Ставится CommView и без проблем всё снифается на любом типе подключения Dial Up/VPN/Lan/WiFi/etc потому что он добавляет свой драйвер везде где только можно. Конечно SSL не расшифрует, но gzip на лету умеет распаковывать.
Еще раз спасибо за ответы, он вот не получается у меня инжектирование в Фаерфоксе 2.0 . В 3-ме норм все.
А я вообще выбрал радикальное но самое эффективное решение. Я поставил логгер - то кто более-менее шарит в кодинге понимает что это такое. Я просто логирую входящие и исходящие пакеты в него, там естественно можно сортировать по всем данным. Но самое главное - из множества потоков можно выбрать один и будут показаны запросы только с него. Это оченб удобно, а все остальное ***ня. Пляс я могу отлаживать отдаленно - компилю с помощью условной компиляции 2 экзе один релизный другой дебажный, когда у клиента что-то не работает он запускает дебажную, и мне в реальном времени все видно как работает прога. Есть несколько способов логирования кроме как по сети. В итоге это самый лучший способ найти баг или еще что-то в многопоточной проге, ever. Лично я юзаю SmartInspect - вместо того чтобы ебаться отлаживать многопоточную прогу часами я посмотрю в логи 10 минут, исправлю то что нужно и пойду пить пиво )). Есть порты на дельфи, сишарп и еще какие то языки.
Сначала думал сделать с помощью очереди сообщений, но потом понял что это не получится если приложение будет консольным. Или все же как-то можно? Если нет, то какой технологией лучше всего передавать данные между процессами?
возможный вариант ServerSlot находится в вашей программе создает слот и ждет сообщений ClientSlot находится в библиотеке в другом процессе открывает созданный вами слот и пишет в него то что награбил вот пример Code: #define MAX_SLOT_CHUNK 512 DWORD WINAPI ServerSlot(HANDLE hInitCompleted) { HANDLE hSlot = CreateMailslot("\\\\.\\mailslot\\sniff", 0, MAILSLOT_WAIT_FOREVER, NULL); SetEvent(hInitCompleted); CHAR buf[MAX_SLOT_CHUNK]; DWORD dwReads; while (ReadFile(hSlot, buf, sizeof(buf), &dwReads, NULL)) { if (!strcmp(buf, "deadc0de")) break; puts(buf); } CloseHandle(hSlot); return EXIT_SUCCESS; } #define MAX_MESSAGE_COUNT 10 DWORD WINAPI ClientSlot(LPVOID) { HANDLE hSlot = CreateFile("\\\\.\\mailslot\\sniff", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); CHAR buf[MAX_SLOT_CHUNK]; DWORD dwWrites; for (size_t i = 0; i < MAX_MESSAGE_COUNT; i++) { int len = sprintf(buf, "%d", rand()); WriteFile(hSlot, buf, len + 1, &dwWrites, NULL); Sleep(rand() % 1000); } WriteFile(hSlot, "deadc0de", 9, &dwWrites, NULL); CloseHandle(hSlot); return EXIT_SUCCESS; } int main() { srand(GetTickCount()); HANDLE arr[2]; HANDLE hInitCompleted = CreateEvent(NULL, FALSE, FALSE, NULL); arr[0] = CreateThread(NULL, 0, ServerSlot, hInitCompleted, 0, NULL); WaitForSingleObject(hInitCompleted, INFINITE); CloseHandle(hInitCompleted); arr[1] = CreateThread(NULL, 0, ClientSlot, NULL, 0, NULL); WaitForMultipleObjects(_countof(arr), arr, TRUE, INFINITE); for_each(arr, arr+_countof(arr), CloseHandle); } еще удобно WM_COPYDATA использовать
Не WM_COPYDATA не подайдет, потому что у меня принимающее приложение консольное. А так можно еще и удобно через FileMapping делать.
Я недавно решил для себя написать простой снифер...Решил сделать как - при запуске EXE прога определяет список процессов и инжектит в них мельчайшую DLL( что бы быстро), потом загружает свой драйвер который через APC информирует о создание процесса(прога и туда сразу инжектит). А уж потом все процессы присылают нам перехваченные данные, причем в особом формате, который будет в себя включать ID процесса, ID потока, сокет и т.д. Короче в идеале прога наша должна отвечать на эти же данные(что пропускать и что изменять), то есть получится и снифер и как бы прокси. Но это все в идеале, я боюсь что скорость трафика сильно упадет, раз только одна программа будет обрабатывать все соединения.
я делал так логировал и ставил таймер скажем на секунду если до истечения периода приходили новые данные просто их пропускал если же таймаут прошел писал в лог и снова взводил таймер но у меня логика позволяла пропускать пакеты нужно было просто видеть активность