Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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

Include Page
00.Notice
00.Notice

List

Table of Contents
outlinetrue
excludeList

Conditions

  • 해당 기술은 다음과 같은 조건에서 동작합니다.
    • 공격자에 의해 동일한 크기의 Fast chunk의 할당과 해제가 자유로워야 합니다.
    • 공격자에 의해 해제된 Fast chunk를 한번더 해제 할 수 있어야 합니다.(Double free bug)

Exploit plan

  • 다음과 같은 방법으로 공격할 수 있습니다.
    • 동일한 크기의 Fast chunk 3개를 생성합니다.
    • 첫번재 Fast chunk를 해제 합니다.
    • 두번째 Fast chunk를 해제 합니다.
    • 해제된 첫번재 Fast chunk를 다시 한번 해제 합니다.

    • 공격 대상 영역과 같은 크기의 Heap 을 3개 할당 합니다.
      • 첫번재 Heap 영역과 세번째 Heap 영역의 주소가 같습니다.

Example

Files

Panel

Source code

Fastbin duplicate

  • "Fastbin duplicate"는 fastbin에 배치된 리스트를 악용한 공격입니다.
    • 애플리케이션이 fastbin에 포함되는 메모리들을 중복으로 해제를 요청할 경우 할당자는 해당 chunk들을 list에 중복으로 배치됩니다.

    • 중복으로 등록된 chunk와 동일한 크기의 메모리 할당을 여러번 요청하면, 할당자는 해당 chunk의 포인터를 중복으로 리턴합니다.

    • 이러한 악용은 fastbin에서만 가능합니다. 
  • 예를 들어 malloc()에 크기가 112byte인 메모리의 할당을 3번 요청합니다.
    • 애플리케이션이 첫번째 메모리의 포인터를 인수로 free()를 호출하면 할당자는 해당 chunk를 fastbin[6]에 배치합니다.
    • 그리고 애플리케이션이 두번째 메모리를 해제를 요청하면 할당자는 fastbin[6]에 배치된 chunk의 fd에 해당 chunk를 배치합니다.
    • 이미 해제된 첫번째 메모리를 다시 해제를 요청하면 해당 chunk가 fastbin[6]의 list 마지막에 배치됩니다.
    • 즉, Fastbin[6]의 list는 "첫번째 메모리(0x602000) --> 두번째 메모리(0x602080) --> 첫번째 메모리(0x602000) --> ..." 와 같은 형태가 됩니다.
  • 애플리케이션이 malloc()에 해제된 메모리와 같은 크기의 메모리의 할당을 요청합니다.
    • 첫번째 요청에서는 Fastbin에 마지막에 배치된 메모리가 재할당합니다.
    • 두번째 요청에서는 그 다음 메모리가 재할당됩니다.
    • 세번째 요청에서 첫번째 요청에서 할당받은 메모리와 동일한 메모리가 할당됩니다.
  • 즉 애플리케이션은 첫번째 메모리와 세번째 메모리의 포인터는 서로 같은 포인터입니다.
Panel
titleFast dup flow

Image Added

Example

  • 다음 코드는 malloc()에게 크기가 112byte인 메모리 할당을 3번 요청합니다.
    • 이 코드는 buf1,buf2 해제를 free()에 요청하고, buf1 해제를 다시 요청합니다.
    • 그리고 다시 크기가 112byte인 메모리 할당을 malloc()에 3번 요청합니다.
Code Block
languagecpp
titlefast_dup.c
Code Block
languagecpp
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
        int *buf1 = malloc(112);
        int *buf2 = malloc(112);
        int *buf3 = malloc(112);
 
        free(buf1);
        free(buf2);
        free(buf1);
 
        int *buf4 = malloc(112);
        int *buf5 = malloc(112);
        int *buf6 = malloc(112);
}

Exploit flow

Panel
titlefastbin_dup

Image Removed

Debugging

  • 다음과 같이 Break point를 설정합니다.
    • 0x4005b6 : 1번째 free() 함수 호출

    • 0x4005c2 : 2번째 free() 함수 호출

    • 0x4005ce : 3번째 free() 함수 호출

    • 0x4005dd : 4번째 malloc() 함수 호출

    • 0x4005eb : 5번째 malloc() 함수 호출

    • 0x4005f9 : 6번째 malloc() 함수 호출

