代码之家  ›  专栏  ›  技术社区  ›  Tony Delroy

好的Linux TCP/IP监控工具不需要根访问?

  •  3
  • Tony Delroy  · 技术社区  · 16 年前

    我想调试我正在增强的程序的TCP/IP交互。我没有根访问权限(因此没有tcpdump等),但应用程序是以我自己的ID运行的。我可以使用strace来拦截系统调用,但是是否有值得推荐的替代方法?如果是,为什么-他们提供什么?命令行首选(目前我的电脑上没有安装X服务器:-(),但对GUI也很好奇。

    理想情况下,它会说:

        app listening on port <portA>
        app listening on port <portB>
        client connection #1 accepted on listening port <portA> to local port <portC>
            from remote <hostX:portXA>
        app sent #1 <number> bytes "<data dump...>"
        app received from client #1 <number> bytes "<data dump...>"
        client #1 closed connection
    

    我自己也会刮伤一个轮子,但太多的轮子无法重新改造……

    事先谢谢。

    更新:保卢贝尔和伊诺斯都提出了非常有益的建议…(希望我能接受这两个答案,因为它们都是明确的,而且同样好)。实现Paul建议的ld_预载拦截的代码如下:

    // TCP comms trace library
    //   as per http://www.jayconrod.com/cgi/view_post.py?23
    
    #define _GNU_SOURCE
    
    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <dlfcn.h>
    
    
    typedef ssize_t (*Recv)(int s, void* buf, size_t len, int flags);
    
    ssize_t recv(int s, void* buf, size_t len, int flags)
    {
        static Recv real = NULL;
    
        if (!real)
            real = (Recv)dlsym(RTLD_NEXT, "recv");
    
        fprintf(stderr, "> recv(s '%d', buf %p, len %lld, flags %d)...\n",
                s, buf, len, flags);
        ssize_t result = real(s, buf, len, flags);
        fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
                s, buf, len, flags, result);
    
        return result;
    }
    
    typedef ssize_t (*Send)(int s, const void* buf, size_t len, int flags);
    
    ssize_t send(int s, const void* buf, size_t len, int flags)
    {
        static Send real = NULL;
    
        if (!real)
            real = (Send)dlsym(RTLD_NEXT, "send");
    
        fprintf(stderr, "> send(s '%d', buf %p, len %lld, flags %d)...\n",
                s, buf, len, flags);
        ssize_t result = real(s, buf, len, flags);
        fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
                s, buf, len, flags, result);
    
        return result;
    }
    
    typedef int (*Connect)(int s, const struct sockaddr* serv_addr, socklen_t addrlen);
    
    int connect(int s, const struct sockaddr* serv_addr, socklen_t addrlen)
    {
        static Connect real = NULL;
    
        if (!real)
            real = (Connect)dlsym(RTLD_NEXT, "connect");
    
        fprintf(stderr, "> connect(s %d, sockaddr %p, addrlen %d)\n",
                s, (void*)serv_addr, addrlen);
        int result = real(s, serv_addr, addrlen);
        fprintf(stderr, "< connect(s %d, sockaddr %p, addrlen %d) return %d\n",
                s, (void*)serv_addr, addrlen, result);
    
        return result;
    }
    
    typedef int (*Accept)(int s, const struct sockaddr* serv_addr, socklen_t* addrlen);
    
    int accept(int s, struct sockaddr* serv_addr, socklen_t* addrlen)
    {
        static Accept real = NULL;
    
        if (!real)
            real = (Accept)dlsym(RTLD_NEXT, "accept");
    
        fprintf(stderr, "> accept(s %d, sockaddr %p, addrlen %p)\n",
                s, (void*)serv_addr, addrlen);
        int result = real(s, serv_addr, addrlen);
        fprintf(stderr, "< accept(s %d, sockaddr %p, addrlen %p -> %d) return %d\n",
                s, (void*)serv_addr, addrlen, *addrlen, result);
    
        return result;
    }
    
    2 回复  |  直到 16 年前
        1
  •  2
  •   ypnos    16 年前

    即使使用与受害者程序相同的用户ID运行,也无法截获套接字连接。

    你需要做的是

    1. 让你自己的程序打印插座号码等。

    2. 让您的程序连接到另一个程序,该程序实际上将连接传输到真正的目的地。您可以在那里转储所有发送/接收的数据。

        2
  •  5
  •   Paul Rubel    16 年前

    其中一个想法是使用 library interpositioning . 基本上,您可以包装一个系统调用,connect和sendto对于您来说似乎是一个很好的起点,并在将数据传递给实际调用之前记录所看到的参数。

    推荐文章