Linux system call

(무선)네트워크 2009. 1. 5. 14:38 Posted by 알 수 없는 사용자


▷ 작성자 : minams (minams@a3sc.co.kr)
▷ 편집자 : minams (minams@a3sc.co.kr
 )

Linux System_call


목차

1. 사용자 공간과 커널공간
2. SYSTEM CALL
3. SYSTEM CALL 과정
4. SYSTEM CALL reference

 

1. 사용자 공간과 커널공간

8051 프로세서는 ROM의 0번지부터 차례대로 읽어가면서 정해진 대로 프로그램을 수행한다. 결국 하나의 메모리에 하나의 프로그램만 존재한다. 반면에 운영체제는 최소한 2개 이상의 프로그램이 메모리에 존재한다.(운영체제, 프로그램) 이렇게 메모리에 운영체제와 사용자 프로그램을 공존하게 하기 위한 해결책이 바로 사용자 영역과 커널 영역이다.

[그림 1-a] 사용자 공간과 커널공간 - i386 32bit(리눅스)

 


 


위와 같이 포인터연산을 잘못해서 커널공간을 침범하는 것을 막기 위해 메모리 접근을 제한 할 수 있는 권한을 부여하였다.

[그림 1-b] 특권 레벨(privilege level)

 


    (보통 운영체제에서 0, 3 두 가지 영역만 사용)

운영체제는 부팅과정 동안에 GDT(Global Descriptor Table)을 이용해 해당 레벨에 사용할 메모리 영역을 지정한다. GDT의 type필드는 코드영역(읽기/실행)인지 데이터영역(읽기/쓰기)인지 지정하고, offset필드는 접근할 수 있는 메모리의 상대범위를 나타낸다.


 

2. SYSTEM CALL

시스템 호출이란 상위레벨(커널영역)로 접근가능하게 하는 문(함수)이다.
- JMP명령으로는 서로 다른 레벨로 접근할 수 없다.
- C언어를 이용해서 프로그래밍을 할 경우 대부분의 SYSTEM CALL은 libc를통한 포장(wrapper)형태로 제공받을 수 있다.
Ex) syscall(SYS_getpid); - 직접 호출
getpid();  - libc를 통한 wrapper 형태
- 인터럽트번호 128번 사용(0x80)



3. SYSTEM CALL 과정

 사용자 프로세스에서 시스템 호출사용 - ex)open()

 Libc에서 시스템 호출 준비
 시스템 호출에 필요한 인자를 register에 저장
 인터럽트 0x80을 발생 (소프트웨어 인터럽트 = 트랩)

 SYSTEM CALL
 IDT에 의해 system call 발생
 인터럽트 서비스 루틴 실행 – system_call()

 결과값 반환 – register에 저장


 

4.  참고 사이트 및 문헌

[표 1-a] 시스템 콜 레퍼런스 - kernel 2.6 #define NR_syscalls 318

번호

함수 이름

설명

소스

1

exit()

현재 프로세스의 종료

kernel/exit.c

2

fork()

자식 프로세스의 생성

arch/i385/kernel/process.c

3

read()

파일 지정자로 부터 읽기

fs/read_write.c

4

write()

파일 지정자로 쓰기

fs/read_write.c

5

open()

파일이나 장치열기

fs/open

6

close()

파일 지정자 닫기

fs/open.c

7

waitpid()

프로세스의 종료를 기다린다

kernel/exit.c

8

creat()

파일이나 장치의 생성

fs/open.c

9

link()

파일을 위한 새로운 이름 만들기

fs/namei.c

10

unlink()

파일 혹은 참조된 이름을 삭제한다

fs/namei.c

11

execv()

프로그램의 실행

arch/i386/kernel/process.c

12

chdir()

작업디렉토리의 변경

fs/open.c

13

time()

초단위의 시간 얻기

kernel/time.h

14

mknod()

일반 혹은 특수파일의 생성

fs/namei.c

15

chmod()

파일의 권한 바구기

fs/open.c

16

chown()

파일의 소유자 변경

fs/open.c

18

stat()

파일의 상태 얻기

fs/stat.c

19

lseek()

파일에서의 위치 변경

fs/read_write.c

20

getpid()

프로세스의 ID를 얻어온다

kernel/sched.c

21

mount()

파일 시스템의 마운트

fs/super.c

22

umount()

파일 시스템 마운트 해제

fs/super.c

23

setuid()

실제 유저 아이디 설정

kernel/sys.c

24

getuid()

실제 유저 아이디 얻어오기

kernel/sched.c

25

stime()

시스템의 시간과 날짜 설정

kernel/time.c

26

ptrace()

부모프로세스가 자식프로세스의 실행을 제어하도록 허가

arch/i386/kernel/ptrace.c

27

alarm()

실정시간후 alarm시그널이 전달되도록 한다.

kernel/sched.c

28

fstat()

파일 상태 얻기

fs/stat.c

29

pause()

시그널이 전달될때까지 대기한다.

arch/i386/kernel/sys_i386.c

30

utime()

파일의 엑세스시간과 수정시간을 수정한다.

fs/open.c

33

access()

파일의 권한을 검사한다.

fs/open.c

34

nice()

프로세스의 우선순위를 번경한다.

kernel/sched.c

36

sync()

슈퍼블럭을 업데이트 한다.

fs/buffer.c

37

kill()

프로세스에 시그널을 전송한다.

kernel/signal.h

38

rename()

파일의 이름과 위치를 변경한다.

fs/namei.c

39

mkdir()

디렉토리를 생성한다.

fs/namei.c

40

rmdir()

디렉토리를 제거한다.

fs/namei.c

41

dup()

열린 파일 지정자를 복사한다.

fs/fcntl.c

42

pipe()

내부통신을 위한 채널을 생성한다.

