Parsing LUKS Headers to Read Integer Value Fields Correctly - c

I'm trying to parse a luks header by reading the raw data off a device with a luks volume installed to it, following the specification given here: https://gitlab.com/cryptsetup/cryptsetup/wikis/LUKS-standard/on-disk-format.pdf, specifically page 6 with the table showing the data that resides at each location, what type of data it is and for how many of those data types there are for a single value.
For instance, the hash-spec string resides at location 72 and contains 32 type char bytes. Collecting this into an array and printing the result is simple, however as detailed in the table for numerical values such as the version or the key-bytes (which is supposedly the length of the key), these values span over multiple integers. The version has two unsigned shorts and the key-bytes has four unsigned ints to represent their values.
I'm somewhat confused by this, and how I should go about interpreting it to retrieve the correct value. I wrote a messy test script to scan through a usb stick encrypted with luks and display what's retrieved from reading these fields.
256
25953
hash spec:
sha256
key bytes (length):
1073741824
3303950314
1405855026
1284286704
This is very confusing, as again the hash spec field holds an expected value, just the string of characters themselves, but how am I supposed to interpreter either the version or key-byte fields? These both seem like completely random numbers, and from what I can tell there isn't anything in the spec that explains this. I figured then this might be a problem with how I'm actually writing the code to do this, below is the script used to display these values:
#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;
}
Any help would be appreciated, thanks.

The problem is the data you're reading is big-endian, but the computer you're running on is little-endian. For example, the bytes you're printing out as 1073741824 are 0x00, 0x00, 0x00, and 0x40, in that order. As a big-endian number, that's 0x00000040, or 64. As a little-endian number, as is usually used on x86 systems, that's 0x40000000, an absurdly long length.
Fortunately, there are functions that can convert these values for you. To convert from a 32-bit big-endian (network byte order) to your system's (host byte order) format, use ntohl, and for a 16-bit integer, use ntohs.
So when you read the data for the 16-bit integers, it would look like this:
for (i=0; i < 2; i++) {
fread(&data[i], sizeof(short), 1, fp);
data[i] = ntohs(data[i]);
}
As a side note, if you're going to be working with values of fixed sizes, it's a little more portable and easier to understand if you do #include <stdint.h> and then use the types uint8_t, uint16_t, and uint32_t. These will always be the right size, since the built-in types can vary between platforms.
If you're interested in reading more about endianness, Wikipedia has an article on it.

Related

How to get customized bytes from /dev/urandom?

