농소

시스템 프로그래밍, 시스템 콜 본문

Security/System Hacking

시스템 프로그래밍, 시스템 콜

농소 2018. 1. 25. 04:37

시스템 프로그래밍



게임 프로그래밍 - 게임 관련 라이브러리 사용

네트워크 프로그래밍 - 소켓을 이용한 네트워크 라이브러리 사용


시스템 프로그래밍


  - 윈도우즈 : win API (Advanced Programing Interface)

  - 리눅스 : system call 


시스템 호출(System call)은 운영 체제의 커널이 제공하는 서비스에 대해, 

응용 프로그램의 요청에 따라 커널에 접근하기 위한 인터페이스이다.


os를 크게 나누면 2가지로 나눌 수 있다


1). shell(user) - 사용자 영역 (목적 - h/w제어)

2). H/W(Device)


  - shell에서 하드웨어에 바로접근하게되면 문제가발생 한다.

  - 그래서 중간에 커널이 존재한다. 또, 장치를 출력하고싶으면 interface를 이용

  - interface = win api, system call 함수형태로 제공


커널 : 장치로부터 자원을 내보내거나 들이거나 어떻게 메모리를 관리할것인가를 관리

         os랑은 다름 os가 더 큰개념


 쉘 | 커널 | 하드웨어 -> os라 함


  - c에서 printf같은경우 내부적으로 write라는 시스템콜을 두번 사용한다.

  - eax레지스터에 system call 번호를 넣고, ebx, ecx, edx, esi, edi 를 인자로 이용한다.

  - 그외 인자를 추가할 시 스택을 이용

  - 인터럽트 명령어를 사용하여 시스템콜을 호출 = 80h


리눅스 시스템 콜 같은경우 win api와는 다르게 웹상에 공개되어있어 쉽게 찾아볼 수 있다.


주로 이용하는 시스템 콜 참조 사이트

https://syscalls.kernelgrok.com/


예를들어 write같은 경우


<write system call 표현방법>



이런식으로 표현이 가능하다.



[실습]


1). 디렉터리 생성 : mkdir 명령어 만들기


  - read, write, mkdir 시스템콜 이용한다.


참고사항

  - read 는 \n까지 읽어들인다

  - read는 읽어들인 문자열의 길이를 반환

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


c언어

int main()

{

  char path[1024] = {0,};

  int end = 0;

  int result = 0;


  write( 1, "input: ", 7 );

  read( 0, path, 1024 );

  while( path[end] != '\n' ) {

    end++

  }

  path[end] = 0;


  result = mkdir( path, 0755);

  if( result < 0) {

    write( 1, "failed\n", 7 )

  } else {

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

  }


  return 0;

}


어셈블리 언어


segment .data

fail            db      'failed', 10, 00

success         db      'success', 10, 00

input           db      'input :', 00


segment .text

global  _start


_start:

        push    ebp

        mov     ebp,    esp

        sub     esp,    1032


        mov     ecx,    256

        mov     eax,    0

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

        rep     stosb


        mov     dword [ebp-1028],       0       ;end

        mov     dword [ebp-1032],       0       ;result


        ; write( 1, "input: ", 7 );

        mov     eax,    4

        mov     ebx,    1

        mov     ecx,    input

        mov     edx,    7

        int     80h


        ; read( 0, path, 1024 );

        mov     eax,    3

        mov     ebx,    0

        lea     ecx,    [ebp-1024]

        mov     edx,    1024

        int     80h


while:

        lea     eax,    [ebp-1024]

        mov     ebx,    [ebp-1028]

        cmp     byte [eax + ebx * 1],   10

        je      end

        inc     dword [ebp-1028]

        jmp     while


end:

        lea     eax,    [ebp-1024]

        mov     ebx,    [ebp-1028]

        mov     byte [eax + ebx * 1],   0    // 마지막 널문자 제거 제거를 안하면

example 파일을 만들시 example\n이 되버림


        ; result = mkdir( path, 0755);

        mov     eax,    27h

        lea     ebx,    [ebp-1024]

        mov     ecx,    0755o

        int     80h


        mov     dword [ebp-1032],       eax


if:

        cmp     dword [ebp-1032],       0

        jge     .else


        mov     eax,    4

        mov     ebx,    1

        mov     ecx,    fail

        mov     edx,    7

        int     80h

        jmp     .end


.else:

        mov     eax,    4

        mov     ebx,    1

        mov     ecx,    success

        mov     edx,    8

        int     80h


.end:

        xor     eax,    eax


        leave

        ret


