Computer Science
[시스템 프로그래밍] Bomb Lab Phase 5
[시스템 프로그래밍] Bomb Lab Phase 5
2022.12.25disas phase_5 명령어로 phase_5의 어셈블리어를 조사하자. +4줄에서 string_length 함수를 호출한다. 문자열의 길이? 어떤 함수일까? 뭔가 조건이 만족 될 때 까지 반복하는 함수 인 것 같다. 입력받은 문자열 내부를 순회하면서 문자열에 따라 특정 값을 계속해서 더하는 것 같은데.. 우선은 phase_5를 계속 조사하자. 다시 phase_5로 돌아와서, +9줄에서 string_length 함수의 반환값이 6과 같은지 검사하고, 6이 아니면 폭탄을 터뜨림을 확인할 수 있다. 그러면 phase_5의 입력 양식은 길이가 6인 문자열 일텐데.. 일단 길이가 6인 아무 문자열이나 입력하고 디버깅해보자. 대충 aaaccc를 입력했다. rdi 레지스터에 입력 값이 저장됨을 확인할 수 있다. +..
[시스템 프로그래밍] Bomb Lab Phase 4
[시스템 프로그래밍] Bomb Lab Phase 4
2022.12.24항상 하던대로 먼저 phase_4의 어셈블리어를 조사하자. +35줄에서 입력받는 부분이 바로 보인다. phase_2와 phase_3에서 한 것처럼 입력 형식을 살펴보자. 이번에도 두 개의 정수를 입력받는다. 두 개의 정수이니, 대충 1 2를 입력하고 한 줄 씩 진행해보자. +40 줄에서 eax값과 2를 비교하고, +43에서 두 값이 다른 경우 폭탄을 터뜨린다. +40줄에서 레지스터의 값을 확인해보니 rax에 2가 저장돼있었다. 따라서 43줄에서 폭탄은 터지지 않는다. 아마 두 개의 입력이 잘 들어왔는지 확인하는 부분 인 것 같다. 이후 +45줄에서 0xe와 rsp에 있는 값을 비교한다. rsp에는 입력한 값인 1과 2가 저장돼있다. +49줄에서 +45줄의 결과에 따라 폭탄을 터뜨린다. 0xe는 10진수로..
[시스템 프로그래밍] Bomb Lab Phase 3
[시스템 프로그래밍] Bomb Lab Phase 3
2022.12.23disas phase_3로 phase_3 함수를 어셈블리어로 조사해보자. +35줄에서 정수를 입력받는 것 같다. phase_2처럼 +28의 source 부분에 입력값의 형태가 저장돼 있을 것 같다. 어떤 형식으로 입력받는지 살펴보자. ni 명령어로 한 줄 씩 읽어가면서 source 부분을 확인해봤다. 정수 2개를 입력받는 것 같다. 적당히 break를 설정하고 두 개의 숫자를 입력해서 다시 실행해보자. 대충 3 4로 입력했다. +40줄에서 1과 eax의 값을 비교한다. 그러면 eax의 값을 알아야 하는데.. 다시 한 줄 씩 실행하면서 확인해보자. +40줄 까지 진행한 후 레지스터의 상태를 확인해보니 rax 레지스터에는 2가 저장돼있음을 확인할 수 있다. +43줄에서 jle 명령어가 실행된다. 2는 1보다..
[시스템 프로그래밍] Bomb Lab Phase 2
[시스템 프로그래밍] Bomb Lab Phase 2
2022.12.22disas phase_2 명령어로 phase_2 함수를 어셈블리어로 살펴보자. +25줄에서 함수를 호출한다. 이름 그대로 6개의 숫자를 입력받는 것 같은데.. 어셈블리어로 살펴보자. +41줄에 scanf 함수를 볼 수 있는데, 역시 숫자를 입력받는게 맞는 것 같다. 레지스터를 열어 보니 확실히 6개의 정수를 입력받는다. 나머지 내용은 잘 모르겠고.. 일단 read_six_numbers 함수에서 여섯 개의 정수를 입력받는다는 사실을 알아냈다. 다시 phase_2 함수로 돌아오자. +30줄에서 스택의 첫 번째 수가 1인지 확인하고 있다. +34줄에서 zero flag가 0이면 +45줄로 가서 폭탄을 터뜨린다. 아하! 스택의 첫 번째 값은 1이구나! 즉, 6개의 정수를 입력받을 때 첫 번째로 입력받는 정수는 ..
[시스템 프로그래밍] Bomb Lab Phase 1
[시스템 프로그래밍] Bomb Lab Phase 1
2022.12.21gdb bomb 명령어로 디버깅 모드에 진입한 후 disas phase_1 명령어로 phase_1 함수가 어셈블리어로 어떻게 작성된 지 확인해봤다. +11 : 함수를 호출한다. +16 : %eax 레지스터를 test한다. +18 : 결과가 같지 않으면 +25로 점프한다. +25 폭탄이 터진다. 음.. +11줄에서 문자열 두 개를 비교하고 %eax 레지스터에 결과를 넣게 되고, 이 결과에 따라서 폭탄이 터지거나 안 터지게 되는 것 같다. 좀 더 자세하게 살펴보자. test 명령어는 두 피연산자를 and 연산한다. jne 명령어는 ZF가 0일 경우 실행된다. 즉, +11줄에서의 결과가 1이면 폭탄이 터지지 않고, 0이면 폭탄이 터지게 됨을 알 수 있다. 그렇다면 당연히 +11줄에서 두 개의 문자열이 같은 경..
[시스템 프로그래밍] Data Lab
[시스템 프로그래밍] Data Lab
2022.12.201. bitNor int bitNor(int x, int y) { return (~x) & (~y); // use de morgan law to use able operands. } 드모르간 법칙을 사용해 사용 가능한 연산자만으로 bitNor를 구현하자. ~(x | y) => (~x) & (~y) 2. float_neg unsigned float_neg(unsigned uf) { int res = (0x80
[시스템 프로그래밍] 동적 메모리
[시스템 프로그래밍] 동적 메모리
2022.11.30메모리는 무한하지 않고, 많은 소프트웨어들이 메모리에 큰 영향을 받는다. 당장 백준 사이트에서 그래프 알고리즘 문제를 풀 때도 메모리를 효과적으로 사용하지 못하면 알고리즘을 제대로 작성했어도 맞았습니다를 받을 수 없다. 가상 메모리.. 캐시... 메모리에도 여러 종류가 있다. 다른 메모리들은 컴퓨터구조나 운영체제를 공부하면서 배우기로 하고, 이번에는 동적 메모리에 대해 자세히 살펴보자. C를 공부하면서 배웠듯 동적 메모리는 Heap 메모리 부분에 할당된다. malloc과 free 함수를 사용해 메모리를 할당받고 반환한다. 자바에서는 Garbage Collection이 있어 반환에 신경쓰지 않아도 되지만, C에서는 메모리를 사용한 후 반납 해 줘야 한다. 프로그램이 돌아갈 때 메모리를 살펴보면 위와 같은 ..
[시스템 프로그래밍] 시그널
[시스템 프로그래밍] 시그널
2022.11.14컴퓨터는 다수의 프로세스를 concurrent 하게 실행시킨다. 각각의 프로세스들이 OS에 의해 문맥이 전환되기 때문에 여러 가지 프로그램이 병행적으로 작동하는게 가능하고, 여기서 시그널이 사용된다. 시그널은 어떤 이벤트가 시스템에 발생했음을 프로세스에게 알려주는 메세지이다. 예외 상황과 인터럽트를 커널에서 추상화 한 개념이고, 커널을 통해 프로세스에게 전달된다. 각각의 시그널들은 정수 값의 아이디로 구분된다. SIGSEGV : 잘못된 주소로 접근했을 때 발생한다. SIGCHLD : 자식이 종료되면 부모에게 SIGCHLD가 보내진다. 커널은 목적지 프로세스의 컨텍스트 내부 상태를 갱신하는 방법으로 시그널을 목적지 프로세스에 보낸다. 무슨 소리인지 자세히 알아보자. 메모리에는 프로세스를 돌리기 위한 자료구..
[시스템 프로그래밍] 프로세스 (2)
[시스템 프로그래밍] 프로세스 (2)
2022.11.06fork() 함수가 실행되는 순간 프로세스가 복사된다. if(fork() == 0) 문장을 실행할 때 fork() 프로세스가 복사되고 복사되자마자 자식은 죽는다. 부모는 리턴값이 0이 아니기에 무한 루프에 빠진다. 어셈블리 부분을 살펴보자. 원래대로라면 부모는 무한 루프에 빠져 입력받을 수 없는 상태겠지만, 명령어 실행 시 &를 붙이면 백그라운드에서 실행하게 돼 명령어를 입력받을 수 있다. ps 명령어로 현재 돌아가는 프로세스를 확인했을 때 자식과 부모 모두 돌아가고 있음을 확인할 수 있다 (부모가 죽지 않아서 자식이 좀비 상태이다) 이후 kill 명령어로 부모를 죽이면 부모와 자식 모두 정리됨을 확인할 수 있다. 부모가 죽지 않으면서 자식이 정리되지 않는 경우가 문제가 되는데.. 이 경우 wait 함수..
[시스템 프로그래밍] 프로세스 (1)
[시스템 프로그래밍] 프로세스 (1)
2022.11.06프로그램이 실행된다는 건, 컴퓨터 내부의 회로들이 시간의 흐름에 따라 작동하고 있음을 의미한다. 즉, 한 번에 한 개의 명령어들이 반복적으로 실행되고, 제어 회로는 명령어가 제대로 실행되도록 돕는다. 하지만, 때로는 제어 흐름이 변경돼야 하는 경우도 있다. 한글 문서 작업을 하고 있는 도중 카카오톡 메세지가 도착했다고 생각하자. 컴퓨터는 한글 문서 작업 관련 명령어를 처리해야 되기 때문에 카카오톡 메세지의 도착을 무시해야 할까? 이런 컴퓨터는 잘 팔리지 않을 것이다. 컴퓨터는 위와 같은 돌발적인 사건에 대응할 수 있어야 한다. 이런 사건을 예외적인 제어 흐름이라고 부르고, 하드웨어와 소프트웨어 두 가지로 나뉜다. 1. 하드웨어 컴퓨터구조에서 배운 Interrupt를 생각하면 이해하기 쉽다. 시스템 이벤트..
[시스템 프로그래밍] 프로시저
[시스템 프로그래밍] 프로시저
2022.10.28프로시저, 함수, 메서드.. 모두 같은 말이다. 그러니 혼용해서 사용해도 괜찮다. 함수 내부에서 다른 함수를 호출하는 방식의 코드를 접한 적이 있을 것이다. C를 공부할 때 스택메모리가 활성화돼서 함수를 호출할 때 마다 스택의 윗부분에 올리는 방식으로 작동한다고 배웠는데, 어셈블리에서는 이 내용이 어떻게 구현되는지 살펴보자. 어셈블리에서 프로시저를 다룰 때 세 가지가 처리된다. 1. 제어의 전달 함수 내부에서 다른 함수를 호출할 때, 실행 중인 함수를 잠시 멈추고 호출한 함수를 실행해야 한다. 즉, ProgramCounter를 호출한 함수의 시작주소로 설정하고 함수가 리턴될 경우를 대비해 원래 실행하던 함수의 위치도 저장한다. 2. 데이터의 전달 함수를 호출할 때 인자로 정보를 전달하고, 함수가 리턴될 ..
[시스템 프로그래밍] 어셈블리어 - 반복문
[시스템 프로그래밍] 어셈블리어 - 반복문
2022.10.24조건문은 어셈블리어의 jX 명령어와 대응되지만, 반복문은 어셈블리어에서 대응되는 명령어가 없다. 즉 jX 명령어와 몇 가지 다른 명령어들의 조합으로 반복문을 구현해야 하는데, 이제 그 예시를 살펴보자. do-while do-while은 실행식이 무조건 한 번은 꼭 실행된다는 부분을 제외하면 while문과 같은 역할을 한다. 위의 그림은 do-while 문법을 goto 문법으로 표현한 후 어셈블리어로 변환하는 예시이다. while while문은 조건식에 따라 실행식이 한 번도 실행되지 않을 수도 있다. while문을 어셈블리어로 변환하는 예시를 살펴보자. 1. Jump to Middle goto 문법을 사용해 바로 조건식으로 이동시키고, 실행식 내부에서 goto 문법을 통해 조건식에 따라 실행식으로 이동시..