http://v0ids3curity.blogspot.kr/2014/12/return-to-vdso-using-elf-auxiliary.html

2016/11/21 - [System/etc] - Memory Layout, Segment / Stack layout



Linux Stack Layout with Auxiliary Vectors

```c
0x7fffffffe0e8: 0x00007ffff7a36f45    ( main's ret )
0x7fffffffe0f0: 0x0000000000000000    ( argc )
0x7fffffffe0f8: 0x00007fffffffe1c8    ( **argv )

....................

0x7fffffffe1c0: 0x0000000000000000    ( argc )
0x7fffffffe1c8: 0x00007fffffffe5a7    ( argv[0] )
0x7fffffffe1d0: 0x0000000000000000    ( last argv[n] == NULL )
0x7fffffffe1d8: 0x00007fffffffe5d5    ( envp[0] )
0x7fffffffe1e0: 0x00007fffffffe67f    ( envp[1] )
..........envp[]..........
0x7fffffffe420: 0x0000000000000000    ( last envp[n] == NULL )

/*****     auxv[]     *****/
                     key                     value
0x7fffffffe428: 0x0000000000000021      0x00007ffff7ffa000      // AT_SYSINFO_EHDR
0x7fffffffe438: 0x0000000000000010      0x000000001f8bfbff
0x7fffffffe448: 0x0000000000000006      0x0000000000001000
0x7fffffffe458: 0x0000000000000011      0x0000000000000064
0x7fffffffe468: 0x0000000000000003      0x0000000000400040
0x7fffffffe478: 0x0000000000000004      0x0000000000000038
0x7fffffffe488: 0x0000000000000005      0x0000000000000009
0x7fffffffe498: 0x0000000000000007      0x00007ffff7dda000
0x7fffffffe4a8: 0x0000000000000008      0x0000000000000000
0x7fffffffe4b8: 0x0000000000000009      0x0000000000400490
0x7fffffffe4c8: 0x000000000000000b      0x00000000000003e8
0x7fffffffe4d8: 0x000000000000000c      0x00000000000003e8
0x7fffffffe4e8: 0x000000000000000d      0x00000000000003e8
0x7fffffffe4f8: 0x000000000000000e      0x00000000000003e8
0x7fffffffe508: 0x0000000000000017      0x0000000000000000
0x7fffffffe518: 0x0000000000000019      0x00007fffffffe559      // AT_RANDOM
0x7fffffffe528: 0x000000000000001f      0x00007fffffffefca
0x7fffffffe538: 0x000000000000000f      0x00007fffffffe569
0x7fffffffe548: 0x0000000000000000      0x0000000000000000
0x7fffffffe558
....................

0x7fffffffe5a7: "filename"     ( argv strings )
..........
0x7fffffffe5d5: "ENV=value"    ( envp strings )

....................

program name (== argv[0] string )
NULL
....................
```

```c

$ set env LD_SHOW_AUXV=1

$ r

AT_SYSINFO_EHDR: 0x7ffff7ffa000      // VDSO addr

AT_HWCAP:        1f8bfbff

AT_PAGESZ:       4096

AT_CLKTCK:       100

AT_PHDR:         0x400040

AT_PHENT:        56

AT_PHNUM:        9

AT_BASE:         0x7ffff7dda000

AT_FLAGS:        0x0

AT_ENTRY:        0x400490            // Entry point of program

AT_UID:          1000

AT_EUID:         1000

AT_GID:          1000

AT_EGID:         1000

AT_SECURE:       0                   // secure-execution mode

AT_RANDOM:       0x7fffffffe559      // point to end of AUXV table

AT_EXECFN:       /home/ubuntu/workspace/study/heap/fastbin_dup

AT_PLATFORM:     x86_64

```

`` AT_RANDOM``을 이용해 stack offset을 계산하는 것은 remote라면 거의 불가능하다. 서버 측 쉘의 환경변수가 얼마나 있는지도 모르고, 각 stack frame size같은 것도 정확히 맞출 수 없기 때문에 어느 정도는 추측해야 한다.


sys_read-sys_write leak

#1 sys_read

```
rax : 0x0  /  rsi : (stack)  /  rdi : (stdin, 0)  /  rdx : size    ( x86_64 )
```
* `` rdi``에서 읽어서, `` rsi``에 쓰게 된다. 결과적으로 read하는 곳이 `` stdin``이라 `` rdi : stdin``
위와 같은 상태에서 `` syscall`` 해서 `` sys_read``를 호출한 다음 `` rax=0x1``로 만들기 위해 `` \n``만 전송한다.

#2 sys_write

`` sys_read``가 끝난 이후 레지스터 상태는 다음과 같다.
```
rax : 0x1  /  rsi : (stack)  /  rdi : (stdin, 0)  /  rdx : size    ( x86_64 )
```
* `` rsi``에서 읽어서, `` rdi``에 쓰게 된다. 결과적으로 write하는 곳이 `` stdin``이라 `` rdi : stdin``
stdin이든 stdout이든 stderr이든 입출력에 아무거나 사용해도 되기 때문에 이대로 `` sys_write``를 호출하면 `` sys_read``에서 데이터를 저장해놓은 지점부터 `` size``만큼 leak.


이를 `` AUXV`` leak에 사용할 수 있다.


Return to vDSO

gadget
server 측에서 사용하는 vDSO page를 알고 있을 때 사용할 수 있기 때문에 제약이 꽤 크다. server OS를 알고 있다면 vDSO page도 알아낼 수는 있을 듯.

64bit에서는 parameter push를 위해 `` rdi, rsi, rdx``를 조작할 수 있어야 하는데, Ubuntu 14.04.5 LTS에는 다음을 제외하면 적당한 gadget이 없다. 
```c
0x7ffff7ffa9d6:      syscall 
0x7ffff7ffa9d8:      pop    rbx
0x7ffff7ffa9d9:      pop    rbp
0x7ffff7ffa9da:      ret    
```
아무튼, vDSO를 사용할 수 있는 환경이라면 이런 유용한 gadget들을 찾아보는게 도움이 된다.

vDSO addr
  1. ``c fork()``하는 경우 vDSO addr이 매번 같기 때문에 `` AT_SYSINFO_EHDR`` leak 하면 바로 알아낼 수 있다.
  2. vDSO page는 random하게 결정되지만, randomize range가 그리 크지 않아 brute force가 불가능한 수준은 아닌 듯.
    https://github.com/umbum/pwn/blob/master/vdso/entropy.py





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

Empire  (0) 2018.11.03
realloc fake size  (0) 2017.11.04
SROP  (0) 2017.08.17
The House of Einherjar  (0) 2017.08.16
The House of Force  (0) 2017.08.15