해킹 분야에서 상대 시스템을 공격하는 것
익스플로잇을 위해 제작된 어셈블리 코드 조각
일반적스로 셸을 획득하기 위한 목적으로 셸코드를 사용
셸을 획득하는 것은 시스템 해킹의 관점에서 매우 중요
해커가 rip을 자신이 작성한 셸코드로 옮길 수 있으면 해커는 원하는 어셈블리 코드를 실행되게 할 수 있음
파일을 열고, 읽은 뒤 화면에 출력해주는 셸코드
C언어 형식의 의사 코드char buf[0x30]; int fd=open("/tmp/flag", RD_ONLY, NULL); read(fd, buf, 0x30); write(1, buf, 0x30);
syscall rax rdi rsi rdx read 0x00 unsigned int fd char *buf size_t count write 0x01 unsigned int fd const char *buf size_t count open 0x02 const char *filename (파일 경로) int flags (r/w/x 열기 모드) umode_t mode
- 파일 서술자(File Descriptor, fd)는 유닉스 계열의 운영체제에서 파일에 접근하는 소프트웨어에 제공하는 가상의 접근 제어자
- 프로세스마다 고유의 서술자 테이블을 가지고 있으며, 그 안에 여러 파일 서술자를 저장
- 서술자 종류 : 0(stdin), 1(stdout), 2(stderr) → 프로세스를 터미널과 연결
- /tmp/flag 문자열을 아스키코드로 변환하면 0x616c662f706d742f67 (리틀 엔디안)
- 이를 스택에 push
- RD_ONLY는 0 → rsi=0
- 파일을 읽을 때는 mode는 의미가 없으므로 rdx=0
- open을 위해 rax=2
1 push 0x67 2 mov rax 0x616c662f706d742f67 3 push rax ; 스택에 push 4 mov rdi rsp ; rdi="/tmp/flag" 5 xor rsi, rsi ; rsi=0 6 xor rdx, rdx ; rdx=0 7 mov rax, 2 ; rax=2 8 syscall ; open("/tmp/flag", RD_ONLY, NULL)
- syscall의 반환값은 rax(함수의 반환값 레지스터)에 저장됨
→ open으로 획득한 /tmp/flag의 fd는 rax에 저장- read의 첫번째 인자 rdi=rax
- rsi는 파일에서 읽은 데이터를 저장할 주소를 가리킴
→ rsi=rsp-0x30- rdx는 파일로부터 읽어낼 데이터의 길이 → rdx=0x30
- read를 위해 rax=0
1 mov rdi, rax ; rdi=fd 2 mov rsi, rsp ; 3 sub rsi, 0x30 ; rsi=rsp-0x30 4 mov rdx, 0x30 ; rdx=0x30 5 mov rax, 0x0 ; rax=0 (read) 6 syscall ; read(fd, buf, 0x30)
- 출력은 stdout이므로 rdi=0x1
- rsi와 rdx는 read에서 사용한 것을 그대로 사용
- write를 위해 rax=1
1 mov rdi, 0x1 ; rdi = 1 (stdout) 2 mov rax, 0x1 ; rax = 1 (write) 3 syscall ; write(fd, buf, 0x30)