I am working on a program that finds partial collision in Bitcoin addresses.
I have obtained source code for urandom and don't see where to start.
So I want to get random bytes from /dev/urandom of length 32 in total (including the masking 0s) because my program expects 256 bit but masked with zeros at the beginning when converted to hex.
The hex output would be like this
000000000000000000000000000000000000000000000000000000000000002d4
Notice the 0s before the actual Hex value( that's what I am calling a mask), in python it is needed by many libraries to get Bitcoin address.
I am struggling with the following code (not from random.c), now I think modifying urandom itself could be more helpful.
static bool init_rand(void *data, size_t size)
{
FILE *stream = fopen("/dev/urandom", "r");
if (stream == NULL)
return false;
bool ok = (fread(data, sizeof(uint8_t), size, stream) == size);
fclose(stream);
return ok;
}
static bool init_rand(void *data, size_t size)
{
size_t size0 = size / sizeof(unsigned) + 1;
assert(size0 * sizeof(unsigned) >= size);
unsigned data0[size0];
for (size_t i = 0; i < size0; i++)
{
int err = rand_s(data0 + i);
if (err != 0)
return false;
}
memcpy(data, data0, size);
return true;
}
static struct seed *make_seed(void)
{
struct seed *seed = (struct seed *)malloc(sizeof(struct seed));
assert(seed != NULL);
seed->counter = 0;
if (!init_rand(seed, sizeof(struct seed)))
{
fprintf(stderr, "error: failed to init random seed\n");
exit(EXIT_FAILURE);
}
if (seed->counter == 0) // Sanity check...
{
fprintf(stderr, "error: random seed initialization failed\n");
exit(EXIT_FAILURE);
}
return seed;
}
For Full code please see Pairgen Here.
Is it possible to modify random.c from Linux kernel drivers to produce bytes already masked with 0s?
You are confusing printed representation ("the hex output") with an actual value.
0x2d4 and 0x000000000000000000000000000000000000000000000000000000000000002d4 are the exact same value.
"0x2d4" and "0x000000000000000000000000000000000000000000000000000000000000002d4" are two very different strings.
If you want to format a string - use formating operations (like sprintf).
Looking at your comments, it appears that you're misunderstanding the concept of 0 and what "hex" means.
Hex stands for Hexadecimal, meaning the interpretation of the value in the base-16 system. It is used to represent the value (for readability), it doesn't affect the value itself. For example, 0xA is the base-16 representation of the decimal value 10. These are the same value, written differently.
Similarly, leading zeroes don't change the value. If you see 0x24b in your debugger, and the variable holding it is 32 bits, then the actual memory representation would be 0x0000024b. You can control how the value is printed using the printf formatting flags.
Last but not least, 0 is a valid value. Every bit can be either 0 or 1, and you can have a random generator provide you an absolutely valid randomly generated value which is 0 for all the 256 bits you asked for. While highly unlikely, it is not impossible. Much more likely is that some of the 256 bits would be 0, and it is entirely possible that some of them would be the highest bits, leading your 256 bit value to be misinterpreted as less than 256 bits if you discard these high bits (as printf does by default).
When used for cryptographic purposes, you should not manipulate the values you read from urandom as this would most likely introduce vulnerabilities and is probably not what you really want to do.

Another invert char array in C

That code will run on a payment device (POS). I have to use legacy C (not C# or C++) for that purpose.
I am trying to prepare a simple Mifare card read/write software data. Below document is my reference and I am trying to achieve what is on page 9, 8.6.2.1 Value blocks explains.
http://www.nxp.com/documents/data_sheet/MF1S50YYX_V1.pdf
I just know very basics of C. All my searches in The Internet have failed. According to document:
1- There is integer variable with value of 1234567.
2- There is char array[4] which should have hex of above value which is 0x0012D687
3- I am supposed to invert that char array[4] and reach value of 0xFFED2978
I need to do some other things but I have stuck in number 3 above. What I have tried lastly is
int value = 1234567;
char valuebuffer[4];
char invertbuffer[4];
sprintf(valuebuffer, "%04x", value);
for(i = 0; i < sizeof(valuebuffer); i++ )
{
invertbuffer[i] ^= valuebuffer[i];
}
When I print, I read some other value in invertbuffer and not 0xFFED2978
Seems like you're making it more complicated than it needs to be. You can do the binary inversion on the int variable rather than messing around with individual bytes.
int value = 1234567;
int inverted= ~ value;
printf("%x\n",value);
printf("%x\n",inverted);
gives you output of
12d687
ffed2978
First of all, you must use the types from stdint.h and not char, because the latter has implementation-defined signedness and is therefore overall unsuitable for holding raw binary data.
With that sorted, you can use a union for maximum flexibility:
#include <stdint.h>
#include <stdio.h>
typedef union
{
uint32_t u32;
uint8_t u8 [4];
} uint32_union_t;
int main (void)
{
uint32_union_t x;
x.u32 = 1234567;
for(size_t i=0; i<4; i++)
{
printf("%X ", x.u8[i]);
}
printf("\n");
x.u32 = ~x.u32;
for(size_t i=0; i<4; i++)
{
printf("%X ", x.u8[i]);
}
printf("\n");
}
Notably, the access order of the u8 is endianess dependent. This might be handy when dealing with something like RFID, which doesn't necessarily have the same network endianess as your MCU.

Swapping bytes of unsigned short integer

I have a partially working function which involves writing to a file.
I have an array, arr, of type unsigned short int and each element must be written to a file in binary format.
My inital solution was:
for(i = 0; i < ROWS; i++) {
fwrite(&arr[i], 1, sizeof(unsigned short int), source);
}
The code above works when writing unsigned short ints to the file. Also, source is a pointer to the file which is being written to in binary format. However, I need to swap the bytes, and am having trouble doing so. Essentially, what is written to the file as abcd should be cdab.
My attempt:
unsigned short int toWrite;
unsigned short int swapped;
for(i = 0; i < ROWS; i++) {
toWrite = &arr[i];
swapped = (toWrite >> 8) | (toWrite << 8);
fwrite(swapped, 1, sizeof(unsigned short int), source);
}
However I get a segmentation fault core dump as a result. I read and used the upvoted answer to this question - convert big endian to little endian in C [without using provided func] - but it doesnt seem to be working. Any suggestions? Thanks!
your attempt is very wrong (and the answers you copied from are okay, the problem isn't in the swapping itself)
First you're taking the address of the value to swap, then you're passing the value instead of the address to write. It should be:
unsigned short int toWrite;
unsigned short int swapped;
for(i = 0; i < ROWS; i++){
toWrite = arr[i];
swapped = (toWrite >>8) | (toWrite <<8); // that part is OK
fwrite(&swapped, 1 , sizeof(unsigned short int) , source);
}
I'm positive that the compiler warned you for this. Warnings are useful.
Welcome to the world of non portable binary formats.
Swapping the numbers is a hack that is error prone because it makes the program non portable: whether to swap the values or not depends on the endianness of the system where you compile and run the program. Your program has a very simple bug: you pass the value of swapped instead of its address. You can fix it with:
fwrite(&swapped, sizeof(swapped), 1, source);
Yet a better solution for your problem is to handle endianness explicitly in your program. This is a portable solution to write the numbers in big endian order:
/* writing 16 bit unsigned integers in big endian order */
for (i = 0; i < ROWS; i++) {
putc(arr[i] >> 8, source);
putc(arr[i] & 255, source);
}
This is the alternative version if you are expected to write in little endian order:
/* writing 16 bit unsigned integers in little endian order */
for (i = 0; i < ROWS; i++) {
putc(arr[i] & 255, source);
putc(arr[i] >> 8, source);
}
Note that it is somewhat confusing to name the stream variable for an output file source.

Understanding And Getting info of Bitmap in C

I am having a hard time understanding and parsing the info data present in a bitmap image. To better understand I read the following tutorial, Raster Data.
Now, The code present there is as follows, (Greyscale 8bit color value)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*-------STRUCTURES---------*/
typedef struct {int rows; int cols; unsigned char* data;} sImage;
/*-------PROTOTYPES---------*/
long getImageInfo(FILE*, long, int);
int main(int argc, char* argv[])
{
FILE *bmpInput, *rasterOutput;
sImage originalImage;
unsigned char someChar;
unsigned char* pChar;
int nColors; /* BMP number of colors */
long fileSize; /* BMP file size */
int vectorSize; /* BMP vector size */
int r, c; /* r = rows, c = cols */
/* initialize pointer */
someChar = '0';
pChar = &someChar;
if(argc < 2)
{
printf("Usage: %s bmpInput.bmp\n", argv[0]);
//end the execution
exit(0);
}
printf("Reading filename %s\n", argv[1]);
/*--------READ INPUT FILE------------*/
bmpInput = fopen(argv[1], "rb");
//fseek(bmpInput, 0L, SEEK_END);
/*--------DECLARE OUTPUT TEXT FILE--------*/
rasterOutput = fopen("data.txt", "w");
/*--------GET BMP DATA---------------*/
originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
fileSize = getImageInfo(bmpInput, 2, 4);
nColors = getImageInfo(bmpInput, 46, 4);
vectorSize = fileSize - (14 + 40 + 4*nColors);
/*-------PRINT DATA TO SCREEN-------------*/
printf("Width: %d\n", originalImage.cols);
printf("Height: %d\n", originalImage.rows);
printf("File size: %ld\n", fileSize);
printf("# Colors: %d\n", nColors);
printf("Vector size: %d\n", vectorSize);
/*----START AT BEGINNING OF RASTER DATA-----*/
fseek(bmpInput, (54 + 4*nColors), SEEK_SET);
/*----------READ RASTER DATA----------*/
for(r=0; r<=originalImage.rows - 1; r++)
{
for(c=0; c<=originalImage.cols - 1; c++)
{
/*-----read data and print in (row,column) form----*/
fread(pChar, sizeof(char), 1, bmpInput);
fprintf(rasterOutput, "(%d, %d) = %d\n", r, c, *pChar);
}
}
fclose(bmpInput);
fclose(rasterOutput);
}
/*----------GET IMAGE INFO SUBPROGRAM--------------*/
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char *ptrC;
long value = 0L;
unsigned char dummy;
int i;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, offset, SEEK_SET);
for(i=1; i<=numberOfChars; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
/* calculate value based on adding bytes */
value = (long)(value + (*ptrC)*(pow(256, (i-1))));
}
return(value);
} /* end of getImageInfo */
What I am not understanding:-
I am unable the understand the 'GET IMAGE INTOSUBPROGRAM' part where the code is trying to get the image infos like no of rows,columns, etc. Why are these infos stored over 4 bytes and what is the use of the value = (long)(value + (*ptrC)*(pow(256, (i-1)))); instruction.
Why there unsigned char dummy ='0' is created and then ptrC =&dummy is assigned?
Why can't we just get the no of rows in an image by just reading 1 byte of data like getting the Greyscale value at a particular row and column.
Why are we using unsigned char to store the byte, isn't there some other data type or int or long we can use effectively here?
Please help me understand these doubts(confusions!!?) I am having and forgive me if they sound noobish.
Thank you.
I would say the tutorial is quite bad in some ways and your problems to understand it are not always due to being a beginner.
I am unable the understand the 'GET IMAGE INTOSUBPROGRAM' part where the code is trying to get the image infos like no of rows,columns, etc. Why are these infos stored over 4 bytes and what is the use of the value = (long)(value + (ptrC)(pow(256, (i-1)))); instruction.
The reason to store over 4 bytes is to allow the image to be sized between 0 and 2^32-1 high and wide. If we used just one byte, we could only have images sized 0..255 and with 2 bytes 0..65535.
The strange value = (long)(value + (*ptrC)*(pow(256, (i-1)))); is something I've never seen before. It's used to convert bytes into a long so that it would work with any endianness. The idea is to use powers of 256 to set the *ptrC to the value, i.e. multiplying first byte with 1, next with 256, next with 65536 etc.
A much more readable way would be to use shifts, e.g. value = value + ((long)(*ptrC) << 8*(i-1));. Or even better would be to read bytes from the highest one to lower and use value = value << 8 + *ptrC;. In my eyes a lot better, but when the bytes come in a different order, is not always so simple.
A simple rewrite to be much easier to understand would be
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char ptrC;
long value = 0L;
int i;
fseek(inputFile, offset, SEEK_SET);
for(i=0; i<numberOfChars; i++) // Start with zero to make the code simpler
{
fread(&ptrC, 1, 1, inputFile); // sizeof(char) is always 1, no need to use it
value = value + ((long)ptrC << 8*i); // Shifts are a lot simpler to look at and understand what's the meaning
}
return value; // Parentheses would make it look like a function
}
Why there unsigned char dummy ='0' is created and then ptrC =&dummy is assigned?
This is also pointless. They could've just used unsigned char ptrC and then used &ptrC instead of ptrC and ptrC instead of *ptrC. This would've also shown that it is just a normal static variable.
Why can't we just get the no of rows in an image by just reading 1 byte of data like getting the Greyscale value at a particular row and column.
What if the image is 3475 rows high? One byte isn't enough. So it needs more bytes. The way of reading is just a bit complicated.
Why are we using unsigned char to store the byte, isn't there some other data type or int or long we can use effectively here?
Unsigned char is exactly one byte long. Why would we use any other type for storing a byte then?
(4) The data of binary files is made up of bytes, which in C are represented by unsigned char. Because that's a long word to type, it is sometimes typedeffed to byte or uchar. A good standard-compliant way to define bytes is to use uint8_t from <stdint.h>.
(3) I'm not quite sure what you're trying to get at, but the first bytes - usually 54, but there are othzer BMF formats - of a BMP file make up the header, which contains information on colour depth, width and height of an image. The bytes after byte 54 store the raw data. I haven't tested yopur code, but there might be an issue with padding, because the data for each row must be padded to make a raw-data size that is divisible by 4.
(2) There isn't really a point in defining an extra pointer here. You could just as well fread(&dummy, ...) directly.
(1) Ugh. This function reads a multi-byte value from the file at position offset in the file. The file is made up of bytes, but several bytes can form other data types. For example, a 4-byte unsigned word is made up of:
uint8_t raw[4];
uint32_t x;
x = raw[0] + raw[1]*256 + raw[2]*256*256 + raw[3]*256*256*256;
on a PC, which uses Little Endian data.
That example also shows where the pow(256, i) comes in. Using the pow function here is not a good idea, because it is meant to be used with floating-point numbers. Even the multiplication by 256 is not very idiomatic. Usually, we construct values by byte shifting, where a multiplication by 2 is a left-shift by 1 and hence a multiplication by 256 is a left-shift by 8. Similarly, the additions above add non-overlapping ranges and are usually represented as a bitwise OR, |:
x = raw[0] | (raw[1]<<8) | (raw[2]<<16) | (raw[3]<<24);
The function accesses the file by re-positioning the file pointer (and leaving it at the new position). That's not very effective. It would be better to read the header as an 54-byte array and accessing the array directly.
The code is old and clumsy. Seeing something like:
for(r=0; r<=originalImage.rows - 1; r++)
is already enough for me not to trust it. I'm sure you can find a better example of reading greyscale images from BMP. You could even write your own and start with the Wikipedia article on the BMP format.

