【问题标题】:How can I monitor network traffic and browser activity如何监控网络流量和浏览器活动
【发布时间】:2021-03-01 12:55:16
【问题描述】:

首先; 让我分享一下我想做什么以及我在哪里苦苦挣扎。

1.我想在网络浏览器中跟踪用户移动

  1. 在任何浏览器中,我想保存有关用户登录的网站、包数据(下载/上传)、用户正在使用的浏览器的信息。

  2. 我想记录我在第2项中提到的协议,本地端口,本地地址和远程端口,远程端口名称,远程地址,发送的数据包和接收的数据包等信息。

我分享了我想做的和不能做的。

我尝试过的方法; 我尝试在google chrome、edge、opera浏览器中做api hook操作。

我已经将trampoline函数方法应用到winhttp.dll函数中,但是我无法获取任何数据。

static  DWORD(WINAPI* MS_WinHttpWebSocketReceive)(HINTERNET hWebSocket,
                                                  PVOID pvBuffer,
                                                  DWORD dwBufferLength,
                                                  DWORD* pdwBytesRead,
                                                  WINHTTP_WEB_SOCKET_BUFFER_TYPE* peBufferType
                                                  ) = WinHttpWebSocketReceive;

static DWORD WINAPI MY_WinHttpWebSocketReceive(HINTERNET hWebSocket,
                                              PVOID pvBuffer,
                                              DWORD dwBufferLength,
                                              DWORD* pdwBytesRead,
                                              WINHTTP_WEB_SOCKET_BUFFER_TYPE* peBufferType)
{
  OutputDebugString(L"=====MY_WinHttpWebSocketReceive Start======");
  OutputDebugString(L"Succeed");
  OutputDebugString(L"=====MY_WinHttpWebSocketReceive End======");
  
  return MS_WinHttpWebSocketReceive(hWebSocket, pvBuffer, dwBufferLength, pdwBytesRead, peBufferType);
}

我对winhttp.dll的很多函数都尝试了蹦床函数的方法,但是失败了。

有人知道他们在我分享的应用程序中使用了哪种方法吗?

Browser and other infos...

Packet etc infos

我怎样才能做我想做的事?

我需要连接哪些 dll 和函数才能获得我想要的信息?

我要保存协议、本地端口、本地地址和远程端口、远程端口名称、远程地址、发送的数据包和接收的数据包等信息。

给我看兔子洞。

【问题讨论】:

  • 你提到的浏览器都没有使用 WinHTTP。他们都使用 Chrome 引擎,它有自己的 HTTP 库。
  • 这个问题的前五段只是噪音。它们没有添加任何有用的东西来帮助说明您要解决的问题。通过保持问题的重点,您可以增加获得有用反馈的机会。
  • 感谢@Botje 的评论。所以我该怎么做?您对这个问题有什么建议吗?
  • 您需要彻底重新考虑您的方法。所有现代网站都使用 HTTPS,因此网络级别的任何拦截都将是随机分布的噪声。当然,开发间谍软件是不道德的。
  • @RecaiCingöz 如果碰巧知道是否有可能的人阅读了这个问题并觉得它很有趣,你就会得到答案。同时,其他人可以帮助您改进问题,使这个潜在的“某人”更有可能真正阅读它。

标签: c++ c windows sockets winapi


【解决方案1】:

您似乎正在寻找类似于Network Monitor 3 tool 的实现。

你可以从Windows Sockets 2开始学习。如果您想快速完成您的项目,那么您可以专注于以下 API。

socket function、bind function、recvfrom function 等

其中,recvfrom接受的缓冲区就是我们需要的。

recvfrom 函数读取已连接和 未连接的套接字并捕获数据所在的地址 发送。此函数通常与无连接套接字一起使用。

对于面向消息的套接字,数据是从第一个 排队的消息,最大为指定的缓冲区大小。如果 数据报或消息大于指定的缓冲区,缓冲区是 填充数据报的第一部分,recvfrom 生成 错误 WSAEMSGSIZE。对于不可靠的协议(例如,UDP) 多余的数据丢失。对于 UDP,如果接收到的数据包不包含数据 (空),recvfrom函数的返回值为零。

..

当然,我们需要一个合适的例子来帮助我们前进。

一些代码:

typedef struct ip_hdr
{
    unsigned char ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also)
    unsigned char ip_version : 4; // 4-bit IPv4 version
    unsigned char ip_tos; // IP type of service
    unsigned short ip_total_length; // Total length
    unsigned short ip_id; // Unique identifier

    unsigned char ip_frag_offset : 5; // Fragment offset field

    unsigned char ip_more_fragment : 1;
    unsigned char ip_dont_fragment : 1;
    unsigned char ip_reserved_zero : 1;

    unsigned char ip_frag_offset1; //fragment offset

    unsigned char ip_ttl; // Time to live
    unsigned char ip_protocol; // Protocol(TCP,UDP etc)
    unsigned short ip_checksum; // IP checksum
    unsigned int ip_srcaddr; // Source address
    unsigned int ip_destaddr; // Source address
} IPV4_HDR;

