Windows 운영체제에서 프로세스는 저마다 PEB(Process Environment Block) 를 가집니다.


이 PEB 는 유저레벨에서도 접근할 필요가 있는 정보들을 담고 있기에 프로세스 주소 공간에 위치하며,


커널레벨에서는 EPROCESS 구조체를 이용해 PEB 의 포인터를 알 수 있습니다.

( EPROCESS 구조체에 Peb 라는 필드가 있거든요~ :D )


이 때 문득...


WOW64 프로세스는 PEB 가 어떻게 될까...??


이런 호기심이 생기더군요~



#1. WOW64 프로세스의 PEB 는 32비트 기반으로 생성된다!?


WOW64 프로세스는 일단 32비트로 에뮬레이팅 되는 개념이라 32비트 코드에 포인터 역시 32비트일테고...


즉, PEB 내부의 각종 정보들도 32비트 기반으로 생성이 될 것이라고 생각을 한거죠...

( 32비트로 생성이 되어야 32비트 기반 코드에서 원활하게 접근이 가능할테니까요... )



#2. WOW64 프로세스의 PEB 는 64비트 기반으로 생성된다!?


위에서도 언급했지만 PEB 는 커널레벨에서도 EPROCESS 를 이용해 접근이 가능한 정보입니다.


64비트 OS 특성상 커널레벨은 64비트 코드가 실행되며 포인터 역시 64비트입니다...


이렇게 되면 위에서 32비트 기반으로 생성이 되었을 PEB 를 제대로 인식을 못할텐데...!?


제대로 인식을 하려면 64비트 기반으로 생성이 되어야될텐데...!?



#1#2 의 딜레마 때문에 살짝 혼란스러웠는데...


확인해보니 32비트 기반 PEB 와 64비트 기반 PEB 를 둘 다 생성을 하더군요... =_=;;;...



[ 커널레벨에서의 WOW64 프로세스 PEB ]


PROCESS fffffa8000d84620
    SessionId: 1  Cid: 0ba4    Peb: 7efdf000  ParentCid: 0534
    DirBase: 20516000  ObjectTable: fffff8a0022199c0  HandleCount:  97.
    Image: notepad.exe

