어셈블리 – MOV MOVZX LEA 명령 MASM32

 어셈블리 – MOV MOVZX LEA 명령 MASM32

이 명령은 어셈블리중 제일 자주 접하게 되는 데이터를 복사(Move가 아니다.)하는 역할을 한다.

CPU는 복사는 같은 사이즈의 데이터끼리만 가능하며, 메모리에서 메모리는 불가능하므로, 복사하고자 하는 데이터을 CPU 레지스터를 이용하여 복사하게 된다. 그리고 세그먼트 레지스터의 내용을 범용 레지스터가 아닌 곳으로 이동은 가능하나 그 반대는 불가능 하다.

masm1.asm
.586

.model flat, stdcall

option casemap:none

.code

; 메인이 시작되는 지점입니다.이라는 것을 알림

main    proc

; 기존 ebp 주소를 백업 하기 위해 사용

push    ebp

; 여기서 부터 함수가 시작 지점을 ebp에 저장하여 Frame Pointer 설정

mov    ebp, esp

sub    esp, 8h

; 여기까지가 함수 프롤로그 이며, Frame Pointer 설정 함수를 생성하는 과정이다.

; 메모리 주소를 가르킬 때 []를 사용한다. 항상 메모리에 접근할때는 ptr로 사이즈를 정의해줘야 한다. dword ptr는 4바이트단위로 접근하겠다는 의미임, 스택은 기본적으로 4바이트 단위로 구성된다.

mov    dword ptr [ebp-4], 22334455h

mov    dword ptr [ebp-8], 00000000h

; 조금전에 저장한 값들을 mov 명령을 이용하여 esi와 edi에 복사하는 명령

mov    esi, dword ptr [ebp-4]

mov    edi, dword ptr [ebp-8]

; 함수 에필로그, Frame pointer를 제거, 지역변수 제거 및 EBP값 복원

mov    esp, ebp

pop    ebp

retn

main    endp

end main

[내용] Masm를 이용한 어셈블리 프로그래밍

어셈블리 프로그램을 작성할 때는 자료 저장에 스택을 사용하는 만큼 스택공간에 주의해야 한다. 위 프로그램을 통해 아래 내용을 이해하기 바란다.

push는 스택의 기본 크기가 4바이트이므로, 4바이트가 넘으면 여러번 사용해야 한다.

ESP 레지스터의 포인터 값을 sub으로 자신이 할당받고 싶은 바이트만큼 뺌으로써 스택공간을 할당받을 수 있다.

EBP 레지스터는 지역변수나 매개변수 접근의 기준점으로 사용된다. (항상 메모리 값에 접근하기 위해서는 ptr로 사이즈를 정의해줘야 함)

생성된 어셈블리 파일을 Ollydbg를 이용하여 파일을 열어보도록 하자. Ollydbg를 실행하고, File
à
Open(F3키)를 이용하여 masm1.exe를 열면 우리가 코드한 어셈블리 내용을 존재하는 것을 확인할 수 있다.

[그림] 생성한 masm1.exe를 Ollydbg로 분석할 수 있다

분석을 진행하는 방법은 Microsoft Visual C# 2010 Express를 이용하여 진행하였던 디버깅과 흡사하다.

Step into(F7키)는 어셈블리 명령을 한줄씩 실행하는데, 프로시저를 만나면 프로시저 안으로 진입하여 계속 한줄씩 실행한다.

Step over(F8키)는 한줄씩 실행하는데 프로시저를 만나면, 프로시저를 안으로 진입하지 않고 실행 결과를 받아서 다음 줄을 실행하게 된다.

그럼 위 masm1.exe를 분석을 Step into(F7키)를 이용하여 한줄씩 실행하면써, 주소 0040100D까지는 스택창을 유심있게 보자.

// 복귀를 위해 현재 EBP 레지스터를 저장한다.

00401000 m>/$ 55 PUSH EBP

// ESP레지스터의 값을 EBP 레지스터에 저장한다.

