__cdecl과 __stdcall의 차이점

__cdecl과 __stdcall의 가장 큰 차이점은 스택 정리 주체가 누구인가하는 점인데 사실 이 차이점이 컴파일된 결과 코드에 미치는 영향은 별로 없다. 스택 정리 주체와는 상관없이 스택은 항상 호출 전의 상태로 복구되며 프로그램의 동작도 완전히 동일하다. 실행 속도는 거의 차이가 없으며 프로그램의 크기는 비록 무시할만한 수준이기는 하지만 __stdcall이 조금 더 작다. 왜냐하면 함수를 여러 번 호출하더라도 스택을 정리하는 코드는 함수 끝의 접미에 딱 한 번만 작성되기 때문이다. 반면 __cdecl은 호출원이 스택을 정리하므로 호출할 때마다 정리 코드가 반복되어 프로그램 크기가 조금 더 커진다.



또 다른 중요한 차이점은 가변 인수 함수를 만들 수 있는가 아닌가 하는 점이다
. __stdcall은 함수가 직접 스택을 정리하기 때문에 가변 인수 함수를 지원하지 않는다. 함수 접미에 스택 정리 코드를 작성하려면 인수의 총 크기를 미리 알아야 하는데 가변 인수 함수는 전달되는 인수 개수가 가변이므로 이 크기가 고정적이지 않아 접미에서 스택을 직접 정리할 수 없다. 컴파일러가 접미의 ret n 명령에 대해 n을 결정할 수 없는 것이다.

이에 비해
__cdecl은 함수가 스택을 정리할 책임이 없으며 호출원이 함수를 부를 때마다 스택을 정리한다. 함수를 호출하는 쪽에서는 인수를 몇개나 전달했는지 알 수 있으므로 실제 전달한 인수 크기만큼 스택을 정리할 수 있다. 그래서 printf나 scanf같은 가변 인수를 지원하는 함수는 모두 __cdecl 호출 규약을 사용한다. 또한 윈도우즈 API 함수의 기본 호출 규약은 __stdcall이지만 wsprintf는 예외적으로 __cdecl로 작성되어 있다.

호출 규약 중 호출원이 스택을 정리하는 것은 __cdecl밖에 없으며 그래서 가변 인수를 지원할 수 있는 호출 규약도 __cdecl이 유일하다. 가변 인수 함수를 만들려면 반드시 __cdecl 호출 규약을 사용해야 한다. 만약 가변 인수 함수를 __stdcall로 작성하면 컴파일러는 이를 무시하고 __cdecl로 강제로 바꾸어 버린다.

출처 : winapi.co.kr 

'Security > Reverse Engineering' 카테고리의 다른 글

[Reversing] MASM32 Install and *.asm files compile  (0) 2011.01.19
[Revsering] ASCII Code List  (0) 2010.10.17
[Reversing] IDA pro 단축키  (0) 2010.09.02
[Reversing] Segment, Offset  (0) 2010.07.02
[Reversing] Ollydbg 단축키  (0) 2010.07.02

[MASM32 install]

http://www.masm32.com
홈페이지에서 masm32 다운로드 받고 설치한다.

설치 후 masm32\bin, masm32\lib 를 환경변수에 등록해 준다.

 
[*.asm파일 컴파일 하기]

Compile :
cmd창을 오픈
c:\masm32\bin\ml.exe /c /coff /Zi  파일명.asm

ml명령어가 실행되고 나면 .obj파일이 생성된다.

Linking :
c:\masm32\bin\link.exe /subsystem:windows  파일명.obj

'Security > Reverse Engineering' 카테고리의 다른 글

[Reversing] __cdecl과 __stdcall의 차이점  (0) 2011.01.20
[Revsering] ASCII Code List  (0) 2010.10.17
[Reversing] IDA pro 단축키  (0) 2010.09.02
[Reversing] Segment, Offset  (0) 2010.07.02
[Reversing] Ollydbg 단축키  (0) 2010.07.02

 

DEC

HEX

OCT

Char

 

DEC

HEX

OCT

Char

 

DEC

HEX

OCT

Char

0

00

000

Ctrl-@ NUL

43

