0

I want to use my own shellcode for a buffer overflow exploit so for that I have written a script in C language[shellcode script].

I have used the following commands.:

gcc -c file.c -o file.o
objdump -sS -D file.o
root@kali:~/shellcode# cat file.c
#include<stdio.h>

int main()
{

    printf("Hi");

}

The above code is of 'file.c'.

I expect the output of the 'objdump -sS -D file.o' to be free from null-bytes, but actually this is my output after typing that command:


file.o:     file format elf64-x86-64

Contents of section .text:
 0000 554889e5 488d3d00 000000b8 00000000  UH..H.=.........
 0010 e8000000 00b80000 00005dc3           ..........].    
Contents of section .rodata:
 0000 486900                               Hi.             
Contents of section .comment:
 0000 00474343 3a202844 65626961 6e20382e  .GCC: (Debian 8.
 0010 332e302d 36292038 2e332e30 00        3.0-6) 8.3.0.   
Contents of section .eh_frame:
 0000 14000000 00000000 017a5200 01781001  .........zR..x..
 0010 1b0c0708 90010000 1c000000 1c000000  ................
 0020 00000000 1c000000 00410e10 8602430d  .........A....C.
 0030 06570c07 08000000                    .W......        

Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # b <main+0xb>
   b:   b8 00 00 00 00          mov    $0x0,%eax
  10:   e8 00 00 00 00          callq  15 <main+0x15>
  15:   b8 00 00 00 00          mov    $0x0,%eax
  1a:   5d                      pop    %rbp
  1b:   c3                      retq   

Disassembly of section .rodata:

0000000000000000 <.rodata>:
   0:   48                      rex.W
   1:   69                      .byte 0x69
    ...

Disassembly of section .comment:

0000000000000000 <.comment>:
   0:   00 47 43                add    %al,0x43(%rdi)
   3:   43 3a 20                rex.XB cmp (%r8),%spl
   6:   28 44 65 62             sub    %al,0x62(%rbp,%riz,2)
   a:   69 61 6e 20 38 2e 33    imul   $0x332e3820,0x6e(%rcx),%esp
  11:   2e 30 2d 36 29 20 38    xor    %ch,%cs:0x38202936(%rip)        # 3820294e <main+0x3820294e>
  18:   2e 33 2e                xor    %cs:(%rsi),%ebp
  1b:   30 00                   xor    %al,(%rax)

Disassembly of section .eh_frame:

0000000000000000 <.eh_frame>:
   0:   14 00                   adc    $0x0,%al
   2:   00 00                   add    %al,(%rax)
   4:   00 00                   add    %al,(%rax)
   6:   00 00                   add    %al,(%rax)
   8:   01 7a 52                add    %edi,0x52(%rdx)
   b:   00 01                   add    %al,(%rcx)
   d:   78 10                   js     1f <.eh_frame+0x1f>
   f:   01 1b                   add    %ebx,(%rbx)
  11:   0c 07                   or     $0x7,%al
  13:   08 90 01 00 00 1c       or     %dl,0x1c000001(%rax)
  19:   00 00                   add    %al,(%rax)
  1b:   00 1c 00                add    %bl,(%rax,%rax,1)
  1e:   00 00                   add    %al,(%rax)
  20:   00 00                   add    %al,(%rax)
  22:   00 00                   add    %al,(%rax)
  24:   1c 00                   sbb    $0x0,%al
  26:   00 00                   add    %al,(%rax)
  28:   00 41 0e                add    %al,0xe(%rcx)
  2b:   10 86 02 43 0d 06       adc    %al,0x60d4302(%rsi)
  31:   57                      push   %rdi
  32:   0c 07                   or     $0x7,%al
  34:   08 00                   or     %al,(%rax)
    ...

Can somebody please explain me how I can remove null-bytes from this program, or if possible write the output in assembly so that I can learn what to change and how

P.S - I know mov $0x0, $rsp can be done by xor $rsp, $rsp but I don't know about movq, lea, add, sub, etc.

Thank you for your precious time.

oguz ismail
  • 1
  • 16
  • 47
  • 69
