<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>누리랩 기술 블로그</title>
    <description>세상의 모든 것들이 불편하지 않도록 연구하는 사람들의 모임
</description>
    <link>http://nurilab.github.io/</link>
    <atom:link href="http://nurilab.github.io/rss" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 13 Dec 2022 12:12:01 +0900</pubDate>
    <lastBuildDate>Tue, 13 Dec 2022 12:12:01 +0900</lastBuildDate>
    <generator>Jekyll v3.9.2</generator>
    
      <item>
        <title>드라이브 내 파일 탐색</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/07/ntfs1/&quot;&gt;첫번째 글: NTFS 파일 시스템&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/08/ntfs2/&quot;&gt;두번째 글: NTFS 파일 시스템 partition data 1&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/12/ntfs3/&quot;&gt;세번째 글: NTFS 파일 시스템 partition data 2&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;네번째 글: 드라이브 내 파일 탐색&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-드라이브-내-파일-위치-탐색&quot;&gt;1. 드라이브 내 파일 위치 탐색&lt;/h2&gt;

&lt;p&gt;앞서 2장에서는 드라이브 내 Root Directory에 접근하는 방법을 확인하였다. Root Directory는 아래의 과정을 통해 접근할 수 있다.&lt;/p&gt;

&lt;p&gt;① HDD에 접근&lt;br /&gt;
② LBA 1에서 기본 정보들 확인, LBA 2 ~ 33중 원하는 Partition 확인 후 해당 위치로 이동&lt;br /&gt;
 (Number of Partition Entry, Size Of Partition Entry, First LBA)&lt;br /&gt;
③ 해당 Partition 정보 확인 후 Start $MFT 확인 및 이동&lt;br /&gt;
 (Bytes per Sector, Sector per Cluster, Start $MFT, Cluster per MFT Record)&lt;br /&gt;
④ $MFT의 $DATA 항목(Attribute Type : b’\x80’) 에서 Run List 확인&lt;br /&gt;
 (MFT Entry Size, $MFT – Run List)&lt;br /&gt;
