C++ Detect If Function Has Been Hooked (32bit Machine) - c++

When people hook a function in general they modify the first few instructions of the function they want to hook with branch instructions to where they want to do some stuff then branch back to original function and restore it, the problem with that is that literally nothing is safe. Any value you are trying to hide can easily be found (these values can be found many other ways than just function hooking, but that's all i'm focusing on in this question)
Let's say you go through the effort of implementing a hash algorithm like MD5 into your C++ application (I haven't, this is just an example for the question), just for the sake of this example assume you have a MD5 function like this
void GENERATEMD5(const char *plain, char *out);
and you would call it like
char hashResult[33] = { 0 };//32 + 1 because of null terminator
GENERATEMD5(passwordInputBuffer, hashResult);
memset(passwordInputBuffer, 0, 32);//set password buf back to null
Anyone could easily hook this GERERATEMD5() function and simply print out the parameters as they are passed to the function. Example
void md5FuncHook(const char *plain, char *out)
{
md5Hook(plain, out);
console::print("Plain: %s - Hash: %s", plain, out);
}
I was thinking about it and there was only one way I could come up with detecting if a function is hooked (assuming they have hooked the function via modifying the function's first few instructions). And that would be to check the first few bytes of the function then confirm that they are what they are supposed to be.
Example, if we know the first few bytes of the function GERERATEMD5() are
int GERERATEMD5_Function_bytes_0 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_1 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_2 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_3 = 0x12341234;//just random bytes for the example
Then we could do something like this
void checkIfGENERATEMD5HasBeenHooked()
{
int GERERATEMD5_Function_bytes_0 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_1 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_2 = 0x12341234;//just random bytes for the example
int GERERATEMD5_Function_bytes_3 = 0x12341234;//just random bytes for the example
int readGENERATEMD5FunctionBytes0, readGENERATEMD5FunctionBytes1, readGENERATEMD5FunctionBytes2, readGENERATEMD5FunctionBytes3;
memcpy(&readGENERATEMD5FunctionBytes0, (char *)(&GENERATEMD5 + 0x00), 0x04);
memcpy(&readGENERATEMD5FunctionBytes1, (char *)(&GENERATEMD5 + 0x04), 0x04);
memcpy(&readGENERATEMD5FunctionBytes2, (char *)(&GENERATEMD5 + 0x08), 0x04);
memcpy(&readGENERATEMD5FunctionBytes3, (char *)(&GENERATEMD5 + 0x0C), 0x04);
if(GERERATEMD5_Function_bytes_0 == readGENERATEMD5FunctionBytes0 && GENERATEMD5_Function_bytes_1 == readGENERATEMD5FunctionBytes1 && GENERATEMD5_Function_bytes_2 == readGENERATEMD5FunctionBytes2 && GENERATEMD5_Function_bytes_3 == readGENERATEMD5FunctionBytes3)
{
//our GENERATEMD5() function is clean
}
else
{
//hook detected or some other form of function modification detected
}
}
But with everything I have tried this just never seems to work. The issue I'm assuming is coming from where I read the bytes of the function itself, like the calls to memcpy aren't actually reading the bytes located at &GENERATEMD5 + OFFSET. Am I just doing something wrong? Or is there a better/different way of doing what I'm trying to accomplish? (btw, yes I know there are many other hooking methods attackers may use when hooking your functions other than what I've described above and just in general many other ways to get a hold of your sensitive information from your executable, but this question has nothing to do with any of that so please just focus on the question rather than just saying something along the lines of "doing this is pointless" or "there are easy ways to bypass this", etc...)

I have done this. The problem is the loader will modify the code during relocation so you cannot rely on the operand fields being the same value every time. In my case I used a disassembly library and did a hash on only the opcode bytes. I used BASTARD to do disassembly at runtime but that project is long dead. I think there are better options now.
In principle you could probably write the target function in such a way that relocation fixups wouldn't happen, but that's going to be more trouble than it is worth.

Related

C++ getting length of char array using a second function

