NosTale Q&A

06/11/2019 16:06 Kolzy16#1
Hey there, someone know how should I convert a string to const char* without losing data in C++? I saw Cryless~ was using a vector<char>, what's the ideal option to do it and how could I do it?
06/11/2019 16:09 IceTrailer#2
I don't know why this should be Nostale related. But:
If you use std::string, e.g.:


Code:
#include <string>

int main() {
    std::string exampleString = "I'm a string";
    const char* exampleCharArray = exampleString.c_str();
    return 0;
}
06/11/2019 16:15 maxderloser2#3
[Only registered and activated users can see links. Click Here To Register...]

[Only registered and activated users can see links. Click Here To Register...]

[Only registered and activated users can see links. Click Here To Register...]
06/11/2019 16:20 Kolzy16#4
Quote:
Originally Posted by IceTrailer View Post
I don't know why this should be Nostale related. But:
If you use std::string, e.g.:


Code:
#include <string>

int main() {
    std::string exampleString = "I'm a string";
    const char* exampleCharArray = exampleString.c_str();
    return 0;
}
This is NosTale related because in order to make a Clientless Bot, you need to use a packet (const char*) to send it via socket, and I don't know if I can encrypt directly on the const char* or I need to pass the packet to a string, encrypt it and then pass it to const char*.

My problem is that when I try to print the const char* encrypted login packet it just prints some few characters, and it only sends few characters. Here's code.

Code:
const char* packet = "NoS0575 7031428 "Username" 3213852420455EE02E4F9FB7E1263751BA49DC01278E8D8AC6B094C2AD555ABE3512267B6A2D9528A2234E6A90E295E95E124AE0AB2E54C406C49B533293B3CF c594947f-d4a9-4462-b545-ad7ddbfd71a2 006EC080\x0B0.9.3.3104 0 2F65F4A00E723E4281EFE51CACE4039D";

std::string packetString = packet;
int packetLength = getLength(packet);

for (int i = 0; i < packetLength; i++)
{
    packetString[i] = (packetString[i] ^ 0xC3) + 0xF;
}

// Here is the problem
const char* exampleCharArray = packetString.c_str();
std::cout << exampleCharArray << std::endl; // Only prints 13 chars
06/11/2019 16:34 IceTrailer#5
Quote:
Originally Posted by Kolzy16 View Post
My question is: why when I try to print the const char* encrypted login packet it just prints some few characters? And only send few characters? Here's code.

Code:
const char* packet = "NoS0575 7031428 "Username" 3213852420455EE02E4F9FB7E1263751BA49DC01278E8D8AC6B094C2AD555ABE3512267B6A2D9528A2234E6A90E295E95E124AE0AB2E54C406C49B533293B3CF c594947f-d4a9-4462-b545-ad7ddbfd71a2 006EC080\x0B0.9.3.3104 0 2F65F4A00E723E4281EFE51CACE4039D";

std::string packetString = packet;
int packetLength = getLength(packet);

for (int i = 0; i < packetLength; i++)
{
    packetString[i] = (packetString[i] ^ 0xC3) + 0xF;
}

// Here is the problem
const char* exampleCharArray = packetString.c_str();
std::cout << exampleCharArray << std::endl; // Only prints 13 chars
Check what the content of the encrypted char array is.
I would think that on index 13 there is null byte (\0)

Edit: You should convert the char pointer to a std::vector<char> since you lose data being prefixed by a \0.

Your code could look as follows:
Code:
int main() {
	// input packet
	const char* buffer = "NoS0575 7031428 Test 3213852420455EE02E4F9FB7E1263751BA49DC01278E8D8AC6B094C2AD555ABE3512267B6A2D9528A2234E6A90E295E95E12"
		"4AE0AB2E54C406C49B533293B3CF c594947f-d4a9-4462-b545-ad7ddbfd71a2 006EC080\x0B0.9.3.3104 0 2F65F4A00E723E4281EFE51CACE4039D";
	// Instatiate new vector
	std::vector<char> packetVector(buffer, buffer + strlen(buffer));

	// Encryption part
	for (int i = 0; i < packetVector.size(); ++i) {
		packetVector[i] = (packetVector[i] ^ 0xC3) + 0xF;
	}

	// Console output part (if you really want to print the encrypted string)
	for (auto it = packetVector.begin(); it != packetVector.end(); ++it) {
		std::cout << std::to_string(*it) << " ";

	}
	return 0;
}
As you can see, I was right. The char on index 13 is a \0.
[Only registered and activated users can see links. Click Here To Register...]

Output:
[Only registered and activated users can see links. Click Here To Register...]

A null byte marks the end of a string in C. Since C is a subset of C++, C++'s std::string uses a char array in the background.

When you e.g. set the value of std::string to "Testabc\0abctest", it removes the abctest because std::string's strlen() counts the number of chars in a string until there is a \0.
06/11/2019 23:14 Kolzy16#6
Quote:
Originally Posted by IceTrailer View Post
Check what the content of the encrypted char array is.
I would think that on index 13 there is null byte (\0)

