I have a file that I open which has a bunch of lines with data like this:
0x804ae1c: W 0x0000000c
I'm trying to extract the 3 different strings into 3 different variables but I'm having problems getting values from the 2nd and third token.
Here is how I'm trying to do it:
unsigned long address;
unsigned long address2;
char* readWrite;
fscanf(traceFile, "%lx %s %lx\n", &address, line, &address2)
I get the pointer for the first line. i.e:
804ae1c
but after that the other 2 variables do not get the proper things assigned to them. I tried changing line to a char but to no avail. How should I proceed fixing this issue?
Thanks!
First, you need to allocate storage, rather than just declaring a char*. If you are reading only a single character, a simple char is sufficient.
As BLUEPIXY's comment mentions, you need to account for the extra : character in your string. Here is a test program that shows this (reads from stdin).
#include <stdio.h>
int main(){
unsigned long address;
unsigned long address2;
char readWrite;
int retVal;
retVal = scanf("%lx: %c %lx", &address, &readWrite, &address2);
if (retVal == 3) {
printf("%lu: %lu %c\n", address, address2, readWrite);
} else {
fprintf(stderr, "Parsing error\n");
}
}
Related
I've defined a struct and a function that returns a pointer to that struct and whenever I try to invoke it I get a runtime error says ** error: conflicting types for ‘readVirus’**
typedef struct virus {
unsigned short SigSize;
char virusName[16];
unsigned char* sig;
}virus;
virus* readVirus(FILE* file){
virus *res;
res=(virus*)malloc(sizeof(virus));
fread(&res->SigSize,2,1,file);
fread(&res->virusName,16,1,file);
res->sig=(char*)malloc(res->SigSize);
fread(res->sig,res->SigSize,1,file);
return res;
free(res);
}
int main(int argc, char **argv) {
FILE *input;
input = fopen(argv[1],"rb");
virus *res;
res=(virus*)malloc(sizeof(virus));
res=readVirus(input);
printf("%s",res->virusName);
free(res);
fclose(input);
}
I've tried to copy the body of readVirus into main directly and deleted the function and it worked perfectly, so I don't think that its an function implementation issue.
thanks in advance :)
having
typedef struct virus {
unsigned short SigSize;
char virusName[16];
unsigned char* sig;}
struct virus* readVirus(FILE* file){
first a ';' is missing after the '}' of the struct and you do not define the type virus, so you need to use struct virus every where in your code
But probably you wanted wanted :
typedef struct virus {
unsigned short SigSize;
char virusName[16];
unsigned char* sig;
} virus;
to allow to just write virus without the struct after its definition
I encourage you to use an uppercase character to start the name of your types, so Virus rather than virus, that help the reading of the code making a distinction with the name of the variables for instance
Problems in main
I get a runtime error says ** error: conflicting types for ‘readVirus’**
This is a message produced when you compile your program, not when you execute it and this is because in that line :
res->sig=(char*)malloc(res->SigSize);
res is a pointer to a virus but your cast is (char*), the types are not the same.
You can fix the cast to use (virus*) but in fact you can just remove it.
Doing :
res=malloc(sizeof(virus));
res=readVirus(input);
the first assignment is lost, introducing a memory leak, remove the fiest assignment
Note in main you do not free res too, at the end of the program this is not a problem, except if you want to check the memory usage with a tool like valgrind
You use argv[1] without checking before the program received an argument, I encourage you do do something like that at the beginning of your program :
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n", *argv);
return -1;
}
else {
I encourage you to check the result of fopen to check you was able to open the file and to signal when it is not the case. If you have the function strerror use it, for instance :
if (input == NULL) {
fprintf(stderr, "cannot open %s : ", argv[1], strerror(errno));
return -1;
}
Flush your printing with a final newline, and you just want to print a string, so in main replace
printf("%s",res->virusName);
by
puts(res->virusName);
Problems in readVirus
In
fread(&res->SigSize,2,1,file);
fread(&res->virusName,16,1,file);
do not use literal number for the size, use sizeof to get the right size whatever happens :
fread(&res->SigSize, sizeof(res->SigSize), 1, file);
fread(&res->virusName, sizeof(res->virusNamee), 1, file);
I also recommend you to check your reads success and to signal when there is an error
Are you sure the file is a binary file where sigSize is the binary representation ? I mean for the size 1234 the file contains the byte of code 4 then the byte of code 210 or the reverse
I'm making PE file format analyzer in C language.
When I used Visual Studio, I could make it much easier.
BUT, I have tired to make it without Visual Studio to improve my C programing.
It was made by GCC(My laptop is macbook).
To analyze PE file format, as you know I have to use file pointer and read file as 'rb' type.
I did it and it looks like worked well.... I wanted to print first and second words("MZ") but It printed unkown(to me) numbers.
P.S I write little different code refer to previous one to smaller than before. But It print NULL.
It means that I wrote code really wrong... PLZ tell me which parts are wrong
#include <stdio.h>
#include <stdlib.h>
// struct to save info of PE_File format
typedef struct _IMAGE_DOS_HEADER
{
unsigned short e_magic;
unsigned short e_cblp;
unsigned short e_cp;
unsigned short e_crlc;
unsigned short e_cparhdr;
unsigned short e_minalloc;
unsigned short e_maxalloc;
unsigned short e_ss;
unsigned short e_sp;
unsigned short e_csum;
unsigned short e_ip;
unsigned short e_cs;
unsigned short e_lfarlc;
unsigned short e_ovno;
unsigned short e_res[4];
unsigned short e_oemid;
unsigned short e_oeminfo;
unsigned short e_res2[10];
unsigned long e_lfanew;
} DOS_HEADER;
// I use two different functions.
// First one was made to import PE File format info from file that I used.
// Another was made to print some imformation. I use some comment because I didn't realize those.
DOS_HEADER get_dos_header(FILE *fp, char* fp_buffer);
void print_data_of_structures(DOS_HEADER/*, NT_HEADER, FILE_HEADER, OPTIONAL_HEADER, DATA_DIRECTORY*/);
int main(void)
{
DOS_HEADER dos_header;
char file_path[1000];
printf("Please input your file path : ");
scanf("%[^\n]s", file_path);
FILE* fp = NULL;
fp = fopen(file_path, "rb");
if(fp == NULL)
printf("Unalbe to open file :/\n");
// To calculate file size.
long fp_size = 0;
fseek(fp, 0, SEEK_END);
fp_size = ftell(fp);
rewind(fp);
// Declare to use as buffer
char* fp_buffer = malloc(sizeof(char) * (fp_size + 1));
// Use function to save analyzed information.
DOS_HEADER info_dos_header = get_dos_header(fp, fp_buffer);
// Print information.
print_data_of_structures(info_dos_header);
fclose(fp);
free(fp_buffer);
return 0;
}
DOS_HEADER get_dos_header(FILE* fp, char* fp_buffer)
{
DOS_HEADER raw_info_dos_header = {0, };
// Read hex info from fp 2 byte 1 time and save at fp_buffer.
fseek(fp, 0, SEEK_SET);
fread(fp_buffer, 2, 1, fp);
raw_info_dos_header.e_magic = fp_buffer;
return raw_info_dos_header;
}
void print_data_of_structures(DOS_HEADER info_dos_header/*, NT_HEADER info_nt_header, FILE_HEADER info_file_header, OPTIONAL_HEADER info_optional_header, DATA_DIRECTORY info_data_directory*/)
{
// print info_dos_header
printf("Print DOS_HEADER\n");
// I tried several print format(for example %hu, %x, %d) But I coudn't "MZ" or any numbers has realation with "MZ".
printf("%s", info_dos_header.e_magic);
}
You have 2 big problems with your code: you are mixing types.
In DOS_HEADER all members (except the last one) are of type unsigned short.
That's important.
In get_dos_header you are doing
fread(fp_buffer, 2, 1, fp);
raw_info_dos_header.e_magic = fp_buffer;
which is wrong.
Don't use magic numbers, use sizeof to get the correct sizes
Check the return value of fread, specially if you are analyzing a binary
format, you must be sure that you've read exactly what you're expecting.
It's much easier to deal with fread when the size argument is 1, because
only when the size argument is 1 the return value of fread matches the
number of bytes read.
e_magic is a unsigned short, fp_buffer is a char*. This assignment is
not copying the contents pointed to by fp_buffer, you are storing an address
as if it were a unsigned short value. You need to copy the memory pointed to
by fp_buffer.
Also I don't see the point of you allocating a buffer of the size of the file
when you are reading chunk by chunk. It would be easier if you don't allocate a
buffer at all and use an array of a size larger than what you are going to read.
int get_dos_header(FILE* fp, DOS_HEADER *dos)
{
unsigned char buffer[8];
size_t ret = fread(buffer, 1, sizeof(dos->e_magic), fp);
if(ret != sizeof(dos->e_magic))
{
fprintf(stderr, "Invalid file size\n");
return 0;
}
memcpy(&dos->e_magic, buffer, sizeof(dos->e_magic));
// DO the others fread operation
...
return 1;
}
Then in main you can do this:
DOS_HEADER raw_info_dos_header = {0, };
if(get_dos_header(fp, &raw_info_dos_header) == 0)
{
fprintf(stderr, "failed to get the DOS header\n");
return 1;
}
...
The second problem is in print_data_of_structures:
printf("%s", info_dos_header.e_magic);
e_magic is a unsigned short, %s expects a pointer to char, it expects a
string. e_magic is definitively not a string. This yield undefined behaviour.
The printf should look like this:
printf("e_magic: %hu\n", info_dos_header.e_magic);
or
printf("e_magic: 0x%04hx\n", info_dos_header.e_magic);
to print it in hexadecimal format.
I also advice you to use pointers instead. Your struct is big and passing a
pointer to a function is much cheaper than passing a copy of a large struct to a
functions. So instead of
void print_data_of_structures(DOS_HEADER info_dos_header);
declare it as
void print_data_of_structures(DOS_HEADER *info_dos_header);
And also don't declare function that can fail (like get_dos_header) as
void, otherwise how do you tell the calling function that it failed? It's
better for such functions to return an int (1 for success, 0 for failure) and
expect a pointer to the struct where the information is stored (see how I
changed get_dos_header above.
I have a binary file which contains 3 differents structs and a christmas text. On the first line of the binaryfile have they provided me with a int which represents the size of a package inside the file. A package contains 3 structs ,the chistmastext and the size.
The structs lies in a file called framehdr.h and the binary file I'm reading is called TCPdump.
Now am I trying to create a program att will read each package at a time and then withdraw the text.
I have started with something like this:
#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
FILE *fileOpen;
char *buffer;
size_t dataInFile;
long filesize;
// The three structs
struct ethernet_hdr ethHdr;
struct ip_hdr ipHdr;
struct tcp_hdr tcpHDr;
fileOpen = fopen("C:\\Users\\Viktor\\source\\repos\\Laboration_3\\Laboration_3\\TCPdump", "rb");
if (fileOpen == NULL)
{
printf("Error\n");
}
else
{
printf("Success\n");
}
char lenOf[10];
size_t nr;
// Reads until \n comes
fgets(lenOf, sizeof(lenOf), fileOpen);
sscanf(lenOf, "%d", &nr);
// Withdraw the size of a package and check if it's correct
printf("Value: %d\n", nr);
printf("Adress: %d\n", &nr);
void *ptr;
fread(&ptr, nr, 1, fileOpen);
int resEth = 14;
printf("resEth: %d\n", resEth);
int resIP = IP_HL((struct ip_hdr*)ptr);
printf("ResIP: %d\n", resIP);
int resTcp = TH_OFF((struct tcp_hdr*)ptr);
printf("tcpIP: %d\n", resTcp);
int res = resEth + resIP + resTcp;
printf("Total: %d", res);
fclose(fileOpen);
//free(buffer);
system("pause");
return 0;
}
I know that the first struct ethernet will always have the size of 14 but I need to get the size of the other 2 and I'm suppose to use IP_HL and TH_OFF for that.
But my problems lies in that I can't seem to read the entire package to one
void * with the fread. I get noting in my *ptr.
Which in turn makes the code break when I try to convert the void * to one of the structs ones.
What I'm doing wrong with the void *?
Two problems:
First you should not really use text functions when reading binary files. Binary files doesn't really have "lines" in the sense that text file have it.
Secondly, with
void *ptr;
fread(&ptr, nr, 1, fileOpen);
you are passing a pointer to the pointer variable, you don't actually read anything into memory and then make ptr point to that memory. What happens now is that the fread function will read nr bytes from the file, and then write it to the memory pointed to by &ptr, which will lead to undefined behavior if nr > sizeof ptr (as then the data will be written out of bounds).
You have to allocate nr bytes of memory, and then pass a pointer to the first element of that:
char data[nr];
fread(data, nr, 1, fileOpen);
You should also get into the habit of checking for errors. What if the fread function fails? Or the file is truncated and there isn't nr bytes left to read?
You can check for these conditions by checking what fread returns.
And not only check for fread, there are more functions than fopen that can fail.
I'm trying to write a TCP server which a client can use to browse the server's directories. In addition to that I want to send the size of the directory if that is a regular file. The size of the file is saved into a size_t variable under a "stat" struct.
I'm doing this here:
char *fullName /* The path to the file *.
/**
* Some code here
*/
struct stat buffer;
lstat(fullName, &buffer)
So now buffer.st_size contains the file's size. Now I want to write() it to the listening socket but apparently I have to convert it to a string somehow. I know this can be done somehow with the bitwise right-shift (>>) operator but it seems too painful to me. Can you help me out here (even if there's no way other that bitwise operators)?
By the way this is not for school or smth...
PS: I'm running this on Linux.
You can use the members the sprintf()-family of functions to convert "something" to a "string".
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
size_t s = 123456789;
char str[256] = ""; /* In fact not necessary as snprintf() adds the
0-terminator. */
snprintf(str, sizeof str, "%zu", s);
fputs(stdout, "The size is '");
fflush(stdout);
write(fileno(stdout), str, strlen(str));
fputs(stdout, "'.\n");
return 0;
}
Prints out:
The size is '123456789'.
You know that size_t is unsigned, but the length is unknown. In C99, we have the z modifier for that, making the complete specifier %zu:
size_t s = 123456789;
char str[256];
snprintf(str, sizeof str, "%zu", s);
char * is not necessarily a string, you can send what you want.
Just manage that the other computer use the same protocol.
so you can do that :
write(socket, &(buffer.st_size), sizeof(size_t));
this is maybe to fast, you may have to take account of the endianness etc.
I'm working with TCP sockets. I'm sending data to the open socket using the write function.
write(Socket_Fd, "test", 4);
That works. But when I do it this way.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char BYTE;
typedef struct LANC
{
BYTE START;
BYTE END;
} LCODE;
int main(int argc, char *argv[]){
LCODE COMMAND;
COMMAND.START = 0x28;
COMMAND.END = 0x06;
short value = (COMMAND.START << 8) | COMMAND.END;
write(socket_FD, value, sizeof(value);
return 0;
}
when I check the size of the value I get 2 bytes which is correct since i combined 0x28 and 0x06. So doing a printf.
printf("%x\n", value);
output is: 2806 which is correct.
printf("%d\n", sizeof(value);
output is: 2 bytes which is correct.
I'm getting an error when I'm trying to write the hexadecimal to the open socket using write. What am I doing wrong?
You're committing two disgusting errors in one line (how does it even compile?). You're passing an integer (value) to write() where it expects a pointer (that won't compile, you're trying to deceive us about your code). Secondly, you're doing something that's endian-dependant, that is, on different processors you'll get different results depending on whether the high-byte of "value" comes first or second in memory.
Solution:
unsigned char value[2] = {COMMAND.START, COMMAND.END};
write(socket_FD, value, sizeof(value));