fox-it/skrapa
GitHub: fox-it/skrapa
一个零依赖的跨平台 Python 库,用于扫描 Windows 和 Linux 进程内存,支持按内存属性过滤和 YARA 规则匹配。
Stars: 66 | Forks: 5
# Skrapa
Skrapa 是一个零依赖且可定制的 Python 库,用于扫描 Windows 和 Linux 进程内存。
# 目录
- [安装](#installation)
- [快速入门](#quickstart)
- [工作原理](#how-it-works)
- [用法](#usage)
- [扫描 PID](#scanning-a-pid)
- [使用 YARA 扫描](#scan-using-yara)
- [页面过滤器](#page-filters)
- [功能](#features)
## 安装
可以使用 `pip` 进行安装:
```
$ pip install skrapa
```
您也可以通过安装 `yara` 变体来包含 YARA 支持:
```
$ pip install skrapa[yara]
```
## 快速入门
安装库后,使用给定的进程 ID 开始扫描:
```
python examples/scan_pid.py --pid 8320 --hex 0000488B0557F402004833C448894424 --protect PAGE_EXECUTE_READ --alloc-protect PAGE_EXECUTE_WRITECOPY --type MEM_IMAGE --state MEM_COMMIT
```
## 工作原理
Skrapa 与传统意义上的内存扫描略有不同,它允许您根据特定的内存属性进行过滤,这可以大大减少扫描进程内存所需的时间。
在 Windows 和 Linux 平台上,分配给特定进程的内存区域各自拥有一组权限。这些权限基本上可以归结为我们熟知且喜爱的权限:`READ`、`WRITE` 和 `EXECUTE`。在进程内存中,这些权限可以组合使用,因为当我们希望从该内存区域执行代码时,某些进程内存需要既可读又可执行。
该 API 旨在保持透明,因此无论脚本是针对 Windows 还是 Linux 编写的都没有关系(唯一的例外是某个仅在 Windows 上可用的权限)。
## 用法
### 扫描 PID
让我们尝试在 Windows 上扫描十六进制模式 `0000488B0557F402004833C448894424`。为了加快扫描过程,我们假设该模式所在的区域设置了以下内存权限:
+ Protect: `PAGE_EXECUTE_READ`
+ Allocation Protect: `PAGE_EXECUTE_WRITECOPY`
+ Type: `MEM_IMAGE`
+ State: `MEM_COMMIT`
任何未设置这些权限的内存区域都将被排除在匹配过程之外,从而提高扫描速度。此类扫描的样板代码如下所示:
```
from skrapa import AccessProtectionType, HexPattern, MemoryAttributes, scan_pid
mem_attributes = MemoryAttributes(
protect=AccessProtectionType.PAGE_EXECUTE_READ,
allocation_protect=AccessProtectionType.PAGE_EXECUTE_WRITECOPY,
type=AllocationType.MEM_IMAGE,
state=AllocationType.MEM_COMMIT,
)
for hit in scan_pid(pid=8320, patterns=HexPattern("0000488B0557F402004833C448894424"), attributes=mem_attributes):
print(hit)
```
对于模式上的每次命中,我们可以查看属于该进程的不同属性:
+ Process name: `hit.process.name`
+ Process path: `hit.process.path`
+ Process architecture: `hit.process.architecture`
或者对于相关的内存区域:
+ Memory region start: `hit.region_start`
+ Memory region size: `hit.region_size`
+ Memory region end: `hit.region_start + hit.region_size`
+ Address of the match: `hit.address`
我们可以从模式匹配的起始位置读取 128 个字节,因为我们可能知道该模式之后会有一些有趣的信息:
```
from skrapa import read_process_memory
match_content = read_process_memory(pid=8320, address=hit.address, size=128)
```
然后,您可以对这些字节进行任何所需的后处理。
### 使用 YARA 扫描
注意:要使用 Skrapa 的 YARA 功能,您需要安装 `yara-python`。您可以手动安装,或者运行 `pip install skrapa[yara]`。
我们继续利用 YARA 在 `notepad.exe` 的进程内存中查找模式。在 Skrapa 中使用 YARA 规则非常简单,只需指向包含您要在进程内存中匹配的规则的 YARA 文件即可。我们在本示例中使用的 YARA 规则是:
```
rule l33t_notepad_rule {
strings:
$ = {
00 00 48 8B 05 57 F4 02
00 48 33 C4 48 89 44 24
}
condition:
any of them
}
```
我们可以使用上面的 YARA 规则在进程内存中查找该模式:
```
from skrapa import AccessProtectionType, MemoryAttributes, scan_pid
try:
import yara
except ImportError:
logging.error("YARA Python module not found, install it with: pip install yara-python")
exit(1)
mem_attributes = MemoryAttributes(
protect=AccessProtectionType.PAGE_EXECUTE_READ,
allocation_protect=AccessProtectionType.PAGE_EXECUTE_WRITECOPY,
type=AllocationType.MEM_IMAGE,
state=AllocationType.MEM_COMMIT,
)
patterns = yara.compile(
source="rule l33t_notepad { strings: $ = {0000488B0557F402004833C448894424} condition: any of them }"
)
for hit in scan_pid(pid=8320, patterns=patterns, attributes=mem_attributes):
print(hit)
```
上述扫描结果的使用方式与前面展示的示例完全相同。如果您更愿意从指定文件加载 YARA,可以将 `yara.compile` 调用中的 `source=` 参数替换为 `filepath=`。
### 页面过滤器
Skrapa 允许用户通过使用回调函数来定义更复杂的内存过滤条件。回调函数还可用于在尝试匹配给定模式之前检查内存区域的大小。
在本例中,我们将定义以下 `page_filter` 函数,它将首先检查:
+ 给定区域是否大于 `0x300000` 且小于 `0x400000`
+ 给定区域是否未设置 `PAGE_NOACCESS` 保护属性
+ 给定区域是否设置了 `PAGE_READWRITE` 保护属性
请注意,在使用上述 `page_filter` 定义时,我们将不提供任何内存属性,而是在函数中定义每个条件:
```
from skrapa import AccessProtectionType, HexPattern, MemoryAttributes, scan_pid
def page_filter(pageinfo) -> bool:
return (
0x300000 > pageinfo.size <= 0x400000
and pageinfo.attributes.protect.name != "PAGE_NOACCESS"
and pageinfo.attributes.protect.name == "PAGE_READWRITE"
)
mem_attributes = MemoryAttributes(protect=None, allocation_protect=None, type=None, state=None)
for hit in scan_pid(pid=8320, patterns=HexPattern("0000488B0557F402004833C448894424"), attributes=mem_attributes, page_filter=page_filter):
print(hit)
```
现在,只有满足 `page_filter` 条件时,我们才会收到命中。
查看 `examples/` 文件夹以快速上手!
## 功能
+ 支持 x86 和 x64 Windows 及 Linux 平台;
+ 按名称或 PID 扫描单个进程,或扫描整个内存空间;
+ 支持 YARA 签名;
+ 支持用于更复杂条件的页面过滤器;
标签:DNS信息、DNS暴力破解, Linux内存, PAGE_EXECUTE_READ, SecList, Windows内存, YARA规则, 云资产清单, 内存取证, 内存扫描, 内存搜索, 内存权限, 十六进制模式, 后渗透, 攻击路径可视化, 数字取证, 流量嗅探, 网络安全审计, 自动化脚本, 进程内存, 逆向工具, 逆向工程, 零依赖, 黑客工具