Go directly to specific parts of a function

I would like to make it clear how to complete this puzzle. I need to be able to print what would normally print in reverse order. Usually it prints hello there

. I need to print there hello

. I am allowed to add code where it is commented out.

Here are some of my thoughts that are not working.

  • I was thinking about using heap to store some data, but can't because it is stdlib.h

    not included.
  • Unable to use goto

    because I cannot add labels and that I would be goto

    all on one line
  • You cannot use recursion because there are no props and global variables to modify.
  • Can't think of how assembly can help, but maybe, maybe?
  • I can't do anything obvious how to just call printf

    and exit the program earlier.
  • Thoughts on something to do with function pointers? I still don't understand how they will help.

#include <stdio.h>
void f1(); void f2(); void f3();

int main() { f1(); printf("\n"); return 0; }

void f1() { f2(); printf(" there "); }

void f2() { f3(); printf(" hello "); }

void f3(){
    int x;
    //Can add whatever under here
}

      

+3


source to share


4 answers


I think the only purpose int x;

is to get the stack pointer without using inline assembly.

The decision on how to do this will depend on your platform, the compiler you are using, and the optimization levels.

I would say first you need to analyze the call stack.

You can do it -

int i;
for (i = 0; i< 10; i++) {
     printf ("%p\n", *(void**)((char*) &x - i * 8)); // I am assumming 64 bit machines. If 32 bit replace 8 with 4
}

      

This will give you the top 10 8 byte values ​​on the stack. Now you need to find two that look like return addresses. One way to recognize them would be to print the value of the function pointer f1 and f2 and see the values ​​close to them.



Now you know the indexes in which they are stored. Just go ahead and change them.

To replace them, say, indices 12 and 14.

Then you can do this -

*(void**)&x = *((void**)&x + 12);
*((void**)&x + 12) = *((void**)&x + 14);
*((void**)&x + 14) = *(void**)&x;

      

Also make sure you don't change the stack structure after getting the indices. This means you are not deleting / adding any variables. Do not apply the operator to any new variables (or remove them from any) and do not remove any function calls.

Also another suggestion. Instead of using int x, you can declare another unsigned long long y and use that instead of swap. Because it will have enough bytes to hold the pointer (on 64-bit machines). Usually, in the case of int x, padding will be added which should save you the problem, but rather be safe.

+2


source


Here's an alternative solution that doesn't depend on stack manipulation. The main "trick" is that the program provides its own implementation printf()

instead of using the standard library.

Tested on gcc (Mingw, Linux x86 and Linux x64) and MSVC:



#include <stdio.h>
void f1(); void f2(); void f3();

int main() { f1(); printf("\n"); return 0; }

void f1() { f2(); printf(" there "); }

void f2() { f3(); printf(" hello "); }

void f3(){
    int x;
    //Can add whatever under here
    return;
}

void putstr( char const* s)
{
    for (;*s;++s) {
        putchar(*s);
    }    
}


int printf(char const* fmt, ...)
{
    static char const* pushed_fmt = 0;

    if (*fmt == '\n') {
        putstr(fmt);
        return 0;
    }

    if (pushed_fmt == 0) { 
        pushed_fmt = fmt;
        return 0;
    }

    putstr(fmt);
    putstr(pushed_fmt);

    return 0;
}

      

+2


source


I think the idea is that from f3 () you have return addresses on the stack up and nothing has been printed so far.

You will have to play with the contents of the stack so that f3 () returns to f1 (), which then returns to f2 ().

Can you take it from here? There will be different ways to do this, depending on the compiler. Inline assembly may or may not be needed.

EDIT: Specifically for GCC, see GCC's built in return interface .

+1


source


It should be a portable solution that doesn't tamper with the stack and returns addresses. This is most likely not what was expected of the person who wrote this challenge, but it is much more fun to think out of the box.

void f3(){
    int x;
    //Can add whatever under here
    static count = 0;
    static char buf[256];
    if(count==0) {
        setvbuf(stdout, buf, _IOFBF, sizeof(buf));
        int atexit (void (*func)(void)); 
        atexit(f3);
        count = 1;
    } else {
        const char *src = " there  hello \n";
        char *dest = buf;
        for(; *src;) *dest++ = *src++;
    } 
}

      

http://ideone.com/S4zMHP

This works by first using setvbuf

to replace the buffer stdout

with the one we provide and switching it to full buffering (instead of line buffering) to make sure no flush occurs until the end of the program (note that no output has been written yet, so the call setvbuf

is legal). We also call atexit

to make sure we are called until the end of the program (we don't stdlib.h

, but who needs headers when the required prototypes are already known).

When we call again (thanks atexit

), two are called printf

, but the buffer has not been cleared yet. We completely replace its content with a range of our interests (which is as great as what was written) and come back. The next implicit one fclose

will dump the changed contents of our buffer instead of what was written printf

.

+1


source







All Articles