C program Reading Hex values from Fat MBR - c

I am new to the C language and am trying to create a forensic tool. So far i have this. It reads a dd file which is a dump of a fat16 MBR. I am able to read certain bytes properly but not some.
What i need help with is the SizeOfFat variable needs to get the values of byte 0x16 and 0x17 read in little endian. How would i have it read FB00 and then convert it to 00FB and then print the value ?
char buf[64];
int startFat16 = part_entry[0].start_sect,sectorSize = 512,dirEntrySize=32;
fseek(fp, startFat16*512, SEEK_SET);
fread(buf, 1, 64, fp);
int rootDir = *(int*)(buf+0x11);
int sectorPerCluster = *(int*)(buf+0x0D);
int sizeOfFat = *(int*)(buf+0x16);
int fatCopies = *(int*)(buf+0x10);
printf("\n Phase 2 \n no of sectors per cluster : %d \n",(unsigned char)sectorPerCluster);
printf("size of fat : %d \n",(unsigned char)sizeOfFat);
printf("no of Fat copies : %d \n",(unsigned char)fatCopies);
printf("maximum number of root directories : %d \n",(unsigned char)rootDir);
The hex values im working with here are -
EB 3C 90 4D 53 44 4F 53 35 2E 30 00 02 08 02 00
02 00 02 00 00 F8 FB 00 3F 00 FF 00 3F 00 00 00
E1 D7 07 00 80 00 29 CD 31 52 F4 4E 4F 20 4E 41

With int, you only got the guarantee that it can hold 32-bit signed integers. With your code, you read sizeof(int) bytes for every of your variables, even though they differ in size. There are uint16_t, uint8_t, uint32_t types on most systems. Use those for fixed-width data. Note also that they are unsigned. You don't want negative sectors per cluster, do you?

Related

How to print data in a buffer irrespective of zeros in between till the given length

I wrote a simple program to read a packet till layer 3 and print the same in hex format.
I gave input in hex format. My output should be same as this.
Input:
45 00 00 44 ad 0b 00 00 40 11 72 72 ac 14 02 fd ac 14
00 06 e5 87 00 35 00 30 5b 6d ab c9 01 00 00 01
00 00 00 00 00 00 09 6d 63 63 6c 65 6c 6c 61 6e
02 63 73 05 6d 69 61 6d 69 03 65 64 75 00 00 01
00 01
I am able to read the packet. Here the hex dump in gdb
(gdb) p packet
$1 = 0x603240 "E"
(gdb) x/32x 0x603240
0x603240: 0x00440045 0x00000000 0x00400b0e 0x00000000
0x603250: 0x00603010 0x0035e587 0xe3200030 0x63206261
0x603260: 0x31302039 0x20303020 0x30203030 0x30302031
0x603270: 0x20303020 0x30203030 0x30302030 0x20303020
0x603280: 0x36203930 0x33362064 0x20333620 0x36206336
0x603290: 0x63362035 0x20633620 0x36203136 0x32302065
0x6032a0: 0x20333620 0x30203337 0x64362035 0x20393620
0x6032b0: 0x36203136 0x39362064 0x20333020 0x36203536
But when I tried to print the packet in console using %s I can't see the total packet because of zeros in between. But I wanted to print it till length of the packet(I am taking it as input to print function).
output on console is:
packet: E
My print function is something like this.
void print(char *packet, int len) {
printf("packet: ");
printf("%s\n\n" , packet );
}
Can you tell me any other way to print the packet till the len(input to print function).
PS: Reading l3 information I didn,t complete. So in gdb of packet l3 information vary form my input.
A string in C is defined as a sequence of characters ending with '\0' (a 0-byte), and the %s conversion specifier of printf() is for strings. So the solution to your problem is doing something else for printing the binary bytes. If you want for example to print their hexadecimal values, you could change your print function like this:
void print(unsigned char *packet, size_t len)
{
for (size_t i = 0; i < len; ++i) printf("%02hhx ", packet[i]);
puts("");
}
Note I also changed the types here:
char can be signed. If you want to handle raw bytes, it's better to always use unsigned char.
int might be too small for a size, always use size_t which is guaranteed to hold any size possible on your platform.
If you really want to print encoded characters (which is unlikely with binary data), you can use %c in printf(), or use the putchar() function, or fwrite() the whole chunk to stdout.

fwrite in binary mode of ints not writing proper number of bytes

