I'm trying to build a float number from a binary file with the following format:
first 4 bytes represents the number of digits on the left side of "."
We'll call that X
Next 4 bytes represents the number of digits on the right side of "."
We'll call that Y
Next byte represents the number's sign : "1" => '-', "0" => "+"
Next X+Y bytes represents the number's digits.
Example:
Data.bin:
4 2 0 2 8 3 9 5 3
The number should be : 2839.53
I've the structure :
typedef struct {
unsigned int digitsBefore;
unsigned int digitsAfter;
char sign;
char *digits;
} Number;
Function used to parse and fill the structure :
Number *fromBinaryToNumber(FILE *file){
int counter = 0, size = 0, i = 0;
size_t bytes_read;
unsigned int firstIndex, secondIndex;
char sign;
char *digits;
Number *nr = calloc(1, sizeof(Number));
// reading digits before
bytes_read = fread(&firstIndex, sizeof(unsigned int), 1, file);
nr->digitsBefore = firstIndex;
printf("Bytes read : %zu\n", bytes_read);
printf("First index %d\n", firstIndex);
size += firstIndex;
// reading digits after
bytes_read = fread(&secondIndex, sizeof(unsigned int), 1, file);
nr->digitsAfter = secondIndex;
printf("Bytes read : %zu\n", bytes_read);
printf("Second index %d\n", secondIndex);
size += secondIndex;
// reading sign
bytes_read = fread(&sign, sizeof(char), 1, file);
nr->sign = sign;
printf("Bytes read : %zu\n", bytes_read);
printf("Sign : %.2X\n", sign);
//reading digits
digits = calloc(size, sizeof(unsigned char));
nr->digits = calloc(size, sizeof(unsigned char));
printf("Digits : \n");
bytes_read = fread(digits, size, 1, file);
for(i = 0 ; i < size; i++){
printf("%.2X ", digits[i]);
}
memcpy(nr->digits, digits, size);
free(digits);
return nr;
}
For the following data in Data.bin (Hexdumped):
04 00 00 00 02 00 00 00 00 02 08 03 09 05 03
I get the output:
Bytes read : 1
First index : 4
Bytes read : 1
Second Index : 2
Bytes read : 1
Sign : 00
Digits :
02 08 03 09 05 03
Function to transform Number strunct in float:
double fromNumbertoDouble(Number *number){
int size = 0;
char *buff;
size = number->digitsAfter + number->digitsBefore + 2;
buff = calloc(size, sizeof(char));
if (!buff) {
fprintf(stderr, "Error calloc in fromNumberToDouble");
exit(1);
}
if (number->sign == '01') {
strcat(buff, "-");
}
strncat(buff, number->digits, number->digitsBefore);
strcat(buff, ".");
strncat(buff, number->digits+number->digitsBefore, number->digitsAfter);
return atof(buff);
}
This always return 0.
When I checked to see what is in the number returned from fromBinaryToNumber, number->digits = "\002\b\003\t\005\003".
I'm aware that atof can't convert something like that into a float.
My question is how can i convert the number->digits into something that would get converted into a float by atof.
Any other idea on how to solve this would also be appreciated.
Thank you for your time.
For each of the digits, add '0', i.e. the codepoint value for the digit 0. This turns the array into a a sequence of digit characters. Of course, it must also be 0-terminated for atof(), which requires a proper string.
You do realize that your format is fantastically awkward, right? A single float would use 4 bytes for the entire number, always. If you're going to convert to float anyway you're not going to be able to keep the arbitrary precision that your format supports.
First your buffer size is wrong - you've not taken into account the decimal point, sign or the zero-terminator. Also you don't initialise buff - so strcat may concatenate anywhere- you should either calloc, or memset the buff to 0 before strcat'ing anything to it.
Related
/***
* Author: Omar IRAQI
*/
#include <stdio.h>
#include <stdlib.h>
#define N 11
int main(void) {
int i, *p, encoded_message[] = {1634558290, 544104804, 1701994827, 539782501, 1918985572,
1970565920, 1953391972, 1226845811, 1936289056, 1870209139, 8565};
char *message;
printf("%s\n", (char*)encoded_message);
/**
* Let's say it again!
*/
message = (char*)malloc(N * sizeof(int));
p = (int*)message;
for (i=0; i < N; i++, p++)
*p = encoded_message[i];
printf("%s\n", message);
return 0;
}
this outputs the message twice:
Ramadan Kareem, dear students. I miss you!
I was wondering what these encoded numbers are since they don't match with ASCII code
Each int should be split into 4 bytes to recover the individual ascii codes. You could simply print each int as hex.
You can also calculate:
1634558290 % 256
(1634558290 >> 8) % 256
(1634558290 >> 16) % 256
and so on.
You have 11 x 4 byte integers for a total of 44 bytes. This corresponds closely to the length of the message.
1 634 558 290 = 0x616D6152
52 : R
61 : a
6D : m
61 : a
Lookup little endian vs big endian for why the bytes are inverted.
I'd like to send a message over a socket that looks like so: "USER anonymous\r\n".
In order to create a formatted string instead of a constant string, I used snprintf(). Unfortunately, it does not seem to copy the newline character \n, but just the carriage return \r.
#define USERNAME_ANONYMOUS "anonymous"
[...]
// Inside a function.
int sz = snprintf(NULL, 0, "USER %s\r\n", USERNAME_ANONYMOUS);
char* username = NULL;
if ((username = calloc(sz + 1, sizeof(char))) == NULL) {
perror("Could not allocate memory");
return;
}
snprintf(username, sz, "USER %s\r\n", USERNAME_ANONYMOUS);
for (int i = 0; i <= sz; i++) {
printf("%c %d\n", username[i], username[i]);
}
The output:
U 85
S 83
E 69
R 82
32
a 97
n 110
o 111
n 110
y 121
m 109
o 111
u 117
s 115
13
0
0
From this snprintf (and family) reference:
At most bufsz - 1 characters are written.
The size you provide must be including the terminator. You need to use sz + 1 to print the full string.
Well, if you allocate a buffer of size sz + 1 then pass that buffer size to the second snprintf call, which is sz + 1 and not sz, which is the number you pass.
The second call to snprintf should read:
snprintf(username, sz + 1, "USER %s\r\n", USERNAME_ANONYMOUS);
or it will overwrite the last \n with the null terminator, because it has not enough space for the whole string you want to print.
void update_memblock(MEMBLOCK *mb)
{
static unsigned char tempbuf[128 * 1024];
SIZE_T bytes_left;
SIZE_T total_read;
SIZE_T bytes_to_read;
SIZE_T bytes_read;
bytes_left = mb->size;
total_read = 0;
while (bytes_left)
{
bytes_to_read = (bytes_left > sizeof(tempbuf)) ?
sizeof(tempbuf) : bytes_left;
ReadProcessMemory(mb->hProc, mb->addr + total_read,
tempbuf, bytes_to_read, &bytes_read);
if (bytes_read != bytes_to_read) break;
memcpy(mb->buffer + total_read, tempbuf, bytes_read);
bytes_left -= bytes_read;
total_read += bytes_read;
}
mb->size = total_read;
}
This is the current code I have, I am initially reading another process' memory using ReadProcessMemory. Now I have the temporary data stored in tempbuf. I am able to output the data from tempbuf in hexadecimal form. But I was planning to display it as shown in the picture, also another complexity I'm facing here is if bytes_left > sizeof(tempbuf) I'm only reading enough data equivalent to the size of tempbuf. How do I read more data as the array I defined can only support as much data?
If I understand correctly, your main question is about how to mimic the output from hex editors.
This can be broken up into 3 parts:
Printing the address
Printing the hex value of each byte
Printing the ASCII value for each byte
Printing an address in hex is easy. We can use %p to print the address of a pointer like this:
char* mem = malloc(99);
printf("%p\n", (void*)mem);
// output: 0xc17080
Next you can print the hex value of a byte using %02x on a char (1 byte). The 02 specifies a zero padded field width of 2. In this case it's just to make 0 print as 00 to make things line up and look pretty.
printf("%02x", mem[0]);
// output: 0A
Lastly, printing ASCII is the easiest of all... almost. We can use %c to print a byte for some ASCII values, but we don't want to print things like \nor \t. To solve this we can limit the use of %c to the character/symbol region of the ASCII table and print . for everything else.
char c = mem[0];
if ( ' ' <= c && c <= '~' ) {
printf("%c", c);
}
else {
printf(".");
}
//output: .
Now we just need to combine these all together. You can decide how many bytes you want to display per line and print "[address] [n hex bytes] [n ascii bytes]" and repeat until you've gone through the entire memory region. I've given a sample function below and you can run it for yourself here.
void display_mem(void* mem, int mem_size, int line_len) {
/*
mem - pointer to beggining of memory region to be printed
mem_size - number of bytes mem points to
line_len - number of bytyes to display per line
*/
unsigned char* data = mem;
int full_lines = mem_size / line_len;
unsigned char* addr = mem;
for (int linno = 0; linno < full_lines; linno++) {
// Print Address
printf("0x%x\t", addr);
// Print Hex
for (int i = 0; i < line_len; i++) {
printf(" %02x", data[linno*line_len + i]);
}
printf("\t");
// Print Ascii
for (int i = 0; i < line_len; i++) {
char c = data[linno*line_len + i];
if ( 32 < c && c < 125) {
printf(" %c", c);
}
else {
printf(" .");
}
}
printf("\n");
// Incremement addr by number of bytes printed
addr += line_len;
}
// Print any remaining bytes that couldn't make a full line
int remaining = mem_size % line_len;
if (remaining > 0) {
// Print Address
printf("0x%x\t", addr);
// Print Hex
for (int i = 0; i < remaining; i++) {
printf(" %02x", data[line_len*full_lines + i]);
}
for (int i = 0; i < line_len - remaining; i++) {
printf(" ");
}
printf("\t");
// Print Hex
for (int i = 0; i < remaining; i++) {
char c = data[line_len*full_lines + i];
if ( 32 < c && c < 125) {
printf(" %c", c);
}
else {
printf(" .");
}
}
printf("\n");
}
}
Sample output:
0x1e79010 74 65 73 74 79 2a 6e t e s t y * n
0x1e79017 0c 3e 24 45 5e 33 27 . > $ E ^ 3 '
0x1e7901e 18 51 09 2d 76 7e 4a . Q . - v . J
0x1e79025 12 53 0f 6e 0b 1a 6d . S . n . . m
0x1e7902c 31 6e 03 2b 01 2f 2c 1 n . + . / ,
0x1e79033 72 59 1c 76 18 38 3c r Y . v . 8 <
0x1e7903a 6e 6b 5b 00 36 64 25 n k [ . 6 d %
0x1e79041 2d 5c 6f 38 30 00 27 - \ o 8 0 . '
0x1e79048 33 12 15 5c 01 18 09 3 . . \ . . .
0x1e7904f 02 40 2d 6c 1a 41 63 . # - l . A c
0x1e79056 2b 72 18 1a 5e 74 12 + r . . ^ t .
0x1e7905d 0d 51 38 33 26 28 6b . Q 8 3 & ( k
0x1e79064 56 20 0b 0b 32 20 67 V . . . 2 . g
0x1e7906b 34 30 68 2e 70 0f 1c 4 0 h . p . .
0x1e79072 04 50 . P
As for the second part of your question, if you cannot increase the size of tempbuf then you are stuck dealing with that amount of memory at any moment in time.
However, if all you want to do is display the memory as described above you can display each section of memory in chunks. You can get a chunk of memory, display it, then get a new chunk, display the new chunk, repeat.
Something along the lines of
while (bytes_left) {
ReadProcessMemory(mb->hProc, mb->addr + total_read, tempbuf, bytes_to_read, &bytes_read);
// Get new chunk
memcpy(mb->buffer + total_read, tempbuf, bytes_read);
// Display chunk
display_mem(tempbuf, bytes_read);
bytes_left -= bytes_read;
}
You will need to do a little more work to check for errors and make everything look nice but hopefully that gives you a good idea of what could be done.
There is no way to store more data than you have space allocated. If you need to store more data, you will need to allocate more space somewhere (more RAM, a disk file, etc). Compression will allow you to store a bit more data in the space allocated, but you aren't going to gain all that much. For virtually unlimited storage, you are going to need to write to disk.
Alternatively, if you just need to display once and then can forget, read in 16 bytes, display the line, and then read the next 16 bytes into the same memory.
Im learning C so i have a little problem.
How to print: unsigned char *tlv_buffer = NULL;
In main function:
unsigned char *tlv_buffer = NULL;
int size = 1;
int len = 0;
int result;
tlv_buffer = BKS_MALLOC(size);
result = append_bertlv_data(&tlv_buffer, &size, &len, 0xDF04, 2,
"\x34\x56");
result = append_bertlv_data(&tlv_buffer, &size, &len, 0xDF81, 3, "ref");
BKS_TRACE("-------- success : %d --------- \n", result);
BKS_TRACE("======== %u =======", &tlv_buffer);
(I cannot see what happens in append_bertlv_data)
It should print df 04 02 34 56 df 81 03 72 65 66 ,
but it does not show like that.
My result is 3204447612
You can use the following:
for (int i = 0 ; i < strlen(tlv_buffer); i++)
printf("%02x ",*(tlv_buffer + i));
It will print each byte in hex.
edit:
use a space to separate and if you want the specific length bytes then specify the length instead of size. best is to use strlen.
I'm trying to construct a string - for every 80 chars in the loop, to add 7 tabs to the beginning of the line, and a new line at the end.
It should print out 7 tabs, then 80 chars, then 1 new line and so on.
However, something strange is happening. It's printing a new line straight after the first 2 chars and then everything is skewed from then on.
I'm also not sure why I need % 40 rather than % 80 - is it because there are 2 bytes?
I think generally im getting confused by 2 bytes.
void do_file(FILE *in, FILE *out, OPTIONS *options)
{
char ch;
int loop = 0;
int sz1,sz2,sz3;
int seeker = offsetof(struct myStruct, contents.datas);
//find total length of file
fseek(in, 0L, SEEK_END);
sz1 = ftell(in);
//find length from beggining to struct beginning and minus that from total length
fseek(in, seeker, SEEK_SET);
sz2 = sz1 - ftell(in);
int tabs = (sz2 / 80) * 8;// Total size / size of chunk * 8 - 7 tabs and 1 new line char
sz3 = ((sz2 + 1 + tabs) * 2); //Total size + nuls + tabs * 2 for 2 bytes
char buffer[sz3];
char *p = buffer;
buffer[0] = '\0';
while (loop < sz2)
{
if(loop % 40 == 0){
//Add 7 tabs to the beginning of each new line
p += sprintf(p, "%s", "\t\t\t\t\t\t\t");
}
fread(&ch, 1, 1, in);
//print hex char
p += sprintf(p, "%02X", (ch & 0x00FF));
if(loop % 40 == 0){
//Add a new line every 80 chars
p += sprintf(p, "%s", "\n");
}
strcat(buffer, p);
loop++;
}
printf("%s", buffer);
}
However, something strange is happening. It's printing a new line straight after the first 2 chars and then everything is skewed from then on.
It's because of the initial value of loop, try with int loop = 1;
I'm also not sure why I need % 40 rather than % 80 - is it because there are 2 bytes?
I think generally im getting confused by 2 bytes.
The point is, for each character you read in input file, you write two characters in buffer, because you decided to print characters as two bytes (%02X).
Now what is your need:
insert LF and tabs each 80 characters of the input file? (Is that your expecting?)
insert LF and tabs each 80 characters of the output? (That is what you coded)