어셈블리어와 악성코드

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

YaluStar 2018. 11. 27. 22:10

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


실습 환경

VMware Workstation 15 Player (FREE 버전)

Windows XP Professional SP3 (32Bit)


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



19E0:0147   MOV AX, 4200

19E0:014A   CWD

 

MOV 명령어로 AX=4200 값을 입력합니다. 이어서 CWD 명령어를 실행합니다.

CWD 명령어 AX 워드 정보를 DX:AX의 더블 워드형으로 확장하는 명령어입니다.

AX는 그대로 유지되지만, DX=0000의 값이 됩니다.

MOV 명령어 대신 사용하여 DX의 값을 0000으로 만들었는데 파일 크기를 줄이는 방법입니다.(CWD=1 Byte, MOV=3 Byte)





19E0:014B   INT 21


INT 21h, 42

파일 포인터 설정

파일의 시작, 파일의 끝 또는 현재 파일 위치에 대하여 상대적인 파일 위치 포인터를 옮긴다.


AH = 42

AL = 00 : 파일 시작에서부터

        01 : 현재 포인터부터

        02 : 파일의 끝에서부터

BX = 파일 핸들

CX = 파일 포인터를 옮길 거리의 상위 워드

DX = 파일 포인터를 옮길 거리의 하위 워드


AL=00, BX=0005, CX=0000, DX=0000


정리 => 레지스터의 값이 AL=00, BX=0005, CX=0000, DX=0000 처럼 설정이 되어 있을 경우 파일의 포인터가 처음으로 이동하게 됩니다.

이 전의 INT 21로 파일의 모든 내용을 읽어 파일 포인터가 끝으로 이동되었던 것을 파일명 앞에 바이러스를 넣기 위해 설정을 위에 처럼 한 것입니다.


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

정상적으로 실행되면 AX=0000, DX=0000 값이 나오고 CF=0(NC)가 됩니다.

AX = 옮겨진 파일 포인터의 하위 워드, DX = 옮겨진 파일 포인터의 상위 워드

 

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





19E0:014D   MOV AH, 40

19E0:014F   POP CX


MOV 명령어AH 값40으로 바꿔줍니다. AX=4000이 됩니다.

POP CX 명령어메모리에 있는 값을 추출합니다. 이 때 19E0:0146   PUSH AX 명령어넣어 두었던 악성코드 크기(64h) + 원본 파일 크기의 값(17h)을 가진 0075값이 추출되어 CX=0075 값을 가지게 됩니다.





19E0:0150   PUSH SI

19E0:0151   POP DX


SI=0100 값을 메모리에 넣었다가 POP DX 명령어로 추출하여 DX에 0100 값저장합니다.





19E0:0152   INT 21


INT 21h, 40

파일에 내용 쓰기

파일에 버퍼에 저장되어 있는 내용을 쓴다.


AH = 40

BX = 파일 핸들

CX = 쓸 바이트 개수

DS:DX = 파일에 쓸 내용이 저장되어 있는 버퍼의 세그먼트와 오프셋



1AE0공간에 있는 0100 ~ 0175까지의 내용을 파일에 작성합니다. (MINI-100 + 파일 원본)

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

정상적으로 실행되면 CF=0(NC), AX=0075 값이 됩니다.

AX = 사용한 Byte 수


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





19E0:0154   PUSH CS

19E0:0155   POP DS

19E0:0156   MOV AH, 3E


CS의 값인 19E0을 메모리에 넣어준 후 POP DS 명령어로 다시 추출하여 DS에 19E0 값을 저장합니다.

MOV 명령어AH에 3E 값을 입력합니다. AX=3E75 값이 됩니다.





19E0:0158   INT 21


INT 21h, 3E

파일 닫기

오픈되어 있는 파일을 닫는다.


AH = 3E

BX = 파일 핸들


성공하면 CF=0, AX=파일 핸들 값을 가지게 된다.

실패하면 CF=1, AX=에러 번호 값을 가진다.



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

정상적으로 실행되면 CF=0(NC), AX=3E00 값이 됩니다.


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





INT 21, 3E 이후에 파일의 속성을 확인하면 파일의 크기가 100 Byte 증가117 Byte가 된 것을 확인할 수 있습니다. (원본 17 Byte)





19E0:015A   MOV AH, 4F

