I wrote a dll application that is hooked into a process. It works but it ONLY shows the FIRST letter.
I wanted to get the whole string. The string could vary from 2 letters to 32 letters.
//READING MEMORY
HANDLE ExeBaseAddress = GetModuleHandleA(0);
char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%c \n", uNameAddr);
I also wanted to understand the parts:
*(char*)((char*) //<-- what this is for.
And if it is possible to use this if using multilevel pointers:
char multipoint = *(char*)((char*)ExeBaseAddress + 0x34F01C + 0x123 + 0x321 + 0x20);
UPDATE
I guess something is wrong here:
if(uNameAddr == "omnicient")
cout << "YOU ARE OMNI" << endl;
I used the username name omnicient but it did not cout YOU ARE OMNI. I guess my compare is wrong?
%c displays chars (single characters), %s displays NULL-terminated char*s (strings):
HANDLE ExeBaseAddress = GetModuleHandleA(0);
char *uNameAddr = (char*) ExeBaseAddress + 0x34F01C;
printf("%s \n", uNameAddr);
Notice that I also tidied up the pointer casting, but the important thing is I got rid of the final dereference (* at the front) and assigned it to a char* (pointer) instead of a char.
If your string isn't NULL-terminated (unlikely), you will need to use %.*s and pass the length of your string too.
As for the second part of your question:
*(char*)((char*) ExeBaseAddress + 0x34F01C)
let's break it down. Inside the brackets (therefore the first thing to be evaluated) is this:
(char *) ExeBaseAddress + 0x34F01C
Well that's a C cast (casting the HANDLE to a char*) followed by an addition. In other words, it says "Treat this thing as if it is a pointer to some memory, then look ahead by 0x34F01C bytes of memory" (char is always 1 byte). It is now a pointer to a new position in memory.
Then we get out of the brackets and cast to char* again... needlessly. It could have been:
*((char*) ExeBaseAddress + 0x34F01C)
and finally we dereference (the * at the front), which says "Now tell me what the bit of memory you're pointing to is". But in this case you don't want that, because you want the whole string, not just the first letter (inside printf, it loops along the memory you send it printing each character until it finds a 0, aka \0 aka NULL).
char uNameAddr is a character, you need a list of chars (or char*)
try this instead:
char* name= (char*)((char*)ExeBaseAddress + 0x34F01C);
printf("%s \n", name);
What does *(char*)((char*) mean?
(char*)ExeBaseAddress treat ExeBaseAddress as a pointer to some data of type char
((char*)ExeBaseAddress + 0x34F01C) means add 0x34F01C to the above pointer to offset it by 0x34F01C chars
(char*)((char*)ExeBaseAddress + 0x34F01C) means treat this new address as pointer to some chars
*(char*)((char*)ExeBaseAddress + 0x34F01C) take the contents of the first char at that location
char uNameAddr = *(char*)((char*)ExeBaseAddress + 0x34F01C); means put that character into the char sized variable called uNameAddr.
So basically you had a pointer, you offset it, and then took the first character and printed it.
In the example I gave note how I don't take the firat character, and I put it a pointer variable.
Then I used %s in the printf to make it print out all the chars potnted to by name.
Related
Why does this code produce runtime issues:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
but this doesn't?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
strcat will look for the null-terminator, interpret that as the end of the string, and append the new text there, overwriting the null-terminator in the process, and writing a new null-terminator at the end of the concatenation.
char stuff[100]; // 'stuff' is uninitialized
Where is the null terminator? stuff is uninitialized, so it might start with NUL, or it might not have NUL anywhere within it.
In C++, you can do this:
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
Now you can do strcat, because the first character of 'stuff' is the null-terminator, so it will append to the right place.
In C, you still need to initialize 'stuff', which can be done a couple of ways:
char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
// so 'stuff' is effectively ""
strcpy(stuff, "hi "); // this initializes 'stuff' if it's not already.
In the first case, stuff contains garbage. strcat requires both the destination and the source to contain proper null-terminated strings.
strcat(stuff, "hi ");
will scan stuff for a terminating '\0' character, where it will start copying "hi ". If it doesn't find it, it will run off the end of the array, and arbitrarily bad things can happen (i.e., the behavior is undefined).
One way to avoid the problem is like this:
char stuff[100];
stuff[0] = '\0'; /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");
Or you can initialize stuff to an empty string:
char stuff[100] = "";
which will fill all 100 bytes of stuff with zeros (the increased clarity is probably worth any minor performance issue).
Because stuff is uninitialized before the call to strcpy. After the declaration stuff isn't an empty string, it is uninitialized data.
strcat appends data to the end of a string - that is it finds the null terminator in the string and adds characters after that. An uninitialized string isn't gauranteed to have a null terminator so strcat is likely to crash.
If there were to intialize stuff as below you could perform the strcat's:
char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");
Strcat append a string to existing string. If the string array is empty, it is not going go find end of string ('\0') and it will cause run time error.
According to Linux man page, simple strcat is implemented this way:
char*
strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
As you can see in this implementation, strlen(dest) will not return correct string length unless dest is initialized to correct c string values. You may get lucky to have an array with the first value of zero at char stuff[100]; , but you should not rely on it.
Also, I would advise against using strcpy or strcat as they can lead to some unintended problems.
Use strncpy and strncat, as they help prevent buffer overflows.
I'm trying to understand why a segmentation fault (SIGSEGV) occurs during the execution of this piece of code. This error occurs when testing the condition specified in the while instruction, but it does not occur at the first iteration, but at the second iteration.
LPTSTR arrayStr[STR_COUNT];
LPTSTR inputStr;
LPTSTR str;
// calls a function from external library
// in order to set the inputStr string
set_input_str(param1, (char*)&inputStr, param3);
str = inputStr;
while( *str != '\0' )
{
if( debug )
printf("String[%d]: %s\n", i, (char*)str);
arrayStr[i] = str;
str = str + strlen((char*)str) + 1;
i++;
}
After reading this answer, I have done some research on the internet and found this article, so I tried to modify the above code, using this piece of code read in this article (see below). However, this change did not solve the problem.
for (LPTSTR pszz = pszzStart; *pszz; pszz += lstrlen(pszz) + 1) {
... do something with pszz ...
}
As assumed in this answer, it seems that the code expects double null terminated arrays of string. Therefore, I wonder how I could check the contents of the inputStr string, in order to check if it actually contains only one null terminator char.
NOTE: the number of characters in the string printed from printf instruction is twice the value returned by the lstrlen(str) function call at the first iteration.
OK, now that you've included the rest of the code it is clear that it is indeed meant to parse a set of consecutive strings. The problem is that you're mixing narrow and wide string types. All you need to do to fix it is change the variable definitions (and remove the casts):
char *arrayStr[STR_COUNT];
char *inputStr;
char *str;
// calls a function from external library
// in order to set the inputStr string
set_input_str(param1, &inputStr, param3);
str = inputStr;
while( *str != '\0' )
{
if( debug )
printf("String[%d]: %s\n", i, str);
arrayStr[i] = str;
str = str + strlen(str) + 1;
i++;
}
Specifically, the issue was occurring on this line:
while( *str != '\0' )
since you hadn't cast str to char * the comparison was looking for a wide nul rather than a narrow nul.
str = str + strlen(str) + 1;
You go out of bounds, change to
str = str + 1;
or simply:
str++;
Of course you are inconsistently using TSTR and strlen, the latter assuming TCHAR = char
In any case, strlen returns the length of the string, which is the number of characters it contains not including the nul character.
Your arithmetic is out by one but you know you have to add one to the length of the string when you allocate the buffer.
Here however you are starting at position 0 and adding the length which means you are at position len which is the length of the string. Now the string runs from offset 0 to offset len - 1 and offset len holds the null character. Offset len + 1 is out of bounds.
Sometimes you might get away with reading it, if there is extra padding, but it is undefined behaviour and here you got a segfault.
This looks to me like code that expects double null terminated arrays of strings. I suspect that you are passing a single null terminated string.
So you are using something like this:
const char* inputStr = "blah";
but the code expects two null terminators. Such as:
const char* inputStr = "blah\0";
or perhaps an input value with multiple strings:
const char* inputStr = "foo\0bar\0";
Note that these final two strings are indeed double null terminated. Although only one null terminator is written explicitly at the end of the string, the compiler adds another one implicitly.
Your question edit throws a new spanner in the works? The cast in
strlen((char*)str)
is massively dubious. If you need to cast then the cast must be wrong. One wonders what LPTSTR expands to for you. Presumably it expands to wchar_t* since you added that cast to make the code compile. And if so, then the cast does no good. You are lying to the compiler (str is not char*) and lying to the compiler never ends well.
The reason for the segmentation fault is already given by Alter's answer. However, I'd like to add that the usual style of parsing a C-style string is more elegant and less verbose
while (char ch = *str++)
{
// other instructions
// ...
}
The scope of ch is only within in the body of the loop.
Aside: Either tag the question as C or C++ but not both, they're different languages.
I have a small school assignment. My output is not correct. Can you see if I'm doing anything wrong?
//1. Create a char pointer named cp
char *cp;
//2. Dynamically allocate a char and store its address in cp
char dynamicChar = 'A';
cp = &dynamicChar;
//3. Write the character 'x' into the char
*cp = 'x';
//4. Print out the value of the char using cout
cout << cp << endl;
The print out statement prints A## instead of just A. I'm not sure what I'm doing wrong.
Try
cout << *cp << endl;
You want to print the character, not the pointer to it. When you hand it the pointer, cout thinks you're telling it to print out a character array starting there.
Sadly, from its origins of the C programming language, char * (i.e. pointers to characters) are not treated as just a pointer to a type like int * (pointer to int) or float * (pointer to a float), but many library functions treat these as NUL-character terminated strings. By "string" we mean text.
Therefore, there are lots of library functions that treat char* as special case and treats them as a "nul-terminated string", meaning it's gonna treat that pointer as an ARRAY of (i.e. multiple contiguous) charactes, until it reaches a NUL character (i.e. numeric value 0, not the character '0' which has a numeric byte value of 48 or 0x30).
So, if in your code you have
char *sz = "123";
this will allocate 4 characters, the 3 you see plus the NUL character
Addr:0x00050014 0x31 // ASCII char '1'
Addr:0x00050015 0x32 // ASCII char '2'
Addr:0x00050016 0x33 // ASCII char '3'
Addr:0x00050017 0x00 // ASCII char nul
sz (a pointer to a character, representing an address) will have the value 0x00050014 (note that the starting address value is determined by your computer via multiple steps via the compiler, then the linker, then the loader, then possibly the progrma itself).
When you do
cout << sz << endl;
the program will interpret the pointer to a character as a pointer to a nul-terminated buffer of characters and dump the character string
123
to the output stream cout. It looks at the value at address 0x00050014 and sees if its NUL (i.e. 0), if not, it dumps out the character, then looks at the next address. If 0x00050015 is not a NUL, it dumps IT out. Then the value at 0x00050016, sees its not a NUL, dumps it out, then it gets to 0x00050017 and sees that it IS NUL, and does NOT dump it out, and stops looking at addresses and returns to YOUR code just after where you did the output of sz, specifically in this code it will return to the point where it will dump the endl (end of line) to cout;
You will eventually learn better ways to represent text than the old C-style char* mechanism, but for now, you just need to understand the legacy behavior that exists.
C++ (or, more specificaly, ostream in this case), will automatically treat a char* as a (C style) string. You need to explicitly cast it to the type you want, such as:
cout << (void*)cp << endl;
if you want the pointer value, or
cout << *cp << endl;
if you want the character itself (as your question seems to indicate).
I am using C Style strings for a project, and I am confusing myself a bit. I am checking strings to see what they are prepended with (zone_, player_, etc) then getting the rest of the string after that.
else if(strncmp(info, "zone_", 5) == 0)
{
int len = strlen(info);
char *zoneName = new char[len];
strncpy(zoneName, &info[5], len-5);
Msg("Zone Selected: %s\n", zoneName);
delete zoneName;
}
When I print out the zoneName variable though, it is correct except it is followed by a bunch of gibberish. What am I doing wrong? (I realize that the gibberish is the rest of the char array being empty, but I don't know a better way to do this)
See strncpy description :
No null-character is implicitly
appended to the end of destination, so
destination will only be
null-terminated if the length of the C
string in source is less than num.
You have to remember that C-style strings are terminated with a NUL character. You've allocated enough space in zoneName, but you only need len-5 plus one:
char *zoneName = new char[len - 5 + 1];
Then, you can actually use strcpy() to copy the tail of the string:
strcpy(zoneName, &info[5]);
You don't need to specify the length because the source string is NUL terminated.
C strings are zero terminated - so they occupy len bytes (chars to be precise) plus one more with value zero known as the 'zero terminator'. You need to allocate one more character, and either copy one more from the source (since it should be zero terminated) or just set the last char of the destination to 0.
int len = strlen(info);
char *zoneName = new char[len - 5 + 1];
strncpy(zoneName, &info[5], len - 5 + 1);
C-style strings has to be finished with a byte with zero value. You should modify your code like this:
char *zoneName = new char[len-5+1];
strncpy(zoneName, &info[5], len-5);
/* correct string ending */
zoneName[len]=0;
/* Now, it's safe to print */
Msg("Zone Selected: %s\n", zoneName);
NoobQuestion:
I heard that filling a char array can be terminated early with the null char. How is this done?
I've searched every single google result out there but still have come up empty handed.
Do you mean something like this:
char test[11] = "helloworld";
std::cout << test << std::endl;
test[2] = 0;
std::cout << test;
This outputs
helloworld
he
?
That's a convention called "null-terminated string". If you have a block of memory which you treat as a char buffer and there's a null character within that buffer then the null-terminated string is whatever is contained starting with the beginning of the buffer and up to and including the null character.
const int bufferLength = 256;
char buffer[bufferLength] = "somestring"; //10 character plus a null character put by the compiler - total 11 characters
here the compiler will place a null character after the "somestring" (it does so even if you don't ask to). So even though the buffer is of length 256 all the functions that work with null-terminated strings (like strlen()) will not read beyond the null character at position 10.
That is the "early termination" - whatever data is in the buffer beyond the null character it is ignored by any code designed to work with null-terminated strings. The last part is important - code could easily ignore the null character and then no "termination" would happen on null character.