본문 바로가기
프로그래밍/SYSTEM HACKING

[SYSTEM HACKING] 시스템 콜 실습 ( mymkdir, mycat, myshell )

by B T Y 2017. 11. 2.
반응형

시스템 콜 실습 ( mymkdir, mycat, myshell )에 대해서 정리한다.

 

 

 

[실습]

 

1. mymkdir ( mkdir 명령 )

 

  - 프로그램 실행 결과

 

  #> ./mymkdir

  path: mydir

  success mkdir

 

  #> ./mymkdir

  path: mydir

  fail mkdir

 

  - system call: read, write, mkdir

 

  * 프로그램 작성시 고려해야 하는 부분

      ! read 시스템 콜은 뉴라인까지 입력을 받는다.

      ! read 시스템 콜은 읽어들인 문자열의 길이를 반환한다.

      ! 메모리는 지역변수만 사용

      ! 다른 C 표준 함수는 사용하지 않는다.

 

 

[ C언어 코드 ]

int main()

{

  char path[1024];

  int len = 0;

  int ret = 0;

 

  write( 1, "path: ", 6 );

  len = read( 0, path, 1024 );

  path[len-1] = 0;

 

  ret = mkdir( path, 0755 );

  if( ret != 0 ) {

    write( 1, "failed\n", 8 );

  }else {

    write( 1, "success\n", 8 );

  }

  return 0;

}

 

 

[ 어셈블리 코드 ]

section .data

path db 'path: ', 00

print_success db 'success', 10, 00

print_failed db 'failed', 10, 00

 

section .text

global _start

 

_start:

   push  ebp

mov ebp, esp                                   ;  prologue

sub esp, 1032

 

mov dword [ebp-1028], 0             ;  int len = 0;

mov dword [ebp-1032], 0                 ;  int ret = 0;

 

; write system call

mov eax, 4

mov ebx, 1

mov ecx, path

mov edx, 6

int 80h

 

; read system call

mov eax, 3

mov ebx, 0

lea ecx, [ebp-1024]

mov edx, 1024

int 80h

 

mov dword [ebp-1024+eax-1], 0          ;  path[len-1] = 0;

 

; mkdir system call

mov eax, 39

lea ebx, [ebp-1024]

mov ecx, 0755q

int 80h

 

cmp eax, 0

jz success

 

; print failed

mov eax, 4

mov ebx, 1

mov ecx, print_failed

mov edx, 7

int 80h

jmp end

 

success:

; print success

mov eax, 4

mov ebx, 1

mov ecx, print_success

mov edx, 8

int 80h

end:

; exit system call

mov eax, 1

mov ebx, 0

int 80h

 

 

 

( mymkdir 프로그램을 실행해서 디렉터리를 생성해보면 정상적으로 생성이 되고

디렉터리 이름이 중복 되었을 경우에는 failed가 출력 되면서 생성이 되지 않는걸 확인할 수 있다 )

 

 

( 실행 권한 또한 mkdir system call 인자에서 0755로 주었기 때문에 rwxr-xr-x의 권한으로 디렉터리가 생성이 되었다 )

 

 

 

 

2. mycat ( cat 명령 )

 

- 프로그램 실행 결과

 

  #> ./mycat

  file: /etc/passwd

  ...

 

  - system call: open,read, write

 

 

* 프로그램 작성시 고려해야 하는 부분

    !! read의 3번째 인자만큼 파일의 내용을 읽어오게 된다.

   !! buffer보다 적게 읽어오면 마지막라인

    !! open 시스템 콜에서 세번째 인자에 O_RDONLY는 번호로 0을 사용한다. 

         ( 해당 인자를 입력 받을때 자료형이 int이다 )

    !! 어셈블리에서 메모리 초기화는 rep stosd 명령어를 이용한다.

 

 

[ C언어 코드 ]

int main()

{

  char path[1024] = {0,};

  char buffer[1024] = {0,};

  int len = 0;

  int ret = 0;

  int fd = 0;

 

  write(1, "file path: ", 11);

  len = read(0, path, 1024);

  path[len-1] = 0;

 

  fd = open( path, 0 );

 

  while( (ret = read( fd, buffer, 400 )) != 0) {

    write( 1, buffer, 1024 );

    memset( buffer, 0, 1024 );

  }

 

  return 0;

}

 

 

[ 어셈블리 코드 ]

section .data

file db 'file: ', 00

 

sectin .text

global _start

 

_start:

 

push ebp

mov ebp, esp

sub esp, 2060

 

mov dword [ebp-2052], 0     ;  int len = 0;

mov dword [ebp-2056], 0     ;  int ret = 0;

mov dword [ebp-2060], 0     ;  int fd = 0;

 

; write system call

mov eax, 4

mov ebx, 1

mov ecx, file

mov edx, 6

int 80h

 

; read system call

mov eax, 3