kd> dt nt!_EPROCESS fffffa8000d84620
   +0x000 Pcb              : _KPROCESS
   +0x160 ProcessLock      : _EX_PUSH_LOCK
   +0x168 CreateTime       : _LARGE_INTEGER 0x1cddc0c`abfc961d
   +0x170 ExitTime         : _LARGE_INTEGER 0x0
   +0x178 RundownProtect   : _EX_RUNDOWN_REF
   +0x180 UniqueProcessId  : 0x00000000`00000ba4
   +0x188 ActiveProcessLinks : _LIST_ENTRY [ 0xfffffa80`00dae678 - 0xfffffa80`031dacb8 ]
   +0x198 ProcessQuotaUsage : [2] 0x2980
   +0x1a8 ProcessQuotaPeak : [2] 0x2980
   +0x1b8 CommitCharge     : 0x1d2
   +0x1c0 QuotaBlock       : 0xfffffa80`02d58280 _EPROCESS_QUOTA_BLOCK
   +0x1c8 CpuQuotaBlock    : (null)
   +0x1d0 PeakVirtualSize  : 0x5917000
   +0x1d8 VirtualSize      : 0x4dcd000
   +0x1e0 SessionProcessLinks : _LIST_ENTRY [ 0xfffff880`03666010 - 0xfffffa80`02fd6240 ]
   +0x1f0 DebugPort        : (null)
   +0x1f8 ExceptionPortData : 0xfffffa80`02944d10
   +0x1f8 ExceptionPortValue : 0xfffffa80`02944d10
   +0x1f8 ExceptionPortState : 0y000
   +0x200 ObjectTable      : 0xfffff8a0`022199c0 _HANDLE_TABLE
   +0x208 Token            : _EX_FAST_REF
   +0x210 WorkingSetPage   : 0x2041a
   +0x218 AddressCreationLock : _EX_PUSH_LOCK
   +0x220 RotateInProgress : (null)
   +0x228 ForkInProgress   : (null)
   +0x230 HardwareTrigger  : 0
   +0x238 PhysicalVadRoot  : (null)
   +0x240 CloneRoot        : (null)
   +0x248 NumberOfPrivatePages : 0x149
   +0x250 NumberOfLockedPages : 0
   +0x258 Win32Process     : 0xfffff900`c2cc9ce0
   +0x260 Job              : (null)
   +0x268 SectionObject    : 0xfffff8a0`02264d70
   +0x270 SectionBaseAddress : 0x00000000`00a30000
   +0x278 Cookie           : 0x9b7242f4
   +0x27c UmsScheduledThreads : 0
   +0x280 WorkingSetWatch  : (null)
   +0x288 Win32WindowStation : 0x00000000`00000054
   +0x290 InheritedFromUniqueProcessId : 0x00000000`00000534
   +0x298 LdtInformation   : (null)
   +0x2a0 Spare            : (null)
   +0x2a8 ConsoleHostProcess : 0
   +0x2b0 DeviceMap        : 0xfffff8a0`01895af0
   +0x2b8 EtwDataSource    : (null)
   +0x2c0 FreeTebHint      : 0x00000000`7ef9d000
   +0x2c8 FreeUmsTebHint   : 0x00000001`00000000
   +0x2d0 PageDirectoryPte : _HARDWARE_PTE
   +0x2d0 Filler           : 0
   +0x2d8 Session          : 0xfffff880`03666000
   +0x2e0 ImageFileName    : [15]  "notepad.exe"
   +0x2ef PriorityClass    : 0x2 ''
   +0x2f0 JobLinks         : _LIST_ENTRY [ 0x00000000`00000000 - 0x0 ]
   +0x300 LockedPagesList  : (null)
   +0x308 ThreadListHead   : _LIST_ENTRY [ 0xfffffa80`02ec1f78 - 0xfffffa80`02f465a8 ]
   +0x318 SecurityPort     : (null)
   +0x320 Wow64Process     : 0x00000000`7efde000
   +0x328 ActiveThreads    : 4
   +0x32c ImagePathHash    : 0x28e040de
   +0x330 DefaultHardErrorProcessing : 1
   +0x334 LastThreadExitStatus : 0
   +0x338 Peb              : 0x00000000`7efdf000 _PEB
   +0x340 PrefetchTrace    : _EX_FAST_REF
   +0x348 ReadOperationCount : _LARGE_INTEGER 0x0
   +0x350 WriteOperationCount : _LARGE_INTEGER 0x0
   +0x358 OtherOperationCount : _LARGE_INTEGER 0x0
   +0x360 ReadTransferCount : _LARGE_INTEGER 0x0
   +0x368 WriteTransferCount : _LARGE_INTEGER 0x0
   +0x370 OtherTransferCount : _LARGE_INTEGER 0x0
   +0x378 CommitChargeLimit : 0
   +0x380 CommitChargePeak : 0x1d2
   +0x388 AweInfo          : (null)
   +0x390 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x398 Vm               : _MMSUPPORT
   +0x420 MmProcessLinks   : _LIST_ENTRY [ 0xfffffa80`00dae910 - 0xfffffa80`031daf50 ]
   +0x430 HighestUserAddress : 0x00000000`7fff0000
   +0x438 ModifiedPageCount : 2
   +0x43c Flags2           : 0xd000
   +0x43c JobNotReallyActive : 0y0
   +0x43c AccountingFolded : 0y0
   +0x43c NewProcessReported : 0y0
   +0x43c ExitProcessReported : 0y0
   +0x43c ReportCommitChanges : 0y0
   +0x43c LastReportMemory : 0y0
   +0x43c ReportPhysicalPageChanges : 0y0
   +0x43c HandleTableRundown : 0y0
   +0x43c NeedsHandleRundown : 0y0
   +0x43c RefTraceEnabled  : 0y0
   +0x43c NumaAware        : 0y0
   +0x43c ProtectedProcess : 0y0
   +0x43c DefaultPagePriority : 0y101
   +0x43c PrimaryTokenFrozen : 0y1
   +0x43c ProcessVerifierTarget : 0y0
   +0x43c StackRandomizationDisabled : 0y0
   +0x43c AffinityPermanent : 0y0
   +0x43c AffinityUpdateEnable : 0y0
   +0x43c PropagateNode    : 0y0
   +0x43c ExplicitAffinity : 0y0
   +0x43c Spare1           : 0y0
   +0x43c ForceRelocateImages : 0y0
   +0x43c DisallowStrippedImages : 0y0
   +0x440 Flags            : 0x144d0801
   +0x440 CreateReported   : 0y1
   +0x440 NoDebugInherit   : 0y0
   +0x440 ProcessExiting   : 0y0
   +0x440 ProcessDelete    : 0y0
   +0x440 Wow64SplitPages  : 0y0
   +0x440 VmDeleted        : 0y0
   +0x440 OutswapEnabled   : 0y0
   +0x440 Outswapped       : 0y0
   +0x440 ForkFailed       : 0y0
   +0x440 Wow64VaSpace4Gb  : 0y0
   +0x440 AddressSpaceInitialized : 0y10
   +0x440 SetTimerResolution : 0y0
   +0x440 BreakOnTermination : 0y0
   +0x440 DeprioritizeViews : 0y0
   +0x440 WriteWatch       : 0y0
   +0x440 ProcessInSession : 0y1
   +0x440 OverrideAddressSpace : 0y0
   +0x440 HasAddressSpace  : 0y1
   +0x440 LaunchPrefetched : 0y1
   +0x440 InjectInpageErrors : 0y0
   +0x440 VmTopDown        : 0y0
   +0x440 ImageNotifyDone  : 0y1
   +0x440 PdeUpdateNeeded  : 0y0
   +0x440 VdmAllowed       : 0y0
   +0x440 CrossSessionCreate : 0y0
   +0x440 ProcessInserted  : 0y1
   +0x440 DefaultIoPriority : 0y010
   +0x440 ProcessSelfDelete : 0y0
   +0x440 SetTimerResolutionLink : 0y0
   +0x444 ExitStatus       : 259
   +0x448 VadRoot          : _MM_AVL_TABLE
   +0x488 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x4a8 TimerResolutionLink : _LIST_ENTRY [ 0x00000000`00000000 - 0x0 ]
   +0x4b8 RequestedTimerResolution : 0
   +0x4bc ActiveThreadsHighWatermark : 4
   +0x4c0 SmallestTimerResolution : 0
   +0x4c8 TimerResolutionStackRecord : (null)