2). 파일 입/출력 : cat


  - open, read, write 시스템콜 이용


c언어

int main()

{

  char path[1024] = {0,};

  char buffer[1024] = {0,};

  int size = 0;

  int fd = 0;

  int end = 0;


  write( 1, "input: ", 7 );

  read( 0, path, 1024 );

  while( path[end] != '\n' ) {

    end++;

  }

  path[end] = 0;


  fd = open( path, 0, 0 );

  size = read( fd, buffer, 1024 );

  

  while(size == 0) {

    write( 1, buffer, 1024 );

    size = read( fd, buffer, 1024 ); 

}


어셈블리 언어


segment .data

input   db      'input: ', 00


segment .text

global  _start


_start:

        push    ebp

        mov     ebp,    esp

        sub     esp,    2060


        mov     ecx,    512

        mov     eax,    0

        lea     edi,    [ebp-2048]

        rep     stosd


        mov     dword [ebp-2052],       0       ; size

        mov     dword [ebp-2056],       0       ; fd

        mov     dword [ebp-2060],       0       ; end


        ;write

        mov     eax,    4

        mov     ebx,    1

        mov     ecx,    input

        mov     edx,    7

        int     80h


        ;read

        mov     eax,    3

        mov     ebx,    0

        lea     ecx,    [ebp-1024]

        mov     edx,    1024

        int     80h


while1:

        lea     eax,    [ebp-1024]

        mov     ebx,    [ebp-2060]

        cmp     byte [eax + ebx * 1],   10

        je      .end


        inc     dword [ebp-2060]

        jmp     while1


.end:

        lea     eax,    [ebp-1024]

        mov     ebx,    [ebp-2060]

        mov     byte [eax + ebx *1],    0


        ;open

        mov     eax,    5

        lea     ebx,    [ebp-1024]

        mov     ecx,    0

        mov     edx,    0

        int     80h


        mov     dword [ebp-2056],       eax

        ;read

        mov     eax,    3

        mov     ebx,    [ebp-2056]

        lea     ecx,    [ebp-2048]

        mov     edx,    1024

        int     80h


        mov     dword [ebp-2052],       eax


while2:

        cmp     dword [ebp-2052],       0

        je      end


        ;write

        mov     eax,    4

        mov     ebx,    1

        lea     ecx,    [ebp-2048]

        mov     edx,    1024

        int     80h


        ;read

        mov     eax,    3

        mov     ebx,    [ebp-2056]

        lea     ecx,    [ebp-2048]

        mov     edx,    1024

        int     80h


        mov     dword [ebp-2052],       eax


        jmp     while2


end:

        xor     eax,    eax


        leave

        ret


3). 쉘 : shell


  - execve, read, write 사용


c언어

#include <stdio.h>


int main()

{

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

  char buffer[1024] = {0,};

  int end = 0;


  write( 1, "input: ", 7 );

  read( 0, buffer, 1024 );


//  while( buffer[end] != '\n' ) {

  while( *(buffer+end) != '\n' ){

    end++;

  }

  }

  buffer[end] = 0;


  argv[0] = buffer;

  argv[1] = NULL;


  execve( buffer, argv, NULL);



  return 0;


}


어셈블리 언어


segment .data

input   db      'input: ', 00


segment .text

global  _start


_start:

        push    ebp

        mov     ebp,    esp

        sub     esp,    1036


        mov     ecx,    256

        mov     eax,    0

        lea     edi,    [ebp-1024]

        rep     stosd


        mov     dword [ebp-1028],       0

        mov     dword [ebp-1032],       0

        mov     dword [ebp-1036],       0


        mov     eax,    4

        mov     ebx,    1

        mov     ecx,    input

        mov     edx,    7

        int     80h


        mov     eax,    3

        mov     ebx,    0

        lea     ecx,    [ebp-1024]

        mov     edx,    1024

        int     80h


while:

        lea     eax,    [ebp-1024]

        mov     ebx,    [ebp-1036]

        cmp     byte [eax + ebx * 1],   10

        je      .end


        inc     dword [ebp-1036]

        jmp     while


.end:

        lea     eax,    [ebp-1024]

        mov     ebx,    [ebp-1036]

        mov     byte [eax + ebx * 1],   0


        lea     eax,    [ebp-1024]

        mov     dword [ebp-1032],       eax

        mov     dword [ebp-1028],       0


        mov     eax,    11

        lea     ebx,    [ebp-1024]

        lea     ecx,    [ebp-1032]

        mov     edx,    0

        int     80h


        xor     eax,    eax


        leave

        ret