Section Header


각 Section 의 속성(property)을 정의한 것이 Section Header 입니다.

section header 구조체를 보기 전에 한번 생각을 해보겠습니다.

앞서 PE 파일은 code, data, resource 등을 각각의 section 으로 나눠서 저장한다고 설명드렸습니다.
분명 PE 파일 포멧을 설계한 사람들은 어떤 장점이 있기 때문에 그랬을 겁니다.

PE 파일을 여러개의 section 구조로 만들었을때 (제가 생각하는) 장점은 바로 프로그램의 안정성입니다.

code 와 data 가 하나의 섹션으로 되어 있고 서로 뒤죽박죽 섞여 있다면, (실제로 구현이 가능하긴 합니다.)
그 복잡한은 무시하고라도 안정성에 문제가 생길 수 있습니다.

가령 문자열 data 에 값을 쓰다가 어떤 이유로 overflow 가 발생(버퍼 크기를 초과해서 입력) 했을때
바로 다음의 code (명령어) 를 그대로 덮어써버릴 것입니다. 프로그램은 그대로 뻗어 버리겠죠.

즉, code/data/resource 마다 각각의 성격(특징, 엑세스 권한)이 틀리다는 것을 알게 된 것입니다.

  • code - 실행, 읽기 권한
  • data - 비실행, 읽기, 쓰기 권한
  • resource - 비실행, 읽기 권한


그래서 PE 파일 포멧 설계자들은 비슷한 성격의 자료를 section 이라고 이름 붙인 곳에 모아두기로 결정하였고,
각각의 section 의 속성을 기술할 section header 가 필요하게 된 것입니다.
(section 의 속성에는 file/memory 에서의 시작위치, 크기, 엑세스 권한 등이 있어야 겠지요.)

이제 section header 가 무슨 역할을 하는지 이해 되셨나요?



IMAGE_SECTION_HEADER


section header 는 각 section 별 IMAGE_SECTION_HEADER 구조체의 배열로 되어있습니다. 

#define IMAGE_SIZEOF_SHORT_NAME              8

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;

    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

* 출처 : Microsoft 의 Visual C++ 에서 제공하는 winnt.h


IMAGE_SECTION_HEADER 구조체에서 알아야 할 중요 멤버는 아래와 같습니다. (나머지는 사용되지 않습니다.)

  • VirtualSize      : 메모리에서 섹션이 차지하는 크기
  • VirtualAddress   : 메모리에서 섹션의 시작 주소 (RVA)
  • SizeOfRawData    : 파일에서 섹션이 차지하는 크기
  • PointerToRawData : 파일에서 섹션의 시작 위치
  • Characteristics  : 섹션의 특징 (bit OR)


VirtualAddress 와 PointerToRawData 의 값은 아무 값이나 가질 수 없고,
각각 (IMAGE_OPTIONAL_HEADER32 에 정의된) SectionAlignment 와 FileAlignment 에 맞게 결정됩니다.

VirtualSize 와 SizeOfRawData 는 일반적으로 서로 틀린값을 가집니다.
즉, 파일에서의 섹션 크기와 메모리에 로딩된 섹션의 크기는 틀리다는 얘기가 되는 거죠.

Characteristics 는 아래 값들의 조합(bit OR)으로 이루어 집니다.

#define IMAGE_SCN_CNT_CODE                   0x00000020  // Section contains code.
#define IMAGE_SCN_CNT_INITIALIZED_DATA       0x00000040  // Section contains initialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA     0x00000080  // Section contains uninitialized data.
#define IMAGE_SCN_MEM_EXECUTE                0x20000000  // Section is executable.
#define IMAGE_SCN_MEM_READ                   0x40000000  // Section is readable.
#define IMAGE_SCN_MEM_WRITE                  0x80000000  // Section is writeable.


마지막으로 Name 항목에 대해서 얘기해보겠습니다.

Name 멤버는 C 언어의 문자열처럼 NULL 로 끝나지 않습니다. 또한 ASCII 값만 와야한다는 제한도 없습니다.
PE 스펙에는 섹션 Name 에 대한 어떠한 명시적인 규칙이 없기 때문에 어떠한 값을 넣어도 되고 심지어 NULL 로 채워도 됩니다.

또한 개발 도구에 따라서 섹션 이름/갯수 등이 달라집니다.

따라서 섹션의 Name 은 그냥 참고용 일뿐 어떤 정보로써 활용하기에는 100% 장담할 수 없습니다.
(데이타 섹션 이름을 ".code" 로 해도 되거든요.)


자 그러면 실제 notepad.exe 의 Section Header 배열을 살펴보죠. (총 3 개의 섹션이 있습니다.)


구조체 멤버별로 살펴보면 아래와 같습니다.

[ IMAGE_SECTION_HEADER ]

 offset   value   description
-------------------------------------------------------------------------------
000001D8 2E746578 Name (.text)
000001DC 74000000
000001E0 00007748 virtual size
000001E4 00001000 RVA
000001E8 00007800 size of raw data
000001EC 00000400 offset to raw data
000001F0 00000000 offset to relocations
000001F4 00000000 offset to line numbers
000001F8     0000 number of relocations
000001FA     0000 number of line numbers
000001FC 60000020 characteristics
                    IMAGE_SCN_CNT_CODE
                    IMAGE_SCN_MEM_EXECUTE
                    IMAGE_SCN_MEM_READ

00000200 2E646174 Name (.data)
00000204 61000000
00000208 00001BA8 virtual size
0000020C 00009000 RVA
00000210 00000800 size of raw data
00000214 00007C00 offset to raw data
00000218 00000000 offset to relocations
0000021C 00000000 offset to line numbers
00000220     0000 number of relocations
00000222     0000 number of line numbers
00000224 C0000040 characteristics
                    IMAGE_SCN_CNT_INITIALIZED_DATA
                    IMAGE_SCN_MEM_READ
                    IMAGE_SCN_MEM_WRITE

00000228 2E727372 Name (.rsrc)
0000022C 63000000
00000230 00008304 virtual size
00000234 0000B000 RVA
00000238 00008400 size of raw data
0000023C 00008400 offset to raw data
00000240 00000000 offset to relocations
00000244 00000000 offset to line numbers
00000248     0000 number of relocations
0000024A     0000 number of line numbers
0000024C 40000040 characteristics
                             IMAGE_SCN_CNT_INITIALIZED_DATA
                             IMAGE_SCN_MEM_READ




RVA to RAW



Section Header 를 잘 이해하셨다면 이제부터는 PE 파일이 메모리에 로딩되었을때
각 섹션에서 메모리의 주소(RVA)와 파일 옵셋을 잘 매핑할 수 있어야 합니다.

이러한 매핑을 일반적으로 "RVA to RAW" 라고 부릅니다.
방법은 아래와 같습니다.