Code Block
gdb-peda$ b *0x00000000004005b6
Breakpoint 1 at 0x4005b6
gdb-peda$ b *0x00000000004005c2
Breakpoint 2 at 0x4005c2
gdb-peda$ b *0x00000000004005ce
Breakpoint 3 at 0x4005ce
gdb-peda$ b *0x00000000004005dd
Breakpoint 4 at 0x4005dd
gdb-peda$ b *0x00000000004005eb
Breakpoint 5 at 0x4005eb
gdb-peda$ b *0x00000000004005f9
Breakpoint 6 at 0x4005f9
gdb-peda$ 
  • 다음과 같이 할당된 Heap 영역을 확인 할 수 있습니다.
    • free() 함수 호출 전에 fastbinsY에 등록된 Chunk가 없습니다.
    • 첫번째 free() 함수 호출 후에 fastbinsY에 0x602000 영역이 등록됩니다.
Code Block
titleBreak point - 0x4005b6
gdb-peda$ r
Starting program: /home/lazenca0x0/Documents/def/fastbin_dup 
Breakpoint 1, 0x00000000004005b6 in main ()

gdb-peda$ x/50gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x0000000000000000	0x0000000000000000
0x602020:	0x0000000000000000	0x0000000000000000
0x602030:	0x0000000000000000	0x0000000000000000
0x602040:	0x0000000000000000	0x0000000000000000
0x602050:	0x0000000000000000	0x0000000000000000
0x602060:	0x0000000000000000	0x0000000000000000
0x602070:	0x0000000000000000	0x0000000000000000
0x602080:	0x0000000000000000	0x0000000000000081
0x602090:	0x0000000000000000	0x0000000000000000
0x6020a0:	0x0000000000000000	0x0000000000000000
0x6020b0:	0x0000000000000000	0x0000000000000000
0x6020c0:	0x0000000000000000	0x0000000000000000
0x6020d0:	0x0000000000000000	0x0000000000000000
0x6020e0:	0x0000000000000000	0x0000000000000000
0x6020f0:	0x0000000000000000	0x0000000000000000
0x602100:	0x0000000000000000	0x0000000000000081
0x602110:	0x0000000000000000	0x0000000000000000
0x602120:	0x0000000000000000	0x0000000000000000
0x602130:	0x0000000000000000	0x0000000000000000
0x602140:	0x0000000000000000	0x0000000000000000
0x602150:	0x0000000000000000	0x0000000000000000
0x602160:	0x0000000000000000	0x0000000000000000
0x602170:	0x0000000000000000	0x0000000000000000
0x602180:	0x0000000000000000	0x0000000000020e81
gdb-peda$ p main_arena.fastbinsY 
$1 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
gdb-peda$ ni
0x00000000004005bb in main ()
gdb-peda$ p main_arena.fastbinsY 
$2 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602000, 0x0, 0x0, 0x0}
gdb-peda$ 
  • 다음과 같이 해제된 2번째 Heap 영역이 fastbinsY에 등록되었습니다.
    • fastbinsY 영역에는 최근에 해제된 heap영역이 등록됩니다.
    • 2번째 해제된 Heap 영역에 free chunk가 생성됩니다.
      • fd 영역에 이전에 해제된 free chunk의 주소가 저장됩니다.
  • 0x4005b7에서 fastbin에 배치된 메모리가 또 배치되는 것을 확인합니다.

    • 0x4005c6, 0x4005d4, 0x4005e2에서는 malloc()에서 반환된 pointer를 확인합니다.

Code Block
titleBreakpoints
lazenca0x0@ubuntu:~/Book/2.fast_dup$ gcc -o fast_dup fast_dup.c 
lazenca0x0@ubuntu:~/Book/2.fast_dup$ gdb -q ./fast_dup
Reading symbols from ./fast_dup...(no debugging symbols found)...done.
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x0000000000400566 <+0>:	push   rbp
   0x0000000000400567 <+1>:	mov    rbp,rsp
   0x000000000040056a <+4>:	sub    rsp,0x30
   0x000000000040056e <+8>:	mov    edi,0x70
   0x0000000000400573 <+13>:	call   0x400450 <malloc@plt>
   0x0000000000400578 <+18>:	mov    QWORD PTR [rbp-0x30],rax
   0x000000000040057c <+22>:	mov    edi,0x70
   0x0000000000400581 <+27>:	call   0x400450 <malloc@plt>
   0x0000000000400586 <+32>:	mov    QWORD PTR [rbp-0x28],rax
   0x000000000040058a <+36>:	mov    edi,0x70
   0x000000000040058f <+41>:	call   0x400450 <malloc@plt>
   0x0000000000400594 <+46>:	mov    QWORD PTR [rbp-0x20],rax
   0x0000000000400598 <+50>:	mov    rax,QWORD PTR [rbp-0x30]
   0x000000000040059c <+54>:	mov    rdi,rax
   0x000000000040059f <+57>:	call   0x400430 <free@plt>
   0x00000000004005a4 <+62>:	mov    rax,QWORD PTR [rbp-0x28]
   0x00000000004005a8 <+66>:	mov    rdi,rax
   0x00000000004005ab <+69>:	call   0x400430 <free@plt>
   0x00000000004005b0 <+74>:	mov    rax,QWORD PTR [rbp-0x30]
   0x00000000004005b4 <+78>:	mov    rdi,rax
   0x00000000004005b7 <+81>:	call   0x400430 <free@plt>
   0x00000000004005bc <+86>:	mov    edi,0x70
   0x00000000004005c1 <+91>:	call   0x400450 <malloc@plt>
   0x00000000004005c6 <+96>:	mov    QWORD PTR [rbp-0x18],rax
   0x00000000004005ca <+100>:	mov    edi,0x70
   0x00000000004005cf <+105>:	call   0x400450 <malloc@plt>
   0x00000000004005d4 <+110>:	mov    QWORD PTR [rbp-0x10],rax
   0x00000000004005d8 <+114>:	mov    edi,0x70
   0x00000000004005dd <+119>:	call   0x400450 <malloc@plt>
   0x00000000004005e2 <+124>:	mov    QWORD PTR [rbp-0x8],rax
   0x00000000004005e6 <+128>:	mov    eax,0x0
   0x00000000004005eb <+133>:	leave  
   0x00000000004005ec <+134>:	ret    
