Python调用ReadProcessMemory()后,如何读取缓冲区内容检测恶意字符串?
内存扫描工具中提取缓冲区内容并进行恶意特征比对的实现方案
问题背景
使用ctypes开发内存扫描工具时,已通过VirtualAlloc()创建缓冲区并调用ReadProcessMemory()将目标进程内存写入该缓冲区,但不清楚如何提取缓冲区中的内容,完成恶意特征字符串与特征库的比对。核心代码片段如下:
while VQEResult != 0: VQEResult = VirtualQueryEx( # 调用VirtualQueryEx获取内存页信息 process, # 目标进程句柄 Adress, # 要查询的内存地址 byref(mbi), # 存储MEMORY_BASIC_INFORMATION的指针 sizeof(mbi), # MEMORY_BASIC_INFORMATION的大小 ) print(mbi.BaseAddress,mbi.RegionSize,Adress) # 注意:原条件逻辑存在问题,应修正为逻辑与判断 if mbi.State == MEM_COMMIT and mbi.RegionSize > 41000: # 仅处理已提交且足够大的内存区域 ContentsBuffer = VirtualAlloc ( # 分配与内存页大小一致的缓冲区 None, # 不指定特定地址 mbi.RegionSize, # 缓冲区大小等于目标内存页大小 0x1000, # MEM_COMMIT 0x04, # PAGE_READWRITE ) if not ReadProcessMemory ( process, # 目标进程句柄 Adress, # 目标内存地址 ContentsBuffer, # 输出缓冲区指针 mbi.RegionSize, # 要读取的字节数 byref(BytesRead), # 存储实际读取字节数的指针 ): continue # print("Erro:",GetLastError) if VQEResult: Adress += mbi.RegionSize
实现步骤与代码修改
1. 提取缓冲区内容
VirtualAlloc()返回的是c_void_p类型的内存指针,可通过以下方式读取指针指向的二进制数据:
- 使用
ctypes.string_at():直接从指针地址读取指定长度的字节数据 - 改用
ctypes.create_buffer():更便捷的缓冲区创建方式,可直接访问缓冲区内容
推荐使用create_buffer()替代VirtualAlloc(),无需手动管理内存分配,代码更简洁:
# 替换原VirtualAlloc的代码 ContentsBuffer = create_buffer(mbi.RegionSize) # 创建指定大小的可访问缓冲区
读取缓冲区内容的两种方式:
# 方式1:用string_at读取VirtualAlloc返回的指针 buffer_data = string_at(ContentsBuffer, BytesRead.value) # 方式2:直接访问create_buffer创建的缓冲区的raw属性 buffer_data = ContentsBuffer.raw[:BytesRead.value]
2. 恶意特征字符串比对
根据恶意特征的编码类型(ASCII、UTF-8或UTF-16LE),将缓冲区字节数据与特征库中的字符串进行匹配:
ASCII/UTF-8特征比对示例
# 假设恶意特征库是一个字符串列表 malicious_signatures = ["malicious_str1", "malicious_str2", "evil_payload"] # 提取缓冲区有效字节数据 buffer_bytes = buffer_data # 遍历特征库检查匹配 for signature in malicious_signatures: sig_bytes = signature.encode('utf-8') if sig_bytes in buffer_bytes: print(f"检测到恶意特征: {signature},内存地址: {Adress}")
宽字符(UTF-16LE)特征比对示例
如果目标进程使用宽字符存储字符串,需将特征转换为UTF-16LE编码:
for signature in malicious_signatures: sig_bytes = signature.encode('utf-16le') if sig_bytes in buffer_bytes: print(f"检测到宽字符恶意特征: {signature},内存地址: {Adress}")
3. 优化内存管理
使用create_buffer()时,Python会自动管理内存释放;若使用VirtualAlloc(),需在使用完缓冲区后调用VirtualFree()释放内存,避免内存泄漏:
VirtualFree(ContentsBuffer, 0, 0x8000) # 0x8000 = MEM_RELEASE
完整修改后的核心代码片段
while VQEResult != 0: VQEResult = VirtualQueryEx( process, Adress, byref(mbi), sizeof(mbi), ) print(mbi.BaseAddress, mbi.RegionSize, Adress) # 修正条件判断逻辑 if mbi.State == MEM_COMMIT and mbi.RegionSize > 41000: # 使用create_buffer创建缓冲区 ContentsBuffer = create_buffer(mbi.RegionSize) if not ReadProcessMemory( process, Adress, ContentsBuffer, mbi.RegionSize, byref(BytesRead), ): continue # 提取缓冲区内容 buffer_data = ContentsBuffer.raw[:BytesRead.value] # 恶意特征比对 malicious_signatures = ["malicious_str1", "malicious_str2"] for sig in malicious_signatures: if sig.encode('utf-8') in buffer_data: print(f"发现恶意特征: {sig},位于内存地址: {Adress}") # 若使用VirtualAlloc,需添加释放代码 # VirtualFree(ContentsBuffer, 0, 0x8000) if VQEResult: Adress += mbi.RegionSize
内容的提问来源于stack exchange,提问作者Leonardo Poloni
相关产品推荐
相关产品推荐

