如何正确地将std::字符串转换为无符号char[]数组*.我觉得我做错了,有人给我指明了正确的方向



我目前正在反向工程一个网络协议,并编写了一个小型解密协议。

我曾经将数据包的字节定义为一个无符号字符数组,如下所示:

unsigned char buff[] = "x00xFFx0A" etc.

为了不在每个数据包中多次重新编译程序,我制作了一个小型GUI工具,它可以从字符串中获取\xFF表示法中的字节。我这样做的方式如下:

int length = int(stencString.length());
unsigned char *buff = new unsigned char[length+1];
memcpy(buff, stencString.c_str(), length+1);

当我调用函数时,当我使用前面的方法对其进行硬编码时,它会给我一个正确的解密,但当我从字符串到数组进行memcpy时,它给我垃圾,然后是字符串的其余部分。令人毛骨悚然的部分?它们都有相同的打印输出!

以下是我如何使用它:http://pastie.org/private/kndfbaqgvmjiuwlounss9g

以下是kdxalgo.h(c)Luigi Auriemma:http://pastie.org/private/7dzemmwyyqtngiamlxy8tw

有人能给我指正确的方向吗?

谢谢!

看看当您将以下内容用于硬编码版本的buff时会发生什么。

unsigned char buff[] =
"\xd3\x8c\x38\x6b\x82\x4c\xe1\x1e"
"\x6b\x7a\xff\x4c\x9d\x73\xbe\xab"
"\x38\xc7\xc5\xb8\x71\x8f\xd5\xbb"
"\xfa\xb9\xf3\x7a\x43\xdd\x12\x41"
"\x4b\x01\xa2\x59\x74\x60\x1e\xe0"
"\x6d\x68\x26\xfa\x0a\x63\xa3\x88";

我怀疑它将产生与您输入以下内容相同的输出:xd3x8cx38x6bx82x4cxe1x1ex6bx7axffx4cx9dx73xbexabx38xc7xc5xb8x71x8fxd5xbbxfaxb9xf3x7ax43xddx12x41x4bx01xa2x59x74x60x1exe0x6dx68x26xfax0ax63xa3x88

编译器会自动获取"\xd3"并将其转换为预期的底层二进制表示形式。您需要有一种将字符反斜杠、x、d、3转换为相同二进制表示的方法。


如果你确信你会收到正确格式的输入,那么答案并不太难:

unsigned char c2h(char ch)
{
    switch (ch)
    {
        case '0': return  0;
        case '1': return  1;
        case '2': return  2;
        case '3': return  3;
        case '4': return  4;
        case '5': return  5;
        case '6': return  6;
        case '7': return  7;
        case '8': return  8;
        case '9': return  9;
        case 'a': return 10;
        case 'b': return 11;
        case 'c': return 12;
        case 'd': return 13;
        case 'e': return 14;
        case 'f': return 15;
    }
}
std::string handle_hex(const std::string& str)
{
    std::string result;
    for (size_t index = 0; index < str.length(); index += 4) // skip to next hex digit
    {
        // str[index + 0] is '\' and str[index + 1] is 'x'
        unsigned char ch = c2h(str[index+2]) * 16 + c2h(str[index+3]);
        result.append((char)ch);
    }
    return result;
}

再次假设格式完美,因此没有错误处理。我知道这个答案会让我失去一些分数,因为这不是最好的方法,但我想让算法尽可能容易理解。

正如Jeffery所指出的,问题在于编译器处理xd3并生成具有该值的字符,但当您读取字符串xd3时,实际上读取的是4个字符:xd3

您需要读取字符串,然后将其解析为有效内容。对于一种简单的方法,您可以更改格式,使输入是编码为0xd3的空格分隔的字符序列(因为解析起来非常简单):

std::string buffer;
std::string input( "0xd3 0x8c 0x38" ); // this would be read
std::istringstream in( input );
in >> std::hex;
std::copy( std::istream_iterator<int>( in ),
           std::istream_iterator<int>(),
           std::back_inserter( buffer ) );

当然,没有必要改变格式,你可以处理它。为此,你只需要一次读取一个字符。当你遇到一个,然后读取下一个字符,如果是x,那么读取接下来的两个字符(比如ch1ch2),并将它们转换为一个整数值:

int value_of_hex( char ch ) {
   if (ch >= '0' && ch <= '9')
      return ch-'0';
   if (tolower(ch) >= 'a' && tolower(ch) <= 'f')
      return 10 + toupper(ch) - 'a';
   // error
   throw std::runtime_error( "Invalid input" );
}
value = value_of_hex( ch1 )*16 + value_of_hex( ch2 );

最新更新