piano - #92

작곡공부 2012/04/08 09:42

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'작곡공부' 카테고리의 다른 글

piano - #92  (0) 2012/04/08
piano - #88-1  (0) 2012/04/02
piano - #85  (0) 2012/03/18
Trackback 0 : Comment 0

piano - #88-1

작곡공부 2012/04/02 21:03


뒷부분을 급하게 수습한...


저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License

'작곡공부' 카테고리의 다른 글

piano - #92  (0) 2012/04/08
piano - #88-1  (0) 2012/04/02
piano - #85  (0) 2012/03/18
Trackback 0 : Comment 0

piano - #85

작곡공부 2012/03/18 17:03



음 그냥 허접한 피아노 곡 만든거..
앞으로 간간히 이 블로그는 이런 것들이 올라올 가능성이 있습니다. ㅋ
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'작곡공부' 카테고리의 다른 글

piano - #92  (0) 2012/04/08
piano - #88-1  (0) 2012/04/02
piano - #85  (0) 2012/03/18
Trackback 0 : Comment 0

Windows 8 Consumer Preview에 TDI 지원

kernel mode 2012/03/10 11:12
TDI가 Windows 7까지 지원하고 Windows 8에서는 삭제 될 줄 알았는데 Windows 8에서도 지원을 하는군요.

빌어먹을 MS에서는 Windows 8에서 지원을 안 할꺼 같아서 WFP ( Windows Filtering Platform ) 로 패킷 필터링을 만들고 Windows XP는 TDI로 필터 드라이버를 만들고 있었는데 그냥 Windows XP용으로 만든걸 그대로 써도 상관이 없겠습니다.

WFP는 약간의 버그가 좀 있고 TDI Filter 에서 쉽게 되었던 부분을 WFP로 구현하려면 꽤나 많은 것들을 공부해야 되기 때문에 드라이버 개발자들이 WFP쪽으로 개발을 할려고 하지 않아서 그런 것 같습니다. 물론 MS측에서는 하위 호환성을 매우 중요시 여기기 때문에 그런 것도 있구요.

아래처럼 DeviceTree를 통해 TDI가 존재함을 볼 수 있습니다.

 


참고 :

Windows Driver Kit (WDK) 8 Consumer Preview 에서 아래와 같은 이슈사항이 있습니다.

TDI Filters and LSPs cannot be included in a certification submission: Network TDI filters and LSPs cannot be used by either kernel-mode or user-mode software or drivers. You cannot include TDI filters or LSPs in your Windows 8 Consumer Preview certification submission.
Workaround: Replace your TDI filter or LSP with WFP (Windows Filtering Platform).  

위에 내용은 TDI Filter 사용 시 윈도우즈 인증을 받을 수 없다라는 것을 의미하며 윈도우즈 인증을 받을려면 윈도우즈 필러링 플랫폼 ( WFP )을 사용하라는 내용입니다.

여기서 말하는 윈도우즈 인증이랑 이전에 알려진 윈도우즈 로고 인증을 의미합니다.
The Windows Certification Program (previously known as the Windows Logo Program) - http://msdn.microsoft.com/en-us/library/windows/hardware/gg463010.aspx )
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comments 3

Windows 8 블루스크린 스샷

kernel mode 2012/03/07 22:32
아시는 분은 다 아시겠지만 아래처럼 깔끔하게 바꼈습니다.
vmware 에서 캡쳐하는 바람에 글자가 매우 작게 나오네요.

 
저작자 표시
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comment 0

커널모드 드라이버에서 C 런타임 문자열 함수를 사용할 때에 주의점

kernel mode 2012/02/24 19:02
C 런타임 문자열 함수를 쓰면은 드라이버안에 문자열 함수가 임베디드 되어서 해당 함수를 호출할 수 있다고 생각 할 수도 있는데 인라인으로 들어가는 경우도 있고 그렇지 않은 경우가 있습니다.

그렇지 않은 경우에는 일반적으로 ntoskrnl.exe에 익스포트되어 있는 함수를 쓰게 됩니다. 이 때 IRQL에 상관없이 쓸 수 있는 함수와 그렇지 않은 함수가 있는데 예를 들어, toupper 함수에 경우 ( 대문자로 변경해주는 함수 ) DISPATCH_LEVEL 이상에서 사용할 경우 블루 스크린이 뜰 수 있습니다.

toupper 함수에 경우 ntoskrnl.exe 에서 익스포트되며, Windows 7 기준으로 논페이지드 메모리에 위치하는 함수입니다. 그리고 다음과 같이 내부적으로 동작합니다.

int __cdecl toupper(int a1)
{
  int result; // eax@2
  ULONG ResultSize; // [sp+0h] [bp-10h]@1
  WCHAR UnicodeString[2]; // [sp+4h] [bp-Ch]@1
  CHAR AnsiChar[4]; // [sp+8h] [bp-8h]@1
  CHAR MbString; // [sp+Ch] [bp-4h]@1
  unsigned __int8 v6; // [sp+Dh] [bp-3h]@4

  *(_DWORD *)AnsiChar = &a1;
  *(_DWORD *)UnicodeString = RtlAnsiCharToUnicodeChar((unsigned int)AnsiChar);
  if ( RtlUpcaseUnicodeToMultiByteN(&MbString, 2u, &ResultSize, UnicodeString, 2u) >= 0 )
  {
    result = (unsigned __int8)MbString;
    if ( ResultSize != 1 )
      result = v6 | ((unsigned __int8)MbString << 8);
  }
  else
  {
    result = a1;
  }
  return result;
}

이 함수가 내부적으로 호출하는 RtlAnsiCharToUnicodeChar 함수와  RtlUpcaseUnicodeToMultiByteN 함수는 둘 다 APC_LEVEL 이하에서만 동작가능합니다. 왜냐하면 해당 함수가 페이지드 메모리에 있기 때문입니다.

아래 메모리덤프는 toupper 함수를 DISPATCH_LEVEL에서 호출했을 때 생긴 덤프입니다.

kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 88a000aa, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, bitfield :
bit 0 : value 0 = read operation, 1 = write operation
bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: 82e7c4db, address which referenced memory

Debugging Details:
------------------


READ_ADDRESS:  88a000aa 

CURRENT_IRQL:  2

FAULTING_IP: 
nt!RtlMultiByteToUnicodeN+241
82e7c4db 668b0430        mov     ax,word ptr [eax+esi]

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0xA

