I'm really tired with this - I tried to fix it for about 5 hours and I still can't semm to find a problem, maybe You guys can.
My problem is that recv at the client side always recv one less byte when I'm sending IP from server. And server is always sending the right ammount of data and right data and IP adress on client side always come without 1 number and it's always the first one so server send:
192.168.0.101
Client receive:
92.168.0.101
What is also important is that client's name is always received without any problems - it only happens with IP adress.
Take a closer look at that:
Server side sending data [2 strings - first is name of client and second is his IP adress]:
j is iterator of list to loop thourght all clients and client variable is the one which is asking for all client's data
std::cout << j->client_name << " ";
int lenght = j->client_name.length()+1 ; //+1 for '\0' byte at the client buffer
std::cout << "Lenght (+1): " << lenght << " ";
lenght = htonl(lenght); //change byte order to network
send(client->client_socket,(char*)&lenght,sizeof(int),0);
std::cout << "I have sent: " << send(client->client_socket,j->client_name.c_str(),j->client_name.length(),0) << std::endl;
std::cout << inet_ntoa(j->client_connection.sin_addr) << " "; //showing IP adress
unsigned lenght2 = strlen(inet_ntoa(j->client_connection.sin_addr))+1; //+1 for '\0' byte at the client buffer
std::cout << "Lenght (+1): " << lenght2 << " ";
unsigned realistic_lenght = lenght2;
lenght2 = htonl(lenght2);
send(client->client_socket,(char*)&lenght,sizeof(unsigned),0);
std::cout << "I have sent: " << send(client->client_socket,inet_ntoa(j->client_connection.sin_addr),realistic_lenght,0) << std::endl;
And as I said on server side everything seems to be good and here's code to receive data on client side:
char* data_buffor;
int lenght = 0;
recv(data.client_socket,(char*)&lenght,sizeof(int),0);
lenght = ntohl(lenght);
std::cout << "I have received: " << lenght << std::endl;
data_buffor = new char[lenght];
if (data_buffor != NULL) std::cout << "ALLOCATION WAS SUCCESFULL" << std::endl;
std::cout << "I have received: " << recv(data.client_socket,data_buffor,lenght,0) << std::endl;
data_buffor[lenght-1] = '\0';
temp.client_name = data_buffor; // everything is fine here
delete data_buffor;
data_buffor = NULL;
unsigned lenght2 = 0;
recv(data.client_socket,(char*)&lenght2,sizeof(unsigned),0);
lenght2 = ntohl(lenght2);
std::cout << "I have received: " << lenght2 << std::endl; // I DONT KNOW WHY BUT HERE I GET CRAZY NUMBERS LIKE 3203 and I should get 14 with IP: 192.168.0.101 + one byte for '\0' I think that may be causing all problems but I have no idea how to fix it.
data_buffor = new char[lenght2];
if (data_buffor != NULL) std::cout << "ALLOCATION WAS SUCCESFULL" << std::endl;
std::cout << "I have received " << recv(data.client_socket,data_buffor,lenght2,0) << std::endl;
temp.client_ip_adress = data_buffor;
all_clients.push_back(temp);
delete data_buffor
data_buffor = NULL;
Any help would be highly appreciated.
When the server sends the client name, it is sending the length as the length of the string + 1 to include the terminating NULL character. However, the value returned by std::string::length() does NOT include the terminating NULL, so the server is not actually sending the terminating NULL to the client. When the client then reads the name, it reads the first character of the IP address as the terminating NULL of the name, but you never notice that because the client overwrites that byte in data_buffor with '\0' instead of relying on the server to send the '\0'.
Related
I successfully added Discord Rich Presence to an old game through DLL injection.
When I open the game the RPC kicks in, and it successfully updates my Discord Status.
I want go to further and make the RPC dynamic, reading values from the client itself.
I got the memory addresses from the client using Cheat Engine, these values are persisting through close/open the game again and again.
Now, I have tried several approaches to get this done.
As I am using an internal dll, I can directly read the values from the memory.
I want to read the level from the player
In the following code I'm trying to obtain the value from the address that stores the level of the player.
I'm using three different GetModuleHandles, just to see which could work.
DWORD moduleBase = (DWORD)GetModuleHandle("1.exe"); //GetModule1
DWORD anothermethod = (DWORD)GetModuleHandleA(0); //GetModule2
uintptr_t* p = (uintptr_t*)((uintptr_t)ExeBaseAddress + 0xD35240);
uintptr_t ModuleBaseAdrs = (DWORD&)*p;
printf("ModBaseAdrsLoc - %p, ModuleBaseAdrs - %X\n", p, ModuleBaseAdrs);
int* level = (int*)GetPointerAddress(moduleBase + 0xD35240, {});
DWORD level2DWORD = (DWORD)(anothermethod + 0x0D35240);
size_t ModuleBase = (size_t)GetModuleHandle("1.exe"); //GetModule3
size_t* Adr = reinterpret_cast<size_t*>((*reinterpret_cast<size_t*>(ModuleBase + 0xD35240)));
DWORD* levellevel = (DWORD*)0x0D35240;
Sleep(2000);
int PID = find("1.exe");
std::cout << "PID: " << PID << std::endl;
std::cout << "level2DWORD: " << level2DWORD << std::endl; //GetModule2
std::cout << "Level: " << level << std::endl; //GetModule1
std::cout << "LevelLevel: " << levellevel << std::endl;
std::cout << "Adr: " << Adr << std::endl; //GetModule3
This is what I get on the console
As you can see, I have tried different approaches but none of them results on the desired output.
Could you please light my path?
How can I successfully read from the memory addresses?
I've been learning sockets, and I have created a basic server where you can telnet into and type messages, then press enter and the message is printed on the server.
Since it's telnet, every key press gets sent to the server. So I basically hold all sent bytes in a buffer, and then when a carriage return ("\r\n") is received, I discard that, and print out the clients current buffer. Then I clear the clients buffer.
My problem is that every once in a while (and I'm not quite sure how to replicate it), the first "line" of data I send in gets an extra space tacked onto each character. For example, I'll type "Test" on the telnet client, but my server will receive it as "T e s t ". I always clear the receiving buffer before receiving any data. One obvious solution is just to remove all spaces serverside, but then that messes up my ability to send more than one word. Is this just an issue with my telnet, or is there something I can do on the server to fix this?
I am using the WinSock2 API and Windows 10 Telnet.
EDIT:
I have checked the hex value of the extra character, and it is 0x20.
EDIT:
Here is the code that receives and handles the incoming telnet data.
// This client is trying to send some data to us
memset(receiveBuffer, sizeof(receiveBuffer), 0);
int receivedBytes = recv(client->socket, receiveBuffer, sizeof(receiveBuffer), 0);
if (receivedBytes == SOCKET_ERROR)
{
FD_CLR(client->socket, &masterFDSet);
std::cerr << "Error! recv(): " << WSAGetLastError() << std::endl;
closesocket(client->socket);
client->isDisconnected = true;
continue;
}
else if (receivedBytes == 0)
{
FD_CLR(client->socket, &masterFDSet);
std::cout << "Socket " << client->socket << " was closed by the client." << std::endl;
closesocket(client->socket);
client->isDisconnected = true;
continue;
}
// Print out the hex value of the incoming data, for debug purposes
const int siz_ar = strlen(receiveBuffer);
for (int i = 0; i < siz_ar; i++)
{
std::cout << std::hex << (int)receiveBuffer[i] << " " << std::dec;
}
std::cout << std::endl;
std::string stringCRLF = "\r\n"; // Carraige return representation
std::string stringBS = "\b"; // Backspace representation
std::string commandBuffer = receiveBuffer;
if (commandBuffer.find(stringCRLF) != std::string::npos)
{
// New line detected. Process message.
ProcessClientMessage(client);
}
else if (commandBuffer.find(stringBS) != std::string::npos)
{
// Backspace detected,
int size = strlen(client->dataBuffer);
client->dataBuffer[size - 1] = '\0';
}
else
{
// Strip any extra dumb characters that might have found their way in there
commandBuffer.erase(std::remove(commandBuffer.begin(), commandBuffer.end(), '\r'), commandBuffer.end());
commandBuffer.erase(std::remove(commandBuffer.begin(), commandBuffer.end(), '\n'), commandBuffer.end());
// Add the new data to the clients data buffer
strcat_s(client->dataBuffer, sizeof(client->dataBuffer), commandBuffer.c_str());
}
std::cout << "length of data buffer is " << strlen(client->dataBuffer) << std::endl;
You have two major problems.
First, you have a variable, receivedBytes that knows the number of bytes you received. Why then do you call strlen? You have no guarantee that the data you received is a C-style string. It could, for example, contain embedded zero bytes. Do not call strlen on it.
Second, you check the data you just received for a \r\n, rather than the full receive buffer. And you receive data into the beginning of the receive buffer, not the first unused space in it. As a result, if one call to recv gets the \r and the next gets the \n, your code will do the wrong thing.
You never actually wrote code to receive a message. You never actually created a message buffer to hold the received message.
Your code, my comments:
memset(receiveBuffer, sizeof(receiveBuffer), 0);
You don't need this. You shouldn't need this. If you do there is a bug later in your code.
int receivedBytes = recv(client->socket, receiveBuffer, sizeof(receiveBuffer), 0);
if (receivedBytes == SOCKET_ERROR)
{
FD_CLR(client->socket, &masterFDSet);
std::cerr << "Error! recv(): " << WSAGetLastError() << std::endl;
closesocket(client->socket);
client->isDisconnected = true;
continue;
You mean 'break'. You got an error. You closed the socket. There is nothing to continue.
}
else if (receivedBytes == 0)
{
FD_CLR(client->socket, &masterFDSet);
std::cout << "Socket " << client->socket << " was closed by the client." << std::endl;
closesocket(client->socket);
client->isDisconnected = true;
continue;
Ditto. You mean 'break'. You got an error. You closed the socket. There is nothing to continue.
}
// Print out the hex value of the incoming data, for debug purposes
const int siz_ar = strlen(receiveBuffer);
Bzzzzzzzzzzzzt. There is no guarantee there is a null anywhere in the buffer. You don't need this variable. The correct value is already present, in receivedBytes.
for (int i = 0; i < siz_ar; i++)
That should be `for (int i = 0; i < receivedBytes; i++)
{
std::cout << std::hex << (int)receiveBuffer[i] << " " << std::dec;
}
std::cout << std::endl;
std::string stringCRLF = "\r\n"; // Carraige return representation
No. That is a carriage return (\r) followed by a line feed (\n), often called CRLF as indeed you have yourself in the variable name. This is the standard line terminator in Telnet.
std::string stringBS = "\b"; // Backspace representation
std::string commandBuffer = receiveBuffer;
Bzzt. This copy should be length-delimited by receivedBytes.
if (commandBuffer.find(stringCRLF) != std::string::npos)
As noted by #DavidShwartz you can't assume you got the CR and the LF in the same buffer.
{
// New line detected. Process message.
ProcessClientMessage(client);
}
else if (commandBuffer.find(stringBS) != std::string::npos)
{
// Backspace detected,
int size = strlen(client->dataBuffer);
client->dataBuffer[size - 1] = '\0';
This doesn't make any sense. You are using strlen() to tell you where the trailing null is, and then you're putting a null there. You also have the problem that there may not be a trailing null. In any case what you should be doing is removing the backspace and the character before it, which requires different code. You're also operating on the wrong data buffer.
}
else
{
// Strip any extra dumb characters that might have found their way in there
commandBuffer.erase(std::remove(commandBuffer.begin(), commandBuffer.end(), '\r'), commandBuffer.end());
commandBuffer.erase(std::remove(commandBuffer.begin(), commandBuffer.end(), '\n'), commandBuffer.end());
// Add the new data to the clients data buffer
strcat_s(client->dataBuffer, sizeof(client->dataBuffer), commandBuffer.c_str());
}
I am writing a simple user interface to communicate with an In-Circuit Serial Programmer. The intention is to remove the need for the end-user to type over a dozen cryptic commands via PuTTY, and in fact to remove the need for typing altogether as the user is inevitably wearing keyboard-unfriendly gloves. The process requires interaction with the user, so a simple batch script is not feasible.
I can find the correct COM port and successfully open it. I can send data, but the response is only ever the equivalent of "unknown command".
I shall refrain from posting the whole code as nobody will be able to recreate my circumstances. However, I can always add everything if necessary.
I open comms using CreateFile() and use WriteFile() or ReadFile() to communicate. For example:
if (!WriteFile(hSerial, "r rc.all\r\n", 10, &bytesRead, NULL))
cout << "Error sending message (" << GetLastError() << ")" << endl;
if (!ReadFile(hSerial, msgBuffer, 15, &bytesRead, NULL))
cout << "No message received" << endl
else
{
cout << "Bytes rcvd = " << bytesRead << endl;
for (int x=0; x<bytesRead; x++)
cout << (unsigned int) msgBuffer[x] << " ";
}
No matter what message I send (either "r rc.all" or "foobar") I always get the same response:
Bytes rcvd = 3
62 13 10
Which is >\r\n. I have tried slowing down the sending of characters to simulate them being typed, but this invokes the same response from the ICSP:
bool serialSend(LPCSTR MESSAGE, PHANDLE hSERIAL)
{
DWORD bytesWritten;
char writeBuff[2];
writeBuff[1] = '\0';
for (UINT x = 0; x <= strnlen(MESSAGE, 64); x++)
{
cout << MESSAGE[x];
writeBuff[0] = MESSAGE[x];
if (!WriteFile(*hSERIAL, writeBuff, 1, &bytesWritten, NULL))
cout << "\t\tERROR! (character '" << MESSAGE[x] << "', error " << GetLastError() << ")" << endl;
Sleep(100);
}
writeBuff[0] = '\n';
if (!WriteFile(*hSERIAL, writeBuff, 1, &bytesWritten, NULL))
cout << "\t\tERROR! (character 'LF', error " << GetLastError() << ")" << endl;
Sleep(100);
writeBuff[0] = '\r';
if (!WriteFile(*hSERIAL, writeBuff, 1, &bytesWritten, NULL))
cout << "\t\tERROR! (character 'CR', error " << GetLastError() << ")" << endl;
cout << endl;
return true;
}
I have set the parameters of the serial connection to match the settings in PuTTY - Byte length, stop bit, parity, flow control, etc. The fact that I get a response at all suggests the connections is not at fault.
What is wrong?
The problem turned out to be the \r\n combination sent at the end of the message.
Sending just \r or just \n does not work. However, sending (char) 13 does - even though that should be the same as \r.
There also needs to be a pause between the sending of each character; 1ms is sufficient.
I am using Namedpipes communication(C++) to transfer data between two processes. For the sake of comfort, I am using wstring to transfer the data and everything is fine at the transfer end. I am not able to receive the total data on the receiving end.
The following is the transfer end code.
wstringstream send_data;
send_data << "10" << " " << "20" << " " << "30" << " " << "40" << " " << "50" << " " << "60" << "\0" ;
DWORD numBytesWritten = 0;
result = WriteFile(
pipe, // handle to our outbound pipe
send_data.str().c_str(), // data to send
send_data.str().size(), // length of data to send (bytes)
&numBytesWritten, // will store actual amount of data sent
NULL // not using overlapped IO
);
The following is the receiving end code.
wchar_t buffer[128];
DWORD numBytesRead = 0;
BOOL result = ReadFile(
pipe,
buffer, // the data from the pipe will be put here
127 * sizeof(wchar_t), // number of bytes allocated
&numBytesRead, // this will store number of bytes actually read
NULL // not using overlapped IO
);
if (result) {
buffer[numBytesRead / sizeof(wchar_t)] = '\0'; // null terminate the string
wcout << "Number of bytes read: " << numBytesRead << endl;
wcout << "Message: " << buffer << endl;
}
The result in buffer contains only 10 20 30
Can someone please explain me why the data is truncated.
You are not sending all of the data with the WriteFile() function. You are sending send_data.str().size() number of bytes which is incorrect as size() gives you the number of characters and not the number of bytes. You can change your code to use:
send_data.str().size() * sizeof(wchar_t) / sizeof(char)
Which will send the correct amount of bytes.
I am developing an application with C++ and having some difficulty with boost sockets. The server sends an image but not all the bytes are received by the client; the client always receives about 500 bytes less than the server sent. Provided below is the pertinent code and screenshots of the program running.
Server code:
int sent = boost::asio::write(*socket, response, boost::asio::transfer_all(), error);
std::cout << "Sent: " << sent << std ::endl;
Client code (I know that read_some will block if the total bytes sent by the server is divisible by 10000; this code is just for testing):
int len = 0;
int count = 0;
do {
len = socket->read_some( boost::asio::buffer( imageData, 10000 ) );
count += len;
std::cout << "len: " << len << std::endl;
std::cout << "count: " << count << std::endl;
} while(len == 10000);
std::cout << "Image Received of size: " << count << std::endl;
Screenshot of server:
Screenshot of client:
Thanks for your time; any help or suggestions would be greatly appreciated.
There're no guarantee you'll receive complete buffers of 10000 bytes.
I'd recommend following approach:
To send some binary data w/o any explicit terminator, first send its size and only then data itself. In this case client will know how many data in this chunk it should receive.