반응형

악성코드 분석을 위한 리버스 엔지니어링 - 기본지식


진수, 보수

  • 숫자를 표현하는 방법

  • 수를 셀 때 자리수가 올라가는 단위를 기준으로 하는 셈법

  • 2진수, 10진수, 16진수 등이 있다.

  • 음수 표현을 위해 사용

  • 1의 보수 : 숫자를 반전

  • 2의 보수 : 1의 보수에 +1

  • 구분 방법 : 최상위 비트가 0이면 양수, 1이면 음수

  • 뺄셈 연산 : 보수를 취하고 더한다.


엔디안

  • 빅 엔디언 : 작은 것을 큰 것으로 배열
    장점 : 사람이 보기 편함. 디버깅에 좋음
    용도 : RISC 계열 CPU, 네트워크 프로토콜
    RISC : 축약형 명령어 적합 구조 - 적은 수의 컴퓨터 명령어로 수행할 수 있게 설계
  • 리틀 엔디언 : 큰 것에서 작은 것으로 배열
    장점 : 산술 연산과 데이터 타입의 확장/축소에 효율
    용도 : Intel x86계열의 CPU, CISC 계열 CPU
    CISC : 복합명령어 메모리 용량 적게 차지하는 프로그램을 구성할 수 있게 설계

BYTE  b = 0x12;
WORD   w= 0x1234;
DWORD   dw = 0x12345678;
Char  str[] = “ABCD”;

TYPE

NAME

SIZE

빅엔디언

리틀엔디언

BYTE

B

1

[12]

[12]

WORD

W

2

[12][34]

[34][12]

DWORD

Dw

4

[12][34][56][78]

[78][56][34][12]

Char[]

str

6

[61][62][63][64][65][00]

[61][62][63][64][65][00]


레지스터

레지스터 : CPU 내부에 존재 하는 저장공간

특징
메모리와 다르게 CPU내부에 있기 때문에 CPU가 데이터를 빠르게 처리하는 것이 가능
명령어의 임시보관이나 데이터의 일시적인 중간 결과를 저장
레지스터는 역할에 따라서 여러가지 종류로 나누어짐
저장 공간이긴 하지만 저장을 위한 것이라기보다는 빠른 연산을 위한 것
악성코드를 분석하기 위해선 디버거가 해석하는 IA-32에서 제공하는 어셈블리 명령어와
 IA-32의 레지스터에 대해 알아야함

General Purpose Register

특징
일반적으로 주소를 저장할 때 사용되며, 특정 레지스터를 조작하기도 함
범용 레지스터라고 하며, 각각의 범용 레지스터의 크기는 4바이트
EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP
8개 존재
각 레지스터들은 16비트 하위 호환을 위해 몇 개의 구획으로 나뉘어짐
4
바이트를 모두 사용할 때는 EAX, 2바이트만 사용할때는 AX
AX는 다시 상위 1바이트 AH와 하위 1바이트 AL로 나뉘어짐


레지스터 이름

EAX
Extended Accumulator Register

곱셈과 나눗셈 명령에서 자동으로 사용되고함수의 리턴 값이 저장됨

ECX

Extended Counter Register

반복 명령어 사용시 반복 카운터로 사용 (ECX > 0 인 동안 반복)

EDX

Extended Data Register

EAX의 보조넘치는거 담아줌부호 확장 명령에 쓰임)

EBX

Extended Base Register

간접 주소가 저장됨(메모리 주소 지정에 사용됨)

ESP

Extended Stack Pointer

스택 프레임의 최상단하나의 스택 프레임의 끝지점 주소가 저장

EBP

Extended Base Pointer

스택 프레임의 기준하나의 스택 프레임의 시작지점 주소가 저장

ESI

Extended Source Index