1) RVA 가 속해 있는 섹션을 찾습니다.
2) 간단한 비례식을 사용해서 파일 옵셋(RAW)을 계산합니다.

IMAGE_SECTION_HEADER 구조체에 의하면 비례식은 이렇습니다.

RAW - PointerToRawData = RVA - VirtualAddress
                   RAW = RVA - VirtualAddress + PointerToRawData


간단한 퀴즈를 내보겠습니다.
아래 그림은 notepad.exe 의 File 과 Memory 에서의 모습입니다.
각각 RVA 를 계산해 보세요. (계산기 calc.exe 를 Hex 모드로 세팅하시면 계산이 편합니다.)



Q1)  RVA = 5000h 일때 File Offset = ?
A1) 먼저 해당 RVA 값이 속해 있는 섹션을 찾아야 합니다.
      => RVA 5000h 는 첫번째 섹션(".text")에 속해있습니다. (ImageBase 01000000h 를 고려하세요.)

      비례식 사용
      => RAW = 5000h(RVA) - 1000h(VirtualAddress) + 400h(PointerToRawData) = 4400h

Q2) RVA = 13314h 일때 File Offset = ?
A2) 해당 RVA 값이 속해 있는 섹션을 찾습니다.
      => 세번째 섹션(".rsrc")에 속해있습니다.

      비례식 사용
      => RAW = 13314h(RVA) - B000h(VA) + 8400h(PointerToRawData) = 10714h

Q3) RVA = ABA8h 일때 File Offset = ?
A2) 해당 RVA 값이 속해 있는 섹션을 찾습니다.
      => 두번째 섹션(".data")에 속해있습니다.

      비례식 사용
      => RAW = ABA8h(RVA) - 9000h(VA) + 7C00h(PointerToRawData) = 97A8h (X)
      => 계산 결과로 RAW = 97A8h 가 나왔지만 이 옵셋은 세번째 섹션(".rsrc")에 속해 있습니다.
           RVA 는 두번째 섹션이고, RAW 는 세번째 섹션이라면 말이 안되지요.
           이 경우에 "해당 RVA(ABA8h)에 대한 RAW 값은 정의할 수 없다" 라고 해야 합니다.
           이런 이상한 결과가 나온 이유는 위 경우에 두번째 섹션의 VirtualSize 값이 SizeOfRawData 값 보다 크기 때문입니다.

PE 파일의 섹션에는 Q3) 의 경우와 같이 VirtualSize 와 SizeOfRawData 값이 서로 틀려서 벌어지는
이상하고 재미있는(?) 일들이 많이 있습니다. (앞으로 살펴보게 될 것입니다.)




이것으로 PE Header 의 기본 구조체들에 대한 설명을 마쳤습니다.

다음에는 PE Header 의 핵심인 IAT(Import Address Table), EAT(Export Address Table) 에 대해서 공부해 보겠습니다.

