이번 시간은 해커의 언어인 어셈블리에 대하여 공부할 것이다.
1. 기계어
CPU가 직접 해독하고 실행할 수 있는 비트 단위로 쓰인 컴퓨터 언어이다. 0과 1로만 구성돼 있어서 단어 위주로 문장을 구사하는 사람으로서 이해하기 어렵다.
2. 어셈블리 언어
기계어와 일대일 대응이 되는 컴퓨터 프로그래밍 저급 언어이다. 컴퓨터 구조에 따라 사용하는 기계어가 달라지며, 어셈블리 언어도 달라진다.
3. 어셈블러
어셈블리어로 작성한 코드를 컴퓨터가 이해할 수 있는 기계어로 코드를 치환해 주는 일종의 통역사이다.
4. 어셈블리 언어 기본 구조
어셈블리 언어는 동사에 해당하는 명령어(Opcode)와 목적어에 해당하는 피연산자(Operand)로 구성된다.
5. 어셈블리 명령어
- 데이터 이동: mov, lea
어떤 값을 레지스터나 메모리에 옮기도록 지시한다.
1) mov
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가 가리키는 주소에 대입 |
2) lea
lea dst, src : src의 유효주소를 dst에 저장한다. | |
lea rsi, [rbx+8*rcx] |
rbx+8*rcx 를 rsi에 대입
|
- 산술 연산 : add, sub, inc, dec
덧셈, 뺄셈, 곱셈, 나눗셈 연산을 지시한다.
1) add
add dst, src : dst에 src의 값을 더한다. | |
add eax, 3 | eax += 3 |
add ax, WORD PTR[rdi] | ax += *(WORD *)rdi |
2) sub
sub dst, src : dst에서 src의 값을 뺀다. | |
sub eax, 3 | eax -= 3 |
sub ax, WORD PTR[rdi] | ax -= *(WORD *)rdi |
3) inc
inc op : op의 값을 1 증가 시킨다. | |
inc eax | eax += 1 |
4) dec
dec op : op의 값을 1 감소 시킨다. | |
dec eax | eax -= 1 |
- 논리 연산 : and, or, xor, not
비트 단위로 이루어지며 비트 연산을 지시한다.
1) and
and dst, src : dst와 src의 비트가 모두 1이면 1, 아니면 0
2) or
or dst, src : dst와 src의 비트 중 하나라도 1이면 1, 아니면 0
3) xor
xor dst, src : dst와 src의 비트가 서로 다르면 1, 같으면 0
4) not
not op : op의 비트 전부 반전
- 비교 : cmp, test
1) cmp
cmp op1, op2 : op1과 op2를 빼서 대소 비교
cmp는 두 피연산자를 빼서 대소를 비교한다. 예를 들어 서로 다른 두수를 빼면 결과가 0이 되어 ZF플래그가 설정되는데 이후에 CPU는 플래그를 보고 두값이 같다는 것을 판단한다. (연산한 결과는 op1에 대입하지 않는다.)
2) test
test op1, op2 : op1과 op2를 비교
test는 두 피연산자에 AND 비트연산을 취한다. (연산 결과는 op2에 대입하지 않는다.)
- 분기 : jmp, je, jg
rip를 이동시켜 실행 흐름을 바꾼다.
1) jmp
jmp addr : addr로 rip를 이동시킨다.
2) je
je addr : 직전에 비교한 두 피연산자가 같으면 점프(jump if equal)
(예)
1: cmp rax, rbx ------> rax와 rbx 비교
2: je 1 ------> rax와 rbx가 같으면 1로 점프
3) jg
jg addr : 직전에 비교한 두 피연산자 중 전자가 더 크면 점프(jump if greater)
(예)
1: cmp rax, rbx ------> rax와 rbx 비교
2: je 1 ------> rax가 rbx보다 크면 1로 점프
6. 피연산자
피연산자에는 상수, 레지스터, 메모리가 올 수 있다. 메모리 피연산자는 [ ]으로 둘러싸인 것으로 표현되며, 앞에 크기 지정자 TYPE PTR이 추가된다. 여기서 타입에는 BYTE(1바이트), WORD(2바이트), DWORD(4바이트), QWORD(8바이트)가 올 수 있다.
- 메모리 피연산자
QWORD PTR [0xFFFFFFF] | 0xFFFFFFF의 데이터를 8바이트만큼 참조 |
DWORD PTR [0xFFFFFFF] | 0xFFFFFFF의 데이터를 4바이트만큼 참조 |
WORD PTR [rax] | rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조 |
이번엔 기계어와 어셈블리 기본구조, 산술연산, 논리연산, 비교, 분기를 공부하였다.
다음은 스택, 프로시저, 시스템콜에 관련된 어셈블리를 공부할 것이다.
'개념정리 > System Hacking' 카테고리의 다른 글
5. gdb 디버거 (0) | 2022.07.21 |
---|---|
4-2. 어셈블리(Assembly) - 스택, 프로시저, 시스템콜 (0) | 2022.07.07 |
3. 리눅스 프로세스의 메모리 구조 (0) | 2022.07.04 |
2. x86-64 아키텍처 (0) | 2022.07.04 |
1. 컴퓨터 아키텍처 (0) | 2022.06.30 |