3. Broken Format


3.4. Body


Body는 오브젝트들로 구성되어 있다고 앞 장에서 설명하였다. 이 영역은 PDF 파일의 대부분을 차지할 만큼 방대하다. 모든 내용을 다루기는 어렵고, 극히 일부에 대해서만 다루고자 한다.

 

가장 먼저 다룰 필드는 스트림의 길이를 나타내는 /Length 키이다. PDF의 오브젝트는 아래 그림과 같이 오브젝트의 속성에서 스트림의 압축방식(/Filter/FlateDecode)과 길이(/Length 145)를 나타낸다

여기서 이 /Length 키는 PDF Reader가 참고하는 부분이 아니다. 이 키에 대한 값이 실제 stream의 길이와 다르더라도 문서는 정상적으로 읽히기 때문이다. , /Length 키와는 무관하게 PDF Reader stream 키워드와 endstream 키워드로만 스트림을 읽어들인다.


stream endstream 키워드 사이에 “endstream”이 존재하는 Fake Keyword가 삽입되는 케이스도 있다. 이 경우 어떻게 되는가에 대해서는 아래 URL을 참고하기 바란다.

http://cerbero-blog.com/?p=1612


각종 키워드가 아래 그림과 같이 오브젝트 사이에 마구잡이로 존재해도 아무 문제 없다.

 PDF는 위치 또는 길이를 나타내는 필드를 신뢰하지 않는다. , 키워드에 따라서 이후에 반드시 해당 값이 존재해야 한다는 제약이 없다. 이러한 것은 PDF Reader에서 이상한 포맷이라고 간주하고, 복구해 줄 수도 있다(포맷이 크게 변할 수 있다).

PDF 문서를 파싱할 때에는 Header - Trailer - Cross-Reference Table - Body 순으로 하기에는 부적합하다. 따라서 문서의 첫 부분부터 순차적으로 내용을 읽어나가야 한다.

 

귀찮아서 점점 대충 쓰고있다.



Posted by bong9
,

3. Broken Format


3.3. Cross-Reference Table


Cross-Reference Table xref 키워드로 시작되는 아래 그림과 같은 구조로 이루어져있다.

이 샘플에서 Line 146의 오브젝트 시작 번호(0)와 개수(20)가 신뢰성 있는 것인지, Line 147부터 Line 166까지 각각의 엔트리에 있는 Offset과 사용 여부 필드들이 신뢰성 있는지를 알아볼 것이다. 다음과 같은 의문에 대해 테스트를 해 본다.


1. Cross-Reference Table이 없어도 문서 파일이 열리는가?

2. 오브젝트 시작 번호가 실제 Body의 정보와 다르더라도 문서 파일이 열리는가?

3. 오브젝트의 개수가 실제 Body의 정보와 다르더라도 문서 파일이 열리는가?

4. 오브젝트의 개수가 실제 Entry 개수와 일치하지 않더라도 문서 파일이 열리는가?

5. Entry의 오프셋 정보가 실제 오브젝트의 위치를 가리키지 않더라도 문서 파일이 열리는가?

6. Entry의 오브젝트 사용 여부 필드가 문서 파일을 읽는 데에 영향을 미치는가?


1번 의문에 대해서는 위와 같이 Cross-Reference Table을 전부 제거해버리고 문서를 열어보면 된다. Trailer와 마찬가지로 문서는 너무나 잘 열린다.


오브젝트 시작 번호를 50으로, 오브젝트 개수를 4로 변경하고 실행해본다. 이것으로 2, 3, 4번의 답을 얻을 수 있다.


Entry의 오프셋 정보를 바꾸고, 사용 안함(f)로 변경한 후 테스트한다. 이렇게 5, 6번의 의문점을 풀 수 있다.


모든 테스트에서 문서는 너무나 잘 열렸다. 결론적으로 Cross-Reference Table은 문서가 열리는 것에 대해서 전혀 관계가 없음으로 확인되었다.



Posted by bong9
,

3. Broken Format


3.2. Trailer


PDF 파일의 끝에는 Trailer가 존재한다고 앞 장의 구조 설명에서 언급하였다.



위 그림에서의 샘플은 Header - Body - XrefTable - Trailer - XrefTable - Trailer 순으로 구성되어 있다. 선택한 영역인 Trailer 영역을 전부 삭제하더라도, 파일은 문제 없이 실행된다.

여기서 몇 가지 가설을 세우고 각각의 가설을 증명해 볼 수 있다.


가설 1. 두 번째 Cross-reference Table이 무시되고, 첫 번째 Trailer가 인식된다.


두 번째 Cross-reference Table 영역을 지우고 실행시켜 본 결과, 문제없이 실행됨을 확인하였다. 이것으로 두 번째 Cross-reference Table이 무시된다는 것은 어렴풋이 알 수 있겠지만, 첫 번째 Trailer가 인식된다는 것을 증명하지는 않는다.


가설 2. Trailer가 없어도 PDF Reader는 문서를 문제없이 읽어들인다.


첫 번째 Trailer부터 파일의 끝까지 지우고 실행해 본 결과, 실행 오류가 발생함을 확인하였다. 정말 PDF Reader가 Trailer를 정상적으로 인식 하는건가에 대한 의문을 다시 품고, 다른 가설을 세워보도록 한다.


가설 3. Trailer 내의 요소들이 반드시 전부 존재해야 한다.



샘플의 두 번째 XrefTable Trailer를 제거한 후 테스트를 진행해 본다. Trailer의 요소는 trailer 키워드, Dictionary, startxref 키워드, xref table의 위치값, EOF marker 5개가 존재한다. 각각의 요소들이 신뢰성이 있는가에 대해 알아보도록 한다.




startxref 키워드와, xref table의 위치값, EOF markertrailer에서 없더라도 정상적으로 문서가 열리는 것으로 확인되었다. 하지만 PDF Reader는 열린 문서를 닫을 때 다음과 같은 메시지를 출력한다.




Adobe Reader로부터 저장 된 PDF 파일은 Trailer가 없는 모습이고, 상당히 많은 구조가 변경되었다. 심지어 새로 저장 된 파일에는 trailer 키워드가 존재하지 않는다.




또 다른 특이사항으로는, Trailer가 없음에도 startxref 키워드가 존재한다는 것이다.





여기까지의 테스트로 다음과 같은 사실을 알 수 있다.


1. startxref Trailer에 종속적이지 않다.

2. Trailer가 없는 PDF 파일도 존재하고, 이러한 파일이 PDF Reader에 의해 읽혀질 수 있다.

3. startxref 키워드와, xref table의 위치값, EOF marker는 무시될 수 있다.

Posted by bong9
,