어셈블리 기본 명령어

리버싱 2019. 11. 14. 14:30

어셈블리 ( 기본 명령어 이해 )

 

1. 어셈블리어 형식

  - 형식 : OPCODE 오퍼랜드1 , 오퍼랜드2

  - intel 문법 : OPCODE [ Destination ] [ Source ] 

  - AT&T 문법 [ Source ] [ Destination ] 

 

2. 어셈블리 자료형 이름

  BYTE         1byte      char

  WORD       2byte     short

  DWORD     4byte     int

  QWORD     8byte     double

 

3. 복사 / 이동 / 대입 명령어

 

1) MOV 

  - 형식 : MOV [ Destination ] [ Source ]

  - 내용 : [ Source ] 를 [ Destination ]으로 대입 / 이동 한다. 이때 , [ Source ] 값은 병경되지 않는다.

  - 예제 : MOV ECX , EAX

 

2) MOVZX

  - 형식 : MOVZX [ Destination ] [ Source ]

  - 내용 : [ Source ] 를 [ Destination ]으로 대입 / 이동 한다. 만약 대입한 이후에 빈공간이 있으면 0 bit 로 채움

  - 예제 : MOV ECX , AX

 

3) MOVSX

  - 형식 : MOVSX [ Destination ] [ Source ]

  - 내용 : [ Source ] 를 [ Destination ]으로 대입 / 이동 한다. 만약 대입한 이후에 빈공간이 있으면 부호비트로 채움

  - 예제 : MOV ECX , AX

 

4) MOVS

  - 형식 : MOVS

  - 내용 : ESI가 가르키는 주소에 있는 값을 EDI가 가르키는 주소에 대입한다

 

5) LEA

  - 형식 : LEA [ Destination ] [ Source ]

  - [ Source ] 의 주소 값을 [ Destination ] 으로 대입한다

  - 예제 : LEA EAX ,DWORD PTR SS:[EBP- 4]

 

4. 더하기 / 빼기 명령어

  1) ADD

    - 형식 : ADD [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ] 를 더해서 [ Operand 1 ] 에 저장한다

    - 예제 : ADD EAX , 5 

    - 해석 : EAX = EAX + 5

 

  2) SUB

    - 형식 : SUB [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ] 를 빼서 [ Operand 1 ] 에 저장한다

    - 예제 : SUB EAX , 5 

    - 해석 : EAX = EAX - 5

 

5. 곱하기 / 나누기 명령어

  1) MUL

    - 형식 : MUL [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ] 를 곱해서 EAX에 값을 저장한다.

    - 예제 : MUL EAX , EBX

    - 해석 : EAX = EAX * EBX

 

  2) IMUL

    - 부호가 있는경우

    - 형식 : IMUL [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ] 를 곱해서 EAX에 값을 저장한다.

    - 예제 : MUL EAX , EBX

    - 해석 : EAX = EAX * EBX

 

  3) DIV

    - 형식 : DIV [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ] 를 나누기 하여 EAX에 값을 저장한다.

    - 예제 : MUL EAX , EBX

    - 해석 : EAX = EAX / EBX

 

  4) IDIV

    - 부호가 있는경우

    - 형식 : IDIV [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ] 를 나누기 하여 EAX에 값을 저장한다.

    - 예제 : MUL EAX , EBX

    - 해석 : EAX = EAX / EBX

 

[ 참고 ] CVW , CWD , CDQ

  - IDIV가 진행하기 이전에 나타나는 부호 비트 확장 코드

  - 나눗셈을 진행하고 부호비트를 넣어줄 공간을 확보하는데 기존 공간의 2배를 할당한다.

 CBW      BYTE     ->  WORD

 CWD      WORD  ->  DWORD

 CBQ      DWORD ->  QWORD

 

 

6. 증가 / 감소 명령어

  1) INC

    - 형식 : INC [ Operand ]

    - 내용 : [ Operand ]  값에서 '1' 을 증가한다.

    - 예제 : INC EBX

    - 해석 : EBX 값에서 '1'을 증가시킨다.

 

  2) DEC

    - 형식 : DEC [ Operand ]

    - 내용 : [ Operand ]  값에서 '1' 을 감소한다.

    - 예제 : DEC EBX

    - 해석 : EBX 값에서 '1'을 감소시킨다.

 

 

