NtGlobalFlag

- 프로세스가 디버깅 중일 때 PEB.NtGlobalFlag 멤버(+0x68)의 값은 0x70으로 설정된다.

- PEB.NtGlobalFlag 값은 

FLG_HEAP_ENABLE_TAIL_CHECK (0x10)

→ Heap 메모리가 해제되었을 때, 버퍼 오버런을 검사한다.

→ 이 Flag는 각 할당된 부분의 끝에 짧은 패턴을 추가한다. 윈도우 힙 매니저는 블록이 해제됐을 때 이러한 패턴들을 감지하고, 블록들이 수정되었을 때 디버거에 들어간다.

FLG_HEAP_ENABLE_FREE_CHECK (0x20)

→ Heap 메모리가 해제되었을 때, Heap의 할당부분을 검사한다.

FLG_HEAP_VALIDATE_PARAMETERS (0x40)

→ Heap 함수가 호출 될 때마다, Heap의 선택된 부분을 검사한다.

  상위 3개의 Flags들의 bit OR 연산이다.

- 디버깅 프로세스의 Heap 메모리에는 일반 실행 프로세스와는 다른 특별한 표시가 존재한다. 이를 위해 PEB.NtGlobalFlag 멤버에 위와 같은 Flag들이 추가된다.

- 실행 중인 프로세스에 디버거를 Attach시킨 경우에 NtGlobalFlag 값은 변하지 않는다.


[C언어로 작성한 예제 파일]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <windows.h>
 
FARPROC pProc = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCurrentTeb");
LPBYTE pTEB = (LPBYTE)(*pProc)();
LPBYTE pPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30);
 
int NtGlobalFlag();
 
int main(){
    while(1){
        if(NtGlobalFlag() != 0){
            printf("Debugging!!!\n");
        }
        else{
            printf("Not Debugging...\n");
        }
        Sleep(1000);
    }
 
    puts("");
    return 0;
}
 
int NtGlobalFlag(){
    DWORD NtGlobalFlag = *(LPDWORD)(pPEB+0x68);
    printf("NtGlobalFlag : %x, ", NtGlobalFlag);
    return (NtGlobalFlag & 0x70);
}
cs


○ 디버깅 중일 때의 모습이다. (Windows XP 환경)


○ PEB.NtGlobalFlag의 값이 0x00000070인것을 알 수 있다.


[우회 방법] : PEB.NtGlobalFlag의 값을 0x00으로 설정하면 된다.

○ NtGlobalFlag의 값을 0으로 설정했다.


○ 우회한 것을 확인할 수 있다.


참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x03. Process Heap  (0) 2016.07.07
Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
PEB 구조  (2) 2016.07.05

Process Heap

- PEB.ProcessHeap 멤버(+0x18)는 Heap 구조체를 가리키는 포인터이다.

- Flags 멤버(+0x0C)와 Force Flags 멤버(+0x10)는 디버깅 중 특정한 값으로 세팅된다.

- 프로세스가 정상 실행 중일 때 Heap.Flags 멤버(+0x0C)의 값은 0x02이고, Heap.ForceFlags 멤버(+0x10)의 값은 0x00이다. (Windows XP 환경)

- Windows XP에서만 효과가 있는 기법이다. Windows 7에서는 이 특성이 없어졌다.

- 실행 중인 프로세스에 디버거를 Attach시킨 경우에도 이 특성이 나타나지 않으므로 동작하지 않는다.


[Heap 구조체의 일부분]

+0x000 Entry : _HEAP_ENTRY

+0x008 Signature : Uint4B

+0x00c Flags : Uint4B

+0x010 ForceFlags : Uint4B

+0x014 VirtualMemoryThreshold : Uint4B

+0x018 SegmentReverse : Uint4B

+0x01c SegmentCommit : Uint4B

+0x020 DecommitFreeBlockThreshold : Uint4B


○ ProcessHeap 의존성 확인

