2019-05-08 lab05_1

2019-05-29  本文已影响0人  ylylhl

书本习题

题目

  1. DLLMain的地址是什么?
  2. 使用Imports窗口并浏览到gethostbyname,导入函数定位到什么地址?
  3. 有多少函数调用了gethostbyname?
  4. 将精力集中在位于0x10001757处的对gethostbyname的调用,你能找出哪个DNS请求将被触发吗?
  5. IDA Pro 识别了在0x10001656处的子过程中的多少个局部变量?
  6. IDA Pro识别了在0x10001656处的子过程中的多少个参数?
  7. 使用Strings窗口,来在反汇编中定位字符串 \cmd.exe /c, 它位于哪儿?
  8. 在引用 \cmd.exe /c的代码所在区域发生了什么?
  9. 在同样的区域,在0x100101C8处,看起来dword_1008E5C4好像是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?(提示:使用交叉引用)
  10. 在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?
  11. PSLIST导出函数做了什么?
  12. 使用图模式来绘制出对sub_10004E79的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?
  13. DllMain直接调用了多少个Windows API?多少个在深度为2时被调用?
  14. 在0x10001358处,有一个对Sleep(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?
  15. 在0x10001701处是一个对socket的调用,它的3个参数是什么?
  16. 使用MSDN页面的socket和IDA Pro中的命名符号常量,你能使参数更有意义吗?修改后,参数是什么?
  17. 搜索in指令(opcode 0xED)的使用。这个指令和一个魔术字符串VMXh用来进行Vmware检测。在这个恶意代码中被使用了吗?使用对执行in指令函数的交叉引用,能发现进一步检测Vmware的证据吗?
  18. 将你的光标跳转到0x1001D988处,你发现了什么?
  19. 如果你安装了IDA Python插件(包括IDA Pro的商业版本插件),运行Lab05-01.py,一个IDA Pro Python脚本(确定光标是在0x1001D988处),在运行该脚本后发生了什么?
  20. 将光标放于同一位置,你如何将这个数据转成一个单一的ASCII字符串?
  21. 使用一个文本编辑器打开这个脚本。它是如何工作的?

分析

DLLMain的地址是什么?

如图,0x1000D02E

使用Imports窗口并浏览到gethostbyname,导入函数定位到什么地址?

0X100163CC

有多少函数调用了gethostbyname?

如图,9个函数调用了gethostbyname

由函数调用导致的交叉引用使用后缀p(看做是Procedure)。
跳转交叉引用使用后缀j(看做是Jump)。
读取交叉引用使用后缀r(看做是Read)。
写入交叉引用使用后缀w(看做是Write)。
偏移量交叉引用使用后缀o(看做是Offset)。

将精力集中在位于0x10001757处的对gethostbyname的调用,你能找出哪个DNS请求将被触发吗?

双击跳转,F5反编译,如下图


双击off_10019040跳转,如图

由于参数是off_10019040[0]+13,即从第14个字符处开始,所以DNS请求为pics.praticalmalwareanalysis.com

IDA Pro 识别了在0x10001656处的子过程中的多少个局部变量?

如图,共识别24个变量

IDA Pro识别了在0x10001656处的子过程中的多少个参数?

如图,识别了一个参数LPVOID lpThreadParameter

使用Strings窗口,来在反汇编中定位字符串 \cmd.exe /c, 它位于哪儿?

如下图,100095B34

在引用 \cmd.exe /c的代码所在区域发生了什么?

双击跳转

F5反编译,可以看到判断了dword_1008e5c4的值,若是,则将commandline变量与字符串\cmd.exe /c连接,若否,则与字符串\command.exe /c连接。猜测是根据系统版本进行了判断,以确保文件名正确。

command.exe是win9x的,cmd.exe是winNT/2k/xp/2003的。cmd是windows的命令行,支持长文件名,且cmd.exe本身是一个32位的程序,command是dos遗留下来的,不支持长文件名,而command.exe本身是一个16位的程序。

此外,根据函数中出现的代码及字符串推测,该函数部分作用为打印程序启动时的欢迎用户字符串及调用cmd。

在同样的区域,在0x100101C8处,看起来dword_1008E5C4好像是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?

查看xref,可以看到在图示地址处有一个写入交叉引用的操作

跳转,F5反编译,得到赋值代码如下

该赋值函数的代码如下:

BOOL sub_10003695()
{
  struct _OSVERSIONINFOA VersionInformation; // [esp+0h] [ebp-94h]
  VersionInformation.dwOSVersionInfoSize = 148;
  GetVersionExA(&VersionInformation); //获取系统版本信息
  return VersionInformation.dwPlatformId == 2;
}

微软官方对OSVERSIONINFOA结构中dwPlatformId的说明如下:

含义
VER_PLATFORM_WIN32_NT 2 操作系统是Windows 7,Windows Server 2008,Windows Vista,Windows Server 2003,Windows XP或Windows 2000。

综上,当操作系统是上述列表中的windows时,dword_1008E5C4被赋值为1,否则为0。亦即,当操作系统为windows 2000及以上时,commandline变量被赋值为\cmd.exe /c,否则被赋值为\command.exe /c字符串。

在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?

定位,跳转,F5反编译,可以看到执行了sub_100052a2函数。

该函数关键代码如下

//sub_100052a2()
  if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, aSoftwareMicros, 0, 0xF003Fu, &phkResult) )
    // aSoftwareMicros='SOFTWARE\Microsoft\Windows\CurrentVersion'
    //打开指定注册表项,若失败,则返回
    return RegCloseKey(phkResult);
  if ( !RegQueryValueExA(phkResult, aWorktime, 0, &Type, &Data, &cbData) )
  //aWorkTime='WorkTime'
  //如果存在worktime子项,则执行以下代码
  {
    v2 = atoi((const char *)&Data);
    //把字符串转换为int值,其中data是指向该项注册表的指针
    sprintf(&Dest, aRobotWorktimeD, v2);
    //换行并输出'[Robot_WorkTime :] %d',%d=v2
    v3 = strlen(&Dest);
    sub_100038EE(s, (int)&Dest, v3);
    //发送至socket
  }
  memset(&Data, 0, 0x200u);
  //将&data所指的内存空间初始化为0
  if ( !RegQueryValueExA(phkResult, aWorktimes, 0, &Type, &Data, &cbData) )
  //aWorkTimes='WorkTimes'
  //其余同上
  {
    v4 = atoi((const char *)&Data);
    sprintf(&Dest, aRobotWorktimes, v4);
    v5 = strlen(&Dest);
    sub_100038EE(s, (int)&Dest, v5);
  }
  return RegCloseKey(phkResult);