I am not able to understand the fread fwrite behavior of the following code snippet, exemplified by the code is straightforward:
#include <stdio.h>
int main(void)
{
FILE *fp;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int temp[100] = {0};
int i;
fp = fopen("testdata.bin","wb");
if( fp!= NULL ) {
fwrite( arr,sizeof(int), 10, fp);
fclose(fp);
}
fp = fopen("testdata.bin","rb");
if( fp!= NULL ) {
fread( temp,sizeof(int), 10, fp);
fclose(fp);
}
for(i=0;i<100;i++)
printf("%#x,",temp[i]);
printf("\b \n");
return 0;
}
The output on stdout is:
0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
which makes sense. However, when I open the testdata.bin file, I see only two bytes for value (int) where I expect 4 bytes as size of int is 4 on my machine.
Here is the content of testdata.bin:
0x00000001: 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00
0x00000010: 09 00 0a 00
I would have expected
0x00000001: 01 00 00 00 02 00 00 00 03 00 00 00 ...
Any ideas?
I think fwrite is working fine. Change the declaration of temp so the type is an array of one-byte unsigned characters:
unsigned char temp [100] = {0} ;
The current version of the code displays a four-byte integer each time in the print statement. This will confirm that the contents of the file are as you expect. On my machine:
0x1,0,0,0,0x2,0,0,0,0x3,0,0,0,0x4,0,0,0,0x5,0,0,0,0x6,0,0,0,0x7,0,0,0,0x8,0,0,0,0x9,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

What is the difference between these two C functions in terms of handling memory?

typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]); //line:data:show_bytes_printf
printf("\n");
}
void show_integer(int* p,size_t len){
size_t i;
for(i=0;i<len;i++){
printf(" %d",p[i]);
}
printf("\n");
}
Suppose I have two functions above, and I use main function to test my functions:
int main(int argc, char *argv[])
{
int a[5]={12345,123,23,45,1};
show_bytes((byte_pointer)a,sizeof(a));
show_integer(a,5);
}
I got the following results in my terminal:
ubuntu#ubuntu:~/OS_project$ ./show_bytes
39 30 00 00 7b 00 00 00 17 00 00 00 2d 00 00 00 01 00 00 00
12345 123 23 45 1
Can someone tell me why I got the result? I understand the second function, but I have no idea why I got 39 30 00 00 7b 00 00 00 17 00 00 00 2d 00 00 00 01 00 00 00 for the first function. Actually I know the number sequence above are hexadecimal decimal for 12345, 123, 23, 45, 1. However, I have no idea: start[i] pointer doesn't point to the whole number such as 12345 or 123 in the first function. Instead, the start[0] just point to the least significant digit for the first number 12345? Can someone help me explain why these two functions are different?
12345 is 0x3039 in hex. because int is 32bits on your machine it will be represented as 0x00003039. then because your machine is little endian it will be represented as 0x39300000. you can read more about Big and Little endian on: https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html
the same applies for other results.
On your platform, sizeof(int) is 4 and your platform uses little endian system. The binary representation of 12345 using a 32-bit representation is:
00000000 00000000 00110000 00111001
In a little endian system, that is captured using the following byte sequence.
00111001 00110000 00000000 00000000
In hex, those bytes are:
39 30 00 00
That's what you are seeing as the output corresponding to the first number.
You can do similar processing of the other numbers in the array to understand the output corresponding to them.

Simple AES encryption decryption with openssl library in C

