На пике славы: «взлом» поисковых систем BUG(O)R Хакер, номер #095, стр. 095-090-3 Пишем код функции TRecv function Nrecv(s: TSocket; Buf: pChar; len, flags: Integer): Integer; stdcall; begin Trecv(s, buf, len, flags); asm pushad end; asm popad end; end; рushad и popad используются для того, чтобы не было проблем. Для незнающих отмечу, что эти команды процессора кладут в стек и восстанавливают оттуда значения всех основных регистров. Поэтому лучше, чтобы все регистры до и после вызова оригинальных функций содержали первоначальные значения. Любые модификации переданных параметров нужно производить в пределах двух ассемблерных вставок. Грубо говоря, мы установили перехват. Теперь, когда в программе встретился вызов одной из этих четырех функций, мы попадаем в функцию с префиксом «N». Как видно, она принимает те же параметры, что и перехватываемая. В пределах двух ассемблерных вставок мы делаем с этими параметрами все, что душе угодно, а далее вызываем оригинальную функцию (здесь это вызов функций с префиксом «T»). Далее, чтобы не повторять много раз один и тот же код, стоит сделать следующую оговорку. Когда я буду говорить: «В функцию перехвата send впишем код...», это будет значить, что между строками «end;» и «asm» в функции Nsend нужно вписать какой-либо код. Теперь давай исследовать запросы и ответы гугла при поиске. При перехвате функций отправки данных (send, WSASend) в полях заголовка среди прочих полей существует поле «Accept-Encoding:deflate, gzip, x-gzip, identity, *;q=0», а это значит, что данные от сервера будут приниматься в сжатом виде и мы не сможем их пропарсить. Как от этого избавиться? Все довольно просто - вместо «gzip» в полях заголовка нужно вписать «none», таким образом, при ответе сервера на запрос данные будут приходить в девственно чистом виде. В функции перехвата send пишем следующий код: if (pos('Host: www.google.ru', Buf) > 0) or (pos('Host: google.ru', Buf) > 0) then ReplaceGZIP(Buf, len); А в функции перехвата WSASend - такой код: if (pos('Host: www.google.ru', lpBuffers.buf) > 0) or (pos('Host: google.ru', lpBuffers.buf) > 0) then ReplaceGZIP(lpBuffers.buf, lpBuffers.len); Чтобы отсечь запросы к другим сайтам (ведь нам их обрабатывать вовсе не нужно), я ввожу проверку наличия строк «Host: www.google.ru» и «Host: google.ru». Функция ReplaceGZIP - это самописная функция, которая ищет строку «gzip» и заменяет ее строчкой «none»: function ReplaceGZIP(lpData: pointer; szData: dword): boolean; begin for i:=szData downto 0 do begin if dword(lpData^) = $70697A67 then dword(lpData^) := $656E6F6E; inc(dword(lpData)); end; end; Вот теперь ответ сервера мы можем спокойно парсить, как любые данные html-формата. Сделай в поисковике запрос по слову «журнал» и открой html-код страницы. Приглядевшись, ты сможешь четко увидеть структуру отображения результатов поиска, которые условно можно разбить на блоки, например самый первый блок будет следующим: |