typedef struct udp_hdr
{
    unsigned short source_port; // Source port no.
    unsigned short dest_port; // Dest. port no.
    unsigned short udp_length; // Udp packet length
    unsigned short udp_checksum; // Udp checksum (optional)
} UDP_HDR;

// TCP header
typedef struct tcp_header
{
    unsigned short source_port; // source port
    unsigned short dest_port; // destination port
    unsigned int sequence; // sequence number - 32 bits
    unsigned int acknowledge; // acknowledgement number - 32 bits

    unsigned char ns : 1; //Nonce Sum Flag Added in RFC 3540.
    unsigned char reserved_part1 : 3; //according to rfc
    unsigned char data_offset : 4; /*The number of 32-bit words in the TCP header.
    This indicates where the data begins.
    The length of the TCP header is always a multiple
    of 32 bits.*/

    unsigned char fin : 1; //Finish Flag
    unsigned char syn : 1; //Synchronise Flag
    unsigned char rst : 1; //Reset Flag
    unsigned char psh : 1; //Push Flag
    unsigned char ack : 1; //Acknowledgement Flag
    unsigned char urg : 1; //Urgent Flag

    unsigned char ecn : 1; //ECN-Echo Flag
    unsigned char cwr : 1; //Congestion Window Reduced Flag

    ////////////////////////////////

    unsigned short window; // window
    unsigned short checksum; // checksum
    unsigned short urgent_pointer; // urgent pointer
} TCP_HDR;

...

int main()
{
    SOCKET sniffer;
    struct in_addr addr;
    int in;

    char hostname[100];
    struct hostent* local;
    WSADATA wsa;

    logfile = fopen("log.txt", "w");
    if (logfile == NULL)
    {
        printf("Unable to create file.");
    }

    //Initialise Winsock
    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        printf("WSAStartup() failed.\n");
        return 1;
    }
    printf("Initialised");

    //Create a RAW Socket
    printf("\nCreating RAW Socket...");
    sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if (sniffer == INVALID_SOCKET)
    {
        printf("Failed to create raw socket.\n");
        return 1;
    }
    printf("Created.");

    //Retrive the local hostname
    if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
    {
        printf("Error : %d", WSAGetLastError());
        return 1;
    }
    printf("\nHost name : %s \n", hostname);

    //Retrive the available IPs of the local host
    local = gethostbyname(hostname);
    printf("\nAvailable Network Interfaces : \n");
    if (local == NULL)
    {
        printf("Error : %d.\n", WSAGetLastError());
        return 1;
    }

    for (i = 0; local->h_addr_list[i] != 0; ++i)
    {
        memcpy(&addr, local->h_addr_list[i], sizeof(struct in_addr));
        printf("Interface Number : %d Address : %s\n", i, inet_ntoa(addr));
    }

    printf("Enter the interface number you would like to sniff : ");
    scanf("%d", &in);

    memset(&dest, 0, sizeof(dest));
    memcpy(&dest.sin_addr.s_addr, local->h_addr_list[in], sizeof(dest.sin_addr.s_addr));
    dest.sin_family = AF_INET;
    dest.sin_port = 0;

    printf("\nBinding socket to local system and port 0 ...");
    if (bind(sniffer, (struct sockaddr*) & dest, sizeof(dest)) == SOCKET_ERROR)
    {
        printf("bind(%s) failed.\n", inet_ntoa(addr));
        return 1;
    }
    printf("Binding successful");

    //Enable this socket with the power to sniff : SIO_RCVALL is the key Receive ALL ;)

    j = 1;
    printf("\nSetting socket to sniff...");
    if (WSAIoctl(sniffer, SIO_RCVALL, &j, sizeof(j), 0, 0, (LPDWORD)&in, 0, 0) == SOCKET_ERROR)
    {
        printf("WSAIoctl() failed.\n");
        return 1;
    }
    printf("Socket set.");

    //Begin
    printf("\nStarted Sniffing\n");
    printf("Packet Capture Statistics...\n");
    StartSniffing(sniffer); 

    //End
    closesocket(sniffer);
    WSACleanup();

    return 0;
}

完整代码:winsock sample(开箱即用)别忘了以管理员身份运行。

您还可以使用 Network Monitor 3.4 工具来了解缓冲区结构。

【讨论】:

  • 嗨,@Recai Cingöz 这个答案对你有用吗?如果对您有帮助,请随时accept。
  • 嗨@Strive Sun - MSFT。你的回答指导了我。我从您的回答开始,并找到了不同的解决方案。 github.com/google/gopacket。谢谢回答
猜你喜欢
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2012-03-26
  • 2021-09-15
  • 1970-01-01
相关资源
最近更新 更多