Segfault when passing structure from main() to worker functions - c

I am trying to write a simple game in C and I'm getting a SEGFAULT and have no idea why!
Here is the code for the program:
#include <stdio.h>
#include <string.h>
#define MAX_PLYS_PER_GAME (1024)
#define MAX_LEN (100)
typedef struct {
char positionHistory[MAX_PLYS_PER_GAME][MAX_LEN];
} Game;
void getInitialGame(Game * game) {
memset(game->positionHistory, 0, MAX_PLYS_PER_GAME*MAX_LEN*sizeof(char));
}
void printGame(Game game) {
printf("Game -> %p (%d)\n", &game, sizeof(game));
fflush(stdout);
}
int hasGameEnded(Game game) {
printGame(game);
return 0;
}
int main(int argc, char *argv[]) {
Game game;
getInitialGame(&game);
if (hasGameEnded(game))
return -1;
return 0;
}
I tried debugging with gdb but the results didn't get me too far:
C:\Users\test>gdb test.exe
GNU gdb 5.1.1 (mingw experimental)
<snip>
This GDB was configured as "mingw32"...
(gdb) run
Starting program: C:\Users\test/test.exe
Program received signal SIGSEGV, Segmentation fault.
0x00401368 in main (argc=1, argv=0x341c88) at fast-chess-bug.c:29
29 if (hasGameEnded(game))
(gdb) bt
#0 0x00401368 in main (argc=1, argv=0x341c88) at fast-chess-bug.c:29

It is probably a stack overflow (really!), although I'm not sure.
You are declaring Game game; in main(). That means all 102400 bytes of game are going on the stack.
Both printGame and hasGameEnded take a Game game, NOT a Game * game. That is, they are getting a copy of the Game, not a pointer to the existing Game. Therefore, you dump another 102400 bytes on the stack whenever you call either one.
I am guessing that the call to printGame is clobbering the stack in a way that causes problems with the hasGameEnded call.
The easiest fix I know of (without getting into dynamic memory allocation, which may be better long-term) is:
Move Game game; outside of main(), e.g., to the line just above int main(...). That way it will be in the data segment and not on the stack.
Change printGame and hasGameEnded to take Game *:
void printGame(Game * game) {
printf("Game -> %p (%d)\n", game, sizeof(Game));
fflush(stdout);
}
int hasGameEnded(Game * game) {
printGame(game);
return 0;
}
That should get you moving forward.

You're likely running out of stack space.
C is pass-by-value. So this code
int hasGameEnded(Game game)
creates a copy of the entire struct {} Game, most likely on the stack.
If the following code works, you ran out of stack space:
...
void printGame(Game *game) {
printf("Game -> %p (%zu)\n", game, sizeof(*game));
fflush(stdout);
}
int hasGameEnded(Game *game) {
printGame(game);
return 0;
}
int main(int argc, char *argv[]) {
Game game;
getInitialGame(&game);
if (hasGameEnded(&game))
return -1;
return 0;
}
Note carefully the changes. Instead of passing the entire structure to hasGameEnded, it's now passing just the address of the structure. That change flows down the call stack, culminating in changes to printGame().
Note also that the proper format specifier for sizeof includes a z modifier. And I took the liberty of making it u for unsigned since a size can't be negative.

Related

How am I supposed to successfully achieve buffer overflow?

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".

How go back to another stack frame? C

EDIT:
thank alot
Im understanding now that I should use gdb
I ask for understand how stack frame working and how change things
exit(0) and goto its not option
How can change that fun 'sec' will return to main?
the output will be:
print start main
print this from first
print this from sec
print exit main
void sec()
{
/*change only here */
printf("print this from sec");
}
void first()
{
printf("print this from first");
sec();
printf("dont print this");
}
int main() {
printf("print start main");
first();
printf("print exit main\n");
return 0;
}
I dont want add asm code, only C.
I try to find the address of the rbp but I dont know how.
Disclaimer: this code should not exist. It is non-portable, makes a lot of assumptions, and relies on a gaping UB. Nevertheless,
#include <execinfo.h>
void sec()
{
/*change only here */
void * bt[4];
int size = backtrace(bt, 4);
while (bt[size] != bt[1])
size++;
bt[size++] = bt[2];
while (bt[size] != bt[2])
size++;
bt[size] = bt[3];
printf("print this from sec");
}
backtrace return an array of four pointers:
where backtrace should return,
where sec should return,
where first should return, and
where main should return.
The following two loops go up the stack looking for those addresses, and patches them to point to next frame.
Try to comment out the second loop, and observe that print exit main is printed twice. Do you see why?