End of assembler dump.
gdb-peda$ b *0x00000000004005b7
Breakpoint 1 at 0x4005b7
gdb-peda$ b *0x00000000004005c6
Breakpoint 2 at 0x4005c6
gdb-peda$ b *0x4005d4
Breakpoint 3 at 0x4005d4
gdb-peda$ b *0x00000000004005e2
Breakpoint 4 at 0x4005e2
gdb-peda$
  • fastbins[6]의 상단에는 마지막에 해제된 메모리(0x602080)가 배치되어 있습니다.. 
    • 해당 chunk의 fd에 앞에서 해제된 메모리의 pointer(0x602000)가 배치되어있습니다.
    • fastbin의 list는 0x602080 --> 0x602000입니다.
    • buf1(0x602000)이 해제가 되면 fastbins[6]의 상단에 buf1(0x602000)이 배치됩니다.
    • fastbin의 list는 0x602000 --> 0x602080 --> 0x602000가 됩니다.
    • 이제 fastbin_dup 구현이 가능해졌습니다.
Code Block
gdb-peda$ r
Starting program: /home/lazenca0x0/Book/2.fast_dup/fast_dup 

Breakpoint 1, 0x00000000004005b7 in main ()
Code Block
titleBreak point - 0x4005c2
gdb-peda$ c
Continuing.
Breakpoint 2, 0x00000000004005c2 in main ()
gdb-peda$ ni
gdb-peda$ p main_arena.fastbinsY [6]
$4$1 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602080, 0x0, 0x0, 0x0}
(mfastbinptr) 0x602080
gdb-peda$ x/50gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x0000000000000000	0x0000000000000000
0x602020:	0x0000000000000000	0x0000000000000000
0x602030:	0x0000000000000000	0x0000000000000000
0x602040:	0x0000000000000000	0x0000000000000000
0x602050:	0x0000000000000000	0x0000000000000000
0x602060:	0x0000000000000000	0x0000000000000000
0x602070:	0x0000000000000000	0x00000000000000004gx 0x602080
0x602080:	0x0000000000000000	0x0000000000000081
0x602090:	0x0000000000602000	0x0000000000000000
0x6020a0:	0x0000000000000000	0x0000000000000000
0x6020b0:	0x0000000000000000	0x0000000000000000
0x6020c0:	0x0000000000000000	0x0000000000000000
0x6020d0:	0x0000000000000000	0x0000000000000000
0x6020e0:	0x0000000000000000	0x0000000000000000
0x6020f0:	0x0000000000000000	0x0000000000000000
0x602100gdb-peda$ x/4gx 0x0000000000602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602110:	0x0000000000000000	0x0000000000000000
0x602120:	0x0000000000000000	0x0000000000000000
0x602130:	0x0000000000000000	0x0000000000000000
0x6021400x602010:	0x0000000000000000	0x0000000000000000
0x602150:	0x0000000000000000	0x0000000000000000
0x602160:	0x0000000000000000	0x0000000000000000
0x602170:	0x0000000000000000	0x0000000000000000
0x602180:	0x0000000000000000	0x0000000000020e81
gdb-peda$ 
  • 다음과 같이 해제되었던 Chunk가 fastbinsY에 등록되었습니다.
    • 해제된 heap 영역을 다시 해제가 가능합니다.
    • 해제되었던 영역이 fastbinsY에 정상적으로 등록됩니다.
    • 그리고 해당 Free chunk의 fd 영역에 2번재 Free chunk의 주소가 저장됩니다.