综上,若比较成功,则会向socket发送两个注册表键值,分别为HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WorkTimeHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WorkTimes

PSLIST导出函数做了什么?

代码如下

int __stdcall PSLIST(int a1, int a2, char *Str, int a4)
{
  int result; // eax
  dword_1008E5BC = 1;
  result = sub_100036C3();
  //return VersionInformation.dwPlatformId == 2 && VersionInformation.dwMajorVersion >= 5
  //判断系统版本是否为windows2000及以上
  if ( result )
  {
    if ( strlen(Str) )
      result = sub_1000664C(0, Str);
      //猜测发送进程列表&详细信息,分析见下
    else
      result = sub_10006518(0);
  }
  dword_1008E5BC = 0;
  return result;
}
sub_1000664C

该函数部分代码如下

多次调用的sub_100038BB函数如下,可以看到向socket发送了传递的char
*Str参数

而给Dest变量赋值的语句中可以看到th32ProcessID等字样,结合CreateToolhelp32Snapshot、Process32First等函数,猜测sub_1000664C函数的作用是向socket发送特定进程(或进程列表)及详细信息,包括进程id,进程名及线程数等。

sub_10006518

部分代码如下

调用的sub_1000620C函数如下

猜测是采用追加方式将进程信息写入了xinstall.dll文件。
综上,该函数检测了运行环境是否为特定windows系统后对Str参数的长度做了判断,若为0,则将进程信息记录在xinstall.dll文件中;若不为0,则将进程信息通过socket发送。

使用图模式来绘制出对sub_10004E79的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?

可以看到这些函数可能被调用