Getting Segmentation Fault in C when using sleep with Pthreads

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.

Accessing the variable inside another code

Is there a way to access a variable initialized in one code from another code. For eg. my code1.c is as follows,
# include <stdio.h>
int main()
{
int a=4;
sleep(99);
printf("%d\n", a);
return 0;
}
Now, is there any way that I can access the value of a from inside another C code (code2.c)? I am assuming, I have all the knowledge of the variable which I want to access, but I don't have any information about its address in the RAM. So, is there any way?
I know about the extern, what I am asking for here is a sort of backdoor. Like, kind of searching for the variable in the RAM based on some properties.
Your example has one caveat, set aside possible optimizations that would make the variable to dissapear: variable a only exists while the function is being executed and has not yet finished.
Well, given that the function is main() it shouldn't be a problem, at least, for standard C programs, so if you have a program like this:
# include <stdio.h>
int main()
{
int a=4;
printf("%d\n", a);
return 0;
}
Chances are that this code will call some functions. If one of them needs to access a to read and write to it, just pass a pointer to a as an argument to the function.
# include <stdio.h>
int main()
{
int a=4;
somefunction(&a);
printf("%d\n", a);
return 0;
}
void somefunction (int *n)
{
/* Whatever you do with *n you are actually
doing it with a */
*n++; /* actually increments a */
}
But if the function that needs to access a is deep in the function call stack, all the parent functions need to pass the pointer to a even if they don't use it, adding clutter and lowering the readability of code.
The usual solution is to declare a as global, making it accessible to every function in your code. If that scenario is to be avoided, you can make a visible only for the functions that need to access it. To do that, you need to have a single source code file with all the functions that need to use a. Then, declare a as static global variable. So, only the functions that are written in the same source file will know about a, and no pointer will be needed. It doesn't matter if the functions are very nested in the function call stack. Intermediate functions won't need to pass any additional information to make a nested function to know about a
So, you would have code1.c with main() and all the functions that need to access a
/* code1.c */
# include <stdio.h>
static int a;
void somefunction (void);
int main()
{
a=4;
somefunction();
printf("%d\n", a);
return 0;
}
void somefunction (void)
{
a++;
}
/* end of code1.c */
About trying to figure out where in RAM is a specific variable stored:
Kind of. You can travel across function stack frames from yours to the main() stack frame, and inside those stack frames lie the local variables of each function, but there is no sumplementary information in RAM about what variable is located at what position, and the compiler may choose to put it wherever it likes within the stack frame (or even in a register, so there would be no trace of it in RAM, except for push and pops from/to general registers, which would be even harder to follow).
So unless that variable has a non trivial value, it's the only local variable in its stack frame, compiler optimizations have been disabled, your code is aware of the architecture and calling conventions being used, and the variable is declared as volatile to stop being stored in a CPU register, I think there is no safe and/or portable way to find it out.
OTOH, if your program has been compiled with -g flag, you might be able to read debugging information from within your program and find out where in the stack frame the variable is, and crawl through it to find it.
code1.c:
#include <stdio.h>
void doSomething(); // so that we can use the function from code2.c
int a = 4; // global variable accessible in all functions defined after this point
int main()
{
printf("main says %d\n", a);
doSomething();
printf("main says %d\n", a);
return 0;
}
code2.c
#include <stdio.h>
extern int a; // gain access to variable from code1.c
void doSomething()
{
a = 3;
printf("doSomething says %d\n", a);
}
output:
main says 4
doSomething says 3
main says 3
You can use extern int a; in every file in which you must use a (code2.c in this case), except for the file in which it is declared without extern (code1.c in this case). For this approach to work you must declare your a variable globally (not inside a function).
One approach is to have the separate executable have the same stack layout as the program in question (since the variable is placed on the stack, and we need the relative address of the variable), therefore compile it with the same or similar compiler version and options, as much as possible.
On Linux, we can read the running code's data with ptrace(PTRACE_PEEKDATA, pid, …). Since on current Linux systems the start address of the stack varies, we have to account for that; fortunately, this address can be obtained from the 28th field of /proc/…/stat.
The following program (compiled with cc Debian 4.4.5-8 and no code generator option on Linux 2.6.32) works; the pid of the running program has to be specified as the program argument.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
void *startstack(char *pid)
{ // The address of the start (i. e. bottom) of the stack.
char str[FILENAME_MAX];
FILE *fp = fopen(strcat(strcat(strcpy(str, "/proc/"), pid), "/stat"), "r");
if (!fp) perror(str), exit(1);
if (!fgets(str, sizeof str, fp)) exit(1);
fclose(fp);
unsigned long address;
int i = 28; char *s = str; while (--i) s += strcspn(s, " ") + 1;
sscanf(s, "%lu", &address);
return (void *)address;
}
static int access(void *a, char *pidstr)
{
if (!pidstr) return 1;
int pid = atoi(pidstr);
if (ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) return perror("PTRACE_ATTACH"), 1;
int status;
// wait for program being signaled as stopped
if (wait(&status) < 0) return perror("wait"), 1;
// relocate variable address to stack of program in question
a = a-startstack("self")+startstack(pidstr);
int val;
if (errno = 0, val = ptrace(PTRACE_PEEKDATA, pid, a, 0), errno)
return perror("PTRACE_PEEKDATA"), 1;
printf("%d\n", val);
return 0;
}
int main(int argc, char *argv[])
{
int a;
return access(&a, argv[1]);
}
Another, more demanding approach would be as mcleod_ideafix indicated at the end of his answer to implement the bulk of a debugger and use the debug information (provided its presence) to locate the variable.

