To start off: I have an app that takes a byte array and loads assembly from it.
My idea, to prevent (easy)piracy, was to have an encrypted string on server, download it on client, decrypt it to get for example:
std::string decrypted = "0x4D, 0x5A, 0x90, 0x0, 0x3, 0x0, 0x0, 0x0, 0x4";
Then to convert from string to binary(byte array) so it would be
uint8_t binary[] = { 0x4D, 0x5A, 0x90, 0x0, 0x3, 0x0, 0x0, 0x0, 0x4 };
And then continue as it was before, but after lots of googling I couldn't find much info on such direct conversion between regular string and byte array.
Thank you for any help! -Sarah
You could use std::stoi in a loop.
It gives you the ending position of the number, which you can then use to check if the string is at its end, or if it's a comma. If it's a comma skip it. Then call std::stoi again using the position as the string to parse.
It's not the most effective, but should work fine.
Use std::stoul to interpret a string as an unsigned integer. The unsigned integer can then be cast to a uint8_t type.
One method of parsing the entire string is by using a stringstream.
Code example:
#include <cstdint>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
// Input string and output vector
std::string const decrypted{"0x4D, 0x5A, 0x90, 0x0, 0x3, 0x0, 0x0, 0x0, 0x4"};
std::vector<std::uint8_t> bytes;
// Parse the string and fill the output vector
std::istringstream decryptedStringStream{decrypted};
std::string decryptedElement;
while (getline(decryptedStringStream, decryptedElement, ','))
{
auto const byte = static_cast<std::uint8_t>(std::stoul(decryptedElement, nullptr, 16));
bytes.push_back(byte);
}
// Print the results (in base 10)
for (auto const &e : bytes)
std::cout << static_cast<int>(e) << '\n';
}
First of all, you should get rid of ", ". Then you can parse char by char, doing bitwise leftshift on every second char and saving as byte
char firstchar = HexCharToByte('5');
char secondchar = HexCharToByte('D');
char result = firstchar | (secondchar << 4);
printf("%%hhu", result); //93
Where HexCharToByte is (upper chars only):
char HexCharToByte(char ch) => ch > 57 ? (ch - 55) : (ch - 48);
This is fast enough method of parsing hex chars.
Related
I need to add a 64 bit floating point number into an unsigned char array at specific indexes (ex. index 1 through 8).
Example unsigned char array:
unsigned char msg[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
I want to add a floating point number like 0.084, for example, which is represented as 1B2FDD240681B53F in hex (little endian) to the unsigned char array at indexes 1,2,3,4,5,6,7,8 and leave indexes 0 and 9 unchanged.
So, I would like the unsigned char array, msg, to contain the following:
msg = {0x00, 0x1B, 0x2F, 0xDD, 0x24, 0x06, 0x81, 0xB5, 0x3F, 0x00}
So far I can get a std::string with the hexadecimal representation of the example floating point value 0.084 using the following code but I'm not sure how to add the string values back into the unsigned char array:
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
int main()
{
union udoub
{
double d;
unsigned long long u;
};
double dVal = 0.084;
udoub val;
val.d = dVal;
std::stringstream ss;
ss << std::setw(16) << std::setfill('0') << std::hex << val.u << std::endl;
std::string strValHexString = ss.str();
cout<< strValHexString << std::endl;
return 0;
}
Output:
3fb5810624dd2f1b
I tried using std::copy like in the example below to copy the values from the std::string to an unsigned char but it doesn't seem to do what I want:
unsigned char ucTmp[2];
std::copy(strValHexString.substr(0,2).begin(), strValHexString.substr(0,2).end(), ucTmp);
Looking for a C or C++ solution.
Formatting the component bytes into a hex string and then reading those back in again is a terrible waste of time and effort. Just use std::memcpy() (in C++) or memcpy (in C):
std::memcpy(&msg[1], &dVal, sizeof(dVal));
This will take care of any required pointer alignment issues. However, it will not do any 'interpretation' in terms of your endianness - but this shouldn't be a problem unless you're then transferring that byte array between different platforms.
Your example has undefined behaviour due to reading from an inactive member of a union. A well defined way to do the conversion to integer:
auto uVal = std::bit_cast<std::uint64_t>(dVal);
Now that you have the data in an integer, you can use bitwise operations to extract individual octets in specific positions:
msg[1] = (uVal >> 0x0 ) & 0xff;
msg[2] = (uVal >> 0x8 ) & 0xff;
msg[3] = (uVal >> 0x10) & 0xff;
msg[4] = (uVal >> 0x18) & 0xff;
msg[5] = (uVal >> 0x20) & 0xff;
...
This can be condensed into a loop.
Note that this works the same way regardless of endianness of the CPU. The resulting order in the array will always be little endian unlike in the direct std::memcpy approach which results in native endianness which is not necessarily little endian on all systems. However, if floating point and integers use different endianness, then the order won't be the same even with this approach.
I would like to know how to pass/COPY a sequence of bytes represented as a char* to a BYTE* in C++ in Windows.
Let's say I have this char* :
const char *ByteString = "\x3B\xC8\x74\x1B"
How would I COPY each byte from this char* to a BYTE *Bytes and vice-versa ?
EDIT: Thanks alot for everyone's help !
The definition of BYTE is:
typedef unsigned char BYTE;
which is not the same as a const char, so you'd need to convert it, but note that casting away const from something declared const to start with results in undefined behaviour and trying to actually change the data poses an even bigger risk.
BYTE* Bytes = reinterpret_cast<BYTE*>(const_cast<char*>(ByteString));
Edit: I just noticed that converting a const char* to a BYTE* was taken out of the question but I'll leave it here for now.
Copying the data (not as a zero terminated string) could be done like this:
const char ByteString[] = "\x3B\xC8\x74\x1B";
BYTE* Bytes = new BYTE[sizeof(ByteString)-1];
std::memcpy(Bytes, ByteString, sizeof(ByteString)-1);
// Use your Bytes
delete[] Bytes; // manual delete when you are done
Or better:
const char ByteString[] = "\x3B\xC8\x74\x1B";
std::basic_string<BYTE> Bytes( reinterpret_cast<const BYTE*>(ByteString), sizeof(ByteString)-1 );
// use Bytes
// Bytes.data() returns a BYTE*
// Bytes.size() returns the length.
But given the nature of what you are doing, you could probably skip these conversions and use an array of the correct type to start with:
BYTE Bytes[] = { 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B };
or
std::basic_string<BYTE> Bytes({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
These won't need any conversions when all you deal with is raw BYTE data. Here's an example using ReadProcessMemory and a basic_string for a buffer and pattern.
using BYTEstr = std::basic_string<BYTE>; // just for convenience
BYTEstr Buffer(1024, 0); // 1024 BYTES initialized with 0
BYTEstr Pattern({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
ReadProcessMemory(hProcess, lpBaseAddress, Buffer.data(), Buffer.size(), &lpNumberOfBytesRead);
BYTEstr::size_type pos = Buffer.find(Pattern);
if (pos == BYTEstr::npos) {
std::cout << "Pattern not found\n";
} else {
std::cout << "Pattern found at position " << pos << "\n";
}
To respect const, use
const BYTE *Bytes = reinterpret_cast<const BYTE*>(ByteString);
and vice versa:
const char *ByteString = reinterpret_cast<const char *>(Bytes);
If you want to make copy of the buffer so that you can modify it, use
len = LenOfChrStr;
BYTE *Bytes = new BYTE[len];
memcpy(Bytes, ByteStr, len);
Given a char const * array of characters, we can make a new buffer with readwrite BYTEs for the API to possibly edit:
char const *ByteString = "\x3B\xC8\x74\x1B";
auto len = std::strlen(ByteString) + 1;
auto ptr = std::make_unique<BYTE[]>(len);
std::memcpy(ptr.get(), ByteString, len);
If you need to surrender the ownership of the memory to the function:
Func(ptr.release());
But if you want to keep the ownership yourself:
Func(ptr.get());
In MSVC (I guess this is your compiler for WinAPI application) you can make the char type unsigned with /J option (more here: https://learn.microsoft.com/en-us/cpp/build/reference/j-default-char-type-is-unsigned?view=vs-2017). If you do this, BYTE becomes the same as char and no conversion would be necessary.
Please note, this might have some other side effects in your application.
Right now in my current project i have a string like this :
std::string ordre="0x010x030x000x320x000x01";
And i would like to create a char array looking like this with it (and if possible the reverse action too) :
unsigned char Com[]= {0x01, 0x03, 0x00, 0x32, 0x00, 0x01};
I have no problem working with the string, creating another std::string and getting the 0x01 part in the beginning using ordre.at() for the characters i want. But i can't find a way to put this new string 0x01 into Com[1].
Writing directly :
Com[1]=0x01;
It works but i would like to make something where Com[1] could change.
Right now in my current project i have a string like this :
std::string ordre="0x010x030x000x320x000x01";
And i would like to create a char array looking like this with it (and if possible the reverse action too) :
unsigned char Com[]= {0x01, 0x03, 0x00, 0x32, 0x00, 0x01};
First, "0x01" is different than 0x01. To extract values from the string, you will need to read it in a loop, four characters at a time:
if(ordre.size() % 4)
throw std::runtime_error{ "invalid string length; format is different" };
std::vector<int> values;
auto b = std::begin(ordre);
const auto e = std::end(ordre);
while(b != e)
{
std::string s{ b, b+4 };
values.push_back(std::stoi(s, 0, 16));
b += 4;
}
If you use C++ : use STL structures instead of (strugling with) arrays
If I where you i'll build a std::vector<unsigned char> and fill it dynamically by iterating over the x in the loop.
I would do the vector filling as such:
Note: This code work ith any size input and is not limited to 4 chars substrings. It is therefore more general but less efficient then the other answers code. Choose according to your needs
std::string order = "0x010x020x030x2360x10240x9001";
std::vector<int> coms;
size_t pos = 0, it;
while ((it = order.find("0x", pos + 1)) != std::string::npos)
{
coms.push_back(std::stoi(order.substr(pos, it-pos), 0, 16));
pos = it;
}
coms.push_back(std::stoi(order.substr(pos), 0, 16));
gives:
0x01 = 1
0x02 = 2
0x03 = 3
0x236 = 556
0x1024 = 4132
0x9001 = 36865
I have an input array with hex values,
const unsigned char arr[]={0x20, 0x34, 0x30};
I need to concatenate the values arr[1]---> 0x34 ---> 4 and
arr[2]---> 0x30 ---> 0
to an integer variable like,
int val = 40;
How can I do this efficiently in c++?.
As The Paramagnetic Croissant commented, you can turn the array to a string (null terminated at the very least) and use strtol
Example:
const unsigned char arr[]={0x20, 0x34, 0x30};
string s(reinterpret_cast<const char*>(arr), 3);
int val = strtol(s.c_str(), nullptr, 10);
My array looks something like this;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, 0x05, 0x00, 0x00, 0x70 };
One of the values is a variable that can change all the time.. so I tried something like this;
const char* input = "0x05";
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
When I compile I get a warning;
warning: initialization makes integer from pointer without a cast
I am a little confused on the conversion I need to do.. since the array has hex strings in it.. and the input string is a char..
in the first line you are declaring a pointer to const char, and initializing to the beginning of string "0x05", that's fine, but it is not the thing you are trying to do.
in the second line, you try to initialize the fourth array element (an unsigned char) with the value of the pointer you assigned to the input variable in the first line. The compiler says you are pretending to embed a pointer value (the address of "0x05" string) into a char variable, so that's why it complained. And also it is not what you intend.
also, take into account that if you are using binary data (from the fact you are initializing arrays with hex numbers) you had better to use unsigned char for binaries, as signed char is valid only for -128 to +127 values, you can expect some more unpredictable behaviour. Perhaps, a declaration typedef unsigned char byte; can do things easier.
typedef unsigned char byte;
byte send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
byte &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
BR,
Luis
Maybe explaining exactly what const char* input = "0x05"; does will clear things up for you.
First the compiler computes the string data and creates it as a static object:
const char data[5] = { 0x30, 0x78, 0x30, 0x35, 0x0 };
Then your variable is initialized:
const char *input = &data[0];
Note that input is a pointer with a value that depends entirely upon the location the compiler chooses to store the string data at, and has nothing to do with the contents of the string. So if you say char c = input; then c basically gets assigned a random number.
So you should be asking yourself "Where is the value 0x05 that I want to store in the send_bytes array?" In your code it's encoded as text, rather than as a number that your program can use directly. You need to figure out how to convert from a string of symbols following the hexadecimal scheme of representing numbers into C++'s native representation of numbers.
Here are a couple hints. Part of the operation involves associating values with each digit symbol. The symbol '0' is associated with the value zero, '1' with the value one, and so on, according to the usual hexadecimal system. Second, once you can get the associated value of a symbol, then you can use those values in some basic arithmetic operations to figure out the value of the number represented by the whole string of symbols.
For example, if you have the symbols '1' '2' and 'a', in that order from left to right then the arithmetic to compute what number is represented is 1 * 16 * 16 + 2 * 16 + 10.
The error string is pretty much telling you exactly what's wrong.
input is of type const char* (a pointer to a const char), whereas your array send_bytes is of type unsigned char[] (an array of unsigned chars).
First, signed and unsigned values are still different types, though your error message isn't referring to that specifically.
In reality, your input value isn't a string (as there is no true string type in C++), but a pointer to a character. This means that the input string doesn't hold the byte x05, but rather the bytes {x30, x78, x30, x35, x00}.
The compiler is saying Hey, I've no idea what you're trying to do, so I'm just converting the address that string I don't understand (input) to an unsigned char and adding it to the array.
That means if the string "0x05" starts at location 0xAB, your array will ultimately contain { 0x0B, 0x11, 0xA6, 0xAB, 0x00, 0x00, 0x70 }.
You're going to either have to convert from a string to an integer using a radix of 16, or just not use a string at all.
I'd also recommend reading up on pointers.
The array doesn't have "hex strings" in it - if they were, they would be enclosed in quotation marks, like all strings.
The literals are integers written in hexadecimal notation, and equivalent to
unsigned char send_bytes[] = { 11, 17, 166, input, 0, 0, 112 };
Since it's an array of unsigned char you should put an unsigned char there:
unsigned char input = 0x05;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
You had better to put in your code:
unsigned char send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
unsigned char &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
this way you can do things like:
input = 0x26;
send_packet(send_bytes);