(continue)



  1. 쵸밥 2009.11.26 03:50 신고 댓글주소 | 수정 | 삭제 | 댓글

    cOrE 님~ 벌써 6장을 향해 달려가고 있네요 ^^* (아 뿌듯해 ㅋ)

    질문이 하나 있어요.

    예전에 뒷장에서 Hello World! 파일을 리버싱 했던거 기억 나시죠?
    그때 "World!" 문자열을 "Reverse" 문자열로 바꿀때 Olly로 대충 끝자락 널 패딩에 데이터를 썼다가
    삑살 났었죠?

    그 때 PE header 을 보고 메모리에 올라가는 영역중에 안쓰는 곳을 골라서 Patch 해 내야 한다고.

    그래서 질문이 하나 있어요!

    제가 지금 Olly 와 이 사이트에서 얻은 PEview 를 사용중이거든요?
    윗 그림을 보면 .data area 의 시작점 01009000 (Image Base + RVA 값) 값은 Olly와 PEview 에 동일하게 표시되요.

    그런데 끝자락을 표시하는 부분이 Olly 와 PEview 가 틀리네요?

    1. Olly 의 데이터창을 보면 0100AFFF 까지 표시되요.

    2. PEview 의 .data section 을 보면 010097FF 까지로 Olly 보다 훨씬 쪼금이네요?

    3. 그런데 이번에는 계산기로 두두려보면 메모리 주소로서의 (VA) .data area 최대값은 0100ABA8 이고 . .

    4. 또 계산기를 두드려보면 파일 (RAW) 에서 메모리로 (VA) 맵핑될 수 있는 최대값은 010097FF 로 PEview 가 보여주는 수준하고 같네요?

    볼수 있는 주소의 한계를 작은 순서대로 정렬해보면 . .
    PEview 의 .data 영역 = (RAW) .data 계산기 < (VA) .data 계산기 < Ollydbg data view
    Ollydbg 가 .data area 를 .rsrc 직전까지로 제일 많이 보여주는데 . .

    우리 맘대로 "Reverse!!" 문자열을 .data area 에 집어 넣는다면 . . 그리고 파일로 패치해 낼 거라면?

    010097FF PEview 가 보여주는 수준 (RAW) 가 (VA) 에 매칭될 수 있는 최대값 안에 "Reverse!!" 문자열을 넣으면 되는건가요 ???

    • reversecore 2009.11.26 15:12 신고 댓글주소 | 수정 | 삭제

      쵸밥님, 안녕하세요.

      잠도 안주무시고 이렇게 열심히 하시다니요... @@~

      제 블로그를 아껴 주셔서 감사합니다.

      답변을 드리자면...
      PEView 에서 섹션 크기 와 실제 실행시 메모리에서 섹션 크기가 왜 틀리냐는 말씀이시죠?

      그건 바로 Section Alignment 항목 때문입니다.
      (IMAGE_OPTIONAL_HEADER 멤버)

      PE Header 의 섹션 정보에는 그 프로그램의 해당 섹션이 메모리에서 점유할 크기가 기록됩니다.

      실제 PE Loader 는 메모리를 Section Header 의 배수크기로 잡기 때문에 실제로는 더 큰값이 되는 것입니다. (효율성 때문입니다.)

      그리고 메모리에 문자열을 쓰실거면 실제 잡힌 크기 내에서 쓰시면 되고요, 파일에서 쓰실려면 적당히 빈 곳에 쓰시면 됩니다.

      감사합니다.

  2. 쵸밥 2009.11.27 00:55 신고 댓글주소 | 수정 | 삭제 | 댓글

    오 . . PE 로더의 동작에 대해서 알아봐야 겠네요 ㄷㄷ;;

  3. 메롱이 2009.11.30 02:50 신고 댓글주소 | 수정 | 삭제 | 댓글

    강좌 잘 읽다가 정말 모르는 부분이 있어서요..

    퀴즈문제(총 3문제)에서 예를 들면 RVA=13314h일때 13314 주소가 세번째 섹션에 속한다라고

    하셨는데 어떤게 세번째 섹션에 속하는지 몰라서요..

    세번째 섹션 주소 범위가 100B00h~1008304h <- 이거 맞죠?

    주소 범위를 10진수 2진수 둘다 바꿔 교해봐도 3314가 범위안에 안들어 가는거 같던데..

    제가 계산하는게 맞는지 모르겠네요..

    워낙 생초보라...ㅎㅎ;;

    수고스러우시겠지만..좀더 설명좀 해주셔용...ㅎㅎ;;

    리버싱은...마치 컴퓨터 안에서 보물찾기 하는거 같은 느낌이나서 공부 할수록 잼있네요..ㅎㅎ;;

    • ReverseCore 2009.11.30 09:08 신고 댓글주소 | 수정 | 삭제

      안녕하세요. 메롱이님.

      위 그림을 보시면 RVA 13314 는 세번째 섹션이에 속한 주소라는걸 아실 수 있습니다. (이 그림은 섹션 헤더의 정보를 기반으로 작성되었습니다.)

      세번째 섹션 범위는 아래와 같습니다.
      파일 8400 ~ 10800
      메모리 100B000 ~ 1014000

      섹션 헤더를 다시 한번 살펴보시기 바랍니다.

  4. Ezbeat 2009.12.23 17:37 신고 댓글주소 | 수정 | 삭제 | 댓글

    강의 잘 보고 있습니다 ^^
    근데 NT header라는 것이 OptionalHeader까지 인것으로 알고있는데
    마지막에 Section header까지 전부 설명하신 후에 NT header의 모든 멤버에 대해 설명을
    마쳤다고 하셔서 쫌 이상한거 같아요 ;;

    • ReverseCore 2009.12.24 02:19 신고 댓글주소 | 수정 | 삭제

      Ezbeat님, 안녕하세요.

      정확한 지적이십니다. ^^

      열심히 읽어주시고 오류를 바로 잡아 주셔서 감사합니다.

      Ezbeat님 덕분에 제 글의 완성도가 높아져서 기분 좋습니다.

      항상 감사합니다. ^^

  5. h0ney 2010.01.12 18:45 신고 댓글주소 | 수정 | 삭제 | 댓글

    제가 최근에 C# 을 사용하여 PE Viewer 를 하나 만들고 있습니다.

    분석중 파일이 Packing 이 되어있는지에 대한 여부를 확인할 때

    이리저리 궁리를 하다가 가장 효과적인 방법이 EP Section 의 Characteristics 을 살펴본 뒤

    이 값이 IMAGE_SCN_MEM_WRITE 플레그가 켜져있을 경우에는

    Packing 이 되었다고 판단하도록 만들었는데 이 부분에 대해서는

    어떻게 생각하시는지요?

    • reversecore 2010.01.13 16:22 신고 댓글주소 | 수정 | 삭제

      h0ney님, 안녕하세요.

      말씀하신대로 EP Section 에 WRITE 속성이 있다면 일단 일반적인 PE 파일은 아닐겁니다. 그렇게 만드는 컴파일러는 본적이 없구요.
      아마 패커 또는 크립터 계열로 작업된 파일일 확률이 매우 높을 겁니다.

      하지만 목표가 packing 된 파일을 찾는거라고 하시면 위 알고리즘은 100% 동작하지는 않을 겁니다.
      이유는 EP 섹션 속성을 건드리지 않는 패커도 꽤 있거든요.
      쉽게 볼 수 있는 파일은 RAR SFX 계열의 파일들입니다.

      다른 분야에서도 팩 여부를 확인하는 것은 중요합니다.
      어떤 논문들을 보면 파일의 entropy 를 확인한다고 합니다.

      저도 자세히 본건 아니라 정확한 설명은 어렵지만 쉽게 얘기해 파일의 '복잡함정도'를 측정하는 것입니다.

      압축알고리즘은 결국 자주 나타나는 패턴을 특정 작은 값으로 매핑시켜주기 때문에 0 ~ FF 의 값이 파일 전반에 걸쳐 골고루 나타날 겁니다. (일반적인 PE 파일에는 0 이 압도적으로 많지요.)

      말씀하신 방법으로도 구현해보시고, 관련해서 검색을 좀 해보시면 다양한 아이디어를 보실 수 있으실 겁니다.

      감사합니다.

  6. graythief 2010.02.21 21:04 신고 댓글주소 | 수정 | 삭제 | 댓글

    파일 오프셋을 구할 때는 그럼 저 위의 File의 offset 값과 메모리의 address 부분을 구해놓고 계산을 해야하는건가요? 그렇다면 파일마다 틀릴것인데 (섹션크기가 더 크다던지 stub 부분이 더 커진다던지 말이에요 ) 일일이 다 일단 저것을 해놓고 분석해야 하는건가요?

    • reversecore 2010.02.21 23:52 신고 댓글주소 | 수정 | 삭제

      graythief님, 안녕하세요.

      RVA <-> File Offset 변환은 보통 유틸리티를 이용합니다. PEView 나 StudPE 같은 유틸리티를 사용하시면 되구요.

      좀더 익숙해 지시면 간단한건 그냥 쉽게 변환하실 수 있습니다.

      감사합니다.

  7. 할라 2010.04.22 05:54 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요~
    열심히 강좌를 보면서 학습을 하고있습니다.
    정말 볼수록 잘 쓰셧다고 감탄사가 흘러나오고 있습니다 ㅋ
    제가 필요한 부분만 추려내고 싶어도 너무 정리가 잘되있어서 결국 다보게되는..ㅋㅋ
    질문드릴께있는데요..
    특정 RVA값이 주어졌을때 그 부분을 계산하는 도중 의문점이 생겼는데요..
    저도 메모장을 peview로 열어서 각 섹션에 사이즈와 시작주소 등등을
    살펴보았는데, 이 그림 예제와 살짝다른... 곳을 발견했는데요
    첫 번째 text에서 버츄얼사이즈가 다르더군요 그러닌까 다른 섹션들도 값이
    다 틀려지는거같은데요.. 그리고 Size of RawData값들도 틀리고요.. 음.. 어째서 이런건지요??
    혹시 이게 시스템마다 다를 수도있는건가요??

    • reversecore 2010.04.23 22:56 신고 댓글주소 | 수정 | 삭제

      할라님, 칭찬 감사합니다. ^^

      질문하신대로 notepad.exe 는 OS 버전에 따라 모두 틀려집니다.
      (다른 모든 시스템 파일도 마찬가지입니다.)

      즉, OS 마다 시스템 파일 버전이 다 틀립니다.
      재빌드 해서 배포한다는 뜻이지요.

      따라서 위 그림과 다르게 보일 수 있습니다.

      감사합니다.

  8. 보름♬달★콤 2010.06.07 16:43 신고 댓글주소 | 수정 | 삭제 | 댓글

    1) VirtualSize 와 SiezOfRawData 설명에 대하여
    : 두개의 설명이 뒤바뀐것 아닌지요?
    VIrtualSize가 File 내의 Section 크기이고 SizeOfRawData가 메모리상에 올려진 setion의 크기 아닌가요? 보통의 경우 SizeOfRawData가 align배수로 roundup된 크기이더군요..
    이름도 이상하게 헷갈리게 되어있는데..

    2) 질문입니다.
    .data섹션의 경우, 이상하게 VIrtualSize보다 SizeOfRawData값이 크게 나와있는데요
    (제가 해본 결과에도 그렇게 나타나는 듯)
    이 경우는 어떻게 fiel offset을 구해야 하는지 알려주세요..
    차후에 설명해주신다고 했는데.. 어디에 써주셨는지 잘 모르겠네요...

    부탁드립니다. 수고하세요!

    • reversecore 2010.06.08 15:38 신고 댓글주소 | 수정 | 삭제

      안녕하세요~

      1) VirtualSize 가 메모리이고, SizeOfRawData 가 파일입니다.
      virtual 은 virtual address (가상메모리) 를 의미한다고 기억하시면 헷갈리지 않으실 거에요.
      SizeOfRawData 가 FileAlignment 의 배수로 된 것이 맞습니다.

      2) 둘은 1:1 매칭 되지 않기 때문에 항상 RVA 에 대한 FileOffset 을 계산할 수 있는 것은 아닙니다. 계산할 수 없는 경우도 있지요.
      예를 들어 PointerToRawData = 1000, VA = 1000 이고 SizeOfRawData = 200, VirtualSize = 400 인 경우라면...
      RVA 가 1200 보다 크다면 그에 해당되는 FileOffset 은 없는 겁니다.

      http://www.reversecore.com/22 글의 Q3) 문제를 참고하시기 바랍니다.

      감사합니다.

  9. blackjack 2010.06.28 20:44 신고 댓글주소 | 수정 | 삭제 | 댓글

    이렇게 올리는거 맞나?
    하여튼 안녕하세요. 요세 한창 리버싱 공부 중인 초짜임니다.
    질문드릴게 있는데 저 RAW계산하는게 저렇게만 봐서 잘 이해가 안갑니다.
    ImageBase 값을 참고하시라고 했는데요. 그걸 어떻게 황용하는지도 모르겠고
    그리고 예를 들어 RVA가5000h인 섹션이 어디인지 어떻게 알아내는지도 모르겟습니다 .^^

    • reversecore 2010.06.29 22:52 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      저 그림만 놓고 생각해 보시기 바랍니다.

      RVA 가 5000 인 섹션은 그림상에서 ".text" 섹션입니다.
      ImageBase 를 고려하라는 말은 저 그림이 VA 기준으로 되어 있기 때문에 ".text" 섹션의 VA 값 01001000 에서 ImageBase 값 01000000 을 빼면 결국 ".text" 섹션은 RVA 1000 에서 시작한다는 뜻입니다. (VA 01001000 에서 시작한다와 같은 말이지요.)

      설명이 좀 어렵지요? ^^

      잘 이해안가시면 다시 질문해 주세요~

  10. blackjack 2010.06.30 05:18 신고 댓글주소 | 수정 | 삭제 | 댓글

    아 이제 알겠습니다.
    RVA가5000이면 속해있는 섹션이 .text섹션이라는게
    .text섹션이 400~7C00이니까 이 안에 속해있어서 그랬군요.
    그럼 VA는 절대주소를 말하는거였잖아요?
    근데 계산 하는걸 보니까 ImageBase값을 빼준 나머지 즉 RVA로 계산해서 값을 구하네요
    그건 왜 그런가요?

    • reversecore 2010.07.03 15:00 신고 댓글주소 | 수정 | 삭제

      .text 섹션은 파일에서 400~7C00 영역이고, 메모리에서는 01001000 ~ 01009000 영역(VA)입니다.

      굳이 VA 를 RVA 로 변환해서 계산하는 이유는 Section Header 의 정보가 전부 RVA 로 되어있기 때문에 VA 를 RVA 로 변환후 계산해야 편리하기 때문입니다. (PE 헤더 정보들 대부분 RVA 로 되어있습니다.)

      PE 헤더에 RVA 만 사용하는 이유는... PE 파일이 꼭 ImageBase 에 로딩된다는 보장이 없기 때문에 RVA 로 써주는 것입니다...

      감사합니다.

  11. Vi0 2010.08.02 20:11 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요
    덕분에 열심히 리버싱공부 하고있습니다
    강좌를 보다 궁금증이 생겨서 질문드리는데요

    첫번째 문제에서 RVA가 5000일때 RAW가 4400이라 구하셨는데
    RVA5000인 곳에 asdf라는 데이터가 있으면
    RAW4400이란 곳에 asdf라는 똑같은 데이터가 있다는 말..맞나요?

    또 RVA는 존재하는데 RAW는 존재하지 않는경우는
    프로그램이 실행되면서 데이터가 push된(표현이 맞나 모르겠습니다..) 경우인가요?

    • reversecore 2010.08.04 22:00 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      첫번째 질문에 대한 답변은 '네' 이구요...
      (그 영역이 메모리에 로딩되는 경우라면 말이죠.)

      두번째 질문은... 조금 난해한데요... ^^
      패커같은 경우에 특정 섹션의 파일 크기가 0 이면서 메모리 크기는 매우 큰 경우가 많습니다. 즉, 파일에서는 사용되지 않지만 메모리에서는 뭔가 사용할 필요가 있어서 예약해놓은 공간이라고 보시면 됩니다. 그대로 메모리는 할당되지요. (보통 이경우에 unpack 된 코드를 이 영역에 풀어내는 경우가 많아요.)

      감사합니다.

  12. tintin 2011.06.21 00:32 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요?
    강의잘보고잇습니다^^
    강의를쭉 읽다가 제가 햇갈리는게 잇어서 질문을 합니다

    PE 파일 첫번째 강의에서

    VA (Virtual Address) 는 프로세스 가상 메모리의 절대 주소를 말하며,
    RVA (Relative Virtual Address) 는 어느 기준위치(ImageBase) 에서부터의 상대 주소를 말합니다.
    VA 와 RVA 의 관계는 아래 식과 같습니다.
    RVA + ImageBase = VA


    이렇게 말씀하셨는데요

    질문.
    이번 강의에서
    VirtualAddress : 메모리에서 섹션의 시작 주소 (RVA)
    이말은 무슨뜻인가요..?ㅠ VirtualAddress는줄여서 VA일테고
    그럼 VA = RVA ?? ,, 무지 햇갈리네요..
    혹시 메모리에서 섹션의 시작 주소 (RVA) 여기에서 오타가 나신건가요..?
    그리고 첫번째 강의에서 VA 랑 두번쨰 강의에서 VA는 같은건가요?


    아오 무슨질문을 했는지도모르겠네요 ㅎ ㅋㅋㅋ 죄송합니다

    • reversecore 2012.11.04 00:47 신고 댓글주소 | 수정 | 삭제

      여기서의 VirtualAddress 는 IMAGE_SECTION_HEADER 구조체의 멤버 변수입니다. 섹션의 메모리에서 시작 위치를 RVA 값으로 나타내지요.

      이름이 저렇게 되어 있어서 헷갈리실만 합니다.

      감사합니다.

    • 크빗 2013.08.17 08:20 신고 댓글주소 | 수정 | 삭제

      저도 같은 부분을 헷갈렸는데 이 글 보고 정확하게 짚어가네요 ㅋㅋ

  13. Bitstream0 2011.08.11 15:40 신고 댓글주소 | 수정 | 삭제 | 댓글

    'VirtualAddress : 메모리에서 섹션의 시작 주소 (RVA)' 라는 말은,

    "VirtualAddress의 값이 RVA로 표현되어 있다"는 말로 이해하시면 될 것 같습니다.

    즉, 특정 섹션의 VirtualAddress의 값이 VirtualAddress : 00001000과 같이 표현되어 있다면,

    해당 섹션의 가상메모리 상의 실제 위치(VirtualAddress)는 ImageBase + 00001000가

    되겠지요..... 지나가다가 글 남겨 봅니다.

  14. 강준성 2012.11.02 03:39 신고 댓글주소 | 수정 | 삭제 | 댓글

    RVA to RAW부분이
    이해가안되서 몇일설치다가..조금 쉽게 써봤어요..저처럼 머리나쁜사람있을까봐..

    일단 PE를 실행하면 섹션헤더를 참고해서 메모리를로드하는데 아래와같다.
    1. virtual address(rva)로 이동
    2. virtual size만큼의 크기를 할당
    3. 파일에있는 해당섹션을 메모리로 로드




    RAW = RVA - VirtualAddress + PointerToRawData 이 공식의 의미는
    PE로더가 파일의 섹션을 메모리의 섹션으로 로드하니까
    메모리가 가르키는값, 즉 RVA에서 섹션시작주소를빼고
    (이경우 메모리의 섹션시작부터 RVA가 가르키는곳까지의 크기를 뜻하게됨)
    파일섹션의 시작주소를합하는 공식
    (메모리의 크기를 구해서 파일의 시작주소를합해서
    파일의 오프셋으로 치환하는..말로는 아주 간단한 공식..)

    아 드디어 읽을수있다...ㅠㅠ
    근데 SizeofRawData(파일상 섹션의 크기)랑 Virtual Size(메모리상의 크기)가 다른이유는 전혀 이해가안가네요..

    • reversecore 2012.11.04 00:54 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      RVA -> RAW 변환은 리버스 엔지니어링에서 매우 중요한 개념입니다. 그리고 처음에는 좀 어렵게 느껴질 수 있습니다.

      지금이야 SizeOfRawData 와 VirtualSize 의 크기가 달라서 이득 볼게 별로 없습니다.

      그러나 PE가 처음 설계될 때는 HDD 가 매우 비쌌지요. 메모리는 가상 메모리 개념을 썼기 때문에 프로세스당 4GB 라고 보면 되는데요. 그당시 실제 컴퓨터 HDD 저장 공간은 10~100MB 수준이었습니다. 그래서 최대한 파일 크기를 작게 만들어야 좋았습니다. 메모리는 넉넉한 대신 파일은 팍팍하게 줄 수 있도록 자유도를 부여한 거라고 보시면 됩니다.

      지금은 패커/프로텍터에게 다양한 창의적인 기법이 가능하도록 빌미를 제공한 셈이 되었지만요... ^^~

      감사합니다.

  15. bach 2013.10.24 10:11 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요,

    rva를 raw로 변환하는 과정에서

    virtual address와 pointer to rawdata 값이 필요한데,

    예제에서는 저 표를 보고 구했잖아요

    다른 파일들은 virtual address와 pointer to rawdata 값을 어떤것을 보고

    알수 있는지 궁금합니다.

    • jaehyuk 2014.02.17 13:54 신고 댓글주소 | 수정 | 삭제

      peview같은 것으로 볼 수 있고, hxd같은 hexa editor로 따라 읽어가면서 보실수 있습니다

  16. 누구에 2016.02.16 14:13 댓글주소 | 수정 | 삭제 | 댓글

    관리자의 승인을 기다리고 있는 댓글입니다