其中GetSystemDefaultLangID返回系统区域设置的语言标识符,在第10题中已分析过sub_100038EE,因此猜测该函数作用是向socket发送系统区域设置的语言标识符,可以重命名为sendSystemLanguageID。

DllMain直接调用了多少个Windows API?多少个在深度为2时被调用?

设置递归深度

如图,直接调用了四个Windows API

同理可得深度2的部分调用如图

数了一下好像是33个?

在0x10001358处,有一个对Sleep(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?

跳转,反编译,得到代码如图

其中off_10019020取值为[This is CTI]30,又因参数为off_10019020[0]+13,因此v14=atoi('30'),即程序会睡眠30秒。

在0x10001701处是一个对socket的调用,它的3个参数是什么?

跳转,反汇编可得参数分别为2,1,6

使用MSDN页面的socket和IDA Pro中的命名符号常量,你能使参数更有意义吗?修改后,参数是什么?

MSDN对socket的定义如下

SOCKET WSAAPI socket(
  int af,
  int type,
  int protocol
);

现将上题中参数对应取值及含义摘录如下表:

取值 含义
AF_INET 2 Internet协议版本4(IPv4)地址系列。
SOCK_STREAM 1 一种套接字类型,提供带有OOB数据传输机制的顺序,可靠,双向,基于连接的字节流。此套接字类型使用传输控制协议(TCP)作为Internet地址系列(AF_INET或AF_INET6)。
IPPROTO_TCP 6 传输控制协议(TCP)。当af参数为AF_INET或AF_INET6且类型参数为SOCK_STREAM时,这是一个可能的值。

因此可以重命名为AF_INET、SOCK_STREAM、IPPROTO_TCP,如图

搜索in指令(opcode 0xED)的使用。这个指令和一个魔术字符串VMXh用来进行Vmware检测。在这个恶意代码中被使用了吗?使用对执行in指令函数的交叉引用,能发现进一步检测Vmware的证据吗?

搜索找到in指令

双击跳转,可以在下一条指令里看到VMXh字样

可以看到有三个函数对该函数进行了交叉引用

此处以InstallRT为例,部分代码如下

  if ( atoi(off_10019034[0] + 13) && ((unsigned __int8)sub_10006119() || sub_10006196()) )
  //检测是否在虚拟机中运行
  //sub_10006119()检测VPC虚拟机,sub_10006196()检测VM虚拟机
  {
    sub_10003592(unk_1008E5F0);
    sub_10003592(aFoundVirtualMa);
    //aFoundVirtualMa=Found Virtual Machine,Install Cancel
    result = sub_10005567(Format);
  }
  else
  {
    atoi(off_1001902C[0] + 13);
    result = sub_1000D3D0(a3);
  }
  return result;

其中sub_10003592函数如下

猜测sub_10003592作用是将参数字符串写入xinstall.log。另两处对sub_10006196()的调用也大同小异,不做重复说明。
综上所述,该指令在恶意代码中被使用了,且可以进一步发现检测虚拟机的证据。若检测到虚拟机,则终止安装并将记录写入xinstall.log文件。

将你的光标跳转到0x1001D988处,你发现了什么?

如果你安装了IDA Python插件(包括IDA Pro的商业版本插件),运行Lab05-01.py,一个IDA Pro Python脚本(确定光标是在0x1001D988处),在运行该脚本后发生了什么?

将光标放于同一位置,你如何将这个数据转成一个单一的ASCII字符串?

使用一个文本编辑器打开这个脚本。它是如何工作的?

其他发现


dllmain -> sub_10001365 -> sub_1000208F


//StartEXS
  WSAStartup(0x202u, &WSAData);
  hdc = CreateDCA(pwszDriver, 0, 0, 0);
  v4 = GetDeviceCaps(hdc, 8);
  v5 = GetDeviceCaps(hdc, 10);
  InitializeCriticalSection(&CriticalSection);
  result = (char *)operator new(4 * v5 * v5);
  v25 = result;

GetDeviceCaps()

参数 含义
HORZRES 8 可打印区域宽度,像素
VERTRES 10 可打印区域高度,像素
上一篇下一篇

猜你喜欢

热点阅读