Skip to content
generated from 8dcc/c-template

Simple C/C++ library for signature scanning on Linux

License

Notifications You must be signed in to change notification settings

8dcc/libsigscan

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

76 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

libsigscan

Simple C/C++ library for signature scanning on Linux.

This library is for matching byte patterns (signatures) in the memory of a process. It’s able to scan the memory of the current process, or an external process using the process_vm_readv function.

It only supports linux, since it parses the /proc/PID/maps file to get the start and end addresses of the loaded modules.

The library asumes all signatures are in IDA (DE AD ? EF) or x64Dbg (DE AD ?? EF) format. See also the sigmaker plugin.

For more information on signature scanning and on how this library works, check out my Signature scanning in C blog entry.

Building the example

To try the example, simply clone the repository, compile it, and run libsigscan-test.out. Please see src/main.c and the Usage section for an example on how to use it.

$ git clone https://github.com/8dcc/libsigscan
$ cd libsigscan
$ make
$ ./libsigscan-test.out

If you want to try the external example, run the following two commands in separate terminals after compiling.

$ ./libsigscan-test-external.out  # Simulates target process, keep it open
$ sudo ./libsigscan-test.out      # Scans the other process, needs root

Usage

Including in a project

If you want to use this library, simply copy the detour source and headers to your project, #include the header in your source files and compile the libsigscan.c source with the rest of your code.

For a full example, see src/main.c. For more information on how to compile it, see the Makefile.

Public functions

The library is pretty simple and consists of one main function for signature scanning, and some wrappers for it. There are also some utilities that may be used independently. All the functions are documented in the header, but I will explain them here as well.

sigscan_pidof

This utility function can be used to get the PID of a process by name.

#include "libsigscan.h"

int pid = sigscan_pidof("my-test.out");

sigscan_pid_module

This is the main function of the library. It scans all the modules loaded by the process with the specified pid, whose name matches the specified regex.

It uses POSIX Extended Regular Expression (ERE) syntax, so keep that in mind before escaping certain characters like +, ?, etc. See also BRE vs. ERE.

Also note that it skips modules starting with [ in /proc/PID/maps, like heap, stack, etc.

#include "libsigscan.h"

#define MODULE_REGEX ".+/libc\\.so\\.6"
#define SIGNATURE    "DE AD BE EF ? ? CA FE"

/*
 * Search for a signature in the modules loaded by "my-test.out" whose name
 * matches the regex.
 */
int pid     = sigscan_pidof("my-test.out");
void* match = sigscan_pid_module(pid, MODULE_REGEX, SIGNATURE);

sigscan_pid, sigscan_module and sigscan

These functions are just wrappers for sigscan_pid_module.

The sigscan_pid function can be used to search for a pattern in all modules loaded by the process with the specified PID. Same as using NULL as the second parameter of sigscan_pid_module.

The sigscan_module function can be used to search for a pattern in the modules loaded by the current process, whose name matches a regex. Same as using SIGSCAN_PID_SELF as the first parameter of sigscan_pid_module.

The sigscan function can be used to search for a pattern in all modules loaded by the current process. Same as using SIGSCAN_PID_SELF and NULL as the first and second parameters of sigscan_pid_module.

sigscan_get_module_bounds and sigscan_free_module_bounds

These functions are used internally by the library when calling sigscan_pid_module. They are exposed, so the user can call them whenever necessary.

The sigscan_get_module_bounds function parses the /proc/PID/maps file (see proc(5)) to get the start and end addresses of the modules loaded by the process with the specified PID, whose name matches the specified regex. Similarly to sigscan_pid_module, it accepts SIGSCAN_PID_SELF as its first parameter, and NULL as its second parameter.

It returns a linked list of SigscanModuleBounds structures, and each element contains the start and end addresses of a readable memory chunk. The caller is responsible for freeing this linked list by calling sigscan_free_module_bounds.

Troubleshooting

If you are having any unexpected problems with this library (e.g. it’s not able to find a signature that you know to be there), try compiling the libsigscan.c source with LIBSIGSCAN_DEBUG defined. You can easily do this by adding the following compilation option to your CFLAGS.

-CFLAGS=-std=gnu99 -Wall -Wextra -Wpedantic
+CFLAGS=-std=gnu99 -Wall -Wextra -Wpedantic -DLIBSIGSCAN_DEBUG

Now the library will print some useful information to stderr. For example:

my-user-program: Searching in all modules matching regex "^.*module\.o$"...
libsigscan: Couldn't get any module bounds matching regex "^.*module\.o$" in /proc/364195/maps

In that example, you might want to look at the output of cat /proc/self/maps and see if, for example, the module.o line ends with (deleted). In that case, you should remove the $ from the regex.

If any other unexpected errors occur, please report them with as much information as possible.