[Q] I need help with c++ stuff

02/03/2015 19:59 NutellaJunkie#1
Hello all.
I'm trying to make a packet editor/sniffer/sender for a game, it all works just fine, except I can't send my own packets. I have all the necessary addresses and all that (I know this because if I hard code a packet, it get sent as it should).
But when I use a "Edit control"-box to make dynamic packets at run time, it gets malformed.
I will try to explain the steps and the output at that step:
1. Get string from Edit box, could look something like this "S>0B C8 32 41"
2. Filter my string. Output "0B C8 32 41" or "0BC83241" (depending on what setting)
3. Take that string and convert it to "char *packet = new char[length]", containing the hex!
4. Send the packet through sendPacket(char* buf, Int len).

My problem occur at step 3, when I try to convert the string. The expected output would be:
packet[0] = 0B Or simply B
packet[1] = C8
packet[2] = 32
packet[3] = 41

But I get:

packet[0] = B
packet[1] = FFFFFFC8
packet[2] = 32
packet[3] = 41

Currently I'm using:
Code:
DWORD StringToByteArray(char *str, char *pbyte)
{
	DWORD ArraySize = ((strlen(str) + 1) / 3); 
	char *pEnd = str;
	for (DWORD i = 0; i < ArraySize; i++)
	{
		pbyte[i] = (char) strtol(pEnd, &pEnd, 16);
	}
	return ArraySize;
}
This code was provided by ms (he is now banned I believe). The original code didn't type cast to char, but BYTE instead. But when I use BYTE the game freezes.

So my problem is at the convert hex string to char* array stage, mainly, when the hex start with a letter (A,B,C,D,E,F) it get converted to "FFFFFFLX". (where F is F in hex, and L is the letter (A,B,C,D,E,F) and X is whatever comes after the letter in the hex-pair.

I read on the interwebz that char and unsigned char can interpret the hex/int value in two totally different ways example:
Code:
char a=0xa1;
unsigned char b=0xa1;
printf ("a=[%02x], b=[%02x]\n",a,b);

output:
a=[ffffffa1], b=[a1]
But I can't use unsigned char since the send function need "char* buf" not "unsigned char* buf".

So my question (after all this wall of text), is there a way I can force my code to convert the string to C8 instead of FFFFFFC8?
Or is there another way to get the hex-pairs from the string to a char* buf?
Or maybe a better way to get the hex from the Edit-box to a char* array?

I use visual studio 2013, win32project as a DLL.
Thanks in advance, NutellaJunkie.

ps. Sorry if I posted in the wrong section.
02/04/2015 12:11 XxharCs#2
Code:
#include <iostream>
#include <string.h>

int main(int argc, char **argv)
{
   std::string str = "0BC83241"; //say this is our read string
   
   char *buf = new char[str.size()+1]; //as 1 char space for null is also required
   *(buf + str.size()) = 0;
   
   memcpy(buf, str.c_str(), str.size());
   
   std::cout << "Output: " << std::endl;
   
   for(int i = 0; i < strlen(buf); i++)
       std::cout << *(buf + i);

    std::cout << std::endl;
   
   return 0;
}
02/04/2015 12:24 Padmak#3
That's just wrong, it outputs the given string again.
Could be replaced by
Code:
std::string str = "asdf";
std::cout << str << std::endl
@OP:
Your code seems fine, the difference in output comes from the different interpretations of char and unsigned char.
If you change char to unsigned char (BYTE is just a define/typedef for unsigned char, at least I think it is) everything should be correct in your output
Maybe your error is somewhere else?

Your numbers starting with a letter are just so "big" that they have the first bit set in their respective byte, so if it gets interpreted as signed, the interpreting code thinks it's negative

(Read https://en.wikipedia.org/wiki/Two%27s_complement and https://en.wikipedia.org/wiki/Signed...epresentations for background)

Padmak
02/04/2015 12:30 XxharCs#4
Quote:
Originally Posted by Padmak View Post
That's just wrong, it outputs the given string again.
Could be replaced by
Code:
std::string str = "asdf";
std::cout << str << std::endl
I know, but I just showed him how to properly convert a string to an array. How he is going to use it for his case, is up to him.
02/04/2015 12:55 Padmak#5
Then you should say that, and much more important: mention that he has to delete buf or else he will have a memory leak!

So i'd rather use something like a vector:
Code:
std::string str = "asdfasdfasdfasdf";
std::vector<char> strArr(str.begin(), str.end());
// use &strArr[0] just like a normal array
It's the same thing, it can be manipulated in-place and it will delete its memory after it gets destroyed

Or alternatively: std::unique_ptr<char>

Padmak
02/04/2015 13:04 NutellaJunkie#6
@Padmak

I changed everything in my code to unsigned char instead, while some packets actually send, some packets make the game to crash. and some packets doesn't work at all.
It might have something todo with the game itself.
But this is good enough, for now :)

So thank you for all your help.
02/04/2015 16:21 +Yazzn#7
Or he could just use standard arrays

Code:
int bytes_received = recv(socket, buffer, length, flags);
// using std::vector
std::vector<char> data(buffer, buffer + bytes_received);

// using std::array
std::array<char, length> data;
memcpy(std::get<0>(data), buffer, bytes_received);

// set null-terminator (make sure bytes_received < length)
std::get<bytes_received> = '\x00';

// access like this
std::get<6>(data) = '\xFF';
std::get<7>(data) = '\x64';
@NutellaJunkie

I don't think it has anything to do with the game itself. Sounds like you're running into an access violation. You might be writing at invalid positions. Have you tried debugging your program to find out where exactly the game freezes?

edit: std::array will only work if you have the length of the buffer hard coded (const int buffer_size = 256; for example) as Padmak mentioned below.
02/04/2015 17:38 Padmak#8
No that doesn't work, std::array must be created using either a const variable or a literal, you can't use variables for that (since it's a template, not a function)

Padmak
02/04/2015 20:58 +Yazzn#9
length is constant. (When hooking send/recv you can just add const to the length parameter)
02/04/2015 22:06 Padmak#10
Have you already tried that? I'm very sure it won't work, because if your's works, this should also compile:
Code:
#include <iostream>
#include <array>

void dosth(const int v)
{
	std::array<char, v> data;
}

int main() {
	size_t length;
	std::cin >> length;
	dosth(length);
	return 0;
}
And it doesn't.

Padmak
02/04/2015 22:34 +Yazzn#11
You're right my bad. I'm a bit off today. My example will only work if you have the size of the buffer hard coded (const int recv_buffer_size = 256; for example). Might not work for send because the send is usually a dynamic container.
02/05/2015 00:12 user11a#12
Avoid dynamic container, sent pm