I want to encrypt a struct containing few String and then decrypt it. I tried following code. The original code is found from the web and it was working perfectly. I change the input of it to a struct. following is the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
typedef struct ticket { /* test field */
int ticketId;
char username[20];
char date[20];
} USR_TICKET;
// a simple hex-print routine. could be modified to print 16 bytes-per-line
static void hex_print(const void* pv, size_t len)
{
const unsigned char * p = (const unsigned char*)pv;
if (NULL == pv)
printf("NULL");
else
{
size_t i = 0;
for (; i<len;++i)
printf("%02X ", *p++);
}
printf("\n");
}
// main entrypoint
int main(int argc, char **argv)
{
int keylength;
printf("Give a key length [only 128 or 192 or 256!]:\n");
scanf("%d", &keylength);
/* generate a key with a given length */
unsigned char aes_key[keylength/8];
memset(aes_key, 0, keylength/8);
if (!RAND_bytes(aes_key, keylength/8))
exit(-1);
/* input struct creation */
size_t inputslength = sizeof(USR_TICKET);
USR_TICKET ticket;
ticket.ticketId = 1;
time_t now = time(NULL);
strftime(ticket.date, 20, "%Y-%m-%d", localtime(&now));
strcpy(ticket.username, "ravinda");
printf("Username - %s\n", ticket.username);
printf("Ticket Id - %d\n", ticket.ticketId);
printf("Date - %s\n", ticket.date);
/* init vector */
unsigned char iv_enc[AES_BLOCK_SIZE], iv_dec[AES_BLOCK_SIZE];
RAND_bytes(iv_enc, AES_BLOCK_SIZE);
memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
// buffers for encryption and decryption
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_out[encslength];
unsigned char dec_out[inputslength];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt((unsigned char *)&ticket, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
printf("original:\t");
hex_print((unsigned char *)&ticket, inputslength);
printf("encrypt:\t");
hex_print(enc_out, sizeof(enc_out));
printf("decrypt:\t");
hex_print(dec_out, sizeof(dec_out));
USR_TICKET * dyc = (USR_TICKET *)dec_out;
printf("Username - %s\n", dyc->username);
printf("Ticket Id - %d\n", dyc->ticketId);
printf("Date - %s\n", dyc->date);
return 0;
}
The problem is only first two members of the struct is decrypting correctly. After that data get currupted. What am I doing wrong here?
I would almost go so far as to say this is a problem with OpenSSL. It seems that when the length parameter passed to AES_cbc_encrypt is > AES_BLOCK_SIZE but not an integral multiple thereof (i.e. length mod AES_BLOCK_SIZE != 0), then the last block is encrypted using the initial IV and not the previous block of ciphertext as should be the case for CBC mode.
You can fix this in one of two ways:
Copy your struct to a buffer whose size is an integral multiple of AES_BLOCK_SIZE, or encrypt in two parts - the full blocks, followed by a single partial block. The latter has the advantage of avoiding additional memory usage and can be done as follows:
size_t fullBlocks = inputslength - (inputslength % AES_BLOCK_SIZE);
size_t remainingBlock = inputslength - fullBlocks;
AES_cbc_encrypt((unsigned char *)&ticket, enc_out, fullBlocks, &enc_key, iv_enc, AES_ENCRYPT);
AES_cbc_encrypt((unsigned char *)&ticket + fullBlocks, enc_out + fullBlocks, remainingBlock, &enc_key, iv_enc, AES_ENCRYPT);
You should then be able to decrypt as you currently are without issue. It's worth noting however that you should declare dec_out as the same size as enc_out, because you're currently overrunning the dec_out buffer when decrypting.
Edit:
I raised this as a bug in OpenSSL: https://rt.openssl.org/Ticket/Display.html?id=3182&user=guest&pass=guest and whilst there is some argument over whether this is actually a bug, or just (undocumented) undefined behavior, the general consensus is that the EVP routines should be used instead, rather than these low-level functions.
The problem might be in the struct you are using, basically because of the struct padding and member sizes. Try to serialize your input and it must work. in a simple way, try to allocate one char buffer and copy your struct contents to the buffer one by one and try to encrypt that buffer and while decrypting also follow the same method. Post here what you are observing after that. We must be able to comment better on that.
The original code has done the padding for you. The problem is that you passed the wrong plaintext length to AES function. You should pass encslength(padded length) to AES_cbc_encrypt. Just change this line
AES_cbc_encrypt((unsigned char *)&ticket, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
to
AES_cbc_encrypt((unsigned char *)&ticket, enc_out, encslength, &enc_key, iv_enc, AES_ENCRYPT);
This should solve your problem.
At least I also think it is not a good practise to use struct and sizeof(a_struct_type) here.
The actual binary sequence of the struct USR_TICKET and the result of sizeof will vary according to different padding and byte alignment implementation.
Here is the test result.
1) Firstly, I download the latest openssl1.0.2c and build it, and test the code here with this library on OS X 10.10.3, the code works fine.
2) And I tried to run the test for 5 times. Each time, even the original plain text will changed due to padding of struct(on my OS, the last 4 bytes will be changed every time).
3) So,the same input to the struct produced different plain text, which finally produced different cipher text. The user might be confused by the different cipher text output, when they try to encrypt the same input info(here raving, 1, 2015-6-25) with the same key and iv.
4) Furthermore, just change the struct internal definition, which will produce the same concern in description (3).
typedef struct ticket { /* test field */
int ticketId;
char username[19]; // here try to change from 20 to 19
char date[20]; // here try to change from 20 to other size
} USR_TICKET;
PS. Some outputs result from above description(2),
Output1:
Give a key length [only 128 or 192 or 256!]:
128
Username - ravinda
Ticket Id - 1
Date - 2015-06-25
original: 01 00 00 00 72 61 76 69 6E 64 61 00 00 00 00 00 00 00 00 00 00 00 00 00 32 30 31 35 2D 30 36 2D 32 35 00 00 00 00 00 00 58 BB 3A 50
encrypt: BA 32 86 CC 71 55 2F 73 ED A1 C9 DE 00 32 1A 20 D9 A5 16 52 8A CD F0 F7 38 04 76 38 5A 47 35 3B A3 07 97 41 C4 C2 05 53 74 93 91 26 7E DE 40 47
decrypt: 01 00 00 00 72 61 76 69 6E 64 61 00 00 00 00 00 00 00 00 00 00 00 00 00 32 30 31 35 2D 30 36 2D 32 35 00 00 00 00 00 00 58 BB 3A 50
Username - ravinda
Ticket Id - 1
Date - 2015-06-25
Output2:
Give a key length [only 128 or 192 or 256!]:
128
Username - ravinda
Ticket Id - 1
Date - 2015-06-25
original: 01 00 00 00 72 61 76 69 6E 64 61 00 00 00 00 00 00 00 00 00 00 00 00 00 32 30 31 35 2D 30 36 2D 32 35 00 00 00 00 00 00 58 0B 10 5A
encrypt: BE 60 0F FC 17 A3 42 4A 95 7C 39 DB BF 2C BA 59 42 DC 0C AD B2 20 76 6A 04 E3 DE 11 3E D0 AF 88 A5 B9 D2 25 D4 AE F0 B7 82 9F 13 39 80 39 61 9D
decrypt: 01 00 00 00 72 61 76 69 6E 64 61 00 00 00 00 00 00 00 00 00 00 00 00 00 32 30 31 35 2D 30 36 2D 32 35 00 00 00 00 00 00 58 0B 10 5A
Username - ravinda
Ticket Id - 1
Date - 2015-06-25