PROCESS_NAME:  telnet.exe

TRAP_FRAME:  8d8f71c0 -- (.trap 0xffffffff8d8f71c0)
ErrCode = 00000000
eax=0000008e ebx=88a00220 ecx=8d8f7268 edx=8d8f7290 esi=88a0001c edi=00000000
eip=82e7c4db esp=8d8f7234 ebp=8d8f7240 iopl=0         nv up ei pl zr na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010246
nt!RtlMultiByteToUnicodeN+0x241:
Page 28e88 not present in the dump file. Type ".hh dbgerr004" for details
82e7c4db 668b0430        mov     ax,word ptr [eax+esi]    ds:0023:88a000aa=????
Resetting default scope

LAST_CONTROL_TRANSFER:  from 82e7c4db to 82c575cb

STACK_TEXT:  
8d8f71c0 82e7c4db badb0d00 8d8f7290 8d8f8000 nt!KiTrap0E+0x2cf
8d8f7240 82e7dad8 8d8f7268 00000002 00000000 nt!RtlMultiByteToUnicodeN+0x241
8d8f726c 82c3b153 8d8f7280 87be6900 8d8f729c nt!RtlAnsiCharToUnicodeChar+0x34
8d8f7288 92cb0282 00000047 8d8f741c 8d8f7400 nt!toupper+0x17


덤프만 보면 마치 toupper 함수에 잘못된 메모리주소 또는 페이지드 메모리주소를 넘겨서 에러가 발생한 것으로 보이지만 실제 에러위치인 nt!RtlMultiByteToUnicodeN+0x241 코드에서 참조하는 mov     ax,word ptr [eax+esi]    ds:0023:88a000aa=???? 는  _NlsAnsiToUnicodeData 변수를 참조하는데 이 변수가 페이지드 변수라서 블루 스크린이 뜨게 된것입니다.

에러 코드 위치:
PAGE:00649E0D                 mov     esi, ds:_NlsAnsiToUnicodeData
PAGE:00649E13                 mov     ax, [eax+esi] <= ds:_NlsAnsiToUnicodeData 를 참조하면서 오류가 남
PAGE:00649E17                 mov     [ecx], ax
PAGE:00649E1A                 inc     ecx
PAGE:00649E1B                 inc     ecx
PAGE:00649E1C                 inc     edx
PAGE:00649E1D
PAGE:00649E1D loc_649E1D:                             ; CODE XREF: RtlMultiByteToUnicodeN(x,x,x,x,x)+239j
PAGE:00649E1D                 test    edi, edi
PAGE:00649E1F                 jz      short loc_649E2C
PAGE:00649E21                 jmp     short loc_649DD1
PAGE:00649E23 ; ---------------------------------------------------------------------------
PAGE:00649E23                 jmp     short loc_649E2C


위에 덤프에 경우 RtlAnsiCharToUnicodeChar 함수와 RtlMultiByteToUnicodeN가 페이지 아웃 된 상태가 아니기 때문에 데이터 참조에 대한 오류가 발생한 것이고, 호출당시 페이지 아웃되어 있는 상태라면 execute operation 오류가 나게 됩니다. ( IRQL_NOT_LESS_OR_EQUAL Arg3 값이 8을 가집니다. )

따라서 toupper 함수는 사용할 수 없으며, 아래처럼 직접 만들어서 사용해야 합니다.

