{"id":14128658,"url":"https://github.com/agustingianni/memrepl","last_synced_at":"2025-08-03T23:31:55.811Z","repository":{"id":66966850,"uuid":"106102156","full_name":"agustingianni/memrepl","owner":"agustingianni","description":"Memory inspection REPL interface","archived":false,"fork":false,"pushed_at":"2017-10-14T11:16:15.000Z","size":20,"stargazers_count":46,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-16T16:22:49.183Z","etag":null,"topics":["debug","debugger","engineering","exploit","exploitation","frida","hacking","memory","re","repl","reverse","vulndev"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agustingianni.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}},"created_at":"2017-10-07T13:59:07.000Z","updated_at":"2021-03-02T08:37:58.000Z","dependencies_parsed_at":"2023-04-27T22:20:04.596Z","dependency_job_id":null,"html_url":"https://github.com/agustingianni/memrepl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agustingianni%2Fmemrepl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agustingianni%2Fmemrepl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agustingianni%2Fmemrepl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agustingianni%2Fmemrepl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agustingianni","download_url":"https://codeload.github.com/agustingianni/memrepl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228571844,"owners_count":17938772,"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":["debug","debugger","engineering","exploit","exploitation","frida","hacking","memory","re","repl","reverse","vulndev"],"created_at":"2024-08-15T16:02:00.513Z","updated_at":"2024-12-07T06:31:33.947Z","avatar_url":"https://github.com/agustingianni.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# memrepl\n\n`memrepl` is a `frida` based script that aims to help a researcher in the task of exploitation of memory corruption related bugs.\n\nThe idea is that the researcher can perform database like `queries` to get information about the contents and layout of the memory of a program. To perform these queries, `memrepl` exposes several global functions listed bellow:\n\n- `memory_list`: query current memory segments.\n- `memory_search`: search for a given value.\n- `memory_read`: read from a memory address.\n- `memory_write`: write to a memory address.\n- `memory_search_pointer`: search any pointers starting from a given address.\n\n## Installation\n\n```\n# Install `pip` if not installed.\n$ easy_install pip\n\n# Install `virtualenv` if not installed.\n$ pip install virtualenv\n\n# Create a virtual python environment.\n$ virtualenv venv_memrepl\n\n# Activate the environment (POSIX system).\n$ source ./venv_memrepl/bin/activate\n\n# Install `memrepl` into the virtual environment.\n$ python setup.py install\n\n```\n### Dependencies\nAll the requirements will be installed automatically using python's `setuptools`.\n- `python`\n- `pip`\n- `virtualenv (optional)`\n- `frida`\n- `ipython`\n- `hexdump`\n\n## Usage\n\nExecute `memrepl` with `-h` to get help:\n\n```\n$ memrepl -h\nusage: memrepl [-h] [-V] (-p PROC_PID | -n PROC_NAME | -l) [-d DEVICE]\n               [-m MOD_NAMES]\n\nMemory Grip.\n\noptional arguments:\n  -h, --help     show this help message and exit\n  -V, --version  show program's version number and exit\n  -p PROC_PID    Process PID.\n  -n PROC_NAME   Process name (follows unix wildcard patterns).\n  -l             Display running processes.\n  -d DEVICE      Select a device by ID. Specify `list` to get a list of\n                 available devices.\n  -m MOD_NAMES   Specify zero or more modules that need to be loaded in the\n                 target process.\n```\n\n### Attaching to a process by pid\n\n```\n$ memrepl -p 39718\nUsing device Device(id=\"local\", name=\"Local System\", type='local').\nAttaching to process pid `39718`.\nAttaching to process `39718`.\n\n ____________________\n\u003c Welcome to MemREPL \u003e\n --------------------\n        \\   ^__^\n         \\  (oo)\\_______\n            (__)\\       )\\/\\\n                ||----w |\n                ||     ||\n\nAvaliable commands:\n\nmemory_list: list memory regions in the attached program\nmemory_search: search for a given value\nmemory_read: read from a given address\nmemory_write: write to a given address\n\nUse help(command_name) to see how to use the command.\n\n\nIn [1]:\n```\n\n## Getting help while on the REPL loop\n\nEach exported function has a help message defined that can be read by using python's `help` function. Each help messages contains usage examples.\n\n```\nIn [10]: help(memory_read)\nHelp on function memory_read in module memrepl:\n\nmemory_read(value_format, address, size=32)\n    Examples:\n    memory_read(\"u8\", 0xcafecafe)\n    memory_read(\"u16\", 0xcafecafe)\n    memory_read(\"u32\", 0xcafecafe)\n    memory_read(\"u64\", 0xcafecafe)\n    memory_read(\"hex\", 0xcafecafe, 4)\n    memory_read(\"bytes\", 0xcafecafe, 4)\n    memory_read(\"BBII\", 0xcafecafe)\n```\n\n## Listing memory\n\n**Exported function signature:** `memory_list(protection=\"---\")`\n\n### Listing all segments\nTo list all the segments present in the target process use the `memory_list` function without an argument:\n```\nIn [5]: memory_list()\n  0: 0x000000010a4f5000 - 0x000000010a4f6000 (      4096 / 0x00001000) next=0x0000000000000000 r-x\n  1: 0x000000010a4f6000 - 0x000000010a4f7000 (      4096 / 0x00001000) next=0x0000000000000000 rw-\n  2: 0x000000010a4f7000 - 0x000000010a4fa000 (     12288 / 0x00003000) next=0x0000000000000000 r--\n  3: 0x000000010a4fa000 - 0x000000010a4fc000 (      8192 / 0x00002000) next=0x0000000000000000 rw-\n  ...\n```\n\n`memory_list` allows a `permission` agument that serves as a match filter, allowing the researcher to filter those segments he is interested in. For instance:\n\n### Executable segments\n```\nIn [7]: memory_list(\"x\")\n 0: 0x000000010a4f5000 - 0x000000010a4f6000 (      4096 / 0x00001000) next=0x0000000000007000 r-x\n 1: 0x000000010a4fd000 - 0x000000010a4fe000 (      4096 / 0x00001000) next=0x000000000000a000 r-x\n 2: 0x000000010a508000 - 0x000000010a738000 (   2293760 / 0x00230000) next=0x0000000000037000 r-x\n 3: 0x000000010a76f000 - 0x000000010a78c000 (    118784 / 0x0001d000) next=0x0000000000091000 r-x\n...\n```\n\n### RWX segments\n\n```\nIn [8]: memory_list(\"rwx\")\n0: 0x00007fffe8dac000 - 0x00007fffe8dad000 (      4096 / 0x00001000) next=0x000000000001c000 rwx /private/var/db/dyld/dyld_shared_cache_x86_64h\n1: 0x00007fffe8dc9000 - 0x00007fffe8dca000 (      4096 / 0x00001000) next=0x00000000000bc000 rwx /private/var/db/dyld/dyld_shared_cache_x86_64h\n2: 0x00007fffe8e86000 - 0x00007fffe8e87000 (      4096 / 0x00001000) next=0x0000000000000000 rwx /private/var/db/dyld/dyld_shared_cache_x86_64h\n```\n\n## Searching memory\n\n**Exported function signature:** `memory_search(value_format, value, out_format=\"hex\", out_size=32)`\n\n### Example search expressions\n\n```\nmemory_search(\"u8\", 0xca)\nmemory_search(\"u16\", 0xcafe)\nmemory_search(\"u32\", 0xcafedead)\nmemory_search(\"u64\", 0xcafecafecafecafe)\nmemory_search(\"hex\", \"ca fe ca fe\")\nmemory_search(\"bytes\", \"\\xca\\xfe\\xca\\xfe\")\n```\n\n### Example search\n\n```\n# Search for the string \"CAFE\" repeated 8 times.\nIn [12]: memory_search(\"bytes\", \"CAFE\" * 8)\nFound @ 0x000026412eceeeb0\n00000000: 43 41 46 45 43 41 46 45  43 41 46 45 43 41 46 45  CAFECAFECAFECAFE\n00000010: 43 41 46 45 43 41 46 45  43 41 46 45 43 41 46 45  CAFECAFECAFECAFE\n...\nGot 203 results.\n\n# Search for a pointer to the found string.\nIn [13]: string_address = 0x000026412eceeeb0\nIn [14]: memory_search(\"u64\", string_address)\nFound @ 0x0000000115f1b6d8\n00000000: B0 EE CE 2E 41 26 00 00  50 01 00 00 E5 E5 E5 E5  ....A\u0026..P.......\n00000010: B8 2B 7C 19 01 00 00 00  00 14 A1 2E 41 26 00 00  .+|.........A\u0026..\n```\n\n## Reading memory\n\n**Exported function signature:** `memory_read(value_format, address, size=32)`\n\n```\n# Reading possible object that points to our address.\nIn [15]: object_address = 0x0000000115f1b6d8\n\n# Read a couple QWORDs before the object to see whats there.\nIn [16]: memory_read(\"hex\", object_address - 8 * 4)\nRead @ 0x0000000115f1b6b8\n00000000: B8 2B 7C 19 01 00 00 00  40 14 A1 2E 41 26 00 00  .+|.....@...A\u0026..\n00000010: 40 00 00 00 E5 E5 E5 E5  B8 2B 7C 19 01 00 00 00  @........+|.....\n\n# Looks like the format is pointer|pointer|uint32|uint32|pointer\nIn [17]: memory_read(\"PPIIP\", object_address - 8 * 4)\nRead @ 0x0000000115f1b6b8\n0x00000001197c2bb8 0x000026412ea11440 0x00000040 0xe5e5e5e5 0x00000001197c2bb8\n```\n\n## Searching for pointers\n\n**Exported function signature:** `memory_search_pointer(address, protection)`\n\nThe main usage of this function is to search for things to overwrite. Basically one can search for pointers to things that may be useful while exploiting bugs. Two cases come to mind:\n\n- Pointers to data (to create infoleaks)\n- Pointers to code (to get code execution)\n\n### Example: looking for the position of a function pointer to overwrite.\n\n```\nIn [18]: memory_search_pointer(object_address, \"x\")\nFound pointer @ 0x0000000115f36e48 = 0x00000001192bfde8 to segment 0x0000000117cbf000 - 0x0000000119598000 r-x\n\nIn [19]: 0x0000000115f36e48 - object_address\nOut[19]: 112496\n\nIn [20]: function_pointer_address = 0x0000000115f36e48\n```\n\n## Writing memory\n\n**Exported function signature:** `memory_write(value_format, address, value)`\n\n```\nIn [21]: memory_write(\"u64\", function_pointer_address, 0xdeadbeef)\n\n# In another console with `lldb` attached:\n(lldb) c\nProcess 39718 resuming\nProcess 39718 stopped\n* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xdeadbeef)\n\n(lldb) register read rip\n     rip = 0x00000000deadbeef\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagustingianni%2Fmemrepl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagustingianni%2Fmemrepl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagustingianni%2Fmemrepl/lists"}