C 解析LUKS标头以正确读取整数值字段
我试图通过读取安装了luks卷的设备上的原始数据来解析luks头,遵循这里给出的规范:,特别是第6页,其中的表格显示了驻留在每个位置的数据、它是什么类型的数据以及单个值的这些数据类型的数量 例如,哈希规范字符串位于位置72,包含32个类型字符字节。将其收集到一个数组中并打印结果很简单,但是正如表中有关版本或密钥字节(假定为密钥长度)等数值的详细信息所示,这些值跨越多个整数。该版本有两个无符号短字符,键字节有四个无符号整数表示其值 我对此有些困惑,以及我应该如何解释它以检索正确的值。我编写了一个凌乱的测试脚本来扫描一个用luks加密的U盘,并显示从读取这些字段中检索到的内容C 解析LUKS标头以正确读取整数值字段,c,linux,binary,luks,C,Linux,Binary,Luks,我试图通过读取安装了luks卷的设备上的原始数据来解析luks头,遵循这里给出的规范:,特别是第6页,其中的表格显示了驻留在每个位置的数据、它是什么类型的数据以及单个值的这些数据类型的数量 例如,哈希规范字符串位于位置72,包含32个类型字符字节。将其收集到一个数组中并打印结果很简单,但是正如表中有关版本或密钥字节(假定为密钥长度)等数值的详细信息所示,这些值跨越多个整数。该版本有两个无符号短字符,键字节有四个无符号整数表示其值 我对此有些困惑,以及我应该如何解释它以检索正确的值。我编写了一个凌
256
25953
hash spec:
sha256
key bytes (length):
1073741824
3303950314
1405855026
1284286704
这是非常令人困惑的,因为hash spec字段同样持有一个期望值,只是字符串本身,但是我应该如何解释version或key byte字段呢?这两个看起来都是完全随机的数字,从我可以看出,规范中没有任何东西可以解释这一点。我想这可能是我如何实际编写代码的问题,下面是用于显示这些值的脚本:
#include <stdio.h>
int main() {
unsigned short data[100];
unsigned char data2[100];
unsigned int data3[100];
int i;
FILE *fp;
fp = fopen("/dev/sdd1", "rb");
fseek(fp, 6, SEEK_SET);
if (fp) {
for (i=0; i < 2; i++) {
fread(&data[i], sizeof(short), 1, fp);
}
fseek(fp, 72, SEEK_SET);
for (i=0; i < 32; i++) {
fread(&data2[i], sizeof(char), 1, fp);
}
fseek(fp, 108, SEEK_SET);
for (i=0; i < 4; i++) {
fread(&data3[i], sizeof(int), 1, fp);
}
printf("version:\n");
for (i=0; i < 2; i++) {
printf("%u\n", data[i]);
}
printf("hash spec:\n");
for (i=0; i < 32; i++) {
printf("%c", data2[i]);
}
printf("\n");
printf("key bytes (length):\n");
for(i=0; i < 4; i++) {
printf("%u\n", data3[i]);
}
fclose(fp);
}
else {
printf("error\n");
}
return 0;
}
#包括
int main(){
无符号短数据[100];
无符号字符数据2[100];
无符号整数数据3[100];
int i;
文件*fp;
fp=fopen(“/dev/sdd1”,“rb”);
fseek(fp,6,SEEK_SET);
if(fp){
对于(i=0;i<2;i++){
fread(和数据[i],sizeof(短),1,fp);
}
fseek(fp,72,SEEK_SET);
对于(i=0;i<32;i++){
fread(&data2[i],sizeof(char),1,fp);
}
fseek(fp,108,SEEK_SET);
对于(i=0;i<4;i++){
fread(&data3[i],sizeof(int),1,fp);
}
printf(“版本:\n”);
对于(i=0;i<2;i++){
printf(“%u\n”,数据[i]);
}
printf(“哈希规范:\n”);
对于(i=0;i<32;i++){
printf(“%c”,数据2[i]);
}
printf(“\n”);
printf(“密钥字节(长度):\n”);
对于(i=0;i<4;i++){
printf(“%u\n”,data3[i]);
}
fclose(fp);
}
否则{
printf(“错误\n”);
}
返回0;
}
任何帮助都将不胜感激,谢谢 问题是,您读取的数据是大端,但您运行的计算机是小端。例如,打印为1073741824的字节按顺序为0x00、0x00、0x00和0x40。作为一个大端数字,它是0x00000040,或64。作为一个小的endian数,通常在x86系统上使用,它是0x40000000,一个长得离谱的长度 幸运的是,有些函数可以为您转换这些值。要将32位big-endian(n网络字节顺序)转换为系统的(host字节顺序)格式,请使用
ntohl
,对于16位整数,请使用ntohs
因此,当您读取16位整数的数据时,它将如下所示:
for (i=0; i < 2; i++) {
fread(&data[i], sizeof(short), 1, fp);
data[i] = ntohs(data[i]);
}
(i=0;i<2;i++)的{
fread(和数据[i],sizeof(短),1,fp);
数据[i]=NTOH(数据[i]);
}
作为旁注,如果您要使用固定大小的值,那么如果您使用#包含,然后使用类型uint8\u t
、uint16\u t
和uint32\u t
,则更便于携带和理解。由于内置类型在不同平台之间可能有所不同,因此它们的大小总是合适的
如果您有兴趣阅读更多有关endianness的内容,.啊,这很有效,谢谢。版本变为1,后跟24933,键字节变为256、25953、0、0。大概只有这些值中的第一个才是相关的-如果第一个值似乎很重要,你知道为什么仍然会有多个整数分配给这些值吗?如果第一个值工作正常,你应该得到1作为第一个值。但问题是我认为你没有正确阅读规范;当它说版本的长度是2时,这意味着2个字节(1uint16\u t
),而不是2uint16\u t
s。您正在读取密码名称作为下一个整数。