此例程枚举了计算机上所有可见的窗口。每个可见窗口都会将其标题与窗口类和样式一起转储并上传到服务器。如果在后台打开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和手动映射的可移植可执行文件中经常出现的内存异常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; } }
新冠肺炎疫情的全球大流行不仅深刻影响了世界政治经济格局的发展演进,而且加速...
作者 许力 阿里云原生多模数据库Lindorm与东软云科技推出联合解决方案 共建面向...
年味到底是什么?不同的时代,人们迎接春节的方式也在变换。 在70后的眼里,年味...
我们将创建以下三个Shell脚本来锁定和解锁多个帐户和查看账号状态。 创建锁定用...
数据目录已成为企业数据管理策略的重要组成部分,但选择合适的数据目录并不是简...
1.男女之间是真的可以有纯友谊的,只要一个打死不说一个装傻到底。 2.不要迷恋...
?又到一年毕业季,即将开启(实习及正式)职场生涯的同学们会有不少疑惑。比如,...
1.世界上最悲哀的事莫过于睡眠不足,尤其是在感冒的时候。 2.我是一个很有原则...
1.我手机掉进厕所了怎么办?是屎在给我发信息吗? 2.生活就像新闻联播,不是换...
Knative 是基于 Kubernetes 的开源 Serverless 应用编排框架。阿里云 Knative 在...