Getting stange error with strings - c

I'm writing a program in C for my beaglebone black to manipulate the gpio pins. This is a very crude program but its just a "beta" if you will. Just to get it up and running. My problem is that I have two character arrays. One holding a command to be passed to the system() function and another holding the path of the file that I am going to be editing, it goes to the fopen function. These character arrays are manipulated to change two numbers depending on what is passed to them from the calling function. For some reason the filename character array is being concatenated with the command. I'm skimming through the program but i don't see any obvious errors.
Here is my code
/*
* gpio.c
*
* Created on: Aug 26, 2014
* Author: Christian Macias
*
* Description: This will control your GPIO (General Purpose IO) pins on the beagle bone. Please
* ensure you are on a kernel that supports device trees.
*
* Usage: gpio(PIN, Value "1" or "0", Inverted? "0" false or "1" for true)
*
* The return value is 0 for success and -1 for failure
*
* GO UTEP!!
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int gpio(int pin, int value, int inv)
{
int sucfail=0;
int pinInt1, pinInt2=-1;
int counterOne=NULL;
char filename[28]= "/sys/class/gpio/gpio00/value";//27 characters
/*
* Checks if file is within the gpio pin range.
*/
if(pin<0 || pin>=99)
{
fprintf(stderr, "\n%s\n\t%s\n\t%s\n", "Error in gpio.c(GPIO): ", "The gpio pin selected is not "
"within the availabilty of the app", "Please select a pin from 0-99");
return -1;
}
/*
* checks to see if value is boolean aka 1 or 0
*/
if(value<0 || value>1)
{
fprintf(stderr, "\n%s\n\t%s\n\t%s", "Error in gpio.c(GPIO): ", "The Selected value is invalid", "Please"
" select a 1 or a 0");
return -1;
}
/*
* Writes the pin to a file so that it can used later
*/
FILE *PINWRITE;
PINWRITE=fopen("pinWRITE", "w+");
fprintf(PINWRITE,"%i", pin);
fclose(PINWRITE);
/*
* This section will check for pre-existence of the the PIN file to prevent errors. or
* opens it if it doesnt exist.
* First it will set up the filenames
*/
PINWRITE=fopen("pinWRITE","r");
fscanf(PINWRITE, "%1i%1i", &pinInt1, &pinInt2);//Checks the pin and sets each digit to its according variable
fclose(PINWRITE);
filename[20]='0'+pinInt1;
if(pinInt2==-1)//If it is a one digit pin, it will move the letters to fit the file name correctly and remove one of the digits
{
for(counterOne=21;counterOne<28;counterOne++)
{
filename[counterOne]=filename[counterOne+1];
}
filename[27]='\0';
}
else//If two digits it will just change the second digit
{
filename[21]='0'+pinInt2;
}
FILE *PINVALUE;//FILE pointer to the files with the value
PINVALUE=fopen(filename,"w+");
/*
* At this point the the actual checking and creation occurs
*/
char exportCommand[32]="echo 00 > /sys/class/gpio/export";//31 characters
if(PINVALUE==NULL)
{
//this runs if the file didnt exist.
exportCommand[5]='0'+pinInt1;
if(pinInt2==-1)//If it is a one digit pin, it will move the letters to fit the file name correctly and remove one of the digits
{
for(counterOne=6;counterOne<32;counterOne++)
{
exportCommand[counterOne]=exportCommand[counterOne+1];
}
exportCommand[31]='\0';
}
else//If two digits it will just change the second digit
{
exportCommand[6]='0'+pinInt2;
exportCommand[32]='\0';
}
system(exportCommand);
printf("\n%s\n", exportCommand);
printf("\n%s\n", filename);
PINVALUE=fopen(filename,"w+");
}
if(PINVALUE==NULL)
{
fprintf(stderr,"\n%s\n\t%s", "Error in gpio.c(GPIO)", "The PINVALUE (.../gpioXX/value) could not be opened");
return -1;
}
/*
* Some pins may be set up backward... on is off and off is on. To correct this we must adjust a file...
* This takes to long and i dont have the time for it so i'm doing a hot fix... sorry but its 11 and i have
* school tomorrow. The correction process it too long and i want to finish today :)
*/
if(inv==1 && value==1)
{
value=0;
}
else if(inv==1 && value==0)
{
value=1;
}
/*
* At this point the file is set up and ready to be written to.
* We will write the value now and close it.
*/
fprintf(PINVALUE, "%i", value);
fclose(PINVALUE);
return sucfail;
}