swapcontext() segmentation fault

I am trying to create a simple hello world example using swapcontext()
Here is the code snippet:
#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
static ucontext_t uctx_main, uctx_func1;
typedef struct test_struct
{
ucontext_t context;
int value;
}test_struct;
test_struct* array[10];
static void
func1(void)
{
printf("func1: started\n");
printf("func1: TESTING\n");
printf("func1: returning\n");
}
void init()
{
memset(array,NULL,10);
array[0] = (test_struct*)malloc(sizeof(test_struct));
array[0]->value = 10;
getcontext(&array[0]->context);
char* func1_stack = (char*)malloc(sizeof(char)*64);
//char func1_stack[64];
array[0]->context.uc_stack.ss_sp = func1_stack;
array[0]->context.uc_stack.ss_size = 64;
array[0]->context.uc_link = &uctx_main;
makecontext(&array[0]->context, func1, 0);
}
int main(int argc, char *argv[])
{
init();
printf("VALUE: %d\n",array[0]->value);
swapcontext(&uctx_main, &array[0]->context);
printf("VALUE: %d\n",array[0]->value);
printf("main: exiting\n");
exit(0);
}
But the problem is when the progam executes swapcontext() a segmentation fault occurs. I have fiddled around a bit and I figured out that the problem is the stack size that I am assigning to the context but I don't know what I am doing wrong.
P.S. I have tried assigning sizeof(func1_stack) but still got a seg fault
Can anyone give me a hint?
Using 64 as the stack size as coded is consistent with the actual given stack size. However, 64 bytes is fairly small for a stack. The example here uses 16K as the stack size. It may be that the size you are using is simply too small.
As an aside, the memset is probably not correct. It is setting the first 10 bytes of the array. It is not actually affecting anything, but it should probably be the following:
memset(array,0,sizeof(array)));

Resources