Reading the BGR colors from a bitmap in C

I was trying to obtain the RGB values from a 24-bit BMP file. The image that I am using is a tiny image, all red, so all pixels BGR configuration should be B:0 G:0 R:255. I do this:
int main(int argc, char **argv)
{
principal();
return 0;
}
typedef struct {
unsigned char blue;
unsigned char green;
unsigned char red;
} rgb;
typedef struct {
int ancho, alto;
rgb *pixeles[MAX_COORD][MAX_COORD];
} tBitmapData;
void principal()
{
FILE *fichero;
tBitmapData *bmpdata = (tBitmapData *) malloc(sizeof(tBitmapData));
rgb *pixel;
int i, j, num_bytes;
unsigned char *buffer_imag;
char nombre[] = "imagen.bmp";
fichero = fopen(nombre, "r");
if (fichero == NULL)
puts("No encontrado\n");
else {
fseek(fichero, 18, SEEK_SET);
fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);
printf("Ancho: %d\n", bmpdata->ancho);
fseek(fichero, 22, SEEK_SET);
fread(&(bmpdata->alto), sizeof((bmpdata->alto)), 4, fichero);
printf("Alto: %d\n", bmpdata->alto);
}
num_bytes = (bmpdata->alto * bmpdata->ancho * 3);
fseek(fichero, 54, SEEK_SET);
for (j = 0; j < bmpdata->alto; j++) {
printf("R G B Fila %d\n", j + 1);
for (i = 0; i < bmpdata->ancho; i++) {
pixel =
(rgb *) malloc(sizeof(rgb) * bmpdata->alto *
bmpdata->ancho * 3);
fread(pixel, 1, sizeof(rgb), fichero);
printf("Pixel %d: B: %3d G: %d R: %d \n", i + 1,
pixel->blue, pixel->green, pixel->red);
}
}
fclose(fichero);
}
The problem is that when I print them, the first pixels are fine, B:0 G:0 R:255, but then they start to change to B:0 G:255 R:0, and then to B:255 G:0 R:0. If the width is 10 pixels, then the change happens every 10 pixels.
In the BMP file format, each row of pixel data may be padded in order to round up to a multiple of 4 bytes.
If you have 10 24-bit pixels, that's 30 bytes, which are then followed by 2 bytes of padding. Your code doesn't skip over the padding.
I think your fread(3) calls are wrong:
fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);
This asks to read 4*sizeof((bmpdata->ancho)) bytes into an int. I assume sizeof((bmpdata->ancho)) returns 4, so I think you're scribbling over unrelated memory with these two calls. Change the 4 to 1 -- you're only reading one item.
You never use num_bytes; delete it. Unused code makes thinking about the used code that much more difficult. :)
You're allocating three times as much memory as you need to:
pixel =
(rgb *) malloc(sizeof(rgb) * bmpdata->alto *
bmpdata->ancho * 3);
The 3 looks like an attempt to account for each of red, green, blue, in your rgb structure, but sizeof(rgb) already knows the correct size of the structure. (Which might be 4 bytes, for convenient alignment for 32-bit CPUs, or it might be 12 bytes, again for alignment (each char on its own 4 byte boundary), or maybe even 24 bytes on 64-bit systems that really enjoy working with data aligned on 8 byte boundaries.)
And the final thing I note:
fread(pixel, 1, sizeof(rgb), fichero);
Because the C compiler is allowed to insert holes into structures, you cannot assume that the on-disk format matches your in-memory structure definition. You need to either use the GNU C extension __packed__ attribute or you need to read data from the from using libraries or structures designed for the bmp format. If this is a fun project for you, then definitely try the __packed__ route: if it works, good, if it doesn't work, hopefully you can learn why not, and re-write your code to load each element of the structure manually. If you're just trying to get something that can correctly parse bitmaps, then you might want to try to find some pre-written libraries that already parse images correctly.
(And yes, it is VERY IMPORTANT to get image parsing correct; CVE has a list of malformed image exploits that allow attackers control over programs, many of them are remotely exploitable.)

Resources