(데이터 복사나 조작시출발지 주소(Source Index)가 저장

EDI

Extended Destination Index

(데이터 복사나 조작시도착지 주소(Destination Index)가 저장

(주로 ESI레지스터가 가리키는 주소의 데이터를 EDI 레지스터가 가리키는 주소로 복사)


EAX, EBX, ECX, EDX산술연산 명령어에서 상수/변수 값의 저장 용도로 많이 사용
ECX반복문에서 카운트로 사용되기도 함
EAXWin32 API에서 함수 리턴 값에 사용 되기도함
EBP,ESP,ESI,EDI는 주로 메모리 주소를 저장하는 포인터로 사용
ESP는 스택 메모리 주소를 가르킴

EBP는 함수 호출 시 그 순간의 ESP를 저장하고 함수가 리턴하기 직전에
다시 ESP값을 변환하는 Stack Frame 기법을 사용


Segment Registers
세그먼트 레지스터는 총 6개이며 각각의 크기는 2바이트

ES,FS,GS는 추가적인 데이터 세그먼트
FS
레지스터는 고급 디버깅 주소 계산에 사용

CS

Code Segment

SS

Stack Segment

DS

Data Segment

ES

Extra Segment

FS

Data Segment

GS

Data Segment



Program Status and Control Register
플레그 레지스터의 이름은 EFLAGS이며 크기는 4바이트임

특징
EFLAGS
2바이트의 FLAGS의 레지스터의 확장임
EFLAGS
는 각각의 비트가 각자의 의미를 가지고 있음

CF(Carry Flag)

연산된 결과값”이 “결과 값이 들어갈 피 연산자의 크기”보다 클 때 세팅

PF(Parity Flag)

연산 결과 최하위 바이트의 값이 1이 짝수 일 경우에패리티 체크를 하는데 사용

AF(Adjust Flag)

연산 결과 carry나 borrow가 3bit 이상 발생할 경우 1이 된다.

ZF(Zero Flag)

연산 결과가 0일 때 세트(1)된다연산 결과가 0이 아닐 때 해제(0)된다. if문 같은 조건문이 만족될 경우 set

SF(Sign Flag)

연산 결과 최상위 비트의 값과 같다양수이면 0, 음수이면 1

TF(Trap Flag)

디버깅을 할 때 single-step을 가능하게 하려면 1을 준다.

DF(Direction Flag)

문자열 처리에 있어서 1일 경우 문자열 처리 instruction이 자동으로 감소(문자열 처리가 high address에서 low로 이루어짐) 0일 경우 자동으로 증가

OF(Overflow Flag)

정수형 결과값이 너무 큰 양수이거나 너무 작은 음수여서 피연산자의 데이터 타입에 모두 들어가지 않을 경우 1이된다.


Instruction Pointer(EIP)
CPU
가 처리할 명령어의 주소를 나타냄
크기는 2바이트인 IP레지스터의 확장 형태로 4바이트임
CPU
EIP에 저장된 주소의 명령어를 처리한 후 처리한 명령어의 길이만큼 EIP를 증가시켜
다음 명령어를 처리함
다른 레지스터와 달리 EIP는 직접 변경할 수 없기 때문에 특정 명령어를 이용해서 변경


메모리 구조

스택
-
스택에서의 데이터 입력을 PUSH, 출력을 POP이라고 함
- Intel CPU에서는 EBP, ESP등을 이용해서 스택을 구현
- EBP
는 현재까지 실행된 주소, ESP는 스택 포인터임


명령어

명령어는 연상 명령어와 0개 이상의 오퍼랜드로 구성됨
오퍼랜드는 연상 명령어에서 사용하는 데이터를 식별하는데 다음 세 가지 유형이 올 수 있음
고정된 값 , 레지스터, 메모리주소

명령어의 종류는 크게 다음과 같이 나누어짐
데이터이동, 조건 분기, 주소 이동, 함수 호출 및 복귀, 산술 연산, 스택 명령어, 비교

 명령어 오퍼랜드1, 오퍼랜드2


MOV
오퍼랜드 2를 오퍼랜드 1로 복사
연산 결과에 따라서 ZF,OF,CF가 설정될 수 있음
MOV EAX, EBX

LEA
지정한 주소를 가져오는 명령어
일반적으로 주소에 저장된 값을 가져올 때 사용
LEA EAX,
DWORd PTR SS:[EBP]

ADD
더하기
오퍼랜드1 = 오퍼랜드1 + 오퍼랜드2

SUB
빼기
오퍼랜드1 = 오퍼랜드1 – 오퍼랜드2

MUL
- 곱하기 연산
-
곱해지는 수는 무조건 EAX레지스터의 EAX, AX, ALA*계열의 레지스터여야 함
-
따라서 연산이 수행되기 전 EAX에 적절한 값이 저장 되어 있어야함
-
곱하는 수는 레지스터 혹은 메모리로 곱해지는 수와 같은 사이즈
MUL 0x50

DIV
-
나누기 연산
- MUL
명령어와 반대로 동작
-
나눠지는 수로는 EAX 레지스터를 사용하고, 연산 값이 32비트 이상인 경우 EDX레지스터도 사용
- 나눠지는 수가 16비트인 경우 나누는 수는 무조건 8비트여야 하며, 레지스터 혹은 메모리 사용가능
-
나눠지는 수는 DX에서 AX에 걸쳐 저장되고 몫은 AX, 나머지는 DX레지스터에 저장
DIV EBX

INC
-
오퍼랜드에 1을 더함
-
연산 결과에 따라 zf,of플래그 값이 세팅

DEC
-
오퍼랜드에 1을 뺌
- 
연산 결과에 따라 ZF,OF플래그 값이 세팅

INC,DEC 명령어에 사용되는 오퍼랜드는 1개이며 메모리와 범용 레지스터 둘다 지정 가능
INC EAX
DEC EAX

TEST
오퍼랜드1과 오퍼랜드2를 AND한 후 결과 값의 상태 정보만 플래그 레지스터에 저장
연산 결과는 반영하지 않고 테스트하여 자신의 상태 값만 확인
- MOV 
명령으로는 플래그 값을 변경하지 못하므로 TEST라는 명령어를 통해 FLAG를 갱신해
조건 설정을 할 때 많이 사용
영향을 받는 플래그는 CF, OF는 초기화되고, ZF는 설정될 수 있음

TEST EAX,EAX
스택 명령어
- PUSH – 
스택에 저장하나의 오퍼랜드만 사용
- POP – 
스택에서 값 꺼내기하나의 오퍼랜드만 사용
- PUSH,POP
명령어 모두 오퍼랜드에는 값메모리레지스터가 올 수 있음

PUSH EBP
POP EBP

비교연산
- CMP
명령어를 이용하여 비교하고, 비교 결과를 플래그에 남김
-
플래그에 세팅된 값에 의해 J로 시작하는 조건 분기 명령들을 이용하여 특정 위치로 이동
- CMP
명령어를 사용할 때 오퍼랜드1이 오퍼랜드2보다 작을 경우 CF가 세팅
- CMP
명령어를 사용할 때 오퍼랜드 1에서 오퍼랜드 2를 뺀 결과가 0일 경우 ZF가 세팅
CMP EAX, EBX


함수 호출 복귀
- CALL
은 프로시저 호출 시 사용함 JMP와 다르게 프로시저가 끝나면 RET명령어를 사용해
원래의 프로시저로 돌아와야함
- CALL
명령어를 사용하게 되면 현재 ESP레지스터를 EBP레지스터에 저장하여 복귀 지점을
기록하고 해당 프로시저에서 사용될 매개 변수가 있다면 EBP 레지스터 기준으로 스택공간을
할당 한다.
-RET
CALL 명령어가 수행될 때 저장한 리턴 주소로 돌아감
-RET
CALL 명령어 수행시 매개변수를 저장하기 위해 할당 받은 스택 공간을 같이 반환

CALL 0x00495c68
RET 8H





반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기