악성코드 분석을 위한 리버스 엔지니어링 - 기본지식
진수, 보수
숫자를 표현하는 방법
수를 셀 때 자리수가 올라가는 단위를 기준으로 하는 셈법
2진수, 10진수, 16진수 등이 있다.
음수 표현을 위해 사용
1의 보수 : 숫자를 반전
2의 보수 : 1의 보수에 +1
구분 방법 : 최상위 비트가 0이면 양수, 1이면 음수
뺄셈 연산 : 보수를 취하고 더한다.
엔디안
- 빅 엔디언 : 작은 것을 큰 것으로 배열
장점 : 사람이 보기 편함. 디버깅에 좋음
용도 : RISC 계열 CPU, 네트워크 프로토콜
RISC : 축약형 명령어 적합 구조 - 적은 수의 컴퓨터 명령어로 수행할 수 있게 설계 - 리틀 엔디언 : 큰 것에서 작은 것으로 배열
장점 : 산술 연산과 데이터 타입의 확장/축소에 효율
용도 : Intel x86계열의 CPU, CISC 계열 CPU
CISC : 복합명령어 메모리 용량 적게 차지하는 프로그램을 구성할 수 있게 설계
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가 데이터를 빠르게 처리하는 것이 가능
명령어의 임시보관이나 데이터의 일시적인 중간 결과를 저장
레지스터는 역할에 따라서 여러가지 종류로 나누어짐
저장 공간이긴 하지만 저장을 위한 것이라기보다는 빠른 연산을 위한 것
악성코드를 분석하기 위해선 디버거가 해석하는 IA-32에서 제공하는 어셈블리 명령어와
IA-32의 레지스터에 대해 알아야함
일반적으로 주소를 저장할 때 사용되며, 특정 레지스터를 조작하기도 함
범용 레지스터라고 하며, 각각의 범용 레지스터의 크기는 4바이트
EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP 총 8개 존재
각 레지스터들은 16비트 하위 호환을 위해 몇 개의 구획으로 나뉘어짐
4바이트를 모두 사용할 때는 EAX, 2바이트만 사용할때는 AX
AX는 다시 상위 1바이트 AH와 하위 1바이트 AL로 나뉘어짐
레지스터 이름 |
|
EAX |
곱셈과 나눗셈 명령에서 자동으로 사용되고, 함수의 리턴 값이 저장됨 |
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 레지스터가 가리키는 주소로 복사) |
다시 ESP값을 변환하는 Stack Frame 기법을 사용
세그먼트 레지스터는 총 6개이며 각각의 크기는 2바이트
FS 레지스터는 고급 디버깅 주소 계산에 사용
CS |
Code Segment |
SS |
Stack Segment |
DS |
Data Segment |
ES |
Extra Segment |
FS |
Data Segment |
GS |
Data Segment |
플레그 레지스터의 이름은 EFLAGS이며 크기는 4바이트임
EFLAGS는 2바이트의 FLAGS의 레지스터의 확장임
EFLAGS는 각각의 비트가 각자의 의미를 가지고 있음
CF(Carry Flag) |
“연산된 결과값”이 “결과 값이 들어갈 피 연산자의 크기”보다 클 때 세팅 |
PF(Parity Flag) |
연산 결과 최하위 바이트의 값이 1이 짝수 일 경우에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이된다. |
CPU가 처리할 명령어의 주소를 나타냄
크기는 2바이트인 IP레지스터의 확장 형태로 4바이트임
CPU는 EIP에 저장된 주소의 명령어를 처리한 후 처리한 명령어의 길이만큼 EIP를 증가시켜
다음 명령어를 처리함
다른 레지스터와 달리 EIP는 직접 변경할 수 없기 때문에 특정 명령어를 이용해서 변경
메모리 구조
- 스택에서의 데이터 입력을 PUSH, 출력을 POP이라고 함
- Intel CPU에서는 EBP, ESP등을 이용해서 스택을 구현
- EBP는 현재까지 실행된 주소, ESP는 스택 포인터임
명령어
고정된 값 , 레지스터, 메모리주소
데이터이동, 조건 분기, 주소 이동, 함수 호출 및 복귀, 산술 연산, 스택 명령어, 비교
오퍼랜드 2를 오퍼랜드 1로 복사
연산 결과에 따라서 ZF,OF,CF가 설정될 수 있음
MOV EAX, EBX
지정한 주소를 가져오는 명령어
일반적으로 주소에 저장된 값을 가져올 때 사용
LEA EAX, DWORd PTR SS:[EBP]
더하기
오퍼랜드1 = 오퍼랜드1 + 오퍼랜드2
빼기
오퍼랜드1 = 오퍼랜드1 – 오퍼랜드2
- 곱하기 연산
- 곱해지는 수는 무조건 EAX레지스터의 EAX, AX, AL등 A*계열의 레지스터여야 함
- 따라서 연산이 수행되기 전 EAX에 적절한 값이 저장 되어 있어야함
- 곱하는 수는 레지스터 혹은 메모리로 곱해지는 수와 같은 사이즈
MUL 0x50
- 나누기 연산
- MUL명령어와 반대로 동작
- 나눠지는 수로는 EAX 레지스터를 사용하고, 연산 값이 32비트 이상인 경우 EDX레지스터도 사용
- 나눠지는 수가 16비트인 경우 나누는 수는 무조건 8비트여야 하며, 레지스터 혹은 메모리 사용가능
- 나눠지는 수는 DX에서 AX에 걸쳐 저장되고 몫은 AX, 나머지는 DX레지스터에 저장
DIV EBX
- 오퍼랜드에 1을 더함
- 연산 결과에 따라 zf,of플래그 값이 세팅
- 오퍼랜드에 1을 뺌
- 연산 결과에 따라 ZF,OF플래그 값이 세팅
INC EAX
DEC EAX
- 오퍼랜드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
'Reversing' 카테고리의 다른 글
악성코드 분석을 위한 리버스 엔지니어링 - PE 구조 (0) | 2017.08.23 |
---|---|
OllyDBG를 이용한 지뢰찾기 지뢰위치 확인 (0) | 2017.08.22 |
OllyDBG를 이용한 지뢰찾기 시간흐름 변경 (0) | 2017.08.22 |
악성코드 분석을 위한 리버스 엔지니어링 - 기본지식2 (0) | 2017.08.22 |
압축_집(Zip)구조 형태 원리 분석 (0) | 2016.07.18 |
최근댓글