- Windows 7에서는 일반 실행했을때 Heap.Flag 멤버의 값과 Heap.ForceFlags의 값이 다르다.

(Heap.Flag 멤버의 값은 0으로 고정되어있고, Heap.ForceFlags의 값은 실행할 때마다 변하는 것을 확인했다.)


[C언어로 작성한 예제 파일]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
 
int main(){
    FARPROC pProc = NULL;
    LPBYTE pTEB = NULL;
    LPBYTE pPEB = NULL;
 
    pProc = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCurrentTeb");
    pTEB = (LPBYTE)(*pProc)();
    pPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30);
 
    while(1){
        LPBYTE pHeap = (LPBYTE)*(LPDWORD)(pPEB+0x18);
        DWORD dwFlags = *(pHeap+0xC);
        DWORD dwForceFlags = *(LPDWORD)(pHeap+0x10);
        
        printf("PEB.ProcessHeap.Flags = 0x%x\n", dwFlags);
        printf("PEB.ProcessHeap.ForceFlags = 0x%x\n", dwForceFlags);
        if(dwFlags != 0x2 || dwForceFlags != 0x0){
            printf("Debugging!!!\n");
        }
        else{
            printf("Not Debugging...\n");
        }
        Sleep(1000);
    }
 
    return 0;
}
cs


○ TEB → PEB → PEB.ProcessHeap 순서대로 접근한다. PEB.ProcessHeap = 0x00240000


○ 현재 디버거로 연 상태이므로 Heap.Flags = 0x50000062, Heap.ForceFlags = 0x40000060 이다.

Heap.Flags 필드는 일반적으로 이 Flag들의 bit OR연산 값으로 설정된다.

HEAP_GROWABLE (0x02)

HEAP_TAIL_CHECKING_ENABLED (0x20)

HEAP_FREE_CHECKING_ENABLED (0x40)

HEAP_SKIP_VALIDATION_CHECKS (0x10000000)

HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)


Heap.ForceFlags 필드는 일반적으로 이 Flag들의 bit OR연산 값으로 설정된다.

HEAP_TAIL_CHECKING_ENABLED (0x20)

HEAP_FREE_CHECKING_ENABLED (0x40)

HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)



[우회 방법] : Heap.Flags를 0x02로, Heap.ForceFlags를 0x00으로 변경하면 된다.

○ Heap.Flags = 0x00000002, Heap.ForceFlags = 0x00000000으로 변경한다.


○ 우회한 것을 확인할 수 있다.


참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x04. NtGlobalFlag  (0) 2016.07.07
Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
PEB 구조  (2) 2016.07.05

LDR

 - Heap 메모리의 사용되지 않는 영역을 0xABABABAB 또는 0xFEEEFEEE 값으로 채우는 특징을 이용해 프로세스의 디버깅 여부를 판별할 수 있다.

※0xABABABAB는 HeapAlloc으로 메모리 할당만 하고 아직 사용하지 않은 경우의 값이고, 0xFEEEFEEE는 Heap에서 메모리를 해제한 경우 설정되어 있는 값이다.

 - PEB.LDR 멤버는 _PEB_LDR_DATA 구조체를 가리키는 포인터이다.

 - XP이하에서만 동작하고 Vista 이후부터는 동작하지 않는다.

 - 실행 중인 프로세스에 디버거를 Attach시킨 경우, Heap 메모리의 특성이 나타나지 않으므로 동작하지 않는다.


○ LDR 의존성 확인

- Windows 7에서는 디버거로 열어도 감지하지 못한다.

- Windows 7의 PEB 주소값은 0x7EFDE000이었다. PEB.Ldr(+0xC) 주소 값 : 0x77E20200


- 0x77E20200에는 0xABABABAB 또는 0xFEEEFEEE가 보이지 않기 때문에 "Not Debugging..." 메시지가 출력되었다.


 [C언어로 작성한 예제 파일]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <windows.h>
 
