https://com24everyday.tistory.com/222
여기서 볼 수 있었던 다음 코드가 64비트 운영체제에서 어떻게 동작하는지, 레지스터들을 배워보고 알아보고 그 레지스터들이 동작되기 위해 사용되는 시스템 콜에 대해서 알아보겠습니다. (마지막 줄에 syscalls 이 아닌 syscall을 해야합니다)
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture
위 링크에 들어가면 마이크로소프트에서 64비트 운영체제에 대한 정보가 나와 있습니다.
레지스터들은 각자 역할들이 있는데 반드시는 아니지만 지켜주시는 것이 좋습니다.
'rax' - 가장 중요한 레지스터로 시스템 콜의 실질적 번호를 가리키는 번호, 함수 결과값이 담기는 레지스터
'rbx' - base register로 메모리 주소를 지정할 때 사용
'rcx' - 보통 반복문에 사용
'rdx' - 데이터 레지스터로 연산 수행할 때 rax 와 많이 사용함
여기 위 네개의 레지스터를 '데이터 레지스터'라고 합니다.
다음 네개는 '포인터 레지스터' 입니다. 이 레지스터들은 특정한 주소를 가리킵니다.
'rsi' - 메모리를 이동하거나 비교할 때 출발주소을 가리키는데 사용
'rdi'- 메모리를 이동하거나 비교할 때 목적지 주소를 가리키는데 사용
'rbp' - 함수 파라미터나 주소를 가리킬 때 사용
'rsp' - 중요, stack의 삽입 및 삭제 명령어에 의해서 변경되는 스택 가장 위를 가리키는 포인터
이런 레지스터를 통해서 어셈블리 코드를 이해할 수 있습니다.
그리고 r8,r9 등의 레지스터가 있습니다. 이는 함수의 매개변수로 많이 사용됩니다.
이제 시스템 콜에 대해 살펴보겠습니다.
https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
다음 블로그의 시스템 콜 함수에 대해 정보를 알 수 있습니다.
확인하시면 다양한 함수들이 커널에서 만들어져있습니다.
시스템 콜을 불러오기 전에 %rax의 값에 따라 어떤 함수를 불러올지 결정하게 됩니다. 만약 '0' 이 %rax 에 들어 있다면 sys_read 함수가 실행되겠죠. 또 이 함수들의 매개변수가 필요합니다.
'1' 의 값이 들어있어서 sys_write 가 실행되면 %rdi 에 파일 디스크립터가 담기게 되고(나중에 배움) 쓰고 싶은 내용을 %rsi 에 담고 그 길이를 %rdx 에 담습니다.
실제로 코딩할때 이렇게 테이블을 참조하여 코딩을 하면 됩니다. 그럼 위 코드를 다시 볼까요?
.data 영역에 'Hello World' 라는 문자를 만들어 놓고 이를 가리키는 포인터 변수로 msg 를 선언합니다.
.text 영역에 가장 첫번째로 시행되는 _start 함수 선언
rax 에 1을 담음으로써 sys_write 를 불러올 걸 알려주고
rdi 에 1을 담음으로써 어떤 것을 출력한다는 걸 매개변수로 알려주고
rsi 에 msg 을 담아서 출력할 문자를 매개변수로 넣어주고
rdx에 12를 넣어서 충분한 길이를 매개변수로 넣어주고
syscall을 출력합니다.
그럼 밑에 있는 건 뭘까요?
rax 에 60을 넣어줬네요. 60은 어떤 시스템콜을 부르는 건지 확인해보겠습니다.
프로그램을 종료하는 거네요. 그리고 rdi 에는 error_code 를 넣어주는데요. 여기서는 0을 넣어서 그냥 안전하게 종료를 하면 됩니다.
'해킹 > 시스템해킹' 카테고리의 다른 글
어셈블리어 문법 간단 정리 (0) | 2020.08.03 |
---|---|
시스템 해킹 echo 구현 (0) | 2020.08.03 |
시스템해킹 메모리 커럽션 (0) | 2020.08.02 |
시스템 해킹 기초 (0) | 2020.08.01 |
시스템해킹 nano 통해 어셈블리코드 실행 (0) | 2020.07.31 |