arch/i386/kernel/sys_i386.c

43

times()

프로세스 시간을 얻는다.

kernel/sys.c

45

brk()

프로세스의 데이터 세그먼트 크기를 변경한다.

mm/mmap.c

46

setgid()

real 그룹 아이디를 설정한다.

kernel/sys.c

47

getgid()

real 그룹 아이디를 얻어온다.

kernel/sched.c

48

sys_signal()

ANSI C 시그널 제어

kernel/signal.c

49

geteuid()

effective 유저 아이디 가져오기

kernel/sched.c

50

getegid()

effective 그룹 아이디 가져오기

kernel/sched.c

51

acct()

프로세스 측정을 켜거나 끈다.

kernel/acct.c

52

umount2()

파일시스템 unmount

fs/super.c

54

ioctl()

장치 제어

fs/ioctl.c

55

fcntl()

파일 제어

fs/fcntl.c

56

mpx

사용되지 않음

 

57

setpgid()

프로세스의 그룹 아이디 설정

kernel/sys.c

58

ulimit()

사용되지 않음

 

59

olduname

구식의 uname 시스템콜

arch/i386/kernel/sys_i386.c

60

umaks()

파일 마스크의 생성

kernel/sys.c

61

chroot()

루트디렉토리의 변경

fs/open.c


 

Expression XSS

웹 어플리케이션 2008. 12. 23. 13:59 Posted by TEAMCR@K
▷ 작성자 : 박성현 컨설턴트
▷ 편집자 : 니키 (ngnicky@a3sc.co.kr)


2008년 1월 14일에 박성현 컨설턴트가 작성을 한 문서입니다. 현재는 군 복무를 하고 있습니다^^)



Expression XSS
요 약
최근 이슈가 되고 있는 XSS 취약점을 이용한 공격이 증가하고 지능화 될 수록 이에 대응하는 기술도 발전하고 있다. 예를들면, 웹 게시판에서 사용자가 악의적인 스크립트를 입력하지 못하도록 특수문자를 필터링 하거나, 특정 메소드의 키워드를 필터링 하는 경우가 대표적이다.


취약점 세부분석

1. 취약점 내용

Expression을 이용한 XSS 취약점이다. 최근 XSS를 이용하여 수많은 크래킹이 일어나고 있는데 이것을 보안하기 위해 보안하는 방법 역시 수많이 나오고 있다. 그런데 대부분 특수 키워드나 SCRIPT 사용을 금지하여 스크립트의 실행을 보안하려고 하지만 우회할 수 있는 방법이다.
HTML의 소스에 중요부분을 URL 인코딩하여 <style> 태그의 width를 이용하여 Expression에 스크립트를 실행 가능하도록 script에 대한 엘레먼트를 만들고 엘레먼트에 대한 주소를 악성JavaScript 파일로 지정하고 이 소스 부분을 인코딩하여 expression부분에 삽입을 한다.

다음은 Expression XSS 공격코드 이다.

 
다음은 exp.js 파일의 내용이다.


2. 공격 분석
HTML이나 스크립트 실행이 가능한 게시판이나 블로그에 expression을 이용한 악성 태그를 삽입 한다.


다음은 글을 쓴 후 글을 열람하게 될 경우 exp.js 파일이 실행되고 JavaScript에 담겨 있는 악성 스크립트가 실행되는 화면이다.




3. 위험 분석
대부분의 웹게시판들이 HTML이 허용 가능하게 해둘 경우 개인 사용자들의 쿠키 도용으로 인한 개인 사용자들의 개인정보나 피해가 매우 크다.


4. 취약점 내용(2)
바이두라는 중국의 구글이라는 홈페이지에서 expression을 이용한 XSS 웜이 발견되었다.해당 취약점도 위 취약점과 같은 방식이다.Expression에 주석을 이용하여 우회하는 방법을 사용하여 바이두 웜의 감염를 위하여 쿠키에 어느 특정문자열 값을 삽입하고 그 특정문자열을 이용하여 웜에 감염되었는지 확인 한 후 감염되지 않았다면 CSS 파일을 삽입하여 xmlhttprequest를 이용하여 요청을 한다.
이 웜에 감염되면 친구 등록되어 있는 사용자들에게 ajax로 사용자 모르게 임의의 글로 메일이 전송되고 사용자가 그 임의의 메일을 열람 할 경우 감염되고 사용자는 또 친구 등록되어 있는 사용자들에게 임의의 글로 메일이 ajax로 사용자 모르게 메일이 전송된다.
웜에 감염된 총 사용자들과 감염된 온라인 사용자들의 통계를 확인 할 수 있다.




관련사이트
본 취약점에 대한 추가적인 정보를 확인할 수 있는 관련 사이트는 다음과 같다.
 http://openmya.hacker.jp/hasegawa/security/expression.txt
 http://www.gnucitizen.org/xssdb/application.htm



대응 방안
XSS(Cross Site Scripting) 취약점과 동일한 대응방안이며, 아래와 같습니다.

XSS는 외부의 공격자가 정상적인 웹사이트를 악용하여 정상적인 웹사이트에 접속하려는 사용자로 하여금 공격자가 의도한 명령이나 작업을 수행하도록 하는 공격입니다. XSS를 이용한 공격 유형에는 사용자 쿠키 정보 추출을 통한 세션 가로채기 공격 등이 있습니다.
XSS 대응 방안은 사용자가 게시물을 업로드 할 수 있는 게시판의 경우와 사용자로부터 값을 입력 받는 경우로 나눌 수 있습니다.