int main(){
    FARPROC pProc = NULL;
    LPBYTE pTEB = NULL;
    LPBYTE pPEB = NULL;
 
    pProc = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCurrentTeb");
    pTEB = (LPBYTE)(*pProc)();
    pPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30);
 
    printf("TEB : %x\n", pTEB);
    printf("PEB : %x\n", pPEB);
 
    puts("");
}

cs


○ 디버깅 중일 때의 모습이다. (Windows XP 환경)


○ PEB.Ldr 주소를 얻고, 그 주소로 가서 0xFEEEFEEE 영역을 찾았다.

<PEB.Ldr 주소는 Little Endian으로 박혀있다. PEB.Ldr 주소 : 0x00251EA0>


<Heap 메모리에서 0xFEEEFEEE로 채워진 영역>


[우회 방법] : 0xFEEEFEEE로 채워진 영역을 NULL로 덮어쓰면 된다.

○ 0xFEEEFEEE로 채워진 영역을 NULL로 덮어쓴다.


○ NULL값으로 덮여써진 것을 확인할 수 있다.


○ 우회한 것을 확인할 수 있다.



의문점 : Windows Vista부터는 0xFEEEFEEE가 생기지 않는 이유, 왜 하필 0xABABABAB 또는 0xFEEEFEEE인가?

참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x04. NtGlobalFlag  (0) 2016.07.07
Static Anti-Debugging 0x03. Process Heap  (0) 2016.07.07
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
PEB 구조  (2) 2016.07.05

IsDebuggerPresent()

 - PEB.BeingDebugged (+0x2)의 값에 따라 디버깅 여부를 알 수 있다.

디버깅 중일 때 : 0x01(TRUE)

일반 실행 중일 때 : 0x00(FALSE)

 [C언어로 작성한 예제 파일]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <windows.h>
 
int main(){
    while(1){
        printf("IsDebuggerPresent() = %d, ", IsDebuggerPresent());
        if(IsDebuggerPresent()){
            printf("Debugging\n");
        }
        else{
            printf("Not Debugging\n");
        }
        Sleep(1000);
    }
 
    puts("");
    return 0;
}
cs

 

○ 일반 실행 중일 때 IsDebuggerPresent()의 값은 0x00이다.


○ 디버깅 중일 때 IsDebuggerPresent()의 값은 0x01이다.


○ IsDebuggerPresent 어셈블리어 코드(환경 : Windows XP)

7C813123 : TEB 구조체 주소를 구한다.

7C813129 : TEB.ProcessEnvironmentBlock 멤버(+0x30)로 PEB주소를 구한다.

7C81312C : PEB.BeingDebugged 멤버(+0x02)에 접근한다.


[우회 방법] : PEB.BeingDebugged 값을 0x00(FALSE)로 변경한다.

○ 우회 전 PEB.BeingDebugged의 값 : 0x01


○ PEB.BeingDebugged의 값을 0x00으로 변경


○ 우회한 것을 확인할 수 있다.


참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x03. Process Heap  (0) 2016.07.07
Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
PEB 구조  (2) 2016.07.05
TEB 구조  (0) 2016.07.05

1. 안티 디버깅이란?
    - 디버깅을 방해하고 분석을 방해하는 기술


2. 안티 디버깅을 왜 공부해야하는가?
    - 각종 안티 디버깅 기법들의 동작 원리를 파악한 후 회피하기 위해서
    - 안티 디버깅 기법을 공부하면서 고급 리버싱을 배울 수 있기 때문에


3. 안티 디버깅의 의존성
    - 안티 디버깅 기법은 디버거와 OS에 강한 의존성이 있다.
    ex) Ldr, ProcessHeap, GetProcessHeap : XP에서만 효과가 있는 기법


4. 안티 디버깅 기법의 분류

1) Static 안티 디버깅
- 특징 : 디버깅을 시작할 때 한번만 해체를 해주면 해결
- 목적 : 디버거 탐지
- 해체 방법 : API Hooking, Debugger Plugin

