본문으로 바로가기

[D+2] 리버싱 소개 (2)

category 해킹&보안/리버싱 2017. 3. 22. 22:51
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. 리버싱 소개


2) 레지스터


▣ 레지스터 종류

(1) EFLAGS 

- 전체가 하나의 값으로 취급되는게 아닌 비트별로 의미가 존재

- 32 bit 저장공간이 32개의 서로 다른 flag로 사용됨 (0 : clear / 1 : set)


1. ZF (Zero Flag)

- 조건문에서 많이 쓰임.

- 연산결과가 0이나오면 flag값이 set. (1)

- 연산결과가 1이 나오면 flag값이 clear. (0)


2. SF (Sign Flag)

- 음수일 때 set, 양수일 때 clear (MSB 생각하면 됨)


3. AF ~ OF : 연산에 사용됨. 연산범위를 넘어섰을 때 set.

① CF (Carry Flag) : 부호없는 연산으로 판단 (unsigned)

② OF (Overflow Flag) : 부호있는 연산으로 판단 (signed)

signed -128 ~ 127

unsigned 0 ~ 255

* 0-1 = -1  -> CF : set, OF : clear

* 128 + 1   -> CF : clear, OF : set

③ AF (Adjust Flag) = half flag


3) 어셈블리 언어


▣ 데이터 형식

 데이터 타입

사용 용도 

BYTE 

부호 없는 1byte

WORD 

부호 없는 2byte

DWORD 

부호 없는 4byte 


▣ 어셈블리 언어

- 어셈블리 표현법 : IA32 (Intel Architecture)->a=1 , AT&T->1=a

- 모든 opcode는 자신이 가지는 operand의 개수와 종류가 모두 정해져있음. (fixed)

표시 기호

설명 

mem

메모리

label

지정된 레이블

imm

즉시 값 (상수)

reg

범용 레지스터

- label : 메모리상의 주소에 이름(꼬리표)를 붙여줌. 가상의 개념. 코드의 주소를 직접 쓰기에는 불편해서.


4) 연산자


▣ INC (Increase)

- operand를 1만큼 증가. (operand는 딱 1개)

INC reg

ex) INC EAX

INC mem

ex) INC [EBP-0x04]

#include <stdio.h>

int main()
{
	int a = 0;
	printf("%d\n", a);

	_asm
	{
		inc a
		inc a
	}

	printf("%d\n", a);
	return 0;
}

- _asm{} : 인라인 어셈. 상위레벨인 c언어 상에서 하위레벨인 어셈블리어를 쓸 수 있게 해줌. (대소문자 구분x)

- 실행 결과

▣ DEC (Decrease)

- operand를 1만큼 감소

DEC reg

ex) INC EAX

DEC mem

ex) INC [EBP-0x04]

#include <stdio.h>

int main()
{
	int a = 2;
	printf("%d\n", a);

	_asm
	{
		dec a
		dec a
	}

	printf("%d\n", a);
	return 0;
}


▣ ADD, SUB

- operand가 2개 필요.

- ADD/SUB op1, op2 (op1 +- op2 값을 op1에 저장)

- 크기지정해줘야함. 안하면 나머지 한쪽에 맞춰짐. 

- operand 2개의 크기가 서로 맞지 않으면 컴파일 에러가 남.

ex) add [ebp-4], eax    ->    [ebp-4] : 4바이트로 맞춰짐.

ex) add [ebp-4],  ax    ->    [ebp-4] : 2바이트로 맞춰짐.

ADD reg, reg

ex) ADD EAX, EBX

ADD reg, mem

ex) ADD EAX, [EBP-0x04]

ADD mem, reg

ex) ADD [EBP-0x04], EAX

ADD mem, imm

ex) ADD [EBP-0x04], 0x05

ADD reg, imm

ex) ADD EAX, 0x05

#include <stdio.h>

int main()
{
	int a = 0;
	printf("%d\n", a);

	_asm
	{
		add a, 0x05
		sub a, 0x03
	}

	printf("%d\n", a);
	return 0;
}


▣ MOV

- operand가 2개 필요

- MOV op1, op2 (op2의 값을 op1에 대입)    

MOV reg, reg

ex) MOV EAX, EBX

MOV reg, mem

ex) MOV EAX, [EBP-0x04]

MOV mem, reg

ex) MOV [EBP-0x04], EAX

MOV mem, imm

ex) MOV [EBP-0x04], 0x05

MOV reg, imm

ex) MOV EAX, 0x05


- 왜 MOV mem, mem 은 없음?

☞ operand를 2개를 가지는 모든 opcode에서 불가능!!

☞ mov a, b (x) : 레지스터에 b 값 넣어두고 다시 그 값을 a에 넣고 해야함.. 귀찮..

- 사람과 컴파일러가 짠 어셈블리어는 티가나게 다름.

☞ 컴파일러는 연산을 무조건 레지스터로 옮긴후에 해야한다는 원칙이 존재하기 때문.





i2sec 대구지점 23기 수료생.

'해킹&보안 > 리버싱' 카테고리의 다른 글

[D+6] 리버싱 소개 (6)  (0) 2017.03.28
[D+5] 리버싱 소개 (5)  (0) 2017.03.27
[D+4] 리버싱 소개 (4)  (0) 2017.03.26
[D+3] 리버싱 소개 (3)  (0) 2017.03.23
[D+1] 리버싱 소개 (1)  (0) 2017.03.21