x64 어셈블리 언어
기본 구조🧱
동사에 해당하는 Operation Code, OP (명령어)와 목적에 해당하는 Operand (피연산자)로 구성

명령어🔫
|
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
|
피연산자🎯
- 상수(Immediate Value)
- 레지스터(Register)
- 메모리(Memory)
크기 지정자 (Size Directive)
|
BYTE
|
1byte = 8bit
|
|
WORD
|
2byte = 16bit
|
|
DWORD
|
4byte = 32bit
|
|
QWORD
|
8byte = 64bit
|
메모리 피연산자 예시
|
QWORD PTR [0x8048000]
|
0x8048000의 데이터를 8바이트만큼 참조
|
|
DWORD PTR [0x8048000]
|
0x8048000의 데이터를 4바이트만큼 참조
|
|
WORD PTR [rax]
|
rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조
|
x86-64 어셈블리 명령어
데이터 이동🚚 - 어떤 값을 레지스터나 메모리에 옮기도록 지시
1. mov dst, src : src에 들어있는 값을 dst에 대입
|
mov rdi, rsi
|
rsi의 값을 rdi에 대입
|
|
mov QWORD PTR[rdi], rsi
|
rsi의 값을 rdi가 가리키는 주소에 대입
|
|
move QWORD PTR[rdi+8*rcs], rsi
|
rsi의 값을 rdi+8*rcs가 가리키는 주소에 대입
|
2. lea dst, src : src의 Effective Address,EA (유효주소)를 dst에 저장
|
lea rsi, [rbx+8*rcx]
|
rbx+8*rcx 를 rsi에 대입
|
산술 연산❌
- add dst, src : dst = dst + src
- sub dst, src : dst = dst - src
- inc op : op++
- dec op : op—
논리 연산🤔
- and dst, src : dst와 src가 모두 1이면 1, 아니면 0
- or dst, src : dst와 src 중 하나라도 1이면 1, 아니면 0
- xor dst, src : dst와 src의 비트가 다르면 1, 같으면 0
- not op : op 비트 반전
비교⚖️
1. cmp op1, op2
- 두 피연산자를 빼서 대소를 비교함
- 연산 결과를 op1에 대입하는 것은 아님
[Code]
1: mov rax, 0xA
2: mov rbx, 0xA
3: cmp rax, rbx ; ZF=1
2. test op1, op2
- 두 피연산자에 AND 비트연산을 취함
- 연산 결과를 op1에 대입하지 않음
분기🔀
- rip(⇒ 현재 실행되고 있는 코드를 가리킴)을 이동시켜 실행 흐름을 바꿈
- jmp addr : addr로 rip을 이동시킴
- je addr : 직전 비교한 두 피연산자가 같으면 점프 (jump if equal)
[Code]
1: mov rax, 0xcafebabe
2: mov rbx, 0xcafebabe
3: cmp rax, rbx ; rax == rbx
4: je 1 ; jump to 1
3. jg addr : 직전에 비교한 두 연산자 중 전자가 더 크면 점프 (jump if greater)
[Code]
1: mov rax, 0x31337
2: mov rbx, 0x13337
3: cmp rax, rbx ; rax > rbx
4: jg 1 ; jump to 1
Opcode: 스택🧱
- push val : val을 stack 최상단에 쌓음
- pop reg : stack 최상단 값을 꺼내서 reg에 대입
Opcode: 프로시저📜
- Procedure 프로시저 : 특정 기능을 수행하는 코드 조각 == 함수
- Call 호출 : 프로시저를 부르는 행위
- Return 반환 : 프로시저에서 돌아오는 것
- 프로시저를 호출할 때는 프로시저를 실행하고 나서 원래의 실행 흐름으로 돌아와야하므로, call 다음의 명령어 주소 ( = 반환 주소, Return Address)를 Stack에 저장하고 프로시저로 rip을 이동시킴
- call addr : addr에 위치한 프로시져(함수) 호출
- leave : 스택프레임 정리
- 스택프레임 : 스택은 함수별로 자신의 지역변수 또는 임시값들을 저장하는 영역, 만약 스택 영역을 아무런 구분 없이 사용하면, 서로 다른 두 함수가 같은 메모리 영역을 사용하게될 수도 있음 → 스택의 영역을 명확히 구분하기 위해서 스택 프레임이 사용됨. 보통 함수는 호출될 때 자신의 스택 프레임을 만들고 반환할 때 이를 정리함.
3. ret : return address로 반환
'Reversing > Dreamhack : Reverse Engineering' 카테고리의 다른 글
| Quiz: x86 Assembly 2-3 (0) | 2025.04.16 |
|---|---|
| Quiz: x86 Assembly 1 (0) | 2025.04.16 |
| Background: Windows Memory Layout (0) | 2025.04.16 |
| Background: Computer Architecture (0) | 2025.04.16 |
| Background: Static Analysis vs. Dynamic Analysis (0) | 2025.04.16 |