● 사용자 게시판
운영상 필요한 경우 이외에는 사용자가 HTML을 사용하지 못하도록 하여야 합니다. 운영상 필요하여 HTML을 허용하여야 할 경우에는 스크립트 태그를 사용하지 못하도록 하여야 합니다. 사용자 태그뿐 아니라 본문에 “cookie” 나 “object”나 “document”와 특수한 문자열에 대한 체크를 하여 입력을 받지 못하도록 합니다.

● 파일의 argument로 값을 입력
HTML 태그가 입력되지 못하도록 하여야 합니다. 필터링 하여야 할 문자로는 <, >, & 등이 있고, 사용자 입력으로 원하는 값이 아닌 다른 모든 문자들을 필터링 하여야 합니다. 파일의 입력으로 받는 문자열일 경우에는 입력을 허용할 문자만을 선택하고 나머지는 필터링을 하거나 에러페이지로 이동하도록 합니다. 입력 값으로 <form>문을 작성할 때 다른 파일의 입력 값이 될 때와 같이 파일에 포함되어야만 할 때에는 입력 받은 문자는 URL Encoding을 하여 화면에 표시하도록 합니다.

● 입력 값 변환
<, >와 같은 문자들을 HTML에 표시하는 &lt; 와 &gt; 로 변환을 하여 저장을 하고 보여주는 방법이 존재합니다. 이 문자들이 HTML에서 <, >로 표시되기 때문에 화면에 나타날 때는 문제가 없습니다.


Copyright(c) 1998-2008 A3 Security ,LTD


Disclaimer
※ 현재 ㈜에이쓰리시큐리티에서 테스트 및 분석 중에 있으며, 이 문서는 계속 업데이트될 것입니다. 본 문서는 보안취약점으로 인한 피해를 최소화하는 데 도움이 되고자 작성되었으나, 본 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다.

OWASP2008_Testing 문서입니다.

보안 소식/주간 이슈 2008. 12. 22. 16:08 Posted by TEAMCR@K
http://docs.thinkfree.com/docs/popup.php?dsn=850002

OWASP2008_Testing V3.0 으로 해서 PDF파일로 배포되고 있습니다.

내용도 349쪽으로 이루어져 있고 알찹니다.

웹 어플리케이션 취약점분석을 하는데 꼭 도움이 되는 문서라고 생각되네요^^)

Anti-Reversing Code [4/4]

S/W 역공학 분석(Reversing) 2008. 12. 22. 11:19 Posted by TEAMCR@K

▷ 작성자 : Hong10 (hong10@a3sc.co.kr)
▷ 편집자 : 니키 (ngnicky@a3sc.co.kr)

문서 작성일 : 2008년 12월 19일
최종 수정일 : 2008년 12월 19일

Hong10님께서 작성하신 "Anti Reversing Code" 큰 주제를 바탕으로 4개로 나눠 작성하였습니다.



5.3 Hardware Break Point
이왕 인터럽터 나 SEH에 대해서 나온 만큼 브레이크 포인트에 대한 안티 리버싱 기술에 대하여 살펴 보겠습니다. 사실 위에서 언급한 Debugger interrupts만으로도 소프트 브레이크 포인터에 대한 탐지가 가능합니다. 물론 언급한 내용외에 코드를 체크하거나 체크섬을 검사하여 탐지를 할수 있습니다. 이번 장에서는 Hardware Break Point를 어떻게 탐지하며 우회를 할 것 인가에 대하여 다루겠습니다. 시작 하기에 앞서 먼저 디버그 레지스터리에 대한 이해가 필요합니다.

디버그 레지스터는 총 7개가 구성이 됩니다. (DR0~DR7) 또한 DR4와 DR5는 사용되 지 않고 있으며 DR0~DR3 까지는 브레이크 포인트가 걸린 주소값을 담는 용도 입니다. 그래서 하드웨어 브레이크 포인트 가 4개 밖에 존재 하지 않습니다.
이러한 하드웨어적인 방식은 DR0~DR3중 하나에 브레이크 포인트로 사용될 주소로 설정하여 준 후 DR7 레지스터에 브레이크가 발생하게 될 조건을 명시하게 됩니다. 좀더 중요한 DR7 레지스터리에 알아봅시다. 아래 출처에서 설명 되어 있어서 긁어 오듯이 설명 하겠습니다.
 


출처 http://slaxcore.tistory.com/entry/하드웨어-브레이크-포인트-탐지

DR7은 Debug Control Register 입니다. 브레이크 포인터 타입 및 활성화 여부 브레이크 포인트 길이 등이 저장 됩니다. 아래는 위 그림에서 RW/0~RW/3 의 설정값.
 



다음 그림은 LEN0~LEN3에 설정되는 브레이크 포인터 Data에 대한 길이 값이 저장됩니다.
 


또한 (L0~L3,G0~G3)은 새로운 브레이크 포인터에 대한 설정값등이 설정됩니다. 앞서 SEH에 대하여 간략하게 설명드렸습니다. 좀더 깊게 이해 하기 위하여 정덕영님의 Windows 구조와 원리 p162에 나와 있는 글로써 인용을 하겠습니다.
구조화 된 예외 처리(Structed Exception Handling)
 프로세스가 메모리와 각종 자원에 대한 구별을 가진다면 스레드는 목적한 코드를 일정시간 동안 수행하는 실행 단위로 구별할 수 있으며,각각의 스레드가 가지는 독립적인 요소중 하나는 에러 핸들러이다.