Edit: You should convert the char pointer to a std::vector<char> since you lose data being prefixed by a \0.

Your code could look as follows:
Code:
int main() {
	// input packet
	const char* buffer = "NoS0575 7031428 Test 3213852420455EE02E4F9FB7E1263751BA49DC01278E8D8AC6B094C2AD555ABE3512267B6A2D9528A2234E6A90E295E95E12"
		"4AE0AB2E54C406C49B533293B3CF c594947f-d4a9-4462-b545-ad7ddbfd71a2 006EC080\x0B0.9.3.3104 0 2F65F4A00E723E4281EFE51CACE4039D";
	// Instatiate new vector
	std::vector<char> packetVector(buffer, buffer + strlen(buffer));

	// Encryption part
	for (int i = 0; i < packetVector.size(); ++i) {
		packetVector[i] = (packetVector[i] ^ 0xC3) + 0xF;
	}

	// Console output part (if you really want to print the encrypted string)
	for (auto it = packetVector.begin(); it != packetVector.end(); ++it) {
		std::cout << std::to_string(*it) << " ";

	}
	return 0;
}
As you can see, I was right. The char on index 13 is a \0.
[Only registered and activated users can see links. Click Here To Register...]

Output:
[Only registered and activated users can see links. Click Here To Register...]

A null byte marks the end of a string in C. Since C is a subset of C++, C++'s std::string uses a char array in the background.

When you e.g. set the value of std::string to "Testabc\0abctest", it removes the abctest because std::string's strlen() counts the number of chars in a string until there is a \0.
Couldn't I work with strings instead of vectors? And, is there a possible way to try avoiding the "\0" while you convert string to const char*?
06/11/2019 23:16 IceTrailer#7
Quote:
Originally Posted by Kolzy16 View Post
Couldn't I work with strings instead of vectors? And, is there a possible way to try avoiding the "\0" while you convert string to const char*?
No and no.

When you have decrypted bytes you should never use a string due to the null byte.
Use a std::vector.
And no, C/C++ terminates strings on the first found \0 byte. You cannot change that.
06/11/2019 23:28 Kolzy16#8
Quote:
Originally Posted by IceTrailer View Post
No and no.

When you have decrypted bytes you should never use a string due to the null byte.
Use a std::vector.
And no, C/C++ terminates strings on the first found \0 byte. You cannot change that.
And how do I insert my vector<char> into a const char*?
06/11/2019 23:30 IceTrailer#9
std::vector has a data() function which returns a char array.
[Only registered and activated users can see links. Click Here To Register...]
06/12/2019 12:06 Kolzy16#10
Quote:
Originally Posted by IceTrailer View Post
std::vector has a data() function which returns a char array.
[Only registered and activated users can see links. Click Here To Register...]
I figured out how to succesfully send and recv packets with sockets but now I have a "problem". I've copied a login packet using packetlooger and send it via socket and decrypt the answer but it says "failc 1" which means wrong client version, but I checked out if the client version and it was good. I don't know what's wrong.
06/12/2019 14:21 IceTrailer#11
Did you generate a suitable md5 hash from the client?
06/12/2019 14:28 Kolzy16#12
Quote:
Originally Posted by IceTrailer View Post
Did you generate a suitable md5 hash from the client?
I just copied the packet from a packetlogger, is it any problem?
06/12/2019 14:34 IceTrailer#13
Is the packet made with the current client version?
06/12/2019 14:37 Kolzy16#14
Quote:
Originally Posted by IceTrailer View Post
Is the packet made with the current client version?
Yes, look.
Code:
std::string encryptPacket(std::string& packet)
{
	for (int i = 0; i < packet.length(); i++)
	{
		packet[i] = (packet[i] ^ 0xC3) + 0x0F;
	}

	return packet;
}

// This account is a 10 minutes hotmail account, so I don't care about it
std::string loginPacket = "NoS0575 3041001 dnj92442 BA3253876AED6BC22D4A6FF53D8406C6AD864195ED144AB5C87621B6C233B548BAEAE6956DF346EC8C17F5EA10F35EE3CBC514797ED7DDD3145464E2A0BAB413 c594947f-d4a9-4462-b545-ad7ddbfd71a2 007B297D\x0B0.9.3.3104 0 E932E27F6E51675C350CD00C4558EA13\xA";
// Maybe the \x0B or the \xA is incorrect or make it crash

int stringLength = loginPacket.length();

send(ConnectSocket, loginPacket.c_str(), stringLength, 0); // This is what I send

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); // This is to get recv
		if (iResult > 0)
		{
			printf("Bytes received: %d\n", iResult);
			std::cout << "[RECV]: ";
			for (int i = 0; i < iResult; i++)
			{
				std::cout << (BYTE)(recvbuf[i] - 0xF);
			}
		}
06/12/2019 14:39 IceTrailer#15
Where do you have the packet from?
Make sure to use your GUID and to generate the hash automatically (so you don‘t have to change it everytime the client gets an update)