Valhalla Legends Forums Archive | C/C++ Programming | pBuffer Help

AuthorMessageTime
Spilled[DW]
Writing my packet buffer i have ran into a few problems and was looking for some help.

Converting these functions to c++ is where i needed help:
[code]
Public Function ToHex(data As String) As String
Dim i As Integer
For i = 1 To Len(data)
    ToHex = ToHex & Right("00" & Hex(Asc(Mid(data, i, 1))), 2)
Next i
End Function

Public Function StrToHex(ByVal String1 As String) As String
On Error Resume Next
    Dim strTemp As String, strReturn As String, i As Long
    For i = 1 To Len(String1)
        strTemp = Hex(Asc(Mid(String1, i, 1)))
    If Len(strTemp) = 1 Then strTemp = "0" & strTemp
    strReturn = strReturn & " " & strTemp
    Next i
        StrToHex = strReturn
End Function
[/code]

As you can see im not too familiar with Hexing in c++ IE both functions deal with hexing.
All help is appreciated! thanks in advance.
June 23, 2005, 5:46 PM
K
This should give you some ideas...

C++ style:
[code]
#include <sstream>
#include <iomanip>
#include <iostream>

int main()
{
// lets pretend this is filled with bytes we want to
// convert to hexadecimal display
char somebuffer[] = "\x1hello there";
int bytes_to_convert = 6;
// this will be our conversion buffer.
std::stringstream buffer;
// tell the buffer to print numbers in hex mode,
// using '0' for padding, with a width of 2
buffer << std::setw(2) << std::setfill('0') << std::hex;
// for each byte to convert...
for(int i = 0; i < bytes_to_convert; ++i)
// insert it into our stream followed by a space.
// note that we cast it to an int to make the buffer
// interpret it as a number and not a char,
// and then mask off everything but the byte
// we want to display
buffer << ((int)(somebuffer[i]) & 0xFF) << ' ';

// .str() returns a std::string; do with it what you will
std::cout <<  buffer.str() << std::endl;
}
[/code]
June 23, 2005, 6:59 PM
Spilled[DW]
Ok, after lookin at your coding i've started to write my ToHex function and heres what ive gotten:
[code]
char* pBuffer::ToHex(char* data)
    {
    int bytes = strlen(data);
    std::stringstream tempbuffer;
    tempbuffer << std::setw(2) << std::setfill('0') << std::hex;
    for(int i = 0; i < bytes; ++i)
    {
            tempbuffer << ((int)(data[i]) & 0xFF) << ' ';
    }
    return tempbuffer;
    }
[/code]

Getting a conversion error at the moment. Help?
June 23, 2005, 8:32 PM
K
The problem is you're trying to convert a std::stringstream to a char*.  If you want to do this, you need to do it like so:
// this would return a const char*
[code]
return tempbuffer.str().c_str();
[/code]

however, this wont work; check the myriad of topics about returning pointers to local data.  I recommend you return a std::string, which you can convert to a const char* at a later time if needed by using the .c_str() member function.

[code]
return tempbuffer.str();
[/code]

