Я работаю над DLL, которая перехватывает функции winsock2, используя C ++ и обходные пути. Моя цель — изменить трафик TCP, который идет от исходного исполняемого файла и обратно. В какой-то момент мне нужно прекратить доставку определенного пакета (чтобы исходный исполняемый файл вообще не имел представления об этом пакете, но все еще сохраняет соединение).
С хуком WSASend это понятно (вы просто не вызываете оригинальный WSASend и возвращаете 0).
Но я понятия не имею, как сделать это в хуке WSARecv, используя структуру WSAOVERLAPPED.
Я надеюсь, что этот код ниже демонстрирует, что я хочу:
__declspec(dllexport) int WINAPI WSARecv_hook(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
// Recieve real data
int ret = WSARecv_real(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
// Loop over lpBuffers and analyze it
for(int i=0; i < dwBufferCount; i++)
{
// analyze it
if(packet_should_be_blocked(lpBuffers[i].buf, lpBuffers[i].len))
{
// Do or return what?
} else {
// Otherwise, just process as usual
}
}
return ret;
}
Как мне сделать вид, что ничего не произошло и пакет не был получен (например, подделка WSA_IO_PENDING)? Есть идеи / мысли?
Постскриптум Из того, что я знаю, исполняемый файл не использует подпрограмму завершения (lpCompletionRoutine всегда NULL), только перекрывающаяся структура.
Основным препятствием является то, что перекрывающиеся операции должны выполняться в фоновом режиме после того, как вызывающая функция вышла с ожидающим статусом. Если звонящий спрашивает WSARecv()
чтобы выполнить перекрывающееся чтение, он ожидает, что данные поступят в фоновом режиме, и вы не сможете проверить данные внутри своей ловушки напрямую, потому что они еще не были получены. Вам придется использовать свой личный WSAOVERLAPPED
выполнить собственное перекрывающееся чтение, используя обратный вызов потока или завершения, чтобы определить, когда заканчивается чтение, чтобы вы могли затем проанализировать данные. Если данные приемлемы, скопируйте их в буфер вызывающей стороны и сообщите WSAOVERLAPPED
, В противном случае отправьте еще одно чтение и дождитесь прибытия этих данных, повторяя их по мере необходимости, пока, наконец, не получите данные, которые вы хотите передать вызывающей стороне.
Гораздо более простой способ изменить трафик TCP — подключить только connect
семейство функций, и заставьте приложение подключаться к прозрачному прокси под вашим контролем, который выполняет фактическую модификацию потока.
Хотя приложение может записать свой собственный номер порта в потоке для сравнения с удаленным концом по адресу источника пакета, на практике это не является проблемой, поскольку
Фактически, прокси FTP должны переписывать эту команду, потому что они порождают подчиненные соединения для передачи файлов. Но большинство современных приложений написаны для совместимости с PAT.