在 lua 中计算字节数组/用户数据的 crc16

标签 c lua wireshark crc16 wireshark-dissector

我正在用 lua 编写 Wireshark 协议(protocol)解析器。它解析的协议(protocol)包含一个 crc16 校验和。解剖者应该检查crc是否正确。

我已经找到了一个用 C 语言编写的 crc16 实现,其中包含 lua 包装器代码 here .我已成功编译并运行它(例如 crc16.compute("test"))。问题是它需要一个字符串作为输入。从 wireshark,我得到一个似乎是 lua 类型 userdata 的缓冲区。所以当我这样做的时候

crc16.compute(buffer(5, 19))

Lua 提示 错误的参数 #1 来计算(需要字符串,得到用户数据)

compute()crc16 implementation看起来像这样:

static int compute(lua_State *L)
{
    const char *data;
    size_t len = 0;
    unsigned short r, crc = 0;

    data = luaL_checklstring(L, 1, &len);

    for ( ; len > 0; len--)
    {
        r = (unsigned short)(crc >> 8);
        crc <<= 8;
        crc ^= crc_table[r ^ *data];
        data ++;
    }

    lua_pushinteger(L, crc);
        return 1;
}

luaL_checklstring 似乎失败了。所以我想我要么需要将输入转换为 lua 字符串,我不确定它是否有效,因为并非我输入的所有字节都是可打印字符。或者我需要调整上面的代码,以便它接受 userdata 类型的输入。我找到了 lua_touserdata(),但这似乎返回了一个指针之类的东西。所以我需要第二个长度参数,对吧?

我不一定需要使用这个实现。任何接受用户数据的 lua crc16 实现都可以完美地解决这个问题。

最佳答案

您从 wireshark 获得的缓冲区可以用作 ByteArray像这样:

byte_array = Buffer(5,19):bytes();

ByteArray 有一个 _toString 函数,可以将字节转换为以十六进制表示的字节的字符串表示形式。所以你可以像这样调用 crc 函数:

crc16.compute(tostring(byte_array))

'Representation of the bytes represented as hex' 表示输入字节的位11111111 将转换为ASCII 字符串FF。 ASCII 字符串 FF 是位 01000110 01000110 或十六进制 46 46。这意味着你在 C 中得到的不是原始字节数组。在计算 crc 之前,您需要将 ascii 表示解码回原始字节,否则我们显然会得到不同的 crc。 首先,此函数将包含一个 ascii 十六进制字符的单个字符 c 转换回它表示的值:

static char ascii2char(char c) {
    c = tolower(c);
    if(c >= '0' && c <= '9')
        return c - '0';
    else if(c >= 'a' && c <= 'f')
        return c - 'a' + 10;
}

现在在计算函数中,我们遍历字符串表示,总是将两个字符组合成一个字节。

int compute(lua_State *L) {
    size_t len;
    const char * str = lua_tolstring(L, 1, &len);
    uint8_t * data = (uint8_t *) malloc(len/2);

    for(int n=0; n<len/2; n++) {
        data[n] = ascii2char(str[2*n]) << 4;
        data[n] |= ascii2char(str[2*n+1]);
    }

    crc16_t crc = crc16_init();
    crc = crc16_update(crc, data, len/2);
    crc = crc16_finalize(crc);

    lua_pushinteger(L, crc);
    free(data);
    return 1;
}

在此示例中,我使用了使用 pycrc 生成的 crc 函数 crc16_initcrc16_updatecrc16_finalize ,而不是问题中链接的 crc 实现。问题是您需要使用与生成 crc 时相同的多项式等。 Pycrc 允许您根据需要生成 crc 函数。 我的数据包也包含一个 crc32。 Pycrc 还可以为 crc32 生成代码,因此它对 crc32 的工作方式完全相同。

关于在 lua 中计算字节数组/用户数据的 crc16,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43211281/

相关文章:

lua - 为什么同一个lua脚本执行结果不一致?

c - 流量的概念是否适用于 tcp 和 udp?

android - 为 armv7 构建 tcc 并在 android 设备上运行它,我应该把头文件放在哪里?

c - 如何解释 C 命令行参数中的特殊字符?

CHOLMOD 稀疏矩阵 cholesky 分解 : incorrect factor?

c - 我的信号处理程序有什么问题?

函数给出奇怪的错误?

lua - 在 Lua 中实现延迟执行?

python - 如何在Wireshark中解析protobuf数据包

frame - 校验和位于以太网帧中的 "physically"位置?