{"id":15061933,"url":"https://github.com/handy-sun/rcheat","last_synced_at":"2026-05-01T07:04:50.394Z","repository":{"id":251870625,"uuid":"836592367","full_name":"handy-sun/rcheat","owner":"handy-sun","description":"Get/modify variable's value in another Linux running process","archived":false,"fork":false,"pushed_at":"2025-03-11T13:53:47.000Z","size":279,"stargazers_count":11,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"dev0","last_synced_at":"2025-03-24T08:42:01.497Z","etag":null,"topics":["cli","elf","gdb","process","ptrace"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/handy-sun.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,"publiccode":null,"codemeta":null}},"created_at":"2024-08-01T07:08:25.000Z","updated_at":"2025-02-20T03:01:16.000Z","dependencies_parsed_at":"2024-08-06T08:44:39.920Z","dependency_job_id":"02738bf4-4fbe-4074-83c8-528af93e77d9","html_url":"https://github.com/handy-sun/rcheat","commit_stats":{"total_commits":55,"total_committers":1,"mean_commits":55.0,"dds":0.0,"last_synced_commit":"34b5f3bb30a40ff10545c47e29d745d0bfee4eb2"},"previous_names":["handy-sun/rcheat"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handy-sun%2Frcheat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handy-sun%2Frcheat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handy-sun%2Frcheat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/handy-sun%2Frcheat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/handy-sun","download_url":"https://codeload.github.com/handy-sun/rcheat/tar.gz/refs/heads/dev0","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248196317,"owners_count":21063392,"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":["cli","elf","gdb","process","ptrace"],"created_at":"2024-09-24T23:27:19.969Z","updated_at":"2026-05-01T07:04:50.368Z","avatar_url":"https://github.com/handy-sun.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# **rcheat**\n\n**English | [简体中文](./README.zh-CN.md)**\u003cbr\u003e\n[![build-test](https://github.com/handy-sun/rcheat/actions/workflows/build-test.yml/badge.svg)](https://github.com/handy-sun/rcheat/actions/workflows/build-test.yml)\n![latest_release](https://img.shields.io/github/v/tag/handy-sun/rcheat?label=release)\n[![Crates.io](https://img.shields.io/crates/v/rcheat.svg)](https://crates.io/crates/rcheat)\n![Linux](https://img.shields.io/badge/-Linux-grey?logo=linux)\n\n\u003e *Get/modify simple variable's value in another Linux running process*\n\n**Please note that this project is only for learning and research purposes, and the author is not responsible for any legal consequences caused by the use of this project.**\n\n------\n\n\u003c!-- vscode-markdown-toc --\u003e\n## Table of Contents\n* 1. [Installation](#Installation)\n\t* 1.1. [Via cargo](#Viacargo)\n\t* 1.2. [Build src](#Buildsrc)\n\t\t* 1.2.1. [Dependencies](#Dependencies)\n\t\t* 1.2.2. [Building](#Building)\n* 2. [Simple Example](#SimpleExample)\n* 3. [Lua Scripting](#lua-scripting)\n* 4. [Todo](#Todo)\n\n\u003c!-- vscode-markdown-toc-config\n\tnumbering=true\n\tautoSave=true\n\t/vscode-markdown-toc-config --\u003e\n\u003c!-- /vscode-markdown-toc --\u003e\n\n##  1. \u003ca name='Installation'\u003e\u003c/a\u003eInstallation\n\n###  1.1. \u003ca name='Viacargo'\u003e\u003c/a\u003eVia cargo\n\n\u003cdetails\u003e\n\u003csummary\u003eSome ways to install cargo\u003c/summary\u003e\n\n- can be obtained using [rustup](https://rust-lang.github.io/rustup/)(Recommond)\n- use Linux package management(e.g. apt, yum, dnf, pacman)\n- download a offline tarball from [forge.rust-lang.org](https://forge.rust-lang.org/infra/archive-stable-version-installers.html)\n\u003c/details\u003e\n\nIn order to install, just run the following command\n\n```sh\ncargo install --force rcheat\n```\n\nThis will install cargo-make in your `~/.cargo/bin`.\nMake sure to add `~/.cargo/bin` directory to your `PATH` variable.\nYou will have a executable available: *`rcheat`*\n\n###  1.2. \u003ca name='Buildsrc'\u003e\u003c/a\u003eBuild src\n\n\u003c!-- \u003ca name=\"dependencies\"\u003e\u003c/a\u003e --\u003e\n####  1.2.1. \u003ca name='Dependencies'\u003e\u003c/a\u003eDependencies\n\n- [cargo](https://github.com/rust-lang/cargo/) \u003e= 1.74\n- [rustc](https://www.rust-lang.org/) \u003e= 1.74\n\nSuggest using the latest version\n\n####  1.2.2. \u003ca name='Building'\u003e\u003c/a\u003eBuilding\n\n```shell\ngit clone https://github.com/handy-sun/rcheat.git\ncd rcheat\ncargo build\n```\n\nYou will have a executable available: *`./target/debug/rcheat`*\n\n**Tips:**\nIf download speed from `crates.io` is too slow. use a mirror to speed up(e.g. use [rsproxy](https://rsproxy.cn)).\n\n\n\u003ca name=\"simple-example\"\u003e\u003c/a\u003e\n##  2. \u003ca name='SimpleExample'\u003e\u003c/a\u003eSimple Example\n\nfor example, a `C` source file `onlyc.c` with some global variables:\n\n```c\n#include \u003cunistd.h\u003e\n\nconst char sc_sig_arr[][6] = { \" \", \"HUP\", \"INT\", \"QUIT\", \"ILL\", \"TRAP\", \"IOT\", \"BUS\", \"FPE\", \"KILL\" };\nconst char techs[] = \"\\x02str.wa : ? !\\ndaw\\r21\";\nstruct DemoStru {\n    int int32;\n    short uint16;\n};\nstruct DemoStru structure;\n\nint main() {\n    structure.int32 = 0x7ffe8092;\n    structure.uint16 = 0x321b;\n    while (1) {\n        sleep(30);\n    }\n    return 0;\n}\n```\n\nThen compile and run it:\n```sh\ngcc onlyc.c -o onlyc \u0026\u0026 ./onlyc\n```\n\nGet pid of `onlyc`(e.g. use command: `pidof`) and use `rcheat` with `-p` option:\n**NOTE: This program must be run with root privileges!**\n\n```sh\npidof onlyc\n# output: 13725\nsudo rcheat -p 13725\n```\n\nThen will get the output about all global variables about this program\n```\n...\nMatched count: 3\nIndex: var_name                                 | var_size(B)\n    0: sc_sig_arr                               |      60\n    1: structure                                |       8\n    2: techs                                    |      21\nPlease input index to choose the var(default is 0):\n```\n\nInput `2` and `Enter`, you will see the byte value and ascii content of this variable (control char that unvisible show as `.`)\n\n```\n0x0000: 0273 7472 2e77 6120 3a20 3f20 210a 6461 ┃ .str.wa : ? !.da\n0x0010: 770d 3231 00                            ┃ w.21.\n```\n\nYou also can specify the total name or partly keyword of the variable with option `-k`\n\n```sh\nsudo rcheat -p 13725 -k sig_arr\n```\n```\n...\n\n0x0000: 2000 0000 0000 4855 5000 0000 494e 5400 ┃  .....HUP...INT.\n0x0010: 0000 5155 4954 0000 494c 4c00 0000 5452 ┃ ..QUIT..ILL...TR\n0x0020: 4150 0000 494f 5400 0000 4255 5300 0000 ┃ AP..IOT...BUS...\n0x0030: 4650 4500 0000 4b49 4c4c 0000           ┃ FPE...KILL..\n```\n\nAfter version `0.1.3`, option `-n/--name` can query pid by process name\n\n```\nsudo rcheat -n onlyc -k sig_arr\n```\n\n##  3. Lua Scripting\n\nSince version `0.2.0`, rcheat supports using Lua scripts to define custom binary struct parsing and formatted table output. Use the `-f lua` option to enable it.\n\n### How It Works\n\n1. Place Lua script files in `/etc/rcheat/lua/`\n2. Run `rcheat` with `-f lua`:\n\n```sh\nsudo rcheat -n onlyc -k structure -f lua\n```\n\n3. rcheat loads `core.lua` (built-in), then loads all `.lua` files from the script directory\n4. Matches the variable name against `Structure.match_table` to find the alias\n5. Calls `Structure:new_\u003calias\u003e(bytes)` to parse the raw bytes into a table\n6. Outputs a formatted table\n\n### Writing a Lua Script\n\nEvery script must define a global `Structure` table with:\n\n- `match_table` — maps variable name patterns (Lua string.find) to aliases\n- `new_\u003calias\u003e(bytes)` — constructor that parses raw bytes and returns an instance\n\nColumn definition format:\n\n| Field | Description | Examples |\n|-------|-------------|----------|\n| `name` | Column header name | `'id'`, `'health'` |\n| `size` | Number of bytes | `1`, `2`, `4`, `8` |\n| `fmt` | [string.unpack](https://www.lua.org/manual/5.4/manual.html#6.4.2) format | `'i'` signed, `'I'` unsigned, `'f'` float, `'s'` string, `'c'` char, `nil` auto signed int |\n\nWhen `fmt` is `'i'`, `'I'`, `'s'`, or `'c'`, the size is appended automatically (e.g. `i4`, `I1`). When `fmt` is `nil`, it defaults to `i\u003csize\u003e` (signed integer). For `'f'`, the size is determined by the format itself (4 bytes for `f`, 8 for `d`).\n\n### Example\n\n`/etc/rcheat/lua/example.lua`:\n\n```lua\nStructure = {}\nStructure.__index = Structure\n\n-- Match variable names containing 'pcmStateList' to alias 'psl'\nStructure.match_table = {\n    ['pcmStateList'] = 'psl',\n}\n\n-- Constructor: parse bytes into a table with columns {id, stared, act}\nfunction Structure:new_psl(bytes)\n    self.psl_col = {\n        { name = 'id',     size = 4, fmt = 'i' },  -- signed 32-bit int\n        { name = 'stared', size = 1, fmt = 'I' },  -- unsigned 8-bit int\n        { name = 'act',    size = 4, fmt = 'f' },  -- 32-bit float\n    }\n\n    return setmetatable({ psl = SetupTableData(bytes, self.psl_col) }, Structure)\nend\n```\n\nOutput (rcheat will format it as an aligned table):\n\n```\n╭─────┬────┬────────╮\n│ (i) │ id │ stared │   act │\n├─────┼────┼────────┤───────┤\n│   0 │  1 │      0 │  3.50 │\n│   1 │  2 │      1 │  7.25 │\n╰─────┴────┴────────┴───────╯\n```\n\n### Built-in Functions (core.lua)\n\n`SetupTableData(bytes, tab_list)` — Iterates over raw bytes according to the column definitions and returns a two-dimensional table. Each row is an array of `{ name, size, data }` entries. The function loops over the byte array, slicing it by each column's `size` and unpacking with `string.unpack` using the specified `fmt`.\n\n##  4. \u003ca name='Todo'\u003e\u003c/a\u003eTodo\n\n*The development plan of the project and the functions to be implemented*\n\n- [ ] parse `.debug*` section\n- [ ] use log crate such as `log/env_logger` etc.\n- [ ] write data to tracee process' memory\n- [ ] use config.toml to reduce some inputs\n- [x] use lib like `table` to format matrix table data\n- [x] use `lua` to customized output\n- [x] search pid by process name (like linux command: `pidof/pgrep`)\n- [x] regex replace String.contain\n- [x] if match more than 1 entry name, ask for which one to select\n- [x] demangle symbols\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhandy-sun%2Frcheat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhandy-sun%2Frcheat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhandy-sun%2Frcheat/lists"}