어셈블리어
컴퓨터의 기계어와 치환되는 언어, CPU에서 사용되는 ISA의 종류가 다양한데 이 종류만큼 많은 수의 어셈블리어가 존재한다.
X64 어셈블리 언어
기본 구조: 명령어(Operation Code, Opcode, 동사에 해당함), 피연산자(Operand, 목적어에 해당함)
피연산자
피연산자에서 올 수 있는 3가지
-상수(lmmediate Value)
-레지스터(Register)
-메모리(Memory): []으로 둘러싸여 표현, 앞에 크기 지정자 TYPE PTR이 추가될 수 있음(TYPE에는 BYTE, WORD, DWORD, QWORD가 올 수 있고 각 1,2,4,8, 바이트의 크기를 지정한다.
-ex)메모리 피연산자의 예
QWORD PTR [0x8048000] | 0x8048000의 데이터를 8바이트만큼 참조 |
DWORD PTR [0x8048000] | 0x8048000의 데이터를 4바이트만큼 참조 |
WORD PTR [rax] | rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조 |
데이터 이동 명령어
어떤 값을 레지스터나 메모리에 옮기도록 지시한다.
mov dst, src : src에 들어있는 값을 dst에 대입
mov rdi, rsi | rsi의 값을 rdi에 대입 |
mov QWORD PTR[rdi], rsi | rsi의 값을 rdi가 가리키는 주소에 대입 |
mov QWORD PTR[rdi+8*rcx], rsi | rsi의 값을 rdi+8*rcx가 가리키는 주소에 대입 |
lea dst, src : src의 유효 주소(Effective Address, EA)를 dst에 저장합니다.
lea rsi, [rbx+8*rcx] | rbx+8*rcx 를 rsi에 대입 |
산술 연산 명령어
덧셈, 뺄셈, 곱셈, 나눗셈 연산을 지시한다
ex) add dst, src : dst에 src의 값을 더한다.
add eax, 3 | eax += 3 |
add ax, WORD PTR[rdi] | ax += *(WORD *)rdi |
ex) sub dst, src: dst에서 src의 값을 뺀다.
sub eax, 3 | eax -= 3 |
sub ax, WORD PTR[rdi] | ax -= *(WORD *)rdi |
ex) inc op: op의 값을 1 증가시킴
inc eax | eax += 1 |
ex) dec op: op의 값을 1 감소 시킴
dec eax | eax -= 1 |
논리 연산 명령어
and, or, xor, neg 등의 비트 연산을 지시한다.(비트 단위로)
and dst, src: dst와 src의 비트가 모두 1이면 1, 아니면 0
[Register]
eax = 0xffff0000
ebx = 0xcafebabe
[Code]
and eax, ebx
[Result]eax = 0xcafe0000
or dst, src: dst와 src의 비트 중 하나라도 1이면 1, 아니면 0
[Register]
eax = 0xffff0000
ebx = 0xcafebabe
[Code]
or eax, ebx
[Result]
eax = 0xffffbabe
논리 연산 xor & not
xor dst, src: dst와 src의 비트가 서로 다르면 1, 같으면 0
[Register]
eax = 0xffffffff
ebx = 0xcafebabe
[Code]
xor eax, ebx
[Result]
eax = 0x35014541
not op: op의 비트 전부 반전
[Register
]eax = 0xffffffff
[Code]
not eax
[Result]
eax = 0x00000000
비교 명령어
두 피연산자의 값을 피교하고 플래그를 설정한다.
cmp op1, op2: op1과 op2를 비교
cmp는 두 피연산자를 빼서 대소를 비교하고 연산의 결과는 op1에 대입하지 않는다.
명령어 분류
데이터 이동(Data Transfer) | mov, lea |
산술 연산(Arithmetic) | inc, dec, add, sub |
논리 연산(Logical) | and, or, xor, not |
비교(Comparison) | cmp, test |
분기(Branch) | jmp, je, jg |
스택(Stack) | push, pop |
프로시져(Procedure) | call, ret, leave |
시스템 콜(System call) | syscall |
요약
데이터 이동 연산자
mov dst, src: src의 값을 dst에 대입
lea dst, src: src의 유효 주소를 dst에 대입
산술 연산
add dst, src: src의 값을 dst에 더함
sub dst, src: src의 값을 dst에서 뺌
inc op: op의 값을 1 더함
dec op: op의 값을 1 뺌
논리 연산
and dst, src: dst와 src가 모두 1이면 1, 아니면 0
or dst, src: dst와 src스택
push val : rsp를 8만큼 빼고, 스택의 최상단에 val을 쌓습니다.
pop reg: 스택 최상단의 값을 reg에 넣고, rsp를 8만큼 더합니다.
프로시저
call addr: addr의 프로시저를 호출합니다.
leave: 스택 프레임을 정리합니다.
ret: 호출자의 실행 흐름으로 돌아갑니다.
syscall: 커널에게 필요한 동작을 요청합니다.
중 한 쪽이라도 1이면 1, 아니면 0
xor dst, src: dst와 src가 다르면 1, 같으면 0
not op: op의 비트를 모두 반전
비교
cmp op1, op2: op1에서 op2를 빼고 플래그를 설정
test op1, op2: op1과 op2에 AND 연산을 하고, 플래그를 설정
분기
jmp addr: addr로 rip 이동
je addr: 직전 비교에서 두 피연산자의 값이 같을 경우 addr로 rip 이동
jg addr: 직전 비교에서 두 피연산자 중 전자의 값이 더 클 경우 addr로 rip 이동
'System & Reversing 필기' 카테고리의 다른 글
[DreamHack] shell_basic 풀이 (0) | 2023.05.08 |
---|---|
DreamHack Stage2(컴퓨터 구조) (0) | 2023.05.01 |
DreamHack Stage2( 리눅스 메모리 구조) (0) | 2023.05.01 |
BoF (0) | 2023.03.18 |
x86, x64 레지스터 (0) | 2023.03.18 |