The House of Mind


unlink와 반대로, chunk가 free되면서 bins와 link하는 과정에서 발생하는 쓰기를 이용하는 방식이다.
```c
bck = unsorted_chunks(av); // == &av->bins[0]
fwd = bck->fd;
if (__glibc_unlikely (fwd->bk != bck))    // DEAD
{
    errstr = "free(): corrupted unsorted chunks";
    goto errout;
}
p->fd = fwd;
p->bk = bck;
if (!in_smallbin_range(size))
{
    p->fd_nextsize = NULL;
    p->bk_nextsize = NULL;
}
bck->fd = p;
fwd->bk = p;
```

fwd->bk = p

``c *(&bins[0] + 8)->bk = p`` ,

``c *(*(&bins[0] + 8) + 12 ) = p`` 이므로

``c *(&bins[0] + 8) + 12`` 번지에 `` p``에 있는 값이 대입

따라서, ``c &bins[0] + 8`` 번지에 ``c Execution point addr - 12`` 주소를 넣는다.

⇒ ``c *(&bins[0] + 8) = Execution point addr - 12``가 되므로, `` Execution point addr``번지에 `` p``를 대입하게 된다.


원래 House of Mind는 이 포인터를 이용하는데, 지금은 patch되어 사용할 수 없다.


bck->fd = p

``c *(&bins[0] + 8) = p ``이므로, 
``c &bins[0] + 8`` 번지에 `` p``에 있는 값이 대입 ( ``c type(p) == mchunkptr`` 이므로 chunk의 주소가 대입된다.)
* ``c &bins[0] +8 == &bins[2]`` 이기는 하다만 arena에도 chunk가 있는 것 처럼 간주하고 동작하기 때문에 이게 맞다. 아래 그림은 조금 잘못그렸다.

이 경우 다음과 같이 `` .dtors``의 위치에 ``c &bins[0] + 8``가 위치하도록 해야 하므로 arena를 아예 `` .dtors`` 주변에 잡아버려야한다.

&bins[0] + 8 && Execution point

 &p

그래서 조건을 충족시키기가 꽤나 어렵다.

[UNDEAD] fastbin method가 이와 동일한 방법으로 동작한다.


exploit

  1. overflow를 이용하는 방식으로는 main_arena bins[0]에 직접 값을 쓸 수는 없다.
    ⇒ fake bins[0] ( fake arena )가 필요하다.
  2. ``c free(chunk)`` 시 main_arena가 아니라 fake arena를 사용하도록 해야 한다.
    ⇒ fake heap_info가 필요하다.
  3. ``c free(chunk)`` 시 fake arena와 연결된 fake heap_info를 사용하도록 해야 한다.
    ⇒ chunk가 main_arena heap range 밖에 있어야 하며, NON_MAIN_ARENA가 set 되어야 한다.


Note) 그림을 조금 잘못 그렸는데, ``c bins[0]``에서 나가는 노란색 화살표가 가리키는 chunk는 실제로는 없고, arena 내부에 있는 것으로 간주한다. 따라서 ``c bins[2] == bins[0]'s fd``다.

* consolidate를 막기 위해 `` P``에 `` PREV_INUSE`` flag도 있어야 한다.

* `` P``를 비롯한 chunk들은 모두 heap에 정상적으로 할당된 chunk들 이며, `` P`` 이후에는 top chunk가 위치하기 때문에 free's next size check는 따로 신경쓰지 않아도 된다.

* 8 bytes A..A는 위쪽 chunk를 free 하면서 `` fd/bk``가 채워지는 자리이므로, 이 부분 이후에 arena가 시작된다. 

  사실 위쪽 chunk를 굳이 free할 필요는 없는 듯.

* 이후 위치하는 8 bytes도 free 하면서 0으로 초기화되므로 뒤 쪽 4 bytes 0을 mutex로 이용한다.


```c

free(p+8);    // free(0x081002a0)

-> 0x08100298              : p's value

-> 0x08100000              : fake heap_info AND ar_ptr

-> 0x0804a010              : fake arena

-> 0x0804a010 + x + 8      : &ar->bins[0]

```


