어셈블리언어


어셈블리언어란?

기계어를 사람이 알아보기 쉬운 니모닉 기호(mnemonic symbol)를 사용해 1:1 대응이 되는 컴퓨터 프로그래밍의 저급 언어이다. 

* 기계어: 컴퓨터가 읽을 수 있는 2 진 숫자(Binary digit, 0 과 1)로 이루어진 언어. 

* 니모닉 기호: 기계어로 된 일련의 숫자를 알아보기 쉽게 언어(단어)로 바꿔준 것. 


- IA-32 레지스터(32bit) // IA -64 레지스터 (64bit) 는 E 대신 R이 붙음

EAX : 누산기 , 산술·연산저장 , 리턴값

EBX : 간접주소지정, 산술·연산저장 

ECX : 반복카운터(차감) , ECX > 0

EDX : EAX 보조역할 //리턴값이 32bit수를 넘어갈 때 나머지를 EDX에 저장

EBP : 스택프레임 기준

ESP : 스택프레임 최상단

ESI I: 출발지(Source) 주소를 담는 공간 

EDI I: 목적지(Destination) 주소를 담는 공간 

EIP I: 다음 실행될 명령어의 주소를 담고 있는 레지스터

EFLAGS : [상태값 : 0(clear), 1(set)], AF,CF,OF,PF,SF,ZF 

  ZF: 산술연산결과가 0일 때 1로 set 되는 flag 

  ex) 1+1 = 2 ZF : 0 

      1-1 = 0 ZF : 1


- 데이터 형식

 BYTE 

 부호 없는 1 byte 

 WORD

 부호 없는 2 byte 

 DWORD

 부호 없는 4 byte 


- INC //operand의 값 1 증가

#include<stdio.h>

int main(){

int a=0;


_asm{ //_asm{} -> 인라인 어셈블러

INC a //or INC [EBP-0x04]

}


printf("%d\n",a);


return 0;

}


- DEC //operand의 값 1 감소

#include<stdio.h>

int main(){

int a=1;


_asm{

DEC a //or DEC [EBP-0x04]

}

printf("%d\n",a);


return 0;

}


- ADD //덧셈

#include<stdio.h>

int main(){

int a=0;


_asm{

ADD a, 0x05

}

printf("%d\n",a);


return 0;

}


- SUB //뺄셈

#include<stdio.h>

int main(){

int a=1;


_asm{

SUB a, 0x01

}

printf("%d\n",a);


return 0;

}


- MOV //복사,대입

#include<stdio.h>

int main(){

int a=0;


_asm{

MOV a, 0x02

}

printf("%d\n",a);


return 0;

}


ex) 예제문제

#include<stdio.h>

int main(){

int a,b,c,d;

a=b=c=0;


_asm{

MOV a , 0x03 // a주소에 3 대입

MOV b , 0x05 // b주소에 5 대입

MOV c , 0x0A // c주소에 10 대입

INC [EBP-0x08] // b주소에 1 증가

DEC [EBP-0x0C] // c주소에 1 감소

MOV EAX,[EBP-0x08] // EAX에 b주소에 있는 값 대입 

ADD EAX,[EBP-0x0C] // EAX(b) , c주소에 있는 값 두 개 더해서 EAX에 대입

MOV [EBP-0x04],EAX // a주소에 EAX값 대입

MOV EBX,[EBP-0x04]

SUB EBX,[EBP-0x0C]

MOV [EBP-0x08], EBX

}

printf("%d\n",a);

printf("%d\n",b);

printf("%d\n",c);

return 0;

}



- AND 

#include<stdio.h>

int main(){

int a=10;


_asm{

AND a, 0x06 

}

printf("%d\n",a);


return 0;

}


- OR

#include<stdio.h>

int main(){

int a=20;


_asm{

OR a, 0x0C

}

printf("%d\n",a);


return 0;

}


- XOR

#include<stdio.h>

int main(){

int a=12;


_asm{

XOR a, 0x08

}

printf("%d\n",a);


return 0;

}


- SHL & SHR //bit 이동

#include<stdio.h>

int main(){

int a=4;

printf("%d\n",a);


_asm{

SHL a, 0x01 //×2

}

printf("%d\n",a);

_asm{

SHR a, 0x02 //÷2

}

printf("%d\n",a);

return 0;

}

- PUSH & POP //push 한 만큼 pop 해야함

#include<stdio.h>

int main(){

int a=0;

_asm{

 push a

 push 0x10

 push eax

 

 pop eax

 pop a

 pop ebx

}

printf("%d\n",a);

return 0;

}


- PUSHAD //EAX->ECX->EDX->EBX->ESP->EBP->ESI->EDI , PUSH만 했기 때문에 에러남!

#include<stdio.h>

int main(){

int a=0;

_asm{

PUSHAD //범용 레지스터의 값들을 스택에 저장 = 백업하는 용도 

}

printf("%d\n",a);

return 0;

}

- POPAD 

#include<stdio.h>

int main(){

int a=0;

_asm{

POPAD //스택의 데이터를 범용 레지스터에 채움 

}

printf("%d\n",a);

return 0;

}


- PTR //데이터 타입 재정의

#include<stdio.h>

int main(){

int a = 1;

printf("%x\n",a); //1

_asm{

MOV WORD PTR a, 0x11111111

}

printf("%x\n",a); //1111

_asm{

MOV DWORD PTR a, 0x11111111

}

printf("%x\n",a); //11111111


return 0;

}


