rev-symbol - Symbol Recovery
SkillDev toolsRestore function symbols by analyzing code patterns, strings, constants, and cross-references
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the rev-symbol - Symbol Recovery skill
What this skill tells your AI
The instructions your AI receives, as published by index-login/mobilere-skill in .kilo/skill/rev-symbol/SKILL.md and read by ahel’s review.
Analyze function code characteristics to recover/identify function symbols and names.
Adapted from P4nda0s/reverse-skills (MIT) for the Ghidra MCP toolchain (upstream targets IDA; the analysis methodology is unchanged).
Data Sources
The upstream skill reads an IDA-NO-MCP export directory (decompile/*.c with callers: / callees: headers, strings.txt, imports.txt, exports.txt). The equivalent sources here — repo scripts live under frida-mobile-security/scripts/utils/:
| Data | Offline (no Ghidra instance) | Ghidra MCP |
|---|---|---|
| Imports / exports / deps / relocs / segments / vaddr↔offset | elfinfo.py <so> --json | ghidra_list_imports, ghidra_list_exports, ghidra_list_external_locations |
| Strings | strings -a -t x <so> | ghidra_list_strings, ghidra_search_strings |
| String → code xrefs | find_strref.py <so> <str_vaddr> | ghidra_get_xrefs_to |
| Callers of a function | find_branch_callers.py <so> <func_vaddr> | ghidra_get_function_callers |
| Callees of a function | read from the pseudocode | ghidra_get_function_callees |
| Function pseudocode | — | ghidra_decompile_function |
| Whole-.so export (upstream layout) | — | ghidra_batch_decompile + ghidra_get_bulk_xrefs, or a custom dump via ghidra_run_ghidra_script |
The offline tools need no Ghidra instance and are deterministic — use them for the static tables; use Ghidra MCP for pseudocode, xrefs and renaming. Single-function recovery should query on demand; build a full export only when the whole .so is in scope.
Pre-check
Ghidra MCP (ghidra_* tools):
- Target .so not yet imported →
adb pullit from the device, thenghidra_import_file(ELF auto-detects the language; explicit IDs: ARM64AARCH64:LE:64:v8A, ARM32ARM:LE:32:v7). - Query the loaded instance: decompile by address/name, get callers/callees, list strings/imports/exports, rename functions, apply comments.
- Exact tool names depend on the loaded tool groups — list or search them with
ghidra_list_tool_groups/ghidra_search_toolswhen unsure.
If no Ghidra instance is connected, check ghidra_list_instances and connect with ghidra_connect_instance, or ask the user to start one.
Symbol Recovery Steps
Step 1: Analyze Internal Characteristics
Carefully examine the target function for:
- String constants: Strings used in the function may reveal its purpose
- Numeric constants / Magic Numbers:
- MD5:
0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476 - CRC32:
0xEDB88320 - Base64 charset:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ - AES S-Box:
0x63, 0x7C, 0x77, 0x7B... - Zlib:
0x78,0x9C(compression header) - other constants/magic numbers...
- MD5:
- Code structure: Loop patterns, bitwise operations, specific algorithm flows
If you can identify a known algorithm through constants/structure, tell the user directly.
Step 2: Analyze Cross-References
Analyze Callees (called functions):
- Get the callee list with
ghidra_get_function_callees, or read the calls from the pseudocode (ghidra_decompile_function). - Classify each callee against the import table —
ghidra_list_imports/ghidra_list_external_locations, orelfinfo.pyoffline. A callee that resolves to an import (external location,thunk_*, undefined in .dynsym) is a library call; name it from the import symbol. - Recognize call patterns even when symbols are missing:
Paired function patterns (identify by matching call pairs):
// malloc/free, new/delete, alloc/dealloc
xx = sub_A(0x100); // alloc: takes size, returns pointer
...
sub_B(xx); // free: takes the same pointer
// mutex_lock/mutex_unlock, pthread_mutex_lock/unlock
sub_A(lock_ptr); // lock
... // critical section
sub_B(lock_ptr); // unlock (same lock object)
// open/close, fopen/fclose, CreateFile/CloseHandle
fd = sub_A("/path", 0); // open: path + flags, returns handle
...
sub_B(fd); // close: takes the handle
// pthread_create/pthread_join
sub_A(&tid, 0, func, arg); // create: out param, attr, func, arg
...
sub_B(tid, &ret); // join: tid, out param
Argument pattern recognition:
// socket(AF_INET, SOCK_STREAM, 0) - fixed constants
sub_XXX(2, 1, 0); // socket: domain=2, type=1, protocol=0
// connect/bind(sockfd, addr, addrlen)
sub_XXX(fd, &var, 16); // addr struct, len=16 for IPv4
// memcpy/memmove(dst, src, size)
sub_XXX(dst, src, n); // 3 params: dst, src, count
// memset(ptr, value, size)
sub_XXX(ptr, 0, 0x100); // 3 params: ptr, byte value, count
// read/write(fd, buf, count)
ret = sub_XXX(fd, buf, n); // returns bytes read/written
// strcmp/strncmp(s1, s2) or (s1, s2, n)
if (sub_XXX(s1, s2) == 0) // returns 0 on equal
Return value patterns:
// file/socket operations: -1 on error
if ((fd = sub_XXX(...)) == -1) goto error;
// allocation: NULL on failure
if (!(ptr = sub_XXX(size))) goto error;
// success/error: 0 = success
if (sub_XXX(...) != 0) goto error;
// strlen: returns size_t
len = sub_XXX(str);
sub_YYY(dst, src, len); // len used in memcpy
Analyze Callers (calling functions):
- Get the caller list with
ghidra_get_function_callers, orfind_branch_callers.pyoffline. - A caller counts as named only when its symbol is not auto-generated (
FUN_/sub_/thunk_/LAB_/j_prefix) — i.e. it comes from the export table or has already been renamed. - Bounded recursion: if the direct caller is unnamed, walk up its callers; stop at the first named caller or at depth 3. If nothing is named, fall back to internal characteristics (Step 1) and web search (Step 3).
- Analyze how the return value is used by callers.
Step 3: Information Gathering and Search
Collect the following information:
- Strings referenced by the function (
ghidra_get_xrefs_toon the string address, orfind_strref.pyoffline) - Magic Numbers / constants
- Known imports in the call chain (
ghidra_list_imports, orelfinfo.pyoffline) - Caller/callee symbol names (
ghidra_list_exports,elfinfo.pyexports, already-renamed functions) - Paired function patterns identified
Based on collected information:
-
First attempt local reasoning based on:
- Function signature (number and types of parameters)
- Paired call patterns (alloc/free, lock/unlock)
- Known imports in the call chain
- Code structure similarity to known algorithms
-
If uncertain, use Web Search to search:
- Search Magic Numbers:
0x67452301 0xEFCDAB89 algorithm - Search code patterns:
rotate left xor constant algorithm - Search unique strings found in the function
- Search parameter patterns:
function(int, int, 0) socket
- Search Magic Numbers:
Output Format
## Symbol Recovery Analysis: <function_address>
### Function Characteristics
- Strings: <list discovered strings>
- Constants: <list key constants>
- Called imports: <list>
### Cross-Reference Analysis
- Callers: <callers and their symbols>
- Callees: <callees and their symbols>
### Inference Result
- **Suggested symbol name**: <suggested_name>
- **Confidence**: High / Medium / Low
- **Reasoning**: <explain why this name is suggested>
### Similar Open Source Implementation
- <if similar open source code is found, provide link>
Signals
- GitHub stars
- 27
- Forks
- 9
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
rev-symbol- Source
- github.com/index-login/mobilere-skill