Reading null characters into char array for hex conversion - c++

I am writing a program which reads input from a text file and converts it to hexadecimal for later processing.
ifstream fin("input.txt"); //open file with ifstream
if(fin.is_open()){ //check if file is open
for(int i = 0; i<length; i++){ //int length for how many characters I need
fin.get(buffer[i]); //write into char array buffer[256]
}
}
else{
cout<<"Can't open file";
exit(0);
}
fin.close();
So everything is fine, it opens up nicely and gets exactly as many characters as I need from there, later I use a function to turn that into a hexadecimal string:
std::string string_to_hex(const std::string input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
which also works fine, it gives me the correct hexadecimal value for the characters that I get.
Now here is the problem: my file contains null characters (hexadecimal "00" characters aka '\0') which I need to read into my program and do a proper conversion so every null character in my array after conversion should look like "00". Every time I
try to convert null characters in my array they change into spaces (hexadecimal "20"), which ruins my data for processing later. Changing "20" into "00" is also not an option since the file contains real spaces that also need to be properly processed.
This is my first time working with null characters and I am absolutely confused on how to properly process them. All I know is that null characters are used at the end of a string or an array so when I print them out the program would know when to stop.
I do not know how I should do it properly. I tried opening the file differently using fopen, I tried copying my input.txt into an array differently. Maybe it copies it properly but the hex conversion doesn't work. Maybe I shouldn't send it as a string for conversion. I don't know. I also noticed that when I tried to copy paste a sample from the file to another file, all the null characters have been replaced by spaces, maybe it has something to do with this?

Related

Load shellcode from file to char* comes strange characters in end of text

I have a char array[] and is like following:
// MessageBox
char xcode[] = "\x31\xc9\x64\x8b\x41\x30\x8b\x40\xc\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x1\xda\x8b\x52\x78\x1\xda\x8b\x72\x20\x1\xde\x31\xc9\x41\xad\x1\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78\x4\x72\x6f\x63\x41\x75\xeb\x81\x78\x8\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x1\xde\x66\x8b\xc\x4e\x49\x8b\x72\x1c\x1\xde\x8b\x14\x8e\x1\xda\x31\xc9\x53\x52\x51\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd2\x83\xc4\xc\x59\x50\x51\x66\xb9\x6c\x6c\x51\x68\x33\x32\x2e\x64\x68\x75\x73\x65\x72\x54\xff\xd0\x83\xc4\x10\x8b\x54\x24\x4\xb9\x6f\x78\x41\x0\x51\x68\x61\x67\x65\x42\x68\x4d\x65\x73\x73\x54\x50\xff\xd2\x83\xc4\x10\x68\x61\x62\x63\x64\x83\x6c\x24\x3\x64\x89\xe6\x31\xc9\x51\x56\x56\x51\xff\xd0";
Then i had inserted all this content of variable above into a file (file with UTF-8 format and content without the "") and tried load this way:
ifstream infile;
infile.open("shellcode.bin", std::ios::in | std::ios::binary);
infile.seekg(0, std::ios::end);
size_t file_size_in_byte = infile.tellg();
char* xcode = (char*)malloc(sizeof(char) * file_size_in_byte);
infile.seekg(0, std::ios::beg);
infile.read(xcode, file_size_in_byte);
printf("%s\n", xcode); // << prints content of xcode after load from file
if (infile.eof()) {
size_t bytes_really_read = infile.gcount();
}
else if (infile.fail()) {
}
infile.close();
I'm seeing some strange characters in end of text see:
What is need to fix it?
The issue is that the printf format specifier "%s" requires that the string is null-terminated. In your case, the null-terminator just happens to be after those characters you're seeing, but nothing guarantees where the null is unless you put one there.
Since you're using C++, one way to print the characters is to use the write() function available for streams:
#include <iostream>
//...
std::cout.write(xcode, file_size_in_bytes);
The overall point is this -- if you have a character array that is not null-terminated and contains data, you must either:
Put the null in the right place before using the array in functions that look for the null-terminator or
Use functions that state how many characters to process from the character array.
The answer above uses item 2.

C++ Send a file containing \0 via sockets without accidental closure

I serialize the file via the code beneath, and send it over winsocks, this works fine with textfiles, but when I tried to send a jpg, the string contains \0 as some of the character elements, so the sockets only send part of the string, thinking \0 is the end, i was considering replacing \0 with something else, but say i replace it with 'xx', then replace it back on the other end, what if the file had natural occurrences of 'xx' that get lost? Sure I could make a large, unlikely sequence, but that bloats the file.
Any help appreciated.
char* read_file(string path, int& len)
{
std::ifstream infile(path);
infile.seekg(0, infile.end);
size_t length = infile.tellg();
infile.seekg(0, infile.beg);
len = length;
char* buffer = new char[len]();
infile.read(buffer, length);
return buffer;
}
string load_to_buffer(string file)
{
char* img;
int ln;
img = read_file(file, ln);
string s = "";
for (int i = 1; i <= ln; i++){
char c = *(img + i);
s += c;
}
return s;
}
Probably somewhere in your code (that isn't seen in the code you have posted) you use strlen() or std::string::length() to send the data, and/or you use std::string::c_str() to get the buffer. This results in truncated data because these functions stop at \0.
std::string is not good to handle binary data. Use std::vector<char> instead, and remove the new[] stuff.

How to write NULL character '\0' to a text file

I have to write some data to a text file, and at the end of each output I have to append a NULL terminating character '\0'. Currently this is what I have come up so far. It works well for some inputs, however for some it sometimes write the whole text file with garbage value. I there a better way to do this?? In my program I have to write some data, store its location on file and use that for some operations. the next write operation starts at address = address + 500;
long int address = get_address();
void write_to_file()
{
fstream pFILE ("my file.txt");
char * buffer = new char [500];
cin.getline(buffer,500);
pFILE.seekp(address);
pFILE << buffer;
pFILE.seekp(address + strlen(buffer));
pFILE << '\0';
address += 500;
}
To write a '\0' to file:
fstream output_file("output_file.txt", ios::binary);
output_file.put('\0');
The ios::binary prevents the compiler or OS from translating the '\0'.

Reading binary text into array?

I have a program that I need to read binary text into. I read the binary text via a redirection:
readData will be an executable made by my Makefile.
Example: readData < binaryText.txt
What I want to do is read the binary text, and store each character in the binary text file as a character inside a char array. The binary text is made up of 32 This is my attempt at doing so...
unsigned char * buffer;
char d;
cin.seekg(0, ios::end);
int length = cin.tellg();
cin.seekg(0, ios::beg);
buffer = new unsigned char [length];
while(cin.get(d))
{
cin.read((char*)&buffer, length);
cout << buffer[(int)d] << endl;
}
However, I keep getting a segmentation fault on this. Might anyone have any ideas on how to read binary text into a char array? Thanks!
I'm more a C programmer rather than a C++, but I think that you should have started your while loop
while(cin.get(&d)){
The easiest would be like this:
std::istringstream iss;
iss << std::cin.rdbuf();
// now use iss.str()
Or, all in one line:
std::string data(static_cast<std::istringstream&>(std::istringstream() << std::cin.rdbuf()).str());
Something like this should do the trick.
You retrieve the filename from the arguments and then read the whole file in one shot.
const char *filename = argv[0];
vector<char> buffer;
// open the stream
std::ifstream is(filename);
// determine the file length
is.seekg(0, ios_base::end);
std::size_t size = is.tellg();
is.seekg(0, std::ios_base::beg);
// make sure we have enough memory space
buffer.reserve(size);
buffer.resize(size, 0);
// load the data
is.read((char *) &buffer[0], size);
// close the file
is.close();
You then just need to iterate over the vector to read characters.
The reason why you are getting segmentation fault is because you are trying to access an array variable using a character value.
Problem:
buffer[(int)d] //d is a ASCII character value, and if the value exceeds the array's range, there comes the segfault.
If what you want is an character array, you already have that from cin.read()
Solution:
cin.read(reinterpret_cast<char*>(buffer), length);
If you want to print out, just use printf
printf("%s", buffer);
I used reinterpret_cast because it thought it is safe to convert to signed character pointer since most characters that are used would range from 0 ~ 127. You should know that character values from 128 to 255 would be converted wrongly.

What is the proper method of reading and parsing data files in C++?

What is an efficient, proper way of reading in a data file with mixed characters? For example, I have a data file that contains a mixture of data loaded from other files, 32-bit integers, characters and strings. Currently, I am using an fstream object, but it gets stopped once it hits an int32 or the end of a string. if i add random data onto the end of the string in the data file, it seems to follow through with the rest of the file. This leads me to believe that the null-termination added onto strings is messing it up. Here's an example of loading in the file:
void main()
{
fstream fin("C://mark.dat", ios::in|ios::binary|ios::ate);
char *mymemory = 0;
int size;
size = 0;
if (fin.is_open())
{
size = static_cast<int>(fin.tellg());
mymemory = new char[static_cast<int>(size+1)];
memset(mymemory, 0, static_cast<int>(size + 1));
fin.seekg(0, ios::beg);
fin.read(mymemory, size);
fin.close();
printf(mymemory);
std::string hithere;
hithere = cin.get();
}
}
Why might this code stop after reading in an integer or a string? How might one get around this? Is this the wrong approach when dealing with these types of files? Should I be using fstream at all?
Have you ever considered that the file reading is working perfectly and it is printf(mymemory) that is stopping at the first null?
Have a look with the debugger and see if I am right.
Also, if you want to print someone else's buffer, use puts(mymemory) or printf("%s", mymemory). Don't accept someone else's input for the format string, it could crash your program.
Try
for (int i = 0; i < size ; ++i)
{
// 0 - pad with 0s
// 2 - to two zeros max
// X - a Hex value with capital A-F (0A, 1B, etc)
printf("%02X ", (int)mymemory[i]);
if (i % 32 == 0)
printf("\n"); //New line every 32 bytes
}
as a way to dump your data file back out as hex.