Skip to content

Commit 1cf04ed

Browse files
committed
Initial commit
0 parents  commit 1cf04ed

File tree

16 files changed

+933
-0
lines changed

16 files changed

+933
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "LuaExMemoryTool"
3+
version = "0.1.0"
4+
edition = "2024"
5+
repository = "https://github.com/Klarexxx/LuaExMemoryTool"
6+
license = "MIT"
7+
8+
[dependencies]
9+
mlua = { version = "0.11.5", features = ["vendored", "lua54"] }
10+
11+
[profile.release]
12+
strip = true
13+
lto = true
14+
debug = false
15+
codegen-units = 1
16+
panic = "abort"
17+
opt-level = "s"

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 klarex
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# LuaExMemoryTool
2+
3+
The LuaExMemoryTool is a Rust-based executable that allows running Lua scripts for **external process memory access and manipulation** on Linux and Android systems.
4+
It uses the **mlua** library to embed Lua and exposes additional native functions for process and memory operations.
5+
6+
> Root access is required.
7+
8+
## Overview
9+
10+
The project compiles into a standalone executable.
11+
You provide a `.lua` file path as an argument, and the executable runs that Lua script with extended memory-related APIs.
12+
13+
Supported platforms:
14+
- Linux
15+
- Android
16+
17+
## Build
18+
19+
This is a standard Rust project.
20+
21+
Requirements:
22+
- Rust toolchain
23+
- Cargo
24+
25+
Build command:
26+
```bash
27+
cargo build --release
28+
````
29+
30+
The resulting executable will be located under:
31+
32+
```
33+
target/release/
34+
```
35+
36+
## Usage
37+
38+
Run the executable and pass a Lua script path:
39+
40+
```bash
41+
./LuaExMemoryTool script.lua
42+
```
43+
44+
Example Lua scripts are provided in the `examples/` directory.
45+
46+
## Lua API
47+
48+
### Process List
49+
50+
Retrieve the list of currently running processes:
51+
52+
```lua
53+
for _, item in ipairs(get_process_list()) do
54+
local pid = item.pid
55+
local package_name = item.name
56+
end
57+
```
58+
59+
Aliases:
60+
61+
* `get_process_list`
62+
* `process_list`
63+
64+
Each item contains:
65+
66+
* `pid`: number
67+
* `name`: string
68+
69+
### Kill Process
70+
71+
Terminate a process by PID:
72+
73+
```lua
74+
kill_process(pid)
75+
```
76+
77+
---
78+
79+
### `process` Class
80+
81+
Used to initialize and manage a target process.
82+
83+
#### Initialization
84+
85+
Initialize by package name:
86+
87+
```lua
88+
process = process.init("package_name")
89+
```
90+
91+
Initialize by PID:
92+
93+
```lua
94+
process = process.init_via_pid(pid)
95+
```
96+
97+
Fields:
98+
99+
* `pid`: number
100+
* `name`: string
101+
102+
#### Memory Maps
103+
104+
Retrieve memory mappings of the process:
105+
106+
```lua
107+
for map in process:get_maps() do
108+
-- ...
109+
end
110+
```
111+
112+
Each map entry contains:
113+
114+
* `start`: number
115+
* `end`: number
116+
* `perms`: string
117+
* `offset`: number
118+
* `dev`: string
119+
* `inode`: number
120+
* `path`: string
121+
122+
---
123+
124+
### `memory` Class
125+
126+
Used to read and write process memory.
127+
128+
#### Initialization
129+
130+
```lua
131+
process = process.init("package_name")
132+
memory = memory.init(process)
133+
```
134+
135+
#### Read / Write Methods
136+
137+
Read methods require only an address.
138+
Write methods require an address and a value.
139+
140+
Supported methods:
141+
142+
* `read_i8(address)` / `write_i8(address, value)`
143+
* `read_bool(address)` / `write_bool(address, value)`
144+
* `read_i16(address)` / `write_i16(address, value)`
145+
* `read_i32(address)` / `write_i32(address, value)`
146+
* `read_i64(address)` / `write_i64(address, value)`
147+
* `read_float(address)` / `write_float(address, value)`
148+
* `read_float64(address)` / `write_float64(address, value)`
149+
* `read_pointer(address)` / `write_pointer(address, value)`
150+
* `read_hex(address, length)`
151+
* `write_hex(address, hex_string)`
152+
153+
## Examples
154+
155+
Example Lua scripts are available in the `examples/` directory and demonstrate:
156+
157+
* Process listing
158+
* Process initialization
159+
* Memory map inspection
160+
* Memory read/write operations
161+
162+
## License
163+
164+
MIT License

examples/get_maps.lua

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
process = process.init("example_app");
2+
3+
for _, item in pairs(process:get_maps()) do
4+
if item.path then
5+
if string.find(item.path, "GameAssembly.so", 1, true) then
6+
print("start: " .. item.start)
7+
print("end: " .. item["end"])
8+
print("perms: " .. item.perms)
9+
print("offset: " .. item.offset)
10+
print("dev: " .. item.dev)
11+
print("inode: " .. item.inode)
12+
print("path: " .. item.path)
13+
print("\n")
14+
end
15+
end
16+
end
17+
18+
--[[
19+
20+
start: number
21+
end: number
22+
perms: string
23+
offset: number
24+
dev: string
25+
inode: number
26+
path: string
27+
28+
----------------------------
29+
30+
start: 138617167020032
31+
end: 138617192181760
32+
perms: r--p
33+
offset: 0
34+
dev: 103:02
35+
inode: 16687707
36+
path: /example_app/GameAssembly.so
37+
38+
39+
start: 138617192181760
40+
end: 138617229164544
41+
perms: r-xp
42+
offset: 25161728
43+
dev: 103:02
44+
inode: 16687707
45+
path: /example_app/GameAssembly.so
46+
47+
48+
start: 138617229164544
49+
end: 138617231609856
50+
perms: r--p
51+
offset: 62144512
52+
dev: 103:02
53+
inode: 16687707
54+
path: /example_app/GameAssembly.so
55+
56+
57+
start: 138617231609856
58+
end: 138617233391616
59+
perms: rw-p
60+
offset: 64589824
61+
dev: 103:02
62+
inode: 16687707
63+
path: /example_app/GameAssembly.so
64+
65+
]]

examples/get_module_base.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function getModuleBase(process, lib_name)
2+
for _, item in pairs(process:get_maps()) do
3+
if item.path then
4+
if string.find(item.path, lib_name, 1, true) then
5+
if item.perms == 'r--p' then
6+
return item.start
7+
end
8+
end
9+
end
10+
end
11+
end
12+
13+
process = process.init("example_app");
14+
15+
module = getModuleBase(process, "GameAssembly.so");
16+
17+
if module then
18+
print("GameAssembly.so Start Address: " .. module)
19+
print("GameAssembly.so Start Address: 0x" .. string.format("%X", module))
20+
else
21+
print("GameAssembly.so Not Found")
22+
end
23+
24+
--[[
25+
26+
GameAssembly.so Start Address: 138617167020032
27+
28+
138617167020032 == 0x7E1253000000
29+
30+
]]

examples/mlbb.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
function getModuleBase(process, lib_name)
2+
for _, item in pairs(process:get_maps()) do
3+
if item.path then
4+
if string.find(item.path, lib_name, 1, true) then
5+
if item.perms == 'r--p' then
6+
return item.start
7+
end
8+
end
9+
end
10+
end
11+
end
12+
13+
process = process.init("com.mobile.legends:UnityKillsMe");
14+
print("process initialized")
15+
16+
memory = memory.init(process);
17+
print("memory initialized")
18+
19+
module = getModuleBase(process, "libcsharp.so");
20+
21+
22+
if module then
23+
print("libcsharp.so Start Address: 0x" .. string.format("%X", module))
24+
else
25+
print("libcsharp.so Not Found")
26+
end
27+
28+
-- you need to find it :)
29+
map_hack = 0x1234567
30+
31+
memory:write_hex(module + map_hack, "20 00 80 D2 C0 03 5F D6");

examples/process_list.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
for _, item in ipairs(get_process_list()) do
2+
local pid = item.pid
3+
local package_name = item.name
4+
print(pid, package_name)
5+
end
6+
7+
--[[
8+
9+
535 android.process.media
10+
1126 com.android.camera
11+
1612 com.android.vending
12+
13+
]]
14+
15+
16+
-- find process
17+
for _, item in ipairs(get_process_list()) do
18+
local pid = item.pid
19+
local app_name = item.name
20+
21+
if string.find(app_name, "example_app", 1, true) then
22+
print("process is running")
23+
print(pid, app_name)
24+
end
25+
26+
end

0 commit comments

Comments
 (0)