각각의 스레드는 자신이 목적하는 코드를 수행하게 되며, 만약 이코드가 수행하던 중 예외적인 상황이 발생하게 되면 운영체제와 컴파일러는 이 예외적 상황을 처리할 수 있는 기회를 스레드에게 제공 하고 있다.C나 C++와 같은 컴파일러에서는 우리에게 _try,_except,catch,thro와 같은 키워드를 제공함으로써 예외적 상황에 대해 프로그래머가 처리할 수 있는 기회를 제공해 주고 있다. 하지만 여기서 간과해서는 안되는 일은 이는 컴파일만으로는 되지 않는다는 점이다.
즉, 어떠한 스레드에서 잘못된 메모리를 참조하는 것과 같은 행위를 하게 되면 마이크로프로세서에서는 예외가 발생하게 되며,이때 이 예외를 어떻게 처리하는지는 OS가 해주어야 하는 몫이다.Windows에서는 이러한 예외가 발생하면 그 예외를 발생시킨 스레드가 그에 대한 에러 처리를 할 수 있도록 해주고 있으며,이를 구조화된 예외처리라고 부른다.

간단한 SEH 처리 과정을 코드와 더불어 설명하겠습니다.
SimpleSEH.cpp
 #include <windows.h>
ULONG G_nValid;
EXCEPTION_DISPOSITION __cdecl except_handler( //예외 처리
 struct _EXCEPTION_RECORD *ExceptionRecord,
 void *EstablisherFrame,
 struct _CONTEXT *ContextRecord,
 void *DisatcherContext
 )
{
 ContextRecord->Eax = (ULONG)&G_nValid;
 return ExceptionContinueExecution;
}
int main(int argc,char *argv[])
{
 ULONG nHandler = (ULONG)except_handler;
 PCHAR pTest = (PCHAR)0;
 __asm //SEH 설치
 {
   push nHandler //에러 핸들링을 수행할 함수 주소
   push FS:[0]
   mov FS:[0],ESP
 }
 __asm
 {
   mov eax,0
   mov [eax],'a' //SEH 발생 잘못된 메모리 참조
 }
 __asm //SEH 제거
 {
   mov eax,[ESP]
   mov FS:[0],EAX
   add esp,8
 }
 return 0;

위의 코드는 사용자가 만든 SEH핸들러에 대한 처리를 정의하고 새로운 SHE를 발생시키기 위하여 0의 주소값을 가리키게 하여 SHE를 발생 시키는 코드입니다. SEH설치 부분을 먼저 살펴 보겠습니다.
 



현재 ESP 값이 기존의 FS:[0]값으로 가리키게 됩니다.이과정은 우리가 직접 넣은 push 명령으로 넣은 데이터들은 실제 Windows에서 EXCEPTOIN_REGISTRATION_RECORD라는 구조체로 정의하고 있는 데이터입니다. 구조체의 정의는 이렇습니다.
 Typedef struct
EXCEPTIONREGISTRATIONRECORD
{
DWORD prev_structure;  //이전에 설치된 Exception handler
DWORD ExceptionHandler; //해당 에러 핸들러
}

이런식으로 싱글리스트 형태로 이전의 Exception handler가 다음의 Exception handler를 가리키게 됩니다. 다음으로는 에러 처리에 해당하는 코드를 살펴보겠습니다. 코드를 보면 에러가 발생한 시점의 Eax 값을 전역변수 G_nValid에 담아서 ExceptionContinueExcecution을 리턴하고 있습니다. 이값은 0값으로 VC헤더 파일인 EXCPT.H에 정의 되어 있습니다.

 Typedef enum _EXCEPTION_DISPOSITION{
ExceptionContinueExcution, //0
ExceptionContinueSearch, //1
ExceptionNestedException,//2
ExceptoinCollidedUnwind//3
}


이러한 값은 악성 코드들에 많이 이용 됩니다. 보통 악성코드들은 앞서 살펴본 디버거 레지스터리 값을 바꿀 때 사용되어 지는 ContextRecord 을 이용하여 디버거 레지스트리의 값을 바꾸어 여러가지에 응용하며 또한 ExceptionContinuExecution(0) 값을 리턴함으로써 에러가 발생할 당시의 Register을 바꾸어 줄 수 있는데 보통  EIP 값을 수정하여 에러가 발생한 시점에 악성코드를 실행한 뒤(exception handler) EIP를 수정하여 보통의 OEP를 가장하는 기법을 이용합니다.
(실제로 디버거를 이용하여 디버깅을 할 때 OEP) 다음은 구조체 CONTEXT의 일부인 디버거 레지스터리(Context Record 구조체중 디버거 레지스터리)를 정의 하고 있는 부분입니다.
 



Hardware Break Point 탐지에 필요한 개념을 이해 하였으면 아래의 코드로 어떻게 탐지를 할수 있는지 애기를 해보겠습니다.

 .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

      include c:\masm32\include\windows.inc
      include c:\masm32\include\user32.inc
      include c:\masm32\include\kernel32.inc

      includelib c:\masm32\lib\user32.lib
      includelib c:\masm32\lib\kernel32.lib

    .data
       KoreaSecurity db "Korea Security",0h
       Protect db "보호하고 싶은가?",0h
       DbgNotFoundTitle db "Debugger status:",0h
       DbgFoundTitle db "Debugger status:",0h
       DbgNotFoundText db "Debugger hardware bpx not found!",0h
       DbgFoundText db "Debugger hardware bpx found!",0h
    .data?
OrgEbp   dd ?
OrgEsp   dd ?
SaveEip  dd ?
    .code
start:
; Setup SEH
MOV EAX,offset @Exit
MOV DWORD PTR[OrgEbp],EAX ;EAX에 @Exit함수주소를 담고 있음
MOV DWORD PTR[SaveEip],EBP; 현재 EBP를 SaveEip라고 담고 있음.
ASSUME FS : NOTHING

PUSH offset @DetectHardwareBPX ;Exception handler
PUSH FS:[0]
MOV DWORD PTR[OrgEsp],ESP ;현재 스택을 OrgEsp에 담고 있음.
MOV  FS:[0], ESP  ; 위에서 설명한 과정

; Fire SEH
XOR EAX,EAX ;EAX값을 0 초기화
XCHG DWORD PTR DS:[EAX],EAX ;0이라는 주소값 참조 exception발생
CALL @Protected;Hardware Break Point 로부터 보호 하고 싶은 영역
@Exit:
POP FS:[0]
ADD ESP,4
PUSH 0
CALL ExitProcess
@Protected:
  PUSH 30h
  PUSH offset KoreaSecurity
  PUSH offset Protect
  PUSH 0
  CALL MessageBox
@DetectHardwareBPX:
PUSH EBP;핸들러가 발생할 때 의 처리
MOV EBP,ESP
MOV EAX,DWORD PTR SS:[EBP+10h] ;Context Record값 세번째인자
; Restore ESP, EBP, EIP

MOV EBX,DWORD PTR[OrgEbp] ;@exit 함수 주소
MOV DWORD PTR DS:[EAX+0B8h],EBX;Context Record의 Ebp값
MOV EBX,DWORD PTR[OrgEsp];fs[0]과 esp가 바뀌기전의 esp값
MOV DWORD PTR DS:[EAX+0C4h],EBX;Context Record의 esp값
MOV EBX,DWORD PTR[SaveEip];
MOV DWORD PTR DS:[EAX+0B4h],EBX;context Record의 eip값

; Check DRx registers

CMP DWORD PTR DS:[EAX+4h],0
JNE @hardware_bpx_found
CMP DWORD PTR DS:[EAX+8h],0
JNE @hardware_bpx_found
CMP DWORD PTR DS:[EAX+0Ch],0
JNE @hardware_bpx_found
CMP DWORD PTR DS:[EAX+10h],0
JNE @hardware_bpx_found
PUSH 40h
PUSH offset DbgNotFoundTitle
PUSH offset DbgNotFoundText
PUSH 0
CALL MessageBox
  @hbpx_exit:
MOV EAX,0 ;위에서 설명한 ExceptionContinuExecution(0) 값
LEAVE
RET
  @hardware_bpx_found:
PUSH 30h
PUSH offset DbgFoundTitle
PUSH offset DbgFoundText
PUSH 0
CALL MessageBox
JMP @hbpx_exit

end start


다소 이때까지 본 코드보다는 길어 보이지만 복잡하지는 않다.앞전에 설명한대로 SHE를 설치하고 SEH처리에서는 디버거 레지스터리를 검사하며 Context Record값중 ebp,esp,eip를 변경하여 다시금 변경된 레지스티리 값을 복구하는 과정이다.
이를 올리로 본 화면은 이렇다. 아래 그림에서 보다시피 보호 하고 싶은 영역에 하드웨어 브레이크 포인트를 설정하였다. 확인하는 방법은 올리에서 Debug  Hardware Breakpoints를 선택하면 된다.


5.4 Hardware Break Point 우회
앞선 설명을 다 이해 했다면 우회하는 방법은 간단합니다.디버깅 체크루틴에서 강제적으로 디버거 레지스터리 값을 0으로 만들어 주거나 혹은 Exception을 유발 시키는 코드에 대해서 NOP을 처리해 해당 루틴이 실행하지 않도록 합니다.혹은 올리 플러그인중 PhantOm 이라는 것을 이용해 Drx 체크옵션을 주면 우회(PhantOm 플러그인을 이용한 우회)를 합니다.
 


다음은 Protect 영역에 Hardware break Point 부분입니다.



F9를 눌러 run을 하여 보자. Hardware break Point 발견을 한 부분 입니다.
 



6.1 Garbage Code & JunkCode
지금부터 설명한 안티 리버싱 방법은 앞선 기술과 달리 리버서들을 심리적으로 짜증나고 지치게 만드는 기법입니다. 단지 보호 될 코드를 분석할 때 시간을 끄는 용도로 사용됩니다. 두 개념은 다소 다른 의미를 지니고 있습니다. 먼저 Garbage코드는 코드중간에 의미없는 코드들을 집어 넣어 리버서들의 집중력(?) 과 혼란을 가중 시켜 버리며 Junkcode는 가령 디버거는 코드를 디어셈 할 때 정의된 OPCODE에 의해 디어셈을 화면에 DISPLAY합니다. 그
것을 착안하여 실행하지 않도록 하는 OPCODE를 중간에 넣으므로써 전혀 엉뚱한 디어셈 코드를 출력함으로써 리버서를 방해 합니다. 앞서 작성한 SHE를 유발 시키는 코드를 보호될 코드 영역으로 정하고 Garbage 코드를 삽입 해 올리로 살펴보겠습니다.

 보호되어야 할 코드
XOR EAX,EAX
XCHG DWORD PTR DS:[EAX],EAX

위와 같은 코드가 보호 되어야 할 것이라면 중간에 Garbage코드(프로그램에 상관없이 의미 없는 코드)를 삽입 합니다.
 Garbage코드 삽입
PUSH EAX
MOV EBX,3
POP EAX
SUB EBX,3
XOR EAX,EAX
MOV EAX,0DEADh
SHR EAX,4
XCHG DWORD PTR DS:[EAX],EAX

간단하게 적용한 모습입니다. 물론 저정도 코드는 중간에 삽입된게 의미가 없다는걸 한눈에 알아 볼수 있지만 이러한 코드들이 무더기로 중간중간에 삽입이 되어 있다면 골치가 아플 것입니다.

다음은 ollydbg에서 Garbage코드가 삽입된 화면을 보여주고 있습니다.

 
다음은 Junk Code를 삽입 하여 보겠습니다. 여기에 해당하는 내용은 제스리버님의 홈페이지의 테스트를 참고로 하였습니다. 코드는 아래와 같습니다.

 #include <windows.h>

int main(int argc,char *argv[])
{
 __asm
 {
  jmp here+1;
  here:
   __emit 0xe9//__emit은 뒤에 바이트를 코드에 포함
  mov eax,1
 }
 return 0;
}



코드를 보면 중간에 박아서 디버거가 제대로된 코드를 뿌려주지 못하도록 하고 있습니다.

다음은 ollydbg로 junk code 삽입된것을 확인한 화면입니다.

 

MOV EAX,1 디어셈 코드는 온데 간데 보이질 않고 덩그러니 JMP코드가 자리 잡고 있습니다. 그런데 JMP하는 주소값이 이상하네요.머 저정도야 금방 눈치채겠지만 그래도 모르는 상태에서 본다면 다소 의아해 할 것 입니다. 해당 옵코드 0xe9 를 0x90(NOP)으로 처리한다면 원래 OP CODE인 mov eax,1을 복원 할 수 있습니다. 다음은 해당 코드를 복원 한 모습입니다. NOP으로 바꾼뒤 올리에서 Ctrl+a 혹은 마우스 우클릭시 Analysis  Alnalse code 을 클릭하면 OPCODE를 재분석 하게 됩니다.

다음은 Junk Code 패치한 화면입니다. 




여기까지 "Anti-Reversing Code" 에 대한 설명을 마치겠습니다.^^)