2) Dynamic 안티 디버깅
- 특징 : 디버깅을 진행하면서 안티 디버깅을 만날 때마다 해결
- 목적 : 내부 코드와 데이터를 숨김
- 해체 방법 : API Hooking, Debugger Plugin, Utilities



참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
PEB 구조  (2) 2016.07.05
TEB 구조  (0) 2016.07.05
Heap, FS, TEB, PEB  (0) 2016.07.05

PEB의 역사 : PEB_Evolution.pdf


(Windows XP 환경)


+0x000 InheritedAddressSpace : UChar // 프로세스가 fork되어졌는지를 나타냄.

+0x001 ReadImageFileExecOptions : UChar

+0x002 BeingDebugged : UChar // 프로세스가 디버깅되고 있는지를 나타냄.

+0x003 SpareBool : UChar

+0x004 Mutant : Ptr32 Void

+0x008 ImageBaseAddress : Ptr32 Void

+0x00c Ldr : Ptr32 _PEB_LDR_DATA // 프로세스에 로딩된 DLL 목록

+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS

+0x014 SubSystemData : Ptr32 Void

+0x018 ProcessHeap : Ptr32 Void // 프로세스의 힙 포인터

+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION

+0x020 FastPebLockRoutine : Ptr32 Void

+0x024 FastPebUnlockRoutine : Ptr32 Void

+0x028 EnvironmentUpdateCount : Uint4B

+0x02c KernelCallbackTable : Ptr32 Void

+0x030 SystemReserved : [1] Uint4B

+0x034 AtlThunkSListPtr32 : Uint4B

+0x038 FreeList : Ptr32 _PEB_FREE_BLOCK

+0x03c TlsExpansionCounter : Uint4B

+0x040 TlsBitmap : Ptr32 Void

+0x044 TlsBitmapBits : [2] Uint4B

+0x04c ReadOnlySharedMemoryBase : Ptr32 Void // 시스템 와이드한 Shared Memory

+0x050 ReadOnlySharedMemoryHeap : Ptr32 Void

+0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void

+0x058 AnsiCodePageData : Ptr32 Void

+0x05c OemCodePageData : Ptr32 Void

+0x060 UnicodeCaseTableData : Ptr32 Void

+0x064 NumberOfProcessors : Uint4B // CPU 개수

+0x068 NtGlobalFlag : Uint4B // NT Global Flag

+0x070 CriticalSectionTimeout : _LARGE_INTEGER

+0x078 HeapSegmentReserve : Uint4B // 예약되어 있는 힙메모리의 양

+0x07c HeapSegmentCommit : Uint4B // 할당되어 있는 힙메모리의 양

+0x080 HeapDeCommitTotalFreeThreshold : Uint4B

+0x084 HeapDeCommitFreeBlockThreshold : Uint4B

+0x088 NumberOfHeaps : Uint4B

+0x08c MaximumNumberOfHeaps : Uint4B

+0x090 ProcessHeaps : Ptr32 Ptr32 Void

+0x094 GdiSharedHandleTable : Ptr32 Void

+0x098 ProcessStarterHelper : Ptr32 Void

+0x09c GdiDCAttributeList : Uint4B

+0x0a0 LoaderLock : Ptr32 Void // PE 로더가 프로세스 로딩 중 사용하는 Lock

+0x0a4 OSMajorVersion : Uint4B // Windows의 버전 정보

+0x0a8 OSMinorVersion : Uint4B // Windows의 버전 정보

+0x0ac OSBuildNumber : Uint2B

+0x0ae OSCSDVersion : Uint2B // 서비스팩 버전 정보

+0x0b0 OSPlatformId : Uint4B // Server인지 Workstation인지와 같은 Platform ID

+0x0b4 ImageSubsystem : Uint4B // 프로세스의 서브시스템

+0x0b8 ImageSubsystemMajorVersion : Uint4B

+0x0bc ImageSubsystemMinorVersion : Uint4B

