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?
Related
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.
I have a very rudimentary understanding of C (though I do understand programming concepts in general). I have an assignment to create a buffer overflow that yields something (like access to unauthorized area, free money, etc.) and not just crash the program.
I've tried different sized buffers and can always "crash" the program but I can't get it to launch any code (i.e., /bin/su). Am I approaching this incorrectly?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <string.h>
#define BUFSIZE 20
int main() {
int month=12;
int day=31;
int year=2016;
int confirm = 0;
double dollars = 5.00;
char *sitenum="97871";
char acctnum[BUFSIZE];
printf("Welcome to the Acme AP-AR System. This is the Accounts Receivable module. \n");
/* Gathering date information */
printf("Please enter the month of transaction as an integer value (2 digits). \n");
printf("For example, July would be 07, December would be 12. Please input the month: ");
for (;;) { /* Start of month input validation loop */
scanf("%d", &month);
if(month>=1 && month<=12) {
printf("Validated. \n");
break;
}
else {
printf("Please enter a value between 1 and 12! \n");
continue;
}
} /* End of month input validation loop */
printf("\nPlease enter the day of transaction as an integer value (2 digits). \n");
printf("For example, the 3rd would be 03, the 25th would be 25. Please input the day: ");
for (;;) { /* Start of day input validation loop */
scanf("%d", &day);
if(day>=1 && day<=31) {
printf("Validated. \n");
break;
}
else {
printf("Please enter a value between 1 and 31! \n");
continue;
}
} /* End of day input validation loop */
/* Gathering sender account number */
printf("\nPlease enter the sender Account Number: ");
scanf("%s", acctnum);
/* Gathering transaction amount */
printf("\nPlease enter the USD amount (including cents) received: $ ");
scanf("%lf", &dollars);
/* Confirming data entry */
printf("\nTransaction information.\n Date: %d-%d-%d \n", month,day,year);
printf("Account: %s-%s \n", sitenum, acctnum);
printf(" Amount: $ %.2lf \n", dollars);
printf("\nProcess transaction information? (Yes=1/No=0) ");
for (;;) { /* Start of confirmation validation loop */
scanf("%d", &confirm);
if(confirm==1) {
printf("Transaction processed. \n");
break;
}
else {
printf("Transaction voided! \n");
break;
}
} /* End of confirmation validation loop */
return (EXIT_SUCCESS);
}
When executing, if you enter 25 characters for the day of month, the program will continue until the end. Only after the last input does it terminate with the stack smashing error. I'm afraid I'm trying to do something that can't be done, but a day (literally, the past 8 hours) of Google searches hasn't yielded an example that I've been able to use.
Can someone push me in a different direction that will get me close to what I'm trying to achieve? Thanks.
You will need an in-depth understanding of the target architecture (x86, x86-64, etc.) to accomplish that. A typical approach would involve carefully constructing the contents of the buffer overflow so that it 1) contains the code you wish to run when the input data is reinterpreted as machine instructions, and 2) overwrites the return address of the stack frame so that it jumps into your code instead of returning to the calling function.
I don't feel comfortable providing code that actually does this, but it's certainly possible to do.
EDIT: By the way, I don't think the assignment was intended to require actually running arbitrary code. I'm guessing based on the code you posted that you're supposed to just overwrite part of the stack so that it looks like you're accessing a different "sitenum". That's definitely possible since the sitenum pointer is going to be stored after acctnum in the stack (at least typically). So if you craft your buffer overrun carefully, you can change the sitenum pointer to point somewhere else. For example, (assuming the sitenum pointer is immediately after acctnum in the stack), you could input 1 extra character into the acctnum, and the null terminating character will overwrite the least significant byte of the sitenum pointer, which most likely will point to a different location then.
In my view, it's a terrible assignment though, because 1) the stack can be arranged differently based on a large number of factors, and 2) most modern development environments will default to adding runtime checks to prevent this kind of stack corruption. For example, in MS Visual C++, you would have to go out of your way to disable the Basic Runtime Checks and Buffer Security Check features to avoid an exception.
Anyway, hope that helps.
Here's a simple example of overwriting the return address on the stack to execute another function(will then promptly crash). Works in Windows VS2015 on x86.
#include "stdafx.h"
void hello()
{
printf("hello world!\n");
}
void run(int a)
{
int * ret = &a;
--ret; // stack grows downward on x86
*ret = (int)hello;
}
int main()
{
int a = 42;
run(a);
printf("this won't print\n");
}
Here's another simple example(VS2015/x86) that saves the return address first, and then after hello() is executed, will put the return address to main() back on the stack. Notice it starts first with a local variable declared in run() and not one passed in as an argument. It comes down to understanding what order the return address, arguments passed, the direction the stack goes, and where the current stack frame starts. You'll probably get notification of failing a run time check in your debugger environment after execution, but you should see this printed to the console:
hello world
main
#include "stdafx.h"
int saveret;
void hello()
{
int a = 43;
printf("hello world!\n");
// put saved return address to main() back on stack
int * ret = &a;
ret += 4;
*ret = saveret;
}
void run()
{
int a = 42;
int * ret = &a;
ret += 4; // stack grows downward on x86
saveret = (int)*ret;
*ret = (int)hello;
}
int main()
{
run();
printf("main\n");
}
Hi I want to ask about setjmp/longjmp. I tried to search, but I was unsucessuful...
#include <stdio.h>
#include <setjmp.h>
jmp_buf a, b;
void jump() {
int aa = setjmp(a);
if (aa)
{
printf("Jump!\n");
}
else
{
longjmp(b, 1);
printf("Should not happened...\n");
}
printf("End of function!\n");
}
int main(int argc, char** argv) {
int bb = setjmp(b);
if (bb)
{
longjmp(a, 1);
printf("Should not happened...\n");
}
else
{
jump();
printf("What here?\n");
}
printf("Exit\n");
return 0;
}
The question is, what will happen after last printf in jump()... I tried this code and it turned into infinite loop. Why? I though that setjmp will store environment data, so the jump function shall return after it's original call... I'm quiet confused. Thanks for reply :)
The whole program has undefined behavior.
setjmp(b); stores the stack state.
jump() is called.
`setjmp(a);' stores the stack state again.
longjmp(b, 1); restores the stack to the point before jump() was ever called. So the state stored in a is now invalid.
Execution continues at the if in main().
longjmp(a, 1); is called. Ouch. This causes undefined behavior due to 4 above.
Your confusion probably results from the slightly imprecise use of the world "return" in the Linux docs for setjmp().
The stack context will be invalidated if the function which called setjmp() returns.
In your example, the function jump() didn't return in the normal way, but the effect was the same: the stack was "chopped" by the first longjmp() to the state before jump(), which is what a return does, too.
I am using setjmp and longjmp for the first time, and I ran across an issue that comes about when I wrap setjmp and longjmp. I boiled the code down to the following example:
#include <stdio.h>
#include <setjmp.h>
jmp_buf jb;
int mywrap_save()
{
int i = setjmp(jb);
return i;
}
int mywrap_call()
{
longjmp(jb, 1);
printf("this shouldn't appear\n");
}
void example_wrap()
{
if (mywrap_save() == 0){
printf("wrap: try block\n");
mywrap_call();
} else {
printf("wrap: catch block\n");
}
}
void example_non_wrap()
{
if (setjmp(jb) == 0){
printf("non_wrap: try block\n");
longjmp(jb, 1);
} else {
printf("non_wrap: catch block\n");
}
}
int main()
{
example_wrap();
example_non_wrap();
}
Initially I thought example_wrap() and example_non_wrap() would behave the same. However, the result of running the program (GCC 4.4, Linux):
wrap: try block
non_wrap: try block
non_wrap: catch block
If I trace the program in gdb, I see that even though mywrap_save() returns 1, the else branch after returning is oddly ignored. Can anyone explain what is going on?
The longjmp() routines may not be called after the routine which called
the setjmp() routines returns.
In other words, you are screwing up your stack.
You might take a look at the assembly to see if you can piece together what's really happening.
setjmp() will save the current call stack and mark a point. When the call stack grows, no matter how far from the marked point, you can use longjmp() to go to the marked point, like you never left the point.
In your code, when returning from mywrap_save(), the marked point was no longer valid, the stack space around the point was dirty, hence you cannot go back to a dirty point.
I have a bit of queue code that I was working on. I was trying to use a global int to keep track of the queue's size.
#define MAX 100
int size=0;
int gEnqueue=gDequeue=0;
int enqueue()
{
gEnqueue++;
if( size == MAX )
return QUEUE_FULL;
/* snip the actual queue handling */
size++;
return 0;
}
int dequeue()
{
gDequeue++;
if(!size)
return QUEUE_EMPTY;
/* snip actual queue handling */
if(size)
size--;
return 0;
}
there is of course much more code then that, but too much to post.
What is happening is the size gets stuck at the max I have set. Both functions get called an even number of times. If I dump the queue I can see that there are only 3 items in it.
What would cause this problem?
edit #1: made the code example match what I actually coded
This is not threaded.
edit #2: I am an idiot and should have done this instead of assuming.
I was wrong about the calls being even to the enqueue() and dequeue().
Note to self, use real metrics not guesses.
If you can't use a debugger I would suggest adding print statements inside both functions showing what size equals and then after running the program examine the output. Usually when looking at the print log the problem is pretty obvious.
The easiest solution is not to call "enqueue" if size==MAX.
But if that's not possible try this:
int size=0;
int overflow=0;
int enqueue()
{
if( size < MAX )
size++;
else
overflow++;
return 0;
}
int dequeue()
{
if(overflow)
overflow--;
else if(size)
size--;
return 0;
}
There's nothing obviously wrong with the code you posted, so this suggests there's something wrong with the code you snipped, or in the way you're calling the code. You'll have to debug this for yourself. There are two main debugging techniques that would help you at this point:
As #KPexEA suggested, debugging using printf() or other logging statements. Put a printf() at the beginning and end of both functions, printing out as much state as you think might possibly be useful.
int enqueue()
{
printf("enqueue(): Enter: size=%d\n", size);
if( size == MAX ) {
printf("enqueue(): Exit: QUEUE_FULL\n");
return QUEUE_FULL;
}
/* snip the actual queue handling */
size++;
printf("enqueue(): Exit: size=%d\n", size);
return 0;
}
int dequeue()
{
printf("dequeue(): Enter: size=%d\n", size);
if(!size) {
printf("dequeue(): QUEUE_EMPTY\n");
return QUEUE_EMPTY;
}
/* snip actual queue handling */
if(size)
size--;
printf("dequeue(): Exit: size=%d\n", size);
return 0;
}
By examining the output, it should become apparent what's happening with the size of your queue. (You could also count the actual number of elements in your queue and print that when you enter and exit your functions.)
The other technique is interactive debugging. This is especially useful to determine exactly how your code is flowing, but you have to sit there every time you run your program to watch how it's running. (If your bug occurs every time, that's easy; if it occurs every once and a while, it's hard to go back and recreate your program's flow after the fact.) Set a breakpoint at the beginning of each of your functions and use the debugger to display the value size. Set another breakpoint at the end of each function and make sure (1) the breakpoint actually gets hit, and (2) your expectations of any changes made to size are met.