Added hexsearch (only as a template to base further work on)
parent
b8600169ef
commit
1e00076df7
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Author: Silas Dunsmore aka 0x517A5D vim:ts=4:sw=4
|
||||
*
|
||||
* Released under the MIT X11 license; feel free to use some or all of this
|
||||
* code, as long as you include the copyright and license statement (below)
|
||||
* in all copies of the source code. In fact, I truly encourage reuse.
|
||||
*
|
||||
* If you do use large portions of this code, I suggest but do not require
|
||||
* that you keep this code in a seperate file (such as this hexsearch.h file)
|
||||
* so that it is clear that the terms of the license do not also apply to
|
||||
* your code.
|
||||
*
|
||||
* Should you make fundamental changes, or bugfixes, to this code, I would
|
||||
* appreciate it if you would give me a copy of your changes.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2007-2008 Silas Dunsmore
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* See also: http://www.opensource.org/licenses/mit-license.php
|
||||
* and http://en.wikipedia.org/wiki/MIT_License
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HEXSEARCH_H
|
||||
#define HEXSEARCH_H
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
extern DWORD df_memory_base, df_memory_start, df_memory_end;
|
||||
extern HANDLE df_h_process, df_h_thread;
|
||||
extern DWORD df_pid, df_main_win_tid;
|
||||
|
||||
extern DWORD here[16];
|
||||
extern DWORD target[16];
|
||||
|
||||
// ============================================================================
|
||||
// export these in case you need to work with them directly.
|
||||
//extern HANDLE df_h_process, df_h_thread;
|
||||
//extern DWORD df_pid, df_main_win_tid;
|
||||
extern char *errormessage;
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// send info to KERNEL32:OutputDebugString(), useful for non-console programs.
|
||||
// (you can watch this with SysInternals' DebugView.)
|
||||
// http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx
|
||||
void d_printf(const char *format, ...);
|
||||
// it turned out that dprintf() is semi-standard to printf to a file descriptor.
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// encapsulate the housekeeping.
|
||||
BOOL open_dwarf_fortress(void);
|
||||
void close_dwarf_fortress(void); // is not (normally) necessary because
|
||||
// it is done at exit time.
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// memory reads and writes (peeks and pokes, in old BASIC terminology)
|
||||
BOOL isvalidaddress(DWORD ea);
|
||||
BOOL peekarb(DWORD ea, OUT void *data, DWORD len);
|
||||
BYTE peekb(DWORD ea);
|
||||
WORD peekw(DWORD ea);
|
||||
DWORD peekd(DWORD ea);
|
||||
char *peekstr(DWORD ea, OUT char *data, DWORD maxlen);
|
||||
char *peekustr(DWORD ea, OUT char *data, DWORD maxlen);
|
||||
BOOL pokearb(DWORD ea, const void *data, DWORD len);
|
||||
BOOL pokeb(DWORD ea, BYTE data);
|
||||
BOOL pokew(DWORD ea, WORD data);
|
||||
BOOL poked(DWORD ea, DWORD data);
|
||||
BOOL pokestr(DWORD ea, const BYTE *data);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// The name has changed because the API HAS CHANGED!
|
||||
//
|
||||
// Now instead of returning HERE, it always returns the start of the match.
|
||||
//
|
||||
// However, there is an array, here[], that is filled with the locations of
|
||||
// the HERE tokens.
|
||||
// (Starting at 1. here[0] is a copy of the start of the match.)
|
||||
//
|
||||
// The here[] array, starting at 1, is filled with the locations of the
|
||||
// HERE token.
|
||||
// here[0] is a copy of the start of the match.
|
||||
//
|
||||
// Also, the target[] array, starting at 1, is filled with the target
|
||||
// addresses of all CALL, JMP, JZ, JNZ, and JCC tokens.
|
||||
//
|
||||
// Finally, you no longer pass it a search length. Instead, each set of
|
||||
// search terms must end with an EOL.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Okay, I admit this one is complicated. Treat it as a black box.
|
||||
//
|
||||
// Search Dwarf Fortress's code and initialized data segments for a pattern.
|
||||
// (Does not search stack, heap, or thread-local memory.)
|
||||
//
|
||||
// Parameters: any number of search tokens, all unsigned ints.
|
||||
// The last token must be EOL.
|
||||
//
|
||||
// 0x00 - 0xFF: Match this byte.
|
||||
// EOL: End-of-list. The match succeeds when this token is reached.
|
||||
// ANYBYTE: Match any byte.
|
||||
// DWORD_: Followed by a dword. Exact-match the dword.
|
||||
// Equivalent to 4 match-this-byte tokens.
|
||||
// ANYDWORD: Match any dword. Equivalant to 4 ANYBYTEs.
|
||||
// HERE: Put the current address into the here[] array.
|
||||
// SKIP_UP_TO, nn: Allow up to nn bytes between the previous match
|
||||
// and the next match. The next token must be a match-this-byte
|
||||
// token. There is sweet, sweet backtracking.
|
||||
// EITHER: Accept either of the next two tokens as a match.
|
||||
// Both must be match-this-byte tokens.
|
||||
// RANGE_LO, nn: Set low byte for a range comparison. DEPRECATED.
|
||||
// RANGE_HI, nn: Set high byte for a range comparison, and do the
|
||||
// comparison. Should immediately follow a RANGE_LO. DEPRECATED.
|
||||
// BYTERANGE, nn, mm: followed by two bytes, the low and high limits
|
||||
// of the range. This is the new way to do ranges.
|
||||
// DWORDRANGE, nnnnnnnn, mmmmmmmm: works like BYTERANGE.
|
||||
// ADDRESS: Accept any legal address in the program's text.
|
||||
// DOES NOT accept pointers into heap space and such.
|
||||
// CALL: Match a near call instruction to a reasonable address.
|
||||
// JUMP: Match a short or near unconditional jump to a reasonable
|
||||
// address.
|
||||
// JZ: Match a short or long jz (jump if zero) instruction.
|
||||
// JNZ: Match a short or long jnz (jump if not zero) instruction.
|
||||
// JCC: Match any short or long conditional jump instruction.
|
||||
// More tokens can easily be added.
|
||||
//
|
||||
// Returns the offset in Dwarf Fortress of the first match of the pattern.
|
||||
// Also sets global variables here[] and target[].
|
||||
//
|
||||
// Note: starting a pattern with ANYBYTE, ANYDWORD, SKIP_UP_TO, or EOL
|
||||
// is explicitly illegal.
|
||||
//
|
||||
#define EOL 0x100
|
||||
#define ANYBYTE 0x101
|
||||
//#define FF_OR_00 0x102 // deprecated
|
||||
#define HERE 0x103
|
||||
#define EITHER 0x104
|
||||
#define SKIP_UP_TO 0x105
|
||||
#define RANGE_LO 0x106 // deprecated
|
||||
#define RANGE_HI 0x107 // deprecated
|
||||
#define DWORD_ 0x108
|
||||
#define ANYDWORD 0x109
|
||||
#define ADDRESS 0x10A
|
||||
#define BYTERANGE 0x10B
|
||||
#define DWORDRANGE 0x10C
|
||||
#define JZ 0x174
|
||||
#define JNZ 0x175
|
||||
#define JCC 0x170
|
||||
#define CALL 0x1E8
|
||||
#define JUMP 0x1E9
|
||||
|
||||
|
||||
DWORD hexsearch2(DWORD token1, ...);
|
||||
|
||||
// You can use this to limit the search to a particular part of memory.
|
||||
// Use 0 for start to search from the very start of Dwarf Fortress.
|
||||
// Use 0 for end to stop searching at the very end of Dwarf Fortress.
|
||||
void set_hexsearch2_limits(DWORD start, DWORD end);
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// patch2() and verify2() support a modified subset of hex_search2() tokens:
|
||||
// The names changed because the API HAS CHANGED!
|
||||
//
|
||||
// 0x00 - 0xFF: pokes the byte.
|
||||
// EOL: End-of-list. Allows you to specify count as 10000 or so
|
||||
// and terminate (with success) when this token is reached.
|
||||
// DWORD_: Followed by a DWORD. Pokes the DWORD.
|
||||
// CALL: given an _address_; pokes near call with the proper _delta_.
|
||||
// JUMP: given an _address_; pokes near jump with the proper _delta_.
|
||||
// JZ: given an _address_; assembles a near (not short) jz & delta.
|
||||
// JNZ: given an _address_; assembles a near jnz & delta.
|
||||
//
|
||||
// Particularly note that, unlike hex_search(), CALL, JUMP, JZ, and JNZ
|
||||
// are followed by a dword-sized target address.
|
||||
//
|
||||
// Note that patch2() does its own verify(), so you don't have to.
|
||||
|
||||
// TODO: is verify() useful enough to maintain?
|
||||
|
||||
// Make an offset in Dwarf Fortress have certain bytes.
|
||||
BOOL patch2(DWORD offset, ...);
|
||||
// Check that an offset in Dwarf Fortress has certain bytes.
|
||||
BOOL verify2(DWORD offset, ...);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // HEXSEARCH_H
|
Loading…
Reference in New Issue