IMAGE_NT_HEADERS - IMAGE_OPTIONAL_HEADER32


PE header 구조체 중에서 가장 크기가 큰 IMAGE_OPTIONAL_HEADER32 입니다.
(64 bit PE 파일의 경우 IMAGE_OPTIONAL_HEADER64 구조체를 사용합니다.)

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;
    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

* 출처 : Microsoft 의 Visual C++ 에서 제공하는 winnt.h


IMAGE_OPTIONAL_HEADER32 구조체에서 주목해야 할 멤버들은 아래와 같습니다.
이 값들 역시 파일 실행에 필수적인 값들이라서 잘 못 세팅되면 파일이 정상 실행 되지 않습니다.


#1. Magic
IMAGE_OPTIONAL_HEADER32 인 경우 10Bh, IMAGE_OPTIONAL_HEADER64 인 경우 20Bh 값을 가지게 됩니다.


#2. AddressOfEntryPoint
EP(Entry Point) 의 RVA(Relative Virtual Address) 값을 가지고 있습니다.


#3. ImageBase
프로세스의 가상 메모리는 0 ~ FFFFFFFFh 범위입니다. (32 bit 의 경우)
ImageBase 는 이렇게 광활한 메모리내에서 PE 파일이 로딩(매핑)되는 시작 주소를 나타냅니다.

