当前位置:主页 > 查看内容

BattlEye堆栈行走(2)

发布时间:2021-04-07 00:00| 位朋友查看

简介:窗口枚举 此例程枚举了计算机上所有可见的窗口。每个可见窗口都会将其标题与窗口类和样式一起转储并上传到服务器。如果在后台打开Google Chrome标签页并推送有关离婚的机密信息时推送此shellcode,BattlEye现在就知道这一点,这 太糟糕了 。虽然这可能是监视……

窗口枚举

此例程枚举了计算机上所有可见的窗口。每个可见窗口都会将其标题与窗口类和样式一起转储并上传到服务器。如果在后台打开Google Chrome标签页并推送有关离婚的机密信息时推送此shellcode,BattlEye现在就知道这一点,这太糟糕了。虽然这可能是监视作弊者活动的一种非常好的方法,但它是一种非常激进的方法,并且可能会产生大量不适当的信息,这些信息将通过互联网发送到游戏服务器。没有窗口可以安全丢弃,因此在加载您喜欢的射击游戏时要小心。

反编译如下:

  top_window_handle = GetTopWindow(0x00);
  if ( top_window_handle )
  {
    report_buffer = (std::uint8_t*)malloc(0x5000);
    report_buffer[0] = 0;
    report_buffer[1] = 0xC;
    buffer_index = 2;
    do
    {
      // FILTER VISIBLE WINDOWS
      if ( GetWindowLongA(top_window_handle, GWL_STYLE) & WS_VISIBLE )
      {
        // QUERY WINDOW TEXT
        window_text_length = GetWindowTextA(top_window_handle, &report_buffer[buffer_index + 1], 0x40);

        for ( I = 0; I < window_text_length; ++i )
          report_buffer[buffer_index + 1 + i] = 0x78; 

        report_buffer[buffer_index] = window_text_length;

        // QUERY WINDOW CLASS NAME
        after_name_index = buffer_index + (char)window_text_length + 1;
        class_name_length = GetClassNameA(top_window_handle, &report_buffer[after_name_index + 1], 0x40);
        report_buffer[after_name_index] = class_name_length;
        after_class_index = after_name_index + (char)class_name_length + 1;

        // QUERY WINDOW STYLE
        window_style = GetWindowLongA(top_window_handle, GWL_STYLE);
        extended_window_style = GetWindowLongA(top_window_handle, GWL_EXSTYLE);
        *(_DWORD *)&report_buffer[after_class_index] = extended_window_style | window_style;

        // QUERY WINDOW OWNER PROCESS ID
        GetWindowThreadProcessId(top_window_handle, &window_pid);
        *(_DWORD *)&report_buffer[after_class_index + 4] = window_pid;


        buffer_index = after_class_index + 8;
      }
      top_window_handle = GetWindow(top_window_handle, GW_HWNDNEXT);
    }
    while ( top_window_handle && buffer_index <= 0x4F40 );
    battleye::send(report_buffer, buffer_index, false);
    free(report_buffer);
  }

Shellcode检测

此专有Shellcode的另一种机制是对所有正在运行的进程进行完整的地址空间枚举。该枚举例程检查在shellcode和手动映射的可移植可执行文件中经常出现的内存异常2。

2手动映射可执行文件是复制Windows图像加载器的过程

这是通过枚举所有进程及其各自的线程来完成的。通过检查每个线程的起始地址并将其与已知模块地址范围进行交叉引用,可以推断出哪些线程用于执行动态分配的shellcode。当发现这样的异常时,线程起始地址,线程句柄,线程索引和线程创建时间都被发送到相应的游戏服务器以进行进一步调查。

之所以会这样做是因为将代码分配到受信任的进程中会增加隐身性。这种方法可以缓解这种情况,因为如果直接为它们启动线程,则shellcode会脱颖而出。这不会捕获任何使用诸如线程劫持之类的方法来执行Shellcode的方法的人,这是另一种方法。

反编译如下:

query_buffer_size = 0x150;
while ( 1 )
{
  // QUERY PROCESS LIST
  query_buffer_size += 0x400;
  query_buffer = (SYSTEM_PROCESS_INFORMATION *)realloc(query_buffer, query_buffer_size);
  if ( !query_buffer )
    break;
  query_status = NtQuerySystemInformation(
                    SystemProcessInformation, query_buffer, 
                    query_buffer_size, &query_buffer_size); 
  if ( query_status != STATUS_INFO_LENGTH_MISMATCH )
  {
    if ( query_status >= 0 )
    {
      // QUERY MODULE LIST SIZE
      module_list_size = 0;
      NtQuerySystemInformation)(SystemModuleInformation, &module_list_size, 0, &module_list_size);
      modules_buffer = (RTL_PROCESS_MODULES *)realloc(0, module_list_size);
      if ( modules_buffer )
      {
        // QUERY MODULE LIST
        if ( NtQuerySystemInformation)(
               SystemModuleInformation,
               modules_buffer,
               module_list_size,
               1) >= 0 )
        {
          for ( current_process_entry = query_buffer;
                current_process_entry->UniqueProcessId != GAME_PROCESS_ID;
                current_process_entry = 
                    (std::uint64_t)current_process_entry + 
                    current_process_entry->NextEntryOffset) )
          {
            if ( !current_process_entry->NextEntryOffset )
              goto STOP_PROCESS_ITERATION_LABEL;
          }
          for ( thread_index = 0; thread_index < current_process_entry->NumberOfThreads; ++thread_index )
          {
            // CHECK IF THREAD IS INSIDE OF ANY KNOWN MODULE
            for ( module_count = 0;
                  module_count < modules_buffer->NumberOfModules
               && current_process_entry->threads[thread_index].StartAddress < 
                    modules_buffer->Modules[module_count].ImageBase
                || current_process_entry->threads[thread_index].StartAddress >= 
                    (char *)modules_buffer->Modules[module_count].ImageBase + 
                        modules_buffer->Modules[module_count].ImageSize);
                  ++module_count )
            {
              ;
            }
            if ( module_count == modules_buffer->NumberOfModules )// IF NOT INSIDE OF ANY MODULES, DUMP
            {
              // SEND A REPORT !
              thread_report.pad = 0;
              thread_report.id = 0xF;
              thread_report.thread_base_address = 
                current_process_entry->threads[thread_index].StartAddress;
              thread_report.thread_handle = 
                current_process_entry->threads[thread_index].ClientId.UniqueThread;
              thread_report.thread_index = 
                current_process_entry->NumberOfThreads - (thread_index + 1);
              thread_report.create_time = 
                current_process_entry->threads[thread_index].CreateTime - 
                    current_process_entry->CreateTime;
              thread_report.windows_directory_delta = nullptr;
              
              if ( GetWindowsDirectoryA(&directory_path, 0x80) )
              {
                windows_directory_handle = CreateFileA(
                                             &directory_path,
                                             GENERIC_READ,
                                             7,
                                             0,
                                             3,
                                             0x2000000,
                                             0);
                if ( windows_directory_handle != INVALID_HANDLE_VALUE )
                {
                  if ( GetFileTime(windows_directory_handle, 0, 0, &last_write_time) )
                    thread_report.windows_directory_delta = 
                        last_write_time - 
                            current_process_entry->threads[thread_index].CreateTime;
                  CloseHandle(windows_directory_handle);
                }
              }
              thread_report.driver_folder_delta = nullptr;
              system_directory_length = GetSystemDirectoryA(&directory_path, 128);
              if ( system_directory_length )
              {
                // Append \\Drivers
                std::memcpy(&directory_path + system_directory_length, "\\Drivers", 9);
                driver_folder_handle = CreateFileA(&directory_path, GENERIC_READ, 7, 0i, 3, 0x2000000, 0);
                if ( driver_folder_handle != INVALID_HANDLE_VALUE )
                {
                  if ( GetFileTime(driver_folder_handle, 0, 0, &drivers_folder_last_write_time) )
                    thread_report.driver_folder_delta = 
                        drivers_folder_last_write_time - 
                            current_process_entry->threads[thread_index].CreateTime;
                  CloseHandle(driver_folder_handle);
                }
              }
              battleye::send(&thread_report.pad, 0x2A, 0);
            }
          }
        }
STOP_PROCESS_ITERATION_LABEL:
        free(modules_buffer);
      }
      free(query_buffer);
    }
    break;
  }
}

本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