악의적인 목적을 위해 작성된 실행 가능한 코드를 의미한다. 악성코드는 다음의 종류들이 있다.
- 바이러스
- 웜
- 트로이 목마
- 스파이웨어
- 애드웨어
- 랜섬웨어
- 기타
Droppper
: 생성Launcher
: 실행Backddor
: 연결Module
: 각각의 악성 행위를 실행하는 악의적인 목적을 위해 작성된 실행 가능한 코드DOS
환경에서 작동하는 debug
툴을 이용하는데, 64bit환경에서 실행하기 위해서는 DOSBox
를 설치해야 한다.
현재 분석을 위한 툴과 악성코드의 경로가 C:\MINI
이므로, mount c c:\mini
명령어를 이용해 해당 폴더를 c:\
로 마운드한다.
debug
를 입력 후 정상적으로 실행되는지 확인한다.
debug
에서 주로 사용할 명령어는 a
, r
, e
, p
, t
, d
정도가 있다.
a
: 특정 주소에 어셈블리어를 작성하는 명령어r
: 현재 레지스터의 값을 보는 명령어이지만r
뒤에 특정 레지스터를 입력하면 해당 레지스터의 값을 설정하는 명령어e
: 특정 주소의 값을edit
하는 명령어p
:proceed
t
:trace
d
: 특정 메모리에 있는 값을 확인하는 명령어
주목할 플래그는 Zero
, Carry
정도가 있다.
IP
는 Instruction Pointer
로 다음에 실행할 코드의 주소를 나타낸다.
현재 주소가 0x0100
이므로 해당 주소에 코드를 작성하도록 하겠다.
MOV Dest, Src
는 Dest
에 Src
값을 저장하는 코드이다.
MOV reg, reg
MOV reg, imm
MOV mem, reg
MOV reg, mem
MOV
는 위의 형태로만 사용할 수 있다.
위의 코드는 0x1234
를 bx
레지스터에 넣고, ax
레지스터에 bx
레지스터 값을 넣고, 0x120
주소에 bx
레지스터 값을 넣고 cx
레지스터에 0x120
주소에 있는 값을 넣는 코드이다.
결과적으로
ax
, bx
, cx
, 0x120
에 모두 0x1234
값이 들어간다.
0x120
에 0x1234
가 잘 들어있는지 확인해보자.
34 12
의 형태로 데이터가 저장되어 있는데, 이것은 반대로 저장된 것이 아니라 리틀 엔디안 방식으로 저장되기 때문에 그렇다.
리틀 엔디안은 낮은 주소에 데이터의 낮은 바이트(LSB, Least Significant Bit)부터 저장하는 방식이다.
INC
는 오퍼랜드의 값을 1 증가 시킨다. 다음의 형태로만 사용 가능하다. 단, 메모리의 경우는 크기를 지정해야 한다.
4bit
:nibble
8bit
:byte
2byte
:word
4byte
:dword
INC reg
INC mem
bx
레지스터의 값이 1만큼 증가한 것을 확인할 수 있다.
INC
명령어를 이용해 Zero
플래그의 변화를 관찰해보자.
bx
레지스터에 0xffff
값을 저장한 후 1을 증가시켰더니 0으로 바뀌며 Zero
플래그가 set
되는 것을 볼 수 있다.
DEC
의 경우, INC
와 반대로 오퍼랜드의 값을 1 감소 시킨다.
bx
를 1 감소 시켰더니 다시 0xffff
가 되면서 Zero
플래그가 NZ
로, Sign
플래그가 NG(Negative)
로 변한 것을 볼 수 있다.
ADD
는 첫 번째 오퍼랜드에 두 번째 오퍼랜드의 값을 더하여 저장하는 명령어이다. 다음의 형태로 사용할 수 있다.
ADD Dest, Src
ADD reg, reg
ADD reg, imm
ADD mem, reg
ADD mem, imm
ADD reg, mem
SUB
는 첫 번째 오퍼랜드에서 두 번째 오퍼랜드의 값을 뺀 후 저장하는 명령어이다.
SUB Dest, Src
SUB reg, reg
SUB reg, imm
SUB mem, reg
SUB mem, imm
SUB reg, mem
CMP
는 매우 중요한 명령어이다. 첫 번째 오퍼랜드에서 두 번째 오퍼랜드를 SUB
연산 진행 후, 값이 같다면 결과가 0이 되면서 Zero
플래그가 set
된다.
Zero
플래그가 ZR
로 바뀐 것을 볼 수 있다.
jmp
: 무조건 해당 주소로 점프jz, je
: 제로 플래그가 1이면(결과가 0이면) 점프jnz, jne
: 제로 플래그가 0이면(결과가 0이 아니면) 점프jc, jb
: 캐리 플래그가 1이면(캐리가 발생하면) 점프jnc, jnb
: 캐리 플래그가 0이면(캐리가 발생하지 않으면) 점프
CALL
은 해당 주소로 이동한 후 돌아올 주소를 스택에 저장한다. RET
을 만나면 스택에 저장된 주소를 POP
해서 해당 주소로 다시 이동한다.
CALL
명령어로 인해 Ox150
주소로 이동한 상황이다. 스택 포인터를 살펴보면 fd
에서 fb
로 낮아진 모습을 볼 수 있다. 스택은 거꾸로 자라기 때문에 스택에 어떤 값이 들어가면 스택 포인터는 위로 이동한다. 스택에 있는 값을 확인해보자.
해당 스택의 주소에 0x103
이 저장되어 있는 모습이다. 이것이 바로 RET
를 만났을 때 되돌아 올 주소이다.
RET
를 만나서 0x103
주소로 되돌아 온 모습이다.
PUSH
는 첫 번째 오퍼랜드의 값을 스택에 저장하는 명령이고, POP
은 스택에 마지막으로 저장된 값을 첫 번째 오퍼랜드에 저장하는 명령이다.
PUSH
를 세번 진행한 후 스택의 모습이다.
리틀 엔디안 방식으로 잘 저장되어 있는 것이 보인다.
POP
을 세번 진행하니 스택에 저장된 값이 모두 빠지고 첫 번째 오퍼랜드에 알맞은 값이 들어갔다.
AND
, OR
, XOR
은 말 그대로 첫 번째 오퍼랜드와 두 번째 오퍼랜드를 각각의 비트연산을 진행한 후 첫 번째 오퍼랜드에 저장하는 명령이다.
mov cx, ax
mov ax, bx
mov bx, cx
xor ax, bx
xor bx, ax
xor ax, bx
push ax
push bx
pop ax
pop bx
xchg ax, bx
네 가지 모두 ax
레지스터의 값과 bx
레지스터의 값을 교환하는 코드이다. mov
의 경우는 cx
라는 레지스터를 추가로 이용해야 하는 단점이 있다.
INT
명령은 소프트웨어 인터럽트를 발생시키는 명령이다.
http://stanislavs.org/helppc/idx_interrupt.html
소프트웨어 인터럽트의 종류를 볼 수 있는 사이트이다.
인터럽트 코드를 진행한 결과이다.
이 인터럽트가 어떤 인터럽트인지 알기 위해서는 위의 링크를 참고해야한다.
인터럽트는 기본적으로 AH
레지스터의 값으로 종류를 구분하기 때문에 찾아야할 인터럽트는 int 1a,2
이다.
실행한 인터럽트에 대한 설명이다. 현재 시간을 불러오는 인터럽트같다.
AH = 02
on return:
CF = 0 if successful
= 1 if error, RTC not operating
CH = hours in BCD
CL = minutes in BCD
DH = seconds in BCD
DL = 1 if daylight savings time option
AH
는 기본적으로 정해져있고, 만약 인터럽트를 실행하는 데 성공했다면 캐리 플래그에 0, 즉 캐리 플래그가 클리어 된다는 뜻이다.
CH
에는 현재 시간이 리턴되고 CL
에는 분, DH
에는 초가 저장되는 것 같다. 위의 실행화면을 살펴보면 캐리 플래그가 NC
이므로 성공적으로 현재 시간을 불러온 것을 알 수 있고, CX
와 DX
를 참고해보면 해당 인터럽트는 22시 56분 41초
에 실행한 것을 알 수 있다.