+0x0c0 ImageProcessAffinityMask : Uint4B

+0x0c4 GdiHandleBuffer : [34] Uint4B

+0x14c PostProcessInitRoutine : Ptr32 void

+0x150 TlsExpansionBitmap : Ptr32 Void

+0x154 TlsExpansionBitmapBits : [32] Uint4B

+0x1d4 SessionId : Uint4B

+0x1d8 AppCompatFlags : _ULARGE_INTEGER

+0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER

+0x1e8 pShimData : Ptr32 Void

+0x1ec AppCompatInfo : Ptr32 Void

+0x1f0 CSDVersion : _UNICODE_STRING // 서비스팩 버전 정보에 대한 문자열

+0x1f8 ActivationContextData : Ptr32 Void

+0x1fc ProcessAssemblyStorageMap : Ptr32 Void

+0x200 SystemDefaultActivationContextData : Ptr32 Void

+0x204 SystemAssemblyStorageMap : Ptr32 Void

+0x208 MinimumStackCommit : Uint4B


참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
TEB 구조  (0) 2016.07.05
Heap, FS, TEB, PEB  (0) 2016.07.05

(Windows XP 환경)


FS:[0x00] 현재 Structured Exception Handling (SEH) 프레임

FS:[0x04] 스택 베이스 / 스택의 바닥 (높은 주소)

FS:[0x08] 스택 한계 / 스택의 천장 (낮은 주소)

FS:[0x0C] SubSystemTib

FS:[0x10] Fiber data

FS:[0x14] 임의 데이터 슬롯

FS:[0x18] TIB의 선형 주소

---- NT subsystem 독립적인 부분 끝 ----

FS:[0x1C] Environment Pointer

FS:[0x20] 프로세스 ID (몇몇 윈도우 버전에서 이 필드는 'DebugContext'로 쓰인다.)

FS:[0x24] 현재 스레드 ID

FS:[0x28] 활동중인 RPC 핸들

FS:[0x2C] thread-local storage 배열의 선형 주소

FS:[0x30] Process Environment Block (PEB)의 선형 주소

FS:[0x34] 마지막 오류 번호

FS:[0x38] Count of owned critical sections

FS:[0x3C] CSR 클라이언트 스레드의 주소

FS:[0x40] Win32 스레드 정보

FS:[0x44] Win32 클라이언트 정보 (NT), user32 private data (Wine), 

0x60 = LastError (Win95), 0x74 = LastError (WinME)

FS:[0xC0] Reserved for Wow64. Wow64에서 FastSysCall에 대한 포인터를 포함한다.

FS:[0xC4] Current Locale

FS:[0xC8] FP Software Status Register

FS:[0xCC] Reserved for OS (NT), kernel32 private data (Wine)

herein: FS:[0x124] Pointer to KTHREAD (ETHREAD) structure

FS:[0x1A4] 예외 코드

FS:[0x1A8] Activation context stack

FS:[0x1BC] Spare bytes (NT), ntdll private data (Wine)

FS:[0x1D4] Reserved for OS (NT), ntdll private data (Wine)

FS:[0x1FC] GDI TEB Batch (OS), vm86 private data (Wine)

FS:[0x6DC] GDI Region

FS:[0x6E0] GDI 펜

FS:[0x6E4] GDI 브러시

FS:[0x6E8] Real Process ID

FS:[0x6EC] Real Thread ID

FS:[0x6F0] GDI cached process handle

FS:[0x6F4] GDI 클라이언트 프로세스 ID (PID)

FS:[0x6F8] GDI 클라이언트 스레드 ID (TID)

FS:[0x6FC] GDI thread locale information

FS:[0x700] Reserved for user application

FS:[0x714] Reserved for GL

FS:[0xBF4] 마지막 상태 값

FS:[0xBF8] Static UNICODE_STRING buffer

FS:[0xE0C] deallocation stack에 대한 포인터

FS:[0xE10] TLS 슬롯, 슬롯 당 4 byte

