리버싱

1일차 리버싱

컴공 2013. 4. 8. 21:15
반응형


- 컴퓨터 버스 구조
- CPU와 연결되는 데이터 버스는 메모리(주기억장치)에 밖에 없다.
- 데이터 입력시
: 입력장치 -> 주기억장치 -> CPU
- 데이터 출력시
: CPU -> 주기억장치 -> 출력장치
- 프로그램 실행시
: 보조기억장치 -> 주기억장치에 적재 -> 주기억장치의 명령을 하나씩 CPU로 가져온다.
(메모리에는 명령이 존재한다)
- CPU는 크게 ALU, Control Unit, Register 로 나누어 진다.
: ALU (산술논리 연산 장치)
: Control Unit (제어 장치) - 명령어를 해독하고, 제어신호를 발생시킨다.
: Register (임시저장공간)


※ ALU (Arithmetic Logic unit

CPU는 I/O 장치에서 받은 정보를 CPU내에 있는 메모리인 레지스터에 담은 뒤에 ALU에서 연산을 하는데, 이때 한 번에 처리할 수 있는 데이터의 양이 bit수로 나타내며 32bit 운영체제의 경우 한번에 처리할 수 있는 비트 수가 4byte(32bit)이다.
레지스터는 CPU 내에 있어서 처리 속도가 매우 빠르다.



※ 리버싱을 하는 이유
1. 악성 코드분석 & 취약점 분석
2. 크랙
3. keygen

Reversing (역공학)

IA32 (Intel Architecture 32 bit) Register
인텔에서 사용하는 CPU의 구조형식을 말한다.
cpu의 경우 AMD 또한 인텔 계열이고 이 외에 모토럴러, 스팍, 썬 등의 CPU계열이 있으나 intel이 가장 대표적이며,
인텔의 CPU 구조인 IA32를 이해하면 모든 구조가 거의 동일하다.

종류 :

Basic program execution registers
x87 FPU registers
MMX registers
XMM registers
Debug registers 등등

여기서 디버깅시 많이 보게되는 기본적인 Basic program execution registers 를 알아야합니다.
한글말로 기본 프로그램 실행 레지스터 입니다.
Basic program execution registers ( 기본 프로그램 실행 레지스터 )에는 4개의 그룹으로 나누어 질수 있습니다.

4개의 그룹:

General Purpose Registers ( 32비트 8개)
Segment Registers ( 16비트 6개 )
Program Status and Control Register ( 32비트 1개 )
Instruction Pointer ( 32비트 1개 )


※ 범용레지스터(General Purpose Register)
보통 상수/주소 등을 저장할 때 주로 사용되며, 특정 어셈블리 명령어에서는 특정 레지스터를 조작하기도 합니다.


EAX : Accumalot (누산기), 컴퓨터는 일반적으로 덧셈만 사용(가감도 가능하나, 연상 효율면이 떨어짐)
초기에 8bit짜리 msdos 시절에는 한번에 다루는 데이터가 8bit여서 A로 표기하여 사용하였으나, 점차 그 양이 많아 짐에 따라 16bit는 AX(A eXtended)를 사용하게 되었고 여기는 상위/하위 레지스터가 있다. 32bit는 EAX를 사용하여 표기한다. AH(A high)와 AL(A low)는 호환을 위해서 만들어졌다.
EAX 레지스터
32비트(bit) = 4바이트(byte)를 모두 사용하고 싶을때는 EAX(4byte) 를 사용하고
16비트(bit) = 2바이트(byte)만 사용하고 싶을때는 AX(2byte) 를 사용하고
8비트(bit) = 1바이트(byte)만 사용하고 싶을때는 상위 AH(1byte) 하위 AL(1byte) 로 나누어 집니다.

EBX : BaseRegister로 자료의 주소 저장시에 사용된다.
ECX : CounterRegister로 반복되는 횟수를 저장한다. for(i=0;i>10;i++){} 시 0~9까지인 10이 저장된다.
EDX : DataRegister로 값이 저장된다.


ESI : 문자열 연산에 시작 주소를 가리킨다.
EDI : 문자열 연산에 끝주소를 가리킨다.
ESP : 스택을 가르키는 것(in the SS segment)
EBP : 스택에 있는 데이터 위치를 가리킨다.


◇ Instruction Pointer (EIP)

- 다음에 실행할 명령이 들어 있는 메모리의 번지를 가진다.
- CS 세그먼트 레지스터와 한 쌍이 되어 실행 번지를 참조한다.
- CPU는 EIP의 주소를 보고, 다음에 처리할 명령을 파악한다.
- 직접 적으로 사용자가 조작할 수 없는 레지스터 이다.
( 버퍼 오버플로우 공격에 사용되는 레지스터 이다 )


 


※ 인텔 계열의 CPU들은 메모리 스택의 삽입 구조가 Full stack(마지막에 값이 있음)에 descending 주소를 가지고 있다.



descending의 경우 메모리 주소가 삽입 순서와 반대로 주어진다. ascending의 경우 일반적인 경우와 동일하다.
윈도우의 경우 반대로 되어 있다.

 메모리 구조

일반적으로 메모리구조는 STACK형식이 후입선출(FILO)과 달리 밑으로 늘어난다.

◇ Eflags Register
- 연산의 결과 및 시스템 제어를 위한 정보가 각각 배정되어 있다.
- 컴퓨터의 상태 정보를 저장하는 레지스터
- 예를 들어 IP Header의 필드를 나눠서 0bit ~ 4bit 는 Version, 64bit ~ 72bit 는 TTL 이다, 하는 것처럼 여러가지 상태 정보를 필드 단위로 쪼개서 저장하는 것이다.

자주쓰이는 Status Flag
▶ CF(Carry Flag)
: 부호 없는 연산 결과가 용량보다 클 때 세트(1) 된다.

▶ ZF(Zero Flag)
: 연산 결과가 0일 때 세트(1) 되고, 0이 아닐 때 해제(0) 된다.

▶ SF(Sign Flag)
: 연산 결과, 최상위 비트가 1일 때(보수표현으로 음수가 되었을 때) 세트(1) 되고, 0일 때 해제(0) 된다.
: 즉 연산 결과가 음수가 되었을 때 세트(1), 양수가 되었을 때 해제(0) 된다.

▶ OF(OverFlow Flag)
: 부호 있는 연산 결과가 용량보다 클 때 세트(1) 된다.

▶ DF(Direction Flag)
: 문자열 처리에서 연속되는 문자열의 처리 방향에 따라 세트된다.
- 이외에도 여러가지 플래그 레지스터가 존재한다.

Exam 다음과 같은 코드가 있을때?>
A=10;
B=20;
if(A==B){
}

: 여기에서 컴퓨터는 이것이 참인지 거짓인지 알지 못한다.
: 컴퓨터는 두 수가 같은지, 적은지 비교할 때는 빼기 연산을 하여 계산을 한다.
: 10 - 10 = 0, 0이니 같구나! 이런 방식이다.
: 0이니 ZF가 1로 셋팅 되고, 아 두 수가 같구나! 하고 if문 안으로 들어가는 것이다.
( 즉 위 코드에서 if문을 만났을 때, 상태 정보를 보고 점프를 할지 들어갈 지를 결정하는 것이다 )

◇ Segment Register (세그먼트 레지스터)
- 세그먼트란?
: 간단하게 말해서 물리 주소를 참조 하기 위해 쓰이는 것이다.
: Segment Register(16bit) 는 Descriptor Table 의 Segment Descriptor을 가리킨다.
: 이 Segment Descriptor Base 주소와 Offset(가상주소)를 합쳐서 선형 주소를 만든다.
: 예전 16bit 시절에는 주소 값이 모잘라서, 세그먼트를 사용했는데,
: 요즘은 32bit라 넉넉하다. (4GB 까지 가능)
: 하지만 영역을 나누기 때문에 관리도 편하고, 보안성도 향상 되어서 계속 사용 중이다.
- 세그먼트 레지스터의 크기는 16Byte 이다
- IA32에서 Windows 의 경우 FS를 제외한 CS, SS, DS 레지스터가 접근하는 메모리의
시작 주소는 0 이다.

▶ CS(Code Segment)
: 코드 세그먼트의 시작 번지를 가리키며, Instruction Pointer(IP) 레지스터가 가진
offset 값과 합쳐서 실행을 위한 명령어의 주소를 참조하게 된다.

▶ DS(Data Segment)
: 데이터 세그먼트의 시작번지를 가리키며, AX, CX, DX, SI, DI 레지스터와
합쳐서 데이터 영역의 주소를 참조하게 된다.

▶ SS(Stack Segment)
: 스택 세그먼트의 시작번지를 가리키며, SP 혹은 BP 레지스터와 합쳐서
스택 영역의 주소를 참조하게 된다.

▶ FS
: 윈도우의 경우 SEH Chain을 위한 용도로 사용된다.

◇ Debug Register (디버그 레지스터)
- Hardware BreakPoint 에 사용되는 레지스터 이다.
- 총 6개의 레지스터가 사용 된다.
- Privileged Level 0 에 의해서만 접근이 가능하다.
★ BreakPoint 에는 Soft BreakPoint 와 Hardware BreakPoint가 있다.
- Soft BreakPoint : 평소 디버깅시 사용하는 BreakPoint
- Hardware BreakPoint : 레지스터에 BreakPoint를 걸 주소를 저장하면서 거는 방법
- Soft BreakPoint를 이용하면 CRC CheckSum값이 변경되는데, 안티 리버싱 에서는
이러한 변화를 감지해 프로그램을 종료 시킨다.
그렇기 때문에 이러한 경우 Hardware BreakPoint를 사용한다.

▶ DR0 - DR3
- Hardware Break Point 로 지정된 Linear Address 값을 가진다.
- 각각의 상태는 DR7 에 정의되어 있다.
( 하드웨어 브레이크 포인트는 4개까지 밖에 못 건다 )

▶ DR4 - DR5
- 예약되어 있는 레지스터

▶ DR6
- 현재 상황에 따라 값이 바뀐다.
( 진행 사항을 저장하는 레지스터 )

▶ DR7
- 현재 하드웨어 브레이크 포인터가 걸려 있는 상태를 저장한다.
- Low-Order Eight Bit
: 0 2 4 6 (Local) = Task 전환 시 원하지 않는 BreakPoint를 막기 위해서 자동으로 Reset 된다.
: 1 3 5 7 (Global) = 모든 Task 에서 사용되므로 Task 전환 되어도 Reset 되어지지 않는다.


 



 

반응형