EXE, DLL 파일은 user memory 영역인 0 ~ 7FFFFFFFh 범위에 위치하고,
SYS 파일은 kernel memory 영역인 80000000h ~ FFFFFFFFh 범위에 위치합니다.


일반적으로 개발 도구(VB/VC++/Delphi)들이 만들어내는 EXE 파일의 ImageBase 값은 00400000h 이고,
DLL 파일의 ImageBase 값은 01000000h 입니다. (물론 다른 값도 가능합니다.)

PE loader 는 PE 파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩(매핑) 시킨 후
EIP 레지스터 값을 ImageBase + AddressOfEntryPoint 값으로 세팅합니다.


#4. SectionAlignment, FileAlignment
PE 파일은 섹션으로 나뉘어져 있는데 파일에서 섹션의 최소단위를 나타내는 것이 FileAlignment 이고
메모리에서 섹션의 최소단위를 나타내는 것이 SectionAlignment 입니다.
(하나의 파일에서 FileAlignment 와 SectionAlignment 의 값은 같을 수도 있고 틀릴 수도 있습니다.)

따라서 파일/메모리의 섹션 크기는 반드시 각각 FileAlignment/SectionAlignment 의 배수가 되어야 합니다.


#5. SizeOfImage
PE 파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image 가 차지하는 크기를 나타냅니다.
일반적으로 파일의 크기와 메모리에 로딩된 크기는 다릅니다. 
(각 섹션의 로딩 위치와 메모리 점유 크기는 나중에 소개할 Section Header 에 정의 되어 있습니다.)


