{"id":23720048,"url":"https://github.com/allencch/med","last_synced_at":"2025-09-03T21:30:41.078Z","repository":{"id":32827449,"uuid":"36420455","full_name":"allencch/med","owner":"allencch","description":"Linux alternative game memory editor","archived":false,"fork":false,"pushed_at":"2023-11-05T09:00:35.000Z","size":783,"stargazers_count":55,"open_issues_count":1,"forks_count":4,"subscribers_count":8,"default_branch":"master","last_synced_at":"2023-11-06T08:24:24.736Z","etag":null,"topics":["cheat-engine","game-cheating","memory-editor","memory-scanning"],"latest_commit_sha":null,"homepage":"https://allencch.wordpress.com/2015/05/28/my-memory-editor-med/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"zeit/hyper","license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/allencch.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":"2015-05-28T06:56:45.000Z","updated_at":"2023-10-02T00:50:45.000Z","dependencies_parsed_at":"2023-01-14T22:21:48.251Z","dependency_job_id":"374f3019-52d8-49a7-b953-eca41ad21531","html_url":"https://github.com/allencch/med","commit_stats":null,"previous_names":[],"tags_count":33,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allencch%2Fmed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allencch%2Fmed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allencch%2Fmed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allencch%2Fmed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/allencch","download_url":"https://codeload.github.com/allencch/med/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231918530,"owners_count":18445746,"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":["cheat-engine","game-cheating","memory-editor","memory-scanning"],"created_at":"2024-12-30T21:56:16.051Z","updated_at":"2024-12-30T21:56:16.707Z","avatar_url":"https://github.com/allencch.png","language":"C++","readme":"# Med (Memory Editor)\n\n![Build status](https://github.com/allencch/med/actions/workflows/actions.yml/badge.svg)\n\nThere was a memory editor in Windows, that was Game Master. But it was not a freeware. And there is a freeware memory editor, it is ArtMoney. But it is also for Windows only. In Linux, there is only one memory editor, **scanmem** with GameConqueror as the GUI. However, it does not fulfil my needs. Thus, I decided to create one which can fit my needs.\n\nEveryone is welcome to contribute to the code.\n\n![Memory editing](http://i.imgur.com/6gSR0WI.png)\n\n\n## Usage\n\n`med-ui` is a GUI memory editor. In order to use it, please use **sudo**.\n\nBefore scanning or opening a JSON file, one must select a target process.\n\n\n## Interface\n\n![UI](https://i.imgur.com/CGvLdwp.png)\n\nThe interface can briefly separated into two panes and a bottom \"Named Scans\".\n\n* Left pane is the result from the scan.\n* Right pane is the memory addresses that we intended to store and save, or open from the file.\n* Bottom area is allows manage the named scans. We can temporary save the scan results according to the target named scan.\n\n\n## Scanning \u0026 filtering\n\n1. Before scanning, please click \"Process\" button to choose the process that we want to scan for the memory.\n2. After choosing the process, you can type in the value that you want to **scan**. (For the current stage, the only data types allowed are int8, int16, int32, float32, float64, and string.) For example, we can scan for the gold amount.\n3. After we make some changes of the gold in the game, you can **filter** it.\n\n## Last digits\n\nThe small field besides the scan value input is the \"Last Digits\" of the target address.\nSome games may have consistent last digit like 0x12341230, where the \"0\" is the last digit.\nThe allowed values are \"0\" to \"f\" (case insensitive).\nOther than that the value will be ignored.\n\nLast digits allows comma separated value, eg: \"4, c\", which will search for the addresses where the last digit match any of the value (i.e. 4 or 0xc).\n\n## Fast scan\n\nThe Option \"Fast Scan\" is to allow faster scanning based on scan type.\nLet's say we are scanning for \"int32\", which is 4 bytes long.\nThe scanning will target on the addresses with the last digit 0, 4, 8, c instead of 0 to f for every byte.\nDisable it if willing to do an exhaustive scanning.\n\n## Manage address\n\nThe scanned or stored memory addresses, you can\n\n* edit the data type.\n* edit the value.\n\nAt the right pane, you can\n\n* Use menu to add **new** memory address and edit manually.\n* When you select (highlight) a row, you can use `Next` or `Previous` to create next/previous memory address based on the row you selected.\n* **delete** the selected memory address with `DEL` key.\n\n## Shifting memory address\n\nMemory are usually dynamically allocated, the memory address will change whenever you start a process. Therefore, we need to shift our saved memory to the new location.\n\nIn order to solve this problem, two input fields: `Shift from` and `Shift to / byte` are provided. And three buttons `Shift`, `Unshift`, and `Move` works with the fields.\n\n\n### Example 1\n\nFor example, one of the item, namely Gold, memory address that you stored is 0x20de9b94. After you restart the game, the memory address you scan is changed to 0x20c3cb80.\n\n1. In order to shift the memory, copy-paste 0x20de9b94 to the `Shift from` and 0x20c3cb80 to the `Shift to / byte`.\n2. Select the memory address (the Gold) that you want to shift. Multiple selection is allowed.\n3. Press `Shift` button.\n4. Then all your selected address will be shifted.\n\n`Unshift` is a reverse of `Shift`.\n\n### Example 2\n\nSimilar to `Shift` and `Unshift`, let's say you have first character HP memory address located at 0x20de9b90, and the second character HP is located at 0x20de9ba2. Use a calculator that supports hexadecimal, then we can get the difference of 18 bytes.\n\nIf you have the memory addresses like HP, MP, strength, wisdom, agility, etc of the first character, then you can move these addresses to the second character location.\n\n1. Fill the 18 at `Shift to / bytes`.\n2. Select the rows that we want to move.\n3. Press `Move` button.\n\nIf we want to move back, fill in with negative value, and press move.\n\n\n## Scan by array\n\nLet's say we know a hero has the attributes like Max HP, HP, Max MP, and MP, with each 16-bits (2 bytes), then we can scan by array choosing `int16` and enter the values with comma,\n\n`3000, 2580, 1500, 1500`\n\nwhere the Max HP is 3000, current HP is 2580, Max MP is 1500, and current MP is 1500.\n\nNOTE: There is a known issue. If the array to be scan involves two `pages` (4096 bytes), then the array will not be found.\n\n## Scan by operators\n\nThere are several operators can be used for scanning,\n\n* `=` - equal, default\n* `\u003e` - greater than\n* `\u003e=` - greater than or equal to\n* `\u003c` - less than\n* `\u003c=` - less than or equal to\n* `!` - not\n* `\u003c\u003e` - between (inclusive)\n* `~` - around\n\nFor `\u003c\u003e`, it requires two operands, example `\u003c\u003e 10 20`, which means scan for the value in the range of [10, 20].\nThis feature is useful to search for the value such as floating point (float or double) that contains decimal places which is not shown in the game, such as Forager.\n\nFor `~`, it requires one operand with second optional operand, example `~ 10`, which will scan for the value [9, 11]. It is translated as 10 ± 1. If the input is `~ 10 2`, it will be 10 ± 2, then will search for the value [8, 12]. This is useful to search the floating point.\n\n\n## Save/open file\n\nThe JSON file is used. Please save the file in the JSON extension.\n\n\n## Memory Editor\n\nWe can view and edit the memory of a process as hexadecimal values.\n\n1. Go to menu Address \u003e Editor. You should get a popup window.\n2. Get the memory address you are interested with, eg: 0x7ffdb8979b90.\n3. Paste the address to the **Base** field in the popup window.\n4. When your cursor is away from the **Base** field, the hex data should be displayed as in the screenshot.\n\nIn the memory editor, **Base** field is the base address of the memory that we are interested.\n**Cursor** field is the memory address according to the cursor that is moving.\n**Value** is currently read-only value of the cursor.\nLeft pane is the memory address.\nMiddle pane is the hex reprensentation of the memory. We can directly make the changes to the memory of the process.\nRight pane is the ASCII representation of the memory. It is useful for viewing the string.\n\n\n## Encoding\n\nMenu View \u003e Encoding allows to change the encoding that we want to read and scan.\nIt will affect the Memory Editor as well.\nCurrently only support Big5 where the Default is actually UTF8.\n\n### Usage\n\nFor example, if a game uses Big5 encoding, we can change the encoding to Big5 and search the text like \"臺灣\" (Traditional Chinese).\n\nNote: Qt6 application run as root doesn't support IME like Fcitx. Please use copy-paste instead.\n\n\n## Search for unknown value (experimental v2)\n\nIf we are interested on a value of the game, but it is not a numerical value, such as a hero of the game is poisoned or normal. We can use unknown search.\n\n1. It requires at least one address in the store (the right panel) for heuristic search.\n2. Enter \"?\", and press \"Scan\" button. You should get the statusbar showing \"Snapshot saved\".\n3. Now make the changes of the status, like from poisoned to normal or vice versa.\n4. Enter \"!\" which indicates \"changed\", and press \"Filter\" button.\n5. The scanner will scan for the memory address with the value changed.\n6. Continue to filter until you get the potential memory address that handles the status.\n\nOther operators are \"\u003e\" and \"\u003c\".\n\n* \"\u003e\" with \"Filter\" will scan for the value that is increased.\n* \"\u003c\" with \"Filter\" will scan for the value that is decreased.\n\nNotes: This feature is tested on Dosbox game.\n\n## Scope search\n\nTo reduce the search space, we can specify the scope start and scope end by entering address in hexadecimal format. After entering both fields, make sure your cursor leave the field, so that the scope will take affect.\n\n## Custom search (experimental, Good!)\n\nCustom search allows to search string and wildcard. To do custom search, one can choose the `custom` type for searching. Then using the following input\n\n```\ns:'1', w:3, s:'2'\n```\n\nwhich will look for hexadecimal pattern `31 xx xx xx 32`. Where `s:` is the string to search, and `w:` is the number of wildcard.\n\nOther scan types are supported: `i8`, `i16`, `i32`, `i64`, `f32`, and `f64`.\nBesides that, operator such as `~`, `\u003c\u003e`, `\u003e`, `\u003c`, `\u003e=`, `\u003c=` are supported as well. Eg `i8:~ 4, f32: 10.5`\n\nRead [here](https://allencch.wordpress.com/2020/05/07/med-experimental-feature/) for the example usage.\n\n\n## Partially known issue\n\nSometimes the process that is being scanned for memory will freeze/pause due to the lock of Med.\nTo resume it, one can toggle the upper-right Pause on and off.\n\nAlternatively, if the process is run through console, one can do `Ctrl+Z` to suspend the process, then run `fg` to bring back to foreground.\n\n\n# Build Instruction\n\nTo build this program, it requires\n\n* cmake\n* clang (which I am using) (or GCC)\n* Qt6 (qt6-tools-dev)\n* libglvnd-dev (required by Qt6)\n* JSONPP (libjsoncpp-dev)\n* ICU (libicu-dev)\n* cxxtest (optional)\n* libreadline-dev ([Issue #6](https://github.com/allencch/med/issues/6), required on Debian Bullseye)\n\nRefer to `.github/workflows/actions.yml` for compilation.\n\n1. In the directory that contains the source code including `CMakeLists.txt`,\n\n```\nmkdir build \u0026\u0026 cd build\ncmake ../\nmake\n```\n\n1. To run the GUI, make sure the `*.ui` files are together with the compiled binary files, and enter\n\n`sudo ./med-ui`\n\n\n# TODO\n\n1. ~~Scan by array.~~\n2. ~~Memory editor dialog (view any memory as block).~~\n3. ~~Scan by string.~~\n4. ~~Scan by changes (scan unknown).~~\n5. ~~Scan within memory block range.~~\n6. Arithmetic operation with prefix notation.\n7. ~~Scan by struct, supports data type syntax~~\n8. Scan by pointer(?)\n\n# Developer notes\n\nFor the process maps, read `man procfs`. To view maps,\n\n```\nsudo cat /proc/[pid]/maps\n```\n\nTo build with `clang`,\n\n```\nexport CC=/usr/bin/clang CXX=/usr/bin/clang++\nmkdir build \u0026\u0026 cd build\ncmake ..\nmake\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallencch%2Fmed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fallencch%2Fmed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallencch%2Fmed/lists"}