You are underestimating the length of string literals you want to copy into arrays, leaving no space for the nul terminator. For example, here
char filename[28]= "/sys/class/gpio/gpio00/value"; //27 characters
the literal actually has 28+1 characters (28 visible, plus a nul terminator).
You need to make the array of size 29. You can do this explicitly,
char filename[29] = "/sys/class/gpio/gpio00/value";
or implicitly:
char filename[] = "/sys/class/gpio/gpio00/value";
Similarly here, where you need the array to be of length 33:
char exportCommand[32]="echo 00 > /sys/class/gpio/export";
There may well be other errors. I would start by fixing those first. It will make finding the other ones easier.

Related

Can't read real numbers from Yale Bright Star Catalog

I'm currently trying to read some star data from the BSC. I've managed to read in the header and that shows up more or less correct, but I'm having trouble reading in the star data itself. The specification states that values are stored as 4/8-byte "Real" numbers, which I assumed meant floats/doubles, but the Ascension and Declination I get are all wrong, a good bit above the trillions for one and zero for the other. The magnitude is also wrong, despite it just being an integer, which I could read fine in the header. Here's and image of the output thus far. Any know what I'm doing wrong?
Alright, after some more testing, I managed to solve my problem. The crucial step was to abandon the binary file altogether and use the ASCII file instead. I had some problems reading from it before due to how it was formatted, but I came up with a method that worked:
/* Struct to store all the attributes I'm interested in */
struct StarData_t{
char Name[11];
char SpType[21];
float GLON, GLAT, Vmag;
};
int main()
{
/* Allocate a list of the structs
(the BSC has 9110 entries) */
struct StarData_t stars[9110];
/* Open the catalog */
FILE *fptr = fopen("catalog", "r");
if(fptr != NULL){
/* Create a buffer for storing the star entries.
The ASCII file has one entry per line.
Each line has a max length of 197,
which becomes 199 with the newline and null terminator,
so I round up to 200. */
size_t star_size = 200;
char *star_buffer;
star_buffer = (char *)malloc(star_size * sizeof(char));
/* Create a buffer for reading in the numbers.
The catalog has no numbers longer than 6 characters,
So I allocate 7 to account for the newline. */
char data_buffer[7];
/* For each entry in the BSC... */
for(int i = 0; i < 9110; i++){
/* Read the line to the buffer */
getline(&star_buffer, &star_size, fptr);
/* And put the data in the matching index,
Using the data buffer to create the floats */
// GLON
strncpy(data_buffer, &(star_buffer[90]), 6);
data_buffer[6] = '\0';
stars[i].GLON = fmod(atof(data_buffer)+180, 360)-180;
// GLAT
strncpy(data_buffer, &(star_buffer[96]), 6);
data_buffer[6] = '\0';
stars[i].GLAT = atof(data_buffer);
// Vmag
strncpy(data_buffer, &(star_buffer[102]), 5);
data_buffer[5] = '\0';
stars[i].Vmag = atof(data_buffer);
// Name
strncpy(stars[i].Name, &(star_buffer[4]), 10);
stars[i].Name[10] = '\0';
// Spectral Type
strncpy(stars[i].SpType, &(star_buffer[127]), 20);
stars[i].SpType[20] = '\0';
printf("Name: %s, Long: %7.2f, Lat: %6.2f, Vmag: %4.2f, SpType: %s\n", stars[i].Name, stars[i].GLON, stars[i].GLAT, stars[i].Vmag, stars[i].SpType);
}
free(star_buffer);
}
}
Hope this is useful!

"Segmentation fault 11" crashing in for loop

