IT 그리고 정보보안/Knowledge base

어셈블리어 개요

plummmm 2021. 4. 17. 10:16
반응형

. Assembly(어셈블리) 란?

-> 기계어와 1:1로 대응되는 저급 프로그래밍 언어이다. 어셈블리 언어를 기계어 형태의 

오브젝트 코드로 해석해주는 어셈블러에 의해 해석된다.

 

2. 어셈블리 기본 정리

- segreg : 16비트 세그먼트 레지스터

- mem : 메모리

- label : 지정된 레이블

- imm : 즉시값(상수)

- reg : 일반 범용 레지스터

 

어셈블리 명령어 앞에 E가 많이 붙는데. 기존 16비트에서 32비트 아키텍쳐가 되면서 범위가 확장된 거임 (Extended)

 

명령어를 보기 전에 일단 프롤로그와 에필로그가 뭔지 좀 알아보자.

 

Prologue(프롤로그) : 스텍 프레임을 잡아주는 것. 즉 함수가 호출 될 때 프롤로그라고 한다.

-> push EBP            ebp의 값을 push하고 esp의 값을 ebp에 저장한다.

     mov EBP ESP

 

Epilogue(에필로그) : 스텍 프레임을 해제하는 것. 함수를 종료할 때를 에필로그라고 한다. (leave 라고도 쓰인다.)

-> mov ESP EBP      ebp의 값을 esp에 저장한다. 그러면 esp가 ebp를 가르키겠지.(스택에 있는거 다 나가리) 

     pop EBP             그리고 난후 EBP의 값을 스택에서 꺼낸다. 그럼 이전 함수로 EBP가 돌아가겠지. 끝.

 

 

다음 간략하게 명령어 정리해봄

 

inc val : val의 값을 1 증가

dec val : val의 값을 1 감소

 

add val1 val2 : 두 값을 더하여 val2에 저장

sub val1 val2 : val1에서 val2를 빼고 val1에 저장

 

push : 값만큼 스택에 쌓음. esp값도 쌓인만큼 변화

pop : 스택 최상단 값을 뽑아냄.

 

mov val1 val2 : val2의 값을 val1에 저장한다. (단 mov mem mem 은 불가능 하다.)

 

LEA reg mem : 레지스터에 메모리의 주소값을 저장하고 싶을때.

OFFSET : 전역변수의 주소 불러오기

 

CMP val1 val2 : val2에서 val1를 빼서 비교한다. 저장안함. 혼자 쓰이지 않고 jmp나 mov와 같이 쓰임.

 

RET : 호출한 함수 바로 다음 지점으로 이동

-> pop EIP 

             

JMP [주소값] : mov EIP [주소값]

CALL [call한 주소] : PUSH EIP

Jmp [call 주소]    

--> 둘다 프로그램 실행 흐름 변화 시킴

 

TEST : 묵시적 and 연산 ( 원래 and 아닌데 and 똑같은 연산을한다함수의 성공 여부 분별)

함수의 반환값은 무조건 eax 저장이 되기 때문에 TEST eax eax 둘다 1이면 1이니까 .

 

and 차이점은 and연산은 저장을하기때문

 

* STOS : EAX의 값을 EDI가 가르키고 있는 공간에 저장한다.

 

* PTR : 데이터 타입 재정의

BYTE : 부호없는 1바이트 (8bit)

WORD : 부호없는 2바이트 (16bit)

DWORD : 부호없는 4바이트 (32bit)

 

QWORD : 부호없는 8바이트 (64bit)

 

그라먼 이제 실습해보자.

어셈블리를 왜 해야하는 지는 설명안해도 충분히 알거라고 생각됨.

우리가 기계가 아니기 때문에 기계어를 봐도 알 도리가 없다. 

그 기계어를 사람이 알기 쉽게 한 것이 어셈블리이다.

 

특히 시스템 관련 공부, 리버스 엔지니어링 등등..

해킹, 보안 공부를 하기 위해선 필수라고 볼 수 있음.

 

그럼 실습을 하면서 공부해보겠음.

일단 32비트 환경에서 masm32 를 설치한다.

 

설치하고.. 일단 모든 프로그래밍 언어의 시작.. Hello world를 찍어보자..

간단한 리버싱을 하며 어셈블리 명령어를 익히기 위한게 주목적이니.

다음에 기회가 된다면 어셈블리 프로그래밍을 자세히 다시 다루도록 하겠음.

 

일단 위의 소스가 어셈블리로 Hello world 찍는 소스이다. 책 예제임.

코드 작성을 했으면 컴파일을 해야겠죠

 

위는 소스 코드를 컴파일해서 오브젝트 파일이 생성되고

생성된 오브젝트 파일에 링크를 걸어 윈도우 서브시스템으로 사용할 수 있도록 한다.

 

 

Hello world가 찍혔다.

이제 우리가 공부할 내용이 나온다. Ollydbg를 이용하여 방금 작성한

헬로 월드를 디스어셈블 해본다.

 

올리디버거는 Opcode 즉, 기계어를 사용자가 알수 있도록 어셈블리어로 변환해주는 기능을 한다.

어셈블리, 레지스터, 메모리, 스택 총 4가지 창으로 다양한 관점에서 분석이 가능하도록 되어있다.

 

간단한 동작에 대해 설명한다.

 

Step in (F7) : 명령을 한 줄씩 실행하다가 CALL 명령을 만나면 프로시저 안으로 들어간다.

현재 프로시저에 쓰이는 하부 프로시저를 분석하고 싶으면 스텝인으로 들어가면됨.

Step out (F8) : 프로시저 실행하고 다음 라인으로 이동한다.

스텝인 반대로 하위 프로시져 뛰어넘고 싶으면 사용하셈.

Run (F9) : 프로그램 실행 상태로 변경.

Pause (F12) : 일시중지.

Break Point (F2) : 브레이크 포인트

Restart (Ctrl + F2) : 프로그램 재시작

 

몇줄 안되니까 한줄 씩 보겠음.

 

PUSH 0

스택 창 최상위에 0을 집어넣는다. 

PUSH abc.00403000

"Message"가 위치한 주소를 스택에 넣는다.

PUSH abc.00403008

"Hello world"가 위치한 주소를 스택에 넣는다.

PUSH 0

Hello world를 스택에 넣는다.

CALL <JMP.&user32.MessageBoxA>

MessageBoxA API를 호출한다.

 

 

 

참고 도서 : 리버싱 윈도우 - 로드북

참고 문서 : Parse and Parse Assembly(어셈블리어 입문자를 위한 어셈블리어 자료들의 모음) - bOBaNa

 

반응형