int main()
    char shellcode[] = "\xbb\x00\x00\x00\x00\xb8\x01\x00\x00\x00\xcd\x80";

    int *ret;
    ret = (int *)&ret + 2;
    (*ret) = (int)shellcode;

I tried to run the above shellcode but got a segmentation fault. Then, I tried putting the shellcode inside the main and it worked, why?

Also, when I do strace to the binary to check the syscall, it shows that exit_group() syscall is called but the shell code is for exit() syscall.

screenshot of strace


First of all, the opcodes that you are pointing are not responsible for the syscall. If you disassemble your shellcode, you get:

0000000000004028 <shellcode>:
    4028:   bb 00 00 00 00          mov    $0x0,%ebx
    402d:   b8 01 00 00 00          mov    $0x1,%eax
    4032:   cd 80                   int    $0x80

A first mov to set ebx to zero (the return code), then a second mov to set eax to the id of the exit syscall, and finally it trigger the system call.

Second, this shellcode is obviously designed for a 32-bit architecture. And, you have to know that the syscall numbers are different between i386 and amd64.

So, my recommendation would be that you compile your program with the option -m32 to ensure that you have a full 32-bit program (and not a mix between 64-bit and 32-bit).

Third, you need to be sure that you compile with -zexecstack in order to be able to execute the code in case it is stored on the stack.

Finally, there is no evidence that getting ret + 2 will set your pointer in front of the saved eip. You'd better write:

int main()
    char shellcode[] = "\xbb\x00\x00\x00\x00\xb8\x01\x00\x00\x00\xcd\x80";

    (*(void(*)()) shellcode)();
    return 0;
  • I am using i386 machine. I believe the 0x1 which is being set to eax is responsible for exit syscall. Please correct me if I am wrong. – Mukesh Mar 12 '19 at 18:49
  • I tried again compiling the program with -m32 option and got exactly the same disassemble as you have mentioned. But, the issue still remains the same. I am using now char shellcode[] = "\xbb\x00\x00\x00\x00\xb8\x01\x00\x00\x00\xcd\x80"; – Mukesh Mar 12 '19 at 18:56
  • Ah, in fact, the exit() syscall call the exit_group() function to kill all threads. So, it might be okay from the beginning. Look at man exit_group – perror Mar 12 '19 at 19:13
  • I think the program is crashing because whatever the opcode number instead of 0x1 I pass, I am getting the same result and hence the exit_group() is called rather than exit() – Mukesh Mar 12 '19 at 19:23
  • Are you compiling with -zexecstack ? – perror Mar 12 '19 at 19:27
div eax
int 0x80
jmp short 0x0

It's different ways exit() syscall

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.