#ifndef _MEMGREP_H #define _MEMGREP_H #include /** * @defgroup memgrep The memory manglement library interface. * * The memory manglement library interface. */ /** * @addtogroup memgrep * * @{ */ /** * @example simple.c * Example for using memgrep as a library. */ /** * Initialize from a given medium. * * Initializes a given memgrep context to a given medium. The 'param' argument should * be one of the enumerations in the MemoryMedium enum. The 'data' argument should * be the arbitrary value associated with the medium. For MEMORY_MEDIUM_PID it will * be the process id. For MEMORY_MEDIUM_CORE it will be the core file. */ #define MEMGREP_CMD_INITIALIZE 0x00000001 /** * Deinitialize from a given medium. * * Deinitializes a given memgrep context. This will free up any resources that had * incurred over the time of its use. */ #define MEMGREP_CMD_DEINITIALIZE 0x00000002 /** * Set parameters on a context. * * The 'param' argument can be one of the following: * * @li MEMGREP_PARAM_FLAGS * The data argument should be set to the flags that are to be enabled on the context. * @li MEMGREP_PARAM_LENGTH * The data argument should be set to the length that is to be used when dumping/searching. * @li MEMGREP_PARAM_PADDING * The data argument should be set to the length that is to be used with padding. */ #define MEMGREP_CMD_SET 0x00000003 /** * Get parameters that have been set on a context. * * The 'param' argument can be one of the following: * * @li MEMGREP_PARAM_FLAGS * The flags the context is using will be returned. * @li MEMGREP_PARAM_LENGTH * The length associated with dumping/searching will be returned. * @li MEMGREP_PARAM_PADDING * The padding associated with dumping will be returned. */ #define MEMGREP_CMD_GET 0x00000004 /** * Populate the address array from supplied address(es). * * The 'param' argument can be one of the following: * * @li A string * If the param argument is a string it should have addresses formatted * with each address being seperated by commas. Addresses can be specified in hex * as well as in the form of a keyword such as: bss, stack, rodata, data, all. * The 'data' parameter should be set to 0. * @li An array * If the param argument is an array it should be an array of unsigned long's * which hold the addresses that are to be used. The 'data' argument should * have the number of elements the array contains. */ #define MEMGREP_CMD_POPULATE 0x00000005 /** * Search for a given criteria in the addresses specified by MEMGREP_CMD_POPULATE. * * The 'param' argument is used in conjunction with the search criteria. * It can be in the following format: * * @li s,example * This will search for the string 'example' in the addresses specified in MEMGREP_CMD_POPULATE * @li i,47 * This will search for the integer 47 in the addresses specified in MEMGREP_CMD_POPULATE * @li x,656667 * This will search for the hex \x65\x66\x67 in the addresses specified in MEMGREP_CMD_POPULATE. * * The 'data' argument is undefined and should be set to 0. */ #define MEMGREP_CMD_SEARCH 0x00000006 /** * Replace memory with the specified data at the addresses specified by MEMGREP_CMD_POPULATE. * * The 'param' argument is used in conjunction with the replace criteria. * It can be in the following format: * * @li s,example * This will replace for the string 'example' in the addresses specified in MEMGREP_CMD_POPULATE * @li i,47 * This will replace for the integer 47 in the addresses specified in MEMGREP_CMD_POPULATE * @li x,656667 * This will replace for the hex \x65\x66\x67 in the addresses specified in MEMGREP_CMD_POPULATE. * * The 'data' argument is undefined and should be set to 0. * * Results are optionally returned in the 'result' argument if it is not null of type MEMGREP_RESULT_TYPE_SEARCH. */ #define MEMGREP_CMD_REPLACE 0x00000007 /** * Search and replace memory that matches the criteria for the addresses specified by MEMGREP_CMD_POUPLATE. * * The 'param' argument is used in conjunction with the search criteria. * It can be in the following format: * * @li s,example * This will search for the string 'example' in the addresses specified in MEMGREP_CMD_POPULATE * @li i,47 * This will search for the integer 47 in the addresses specified in MEMGREP_CMD_POPULATE * @li x,656667 * This will search for the hex \x65\x66\x67 in the addresses specified in MEMGREP_CMD_POPULATE. * * The 'data' argument is used in conjunction with the replace criteria. * It can be in the following format: * * @li s,example * This will replace for the string 'example' in the addresses that match the search criteria. * @li i,47 * This will replace for the integer 47 in the addresses that match the search criteria. * @li x,656667 * This will replace for the hex \x65\x66\x67 in the addresses that match the search criteria. * * Results are optionally returned in the 'result' argument if it is not null of type MEMGREP_RESULT_TYPE_REPLACE. */ #define MEMGREP_CMD_SEARCHREPLACE 0x00000008 /** * Dump memory for the addresses specified in MEMGREP_CMD_POPULATE. * * No parameters are required. * * Results are optionally returned in the 'result' argument if it is not null of type MEMGREP_RESULT_TYPE_DUMP. */ #define MEMGREP_CMD_DUMP 0x00000009 /** * List all the segments of a given medium such as rodata, stack, bss, etc. * * No parameters are required. */ #define MEMGREP_CMD_LISTSEGMENTS 0x0000000A /** * Destroy the contents of a result that was handed back by a command * * The 'param' argument should be a pointer to a result structure. * * The 'data' argument is undefined and should be 0. */ #define MEMGREP_CMD_DESTROYRESULT 0x0000000B /** * Enumerate the heap of a running process * * The 'param' argument is the minimize size of the heap unit, or 0. * * The 'data' argument is undefined and should be 0. */ #define MEMGREP_CMD_HEAPENUMERATE 0x0000000C /** * Specifies that the data parameter will be flags when used in conjunction with MEMGREP_CMD_SET. */ #define MEMGREP_PARAM_FLAGS 0x00000001 /** * Specifies that the data parameter will be the length when used in conjunction with MEMGREP_CMD_SET. */ #define MEMGREP_PARAM_LENGTH 0x00000002 /** * Specifies that the data parameter will be dump padding size when used in conjunction with MEMGREP_CMD_SET. */ #define MEMGREP_PARAM_PADDING 0x00000003 /** * Specifies that the data parameter will be the format to use when dumping. */ #define MEMGREP_PARAM_DUMPFORMAT 0x00000004 /** * The derived instance of this row is a MEMGREP_RESULT_ROW_SEARCH and should be cast as such. */ #define MEMGREP_RESULT_TYPE_SEARCH 0x00000001 /** * The derived instance of this row is a MEMGREP_RESULT_ROW_REPLACE and should be cast as such. */ #define MEMGREP_RESULT_TYPE_REPLACE 0x00000002 /** * The derived instance of this row is a MEMGREP_RESULT_ROW_DUMP and should be cast as such. */ #define MEMGREP_RESULT_TYPE_DUMP 0x00000003 /** * The derived instance of this row is a MEMGREP_RESULT_ROW_HEAP and should be cast as such. */ #define MEMGREP_RESULT_TYPE_HEAP 0x00000004 /** * Flag used to enable verbose output when performing actions. */ #define MEMGREP_FLAG_VERBOSE (1 << 0) /** * Flag used to enable prompting before replacing memory. */ #define MEMGREP_FLAG_PROMPT (1 << 1) /** * Flag used to enable output of dumping memory in a clear-text format rather than hex. */ #define MEMGREP_FLAG_DUMPCLEAN (1 << 2) /** * Mediums used when operating with memgrep. * * @short memory access mediums */ enum MemoryMedium { /** * An unknown medium */ MEMORY_MEDIUM_UNKNOWN = 0, /** * Access memory via a process id */ MEMORY_MEDIUM_PID = 1, /** * Access memory via a core file */ MEMORY_MEDIUM_CORE = 2 }; /** * The format to use when dumping memory * * @short memory dumping format */ enum MemoryDumpFormat { /** * Dump as hex integers (0xabcdef00) */ MEMORY_DUMP_FORMAT_HEXINT = 0, /** * Dump as hex shorts (0xabcd) */ MEMORY_DUMP_FORMAT_HEXSHORT = 1, /** * Dump as hex characters (0xab) */ MEMORY_DUMP_FORMAT_HEXBYTE = 2, /** * Dump as decimal integers (1234) */ MEMORY_DUMP_FORMAT_DECINT = 3, /** * Dump as decimal shorts (65535) */ MEMORY_DUMP_FORMAT_DECSHORT = 4, /** * Dump as decimal characters (127) */ MEMORY_DUMP_FORMAT_DECBYTE = 5, /** * Dump as ascii printable characters */ MEMORY_DUMP_FORMAT_PRINTABLE = 6, }; /** * Holds the addresses that signify the start of a given logical section. * * @short Section addresses */ typedef struct _process_section_addrs { /** * 0.8.0+: Text section of the binary image. */ unsigned long text; /** * 0.8.0+: The length of the text section of the binary image. */ unsigned long textLength; /** * Read-only data, commonly associated with static text. */ unsigned long rodata; /** * 0.8.0+: The length of the read-only data section. */ unsigned long rodataLength; /** * Data, commonly associated with global or static variables. */ unsigned long data; /** * 0.8.0+: The length of the data section. */ unsigned long dataLength; /** * bss, commonly associated with the 'heap'. */ unsigned long bss; /** * stack, self explanatory. */ unsigned long stack; } PROCESS_SECTION_ADDRS; /** * Holds virtual memory segments of a core file as well as their length. * * @short Core file virtual-memory segments. */ typedef struct _core_memory_sections { /** * The virtual memory addresses of the segment */ unsigned long vma; /** * The length of the segment */ unsigned long length; /** * The mmap()'d address of the segment. */ unsigned long rma; } CORE_MEMORY_SECTIONS; /** * Extended data structure holding information about a core file. * * @short Core file information. */ typedef struct _mem_ctx_core_data { /** * The file descriptor associated with the core file. */ int fd; /** * The elf header of the core file. */ Elf32_Ehdr elfHeader; /** * The array of program headers. */ Elf32_Phdr *programHeaders; /** * The array of virtual memory segments. */ CORE_MEMORY_SECTIONS *sections; /** * The number of segments. */ unsigned long numSections; } MEM_CTX_CORE_DATA; struct _mem_ctx; /** * The medium-independant function table used internally by memgrep. * * @short Medium-independant function table. */ typedef struct _memgrep_functions { /** * Open the medium and prepare it for operation. * * @param ctx [in] The memgrep context. * @return On success, 1 is returned, otherwise 0 is returned. */ unsigned long (*open)(struct _mem_ctx *ctx); /** * Closes the medium, releasing any resources used. * * @param ctx [in] The memgrep context. * @return On success, 1 is returned, otherwise 0 is returned. */ unsigned long (*close)(struct _mem_ctx *ctx); /** * Get the sections (rodata, bss, data, stack) associated with a given medium. * * @param ctx [in] The memgrep context. * @return On success, 1 is returned, otherwise 0 is returned. */ unsigned long (*getSections)(struct _mem_ctx *ctx); /** * Gets a memory address for a specified number of bytes. * * @param ctx [in] The memgrep context. * @param addr [in] The address to start from. * @param length [in] The number of bytes to get. * @return On success, a buffer containing the data at the specified address is returned. Otherwise, NULL is returned. */ unsigned char *(*get)(struct _mem_ctx *ctx, unsigned long addr, unsigned long length); /** * Puts arbitrary data into memory at the specified address for a given length. * * @param ctx [in] The memgrep context. * @param addr [in] The address to start from. * @param buf [in] The buffer to write from. * @param bufLength [in] The number of bytes to write. * @return On success, 1 is returned, otherwise 0 is returned. */ unsigned long (*put)(struct _mem_ctx *ctx, unsigned long addr, unsigned char *buf, unsigned long bufLength); /** * Populate the addresses array from a given keyword. * * @param ctx [in] The memgrep context. * @param keyword [in] The keyword to replace (such as 'bss'). * @return If the keyword is valid, 1 is returned, otherwise 0 is returned. */ unsigned long (*populateKeyword)(struct _mem_ctx *ctx, const char *keyword); /** * List the segments of a given medium. * * @param ctx [in] The memgrep context. * @return On success, 1 is returned, otherwise 0 is returned. */ unsigned long (*listSegments)(struct _mem_ctx *ctx); /** * Enumerate the heap of the given medium. * * @param ctx [in] The memgrep context. * @param current [in] The current node in the list, or 0 if the first node. * @param addr [out] The adderss of the allocation unit at this point. * @param size [out] The size of the allocation unit at this point. * @return On success, 1 is returned, otherwise 0 is returned. */ unsigned long (*heapEnumerate)(struct _mem_ctx *ctx, unsigned long current, unsigned long *addr, unsigned long *size); } MEMGREP_FUNCTIONS; /** * The base for all rows in a result * * @short Result row base structure. */ typedef struct _memgrep_result_row { /** * The length in bytes of the structure. */ unsigned long length; /** * The type of structure. This can be one of the following: * * @li MEMGREP_RESULT_TYPE_SEARCH * The derived structure is 'MEMGREP_RESULT_ROW_SEARCH' * @li MEMGREP_RESULT_TYPE_REPLACE * The derived structure is 'MEMGREP_RESULT_ROW_REPLACE' * @li MEMGREP_RESULT_TYPE_DUMP * The derived structure is 'MEMGREP_RESULT_ROW_DUMP' */ unsigned long type; } MEMGREP_RESULT_ROW; /** * The result from a given operation, including any rows that were returned. * * @short The result of a given operation. */ typedef struct _memgrep_result { /** * The error code, 0 if no error. */ unsigned long error; /** * The number of rows returned by the query. */ unsigned long numRows; /** * The array of rows. */ MEMGREP_RESULT_ROW **rows; } MEMGREP_RESULT; /** * Used in association with MEMGREP_CMD_SEARCH. * * @short Row for search results. */ typedef struct _memgrep_result_row_search { /** * The base structure for all rows */ MEMGREP_RESULT_ROW base; /** * The address that a matching instance of the search criteria was found at */ unsigned long addr; } MEMGREP_RESULT_ROW_SEARCH; /** * Used in association with MEMGREP_CMD_HEAPENUMERATE * * @short Row for heap enumeration results. */ typedef struct _memgrep_result_row_heap { /** * The base structure for all rows */ MEMGREP_RESULT_ROW base; /** * The base address of the allocation in the heap */ unsigned long addr; /** * The size of the allocation */ unsigned long size; } MEMGREP_RESULT_ROW_HEAP; /** * Used in association MEMGREP_CMD_SEARCHREPLACE and MEMGREP_CMD_REPLACE * * @short Row for replace reuslts. */ typedef struct _memgrep_result_row_replace { /** * The base structure for all rows */ MEMGREP_RESULT_ROW base; /** * The address where an instance of memory was replaced at. */ unsigned long addr; } MEMGREP_RESULT_ROW_REPLACE; /** * Used in association with MEMGREP_CMD_DUMP * * @short Row for memory dump results. */ typedef struct _memgrep_result_row_dump { /** * The base structure for all rows */ MEMGREP_RESULT_ROW base; /** * The adderss that the dump occured at. */ unsigned long addr; /** * The memory at that address */ unsigned char *buf; /** * The number of bytes held in buf */ unsigned long bufLength; } MEMGREP_RESULT_ROW_DUMP; /** * The memgrep context. * * @short memgrep context */ typedef struct _mem_ctx { /** * Holds the flags for the conetxt. These can be a combination of the following: * * @li MEMGREP_FLAG_VERBOSE * Be verbose. This enables output for given commands. * @li MEMGREP_FLAG_PROMPT * Prompt before overwriting memory. * @li MEMGREP_FLAG_DUMPCLEAN * Dump the memory in human read-able format. This is only useful with verbose set. */ unsigned long flags; /** * The medium that will be operated upon. This can be: * * @li MEMORY_MEDIUM_PID * Operate on a process id. * @li MEMORY_MEDIUM_CORE * Operate on a core file. */ enum MemoryMedium medium; /** * The process id to operate on. */ int pid; /** * The core file to operate on. */ char *core; /** * Medium specific function table. */ MEMGREP_FUNCTIONS functions; /** * Section addresses associated with the medium. */ PROCESS_SECTION_ADDRS sections; /** * Array of addresses populated by MEMGREP_CMD_POPULATE */ unsigned long *addrs; /** * Number of elements in the 'addrs' array. */ unsigned long numAddrs; /** * The length used when searching, and dumping. */ unsigned long length; /** * Padding used when dumping memory. */ unsigned long padding; /** * Format for use when dumping */ enum MemoryDumpFormat dumpFormat; /** * Extended data related to core files */ MEM_CTX_CORE_DATA coreData; /** * MISC: * * procFd => Solaris fd for proc access */ int procCtlFd; int procAsFd; } MEM_CTX; /** * The method used to operate memgrep. * * @param ctx [in] The memgrep context. * @param cmd [in] The command to execute. See each command for a description of its parameters. * @param result [out] The result of a given action. This can be NULL. * @param param [in] An arbitrary parameter for a given command. * @param data [in] An arbitrary parameter for a given command. * @return Return values vary from one command to another. */ unsigned long memgrep(MEM_CTX *ctx, unsigned long cmd, MEMGREP_RESULT *result, unsigned long param, unsigned long data); /* * These functions should not be called directly. */ unsigned long memgrep_initialize(MEM_CTX *ctx, enum MemoryMedium medium, void *data); // 1 for success, 0 for failure unsigned long memgrep_deinitialize(MEM_CTX *ctx); // 1 for success, 0 for failure unsigned long memgrep_set(MEM_CTX *ctx, unsigned long param, unsigned long data); // 1 for success, 0 for failure unsigned long memgrep_get(MEM_CTX *ctx, unsigned long param); // the value associated w/ the param unsigned long memgrep_populate_string(MEM_CTX *ctx, const char *addresses); // number of addresses populated unsigned long memgrep_populate_array(MEM_CTX *ctx, unsigned long *array, unsigned long elements); // number of addresses populated unsigned long memgrep_search(MEM_CTX *ctx, MEMGREP_RESULT *result, const char *searchPhrase); // number of addresses found unsigned long memgrep_replace(MEM_CTX *ctx, MEMGREP_RESULT *result, const char *replacePhrase); // number of addresses replaced unsigned long memgrep_searchreplace(MEM_CTX *ctx, MEMGREP_RESULT *result, const char *searchPhrase, const char *replacePhrase); // number of addresses search/replaced unsigned long memgrep_dump(MEM_CTX *ctx, MEMGREP_RESULT *result); // 1 for success, 0 for failure unsigned long memgrep_listSegments(MEM_CTX *ctx); // 1 for success, 0 for failure unsigned long memgrep_destroy(MEM_CTX *ctx, MEMGREP_RESULT *result); // Destroy a resultant value, 1 for success 0 for failure unsigned long memgrep_heapenumerate(MEM_CTX *ctx, MEMGREP_RESULT *result, unsigned long minSize); // 1 for success, 0 for failure /** * @} */ #endif