I'm trying to get the length of a character array in a second function. I've looked at a few questions on here (1 2) but they don't answer my particular question (although I'm sure something does, I just can't find it). My code is below, but I get the error "invalid conversion from 'char' to 'const char*'". I don't know how to convert my array to what is needed.
#include <cstring>
#include <iostream>
int ValidInput(char, char);
int main() {
char user_input; // user input character
char character_array[26];
int valid_guess;
valid_guess = ValidGuess(user_input, character_array);
// another function to do stuff with valid_guess output
return 0;
}
int ValidGuess (char user_guess, char previous_guesses) {
for (int index = 0; index < strlen(previous_guesses); index++) {
if (user_guess == previous_guesses[index]) {
return 0; // invalid guess
}
}
return 1; // valid guess, reaches this if for loop is complete
}
Based on what I've done so far, I feel like I'm going to have a problem with previous_guesses[index] as well.
char user_input;
defines a single character
char character_array[26];
defines an array of 26 characters.
valid_guess = ValidGuess(user_input, character_array);
calls the function
int ValidGuess (char user_guess, char previous_guesses)
where char user_guess accepts a single character, lining up correctly with the user_input argument, and char previous_guesses accepts a single character, not the 26 characters of character_array. previous_guesses needs a different type to accommodate character_array. This be the cause of the reported error.
Where this gets tricky is character_array will decay to a pointer, so
int ValidGuess (char user_guess, char previous_guesses)
could be changed to
int ValidGuess (char user_guess, char * previous_guesses)
or
int ValidGuess (char user_guess, char previous_guesses[])
both ultimately mean the same thing.
Now for where things get REALLY tricky. When an array decays to a pointer it loses how big it is. The asker has gotten around this problem, kudos, with strlen which computes the length, but this needs a bit of extra help. strlen zips through an array, counting until it finds a null terminator, and there are no signs of character_array being null terminated. This is bad. Without knowing where to stop strlen will probably keep going1. A quick solution to this is go back up to the definition of character_array and change it to
char character_array[26] = {};
to force all of the slots in the array to 0, which just happens to be the null character.
That gets the program back on its feet, but it could be better. Every call to strlen may recount (compilers are smart and could compute once per loop and store the value if it can prove the contents won't change) the characters in the string, but this is still at least one scan through every entry in character_array to see if it's null when what you really want to do is scan for user_input. Basically the program looks at every item in the array twice.
Instead, look for both the null terminator and user_input in the same loop.
int index = 0;
while (previous_guesses[index] != '\0' ) {
if (user_guess == previous_guesses[index]) {
return 0; // prefer returning false here. The intent is clearer
}
index++;
}
You can also wow your friends by using pointers and eliminating the need for the index variable.
while (*previous_guesses != '\0' ) {
if (user_guess == *previous_guesses) {
return false;
}
previous_guesses++;
}
The compiler knows and uses this trick too, so use the one that's easier for you to understand.
For 26 entries it probably doesn't matter, but if you really want to get fancy, or have a lot more than 26 possibilities, use a std::set or a std::unordered_set. They allow only one of an item and have much faster look-up than scanning a list one by one, so long as the list is large enough to get over the added complexity of a set and take advantage of its smarter logic. ValidGuess is replaced with something like
if (used.find(user_input) != used.end())
Side note: Don't forget to make the user read a value into user_input before the program uses it. I've also left out how to store the previous inputs because the question does as well.
1 I say probably because the Standard doesn't say what to do. This is called Undefined Behaviour. C++ is littered with the stuff. Undefined Behaviour can do anything -- work, not work, visibly not work, look like it works until it doesn't, melt your computer, anything -- but what it usually does is the easiest and fastest thing. In this case that's just keep going until the program crashes or finds a null.

How much consistency is there with WinAPI functions that have string out parameters?

I have recently begun to write in C on Windows and have been trying to be careful with the different ways that string buffers are handled. For instance, GetWindowText() takes an int nMaxCount of the maximum number of characters, including null. GetModuleFileName() takes a DWORD nSize of the size of the buffer, in TCHARs (I assume this also includes null). Even though these are worded differently and one takes a DWORD while the other takes an int (why the difference in types?), the behavior is identical, correct?
Both return the length of the string that is copied, not including the null, so I should be able to call either of them repeatedly, doubling the buffer size until the returned length is less than the buffer size passed in, like this:
DWORD buf_size = 1024;
DWORD return_val;
wchar_t *full_path = malloc(buf_size * sizeof(wchar_t));
// double the buffer until it's big enough
while ((return_val = GetModuleFileNameW(NULL, full_path, buf_size)) == buf_size) {
buf_size *= 2;
full_path = realloc(full_path, buf_size * sizeof(wchar_t));
}
if (!return_val) {
fprintf(stderr, "Error in GetModuleFileNameW()\n");
return NULL;
}
Do all of the Windows API functions with string [out] parameters work in the same way? Are there any individual functions or groups of functions that behave differently? (for instance, functions that take the size of the buffer in bytes instead of characters, or that take a maximum string length not including the null character or that return a different value than these two)
Actually, I just noticed that the return value of these two is not entirely consistent: GetModuleFileName() returns 0 when it errors; GetWindowText() will return 0 whenever there is an empty string for the window text, which I think I saw quite frequently when I was enumerating windows...
One reason I want to understand it in detail is because in some cases (GetModuleFileName() on WinXP, for instance), an off-by-one error in my code will result in a string that is not null-terminated.
By and large the majority of the Win32 API functions that return strings do so in a consistent manner. GetWindowText is a good choice for a canonical such function. However, there are exceptions, and I don't think anyone has ever compiled a comprehensive list.
The bottom line here is that you need to consult the documentation carefully every single time you write code to call a Win32 API function. Not only regarding the treatment of string output values, but all parameters. And all return values. And error handling. There is variation in style across the API, and even variation within related groups of functions.

C++ Can programs run out of stack memory even when plenty of memory is available?

I'm writing a parser for a large file and one of my functions responsible for reading from the input file has a char buffer called peek. Basically, as main repeatedly calls this function, peek is eventually getting over-written with some odd values. Here's the function that's being called by main. bufferAsInt:
void bufferAsInt(ifstream &inf, int &i)
{
char peek[3];
inf.read(peek, 3);
i = atoi(peek);
//I'm not using the >> operator to read an int because the int is just
//3 chars long in the input file and two consecutive integer values can
//be written like this: 123456 for 123 and 456.
}
I found that as I wrote these values to an output file, when reading an int value that was only two digits long, the third digit (or some other number) would be left over in the char buffer peek and the value would be written incorrectly to the output file (this only happened after reading a very very large amount of data from the input file.) So after tens of thousands of iterations, when reading a number like 15, the value that would get written to my output file might have been something like 156.
To solve the problem I changed my implementation of bufferAsInt to this:
void bufferAsInt(ifstream &inf, int &i)
{
char *peek = new char[3];
inf.read(peek, 3);
i = atoi(peek);
delete [] peek;
}
(Of course I was guessing at what the issue was). What I'd like to know is if the fact that my problem was solved is some sort of weird consequence of declaring this char buffer on the heap or if the issue actually was that my program was running out of stack memory.
I have 6GB of RAM in my computer and at the time of running, no other programs would have been using enough memory to cause this issue to the best of my knowledge.
You're off by one.
atoi expects a null-terminated string. So a three-digit number needs a char[4] to be properly stored. Also, read doesn't put a null on the end.
Try this:
void bufferAsInt(ifstream &inf, int &i)
{
char peek[4];
inf.read(peek, 3);
peek[3] = 0;
i = atoi(peek);
}
atoi() expects a C 'NUL terminated string' as input, that is, ASCII characters followed by an ASCII zero byte. That's the only way the function knows where to stop converting.
In your first code listing, you read three bytes into a three byte buffer, but you have no control over the byte that follows in memory. I believe that's undefined behavior in C++, so literally anything can happen. Typically, though, if the following byte happens to be a zero or a non-digit, the string will convert properly; if it happens to be a digit, you get a different number when you were expecting.
The proper fix is to use your first example, but:
char peek[4]; // 4 char buffer instead of 3
inf.read(peek, 3);
peek[3] = '\0'; // ensure the 4th char is zero
i = atoi(peek);
Most likely the only thing that changed was that the new, with your compiler and options, zeroes the array.
To guarantee that you could write
char *peek = new char[3]();
But the dynamic allocation serves no purpose, so instead do it like this:
char peek[3] = {};
Note: if the file contains 3 digits, then you should instead use four digits array, in order to have room for terminating zero.

C++ WriteProcessMemory Without Variables

I want to do WriteProcessMemory In C++ using Dword or Int, without storing it in a Variable i found one way to do this but i can only do it with bytes. does anyone know how to do this??
this one works using bytes.
WriteProcessMemory(hProcess, (void*)(BasePointer + 0x728),"\x90\x90", 4, NULL);
Thanks for the help everyone i made a function and its working really good
void WriteMemory(DWORD Address,DWORD NewValue, int NewValueSize)
{
WriteProcessMemory(hProcess, (void*)Address, (void*)&NewValue, NewValueSize, NULL);
}
int main()
{
srand(time(0));
GetProcess();
WriteMemory((BasePointer + 0x6F8),2+rand()%65500,2);
CloseHandle(hProcess);
return 0;
}
The reason your code "works" with bytes is that you're using a string literal. A string literal is an array of char, and an array of char automatically converts to a pointer to the first element if the context calls for it, as it does when you try to pass one as the third argument of WriteProcessMemory.
You can write any value you want as a string literal, including a four-byte DWord, as long as you're willing to express it one byte at a time. For example, "\x70\x71\x72\x73". On Windows, that's equivalent to a pointer to the DWord value 0x73727170. You probably won't want to do that, though; expressing numbers like that is tedious.
C++ doesn't offer any facility for having literal arrays of non-char type. There's just not much demand for it. Demand for literal char arrays is high because everyone deals with text, so we want easy ways of expressing it in our code. Although everyone also works with numbers, we rarely have need to express blobs of numerical data in our code, especially not mid-expression.
You haven't given a practical problem to be solved by your question. You're just asking whether something is possible to do. I'm sorry to be the bearer of bad news, but the answer is that what you're asking for cannot be done in C++. You'll just have to do like everyone else and declare a variable. Variables are cheap; feel free to use them whenever the need arises. Nonetheless, you've been shown ways to keep your code concise by using subroutines. Macros can also help shorten your code, if that's your goal.
Please also note that the string literal in your code is an array of three characters — the two between quotation marks, plus the nul character the compiler automatically includes at the end of all string literals. You're telling the function that you've provided a pointer to a block of four bytes, which is false. the fourth byte that the function writes into the other process will have an unspecified value.
Put the data into an array, and have a small loop get each item from the array, write it to the target process, then move to the next:
struct data {
DWORD offset;
DWORD length;
char data[256];
};
data items[] = {
{0x728, 4, "\x90\x90"},
// ...
};
for (int i=0; i<elements(items); i++)
WriteProcessMemory(hProcess, (void *)(BasePointer + items[i].offset), items[i].data, items[i].length, NULL);

boost memorybuffer and char array

I'm currently unpacking one of blizzard's .mpq file for reading.
For accessing the unpacked char buffer, I'm using a boost::interprocess::stream::memorybuffer.
Because .mpq files have a chunked structure always beginning with a version header (usually 12 bytes, see http://wiki.devklog.net/index.php?title=The_MoPaQ_Archive_Format#2.2_Archive_Header), the char* array representation seems to truncate at the first \0, even if the filesize (something about 1.6mb) remains constant and (probably) always allocated.
The result is a streambuffer with an effective length of 4 ('REVM' and byte nr.5 is \0). When attempting to read further, an exception is thrown. Here an example:
// (somewhere in the code)
{
MPQFile curAdt(FilePath);
size_t size = curAdt.getSize(); // roughly 1.6 mb
bufferstream memorybuf((char*)curAdt.getBuffer(), curAdt.getSize());
// bufferstream.m_buf.m_buffer is now 'REVM\0' (Debugger says so),
// but internal length field still at 1.6 mb
}
//////////////////////////////////////////////////////////////////////////////
// wrapper around a file oof the mpq_archive of libmpq
MPQFile::MPQFile(const char* filename) // I apologize my naming inconsistent convention :P
{
for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
{
// gOpenArchives points to MPQArchive, wrapper around the mpq_archive, has mpq_archive * mpq_a as member
mpq_archive &mpq_a = (*i)->mpq_a;
// if file exists in that archive, tested via hash table in file, not important here, scroll down if you want
mpq_hash hash = (*i)->GetHashEntry(filename);
uint32 blockindex = hash.blockindex;
if ((blockindex == 0xFFFFFFFF) || (blockindex == 0)) {
continue; //file not found
}
uint32 fileno = blockindex;
// Found!
size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);
// HACK: in patch.mpq some files don't want to open and give 1 for filesize
if (size<=1) {
eof = true;
buffer = 0;
return;
}
buffer = new char[size]; // note: size is 1.6 mb at this time
// Now here comes the tricky part... if I step over the libmpq_file_getdata
// function, I'll get my truncated char array, which I absolutely don't want^^
libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);
return;
}
}
Maybe someone could help me. I'm really new to STL and boost programming and also inexperienced in C++ programming anyways :P Hope to get a convenient answer (plz not suggest to rewrite libmpq and the underlying zlib architecture^^).
The MPQFile class and the underlying uncompress methods are acutally taken from a working project, so the mistake is either somewhere in the use of the buffer with the streambuffer class or something internal with char array arithmetic I haven't a clue of.
By the way, what is the difference between using signed/unsigned chars as data buffers? Has it anything to do with my problem (you might see, that in the code randomly char* unsigned char* is taken as function arguments)
If you need more infos, feel free to ask :)
How are you determining that your char* array is being 'truncated' as you call it? If you're printing it or viewing it in a debugger it will look truncated because it will be treated like a string, which is terminated by \0. The data in 'buffer' however (assuming libmpq_file_getdata() does what it's supposed to do) will contain the whole file or data chunk or whatever.
Sorry, messed up a bit with these terms (not memorybuffer actually, streambuffer is meant as in the code)
Yeah you where right... I had a mistake in my exception handling. Right after that first bit of code comes this:
// check if the file has been open
//if (!mpf.is_open())
pair<char*, size_t> temp = memorybuf.buffer();
if(temp.first)
throw AdtException(ADT_PARSEERR_EFILE);//Can't open the File
notice the missing ! before temp.first . I was surprized by the exception thrown, looked at the streambuffer .. internal buffer at was confused of its length (C# background :P).
Sorry for that, it's working as expected now.