참고사이트 및 문서
EDIT PLUS 를 이용한 MASM 환경 구축
http://mysilpir.net/entry/EditPlus-Assembly-%EC%84%A4%EC%A0%95-MASM
ANTI REVERSE
http://zesrever.xstone.org/
http://slaxcore.tistory.com
http://beist.org/research/public/artofunpacking/artofunpacking.pdf
http://openrce.org
정덕영님의 윈도우 구조와 원리
THX to zersrever,slaxcore,ashine,ap0x,정덕영FROM Hong10


Copyright(c) 1998-2008 A3 Security ,LTD


Disclaimer
※ 현재 ㈜에이쓰리시큐리티에서 테스트 및 분석 중에 있으며, 이 문서는 계속 업데이트될 것입니다. 본 문서는 보안취약점으로 인한 피해를 최소화하는 데 도움이 되고자 작성되었으나, 본 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다.

Anti-Reversing Code [3/4]

S/W 역공학 분석(Reversing) 2008. 12. 22. 11:00 Posted by TEAMCR@K
▷ 작성자 : Hong10 (hong10@a3sc.co.kr)
▷ 편집자 : 니키 (ngnicky@a3sc.co.kr)

문서 작성일 : 2008년 12월 19일
최종 수정일 : 2008년 12월 19일