- OFFSET //전역변수 주소값 구하기

#include<stdio.h>

int g=10;

int main(){

int addr = 0;

int val = 0;

_asm{

MOV EAX, OFFSET g //데이터 세그먼트(영역) 시작부터의 상대적 거리값

MOV addr , EAX


MOV EBX, [EAX]

MOV val, EBX

}

printf("%x\n",addr);

printf("%x\n",val);

return 0;

}


- LEA //주소값 구하기

#include<stdio.h>

int main(){

int a = 4;

printf("%.8x\n",a);

printf("%.8x\n",&a);

_asm{

MOV EAX, [EBP-0x04]

MOV a, EAX

}

printf("%.8x\n",a);

_asm{

LEA EAX, [EBP-0x04]

MOV a, EAX

}

printf("%.8x\n",a);

return 0;

}


- STOS // EDI가 가르키는 주소에 EAX 값을 저장

#include<stdio.h>

int main(){

char Buffer[20];

      _asm{

MOV EAX, 0x00

LEA EDI, DWORD PTR [Buffer]

STOS DWORD PTR [EDI]

      }

printf("%s\n",Buffer);

      return 0;

}

- REP //Repeat , STOS,MOVS,SCAS 에서 사용가능

#include<stdio.h>

int main(){

char Buffer[20];

      _asm{

MOV EAX, 0x00

LEA EDI, DWORD PTR [Buffer]

MOV ECX, 0x05

REP STOS DWORD PTR [EDI]

      }

printf("%s\n",Buffer);

      return 0;

}

- MOVS //ESI가 가리키는 곳에 값을 EDI가 가리키는 곳에 복사(대입)

#include<stdio.h>

#include<string.h>

int main(){

char * str1 = "Hello~ world!!!";

      char str2[20];

      int Len = strlen(str1);

      _asm{ //strcpy 구현

MOV ESI, DWORD PTR [str1]

LEA EDI, DWORD PTR [str2]

MOV ECX, Len

REP MOVS BYTE PTR [EDI], BYTE PTR[ESI]

MOV BYTE PTR [EDI], 0x00

      }

printf("%s\n",str2);

      return 0;

}


- TEST //묵시적 AND 연산 , OPRAND에는 영향을 미치지 않음 , ZF:0

#include<stdio.h>

int main(){

int a = 3;

_asm{

TEST a, 0x02 

//ex) TEST EAX, EAX 리턴값이 NULL이 아닌지 확인

}

printf("%d\n",a);

return 0;

}


- CMP //내부적으로 - 연산

#include<stdio.h>

int main(){

int a = 5;

_asm{

CMP a, 0x05 //OPRAND에는 영향을 미치지 않음 

//CF:부호없는 산술연산 결과(음수 포함)가 너무 커서 담을 수 없을 때 1로 set 되는 flag , ZF:0

}

printf("%d\n",a);

return 0;

}


ex) CMP 5, 6 = -1 ZF:0 CF:1

ex) CMP 6, 5 = 1  ZF:0 CF:0

ex) CMP 5, 5 = 0  ZF:1 CF:0


- JMP//지정한 위치 이동에 사용

#include<stdio.h>

int main(){

int a = 5;

_asm{

JMP L1

MOV a, 0x09


L1: //레이블은 인라인 어셈 안이나 밖이나 사용 가능

MOV a, 0x01

}

printf("%d\n",a);

return 0;

}


- 조건 점프 명령

 JA 

 CMP a > b

 JB

 CMP a < b

 JE

 CMP a == b

 JNE

 CMP a != b

 JZ

 TEST EAX, EAX (EAX = 0), ZF = 1

 JNZ

 TEST EAX, EAX (EAX = 1), ZF = 0


 JAE

 CF = 0 and ZF = 0 

 JBE

 CF = 1 and ZF = 1 

 JC

 CF = 1 

 JCXZ

 CX = 0 

 JECXZ

 ECX = 0 

 JG

 ZF = 0 and SF == OF 


- call
 
//레이블은 인라인 어셈 안이나 밖이나 사용 가능

#include<sdtio.h>

int sum(){

int a = 0;

int b = 2;

printf("Result\n");

return a + b;


}

int main(){

int result =0;

printf("%d\n", result);

_asm{

CALL sum

MOV result, EAX

}

printf("%d\n",result);

return 0;

}


- RET (== RETN) //ESP 레지스터가 가리키는 값을 EIP 레지스터에 저장

호출한 함수가 명령을 마치고 돌아갈 주소를 지정한 공간이다. 

인자를 정리할 때 사용한다. * RET imm8 = RET 0~255 

ex) RET 8 -> ESP 를 8bit 만큼 증가 

 

- NOP //아무 일도 하지 않는 명령어 

1byte 의 크기를 가지며 16 진수로 0x90 이다. 

명령어 사이의 빈공간을 채워주는 역할을 한다. 

- 바이너리 디버거 다운로드

OllyDBG          http://www.ollydbg.de/

Immunity DBG    http://debugger.immunityinc.com/

IDA Pro          https://www.hex-rays.com/products/ida/support/download.shtml

WinDBG          https://msdn.microsoft.com/ko-kr/windows/hardware/hh852365.aspx



'보안 > 리버싱' 카테고리의 다른 글

Reversing -3 함수호출규약  (0) 2017.02.01
Reversing -2 레지스터  (0) 2017.02.01

+ Recent posts