FS:[0xF10] TLS 링크 (LIST_ENTRY structure)

FS:[0xF18] VDM

FS:[0xF1C] Reserved for RPC

FS:[0xF28] 스레드 에러 모드(RtlSetThreadErrorMode)



참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
PEB 구조  (2) 2016.07.05
Heap, FS, TEB, PEB  (0) 2016.07.05

1. Heap 영역


1) Heap 영역이란?

 - 동적으로 메모리를 할당하는 영역


2) Heap 영역이 왜 필요한가?

 - 메모리를 효율적으로 사용하기 위해서 필요하다.


※추가설명 : 가상 메모리에서 메모리를 할당할 때에는 페이지 단위(4096byte)단위로 할당하는데, 만약 256byte 만큼의 적은 메모리만 사용하고 싶다고 했을때에도 4096byte를 할당해야하는 문제가 있다. 이러한 단점을 보안하기 위해서 Heap 메모리가 필요다.


※나중에 추가로 공부해야할 내용 : malloc, calloc, realloc 동적 메모리 할당


2. FS Register, TEB, PEB


1) FS Register

 - 커널 모드에서는 KPCR 구조체를 가리킨다.

 - 유저 모드에서는 TEB 구조체를 가리킨다.


2) TEB(Thread Envrionment Block)

 - 프로세스에서 실행되는 스레드에 대한 정보를 담고 있는 구조체

 - TIB(Thread Information Block)라고도 한다.

 - TEB 구조체는 OS마다 달라짐(Windows 7의 경우, Windows XP SP3보다 확장됨)

 - 시작 주소 : FS:[0x00], FS:[0x18] (유저 모드)


※ 왜 FS:[0x18]은 Self Field를 참조하고 있는걸까?

 - 미래에 TEB가 아닌 다른 구조체가 FS:[]로 바뀌어도, 0x18 오프셋은 TEB의 포인터를 가리키므로 후방 호환성이 유지되기 때문이라고 추측할 수 있다.


 - TEB 접근 방법

   Ntdll.NtCurrentTeb() : 현재 스레드의 TEB 구조체 주소를 리턴하는 함수

   Ntdll.NtCurrentTeb() API를 이용하면 된다.


3) PEB(Process Environment Block)

 - 프로세스의 정보를 저장하는 구조체

 - PEB 구조체는 OS마다 달라짐(Windows 7의 경우, Windows XP SP3보다 확장됐다.)

 - 시작주소는 OS마다 다르다.

   SP2 미만 → 0x7FFDF000

   SP2 이상 → fs:[0x30]

   win7 유저 모드 → fs:[0x30]

   win7 커널 모드 → fs:[0x18]

 

 - PEB 접근 방법

   TEB.ProcessEnvironmentBlock : PEB 구조체의 주소

   (FS:[30] = TEB.ProcessEnvironmentBloc = Address of PEB)

※Tip. OllyDbg로 디버깅을 시작할 때 EBX 레지스터에 PEB 주소가 저장되어있다.



[C언어로 TEB, PEB주소값 구하기 - NtCurrentTeb]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <windows.h>
 
int main(){
    FARPROC pProc = NULL;
    LPBYTE pTEB = NULL;
    LPBYTE pPEB = NULL;
 
    pProc = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCurrentTeb");
    pTEB = (LPBYTE)(*pProc)();
    pPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30);
 
    printf("TEB : %x\n", pTEB);
    printf("PEB : %x\n", pPEB);
 
    puts("");
}

cs





참고 : 리버싱 핵심원리(책), Windows 구조와 원리(책), MSDN

'Reversing' 카테고리의 다른 글

Static Anti-Debugging 0x02. LDR  (0) 2016.07.06
Static Anti-Debugging 0x01. IsDebuggerPresent()  (0) 2016.07.06
Anti-Debugging  (0) 2016.07.06
PEB 구조  (2) 2016.07.05
TEB 구조  (0) 2016.07.05

+ Recent posts