2B

053

+

86

56

126

V

1

01

001

Ctrl-A SOH

44

2C

054

,

87

57

127

W

2

02

002

Ctrl-B STX

45

2D

055

-

88

58

130

X

3

03

003

Ctrl-C ETX

46

2E

056

.

89

59

131

Y

4

04

004

Ctrl-D EOT

47

2F

057

/

90

5A

132

Z

5

05

005

Ctrl-E ENQ

48

30

060

0

91

5B

133

[

6

06

006

Ctrl-F ACK

49

31

061

1

92

5C

134

\

7

07

007

Ctrl-G BEL

50

32

062

2

93

5D

135

]

8

08

010

Ctrl-H BS

51

33

063

3

94

5E

136

^

9

09

011

Ctrl-I HT

52

34

064

4

95

5F

137

_

10

0A

012

Ctrl-J LF

53

35

065

5

96

60

140

`

11

0B

013

Ctrl-K VT

54

36

066

6

97

61

141

a

12

0C

014

Ctrl-L FF

55

37

067

7

98

62

142

b

13

0D

015

Ctrl-M CR

56

38

070

8

99

63

143

c

14

0E

016

Ctrl-N SO

57

39

071

9

100

64

144

d

15

0F

017

Ctrl-O SI

58

3A

072

:

101

65

145

e

16

10

020

Ctrl-P DLE

59

3B

073

;

102

66

146

f

17

11

021

Ctrl-Q DCI

60

3C

074

<

103

67

147

g

18

12

022

Ctrl-R DC2

61

3D

075

=

104

68

150

h

19

13

023

Ctrl-S DC3

62

3E

076

>

105

69

151

i

20

14

024

Ctrl-T DC4

63

3F

077

?

106

6A

152

j

21

15

025

Ctrl-U NAK

64

40

100

@

107

6B

153

k

22

16

026

Ctrl-V SYN

65

41

101

A

108

6C

154

l

23

17

027

Ctrl-W ETB

66

42

102

B

109

6D

155

m

24

18

030

Ctrl-X CAN

67

43

103

C

110

6E

156

n

25

19

031

Ctrl-Y EM

68

44

104

D

111

6F

157

o

26

1A

032

Ctrl-Z SUB

69

45

105

E

112

70

160

p

27

1B

033

Ctrl-[ ESC

70

46

106

F

113

71

161

q

28

1C

034

Ctrl-\ FS

71

47

107

G

114

72

162

r

29

1D

035

Ctrl-] GS

72

48

110

H

115

73

163

s

30

1E

036

Ctrl-^ RS

73

49

111

I

116

74

164

t

31

1F

037

Ctrl_ US

74

4A

112

J

117

75

165

u

32

20

040

Space

75

4B

113

K

118

76

166

v

33

21

041

!

76

4C

114

L

119

77

167

w

34

22

042

"

77

4D

115

M

120

78

170

x

35

23

043

#

78

4E

116

N

121

79

171

y

36

24

044

$

79

4F

117

O

122

7A

172

z

37

25

045

%

80

50

120

P

123

7B

173

{

38

26

046

&

81

51

121

Q

124

7C

174

|

39

27

047

'

82

52

122

R

125

7D

175

}

40

28

050

(

83

53

123

S

126

7E

176

~

41

29

051

)

84

54

124

T

127

7F

177

DEL

42

2A

052

*

85

55

125

U

 Text search  Alt+T
 Show strings window  Shift+F12
 Show operand as hex value  Q
 Insert comment  :
 Follow jump or call in view  Enter
 Return to previous view  Esc
 Go to next view  Ctrl+Enter
 Show names window  Shift+F4
 Display function's flow chart  F12
 Display graph of function calls  Ctrl+F12
 Go to program's entry point  Ctrl+E
 Go to specific address  G
 Rename a variable or function  N
 Show listing of names  Ctrl+L
 Display listing of segments  Ctrl+S
 Show cross-references to selected function  Select function name » Ctrl+X
 Show stack of current function  Ctrl+K


Segment Memory

8086 1mb의 메모리 공간을 다음과 같은 4개의 세그먼트 공간으로 나누어 관리함

Code Segment

명령어 코드를 저장

Data Segment

데이터를 저장

Stack Segment

메모리에 할당된 스택 영역

Extra(Heap) Segment

여분의 데이터 영역

 

 

Segment Register

8086이 필요한 정보를 세그먼트 단위로 나누어 저장하고 있기 때문에 정보를 가져오기 위해선 각 세그먼트의 시작 주소를 알아야 함

따라서 4개의 세그먼트 레지스터를 이용해 각 세그먼트 영역의 시작 주소를 가리킴

CS

실행 할 명령어들이 들어있는 코드 세그먼트의 시작 주소를 가지고 있는 레지스터.

CS * 10H + OFFSET(IP)로 물리 메모리 주소 결정

DS

데이터 세그먼트의 시작 주소를 가지고 있다.

메모리 직접 주소 지정 혹은BP외의 레지스터와 함께 사용하여 메모리 간접 주소 지정에서 오프셋 값과 더해져 물리 주소를 산출한다.

SS

스택 세그먼트의 시작 주소를 가지고 있다.

SP SS * 10H의 합으로 물리 주소를 결정한다. BP를 사용하는 메모리 간접 주소 지정에서 오프셋과 합해 물리 주소를 생성한다.

ES

일반적으로 문자열 처리에 사용.

문자열 처리 명령어가 수행되면 목적지의 위치는 DI EX * 10H로 결정되고 출발지는 SI DX * 10H로 물리주소 결정한다.

 

OffSet Register

최대 64KB인 세그먼트 안에 저장되어 있는 정보를 엑세스하기 위해서는 세그먼트 레지스터만으로 불가능함
-->
  다른 16비트 크기를 포인트 할 수 있는 레지스터가 필요함(offset register)

하나의 세그먼트에 접근하기 위해 대상이 되는 세그먼트 레지스터가 가진 시작 주소에 오프셋을 더해 데이터에 액세스

메모리 동작

묵시적 레지스터

대체가능 레지스터

오프셋

명령어 인출

CS

-

IP

스택 처리

SS

-

SP

데이터 엑세스

DS

CS, ES, SS

주소저장방식에 따라 다름

20bit 물리적 주소 산출

16비트 세그먼트 레지스터 << 4 + 16비트 offset

(segment:offset 구조로 되어 있는 논리주소는 segment주소를 4비트 쉬프트하고, offset을 더해주어서 물리주소로 변환)

seg : 20H offset : 10H일 때 → 200H(20H << 4) + 10H = 210H

1000004bit 쉬프트 = 100000 0000 → 1000000000 → 200H

10H → 10000

1000000000 + 10000 → 1000010000 → 210H

 

 


'Security > Reverse Engineering' 카테고리의 다른 글

[Revsering] ASCII Code List  (0) 2010.10.17
[Reversing] IDA pro 단축키  (0) 2010.09.02
[Reversing] Ollydbg 단축키  (0) 2010.07.02
[Reversing]구조화된 예외 처리(SEH)  (0) 2010.05.10
[Reversing]Input and Output  (0) 2010.05.10

Ctrl+F2

프로그램 재실행

Alt+F2

프로그램 닫기

F3

새 프로그램 열기

F5

활성화 되어 있는 윈도우 최대화, 혹은 원복

Alt+F5

olly 디버거 윈도우를 항상 위로

F7

Step into (함수 진입)

Ctrl+F7

Animate into (entering functions)

F8

Step over (executing function calls at once)

Ctrl+F8

Animate over (executing function calls at once)

F9

실행

Shift+F9

Pass exception to standard handler and run

Ctrl+F9

Execute till return

Alt+F9

Execute till user code

Ctrl+F11

Trace into

F12

Pause

Ctrl+F12

Trace over

Alt+B

Open Breakpoints window

Alt+C

Open CPU window

Alt+E

Open Modules window

Alt+L

Open Log window

Alt+M

Open Memory window

Alt+O

Open Options dialog

Ctrl+T

Set condition to pause Run trace

Alt+X

Close OllyDbg

F2

Toggle breakpoint

Shift+F2

Set conditional breakpoint

F4

Run to selection

Alt+F7

Go to previous reference

Alt+F8

Go to next reference

Ctrl+A

Analyse code

Ctrl+B

Start binary search

Ctrl+C

Copy selection to clipboard

Ctrl+E

Edit selection in binary format

Ctrl+F

Search for a command

Ctrl+G

Follow expression

Ctrl+J

Show list of jumps to selected line

Ctrl+K

View call tree

Ctrl+L

Repeat last search

Ctrl+N

Open list of labels (names)

Ctrl+O

Scan object files

Ctrl+R

Find references to selected command

Ctrl+S

Search for a sequence of commands

Asterisk (*)

Origin

Enter

Follow jump or call

Plus (+)

Go to next location/next run trace item

Minus (-)

Go to previous location/previous run trace item

Space ( )

Assemble

Colon (:)

Add label

Semicolon (;)

Add comment

ctrl+, 아래 화살표키

디스어셈블 위치 지정


 

'Security > Reverse Engineering' 카테고리의 다른 글

[Reversing] IDA pro 단축키  (0) 2010.09.02
[Reversing] Segment, Offset  (0) 2010.07.02
[Reversing]구조화된 예외 처리(SEH)  (0) 2010.05.10
[Reversing]Input and Output  (0) 2010.05.10
[Reversing]실행 포멧  (0) 2010.05.08

구조화된 예외 처리(Structured Exception Hadling)

-       SEH : OS가 발생한 예외를 구조화된 방법으로 App에게 전달하는 메커니즘을 제공함

-       예외(exception)는 예외 핸들러라고 불리는 특별한 함수로 즉각 점프하게 하는 프로그램 안에서의 특별한 조건

-       예외 핸들러는 발생한 문제점을 해결할 것인지,

                                     프로그램이 동일한 코드를 다시 실행하게 만들 것인지,

                                     프로그램의 다른 부분이 실행되게 할 것인지,

                                     프로그램을 종료할 것인지

결정함

 

 

  하드웨어 예외

-       프로세스가 만들어 내는 예외

Ex: 유효하지 않은 메모리 접근, 0나누기 등

 

  소프트웨어 예외

-       프로그램이 에러를 보고하기 위해서 예외를 생성할 때 발생

Ex: C++에서 throw키워드 이용

 


'Security > Reverse Engineering' 카테고리의 다른 글

[Reversing] Segment, Offset  (0) 2010.07.02
[Reversing] Ollydbg 단축키  (0) 2010.07.02
[Reversing]Input and Output  (0) 2010.05.10
[Reversing]실행 포멧  (0) 2010.05.08
[Reversing]API  (0) 2010.05.04

 입력과 출력

- 로우레벨 계층의 I/O 시스템 : 하드웨어 등과의 통신 담당
- 하이레벨 계층의 Win32 서브시스템 : GUI를 구현하고 사용자 입력 처리 작업 담당

  I/O 시스템

-       시스템에서 동작하는 디바이스 드라이버를 관리

-       App과 디바이스 드라이버 간의 통신 담당 커널 컴포넌트들로 구성됨

-       App의 디바이스 드라이버에 대한 요청을 전달하는 작업을 담당함

-       계층 구조로 이루어짐(각 디바이스에 대해 여러 개의 디바이스 드라이버가 스택구조로 존재할 수 있음 : 드라이버와 App 간이나 두 드라이버 간의 통신을 모니터링하거나 변경하기 위한 필터 드라이버 추가에 적합)

-       각 드라이버 간의 연결을 책임지고 담당

 

  Win32 서브시스템

-       윈도우 사용자 인터페이스의 모든 부분을 담당하는 컴포넌트

-       GDI(Graphics Device Interface)라고 하는 로우레벨 그래픽 엔진과 윈도우창, 메뉴, 사용자 입력 처리와 같은 하이레벨의 GUI를 처리하는USER컴포넌트로 구성됨

 

# Win32 서브시스템 동작방식

-       Win32 서브시스템은 모든 Win32 API를 담당하는 것이 아니고, 단지 USER, GDI 부분만을 담당함

-       커널 레벨의 WIN32K.SYS에 의해서 구현되고 유저레벨의 USER32.DLL GDI32.DLL에 의해서 관리됨

-       유저모드 DLL과 커널 컴포넌트 사이의 통신은 기존의 시스템 콜 방식을 이용해서 이루어짐

 

  객체 관리자

-       USER, GDI는 윈도우 초기 버전부터 존재해 왔으므로 커널 객체 관리자를 사용하지 않음

-       자신만의 작은 객체 관리 메커니즘 이용함

-       윈도우 창, 디바이스 컨텍스트와 같은 Win32 객체에 대한 핸들값 → 객체 테이블에 대한 인덱스

-       객체 테이블은 커널 메모리에 저장됨(읽기 모드)

-       USER, GDI 핸들 테이블은 전역(global)

'Security > Reverse Engineering' 카테고리의 다른 글

[Reversing] Ollydbg 단축키  (0) 2010.07.02
[Reversing]구조화된 예외 처리(SEH)  (0) 2010.05.10
[Reversing]실행 포멧  (0) 2010.05.08
[Reversing]API  (0) 2010.05.04
[Reversing]프로세스 동기화, 초기화 과정  (0) 2010.05.04

 ▣ 실행 포맷

윈도우 실행파일 포맷인 PE(Portable Executable)의 기본적인 구조 이해

    기본 개념

-       실행파인은 재배치 될 수 있음(로드될 때마다 다른 가상 메모리 주소에 로드될 수 있음)

-       OS는 각 프로세서마다 고유한 주소 공간을 제공하지만 주소 공간에는 여러 개의 실행 바이너리들이 로드됨

-       프로그램은 자신의 주소 공간에 실행파일뿐만 아니라 DLL과 같은 추가적인 실행 모듈들을 로드함

-       기존에 사용하고 있는 주소에 다른 프로그램이 해당 주소를 사용하려고 하는 경우 다른 주소에 로딩해야 되는데 이때 재배치 작업을 수행함

 

MOV    EAX,   DWORD  PTR [pGlobalVariable]

위 코드는 전역변수에 접근하는 전형적인 코드

컴파일러와 링커가 pGlobalVariable에 대한 주소로 어떤 값을 사용해야 하는가?

→일반적으로 파일의 시작 지점으로부터의 상대주소를 생각할 수 있다. 이 주소를 사용할 경우 어느 주소로 로드되는지 걱정할 필요가 없다. 그러나위의 코드는 프로세서가 직접 실행하는 코드이다. 따라서 로더는 코드상의 모든 주소를 정확한 위치를 가리키는 절대주소로 변환한다.

 

# 재배치가 중요한 이유

-       실행모듈헤더에서는 절대주소가 사용되지 않고 코드에서만 절대주소가 사용되기 때문

-       실행 모듈 헤더에서는 항상 상대가상주소(RVA, Relative Virtual Address : 단순 offset)를 상요함

-       실행 모듈이 로드되고 가상주소를 할당받을 때 로더는 실제 가상주소를 계산함

(모듈의 Based Address + RVA = 실제 가상주소)

 

    이미지 섹션

-       실행이미지는 여러가지 섹션으로 나누어 짐

-       코드(text)섹션 : 실행모듈의 코드 포함

-       데이터섹션 : 데이터 포함

-       실행 모듈 로딩 시 메모리 관리자는 섹션 헤더의 설정 내용에 따라 각 섹션에 해당하는 메모리 페이지에 대한 접근 권한 설정함

Char   szMessage[] = “Welcome to my program!”;

위의 코드에서 컴파일러는 실행 이미지의 어딘가에 정의된 문자열을 저장해야 함

위의 문자열은 초기화된 데이터이며 따라서 해당 문자열과 그것을 가리키는 변수는 초기화된 데이터 섹션에 저당됨

 

 

    섹션 정렬

-       메모리에 로드되는 섹션의 크기는 일반적으로 페이지 크기의 배수

-       반대로 실행 이미지를 페이지 크기 단뒤로 디스크에 저장하면 실제 필요한 용량보다 훨씬 큰 용량을 차지함(디스크 낭비)

 

→ 위의 이유로 인해 PE헤더는 섹션정렬을 위한 두개의 필드가 존재함

섹션정렬 필드 : 실행 이미지를 메모리에 로드할 때 사용

파일정렬 필드 : 파일을 디스크에 저장할 때 사용

 

    동적 링크 라이브러리(DLL)

-       동적 링크 라이브러리의 개념

프로그램은 하나 이상의 실행 파일로 분리될 수 있고, 각 실행 파일은 프로그램 기능의 일부분이나 일부 기능을 수행하는 것

           장점 : 필요한 기능을 제공하는 실행 모듈만 로드해서 사용함(메모리 낭비를 줄임)

                  프로그램의 기능 변경시 해당 모듈만 변경하거나 추가하면 됨

    정적 라이브러리(.lib)

-       실행 모듈에 영구히 링크됨

-       프로그램이 빌드될 때 .lib파일안의 코드를 원래 소스코드의 일부분인 것처럼 실행 모듈에 정적으로 링크시킴

-       실행 모듈이 로드될 때 OS는 로드된 실행 모듈안에 정적라이브러리가 있다는 것을 알지 못함. 이는 같은 정정적라이브러리가 포함된 A, B프로그램이 있다면 정정라이브러리가 중복되서 로드될 것임(메모리 낭비가 발생할 수 있음)

 

    윈도우 프로그램 실행 시 DLL로드 방법

(1)   정적링크

-       실행 이미지의 임포트 테이블 안에 다른 실행모듈에 대한 정보를 포함시키는 과정

-       실행 이미지가 사용하는 모듈들도 같이 로드함

-       해당 모듈들에 대한 모든 외부 레퍼런스 정보를 올바르게 맞춤

 

(2)   동적링크

-       실행 이미지가 런타임 시에 다른 실행 모듈에 대한 로드여부를 판단함

-       런타임 시에 모듈을 직접 로드하고 로드한 모듈 이미지의 헤더를 검색해서 호출하고자 하는 함수를 찾아야만 함

  리버싱 관점에서 볼 때 정적 링크 방법은 어떤 모듈의 어떤 함수를 사용하는지 전부 할 수 있으므로 좀더 다루기 쉽다


    헤더(Header)

-       PE파일은 DOS헤더로 시작함

-       하위 호환을 위한 부분으로 DOS시스템에서 PE파일이 실행될 때 에러처리를 하기 위함

(ex: “This program connot be run in DOS mode”라는 메시지가 나타나는 경우가 있는데, DOS상에서 PE실행 이미지를 실행 시킬 수 없다는 의미 → 이 메시지를 출력하기 위해서 PE실행 이미지에는 작은 16bit DOS 프로그램을 포함)

-       헤더 안의 모든 포인터는 절대주소가 아닌 RAV값임

-       유용한 정보들은 PE헤더 안의 추가적인 데이터 구조체 배열인 DataDirectory 구조체 안에 포함됨

 

(1)   DOS 헤더

-       e_lfanew : 실제 PE 헤더를 가리키는 포인터

 

(2)   PE헤더

-       DOS헤더가 확장된 것임

 

    임포트와 익스포트

-       실행 이미지의 동적링크를 가능하게 해주는 메커니즘

-       컴파일러와 링커는 임포트하는 함수의 실제 주소를 알지 못함 → 실행 시에만 알 수 있음

(임포트 테이블 : 실행 이미지가 사용하는 각 모듈목록과 그 모듈에서 사용하는 함수 목록의 정보가 저장되어 있음)

-       모듈이 모드될 때 로더는 임포트 테이블에 명시된 모든 모듈을 로드 함

-       로드한 각 모듈의 함수 목록에 있는 함수들의 주소를 산출

-       함수 주소는 임포트한 모듈의 익스포트 테이블을 통해 산출

(익스포트 테이블 : 해당 모듈이 익스포트하는 모든 함수의 이름과 RVA를 가지고 있음)

 

    디렉토리

-       데이터 구조체

이름

설명

관련 구조체

export table

모듈의 모든 익스포트 함수 이름과 RVA를 포함

IMAGE_EXPORT_DIRECTORY

import table

·임포트하는 모듈과 함수 이름을 포함함

·함수별로 함수 이름 문자열(또는 서수)과 함수의 임포트 어드레스 테이블 엔트리를 가리키는 RVA를 포함

·모듈이 로드될 때 임포트한 함수의 실제 주소를 전달받는 시작점이 됨

IMAGE_IMPORT_DESCRIPTOR

resource table

·실행 모듈의 리소스 디렉토리 포인터

·리소스 디렉토리는 문자열, 대화상자 레이아웃, 메뉴와 같은 다양한 사용자 인터페이스 요소와 정적인 요소를 정의함

IMAGE_RESOURCE_DIRECTORY

Base Relocation table

모듈이 빌드되면서 설정된 로드 주소가 아닌 다른 주소로 로드되어야 할 때 재배치되어야 하는 주소들의 목록

IMAGE_BASE_RELOCATION

Debugging Information

·실행 모듈을 위한 디버깅 정보

·일반적으로 실질적인 디버깅 정보를 담고 있는 외부 심볼 파일에 대한 링크 정보를 제공함

IMAGE_DEBUG_DIRECTORY

Thread Local Storage table

·쓰레드 로컬 변수를 포함할 수 있는 실행 모듈의 쓰레드 로컬 섹션에 대한 포인터

·이 기능은 로더가 실행 모듈을 로드할 때 사용함

IMAGE_TLS_DIRECTORY

Load Configuration table

·LOCK prefix테이블(단일 프로세서 시스템이나 멀티 프로세스 시스템에 맞게 실행 모듈이 로드될 때 실행 모듈 이미지를 변경 가능)과 같은 다양한 이미지 설정 요소를 포함

·모듈의 예외 핸들러 목록 포함(악의적인 코드가 예외 핸들러를 설치하는 것을 방지하기 위함)

IMAGE_LOAD_CONFIG_DIRECTORY

Bound Import table

·바운드 임포트 엔트리 정보를 담고 있는 추가적인 임포트 테이블

·임포트한 실행 모듈의 실제 주소가 포함되어 있다는 것을 의미함(그 주소가 여전이 유효한지 확인하기 위함)

IMAGE_BOUND_IMPORT_DESCIPTOR

Import Address table(IAT)

·임포트된 각 함수의 목록을 포함

·실행 모듈이 로드될 때 각 임포트 함수의 엔트리가 해당 함수에 대한 실제 주소로 초기화 됨

32bit 포인터 목록

Delay Import Descriptor

·임포트한 함수를 처음 호출할 때 해당 함수의 실제 주소가 매핑되는 지연 임포트 로딩 메커니즘을 구현하기 위해 사용됨

·이 메커니즘은 OS가 제공하는 것이 아니라 C런타임 라이브러리에 의해서 구현됨

ImgDelayDescr

 [ PE파일 포맷의 디렉토리]

 


Application Programming Interface(API)

-       API OS App과 통신하기 위해서 제공하는 함수 모음

 

    Win32 API

-       로우레벨 프로그래밍 인터페이스 → 향후 하이레벨 인터페이스로 개발됨

-       계층적 구조 : 프로그래머들에게는 프로그래밍하기에 친숙하지만, OS는 모든 호출이 상위계층을 거치므로 다소 성능이 저하됨

-       윈도우에서 핵심적인 Win32 API는 약2,000

[Win32 인터페이스 DLL과 커널 컴포넌트와의 관계]

 

    Kernel API

-       Based API라고도 불리움

-       KERNEL32.DLL 모듈 안에 구현되어 있음

-       GUI와 관련되지 않은 서비스들, 즉 파일I/O, 메모리 관리, 객체 관리, 프로세스와 스레드 관리 등

-       NTDLL.DLL의 네이티브 API를 호출하여 다양한 서비스를 구현함

 

    Native API

-       Window NT 시스템의 실질적인 인터페이스

-       Win32 API는 네이티브 API에 상위 계층일 뿐

-       그래픽 관련 서비스를 포함하지 않음

-       메모리 관리자, I/O 시스템, 객체 관리자, 프로세스와 쓰레드 등에 직접 접근할 수 있는 인터페이스 제공(윈도우 커널에 대한 가장 직접적인 인터페이스)

-       App 프로그램은 Win9x와 호환성을 유지하기 위해서 네이티브 API를 직접 호출하면 안됨

-       NTDLL.DLL(user mode 호출자를 위한) NTOSKRNL.EXE(kernel mode 호출자를 위한)에서 익스포트된 함수들의 집합

-       네이티브 API 이름은 항상 Nt, Zw로 시작됨

Nt 버전 API : 해당 API를 실질적으로 구현하는 함수

Zw 버전 API : 시스템 콜 메커니즘이 수행되는 함수


#시스템 콜 메커님즘을 통해 커널 모드 API를 호출하는 이유?

API를 커널 모드에서 호출한다는 것을 알려주기 위해서이다.

이런 구분 없이 API를 무작정 호출하면 자신이 유저 모드에서 호출되지는 커널 모드에서 호출되는 알 수 없게 된다. 유저 모드에서 커널 모드 API를 호출하면 유저 모드에서 호출했다고 판단해 유저 모드 주소를 포함하고 있는 모든 파라미터를 조사할 것이다. 이는 유저 모드에서 커널 메모리 주소를 전달함으로써 발생할 수 있는 시스템 충돌을 방지하기 위한 메커니즘이다.

 

    시스템 콜 메커니즘

-       시스템 콜은 유저 모드에서 커널 모드 함수를 호출할 필요가 있을 때 발생

-       유저모드에서 커널 함수를 직접 호출하는 것은 불가능함(직접 호출이 가능하다면 보안상 위험이 발생할 수 있음)

프로세스가 특권 모드로 스위칭 → 특별한 CPU 명령(특별한 디스패치 루틴을 호출하게 명령)을 유저모드에서 호출 → 호출된 디스패치 루틴은 유저모드에서 요청한 특정 시스템 함수를 호출

-       Window 2000 이후 메커니즘 변경됨

 

Window 2000 이하 버전

인터럽트 2E를 이용해서 커널 호출

Ntdll!ZwReadFile:

77f8c552  mov  eax,0xa1   //eax 레지스터에 서비스 번호 로드

77f8c557  lea  edx,[esp+0x4]  //edx 레지스터에 커널모드 함수에 전달되는 첫번째 파라미터 주소 저장

77f8c55b  int   2e  //인터럽트 디스크립터 테이블(IDT)을 이용해서 해당 인터럽트 핸들러 호출

77f8c55d  ret   0x24

 

Window 2003 server

Window XP

인터럽트 사용 안함

SYSENTER 명령어 사용 : 고성능 커널모드 스위칭 명령으로, SYSENTER_EIP_MSR이라는 특별한 MSR 레지스터에 저장된 주소를 호출함

Ntdll!ZwReadFile:

77f4302f  mov  eax,0xbf   //eax 레지스터에 서비스 번호 로드

77f43034  mov  edx,[0x7ffe0300]  //0x7ffe0300 : SharedUserData!SystemCallStub함수

77f43039  call   edx 

77f4303b  ret   0x24

[디스어셈블 코드]

SharedUserData!SystemCallStub:

7ffe0300    mov     edx,esp

7ffe0302    sysenter

7ffe0304    ret   // 실제 실행되지 않음

 

    시스템 콜 메커니즘

-       어떤 상태 정보도 저장하지 않음

-       SystemCallStub함수를 호출해 OS가 현재의 유저모드 주소 정보를 스택에 저장하게 만듬(이렇게 해야 나중에 되돌아갈 주소를 알 수 있음)

-       커널에서의 작업이 완료되고 다시 유저모드로 되돌아갈 때 단순히 스택에 저장된 주소로 돌아감(따라서, 7ffe0304 ret명령은 실제 실행되지 않음)

'Security > Reverse Engineering' 카테고리의 다른 글

[Reversing]Input and Output  (0) 2010.05.10
[Reversing]실행 포멧  (0) 2010.05.08
[Reversing]프로세스 동기화, 초기화 과정  (0) 2010.05.04
[Reversing]프로세스와 쓰레드  (0) 2010.05.04
[Reversing]네임드 객체  (0) 2010.05.03

+ Recent posts