I'm trying to get an ip address from the command line, so I prepared a simple parser. The problem is that the program seems to stop when I try to read from argv[i].
int main(int argc, char * argv[]){
unsigned char packet[1500];
int n,len,i,j;
unsigned char dstmac[6];
unsigned char targetip[4];
unsigned char * add;
unsigned char byte=0;
if(argc==2){
j=0;
i=0;
add = argv[1];
printf(">>%s<< \n",add);
fflush(stdout);
printf("%c ",add[1]);
fflush(stdout);
while(add[i]) {
printf("%c ",add[i]);
fflush(stdout);
if( add[i] != '.' )
byte = byte*10+(add[i]-48);
else{
targetip[j++] = byte;
byte=0;
}
i++;
}
targetip[j++]=byte;
}
else{
targetip[0]=88;
targetip[1]=80;
targetip[2]=187;
targetip[3]=50;
}
printf("TARGET IP: %d.%d.%d.%d",targetip[0],targetip[1],targetip[2],targetip[3]);
fflush(stdout);
struct eth_frame * eth;
struct ip_datagram * ip;
struct icmp_packet * icmp;
//etc.....
I really don't know why. Can you help me?
EDIT: update code with fflush(stdout)
ACTUAL OUTPUT:
1238166#localhost:~/ping$ gcc ping2.c -o np
1238166#localhost:~/ping$ ./np 216.58.205.67
>>216.58.205.67<<
1
2 1 6 . 5 8 . 2 0 5 . 6 7 TARGET IP: 216.58.205.67
now the programm blocks when it prints the "TARGET IP".
In the rest of the programm there is the pakcet initialization and exchange. I have already tested this part and it should work.
UPDATE: what I noticed is that the program now needs an ffflush(stdout) to go on, but before this was not necessary. If I run for example without arguments (the else clause), all works properly.
1238166#localhost:~/ping$ ./np
TARGET IP: 88.80.187.50destmac: f2(242) 3c(060) 91(145) 2c(044)
53(083) b7(183)
================
SENT PACKET:
f2(242) 3c(060) 91(145) 2c(044)
53(083) b7(183) ....
When I tried your program, it didn’t block. The program terminates.
However, the instructions printf("%c ",add[1]); and printf("%c ",add[i]); had no visible effect. This is because the character is buffered and not printed to the console. The buffered content is out put to the console when a fflush(stdout); is performed. Printf does this itself when there is a \n in the output string. The buffer content is also output to the console when the program terminates on Linux.
When I run your program with the argument 123.45.67.255, I get the single line output 2 1 2 3 . 4 5 . 6 7 . 2 5 5 TARGET IP: 123.45.67.255 which is what it is supposed to be.
The output you see is Windows specific.Apparently, on Windows the buffer content is not flushed when the program terminates. You must add a \n at the end of the format string of the last printf.
Note: modifying the question after the question is answered make the answer confusing.
Related
I discovered the function read(), but I don't understand everything.
Here is my code:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
char array[10];
int ret;
printf("read : ");
fflush(stdout);
array[sizeof(array) - 1] = '\0';
ret = read(STDIN_FILENO, array, sizeof(array) - 1);
printf("array = %s\n", array);
printf("characters read = %d\n", ret);
//getchar();
return (0);
}
Here is an example of the running program :
$> ./a.out
read : hi guys how are you
array = hi guys h
characters read = 9
$> ow are you
zsh: command not found: ow
$>
Why is it launching a shell command after the end of the program?
I noticed that if I uncomment the getchar() line, this strange behavior disappears. I'd like to understand what is going on, if someone has an idea :)
Your call to read is reading in the first 9 characters of what you've type. Anything else will be left in the input buffer so that when you program exits, your shell will read it instead.
You should check the return value of read so you know how much has been read as it's not guaranteed that it'll be the amount you ask for and also the value returned is used to indicate an error.
The string read in won't be null-terminated either, so you also should use the return value (if positive) to put the NUL character in so that your string is valid.
If you want to read in the whole line, you'll need to put in a loop and identify when there is an end of line character (most likely '\n').
You typed about 20 characters, but you only read 9 characters with read(). Everything after that was left in the terminal driver's input buffer. So when the shell called read() after the program exited, it got the rest of the line, and tried to execute it as a command.
To prevent this, you should keep reading until you get to the end of the line.
int main()
{
int t, i;
int *nums;
scanf("%d", &t);
nums = malloc(t * sizeof(int));
for(i = 0; i < t; i++)
{
scanf("%d", &nums[i]);
}
printf("hey");
}
For some reason, it hangs, waiting for more input! Any ideas?
This code is correct, except for the fact that you're not freeing your memory (not a big issue for this simple code) and you're not checking scanf for errors, which may be the cause of your problem.
A better implementation with error checking and correct memory handling is described below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int t, i, ret;
int *nums;
ret = scanf("%d", &t);
if(ret != 1)
{
/* something wrong */
}
nums = malloc(t * sizeof(int));
if(nums==NULL)
{
/* memory error */
}
for(i = 0; i < t; i++)
{
ret = scanf("%d", &nums[i]);
if(ret != 1)
{
/* something wrong */
}
}
free(nums);
printf("hey");
return 0;
}
Just a guess here...
But I'm guessing you ran it and entered :
4
1234
For example, you put in 4 and then 1234 and it hangs. Well, that would be because 1234 is the first number and not 4 distinct numbers so its waiting for the second number. You have to press enter or some such delimiter between each number.
Try this set of inputs instead:
4
1234
29
4
5
You should get :
hey
Pro grammatically, you should be checking return values from your function calls. Make sure malloc didn't return zero. Make sure scanf returns the number of inputs you expected to read. Add in printouts to make sure the values it read in are what you expected/wanted to read in.
EDIT :
Guessing you have a typo in the program which isn't displayed here. such as :
scanf("%s", &t);
Or you are getting the 'hey' and just not seeing it.
[ov#MARVIN sotest]$ ./a.out
5 5 4 3 23 1
hey[ov#MARVIN sotest]$
See the 'hey' is sort of hidden in my prompt because you are missing the '\n' new line in the printout?
Remember to flush when you are done.
In chat, OP's comments "No... BTW, if I add a printf in the loop that prints the current input, it prints everything except from the last one...". This hinted that the issue was on the final output.
The following sends data out to be printed. But stdout is typically buffered. Actual output may not occur until sometime later. Output is flushed when 1) output contains an end-of-line '\n', 2) fflush() is called 3) the program ends. I am surprised output did not appear when the program ended, but possibly OP's true code differs from the post.
printf("hey");
Change to
printf("hey\n");
Or #Cool Guy
printf("hey");
fflush(stdout);
BTW: This is also hinted in #Diversity answer.
Note: Always a good idea to check the result of scanf()
// scanf("%d", &t)
if (1 != scanf("%d", &t)) Handle_BadInput_or_EOF();
So I'm doing an exercise where I want to call the function void not_called() just by inputting a buffer. Basically what I want to do is use a buffer overflow to call not_called(). I'm approaching this by using a binary exploit string then using a program hex2raw (takes hex format then turns it into the ASCII for decimal digit.) I'm then going to put that binary exploit string into a .txt file, then use a series of pipes in the unix terminal to call not_called() like so:
cat exploit.txt | ./hex2raw | ./nameofpgrm
So what I'm struggling with is finding that binary exploit string. I think what I need to do is find the location in memory where not_called is called with an objdump, but I'm not sure. Any help on what I can do? I know I'm going to have to use gdb to find it. I just don't really know where to look.
#include <stdlib.h>
#include <stdio.h>
void echo();
/* Main program */
int main() {
while (1)
echo();
return(0); // never called
} // main
/* My gets -- just like gets - Get a string from stdin */
char *mygets(char *dest) {
int c = getchar();
char *p = dest;
while (c != EOF && c != '\n') {
*p++ = c;
c = getchar();
}
*p = '\0';
return dest;
} // mygets
/* Echo Line */
void echo() {
char buf[4]; /* Way too small */
mygets(buf);
puts(buf);
} // echo
void not_called() {
printf("This routine is never called\n");
printf("If you see this message, something bad has happend\n");
exit(0);
} // not_called
You want to overwrite the return address from the function echo with bytes read from stdin so that is now points to not_called entry point.
Let's use for example Mac OS/X 10.10 aka Yosemite. I simplified the code and added an extra printf to get the actual address of the function not_called:
#include <stdlib.h>
#include <stdio.h>
void echo(void) {
char buf[4]; /* Way too small */
gets(buf);
puts(buf);
}
void not_called(void) {
printf("This routine is never called\n");
printf("If you see this message, something bad has happened\n");
exit(0);
}
int main(void) {
printf("not_called is at address %p\n", not_called);
echo();
}
Let's compile and execute this code using clang:
chqrlie> clang t20.c && ./a.out
The output is quite clear:
not_called is at address 0x106dade50
warning: this program uses gets(), which is unsafe.
Using a hex editor, let's coin the input and paste it to the console: the short buffer buf aligned on 64 bits, 8 bytes below the saved copy of the stack frame pointer rbp, itself followed by the return address we want to overwrite. The input in hex is for example:
0000 3031 3233 3435 3637-3839 3031 3233 3435 0123456789012345
0010 50de da06 0100 0000- P��.....
Let's paste these 24 bytes to the console and hit enter:
0123456789012345P��^F^A^#^#^#
0123456789012345P��^F^A
This routine is never called
If you see this message, something bad has happened
Segmentation fault: 11
Function echo uses gets to read stdin, the 24 bytes are stored beyond the end of buf, overwriting the frame pointer rbp, the return address, and an extra 0 byte. echo then calls puts to output the string in buf. Output stops at the first "'\0'" as expected. rbp is then restored from the stack and gets a corrupt value, control is transferred to the return address. The return address was overwritten with that of function not_called, so that's what gets executed next. Indeed we see the message from function not_called and for some reason exit crashes instead of exiting the process gracefully.
I used gets on purpose so readers understand how easy it to cause buffer overflows with this function. No matter how big the buffer, input can be coined to crash the program or make it do interesting things.
Another interesting find is how Mac OS/X tries to prevent attackers from using this trick too easily: the address printed by the program varies from one execution to the next:
chqrlie > ./a.out < /dev/null
not_called is at address 0x101db8e50
warning: this program uses gets(), which is unsafe.
chqrlie > ./a.out < /dev/null
not_called is at address 0x10af4ae50
warning: this program uses gets(), which is unsafe.
chqrlie > ./a.out < /dev/null
not_called is at address 0x102a46e50
warning: this program uses gets(), which is unsafe.
The code is loaded at a different address each time, chosen randomly.
The input required to make function echo return to not_called is different each time. Try your own OS and check if it uses this trick. Try coining the appropriate input to get the job done (it depends on your compiler and your system). Have fun!
Im using fgets to read from 2 different pipes which have been sent 2 different messages thus should be returning 2 different messages. I have 2 pipes for each and closed the unneeded child end, all my fprintfs are flushed yet theyre both returning the same message then it just hangs. I have no idea why. Debugging didnt help me though i could have missed something.
int reader(FILE *output, int **pipes, char *getMessage) {
if(output == NULL) {
fprintf(stderr, "Player quit\n");
}
fgets(getMessage, sizeof(getMessage), output);
printf("mes %s\n", getMessage);
return 0;
}
Is my reader method (I am using the same buffer for both but i was using memset to try to clear it each time:
printf("test%c\n", roundDeck[deckPos]);
fprintf(input[pickturn], "yourturn %c\n", roundDeck[deckPos]);
fprintf(stdout, "yourturn %c\n", roundDeck[deckPos]);
fflush(input[pickturn]);
allHeldCards[pickturn][1] = roundDeck[deckPos];
roundDeck[deckPos] = '-';
//fclose(inPut);
deckPos++;
if(deckPos == 16) {
deckPos = 0;
}
printf("pt %d\n", pickturn);
reader(output[pickturn], pipes, getMessage);
if(msgProcess(pickturn, allIds, allFlags, allHeldCards,
getMessage, pipes, roundDeck,
deckPos, numPlayers, input) == 1) {
roundDeck[deckPos] = '-';
deckPos++;
if(deckPos == 16) {
deckPos = 0;
}
}
memset(getMessage, 0, 50);
the inputs were changing where they needed to do on the outside so maybe Im using memset incorrectly?
There is a problem here:
fgets(getMessage, sizeof(getMessage), output);
Since getMessage has type char *, then sizeof(getMessage) is sizeof(char *) which is likely to be 4 or 8. You read that many bytes from the "output" into getMessage.
Instead, you need to specify how many bytes to read. Even if you replace sizeof(getMessage) with your buffer size, that means it will block until all that number of bytes have been read, or the input is closed. Either your message protocol has to contain the length it expects to read, or you have to define your function to read until the input is closed or a certain delimiter occurs.
Then you have to make sure that the data you read contains a null-terminated string before you try and print it with %s or any other function that expects a string.
Not clear why your inputs are called output and your outputs are called input either.
It's hard to debug further without seeing more of a complete program than just these snippets
I wanted to know how to read data from an unknown source of input, meaning I don't know if the user is going to just type a sentence or is he going to give me some text file.
I've tried using fscanf since I've read it is meant for unformatted input type
this is my code, Im suppose to get some type of input(file or just a sentence (echo bla bla bla) and "int" and print only the "int" first words. The program should be used for piping meaning the command would look like that :
There are 2 ways to ways of using the program:
1.echo "blabla" | myprog 2 (number of words to print)
2.cat input.txt | myprog 2 (number of words to print)
The problematic line is line 16, I tried using fscanf
Thanks!
1 #include <stdio.h>
2 #include <ctype.h>
3 #include <string.h>
4 #include <stdlib.h>
5
6
7 int main(int argc, char *argv[]){
8 char *words[32];
9 int numofwords = atoi(argv[2]);
10 int i=0;
11 int len;
12 char *word = malloc (32 * sizeof(char));
13 char c;
14 while (i<=numofwords){
15 if ((c = getc (argv[1])) != EOF){
16 fscanf(argv[1],"%s",&word);
17 len = strlen (word);
18 words[i] = malloc ((len+1) * sizeof(char));
19 i++
20 }
21 printf(words[i]);
22 }
23 return 0;
24 }
25
May be I am correctly understood your need.
I am not rectifying your code but writing my own.
Below is simple code that read from console: code: main.c
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
if(argc!=2){
printf("\n wrong number of argument\n");
exit(1);
}
int numofwords = atoi(argv[1]);
char buffer[128];
//printf("%d\n",numofwords);
while(numofwords--){
scanf("%s",buffer);
printf("%s\n",buffer);
}
return 0;
}
How does it works:
~$ gcc main.c -o main
execute:
:~$ ./main
wrong number of argument
:~$ ./main 2
grijesh
grijesh
yourname
yourname
:~$
I hope its understood to you. the program simply read (scan) from console and print out to console. The while loop runs for number of time you pass on command line input.
Now, A text file dumy.txt a input file:
:~$ cat dumy.txt
yourname
myname
hisname
hername
:~$
Now see what you want to achieve through you code:
:~$ cat dumy.txt | ./main 2
yourname
myname
:~$
If you want to pass through echo :
:~$ echo $'one\ntwo\nthree' | ./main 2
one
two
:~$
Is this you want?
If yes:
What you miss understood that:
[your code]
(mistake 1,2)
Your fsacnf is wrong in two ways:
fscanf(argv[1],"%s",&word);
First argument is argv[1] is char* that is wrong you need to pass FILE* type. As explained in Mr. Oli Charlesworth's answer.
Second you still need to read from stdin. | operator redirects the output from first command to second command.
(mistake 3, 4, 5, 6)
By sending echo "blabla" you are just sending a single sting you need to do something like I did (I added \n in echo string for new line also my echo string start with $ so it not print as raw string). echo so that you can read from code according to second argument that is argv[1] not argv[2]. So in your code following line is wrong too.
int numofwords = atoi(argv[2]);
I corrected this line in my code.
and i is initialised to zero i = 0 , in while loop condition is <=, I think it should be <.
(mistake 7)
The way you run your code is wrong echo "blabla" | myprog 2 your program not know as mygrog you have to pass complete path. like I did ./main, ./ means current directory.
this just my view about your question. Read also the answer in comment given by Mr. William Pursell.
Let me know if you have other doubts.
I'm not sure exactly what your question is, but I think it may be "how do I treat a file input and console input the same?".
Are you aware that stdin (the standard input) is already a FILE *? So that means you can pass it as the first argument to fscanf, just like a "normal" file:
FILE *normal_file = fopen(...);
// Read from normal file
fscanf(normal_file, "%d", &x);
// Read from stdin
fscanf(stdin, "%d", &y);
An alternate choice would be pass the file name as an argument instead.
echo "blabla" | myprog 2 (number of words to print)
myprog 2 input.txt (number of words to print)
Then you'd:
if argc == 1, then proceed normally and process stdin (stdin is a FILE*) with fgetc, or another alternate f* method.
If argc == 2, then get the filename from argv[1], use fopen(filename) to get a FILE* and process it.
Otherwise, you would do what Oli said and get the first word, then either fopen and pass to your processing function, or fseek(stdin, SEEK_SET, 0) then pass stdin to your processing function.