#6. SizeOfHeader
PE header 의 전체 크기를 나타냅니다.
이 값 역시 FileAlignment 의 배수 이어야 합니다.

파일 시작에서 SizeOfHeader 옵셋만큼 떨어진 위치에 첫번째 섹션이 위치합니다.


#7. Subsystem
1 : Driver file (*.sys)
2 : GUI (Graphic User Interface) 파일 -> notepad.exe 와 같은 윈도우 기반 어플리케이션
3 : CUI (Console User Interface) 파일 -> cmd.exe 와 같은 콘솔 기반 어플리케이션


#8. NumberOfRvaAndSizes
마지막 멤버인 DataDirectory 배열의 갯수

구조체 정의에 분명히 배열 갯수가 IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16) 이라고 명시 되어 있지만,
PE loader 는 NumberOfRvaAndSizes 의 값을 보고 배열의 크기를 인식합니다.



#9. DataDirectory
IMAGE_DATA_DIRECTORY 구조체의 배열로써, 배열의 각 항목마다 정의된 값을 가지게 됩니다.

아래에 각 배열 항목을 나열하였습니다.

DataDirectory[0] = EXPORT Directory        
DataDirectory[1] = IMPORT Directory        
DataDirectory[2] = RESOURCE Directory      
DataDirectory[3] = EXCEPTION Directory     
DataDirectory[4] = SECURITY Directory      
DataDirectory[5] = BASERELOC Directory     
DataDirectory[6] = DEBUG Directory         
DataDirectory[7] = COPYRIGHT Directory     
DataDirectory[8] = GLOBALPTR Directory     
DataDirectory[9] = TLS Directory           
DataDirectory[A] = LOAD_CONFIG Directory   
DataDirectory[B] = BOUND_IMPORT Directory  
DataDirectory[C] = IAT Directory           
DataDirectory[D] = DELAY_IMPORT Directory  
DataDirectory[E] = COM_DESCRIPTOR Directory
DataDirectory[F] = Reserved Directory       


여기서 말하는 Directory 란 그냥 어떤 구조체의 배열이라고 생각하시면 됩니다.

빨간색으로 표시한 EXPORT, IMPORT, RESOURCE, TLS Directory 를 눈여겨 보시기 바랍니다.
특히 IMPORT 와 EXPORT Directory 구조는 PE header 에서 매우 중요하기 때문에 나중에 따로 설명하도록 하겠습니다.

나머지는 크게 중요하지 않다고 보시면 됩니다.


이제 실제로 notepad.exe 의 IMAGE_OPTIONAL_HEADER32 를 확인해 보겠습니다.


구조체 멤버별 값과 설명은 아래와 같습니다.

[ IMAGE_OPTIONAL_HEADER ] - notepad.exe

 offset   value   description
-------------------------------------------------------------------------------
000000F8     010B magic
000000FA       07 major linker version
000000FB       0A minor linker version
000000FC 00007800 size of code
00000100 00008C00 size of initialized data
00000104 00000000 size of uninitialized data
00000108 0000739D address of entry point
0000010C 00001000 base of code
00000110 00009000 base of data
00000114 01000000 image base
00000118 00001000 section alignment
0000011C 00000200 file alignment
00000120     0005 major OS version
00000122     0001 minor OS version
00000124     0005 major image version
00000126     0001 minor image version
00000128     0004 major subsystem version
0000012A     0000 minor subsystem version
0000012C 00000000 win32 version value
00000130 00014000 size of image
00000134 00000400 size of headers
00000138 000126CE checksum
0000013C     0002 subsystem
0000013E     8000 DLL characteristics
00000140 00040000 size of stack reserve
00000144 00011000 size of stack commit
00000148 00100000 size of heap reserve
0000014C 00001000 size of heap commit
00000150 00000000 loader flags
00000154 00000010 number of directories
00000158 00000000 RVA  of EXPORT Directory
0000015C 00000000 size of EXPORT Directory
00000160 00007604 RVA  of IMPORT Directory
00000164 000000C8 size of IMPORT Directory
00000168 0000B000 RVA  of RESOURCE Directory
0000016C 00008304 size of RESOURCE Directory
00000170 00000000 RVA  of EXCEPTION Directory
00000174 00000000 size of EXCEPTION Directory
00000178 00000000 RVA  of SECURITY Directory
0000017C 00000000 size of SECURITY Directory
00000180 00000000 RVA  of BASERELOC Directory
00000184 00000000 size of BASERELOC Directory
00000188 00001350 RVA  of DEBUG Directory
0000018C 0000001C size of DEBUG Directory
00000190 00000000 RVA  of COPYRIGHT Directory
00000194 00000000 size of COPYRIGHT Directory
00000198 00000000 RVA  of GLOBALPTR Directory
0000019C 00000000 size of GLOBALPTR Directory
000001A0 00000000 RVA  of TLS Directory
000001A4 00000000 size of TLS Directory
000001A8 000018A8 RVA  of LOAD_CONFIG Directory
000001AC 00000040 size of LOAD_CONFIG Directory
000001B0 00000250 RVA  of BOUND_IMPORT Directory
000001B4 000000D0 size of BOUND_IMPORT Directory
000001B8 00001000 RVA  of IAT Directory
000001BC 00000348 size of IAT Directory
000001C0 00000000 RVA  of DELAY_IMPORT Directory
000001C4 00000000 size of DELAY_IMPORT Directory
000001C8 00000000 RVA  of COM_DESCRIPTOR Directory
000001CC 00000000 size of COM_DESCRIPTOR Directory
000001D0 00000000 RVA  of Reserved Directory
000001D4 00000000 size of Reserved Directory


여기까지 NT Header 의 설명을 마치고 다음에 Section Header 에 대해서 살펴보도록 하겠습니다.