One other note: you might want to calculate the length of the string by using the strlen() function, since it will stop at the first null character.  instead you should pass the length of the buffer as a second parameter.
June 23, 2005, 11:31 PM
OnlyMeat
[quote author=Spilled[DW] link=topic=11935.msg117078#msg117078 date=1119558760]
Ok, after lookin at your coding i've started to write my ToHex function and heres what ive gotten:
[code]
char* pBuffer::ToHex(char* data)
    {
    int bytes = strlen(data);
    std::stringstream tempbuffer;
    tempbuffer << std::setw(2) << std::setfill('0') << std::hex;
    for(int i = 0; i < bytes; ++i)
    {
            tempbuffer << ((int)(data[i]) & 0xFF) << ' ';
    }
    return tempbuffer;
    }
[/code]
[/quote]

Returning a pointer to a local std::stringstream is going to cause you problems. You could just return it like this.

[code]
std::string pBuffer::ToHex(char* data)
    {
    int bytes = strlen(data);
    std::stringstream tempbuffer;
    tempbuffer << std::setw(2) << std::setfill('0') << std::hex;
    for(int i = 0; i < bytes; ++i)
    {
            tempbuffer << ((int)(data[i]) & 0xFF) << ' ';
    }
    return tempbuffer.str();
    }
[/code]

That way the return value will just be copied.
June 24, 2005, 12:49 AM
shout
I'm not understanding what you are trying to do here. It looks kind of like you are trying to use a VB way of doing things and converting everything to a string. Correct me if I am wrong.
June 24, 2005, 3:42 AM
Spilled[DW]
[quote author=Shout link=topic=11935.msg117174#msg117174 date=1119584537]
I'm not understanding what you are trying to do here. It looks kind of like you are trying to use a VB way of doing things and converting everything to a string. Correct me if I am wrong.
[/quote]

I'm just looking to make similar functions to those in C++ as i am creating my packet buffer in c++. Help is what i was looking for and thats what i got. On the other hand, im gonna work on this a little more after reading your reply's. I should post a follow up on what i've gotten out of your replys. Thanks everyone.
June 24, 2005, 7:24 AM
shout
I suggest NOT using a char array. Using a single void pointer, the address-of operator, your favorite allocation method, and CopyMemory you could probably produce a decent 2-method packet buffer.

[untested]
[code]
void insert(void *buff, DWORD position, void *data, DWORD length)
{
void *tmp = _alloca(position + length); //my personal favorite
CopyMemory(tmp, buff, position);
CopyMemory(tmp, data, length);
free(buff);
buff = tmp;
}

void get(void *buff, DWORD buff_length, DWORD data_length, void *data)
{
DWORD copylen = buff_length - data_length;
void *tmp = _alloca(copylen);
CopyMemory(tmp, &buff[data_length], copylen);
CopyMemory(data, buff, data_length);
free(buff);
buff = tmp;
}

//insert a dword
DWORD avalue = 0x01337A55;
insert(buffer, buffer_len, &avalue, sizeof(DWORD));

//get a dword
DWORD avalue = 0;
get(buffer, buffer_len, &avalue, sizeof(DWORD));

//insert a string
char hello[] = "I am a null terminated string, bitch";
insert(buffer, buffer_len, hello, strlen(hello));

{...}
[/code]
[/untested]
June 24, 2005, 2:08 PM
Spilled[DW]
[quote author=Shout link=topic=11935.msg117174#msg117174 date=1119584537]
I'm not understanding what you are trying to do here. It looks kind of like you are trying to use a VB way of doing things and converting everything to a string. Correct me if I am wrong.
[/quote]

Your right I am new to C++ and im trying to make a packet buffer in c++ the VB way but i am lost on how to do it in c++. Little more code and explanation or a quick chat on AIM with a little walk threw would be very appreciated. Maybe link me to DM's DynBuffer class so i could study it? Anything at this point would be appreciated. So far this is where im at on my packet buffer:

[code]
#include "pbuffer.h"
#include <string>
#include <windows.h>
#include <iostream>
using namespace std;
/* Buffer Coding */
string buffer;
pBuffer::pBuffer()
{
// code here
}

pBuffer::~pBuffer()
{
// code here
}


void pBuffer::insertntstring(char *data)
     {
     buffer += data;
     buffer += char(0);
     return;
     }

void pBuffer::insertnonntstring(char *data)
     {
     buffer += data;
     return;
     }

double pBuffer::LShift(long lValue, long lShift)
     {           //??????????????????
     double temp;
     temp = double (lValue * (lShift * lShift));
     
     return temp;
     }

double pBuffer::RShift(long lValue, long lShift)
     {
     double temp;
     temp = double (lValue / (lShift * lShift));
     return temp;
     }

char* pBuffer::KillNull(char* data)
{
      int val;
   for(int i = 0; i < strlen(data) + 1; i++)
    {       
        if(data[i] == char(0))
         { 
            val = i;
            i = strlen(data) + 1;
         }
    }

   
     if(val == 0)
         return data;
     else
     {
        char *temp[val];
        for(int i = 0; i < val + 1; i++)
              *temp[i] = data[i];
         return *temp;
     }
}
char pBuffer::GetHexValue(long v)
    {
    v += 0xF;
    if (v < 10)
        return char(v + 0x30);
    else
        return char(v + 0x37);
    }

int pBuffer::GetNumValue(char c)
     {
     int asc;
     asc = int(c);
     if(IsCharAlpha(c) == false)
        return asc - 0x30;
     else
       return asc - 0x37;
     }

void pBuffer::InsertDWORD(void* data)
     {
     char* umm = new char[4];
     CopyMemory(umm, &data, 4);
     buffer += umm;
     }

void pBuffer::InsertWORD(int data)
     {
     buffer += WORD(data);
     }

void pBuffer::InsertBYTE(int data)
     {
     buffer += char(data);
     }


char* pBuffer::ToHex(char* data)
     {
     int ascii;
     char fp, sp;
     char* retArray = new char[strlen(data) * 2];
     for(int i = 0; i < strlen(data) + 1; i++)
     {
      ascii = (int) data[i];
      fp = HexDigit(ascii / 16);
      sp = HexDigit(ascii % 16);
      retArray[i * 2] = fp;
      retArray[i * 2 + 1] = sp;
     }
     retArray[strlen(data) * 2] = char(0);
     return retArray;
     }
[/code]
July 5, 2005, 4:16 PM
K
One thing you might like to know is that C++ has built in left shift/right shift operators.  You don't have to write crappy workaround functions!

[code]
int i = 3;
int f = (i << 3); // f = i left shifted by 3
f >>= 3; // f = f right shifted 3
// etc;
[/code]
July 5, 2005, 6:44 PM
Spilled[DW]
o, i didn't know that. Thanks :) Like i said im still learning but do you have anything to say about my packetbuffer. Any help? i would appreciate it thanks in advance.
July 5, 2005, 7:18 PM
shout
My advice: get rid of the string crap you got going on.  Treat your data as what it is; binary, not textual. I suggust taking a look at the code I posted earlier, you should be able to base as packetbuffer class off that.

Your code:
[code]
void pBuffer::InsertDWORD(void* data)
     {
     char* umm = new char[4];
     CopyMemory(umm, &data, 4);
     buffer += umm;
     }
[/code]

That will not work. The += overload will search for a null terminator, which may or may not exist in your DWORD. AFAIK, the MSCC  makes all the default data in the process 0xCC or 0xCD, so it could be quite a long string you're concating.

Lets say your DWORD is 0x000000CD, which just happens to be the version byte of starcraft. When that is inserted, the number is turned around into 0xCD 0x00 0x00 0x00. It will insert 0xCD, then stop when it reaches the second byte, because it reaches the null terminator. So in the end you only inserted one byte, not the entire DWORD.

Now lets say your DWORD is 0x01010301, or the (old?) version number for starcraft. When that is inserted, the number is turned around into 0x01 0x03 0x01 0x01. Now there is no 0x00, or null terminator, so the data will venture into your programs memory, copying usless and potentially harmful junk data, most definatly alot in the debug versions.

Using strings for buffers is something that only VB programmers do, and it is a BAD idea for any other langauge.

Now lets say you wanted to insert a string into the buffer. What would you do if your buffer is a PVOID or PBYTE?
[code]
void pbuffer::insertstring(LPCSTR string)
{
DWORD length = strlen((char *)string);
for (DWORD i = 0; i < length; i++)
((PBYTE)this->buffer)[this->pos + i] = string[i];
this->pos += length;
}
[/code]

That should be enough to get you started. :D
July 5, 2005, 7:56 PM
Kp
[quote author=Shout link=topic=11935.msg119035#msg119035 date=1120593417]AFAIK, the MSCC  makes all the default data in the process 0xCC or 0xCD, so it could be quite a long string you're concating.[/quote]I think it does this only in Debug build, so if he's already reconfigured for Release, even worse and less predictable things will happen. :)  Or, worse from the theoretical standpoint, it might end up mostly working if the release grade build has a higher probability of having nulls nearby, thus avoiding too serious a memory corruption (in the worst case, doing so little damage that it takes a very long time for the program to finally become unstable).
July 6, 2005, 2:47 AM
shout
You will also want to think about the fact that the C++ API's don't take strings for parameters. (Unless of course it's a string related method) Also, do not worry so much about how to display the data, this should be hidden from the bot user, they will have no idea what it is and will think you are H4X0Ring them.
July 6, 2005, 2:54 AM
Spilled[DW]
After using the code you gave me in the previous replay, im getting an error passing information to my functions.
This is my code for passing into the insert function:

[code]
Buffer.insert(Buffer.buffer, strlen((const char*) Buffer.buffer), 0x0, sizeof(DWORD));
[/code]

and.... here is my buffer class:

[code]

#include "pbuffer.h"
#include <string>
#include <windows.h>
#include <iostream>
#include <malloc.h>
using namespace std;
/* Buffer Coding */
void* buffer;
// class constructor
pBuffer::pBuffer()
{
// code here
}

// class destructor
pBuffer::~pBuffer()
{
// code here
}
void pBuffer::insert(void *buff, DWORD position, void *data, DWORD length)
{
MessageBox(0, "test", "fa", 0);
void *tmp = _alloca(position + length); //my personal favorite
CopyMemory(tmp, buff, position);
CopyMemory(tmp, data, length);
free(buff);
buff = tmp;
}

void pBuffer::get(void *buff, DWORD buff_length, DWORD data_length, void *data)
{
DWORD copylen = buff_length - data_length;
void *tmp = _alloca(copylen);
CopyMemory(tmp, buff, copylen);
CopyMemory(data, buff, data_length);
free(buff);
buff = tmp;
}
[/code]

Any ideas?
July 6, 2005, 5:34 PM
shout
The void *data parameter is a pointer; not a type. What you are doing is passing a pointer to address 0, which is protected memory. To something like that, you need to make a DWORD with a value of 0, then pass the address of the DWORD to the function. Or you could make a method like this:

[code]
void pBuffer::insertDWORD(DWORD n)
{
void *tmp = _alloca(sizeof(n) + bufferlen)
CopyMemory(tmp, buffer, bufferlen);
((LPDWORD)tmp)[(bufferlen / sizeof(n))]  = n;
}
[/code]

Or something like that.

I don't want to hold your hand through your entire packetbuffer making experince. Don't copy & paste my code, try to learn from it. To be honest, I haven't made a packetbuffer in C++ yet, so I don't know how trustworthy my code really is.
July 6, 2005, 6:24 PM

Search