Salsa20 using Crypto++ - c++

I am trying to use the salsa20 code in the crypto++ Library. ( http://www.cryptopp.com/) to communicate between two programs.
Both programs use the same code which follows
std::string salsaDo(std::string key, std::string msg, byte iv[STREAM_IV_LENGTH]) {
//Set up byte arrays for proccess
byte *plaintextBytes = (byte *)msg.c_str();
byte *ciphertextBytes = new byte[msg.length()];
byte *reversetextBytes = new byte[msg.length()];
//Set up key array
byte* keyBytes = (byte *)key.substr(0, STREAM_KEY_LENGTH).c_str();
//Peform encryption method
Salsa20::Encryption salsa;
salsa.SetKeyWithIV(keyBytes, STREAM_KEY_LENGTH, iv);
salsa.ProcessData(ciphertextBytes, plaintextBytes, msg.length());
salsa.SetKeyWithIV(keyBytes, STREAM_KEY_LENGTH, iv);
salsa.ProcessData(reversetextBytes, ciphertextBytes, msg.length());
std::string ivStr((char*)iv, STREAM_IV_LENGTH);
std::cout << "____\nK:" << key.c_str();
std::cout << "\nI:" << ivStr.c_str();
std::cout << "\nM:" << msg.c_str();
std::cout << "\nE:" << std::string((const char *)ciphertextBytes, msg.length()).c_str();
std::cout << "\nR:" << std::string((const char *)reversetextBytes, msg.length()).c_str();
std::cout << "\n____\n";
//return msg;
//return string
return std::string((const char *)ciphertextBytes, msg.length());
}
An image from the programs is at http://s21.postimg.org/wgfmkjcn9/encrypt.png
Explanation:
Step1 : plain text is encrypted (server-M to server-E)
Step2 : encrypted text is decrypted (Server-E to server-R and client-M to client-E.) These two should give the same result but don't
Step3 : client-E is run through again to check that it equals the msg the server sent.

There are a few problems with this code.
This line technically invokes Undefined Behavior:
byte* keyBytes = (byte *)key.substr(0, STREAM_KEY_LENGTH).c_str();
In this case, the substr() call returns a temporary std::string object containing the substring. The lifetime of this temporary std::string extends through the evaluation of the entire line (the full expression). The lifetime of the C string returned by std::string::c_str() is the same as the std::string, except that it is invalidated by a mutating operation. Thus, in this full expression, keyBytes is likely an invalid pointer once the line has executed.
You can fix the problem by overwriting key to the desired substring. In this case, assigning to key ensures that the lifetime is extended through where it is used:
key = key.substr(0, STREAM_KEY_LENGTH);
const byte* keyBytes = static_cast<const byte*>(key.c_str());
This salsaDo() function leaks memory. The byte arrays created by:
byte *ciphertextBytes = new byte[msg.length()];
byte *reversetextBytes = new byte[msg.length()];
.. are not freed. Consider using a std::unique_ptr<byte[]>:
std::unique_ptr<byte[]> ciphertextBytes(new byte[msg.length()]);
std::unique_ptr<byte[]> reversetextBytes(new byte[msg.length()]);
C++ does not technically support passing arrays to functions. The parameter byte iv[STREAM_IV_LENGTH] is actually treated as if you had written byte* iv instead.
You could pass a reference to the array. Also, for const-correctness, you should mark the initialization vector bytes const:
std::string salsaDo(std::string key, std::string msg, const byte (&iv)[STREAM_IV_LENGTH])
{
//...
}
I wouldn't use a std::string to store the key, or really any array of bytes such as the returned encrypted bytes. Consider using a std::unique_ptr<byte[]> or std::shared_ptr<byte[]>, or passing a reference to a const array, or passing a pointer and length (e.g. const byte* key and size_t keyLength).

Related

Convert from vector<unsigned char> to char* includes garbage data

I'm trying to base64 decode a string, then convert that value to a char array for later use. The decode works fine, but then I get garbage data when converting.
Here's the code I have so far:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
decodedChar[decodedData.size() + 1] = 0; // terminate the string
for (size_t i = 0; i < decodedData.size(); ++i) {
decodedChar[i] = decodedData[i];
}
vector<BYTE> is a typedef of unsigned char BYTE, as taken from this SO answer. The base64 code is also from this answer (the most upvoted answer, not the accepted answer).
When I run this code, I get the following value in the VisualStudio Text Visualiser:
TestStringÍ
I've also tried other conversion methods, such as:
char* decodedChar = reinterpret_cast< char *>(&decodedData[0]);
Which gives the following:
TestStringÍÍÍýýýýÝÝÝÝÝÝÝ*b4d“
Why am I getting the garbage data at the end of the string? What am i doing wrong?
EDIT: clarified which answer in the linked question I'm using
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
Why would you manually allocate a buffer and then copy to it when you have std::string available that does this for you?
Just do:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
std::string decodedString { decodedData.begin(), decodedData.end() };
std::cout << decodedString << '\n';
If you need a char * out of this, just use .c_str()
const char* cstr = decodedString.c_str();
If you need to pass this on to a function that takes char* as input, for example:
void someFunc(char* data);
//...
//call site
someFunc( &decodedString[0] );
We have a TON of functions and abstractions and containers in C++ that were made to improve upon the C language, and so that programmers wouldn't have to write things by hand and make same mistakes every time they code. It would be best if we use those functionalities wherever we can to avoid raw loops or to do simple modifications like this.
You are writing beyond the last element of your allocated array, which can cause literally anything to happen (according to the C++ standard). You need decodedChar[decodedData.size()] = 0;

How to use WriteProcessMemory (WPM) to replace strings?

I am trying to write a simple code to replace a string in a program by another using WPM and I am able to make it work, but only partly. This is part of the code I used to get the result.
string strWrite;
cin >> strWrite;
strWrite = strWrite + "\0";
if (WriteProcessMemory(hProcess, (LPVOID) reqdAddr, &strWrite[0], strWrite.size(), NULL) == false)
{
cout << "WriteProcessMemory failed. GetLastError = " << dec << GetLastError() << endl;
system("pause");
return EXIT_FAILURE;
}
When I try to replace the original string DefaultString with blabla, the result I get is blablatString. I have tried things like replacing strWrite.size() by strWrite.size() + 1 and realized that the result changes to blabla String. I need help replacing the entire string and not just the part of it.
If (as appears to be the case) the target string is stored as a std::string then this approach is not going to work. These have an internal structure that programmers are not supposed to be privy to (unless you go digging around in the header file) and the code you have there is not taking account of that. And even if you do, the next version of the compiler is probably going to break your code.
So consider instead (if you can) storing the target string as a simple C string. Overwriting it is then straightforward just so long as you don't run off the end and you add a terminating nul. I would do this explicitly - don't assume that the source string is nul-terminated, it may not be. Or use std::string.c_str() and copy size() + 1 bytes from that.
std::string is a container that managed a char array on the back end.
As it stands right now, on x86 if the string you want to write is the same size or less than the current string, you can perform this with relative ease but it is not recommended.
offset 0x14 of the container is the size of the array
if the char array is less than 15 characters, the array is stored at offset 0x4
if the char array is greater than 15 characters, this offset is turned into a pointer to the dynamic array elsewhere
So you read the size of the array, then write to the correct address depending on it's size. This code will do that and output "goodbye m8"
void WriteExternalString(HANDLE hProc, BYTE* addr, char* newstr)
{
unsigned int arraySize;
//Get the size of the array, offset 0x14 is the size of the array
ReadProcessMemory(hProc, (BYTE*)(addr + 0x14), &arraySize, sizeof(arraySize), 0);
if (arraySize > 15)
{
uintptr_t addrOfCharArray;
//dereference the pointer in the second member variable to get the dynamic address of the array
ReadProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), &addrOfCharArray, sizeof(void*), 0);
//Write the buffer to the array, +1 to get the null terminator
WriteProcessMemory(hProc, (BYTE*)(addrOfCharArray), newstr, strlen(newstr) + 1, 0);
}
else
{
WriteProcessMemory(hProc, (BYTE*)(addr + sizeof(void*)), newstr, strlen(newstr) + 1, 0);
}
}
int main()
{
std::string str = "Hello Mate";
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
char newstr[] = "Goodbye m8";
WriteExternalString(hProcess, (BYTE*)&str, newstr);
cout << "string char array = " << str << endl;
system("pause");
return 0;
}

