SROP基本原理和利用

概述

SROP: Sigreturn Oriented Programming ,系统Signal Dispatch之前会将所有寄存器压入栈,然后调用signal handler,signal handler返回时会将栈的内容还原到寄存器。 如果事先填充栈,然后直接调用signal handler,那在返回的时候就可以控制寄存器的值。

资源

1. Framing Signals—A Return to Portable Shellcode

http://www.ieee-security.org/TC/SP2014/papers/FramingSignals-AReturntoPortableShellcode.pdf

PS:SROP的论文,不容易理解,未读。

 2. Sigreturn Oriented Programming (SROP) Attack攻击原理

http://www.freebuf.com/articles/network/87447.html

PS:介绍了SROP的基本原理。

3. Sigreturn Oriented Programming攻击简介

https://www.anquanke.com/post/id/85810

PS:介绍了SROP的基本原理。附带有32位的DEMO。

4. Playing around with SROP

https://x86overflow.blogspot.in/2014/04/playing-around-with-srop.html

PS:32位SROP DEMO

5. Sigreturn Oriented Programming

https://www.slideshare.net/AngelBoy1/sigreturn-ori

PS:介绍了SROP的基本原理

6. 2017 429 ichunqiu ctf smallest(pwn300) writeup

http://anciety.cn/2017/04/21/2017429ctf-smallest-writeup/

PS:64位SROP实例

7. Return to VDSO using ELF Auxiliary Vectors。https://v0ids3curity.blogspot.jp/2014/12/return-to-vdso-using-elf-auxiliary.html。

PS:VDSO的利用,SROP可以利用VDSO。

8. Defcon 2015 Qualifier fuckup

https://github.com/ctfs/write-ups-2015/tree/master/defcon-qualifier-ctf-2015/pwnable/fuckup

此题较难。

SROP原理

原理主要参考上面freebuf和 anquanke的文章,不再赘述。

SROP利用

4.1 Signal Frame

Ubuntu 16.04 64

4.1.1 X86

Sigcontext

x86来说,此数据结构为sigcontext。

大小为80字节,示例:

frame.set_regvalue("eax", SYS_MPROTECT) #125

frame.set_regvalue("ebx", page_text_segment) #0x08048000

frame.set_regvalue("ecx", 0x1000)

frame.set_regvalue("edx", 0x7)

frame.set_regvalue("ebp", page_text_segment)

frame.set_regvalue("eip", INT_80) #0x08048071

frame.set_regvalue("esp", page_text_segment+16)

frame.set_regvalue("cs", 0x23)

frame.set_regvalue("ss", 0x2b)

frame.set_regvalue("ds", 0x2b)

frame.set_regvalue("es", 0x2b)

frame.set_regvalue("fs", 0x0)

frame.set_regvalue("gs", 0x0)

00000000: 00 00 00 00 00 00 00 00  2B 00 00 00 2B 00 00 00  ........+...+...

00000010: 00 00 00 00 00 00 00 00  00 80 04 08 10 80 04 08  ................

00000020: 00 80 04 08 07 00 00 00  00 10 00 00 7D 00 00 00  ............}...

00000030: 00 00 00 00 00 00 00 00  71 80 04 08 23 00 00 00  ........q...#...

00000040: 00 00 00 00 00 00 00 00  2B 00 00 00 00 00 00 00  ........+.......

/usr/include/x86_64-linux-gnu/bits/sigcontext.h

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;

};

4.1.2 X64

ucontext

Sigcontext

大小为248个字节(0xF8),示例:

frame = SigreturnFrame()

frame.rsp = elf_hdr_addr+0x18        #0x400018

frame.rax = constants.SYS_mprotect   #0x0a

frame.rdi = elf_hdr_addr              #0x400000

frame.rsi = 0x1000

frame.rdx = 0x7

frame.rip = syscall_addr

00000010  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│

    *

    00000070  00 00 00 00  00 00 00 00  00 00 40 00  00 00 00 00  │····│····│··@·│····│

    00000080  00 10 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│

    00000090  00 00 00 00  00 00 00 00  07 00 00 00  00 00 00 00  │····│····│····│····│

    000000a0  0a 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│

    000000b0  18 00 40 00  00 00 00 00  be 00 40 00  00 00 00 00  │··@·│····│··@·│····│

    000000c0  00 00 00 00  00 00 00 00  33 00 00 00  00 00 00 00  │····│····│3···│····│

    000000d0  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  │····│····│····│····│

    *

    00000100  00 00 00 00  00 00 00 00  0a                        │····│····│·│

