분명 돼야 하는데 안된다면 `` i r``로 레지스터 모두가 정상인 상태로 설정되어 있는지 확인해본다.
Sigreturn
- `` int`` instruction을 실행하면, kernel mode로 진입하면서 user mode context를 kernel stack에 push해놓는다.
- signal을 감지하는 것은 kernel mode에서 수행된다.
kernel은 수신된 signal이 있는지 확인하고 nonblocked pending signal이 있으면 ``c do_signal()``를 호출한다. - 여기서 signal을 처리하게 되는데, 이 때 signal handler가 등록되어 있는 경우, signal handler를 실행하기 위해 user mode로 나가야한다.
일단 kernel mode에서 벗어나면 kernel stack이 초기화되기 때문에, 아까 push해 둔 user mode context가 유실되어 어느 user mode로 돌아가야할지 알 수 없게된다. - 따라서, signal handler를 실행하기 위해 user mode로 나가기 전에 kernel stack에 존재하는 user mode context를 user stack에 복사해두고, 나중에 이를 복원하기 위해 ret addr을 ``c sigreturn()`` syscall 주소로 설정한다.
- signal handler를 실행한다.
- signal handler 실행을 마치고 리턴하면서 ``c sigreturn()``이 호출되며 다시 kernel mode로 진입하게 되며 user stack에 있는 context가 kernel stack에 복원된다.
Note ) `` sigcontext``에 지정된 `` eip``는 최종적으로 kernel mode에서 user mode로 나가게 될 때 실행되는 지점이다. ``c sigreturn()``은 syscall 이기 때문에 이미 호출되면서 kernel mode로 넘어간다.
32bit
/usr/include/x86_64-linux-gnu/asm/unistd_32.h link
/usr/include/x86_64-linux-gnu/bits/sigcontext.h
```c
struct sigcontext
{
unsigned short gs, __gsh;
unsigned short fs, __fsh;
unsigned short es, __esh;
unsigned short ds, __dsh;
unsigned long edi;
unsigned long esi;
unsigned long ebp;
unsigned long esp;
unsigned long ebx;
unsigned long edx;
unsigned long ecx;
unsigned long eax;
unsigned long trapno;
unsigned long err;
unsigned long eip;
unsigned short cs, __csh;
unsigned long eflags;
unsigned long esp_at_signal;
unsigned short ss, __ssh;
struct _fpstate * fpstate;
unsigned long oldmask;
unsigned long cr2;
};
```
* sigreturn으로 리턴하는 위치 바로 아래부터 `` gs, __gsh, fs, ...`` 순으로 위치시키면 된다.
```bash
$ objdump -d /lib/i386-linux-gnu/libc.so.6 | grep \<execve\>: -A 20
000b5f40 <execve>:
b5f40: 57 push %edi
b5f41: 53 push %ebx
b5f42: 8b 54 24 14 mov 0x14(%esp),%edx
b5f46: e8 90 08 07 00 call 1267db <__frame_state_for+0x35b>
b5f4b: 81 c3 b5 50 0f 00 add $0xf50b5,%ebx
b5f51: 8b 4c 24 10 mov 0x10(%esp),%ecx
b5f55: 8b 7c 24 0c mov 0xc(%esp),%edi
b5f59: 87 df xchg %ebx,%edi
b5f5b: b8 0b 00 00 00 mov $0xb,%eax
b5f60: 65 ff 15 10 00 00 00 call *%gs:0x10
```
따라서 레지스터를 다음과 같이 설정한다.
```bash
eax : 0xb
ebx : argument string
ecx : 0x00000000
edx : 0x00000000
eip : syscall OR ret
```
Note) 이 밖의 다른 레지스터들도 적절히 설정해주어야 한다.
cs, ss
fs, gs
*fpstate
EOF
```
64bit
/usr/include/x86_64-linux-gnu/asm/unistd_64.h link
/usr/include/x86_64-linux-gnu/bits/sigcontext.h
따라서 레지스터를 다음과 같이 설정한다.
```bash
rax : 0x3b
rdx : envp ( 0x0 )
rsi : argv ( 0x0 )
rdi : argument string
rip : syscall OR ret
```
vsyscall's syscall; ret gadget
0xffffffffff600000 0xffffffffff601000 r-xp [vsyscall]
gdb-peda$ x/3i 0xffffffffff600007
0xffffffffff600007: syscall
0xffffffffff600009: ret
```
'Security > System Exploit' 카테고리의 다른 글
realloc fake size (0) | 2017.11.04 |
---|---|
Return to VDSO using ELF Auxiliary Vectors leck (0) | 2017.09.02 |
The House of Einherjar (0) | 2017.08.16 |
The House of Force (0) | 2017.08.15 |
[UNDEAD] The House of Mind (0) | 2017.08.15 |