I'm trying to make a code in C that can get environment variable and then search for a specific word from that result using strstr. I'm using UBUNTU OS and gcc compiler. Here is the code that I've written. The comment are what I expected to happen.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
extern char **environ;
extern char **tmp;
extern char **tmp2;
char *search_string(char *tmp,int x)
{
char string[]="ABC"; //I'm looking for ABC in the environment variable
char *pointer;
pointer=strstr(tmp,string); //pointer will point to the result of strstr
if(pointer != NULL)
{ printf("%s ,",tmp);
printf("data found : %s \n",pointer);
} else {
//hope to do something
}
return (pointer);
}
int main(char *tmp2)
{
int x = 0;
for(x=0;environ[x]!='\0';x++){ //I'm expecting it to keep looping until finish
tmp2=search_string(environ[x],x); //tmp2 will point to the function return value
printf("%s\n",tmp2); //print the return value
} //If the search_string return NULL, does it consider string or something else?
return 0;
}
After running the code, it crashes because of core dump. Here are the output.
ABC=/tmp ,data found : ABC=/tmp
ABC=/tmp
Segmentation fault (core dumped)
From what I see, it can only do the search_string for only 1 time. Then it crashes. Then I use gdb to find out at what line does it actually crash and here are the result:
Starting program: /home/fikrie/a.out
ABC=/tmp ,data found : ABC=/tmp
ABC=/tmp
Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99 ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
What I dont understand from the debug is that it's receiving error because of SEGV signal. Can someone point me on how to solve this problem? Is it because the search_string returns a NULL value?
The problem is that if search_string() doesn't find the string, it returns NULL. You then pass that NULL to printf(), which crashes.
In main(), you need something like:
if (tmp2)
printf("%s\n", tmp2);
Also, the tmp2 variable should be of type char *, not char **. And there's no reason not to declare it local to main().
A very simple change to your main loop stops the program from crashing:
int main(char *tmp2)
{
int x = 0;
for(x=0;environ[x]!='\0';x++){ //I'm expecting it to keep looping until finish
tmp2=search_string(environ[x],x); //tmp2 will point to the function return value
// >>>>> change these next two lines:
if(tmp2 != NULL) printf("%s\n",tmp2); //print the return value
else printf("%s does not contain ABC\n", environ[x]);
// <<<<< end of change
} //If the search_string return NULL, does it consider string or something else?
return 0;
}
Note that if you only expect one match, you could add a break; when you print the match. The above code prints out all the environment variables - you can see it doesn't stop...
Related
I am currently tackling on an assignment, where I need to upload exploit.c and target.c onto a ubuntu server, and successfully achieve a buffer overflow attack with exploit onto target. I was provided a shellcode. Now, target.c is not to be altered, just exploit.c. I had to use GDB on exploit.c to force an external breakpoint on foo() from target.c, to figure out the return addresses using info frame.
I was provided with the working shellcode, and minimal instructions.
I am pretty sure I was able to successfully pull the return addresses, but my issue is that I cannot figure out what code to put into exploit.c to have it successfully perform a buffer overflow attack. I was also instructed that one of the return addresses must be input into the exploit code for it to function properly.
I understand that the exploit is trying to call back to the return address, to then push itself into the buffer, so I can obtain access to the shell.
Here is exploit.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "shellcode.h"
// replace this define environment to have the correct path of your own target code
#define TARGET "/*******************"
int main(void)
{
char *args[3];
char *env[2];
char *tmp = NULL;
// Creating an input buffer that can cause buffer overflow in strcpy function in the target.c executable code
int buffSize = 1000;
char buff[buffSize];
// Intialize buffer elements to 0x01
int i;
for (i=0; i < buffSize; i++) buff[i] = 0x01;
// write your code below to fill the 22 bytes shellcode into the buff variable, and
// at the correct location overwrite the return address correctly in order to achieve stack overflow
// Your own code starts here:
strcpy (buff[buffSize-22], shellcode);
// Your code ends here.
// prepare command line input to execute target code
args[0] = TARGET; // you must have already compiled and generated the target executable code first
args[1] = buff; // the first input parameter to the target code (artfully crafted buffer overflow string)
args[2] = NULL;
env[0] = "FOO=bar";
env[1] = NULL;
if (0 > execve(TARGET, args, env))
fprintf(stderr, "execve failed.\n");
return 0;
}
Here is the target.c code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int foo(char* arg)
{
char localBuf[240];
short len = 240;
float var1=2.4;
int *ptr = NULL;
strcpy(localBuf, arg);
printf("foo() finishes normally.\n");
return 0;
}
int kbhit(void)
{
struct timeval tv;
fd_set read_fd;
tv.tv_sec=0; tv.tv_usec=0;
FD_ZERO(&read_fd); FD_SET(0,&read_fd);
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
return 0;
if(FD_ISSET(0,&read_fd))
return 1;
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "target: argc != 2\n");
exit(EXIT_FAILURE);
}
printf("Press any key to call foo function...\n");
while(!kbhit())
;
foo(argv[1]);
return 0;
}
I compiled both target and exploit. Then I ran GDB on exploit, and formed a breakpoint using "break target.c:10". Using Info Frame I was able to obtain the return addresses.
I used strcpy, because it is essentially the only line of code we were taught for this section involving overflow attacks, even though it clearly states in the document "Fill the shell executable code (in the string array shellcode[]) byte-by-
byte into the buff for your modified return address to execute, do not
use strcpy() because shellcode[] is not an ASCII string (and not
copying NULL byte, too)."
Exploit compiles fine, and it runs fine, but it does not give me access to a shell. I was instructed that I would know if it worked, if I was presented with two dollar signs ($$) instead of one ($).
I am a network engineer, and I am not entirely savvy with C, or attacking vulnerabilities in programs, any help would be appreciated. The entire lesson revolves around "stack overflow", but this assignment is called "buffer overflow attack".
I am creating a thread in C with PThreads which executes a function that is running in an infinit loop and prints some random json string every second into the console. At the beginning he prints the result of the function simulateLED with no problem, but after sleeping for 1 second, I'll get a Segmentation Fault (Core dumped). If I remove sleep, I'll not get it and the program works fine. Why do I get a Segmentation Fault with sleeping and how to fix it?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *simulateLED() {
int temp;
int luftf;
char* jsonString;
time_t t;
srand((unsigned) time(&t));
int x=-10, y=50;
temp=(rand()%((y+1)-x))+x;
x=2, y=30;
luftf=(rand()%((y+1)-x))+x;
printf("%d %d\n", temp, luftf);
fflush(stdout);
sprintf(jsonString, "{\n\"TEMP\": %d,\n\"HUMI\": %d\n}", temp, luftf);
return jsonString;
}
void *simAndSendThread(void *param) {
while(1) {
printf("%s", simulateLED());
sleep(1);
}
}
int main(int argc, char *argv[]) {
pthread_t thread;
if(pthread_create(&thread, NULL, simAndSendThread, NULL)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
if(pthread_join(thread, NULL)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
pthread_exit(NULL);
return 0;
}
As #DavidSchwartz has pointed out, the reason for the Segmentation fault (core dumped) error is related to the jsonString pointer, that is currently not initialized (i.e., not pointing to anything). Hence, sprintf is writing to a random location, which might or might not work at times.
In order to fix it, you can statically assign space to the jsonString variable when you declare it, such as:
...
char jsonString[256];
...
This implies that you can have a string up to 255 characters (1 extra character reserved for \0). Alternatively, you can dynamically allocate the space using malloc:
...
char *jsonString = (char *)malloc(sizeof(char) * 256);
// Your code here
free(jsonString);
...
In this case, you must remember to release the allocation at the end of your function using free, otherwise you will leak memory. In case you haven't learned about dynamic memory yet, see When and why to use malloc?.
P.S.: If you are on Linux, I strongly recommend to use valgrind when you have memory-related errors. This tool will most probably hint where did you made the mistake. Check the Valgrind Quick Start Guide for more information.
You haven't allocated memory to jsonString and still trying to do sprintf and after return print
Try this
char* jsonString;
jsonString = malloc( 1024 );
And don't forget to free once done, you are using a while(1) and if you don't free there is every chance that you'll hit the out of memory error very soon.
If you enable full warnings you should have received a warning message for uninitialized variable for which eventually would have avoided all the crahes.
I am trying to get name of the input, output, and data files from the array for further processing. However, I am getting a weird error or problem. So, my program is not reaching the for loop. It does not even print the statement before the for loop. However, I tried using the debugger and the program is correctly printing step by step. So, when I run it does not print and when I debug step by step it prints. That is Weird!
char *method;
method=malloc(25);
method=NULL;
char *dataFileName;
char *inputMethod;
inputMethod=malloc(25);
inputMethod=NULL;
char *inputFileName;
char *outputMethod;
outputMethod=malloc(25);
outputMethod=NULL;
char *outputFileName;
char *commandArray[]={"if=q.txt","of=output.txt"};
char**args=(char**) malloc(sizeof(char*)*256);
args=commandArray;
int i;
printf("Before second for");
for(i=0;i<2;i++)
{
printf("I am here");
if(*args[i]=='d')
{
method=strtok_r(args[i],"=",&dataFileName);
printf("The method given is %s",method);
printf("Data File Name is %s",dataFileName);
}
else if(*args[i]=='o')
{
outputMethod=strtok_r(args[i],"=",&outputFileName);
printf("The output method given is %s",outputMethod);
printf("output File Name is %s",outputFileName);
}
else
{
inputMethod=strtok_r(args[i],"=",&inputFileName);
printf("The input method given is %s",inputMethod);
printf("Input File Name is %s",inputFileName);
}
}
if(method==NULL)
{
dataFileName=malloc(256);
printf("Please Enter A File Name");
scanf("%255s",dataFileName);
printf("%s",dataFileName);
}
if((inputMethod==NULL)||(outputMethod==NULL) )
{
char* array[]={"stdin","stdout"};
if(inputMethod==NULL)
inputMethod=array[0];
if(outputMethod==NULL)
outputMethod=array[1];
}
I am developing using Netbeans in C. The above code is written inside main. Thanks!
i intentionally left the previous answer because understanding memory allocation is trivial in programming in c specially. and as i see you have a big issue with that.
but still you have issue in nearly every thing. in my actual answer, i will try to simplify you how to use strtok, to split string and parse it. i guess this is the second main problem with your code.
the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char commandArray[][256]={
"if=q.txt",
"of=output.txt"
};
char infile[256], outfile[256];
for(int i=0; i<2;i++){
char *ptr,*cmd;
cmd=commandArray[i];
ptr=NULL;
printf("parsing command '%s'\n",cmd);
cmd=strtok(cmd,"=");
ptr=strtok(NULL,"=");
if(!cmd){
printf("Error parsing the string '%s'\n",commandArray[i]);
exit(1);
}
if (strcmp(cmd,"if")==0){
strcpy(infile,ptr);
}
else if (strcmp(cmd,"of")==0){
strcpy(outfile,ptr);
}
else{
printf("unknow token '%s'\n",cmd);
exit(1);
}
}
printf(
"\n\n"
"input file: '%s'\n"
"output file: '%s'\n"
"\n\n",
infile,outfile);
return 0;
}
the main problem is this:
char *method;
method=malloc(25);//allocating space for 25 char
method=NULL; // throwing up the allocation without freeing it;
// now the allocation is lost
// now method is useless (it is null)
Can anyone tell me how this code gets an input, as well as how this code is vulnerable to an arc injection by buffer overflow??
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
Sets Size to 65
enum {SIZE = 65};
Variable that I'm trying to change
int True = 0;
char name[SIZE];
FILE *f;
int i = 0;
How does this read from a file?
void read(char *s) {
int c;
char buffer[SIZE];
for (;;)
{
c = getchar();
if ((c == EOF) || (c == '\n'))
break;
buffer[i] = c;
i++;
}
buffer[i] = '\0';
for (i = 0; i < SIZE; i++)
s[i] = buffer[i];
}
int main(void) {
read(name);
if (!True)
printf("%s: You are a hacker\n", name);
else
printf("%s: You are not a hacker\n", name);
How can you not use a return value?
exit(0);
}
This code gets an input through 'stdin;. By default, this would be done by keyboard input. However, it may also possible to 'pipe' the content of a file into 'stdin' when loading the program on the command line.
This code is vulnerable to an arc injection by buffer overflow. Specifically, if more than 65 characters are copied into 'name' array, the value of 'True' will be overwritten. Most likely, this will change the value of 'True' to a non-zero value. This will reverse the 'if (!True)' and cause the line 'printf("%s: You are a hacker\n", name);' to execute.
This is the line that can cause buffer overflow
buffer[i] = c;
since you are not checking whether i is within bounds before that statement.
When that happens, you are most likely going to override the part of stack frame that contains code since there is no other function variable after buffer.
I ran the program by piping the contents of a file that contains 100 As in it to the stdin of the program. I got the following message, which confirmed my suspicion.
>> cat test-121.in | ./test-121
*** stack smashing detected ***: ./test-121 terminated
Aborted
I don't see how that could change the value of True at all.
BTW, you have:
if (!True)
printf("%s: You are a hacker\n", name);
else
printf("%s: You are not a hacker\n", name);
did you mean if (True)?? You have initialized True to 0.
Update
You asked: How can you not use a return value?
Answer: return statement is optional for main. Here's a section of the description of main from http://en.cppreference.com/w/cpp/language/main_function.
(4) The body of the main function does not need to contain the return statement: if control reaches the end of main without encountering a return statement, the effect is that of executing return 0;
Whenever i try to do:
char buffed[1024];
snprintf(buffed, sizeof(buffed), "bash.sh %s &", get_value("request-uri"));
system(buffed);
this is the function I use:
char *get_value(char *name) {
FORMAT_NODE *node;
#ifdef DEBUG
ASSERT(name);
#endif
if (strlen(name) == 0)
return EMPTY_FIELD;
if ((node = get_field(name))) {
return node->value;
} else {
return EMPTY_FIELD;
}
}
Compiling is okay but whenever it should print the value it gives a segmentation fault and crashes, can someone explain me what I am doing wrong?
Thanks in advance!
edit:
get_value("request-uri") is the one im talking about and it should be a string
strstr(get_value("request-uri"), "index.php") works perfectly!
but "index.php" should come from get_value
edit2:
gdb:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff73f3321 in __strlen_sse2 () from /lib64/libc.so.6
The problem here was solved by CBIII for telling me to use gdb, the value was empty because it flushed before it was used.
get_value("request-uri") returned 0x0