Hong10님께서 작성하신 "Anti Reversing Code" 큰 주제를 바탕으로 4개로 나눠 작성하였습니다.


2.1 PEB.NtGlobalFlag
PEB은 BeingDebugged 플래그 외에도, PEB는 NtGlobalFlag라는 필드를 갖고 있는데 NtGlobalFlag는 PEB으로부터 0x68 위치에 존재합니다. LiveKD를 이용하여 PEB의 구조체 값을 확인 해보았습니다.
 


이 플러그인의 값은 디버깅 중이 아니라면 0x0 값이 담기지만 디버깅 중이라면 0x70 값이 담겨 집니다. 그와 같은 것을 이용하여 디버깅 탐지를 합니다.

다음은 NtGlobalFlag Code 부분입니다.

 .386
.model flat, stdcall
option casemap :none   ; case sensitive

include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

.data
DbgNotFoundTitle db "Debugger status:",0h
DbgFoundTitle db "Debugger status:",0h
DbgNotFoundText db "Debugger not found!",0h
DbgFoundText db "Debugger found!",0h
.code
start:

ASSUME FS:NOTHING
MOV EAX,DWORD PTR FS:[30h]
ADD EAX,68h
MOV EAX,DWORD PTR DS:[EAX]
CMP EAX,70h
JE @DebuggerDetected

PUSH 40h
PUSH offset DbgNotFoundTitle
PUSH offset DbgNotFoundText
PUSH 0
CALL MessageBox

JMP @exit
@DebuggerDetected:

PUSH 30h
PUSH offset DbgFoundTitle
PUSH offset DbgFoundText
PUSH 0
CALL MessageBox

@exit:

PUSH 0
CALL ExitProcess

end start




여기서 ASSUME FS:NOTHING 이란 구문은 세그먼트 레지스트의 주소값을 재할당 하는 것이 아니라 이 디렉티브를 맞나면 실행 시에 어셈블러가 주소를 계산하는 방법을 변경한다. 즉 FS 세그먼트에 NOTHING이라는 속성을 붙이는 의미이다.
해당 내용을 더 깊에 알아 보았는데 다음과 같은 사이트에서 친철히 설명 해주고 있었다.
http://www.winasm.net/forum/index.php?showtopic=2082

간단히 축약해서 애기하자면(맞는 애기인지도 모르겠다,필자의 영어실력은 가히 밑바닥 수준이라서…) FS:[0] 은 Exception handler를 Default를 가지고 있다. MASM 컴파일러는 기본적으로 이 레지스터를 사용할 때 ERORR를 뱉기 때문에 위와 같이 ASSUM FS:NOTHING 을 써주면 그와 같은 ERORR Check를 Remove 해준다고 설명이 되어 있다.

다음으로FS:[30] 는 PEB의 위치에서 ADD EAX,68h 에는 NtGlobalFlag 가 존재한다. 해당 코드를 올리로 열어 보았다.
 

Olly 로 확인한 NtGlobalFlag 루틴

2.2 NtGlobalFlag 우회
해당 탐지를 우회는 간단하다. 직접 코드 패치를 하여 바꾸 거나 혹은 플래그 값을 수정하거나 이다. 하지만 이것도 역시 올리에서 플러그인 형태로 지원을 하고 있다. 다음 사이트에서 다운로드 하여 쓰시면 됩니다.
http://www.openrce.org/downloads/details/241/Olly_Advanced

