Hongfluenza

ASSEMBLY : 어셈블리어 본문

STUDY/REVERSING

ASSEMBLY : 어셈블리어

Hongfluenza 2019. 9. 22. 23:10
어셈블리어란?
  • 기계어 : 컴퓨터가 읽을 수 있는 이진수(0,1)로 이루어진 프로그램
  • 기계어는 컴퓨터가 바로 읽을 수 있다는 점을 제외하면 장점이 없기 때문에, 이를 보완하기 위해 나온 것이 어셈블리어다.
  • 어셈블리어 : 기계어를 사람이 보기 쉽게 문자를 기호화 하여 나타낸 것 (기계어와 1:1대응을 한다.)

 

어셈블리어의 명령 포맷
  •  IA-32의 기본 형태 : 명령어 + 인자
  • 명령어(=opcode,옵코드), 예를 들면 mov나 push에 해당한다.
  • 인자(=operand,오퍼랜드), '명령어에 해당하는 값' 또는 '어떤 장소로 값을 넣을 것인가'에 해당한다. 
  • push 123 :  명령어(opcode,옵코드)→push | 인자(operand,오퍼랜드)→123
  • mov eax,1 :
    명령어(opcode,옵코드)→mov 
    인자(operand,오퍼랜드)→ eax(목적지,destination=dest), 인자(operand,오퍼랜드)→ 1(출발지,source,src)

    ※다음과 같이 인자(오퍼랜드)는 두 개가 올 수 있다. 첫 번째 인자는 목적지, 두 번째 인자는 출발지

 

레지스터

1. 데이터 레지스터

: 각종 데이터 처리를 대상으로 하는 32비트 레지스터 및 16비트 레지스터 일부를 프로그래머가 명령 중에서 자유롭게 지정 할 수 있는 범용 레지스터

: EAX, EBX, ECX, EDX

 

2. 포인터 레지스터

: ESP (스택 포인터, 스택의 최종점을 저장함) 
: EBP (ESP를 대신해 스택에 저장된 함수의 파라미터 지역 변수의 주소를 가리키는 용도로 사용됨)

 

3. 인덱스 레지스터

: ESI, EDI

 

4. 세그먼트 레지스터

: CS, DS, SS, ES

 

 

어셈블리어 명령어

1. 데이터의 이동 : mov, lea

  • mov (move data)
    - mov eax, ebx : ebx의 데이터를 eax로 이동
    - 레지스터끼리의 이동은 가능하나, 메모리 주소 간의 데이터 이동은 불가능
    - 메모리 간의 복사를 위해서는 복사하고자 하는 데이터를 먼저 특정 레지스터로 이동 한 후에 이동해야 한다.
    - mov byte ptr [var], eax : eax를 var가 가리키는 주소로 복사
    - 쉽게 생각하면, mov 명령어는 '값'을 가져오는 것
  • lea (load effective address)
    -  두 번째 인자의 메모리 주소를 첫 번째 인자에 넣음

    -  원하는 메모리의 포인터를 얻을 때 흔히 사용됨, 쉽게 생각하면 lea 명령어는 '주소'를 가져오는 것
    -  lea EDI, [EBX+4*ESI] : EBX+4*ESI의 주소 값에 담긴 데이터가 EDI에 로드됨. 
    -  lea eax, [val] : val의 데이터가 eax에 로드됨

2. 논리, 연산 : add, sub, inc, dec

  • add
    -  add op1, op2 : op1+op2의 값이 op1에 저장됨
    -  두 개의 오퍼랜드 모두에 메모리로 조합되는 것은 불가능
  • sub
    -  sub op1, op2 : op1-op2의 값이 op1에 저장됨
    -  메모리끼리의 뺄셈은 할 수 없다
  • inc
    - 피연산자에 1을 더한 후, 결과 값을 다시 저장
  • dec
    - 피연산자에 1을 뺀 후, 결과 값을 다시 저장

3. 흐름 제어 : cmp, jmp

  • cmp
    - cmp %eax, 1 → eax 레지스터의 값을 1과 비교한다.
        je start → 비교 결과가 같다면 start로 분기한다.
        다음 명령어 → 같지 않다면 je 명령어 다음에 오는 명령어를 실행한다.

    - 두 값을 비교하고, 비교 결과에 따라 분기한다. (보통 레지스터나 메모리 및 숫자의 크기 비교)
    -  cmp 명령어는 혼자 사용되지 않고, 조건 점프 명령이나 조건 이동(mov) 명령어와 함께 사용됨
    - 조건 점프 명령어 : cmp 명령어의 결과에 따라 점프하는 명령어
  • jmp
    - 피연산자의 위치로 실행 흐름이 변경됨
    - 피연산자에는 레이블, 레지스터, 메모리 값이 올 수 있음
    - JA : CMP a>b
    - JB : CMP a<b
    - JE : CMP a==b
    - JNE : CMP a!=b
    - JZ (Zeroflag) : TEST EAX, EAX (EAX=0)
    - JNZ (JMP Not Zero ) : TEST EAX, EAX (EAX=1)

4. 프로시저 : call, ret

  • call
    - 함수 호출 시 사용
    - 프로그램의 실행 흐름이 변경되지만, 되돌아올 리턴 어드레스(call 다음 명령)를 스택에 저장함
    - 되돌아올 주소를 저장하기 때문에 함수 호출 후 원래 위치로 실행 흐름을 되돌릴 수 있음
    ( 호출한 함수가 일을 다 마치면 원래의 위치에서 다시 프로그램이 실행될 수 있음을 의미)

  • ret
    - 호출된 함수에서 호출한 함수로 복귀
    - ESP에 있는 값을 꺼내(POP) EIP 레지스터에 할당한다.
    - 즉, call 명령 당시 PUSH 되었던 주소를 POP하여 EIP에 넣는다.

 

 

5. 스택 조작 : PUSH, POP

  • push
    ESP 레지스터가 가리키고 있는 위치의 스택 공간에 4byte 만큼을 desination 피연산자에 복사하고 ESP 레지스터의 값에 4를 더한다.
  • POP
    - 스택에 값을 넣는다.
    - ESP의 값이 4만큼 줄어들어 이 위치에 새로운 값이 채워진다.

 

 

6. 인터럽트 : int

  • 운영체제에 할당된 인터럽트 영역을 system call