본문으로 바로가기

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

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

1. 리버싱 소개


1) 연산자


▣ PUSHAD

- Stack에 범용레지스터 8개의 값을 push함. (주로 백업용도)

- 순서 : EAX -> ECX -> EDX -> EBX -> ESP -> EBP -> ESI -> EDI

#include <stdio.h>

int main()
{
	int a = 1;

	_asm
	{
		pushad
	}

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

- 실행이 되지 않음.    

☞ push&pop 처럼 pushad 한만큼 8개의 값을 pop 해줘야함. (popad)


▣ POPAD

- Stack 안에 있는 8개의 범용레지스터 값을 거꾸로 빼와서 범용레지스터에 저장. (stack -> 범용레지스터)

#include <stdio.h>

int main()
{
	int a = 1;

	_asm
	{
		popad
	}

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

- 이 또한 실행되지 않음.

#include <stdio.h>

int main()
{
	int a = 1;

	_asm
	{
		pushad
		popad
	}

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

- 이렇게 같이 사용해야 돌아감.


[주의사항]

: pushad 이후 스택을 사용하게 되면 pop할 때 그 순서가 뒤바뀔 수 있음. 

☞ 순서대로 범용레지스터 값들이 저장되어있을 때 push 명령어등으로 새로운 값을 stack에 저장하게 되면

   popad를 하게 됐을 때 값이 밀려서 저장이 될 수 있음.

EDI

 내가 push 한 값

ESI

 EDI

EBP

 ESI

 ...

 ...


▣ PTR

- 데이터타입 재정의 (like c언어 캐스팅 연산자)

- usage : [데이터타입] PTR ([데이터타입] : BYTE, WORD, DWORD)

#include <stdio.h>

int main()
{
	int a = 1;

	printf("%X\n", a);

	_asm
	{
		mov word ptr a, 0x11111111
	}

	printf("%X\n", a);

	_asm
	{
		mov dword ptr a, 0x11111111
	}

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

- 실행 결과

- 설명

☞ 11줄 : a를 2바이트로 취급, 뒤의 2바이트만 대입이 됨. (a : 00 00 11 11)

☞ 18줄 : a를 4바이트로 취급, 4바이트 대입이 됨. (a : 11 11 11 11)


▣ OFFSET

- Data 영역에 있는 전역변수의 주소를 가져옴.

- usage : OFFSET op1 (op1은 전역변수이고 주소를 가져옴)

#include <stdio.h>

int global = 30;

int main()
{
	int addr = 0;
	int value = 0;
	
	_asm
	{
		mov eax, offset global
		mov addr, eax

		mov ebx, [eax]
		mov value, ebx
	}

	printf("addr  : %p\n", addr);
	printf("value : %d\n", value);

	return 0;
}

- 실행 결과

- 설명

☞ 12줄 : 전역변수 global의 주소를 EAX에 저장.

☞ 15줄 : EAX를 주소로 취급하고 EAX가 가리키는 주소에 있는 값을 EBX에 저장.


▣ LEA (Load Effective Address)

- usage : LEA op1 , op2

- op2(지역변수, 전역변수)의 메모리 절대주소를 op1에 저장.

☞ mov는 op1에 레지스터 뿐만아니라 다른 지역변수나 전역변수 모두 가능

LEA reg, mem

#include <stdio.h>

int main()
{
	int a = 4;
	
	printf("%.8X\n", a);
	printf("%.8X\n", &a);

	_asm
	{
		mov eax, [ebp - 0x04]
		mov a, eax
	}

	printf("%.8X\n", a);

	_asm
	{
		lea eax, [ebp - 0x04]
		mov a, eax
	}

	printf("%.8X\n", a);

	return 0;
}


▣ STOS (Store String)

- EDI가 가리키는 주소에 EAX 값을 저장. 

☞ 반드시 EDI에는 주소값, EAX에는 어떠한 값이 저장되어 있어야함.

- 복사한 크기만큼 EDI값 증가

- REP 명령어랑 같이 연속된 저장공간(=배열)을 초기화할 때 사용됨.

STOS mem

#include <stdio.h>

int main()
{
	char buffer[20];

	_asm
	{
		mov eax, 0x61
		lea edi, dword ptr [buffer]
		stos dword ptr [edi]
	}

	printf("%s\n", buffer);

	return 0;
}

- 실행 결과

- 설명

☞ 10줄 : buffer 변수의 주소를 4바이트 데이터타입으로 전환시킨 후 EDI에 저장.

☞ 11줄 : 현재 EDI에 저장된 주소는 buffer의 주소. EAX에 있는 값은 0x61('a')임.


▣ REP (Repeat String Operation)

- String 관련 명령어를 반복시킴. (STOS, MOVS, SCAS)

- 반복횟수 카운터로 ECX를 사용.

☞ 한 번 반복할 때 마다 ECX를 1씩 감소시키며 0이 되면 반복을 종료.

#include <stdio.h>

int main()
{
	char buffer[20];

	_asm
	{
		mov eax, 0x61
		lea edi, dword ptr [buffer]
		mov ecx, 0x05
		rep stos dword ptr [edi]
	}

	printf("%s\n", buffer);

	return 0;
}

- 반복 종료 후 EDI 값은 처음 값보다 +5가 되어있음.






i2sec 대구지점 23기 수료생.

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

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