What is the exact usage of shift operator in C

I thought shift operator shifts the memory of the integer or the char on which it is applied but the output of the following code came a surprise to me.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
uint64_t number = 33550336;
unsigned char *p = (unsigned char *)&number;
size_t i;
for (i=0; i < sizeof number; ++i)
printf("%02x ", p[i]);
printf("\n");
//shift operation
number = number<<4;
p = (unsigned char *)&number;
for (i=0; i < sizeof number; ++i)
printf("%02x ", p[i]);
printf("\n");
return 0;
}
The system on which it ran is little endian and produced the following output:
00 f0 ff 01 00 00 00 00
00 00 ff 1f 00 00 00 00
Can somebody provide some reference to the detailed working of the shift operators?
I think you've answered your own question. The machine is little endian, which means the bytes are stored in memory with the least significant byte to the left. So your memory represents:
00 f0 ff 01 00 00 00 00 => 0x0000000001fff000
00 00 ff 1f 00 00 00 00 => 0x000000001fff0000
As you can see, the second is the same as the first value, shifted left by 4 bits.
Everything is right:
(1 * (256^3)) + (0xff * (256^2)) + (0xf0 * 256) = 33 550 336
(0x1f * (256^3)) + (0xff * (256^2)) = 536 805 376
33 550 336 * (2^4) = 536 805 376
Shifting left by 4 bits is the same as multiplying by 2^4.
I think you printf confuses you. Here are the values:
33550336 = 0x01FFF000
33550336 << 4 = 0x1FFF0000
Can you read you output now?
It doesn't shift the memory, but the bits. So you have the number:
00 00 00 00 01 FF F0 00
After shifting this number 4 bits (one hexadecimal digit) to the left you have:
00 00 00 00 1F FF 00 00
Which is exactly the output you get, when transformed to little endian.
Your loop is printing bytes in the order they are stored in memory, and the output would be different on a big-endian machine. If you want to print the value in hex just use %016llx. Then you'll see what you expect:
0000000001fff000
000000001fff0000
The second value is left-shifted by 4.

Resources