I'm super new to C programming, only taking it for a required course in uni and finally getting done with my final project this week.
Problem is every time I run this code I get an error message that says "segmentation fault: 11" and I'm not sure what that means.
The code is supposed to run two-player race. Each player has a pre-determined "speed modifier", aka a number from 0-9. A random number from 1-10 is generated; if the speed modifier + the random number doesn't exceed 10, then the speed modifier is added and the car moves that total amount of "spaces". The whole race track is 90 "spaces".
Every time I run this code it works somewhat fine (more on that later) for one or two iterations, then gives out that error message. I normally don't ask for homework help online but I'm honestly so confused. Any help at all would be super appreciated.
Here is the relevant code:
Race (main) function:
int race(struct car cars[4], int mode)
{
/* Define variables. */
int endgame, i, x, y, first=-1, second=-1, randnum, spaces[]={};
char input[100];
/* Declare pointer. */
int *spacesptr=spaces;
for (i=0; i<mode; i++)
{
/* Array spaces will keep track of how many spaces a car has moved. Start each car at 0. */
spaces[i]=0;
}
/* Clear screen before race. */
system("cls");
/* Print message to indicate race has started. */
printf("\n3...\n2...\n1...\nGO!\n\n");
/* Open do while loop to keep race running until it is over. */
do
{
/* Conditions for two player mode. */
if (mode==2)
{
/* Run the next block of code once for each player. */
for (i=0; i<mode; i++)
{
/* Generate random integer from 1-10 to determine how many spaces the car moves. */
x=10, y=1;
randnum=(getrandom(x, y));
spaces[i]=spaces[i]+randnum;
/* Call function speedmod to determine if speedmodifier should be added. */
speedmod(cars, spaces, randnum);
/* Rank players. */
if (spaces[i]>89)
{
if (first==-1)
{
first=i;
}
else if (second==-1)
{
second=i;
}
}
}
}
...
/* Call function displayrace to display the race. */
displayrace(cars, spaces, mode);
/* Call function endgame to determine if the race is still going. */
endgame=fendgame(mode, spaces);
if (endgame==0)
{
/* Ask for player input. */
printf("Enter any key to continue the race:\n");
scanf("%s", input);
/* Clear screen before loop restarts. */
system("cls");
}
} while (endgame==0);
}
Random number function:
int getrandom(int x, int y)
{
/* Define variable. */
int randnum;
/* Use time seed. */
srand(time(0));
/* Generate random numbers. */
randnum=(rand()+y) % (x+1);
return randnum;
}
Add speed modifier function:
void speedmod(struct car cars[4], int spaces [], int go)
{
/* Declare pointer. */
int *spacesptr=spaces;
/* If the number of spaces plus the speed modifier is less than or equal to ten... */
if (spaces[go]+cars[go].speedmod<=10)
{
/* ...add the speed modifier to the number of spaces moved. */
spaces[go]=spaces[go]+cars[go].speedmod;
}
}
Display race function:
void displayrace(struct car cars[4], int spaces[], int mode)
{
/* Define variables. */
int i, j;
/* Declare pointers. */
int *spacesptr=spaces;
struct car *carsptr=cars;
/* Open for loop. */
for (i=0; i<mode; i++)
{
/* Print racecar number. */
printf("#%d\t", cars[i].carnumber);
/* For every space the car has moved... */
for (j=0; j<spaces[i]; j++)
{
if (j<=90)
{
/* ...print one asterisk. */
printf("*");
}
}
/* New line. */
printf("\n");
}
}
End game function:
int fendgame(int mode, int spaces[])
{
/* Define variables. */
int racers=0, endgame=0, i;
/* Declare pointer. */
int *spacesptr=spaces;
/* Open for loop. */
for (i=0; i<mode; i++)
{
/* If any of the racers have not yet crossed the finish line (90 spaces)... */
if (spaces[i]<=90)
{
/* ...then add to the number of racers still in the game. */
racers++;
}
}
/* If all the racers have crossed the finish line... */
if (racers==0)
{
/* ...then end the game. */
endgame=1;
}
return endgame;
}
Now to be more specific on the issue...it's messing up somewhere on the "for" loop in the race function. For some reason it doesn't actually go through each iteration of "i", specifically in this line:
spaces[i]=spaces[i]+randnum;
I know this because I put in printf statements to display the value of spaces[i] before and after; the first iteration of i works fine...but the second iteration actually uses spaces[i-1] instead and adds the randnum to that value?
And then, like I said, it crashes after one or two times of this...:-(
I know it's a lot but I'm hoping someone more experienced than I could spot the error(s) in this code for me! Please help!
I believe the first user above was correct in saying that the error is because there is no initial size declared for the array, but the solution is incorrect. You would have to allocate its size dynamically using malloc.
Also, I'd shorten spaces[i]=spaces[i]+randnum to just spaces[i] += randnum.
regarding: Problem is every time I run this code I get an error message that says "segmentation fault: 11" and I'm not sure what that means.
This means your program is trying to access memory that the application does not own.
For instance, a 'wild' pointer or uninitialized pointer or writing past the end of an array.
Thanks for the help. After a ton of tinkering around with this code I finally found the issue.
I was passing randnum to the speedmod function as if it were an index of the array spaces. I changed the function to the following, where num is the random number generated and go is the index:
void speedmod(struct car cars[4], int spaces [], int num, int go)
{
/* Declare pointer. */
int *spacesptr=spaces;
/* If the number of spaces plus the speed modifier is less than or equal to ten... */
if (num+cars[go].speedmod<=10)
{
/* ...add the speed modifier to the number of spaces moved. */
spaces[go]+=cars[go].speedmod;
}
}
Works perfectly now. Thanks for the help again.
you declare spaces[]={}, so it allocates a ptr that points to nothing. then you start writing all over it, which destroys probably your stack, your other variables, and whatever else is there -> undefined behavior.
you need to provide the memory to write to before you use it, for example spaces[1000]={}, ot however much you need.

Create an array of values from different text files in C

I'm working in C on 64-bit Ubuntu 14.04.
I have a number of .txt files, each containing lines of floating point values (1 value per line). The lines represent parts of a complex sample, and they're stored as real(a1) \n imag(a1) \n real(a2) \n imag(a2), if that makes sense.
In a specific scenario there are 4 text files each containing 32768 samples (thus 65536 values), but I need to make the final version dynamic to accommodate up to 32 files (the maximum samples per file would not exceed 32768 though). I'll only be reading the first 19800 samples (depending on other things) though, since the entire signal is contained in those 39600 points (19800 samples).
A common abstraction is to represent the files / samples as a matrix, where columns represent return signals and rows represent the value of each signal at a sampling instant, up until the maximum duration.
What I'm trying to do is take the first sample from each return signal and move it into an array of double-precision floating point values to do some work on, move on to the second sample for each signal (which will overwrite the previous array) and do some work on them, and so forth, until the last row of samples have been processed.
Is there a way in which I can dynamically open files for each signal (depending on the number of pulses I'm using in that particular instance), read the first sample from each file into a buffer and ship that off to be processed. On the next iteration, the file pointers will all be aligned to the second sample, it would then move those into an array and ship it off again, until the desired amount of samples (19800 in our hypothetical case) has been reached.
I can read samples just fine from the files using fscanf:
rx_length = 19800;
int x;
float buf;
double *range_samples = calloc(num_pulses, 2 * sizeof(range_samples));
for (i=0; i < 2 * rx_length; i++){
x = fscanf(pulse_file, "%f", &buf);
*(range_samples) = buf;
}
All that needs to happen (in my mind) is that I need to cycle both sample# and pulse# (in that order), so when finished with one pulse it would move on to the next set of samples for the next pulse, and so forth. What I don't know how to do is to somehow declare file pointers for all return signal files, when the number of them can vary inbetween calls (e.g. do the whole thing for 4 pulses, and on the next call it can be 16 or 64).
If there are any ideas / comments / suggestions I would love to hear them.
Thanks.
I would make the code you posted a function that takes an array of file names as an argument:
void doPulse( const char **file_names, const int size )
{
FILE *file = 0;
// declare your other variables
for ( int i = 0; i < size; ++i )
{
file = fopen( file_names[i] );
// make sure file is open
// do the work on that file
fclose( file );
file = 0;
}
}
What you need is a generator. It would be reasonably easy in C++, but as you tagged C, I can imagine a function, taking a custom struct (the state of the object) as parameter. It could be something like (pseudo code) :
struct GtorState {
char *files[];
int filesIndex;
FILE *currentFile;
};
void gtorInit(GtorState *state, char **files) {
// loads the array of file into state, set index to 0, and open first file
}
int nextValue(GtorState *state, double *real, double *imag) {
// read 2 values from currentFile and affect them to real and imag
// if eof, close currentFile and open files[++currentIndex]
// if real and imag were found returns 0, else 1 if eof on last file, 2 if error
}
Then you main program could contain :
GtorState state;
// initialize the list of files to process
gtorInit(&state, files);
double real, imag);
int cr;
while (0 == (cr = nextValue(&state, &real, &imag)) {
// process (real, imag)
}
if (cr == 2) {
// process (at least display) error
}
Alternatively, your main program could iterate the values of the different files and call a function with state analog of the above generator that processes the values, and at the end uses the state of the processing function to get the results.
Tried a slightly different approach and it's working really well.
In stead of reading from the different files each time I want to do something, I read the entire contents of each file into a 2D array range_phase_data[sample_number][pulse_number], and then access different parts of the array depending on which range bin I'm currently working on.
Here's an excerpt:
#define REAL(z,i) ((z)[2*(i)])
#define IMAG(z,i) ((z)[2*(i)+1])
for (i=0; i<rx_length; i++){
printf("\t[%s] Range bin %i. Samples %i to %i.\n", __FUNCTION__, i, 2*i, 2*i+1);
for (j=0; j<num_pulses; j++){
REAL(fft_buf, j) = range_phase_data[2*i][j];
IMAG(fft_buf, j) = range_phase_data[2*i+1][j];
}
printf("\t[%s] Range bin %i done, ready to FFT.\n", __FUNCTION__, i);
// do stuff with the data
}
This alleviates the need to dynamically allocate file pointers and in stead just opens the files one at a time and writes the data to the corresponding column in the matrix.
Cheers.

Creating a basic stack overflow using IDA

This program is running with root privileges on my machine and I need to perform a Stack overflow attack on the following code and get root privileges:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/sha.h>
void sha256(char *string, char outputBuffer[65])
{
unsigned char hash[SHA256_DIGEST_LENGTH];
int i = 0;
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, string, strlen(string));
SHA256_Final(hash, &sha256);
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}
int password_check(char *userpass)
{
char text[20] = "thisisasalt";
unsigned int password_match = 0;
char output[65] = { 0, };
// >>> hashlib.sha256("Hello, world!").hexdigest()
char pass[] = "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3";
text[0] = 'a';
text[1] = 't';
text[2] = 'j';
text[3] = '5';
text[4] = '3';
text[5] = 'k';
text[6] = '$';
text[7] = 'g';
text[8] = 'f';
text[9] = '[';
text[10] = ']';
text[11] = '\0';
strcat(text, userpass);
sha256(text, output);
if (strcmp(output, pass) == 0)
{
password_match = 1;
}
return (password_match == 1);
}
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("Usage: %s <pass> <command>\n", argv[0]);
exit(1);
}
if (strlen((const char *) argv[1]) > 10)
{
printf("Error: pasword too long\n");
exit(1);
}
if (password_check(argv[1]))
{
printf("Running command as root: %s\n", argv[2]);
setuid(0);
setgid(0);
system(argv[2]);
}
else
{
printf("Authentication failed! This activity will be logged!\n");
}
return 0;
}
So I try to analyse the program with IDA and I see the text segment going from the lower addresses to the higher addresses, higher than that I see the data and then the bss and finally external commands.
Now as far as I know the stack should be just above that, but I'm not certain how to view it, how exactly am I supposed to view the stack in order to know what I'm writing on? (Do I even need it or am I completely clueless?)
Second question is considering the length of the input, how do i get around this check in the code:
if (strlen((const char *) argv[1]) > 10)
{
printf("Error: pasword too long\n");
exit(1);
}
Can I somehow give the string to the program by reference? If so how do I do it? (Again, hoping I'm not completely clueless)
Now as far as I know the stack should be just above that, but I'm not certain how to view it, how exactly am I supposed to view the stack in order to know what I'm writing on? (Do I even need it or am I completely clueless?)
The stack location varies all the time - you need to look at the value of the ESP/RSP register, its value is the current address of the top of the stack. Typically, variable addressing will be based on EBP rather then ESP, but they both will point to the same general area of memory.
During analysis, IDA sets up a stack frame for each function, which acts much like a struct - you can define variables with types and names in it. This frame is summarized at the top of the function:
Double-clicking it or any local variable in the function body will open a more detailed window. That's as good as you can get without actually running your program in a debugger.
You can see that text is right next to password_match, and judging from the addresses, there are 0x14 bytes allocated for text, as one would expect. However, this is not guaranteed and the compiler can freely shuffle the variables around, pad them or optimize them into registers.
Second question is considering the length of the input, how do i get around this check in the code:
if (strlen((const char *) argv[1]) > 10)
{
printf("Error: pasword too long\n");
exit(1);
}
You don't need to get around this check, it's already broken enough. There's an off-by-one error.
Stop reading here if you want to figure out the overflow yourself.
The valid range of indices for text spans from text[0] through text[19]. In the code, user input is written to the memory area starting at text[11]. The maximum input length allowed by the strlen check is 10 symbols + the NULL terminator. Unfortunately, that means text[19] contains the 9th user-entered symbol, and the 10th symbol + the terminator overflow into adjacent memory space. Under certain circumstances, that allows you to overwrite the least significant byte of password_match with an arbitrary value, and the second least significant byte with a 0. Your function accepts the password if password_match equals 1, which means the 10th character in your password needs to be '\x01' (note that this is not the same character as '1').
Here are two screenshots from IDA running as a debugger. text is highlighted in yellow, password_match is in green.
The password I entered was 123456789\x01.
Stack before user entered password is strcat'd into text.
Stack after strcat. Notice that password_match changed.

The Vigenere encryption

I have written some code, and the Vigenere encryption is used in it. This is a simple program for encrypting/decrypting any files.
#include<stdio.h>
/*
LANGUAGE: C.
STANDARD: C89.
ABOUT PROGRAM:
This is a simple program for encrypting/decrypting any files.
The size of source file coincide with size of result file.
For encryption of file are use any string key. For decrypting,
you must to use the same key, which was used for encryption.
NOTES:
The Vigenere encryption are used in it.
Info at the site: http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher.
This simple algorithm is often used at commercial products. The
Vigenere's algorithm are using a string key, and 'XOR' for
encrypting/decrypting information.
WARNING!
The use of this method, doesn't give 100% of a warranty
for protection of your information. Don't create the keys,
consisting of identical characters, for example" "aaaaa",
"zzz", "xxxx" e.t.c. - it is very feeble protection!
Don't forget your encrypting keys... :)
SYNTAX OF USING:
vigenere StringKey SourceFileName ResultFileName
where:
vigenere - program name;
StringKey - string key for encrypting/decrypting;
SourceFileName - source file name;
ResultFileName - result file name;
EXAMPLE OF USING:
vigenere "G5$hj4*df7f3+x" "c:\temp\source.txt" "c:\temp\result.txt"
*/
int main(int argc, char *args[]){
/****************************************************/
/* All variables must be defined on top in function, otherwise
some compilers can't compile this code (for example - MS
Visual Studio 2012. */
char ch; /* The next char for encrypting/decrypting. */
char *x; /* String key. */
FILE *srcFile; /* Source file. */
FILE *trgFile; /* Result file. */
/****************************************************/
/* The first argument always is a program file name. */
if (4 != argc)
return 1; /* Invalid arguments count. */
if (!*args[1] || !*args[2] || !*args[3])
return 2; /* Contains the empty argument. */
x = args[1];
if ((srcFile = fopen(args[2], "rb")) != NULL){
if ((trgFile = fopen(args[3], "wb")) != NULL){
while((ch = getc(srcFile)) != EOF){
if(!*x++)
x = args[1];
putc((ch ^= *x), trgFile);
}
fclose(trgFile);
}
else
return 4; /* Result file wasn't created. */
fclose(srcFile);
}
else
return 3; /* Source file wasn't opened. */
return 0; /* Successful operation. */
}
But this code does not always work well. I don't understand why it occurs. I do XOR for each byte. I have tested this code on such TXT files. Where is my mistake?
char ch;
/* ... */
while((ch = getc(srcFile)) != EOF)
ch must be an int. EOF is defined as a negative int.
In addition to ouah's answer, the pointer value increment looks off.
your if statement, if(!*x++), is bad for two reasons:
By doing an increment before the actual XOR operation, you're skipping the first character of your key in the initial loop.
There's no point in incrementing the pointer if you already reach the null-terminating character.
The better code would be:
while((ch = getc(srcFile)) != EOF){
putc((ch ^= *x), trgFile);
if(!*++x)
x = args[1];
}

Resources