⑤ $MFT(#5)의 $Index Allocation 항목(Attribute Type : b’\xA0)에서 Run List 확인&lt;br /&gt;
 ($MFT(#5)- Run List, Root Directory 도착)&lt;/p&gt;

&lt;h3 id=&quot;11-resident-파일의-경우&quot;&gt;1.1 Resident 파일의 경우&lt;/h3&gt;

&lt;p&gt;Resident 파일은 Attribute 내에 정보를 가지고 있기 때문에, 데이터 확인 과정에서 별도의 Run List를 구성할 필요가 없다. 탐색에 사용할 파일은 ‘C:\AMD\Q.txt‘ 이다. 해당 파일은 아래의 &amp;lt;그림 4-1&amp;gt;을 통해 확인 할 수 있는데, 총 8 Bytes의 정보를 포함하고 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_1.png&quot; alt=&quot;&amp;lt;그림 4-1&amp;gt; 파일 Q.txt와 그 내부 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;해당 파일은 Root Directory에서 AMD 디렉토리를 찾은 다음, 디렉토리 내부의 Q.txt Address로 이동하면 내부의 Attribute 중에 $Data 항목에서 내용을 확인 할 수 있을 것이다. 앞에서 Root Directory의 위치가 Cluster 813 / LBA 6504 임을 확인 하였으니, 이를 통해 AMD로 이동할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_2.png&quot; alt=&quot;&amp;lt;그림 4-2&amp;gt; Root Directory에서 15번째에 위치한 AMD 파일의 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 &amp;lt;그림 4-2&amp;gt;를 확인해 보면 MFT Reference Address가 있는데, 이는 0x1DBDF(HEX) / 121823(DEC) 인데, 이는 앞서 언급한 것과 마찬가지로 $MFT Entry(#121823)이라는 의미이다. 그러므로 $MFT Entry(#121823) 의 위치는 $MFT(#0)의 위치 + 121823 * MFT Entry Size 를 통해 계산할 수 있다. $MFT(#0)의 위치는 Cluster 786432이고, MFT Entry는 LBA 2개 이므로,&lt;/p&gt;

&lt;p&gt;$MFT Entry(#121823)의 위치 = 786432 * 8 + 121823 * 2 = LBA 6535102&lt;/p&gt;

&lt;p&gt;이다. 이는 아래의 &amp;lt;그림 4-3&amp;gt;에서도 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_3.png&quot; alt=&quot;&amp;lt;그림 4-3&amp;gt; WinHex 에서 확인할 수 있는 Entry(#121823)의 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 4-4&amp;gt;는 AMD 디렉토리의 정보를 가지고 있는 Attribute들의 정보를 보여주고 있다. 해당 위치에는 여러 파일들의 정보가 있는데, 이 중 Q.txt는 &amp;lt;그림 4-4&amp;gt;의 하단에 위치해 있고, &amp;lt;그림 4-5&amp;gt;에서 정보를 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_4.png&quot; alt=&quot;&amp;lt;그림 4-4&amp;gt; Root Directory\AMD에 위치한 파일들의 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_5.png&quot; alt=&quot;&amp;lt;그림 4-5&amp;gt; Root Directory\AMD\Q.txt에 대한 기본 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 4-4&amp;gt;의 8번째부터 Q.txt에 대한 정보가 시작이다. 8~13번째가 Address에 대한 정보이므로, MFT Entry (#0x7F5F(HEX) / #32607(DEC)) 로 이동하여 파일의 자세한 정보를 얻을 수 있다. 해당 Address로 이동한 후, $Data 항목을 확인하니 아래의 &amp;lt;그림 4-6&amp;gt;의 정보를 확인하였다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_6.png&quot; alt=&quot;&amp;lt;그림 4-6&amp;gt; MFT Entry(# 32607)의 Attribute 중 $Data 항목 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Resident Data Length가 8인데, Res Offset가 24이므로, 총 32바이트 중 24번째 Bytes 부터 총 8 Bytes의 값을 Data로 가진다. Root Directory의 위치부터 시작하여 AMD 라는 이름의 디렉토리 위치를 확인하였고, Q.txt 파일 위치를 확인한 후 내부의 정보를 확인 할 수 있었다. 이번에는 좀 더 많은 디렉토리 경로를 가진 Non Resident 파일을 확인하여 Resident 파일과 어떤 부분이 다른지 비교 할 것이다.&lt;/p&gt;

&lt;h3 id=&quot;12-non-resident-파일의-경우&quot;&gt;1.2 Non Resident 파일의 경우&lt;/h3&gt;

&lt;p&gt;이번에 탐색할 파일은 C:\AMD\AMD-Software-Adrenalin-Edition-22.10.1-MinimalSetup-221003_web\setup.exe 이다. &amp;lt;그림 4-3&amp;gt;에서 AMD-Software-Adrenalin-Edition-22.10.1-MinimalSetup-221003_web(이하 AMD-Software)으로 분기하는 것으로 탐색할 수 있다. AMD-Software 파일의 정보는 아래 &amp;lt;그림 4-7&amp;gt;에서 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_7.png&quot; alt=&quot;&amp;lt;그림 4-7&amp;gt; AMD-Software 파일의 기본 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위 파일은 Setup.exe파일로 가기 위한 경로이기 때문에, 파일의 위치만 확인하고 넘어갈 수 있다. 위의 정보를 바탕으로 MFT Entry(#0x1DBE0(HEX) / #121824(DEC)로 이동하여 같은 방법으로 Setup.exe 정보를 확인하면 아래의 &amp;lt;그림 4-8&amp;gt;와 같은 정보를 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_8.png&quot; alt=&quot;&amp;lt;그림 4-8&amp;gt; Setup.exe 파일의 기본 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;목표로 하는 파일의 기본정보에 도달하였으므로, 파일의 상세 정보를 확인하기 위해 MFT Entry(#0x1DBE3(HEX) / #121827(DEC))로 이동해야 한다. 이동 후 내부 Attribute 중 $Data 항목을 확인하면 해당 파일의 정보가 어디에 위치해 있는지 Run List를 구성하여 확인 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_9.png&quot; alt=&quot;&amp;lt;그림 4-9&amp;gt; MFT Entry(#0x1DBE3(HEX) / #121827(DEC))의 $Data &amp;amp; Run List&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Run List를 구성하였으므로, cluster 6246497로 이동하여 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_10.png&quot; alt=&quot;&amp;lt;그림 4-10&amp;gt; WinHex에서 확인한 Cluster 6246497의 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 4-9&amp;gt;을 통해 위에서 확인한 Cluster 시작 번호와, 총 개수가 &amp;lt;그림 4-10&amp;gt;과 일치하는 것을 확인할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;13-파일-복제&quot;&gt;1.3 파일 복제&lt;/h3&gt;

&lt;p&gt;예시로 사용할 파일은 다음과 같다&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_11.png&quot; alt=&quot;&amp;lt;그림 4-11&amp;gt; 데이터 복제에 사용할 예시 파일. Non Resident.txt&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위에서 설명해 둔 방법들을 활용하여 $Data를 찾으면&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_12.png&quot; alt=&quot;&amp;lt;그림 4-12&amp;gt; Non Resident.txt의 $Data Attribute&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 내용을 확인할 수 있는데, 여기서 Run Data를 구하면 아래 &amp;lt;그림 4-13&amp;gt;과 같다. 그리고 파일의 크기는 0xE8E(HEX) / 3726(DEC) Bytes 이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_13.png&quot; alt=&quot;&amp;lt;그림 4-13&amp;gt; &amp;lt;그림 4-12&amp;gt;의 Run List&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 Cluster와, 파일의 크기를 확인하여 아래의 코드를 작성하였다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_14.png&quot; alt=&quot;&amp;lt;그림 4-14&amp;gt; &amp;lt;그림 4-13&amp;gt;의 Run List를 확인하기 위한 테스트 코드&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 과정을 통해 디스크에 저장되어 있는 파일 데이터를 복제할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_15.png&quot; alt=&quot;&amp;lt;그림 4-15&amp;gt; &amp;lt;그림 4-14&amp;gt;의 코드 실행 결과. 데이터는 모두 0xE8E Bytes 이다.&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;14-삭제된-파일-복구&quot;&gt;1.4 삭제된 파일 복구&lt;/h3&gt;

&lt;p&gt;다음은 삭제된 파일의 복구에 대한 내용인데, 기본적인 내용은 위의 파일 복제와 비슷하지만, 파일이 삭제되면 필요에 따라 Cluster를 다른 파일에 할당하는 경우가 생길 수도 있다. 이런 경우 파일을 복구할 수 없다. 본 문서에서 다루는 파일의 복구는 해당 파일의 데이터가 보존되어 있는 경우에 한한다. 상술해 둔 방법들을 통해 AMD 파일 내의 setup.exe 를 복구하려고 한다. 우선 파일을 삭제하고 데이터의 변화를 확인하였다. AMD- Software 내부에서 여전히 Setup.exe 파일에 대한 정보를 포함하고 있었고, 이를 통해 해당 파일의 Address 값을 통해 이동하였다. MFT Entry 내부에서 MFT Entry Header가 가진 정보 중 Flag라는 항목이 있는데, 이 항목은 파일의 상태를 나타내는 값으로, 삭제가 되면 1 ~ 3이 아닌 다른 값을 가지게 된다. 아래의 &amp;lt;그림 4-16&amp;gt;를 통해 비교해 볼 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_16.png&quot; alt=&quot;&amp;lt;그림 4-16&amp;gt; Flag 값이 다른 두 파일&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 4-16&amp;gt;에서 아래에 있는 값이 삭제된 setup.exe의 MFT Entry Header이다. 삭제 후 0으로 값이 변경 된 것을 확인 할 수 있다. 삭제 후에도 이름이 남아서 어떤 파일에 대한 Address 정보인지 확인 할 수 있었다. 이후 Run List 정보가 동일하여 다음의 코드를 통해 데이터를 확인하였다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_17.png&quot; alt=&quot;&amp;lt;그림 4-17&amp;gt; 삭제된 Setup.exe의 데이터 복제를 위한 코드&quot; /&gt;&lt;/p&gt;

&lt;p&gt;삭제 직후에는 바로 코드를 통해 지정된 위치의 값을 읽어와서 기존의 데이터와 일치하는 파일을 생성하였으나, 시간이 경과함에 따라 시스템에서 새로운 파일을 해당 Address와 영역에 할당하여 기존의 Entry정보로는 더 이상 파일에 접근할 수 없게 되었다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_4_18.png&quot; alt=&quot;&amp;lt;그림 4-18&amp;gt; Setup.exe의 Address 였던 곳에 새롭게 할당된 파일의 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;시간의 경과에 따라 시스템에서 새롭게 파일을 할당하는 경우들이 빈번히 발생하기 때문에, 파일의 삭제 후 바로 복구하지 않으면 복구율이 떨어지는 문제가 발생하게 된다.&lt;/p&gt;
</description>
        <pubDate>Tue, 13 Dec 2022 02:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2022/12/13/ntfs4/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2022/12/13/ntfs4/</guid>
        
        <category>ntfs</category>
        
        
      </item>
    
      <item>
        <title>NTFS 파일 시스템 partition data 2</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/07/ntfs1/&quot;&gt;첫번째 글: NTFS 파일 시스템&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/08/ntfs2/&quot;&gt;두번째 글: NTFS 파일 시스템 partition data 1&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;세번째 글: NTFS 파일 시스템 partition data 2&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/13/ntfs4/&quot;&gt;네번째 글: 드라이브 내 파일 탐색&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h3 id=&quot;11-mft-탐색&quot;&gt;1.1. $MFT 탐색&lt;/h3&gt;

&lt;p&gt;위의 정보들을 활용하여 $MFT에 할당된 cluster를 확인해볼 수 있다. 그러기 위해 우선 헤더를 분석하고, 그 다음 내부의 Attribute 들의 정보를 확인해야 한다. Header에 FixUp이 있는 부분들은 우선적으로 FixUp을 통해 무결성을 확인하고 값을 교환해 준 다음, 다른 부분들을 확인해야 한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_1.png&quot; alt=&quot;&amp;lt;그림 3-1&amp;gt; $MFT(#0)의 Entry data 중 일부 (LBA 3221225472)&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;12-fixup-수행-방법&quot;&gt;1.2 FixUp 수행 방법&lt;/h3&gt;

&lt;p&gt;FixUp은 상술한 것과 마찬가지로 무결성 확인을 위해 배치해 두는 것이다. 미리 설정해 둔 값을 마커로 사용하여 데이터에 문제가 없음을 확인한 후 원래 값으로 되돌려주는 작업을 수행한 후 해당 섹터의 데이터를 사용해야 한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_2.png&quot; alt=&quot;&amp;lt;그림 3-2&amp;gt; FixUp 에시. 0~FFF까지의 데이터 중 일부이다.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 &amp;lt;그림 3-2&amp;gt;는 Fixup을 보여주기 위해 가져온 데이터이다. 위의 데이터에서 Fixup Offset을 통해서 FixUp의 수행방법을 확인할 수 있다. 여기서는 값을 계산하는 것이 아니기 때문에 Little Endian을 유지하여 표기하도록 하겠다.&lt;/p&gt;

&lt;p&gt;① 우선, 노란색으로 표시해 둔 것은 FixUp Offset으로 FixUp을 수행할 값들의 위치를 알려준다.
② 그다음으로 초록색으로 표기한 것은 FixUp count인데, 이는 FixUp과 연관된 숫자의 개수가 9개라는 것을 알려준다. 화살표 이후 처음 있는 0x6702
③ 화살표를 따라서 가면 0x6702라는 숫자가 있는데, 이는 하단의 8군데의 숫자들과 같은 값을 가지는데, 이 부분이 동일하지 않으면 무결성을 통과하지 못한다.
④ 만약 ③을 통과하게 되면 그 후 주황색 상자들을 사용할 차례인데, 이 숫자들로 파란색 박스의 숫자들을 순서대로 대체하면 FixUp을 수행한 원본 자료가 된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_3.png&quot; alt=&quot;&amp;lt;그림 3-3&amp;gt; $MFT(#0)의 Header Data&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/MFT_entry_header.png&quot; alt=&quot;&amp;lt;표 1&amp;gt; MFT Entry Header 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/resident_attribute_header.png&quot; alt=&quot;&amp;lt;표 2&amp;gt; Resident Attribute Header 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_4.png&quot; alt=&quot;&amp;lt;그림 3-4&amp;gt; $MFT(#0)의 $Standard Information&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_5.png&quot; alt=&quot;&amp;lt;그림 3-5&amp;gt; $MFT(#0)의 $Name&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 3-4&amp;gt;, &amp;lt;그림 3-5&amp;gt; 모두 8번째 byte 값이 0 인 것으로 Resident Type 인 것을 알 수 있다. Attribute Length를 통해 다음 Attribute 위치를 확인 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_6.png&quot; alt=&quot;&amp;lt;그림 3-6&amp;gt; $MFT(#0)의 $Data&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/MFT_entry_header.png&quot; alt=&quot;&amp;lt;표 3&amp;gt; Non Resident Attribute Header 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_7.png&quot; alt=&quot;&amp;lt;그림 3-7&amp;gt; Run List 예시. 해당 파일의 용량으로 4군데의 Cluster 묶음을 할당하였다.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 3-7&amp;gt;을 보면 Attribute Type이 $Data인 경우 중에서 Run List를 가진 경우의 정보를 확인 할 수 있다. Run List는 2가지의 정보를 가지고 있는데, 하나는 정보가 시작되는 Cluster 번호이고, 나머지는 할당 된 Cluster의 개수이다. &amp;lt;그림 3-7&amp;gt;의 두번째에 나오는 파란색의 박스들을 보면, 1 Byte의 숫자가 b’\x43’이라고 되어있고, 그 뒤에 3 Bytes 한 박스, 4 Bytes 한 박스가 있다. 1 Byte의 숫자 중 16의 자리와 1의 자리로 구분해서 볼 때, 16의 자리 숫자는 시작하는 클러스터 번호를 나타내는데 필요한 바이트의 크기를 의미하고, 1의 자리 숫자는 클러스터의 개수를 나타내는데 필요한 바이트의 크기를 의미한다. 그리고, 바로 뒤에 이 바이트들은 바로 뒤에 따라 나오는데, Cluster count에 해당되는 정보가 먼저 나오고, 그 다음 Cluster number가 나온다. 위의 자료들을 확인하면 하단의 &amp;lt;그림 3-8&amp;gt;과 같이 볼 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_8.png&quot; alt=&quot;&amp;lt;그림 3-8&amp;gt; $MFT(#0)의 Run List 분석 결과&quot; /&gt;&lt;/p&gt;

&lt;p&gt;각 클러스터 구간별 시작하는 위치는, 이전 클러스터들의 시작값 들의 누적 합으로 구할 수 있다. 예를 들어, 3번째의 Start Cluster 위치는&lt;/p&gt;

&lt;p&gt;786432 + 8945109 + 5452865 = 15195406&lt;/p&gt;

&lt;p&gt;이다. 위의 과정을 통해 $MFT(#0)이 어디에 할당되어 있는지를 확인 할 수 있었다. &amp;lt;그림 3-3&amp;gt;의 Header를 확인한 이후, FixUp을 수행하고, &amp;lt;그림 3-3&amp;gt;의 First Attribute Offset을 따라 56번째 Byte 값인 b’\x10’ 부분부터 시작하여 Attribute Type이 Data 인 곳으로 이동하였고, Run List를 확인하여 $MFT(#0)에 할당된 Cluster를 확인 할 수 있었다. 이는 모든 파일과 디렉토리에 대한 $MFT 배열을 파악한 것이다.&lt;/p&gt;

&lt;h3 id=&quot;13-index-탐색&quot;&gt;1.3 Index 탐색&lt;/h3&gt;

&lt;p&gt;Root Directory 내부의 파일을 탐색하기 위해 Root Directory의 Index 정보를 확인해야 한다. Root Directory는 두번째 글의 &amp;lt;표 2&amp;gt;에서 보여준 것처럼, $MFT Entry(#5)에 해당한다. 각 Entry에 2개의 LBA를 할당하므로, $MFT(#0)을 기준으로 10개의 LBA 뒤에 해당 Entry가 존재한다. 그러므로 해당 위치를 이동하기 위해서는 Cluster 786432 + Entry #5를 계산해야 하는데, 이는 LBA 786432&lt;em&gt;8 + 5&lt;/em&gt;2에 해당한다. LBA 6291466으로 이동하여 데이터를 확인해 보면 아래와 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_9.png&quot; alt=&quot;&amp;lt;그림 3-9&amp;gt; $MFT Entry(#5) Root Directory(LBA 6291466 ~ 6291467)의 일부&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_10.png&quot; alt=&quot;&amp;lt;그림 3-10&amp;gt; $MFT Entry(#5) Root Directory의 데이터 중 Attribute Type이 $Index Allocation인 경우&quot; /&gt;&lt;/p&gt;

&lt;p&gt;$MFT(#0)의 경우와 동일하게, Attribute Type과 Attribute Length를 확인하여 $Index Allocation로 이동한 후, Run List를 분석하여 Root Directory 위치를 확인 할 수 있다. 확인하면 cluster 813, cluster count = 2를 구할 수 있다. 해당 Cluster는 Root Directory와 그 내부에 들어있는 파일들의 정보를 가지고 있다. 이를 통해서 C 드라이브에 있는 파일들의 목록과 그 파일들의 정보들을 확인 할 수 있다.&lt;/p&gt;

&lt;p&gt;###1.4 Root Directory 탐색&lt;/p&gt;

&lt;p&gt;앞서 얻은 cluster 813으로 이동하면 INDX로 시작하는 Signature를 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_3_11.png&quot; alt=&quot;&amp;lt;그림 3-11&amp;gt; Cluster 813 / LBA 6504의 데이터. Root Directory의 기능을 가진다.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/index_header.png&quot; alt=&quot;&amp;lt;표 4&amp;gt; Index Header&quot; /&gt;&lt;/p&gt;

&lt;p&gt;두 번째 글의 &amp;lt;표 2&amp;gt;를 참고하여 &amp;lt;그림 3-11&amp;gt;에서 Index Header를 분석할 수 있다. 여기에도 FixUp을 우선적으로 수행해주어야 한다. 이후 아래의 &amp;lt;표 5&amp;gt;를 참조하여 Index Node Header를 분석해야 한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/index_node_header.png&quot; alt=&quot;&amp;lt;표 5&amp;gt; Index Node Header&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;표 1&amp;gt;의 구조를 통해 Index Offset이 b’\x40’인 것으로 확인 되었다. 그러므로 Index Entry는 Index Node Header의 시작점인 b’\x18’에서 offset만큼 떨어진 b’\x58’에서 시작인 것을 알 수 있다.&lt;/p&gt;

&lt;p&gt;이제 &amp;lt;표 2&amp;gt;의 정보들을 참고하여 Index Entry Size만큼 구간을 나누어서 위의 정보들을 확인하고, Name Offset 이후의 정보를 통해 해당 파일의 이름을 확인할 수 있다. MFT Reference Address는 $MFT(#0)을 기준으로 MFT Entry 상의 번호를 나타낸다. MFT Entry는 LBA를 2개씩 할당하여 사용하기 때문에, Root Directory로부터 원하는 파일을 찾아가기 위해서는 각 단계마다 MFT Reference Address 들을 확인하여 해당 Entry로 이동하고, 원하는 파일에 도달한 경우 해당파일의 Attribute를 확인하여 $Data 항목을 참조하면 내용을 확인 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/index_entry_structure.png&quot; alt=&quot;&amp;lt;표 6&amp;gt; Index Node Header&quot; /&gt;&lt;/p&gt;

&lt;p&gt;다음 장에서 Resident 파일과 Non Resident 파일의 경우를 나누어 파일 탐색하는 과정을 통해 MFT Entry를 활용하여 파일의 데이터에 접근하는 과정을 확인 할 수 있다. 또한 이후 파일의 복제나, 삭제된 파일의 확인 및 복구하는 과정을 확인 할 수 있다.&lt;/p&gt;
</description>
        <pubDate>Mon, 12 Dec 2022 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2022/12/12/ntfs3/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2022/12/12/ntfs3/</guid>
        
        <category>ntfs</category>
        
        
      </item>
    
      <item>
        <title>NTFS 파일 시스템 partition data 1</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/07/ntfs1/&quot;&gt;첫번째 글: NTFS 파일 시스템&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;두번째 글: NTFS 파일 시스템 partition data 1&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/12/ntfs3/&quot;&gt;세번째 글: NTFS 파일 시스템 partition data 2&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/13/ntfs4/&quot;&gt;네번째 글: 드라이브 내 파일 탐색&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-파티션에-저장된-파일-정보&quot;&gt;1. 파티션에 저장된 파일 정보&lt;/h2&gt;

&lt;p&gt;각 파티션마다 별도의 시스템을 사용할 수 있다. 현재 사용중인 컴퓨터는 윈도우 10 Pro 인데, 내부 Partition 중 하나는 FAT 시스템을 사용중이다. 아래의 &amp;lt;그림 2-1&amp;gt;에는 OEM Name이 NTFS가 아니라 MSDOS라고 표시되어 있는 것을 통해 FAT 시스템으로 설정된 것을 확인 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_2_1.png&quot; alt=&quot;&amp;lt;그림 2-1&amp;gt; Partition 1 의 정보&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;11-logical-sector--physical-sector&quot;&gt;1.1 Logical Sector / Physical Sector&lt;/h3&gt;

&lt;p&gt;Partition 내부의 정보들은 모두 LBA로 위치를 표시할 수 있다. 그런데, 해당 Partition의 위치가 0이 아니기 때문에, 내부의 정보들은 Partition의 위치 + Partition 내부의 위치로 정보를 표기하게 된다. 이럴 경우 규칙성을 파악하기도 불편해 지고, 불필요한 표기가 많아지기 때문에, 해당 파티션 $Boot 의 위치를 0으로 하는 Logical Sector를 새로 사용할 수 있다. Partition 3의 경우 Start LBA가 1261568 이기 때문에,&lt;/p&gt;

&lt;p&gt;Logical Sector No + 1261568 = Physical Sector No&lt;/p&gt;

&lt;p&gt;가 된다. 이후 사용하는 LBA 번호는 Logical Sector 번호를 기본값으로 한다.&lt;/p&gt;

&lt;h3 id=&quot;12-파티션-기본-정보&quot;&gt;1.2 파티션 기본 정보&lt;/h3&gt;

&lt;p&gt;다음의 &amp;lt;그림 2-2&amp;gt;는 Partition 3의 기본 데이터이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_2_2.png&quot; alt=&quot;&amp;lt;그림 2-2&amp;gt; LBA 1261568 Data. Partition 3&quot; /&gt;&lt;/p&gt;

&lt;p&gt;NTFS의 경우 Boot파일은 아래의 표3에 있는 데이터를 통해 각 의미를 파악 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_table.png&quot; alt=&quot;&amp;lt;표 1&amp;gt; NTFS Boot file&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 &amp;lt;표 1&amp;gt;을 통해 해당 섹터를 확인하면 아래의 &amp;lt;그림 2-3&amp;gt;과 같은 결과를 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_2_3.png&quot; alt=&quot;&amp;lt;그림 2-3&amp;gt; &amp;lt;그림 2-2&amp;gt;의 LBA 1261568을 표 3의 정보들을 통해 분석한 결과&quot; /&gt;&lt;/p&gt;

&lt;p&gt;OEM Name을 통해 NTFS인 것을 확인 할 수 있고, Bytes per Sector, Sector Per Cluster, Start $MFT, Start $MFT Mirror, Cluster Per MFT Record 등을 확인할 수 있다. Bytes per Sector를 통해 1개 LBA sector는 512 Bytes이고, Sector Per Cluster를 통해 1개 Cluster는 4096 Bytes임을 알 수 있다. Start $MFT는 Partition 3의 $MFT 파일의 위치(Cluster, not LBA)를 알 수 있다. Cluster per MFT Record 값은 음수가 나올 수 있는데, 이는 Cluster에 비해 MFT Record가 작기 때문이다. 이런 경우 계산은 아래와 같이 할 수 있다.&lt;/p&gt;

&lt;p&gt;Value = Cluster per MFT Record = 0xF6(HEX) / -10(DEC)
MFT Record size = 2^(-1 * Value) = 1024 Bytes&lt;/p&gt;

&lt;p&gt;Cluster Per MFT Record 값이 1024 Bytes이므로, 1개 MFT Record는 2개의 LBA로 이루어져 있고, 1개 Cluster에 4개의 MFT Record가 들어있는 것을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;위에서 확인 한 기본 크기들을 통해, 이후에 각 파일이 가지고 있는 Address 값을 계산하여 $MFT를 기준으로 몇 번째 LBA에 존재하는지 등을 확인하는 것이기 때문에, 각 Partition이 가지고 있는 기본 설정값들을 확인 하는 것은 중요하다. 내부의 $MFT는 위의 Start $MFT 항목에 786432라는 값을 통해 접근할 수 있는데, 이는 Cluster 번호이다. MFT는 매우 큰 파일이기 때문에, 대량의 Cluster를 할당해야하기 때문이다. 위의 값을 이용해 Cluster 786432 / LBA 3221225472 / Offset C0000000(HEX)로 이동할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;13-mft&quot;&gt;1.3 $MFT&lt;/h3&gt;

&lt;p&gt;$MFT는 Master File Table의 약자로, 메타 데이터파일(Meta Data File)과 일반 파일/디렉토리의 정보를 저장하고 있는 MFT Entry로 구성되어 있다. 특이하게도, $MFT라는 것은 고유번호 0번의 파일로 존재하지만, 동시에 파일들에 대한 정보를 가지고 있는 Entry의 역할을 가지고 있다. 각 Entry는 시작할 때 File(b’\x46\x49\x4C\x45’)이라는 $MFT Entry Signature로 시작한다.&lt;/p&gt;

&lt;p&gt;1개의 파일마다 2개의 LBA를 할당하여 정보를 저장하고, 해당 파일의 종류에 따라 Run List 등을 확인하여 해당 파일의 실제 정보에 접근할 수 있다. 각 파일에 부여된 Address 값을 통해 $MFT의 위치를 기준으로 하여 접근하게 된다. 아래의 표4는 고유 번호에 따른 Meta Data File의 명칭과 그 기능이다. 고유번호는 $MFT를 0번으로 하여 배치된 순서를 알려주는 값으로, 고유번호 혹은 Address 값에 2를 곱하고, $MFT위치의 값을 더하면 해당 파일의 $MFT 내부의 위치를 얻을 수 있다. 우선은 $MFT 위치로 이동한다.&lt;/p&gt;

&lt;h4 id=&quot;131-mft-record의-분류&quot;&gt;1.3.1 $MFT Record의 분류&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/files/MFT_Record.png&quot; alt=&quot;&amp;lt;표 2&amp;gt; NTFS Boot file&quot; /&gt;&lt;/p&gt;

&lt;p&gt;기본적으로 $MFT Record는 위의 표에 있는 것처럼 기본 역할을 수행하는 파일들을 가지고 있고, 사용자가 생성하는 디렉토리나 파일들은 Address 24번 이후로 생성되어 각자 고유한 번호를 가지게 된다. Partition 내부의 파일을 확인하기 위해서는 고유번호 5번인 Root Directory를 확인해야 한다.&lt;/p&gt;

&lt;h4 id=&quot;132-attribute-type에-따른-분류&quot;&gt;1.3.2 Attribute Type에 따른 분류&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/files/attribute_type.png&quot; alt=&quot;&amp;lt;표 2&amp;gt; $MFT 속성 정보에 따른 기능 분류&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;표 2&amp;gt;의 속성번호는 이후에 나올 각각의 Attribute가 가진 데이터 중 첫 4 Bytes 값이다. 이를 확인하여 해당 Attribute가 어떤 속성을 가지는지 확인할 수 있다.&lt;/p&gt;

&lt;h4 id=&quot;133-resident--non-resident의-차이점&quot;&gt;1.3.3 Resident / Non Resident의 차이점&lt;/h4&gt;

&lt;p&gt;Resident와 Non Resident은 해당 파일의 용량에 따라 구분된다. Resident Type의 경우 데이터의 크기가 700 Byte 이하인 경우 Attribute Header 바로 뒤에 내용을 모두 담아둔다. Non Resident의 경우 Attribute의 내용이 MFT Entry에 담을 수 없을 정도로 커서 따로 속성 내용이 존재하는 클러스터 위치 값을 나열하는 형태이다.&lt;/p&gt;
</description>
        <pubDate>Thu, 08 Dec 2022 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2022/12/08/ntfs2/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2022/12/08/ntfs2/</guid>
        
        <category>ntfs</category>
        
        
      </item>
    
      <item>
        <title>NTFS 파일 시스템</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;첫번째 글: NTFS 파일 시스템&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/08/ntfs2/&quot;&gt;두번째 글: NTFS 파일 시스템 partition data 1&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/12/ntfs3/&quot;&gt;세번째 글: NTFS 파일 시스템 partition data 2&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2022/12/13/ntfs4/&quot;&gt;네번째 글: 드라이브 내 파일 탐색&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-분석-목적&quot;&gt;1. 분석 목적&lt;/h2&gt;

&lt;p&gt;NTFS 시스템의 특징을 이해하여 데이터 복제 및 복원을 가능하게 한다. 그리고 이를 확인 하기 위해 사용한 프로그램이나 함수들을 설명한다.&lt;/p&gt;

&lt;h2 id=&quot;2-ntfs-file-system&quot;&gt;2. NTFS File System&lt;/h2&gt;
&lt;p&gt;NTFS 파일 시스템은 Windows NT에서 최초로 지원된 파일 시스템으로, FAT를 대체하기 위해 새롭게 개발된 파일 시스템이다. NTFS는 New Technology File System의 준말인데, 93년 7월 윈도우 NT 3.1에서 처음 도입 되었고, 기존의 시스템에 비해 보다 효율적으로 데이터를 저장하고, 보관하며, 대용량 파일에 대응할 수 있도록 개발되었다.&lt;/p&gt;

&lt;h3 id=&quot;1-ntfs-시스템의-특징&quot;&gt;(1). NTFS 시스템의 특징&lt;/h3&gt;

&lt;p&gt;① 데이터 복구 기능 : 신뢰성을 높이기 위해 모든 작업을 기록하고, 문제 발생시 기록을 토대로 복원하는 기능을 탑재하였음.&lt;br /&gt;
② 암호화&lt;br /&gt;
③ 압축 : LZ77의 변형된 알고리즘을 통해 파일 시스템 수준에서 압축&lt;br /&gt;
④ ADS(Alternate Data Stream) 저장 기능&lt;br /&gt;
⑤ 대용량 지원 : 이론상 264 Bytes까지 가능하나, 실제로 244 Bytes(16TB)까지 지원.&lt;/p&gt;

&lt;h3 id=&quot;2-mbr-vs-ntfs&quot;&gt;(2). MBR vs NTFS&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_1.png&quot; alt=&quot;&amp;lt;그림 1-1&amp;gt; MBR vs GPT 구조의 차이(https://productkeysbuzz.co/difference-between-mbr-and-gpt/)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;그림 1-1은 MBR과 GPT의 구조 차이를 나타낸 것이다. MBR의 경우 데이터의 처음 부분에 Master Boot Record와 Partition Entry를 가지고 있고, 뒤에 데이터들을 가지고 있는 구조이다. GPT의 경우, 데이터손실 발생시 복원을 고려하여 BackUp data를 고려한 설계를 한 것이 
다른 점이다. Protective MBR 뒤에 최대 128개의 Entry 공간이 있고, 각 파티션이 따라온 다음, 데이터를 끝내기 전에 다시 엔트리 정보와 헤더가 있어서 한쪽에 손실이 발생하더라도 데이터를 보존할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;3-gpt-system의-파티션-데이터&quot;&gt;(3). GPT system의 파티션 데이터&lt;/h3&gt;

&lt;p&gt;아래의 그림 2를 참고하여 데이터 구간별로 부여된 기능에 대해 확인해 볼 수 있다. 1.2에서 언급한 것처럼, GPT는 Primary GPT와 Secondary GPT를 가지고 있는데, 이는 한쪽에서 손실이 발생하더라도 데이터를 보존하기 위함인데, 왼쪽에 음수로 표시된 부분은 맨 끝에서 거꾸로 구조가 시작되는 것을 의미한다. LBA는 논리 블록 주소 지정(Logical block addressing)이라는 것인데, 컴퓨터 기억 장치에 저장되는 데이터 블록의 위치를 지정하는데 쓰이는 용어이다. 여기서는 512 Bytes 단위로 사용된다. 데이터의 표기는 Little Endian 방식을 사용한다.&lt;/p&gt;

&lt;p&gt;Byte 표기법에는 Big Endian과 Little Endian이 있다. 10진수로 123456을 표기하고자 할때, 16진수로는 0x1 E2 40로 표기할 수 있는데, 이 표기가 Big Endian이다. (설명을 위해 두 자리씩 띄어서 숫자를 표기하였다.) Little Endian은 가장 낮은 자리부터 두 자리씩 끊어서 구분한 다음 이를 역순으로 표기하는 것이 Little Endian이다. 그래서 위의 수를 Little Endian으로 표기하는 경우 이는 0x40 E2 01가 된다. 그래서 2 Bytes이상의 데이터를 읽어올 때 숫자로 변환해야 하는 경우에는 표기법이 Little Endian이기 때문에 마찬가지로 Int.from_bytes(data, byteorder=’little’) 이라는 함수를 사용하여 올바르게 변환하도록 해야 한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_2.png&quot; alt=&quot;&amp;lt;그림 1-2&amp;gt; GUID Partition Table 구조(https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs)&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;3-1-lba-0&quot;&gt;(3)-1. LBA 0&lt;/h4&gt;
&lt;p&gt;Pretective MBR 이라고 한다. 일반 MBR에서 실수로 데이터를 변경하지 않도록 Offset 0x1C2 자리에 b’\xEE’라고 표기하여 사용중임을 표시하고, 나머지 대부분의 자리는 비워둔다. Offset 0x1FE~0x1FF 자리에 signature인 b’\x55\xAA’를 기록한다.&lt;/p&gt;

&lt;h4 id=&quot;3-2-lba-1&quot;&gt;(3)-2. LBA 1&lt;/h4&gt;
&lt;p&gt;실질적인 GPT Header 역할을 한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/gpt_header.png&quot; alt=&quot;&amp;lt;표 1&amp;gt; NTFS Boot Record Header&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_3.png&quot; alt=&quot;&amp;lt;그림 1-3&amp;gt; NTFS header Data&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 &amp;lt;표 1&amp;gt;을 바탕으로 &amp;lt;그림 1-3&amp;gt;의 데이터를 해석하면 다음과 같은 내용을 얻을 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_4.png&quot; alt=&quot;&amp;lt;그림 1-4&amp;gt; &amp;lt;그림 3의 데이터 해석 결과&amp;gt;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;우선 Signature를 통해 본 시스템이 UEFI에 바탕을 둔 시스템인 것을 확인하였다. 해당 data가 있는 위치가 LBA 1 인 것이 표시 되어있고, Partition Entry가 LBA 2에서 시작하는 것과, Entry의 최대 개수, 각 Entry의 크기가 각각 128개, 128 Bytes 임을 확인 할 수 있다. Entry의 크기와 위치, 최대 개수를 확인 하였으니, LBA 2로 이동하여 Entry에 들어있는 데이터를 확인할 수 있다.&lt;/p&gt;

&lt;h4 id=&quot;3-3-lba-2--33&quot;&gt;(3)-3. LBA 2 ~ 33&lt;/h4&gt;

&lt;p&gt;앞서 확인했던 LBA 1의 그림 4에서 얻은 정보를 계산해 보면, 각 Entry의 크기는 128 Bytes 이므로, 각 LBA 는 4개의 Entry를 가진다. 그러므로 128개의 Entry에 할당된 LBA는 32개 이다. 기존의 정보를 통해 LBA 2번부터 33번까지는 Partition Entry 0번부터 127번까지에 할당되어 있는 것을 확인 하였다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/partition_table.png&quot; alt=&quot;&amp;lt;표 2&amp;gt; Partition Entry Data&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 &amp;lt;표 2&amp;gt;를 통해 각 Entry의 Data에 대해 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_5.png&quot; alt=&quot;&amp;lt;그림 1-5&amp;gt; 4번째 파티션(Partition 3)의 Entry data&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_6.png&quot; alt=&quot;&amp;lt;그림 1-6&amp;gt; Partition 3의 Data 해석 정보&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 1-6&amp;gt;을 통해 First LBA를 확인 했는데, 이는 해당 파티션이 시작되는 위치이다. 각 파티션은 각자에 할당된 구간의 LBA를 사용하는데, Partition 3는 LBA 1261568 ~ 500117503을 할당 받아 사용한다. 현재 Partition 3를 C 드라이브로 사용하고 있고, 해당 드라이브 내부의 자료를 확인하기 위해 LBA 1261568로 이동해야 한다.&lt;/p&gt;

&lt;h3 id=&quot;4-참고-사항&quot;&gt;(4). 참고 사항&lt;/h3&gt;

&lt;p&gt;하드디스크 정보에 접근하기 위해 사용한 방법들&lt;/p&gt;

&lt;h4 id=&quot;4-1-winhex-프로그램&quot;&gt;(4)-1. WinHex 프로그램&lt;/h4&gt;

&lt;p&gt;WinHex프로그램은 독일의 X – Ways 사에서 만든 프로그램으로 컴퓨터 포렌식과 소프트웨어 데이터 복구의 기능을 가진 Hex Editor 및 Disk Editor이다. 22년 11월 15일 기준으로 WinHex 20.7 버전이 출시되어 있다. 현재는 가로 한줄에 32 Bytes씩 표시해주고 있다.&lt;/p&gt;

&lt;p&gt;Winhex.exe의 실행 시 관리자 권한으로 실행을 해야 하드디스크 정보에 접속할 수 있는 권한이 생긴다. 실행 후 상단 메뉴에서 Tools – Open Disk로 원하는 정보를 확인할 수 있으며, Physical Storage Devices 중에서 실행하게 되면, 상단의 파티션들을 더블클릭하여 해당 Logical Volume만 따로 확인하는 기능도 지원하고 있다.&lt;/p&gt;

&lt;h4 id=&quot;4-2-vs-code를-통한-hdd-접근-방법&quot;&gt;(4)-2. VS Code를 통한 HDD 접근 방법&lt;/h4&gt;

&lt;p&gt;VS Code를 통해서 접근하는 과정에도 관리자 권한이 필요하다. 프로그램 실행할 때 관리자 권한으로 실행해야 내부의 바이너리 데이터를 확인할 수 있다.&lt;/p&gt;

&lt;h4 id=&quot;4-3-hexdump&quot;&gt;(4)-3. Hexdump&lt;/h4&gt;

&lt;p&gt;HexDump는 Python 3에서 사용할 수 있는 라이브러리 중 하나이다. 처음 사용할때는 !pip install hexdump 라는 명령어를 사용하여 설치한 다음, 코드 안에서 import를 하여 사용한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_7.png&quot; alt=&quot;&amp;lt;그림 1-7&amp;gt; Hexdump 사용 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 예시에서 변수 data는 16진수 형태의 바이너리파일로, 위의 예시처럼 hexdump.hexdump() 로 함수를 불러서 함수 안에 바이너리 데이터를 입력하면 아래의 &amp;lt;그림 1-8&amp;gt;과 같이 출력된다&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/NTFS_1_8.png&quot; alt=&quot;&amp;lt;그림 1-8&amp;gt; Hexdump 출력 예시&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;4-4-사용한-기본-함수들&quot;&gt;(4)-4. 사용한 기본 함수들&lt;/h4&gt;

&lt;p&gt;① Open( )
하드디스크의 정보를 불러오는데 사용하였다. 바이너리 데이터로 불러오기 위해, reading + binary를 합쳐 ‘rb’라고 표기하여 정보를 불러온다.&lt;/p&gt;

&lt;p&gt;② Seek( )
read()에서 자료를 읽기 위해, 자료의 시작지점을 입력하는 함수이다.&lt;/p&gt;

&lt;p&gt;③ Read( )
입력받은 숫자만큼의 데이터를 읽는 함수로, 최소 단위로 1개 LBA(512 Bytes)가 적절하여 512를 입력하여 사용하였다.&lt;/p&gt;

&lt;p&gt;④ Chr( )
출력하고자 하는 결과가 이름인 경우, 입력받은 값들을 ASCII 등으로 바꾸기 위해 사용하였다.&lt;/p&gt;

&lt;p&gt;⑤ Join( )
Chr( )로 문자로 바꾼 것들을 한 문자열로 합치기 위해 사용하였다.&lt;/p&gt;

&lt;p&gt;⑥ Int.from_bytes( data, byteorder=’little’)
data 자리에 바이트 값을 입력하면 이를 Little Endian으로 계산하여 정수로 출력해주는 함수이다. 다만, 이를 위해 슬라이싱 인덱스를 사용할 때 주의해야 할점은, 구간이 아니라 특정 자리를 지정할 경우 Byte type이 아니라 Int type으로 출력된다는 점이다. Data[5:6]은 1자리의 Byte type이 출력되지만, Data[5]의 경우 Int Type이 출력되기 때문에, Type Error를 유발하게 된다.&lt;/p&gt;
</description>
        <pubDate>Wed, 07 Dec 2022 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2022/12/07/ntfs1/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2022/12/07/ntfs1/</guid>
        
        <category>ntfs</category>
        
        
      </item>
    
      <item>
        <title>그래프DB(Neo4j)를 활용한 프로세스 행위 로그 시각화 방법 - 소개</title>
        <description>&lt;p&gt;안녕하세요.
이번 블로그 내용은 프로세스 행위 로그 분석을 위해 수집된 로그 데이터를 대상으로 그 특성을 파악하기 위한 시각화 방법 중 그래프DB를 활용한 방법을 소개해 드리고자 합니다.&lt;/p&gt;

&lt;h2 id=&quot;1-개요&quot;&gt;1. 개요&lt;/h2&gt;

&lt;p&gt;프로세스 행위 로그는 실시간 I/O 모니터링을 통해 추출한 원시 로그 데이터로 서로 복잡하게 연결되어 있어 하나의 프로세스가 다른 프로세스와 어떤 연관성이 있는지 파악하기 어렵기 때문에 그래프DB를 활용하여 프로세스 간 관계를 시각화하여 데이터 특성을 파악해 보고자 합니다.&lt;/p&gt;

&lt;p&gt;아래의 그림은 프로세스 익스플로러&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;의 실행 모습으로 프로세스 행위 로그에서 다루고 있는 정보들(프로세스 명과 프로세스 커맨드라인, 프로세스 생성 시간 등)에 대한 이해를 돕기 위해 첨부하였습니다.  프로세스 익스플로러(마이크로소프트 윈도우용 프리웨어 작업 관리자, 시스템 모니터)는 사용자의 시스템에서 실행 중인 프로세스들에 관한 정보를 수집하고 윈도우 작업 관리자 기능을 제공하는 유틸리티입니다. 프로세스 익스플로러를 통해 &lt;strong&gt;현재 실행되고 있는 프로세스들의 정보&lt;/strong&gt;를 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/neo4j_1.jpg&quot; alt=&quot;프로세스 익스플로러 실행 모습&quot; /&gt;&lt;/p&gt;

&lt;p&gt;참고로 본 글에서는 프로세스 행위 로그를 바탕으로 프로세스 간 생성 관계를 파악하여 시각 화하는데 초점이 맞춰져 있습니다. 그래프DB(Neo4j)에 대해 더 궁금하신 사항이 있으시면 아래의 링크를 참고하시면 될 것 같습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;그래프 데이터베이스에 대한 소개: &lt;a href=&quot;https://neo4j.com/download/&quot;&gt;Neo4j 공식홈페이지&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Neo4j 기본 컨셉 및 Cypher 개념: &lt;a href=&quot;https://wikidocs.net/book/3724&quot;&gt;Sudan님이 작성하신 WikiDocs 페이지&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-그래프-데이터베이스neo4j-란&quot;&gt;2. 그래프 데이터베이스(Neo4j) 란?&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/neo4j_2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;그래프DB(Neo4j)에 대해 간단하게 설명 드리면, 수학적 그래프 이론에 토대를 둔 일종의 NoSQL 데이터 베이스입니다. 
기존의 관계형 데이터베이스(RDBMS)나 기타 DB를 사용하는 것 보다 그래프 자체를 있는 그대로 저장하고 사용할 수 있다는 장점이 있어 데이터 특성(패턴)을 파악하는데 도움이 됩니다.&lt;/p&gt;

&lt;p&gt;일반적으로 어떤 프로그램을 PC에 설치하는 과정을 생각해 보면 윈도우 탐색기를 통해 인터넷 브라우저를 실행하고 자신이 원하는 프로그램의 설치파일을 검색한 후 다운받아 설치합니다.  이때 어떤 프로세스들이 생성되는지 프로세스 간 관계 그래프 데이터 모델을 통해 살펴보고자 합니다.&lt;/p&gt;

&lt;p&gt;프로세스 관계 그래프 데이터 모델의 구성은 앞서 설명한 것과 같이 노드-관계-속성이며 각각의 해당하는 부분을 그래프로 표현하기 위해 그래프 데이터베이스에서 사용하는 쿼리 문법인 Cypher를 사용하며, Cypher의 기본 구조를 간단하게 살펴보면 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;※ Cypher 기본 구조 설명
노드 : ( ) , (변수:라벨) 
관계 : [ ]
화살표: 방향 -[:DIRTECTER]-&amp;gt;
패턴(Pattern) : ( )-[ ]-( )
                ( )-[ ]-&amp;gt;( )
                ( )&amp;lt;-[ ]-( )
속성: { } 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;아래 그림의 예시는 ‘브라우저 상 프로그램 설치 시나리오’를 프로세스 간 관계 그래프 데이터 모델로 표현한 결과의 일부입니다. 노드는 해당 프로세스들이며, 속성은 프로세스 ID, 프로세스 명, 프로세스 생성시간 등으로 구성하였습니다. CREATED_TO라는 레이블을 통해 하나의 프로세스(부모 프로세스)가 다른 프로세스(자식 프로세스)를 생성하는 관계를 갖도록 하였습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/neo4j_3.jpg&quot; alt=&quot;프로세스 간 관계 그래프 데이터 모델 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위 그림에 해당하는 Cypher 쿼리문을 간단하게 살펴보면 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Cypher 쿼리 언어를 사용한 프로세스 간 관계 그래프 표현

1. MATCH (n:ProcInfo)
2. MERGE (a:LinkedTO {name:n.PID, service:n.PName, createdTime:n.PCTime})
   MERGE (b:LinkedTO {name:n.ObjID, service:n.OName, createdTime:n.OCTime})
3. MERGE (b)&amp;lt;-[r:CREATED_TO]-(a)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;MATCH를 통해 해당하는 정보를 가져오는데 n이라는 변수에 프로세스 생성관련 행위 로그 전체의 패턴을 저장합니다. MERGE는 노드가 있으면 찾는 기능과 없으면 생성하는 기능을 가진다고 생각하시면 되며, 이를 통해 a프로세스가 b 프로세스를 생성하는 관계를 가진다는 의미를 한눈에 파악할 수 있도록 하였습니다.&lt;/p&gt;

&lt;h2 id=&quot;3-마무리&quot;&gt;3. 마무리&lt;/h2&gt;

&lt;p&gt;간단하게 윈도우 탐색기(Explorer.exe)를 통해 브라우저를 실행(chrome.exe)하고 자신이 원하는 프로그램을 다운받아 설치(veraport.exe)하는 과정 중 일부분을 그래프 데이터베이스 Neo4j와 Cypher 쿼리문을 통해 프로세스 간 관계 그래프 데이터 모델을 만들어 보았습니다. 이를 통해 프로세스 간 관계를 파악하는데 그래프형태로 시각화하여 보다 직관적으로 확인할 수 있었고 전체적인 데이터의 특성(패턴)을 파악해 볼 수 있었습니다.&lt;/p&gt;

&lt;h2 id=&quot;참조&quot;&gt;참조&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;프로세스 익스플로러: &lt;a href=&quot;https://ko.wikipedia.org/wiki/프로세스_익스플로러&quot;&gt;https://ko.wikipedia.org/wiki/프로세스_익스플로러&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 02 Jul 2021 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2021/07/02/process_log_with_neo4j/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2021/07/02/process_log_with_neo4j/</guid>
        
        <category>process</category>
        
        <category>neo4j</category>
        
        
      </item>
    
      <item>
        <title>악성 PDF 파일 진단</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2021/05/16/fileformat_pdf/&quot;&gt;첫번째 글: PDF 파일 구조 분석&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2021/05/18/pdf_exploit/&quot;&gt;두번째 글: PDF 취약점과 진단 방안&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;세번째 글: 악성 PDF 파일 진단&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-들어가며&quot;&gt;1. 들어가며&lt;/h2&gt;

&lt;p&gt;취약점과 진단 방안을 통해 PDF파일에서 공격에 활용될 수 있는 취약점과 악성 여부 진단 방안을 알아보았다. 이를 바탕으로 실제 악성파일의 동작방식과 사용된 취약점을 확인하고 진단과정을 적용해본다.&lt;/p&gt;

&lt;h2 id=&quot;2-악성-pdf-파일-진단&quot;&gt;2. 악성 PDF 파일 진단&lt;/h2&gt;

&lt;h3 id=&quot;1-cve-2017-8759&quot;&gt;(1) CVE-2017-8759&lt;/h3&gt;

&lt;p&gt;CVE-2017-8759은 Microsoft .Net Framework 코드 실행 취약점으로 2017년 9월 12일에 발표되었다. 해당 취약점은은 WSDL의 부적절한 xml처리 때문에 발생한다. 공격자는 WSDL 메시지 구조 안의 address이하 부분을 Parsing하는 과정에서 발생하는 결함을 통해 사용자의 시스템에 임의의 코드를 주입할 수 있다. 주로 Microsoft Office .RTF, .Doc, .ppt 문서형태로 배포되며, 문서가 열리는 동시에 매크로 및 링크에 대한 확인 없이 공격자가 원하는 코드가 수행될 수 있는 공격이다. PDF에서는 EmbeddedFiles 작업을 통한 드롭퍼 형태의 exploit이 확인되었다.&lt;/p&gt;

&lt;h4 id=&quot;1-1-동작-방식&quot;&gt;(1)-1. 동작 방식&lt;/h4&gt;

&lt;p&gt;MD5 Hash 값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f4a689ca564df7dce73a682047691449&lt;/code&gt;인 PDF파일은 취약점 CVE-2017-8759로 exploit하는 악성 PDF이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_1.png&quot; alt=&quot;&amp;lt;그림 2-1&amp;gt; Object 구성과 tree구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;해당 PDF파일은 총 9개의 Object를 가지고 있으며, Root Object (Catalog Dictionary MD5 Hash 값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f4a689ca564df7dce73a682047691449&lt;/code&gt;인 PDF파일은 취약점 CVE-2017-8759로 exploit하는 악성 PDF이다. data type)는 Page, Action, Filespec, Outlines Object를 참조한다.&lt;/p&gt;

&lt;p&gt;이를 통해 Page에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;This PDF document embeds file Achi1.doc&lt;/code&gt;이라는 문자열이 출력되도록 하고, Action에서 PDF파일이 열렸을 때 embed되어있던 Achi1.doc악성파일이 사용자 컴퓨터로 저장되고 실행되도록 하는 JavaScript코드를 실행시킨다. Filespec에서는 Achi1.doc파일에 대해 정의하며 파일의 내용은 8 0 obj에 저장되어 있음을 알린다. 따라서 PDF파일의 역할은 embed되어있는 악성파일 Achi1.doc이 사용자 컴퓨터에 저장, 실행되도록 하는 것이다.&lt;/p&gt;

&lt;p&gt;해당 PDF에 embed되어있던 Achi1.doc은 파일 시그니쳐 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7B 5C 72 74 66({rft)&lt;/code&gt;를 갖는 RTF파일 이였으며, OLE control objects를 포함하고 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_2.png&quot; alt=&quot;&amp;lt;그림 2-2&amp;gt; Achi1.doc(.rtf)파일 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위 &amp;lt;그림 2-2&amp;gt;는 Achi1.doc파일 구조의 일부이다.&lt;/p&gt;

&lt;p&gt;해당 부분을 통해 object type이 objocx임을 확인할 수 있다. objocx는 OLE control objects를 embed하기 위해 악성 RTF파일에서 가장 일반적인 사용되는 유형이다.&lt;/p&gt;

&lt;p&gt;objdata부분에는 객체에 대한 데이터가 포함되어 있는데, 이 부분은 OLESaveToStream함수에 의해 구조가 생성되기 때문에 OLE포맷과 동일한 구조를 가지게 된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_3.png&quot; alt=&quot;&amp;lt;그림 2-3&amp;gt; Achi1.doc(.rtf)파일 object data부분&quot; /&gt;&lt;/p&gt;

&lt;p&gt;object data 안의 문자열 중에는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsdl=https://a.doko.moe/qvomoe/qvomoa&lt;/code&gt;을 확인 할 수 있다. wsdl은 웹 서비스와 웹 접근 방법에 대해 기술하는 xml 기반으로 정의된 파일이며, soap이라는 xml기반의 프로토콜을 통해 통신 된다.&lt;/p&gt;

&lt;p&gt;위 그림의 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://a.doko.moe/qvome/qvomoa&lt;/code&gt;에 접근하게 된다.&lt;/p&gt;

&lt;p&gt;외부 통신이 수행되면 프로세스의 흐름상 접근된 qvomoa는 WSDL로서 기술된 XML파일일 것이며 아래 &amp;lt;그림 2-4&amp;gt;과 같은 구문을 사용하여 공격이 수행될 것이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_4.png&quot; alt=&quot;&amp;lt;그림 2-4&amp;gt; Exploit WSDL 파일 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Microsoft의 .Net Framework에서는 XML파일의 soap:address 문자열 이후의 url정보를 parsing하여 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Runtime.Remoting.metadata.wsdlparser.cs&lt;/code&gt;에 정의된 PrintClientProxy 함수 안에서 사용하게 되는데, parsing 과정에서 CRLF문자 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt;을 필터링 하지 못해 함수 내의 주석처리를 우회하게 되며 이 후 등장하는 C#코드가 정상 수행되도록 만든다. 공격자가 이 부분에 악성 코드를 주입하면 해당 코드는 .Net Framework의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csc.exe&lt;/code&gt;에 의해 컴파일 되고 생성된 파일은 은 Office에 의해 DLL로 호출되어 실행된다.&lt;/p&gt;

&lt;h4 id=&quot;1-2-진단-과정&quot;&gt;(1)-2. 진단 과정&lt;/h4&gt;

&lt;p&gt;PDF파일에서는 악성 행위 수행을 위해 위험한 작업(Action) 중 하나인 EmbeddedFiles가 수행되었으며, 파일의 실행 방법으로 JavaScript문이 이용되었다.&lt;/p&gt;

&lt;p&gt;작업을 호출한 경로는, EmbeddedFiles의 경우 Root object의 Dictionary Key인 Names의 Value값으로써 호출되었고, JavaScript의 경우 Root object의 Dictionary Key인 Action(OpenAction)의 Value값으로 호출되었다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_5.png&quot; alt=&quot;&amp;lt;그림 2-5&amp;gt; EmbeddedFiles, JavaScript 호출 Object&quot; /&gt;&lt;/p&gt;

&lt;p&gt;취약한 작업의 호출이 확인되었기 때문에 작업에 포함된 내용을 확인하여 악성 여부를 진단해야 한다. JavaScript의 내용을 확인하기 위해서 Object 9번으로 이동하면 &amp;lt;그림 2-5&amp;gt;와 같은 내용을 볼 수 있는데, 주의해서 봐야 할 부분은 함수 명 exportDataObject와 그 파라미터 값인 nLaunch이다. exportDataObject함수는 지정된 데이터를 외부파일로 추출하는 역할을 한다. 이때 주어지는 nLaunch에 값에 따라 추출 후 수행할 작업이 달라진다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_6.png&quot; alt=&quot;&amp;lt;표 2-1&amp;gt; exportDataObject함수의 nLaunch 파라미터&quot; /&gt;&lt;/p&gt;

&lt;p&gt;공격자들은 nLaunch의 파라미터 값으로 2번을 주로 사용하는데, 이유는 파일을 사용자가 알지 못하는 경로에 은밀하게 저장할 수 있기 때문이다.&lt;/p&gt;

&lt;p&gt;그 다음으로는 추출되는 파일의 악성여부를 확인해야 한다.&lt;/p&gt;

&lt;p&gt;EmbeddedFiles의 내용을 확인하기 위해 Object 1번으로 이동하면 &amp;lt;그림 2-5&amp;gt;와 같은 내용을 볼 수 있다. 이를 통해 PDF에 포함되어 있는 문서가 Achi1.doc이라는 것과 Achi1.doc에 대한 내용은 Objcet 7번을 참조한다는 것을 알 수 있다. &amp;lt;표 2-1&amp;gt;의 tree구조를 통해 알 수 있듯이, Object 7번은 Object 8번을 참조함으로써 파일의 Stream정보를 나타낸다. 따라서 Object 8번의 Stream을 Dump하면 악성 파일이 나올 것이라 예상할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_7.png&quot; alt=&quot;&amp;lt;그림 2-6&amp;gt; Object 8번의 Stream&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Object 8번에 포함된 Stream은 FlateDecode 필터로 압축 되어있으며 8346바이트 길이를 갖는다. HxD프로그램을 통해 Stream 부분만 Dump하여 파일로 만든 다음, FlateDecode 필터 압축에 대한 uncompress를 수행하면 embed 되어있던 파일을 얻을 수 있다. 찾은 파일을 virustotal과 같은 바이러스 검색 엔진에 업로드 함으로써 악성여부를 1차 판단한다.&lt;/p&gt;

&lt;p&gt;우선 uncompress되지 않은 파일을 Virustotal에서 검사해본 결과 &amp;lt;그림 2-6&amp;gt;의 왼쪽 그림과 같이 낮은 탐지율을 보인다. 그러나 파일을 uncompress하여 다시 검사하면 &amp;lt;그림 2-6&amp;gt;의 오른쪽 결과와 같이 탐지된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_8.png&quot; alt=&quot;&amp;lt;그림 2-7&amp;gt; export될 파일의 Virustotal 검사 결과 (압축 / 비압축)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이를 통해 악성 파일인 Achi1.doc은 압축되어 PDF에 embed되는 과정에서 많은 바이러스 검사 엔진들로부터 탐지를 회피할 수 있었으나, 단순히 원문형태로 변환하는 과정을 통해서도 진단이 가능함을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;PDF가 embed하고 있는 파일을 추출하였다면, 파일 시그니쳐를 확인하여 포맷을 확인해야 하고 문자열 soap:wsdl=(url)의 유무를 확인 해야한다.&lt;/p&gt;

&lt;p&gt;공격자는 XML언어로 기술된 WSDL메시지 구조를 soap프로토콜로 통신할 것이기 때문이다.&lt;/p&gt;

&lt;p&gt;접근하려는 서버와 통신할 메시지를 확인하면 sandbox환경에서 서버와 통신하여 파일에 접근한 후 문서 내의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soap:address location =”;&lt;/code&gt; 문자열의 등장 여부를 확인하여 악성여부를 판단한다.&lt;/p&gt;

&lt;h3 id=&quot;2-db0c822d49a1dbff0e760d6e7e111370&quot;&gt;(2) DB0C822D49A1DBFF0E760D6E7E111370&lt;/h3&gt;

&lt;h4 id=&quot;2-1-동작-방식&quot;&gt;(2)-1. 동작 방식&lt;/h4&gt;

&lt;p&gt;MD5 Hash 값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;db0c822d49a1dbff0e760d6e7e111370&lt;/code&gt;인 악성 PDF이다.&lt;/p&gt;

&lt;p&gt;파일을 HxD나 vim에디터로 열어보면 구조가 손상되어 있는 것을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_9.png&quot; alt=&quot;&amp;lt;그림 2-8&amp;gt; db0c822d49a1dbff0e760d6e7e111370 손상된 파일 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위 &amp;lt;그림 2-8&amp;gt;은 Offset 00000000 ~ 0000026까지 나타낸 것이다.&lt;/p&gt;

&lt;p&gt;xref table을 통해 확인되는 Object의 offset주소는 실제와 달랐으며, 증분 업데이트 이전의 내용 또한 xref table에서 확인할 수 있는 Object들이 실제 Body부분에 포함되지 않아 손상된 구조임을 확인할 수 있었다.&lt;/p&gt;

&lt;p&gt;Root Object(15 0 obj)의 참조 Object 중, 주의해서 봐야 할 Object로는 /AA (12 0 object), /AcroForm (16 0 object), /Names (17 0 object), /Pages (4 0 object), /Metadata(10 0 object)가 있으며 이중 취약점은 /Names에서 찾을 수 있었다.&lt;/p&gt;

&lt;p&gt;/Names는 객체가 아닌 이름을 통한 참조 시 이름과 객체간의 대응(mapping)에 사용되는 Object이다. Dictionary를 이루는 Key들은 특정 범주의 개체에 대한 이름을 정의하는 name tree의 루트를 지정한다. 해당 파일에서 Names Object는 IDS(5 0 object)와 JavaScript(18 0 object), URLS(6 0 object)라는 이름의 Key를 가지고 있으며 파일이 열리면 해당 root name tree부터(Key) 모든 작업이 실행된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_10.png&quot; alt=&quot;&amp;lt;그림 2-9&amp;gt; Names&quot; /&gt;&lt;/p&gt;

&lt;p&gt;IDS는 디지털 식별자와 Web Capture Content Set을 Mapping하는 name tree이고, URLS는 Web Capture Content Set와 URL을 Mapping하는 name tree이며 JavaScript는 이름(문자열)과 문서 수준의 JavaScript를 Mapping하기 위한 name tree이다. Web Capture Content Set이란 동일 Source Data로부터 생성된 Object의 세트를 말하며 여기에는 세트 자체 혹은 Object 들의 공통된 정보를 포함한다. Web Capture Contest에는 2가지 Subtype이 있는데 Page유형과 Image유형이다. Page유형의 경우 SPS (Spider Page Set)로 표현되고 Image유형의 경우 SIS (Spider Image Set)로 표현된다. 분석중인 PDF는 SPS유형의 Web Capture Content Set로 URLS(6 0 object)를 통해 Web Capture Content Set(8 0 object)와 url정보를(7 0 object)를 Mapping하고, IDS를 통해 Web Capture Content Set와 디지털 식별자를(27 0 object) Mapping하여 Page Set이룬다. 해당 Page Set 참조하여 Page(20 0)가 작성된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_11.png&quot; alt=&quot;&amp;lt;그림 2-10&amp;gt; Web Capture File 구조 (SPS)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;JavaScript name tree는 18 0 object, 19 0 object를 참조하여 정의된다.&lt;/p&gt;

&lt;p&gt;stream은 19 0 object에서 참조함으로 해당 object의 Dictionary Key인 JS의 value값을 Dump하여 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;아래 &amp;lt;그림 2-11&amp;gt;는 Dump된 JavaScript 코드를 재정렬 한 것이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_12.png&quot; alt=&quot;&amp;lt;그림 2-11&amp;gt; JavaScript&quot; /&gt;&lt;/p&gt;

&lt;p&gt;악성코드는 변수 a에 encoding되어 있다. decoding 알고리즘은 다음과 같다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1)	변수 a 중간에 들어가는 변수 zxc에 대해 문자 a로 대체한다.
2)	변수 a의 문자열을 2자리씩 끊고, 31진수 숫자로 읽는다.
3)	31진수를 10진수로 변환한다. &amp;lt;br&amp;gt;
4)	변환한 값을 Ascii코드 번호로 읽는다.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;decoding된 알고리즘은 &amp;lt;그림 2-12&amp;gt;와 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_scan_13.png&quot; alt=&quot;&amp;lt;그림 2-12&amp;gt; eval()함수에 들어가는 문자열&quot; /&gt;&lt;/p&gt;

&lt;p&gt;해당 코드는 CVE-2009-0927, CVE-2007-5659, CVE-2008-2992 취약점 공격코드를 포함하고 있으며 heap spray공격을 수행한 후 Reader의 버전을 체크하고 버전별로 exploit코드를 다르게 실행한다. CVE-2009-0927취약점 공격코드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Collab.getIcon()&lt;/code&gt; 함수를 이용하며, 해당 함수는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N.&lt;/code&gt;다음으로 등장하는 문자열(확장자)를 strcat을 통해 복사하는데 이때 strcat함수가 문자열의 끝을 계산하지 않고 넘어온 값을 다 전달하기 때문에 overflow를 발생시키고 결과적으로 eip값이 변경되어 공격이 수행된다.&lt;/p&gt;

&lt;p&gt;CVE-2007-5659 취약점 코드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Collab.collectEmailInfo()&lt;/code&gt; 함수를 이용한 공격으로, 공격자가 해당 함수의 두 번째 인자로써 대량의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0c0c0c0c&lt;/code&gt; 값을 갖는 msg를 넣는다. 함수는 이 인자의 boundary를 확인하지 않고 받아들인 뒤 해당 인자가 담긴 메모리 주소 범위에서 일정크기의 값을 가져와 비교하는 알고리즘을 수행한다. 참 인 결과 또는 끝나는 조건을 만족하지 못한 비교 알고리즘은 계속 반복되며 0x0c0c값을 스택에 채우게 되고 overflow를 발생시킨다.&lt;/p&gt;

&lt;p&gt;CVE-2008-2992 취약점 코드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util.prinf()&lt;/code&gt; 함수에서 부동 소수점 지정자를 포함하는 포맷 스트링을 파싱할 때 boundary error가 발생할 수 있다는 점을 이용하며, 이를 통해 버퍼 overflow를 발생시킨다.&lt;/p&gt;

&lt;h4 id=&quot;2-2-동작-방식&quot;&gt;(2)-2. 동작 방식&lt;/h4&gt;

&lt;p&gt;악성파일 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;db0c822d49a1dbff0e760d6e7e111370&lt;/code&gt;의 경우 Root Object의 Entry인 Names Object로부터 문서 수준의 JavaScript를 참조하여 실행 시킴으로써 악성행위를 수행하였다. Names Object의 Entry로부터 JavaScript 이름을 갖는 root name tree를 찾았고(18 0 object), 그 아래의 19 0 object name tree를 찾아 코드를 확인하였다.&lt;/p&gt;

&lt;p&gt;코드는 19 0 object에서 Dictionary Key인 JS의 Value값으로 들어있기 때문에 해당 영역을 dump하였으며. 그 내용은 &amp;lt;그림 2-11&amp;gt;와 같다.&lt;/p&gt;

&lt;p&gt;실질적인 악성코드 부분은 변수 a에 encoding되어 decoding하기 이전 까지는 내용확인이 어렵기 때문에 진단은 &amp;lt;그림 2-11&amp;gt;에 해당하는 코드에서 수행되어야 한다.&lt;/p&gt;

&lt;p&gt;하지만 취약점이 동작하는 부분을 직접 확인할 수 없는 상태에서 진단이 수행되어야 하며, 확실한 악성 탐지는 수행되기 어렵다.&lt;/p&gt;

&lt;p&gt;때문에 악성 의심 수준으로 진단될 수 있으며, JavaScript코드 진단 결과가 악성을 의심할 수 있는 조건을 연속적으로 부합할 경우 사용자에게 악성 의심 경고를 알리도록 한다. 악성의심으로 판단할 조건은 다음과 같다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1)	변수가 비정상적인 크기의 문자열을 가질 경우
2)	반복문안에 fromCharCode등 문자, 문자열 생성이나 Decoding 관련 함수가 등장할 경우
3)	eval함수가 사용되는 경우
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;다음 조건이 2개이상 일치 될 경우 높은 확률로 악성코드로 의심할 수 있다.&lt;/p&gt;

&lt;p&gt;위와 같은 조건을 둔 이유는 정상 PDF내 JavaScript의 용도상 encoding 난독화를 수행할 필요성이 적고 decoding 된 문자열이 eval함수를 통해 JavaScript로써 실행되는 경우가 거의 없기 때문이다.&lt;/p&gt;

&lt;h2 id=&quot;3-마무리&quot;&gt;3. 마무리&lt;/h2&gt;

&lt;p&gt;지금까지 2종류의 악성 PDF 파일의 동작 방식과 진단하는 방법에 대해 살펴보았다. PDF 파일은 포맷 구조가 복잡하고 다양한 encoding으로 구성되어 있어 탐지 로직을 개발하는 것은 매우 까다롭다. 하지만, PDF 파일 포맷 파서와 다양한 encoding을 decoding하는 로직만 갖출 수만 있다면 악성 PDF 파일에 대한 탐지는 가능하다. 이는 향후 누리랩에서 개발하는 PDFScan을 통해 그 유용성 및 사용법에 대해서도 블로그에 새롭게 정리하도록 하겠다.&lt;/p&gt;

</description>
        <pubDate>Mon, 31 May 2021 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2021/05/31/pdf_exploit_scan/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2021/05/31/pdf_exploit_scan/</guid>
        
        <category>pdf</category>
        
        <category>exploit</category>
        
        
      </item>
    
      <item>
        <title>PDF 취약점과 진단 방안</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2021/05/16/fileformat_pdf/&quot;&gt;첫번째 글: PDF 파일 구조 분석&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;두번째 글: PDF 취약점과 진단 방안&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2021/05/31/pdf_exploit_scan/&quot;&gt;세번째 글: 악성 PDF 파일 진단&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-취약점과-진단-방안&quot;&gt;1. 취약점과 진단 방안&lt;/h2&gt;

&lt;h3 id=&quot;1-위험한-작업action&quot;&gt;(1) 위험한 작업(Action)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_1.png&quot; alt=&quot;&amp;lt;그림 1-1&amp;gt; 공격에 활용될 수 있는 작업들(Actions)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위 그림의 작업(Action)들은 파일 핸들에 대한 직접 또는 간접적인 액세스를 허용하므로 URL호출 또는 파일 쓰기와 같은 위험한 기능에 악용될 가능성이 있다. 예를 들어 Page Object의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/AA&lt;/code&gt;(Addition Actions) Entry는 GotoE Entry를 호출할 수 있어 다른 PDF의 악성 content에 접근하여 악성 행위를 수행시킬 수 있다. JavaScript 코드의 경우 JavaScript 엔진상의 취약점을 이용해 공격을 수행할 수 있으므로 삽입되는 JavaScript에 대한 악성 여부 파악이 필요하다. 많은 공격들이 위 그림과 같이 정상적인 작업들을 활용하여 수행된다. 때문에 &amp;lt;그림 1-1&amp;gt;에서 확인할 수 있는 작업들과 이러한 작업들을 호출할 수 있는 Object들을 목록화하여 문서 내 등장 여부를 확인해야 하고, 악성, 정상 여부를 가려내기 위한 기준을 잡아야 한다.&lt;/p&gt;

&lt;p&gt;&amp;lt;표 1-1&amp;gt;은 &amp;lt;그림 1-1&amp;gt;을 바탕으로 파일에 직접 또는 간접적으로 액세스 할 수 있는 Action과 그러한 Action을 호출할 수 있는 Object들을 목록화 한 것이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_2.png&quot; alt=&quot;&amp;lt;표 1-1&amp;gt; 취약한 작업(Action) 목록&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-denial-of-service&quot;&gt;(2) Denial of Service&lt;/h3&gt;

&lt;p&gt;Denial of Service(DoS)은 PDF 응용 프로그램을 처리하는 과정에서 사용 가능한 자원을 고갈시키거나 충돌을 발생시켜 서비스를 이용하지 못하도록 만든다. PDF 파일을 이용한 DoS공격은 두 가지 유형으로 나눌 수 있다.&lt;/p&gt;

&lt;p&gt;하나는 Infinite-loop를 이용한 공격이고 다른 하나는 압축을 이용한 공격으로 압축 폭탄이라고 불린다. Infinite-loop는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/GoTo&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Next&lt;/code&gt;와 같은 다음 행동을 지정하는 작업을 통해 loop를 생성하거나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/JS&lt;/code&gt; 타입의 Object에서 JavaScript 코드의 반복문을 활용하여 공격이 수행된다.&lt;/p&gt;

&lt;p&gt;다음 예시는 각각 JavaScript, Outline-Next작업을 이용한 dos공격이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_3.png&quot; alt=&quot;&amp;lt;그림 1-2&amp;gt; Denial of Service (Outline-Next) 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Outline은 PDF에 개요 목록을 표시해주는 기능으로 예시 코드에서는 Root Object(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 0 object&lt;/code&gt;)에서 Outline의 정보를 담고 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8 0 object&lt;/code&gt;를 참조하여 표현한다. Outline은 계층 구조를 가지며 Dictionary Key인 First와 Last를 통해 자신의 직계 하위 계층의 첫 번째와 마지막 번째를 가리킨다. 해당 코드에서는 최상위 Outline인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 0 object&lt;/code&gt;가 하위 계층으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 object&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7 0 object&lt;/code&gt;를 가지며 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 object&lt;/code&gt;가 첫 번째이고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7 0 object&lt;/code&gt;가 마지막 번째가 된다. 같은 수준의 계층에서는 링크되는 순서에 따라 화면에 출력되는데 이때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7 0 object&lt;/code&gt;가 다음 항목으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 object&lt;/code&gt;를 참조하면서 Infinite-loop가 발생하여 DoS공격이 이뤄진다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_4.png&quot; alt=&quot;&amp;lt;그림 1-3&amp;gt; Denial of Service (JavaScript) 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;JavaScript를 이용한 DoS는 PDF에 JavaScript가 허용된다는 점을 악용한 공격이다. 위 예시에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 0 object&lt;/code&gt;의 Dictionary Key인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;의 value값 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/JavaScript&lt;/code&gt;로 OpenAction에서 JavaScript를 참조함을 알 수 있고, Dictionary Key인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/JS&lt;/code&gt;의 value값 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 R&lt;/code&gt;을 통해 JavaScript 코드가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 object&lt;/code&gt;를 참조함을 알 수 있다. 참조된 코드는 변수 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;에 문자열 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;를 넣고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x=x+x&lt;/code&gt; 작업을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for(;;)&lt;/code&gt;문을 통하여 무한 반복하는 내용으로 변수 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;의 크기를 계속 늘려가며 메모리 부족을 유도하는 DoS 공격이다.&lt;/p&gt;

&lt;p&gt;해당 취약점을 이용하는 악성 PDF 여부를 진단할 수 있는 방법은 다음과 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_5.png&quot; alt=&quot;&amp;lt;표 1-2&amp;gt; DoS Exploit 진단 방안 (Infinite-loop)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;압축 폭탄 공격은 PDF파일 내의 stream을 flatedecode와 같은 다양한 encoding알고리즘으로 압축할 수 있다는 점을 이용한다. 이러한 압축 알고리즘을 중첩으로 사용하면 매우 큰 용량의 stream을 적은 용량으로 압축 할 수 있다. 사용자가 stream의 내용을 확인하기 위해 압축을 해제하면 자원 부족으로 인한 서비스 중지가 발생한다. 이러한 공격은 주로 바이러스 검사 프로그램을 겨냥하며, 검사 프로그램이 PDF의 악성여부를 진단하는 과정에서 DoS공격이 수행되어 프로그램의 서비스가 중지된다.&lt;/p&gt;

&lt;p&gt;다음 예시는 flatedecode encoding 중첩을 통한 압축 폭탄 공격이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_6.png&quot; alt=&quot;&amp;lt;그림 1-4&amp;gt; Denial of Service (압축 폭탄) 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;예시에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Root Object -&amp;gt; Pages(2 0 obj) -&amp;gt; Page(3 0 obj) -&amp;gt; Contents(4 0 obj)&lt;/code&gt;순으로 참조하며 마지막 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4 0 obj&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream&lt;/code&gt;을 담고 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj&lt;/code&gt;로 Dictionary Key인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Filter&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Length&lt;/code&gt;값을 가지며 이를 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream&lt;/code&gt;의 길이가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20872911&lt;/code&gt;이고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASCIIHexDecode&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FlateDecode&lt;/code&gt;를 이용하여 encoding되었음을 알 수 있다. 길이 1당 1byte를 의미하며 예시의 문서는 encoding된 하나의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream&lt;/code&gt;만으로 20,383KB의 크기를 가졌다. 이외에도 압축폭탄 공격은 여러 번의 encoding이 수행된다는 것과 극적인 압축을 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream&lt;/code&gt;내에 반복적인 문자열이 많이 등장한다는 특징을 가진다.&lt;/p&gt;

&lt;p&gt;해당 취약점을 이용하는 악성 PDF 여부를 진단할 수 있는 방법은 다음과 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_7.png&quot; alt=&quot;&amp;lt;표 1-3&amp;gt; DoS Exploit 진단 방안 (압축 폭탄)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;분석가가 이러한 PDF를 분석하기 위해 필요한 기능은 다음과 같다.&lt;/p&gt;

&lt;p&gt;(1)	Object간의 참조 관계를 확인하는 기능&lt;br /&gt;
(2)	사용된 JavaScript 코드만을 추출하여 확인하는 기능&lt;br /&gt;
(3)	문서 내의 stream 부분만 추출하여 세부 정보(길이, encoding방식)와 함께 확인할 수 있는 기능&lt;/p&gt;

&lt;h3 id=&quot;3-information-disclosure&quot;&gt;(3) Information Disclosure&lt;/h3&gt;

&lt;p&gt;Information Disclosure는 공격자의 서버에 자동으로 연결되어 PDF 문서 양식데이터, 로컬 파일 또는 NTLM 자격 증명과 같은 민감한 데이터가 공격자에게 유출되는 공격이다. 다음 예시는 로컬 파일을 외부 서버에 전송하는 유형이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_8.png&quot; alt=&quot;&amp;lt;그림 1-5&amp;gt; Information Disclosure 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;예시 코드에서 Root Object는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 0 object&lt;/code&gt;로 문서가 열렸을 때의 동작인 OpenAction object (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 0 obj&lt;/code&gt;)을 참조하고, OpenAction object는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Next&lt;/code&gt;라는 이름의 Dictionary Key를 갖는다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;의 value값인 ImportData는 데이터를 가져오는 작업이 수행됨을 알 린다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;의 value는 Dictionary data type으로 다시 Key인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;를 가지며, 해당 키의 value 값으로 가져올 데이터의 경로 값을 저장한다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Next&lt;/code&gt;는 이어서 참조할 Action Object (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 obj&lt;/code&gt;)을 가리키며, Action Object(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 obj&lt;/code&gt;)는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;라는 이름의 Dictionary Key를 가진다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;의 value값인 SubmitForm은 데이터를 제출하는 작업이 수행됨을 알리고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;의 value값은 Dictionary data type으로 다시 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FS&lt;/code&gt;라는 이름의 Key값을 갖는다. 이 중, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;의 value값이 데이터를 전달받는 서버의 주소를 갖는다.&lt;/p&gt;

&lt;p&gt;해당 취약점은 PDF파일의 정상 기능을 이용한 것으로 악용 여부를 진단할 수 있는 방법은 다음과 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_9.png&quot; alt=&quot;&amp;lt;표 1-4&amp;gt; Information Disclosure유형의 Exploit 진단방안&quot; /&gt;&lt;/p&gt;

&lt;p&gt;분석가가 이러한 PDF파일을 분석하기 위해 필요한 기능은 다음과 같다&lt;/p&gt;

&lt;p&gt;(1)	PDF에서 접근하는 파일에 대한 세부적인 정보를 확인할 수 있는 기능 &lt;br /&gt;
(ex. 파일명, 경로, 파일 형식, 수정한 날짜 등)&lt;/p&gt;

&lt;h3 id=&quot;4-data-manipulation&quot;&gt;(4) Data Manipulation&lt;/h3&gt;

&lt;p&gt;Data Manipulation은 PDF파일의 기능을 이용하여 양식 데이터를 자동으로 수정하거나, 희생자의 로컬 파일에 쓰기 작업을 하거나, PDF Reader 프로그램에 따라 다른 콘텐츠가 표시되도록 만든다. 다음은 로컬 파일에 쓰기 작업을 수행하는 예시이다&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_10.png&quot; alt=&quot;&amp;lt;그림 1-6&amp;gt; Data Manipulation 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;예시 코드에서 Root Object인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 0 object&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/AcroForm&lt;/code&gt;으로 대화형 양식 필드를 정의하였고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/AcroForm&lt;/code&gt;의 필드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Annots [6 0 R, 7 0 R, &amp;lt;&amp;lt;…Dictionary…&amp;gt;&amp;gt;]&lt;/code&gt;로 3개의 Annotation 정보를 가진다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 0 object&lt;/code&gt;의 Dictionary Key인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;V&lt;/code&gt;는 Object의 필드 유형에 따라 다른 유형의 value값을 가지며 해당 Object는 텍스트 유형이기 때문에 value값으로 문자열 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text to write&lt;/code&gt;의 Widget을 띄운다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7 0 object&lt;/code&gt;는 생성하는 Widget에서 사용자가 버튼 클릭을 할 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 0 object&lt;/code&gt;를 참조하여 Dictionary Key인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;의 value값으로 지정된 경로에 쓰기작업을 수행하며, 쓰여지는 데이터는 PDF문서양식에 맞춰 작성된다.&lt;/p&gt;

&lt;p&gt;Dictionary Data type으로 배열 내에서 바로 정의된 마지막 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Annotation&lt;/code&gt;은 Link type의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Annotation&lt;/code&gt;으로 문서의 다른 곳 또는 수행할 작업에 대한 하이퍼텍스트 링크를 나타낸다. 위 코드에서는 Link가 활성화되었을 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 0 obj&lt;/code&gt;를 참조하여 Data Manipulation이 수행되도록 하고 있다.&lt;/p&gt;

&lt;p&gt;해당 취약점은 PDF의 정상적인 작업이 악의적 의도에 의해 사용될 경우 발생하며, 이 경우 주로 파일에 대한 덮어쓰기 작업이 사용자와의 상호작용 없이 곧바로 일어남을 이용한다.&lt;/p&gt;

&lt;p&gt;악성 여부를 진단할 수 있는 방법은 다음과 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_11.png&quot; alt=&quot;&amp;lt;표 1-5&amp;gt; Data Manipulation유형의 Exploit 진단방안&quot; /&gt;&lt;/p&gt;

&lt;p&gt;분석가가 이러한 PDF를 분석하기 위해 추가적으로 필요한 기능은 다음과 같다.&lt;/p&gt;

&lt;p&gt;(1)	PDF에서 쓰기작업을 수행하려는 파일에 대한 세부 정보를 확인할 수 있는 기능&lt;/p&gt;

&lt;h3 id=&quot;5-code-execution&quot;&gt;(5)	Code Execution&lt;/h3&gt;

&lt;p&gt;Code Execution은 희생자의 컴퓨터에 공격자가 제어하고자 하는 코드를 실행시키는 것을 목표로 한다. 공격자는 PDF파일의 Launch 작업과 같이, 로컬 경로, 네트워크 공유, URL 또는 PDF 문서 자체에 포함된 파일을 실행시킬 수 있는 기능들을 활용한다. 이 기능을 이용해 사전에 숨겨둔 악성파일을 동작 시킴으로써 악성행위가 이뤄질 수 있다. 다음은 PDF파일을 실행시킴으로써 명령 프롬프트 프로그램이 동작되는 예시이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_12.png&quot; alt=&quot;&amp;lt;그림 1-7&amp;gt; Code Execution 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;예시의 코드는 PDF 파일이 Open 될 때와 Page가 Open 될 때 각각 한번씩 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5 0 object&lt;/code&gt;를 참조하여 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd.exe&lt;/code&gt;를 실행시키는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Launch&lt;/code&gt; 작업을 수행한다. 이러한 작업은 정상적인 PDF의 기능이지만, 의도에 따라 악의적으로 사용될 수 있다. 해당 취약점의 악용 여부를 진단할 수 있는 방법은 다음과 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_13.png&quot; alt=&quot;&amp;lt;표 1-6&amp;gt; Code Execution 유형의 Exploit 진단 방안&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이러한 경우 프로그램의 악성여부 탐지가 필요하며, 바이러스 탐지 엔진을 따로 개발하여 탐지가 진행되어야 할 것 같다.&lt;/p&gt;

&lt;p&gt;분석가가 이러한 PDF를 분석하기 위해 필요한 기능은 다음과 같다.&lt;/p&gt;

&lt;p&gt;(1)	Launch 작업에서 접근하려는 프로그램 정보를 확인할 수 있는 기능&lt;br /&gt;
(2)	프로그램을 바이러스 탐지 엔진과 연동하여 진단할 수 있는 기능&lt;/p&gt;

&lt;h3 id=&quot;6-shadow-attack&quot;&gt;(6)	Shadow Attack&lt;/h3&gt;

&lt;p&gt;Shadow Attack은 서명된 PDF를 대상으로 서명 유효성을 유지한 채 콘텐츠를 숨기거나 바꾸는 공격이다. Hide형태의 Shadow Attack을 수행하는데 사용할 수 있는 취약점은 2가지이다.&lt;/p&gt;

&lt;p&gt;첫 번째는 서명된 PDF가 콘텐츠 제거에 대한 경고 알람을 발생시키지 않는 경우가 있다는 것이다. 다수의 Reader 프로그램들이 서명된 PDF 파일에 새 콘텐츠 추가, 삭제될 경우 경고 알람을 발생시킨다. 그러나 낮은 버전의 일부 Reader 프로그램들은 콘텐츠 제거에 대해서 경고 알람을 발생시키지 않았다.&lt;/p&gt;

&lt;p&gt;두 번째는 서명된 PDF가 증분 업데이트 될 때 MetaData와 Annotation와 같이 Reader 프로그램에서 무해한 것으로 판단하는 몇 가지 기능이 존재한다는 것이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_14.png&quot; alt=&quot;&amp;lt;그림 1-8&amp;gt; Shadow Attack – Hide 유형 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;그림 1-8&amp;gt;은 공격자가 악의적인 문구를 은닉한 PDF를 생성하고 서명을 받은 경우이다. 서명이 완료된 PDF에 대해서 공격자는 PDF의 메타 데이터를 수정하여 증분 업데이트 유도한 후, 악의적인 문구를 덮고 있던 image파일에 대한 Object인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8 0 obj&lt;/code&gt;의 offset 주소를 메타데이터 정보를 가리키던 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6 1 obj&lt;/code&gt;의 offset주소와 동일하게 수정해줌으로써 서명의 유효성을 유지한 채 콘텐츠를 숨길 수 있다. 해당 취약점의 악용 여부를 진단할 수 있는 방법은 다음과 같다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/pdf_exploit_15.png&quot; alt=&quot;&amp;lt;표 1-7&amp;gt; Shadow Attack (hide) 유형 Exploit 진단 방안&quot; /&gt;&lt;/p&gt;

&lt;p&gt;분석가가 이러한 PDF를 분석하기 위해 필요한 기능은 다음과 같다.&lt;/p&gt;

&lt;p&gt;(1)	증분 업데이트 이력과 변경, 추가된 Object에 대한 내용을 확인하는 기능 &lt;br /&gt;
(2)	xref table 정보를 통합하여 출력해주는 기능&lt;/p&gt;

&lt;h2 id=&quot;2-마무리&quot;&gt;2. 마무리&lt;/h2&gt;

&lt;p&gt;지금까지 우리는 PDF 취약점에 대한 다양한 형태에 대해서 살펴보았다. 다음에는 PDF 취약점을 이용한 악성 PDF 파일을 진단하는 방법에 대해서 살펴보기로 한다.&lt;/p&gt;

</description>
        <pubDate>Tue, 18 May 2021 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2021/05/18/pdf_exploit/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2021/05/18/pdf_exploit/</guid>
        
        <category>pdf</category>
        
        <category>exploit</category>
        
        
      </item>
    
      <item>
        <title>PDF 파일 구조 분석</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;첫번째 글: PDF 파일 구조 분석&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2021/05/18/pdf_exploit/&quot;&gt;두번째 글: PDF 취약점과 진단 방안&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2021/05/31/pdf_exploit_scan/&quot;&gt;세번째 글: 악성 PDF 파일 진단&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-분석-목적&quot;&gt;1. 분석 목적&lt;/h2&gt;

&lt;p&gt;PDF 파일의 구조를 파악하여 취약점을 확인하고 파일의 악성 여부 진단이 가능하도록 한다.&lt;/p&gt;

&lt;h2 id=&quot;2-pdf의-구조&quot;&gt;2. PDF의 구조&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_1.png&quot; alt=&quot;&amp;lt;그림 1-1&amp;gt; PDF 파일의 전체 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;PDF 파일은 &amp;lt;그림 1-1&amp;gt; 과 같이 크게 Header, Body, Cross Reference Table, Trailer 부분으로 이루어 진다.&lt;/p&gt;

&lt;h3 id=&quot;1-pdf-header&quot;&gt;(1) PDF Header&lt;/h3&gt;

&lt;p&gt;8 Byte의 크기를 가지며, PDF 파일의 Signature 값과(%PDF) 버전정보를 담는다.&lt;/p&gt;

&lt;h3 id=&quot;2-pdf-body&quot;&gt;(2) PDF Body&lt;/h3&gt;

&lt;p&gt;PDF 의 Body 영역은 PDF 문서가 가지는 내용에 대한 Object 들이 기록되어 있다.
해당 Object는 다양한 압축, 암호화 형태를 가질 수 있으며, 일반적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj&lt;/code&gt; ~ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;endobj&lt;/code&gt; 문자열 사이에 데이터가 존재한다.&lt;/p&gt;

&lt;h3 id=&quot;3-cross-reference-table&quot;&gt;(3) Cross Reference Table&lt;/h3&gt;

&lt;p&gt;PDF 의 Cross Reference Table(이하 xref table) 는 Body 에 존재하는 Object 들에 대한 위치정보, 오브젝트가 유효한지 등의 정보를 가진다. 해당 테이블은 일반적으로 문자열로 존재하는 Table 형태를 가지지만, 최신 문서의 경우 Table 이 아닌 Binary Stream 형태를 가질 수도 있으며, 두 가지가 결합된 경우도 있을 수 있다. 또한 1개의 PDF 에서 여러 개의 xref table 이 존재 할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;4-trailer&quot;&gt;(4) Trailer&lt;/h3&gt;

&lt;p&gt;PDF 의 Trailer 은 PDF 분석 시 Header 의 유효성 체크 후 가장먼저 분석 되어야 할 위치이다. Trailer 은 xref table 의 위치, 특수 Object (암호화 Object, Root Object, ID 값 등)의 위치 정보를 가진다. 이 Trailer 는 1개의 PDF 에서 여러 번 존재 할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;5-pdf-파일이-수정된-경우의-변화&quot;&gt;(5) PDF 파일이 수정된 경우의 변화&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_2.png&quot; alt=&quot;&amp;lt;그림 1-2&amp;gt; PDF 파일이 수정된 경우 구조&quot; /&gt;&lt;/p&gt;

&lt;p&gt;PDF 파일이 수정되는 경우 위 &amp;lt;그림 1-2&amp;gt;와 같이 기존 구조에 덧붙어 기록이 된다. 따라서 PDF 를 분석하기 위해서는 수정된 모든 Trailer 와 xref table, Body 를 분석 하여야 한다.&lt;/p&gt;

&lt;h2 id=&quot;3-object-data-type&quot;&gt;3. Object Data type&lt;/h2&gt;

&lt;p&gt;PDF문서는 여러 작은 Object들로 구성된 모임이다. Object는 다음과 같은 8가지 기본적인 유형을 갖는다.&lt;/p&gt;

&lt;h3 id=&quot;1-boolean&quot;&gt;(1) Boolean&lt;/h3&gt;

&lt;p&gt;오브젝트 내에서 참(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;)과 거짓(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;)를 나타낼 때 사용되며 배열의 요소나 Dictionary 의 Entry 값으로서 사용된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_3.png&quot; alt=&quot;&amp;lt;그림 1-3&amp;gt; Boolean Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-numeric&quot;&gt;(2) Numeric&lt;/h3&gt;

&lt;p&gt;숫자를 표현할 때 사용되며 크게 Integer object와 Real object로 구분된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_4.png&quot; alt=&quot;&amp;lt;그림 1-4&amp;gt; Numeric Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-string&quot;&gt;(3) String&lt;/h3&gt;

&lt;p&gt;문자열을 나타낼 때 사용되며 Literal String과 Hexadecimal String가 있다.
Literal String은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;로 문자열의 시작을, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;로 문자열의 끝을 알린다.
또한, Literal String 내에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt; 또는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;를 허용하지 않는다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt; 쌍으로 이뤄져 있을 때에는 특별한 처리 없이 문자열로 인식되며, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;또는 특수 문자들을 문자 상수로 표현하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;가 사용되기 때문이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_5.png&quot; alt=&quot;&amp;lt;그림 1-5&amp;gt; String Data type (Literal String) 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hexadecimal String은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; 안의 0-9, A-F로 이루어진 2바이트의 데이터가 하나의 Hex data로 인식되는 문자열이다. 2바이트 짝이 맞지 않을 경우 마지막에 0이 생략된 것으로 간주한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_6.png&quot; alt=&quot;&amp;lt;그림 1-6&amp;gt; String Data type (Hexadecimal String) 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;4-name&quot;&gt;(4) Name&lt;/h3&gt;

&lt;p&gt;Name은 하나의 symbol로써 같은 문자열의 Name을 갖는 다른 Object가 있을 수 없다. Name은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;이후의 문자열로, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt;이후 등장하는 2바이트의 문자는 하나의 Hex값으로 취급한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_7.png&quot; alt=&quot;&amp;lt;그림 1-7 &amp;gt; Name Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;5-array&quot;&gt;(5) Array&lt;/h3&gt;

&lt;p&gt;Array는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt;로 시작하여 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt;로 끝나는 배열을 의미한다.
배열 내 각 요소들은 Array 포함한 PDF의 모든 Data type을 가질 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_8.png&quot; alt=&quot;&amp;lt;그림 1-8&amp;gt; Array Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;6-dictionary&quot;&gt;(6) Dictionary&lt;/h3&gt;

&lt;p&gt;Dictionary는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt; 내에서 Key-Value의 쌍으로 구성된다. 
Key는 반드시 Data type이 Name이여야 하고, Value는 Dictionary를 포함한 모든 Data type을 가질 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_9.png&quot; alt=&quot;&amp;lt;그림 1-9&amp;gt; Dictionary Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;7-stream&quot;&gt;(7) Stream&lt;/h3&gt;

&lt;p&gt;Stream은 길이에 제한이 없는 연속적인 바이트의 집단이다.
상대적으로 크기가 큰 이미지나 파일 내용은 Stream을 통해 표현한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_10.png&quot; alt=&quot;&amp;lt;그림 1-10&amp;gt; Stream Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Stream은 해당 Object내에 선행되는 Dictionary에서 몇 가지 속성을 지시한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_11.png&quot; alt=&quot;&amp;lt;그림 1-11&amp;gt; Stream에 대한 Dictionary의 Entries&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;8-indirect&quot;&gt;(8) Indirect&lt;/h3&gt;

&lt;p&gt;Indirect는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n1 n2 R&lt;/code&gt;과 같이 표현되며 참조하는 오브젝트를 의미한다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_12.png&quot; alt=&quot;&amp;lt;그림 1-12&amp;gt; Indirect Data type 예시&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;9-계층-구조&quot;&gt;(9) 계층 구조&lt;/h3&gt;

&lt;p&gt;Body 섹션 안의 Object들은 트리 형태로 계층적 구조를 이루고 있다.
계층의 최상위인 Root Object는 항상 catalog dictionary Data type을 가지며, Indirect를 통해 다른 모든 개체에 도달 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_pdf_13.png&quot; alt=&quot;&amp;lt;그림 1-13&amp;gt; Object의 기본적인 계층 구조&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;4-마무리&quot;&gt;4. 마무리&lt;/h2&gt;

&lt;p&gt;PDF Exploit을 분석하는 가장 기본은 역시 PDF 파일의 구조를 아는 것이다. 이후부터는 PDF Exploit이란 무엇이며 PDF Exploit 진단 방법 및 악성코드 진단 예시를 살펴볼 예정이다.&lt;/p&gt;
</description>
        <pubDate>Sun, 16 May 2021 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2021/05/16/fileformat_pdf/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2021/05/16/fileformat_pdf/</guid>
        
        <category>fileformat</category>
        
        <category>pdf</category>
        
        
      </item>
    
      <item>
        <title>RanSim을 이용한 랜섬웨어 행위 시나리오 확인하기</title>
        <description>&lt;h2 id=&quot;개요&quot;&gt;개요&lt;/h2&gt;

&lt;p&gt;RanSim이라는 프로그램을 소개하고 랜섬웨어가 어떠한 방식으로 사용자의 파일을 암호화하는지 살펴본다.&lt;/p&gt;

&lt;h2 id=&quot;ransim이란&quot;&gt;RanSim이란&lt;/h2&gt;

&lt;p&gt;KnowBe4&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;사는 과거 유명한 해커였던 Kevin Mitnick이 보안 컨설턴트로 참여하고 있으며 랜섬웨어나 다른 보안 문제를 효과적으로 관리할 수 있는 도구와 교육을 제공하고 있다. RanSim&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;은 이 KnowBe4 사에서 개발한 랜섬웨어 행위 시뮬레이터 프로그램이다.&lt;/p&gt;

&lt;p&gt;RanSim은 기존 시스템에 존재하는 파일에는 영향을 주지 않으며 100% 안전한 시뮬레이션을 제공한다. 본 문서에서 사용한 RanSim 버전은 2.1.0.3 버전이다. RanSim은 버전을 업그레이드하면서 최신 랜섬웨어 경향을 반영하고 있으며 시나리오의 개수도 점점 늘어나고 있다. 2.1.0.3 버전에서는 2개의 정상 시나리오와 19개의 감염 시나리오를 제공한다. 이들에 대한 간략한 정리를 아래의 표에서 확인할 수 있다.&lt;/p&gt;

&lt;p /&gt;

&lt;table style=&quot;border: 2px solid #dcdcdc;&quot;&gt;
    &lt;tr style=&quot;background: #fafafa&quot;&gt;
        &lt;td&gt;이름&lt;/td&gt;
        &lt;td&gt;&lt;div style=&quot;width: 120px;&quot;&gt;기대 결과&lt;/div&gt;&lt;/td&gt;
        &lt;td&gt;설명&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#a9d08e&quot;&gt;Archiver&lt;/td&gt;
        &lt;td&gt;정상 실행&lt;/td&gt;
        &lt;td&gt;gzip 알고리즘을 사용하여 단순히 파일을 압축 보관한다. 이 시나리오는 차단되어서는 안된다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#a9d08e&quot;&gt;Remover&lt;/td&gt;
        &lt;td&gt;정상 실행&lt;/td&gt;
        &lt;td&gt;단순히 파일을 삭제한다. 어떠한 파일도 생성하지 않는다. 이 시나리오는 차단되어서는 안된다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;WeakCryptor&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;약한 암호화 방식으로 파일을 암호화한다. 원본 파일은 삭제한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;VirlockVariant&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;Virlock 랜섬웨어가 공통적으로 사용하는 파일 행위를 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;ThorVariant&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;최근 버전의 Thor 랜섬웨어의 행위를 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;StrongCryptor&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;강력한 암호화 방식으로 파일을 암호화한다. 원본 파일은 안전하게 삭제한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;StrongCryptorFast&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;강력한 암호화 방식으로 파일을 암호화한다. 원본 파일은 삭제한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;StrongCryptorNet&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;강력한 암호화 방식으로 파일을 암호화한다. 원본 파일은 삭제한다. 더불어 HTTP 연결방식으로 서버에 암호화 키 전송을 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;Streamer&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;강력한 암호화 방식으로 파일을 암호화해서 하나의 파일에 그 데이터를 저장한다. 원본 파일은 삭제한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;SlowCryptor&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;보안 제품에 의한 진단을 피하기 위해서 파일을 천천히 암호화하는 랜섬웨어 변종의 행위를 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;RIPlacer&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;&quot;제어된 폴더 액세스&quot; 방식으로 보호하고 있는 폴더 내 파일을 암호화하려고 시도한다. Windows Defender의 &quot;제어된 폴더 액세스&quot;에 대한 별도 설정을 미리 수행해야 한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;RigSimulator&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;Monero 암호화폐를 채굴하기 위해서 머신 CPU를 사용하는 &quot;Mining Rig&quot;를 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;Replacer&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;원본 파일의 내용을 암호화 되지 않은 다른 내용으로 교체한다. 실제 랜섬웨어는 사용자로 하여금 파일들을 복구할 수 있다고 속이는 메시지를 보여준다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;Injector&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;일반적인 방법으로 정상 프로세스 안으로 암호화 코드를 삽입함으로써 파일을 암호화한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;ReflectiveInjector&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;보다 발전된 방법으로 정상 프로세스 안으로 암호화 코드를 삽입함으로써 파일을 암호화한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;HollowInjector&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;프로세스 Hollowing 방법으로 정상 프로세스 안으로 암호화 코드를 삽입함으로써 파일을 암호화한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;Mover&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;강력한 암호화 방식으로 파일을 암호화 후 다른 폴더로 복사한다. 원본 파일은 안전하게 삭제한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;LockyVariant&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;최근 버전의 Locky 랜섬웨어의 행위를 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;InsideCryptor&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;파일의 헤더는 그대로 두고 파일의 내용 영역(대략 512 바이트 이후)을 강력한 암호화 방식으로 암호화한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;CritroniVariant&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;최근 버전의 Critroni 랜섬웨어의 행위를 시뮬레이트한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td bgcolor=&quot;#f4b084&quot;&gt;Collaborator&lt;/td&gt;
        &lt;td&gt;차단 및 복원&lt;/td&gt;
        &lt;td&gt;최근 버전의 Critroni 랜섬웨어와 유사한 방식으로 파일을 암호화한다. 그러나 파일의 열거, 이동, 삭제에 대한 연산은 여러 개의 다른 프로세스가 수행한다.&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;아래의 그림은 RanSim이 각각의 시나리오를 테스트할 때 사용하는 원본 파일들이다. RanSim은 각 시나리오에 해당하는 디렉터리에 이 원본 파일을 복사하면서 시작한다. RanSim 프로그램은 동작 말미에 각각의 시나리오 디렉터리에 복사한 파일과 원본 파일의 차이를 비교한다. 그 비교 결과에 따라 차단 및 복원이 정상적인지 확인 할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_1.png&quot; alt=&quot;RanSim 테스트 원본 파일&quot; /&gt;&lt;/p&gt;

&lt;p&gt;아래의 그림은 WeakCryptor 시나리오의 결과를 보여준다. 원본 파일은 존재하지 않고 “cr” 이라는 확장자를 가지는 암호화된 파일만 존재한다. RanSim 테스트시 사용하는 암호화된 파일의 확장자는 그 시나리오를 대표하는 식별자 역할을 하지 않는다. 그렇기 때문에 WeakCryptor 방식으로 동작하는 랜섬웨어는 “cr” 이라는 확장자를 사용하는구나 식의 오해는 하지 않길 바란다. 실제 랜섬웨어는 너무나도 다양한 방식으로 동작하고 다양한 형태의 확장자를 사용한다. RanSim은 단지 랜섬웨어의 대표적인 행위 패턴을 시뮬레이션 해주는 프로그램이고 그 정도로도 충분히 훌륭하다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_2.png&quot; alt=&quot;WeakCryptor 시나리오 암호화 결과&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;archiver-시나리오&quot;&gt;Archiver 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;gzip 알고리즘을 사용하여 단순히 파일을 압축 보관한다. 이 시나리오는 랜섬웨어의 행위가 아니기 때문에 안티 랜섬웨어 프로그램은 이러한 행위를 차단하면 안된다. 테스트 디렉터리에 생성된 파일들을 확인해보면 아래의 그림과 같이 모두 gzip 파일에 대한 시그너처(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1F 8B&lt;/code&gt;)를 가지고 있음을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_4.png&quot; alt=&quot;gzip 파일 시그너처&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;remover-시나리오&quot;&gt;Remover 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;단순히 파일을 삭제한다. 어떠한 파일도 생성하지 않는다. 이 시나리오는 일반적으로 발생하는 파일 연산이기 때문에 안티 랜섬웨어 프로그램은 이 연산을 진단해서는 안된다.&lt;/p&gt;

&lt;p&gt;앞서 설명한 두 개의 시나리오는 정상적인 경우를 나타낸 것이다. 이제부터 설명하는 시나리오는 안티 랜섬웨어 프로그램에서 차단해야 하는 랜섬웨어 행위를 보여준다. 다만 우리가 사용하는 정상 프로그램 중에서도 자체 업데이트를 수행하거나 프로그램의 특수한 목적 때문에 이러한 행위를 수행할 수도 있다. 이런 경우에는 해당 프로그램을 예외처리 해주어야 한다.&lt;/p&gt;

&lt;h2 id=&quot;weakcryptor-시나리오&quot;&gt;WeakCryptor 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;원본 파일을 읽은 후 약한 암호화 방식으로 암호화한다. 그런 다음 신규 파일을 생성하여 암호화된 데이터를 쓴다. 마지막으로 원본 파일은 삭제한다.&lt;/p&gt;

&lt;h2 id=&quot;virlockvariant-시나리오&quot;&gt;VirlockVariant 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Virlock 랜섬웨어가 공통적으로 사용하는 파일 행위를 시뮬레이트한다. WeakCryptor 와 동일한 것처럼 보이지만 최종적으로 암호화된 파일이 exe 확장자를 갖는다는 점에서 주의해야 한다. 실제 VirLock 랜섬웨어는 exe 확장자를 가지는 실행가능한 암호화 파일을 만들고 확장자 숨기기 설정을 적용한다. 감염상황을 인지하지 못한 사용자는 문서 파일을 연다고 생각하지만 실제로는 또 다시 랜섬웨어 감염 연산이 시작된다. 이것은 파일 서버를 사용하는 회사나 클라우드를 공유하는 사용자들에게서 쉽게 전파될 수 있는 상황이다.&lt;/p&gt;

&lt;h2 id=&quot;thorvariant-시나리오&quot;&gt;ThorVariant 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Thor 랜섬웨어는 원본 파일을GUID 형태의 파일 이름과 thor 확장자를 가지는 파일로 Rename 한 후 암호화를 수행한다.&lt;/p&gt;

&lt;h2 id=&quot;strongcryptor-시나리오&quot;&gt;StrongCryptor 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;우선 원본 파일을 강력한 암호화 방식으로 암호화한다. 그런 다음 신규 파일을 생성하여 암호화된 원본 파일의 내용을 신규 파일에 쓴다. 마지막으로 (암호화된) 원본 파일은 삭제한다.&lt;/p&gt;

&lt;h2 id=&quot;strongcryptorfast-시나리오&quot;&gt;StrongCryptorFast 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;원본 파일을 읽은 후 강력한 암호화 방식으로 암호화한다. 그런 다음 신규 파일을 생성하고 암호화된 데이터를 쓴다. 원본 파일은 삭제한다. StrongCryptor 시나리오에 비해서 Write 연산이 줄어서 Fast 라는 이름을 붙은 것으로 생각된다.&lt;/p&gt;

&lt;h2 id=&quot;strongcryptornet-시나리오&quot;&gt;StrongCryptorNet 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;StrongCryptorFast 시나리오와 거의 동일하다. 다만 그림에서는 표현되지 않았지만 HTTP 연결방식으로 서버에 암호화 키 전송을 시뮬레이트한다.&lt;/p&gt;

&lt;h2 id=&quot;streamer-시나리오&quot;&gt;Streamer 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Streamer 시나리오는 그 이름에서도 알 수 있듯이 여러 개의 파일을 읽어서 그 데이터를 암호화하여 실행 초기에 생성해 둔 하나의 신규 파일에 암호화된 데이터를 순차적으로 쓴다. 암호화된 데이터를 신규 파일에 쓴 후에 원본 파일은 삭제한다.&lt;/p&gt;

&lt;h2 id=&quot;slowcryptor-시나리오&quot;&gt;SlowCryptor 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_13.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;안티 랜섬웨어 프로그램에 의한 진단을 피하기 위해서 파일을 천천히 암호화하는 랜섬웨어 변종의 행위를 시뮬레이트한다. 위의 그림에서도 알 수 있듯이 원본 파일을 읽고 삭제한 후 대략 2초의 시간이 지나고 나서야 신규 파일을 생성하고 전에 읽어 둔 데이터를 암호화하여 쓴다.&lt;/p&gt;

&lt;h2 id=&quot;riplacer-시나리오&quot;&gt;RIPlacer 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_14.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;“제어된 폴더 액세스” 방식으로 보호하고 있는 폴더 내 파일을 암호화하려고 시도한다. Windows Defender의 “제어된 폴더 액세스”에 대한 별도 설정을 미리 수행해야 한다. Move 연산은 다른 디렉터리로 파일을 옮기는 연산이다. 이 때 파일의 이름을 바꿀 수도 있다. 반면에 Rename 연산은 동일한 디렉터리에서 파일의 이름만 바꾸는 연산이다. 위의 시나리오는 Move 연산을 반복하면서 여러 경로로 파일을 옮기고 그 과정에서 파일을 암호화한다.&lt;/p&gt;

&lt;h2 id=&quot;rigsimulator-시나리오&quot;&gt;RigSimulator 시나리오&lt;/h2&gt;

&lt;p&gt;이 시나리오는 Monero 암호화폐 채굴에 대한 것으로 본 문서에서는 다루지 않는다.&lt;/p&gt;

&lt;h2 id=&quot;replacer-시나리오&quot;&gt;Replacer 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_15.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;원본 파일의 내용을 암호화 되지 않은 다른 내용으로 교체한다. 원본 파일의 내용이 바뀌기는 했지만 암호화되지 않은 정상 파일 포맷을 가지기 때문에 안티 랜섬웨어 프로그램을 우회하는 기법으로 많이 사용된다.&lt;/p&gt;

&lt;h2 id=&quot;insidecryptor-시나리오&quot;&gt;InsideCryptor 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_16.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;파일의 헤더는 그대로 두고 파일의 내용 영역(대략 512 바이트 이후)을 강력한 암호화 방식으로 암호화한다. 안티 랜섬웨어 프로그램은 파일의 암호화 여부를 파일 시그너처로 판별하기도 하는데 InsideCryptor 시나리오는 이러한 방법을 우회할 때 사용한다.&lt;/p&gt;

&lt;h2 id=&quot;injector-시나리오&quot;&gt;Injector 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_17.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;DLL 인젝션 방법으로 정상 프로세스 안으로 암호화 코드를 삽입함으로써 파일을 암호화한다. RanSim에서 설명하는 인젝션 시나리오에서는 모두 notepad.exe를 인젝션 대상 프로세스로 사용하지만 실제 랜섬웨어는 svchost.exe, explorer.exe, iexplore.exe 등의 다양한 정상 프로세스를 대상으로 인젝션을 수행한다. notepad.exe 프로세스는 N 개의 파일을 암호화한 후에 N 개의 파일을 삭제한다. Injector.exe나 inj.exe는 실질적으로 파일 암호화에 관여하지 않았다. 모두 notepad.exe가 랜섬웨어 행위를 수행했다. 안티 랜섬웨어 프로그램은 이러한 공격을 진단하기 위해서 프로세스의 부모-자식 관계 및 리모트스레드 생성 등의 연산을 관리할 수 있어야 한다.&lt;/p&gt;

&lt;h2 id=&quot;reflectiveinjector-시나리오&quot;&gt;ReflectiveInjector 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_18.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Injector 시나리오와 거의 동일하다. 다만 DLL 인젝션이 아닌 Code 인젝션 방식을 사용한다. Code 인젝션 방식을 사용하게 되면 랜섬웨어 입장에서는 디스크에 랜섬웨어 행위를 수행하는 파일을 쓰지 않고 메모리 상에서 모든 것이 이뤄지기 때문에 진단을 어렵게 하는 효과가 있다. 이를 보통 fileless 방식이라고도 한다.&lt;/p&gt;

&lt;h2 id=&quot;hollowinjector-시나리오&quot;&gt;HollowInjector 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_19.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;프로세스 Hollowing 방법으로 정상 프로세스 안으로 암호화 코드를 삽입함으로써 파일을 암호화한다. Inj.exe는 suspend 상태로 notepad.exe프로세스를 생성하고 기존 모듈을 unmap 한다. 그런 다음 랜섬웨어 행위에 필요한 메모리를 notepad.exe 프로세스에 쓴다. 마지막으로 실행 시작지점을 변경한 다음 resume 함으로써 notepad.exe는 본연의 기능을 상실하고 랜섬웨어로 동작하게 된다.&lt;/p&gt;

&lt;h2 id=&quot;mover-시나리오&quot;&gt;Mover 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_20.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;WeakCryptor 시나리오와 거의 유사한 파일 연산 과정을 가지고 있지만 Mover 시나리오는 암호화되는 신규 파일이 원본 파일과 동일한 위치가 아니라 다른 디렉터리에 존재하다는 차이가 있다.&lt;/p&gt;

&lt;h2 id=&quot;lockyvariant-시나리오&quot;&gt;LockyVariant 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_21.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;ThorVariant 시나리오와 유사한 파일 연산을 수행한다. 최신 버전의 Locky 랜섬웨어의 행위를 시뮬레이트한다.&lt;/p&gt;

&lt;h2 id=&quot;critronivariant-시나리오&quot;&gt;CritroniVariant 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_22.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;CritroniVariant 시나리오의 특징은 aaaaall.tmp 라는 이름을 암호화 단계의 중간 파일로 사용한다는 것이다. 그리고 “N개의 원본 파일 1개의 aaaaall.tmp 파일 N 개의 암호화 파일” 과 같은 형식으로 aaaaall.tmp 파일이 암호화되는 모든 파일에 관여하기 때문에 행위기반 안티 랜섬웨어 프로그램은 이러한 파일 연산을 주의 깊게 관찰해야 한다.&lt;/p&gt;

&lt;h2 id=&quot;collaborator-시나리오&quot;&gt;Collaborator 시나리오&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_23.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Collaborator 시나리오는 그 이름에서도 알 수 있듯이 여러 프로세스가 협력하여 파일 암호화를 수행한다. 위의 그림은 하나의 파일을 암호화하는 과정을 도식화한 것이다. Collaborator.exe는 cmd.exe 프로세스를 실행하여 원본 파일을 암호화 파일로 복사한다. 여기까지는 아직 암호화되지 않은 상태이다. 복사가 완료되면 collaborator.exe는 파일 암호화를 수행한다. 마지막으로 원본 파일의 삭제는 다시 새로운 cmd.exe 프로세스를 실행하여 수행한다.&lt;/p&gt;

&lt;p&gt;아래의 그림은 RanSim으로 Collaborator 시나리오가 수행될 때 cmd.exe 프로세스의 생성을 로깅한 것이다. 원본 파일을 암호화하기 위해서 그 개수에 비례해서 cmd.exe 프로세스가 실행된 것을 확인할 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ransim_24.png&quot; alt=&quot;Collaborator.exe가 생성한 cmd.exe 실행 이력&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;랜섬웨어-vs-안티-랜섬웨어&quot;&gt;랜섬웨어 VS. 안티 랜섬웨어&lt;/h2&gt;

&lt;p&gt;RanSim 은 어디까지나 시뮬레이션 프로그램이다. 현실 세계의 랜섬웨어는 본 문서에서 소개한 다양한 시나리오가 복합적으로 반영되어 동작하는 경우도 많다. 또한 문서 파일만 노려서 암호화하던 초기 랜섬웨어와는 달리 실행 파일은 물론이고 운영체제 백업 및 복원과 관련된 ShadowCopy를 삭제하거나 MBR/GPT 영역을 조작하는 등 다양한 기법이 출현하고 있다. 최근 들어서는 암호화한 파일의 복호화 비용을 요구하는 데서 그치지 않고 더 나아가 파일을 유출하여 외부에 공개하는 것으로 금전을 요구하기도 한다.&lt;/p&gt;

&lt;p&gt;안티 랜섬웨어 프로그램은 다양한 기법으로 대응방법을 제시하고 있다. 랜섬웨어의 행위를 추적하여 파일의 변조가 발생하기 전에 실시간으로 백업을 수행하고 랜섬웨어 행위로 진단되면 해당 프로세스를 종료하여 암호화된 파일을 복원해주는 방식이 있다. 그리고 보호 대상 디렉터리를 지정하여 허용 프로그램에 대해서만 접근을 제한하는 방법도 있다. 그 외에도 랜섬웨어가 결제관련 내용을 알리기 위해서 생성하는 랜섬노트 파일의 이름 형식이나 미끼 파일의 변조 유무를 확인하는 방식을 사용하기도 한다. 다양한 안티 랜섬웨어 제품들이 기능을 보완하면서 이러한 대응 기법들이 복합적으로 적용되고 있는 추세이다.&lt;/p&gt;

&lt;h2 id=&quot;마무리&quot;&gt;마무리&lt;/h2&gt;

&lt;p&gt;랜섬웨어의 암호화 기법은 나날이 고도화되고 있다. 본 문서에서 소개한 RanSim 프로그램의 시나리오가 모든 랜섬웨어의 행위를 표현한다고 할 수는 없다. 실제 랜섬웨어는 이러한 암호화 기법들을 다양하게 조합하여 공격하는 추세이기 때문이다. 다양한 랜섬웨어 공격에 대비하기 위해서 안티 랜섬웨어 프로그램을 사용하는 것도 중요하지만 무엇보다도 랜섬웨어를 대비하는 가장 좋은 방법은 중요한 파일을 안전하게 백업하는 것일 터이다.&lt;/p&gt;

&lt;h2 id=&quot;참조&quot;&gt;참조&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;KnowBe4: https://www.knowbe4.com/free-it-security-tools &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;RanSim: https://www.knowbe4.com/ransomware-simulator &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 06 Jul 2020 09:00:00 +0900</pubDate>
        <link>http://nurilab.github.io/2020/07/06/ransim/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2020/07/06/ransim/</guid>
        
        <category>ransomware</category>
        
        <category>ransim</category>
        
        
      </item>
    
      <item>
        <title>안드로이드 실행 파일 포맷 - dex (3)</title>
        <description>&lt;fieldset style=&quot;margin:0px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong style=&quot;font-weight:bold;&quot;&gt;연재 순서&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;/files/images/exclamationmark.png&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2020/05/12/fileformat_dex_1/&quot;&gt;첫번째 글: classes.dex 파일 포맷 (Header, String IDs)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;&lt;a href=&quot;/2020/06/08/fileformat_dex_2/&quot;&gt;두번째 글: classes.dex 파일 포맷 (Type IDs, Proto IDs)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin: 0; background:#ddd;&quot;&gt;세번째 글: classes.dex 파일 포맷 (Field IDs, Method IDs)&lt;/p&gt;
&lt;p style=&quot;margin: 0;&quot;&gt;네번째 글: classes.dex 파일 포맷 (Class Defs, Map List)&lt;/p&gt;
&lt;/div&gt;&lt;/fieldset&gt;

&lt;h2 id=&quot;1-classesdex-추가-파일-포맷&quot;&gt;1. classes.dex 추가 파일 포맷&lt;/h2&gt;

&lt;p&gt;이전 글에 이어 계속 설명을 이어갑니다.&lt;/p&gt;

&lt;h3 id=&quot;5-field-ids&quot;&gt;(5) Field IDs&lt;/h3&gt;

&lt;p&gt;Field 정보 역시 헤더에 시작 위치와 개수가 저장되어 있다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;print hdr['field_ids_size']      # 전체 Field 정보 개수
print hex(hdr['field_ids_off'])  # 전체 Field 정보 시작 위치
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[실행결과]&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;326
0x2634
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;0x2634 위치에 가면 8Byte씩으로 구성된 Field 정보가 나타난다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_dex3_1.png&quot; alt=&quot;Field 정보 시작 위치&quot; /&gt;&lt;/p&gt;

&lt;p&gt;8Byte 정보는 다음과 같은 형태로 구성되어 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_dex3_2.png&quot; alt=&quot;Field 정보 구성 요소&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;field_size = hdr['field_ids_size']  # 전체 Field 정보 개수
field_off  = hdr['field_ids_off']   # 전체 Field 정보 시작 위치

class_idx = struct.unpack('&amp;lt;H', mm[field_off  :field_off+2])[0] # class_idx
type_idx  = struct.unpack('&amp;lt;H', mm[field_off+2:field_off+4])[0] # type_idx
name_idx  = struct.unpack('&amp;lt;L', mm[field_off+4:field_off+8])[0] # name_idx

print hex(class_idx)
print hex(type_idx)
print hex(name_idx)

print '----------------------------------'

print string_ids[type_ids[class_idx]]
print string_ids[type_ids[type_idx]]
print string_ids[name_idx]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[실행결과]&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x20
0x3
0x27f
----------------------------------
Landroid/graphics/Rect;
I
bottom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 결과를 통해 얻은 Filed 정보 내용은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int android.graphics.Rect.bottom&lt;/code&gt;이 된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_dex3_3.png&quot; alt=&quot;Field 정보 리스트&quot; /&gt;&lt;/p&gt;

&lt;p&gt;classes.dex 파일에는 위 그림처럼 다양한 Field 정보가 존재하며 이들을 모두 구하기 위한 방법은 아래와 같다. (위 그림은 그림 크기를 고려하여 일부 정보만이 갭쳐되었다.)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#-----------------------------------------------------------------
# field_id_list : dex 파일의 field 리스트를 추출한다.
#-----------------------------------------------------------------
def field_id_list(mm, hdr) :
    field_list = []
    field_ids_size = hdr['field_ids_size'  ]
    field_ids_off  = hdr['field_ids_off'   ]
    for i in range(field_ids_size) :
        class_idx = struct.unpack('&amp;lt;H', mm[field_ids_off+(i*8)  :field_ids_off+(i*8)+2])[0]
        type_idx  = struct.unpack('&amp;lt;H', mm[field_ids_off+(i*8)+2:field_ids_off+(i*8)+4])[0]
        name_idx  = struct.unpack('&amp;lt;L', mm[field_ids_off+(i*8)+4:field_ids_off+(i*8)+8])[0]
        field_list.append([class_idx, type_idx, name_idx])
    return field_list
    
#---------------------------------------------------------------------
# TEST
#---------------------------------------------------------------------
field_ids = field_id_list(mm, hdr)# 전체 문자열 출력하기
for i in range(len(field_ids)) :
    (class_idx, type_idx, name_idx) = field_ids[i]
    class_str = string_ids[type_ids[class_idx]]
    type_str  = string_ids[type_ids[type_idx]]
    name_str  = string_ids[name_idx]
    mag = '%s %s.%s' % (type_str, class_str, name_str)
    print '[%4d] %s' % (i, mag)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[실행결과]&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[   0] I Landroid/graphics/Rect;.bottom
[   1] I Landroid/graphics/Rect;.left
[   2] I Landroid/graphics/Rect;.right
[   3] I Landroid/graphics/Rect;.top
[   4] I Landroid/os/Build$VERSION;.SDK_INT
         (중간 생략)
[ 323] Landroid/content/Context; Lcom/example/com/android/receiver/d;.c
[ 324] Lcom/example/com/android/receiver/NetChangeReceiver; Lcom/example/com/android/receiver/e;.a
[ 325] Landroid/content/Context; Lcom/example/com/android/receiver/e;.b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;6-method-ids&quot;&gt;(6) Method IDs&lt;/h2&gt;

&lt;p&gt;모든 Method도 classes.dex 내부에서는 별도로 정의된 공간에 저장되어 있다. 헤더에는 Method 개수와 위치가 저장되어 있다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;print hdr['method_ids_size']      # 전체 Method 정보 개수
print hex(hdr['method_ids_off'])  # 전체 Method 정보 시작 위치
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[실행결과]&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1078
0x3064
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;0x3064에 가면 8Byte로 구성된 Method 정보를 볼 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_dex3_4.png&quot; alt=&quot;Method 정보 시작 위치&quot; /&gt;&lt;/p&gt;

&lt;p&gt;8Byte 정보는 아래와 같이 구성이 되어 있다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_dex3_5.png&quot; alt=&quot;Method 정보 구성 요소&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;method_size = hdr['method_ids_size']  # 전체 Method 정보 개수
method_off  = hdr['method_ids_off']   # 전체 Method 정보 시작 위치

class_idx = struct.unpack('&amp;lt;H', mm[method_off  :method_off+2])[0] # class_idx
proto_idx = struct.unpack('&amp;lt;H', mm[method_off+2:method_off+4])[0] # proto_idx
name_idx  = struct.unpack('&amp;lt;L', mm[method_off+4:method_off+8])[0] # name_idx

print hex(class_idx)
print hex(proto_idx)
print hex(name_idx)

print '----------------------------------'

print string_ids[type_ids[class_idx]]
print string_ids[proto_ids[proto_idx][0]]
print string_ids[name_idx]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[실행결과]&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x5
0x1b
0x2df
----------------------------------
Landroid/animation/ValueAnimator;
J
getFrameDelay
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 결과를 통해 함수 원형은 J, 즉 리턴값이 long이며 인자값은 없다. 따라서 이 Method는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;long android.animation.ValueAnimator.getFrameDelay()&lt;/code&gt;가 된다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/files/ff_dex3_6.png&quot; alt=&quot;Method 정보 리스트&quot; /&gt;&lt;/p&gt;

&lt;p&gt;classes.dex 파일에는 위 그림처럼 다양한  Method 정보가 존재하며 이들을 모두 구하기 위한 방법은 아래와 같다. (위 그림은 그림 크기를 고려하여 일부 정보만이 갭쳐되었다.)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#-----------------------------------------------------------------
# method_id_list : dex 파일의 method 리스트를 추출한다.
#-----------------------------------------------------------------
def method_id_list(mm, hdr) :
    method_list = []
    method_ids_size = hdr['method_ids_size'  ]
    method_ids_off  = hdr['method_ids_off'   ]
    for i in range(method_ids_size) :
        class_idx = struct.unpack('&amp;lt;H', mm[method_ids_off+(i*8)  :method_ids_off+(i*8)+2])[0]
        proto_idx = struct.unpack('&amp;lt;H', mm[method_ids_off+(i*8)+2:method_ids_off+(i*8)+4])[0]
        name_idx  = struct.unpack('&amp;lt;L', mm[method_ids_off+(i*8)+4:method_ids_off+(i*8)+8])[0]
        method_list.append([class_idx, proto_idx, name_idx])
    return method_list
    
#---------------------------------------------------------------------
# TEST
#---------------------------------------------------------------------
method_ids = method_id_list(mm, hdr)# 전체 문자열 출력하기
for i in range(len(method_ids)) :
    (class_idx, proto_idx, name_idx) = method_ids[i]
    class_str = string_ids[type_ids[class_idx]]
    name_str  = string_ids[name_idx]
    print '[%04d] %s.%s()' % (i, class_str, name_str)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[실행결과]&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[0000] Landroid/animation/ValueAnimator;.getFrameDelay()
[0001] Landroid/app/Activity;.&amp;lt;init&amp;gt;()
[0002] Landroid/app/Activity;.invalidateOptionsMenu()
[0003] Landroid/app/Activity;.onActivityResult()
[0004] Landroid/app/Activity;.onConfigurationChanged()
         (중간 생략)
[1074] Lorg/apache/http/client/HttpClient;.execute()
[1075] Lorg/apache/http/client/methods/HttpGet;.&amp;lt;init&amp;gt;()
[1076] Lorg/apache/http/impl/client/DefaultHttpClient;.&amp;lt;init&amp;gt;()
[1077] Lorg/apache/http/util/EntityUtils;.toString()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;2-결론&quot;&gt;2. 결론&lt;/h2&gt;

&lt;p&gt;이번 글에서는 Field와 Method에 대해서 알아보았다. 다음편이 classes.dex의 마지막인 Class Defs와 Map List를 살펴볼 것이다. 실제 classes.dex 파일 포맷을 보면서 이게 무슨 의미가 있나? 생각할지도 모르겠다.&lt;/p&gt;

&lt;p&gt;이는 앞으로 다룰 classes.dex 디컴파일러를 위해 필요한 정보이다. 그때 이 정보가 엄청난 도움이 된다는 것을 알게 될 것이다.&lt;/p&gt;

&lt;h2 id=&quot;3-참조&quot;&gt;3. 참조&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Dalvik Executable Format: &lt;a href=&quot;https://source.android.com/devices/tech/dalvik/dex-format&quot;&gt;https://source.android.com/devices/tech/dalvik/dex-format&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Mon, 15 Jun 2020 18:30:00 +0900</pubDate>
        <link>http://nurilab.github.io/2020/06/15/fileformat_dex_3/</link>
        <guid isPermaLink="true">http://nurilab.github.io/2020/06/15/fileformat_dex_3/</guid>
        
        <category>fileformat</category>
        
        <category>python</category>
        
        <category>dex</category>
        
        
      </item>
    
  </channel>
</rss>