해당 플러그 인을 실행하고 NtGlobalFlag 를 체크 뒤 확인 해주면 자동적으로 리턴시 플래그 값을 수정하여 디버거 탐지를 우회 하게 됩니다. 그 외 코드 패치 등 다양한 방법 이 존재 합니다. 툴로써 좀 더 편하게 하는게 좋겠죠 ??;
 
다음은 Olly Advanced NtGlobalFlag 입니다.



3.1 Heap.HeapFlag , Heap.ForceFlags
ProcessHeap 은 PEB 에서 0x18 만큼 떨어져 있고 이 플래그는 프로세서가 디버깅 될 때 heap 이 만들어 지고 이때 설정 되는 플래그들은 HeapFlag와 ForceFlas 입니다. 처음 프로그램이 힙 영역을 만들면 ForceFlags 에는 0x0 값이 HeapFlag 에는 0x2 값이 설정 됩니다. 하지만 디버깅 중이라면 NtGlobalFlag 에 따라 두개의 플래그 값이 변경 됩니다.
만약 디버깅이 탐지 되어 변경 되었다면 FoceFlags에는 0x40000060값이 할당 되며 HeapFlag 에는 0x50000062 값이 할당 됩니다.이때 변경된 값을 체크 하므로써 디버깅의 유무를 판별합니다.

다음은 PEB 의 ProcessHeap 구조체 offset 입니다.


여기서 ProcessHeap의 구조체 를 살펴보면 언급한 두개의 값들이 존재합니다.



다음은 Process_Heap Code 부분입니다.

 .386
.model flat, stdcall
option casemap :none   ; case sensitive

include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\kernel32.inc

includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

.data
DbgNotFoundTitle db "Debugger status:",0h
DbgFoundTitle db "Debugger status:",0h
DbgNotFoundText db "Debugger not found!",0h
DbgFoundText db "Debugger found!",0h
.code

start:

ASSUME FS:NOTHING
MOV EAX,DWORD PTR FS:[18h] ;TEB
MOV EAX,DWORD PTR [EAX+30h] ;PEB
MOV EAX,DWORD PTR[EAX+18h] ;Process_Heap
CMP DWORD PTR DS:[EAX+10h],0 ;Force_Flags
JNE @DebuggerDetected

MOV EAX,DWORD PTR FS:[18h] ;TEB
MOV EAX,DWORD PTR [EAX+30h] ;PEB
MOV EAX,DWORD PTR[EAX+18h] ;Process_Heap
CMP DWORD PTR DS:[EAX+0ch],2 ;Force_Flags
JNE @DebuggerDetected

PUSH 40h
PUSH offset DbgNotFoundTitle
PUSH offset DbgNotFoundText
PUSH 0
CALL MessageBox

JMP @exit
@DebuggerDetected:

PUSH 30h
PUSH offset DbgFoundTitle
PUSH offset DbgFoundText
PUSH 0
CALL MessageBox

@exit:

PUSH 0
CALL ExitProcess

end start


3.2 Heap.HeapFlag , Heap.ForceFlags 우회
역시 앞선 방법과 동일 하게 코드 패치 및 플래그 변조로 우회를 할수 있다. 또는 올리 플러그인 OllyAdvanced 를 이용하면 쉽게 플래그 값을 자동으로 수정 해준다.
 
다음은 Olly Advanced HeapFlag,ForceFlags 우회 부분입니다.




4.1 NtQueryInformationProcess
CheckRemoteDebuggerPresent API는 디버거가 프로세서를 attach 하는 것을 감지합니다. 이 API 는 내부적으로 NtQueryInformationProcess를 호출합니다.이 함수는 또한 내부적으로 커널 구조체인 EPROCESS의 DebugPort 플래그를 검사합니다. 가령 유저 모드 디버거가 프로세서를 attach 한 상태이면 DebugPort 플래그 값은 0이 아닌값으로 설정이 됩니다.
앞서 저희는 PEB에 대해 간략하게 알아 봤습니다. PEB은 유저모드 레벨 프로세스에 대한 추가 정보 이며 여기서 설명하는 EPROCESS는 커널에서 프로세스를 관리하기 위해 사용하는 구조체 정도가 되겠습니다. 또한 NtQueryInformationProcess 을 내부적으로 불러 낼때에는 인자 값중 ProcessInformation 값은 7이 됩니다.
또한 DebugPort의 오프셋은 0x120 위치에 존재하며 유저모드 에서 디버깅 중이라면 NtQueryInformationProcess 함수의 인자 값중 hProcess는 0xfffffff 값이 되며 그렇지 않을 경우에는 0이라는 값이 담기게 됩니다

다음은 NtQueryInformationProcess Code 부분입니다.

 .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

      include c:\masm32\include\windows.inc
      include c:\masm32\include\user32.inc
      include c:\masm32\include\kernel32.inc

      includelib c:\masm32\lib\user32.lib
      includelib c:\masm32\lib\kernel32.lib

    .data
       DbgNotFoundTitle db "Debugger status:",0h
       DbgFoundTitle db "Debugger status:",0h
       DbgNotFoundText db "Debugger not found!",0h
       DbgFoundText db "Debugger found!",0h
       ntdll db "ntdll.dll",0h
       zwqip db "NtQueryInformationProcess",0h
    .data?
       NtAddr dd ?
       MinusOne dd ?
    .code

start:

MOV [MinusOne],0FFFFFFFFh

PUSH offset ntdll ;ntdll.dll
CALL LoadLibrary

PUSH offset zwqip ;NtQueryInformationProcess
PUSH EAX
CALL GetProcAddress