CHAR MyToupper(CHAR ch)
{
if(ch >= 'a' && ch <= 'z')
{
ch -= 32;
}
return ch;
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comments 2

IRQL에 따른 스레드 선점에 대한 주의사항

kernel mode 2012/01/15 19:01
윈도우즈 커널이나 드라이버에 대한 설명을 나온 책을 보면 항상 IRQL 에 따른 스레드 선점에 대한 얘기가 나오는데 다음과 같은 내용은 오해를 불러일으킬 소지가 있습니다.

"낮은 수준의 IRQL에서 실행하는 코드(스레드)는 높은 수준의 IRQL의 작업이 발생하게 되면 항상 선점된다."
"상승 된 IRQL에 코드는 상승 된 IRQL보다 낮은 레벨에 코드가 실행되는 것을 블록시킨다."

그러나 위에 사항들은 예외적일 수 있습니다.

예를 들어, 스레드 A가 APC_LEVEL로 실행중이고, 스레드 B는 이전에 PASSIVE_LEVEL에서 실행중이었다라고 가정합니다. 그렇다면 스레드 A가 APC_LEVEL로 실행중이기 때문에 스레드 B보다 IRQL이 높으므로 스레드A가 PASSIVE_LEVEL로 IRQL이 내려가지 않는 이상은 스레드 B에 코드는 실행되지 않을 것으로 예상 할 수 있습니다.

하지만 그렇지 않습니다. 스레드 A가 APC_LEVEL로 실행중이더라도, 커널 스케쥴러에 의해 스레드 B를 스케쥴링하고 PASSIVE_LEVEL로 실행하게 됩니다. 즉, APC_LEVEL로 실행중이던 스레드 A는 PASSIVE_LEVEL로 실행중인 스레드 B에 선점당하게 됩니다.

( 위에 사항들은 멀티 CPU일 경우를 말하는것이 아닙니다. 싱글 CPU도 마찬가지입니다. )

이렇게 되는 이유는 IRQL이 프로세서 종속적인 IRQL과 스레드 종속적인 IRQL로 나뉘어지기 때문입니다.

프로세서 종속적인 IRQL은 DISPATCH_LEVEL 이상에 IRQL을 의미합니다. 이 경우에는 우리가 이미 알고 있는 IRQL에 선점 및 블록에 대한 규칙과 똑같습니다.

스레드 종송적인 IRQL은 DISPATCH_LEVEL 보다 낮은 IRQL을 의미합니다.
APC_LEVEL, PASSIVE_LEVEL IRQL이 있습니다. ( 시스템 내부적으로 PASSIVE_LEVEL width critical region 이라는 가상에 IRQL도 있습니다. guarded region 이라고 Windows 2003 Server부터 추가 된 부분도 있는데 참고용으로 적어둡니다.)

스레드 종속적이다라는 말은 현재 스레드에 한해서만 영향을 끼치는 IRQL라는 의미입니다. 예를 들어, 스레드 A가 PASSIVE_LEVEL로 실행중일 때 스레드 A에 APC 루틴이 실행되어야 할 경우 스레드 A는 APC에 의해 선점 될 수 있습니다. 이 때 선점당한다라는 말은 다른 스레드에 선점당한다는것이 아니라 자기자신에 스레드에게 선점당한다는 의미입니다. 스레드 A는 스레드 A에 APC 루틴에 의해 선점당한 상황이 발생하게 된다는 것을 의미합니다.

스레드 종송적인 IRQL이 구현될 수 있는 것은 스레드 스케쥴러와 연관이 있습니다.

MS에 "Scheduling, Thread Context, and IRQL"라는 문서에 다음과 같은 문장이 있습니다.

The thread scheduler considers only thread priority, and not IRQL, when preempting a thread. If a thread running at IRQL=APC_LEVEL blocks, the scheduler might select a new thread for the processor that was previously running at PASSIVE_LEVEL.

스레드 스케쥴러는 오직 스레드에 우선순위만 고려할 뿐 IRQL은 전혀 고려하지 않습니다. 어떤 스레드가 APC_LEVEL로 실행중이더라도 스케쥴러는 이전에 PASSIVE_LEVEL로 실행중인 스레드로 스케쥴링 할 수 있습니다.

또한 스레드 스케쥴러는 DISPATCH_LEVEL에서 동작하게 됩니다. ( 그래야 원하는 시점에 DISPATCH_LEVEL보다 낮은 스레드를 선점해서 다른 스레드로 스케쥴링 할 수 있겠죠. )


 
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comments 2

커널에서 SpinLock을 사용 할 때에 주의점

kernel mode 2012/01/13 18:03
기본적인 부분들에 대해서 정리해둡니다.

-  KeAcquireSpinLock 으로 락을 획득 후, 페이지드 메모리에 접근하면 안됩니다. 이는 IRQL이 DISPATCH_LEVEL로 상승하기 때문입니다. ( 논페이지드 메모리에만 접근가능합니다. )

-  KeAcquireSpinLock 으로 락을 획득 후, 외부 함수를 호출 할 때, 외부 함수가 페이지드 된 메모리에 접근하거나 예외를 발생시켜선 안됩니다.

-  KeAcquireSpinLock 으로 락을 획득 후, 락을 획득한 함수가 재귀호출되어선 안됩니다.

-  KeAcquireSpinLock 으로 락을 획득 후, KeReleaseSpinLock로 락을 해제하기까지 25 마이크로 세컨드 이상 걸리면 안됩니다. ( 강제사항은 아지만 DISPATCH_LEVEL에 너무 오랫동안 머물러 있어서는 안된다라는 말입니다. )

- 자체적으로 SpinLock을 만들어서 사용하지 않고 WDK 함수를 사용하는 것이 좋습니다. 예를 들어, KeAcquireSpinLock  함수는 DISPATCH_LEVEL로 IRQL를 올리게 되는데, 만약 일반적인 스핀락을 자체적으로 구현하고 IRQL를 올리지 않을 경우 다음과 같은 시나리오로 데드락에 빠질 수 있습니다.

싱글 CPU를 예로 들자면, PASSIVE_LEVEL에 스레드에서 자체적으로 구현한 스핀락을 획득하고 코드가 실행 중에 DPC 루틴이 실행되었고 DPC 루틴에서 자체적으로 구현한 스핀락을 획득하려고 할 경우 현재 DISPATCH_LEVEL에서 코드가 실행중이기 때문에, PASSIVE_LEVEL에서 얻은 스핀락을 해제하기 위한 스레드가 스레드 스케줄링이 되지 않기 때문에 데드락에 걸립니다.
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comment 0

ObRegisterCallbacks 함수에 PreOperation, PostOperation 콜백은 어떻게 호출될까?

kernel mode 2011/11/08 18:51
참고사항 : 운영체제는 Windows 7 x86 SP1 입니다.

ObRegisterCallbacks 함수는 Windows Vista SP1이상에서 추가 된 커널 오브젝트 생성에 대한 필터링을 할 수 있는 함수입니다. ( 현재는 프로세스와 스레드에 대한 오브젝트만 지원하고 있습니다. )

ObRegisterCallbacks 함수를 이용하면, 단순한 필터링만 하는것이 아니라, 특정 프로세스를 종료하지 못 하게 한다던지 할수가 있는데 해당 함수를 통해 필터링 시 콜백함수가 언제 호출되는지에 대한 정보가 없어서 알아보았습니다. 직접 ObRegisterCallbacks 함수를 사용하는 코드를 작성하여 테스트 할 수 있으나 서명등에 압박이 있어서 이미 이를 사용하고 있는 제품중에 Microsoft Security Essentials 라는 백신이 있어서 해당 백신을 통해서 알아보도록 합니다.

Microsoft Security Essentials ( 이하 MSE로 명칭 ) 를 다음과 같이 설치할 때 nt!ObRegisterCallbacks 에 브레이크 포인터를 걸면 브레이크 포인트가 걸립니다.



nt!ObRegisterCallbacks:
82f1b1f9 8bff            mov     edi,edi

콜스택을 보면 MpFilter.sys에서 호출함을 볼 수 있는데 MSE에서 사용하는 드라이버로 Minifilter 코드도 포함되어 있습니다.

kd> k
ChildEBP RetAddr  
807efa24 91d57d13 nt!ObRegisterCallbacks
WARNING: Stack unwind information not available. Following frames may be wrong.
807efa74 91d57ea8 MpFilter+0x20d13
807efaa4 91d56e03 MpFilter+0x20ea8
807efad8 82e092e6 MpFilter+0x1fe03
807efcbc 82e0cd98 nt!IopLoadDriver+0x7ed
807efd00 82cc2aab nt!IopLoadUnloadDriver+0x70
807efd50 82e4ef5e nt!ExpWorkerThread+0x10d
807efd90 82cf6219 nt!PspSystemThreadStartup+0x9e
00000000 00000000 nt!KiThreadStartup+0x19 

이 상태에서 스택을 보면..

kd> dd esp
807efa28  91d57d13 807efa40 807efa6c 00000000
807efa38  82e0e47d 82f1b1f9 00010100 000e000c
807efa48  91d58e76 00000000 807efa54 82daf02c
807efa58  00000003 91d5148e 00000000 000e000c
807efa68  91d58e76 00000000 c0000001 807efaa4
807efa78  91d57ea8 807efa9c 82c7c50e 91d3bd80
807efa88  91d3b2a8 002c002a 91d58ef4 00280026
807efa98  91d58f20 00000000 00000000 807efad8

여기서 POB_CALLBACK_REGISTRATION 은 807efa40 임을 볼 수 있습니다.
807efa40 값을 덤프해보면..

kd> dd 807efa40 
807efa40  00010100 000e000c 91d58e76 00000000
807efa50  807efa54 82daf02c 00000003 91d5148e
807efa60  00000000 000e000c 91d58e76 00000000
807efa70  c0000001 807efaa4 91d57ea8 807efa9c
807efa80  82c7c50e 91d3bd80 91d3b2a8 002c002a
807efa90  91d58ef4 00280026 91d58f20 00000000
807efaa0  00000000 807efad8 91d56e03 11ad7e08
807efab0  85b6f000 85b64dd0 00000000 00000000 

807efa54 이 OB_OPERATION_REGISTRATION 구조체이며, 다시 이를 덤프하면,

kd> dd 807efa54 
807efa54  82daf02c 00000003 91d5148e 00000000
807efa64  000e000c 91d58e76 00000000 c0000001
807efa74  807efaa4 91d57ea8 807efa9c 82c7c50e
807efa84  91d3bd80 91d3b2a8 002c002a 91d58ef4
807efa94  00280026 91d58f20 00000000 00000000
807efaa4  807efad8 91d56e03 11ad7e08 85b6f000
807efab4  85b64dd0 00000000 00000000 807efaac
807efac4  40000000 807efd80 91d39e70 00003890 

Operations은 ( OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE ) 이며, PreOperation에 경우 91d5148e 임을 알 수 있습니다.

91d5148e 이 PreOperation 이며 다음과 같이 생겼습니다.

kd> u 91d5148e 
MpFilter+0x1a48e:
91d5148e 8bff            mov     edi,edi
91d51490 55              push    ebp
91d51491 8bec            mov     ebp,esp
91d51493 8b0d98aed391    mov     ecx,dword ptr [MpFilter+0x3e98 (91d3ae98)]
91d51499 56              push    esi
91d5149a 8b750c          mov     esi,dword ptr [ebp+0Ch]
91d5149d 8b460c          mov     eax,dword ptr [esi+0Ch]
91d514a0 57              push    edi

이제 아래에 콜백에 브레이크 포인트를 걸어보면,

kd> bp 91d5148e 


오브젝트 핸들이 생성될 때 다음과 같은 콜스택을 얻을 수 있습니다.

kd> k
ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
8bd478b0 82f1b748 MpFilter+0x1a48e
8bd478f8 82f1b935 nt!ObpCallPreOperationCallbacks+0x163
8bd47940 82e69b99 nt!ObpPreInterceptHandleCreate+0x6f
8bd479a0 82e87630 nt!ObpCreateHandle+0x219
8bd47b20 82e92688 nt!ObOpenObjectByPointerWithTag+0xc1
8bd47b48 82ebd09e nt!ObOpenObjectByPointer+0x24
8bd47cfc 82e58a09 nt!PsOpenProcess+0x231
8bd47d1c 82c831ea nt!NtOpenProcess+0x2d
8bd47d1c 771e70b4 nt!KiFastCallEntry+0x12a
004af680 6d38fca4 0x771e70b4
004af698 6d3b3dd9 0x6d38fca4
004af6e0 6d151bed 0x6d3b3dd9
004af744 6d15368a 0x6d151bed
004af7d4 6d148d52 0x6d15368a
004af7dc 6d318b87 0x6d148d52
004af80c 6d318c03 0x6d318b87
004af814 6d31b3b6 0x6d318c03
004af820 771b2661 0x6d31b3b6
004af844 771d0842 0x771b2661
004af9a4 76ec3c45 0x771d0842
004af9b0 772037f5 0x76ec3c45
004af9f0 772037c8 0x772037f5
004afa08 00000000 0x772037c8

ObpCreateHandle 함수를 보면 다음과 같고, ObpPreInterceptHandleCreate 함수를 호출하면서 오브젝트 매니저 콜백을 호출하게 됩니다.

int __stdcall ObpCreateHandle(int a2, int a3, int AccessMask, int a5, unsigned int a6, int a7, int a8, int a9, int a10, int a11)
{
  ULONG_PTR v10; // ecx@3
  int v11; // edi@6
  int result; // eax@7
  int v13; // eax@14
  int v14; // esi@14
  int v16; // esi@25
  int v17; // eax@26
  unsigned int v25; // esi@37
  int v32; // eax@48
  unsigned int v33; // esi@49
  int v40; // edi@56
  int v41; // eax@59
  int v43; // esi@59
  int v45; // eax@72
  char v46; // [sp+13h] [bp-35h]@1
  int v47; // [sp+14h] [bp-34h]@7
  int v48; // [sp+18h] [bp-30h]@48
  ULONG_PTR BugCheckParameter1; // [sp+1Ch] [bp-2Ch]@2
  int v50; // [sp+20h] [bp-28h]@2
  int v51; // [sp+24h] [bp-24h]@4
  int v52; // [sp+28h] [bp-20h]@1
  int v53; // [sp+2Ch] [bp-1Ch]@1
  int v54; // [sp+30h] [bp-18h]@36
  int v55; // [sp+34h] [bp-14h]@62
  int *v56; // [sp+38h] [bp-10h]@34
  int *v57; // [sp+3Ch] [bp-Ch]@34
  char v58; // [sp+40h] [bp-8h]@48

  v53 = 0;
  v52 = 0;
  v46 = 0;
  if ( a7 & 0x200 )
  {
    v50 = ObpKernelHandleTable;
    BugCheckParameter1 = PsInitialSystemProcess;
LABEL_4:
    LOBYTE(v51) = 1;
    goto LABEL_6;
  }
  v10 = *(_DWORD *)(*MK_FP(__FS__, 292) + 80);
  v50 = *(_DWORD *)(*(_DWORD *)(*MK_FP(__FS__, 292) + 80) + 244);
  BugCheckParameter1 = v10;
  if ( v50 == ObpKernelHandleTable )
    goto LABEL_4;
  LOBYTE(v51) = 0;
LABEL_6:
  v11 = a5;
  if ( a5 )
  {
    result = ObpGrantAccess(a3, a8, a2, a5, a7, (int)&v47);
    if ( result < 0 )
      return result;
  }
  else
  {
    if ( AccessMask & 0x2000000 )
      AccessMask = AccessMask & 0xFDFFFFFF | 0x10000000;
    if ( AccessMask & 0xF0000000 )
      RtlMapGenericMask((PACCESS_MASK)&AccessMask, (PGENERIC_MAPPING)(*(&ObTypeIndexTable + *(_BYTE *)(a3 - 12)) + 52));
    v47 = AccessMask;
  }
  v14 = a9;
  v13 = 0;
  if ( a9 )
    v13 = *(_DWORD *)(a9 + 24);
  result = ObpIncrementHandleCountEx(a2, (int)&v47, BugCheckParameter1, a3, a8, a7, v13);
  if ( result >= 0 )
  {
    if ( v11 )
    {
      if ( v14 )
      {
        result = ObpInsertOrLocateNamedObject(BugCheckParameter1, &v47, v11, a8, v14, &v52);
        if ( result < 0 )
          return result;
        if ( v52 == a3 )
        {
          v52 = 0;
        }
        else
        {
          a3 = v52;
          v46 = 1;
        }
      }
      if ( *(_BYTE *)(v11 + 10) )
        a7 |= 4u;
    }
    v16 = *(&ObTypeIndexTable + *(_BYTE *)(a3 - 12));
    _EBX = a3 - 24;
    v47 &= *(_DWORD *)(v16 + 68) | 0x1000000;
    if ( v11 )
    {
      v17 = SeComputeCreatorDeniedRights(v11 + 28, v47, a3);
      v47 &= ~v17;
      *(_DWORD *)(v11 + 20) = v47;
      v53 = *(_DWORD *)(*(_DWORD *)(v11 + 48) + 24);
    }
    if ( a6 )
    {
      if ( ObpTraceFlags )
      {
        if ( *(_BYTE *)(_EBX + 13) & 1 )
          ObpPushStackInfo(_EBX, 1, a6, 1953261124);
      }
      _EAX = a6;
      _ECX = a3 - 24;
      __asm { lock xadd [ecx], eax }
    }
    if ( v52 )
      ObfDereferenceObject(v52);
    v57 = (int *)&v56;
    v56 = (int *)&v56;
    if ( *(_BYTE *)(v16 + 42) & 0x40 && *(_DWORD *)(v16 + 128) != v16 + 128 )
    {
      v54 = v47;
      v52 = ObpPreInterceptHandleCreate(a3, v51, &v54, &v56);
      if ( v52 < 0 )
      {
        ObpDecrementHandleCount(BugCheckParameter1);
        v25 = a6;
        if ( a6 )
        {
          if ( a6 > 1 )
          {
            if ( ObpTraceFlags )
            {
              if ( *(_BYTE *)(_EBX + 13) & 1 )
                ObpPushStackInfo(_EBX, 0, a6 - 1, 1953261124);
            }
            _EAX = 1 - v25;
            __asm { lock xadd [ebx], eax }
          }
          ObfDereferenceObject(a3);
        }
        return v52;
      }
      if ( !(_BYTE)v51 )
      {
        v47 = v54;
        if ( v11 )
          *(_DWORD *)(v11 + 20) = v54;
      }
    }
    ObpInitializeHandleTableEntry(_EBX, a8);
    v32 = ExCreateHandle(v50, &v58);
    v48 = v32;
    if ( v32 )
    {
      if ( v11 )
      {
        if ( v53 )
        {
          v43 = *MK_FP(__FS__, 292);
          --*(_WORD *)(v43 + 132);
          v41 = ExMapHandleToPointer(v32);
          _EDI = v41;
          if ( v41 )
          {
            if ( (*(_DWORD *)v41 & 0xFFFFFFF8) == _EBX )
              ExSetHandleInfo(&v53);
            _EAX = 1;
            __asm { lock or [edi], eax }
            v55 = 1;
            if ( *(_DWORD *)(v50 + 24) )
              ExfUnblockPushLock(v50 + 24, 0);
          }
          ++*(_WORD *)(v43 + 132);
          if ( !*(_WORD *)(v43 + 132) )
          {
            if ( *(_DWORD *)(v43 + 64) != v43 + 64 )
            {
              if ( !*(_WORD *)(v43 + 134) )
                KiCheckForKernelApcDelivery();
            }
          }
          v11 = a5;
        }
        if ( *(_BYTE *)(v11 + 9) )
          SeAuditHandleCreation(v48);
        if ( !a2 )
        {
          v45 = **(_DWORD **)(v11 + 48);
          if ( v45 )
          {
            if ( *(_DWORD *)v45 )
              SePrivilegeObjectAuditAlarm(
                v48,
                v11 + 28,
                *(_DWORD *)(v11 + 20),
                v45,
                1,
                *(_BYTE *)(*MK_FP(__FS__, 292) + 314));
          }
        }
      }
      if ( a6 )
      {
        if ( a10 )
          *(_DWORD *)a10 = a3;
      }
      v40 = (unsigned __int8)v46 != 0 ? 0x40000000 : 0;
      if ( (_BYTE)v51 == 1 )
        v48 |= 0x80000000u;
      *(_DWORD *)a11 = v48;
    }
    else
    {
      ObpDecrementHandleCount(BugCheckParameter1);
      v33 = a6;
      if ( a6 )
      {
        if ( a6 > 1 )
        {
          if ( ObpTraceFlags )
          {
            if ( *(_BYTE *)(_EBX + 13) & 1 )
              ObpPushStackInfo(_EBX, 0, a6 - 1, 1953261124);
          }
          _EAX = 1 - v33;
          __asm { lock xadd [ebx], eax }
        }
        ObfDereferenceObject(a3);
      }
      v40 = -1073741670;
    }
    if ( (int **)v56 != &v56 )
      ObpPostInterceptHandleCreate(v51, v40, v47);
    result = v40;
  }
  return result;
}
 

핸들에 새로운 생성이 아닌 Duplicate를 할 경우에는 콜스택이 다음과 같고, ObpPreInterceptHandleDuplicate 함수를 통해서 콜백이 호출됩니다.

kd> k
ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
8c2f3a38 82f1b748 MpFilter+0x1a48e
8c2f3a80 82f1b9d8 nt!ObpCallPreOperationCallbacks+0x163
8c2f3ac8 82e7b2e0 nt!ObpPreInterceptHandleDuplicate+0x7d
8c2f3cac 82e785c9 nt!ObDuplicateObject+0x34d
8c2f3d10 82c831ea nt!NtDuplicateObject+0xd9
8c2f3d10 771e70b4 nt!KiFastCallEntry+0x12a
01fbfa24 75354d55 0x771e70b4
01fbfb98 771a5e7a 0x75354d55
01fbfbd8 772037c8 0x771a5e7a
01fbfbf0 00000000 0x772037c8

signed int __thiscall ObDuplicateObject(void *BugCheckParameter1, void *a2, ULONG_PTR a3, int a4, int AccessMask, int a6, char a7, int a8)
{
  ULONG_PTR v8; // ebx@1
  ULONG_PTR v9; // edi@1
  int v11; // eax@9
  signed int v12; // esi@11
  int v13; // eax@23
  int v14; // esi@27
  int v15; // edi@32
  char *v16; // ebx@34
  int v17; // eax@54
  int v18; // eax@61
  int v19; // ebx@61
  int v20; // eax@63
  int v22; // esi@63
  int v24; // eax@76
  char v25; // [sp+Ch] [bp-1B4h]@1
  int v26; // [sp+10h] [bp-1B0h]@38
  ULONG_PTR v27; // [sp+14h] [bp-1ACh]@1
  char v28; // [sp+1Bh] [bp-1A5h]@34
  int v29; // [sp+1Ch] [bp-1A4h]@34
  int v30; // [sp+20h] [bp-1A0h]@11
  ULONG_PTR v31; // [sp+24h] [bp-19Ch]@1
  char *v32; // [sp+28h] [bp-198h]@34
  HANDLE Handle; // [sp+2Ch] [bp-194h]@1
  int v34; // [sp+30h] [bp-190h]@12
  int v35; // [sp+34h] [bp-18Ch]@27
  int v36; // [sp+38h] [bp-188h]@32
  int *v37; // [sp+3Ch] [bp-184h]@55
  int *v38; // [sp+40h] [bp-180h]@55
  int v39; // [sp+44h] [bp-17Ch]@6
  int v40; // [sp+48h] [bp-178h]@23
  int v41; // [sp+4Ch] [bp-174h]@1
  int v42; // [sp+50h] [bp-170h]@1
  int v43; // [sp+54h] [bp-16Ch]@11
  ACCESS_MASK v44; // [sp+58h] [bp-168h]@27
  int v45; // [sp+5Ch] [bp-164h]@66
  int v46; // [sp+60h] [bp-160h]@18
  char v47; // [sp+78h] [bp-148h]@61
  char v48; // [sp+80h] [bp-140h]@38
  char v49; // [sp+F8h] [bp-C8h]@38
  unsigned int v50; // [sp+1BCh] [bp-4h]@1

  v50 = (unsigned int)&v25 ^ __security_cookie;
  v41 = 0;
  v8 = a3;
  Handle = a2;
  v9 = (ULONG_PTR)BugCheckParameter1;
  v31 = (ULONG_PTR)BugCheckParameter1;
  v27 = a3;
  v42 = a4;
  if ( a6 & 0x200 )
  {
    if ( !(_BYTE)a8 )
    {
      v8 = PsInitialSystemProcess;
      v27 = PsInitialSystemProcess;
    }
  }
  a6 &= 0xFFFFFDFFu;
  if ( a4 )
    *(_DWORD *)a4 = 0;
  v39 = a7 & 2;
  if ( !(a7 & 2) && AccessMask & 0xCE00000 )
    return -1073741790;
  v11 = ObReferenceProcessHandleTable();
  if ( !v11 )
    return -1073741558;
  v12 = ObpReferenceProcessObjectByHandleWithTag(Handle, v11, a8, &v30, &v43, &v41);
  if ( v12 < 0 )
  {
    ObDereferenceProcessHandleTable(v9);
    return v12;
  }
  v34 = v43 & 4;
  if ( !(v43 & 4) )
    v41 = 0;
  if ( !v8 )
  {
    if ( !(a7 & 1) )
      v12 = -1073741811;
    if ( a7 & 1 )
    {
      KeStackAttachProcess(v9, (int)&v46);
      NtClose(Handle);
      KeUnstackDetachProcess(&v46);
    }
LABEL_19:
    ObDereferenceProcessHandleTable(v9);
LABEL_20:
    ObfDereferenceObject(v30);
    return v12;
  }
  v13 = ObReferenceProcessHandleTable();
  v40 = v13;
  if ( !v13 )
  {
    if ( a7 & 1 )
    {
      KeStackAttachProcess(v9, (int)&v46);
      NtClose(Handle);
      KeUnstackDetachProcess(&v46);
    }
    v12 = -1073741558;
    goto LABEL_19;
  }
  v14 = v44;
  LOBYTE(v35) = v13 == ObpKernelHandleTable;
  if ( v39 )
    AccessMask = v44;
  if ( a7 & 4 )
    a6 = v43;
  else
    a6 |= v34;
  v36 = v30 - 24;
  v15 = *(&ObTypeIndexTable + *(_BYTE *)(v30 - 24 + 12));
  v34 = v41;
  if ( AccessMask & 0xF0000000 )
    RtlMapGenericMask((PACCESS_MASK)&AccessMask, (PGENERIC_MAPPING)(v15 + 52));
  v16 = 0;
  v29 = AccessMask & (*(_DWORD *)(v15 + 68) | 0x1000000);
  v28 = 0;
  v32 = 0;
  if ( !(~v14 & v29) )
  {
    v26 = 0;
LABEL_42:
    if ( v26 >= 0 )
      v26 = ObpIncrementHandleCount(2, (int)&v29, v27, v30, a8, a6);
    goto LABEL_44;
  }
  if ( *(int (__stdcall **)(int, int, int, PVOID, int, int, POOL_TYPE, GENERIC_MAPPING *, int))(v15 + 108) != SeDefaultObjectMethod )
  {
    v26 = -1073741790;
    goto LABEL_42;
  }
  if ( *(_DWORD *)(*MK_FP(__FS__, 292) + 80) != v27 )
  {
    KeStackAttachProcess(v27, (int)&v46);
    v28 = 1;
  }
  v16 = &v48;
  v26 = SeCreateAccessState(&v48, &v49, v29, (PGENERIC_MAPPING)(v15 + 52));
  v32 = &v48;
  if ( v26 >= 0 )
  {
    v26 = ObpGrantAccess(v30, a8, 2, (int)&v48, a6, (int)&v29);
    goto LABEL_42;
  }
LABEL_44:
  if ( v28 )
    KeUnstackDetachProcess(&v46);
  if ( a7 & 1 )
  {
    KeStackAttachProcess(v31, (int)&v46);
    NtClose(Handle);
    KeUnstackDetachProcess(&v46);
  }
  if ( v26 < 0 )
    goto LABEL_49;
  if ( v16 )
  {
    if ( v16[10] == 1 )
    {
      v17 = *(_DWORD *)(*((_DWORD *)v16 + 12) + 24);
      a6 |= 4u;
      v34 = v17;
    }
  }
  v38 = (int *)&v37;
  v37 = (int *)&v37;
  if ( *(_BYTE *)(v15 + 42) & 0x40 && *(_DWORD *)(v15 + 128) != v15 + 128 )
  {
    v39 = v29;
    v26 = ObpPreInterceptHandleDuplicate(v30, v35, &v39, v31, v27, &v37);
    if ( v26 < 0 )
    {
      ObpDecrementHandleCount(v27);
LABEL_49:
      if ( v16 )
        SeDeleteAccessState(v16);
      ObDereferenceProcessHandleTable(v31);
      ObDereferenceProcessHandleTable(v27);
      v12 = v26;
      goto LABEL_20;
    }
    if ( !(_BYTE)v35 )
      v29 = v39;
  }
  ObpInitializeHandleTableEntry(v36, a8);
  v18 = ExCreateHandle(v40, &v47);
  v19 = v18;
  if ( v18 )
  {
    if ( v34 )
    {
      v22 = *MK_FP(__FS__, 292);
      --*(_WORD *)(v22 + 132);
      v20 = ExMapHandleToPointer(v18);
      _EDI = v20;
      if ( v20 )
      {
        if ( (*(_DWORD *)v20 & 0xFFFFFFF8) == v36 )
          ExSetHandleInfo(&v34);
        _EAX = 1;
        __asm { lock or [edi], eax }
        v45 = 1;
        if ( *(_DWORD *)(v40 + 24) )
          ExfUnblockPushLock(v40 + 24, 0);
      }
      ++*(_WORD *)(v22 + 132);
      if ( !*(_WORD *)(v22 + 132) )
      {
        if ( *(_DWORD *)(v22 + 64) != v22 + 64 )
        {
          if ( !*(_WORD *)(v22 + 134) )
            KiCheckForKernelApcDelivery();
        }
      }
    }
    if ( v32 )
      SeAuditHandleCreation(v19);
    if ( v47 & 4 )
    {
      if ( v32 )
      {
        v24 = *((_DWORD *)v32 + 7);
        if ( !v24 )
          v24 = *((_DWORD *)v32 + 9);
      }
      else
      {
        v24 = 0;
      }
      if ( (unsigned __int8)SeAuditingWithTokenForSubcategory(121, v24) )
        SeAuditHandleDuplication(Handle, v19, v31, v27);
    }
  }
  else
  {
    ObpDecrementHandleCount(v27);
    ObfDereferenceObject(v30);
    v26 = -1073741670;
  }
  if ( (_BYTE)v35 == 1 )
    v19 |= 0x80000000u;
  if ( v42 )
    *(_DWORD *)v42 = v19;
  if ( v32 )
    SeDeleteAccessState(v32);
  ObDereferenceProcessHandleTable(v31);
  ObDereferenceProcessHandleTable(v27);
  if ( (int **)v37 != &v37 )
    ObpPostInterceptHandleDuplicate(v35, v26, v29);
  return v26;
}


추가로 PostOperation에 경우 위에서 PreOperation 함수를 호출하는 루틴에서 핸들 생성과 Duplicate에 대해서 각각 ObpPostInterceptHandleCreate, ObpPostInterceptHandleDuplicate 함수를 호출하게 됩니다. 
 
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comment 0

Windbg, livekd에서 dt명령어를 사용할 때에 주의점

kernel mode 2011/11/06 10:29
EPROCESS 구조체를 확인 후 EPROCESS 구조체에 직접 접근해서 PEB를 가져온다고 했을 경우 EPROCESS 구조체에 타입을 알기 위해서 일반적으로 다음과 같은 명령을 사용합니다.

dt _EPROCESS

그러면 다음과 같이 출력이 되는데 ( Windows 7 x64 SP1 )

ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x160 ProcessLock      : _EX_PUSH_LOCK
   +0x168 CreateTime       : _LARGE_INTEGER
   +0x170 ExitTime         : _LARGE_INTEGER
   +0x178 RundownProtect   : _EX_RUNDOWN_REF
   +0x180 UniqueProcessId  : Ptr64 Void
   +0x188 ActiveProcessLinks : _LIST_ENTRY
   +0x198 ProcessQuotaUsage : [2] Uint8B
   +0x1a8 ProcessQuotaPeak : [2] Uint8B
   +0x1b8 CommitCharge     : Uint8B
   +0x1c0 QuotaBlock       : Ptr64 _EPROCESS_QUOTA_BLOCK
   +0x1c8 CpuQuotaBlock    : Ptr64 _PS_CPU_QUOTA_BLOCK
   +0x1d0 PeakVirtualSize  : Uint8B
   +0x1d8 VirtualSize      : Uint8B
   +0x1e0 SessionProcessLinks : _LIST_ENTRY
   +0x1f0 DebugPort        : Ptr64 Void
   +0x1f8 ExceptionPortData : Ptr64 Void
   +0x1f8 ExceptionPortValue : Uint8B
   +0x1f8 ExceptionPortState : Pos 0, 3 Bits
   +0x200 ObjectTable      : Ptr64 _HANDLE_TABLE
   +0x208 Token            : _EX_FAST_REF
   +0x210 WorkingSetPage   : Uint8B
   +0x218 AddressCreationLock : _EX_PUSH_LOCK
   +0x220 RotateInProgress : Ptr64 _ETHREAD
   +0x228 ForkInProgress   : Ptr64 _ETHREAD
   +0x230 HardwareTrigger  : Uint8B
   +0x238 PhysicalVadRoot  : Ptr64 _MM_AVL_TABLE
   +0x240 CloneRoot        : Ptr64 Void
   +0x248 NumberOfPrivatePages : Uint8B
   +0x250 NumberOfLockedPages : Uint8B
   +0x258 Win32Process     : Ptr64 Void
   +0x260 Job              : Ptr64 _EJOB
   +0x268 SectionObject    : Ptr64 Void
   +0x270 SectionBaseAddress : Ptr64 Void
   +0x278 Cookie           : Uint4B
   +0x27c Spare8           : Uint4B
   +0x280 WorkingSetWatch  : Ptr64 _PAGEFAULT_HISTORY
   +0x288 Win32WindowStation : Ptr64 Void
   +0x290 InheritedFromUniqueProcessId : Ptr64 Void
   +0x298 LdtInformation   : Ptr64 Void
   +0x2a0 Spare            : Ptr64 Void
   +0x2a8 ConsoleHostProcess : Uint8B
   +0x2b0 DeviceMap        : Ptr64 Void
   +0x2b8 EtwDataSource    : Ptr64 Void
   +0x2c0 FreeTebHint      : Ptr64 Void
   +0x2c8 PageDirectoryPte : _HARDWARE_PTE
   +0x2c8 Filler           : Uint8B
   +0x2d0 Session          : Ptr64 Void
   +0x2d8 ImageFileName    : [15] UChar
   +0x2e7 PriorityClass    : UChar
   +0x2e8 JobLinks         : _LIST_ENTRY
   +0x2f8 LockedPagesList  : Ptr64 Void
   +0x300 ThreadListHead   : _LIST_ENTRY
   +0x310 SecurityPort     : Ptr64 Void
   +0x318 Wow64Process     : Ptr64 Void
   +0x320 ActiveThreads    : Uint4B
   +0x324 ImagePathHash    : Uint4B
   +0x328 DefaultHardErrorProcessing : Uint4B
   +0x32c LastThreadExitStatus : Int4B
   +0x330 Peb              : Ptr64 _PEB
   +0x338 PrefetchTrace    : _EX_FAST_REF

실제로 EPROCESS에 Peb는 0x330에 있는게 아닙니다. 왜냐면 ntdll에 심볼을 참조했기 때문입니다.
따라서 정확히 dt nt!_EPROCESS 라고 입력하는게 맞습니다.

구조체를 보면 ntdll과 nt랑은 결과가 다름을 볼 수 있습니다.
kd> dt nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x160 ProcessLock      : _EX_PUSH_LOCK
   +0x168 CreateTime       : _LARGE_INTEGER
   +0x170 ExitTime         : _LARGE_INTEGER
   +0x178 RundownProtect   : _EX_RUNDOWN_REF
   +0x180 UniqueProcessId  : Ptr64 Void
   +0x188 ActiveProcessLinks : _LIST_ENTRY
   +0x198 ProcessQuotaUsage : [2] Uint8B
   +0x1a8 ProcessQuotaPeak : [2] Uint8B
   +0x1b8 CommitCharge     : Uint8B
   +0x1c0 QuotaBlock       : Ptr64 _EPROCESS_QUOTA_BLOCK
   +0x1c8 CpuQuotaBlock    : Ptr64 _PS_CPU_QUOTA_BLOCK
   +0x1d0 PeakVirtualSize  : Uint8B
   +0x1d8 VirtualSize      : Uint8B
   +0x1e0 SessionProcessLinks : _LIST_ENTRY
   +0x1f0 DebugPort        : Ptr64 Void
   +0x1f8 ExceptionPortData : Ptr64 Void
   +0x1f8 ExceptionPortValue : Uint8B
   +0x1f8 ExceptionPortState : Pos 0, 3 Bits
   +0x200 ObjectTable      : Ptr64 _HANDLE_TABLE
   +0x208 Token            : _EX_FAST_REF
   +0x210 WorkingSetPage   : Uint8B
   +0x218 AddressCreationLock : _EX_PUSH_LOCK
   +0x220 RotateInProgress : Ptr64 _ETHREAD
   +0x228 ForkInProgress   : Ptr64 _ETHREAD
   +0x230 HardwareTrigger  : Uint8B
   +0x238 PhysicalVadRoot  : Ptr64 _MM_AVL_TABLE
   +0x240 CloneRoot        : Ptr64 Void
   +0x248 NumberOfPrivatePages : Uint8B
   +0x250 NumberOfLockedPages : Uint8B
   +0x258 Win32Process     : Ptr64 Void
   +0x260 Job              : Ptr64 _EJOB
   +0x268 SectionObject    : Ptr64 Void
   +0x270 SectionBaseAddress : Ptr64 Void
   +0x278 Cookie           : Uint4B
   +0x27c UmsScheduledThreads : Uint4B
   +0x280 WorkingSetWatch  : Ptr64 _PAGEFAULT_HISTORY
   +0x288 Win32WindowStation : Ptr64 Void
   +0x290 InheritedFromUniqueProcessId : Ptr64 Void
   +0x298 LdtInformation   : Ptr64 Void
   +0x2a0 Spare            : Ptr64 Void
   +0x2a8 ConsoleHostProcess : Uint8B
   +0x2b0 DeviceMap        : Ptr64 Void
   +0x2b8 EtwDataSource    : Ptr64 Void
   +0x2c0 FreeTebHint      : Ptr64 Void
   +0x2c8 FreeUmsTebHint   : Ptr64 Void
   +0x2d0 PageDirectoryPte : _HARDWARE_PTE
   +0x2d0 Filler           : Uint8B
   +0x2d8 Session          : Ptr64 Void
   +0x2e0 ImageFileName    : [15] UChar
   +0x2ef PriorityClass    : UChar
   +0x2f0 JobLinks         : _LIST_ENTRY
   +0x300 LockedPagesList  : Ptr64 Void
   +0x308 ThreadListHead   : _LIST_ENTRY
   +0x318 SecurityPort     : Ptr64 Void
   +0x320 Wow64Process     : Ptr64 Void
   +0x328 ActiveThreads    : Uint4B
   +0x32c ImagePathHash    : Uint4B
   +0x330 DefaultHardErrorProcessing : Uint4B
   +0x334 LastThreadExitStatus : Int4B
   +0x338 Peb              : Ptr64 _PEB


ntdll!_EPROCESS 에 경우 PEB는 0x330을 가르키지만 nt!_EPROCESS에 경우 PEB는 0x338을 가지며, 0x338 오프셋이 올바른 값입니다.
저작자 표시 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comment 0