(continue)


 

  1. 뭉이 2010.01.06 18:01 신고 댓글주소 | 수정 | 삭제 | 댓글

    하나의 파일에서 FileAlegnment과 SectionAlegnment는 같을 수도 있고 다를수도 있다고 했는데..
    만약 SectionAlegnment이 FileAlegnment보다 작게 되면
    파일의 각 섹션에 있는 내용이 로드될때,... 내용이 잘리게 되는 경우는 없는지요?..

    SectionAlegnment과 FileAlegnmentr값은 누가 어떻게 결정 되나요?

    • reversecore 2010.01.06 23:23 신고 댓글주소 | 수정 | 삭제

      뭉이님, 안녕하세요.

      기발한 생각이네요~

      SectionAlignment 가 FileAlignment 보다 작은 경우는 본적이 없습니다만... 굳이 안될것 같지는 않네요.

      이 값들은 기본 단위값이기 때문에 내용이 잘리지 않도록 단위의 배수만큼 섹션 크기를 조절하면 될거 같습니다.

      이 값들은 개발 툴에서 결정되는데요...
      VC++ 에서 옵션을 못찾겠네요...

      검색을 좀 해봐야 하겠습니다.

      감사합니다.

    • 뭉이 2010.01.07 00:42 신고 댓글주소 | 수정 | 삭제

      아...SectionAlegnment는 항상 FileAlignment보다 크게 정해진다는 말씀이시죠?....

      답변 감사합니다..^^

      크게 중요한 부분은 아닌거 같은데...글을 읽다가...
      자꾸 그부분이 이상하게 궁금해서...물어봤습니다..

      이런사소한 질문에 시간내서 답변달아주셔서 정말 감사합니다..^^
      ...

    • newbie 2010.07.21 19:52 신고 댓글주소 | 수정 | 삭제

      SectionAlignment와 FileAlignment의 값이 상당히 중요한걸로 알고 있습니다. 이게 제대로 맞지 않으면 오류를 내는것 같더라구요 예전에 확인해본 결과 FileAlignment를 SectionAlignment값보다 크게 잡으면 오류가 났었던것 같아요. 아무리 커도 SectionAlignment값보다는 크지 않아야 하고 꼭 0200h의 배수가 되어야 하나 그랬던걸로 기억합니다. 오래전 기억이어서 가물가물하지만 참고가 되었으면 좋겠네요~

  2. Vi0 2010.08.04 21:23 신고 댓글주소 | 수정 | 삭제 | 댓글

    PE IMAGE란것이 무엇인가요.?
    PE파일 전체를 말하는건가요?

  3. 비빅 2010.08.04 23:11 신고 댓글주소 | 수정 | 삭제 | 댓글

    내용중에 #.5 SizeOfImage 설명이 잘 이해가 안되는데요 특히 PEImage가 무엇을 말하는지
    모르겠습니다;; 순서대로 읽어왔는데 처음보는거같은데 #.5부분만 조금 자세히
    설명 부탁드립니다 ^^;

  4. reversecore 2010.08.06 07:20 신고 댓글주소 | 수정 | 삭제 | 댓글

    Vi0 님과 비빅님께서 거의 동시에 같은 내용의 질문을 해주셨네요~ ^^

    IMAGE 라는 용어는 PE 구조를 만든 MS 에서 만들어낸 용어입니다.
    보통은 PE 파일이 메모리에 로딩된 상태에서 PE 메모리 영역 전체를 말한다고 생각하시면 거의 정확합니다.

    PE 헤더 정보중에 SizeOfImage 라는 것이 있는데 이것이 바로 PE Image 가 점유한 메모리 크기를 의미하는 것입니다. 이 크기는 당연히 파일 크기와는 다르지요.

    PE File Format 의 묘미중의 하나가 바로 파일 상태의 모습과 메모리 상태의 모습이 다르다는 것이지요.

    감사합니다.

    • 비빅 2010.08.06 13:46 신고 댓글주소 | 수정 | 삭제

      답변 감사합니다 ^^

      설명해주신대로 PE이미지가 PE메모리 영역 전체라고 하셔서 제 생각으로는 image_section_header 들의
      Virtual Size 값들을 모두 합하면 PE Image 값이
      나오는건가? 생각해보고 계산해봤는데..

      ㅋㅋ 역시 그건아니더군요;;
      Virtual Size값이 어떤 계산에 의해서 나오는지
      궁금합니다 ㅎ

    • reversecore 2010.08.09 11:27 신고 댓글주소 | 수정 | 삭제

      VirtualSize 값이요?
      그건 섹션 헤더에 나와 있구요...

      아마 SizeOfImage 값이 궁금하신것 같은데요...

      VirtualSize 를 다 합쳐도 SizeOfImage 값이 나오지 않는 이유는 SectionAlignment 때문입니다. SectionAlignment (보통 1000) 에 맞게 확장시킨후 더하시면 정확한 값이 나오게 됩니다. (예를 들면 첫번째 섹션의 VirtualSize = E00 이면 SectionAlignment 에 맞춰서 1000 으로 확장됩니다.)

      이렇게 모든 섹션의 보정된 VirtuslSize 를 다 더하고,
      마지막으로 PE 헤더 크기만큼 더하면 됩니다. (그건 그냥 쉽게 첫번째 섹션의 RVA 값을 더해주면 되지요.)

      잘 이해 안되시면 다시 질문 올려주세요~

      감사합니다.

  5. 비빅 2010.08.09 23:09 신고 댓글주소 | 수정 | 삭제 | 댓글

    아 제가 SizeOfImage를 물어본다는게 VirtualSize값을 물어봤네요;;

    알려주신대로 계산해보니 제대로 계산이 됩니다 감사합니다^^
    SectionAlignment값에 의해 확장까진 생각했는데 PE헤더 만큼 더해주는걸 생각못했네요 ㅎㅎ

  6. 호동왕자 2010.11.30 14:42 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.

    몇일 동안 헤메다가 이제서야 여기까지 왔네요.

    보는데 궁금증이 생겨서요. 오늘도 바로 답변해 주시고 정말 감사 합니다.

    질문은 이렇습니다.

    IMAGE_OPTIONAL_HEADER

  7. 호동왕자 2010.11.30 14:46 신고 댓글주소 | 수정 | 삭제 | 댓글

    위에 글이 삭제가 안되네요. 잘못 클릭 했는데 말이죠..

    IMAGE_OPTIONAL_HEADER 을 실제적으로 확인해 보았을때

    지금 현재 스크린샷을 찍으셔서 파란칸으로 만드셨잖아요..

    그런데 처음에 0B 01 07 ~ 00 00 00 00 으로 끝나잖아요...

    그런데 제가 PEview로 확인을 해봤는데요.

    맨처음 desscription magic에서 data가 01 0B 로 시작 하는데요

    제가 지금 잘못 된건지.. 알고 싶어서요..

    • reversecore 2010.12.03 16:50 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      Endian 문제인데요...

      위 그림의 Hex Editor 에서는 0B 01 로 나오지만...
      구조체 멤버로는 WORD 타입이기 때문에
      PEView 에서 읽으면 010B 가 맞습니다.

      Intel CPU 는 Little Endian 방식을 사용하기 때문에 이처럼 값이 뒤집혀 저장됩니다.

      * Little Endian 이라고 검색을 해보시면 관련 설명이 많이 검색될 것입니다.

      감사합니다.

  8. TeamKhan 2011.04.01 18:36 신고 댓글주소 | 수정 | 삭제 | 댓글

    size of image값을 구하는방법을 설명해주셧는데
    그부분이 잘 이해가안가서요..확장시킨후 더하라는말이 무엇인가요?
    그리고 Virtual size=e00 이면 SectionAlignment 에 맞춰서 1000 으로 확장됩니다.)
    라는 말의 의미도 무슨뜼인지 잘 모르겟습니다...
    virtual size가무엇인지요 ㅠㅠ sectionAlignment 는 위글에서 설명해주셧듯이
    메모리상에서 섹션의 최소단위인건 알겟구요...ㅠ
    모든 섹션의 보정된 VirtuslSize 를 다 더하고,
    마지막으로 PE 헤더 크기만큼 더하면 됩니다. (그건 그냥 쉽게 첫번째 섹션의 RVA 값을 더해주면
    된다는말도 이해가잘안되내요...RVA가 제가 알기론 기준점이있고 그기준점에서부터 OFFSET값으로 RVA가 구성된다는것으로알고잇는데요...
    쉽게말씀드려서 sectionAlignment뺴고는 전부 무슨말씀이신지 이해가안가내요...

    • reversecore 2011.04.06 01:04 신고 댓글주소 | 수정 | 삭제

      안녕하세요. ^^

      네, 위의 설명이 좀 어려운게 사실입니다.
      먼저 개념을 이해하시면 설명이 조금 보기 편하실 거에요.

      음... 쉽게 말하자면...
      Windows 운영체제에서 메모리를 할당하는 방법에 관한 건데요...

      예전에 귤->박스->컨테이너->창고 식으로 설명을 많이 했었는데요... 잘 생각이 안나네요. ^^

      어쨌든 컴퓨터 메모리, 하드디스크 등은 기본 단위 크기로 움직인다는 것이 핵심입니다. 기본 규격이라고 보시면 됩니다. 즉 1 바이트 저장을 위해서 SectionAlignment (보통 1000) 바이트가 필요한거죠. PE 파일에서도 실제 필요한 메모리 크기는 10001 바이트라고 하면 기본 단위 규격에 맞게 11000 바이트를 잡는 것이지요.

      * VirtualSize 는 메모리 크기를 의미합니다.

      잘 이해가 안되시면 다시 질문해 주세요~

      감사합니다.

  9. reversingk 2011.05.17 13:40 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세여 ^^ 리버스코어님 강의 잘봤습니다.
    그런데 궁굼한것이 하나 생겨서 여쭈어봅니다.
    pe파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩 (매핑)시킨후 EIP 레지스터 값을 addressofEntrypoint + imageBase 값으로 셋팅 한다는 말이 메모리에 로딩되었을때
    시작점을 말하는 것인가여?? 아니면 main()의 시작점을 말하는 것인가요?

    그리고 notepad 를 ollydbg로 열어보니 00da3689값으로 나오던데 혹시 이값이 맞나여?
    마즈면 왜 01003689가 아닌 00da3689값이 나오는지도 알고 싶습니다.

    너무 질문만 하는거 아닌지 모르겟네여 ^^;; ㅎㅎ

    • reversecore 2011.05.18 20:08 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      다른 곳에 비슷한 질문을 올려 주셨죠? ^^

      ASLR 기능 때문이구요. 아래 포스트를 참고하시면 되겠습니다.

      http://www.reversecore.com/69

      감사합니다.

  10. EP 2011.06.04 15:43 신고 댓글주소 | 수정 | 삭제 | 댓글

    EP(Entry Point)가 메모리에 로딩되는 위치를 말하는 건가요 ?

    RVA로 표현된다면
    739D니까

    메모리에 올라갈경우 100739D가 되는건가요 ?

    EntryPoint 개념을 잘 모르겠네요 ..

    • reversecore 2011.06.06 21:32 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      EP(EntryPoint) 란 사용자 프로그램에서 최초로 실행되는 코드 주소를 말합니다. PE Header 에 RVA 로 명시되어 있지요.

      그리고 PE 파일이 로딩 되는 기준 주소를 ImageBase 라고 하지요.

      따라서 EP 의 VA = ImageBase(1000000) + RVA of EP(739D) = 100739D 가 됩니다.

      감사합니다.

  11. SmartSnake 2011.10.27 17:30 신고 댓글주소 | 수정 | 삭제 | 댓글

    pe파일에서.. rva랑 offset이랑 이해가 잘안되여..

    rva는 기준주소로부터의 상대주소값을 말하고
    file offset은 하드디스크상에 있을때의 메모리 주소를말하는거지요?
    파일이 메모리에 올라오면 RVA로 되는거구요..맞나요?!!

    • reversecore 2013.02.25 21:51 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      네, 맞습니다.

      PE 파일이 하드디스크의 파일로 존재할 때와 메모리의 PE Image 로서 존재할 때의 모습(형태)가 달라지기 때문에...

      각각의 옵셋을 얘기할 때 file offset(RAW), RVA 라고 얘기합니다.

      감사합니다.

  12. 2013.02.25 20:29 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

    • reversecore 2013.02.25 21:49 신고 댓글주소 | 수정 | 삭제

      안녕하세요. 반갑습니다~ ^^

      winhack은 안써봤습니다.

      질문의 요지는 Windows OS 의 핵심 개념중의 하나인 "모든 프로세스에게는 4GB 크기의 가상메모리(VirtualMemory)가 할당된다" 는 개념인것 같습니다.

      따라서 1.exe 프로세스의 ImageBase 는 40000h 이고, 2.exe 프로세스의 ImageBase 도 40000h 이 될 수 있는 것입니다. 물리적 메모리는 완전 다르지만 각 프로세스는 자신이 4GB 크기의 물리메모리를 가지고 있다고 착각하는 것이죠.

      이 개념을 사용하기 때문에 (일반적으로는) 다른 프로세스의 메모리에 접근할 수 없습니다.

      감사합니다.

  13. Null0 2014.07.01 12:56 신고 댓글주소 | 수정 | 삭제 | 댓글

    이론 상으로는 file alignment가 1이여도 정상적인 실행이 되야하는데 자꾸 오류가 뜨네요
    위에 댓글다신 분 말씀처럼 0x200의 배수여야만 하는건가요?





티스토리 툴바