[KDT_AISEC] 8주차 - 악성코드와 어셈블리어

Gloomy·2024년 1월 30일
0

KDT_AISEC

목록 보기
19/25
post-thumbnail

악성코드 개요


악성코드란?

악의적인 목적을 위해 작성된 실행 가능한 코드를 의미한다. 악성코드는 다음의 종류들이 있다.

  • 바이러스
  • 트로이 목마
  • 스파이웨어
  • 애드웨어
  • 랜섬웨어
  • 기타

악성코드의 역할

  • Droppper: 생성
  • Launcher: 실행
  • Backddor: 연결
  • Module: 각각의 악성 행위를 실행하는 악의적인 목적을 위해 작성된 실행 가능한 코드

악성코드 분석 실습


분석 툴

DOS환경에서 작동하는 debug툴을 이용하는데, 64bit환경에서 실행하기 위해서는 DOSBox를 설치해야 한다.

Debug 기본 사용법

현재 분석을 위한 툴과 악성코드의 경로가 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: 특정 메모리에 있는 값을 확인하는 명령어

debug 플래그


주목할 플래그는 Zero, Carry정도가 있다.

명령어 실습


IPInstruction Pointer로 다음에 실행할 코드의 주소를 나타낸다.
현재 주소가 0x0100이므로 해당 주소에 코드를 작성하도록 하겠다.

MOV


MOV Dest, SrcDestSrc값을 저장하는 코드이다.

MOV reg, reg
MOV reg, imm
MOV mem, reg
MOV reg, mem

MOV는 위의 형태로만 사용할 수 있다.
위의 코드는 0x1234bx레지스터에 넣고, ax레지스터에 bx레지스터 값을 넣고, 0x120주소에 bx레지스터 값을 넣고 cx레지스터에 0x120주소에 있는 값을 넣는 코드이다.

결과적으로
ax, bx, cx, 0x120에 모두 0x1234값이 들어간다.

0x1200x1234가 잘 들어있는지 확인해보자.

34 12의 형태로 데이터가 저장되어 있는데, 이것은 반대로 저장된 것이 아니라 리틀 엔디안 방식으로 저장되기 때문에 그렇다.

리틀 엔디안은 낮은 주소에 데이터의 낮은 바이트(LSB, Least Significant Bit)부터 저장하는 방식이다.

INC

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

DEC의 경우, INC와 반대로 오퍼랜드의 값을 1 감소 시킨다.

bx를 1 감소 시켰더니 다시 0xffff가 되면서 Zero플래그가 NZ로, Sign플래그가 NG(Negative)로 변한 것을 볼 수 있다.

ADD

ADD는 첫 번째 오퍼랜드에 두 번째 오퍼랜드의 값을 더하여 저장하는 명령어이다. 다음의 형태로 사용할 수 있다.

ADD Dest, Src
ADD reg, reg
ADD reg, imm
ADD mem, reg
ADD mem, imm
ADD reg, mem

SUB

SUB는 첫 번째 오퍼랜드에서 두 번째 오퍼랜드의 값을 뺀 후 저장하는 명령어이다.

SUB Dest, Src
SUB reg, reg
SUB reg, imm
SUB mem, reg
SUB mem, imm
SUB reg, mem

CMP

CMP는 매우 중요한 명령어이다. 첫 번째 오퍼랜드에서 두 번째 오퍼랜드를 SUB연산 진행 후, 값이 같다면 결과가 0이 되면서 Zero플래그가 set된다.

Zero플래그가 ZR로 바뀐 것을 볼 수 있다.

Jump Instructions

  • jmp: 무조건 해당 주소로 점프
  • jz, je: 제로 플래그가 1이면(결과가 0이면) 점프
  • jnz, jne: 제로 플래그가 0이면(결과가 0이 아니면) 점프
  • jc, jb: 캐리 플래그가 1이면(캐리가 발생하면) 점프
  • jnc, jnb: 캐리 플래그가 0이면(캐리가 발생하지 않으면) 점프

CALL, RET

CALL은 해당 주소로 이동한 후 돌아올 주소를 스택에 저장한다. RET을 만나면 스택에 저장된 주소를 POP해서 해당 주소로 다시 이동한다.

CALL명령어로 인해 Ox150주소로 이동한 상황이다. 스택 포인터를 살펴보면 fd에서 fb로 낮아진 모습을 볼 수 있다. 스택은 거꾸로 자라기 때문에 스택에 어떤 값이 들어가면 스택 포인터는 위로 이동한다. 스택에 있는 값을 확인해보자.

해당 스택의 주소에 0x103이 저장되어 있는 모습이다. 이것이 바로 RET를 만났을 때 되돌아 올 주소이다.

RET를 만나서 0x103주소로 되돌아 온 모습이다.

PUSH, POP

PUSH는 첫 번째 오퍼랜드의 값을 스택에 저장하는 명령이고, POP은 스택에 마지막으로 저장된 값을 첫 번째 오퍼랜드에 저장하는 명령이다.

PUSH를 세번 진행한 후 스택의 모습이다.

리틀 엔디안 방식으로 잘 저장되어 있는 것이 보인다.

POP을 세번 진행하니 스택에 저장된 값이 모두 빠지고 첫 번째 오퍼랜드에 알맞은 값이 들어갔다.

AND, OR, XOR

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

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이므로 성공적으로 현재 시간을 불러온 것을 알 수 있고, CXDX를 참고해보면 해당 인터럽트는 22시 56분 41초에 실행한 것을 알 수 있다.

profile
𝙋𝙤𝙨𝙨𝙤 𝙁𝙖𝙧𝙚!

0개의 댓글