MOV [NtAddr],EAX

MOV EAX,offset MinusOne
PUSH EAX
MOV EBX,ESP

PUSH 0
PUSH 4
PUSH EBX
PUSH 7
PUSH DWORD PTR[EAX]
CALL [NtAddr]

POP EAX

TEST EAX,EAX
JNE @DebuggerDetected

PUSH 40h
PUSH offset DbgNotFoundTitle
PUSH offset DbgNotFoundText
PUSH 0
CALL MessageBox

JMP @exit
  @DebuggerDetected:

PUSH 30h
PUSH offset DbgFoundTitle
PUSH offset DbgFoundText
PUSH 0
CALL MessageBox

  @exit:

PUSH 0
CALL ExitProcess

end start



위의 코드에서 ? 는 아마 변수를 선언할 때 값을 할당하지 않은 상태일꺼라 생각이 듭니다. 어째든 위의 코드에서 커널 API를 수행하기 위해서 LoadLibrary와 GetProcAddress를 이용하여 해당 함수 주소를 얻은뒤 앞서 설명한 인자값을 토대로 호출 하고 디버깅 중이라면 리턴되는 값을 체크하여 디버거 존재 유무를 판별 하고 있습니다.

다음 그림은 위의 코드를 Olly에서 확인한 장면(NtQueryInformationProcess in Olly)입니다.
 


그림에서 알수 있듯이 인자 값이 저런식으로 들어가 호출하게 되어야지 디버깅 체크를 할수 있습니다.


4.2 NtQueryInformationProces 우회
이 방법을 우회하는 방법 역시 여러가지가 존재 할수 있습니다. 다만 올리 플러그 인중 Olly Advanced 는 NtQueryInformationProcess 의 인자 값중 하나인 hProcess를 0으로 만듬으로써 해당 루틴을 우회하게 될꺼라고 생각했으나 잘 안되는군요. 일단은 그냥 주 루틴이 나오면 리턴되는 부분에 EAX값을 0을 설정하면 우회가 됩니다.
 



5.1 Debugger Interrupts

이 방법은 디버거가 하나의 소프트 브레이크 포인트를 수행하려고 할 때 INT3(0xcc)를 삽입 함으로 써 수행이된다. 인터럽터 가 수행이 된다는 말은 즉 예외처리가 일어 난다는 의미이다. 하지만 디버거가 디버깅 수행중 일 때 같은 OP 코드인 INT3을 만난 다면 예외 처리없이 수행을 하게된다.
이 Debugger Interrupts는 바로 이러한 것을 착안하여 안티 디버깅을 수행한다. 즉 Interrupt 수행중에 같은 인터럽터 코드를 만났을 때 exception을 하지 않는 경우를 디버깅 중이라고 판별하게 된다. 좀더 유연한 이해를 위해 아래 코드를 참고 한다.

다음은 Debugger Interrupts 부분입니다.

 .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

      include c:\masm32\include\windows.inc
      include c:\masm32\include\user32.inc
      include c:\masm32\include\kernel32.inc

      includelib c:\masm32\lib\user32.lib
      includelib c:\masm32\lib\kernel32.lib

    .data
msgTitle db "Execution status:",0h
msgText1 db "No debugger detected!",0h
msgText2 db "Debugger detected!",0h
    .code

start:

ASSUME FS:NOTHING
PUSH offset @Check
PUSH FS:[0]
MOV FS:[0],ESP

; Exception
INT 3h

PUSH 30h
PUSH offset msgTitle
PUSH offset msgText2
PUSH 0
CALL MessageBox

PUSH 0
CALL ExitProcess

; SEH handleing
@Check:
POP FS:[0]
ADD ESP,4

PUSH 40h
PUSH offset msgTitle
PUSH offset msgText1
PUSH 0
CALL MessageBox

PUSH 0
CALL ExitProcess

end start


위에 코드에서 @Check는 exception이 일어 날 때 등록되는 SEH 이다. INT 3이 수행될 때 익셉션이 일어 나지 않는다면 Debuger dectect 메시지가 출력 될것이다.다음은 올리(Debugger Interrupt in Olly)에서 살펴본 모습이다.

 


저기에서 INT3을 유심히 살펴 보면 저기가 분기문이라고 이해하시는 편이 더 수월 할수도 있습니다 INT3이 exception을 일으킨다면 0x0040103e로 향하게 될것이며 그렇지 않을경우 0x00401024코드로 향하게 될것입니다.


5.2 Debug Interrupts 우회
우회 방법은 간단합니다. 올리에서 디버깅 옵션에 보면 INT 3 을 만났을 때 무시하지 않고 SEH를 following 하라는 옵션을 선택하여 줍니다.




다음과 같이 우회를 하게 된다면 Exception Handle로 빠지는 루틴(Exception Handle 을 호출하는 루틴)을 보실수 있습니다.



[계속...]

참고사이트 및 문서
EDIT PLUS 를 이용한 MASM 환경 구축
http://mysilpir.net/entry/EditPlus-Assembly-%EC%84%A4%EC%A0%95-MASM
ANTI REVERSE
http://zesrever.xstone.org/
http://slaxcore.tistory.com
http://beist.org/research/public/artofunpacking/artofunpacking.pdf
http://openrce.org
정덕영님의 윈도우 구조와 원리
THX to zersrever,slaxcore,ashine,ap0x,정덕영FROM Hong10


Copyright(c) 1998-2008 A3 Security ,LTD


Disclaimer
※ 현재 ㈜에이쓰리시큐리티에서 테스트 및 분석 중에 있으며, 이 문서는 계속 업데이트될 것입니다. 본 문서는 보안취약점으로 인한 피해를 최소화하는 데 도움이 되고자 작성되었으나, 본 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다.