Code Block
titleBreak point - 0x4005ce
gdb-peda$ c
Continuing.


Breakpoint 3, 0x00000000004005ceni

0x00000000004005bc in main ()
gdb-peda$ ni
0x00000000004005d3 in main ()x/4gx 0x0000000000602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x0000000000602080	0x0000000000000000
gdb-peda$ p main_arena.fastbinsY [6]
$5$2 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602000, 0x0, 0x0, 0x0}
gdb-peda$ x/50gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x0000000000602080	0x0000000000000000
0x602020:	0x0000000000000000	0x0000000000000000
0x602030:	0x0000000000000000	0x0000000000000000
0x602040:	0x0000000000000000	0x0000000000000000
0x602050:	0x0000000000000000	0x0000000000000000
0x602060:	0x0000000000000000	0x0000000000000000
0x602070:	0x0000000000000000	0x0000000000000000
0x602080:	0x0000000000000000	0x0000000000000081
0x602090:	0x0000000000602000	0x0000000000000000
0x6020a0:	0x0000000000000000	0x0000000000000000
0x6020b0:	0x0000000000000000	0x0000000000000000
0x6020c0:	0x0000000000000000	0x0000000000000000
0x6020d0:	0x0000000000000000	0x0000000000000000
0x6020e0:	0x0000000000000000	0x0000000000000000
0x6020f0:	0x0000000000000000	0x0000000000000000
0x602100:	0x0000000000000000	0x0000000000000081
0x602110:	0x0000000000000000	0x0000000000000000
0x602120:	0x0000000000000000	0x0000000000000000
0x602130:	0x0000000000000000	0x0000000000000000
0x602140:	0x0000000000000000	0x0000000000000000
0x602150:	0x0000000000000000	0x0000000000000000
0x602160:	0x0000000000000000	0x0000000000000000
0x602170:	0x0000000000000000	0x0000000000000000
0x602180:	0x0000000000000000	0x0000000000020e81
(mfastbinptr) 0x602000
gdb-peda$ 
  • 다음과 같이 Heap 영역을 할당 받습니다.4번째

    malloc(

    112) : 0x602010
  • 5번째 malloc(112) : 0x602090
  • 6번째 malloc(112) : 0x602010
  • fastbinsY의 변화
    • 0x602000 → 0x602080 → 0x602000 → 0x602080

    • malloc()함수는 fastbinsY에 동일한 크기의 free chunk가 존재하기 때문에 fastbinsY에 등록되어 있는 heap 영역을 재할당 합니다.
  • 이러한 현상이 발생하는 이유는 다음과 같습니다.
    • fastbins은 free chunk를 Single list로 관리하고 있습니다.
      • 동일한 크기의 fast chunk가 여러 개가 해제되면, chunk header의 fd 영역을 이용해 관리합니다.
    • 즉, 해당 현상이 발생하는 이유는 Double free로 인해 buf1과 buf2 free chunk의 fd 값이 상대 chunk를 가리키고 있기 때문입니다.
  • )에 112byte를 요청하면 fastbinsY[6]의 상단에 있는 메모리(0x602010)가 재할당됩니다.

    • fastbinsY[6]의 상단에는 다음 메모리(0x602080)가 배치됩니다.

    • 마지막 요청에서는 첫 재할당된 메모리(0x602010)와 같은 메모리(0x602010)가 재할당됩니다.

Code Block
titlefast dup
Code Block
titleExploit
gdb-peda$ c
Continuing.

Breakpoint 42, 0x00000000004005dd0x00000000004005c6 in main ()
gdb-peda$ i r rax
rax            0x602010	0x602010
gdb-peda$ p main_arena.fastbinsY [6]
$6$3 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602080, 0x0, 0x0, 0x0}

(mfastbinptr) 0x602080
gdb-peda$ c
Continuing.

Breakpoint 53, 0x00000000004005eb0x00000000004005d4 in main ()
gdb-peda$ i r rax
rax            0x602090	0x602090p main_arena.fastbinsY[6]
$5 = (mfastbinptr) 0x602000
gdb-peda$ p main_arena.fastbinsY 
$7 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602000, 0x0, 0x0, 0x0}

i r rax
rax            0x602090	0x602090
gdb-peda$ c
Continuing.
Breakpoint 64, 0x00000000004005f90x00000000004005e2 in main ()
gdb-peda$ i r rax
rax            0x602010	0x602010
gdb-peda$ p main_arena.fastbinsY [6]
$8$4 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602080, 0x0, 0x0, 0x0}(mfastbinptr) 0x602080
gdb-peda$ 

Related information

...