{"id":28486075,"url":"https://github.com/fox-it/skrapa","last_synced_at":"2025-10-23T21:31:36.971Z","repository":{"id":219080161,"uuid":"742419248","full_name":"fox-it/skrapa","owner":"fox-it","description":"A zero dependency and customizable Python library for scanning Windows and Linux process memory.","archived":false,"fork":false,"pushed_at":"2024-02-01T14:42:27.000Z","size":29,"stargazers_count":66,"open_issues_count":0,"forks_count":5,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-06-05T12:47:54.102Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fox-it.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-01-12T12:42:56.000Z","updated_at":"2025-03-07T10:51:51.000Z","dependencies_parsed_at":"2024-02-01T16:22:23.218Z","dependency_job_id":null,"html_url":"https://github.com/fox-it/skrapa","commit_stats":null,"previous_names":["fox-it/skrapa"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/fox-it/skrapa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fox-it%2Fskrapa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fox-it%2Fskrapa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fox-it%2Fskrapa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fox-it%2Fskrapa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fox-it","download_url":"https://codeload.github.com/fox-it/skrapa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fox-it%2Fskrapa/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263130374,"owners_count":23418268,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-08T01:10:10.681Z","updated_at":"2025-10-23T21:31:31.929Z","avatar_url":"https://github.com/fox-it.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skrapa\n\nSkrapa is a zero dependency and customizable Python library for scanning Windows and Linux process memory.\n\nContents\n========\n- [Installation](#installation)\n- [Quickstart](#quickstart)\n- [How it works](#how-it-works)\n- [Usage](#usage)\n  - [Scanning a PID](#scanning-a-pid)\n  - [Scan using YARA](#scan-using-yara)\n  - [Page filters](#page-filters)\n- [Features](#features)\n\n## Installation\n\nInstallation can be done using `pip`:\n\n```bash\n$ pip install skrapa\n```\n\nYou can also include YARA support by installing the `yara` variant:\n\n```bash\n$ pip install skrapa[yara]\n```\n\n## Quickstart\n\nStart scanning with a given process ID after installing the library:\n\n```bash\npython examples/scan_pid.py --pid 8320 --hex 0000488B0557F402004833C448894424 --protect PAGE_EXECUTE_READ --alloc-protect PAGE_EXECUTE_WRITECOPY --type MEM_IMAGE --state MEM_COMMIT\n```\n\n\n## How it works\n\nSkrapa differs slightly from the traditional sense of memory scanning in that it allows you to filter on specific memory attributes, which can greatly reduce the time it takes to scan process memory.\n\nOn the Windows and Linux platforms the memory regions assigned to a specific process each hold their own set of permissions. These permissions can basically be boiled down to the permissions we know and love: `READ`, `WRITE`, and `EXECUTE`. Within process memory these permissions can be combined as some process memory needs to be readable as well as executable when we want to execute code from this memory region.\n\nThe API was designed to be transparent so it doesn't matter if the script was written for Windows or Linux (with the single exception for a permission that is only available on Windows).\n\n\u003e **Warning**\n\u003e to effectively scan the memory space on Windows or Linux you will need administrative privileges on the target system.\n\n## Usage\n\n### Scanning a PID\n\nLet's try to scan for the hex pattern of `0000488B0557F402004833C448894424` on Windows. To speed up the scanning process we assume that the following memory permissions are set for the region that the pattern should exist in:\n+ Protect: `PAGE_EXECUTE_READ`\n+ Allocation Protect: `PAGE_EXECUTE_WRITECOPY`\n+ Type: `MEM_IMAGE`\n+ State: `MEM_COMMIT`\n\nAny memory region that does not have these permissions set will be exempt from the matching process, increasing the speed of the scan. The boilerplate code for such a scan would look something like this:\n\n```python\nfrom skrapa import AccessProtectionType, HexPattern, MemoryAttributes, scan_pid\n\nmem_attributes = MemoryAttributes(\n    protect=AccessProtectionType.PAGE_EXECUTE_READ,\n    allocation_protect=AccessProtectionType.PAGE_EXECUTE_WRITECOPY,\n    type=AllocationType.MEM_IMAGE,\n    state=AllocationType.MEM_COMMIT,\n)\n\nfor hit in scan_pid(pid=8320, patterns=HexPattern(\"0000488B0557F402004833C448894424\"), attributes=mem_attributes):\n    print(hit)\n```\n\nFor each hit on the pattern we can look at the different attributes belonging to the process:\n+ Process name: `hit.process.name`\n+ Process path: `hit.process.path`\n+ Process architecture: `hit.process.architecture`\n\nOr for the associated memory region:\n+ Memory region start: `hit.region_start`\n+ Memory region size: `hit.region_size`\n+ Memory region end: `hit.region_start + hit.region_size`\n+ Address of the match: `hit.address`\n\nWe can read 128 bytes from the start of the pattern match because we might know there will be some interesting information after this pattern:\n\n```python\nfrom skrapa import read_process_memory\n\nmatch_content = read_process_memory(pid=8320, address=hit.address, size=128)\n```\n\nYou can then do whatever post processing you want on these bytes.\n\n### Scan using YARA\n\nNote: to use the YARA functionality of Skrapa, you'll need to have `yara-python` installed. You can install this manually or run `pip install skrapa[yara]`.\n\nWe're continuing our search leveraging YARA to find a pattern in the process memory of `notepad.exe`. Using YARA rules with Skrapa is as easy as pointing to your YARA file containing the rule(s) you want to match within the process memory. The YARA rule we're using for this example is:\n\n```yara\nrule l33t_notepad_rule {\n    strings:\n        $ = {\n            00 00 48 8B 05 57 F4 02\n            00 48 33 C4 48 89 44 24\n        }\n    condition:\n        any of them\n}\n```\n\nWe can use the YARA rule from above to find the pattern in the process memory:\n\n```python\nfrom skrapa import AccessProtectionType, MemoryAttributes, scan_pid\n\ntry:\n    import yara\nexcept ImportError:\n    logging.error(\"YARA Python module not found, install it with: pip install yara-python\")\n    exit(1)\n\nmem_attributes = MemoryAttributes(\n    protect=AccessProtectionType.PAGE_EXECUTE_READ,\n    allocation_protect=AccessProtectionType.PAGE_EXECUTE_WRITECOPY,\n    type=AllocationType.MEM_IMAGE,\n    state=AllocationType.MEM_COMMIT,\n)\n\npatterns = yara.compile(\n    source=\"rule l33t_notepad { strings: $ = {0000488B0557F402004833C448894424} condition: any of them }\"\n)\n\nfor hit in scan_pid(pid=8320, patterns=patterns, attributes=mem_attributes):\n    print(hit)\n```\n\nThe results of the above scan can be used in the exact same manner as the previous example shown. If you'd rather load in a YARA from a specified file you can switch the `source=` parameter of the `yara.compile` call with `filepath=`.\n\n### Page filters\n\nSkrapa allows users to define more complex memory filtering conditions by making use of a callback function. The callback function can also be used to check the size of the memory region before trying to match the given pattern.\n\nFor this example we will define the following `page_filter` function that will first check if:\n+ The given region is bigger than `0x300000` and smaller than `0x400000`\n+ The given region does not have the `PAGE_NOACCESS` protect attribute set\n+ The given region has the `PAGE_READWRITE` protect attribute set\n\nNote that we will not provide any of the memory attributes when using the above `page_filter` definition, instead we define every condition in the function:\n\n```python\nfrom skrapa import AccessProtectionType, HexPattern, MemoryAttributes, scan_pid\n\ndef page_filter(pageinfo) -\u003e bool:\n    return (\n        0x300000 \u003e pageinfo.size \u003c= 0x400000\n        and pageinfo.attributes.protect.name != \"PAGE_NOACCESS\"\n        and pageinfo.attributes.protect.name == \"PAGE_READWRITE\"\n    )\n\nmem_attributes = MemoryAttributes(protect=None, allocation_protect=None, type=None, state=None)\n\nfor hit in scan_pid(pid=8320, patterns=HexPattern(\"0000488B0557F402004833C448894424\"), attributes=mem_attributes, page_filter=page_filter):\n    print(hit)\n```\n\nWe will now only receive hits if the `page_filter` conditions were met.\n\nCheck out the `examples/` folder to quickly get started!\n\n## Features\n\n+ Supports x86 and x64 Windows and Linux platforms;\n+ Scan a single process by name or PID, or scan the entire memory space;\n+ Support for YARA signatures;\n+ Support for page filters for more complex conditions;\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffox-it%2Fskrapa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffox-it%2Fskrapa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffox-it%2Fskrapa/lists"}