7. 비교 관련 명령어

 

  1) CMP

    - 형식 : CMP [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 에서 [ Operand 2 ] 를 빼서 결과 값이 '0'인지 확인한다.

    - 예제 : CMP EAX , 1

    - 해석 : EAX 값에서 '1'을 뺀 경유 , 결과 값이 '0' 이라면 두 오퍼랜드 값은 동일하다.

 

  2) TEST

    - 형식 TEST [ Operand 1 ] [ Operand 2 ]

    - 내용 : [ Operand 1 ] 과 [ Operand 2 ]를 AND 연산을 실시한다.

    - 예제 : TEST EAX , EAX

    - 해석 : 두 오퍼랜드가 '0' 인지 아닌지를 판단할 수 있다.

    - 즉 , 두 오퍼랜드가 '0' 이면 AND 연산 결과 값이 '0'으로 나온다. 그래서 함수의 리턴값이 '0'인지 아닌지를 판단할

      때 주로 사용 한다.

 

  3) 상태 플래그

    - CMP , TEST 비교 이후에 분기 명령어가 있으면 상태 플래그를 확인하여 분기를 실시한다.

    ZF    Zero Flag              연산 결과가 '0' 이면 참 , ZF = 1 설정

    SF    Sign Flag               연산 결과가 음수이면 참 , SF = 1 설정

    CF    Carry Flag              부호 없는 숫자의 연산 결과 비트 범위를 넘으면 참 , CF = 1 설정 

    OF    OVerflow Flag         부호 있는 숫자의 연산 결과가 비트 범위를 넘으면 참 , OF  = 1 설정

 

 

8. 분기 관련 명령어

   - CMP , TEST 결과에 따라서 ZF가 '1' 또는 '0'으로 설정되며 , ZF 플래그 값에 따라서 분기되는 내용이 다르다

   - CMP 결과 값이 '0'이면 두 값은 동일한 값(참) 이며 , ZF = 1 로 설정 된다

   - 만약 , CMP 결과 값이 '0'이 아니면 두 값은 다른 값(거짓)이며 , ZF = 0 으로 유지된다

 

   - TEST 결과 값이 '0'이면 ZF =  1 로 설정된다.

   - 만약 , TEST 결과 값이 '0'이 아니면 , ZF = 0 으로 유지된다.

 

  1) JMP

    - 형식 : JMP [ Code Address ]

    - 내용 : 무조건 해당 주소로 점프한다

    - 예제 : JMP 401140

    - 해석 : 무조건 401140 번지로 점프한다 

 

  2) JZ ( JE 동일 )

    - 형식 : JZ [ Code Address ]

    - 내용 : 비교 결과 값이 '0' 이면  (ZF =1 설정된 경우 ) , 해당 주소로 점프한다.

    - 예제 : JZ 401140

    - 해석 : ZF = 1 인 경우 , 401140 으로 점프한다.

    - 조건 : Operand 1 == Operand 2 

 

  3) JNZ ( JNE 동일 )

    - 형식 : JZ [ Code Address ]

    - 내용 : 비교 결과 값이 '0' 이면  (ZF = 0  설정된 경우 ) , 해당 주소로 점프한다.

    - 예제 : JZ 401140

    - 해석 : ZF = 0 인 경우 , 401140 으로 점프한다.

    - 조건 : Operand 1 != Operand 2 

 

  4) JLE ( JBE 비슷함 )

   - 형식 JLE [ Code Address ]

   - 내용 : 비교 결과 값이 '0'이거나 (ZF =1) , 작을 경우 해당 주소로 점프한다.

   - 예제 : JLE 401140

   - 해석 : ZF =1 이거나 , 결과 값이 작은 경우 401140으로 점프한다.

   - 조건 : Operand 1 <= Operand 2 

 

  5) JGE ( JAE 비슷함 )

   - 형식 JGE [ Code Address ]

   - 내용 : 비교 결과 값이 '0'이거나 (ZF =1) , 작을 경우 해당 주소로 점프한다.

   - 예제 : JGE 401140

   - 해석 : ZF =1 이거나 , 결과 값이 작은 경우 401140으로 점프한다.

   - 조건 : Operand 1 <= Operand 2 

 

  6) JL ( JB 비슷함 )

   - 형식 JL [ Code Address ]

   - 내용 : Operand 1 이 Operand 2 보다 작은 경우 해당 주소로 점프한다

   - 예제 : JL 401140

   - 해석 : Operand 1 이 Operand 2 보다 작은 경우 401140으로 점프한다

   - 조건 : Operand 1 < Operand 2 

 

  7) JG ( JG 비슷함 )

   - 형식 JG [ Code Address ]

   - 내용 : Operand 1 이 Operand 2 보다 큰 경우 해당 주소로 점프한다

   - 예제 : JG 401140

   - 해석 : Operand 1 이 Operand 2 보다 큰 경우 401140으로 점프한다

   - 조건 : Operand 1 > Operand 2 

 

 