00401001 |. 8BEC MOV EBP,ESP

// 아래 SUB ESP, 8이 실행되면, 스택창에 스택이 2개 생성되는 것을 확인할 있다.

00401003 |. 83EC 08 SUB ESP,8

// [LOCAL.1]은 스택0012FF84=00000000를 나타낸다. 해당 공간에 22334455h값을 저장하게 된다.

00401006 |. C745 FC 55443322 MOV [LOCAL.1],22334455

// [LOCAL.2]은 스택0012FF80=00000000를 나타낸다. 해당 공간에 0h값을 저장하게 된다.

0040100D |. C745 F8 00000000 MOV [LOCAL.2],0

[내용] 어셈블리 0040100D까지 분석내용

0040100D까지 Step into(F7키)로 진행해보면 아래와 같이 스택에 값이 저장됨을 확인 할 수 있다.

[그림] 스택에 우리가 지시한 값이 저장된다

그림이제 0040101A까지 어셈블리를 Step into(F7키)로 실행해 보도록 하자.

// 스택 [0012FF84]=22334455에 위치한 값을 ESI에 복사를 진행한다.

00401014 |. 8B75 FC MOV ESI,[LOCAL.1]

// Stack SS:[0012FF80]=00000000에 위치한 값을 EDI에 복사를 진행한다.

00401017 |. 8B7D F8 MOV EDI,[LOCAL.2]

// 아래는 스택 에필로그로 복귀를 진행하게 된다.

0040101A |. 8BE5 MOV ESP,EBP

0040101C |. 5D POP EBP

0040101D . C3 RETN

[내용] 어셈블리 0040101D까지 분석내용

0040101A까지 진행하였다면 레지스터창에서 ESI와 EDI 레지스터가 변경되어 있음을 확인 할 수 있을것이다.

[그림] ESI, EDI 레지스터가 지시한 값으로 저장된다

-박스시작-

주소위치

ax 와 [ax]의 차이는 바로 ax는 ax의 값을 복사하는 곳이고, [ax]는 ax에 저장된 값이 주소가 되어 ax가 가르키는 메모리의 값이 복사되는 것이다.

만약 EBX레지스터에 아래값이 저장되어 있다고 하자.

ebx=12345678

1) mov eax, ebx

EBX레지스터에 저장된 값 12345678을 EAX레지스터로 복사

2) mov eax, [ebx]

EBX레지스터에 저장된 값 12345678의 메모리에 위치한 값을 EAX레지스터로 복사

-박스종료-

MOVZX 명령

이 명령은 MOV 의 확장 명령중 하나로써 operland2보다 크기가 큰 operland1에게 이동할 수 있다.  데이터를 이동할 때 상위에 남게되는 바이트는 0으로 채워진다.

masm2.asm
.586

.model flat, stdcall

option casemap:none

.code

main    proc

push    ebp

mov    ebp, esp

sub    esp, 4h

mov    dword ptr [ebp-4], 0000ffffh

; bx(16비트)레지스터를 movzx를 사용하여 eax에 복사한다.

; BX레지스터에 ffff를 저장한다.

mov    bx, word ptr [ebp-4]

; BX레지스터의 값을 EAX 레지스터에 복사한다.

movzx eax, bx

mov    esp, ebp

pop    ebp

retn

main    endp

end main

; 실행 결과

; eax=0x0000ffff

[내용] movzx 명령 예제

위 파일을 앞서 방법을 이용하여 MASM32를 통해 컴파일한후 Ollydbg를 이용하여 분석을 진행해보자. 00401011처리시 내용을 주의깊게 확인하도록 하자.

// 0041003까지 스택 프롤로그 부분이다.

00401000 m>/$ 55 PUSH EBP

00401001 |. 8BEC MOV EBP,ESP

00401003 |. 83EC 04 SUB ESP,4

// [LOCAL.1]은 EBP-4지점으로, 해당 지점에 FFFFh값을 입력한다.

00401006 |. C745 FC FFFF0000 MOV [LOCAL.1],0FFFF