nltc
  • 83
  • 2
  • 10
  • 4
    *Why* did you expect no 0 bytes? – Shawn Aug 18 '19 at 07:48
  • I want to use this shellcode for my bufferoverflow exploit so having \x00 bytes in between will terminate the program[ correct me if I am wrong. ] and not execute the entire script properly as expected. – nltc Aug 18 '19 at 08:50
  • 1
    It depends on the weakness you are trying to exploit. For example, the `read` function does read null bytes. `sprintf`, on the other hand, stops at the first null byte. – AdamGold Aug 18 '19 at 09:00
  • Oh so does that mean that even with these null bytes I can bufferoverflow a program which uses the read function? – nltc Aug 18 '19 at 09:18
  • 1
    `I can bufferoverflow a program` - if you mean to "take a program to a state that it accesses an invalid address to memory", that's independent of read function and null bytes. Its dependent on the program itself. Please post the full assembly output, you are not seeing all sections. Find where is string stored (it will be stored using `byte` instructions most probably) and replace the value. It should be somewhere in .rodata section. Or have a separate section, compile with debugging symbols enabled and check. `callq 15
    ` what does this jump?
    – KamilCuk Aug 18 '19 at 10:20
  • Forgive me if I am wrong but I have posted the full assembly output. And yes you are right the string is stored with ```.byte``` instruction in the ```.rodata```. Tell me if you require anything else. Please correct me if I have wrongly understood you. – nltc Aug 18 '19 at 10:47

1 Answers1

1

Removing nullbytes (\x00) from shellcode is only necessary if you are using functions that depend on a trailing \x00, such as strcpy:

char * strcpy ( char * destination, const char * source ); 

which copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).

However strncpy copies the first num characters of source to destination, padding it with zeros until num characters have been written to destination.

char * strncpy ( char * destination, const char * source, size_t num );

This means if you pass your shellcode size/length to the parameter num, it will copy all characters into the buffer, without the hassle of removing nullbytes as they aren't terminating copying from source to destination.

To get the length of the shellcode:

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

int main()
{
    char* evil="\x90\x83\xc8\xff\xf7\xd0\x50";
    printf("%d",strlen(evil));
}

will return:

7
pr0f3ss
  • 527
  • 1
  • 4
  • 17
  • Thanks you for your answer. However I have one last doubt. I have two files 'bufferoverflow.c' and 'payload.py'. I have stored the output of 'payload.py' in a file called 'fuzzing'. 'fuzzing' is used as an input for 'bufferoverflow'[the compiled version of 'bufferoverflow.c']. Still I do not get any thing. The string is not printed on screen. The link to bufferoverflow.c: https://pastebin.com/bgQXfYzA The link to payload.py: https://pastebin.com/s2eXTdx0 – nltc Aug 18 '19 at 10:31
  • By using shellcodes of metasploit like ```linux/x64/shell_reverse_tcp``` with this script works flawlessly but anyways what according to you might be the perfect ```payload.py``` file? – nltc Aug 18 '19 at 10:56
  • @nltc whats the return value of `read(0, arr, 800)`? If it's <0 then the system call returned an error. I just rechecked the `payload.py` file, should be fine as is. – pr0f3ss Aug 18 '19 at 10:58
  • sorry for the late reply. after changing the code a little bit I was able to display the output of return_status. It came out to be 433. What should I do now? – nltc Aug 18 '19 at 14:24
  • @nltc If return_status returns >= 0, then this means exactly 433 bytes have been written into the buffer. That is exactly 424 payload bytes + 8 return address bytes + 1 terminating byte. Your buffer (arr) should now contain the first 400 bytes. Is that not the case? – pr0f3ss Aug 18 '19 at 14:42
  • Can you exploit me why only 400 bytes and yes you are right I set the arr to contain 400 characters. You can see in pastebin.com/bgQXfYzA – nltc Aug 18 '19 at 14:59
  • @nltc The array has only allocated a total of 400 bytes and the rest must be written somewhere else. The 33 bytes are overflow and written to adjacent memory locations if you are lucky. What does your program output exactly when running? – pr0f3ss Aug 18 '19 at 15:03
  • @pr0fss I have upload the err properly on pastebin. https://pastebin.com/C0nfyLtf – nltc Aug 18 '19 at 15:16
  • @nltc A segfault is a access violation caused by trying to write into protected memory. So basically this means the OS throws a segfault as you are overflowing the arr with data and you are trying to write the overflowed bytes into a restricted area of memory. This is because the newest operation systems are protecting their memory. You gotta find a platform/OS where you can find the vulnerability of having no protected memory. – pr0f3ss Aug 18 '19 at 15:26
  • @pr0fe3ss Ok understood but then how come when I use metasploit's shellcode in ```payload.py``` and store output in ```fuzzing``` and start ```bufferoverflow``` using gdb with ```fuzzing``` as input, the exploit works flawlessly? – nltc Aug 18 '19 at 15:41
  • @nltc Sorry, haven't been on since. Is the shellcode from metasploit also nullbyte free? If yes, try to encode your current shellcode (which has nullbytes) with the msfvenom tool until you have no nullbytes left. It will place the decoding stub inside the shellcode so you dont have anything to do, but do encode the shellcode with msfvenom. – pr0f3ss Aug 22 '19 at 19:50
  • How can I do that? – nltc Aug 31 '19 at 10:42
  • @nltc Look up tutorials on mfsvenom and encoding. – pr0f3ss Aug 31 '19 at 16:11
  • @nltc Also, did you ensure that your NOP slide really writes over the RIP register and that the return address is exactly the address of your code? – pr0f3ss Sep 02 '19 at 05:41
  • I have programmed a little snippet in x64 linux assembly. Check out the link:https://pastebin.com/uuKs6EJm however when I disassemble it with objdump I can clearly see that there are null bytes which will stop the execution of my program. How can I get rid of them? – nltc Sep 06 '19 at 12:05