-3

The code of the c program is shown below, and what it is supposed to do is running the opcode in a char array, which in turn would spawn a shell.

/* call_shellcode.c */
/*A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char code[] =
"\x31\xc0" /* Line 1: xorl %eax,%eax */
"\x50" /* Line 2: pushl %eax */
"\x68""//sh" /* Line 3: pushl $0x68732f2f */
"\x68""/bin" /* Line 4: pushl $0x6e69622f */
"\x89\xe3" /* Line 5: movl %esp,%ebx */
"\x50" /* Line 6: pushl %eax */
"\x53" /* Line 7: pushl %ebx */
"\x89\xe1" /* Line 8: movl %esp,%ecx */
"\x99" /* Line 9: cdq */
"\xb0\x0b" /* Line 10: movb $0x0b,%al */
"\xcd\x80" /* Line 11: int $0x80 */
;
int main(int argc, char **argv)
{
char buf[sizeof(code)];
strcpy(buf, code);
((void(*)( ))buf)( );
}

The shellcode(the opcode contained in the char array) itself runs perfectly when written in assembly and compiled by assembler, and I got the opcode from disassembling the executable file compiled by assembler.

WHY is it not working when it's put inside this C program?

cadaniluk
  • 15,027
  • 2
  • 39
  • 67
glenjoker
  • 91
  • 7
  • 3
    Maybe due to the protection of OS? – MikeCAT Dec 01 '15 at 14:05
  • 4
    What OS are you using? Shellcode is in .data part of that executable most current OS will prevent it's execution it's called DEP (Data Execution Prevention) I think. – J91321 Dec 01 '15 at 14:09
  • Compile using `gcc -z execstack`. – Jester Dec 01 '15 at 14:15
  • Try to disassemble your binary, and debug it. It hard to say whats wrong. – Yuriy Orlov Dec 01 '15 at 14:16
  • The assembly is calling `int 0x80` which is the linux sys call gate on 32 bit machines. Are you running on 64? – user2697817 Dec 01 '15 at 14:40
  • @glenjoker I would not use strcpy for copying binary data, since it stops at a nul byte – user877329 Dec 01 '15 at 14:40
  • @Kay, with exception that this is a piece of self-modifying code. I would say DEP. – user877329 Dec 01 '15 at 14:41
  • @J91321 sorry that I forgot to mention, my distribution is 64-bit Ubuntu version14.04. I compiled the c program with command "gcc -z execstack -o code code.c", so I guess whether it is executable would not be a issue here? – glenjoker Dec 02 '15 at 02:08
  • @Jester I did compile it with that command, and the segmentation fault followed. – glenjoker Dec 02 '15 at 02:10
  • @user877329 yes, I am running on 64-bit OS, but I compiled and linked the assembly code using "nasm -f elf shellcode.asm" and "ld -m elf_i386 -o shellcode shellcode.o". I got the C program code from my prof, and I guess strcpy is exactly what he intended to make us find a way not containing any zeros in the shell code. – glenjoker Dec 02 '15 at 02:17
  • Since you are in 64 bit, you should have compiled with `gcc -m32 -z execstack -o code code.c` – Jester Dec 02 '15 at 10:10

2 Answers2

0

Your assembly code is called as a function. Your compiler will most likely generate a call instruction to call the function. Thus the return address will be on the stack. Since your assembly doesn't contain a ret instruction to pop this off and return back to the caller, after the last instruction in your assembly code, your program will try to execute whatever is located right after it. This is what is causing the segmentation fault. Add a ret instruction at the end of the assembly to solve it.

EDIT: After inspecting your assembly a little more thoroughly. You seem to use string literals within your assembly as well. But since you're already executing the program (no assembler will look at it no more), these will not be converted to addresses of a string. So replace the /bin and /sh in your assembly with the addresses of the actual string.

Shadowwolf
  • 973
  • 5
  • 13
  • This is a good point, but execve does never return so this does not apply in this case. – user877329 Dec 01 '15 at 14:37
  • "You seem to use string literals", I missed that. And, if the OS allows execution from the stack, the program should sigsegv in execve, which tries to dereference a pointer to...??? – user877329 Dec 01 '15 at 14:55
  • No problem with the string literals, either. The only problem is DEP. The code works with `-z execstack`. – Jester Dec 01 '15 at 17:07
-1

Your code exhibits undefined behavior because C does not provide for pointers to objects (i.e. char *) to be converted to pointers to functions (i.e. void(*)()) or vise versa. The exact nature of the segfault is immaterial, and cannot be determined as a property of your program source -- that's a consequence of the "undefined" aspect of the program's behavior.

You probably want to look into inline assembly, but even that is only a common extension, not a standard feature of C. Possibly you want to write your assembly code as a separate assembly source file, to be assembled into an object file independently and linked to your C code afterward. Details of how to do any of this depend on your tool chain.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157