`` p``가 가리키는 곳은 chunk의 `` prev_size(0x08100298)``이므로 여기에 shellcode를 넘기면 되는데 그 아래 field가 망가지면 안된다.

따라서 `` p``가 가리키는 곳에는 jmp instruction을 넣고, field 아래에 shellcode를 넣어 그리로 jmp할 수 있도록 구성한다.


DEAD

check를 통과하기 위해서는 ``c *(&bins[0] + 8) + 12`` 번지에 있는 값이, ``c &bins[0]`` 이어야만 한다.

``c &bins[0] + 8`` 번지의 값이 가리키는 B chunk의 `` bk``의 값이 ``c &bins[0]``이어야 한다.(  )


최종적으로 `` P``가 대입되는 곳(B chunk의 `` bk``)의 값이 ``c &bins[0]``인 경우에만 사용할 수 있기 때문에, 사실상 사용할 수 없다.

* 최종적으로 `` P``가 대입되는 곳을 ``c &bins[0]``으로 만들어 주는 것은, 이미 target의 값을 조작할 수 있다는 것을 의미하므로 모순이다.


[UNDEAD] fastbin method

```c

p->fd = *fb;

*fb = p;

```

* 소스가 조금 변경되어 ``c *fp = p`` 부분을 매크로에서 처리하는 것 같지만, 별다른 check가 새로 생긴 것 같지는 않아 아직 동작한다. (2.24)

``c fwd->bk = p``를 활용하는 House of Mind 방법과는 꽤나 다른 것이, 포인터를 한 번 덜 거치기 때문에 아예 arena를 Execution point를 포함하는 영역으로 잡아버려야 한다.


* fastbin 처리 부분은 ``c _int_free()``에서 두 가지 기본적인 check 이후 바로 등장하기 때문에 fastbin size라면 바로 fastbin 처리 부분을 수행하게 된다.

* ``c ar_ptr = arena_for_chunk(p);``는 ``c _int_free()`` 이전에 이미 구해져서 넘어오기 때문에 fastbin도 다른 arena를 참조하도록 하는 것이 가능하다.


사실상 arena가 다음과 같이 구성되어 있을 때 `` fastbins[idx]``에 값을 쓰게 되는 건데,

`` mutex == 00000000``이어야만 하며, `` system_mem``도 너무 작으면 안된다.

(원래는 `` max_fast``도 신경 써주어야 하지만 버전이 올라가면서 `` flag``로 변경되었다.)

 mutex 

 flag || max_fast ( old version )

 fastbinsY[0]

 ...

 system_mem ( av+1848 )


따라서 Execution point 근처에서 두 가지 정도만 만족한다면 사용할 수 있다.


그러나 문제는 이 방법을 이용해 Execution point에 대입할 수 있는 값은 heap addr인 ``c p``(chunk's addr)뿐인데, heap에 X 권한이 없다. ( 원하는 값을 아무거나 쓸 수는 없다. "arena에 ``c p``만" 쓸 수 있다. / NX가 해제되어 있어도 보통 stack에만 X권한 있고 heap에는 없다. )

따라서 Execution point의 값이 ``c p``로 변경된다고 해도 ``c p``위치에 있는(mchunkptr) instruction을 실행할 수 없다는게 문제.


그래서 instruction까지 가기 위해 포인터를 한 번 더 거치는 Execution point에만 사용할 수 있다.

GOT에는 ``c &func``가 들어가기 때문에, ``c p``위치에 바로 instruction이 있어야 해서 사용 불가.

``c func@plt + 2``에 대입하는 방법도 생각해 볼 수 있겠지만, 여기는 쓰기 권한이 없다.


따라서  double function pointer 정도로 사용처가 제한되기 때문에, 상당히 적용하기가 그렇다.



'Security > System Exploit' 카테고리의 다른 글

The House of Einherjar  (0) 2017.08.16
The House of Force  (0) 2017.08.15
unsorted bin attack  (0) 2017.08.15
[UNDEAD] unlink  (0) 2017.08.15
The House of Lore  (0) 2017.08.15