/usr/include/x86_64-linux-gnu/bits/sigcontext.h

/usr/include/x86_64-linux-gnu/bits/sigstack.h

/usr/include/x86_64-linux-gnu/bits/sigset.h

typedef struct sigaltstack

{

void *ss_sp;

int ss_flags;

size_t ss_size;

} stack_t;

 

typedef struct _libc_fpstate *fpregset_t;

 

#ifdef __x86_64__

__extension__ typedef long long int greg_t;

#define NGREG 23

typedef greg_t gregset_t[NGREG];

#else /* !__x86_64__ */

typedef int greg_t;

#define NGREG 19

typedef greg_t gregset_t[NGREG];

#endif

 

/* Context to describe whole processor state. */

typedef struct

{

gregset_t gregs;

/* Note that fpregs is a pointer. */

fpregset_t fpregs;

__extension__ unsigned long long __reserved1 [8];

} mcontext_t;

 

# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))

typedef struct

  {

    unsigned long int __val[_SIGSET_NWORDS];

  } __sigset_t;

 

/* Userlevel context. */

typedef struct ucontext

{

unsigned long int uc_flags;

struct ucontext *uc_link;

stack_t uc_stack;

mcontext_t uc_mcontext;    /* sigcontext for x86_64 */

__sigset_t uc_sigmask;

struct _libc_fpstate __fpregs_mem;

} ucontext_t;

 

struct sigcontext

{

__uint64_t r8;

__uint64_t r9;

__uint64_t r10;

__uint64_t r11;

__uint64_t r12;

__uint64_t r13;

__uint64_t r14;

__uint64_t r15;

__uint64_t rdi;

__uint64_t rsi;

__uint64_t rbp;

__uint64_t rbx;

__uint64_t rdx;

__uint64_t rax;

__uint64_t rcx;

__uint64_t rsp;

__uint64_t rip;

__uint64_t eflags;

unsigned short cs;

unsigned short gs;

unsigned short fs;

unsigned short __pad0;

__uint64_t err;

__uint64_t trapno;

__uint64_t oldmask;

__uint64_t cr2;

__extension__ union

{

struct _fpstate * fpstate;

__uint64_t __fpstate_word;

};

__uint64_t __reserved1 [8];

};

4.2 Sigreturn系统调用

关于sigreturn的系统调用:

    /*for x86*/

    mov eax,0x77

    int 80h

    /*for x86_64*/

    mov rax,0xf

    syscall

4.3 Sigreturn gadget

 

l X86 VDSO中有sigreturn gadget

millionsky@ubuntu-12:~/tmp$ objdump -d linux-gate.so.1

linux-gate.so.1:     file format elf32-i386

Disassembly of section .text:

ffffe400 <__kernel_sigreturn>:

ffffe400:       58                      pop    %eax

ffffe401:       b8 77 00 00 00          mov    $0x77,%eax

ffffe406:       cd 80                   int    $0x80

ffffe408:       90                      nop

ffffe409:       8d 76 00                lea    0x0(%esi),%esi

......

millionsky@ubuntu-16:~/tmp/VDSO$ objdump -D -b binary -mi386:x86-64 /tmp/linux-vsyscall.so  | grep syscall -C 2

/tmp/linux-vsyscall.so:     文件格式 binary

--

0000000000000000 <.data>:

       0:       48 c7 c0 60 00 00 00    mov    $0x60,%rax

       7:       0f 05                   syscall

       9:       c3                      retq   

       a:       cc                      int3   

l X86也可以寻找设置eaxint $0x80gadget

l X64 vsyscall中有syscall&ret指令

l X64也可以寻找设置raxsyscall指令的gadget

4.4 SROP利用

【利用方式】

1) 伪造sigcontext结构,push到栈中;

2) Ret address设置为sigreturn gadget;

3) signal frame中的RIP(EIP)设置为syscall/int 0x80;

4) sigreturn回来后,就会执行设置的syscall,如execve,read,write...etc

【前提】

需要可控的IP和栈(如ROP

需要知道sigreturn系统调用gadget的地址;或者通过ROP构造sigreturn系统调用;

需要知道syscall/int 0x80指令的地址;

【特点】

全部的register都可控;

可以改变stack的位置;

【注意】

csssdsesfsgssegment selector register尽量按照原本的填,不然会喷掉;

Esp,ebp不可为0,不然一样会喷;

猜你喜欢

转载自blog.csdn.net/luozhaotian/article/details/79607572