상대 시스템을 공격하는 것
⭐ 해커가 rip을 자신이 작성한 셸코드의 주소로 변경
char buf[0x30];
int fd = open("/tmp/flag", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);
; int fd = open("/tmp/flag", O_RDONLY, NULL) 이 부분을 구현할거임
push 0x67 ; g의 아스키코드 g는 왜 따로 하느냐? 64비트(8글자)가 다 차버려서ㅠㅠ
mov rax, 0x616c662f706d742f ; /tmp/fla 문자열의 아스키 코드 -> 리틀 엔디언
push rax ; 16진수 두개씩 끊어서 읽어봐
mov rdi, rsp ; rdi = "/tmp/flag" , rdi는 arg0임
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)
; read(fd, buf, 0x30) 이번엔 이 부분을 구현할 거임
; – 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
; write(1, buf, 0x30) 차례
; rsi, rdx는 read에서 사용한 값을 그대로 사용
mov rdi, 1 ; rdi = 1 ; fd = stdout 출력은 stdout으로 할거라서
mov rax, 0x1 ; rax = 1 ; syscall_write
syscall ; write(fd, buf, 0x30)
📌 fd란?
유닉스 계열의 운영체제에서 파일에 접근하는 소프트웨어에 제공하는 가상의 접근 제어자
0 : 일반 입력(Standard Input, STDIN) 주로 키보드
1 : 일반 출력(Standard Output, STDOUT) 화면
2 : 일반 오류(Standard Error, STDERR)
: 임의의 프로그램을 실행하는 셸코드
📌 출처 : 진구
C 언어에서 execve()
함수는 새로운 프로세스를 생성하는 시스템 콜입니다. 이 함수는 기존의 프로세스를 새로운 프로세스로 대체하는데 사용됩니다.
execve()
함수는 다음과 같은 선언을 갖습니다.
int execve(const char *filename, char *const argv[], char *const envp[]);
filename
: 실행할 프로그램의 경로와 이름입니다.argv[]
: 실행할 프로그램에 전달할 인자값들을 담고 있는 문자열 배열입니다.envp[]
: 실행할 프로그램에서 사용할 환경 변수를 담고 있는 문자열 배열입니다.execve()
함수를 호출하면 새로운 프로세스가 생성되고 filename
으로 지정한 프로그램이 실행됩니다. 실행할 프로그램은 현재 프로세스와는 독립적으로 동작하며, argv[]
와 envp[]
를 통해 전달된 인자와 환경 변수를 사용할 수 있습니다.
execve()
함수는 호출에 성공하면 현재 프로세스의 메모리 영역을 대체하여 새로운 프로그램을 실행합니다. 즉, 현재 프로세스는 새로운 프로그램이 종료될 때까지 더 이상 실행되지 않습니다. 이러한 특징으로 인해, execve()
함수는 다른 프로그램을 실행하는 용도로 주로 사용됩니다.
예를 들어, 다음과 같은 코드는 ls
명령어를 실행하는 예제입니다.
#include <stdio.h>
#include <unistd.h>
int main(void) {
char *argv[] = {"ls", "-l", NULL};
execve("/bin/ls", argv, NULL);
printf("This line will not be executed\n");
return 0;
}
위 코드에서 execve()
함수는 /bin/ls
프로그램을 실행합니다. argv
배열은 ls
프로그램에 전달할 인자를 저장하고 있으며, NULL
을 마지막으로 구분합니다. envp
배열은 NULL
로 설정하여 환경 변수를 사용하지 않도록 합니다. 실행 결과로는 현재 디렉토리의 파일 목록이 출력됩니다. 이후의 코드는 execve()
함수가 호출되면 실행되지 않습니다.
드림핵, 우리 학교 교수님