[ 유저레벨에서의 WOW64 프로세스 PEB ]




* FS 레지스터 : 0x7EFD7000




* FS:[30] (PEB) = 0x7EFDE000



정리해보면 EPROCESS 의 Peb 필드에 64비트 기반 PEB 의 포인터를 가지고 있고...


Wow64Process 필드에 32비트 기반 PEB 의 포인터를 가지고 있습니다... @_@..



막연하긴 하지만 유저레벨에서 다른 프로세스에 접근을 한다고 했을 때...


내 프로세스가 WOW64 모드인지 Native64 모드인지...


또, 접근대상이 WOW64 모드인지 Native64 모드인지에 따라 꽤나 복잡해질 수도 있겠구나...


하는 생각이 드는군요... @_@


틈틈이 WOW64 아키텍쳐에 대해서 좀 더 공부를 해봐야겠네요...




YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST
  1. BlogIcon Ezbeat 2012.12.17 23:32  댓글주소  수정/삭제  댓글쓰기

    EPROCESS 구조체엔 32,64 각각에 대한 PEB를 가지고 있군요.
    WOW64 에뮬레이션은 알아가면 알아갈수록 잼있는 놈이네요 ㅋ

    • BlogIcon XeroNic(HS) 2012.12.18 10:24 신고  댓글주소  수정/삭제

      EPROCESS 구조체에 Wow64Process 란 필드가 있는데...
      WOW64 프로세스의 경우에는 저기에 32비트 PEB 포인터가 설정되고..
      Native64 프로세스는 그냥 (null) 이더라구요~ㅎ

      향후 얼마간 32비트 체계는 계속 유지가 될텐데...
      WOW64 에 대해서 알아둬서 손해볼 건 없을거 같아요 :)

  2. StackSize 2013.01.16 22:58  댓글주소  수정/삭제  댓글쓰기

    안녕하세요,
    Windows 에서 실행프로그램에 할당하는 탄창의 크기는 디폴트로 얼마인가요?
    그 크기는 Windows 버젼에 따라 또는 32/64 에 따라 다른가요?
    그에 대하여 서술한 마소잡지 같은 것은 어디서 찾을 수 있는가요?
    감사합니다.

  3. StackSize 2013.01.17 16:54  댓글주소  수정/삭제  댓글쓰기

    아하! 제가 질문을 잘 못 했나 보네요,
    제가 말하는 탄창이란 OS 가 프로세스에 할당하는 stack memory를 의미합니다.
    제 생각에는 OS가 모든 Process 에게 스레드 단위로 같은 크기로 stack을 할당하는 것 같은데 그에 대한 정보를 얻고 싶어서 질문 해봅니다.
    감사합니다.

    • BlogIcon XeroNic(HS) 2013.01.18 09:00 신고  댓글주소  수정/삭제

      아하.. 일반적으로 실행 파일을 빌드할 때 스택의 크기 등이 파일에 셋팅이 됩니다.
      PE 구조 상에서는 IMAGE_NT_HEADERS -> IMAGE_OPTIONAL_HEADER 에...
      SizeOfStackReserve, SizeOfStackCommit 항목이 있는데...
      OS 에서는 이 값들을 참조해서 스택을 할당하게 됩니다.
      컴파일 시 특별히 스택 관련 크기를 지정하지 않았다면...
      Visual C++ 계열에서는 예약크기는 대략 1M 이고..
      커밋크기는 4K 인걸로 알고 있습니다.

  4. StackSize 2013.01.22 17:34  댓글주소  수정/삭제  댓글쓰기

    안녕하세요.
    초기에 eip는 EntryPoint로 설정되는 것 같은데 esp는 어떤 값으로 설정되는건가요?
    저는 다음의 코드로 얻었는데 esp 한계를 API 를 안쓰고 어떻게 Assembly 로 못얻을가요?
    {
    DWORD dwESP;

    __asm{ mov dwESP, esp }
    MEMORY_BASIC_INFORMATION mbi;

    DWORD dwCurPID = GetCurrentProcessId();
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurPID);

    VirtualQueryEx( hProcess , (LPVOID) dwESP , &mbi ,sizeof(mbi));
    printf( "base=0x%x size=0x%x esp=0x%x", mbi.BaseAddress, mbi.RegionSize / 1024, dwESP);

    }
    그리고 어떤 선배님이 말씀 하시기를 탄창은 스레드마다 독립이라며 tls 대신 스레드 스택을 잘리용해도 된다고 하더라구요. ???
    그렇다면 스레드 스택의 크기는 어떻게 할당되며 그의 현재 크기는 어떻게 얻어낼수 있을가요?
    또 그 때 스레드 스택과 PE 에 반영된 스택크기와 는 어떤 관계가 있을가요?
    PE 스택은 프로세스에 할당될 스택크기이고 프로세스는 여러개의 스레드로 되 있지 않나요.
    자꾸 의문이 생겨서 질문해봅니다.
    좋은 하루 되세요.

    • BlogIcon XeroNic(HS) 2013.08.29 09:24 신고  댓글주소  수정/삭제

      우선.. ESP 가 어떤값으로 초기화가 되는건지는 저 역시 모르겠네요.. @_@;;
      그리고 쓰레드 스택의 크기는...
      쓰레드를 생성할 때 쓰레드 스택의 크기를 PE 쪽의 정보를 참고해서..
      생성하는 것으로 알고 있습니다..

  5. StackSize 2013.01.27 20:23  댓글주소  수정/삭제  댓글쓰기

    답변에 감사합니다.

  6. 오곡 2013.08.28 15:20  댓글주소  수정/삭제  댓글쓰기

    잘배우고 갑니다 ^^