해킹분야에선 상대 시스템을 공격하는것을 익스플로잇(Exploit)이라고 부른다.
이 커리큘럼에서는 9가지 공격기법을 배우는데 이 코스에서는 셸코드를 소개한다.
익스플로잇을 위해 제작된 어셈블리 코드 조각을 일컫습니다.
일반적으로 셸을 획득하기 위한 목적으로 셸코드를 사용한다. 셸을 휙득하는 것은 시스템 해킹의 관점에서 매우 중요하다. 그 이유를 execve 셸 코드에서 살펴보겠다.
만약 해커가 rip(현재 실행되고 있는 명령의 실행 주소)를 자신이 작성한 셸코드로 옮길 수 있으면 해커가 원하는 어셈블리 코드가 실행 되게 할 수 잇다.
셸코드는 어셈블리어로 구성되므로 공격을 수행할 대상 아키텍처와 운영체제에 따라, 그리고 셸코드의 목적에 따라 다르게 작성됩니다. 일반적인 인터넷에 공유되는 셸코드는 범용적으로 작성된 것이기 때문에, 실행될 때의 메모리 상태 같은 시스템 환경을 완전히 반영하지 못하기 때문에, 실행될 때의 메모리 상태 같은 시스템 환경을 완전히 반영하지는 못한다.
따라서 최적의 셸코드는 일반적으로 직접 작성해야 하며, 상황에 따라 반드시 그래야만 할 수도 있다.
첫 번째로 해야 할 일은 "/tmp/flag"라는 문자열을 메모리에 위치시키는 것이다. 이를 위해 /tmp/flag를 16진수 0x616c662f706d742f67로 바꿔주고 push한다. 그리고 rdi가 이를 가리키도록 rsp를 rdi로 옮긴다. O_RDONLY는 0이므로 rsi는 0으로 설정한다.
파일을 읽을떄 mode는 의미를 가지지 않으므로 rdx는 0으로 설정한다.
마지막으로 rax를 open의 syscall 값인 2로 설정한다.
구현
push 0x67 mov rax, 0x616c662f706d742f push rax mov rdi, rsp ; rdi = "/tmp/flag" xor rsi, rsi ; rsi = 0 ; RD_ONLY xor rdx, rdx ; rdx = 0 mov rax, 2 ; rax = 2 ; syscall_open syscall ; open("/tmp/flag", RD_ONLY, NULL)
syscall의 반환 값은 rax로 저장된다. 따라서 open으로 획득한 /tmp/flag의 fd는 rax에 저장된다. read의 첫번째 인자를 이 값으로 설정해야 하므로 rax를 rdi에 대입한다. rsi는 파일에서 읽은 데이터를 저장할 주소를 가리킨다. 0x30만큼 읽을 것이므로 rsi에 rsp-0x30을 대입한다.
rdx는 파일로부터 읽어낼 데이터의 길이인 0x30으로 설정합니다.
read 시스템 콜을 호출하기 위해서는 rax를 0으로 설정한다.
구현
mov rdi, rax ; rdi = fd mov rsi, rsp sub rsi, 0x30 ; rsi = rsp-0x30 ; buf mov rdx, 0x30 ; rdx = 0x30 ; len mov rax, 0x0 ; rax = 0 ; syscall_read syscall ; read(fd, buf, 0x30)
출력은 stdout으로 할 것이므로 rdi를 0x1로 설정한다.
rsi와 rdx는 read에서 사용한 값을 그대로 사용한다.
write 시스템 콜을 호출하기 위해서 rax를 1로 설정한다.
구현
mov rdi, 10; rdi = 1 ; fd = stdout mov rax, 0x1 ; rax = 1 ; syscall_write syscall ; write(fd, buf, 0x30)