본문 바로가기

개념정리/System Hacking

4-1. 어셈블리(Assembly) - 산술연산, 논리연산, 비교, 분기

 

이번 시간은 해커의 언어인 어셈블리에 대하여 공부할 것이다. 

 


 

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바이트 만큼 참조

 


 

이번엔 기계어와 어셈블리 기본구조, 산술연산, 논리연산, 비교, 분기를 공부하였다.

다음은 스택, 프로시저, 시스템콜에 관련된 어셈블리를 공부할 것이다.