// 입력된 값을 BX레지스터(EBX의 16비트형)에 복사한다.

0040100D |. 66:8B5D FC MOV BX,WORD PTR SS:[EBP-4]

// MOVZX 명령을 이용해 BX 레지스터보다 큰 EAX 레지스터에 복사하고, 남는 공간은 0으로 채운다.

00401011 |. 0FB7C3 MOVZX EAX,BX

// 스택 에필로그 부분이다.

00401014 |. 8BE5 MOV ESP,EBP

[그림] EAX레지스터에 FFFFh값이 업데이트 된다.

// EBP레지스터로 스택에 저장된 복귀 주소를 꺼낸후 스택을 종료 한다.

00401016 |. 5D POP EBP

00401017 . C3 RETN

[내용] MOVZX 명령 분석 내용

LEA 명령

지정한 주소값을 가져오는 명령으로, 일반적으로 값을 가져와야 하는 경우 사용된다.

MOV 명령과는 다른 결과를 나타내는데, 다름 예제를 통해 차이를 확인해 보자.

masm3.asm
.586

.model flat, stdcall

option casemap:none

.data

; 데이터 세그먼트를 지정하여 1234값을 저장한다.

message db “1234”

.code

main    proc

push    ebp

mov    ebp, esp

sub    esp, 4h

; EBP-4 스택에 0040200h값을 입력한다. 이 주소는 “1234”를 저장한 주소 이다.

mov    dword ptr [ebp-4], 00402000h

; 그럼 먼저 MOV명령을 이용해 보자. MOV는 EBP-4 스택에 저장된 값을 복사하게 된다.

mov eax, dword ptr [ebp-4]

; 이제 LEA명령을 이용해 보자. LEA은 EBP-4의 주소를 복사한다.

lea ecx, dword ptr [ebp-4]

; 차이값을 확인해 보자.

; EAX 레지스터의 지정된 주소을 EBX 레지스터로 복사하면, 1234값을 가져오게 된다.

mov ebx, [eax]

; ECX 레지스터에는 해당 스택의 주소가 저장되어 있으므로, 00402000이라는 값으 EDX레지스터에 저장된다.

mov edx, [ecx]

mov    esp, ebp

pop    ebp

retn

main    endp

end main

; 실형 결과

;eax=00402000

;ecx=0012ff854

;edx=00402000

;ebx=34333231

[내용] lea 명령 사용 예제

그럼 이 내용도 분석을 진행해 보자.

// 스택 프롤로그부분이다.

00401000 m>/$ 55 PUSH EBP

00401001 |. 8BEC MOV EBP,ESP

00401003 |. 83EC 04 SUB ESP,4

// [LOCAL.1], 즉 EBP-4 스택 공간에 “1234”의 메모리 주소 00402000을 저장한다.

00401006 |. C745 FC 00204000 MOV [LOCAL.1], 00402000 ; ASCII “1234”

// EBP-4 스택 공간의 값인 00402000을 EAX 레지스터에 복사한다.

0040100D |. 8B45 FC MOV EAX,[LOCAL.1]

// EBP-4 스택 공간의 주소값을 ECX 레지스터에 복사한다.

00401010 |. 8D4D FC LEA ECX,[LOCAL.1]

// 각 값의 주소값을 EBX, EDX 레지스터에 복사해 보자.

// LEA과 MOV명령의 차이로 인한, 아래와 같이 다른 결과 값이 저장된다.

00401013 |. 8B18 MOV EBX,DWORD PTR DS:[EAX]

00401015 |. 8B11 MOV EDX,DWORD PTR DS:[ECX]

[그림] EBX, EDX레지스터의 결과가 LEA 명령으로 차이가 있다.

// 스택 에필로그 부분이다.

00401017 |. 8BE5 MOV ESP,EBP

00401019 |. 5D POP EBP

0040101A . C3 RETN

[내용] LEA 명령 예제 분석

Facebook Comments

Leave A Reply

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.