본문 바로가기

시스템

3주차_시스템

 

셸코드

셸코드(Shellcode)는 익스플로잇을 위해 제작된 어셈블리 코드 조각다. 일반적으로 셸을 획득하기 위한 목적이다.

 

/tmp/flag를 읽는 셸코드

char buf[0x30];

int fd = open("/tmp/flag", RD_ONLY, NULL);
read(fd, buf, 0x30); 
write(1, buf, 0x30);

 

syscall

syscall rax arg0(rdi) arg(rsi) arg(rdx)
read 0x00 unsigned int fd char *buf size_t count
write 0x01 unsigned int fd const char *buf size_t count
open 0x02 const char *filename int flags umode_t mode

 

int fd = open(“/tmp/flag”, O_RDONLY, NULL)

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)

read(fd, buf, 0x30)

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)

mov rdi, 1        ; rdi = 1 ; fd = stdout
mov rax, 0x1      ; rax = 1 ; syscall_write
syscall           ; write(fd, buf, 0x30)

 

 

execve 셸코드는 임의의 프로그램을 실행하는 셸코드인데, 이를 이용하면 서버의 셸을 획득할 수 있다. 

 

syscall rax arg0(rdi) arg1(rst) arg2(rdx)
execve 0x3b const char *filename const char *const *argv const char *const *envp

 

여기서 argv는 실행파일에 넘겨줄 인자, envp는 환경변수다.

 

스켈레톤 코드를 이용한 execve셸코드 컴파일

// File name: execve.c
// Compile Option: gcc -o execve execve.c -masm=intel

__asm__(
    ".global run_sh\n"
    "run_sh:\n"

    "mov rax, 0x68732f6e69622f\n"
    "push rax\n"
    "mov rdi, rsp  # rdi = '/bin/sh'\n"
    "xor rsi, rsi  # rsi = NULL\n"
    "xor rdx, rdx  # rdx = NULL\n"
    "mov rax, 0x3b # rax = sys_execve\n"
    "syscall       # execve('/bin/sh', null, null)\n"

    "xor rdi, rdi   # rdi = 0\n"
    "mov rax, 0x3c	# rax = sys_exit\n"
    "syscall        # exit(0)");

void run_sh();

int main() { run_sh(); }

 

퀴즈

Q1. stderr, stdin, stdout의 파일 지정자의 올바른 값을 고르시오.

A.stdin은 표준 입력으로 0, stdout은 표준 출력으로 1, stderr은 표준 오류로 2를 나타낸다. 

 

 

A. rdi는 파일 실행 경로를 말한다. x/s 0x7fffffffc278의 실행결과가 /bin/sh\x00이니, 0x7fffffffc278이다. 

 

Q3.(b)의 값은?

A. 0x3b이다. 리눅스시스템의 호출 번호다. 

 

어셈블리어 문제

2.

   0x0000000000001129 <+0>:	endbr64 
   0x000000000000112d <+4>:	push   rbp //스택 생성
   0x000000000000112e <+5>:	mov    rbp,rsp //rsp를 rbp에 복사
   0x0000000000001131 <+8>:	mov    DWORD PTR [rbp-0xc],0xa //rbp-0xc에 0xa저장
   0x0000000000001138 <+15>:	mov    DWORD PTR [rbp-0x8],0x18 //rbp-0x8에 0x18 저장
   0x000000000000113f <+22>:	mov    BYTE PTR [rbp-0xd],0x61 // rbp-0xd에 0x61저장
   0x0000000000001143 <+26>:	mov    eax,DWORD PTR [rbp-0x8] // eax에 rbp-0x8저장
   0x0000000000001146 <+29>:	mov    DWORD PTR [rbp-0x4],eax // rbp-0x4에 eax값 저장
   0x0000000000001149 <+32>:	sub    DWORD PTR [rbp-0xc],0x1 // rbp-0xc에 1을 뺀다
   0x000000000000114d <+36>:	mov    eax,DWORD PTR [rbp-0xc] //rbp-0xc를 eax에 저장
   0x0000000000001150 <+39>:	imul   eax,DWORD PTR [rbp-0x8] // rbp-0x8의 값에 4를 곱하여 eax에 저장
   0x0000000000001154 <+43>:	mov    DWORD PTR [rbp-0x4],eax //rbp-0x4를 eax에 저장
   0x0000000000001157 <+46>:	mov    eax,0x0 // eax에 0저장
   0x000000000000115c <+51>:	pop    rbp //함수 호출 끝
   0x000000000000115d <+52>:	ret     // 종료

3.

rbp-0xc a
rbp-0x8 c
rbp-0xd e
rbp-0x4 b

 

4.

코드를 최적화하기 위하여 불필요한 부분은 작성되지 않았다.  사용되지 않았기에 불필요하다고 판단, 컴파일 과정에서 제거된다. 

 

5.

push rbp

mov rbp,rsp

push rbp
mov rbp,rsp
int main()
mov DWORD PTR [rbp-0xc], 0xa int a = 10;
mov DWORD PTR [rbp-0x8], 0x18 int b = 24;
mov BYTE PTR [rbp-0xd], 0x61 int c = 'a';
mov eax, DWORD PTR [rbp-0x8]
mov DWORD PTR [rbp-0x4], eax
int d = c;
sub DWORD PTR [rbp-0xc], 0x1 d = a*b;
sub DWORD PTR [rbp-0xc], 0x1 return 0;

 

Bomb lab

disass mian을 하고 결과를 봅니다

결과를 얻어줍니다

'시스템' 카테고리의 다른 글

7주차 시스템  (0) 2024.08.19
5주차_시스템  (0) 2024.08.07
4주차_시스템  (0) 2024.07.29
시스템 2주  (1) 2024.07.15
시스템 1주  (0) 2024.07.07