19E0:015C   JMP 0113


MOV 명령어를 이용하여 AH에 4F 값을 입력합니다. AX=4F00이 됩니다.

JMP 0113  명령어를 실행하면 19E0:0113 주소로 점프합니다.





19E0:0113   INT 21


INT 21h, 4F

다음 파일 찾기

함수 4E를 사용한 뒤 계속해서 파일을 찾을 때 사용한다.


AH = 4F


성공하면 CF=0, 현재 디스크 전송 영역(DTA)의 내용이 다음과 같이 변경된다.

실패하면 CF=1, AX=에러 번호3 값을 가진다.



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

찾는 파일이 더이상 없게 되어 AX=0012, CF=1(CY) 값을 가지게 됩니다.





19E0:0115   JNB 012D


JNB 명령어CF=0(NC)일 때 발동하는 점프문입니다.

그러나 INT 21, 4F 명령어가 실패 결과가 발생하여 CF=1(CY)가 되어 JNB 명령어는 발동하지 않고 지나치게 됩니다.

찾는 파일이 있을 경우 JNB 명령어가 수행됩니다.(추가 감염)





19E0:0117   PUSH SI

19E0:0118   PUSH ES

19E0:0119   PUSH CS

19E0:011A   POP ES


차례대로 SI의 0100 값, ES의 1AE0 값, CS의 19E0 값을 메모리에 넣어줍니다.

그리고 POP ES 명령어로 마지막에 넣어준 CS의 19E0 값을 추출해 ES에 저장합니다.






19E0:011B   XCHG DI, SI

19E0;011D   MOV CX, FE9B


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

SI=0164, DI=0100

MOV 명령어를 통해 CX에 FE9B 값을 입력합니다.

CX=FE9B





19E0:0120   MOV AX, 0125

19E0:0123   PUSH AX


MOV 명령어를 이용하여 AX에 0125 값을 입력합니다.

PUSH 명령어AX의 0125 값을 메모리에 저장합니다.






19E0:0124   RETF


RETF 명령어를 실행하면 스택에서 두 워드를 꺼내 처음 꺼낸 값은 IP에 넣고, 두번째로 꺼낸 값은 CS에 넣습니다.

CS:IP는 항상 다음에 실행할 명령어를 가리키므로 19E0:0124에서 1AE0:0125로 실행 흐름이 변경됩니다.




RETF끝난 다음에는 1AE0:0125로 주소가 변경되고 REPZ 명령어가 나오게 됩니다.





1AE0:0125   REPZ

1AE0:0126   MOVSB


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

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


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

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

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


정리하면 REPZ와 MOVSB 명령어를 통해 19E0:0164에서 19E0:0100으로 복사하는 작업을 합니다. CX는 1씩 감소하여 최종적으로 0000 값이 되고, SI와 DI는 1씩 증가하여 SI=FFFF, DI=FF9B 값이 됩니다.





1AE0:0127   POP SI

1AE0:0128   PUSH ES


코드 실행 전 값 ES=19E0

POP SI 명령어를 통해 스택에 저장되어 있던 0100 값이 추출되어 SI는 0100의 값을 가지게 되고, PUSH ES 명령어ES의 값 19E0 값이 스택에 저장됩니다.

코드 실행 후 값 ES=19E0, SI=0100






1AE0:0129   PUSH ES

1AE0:012A   POP DS

1AE0:012B   PUSH SI

1AE0:012C   RETF


코드 실행전 값 ES=19E0, SI=0100

PUSH ES 명령어19E0 값을 한 번더 스택에 저장합니다. 그리고 POP DS 명령어19E0 값을 추출하여 DS에 저장합니다.

마지막으로 PUSH SI 명령어로 0100 값을 스택에 저장합니다.

코드 실행후 값 ES=19E0, DS=19E0, SI=0100





1AE0:012C   RETF


RETF 명령어를 실행하면 스택에서 두 워드를 꺼내 처음 꺼낸 값은 IP에 넣고, 두번째로 꺼낸 값은 CS에 넣습니다.

CS:IP항상 다음에 실행할 명령어를 가리키므로 1AE0:012C에서 19E0:0100으로 실행 흐름이 변경됩니다.







이상으로 MINI-100 바이러스의 코드에 대하여 알아보았습니다.

감사합니다.


반응형