concatenate string and integer to produce byte array c++

I have a std string and and long that I want to concatenate to produce a byte array (unsigned char *). I have no clue how to do it in c++, I struggled trying to do it with memory.
In java System.arraycopy does the trick.
here are my inputs :
unsigned long part1 = 0x0100000002;
std::string part2 = "some_str";
what i want to have is unsigned char * combined = part2 + part1
any hint ?
There are lots of ways to do this, but here's one using a std::vector to hold the destination buffer (and manage all the memory allocation and deallocation associated with it) and std::memcpy (which is similar to System.arraycopy) to do the copying.
unsigned long part1 = 0x0100000002;
std::string part2 = "some_str";
// create a vector big enough to hold both components
std::vector<char> buffer(sizeof(part1) + part2.size());
// copy the string into the beginning of the buffer
std::memcpy(&buffer[0], &part2[0], part2.size());
// copy the int into the space after the string
std::memcpy(&buffer[part2.size()], &part1, sizeof(part1));
std::cout.write(&buffer[0], buffer.size());
std::cout << "\n";
You can get a plain old char* pointer from a std::vector<char> by doing things like &buffer[0], which gets a pointer to the first element in the underlying array that makes up the vector. You may need to handle your own null termination, if you wanted to use this like a string (which is why I used std::cout.write instead of std::cout << in my example).
An alternative that avoids using memcpy and having to handle the buffer size yourself is to use a stream:
std::stringstream ss;
ss.write(&part2[0], part2.size());
ss.write(reinterpret_cast<const char*>(&part1), sizeof(part1));
std::string buf = ss.str();
std::cout.write(buf.c_str(), buf.size());
std::cout << "\n";
As output on windows from either version, I get this:
some_str☻

