엄범


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
Return to VDSO using ELF Auxiliary Vectors leck  (0) 2017.09.02
SROP  (0) 2017.08.17
The House of Einherjar  (0) 2017.08.16
The House of Force  (0) 2017.08.15