1 Shellcode
(1) Helloworld2.c
- 2의 보수를 이용한 접근법
- 역 방향으로 Call 명령어를 수행하여 Call 명령어에 null byte가 존재하지 않도록 함
- nasm을 이용해서 helloworld2.s을 어셈블(assemble), Hexdump로 쉘코드 생성
- call 명령어의 널바이트 제거됨
- mov 명령어의 널바이트는 여전히 제거되지 않음
BITS 32 ; Tell nasm this is 32-bit code.
jmp short one ; Jump down to a call at the end.
two:
; ssize_t write(int fd, const void *buf, size_t count);
pop ecx ; Pop the return address (string ptr) into ecx.
mov eax, 4 ; Write syscall #4
mov ebx, 1 ; STDOUT file descriptor
mov edx, 15 ; Length of the string
int 0x80 ; Do syscall: write(1, string, 14)
; void _exit(int status);
mov eax, 1 ; Exit syscall #1
mov ebx, 0 ; Status = 0
int 0x80 ; Do syscall: exit(0)
one:
call two ; Call back upwards to avoid null bytes
db "Hello, World!", 0x0a, 0x0d ; with newline and carriage return bytes
(2) Helloworld3.c
- mov 명령어에서 Null 바이트 제거하기
- 8byte 레지스터를 사용함 (al, bl, cl, dl)
- mov 명령어 널바이트 제거됨
BITS 32 ; Tell nasm this is 32-bit code.
jmp short one ; Jump down to a call at the end.
two:
; ssize_t write(int fd, const void *buf, size_t count);
pop ecx ; Pop the return address (string ptr) into ecx.
xor eax, eax ; Zero out full 32 bits of eax register.
mov al, 4 ; Write syscall #4 to the low byte of eax.
xor ebx, ebx ; Zero out full 32 bits of ebx register.
inc ebx ; Increment ebx to 1, STDOUT file descriptor.
xor edx, edx ; Zero out full 32 bits of edx register.
mov dl, 15 ; Length of the string
int 0x80 ; Do syscall: write(1, string, 14)
; void _exit(int status);
mov al, 1 ; Exit syscall #1, the top 3 bytes are still zeroed.
dec ebx ; Decrement ebx back down to 0 for Status = 0
int 0x80 ; Do syscall: exit(0)
one:
call two ; Call back upwards to avoid null bytes
db "Hello, World!", 0x0a, 0x0d ; with newline and carriage return bytes
2 shell-spawning Shellcode
(1) exec_shell1.c
- exec_shell2.s의 쉘코드 생성
(2) exec_shell2.c
- exec_shell2.s의 쉘코드 생성
- 1과 달리 스텍을 사용하여 생성함 > Shell code의 크기 줄어듬
- 공격에 유리함
3 Shellcode 연습문제
(1) 쉘 코드를 작성하여 /usr/bin/who와 동일한 출력 만들어내기