std::string to BYTE[]

My goal is to get this:
BYTE Data1[] = {0x6b,0x65,0x79};
BYTE Data2[] = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
But my starting point is:
std::string msg = "message";
std::string key = "key";
I am not able to get from std::string to BYTE[].
I tried the following:
std::vector<BYTE> msgbytebuffer(msg.begin(), msg.end());
BYTE* Data1 = &msgbytebuffer[0];
This didn't cause compile or run time error. However, the end result (I feed this to a winapi function - crypto api) was not the same as when I used the actual byte array like in top most ({0x6D,0x65,0x73,0x73,0x61,0x67,0x65}).
You can use string::c_str() function which returns a pointer to c style string that can be passed to winapi functions like:
foo(string.c_str());
What it actually does is that it returns a pointer to an array that contains a null-terminated sequence of characters.
I suppose BYTE[] is actually a char array. You can assign your std::string to char array by doing:
std::string str = "hello";
BYTE byte[6]; // null terminated string;
strcpy(byte, str.c_str()); // copy from str to byte[]
If you want to copy the str without the 0 at the end, use strncpy instead:
BYTE byte[5];
strncpy(byte, str.c_str(), str.length());
Seems me that winapi is waiting a null terminated c-string. You can achieve that by using:
msg.c_str();
or, using your BYTE type, something like that:
std::vector<BYTE> msgbytebuffer(msg.length() + 1, 0);
std::copy(msg.begin(), msg.end(), msgbytebuffer.begin());

string <-> byte[] conversions

I'm implementing a system that uses libcrafter and crypto++ to transmit specific frames on the network. But the problem I'm stuck with isn't at this level at all.
It's about conversion between types used in these libraries.
1) At the emission (solved)
I'm trying to convert the Crafter::byte array to a std::string, in order to put this message into a network frame (as an initialization vector for an AES encryption/decryption).
Moreover, the iv must be zeroed, and I can't initialize it properly (despite the answers here or there).
EDIT : to initialize it to 00, I had to do it in hexadecimal : 0x30. And to convert it to a std::string I had to provide the length ie ivLen2 (thanks for the answers).
Here's what I do :
const int ivLen2 = 2;
std::string encrypted_message("whatever");
Crafter::byte iv[ivLen2]={0x30, 0x30}; // crypto salt of 2 bytes at 0.
std::string ivStr( reinterpret_cast< char const* >(iv), ivLen2 ) ;
string mess2send = ivStr + encrypted_message;
And if I display them, with this :
cout<<"iv[0] : "<<iv[0]<<endl; // display 0
cout<<"mess2send : "<<mess2send<<endl; // display 00whatever
Why don't I simply create a zeroed string and send it ? In order to have generic functions, and a re-usable code.
2) At the reception (pending)
Without surprises I have to do the opposite. I get a iv and the message concatenated within a vector<byte>* payload, and I have to extract the iv as a byte array, and the message within a string.
The message isn't actually the problem, given that std::string is close to vector.
Here's what I tempt to retrieve the iv :
Crafter::byte iv[ ivLen2 ];
for (int i = 0; i < ivLen2; i++)
{
iv[i] = (byte)payload->at(i);
}
std::string iv_rcv( reinterpret_cast< char const* >(iv) ) ;
And to display them, I do (in the same loop) :
cout<<iv[i];
But it gives me a non-ASCII character.
I've also tried this (following this and this answers) :
Crafter::byte* iv;
std::string iv_rcv( payload->begin(), payload->begin()+ivLen2 ) ;
iv = (byte*)iv_rcv.c_str();
But it doesn't give me the supposed initialized values...
Does anybody have a clue ? Is my code wrong ?
I don't think this will work:
const int ivLen2 = 2;
std::string encrypted_message("whatever");
Crafter::byte iv[ivLen2]={0x00, 0x00}; // crypto salt of 2 bytes
std::string ivStr( reinterpret_cast< char const* >(iv) ) ;
How does the std::string know how much data to copy from the iv pointer?
You have to use a constructor that takes the length of the data like:
std::string ivStr( reinterpret_cast< char const* >(iv), ivLen2 ) ;
The pointer only constructor is for specifically encoded strings that are terminated by a null character. Unless you are using one of those you must pass the length.
Try this:
const int ivLen2 = 2;
std::string encrypted_message("whatever");
Crafter::byte iv[ivLen2]={0x00, 0x00}; // crypto salt of 2 bytes
std::string ivStr( reinterpret_cast< char const* >(iv), ivLen2 ) ;
std::string mess2send = ivStr + encrypted_message;
std::cout << (int)mess2send[0] << (int)mess2send[1] << mess2send.substr(2) << '\n';