9. 스택 관련 명령어

 

  1) PUSH

    - 형식 : PUSH [ Operand ]

    - 내용 : Operand 값을 스택에 4byte 공간을 확보하고 저장한다.

    - 예제 : PUSH ECX

    - 해석 : 스택에 4byte 공간을 확보하고 'ECX' 값을 저장한다.

    - 용도 : 스택에 지역 변수 값을 저장 , 함수 인자 값 저장

    - 특징 : 'CALL' 명령어를 이용하여 함수를 호출하기 이전에 'PUSH' 명령어를 확인할 수 있다.

    - 참고 : 'PUSHAD' 명령어는 EAX ~ EDI 레지스트 값을 스택에 저장 (백업)할 때 사용한다.

 

  2) CALL

    - 형식 CALL [ 함수 주소 ]

    - 내용 : [ 함수 주소 ] 로 이동하여 함수를 실행한다.

    - 예제 : CALL 401000

    - 해석 : '401000' 주소에 있는 함수를 실행한다.

    - 함수가 호출되어 실행되기 이전에 다음과 같은 동작을 실시한다.

 

    'PUSH EIP' 를 실시하여 EIP 값(다음 명령어 / 리턴 주소)을 스택에 저장한다.

    그리고 해당 함수가 처리 완료되면 스택에 저장된 EIP 값을 확인하여 다음 명령어로 이동한다.

    'JMP [ 함수 주소 ] '를 실시하여 해당 함수로 점프하여 함수 내의 명령을 실행한다. 

 

  3) POP

    - 형식 : POP [ Operand ]

    - 내용 : PUSH를 통해서 저장된 값 / 확보된 공간을 제거한다

    - 예제 : POP ECX

    - 해석 : 스택에 저장된 ECX를 재거한다

    - 참고 : 'POPAD' 명령어는 스택에 저장된 EAX ~ EDI 레지스터를 제거(복원)할때 사용한다.

 

  4) RET

    - 형식 : RET

    - 내용 : CALL 명령어를 통해서 호출된 함수를 종료하고 다음 명령어로 이동한다.

    - RET이 실행되면 다음과 같은 동작을 실시한다.

       

      'POP EIP'를 실시하여 함수 호출때 스택에 PUSH한 EIP 값을 제거한다.

      'JMP EIP'를 실시하여 EIP 값의 주소로 점프하여 다음 명령어를 실행한다.

 

  5) NOP 

    - 형식 : NOP

    - 내용 : 아무 명령도 수행하지 않는 명령어이다.

    - 용도 : 명령어와 명령어 사이에 빈공간(1byte)을 채워주는 용도로 사용하며 , 16진수 값으로는 '0x90' 이다.

 

 

 

 

 

 

 

 

'리버싱' 카테고리의 다른 글

어셈블리 ( 구조체 )  (0) 2019.11.15
어셈블리 ( 스택 프레임)  (0) 2019.11.14
어셈블리(레지스터 이해)  (0) 2019.11.13
화면 잠금 프로그램 'Lock Workstation' 제작  (0) 2019.11.13
PE 파일 분석 IAT & Pre Binding  (0) 2019.11.11

설정

트랙백

댓글