티스토리 뷰

System Hacking

x86 Assembly (2)

SeYuNi 2024. 2. 17. 04:15

Opcode: 스택

* push val: val을 스택 최상단에 쌓음

연산
rsp -= 8
[rsp] = val

 

* pop reg: 스택 최상단의 값을 꺼내서 reg에 대입

연산
rsp += 8
reg = [rsp-8]

 

 

Opcode: 프로시저

컴퓨터 과학에서 프로시저(Procedure)는 특정 기능을 수행하는 코드 조각을 말한다. 프로시저를 사용하면 반복되는 연산을 프로시저 호출로 대체할 수 있어서 전체 코드의 크기를 줄일 수 있으며, 기능별로 코드 조각에 이름을 붙일 수 있게 되어 코드의 가독성을 크게 높일 수 있다.

프로시저를 부르는 행위를 호출(Call)이라고 부르며, 프로시저에서 돌아오는 것을 반환(Return)이라고 부른다. 프로시저를 호출할 때는 프로시저를 실행하고 나서 원래의 실행 흐름으로 돌아와야 하므로, call 다음의 명령어 주소(Return Address, 반환 주소)를 스택에 저장하고 프로시저로 rip를 이동시킨다.

 

* call addr: addr에 위치한 프로시저 호출

연산
push return_address
jmp addr

 

* leave: 스택프레임 정리

연산
mov rsp, rbp
pop rbp

 

* ret: return address로 반환

연산
pop rip

 

* 스택프레임이란?

스택은 함수별로 자신의 지역변수 또는 연산과정에서 부차적으로 생겨나는 임시 값들을 저장하는 영역이다. 만약 이 스택 영역을 아무런 구분 없이 사용하게 된다면, 서로 다른 두 함수가 같은 메모리 영역을 사용할 수 있게 된다.  함수별로 서로가 사용하는 스택의 영역을 명확히 구분하기 위해 스택프레임이 사용된다. 대부분의 Application binary interface (ABI)에서는 함수는 호출될 때 자신의 스택프레임을 만들고, 반환할 때 이를 정리한다.

스택 프레임 시각화

 

Opcode: 시스템 콜

운영체제는 연결된 모든 하드웨어 및 소프트웨어에 접근할 수 있으며, 이들을 제어할 수도 있다. 그리고 해킹으로부터 이 막강한 권한을 보호하기 위해 커널 모드와 유저 모드로 권한을 나눈다.

리눅스 계층

 

* 커널 모드

: 운영체제가 전체 시스템을 제어하기 위해 시스템 소프트웨어에 부여하는 권한이다. 파일시스템, 입력/출력, 네트워크 통신, 메모리 관리 등 모든 저수준의 작업은 사용자 모르게 커널 모드에서 진행된다. 커널 모드에서는 시스템의 모든 부분을 제어할 수 있기 때문에, 해커가 커널 모드까지 진입하게 되면 시스템은 거의 무방비 상태가 된다.

 

* 유저 모드

: 운영체제가 사용자에게 부여하는 권한이다. 브라우저를 이용하거나, 유튜브를 시청하는 것, 게임을 하고 프로그래밍을 하는 것 등은 모두 유저 모드에서 이루어진다. 리눅스에서 루트 권한으로 사용자를 추가하고, 패키지를 내려 받는 행위 등도 마찬가지이다. 유저 모드에서는 해킹이 발생해도, 해커가 유저 모드의 권한까지 밖에 획득하지 못하기 때문에 해커로 부터 커널의 막강한 권한을 보호할 수 있다.

 

* 시스템 콜(system call, syscall)

: 유저 모드에서 커널 모드의 시스템 소프트웨어에게 어떤 동작을 요청하기 위해 사용된다. 소프트웨어 대부분은 커널의 도움이 필요하다. 예를 들어, 사용자가 cat flag를 실행하면, cat은 flag라는 파일을 읽어서 사용자의 화면에 출력해 줘야 한다. 그런데 flag는 파일 시스템에 존재하므로 이를 읽으려면 파일시스템에 접근할 수 있어야 한다. 유저 모드에서는 이를 직접 할 수 없으므로 커널이 도움을 줘야 한다. 여기서, 도움이 필요하다는 요청을 시스템 콜이라고 한다. 유저 모드의 소프트웨어가 필요한 도움을 요청하면, 커널이 요청한 동작을 수행하여 유저에게 결과를 반환한다.

 

* syscall

요청: rax

인자 순서: rdi -> rsi -> rdx -> rcx -> r8 -> r9 -> stack

 

* x64 syscall 테이블

syscall rax arg0 (rdi) arg1 (rsi) arg2 (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
close 0x03 unsigned int fd

mprotect 0x0a unsigned long start size_t len unsigned long prot
connect 0x2a int sockfd struct sockaddr * addr int addrlen
execve 0x3b const char *filename const char *const *argv const char *const *envp

 

 

 


요약

  1. 스택
    • push val: rsp를 8만큼 빼고, 스택의 최상단에 val을 쌓는다.
    • pop reg: 스택 최상단의 값을 reg에 넣고, rsp를 8만큼 더한다.
  2. 프로시저
    • call addr: addr의 프로시저를 호출한다.
    • leave: 스택 프레임을 정리한다.
    • ret: 호출자의 실행 흐름으로 돌아간다.
  3. 시스템 콜
    • syscall: 커널에게 필요한 동작을 요청한다.

 

 

 

 

 

 

 

 

 

 

 

'System Hacking' 카테고리의 다른 글

[드림핵] Tool Installation_gdb, pwntools  (0) 2024.02.25
[프로젝트] 악성코드 - 웜  (0) 2024.02.24
기본 명령어 및 vi 에디터  (1) 2024.01.28
x86 Assembly (1)  (0) 2024.01.28
리눅스 메모리 구조 (Linux Memory Layout)  (0) 2024.01.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함