카테고리 없음

리버싱 드림핵 4 정리

미숫가루빙수 2024. 3. 24. 20:33

 

어셈블리어와 x86-64

 

 

x64 어셈블리 언어의 기본 구조

  1. 명령어 (Operation Code, Opcode): 어셈블리 언어의 명령어는 컴퓨터가 실행할 동작을 지시한다. 이것이 어셈블리 코드의 동사에 해당한다.
  2. 피연산자 (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

 

 

 

피연산자

 

 

  1. 상수 (Immediate Value): 명령어가 직접적으로 사용하는 값으로, 상수로 지정된다. 예를 들어, mov eax, 10에서 10은 상수이다.
  2. 레지스터 (Register): CPU의 레지스터에 저장된 값을 가리킨다. 레지스터는 CPU가 사용하는 임시 저장 공간으로, 데이터를 빠르게 읽고 쓸 수 있다. 예를 들어, mov eax, ebx에서 ebx는 레지스터이다.
  3. 메모리 (Memory): 주소로 참조되는 데이터로, RAM에 저장된 값을 가리킨다. 메모리 피연산자는 []으로 둘러싸여 표현되며, 앞에 크기 지정자(Size Directive)인 TYPE PTR이 추가될 수 있다. 

 

메모리 피연산자

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에 대입

 

 

 

 

산술연산

add dst, src : dst에 src의 값을 더합니다.

add eax, 3 eax += 3
add ax, WORD PTR[rdi] ax += *(WORD *)rdi

 

sub dst, src: dst에서 src의 값을 뺍니다.

sub eax, 3 eax -= 3
sub ax, WORD PTR[rdi] ax -= *(WORD *)rdi

 

inc op: op의 값을 1 증가시킴

inc eax eax += 1

 

dec op: op의 값을 1 감소 시킴

dec eax eax -= 1

 

 

 

논리연산

 and & or

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

 

비교

 

비교 명령어는 두 피연산자의 값을 비교하고, 플래그를 설정한다.

 

[Code]1: mov rax, 0xA2: mov rbx, 0xA3: cmp rax, rbx ; ZF=1

 

 

분기

 

분기 명령어는 rip를 이동시켜 실행 흐름을 바꾼다.

 

[Code]1: mov rax, 0x313372: mov rbx, 0x133373: cmp rax, rbx ; rax > rbx4: jg 1 ; jump to 1

 

 

요약

 

  1. 데이터 이동 연산자
    • mov dst, src: src의 값을 dst에 대입
    • lea dst, src: src의 유효 주소를 dst에 대입
  2. 산술 연산
    • add dst, src: src의 값을 dst에 더함
    • sub dst, src: src의 값을 dst에서 뺌
    • inc op: op의 값을 1 더함
    • dec op: op의 값을 1 뺌
  3. 논리 연산
    • 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의 비트를 모두 반전
  4. 비교
    • cmp op1, op2: op1에서 op2를 빼고 플래그를 설정
    • test op1, op2: op1과 op2에 AND 연산을 하고, 플래그를 설정
  5. 분기
    • jmp addr: addr로 rip 이동
    • je addr: 직전 비교에서 두 피연산자의 값이 같을 경우 addr로 rip 이동
    • jg addr: 직전 비교에서 두 피연산자 중 전자의 값이 더 클 경우 addr로 rip 이동

 

 

프로시저

 

특정 기능을 수행하는 코드 조각을 말한다.

ex. call, 반환 등