mov ebx, 0

lea ecx, [ebp-1024]

mov edx, 1024

int 80h

 

mov dword [ebp-2052], eax         ;  len = read(0, path, 1024);

mov ebx, dword [ebp-2052]

mov dword [ebp-1024+ebx-1] ;  path[len-1] = 0;

 

; open system call

mov eax, 5

lea ebx, [ebp-1024]

mov ecx, 0                 ;  O_RDONLY( 0 )

int 80h

 

mov dword [ebp-2060], eax         ;  fd = open( path, 0 );

 

while:

mov ecx, 256

mov eax, 0

lea edi, [ebp-2048]

rep stosd                 ;  initialize the array

 

;read  system call

mov eax, 3

mov ebx, dword [ebp-2060]

lea ecx, [ebp-2048]

mov edx, 400

int 80h

 

cmp eax, 0

jz while_end

 

; write system call

mov eax, 4

mov ebx, 1

lea ecx, [ebp-2048]

mov edx, 400

int 80h

jmp while

while_end:

; exit system call

mov eax, 1

mov eax, 0

int 80h

 

 

rep stosd 코드 ( 배열 초기화 예시 코드 )

 

   - 해당 코드를 실행 해보면 rep stosd를 어떻게 사용이 되는지 이해하기 쉽다.

 

section .data

file db 'file: ', 00

 

section .text

global _start

 

_start:

 

push ebp

mov ebp, esp

sub esp, 1024

 

mov ecx, 256

mov eax, 41414141h

lea edi, [ebp-1024]

rep stosd

 

mov eax, 4

mov ebx, 1

lea ecx, [ebp-1024]

mov edx, 1024

int 80h

 

 

 

( mycat 프로그램을 실행하게 되면 cat 명령을 실행할 경로를 절대경로로 입력 받게 된다.

여기서는 사용자 정보가 들어있는 /etc/passwd를 입력했다. )

 

 

( 출력된 결과가 많아서 한 화면에 다 나오지 않았지만 마지막 사용자인 squid까지 모두 출력이 되었다. )

 

 

 

 

3. myshell ( shell 만들기 )

 

- 프로그램 실행 결과

 

  #> ./myshell

  cmd: /bin/ls

  ...

 

  - system call: read, write, execve

 

 

[예시 코드]

int main()

{

  char *shell[2] = {0,};

 

  shell[0] = "/bin/ls";

  shell[1] = 0;

 

  execve( shell[0], shell, 0 );

 

  return 0;

 }

 

 

[C언어 코드]

int main()

{

  char cmd[1024] = {0,};

  char *shell[2] = {0,};

  int len = 0;

  int ret = 0;

 

  write(1, "cmd: ", 5);

  len = read(0, cmd, 1024);

  cmd[len-1] = 0;

 

  shell[0] = cmd;

  shell[1] = 0;

 

  execve( shell[0], shell, 0 );

 

  return 0;

 }

 

 

[ 어셈블리 코드 ]

section .data

print_cmd db 'cmd: ', 00

 

section .text

global _start

 

_start:

push ebp

mov ebp, esp                         ;  prologue

sub esp, 1040

 

mov ecx, 256

mov eax, 0

lea edi, [ebp-1024]                         ;  char cmd[1024] = {0,};

rep stosd

 

mov dword [ebp-1028], 0

mov dword [ebp-1032], 0         ;  char *shell[2] = {0,};

mov dword [ebp-1036], 0         ;  int len = 0;

mov dword [ebp-1040], 0         ;  int ret = 0;

 

; write system call

mov eax, 4

mov ebx, 1

mov ecx, print_cmd

mov edx, 5

int 80h

 

; read system call

mov eax, 3

mov ebx, 0

lea ecx, [ebp-1024]

mov edx, 1024

int 80h

 

mov dword [ebp-1036], eax                 ;  len = read(0, path, 1024);

mov ebx, dword [ebp-1036]

lea eax, [ebp-1024+ebx-1]

mov byte [eax] , 0                         ;  path[len-1] = 0;

 

lea eax, [ebp-1024]

mov dword [ebp-1032], eax         ;  shell[0] = cmd;

mov dword [ebp-1028], 0         ;  shell[1] = 0;

 

; execve system call

mov eax, 11

mov ebx [ebp-1032]

lea ecx, [ebp-1032]

mov edx, 0

int 80h

 

; exit system call

mov eax, 1

mov ebx, 0

 

int 80h

 

 

 

( myshell 프로그램을 실행하면 명령어 절대 경로를 입력 받게 되고 /bin/ls를 입력한 결과

해당 디렉터리에서 ls 명령어가 실행되 파일과 디렉터리 목록이 보이게 된다 )

 

!! execve는 path를 확인하지 않기 때문에 명령어를 실행하려면 절대경로를 입력해줘야 한다.

 

 

반응형

댓글