<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>방망이</title>
    <link>https://manguu.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 26 Jul 2026 16:32:10 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>망구입니다</managingEditor>
    <image>
      <title>방망이</title>
      <url>https://tistory1.daumcdn.net/tistory/8563837/attach/759665839a6c4fbc90e48d07e0f63864</url>
      <link>https://manguu.tistory.com</link>
    </image>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 16주차 - 스크립트 업데이트를 위하여..</title>
      <link>https://manguu.tistory.com/17</link>
      <description>&lt;h4 data-sourcepos=&quot;3:1-3:17;49-65&quot; data-ke-size=&quot;size20&quot;&gt;왜 업그레이드가 필요한가&lt;/h4&gt;
&lt;p data-sourcepos=&quot;5:1-5:323;67-389&quot; data-ke-size=&quot;size16&quot;&gt;기존에 작성한 DepexHunter 스크립트는 UEFI 펌웨어 이미지를 UEFIExtract로 풀어놓은 덤프 폴더를 순회하면서, 각 DXE 드라이버의 DEPEX(Dependency Expression) 섹션을 파싱해 &quot;이 드라이버가 요구하는 프로토콜이 이미지 안의 어떤 드라이버로도 제공되지 않는&quot; 경우를 찾아내는 스크립트다. 이 스크립트는 GhidraScript를 상속하고 있음에도 정작 Ghidra의 핵심 기능인 디스어셈블/디컴파일/P-code 분석은 전혀 쓰지 않는다. 실제 동작은 info.txt와 body.bin을 텍스트&amp;middot;바이너리 레벨에서 직접 파싱하는 파일 시스템 순회에 가깝다.&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:323;67-389&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:323;67-389&quot; data-ke-size=&quot;size16&quot;&gt;프로토콜을 &quot;누가 제공하는가&quot;를 판단하는 로직도 마찬가지로 코드 분석이 아니라 이름 매칭에 의존한다. 1단계로 약 200개 프로토콜을 하드코딩해둔 switch-case 테이블(knownProtocolProvider)을 먼저 확인하고, 여기서 못 찾으면 2단계로 프로토콜 이름에서 &quot;Protocol&quot;, &quot;Guid&quot;, &quot;Efi&quot; 같은 접두&amp;middot;접미사를 제거한 뒤 그 문자열이 드라이버 이름에 부분 문자열로 포함되는지를 본다. 이 방식은 두 방향으로 오류가 난다. 이름이 우연히 겹치면 실제로는 관련 없는 드라이버를 provider로 오인하고, 이름이 표준 명명 규칙을 따르지 않는 벤더 커스텀 드라이버라면 실제로 프로토콜을 제공하고 있어도 놓친다. 하드코딩 테이블도 EDK2 표준 프로토콜에만 대응하기 때문에 새로운 펌웨어나 벤더 특화 프로토콜이 나올 때마다 사람이 계속 추가해줘야 하는 구조다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:323;67-389&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:323;67-389&quot; data-ke-size=&quot;size16&quot;&gt;이걸 근본적으로 고치려면, &quot;이름이 비슷한가&quot;가 아니라 &quot;그 드라이버의 코드가 실제로 해당 GUID로 프로토콜을 install하는가&quot;를 코드 레벨에서 직접 확인해야 한다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;(이게 P-code를 공부하는 이유)&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:323;67-389&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-sourcepos=&quot;11:1-11:46;958-1003&quot; data-ke-size=&quot;size20&quot;&gt;필요한 개념 1: 간접 호출 해석 (EFI_BOOT_SERVICES 구조체)&lt;/h4&gt;
&lt;p data-sourcepos=&quot;13:1-13:261;1005-1265&quot; data-ke-size=&quot;size16&quot;&gt;UEFI 드라이버 코드에서 프로토콜을 등록하는 호출은 대부분&lt;/p&gt;
&lt;pre id=&quot;code_1784795010722&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;gBS-&amp;gt;InstallProtocolInterface(...)
gBS-&amp;gt;InstallMultipleProtocolInterfaces(...)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-sourcepos=&quot;13:1-13:261;1005-1265&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;13:1-13:261;1005-1265&quot; data-ke-size=&quot;size16&quot;&gt;위 두 형태로, EFI_BOOT_SERVICES 구조체 포인터를 통한 간접 호출로 나타난다. 어셈블리 레벨에서는 이게 CALLIND(간접 호출) PcodeOp으로 표현되고, 타겟 주소는 특정 함수 심볼이 아니라 어떤 레지스터나 메모리 위치에서 LOAD된 값이다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:284;1267-1550&quot; data-ke-size=&quot;size16&quot;&gt;이걸 식별하려면 CALLIND의 타겟 Varnode를 역추적해서, 그것이 gBS 전역 포인터에서 구조체 필드 오프셋만큼 떨어진 위치를 LOAD한 결과인지 확인해야 한다. EFI_BOOT_SERVICES 구조체에서 InstallProtocolInterface는 정해진 오프셋에 위치하므로, Ghidra에 이 구조체 타입을 데이터 타입으로 씌워두면 오프셋 기반 필드 매칭이 훨씬 수월해진다. 이 부분을 중점으로 앞으로 공부하지 않을까 싶다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:284;1267-1550&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-sourcepos=&quot;17:1-17:37;1552-1588&quot; data-ke-size=&quot;size20&quot;&gt;필요한 개념 2: CALL 인자 추적 (Use-Def 체인)&lt;/h4&gt;
&lt;p data-sourcepos=&quot;19:1-19:413;1590-2002&quot; data-ke-size=&quot;size16&quot;&gt;호출 대상이 InstallProtocolInterface라는 것을 확인했다면, 다음은 그 두 번째 인자인 GUID 포인터를 추적할 차례다. 이 인자로 쓰인 Varnode에서 getDef()를 통해 정의 지점을 거슬러 올라가면, 결국 .data 섹션의 어떤 고정 주소(보통 gEfiXxxProtocolGuid 심볼)를 가리키는 CONST Varnode에 도달하게 된다 &quot;이 인자가 어떤 고정된 상수인가&quot;를 확인하는 것이므로 Use-Def체인을 사용한다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;19:1-19:413;1590-2002&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-sourcepos=&quot;21:1-21:24;2004-2027&quot; data-ke-size=&quot;size20&quot;&gt;필요한 개념 3: GUID 상수 추출&lt;/h4&gt;
&lt;p data-sourcepos=&quot;23:1-23:293;2029-2321&quot; data-ke-size=&quot;size16&quot;&gt;CONST Varnode로 가리켜지는 주소를 찾았다면, 그 주소에서 16바이트를 읽어 실제 GUID 값을 얻어야 한다. 이 값을 기존에 갖고 있는 GUID 데이터베이스(guids.csv)와 대조하면, 이름 문자열이 아니라 실제 바이트 값으로 어떤 프로토콜인지 확정할 수 있다. 이렇게 하면 기존에 &lt;s&gt;똥멍청이스크립트에서&lt;/s&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용하던&lt;/span&gt; 하드코딩된 switch-case 테이블도, 이름 유사도 기반 substring 매칭도 모두 필요 없어진다. 드라이버 이름이 표준 명명 규칙을 따르든 따르지 않든, 코드가 실제로 그 GUID를 install하기만 하면 잡아낼 수 있다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;23:1-23:293;2029-2321&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-sourcepos=&quot;25:1-25:12;2323-2334&quot; data-ke-size=&quot;size20&quot;&gt;학습 순서&lt;/h4&gt;
&lt;p data-sourcepos=&quot;27:1-27:279;2336-2614&quot; data-ke-size=&quot;size16&quot;&gt;우선 EFI_BOOT_SERVICES 구조체를 Ghidra 데이터 타입으로 적용하고 CALLIND의 타겟을 오프셋 기반으로 식별하는 연습부터 시작하는 게 좋을 것 같다. 이게 되면 InstallProtocolInterface 호출 지점을 코드에서 자동으로 찾아낼 수 있는 상태가 된다고 한다(클로드가). 그다음은 CALL 인자 추적으로 GUID 포인터의 Use-Def 체인을 따라가 실제 상수 주소를 특정하고, 마지막으로 그 주소에서 GUID 바이트를 읽어 기존 GUID DB와 매칭하는 순서로 진행하면 좋을 것 같다.&lt;/p&gt;
&lt;p data-sourcepos=&quot;27:1-27:279;2336-2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;29:1-29:143;2616-2758&quot; data-ke-size=&quot;size16&quot;&gt;이 세 단계가 완성되면 provider 추정 로직 전체를 이름 기반 휴리스틱에서 코드 기반 검증으로 교체할 수 있고, 이후 알려진 CVE가 있는 실제 펌웨어 바이너리에 적용해보면서 하드코딩 테이블 없이도 정확히 동작하는지 검증하는 단계로 넘어갈 수 있다.&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/17</guid>
      <comments>https://manguu.tistory.com/17#entry17comment</comments>
      <pubDate>Thu, 23 Jul 2026 17:31:10 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 15주차 - P-code Phase3</title>
      <link>https://manguu.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- 오늘의 주제 및 키워드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;gt; &lt;b&gt;데이터 흐름 기초&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;gt; &lt;b&gt;[Reaching Def, Def-Use, Live Variable]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;데이터 흐름 (Data Flow Analysis)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P-code로 취약점을 분석할 때 핵심 포인트는 &quot;외부에서 들어온 값이 위험한 함수까지 도달할 수 있는가?&quot;에 대한 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 질문에 대한 답을 하기 위해서는 코드를 실행하지 않고도 값이 어디서 왔고, 어디로 흘러가는지 파악할 수 있어야 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Def-Use Chain&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수의 정의(Def)와 사용(Use)을 연결한 체인&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Def - 변수에 값이 처음 할당되는 지점(의미 있는 값이 처음 들어오는 시점)&lt;/li&gt;
&lt;li&gt;Use - 그 값이 입력으로 읽히는 지점&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드를 예시로 들어보자.&lt;/p&gt;
&lt;pre id=&quot;code_1782971850375&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void func(int sock) {
    char buf[64];
    recv(sock, buf, 64, 0);  // 외부에서 데이터 수신 (Def 지점)
    strcpy(dst, buf);        // buf를 그대로 복사 (Use 지점)
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;recv() &amp;rarr; buf 정의(Def)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;recv()가 외부 네트워크에서 데이터를 읽어서 buf에 저장. 이 순간 buf라는 변수에 값이 처음 할당됨. 이 부분이 Def(정의) 지점.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;rarr; strcpy에 전달(Use)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;buf에 담긴 값이 strcpy의 두 번째 인자로 전달. 이 순간 buf의 값이 읽힘. 이 부분이 Use(사용) 지점.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;rarr; 취약점!
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;strcpy는 길이 검사를 하지 않음. buf에 외부에서 온 데이터가 담겨 있는데, 그 길이를 확인하지 않고 그대로 복사하면 버퍼 오버플로가 발생할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ghidra에서는 API로 접근 가능&lt;/p&gt;
&lt;pre id=&quot;code_1782971659276&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;varnodeAST.getDef()          // 이 Varnode의 값이 어떤 op에 의해 만들어졌는가 (역방향)
varnodeAST.getDescendants()  // 이 Varnode의 값이 어떤 op들에서 사용되는가 (순방향)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSA에서는 변수가 딱 한 번만 정의되므로 getDef()가 항상 하나의 op만 반환.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비SSA 코드라면 같은 변수가 여러 곳에서 정의될 수 있어서 추적이 복잡하지만, High P-code는 SSA form이라 체인 추적이 단순하고 명확함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;getDef()&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 예시로 든 C 코드를 기반으로 봤을 때&lt;/p&gt;
&lt;pre id=&quot;code_1782972625067&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;buf.getDef()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호출시 CALL recv() op 반환 &amp;rarr; buf의 값은 recv()가 만들었다는 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getDef()가 &lt;b&gt;null을 반환하는 경우&lt;/b&gt;도 있는데, 이는 더 이상 거슬러 올라갈 곳이 없다는 뜻으로 아래 두 가지 경우에 해당함.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;함수 인자(HighParam) &amp;rarr; 호출자가 넘겨준 값 &amp;rarr; Taint Source!&lt;/li&gt;
&lt;li&gt;전역 변수 &amp;rarr; 외부 상태(&lt;span data-newtext-seq=&quot;0&quot;&gt;현재&lt;/span&gt;&lt;span data-newtext-seq=&quot;2&quot;&gt; 분석 중인 &lt;/span&gt;&lt;b&gt;&lt;span data-newtext-seq=&quot;11&quot;&gt;함수 바깥에서 관리되는 값. &lt;/span&gt;&lt;/b&gt;&lt;span data-newtext-seq=&quot;11&quot;&gt;함수 입장에서는 어떤 값이 들어있는지 알 수 없는 외부의 상태라는 뜻&lt;/span&gt;)&amp;nbsp; &amp;rarr; Taint Source 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 다 이 함수 안에서 정의된 것이 아니므로 더 이상 역추적할 수 없음. 그래서 탐색을 멈추고 &lt;b&gt;Taint source로 판정&lt;/b&gt;하는 조건이 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이는 역방향 슬라이싱의 탐색 종료 조건이 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;getDescendants&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 하나의 값이 여러 곳에서 쓰일 수 있으므로 Iterator로 반환됨.&lt;/p&gt;
&lt;pre id=&quot;code_1782973438515&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VarnodeAST buf = ...;                      // buf Varnode
Iterator&amp;lt;PcodeOp&amp;gt; uses = buf.getDescendants();
while (uses.hasNext()) {
    PcodeOp useOp = uses.next();
    println(useOp.getMnemonic());          // buf를 쓰는 op들 출력
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getDef와 getDescendants를 함께 쓰는 이유는 아래와 같은 로직을 사용하여 외부 입력으로 인한 위험 함수 경로를 파악.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;getDef()&lt;/b&gt; &amp;rarr; &quot;이 값이 외부 입력에서 왔는가?&quot; 판단 &amp;rarr; Taint source 확인&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getDescendants()&lt;/b&gt; &amp;rarr; &quot;이 tainted 값이 어디까지 퍼지는가?&quot; 추적 &amp;rarr; sink 도달 여부 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Reaching Definitions&lt;/h3&gt;
&lt;pre id=&quot;code_1782980578866&quot; class=&quot;gauss&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;x = input;       // 정의 d1
if (cond) {
    x = 0;       // 정의 d2
}
use(x);          // 여기서 도달 가능한 정의는?
                 // &amp;rarr; d1과 d2 둘 다 가능&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 지점에서 &lt;b&gt;&quot;어떤 정의가 여기까지 도달 가능한가&quot;&lt;/b&gt; 를 분석. 변수의 출처를 판단하는 데 사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;High P-code는 SSA(Static Single Assignment) 형태&lt;/b&gt;라서 Reaching Definition 개념을 곧바로 적용하기 애매함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SSA에서는 변수가 딱 한 번만 정의됨.&lt;/b&gt; 같은 변수를 여러 번 대입하는 코드가 있어도, SSA로 변환되는 과정에서 x#1, x#2, x#3처럼 매번 새로운 이름이 붙음. 그래서 getDef()를 호출하면 언제나 정확히 하나의 op만 반환되고, &quot;여러 정의가 도달 가능하다&quot;는 상황 자체가 애초에 생기지 않게 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분기가 있으면 합류점에서 여러 정의가 동시에 도달할 수 있는데, High P-code에서는 이 상황을 &lt;b&gt;MULTIEQUAL(&amp;phi;노드)&lt;/b&gt; 로 표현.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 사실 &quot;이 지점에 x#1과 x#2라는 정의가 동시에 도달 가능하다&quot;는 &lt;b&gt;Reaching Definitions 분석의 결과가 이미 코드 구조에 반영되어 있는 것.&amp;nbsp;&lt;/b&gt;즉, Ghidra가 Raw P-code를 High P-code(SSA)로 변환하는 과정 자체가, 내부적으로 Reaching Definitions와 본질적으로 같은 계산을 수행한 결과물이라는 뜻.&lt;/p&gt;
&lt;pre id=&quot;code_1782980608316&quot; class=&quot;llvm&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;x#3 = MULTIEQUAL(x#1_input, x#2_zero)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 SSA 위에서 GEN/KILL/IN/OUT 알고리즘을 직접 돌리는 건 의미가 없음. &amp;mdash; 이미 계산되어 있는 답을 다시 계산하는 셈이기 때문. MULTIEQUAL의 입력 목록을 확인하는 것만으로 &quot;이 지점에 어떤 정의가 도달하는가&quot;에 대한 답을 바로 얻을 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일러개론 수업에서 배운 &lt;b&gt;GEN/KILL/IN/OUT 고정점 반복 알고리즘을 직접 구현하고 확인&lt;/b&gt;해보려면, 정의가 여러 번 일어날 수 있는 &lt;b&gt;비SSA 코드, 즉 Raw P-code&lt;/b&gt;로 내려가야 함. Raw P-code는 명령어 단위 그대로의 저수준 표현이라 같은 레지스터/스택 위치에 값이 여러 번 쓰일 수 있기 때문.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석 알고리즘은 각 블록의 IN/OUT 집합을 계산하며 변화가 없을 때까지 반복. (고정점 반복)&lt;/p&gt;
&lt;pre id=&quot;code_1782974432372&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;OUT[B] = GEN[B] &amp;cup; (IN[B] - KILL[B])
IN[B]  = &amp;cup; OUT[pred]  for all predecessors&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Live Variable Analysis&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 지점에서 &lt;b&gt;&quot;이후에 사용될 변수가 무엇인가&quot;&lt;/b&gt; 를 분석. Reaching Definitions가 과거&amp;rarr;현재 방향의 &lt;b&gt;순방향 분석&lt;/b&gt;이라면, Live Variable은 미래&amp;rarr;현재 방향의 &lt;b&gt;역방향 분석&lt;/b&gt;.&lt;/p&gt;
&lt;pre id=&quot;code_1782974713040&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;x = input;   // x: live (아래에서 쓰임)
y = x + 1;   // x: 이후 dead, y: live
z = 10;      // z: dead (이후 z를 읽는 곳 없음)
use(y);      // y: 이후 dead&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;z는 이후에 전혀 사용되지 않으므로 &lt;b&gt;Dead Variable&lt;/b&gt;. Taint 분석에서 z를 추적하는 것은 불필요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Live Variable Analysis는 취약점 분석에서 세 가지 역할을 함.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;불필요한 Taint 추적 제거 &amp;mdash; Dead Variable은 이후 취약점을 유발할 수 없으므로 분석 대상에서 제외해 속도를 높임.&lt;/li&gt;
&lt;li&gt;False Positive 감소 &amp;mdash; tainted 변수가 sink 이전에 Dead가 된다면 실제로는 위험하지 않음. 이를 걸러내면 잘못된 정보를 줄일 수 있음.&lt;/li&gt;
&lt;li&gt;Sanitizer 탐지 &amp;mdash; tainted 변수가 검증 함수를 거친 뒤 새 변수에 할당되면 이전 tainted 버전이 Dead가 됨. 이 패턴으로 입력 검증 코드를 자동 인식할 수 있음.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1782974974881&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char* sanitize(char* input) {
    // 길이 검사, 특수문자 제거 등
    return cleaned_input;
}

void func(char* input) {       // input: tainted
    char* safe = sanitize(input);  // 검증 후 새 변수에 할당
    strcpy(dst, safe);             // safe를 사용
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sanitize함수는 사용자 입력을 검증하거나 정제하는 함수.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sanitizer를 거치는 경우 검증 후 새 변수에 할당되므로 sanitizer 호출 이후 이 변수는 Dead variable이 됨.&lt;/p&gt;
&lt;pre id=&quot;code_1782975075870&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tainted 변수(input#1)가
  &amp;rarr; 어떤 함수(sanitize)를 거쳐
  &amp;rarr; 새 변수(safe#1)에 할당되고
  &amp;rarr; 기존 tainted 변수(input#1)가 Dead가 됨
  &amp;rarr; 이 함수가 Sanitizer일 가능성이 높다!
  즉 &quot;tainted 변수가 Dead가 되는 지점에 함수 호출이 있다면&quot; 그 함수를 Sanitizer 후보로 자동 인식할 수 있음.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 로직으로 분석기가 Sanitizer를 탐지할 수 있게 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 Live Variable Anaysis로 Sanitizer를 탐지하게 되면, 그 이후의 변수를 &lt;b&gt;tainted 목록에서 제거&lt;/b&gt;할 수 있으므로 tainted 변수 추적에 도움을 줄 수 있음.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.0698%;&quot;&gt;기법&lt;/td&gt;
&lt;td style=&quot;width: 43.9535%;&quot;&gt;기&lt;/td&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;방향&lt;/td&gt;
&lt;td style=&quot;width: 19.186%;&quot;&gt;역할&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.0698%;&quot;&gt;Def-Use 체인&lt;/td&gt;
&lt;td style=&quot;width: 43.9535%;&quot;&gt;값이 어디서 왔고 어디로 가는가&lt;/td&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;양방향&lt;/td&gt;
&lt;td style=&quot;width: 19.186%;&quot;&gt;흐름 추적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.0698%;&quot;&gt;Reaching Definitions&lt;/td&gt;
&lt;td style=&quot;width: 43.9535%;&quot;&gt;어떤 정의가 여기까지 도달 가능한가&lt;/td&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;순방향&lt;/td&gt;
&lt;td style=&quot;width: 19.186%;&quot;&gt;출처 판단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.0698%;&quot;&gt;Live Variable&lt;/td&gt;
&lt;td style=&quot;width: 43.9535%;&quot;&gt;이 변수가 이후에 사용되는가&lt;/td&gt;
&lt;td style=&quot;width: 12.5581%;&quot;&gt;역방향&lt;/td&gt;
&lt;td style=&quot;width: 19.186%;&quot;&gt;분석 범위 축소&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 세가지 기법은 독립적으로 동작하는 것이 아니라&lt;b&gt;&amp;nbsp;Def-Use로 흐름을 추적&lt;/b&gt;하고, &lt;b&gt;Reaching Definitions로 출처를 판단&lt;/b&gt;하고, &lt;b&gt;Live Variable로 분석 범위를 좁히는&lt;/b&gt; 방식으로 함께 동작.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실습&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; DVRF(Damn Vulnerable Router Firmware)를 다운 받아서 진행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/praetorian-inc/DVRF&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/praetorian-inc/DVRF&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/DVRF/Firmware/_DVRF_v03.bin.extracted/squashfs-root/pwnable/Intro/stack_bof_01 파일 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. Def-Use 체인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d6Fn0P/dJMcacRaPws/LaHBjO2iyPWleF6nTKJAc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d6Fn0P/dJMcacRaPws/LaHBjO2iyPWleF6nTKJAc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d6Fn0P/dJMcacRaPws/LaHBjO2iyPWleF6nTKJAc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6Fn0P%2FdJMcacRaPws%2FLaHBjO2iyPWleF6nTKJAc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;412&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cluade에서 Def-Use 체인을 실습할 수 있는 스크립트를 생성해서 돌려본 결과&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KxOVz/dJMcadoZAju/IrryO3TVW1Bv2GI9hBT5Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KxOVz/dJMcadoZAju/IrryO3TVW1Bv2GI9hBT5Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KxOVz/dJMcadoZAju/IrryO3TVW1Bv2GI9hBT5Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKxOVz%2FdJMcadoZAju%2FIrryO3TVW1Bv2GI9hBT5Tk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;676&quot; height=&quot;390&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Taint Source&lt;/b&gt;: param_2(=argv)가 main의 함수 인자로서 이 함수 안에서 정의되지 않음 &amp;rarr; getDef() = null &amp;rarr; Taint Source 판정&lt;/li&gt;
&lt;li&gt;즉, &quot;함수 인자로 들어온 외부 입력이 검증 없이 strcpy까지 도달&quot;하는 것을 찾아냄.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. Reaching Definitions&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일러개론 수업에서 배웠던 GEN/KILL, IN/OUT을 스크립트로 구해보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;782&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3SdvH/dJMcadikLWF/kkQRyuJrCPPHTQdJVOggh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3SdvH/dJMcadikLWF/kkQRyuJrCPPHTQdJVOggh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3SdvH/dJMcadikLWF/kkQRyuJrCPPHTQdJVOggh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3SdvH%2FdJMcadikLWF%2FkkQRyuJrCPPHTQdJVOggh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1540&quot; height=&quot;782&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;782&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수업 때 배웠던 내용을 직접 스크립트로 구해보고 볼 수 있는 것이 굉장히 신기하고 유익하다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. Live Variable Analysis&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XCAbT/dJMcafAqq2G/ZdOUK96aJWTapJo4zzab6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XCAbT/dJMcafAqq2G/ZdOUK96aJWTapJo4zzab6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XCAbT/dJMcafAqq2G/ZdOUK96aJWTapJo4zzab6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXCAbT%2FdJMcafAqq2G%2FZdOUK96aJWTapJo4zzab6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1018&quot; height=&quot;616&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스크립트에서는 Dead Variable을 찾는다. 해당 블록에서 벗어나는 순간 Dead 상태가 되는 변수를 찾아내는 스크립트이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습은 간단하게 각 개념을 적용하는 함수를 사용해보는 수준의 실습이지만,&amp;nbsp;위에서 정리한 개념과 실습 내용을 바탕으로 Taint 분석과 취약점 탐지 스크립트에 적용하면 더 좋은 결과를 낼 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/16</guid>
      <comments>https://manguu.tistory.com/16#entry16comment</comments>
      <pubDate>Thu, 2 Jul 2026 15:54:35 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 14주차 - P-code Phase2</title>
      <link>https://manguu.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;[P-code 공부 커리큘럼]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;1706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwZDSE/dJMcafz2Gtj/MV00Baw58w7VMyAKhwauy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwZDSE/dJMcafz2Gtj/MV00Baw58w7VMyAKhwauy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwZDSE/dJMcafz2Gtj/MV00Baw58w7VMyAKhwauy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwZDSE%2FdJMcafz2Gtj%2FMV00Baw58w7VMyAKhwauy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;742&quot; height=&quot;1706&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;1706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Phase2에서 4, 5번에 대한 내용은 팀원들의 블로그를 참고한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Phase2 - 4 (Varnode, PcodeOp) &lt;a href=&quot;https://ludence8.github.io/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/2026-05-16-PCode-1.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ludence8.github.io/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/2026-05-16-PCode-1.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1780210673392&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Ghidra P-Code 알아보기 1&quot; data-og-description=&quot;P-Code (사실 P-Code는 다들 너무 잘 알고 있을 것이라 생각한다&amp;hellip;) P-Code는 Ghidra가 사용하는 IR로, 다양한 프로그래밍 언어들을 통일하기 위한 목적인 컴파일러 레벨의 IR들과 달리 P-Code는 MIPS, x86, ARM&quot; data-og-host=&quot;ludence8.github.io&quot; data-og-source-url=&quot;https://ludence8.github.io/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/2026-05-16-PCode-1.html&quot; data-og-url=&quot;https://ludence8.github.io/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/2026-05-16-PCode-1.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dRiwui/dJMb9g5hZKg/f5364gKLK6x6bA3kRr0dDk/img.png?width=646&amp;amp;height=246&amp;amp;face=0_0_646_246&quot;&gt;&lt;a href=&quot;https://ludence8.github.io/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/2026-05-16-PCode-1.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ludence8.github.io/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/2026-05-16-PCode-1.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dRiwui/dJMb9g5hZKg/f5364gKLK6x6bA3kRr0dDk/img.png?width=646&amp;amp;height=246&amp;amp;face=0_0_646_246');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Ghidra P-Code 알아보기 1&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;P-Code (사실 P-Code는 다들 너무 잘 알고 있을 것이라 생각한다&amp;hellip;) P-Code는 Ghidra가 사용하는 IR로, 다양한 프로그래밍 언어들을 통일하기 위한 목적인 컴파일러 레벨의 IR들과 달리 P-Code는 MIPS, x86, ARM&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ludence8.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Phase2 - 4 (SLEIGH, High Pcode vs Raw P-Code)&lt;br /&gt;&lt;a href=&quot;https://eatrawlife.github.io/posts/2026/05/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://eatrawlife.github.io/posts/2026/05/17&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1780237394814&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;UEFI 스터디 15차 - 기드라 p 코드 공부 (sleigh, high VS low pcode.)&quot; data-og-description=&quot;sleigh&quot; data-og-host=&quot;eatrawlife.github.io&quot; data-og-source-url=&quot;https://eatrawlife.github.io/posts/2026/05/17&quot; data-og-url=&quot;https://eatrawlife.github.io/posts/2026/05/17&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/hwGx9/dJMb8QMi7Cw/4dlPKKQOIQwDbd6XaDlUVk/img.png?width=1398&amp;amp;height=507&amp;amp;face=0_0_1398_507,https://scrap.kakaocdn.net/dn/bpxFsJ/dJMb8XkmrMH/nLMvCSThKaEm0ksxa0cTJ0/img.png?width=1527&amp;amp;height=455&amp;amp;face=0_0_1527_455,https://scrap.kakaocdn.net/dn/c0qtro/dJMb8ZvIsNO/0Zm0hHH5A77p4ANhVXfWck/img.png?width=797&amp;amp;height=772&amp;amp;face=0_0_797_772&quot;&gt;&lt;a href=&quot;https://eatrawlife.github.io/posts/2026/05/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://eatrawlife.github.io/posts/2026/05/17&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/hwGx9/dJMb8QMi7Cw/4dlPKKQOIQwDbd6XaDlUVk/img.png?width=1398&amp;amp;height=507&amp;amp;face=0_0_1398_507,https://scrap.kakaocdn.net/dn/bpxFsJ/dJMb8XkmrMH/nLMvCSThKaEm0ksxa0cTJ0/img.png?width=1527&amp;amp;height=455&amp;amp;face=0_0_1527_455,https://scrap.kakaocdn.net/dn/c0qtro/dJMb8ZvIsNO/0Zm0hHH5A77p4ANhVXfWck/img.png?width=797&amp;amp;height=772&amp;amp;face=0_0_797_772');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;UEFI 스터디 15차 - 기드라 p 코드 공부 (sleigh, high VS low pcode.)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;sleigh&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;eatrawlife.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Phase2 - 5(P-code 연산자)&lt;br /&gt;&lt;a href=&quot;https://img1244.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://img1244.tistory.com/28&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1780210816579&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;15차 전원회의 - p-code operator를! 공부해보자&quot; data-og-description=&quot;p-code 오퍼레이터는 ghidra 공식 문서를 참조https://ghidra.re/ghidra_docs/languages/html/pcodedescription.html#cpui_copy P-Code Operation ReferenceFor each possible p-code operation, we give a brief description and provide a table that lists th&quot; data-og-host=&quot;img1244.tistory.com&quot; data-og-source-url=&quot;https://img1244.tistory.com/28&quot; data-og-url=&quot;https://img1244.tistory.com/28&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJsrA2/dJMb9gxsnpk/BRJMyywh4NGmWKy8wwAd70/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dYCmJs/dJMb8ZvIqCE/CpJY2zKr8YdOLybRNYNJj0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/3vx32/dJMb9efkVsU/kVNnDFBee1qQPKMLlNv540/img.jpg?width=734&amp;amp;height=720&amp;amp;face=0_0_734_720&quot;&gt;&lt;a href=&quot;https://img1244.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://img1244.tistory.com/28&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJsrA2/dJMb9gxsnpk/BRJMyywh4NGmWKy8wwAd70/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dYCmJs/dJMb8ZvIqCE/CpJY2zKr8YdOLybRNYNJj0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/3vx32/dJMb9efkVsU/kVNnDFBee1qQPKMLlNv540/img.jpg?width=734&amp;amp;height=720&amp;amp;face=0_0_734_720');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;15차 전원회의 - p-code operator를! 공부해보자&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;p-code 오퍼레이터는 ghidra 공식 문서를 참조https://ghidra.re/ghidra_docs/languages/html/pcodedescription.html#cpui_copy P-Code Operation ReferenceFor each possible p-code operation, we give a brief description and provide a table that lists th&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;img1244.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주에 내가 공부한 내용은 위 커리큘럼에서 Phase2에 6~7부분 중 &lt;b&gt;SSA 정적 단일 할당과 데이터 흐름 추적&amp;nbsp;&lt;/b&gt;파트이다. 이 파트에서는 Varnode와 High Variable, 심볼 분류와 분석 소스 판정, Def-Use 체인에 대한 내용을 다룰 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Varnode와 High Variable&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Varnode는 P-code에서 모든 값을 표현하는 기본 단위이다. 레지스터든, 메모리든, 상수든간에 전부 (address space, offset, size) 이렇게 세 필드로 표현된다.&lt;/li&gt;
&lt;li&gt;Raw P-code에서는 Varnode가 단순히 레지스터 위치((register, 0x0, 8)=RAX)를 가리키는 데 그친다. 하지만 High P-code로 올라오면 High Variable이라는 개념이 추가된다.&lt;/li&gt;
&lt;li&gt;High Variable은 SSA 변환 이후 여러 SSA 버전을 하나의 논리적 변수로 묶은 것.&lt;br /&gt;예를 들어, 동일한 변수 x가 코드 흐름에서 세번 재정의되면 SSA에서는 x#0, x#1, x#2로 분리되는데, 이 세 개가 모두 같은 High Variable에 속한다.&lt;br /&gt;Varnode&amp;nbsp;(x#0)&amp;nbsp;&amp;nbsp;─┐ &lt;br /&gt;Varnode&amp;nbsp;(x#1)&amp;nbsp;&amp;nbsp;─┼─&amp;rarr;&amp;nbsp;HighVariable&amp;nbsp;&quot;x&quot;&amp;nbsp;&amp;nbsp;(이름,&amp;nbsp;타입,&amp;nbsp;심볼&amp;nbsp;종류&amp;nbsp;보유) &lt;br /&gt;Varnode&amp;nbsp;(x#2)&amp;nbsp;&amp;nbsp;─┘&lt;br /&gt;(Ghidra 디컴파일러가 &quot;이 두 SSA 버전은 결국 같은 논리적 변수다&quot;라고 판단)&lt;/li&gt;
&lt;li&gt;SSA는 분석을 위해 변수를 쪼개고, HighVariable은 사람이 이해할 수 있도록 다시 합쳐주는 역할&lt;/li&gt;
&lt;li&gt;API로는 varnode.getHigh()로 HighVariable에 접근하고, highVar.getInstances()를 호출하면 해당 HighVariable에 속한 &lt;b&gt;모든 SSA 버전 Varnode 목록&lt;/b&gt;(x#0, x#1, x#2)이 반환.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Taint 분석에서 변수의 모든 사용 지점을 빠짐없이 추적할 때 이 메서드 사용.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-31 193153.png&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/30TeM/dJMcagFKvvS/ZSB2YRVXM8CRYTkbJa1jNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/30TeM/dJMcagFKvvS/ZSB2YRVXM8CRYTkbJa1jNk/img.png&quot; data-alt=&quot;[참조] SSA&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/30TeM/dJMcagFKvvS/ZSB2YRVXM8CRYTkbJa1jNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F30TeM%2FdJMcagFKvvS%2FZSB2YRVXM8CRYTkbJa1jNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;771&quot; height=&quot;336&quot; data-filename=&quot;스크린샷 2026-05-31 193153.png&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[참조] SSA&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;심볼 분류와 분석 소스 판정&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;High Variable은 getSymbol() 메서드로 심볼 종류를 구분할 수 있음. 취약점 분석에서 이 분류가 중요한 이유는 Taint의 시작점(Taint source)을 정의할 수 있는 기준이 되기 때문.&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 98.7213%; height: 261px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 18.2564%; height: 24px;&quot;&gt;종류&lt;/td&gt;
&lt;td style=&quot;width: 46.6992%; height: 24px;&quot;&gt;의미&lt;/td&gt;
&lt;td style=&quot;width: 35.0443%; height: 24px;&quot;&gt;Taint 관련성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 18.2564%; height: 24px;&quot;&gt;HighParam&lt;/td&gt;
&lt;td style=&quot;width: 46.6992%; height: 24px;&quot;&gt;함수 선언부의 인자. int func(int a, char* buf)에서 a와 buf&lt;/td&gt;
&lt;td style=&quot;width: 35.0443%; height: 24px;&quot;&gt;Taint source - 외부 입력 진입점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 18.2564%; height: 24px;&quot;&gt;HighLocal&lt;/td&gt;
&lt;td style=&quot;width: 46.6992%; height: 24px;&quot;&gt;함수 내부에서 선언된 지역 변수. char buf[64] 같은 것&lt;/td&gt;
&lt;td style=&quot;width: 35.0443%; height: 24px;&quot;&gt;버퍼 위치 추적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 18.2564%; height: 24px;&quot;&gt;HighGlobal&lt;/td&gt;
&lt;td style=&quot;width: 46.6992%; height: 24px;&quot;&gt;함수 밖에 선언된 전역/정적 변수&lt;/td&gt;
&lt;td style=&quot;width: 35.0443%; height: 24px;&quot;&gt;외부 상태 추적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 24px;&quot;&gt;
&lt;td style=&quot;width: 18.2564%; height: 24px;&quot;&gt;HighOther&lt;/td&gt;
&lt;td style=&quot;width: 46.6992%; height: 24px;&quot;&gt;디컴파일러가 내부적으로 만들어낸 임시 변수. 소스 코드에 대응하는 변수가 없음&lt;/td&gt;
&lt;td style=&quot;width: 35.0443%; height: 24px;&quot;&gt;대부분 무시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;Taint source 판정 규칙
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HighParam &amp;rarr; 즉시 Taint source (함수 인자는 &lt;b&gt;외부 호출자가 넘겨준 값&lt;/b&gt;이라 신뢰할 수 없기 때문)&lt;/li&gt;
&lt;li&gt;getDef()를 역추적했을 때 read() / recv() / fgets() 같은 외부 입력 함수의 CALL output Varnode에 닿으면 &amp;rarr; Taint&amp;nbsp; source
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 규칙은 &lt;b&gt;함수 인자가 아닌 로컬 변수&lt;/b&gt;가 외부 입력을 받는 경우를 잡기 위한 것&lt;/li&gt;
&lt;li&gt;ex.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;void&amp;nbsp;func()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char buf[64];&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // HighLocal &amp;mdash; 인자가 아님 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;recv(sock, buf, 64, 0);&amp;nbsp; // 여기서 buf에 외부 데이터가 들어옴 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;strcpy(dst, buf);&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // buf가 tainted인지 알아야 함 &lt;br /&gt;}&lt;/li&gt;
&lt;li&gt;위와 같은 코드의 경우 buf가 HighParam이 아니기 때문에 규칙 1에서 잡히지 않음. 그래서 getDef()를 따라 역추적.&lt;/li&gt;
&lt;li&gt;strcpy가 위험한 이유 : strcpy(dst, src)는 src 문자열을 dst 버퍼에 복사하는데, &lt;b&gt;src의 길이를 전혀 확인하지 않음 &amp;rarr; &lt;/b&gt;공격자가 64바이트보다 긴 데이터를 보내면&amp;nbsp;&lt;b&gt;Buffer Overflow&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java코드로는 아래와 같이 판정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1780224353858&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HighVariable hv = varnodeAST.getHigh();
if (hv != null &amp;amp;&amp;amp; hv.getSymbol() != null) {
    String kind = hv.getSymbol().getClass().getSimpleName();
    if (kind.equals(&quot;HighParam&quot;)) {
        // Taint source로 등록
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Def-Use 체인 슬라이싱&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SSA의 핵심 장점은 각 변수가 딱 한 번만 정의된다는 것. 이 덕분에 어떤 Varnode든 그것을 만든 op와 그것을 사용하는 op를 바로 추적할 수 있음.&lt;/li&gt;
&lt;li&gt;역방향 슬라이싱 - getDef()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Varnode를 만든 op를 거슬러 올라갑니다. Taint가 어디서 시작됐는지 출처를 사용할 때 사용.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;strcpy의 src 인자 &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;larr; INT_ADD (버퍼 + 오프셋) &lt;br /&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;larr; LOAD (메모리에서 읽기)&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;larr; CALL recv() &amp;larr; [SOURCE] 외부 입력&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;순방향 슬라이싱 - getDescendant()&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Varnode가 이후 어디서 사용되는지 흐름을 따라감. Taint가 어디까지 전파되는지, 어떤 sink에 도달하는지 추적할 때 사용.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1780224631841&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 역방향
PcodeOp defOp = varnodeAST.getDef();

// 순방향
Iterator&amp;lt;PcodeOp&amp;gt; uses = varnodeAST.getDescendants();
while (uses.hasNext()) {
    PcodeOp use = uses.next();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MULTIEQUAL 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조건 분기가 있으면 합류점에서 MULTIEQUAL op가 생김. Taint 분석에서 이 노드를 처리하지 않으면 false negative가 발생하게 됨.&lt;/li&gt;
&lt;li&gt;따라서 MULTIEQUAL을 처리하는 방법은 MULTIEQUAL의 입력 중 하나라도 tainted이면 출력도 tainted.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1780225694247&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (op.getMnemonic().equals(&quot;MULTIEQUAL&quot;)) {
    for (Varnode inp : op.getInputs()) {
        if (tainted.contains(inp)) {
            tainted.add(op.getOutput()); // 전파
        }
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/15</guid>
      <comments>https://manguu.tistory.com/15#entry15comment</comments>
      <pubDate>Sun, 31 May 2026 20:21:22 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 13주차 - P-code Phase1</title>
      <link>https://manguu.tistory.com/14</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;01 어셈블리 기초&lt;/h3&gt;
&lt;div style=&quot;color: #9c9a92; text-align: start;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;핵심 레지스터 (x86-64)&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RAX&lt;/b&gt; &lt;br /&gt;64-bit&amp;nbsp;accumulator &lt;br /&gt;함수&amp;nbsp;반환값,&amp;nbsp;산술&amp;nbsp;연산 &lt;br /&gt;&lt;br /&gt;&lt;b&gt;RBP&lt;/b&gt; &lt;br /&gt;base&amp;nbsp;pointer &lt;br /&gt;스택&amp;nbsp;프레임&amp;nbsp;기준점 &lt;br /&gt;&lt;br /&gt;&lt;b&gt;RSP&lt;/b&gt; &lt;br /&gt;stack&amp;nbsp;pointer &lt;br /&gt;현재&amp;nbsp;스택&amp;nbsp;탑&amp;nbsp;위치 &lt;br /&gt;&lt;br /&gt;&lt;b&gt;RIP&lt;/b&gt; &lt;br /&gt;instruction&amp;nbsp;pointer &lt;br /&gt;다음&amp;nbsp;실행할&amp;nbsp;명령어&amp;nbsp;주소 &lt;br /&gt;&lt;br /&gt;&lt;b&gt;RDI/RSI&lt;/b&gt; &lt;br /&gt;1st&amp;nbsp;/&amp;nbsp;2nd&amp;nbsp;argument &lt;br /&gt;함수&amp;nbsp;인자&amp;nbsp;(Linux&amp;nbsp;x64) &lt;br /&gt;&lt;br /&gt;&lt;b&gt;RDX/RCX&lt;/b&gt; &lt;br /&gt;3rd&amp;nbsp;/&amp;nbsp;4th&amp;nbsp;argument &lt;br /&gt;함수&amp;nbsp;인자&amp;nbsp;(Linux&amp;nbsp;x64)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;어셈블리 읽기 &amp;mdash; 실제 예제&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;아래는&lt;span&gt;&amp;nbsp;&lt;/span&gt;int add(int a, int b) { return a + b; }&lt;span&gt;&amp;nbsp;&lt;/span&gt;의 컴파일 결과입니다&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0x1129&amp;nbsp; &amp;nbsp;push&amp;nbsp; rbp&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;&amp;nbsp;호출자&amp;nbsp;RBP&amp;nbsp;저장 &lt;br /&gt;0x112a&amp;nbsp; &amp;nbsp;mov&amp;nbsp; &amp;nbsp;rbp, rsp&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;&amp;nbsp;새&amp;nbsp;스택&amp;nbsp;프레임&amp;nbsp;설정 &lt;br /&gt;0x112d&amp;nbsp; &amp;nbsp;mov&amp;nbsp; &amp;nbsp;[rbp-0x4], edi&amp;nbsp; &amp;nbsp; &amp;nbsp; ; 인자 a 저장 &lt;br /&gt;0x1130&amp;nbsp; &amp;nbsp;mov&amp;nbsp; &amp;nbsp;[rbp-0x8], esi&amp;nbsp; &amp;nbsp; &amp;nbsp; ; 인자 b 저장 &lt;br /&gt;0x1133&amp;nbsp; &amp;nbsp;mov&amp;nbsp; &amp;nbsp;eax, [rbp-0x4]&amp;nbsp; &amp;nbsp; &amp;nbsp;; a &amp;rarr; EAX &lt;br /&gt;0x1136&amp;nbsp; &amp;nbsp;add&amp;nbsp; &amp;nbsp; eax, [rbp-0x8]&amp;nbsp; &amp;nbsp; &amp;nbsp;;&amp;nbsp;EAX&amp;nbsp;=&amp;nbsp;a&amp;nbsp;+&amp;nbsp;b &lt;br /&gt;0x1139&amp;nbsp; &amp;nbsp;pop&amp;nbsp; &amp;nbsp; rbp&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;&amp;nbsp;프레임&amp;nbsp;해제 &lt;br /&gt;0x113a&amp;nbsp; &amp;nbsp;ret&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;&amp;nbsp;EAX에&amp;nbsp;결과&amp;nbsp;담아&amp;nbsp;반환&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #666666; text-align: start;&quot;&gt; 스택 프레임 구조 &lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba4BLc/dJMcahYJKgK/U3BvO2Y5Akhu7ky08CasxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba4BLc/dJMcahYJKgK/U3BvO2Y5Akhu7ky08CasxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba4BLc/dJMcahYJKgK/U3BvO2Y5Akhu7ky08CasxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba4BLc%2FdJMcahYJKgK%2FU3BvO2Y5Akhu7ky08CasxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;332&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;02 Ghidra&amp;nbsp; 도구&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;핵심&amp;nbsp;뷰&amp;nbsp;&amp;amp;&amp;nbsp;도구&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CodeBrowser &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인&amp;nbsp;분석&amp;nbsp;뷰.&amp;nbsp;어셈블리&amp;nbsp;&amp;harr;&amp;nbsp;P-code&amp;nbsp;전환,&amp;nbsp;심볼&amp;nbsp;레이블링,&amp;nbsp;참조&amp;nbsp;추적.&amp;nbsp;오른쪽&amp;nbsp;클릭&amp;nbsp;&amp;rarr;&amp;nbsp;&quot;Show&amp;nbsp;Pcode&quot;로&amp;nbsp;Raw&amp;nbsp;P-code&amp;nbsp;확인&amp;nbsp;가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Decompiler &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어셈블리&amp;nbsp;&amp;rarr;&amp;nbsp;C&amp;nbsp;유사&amp;nbsp;코드로&amp;nbsp;변환.&amp;nbsp;내부적으로&amp;nbsp;High&amp;nbsp;P-code를&amp;nbsp;사용.&amp;nbsp;변수&amp;nbsp;이름&amp;nbsp;재지정,&amp;nbsp;타입&amp;nbsp;선언&amp;nbsp;적용&amp;nbsp;가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Script&amp;nbsp;Manager &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java&amp;nbsp;/&amp;nbsp;Python(Jython)&amp;nbsp;스크립트&amp;nbsp;실행&amp;nbsp;환경.&amp;nbsp;P-code&amp;nbsp;자동&amp;nbsp;분석기&amp;nbsp;개발의&amp;nbsp;시작점.&amp;nbsp;GhidraScript&amp;nbsp;API&amp;nbsp;전체&amp;nbsp;사용&amp;nbsp;가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Function&amp;nbsp;Graph &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어&amp;nbsp;흐름&amp;nbsp;그래프(CFG)&amp;nbsp;시각화.&amp;nbsp;기본&amp;nbsp;블록&amp;nbsp;단위로&amp;nbsp;구조&amp;nbsp;파악.&amp;nbsp;P-code&amp;nbsp;분석의&amp;nbsp;CFG&amp;nbsp;개념을&amp;nbsp;시각적으로&amp;nbsp;확인.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Symbol&amp;nbsp;Tree &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수,&amp;nbsp;심볼,&amp;nbsp;레이블&amp;nbsp;전체&amp;nbsp;목록.&amp;nbsp;분석&amp;nbsp;대상&amp;nbsp;함수를&amp;nbsp;빠르게&amp;nbsp;찾고&amp;nbsp;Import/Export&amp;nbsp;구조&amp;nbsp;파악.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Auto&amp;nbsp;Analysis &lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바이너리&amp;nbsp;최초&amp;nbsp;임포트&amp;nbsp;시&amp;nbsp;실행.&amp;nbsp;Disassembly,&amp;nbsp;Function&amp;nbsp;Discovery,&amp;nbsp;Reference&amp;nbsp;Analysis&amp;nbsp;등&amp;nbsp;파이프라인&amp;nbsp;자동&amp;nbsp;수행.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;P-code 보는 방법 &amp;mdash; 12.0 이 버전 기준&lt;/span&gt;&lt;br /&gt;1.&amp;nbsp;함수&amp;nbsp;열기 &lt;br /&gt;Symbol&amp;nbsp;Tree에서&amp;nbsp;함수&amp;nbsp;더블클릭&amp;nbsp;&amp;rarr;&amp;nbsp;CodeBrowser에&amp;nbsp;어셈블리&amp;nbsp;표시 &lt;br /&gt;⇩&lt;br /&gt;2. Low P-code&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1단계&lt;/b&gt; &amp;mdash; Tool Options에서 먼저 활성화:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;Edit &amp;rarr; Tool Options &amp;rarr; Listing Fields &amp;rarr; Pcode Field &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;rarr; &quot;Display Raw Pcode&quot; 체크 ON&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;b&gt;2단계&lt;/b&gt; &amp;mdash; Listing 뷰 우상단 &lt;b data-index-in-node=&quot;26&quot; data-path-to-node=&quot;5,1,0&quot;&gt;&quot;Edit the Listing Fields&quot;&lt;/b&gt;&lt;b&gt;&amp;nbsp;아이콘&lt;/b&gt; 클릭: &lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;span&gt;&lt;span&gt;Listing 뷰 오른쪽 상단에 있는 &amp;equiv; 같은 아이콘 클릭 &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;rarr; &lt;/span&gt;&lt;span&gt;PCode 항목 찾아서 우클릭 &amp;rarr; &quot;Enable Field&quot; 클릭하여 활성&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt; 활성화가 완료되면 각 어셈블리 명령어 아래에 매핑된 Low P-code가 실시간으로 표시&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wb3Zv/dJMcacwol2B/KbisSYmWfab7edSEmADH81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wb3Zv/dJMcacwol2B/KbisSYmWfab7edSEmADH81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wb3Zv/dJMcacwol2B/KbisSYmWfab7edSEmADH81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwb3Zv%2FdJMcacwol2B%2FKbisSYmWfab7edSEmADH81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;840&quot; height=&quot;158&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⇩&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. High P-code&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ghidra 12.0은 GUI가 없어서 따로 설정이 필요하다는데, 다양한 방법 공유 부탁드립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;03 컴파일러 &amp;amp;&amp;nbsp; IR&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;왜 IR이 필요한가?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baWDen/dJMcabEeef9/yDkfLkblQ99qalKjHAN1zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baWDen/dJMcabEeef9/yDkfLkblQ99qalKjHAN1zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baWDen/dJMcabEeef9/yDkfLkblQ99qalKjHAN1zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaWDen%2FdJMcabEeef9%2FyDkfLkblQ99qalKjHAN1zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1584&quot; height=&quot;394&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;IR(중간 표현, Intermediate Representation) 을 사용하면 분석 알고리즘을 한 번만 구현해도 수십 개의 아키텍처에 적용할 수 있음. P-code가 바로 Ghidra의 IR이며, x86 명령어든 ARM 명령어든 모두 P-code로 변환된 뒤 분석.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;SSA Form (단일 정적 대입)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;P-code의 High 레이어는 SSA form을 사용. 각 변수는 정확히 한 번만 정의되므로, 데이터 흐름을 추적하기 훨씬 쉬워짐.&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZpkYe/dJMcabRIyuO/yqls0ZXsDxNG56NhX46D81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZpkYe/dJMcabRIyuO/yqls0ZXsDxNG56NhX46D81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZpkYe/dJMcabRIyuO/yqls0ZXsDxNG56NhX46D81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZpkYe%2FdJMcabRIyuO%2Fyqls0ZXsDxNG56NhX46D81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1602&quot; height=&quot;468&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;Basic Block &amp;amp; CFG&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;Basic Block은 연속된 명령어의 묶음으로, 중간에 분기가 없음. CFG(Control Flow Graph)는 이 블록들 사이의 분기 관계를 그래프로 표현. P-code 분석기는 CFG를 순회하며 각 블록의 P-code를 처리.&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;어셈블리 &amp;rarr; P-code 변환 예시&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #000000; text-align: start;&quot;&gt;같은 동작을 어셈블리와 P-code로 비교&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be1dtS/dJMcaii2M0D/e2vPVqVYg6HdeAR0Or2wmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be1dtS/dJMcaii2M0D/e2vPVqVYg6HdeAR0Or2wmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be1dtS/dJMcaii2M0D/e2vPVqVYg6HdeAR0Or2wmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe1dtS%2FdJMcaii2M0D%2Fe2vPVqVYg6HdeAR0Or2wmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1710&quot; height=&quot;816&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;816&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/14</guid>
      <comments>https://manguu.tistory.com/14#entry14comment</comments>
      <pubDate>Tue, 12 May 2026 18:56:37 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 12주차 - P-code 이론</title>
      <link>https://manguu.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 진행하던 프로젝트의 전반적인 개발은 일단락 되었고, 앞으로 진행할 방향에 대해 고민하는 시간과 함께 스크립트 발전에 대해 목마른 팀원분들과 함께 P-code를 공부해보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P-code 공부는 AI를 활용하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주는 P-code에 대해 개념 공부를 하기 보단 커리큘럼을 먼저 설계해보기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 내가 주로 쓰는 세 가지 정도의 AI 툴로 테스트 해보았고, 모두 동일한 프롬프트를 사용하였다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Claude Sonnet 4.6 (무료)&lt;/li&gt;
&lt;li&gt;Gemini Pro (유료)&lt;/li&gt;
&lt;li&gt;Chat GPT (무료)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P-code에 대해 잘 모르는 사람 입장에서 위 세 가지 툴 모두 시키는거 많고 해야할 거 많고 체계적으로 짜준 것 같긴 하다만 Claude가 로드맵 형식으로 구체적이면서 시각적으로 한눈에 들어오게 만들어준 것 같아서 이걸 사용해 보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 세 가지가 사람마다 취향이 갈려서 자신이 편하게 느껴지는 툴을 사용하면 좋을 것 같긴 하지만, 출처나 관련 자료 링크를 쉽게 볼 수 있는 툴(ex. Perplexity)과 1, 2, 3번 중 한가지를 동시에 쓰면 더 수월하고 전문성 있게 공부할 수 있겠다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Cluade를 사용한 자료이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 커리큘럼 로드맵&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;1706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekr8uu/dJMcagMf39g/5IoqBrRuTRKJs0YA0Tw2IK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekr8uu/dJMcagMf39g/5IoqBrRuTRKJs0YA0Tw2IK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekr8uu/dJMcagMf39g/5IoqBrRuTRKJs0YA0Tw2IK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fekr8uu%2FdJMcagMf39g%2F5IoqBrRuTRKJs0YA0Tw2IK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;742&quot; height=&quot;1706&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;1706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Phase 1 &amp;mdash; 기반 지식 구축 (2~3주)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;P-code는 결국 어셈블리를 추상화한 IR이기 때문에, x86/x64 어셈블리를 읽을 수 있어야 함. 동시에 SSA form, 기본 블록, CFG 같은 컴파일러 이론 개념도 먼저 익혀두는 게 Phase 2 진입을 훨씬 수월하게 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Phase 2 &amp;mdash; P-code 핵심 이해 (3~4주)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커리큘럼의 핵심 단계. Varnode(P-code의 변수 단위), PcodeOp(연산 단위), SLEIGH 명세 언어의 삼각 관계를 이해해야 함. Ghidra는 Raw P-code(어셈블리 1:1 변환)와 High P-code(디컴파일러 내부 최적화 표현) 두 레이어를 제공하는데, 취약점 분석은 주로 High P-code에서 작업함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Phase 3 &amp;mdash; 프로그램 분석 기법 (4~5주)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Taint analysis가 핵심. 사용자 입력(source) &amp;rarr; 위험한 함수(sink)까지의 데이터 흐름을 P-code Def-Use 체인을 따라 추적하는 것이 취약점 분석기의 기본 원리.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Phase 4 &amp;mdash; 취약점 분석 패턴 (4~5주)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Buffer overflow는 LOAD/STORE op의 오프셋 범위 검증, UAF는 COPY op 이후 STORE 추적, 포맷 스트링은 CALL op의 인자 Varnode를 역방향 슬라이싱하는 식으로 각 취약점 유형마다 P-code 레벨의 패턴이 있음. 실제 CVE 바이너리로 직접 연습하는 것을 강력히 권장.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Phase 5 &amp;mdash; 분석기 개발 (4~6주)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ghidra의 AbstractAnalyzer를 상속해서 플러그인을 만들고, 필요하다면 PcodeEmulator나 AngR 같은 심볼릭 실행 엔진과 연동. Ponce(Ghidra용 taint 분석기)나 Kaiju 같은 오픈소스 플러그인 코드를 참고하면 구조 파악에 큰 도움이 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 커리큘럼에서 전부를 하는 것은 아니고, 필요한 부분만 골라서 진행하면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/13</guid>
      <comments>https://manguu.tistory.com/13#entry13comment</comments>
      <pubDate>Mon, 4 May 2026 20:16:50 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 11주차 - Ghidra Script 수정 및 검증</title>
      <link>https://manguu.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[검증 전 확인 및 로직 보강]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검증을 하다보니 이런식으로 드라이버 별 구분이 아니라 프로토콜 별 구분으로 되어서 json 출력 로직을 수정하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;812&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjlZ8S/dJMcac3DMaP/HCSUnL5k22yu9qOeMaabl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjlZ8S/dJMcac3DMaP/HCSUnL5k22yu9qOeMaabl1/img.png&quot; data-alt=&quot;수정 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjlZ8S/dJMcac3DMaP/HCSUnL5k22yu9qOeMaabl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjlZ8S%2FdJMcac3DMaP%2FHCSUnL5k22yu9qOeMaabl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;477&quot; height=&quot;247&quot; data-origin-width=&quot;1570&quot; data-origin-height=&quot;812&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;수정 전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 드라이버 이름 기반으로 먼저 탐지하고 knownProtocolProvider() 함수에 있는 switch-case를 그 다음으로 보는 방법으로 했었는데, 그 두개의 순서를 바꾸어 자기 자신에 대한 프로토콜 제공자를 매칭하는 오탐을 수정하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bug를 사용할지 Defect를 사용할지 고민했었는데, Defect로 결정하게 되어 이것도 수정하였다. (블로그 작성 이후에 수정함)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cIcKAY/dJMcacvUmAq/IzyBWyoKkeubcqPUMJtxv0/DepexHunter_v3_1_0.java?attach=1&amp;amp;knm=tfile.java&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;DepexHunter_v3_1_0.java&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.04MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[실행이 안 될 경우 BDS(Boot Device Selection) 페이즈로 넘어가지 못하는 드라이버]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;CpuDxe&lt;/b&gt; (1A1E4886-9517-440E-9FDE-3BE44CEE2136)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU 초기화 및 인터럽트 처리를 담당하는 CPU 아키텍처 프로토콜을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;Timer&lt;/b&gt; (C190FE35-44AA-41A1-8AEA-4947BC60E09D)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 기본 타이머 아키텍처를 제공합니다. 스케줄링 및 딜레이 처리에 필수적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;RuntimeDxe&lt;/b&gt; (B601F8C4-43B7-4784-95B1-F4226CB40CEE)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OS로 진입한 후에도 유지되어야 하는 런타임 서비스 아키텍처 프로토콜을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,3,0&quot;&gt;SecurityStubDxe&lt;/b&gt; (F80697E9-7FD6-4665-8646-88E33EF71DFC)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,3,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보안(Security) 아키텍처 프로토콜을 제공합니다. 이미지 검증 등의 기반이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,4,0&quot;&gt;VariableSmmRuntimeDxe&lt;/b&gt; (9F7DCADE-11EA-448A-A46F-76E003657DD1)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,4,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UEFI 환경 변수(Variable) 읽기/쓰기를 위한 아키텍처 프로토콜입니다. 부팅 순서 등 핵심 정보 접근에 필요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,5,0&quot;&gt;ResetSystemRuntimeDxe&lt;/b&gt; (4B28E4C7-FF36-4E10-93CF-A82159E777C5)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,5,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템 재부팅 및 종료를 담당하는 Reset 아키텍처 프로토콜을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,6,0&quot;&gt;MonotonicCounterRuntimeDxe&lt;/b&gt; (AD608272-D07F-4964-801E-7BD3B7888652)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,6,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단조 증가 카운터 아키텍처를 제공하며, 보안 및 식별 작업에 필수적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,7,0&quot;&gt;WatchdogTimer&lt;/b&gt; (F099D67F-71AE-4C36-B2A3-DCEB0EB2B7D8)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,7,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부팅 중 무한 루프에 빠지는 것을 방지하는 워치독 타이머 아키텍처입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,8,0&quot;&gt;Metronome&lt;/b&gt; (C8339973-A563-4561-B858-D8476F9DEFC4)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,8,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매우 짧은 딜레이를 측정하는 Metronome 아키텍처 프로토콜입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,9,0&quot;&gt;BdsDxe&lt;/b&gt; (6D33944A-EC75-4855-A54D-809C75241F6C)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,9,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DXE 페이즈의 최종 목적지로, 이 드라이버가 실행되어야 비로소 부팅 가능한 디바이스를 찾고 OS 로더를 실행하는 BDS 페이즈가 시작됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PcRtc&amp;nbsp;&lt;/b&gt;(378D7B65-8DA9-4773-B6E4-A47826A833E1)&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;b&gt;RealTimeClockRuntimeDxe&lt;/b&gt; (B336F62D-4135-4A55-AE4E-4971BBF0885D)&lt;/s&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UEFI&amp;nbsp;PI(Platform&amp;nbsp;Initialization)&amp;nbsp;스펙에서&amp;nbsp;명시한&amp;nbsp;핵심&amp;nbsp;아키텍처&amp;nbsp;프로토콜(Architectural&amp;nbsp;Protocols)&amp;nbsp;중&amp;nbsp;하나인&amp;nbsp;Real&amp;nbsp;Time&amp;nbsp;Clock&amp;nbsp;(RTC)&amp;nbsp;아키텍처&amp;nbsp;프로토콜을&amp;nbsp;시스템에&amp;nbsp;제공합니다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL이 설치 되어야 부팅이 가능&lt;/li&gt;
&lt;li&gt;QEMU환경 (x86 하드웨어, ARM 등 다른 환경에서는 다름)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PcRtc만 있으면 프로토콜이 설치 가능하지만&lt;/li&gt;
&lt;li&gt;RealTimeClockRuntimeDxe만 있으면 하드웨어를 못읽어서 제대로 동작을 안함. 즉, PcRtc만 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;ReportStatusCodeRouterRuntimeDxe&lt;/b&gt; (D93CE3D8-A7EB-4730-8C8E-CC466A9ECC3C)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의&amp;nbsp;상태와&amp;nbsp;에러&amp;nbsp;로깅을&amp;nbsp;담당하는&amp;nbsp;상태&amp;nbsp;코드(Status&amp;nbsp;Code)&amp;nbsp;아키텍처&amp;nbsp;프로토콜&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 12개의 드라이버를 앞으로는 &lt;b&gt;'부팅실패드라이버모음'&lt;/b&gt;이라고 부르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[Edk2 v21.02 Depex에서 요구되는 드라이버 및 프로토콜]&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;586&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;275&quot; height=&quot;24&quot;&gt;드라이버&lt;/td&gt;
&lt;td width=&quot;311&quot;&gt;프로토콜&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;AcpiTableDxe&lt;/td&gt;
&lt;td&gt;EfiAcpiTableProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;BdsDxe&lt;/td&gt;
&lt;td&gt;EfiBdsArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;48&quot;&gt;CpuDxe&lt;/td&gt;
&lt;td&gt;EfiCpuArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiMpServiceProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;CpuIo2Dxe&lt;/td&gt;
&lt;td&gt;EfiCpuIo2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;DevicePathDxe&lt;/td&gt;
&lt;td&gt;EfiDevicePathUtilitiesProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;4&quot; height=&quot;96&quot;&gt;HiiDatabase&lt;/td&gt;
&lt;td&gt;EfiHiiConfigRoutingProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiHiiDatabaseProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiHiiImageExProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiHiiStringProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;48&quot;&gt;IoMmuDxe&lt;/td&gt;
&lt;td&gt;EdkiiIoMmuProtocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;IoMmuAbsentProtocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;Legacy5259&lt;/td&gt;
&lt;td&gt;EfiLegacy8259ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;Metronome&lt;/td&gt;
&lt;td&gt;EfiMetronomeArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;MonotonicCounterRuntimeDxe&lt;/td&gt;
&lt;td&gt;EfiMonotonicCounterArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;PcdDxe&lt;/td&gt;
&lt;td&gt;EfiPcdProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;PcRtc&lt;/td&gt;
&lt;td&gt;EfiRealTimeClockArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;PiSmmIpl&lt;/td&gt;
&lt;td&gt;EfiMmCommunication2Protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;ReportStatusCodeRouterRuntimeDxe&lt;/td&gt;
&lt;td&gt;EfiRscHandlerProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;ResetSystemRuntimeDxe&lt;/td&gt;
&lt;td&gt;EfiResetArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;RuntimeDxe&lt;/td&gt;
&lt;td&gt;EfiRuntimeArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SecurityStubDxe&lt;/td&gt;
&lt;td&gt;EfiSecurityArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;48&quot;&gt;SetupBrowser&lt;/td&gt;
&lt;td&gt;EdkiiFormBrowserEx2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiFormBrowser2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmbiosDxe&lt;/td&gt;
&lt;td&gt;EfiSmbiosProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmmAccess2Dxe&lt;/td&gt;
&lt;td&gt;EfiSmmAccess2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmmControl2Dxe&lt;/td&gt;
&lt;td&gt;EfiSmmControl2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmmLockBox&lt;/td&gt;
&lt;td&gt;EfiLockBoxProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;Timer&lt;/td&gt;
&lt;td&gt;EfiTimerArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;48&quot;&gt;VariableSmmRuntimeDxe&lt;/td&gt;
&lt;td&gt;EfiVariableArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiVariableWriteArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;WatchdogTimer&lt;/td&gt;
&lt;td&gt;EfiWatchdogTimerArchProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 표 중에서 &lt;b&gt;부팅실패드라이버모음&lt;/b&gt;을&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;제외하면 아래와 같은 표가 완성된다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;567&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;256&quot; height=&quot;24&quot;&gt;드라이버&lt;/td&gt;
&lt;td width=&quot;311&quot;&gt;프로토콜&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;AcpiTableDxe&lt;/td&gt;
&lt;td&gt;EfiAcpiTableProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;CpuIo2Dxe&lt;/td&gt;
&lt;td&gt;EfiCpuIo2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;DevicePathDxe&lt;/td&gt;
&lt;td&gt;EfiDevicePathUtilitiesProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;4&quot; height=&quot;96&quot;&gt;HiiDatabase&lt;/td&gt;
&lt;td&gt;EfiHiiConfigRoutingProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiHiiDatabaseProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiHiiImageExProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiHiiStringProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;48&quot;&gt;IoMmuDxe&lt;/td&gt;
&lt;td&gt;EdkiiIoMmuProtocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;IoMmuAbsentProtocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;Legacy5259&lt;/td&gt;
&lt;td&gt;EfiLegacy8259ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;PcdDxe&lt;/td&gt;
&lt;td&gt;EfiPcdProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;PiSmmIpl&lt;/td&gt;
&lt;td&gt;EfiMmCommunication2Protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;48&quot;&gt;SetupBrowser&lt;/td&gt;
&lt;td&gt;EdkiiFormBrowserEx2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;EfiFormBrowser2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmbiosDxe&lt;/td&gt;
&lt;td&gt;EfiSmbiosProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmmAccess2Dxe&lt;/td&gt;
&lt;td&gt;EfiSmmAccess2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmmControl2Dxe&lt;/td&gt;
&lt;td&gt;EfiSmmControl2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;24&quot;&gt;SmmLockBox&lt;/td&gt;
&lt;td&gt;EfiLockBoxProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 13개의 드라이버 중 &lt;b&gt;부팅실패드라이버모음&lt;/b&gt;에서 요구되는 드라이버가 존재하여, 없을 경우 연쇄작용으로 &lt;b&gt;부팅실패드라이버모음&lt;/b&gt;에 있는 드라이버가 실행이 안될 수 있으므로 이 또한 제외할 경우 최종적으로 아래와 같은 표가 완성된다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;537&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;243&quot; height=&quot;23&quot;&gt;드라이버&lt;/td&gt;
&lt;td width=&quot;294&quot;&gt;프로토콜&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;23&quot;&gt;AcpiTableDxe&lt;/td&gt;
&lt;td&gt;EfiAcpiTableProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;23&quot;&gt;CpuIo2Dxe&lt;/td&gt;
&lt;td&gt;EfiCpuIo2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot; height=&quot;46&quot;&gt;SetupBrowser&lt;/td&gt;
&lt;td&gt;EdkiiFormBrowserEx2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;23&quot;&gt;EfiFormBrowser2ProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;23&quot;&gt;SmbiosDxe&lt;/td&gt;
&lt;td&gt;EfiSmbiosProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height=&quot;23&quot;&gt;SmmLockBox&lt;/td&gt;
&lt;td&gt;EfiLockBoxProtocolGuid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 위 표와 같이 총 5개의 드라이버만 남게 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 중 SmmLockBox는 SMM 드라이버이지만, 이 드라이버가 없을 경우 DXE 드라이버가 영향을 받으므로 포함한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;UEFITool을 가지고 일부 드라이버를 삭제한 후 진행하려 하는데, NE 버전은 드라이버 삭제가 불가하고 이전 버전은 FV 내부의 체크섬이 깨질 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 OVMF.fd 파일을 만드는 방법은&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. UEFITool 0.28.0 버전으로 드라이버를 삭제&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. QEMU로 부팅 확인&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 2단계를 거쳐서 진행하려 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재 기대되는 결과는 다음과 같다&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 183px;&quot; border=&quot;1&quot; width=&quot;696&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 23px;&quot;&gt;
&lt;td style=&quot;width: 27.093%; height: 23px;&quot; width=&quot;243&quot; height=&quot;23&quot;&gt;드라이버&lt;/td&gt;
&lt;td style=&quot;width: 35.4651%; height: 23px;&quot; width=&quot;294&quot;&gt;프로토콜&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 23px;&quot; width=&quot;159&quot;&gt;요구한 드라이버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 23px;&quot;&gt;
&lt;td style=&quot;width: 27.093%; height: 23px;&quot; height=&quot;23&quot;&gt;AcpiTableDxe&lt;/td&gt;
&lt;td style=&quot;width: 35.4651%; height: 23px;&quot;&gt;EfiAcpiTableProtocolGuid&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 23px;&quot;&gt;AcpiPlatform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 23px;&quot;&gt;
&lt;td style=&quot;width: 27.093%; height: 23px;&quot; height=&quot;23&quot;&gt;CpuIo2Dxe&lt;/td&gt;
&lt;td style=&quot;width: 35.4651%; height: 23px;&quot;&gt;EfiCpuIo2ProtocolGuid&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 23px;&quot;&gt;PciHostBridgeDxe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 27.093%; height: 68px;&quot; rowspan=&quot;2&quot; height=&quot;46&quot;&gt;SetupBrowser&lt;/td&gt;
&lt;td style=&quot;width: 35.4651%; height: 17px;&quot;&gt;EdkiiFormBrowserEx2ProtocolGuid&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 17px;&quot;&gt;DisplayEngine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 51px;&quot;&gt;
&lt;td style=&quot;width: 35.4651%; height: 51px;&quot; height=&quot;23&quot;&gt;EfiFormBrowser2ProtocolGuid&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 51px;&quot;&gt;SecureBootConfigDxe&lt;br /&gt;RamDiskDxe &lt;br /&gt;DriverHealthManagerDxe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 23px;&quot;&gt;
&lt;td style=&quot;width: 27.093%; height: 23px;&quot; height=&quot;23&quot;&gt;SmbiosDxe&lt;/td&gt;
&lt;td style=&quot;width: 35.4651%; height: 23px;&quot;&gt;EfiSmbiosProtocolGuid&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 23px;&quot;&gt;SmbiosPlatformDxe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 23px;&quot;&gt;
&lt;td style=&quot;width: 27.093%; height: 23px;&quot; height=&quot;23&quot;&gt;SmmLockBox&lt;/td&gt;
&lt;td style=&quot;width: 35.4651%; height: 23px;&quot;&gt;EfiLockBoxProtocolGuid&lt;/td&gt;
&lt;td style=&quot;width: 37.3256%; height: 23px;&quot;&gt;BootScriptExecutorDxe&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;AcpiTableDxe
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;AcpiPlatform 드라이버에서 요구, Bug로 판정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;CpuIo2Dxe
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;PciHostBridgeDxe 드라이버에서 요구, Bug로 판정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;SetupBrowser
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DisplayEngine 드라이버에서 요구, Bug로 판정&lt;/li&gt;
&lt;li&gt;SecureBootConfigDxe 드라이버에서 요구, Vulnerability로 판정&lt;/li&gt;
&lt;li&gt;RamDiskDxe 드라이버에서 요구, Bug로 판정&lt;/li&gt;
&lt;li&gt;DriverHealthManagerDxe 드라이버에서 요구, Bug로 판정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;SmbiosDxe
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SmbiosPlatformDxe 드라이버에서 요구, Bug로 판정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;SmmLockBox
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;BootScriptExecutorDxe 드라이버에서 요구, Vulnerability로 판정&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. UEFITool 0.28.0 버전으로 드라이버를 삭제&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/b2O8tq/dJMcaibLz3k/3UjyzKkTc6Viksbbp17GrK/OVMF_AcpiTableDxe.fd?attach=1&amp;amp;knm=tfile.fd&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;OVMF_AcpiTableDxe.fd&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/8XfFR/dJMcaiivj9V/2M93W15mAk2itd6EIOt75K/OVMF_CpuIo2Dxe.fd?attach=1&amp;amp;knm=tfile.fd&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;OVMF_CpuIo2Dxe.fd&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bHtLF2/dJMcaiivj9U/s3R5Z2KOn4gXYoJJnrWetK/OVMF_SetupBrowser.fd?attach=1&amp;amp;knm=tfile.fd&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;OVMF_SetupBrowser.fd&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/dnqv6d/dJMcabXZPQV/6j3q3YKBYNfoIhuZMpUXS0/OVMF_SmbiosDxe.fd?attach=1&amp;amp;knm=tfile.fd&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;OVMF_SmbiosDxe.fd&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bVeSl6/dJMcabXZPQW/zCqJp6DkBiZvcuWjfsXUC1/OVMF_SmmLockBox.fd?attach=1&amp;amp;knm=tfile.fd&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;OVMF_SmmLockBox.fd&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5가지 드라이버를 각각 삭제한 총 5개의 fd 파일을 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. QEMU로 부팅 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Edk2 v21.02 빌드는 Ubuntu 24.02 LTS 환경에서 아래 블로그를 참고하며 진행하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://manguu.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://manguu.tistory.com/12&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진은 정상적으로 부팅되었을 때 QEMU 화면이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1573&quot; data-origin-height=&quot;1285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xnyBX/dJMcaiphY6P/RdarQJt04upDiYQHKrKxvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xnyBX/dJMcaiphY6P/RdarQJt04upDiYQHKrKxvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xnyBX/dJMcaiphY6P/RdarQJt04upDiYQHKrKxvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxnyBX%2FdJMcaiphY6P%2FRdarQJt04upDiYQHKrKxvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1573&quot; height=&quot;1285&quot; data-origin-width=&quot;1573&quot; data-origin-height=&quot;1285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AcpiTableDxe, SetupBrowser, SmbiosDxe, SmmLockBox 드라이버에 대해서는 부팅이 잘 완료 되었으나, CpuIo2Dxe 드라이버가 없을 경우 부팅이 완료되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유를 찾아보니&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;CpuIo2Dxe가 없으면 &lt;b&gt;PciHostBridgeDxe&lt;/b&gt; 실행이 안되는데, &lt;b&gt;PciBusDxe&lt;/b&gt;가 Depex에는 PciHostBridgeDxe를 요구하지 않아서 로드는 되지만, &lt;b&gt;PCI 열거(enumeration) 시점&lt;/b&gt;에 &lt;b&gt;EfiPciHostBridgeResourceAllocationProtocol&lt;/b&gt;을 찾지 못해 동작에 실패한다. 따라서 CpuIo2Dxe 드라이버가 없을 경우 &lt;b&gt;연쇄 작용&lt;/b&gt;으로 PciBusDxe의 동작이 실패하여 최종적으로 부팅에 실패하게 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하자면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CpuIo2Dxe 없음 &amp;rarr; PciHostBridgeDxe 로드 실패 &amp;rarr; PciBusDxe가 PCI 장치 열거 불가 &amp;rarr; 부팅 불가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 CpuIo2Dxe 드라이버를 제외한 4개의 드라이버에 대해 검증을 하도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;추가로 앞서 소개한 Depex에서 요구되는 모든 드라이버에 대해 존재하지 않을 때 부팅 여부를 확인해본 결과, 위 4가지 드라이버를 제외한 모든 드라이버가 예상했던 대로 부팅이 완료되지 않았다. -&amp;gt; 4개의 드라이버를 검증 대상으로 하는 근거 검증 완료&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;간단히 정리하자면 아래와 같다. 사용할 OVMF.fd 파일도 같이 올린다.&lt;/p&gt;
&lt;pre id=&quot;code_1775454366749&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;현재 펌웨어볼륨 환경 : edk2 v21.02버전
DXE 드라이버 개수 : 101개
DEPEX에서 요구되는 (프로토콜을 설치하는) 드라이버(SMM 드라이버 포함) : 25개
삭제될 경우 부팅이 완료되지 않을 드라이버 (SMM 드라이버 포함) : 20개
-&amp;gt; 없어도 부팅이 완료될 드라이버 5개
   1. AcpiTableDxe
   2. CpuIo2Dxe
   3. SetupBrowser
   4. SmbiosDxe
   5. SmmLockBox&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cd9gkv/dJMcaco7DlF/qZzReCaHbLblebkrsJjqw0/OVMF.fd?attach=1&amp;amp;knm=tfile.fd&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;OVMF.fd&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[검증]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;AcpiTableDxe
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;AcpiPlatform 드라이버에서 요구, Bug로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CFZGw/dJMcacCB4ic/AKkCFWUbGzDk6iujtTAch0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CFZGw/dJMcacCB4ic/AKkCFWUbGzDk6iujtTAch0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CFZGw/dJMcacCB4ic/AKkCFWUbGzDk6iujtTAch0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCFZGw%2FdJMcacCB4ic%2FAKkCFWUbGzDk6iujtTAch0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1340&quot; height=&quot;618&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SetupBrowser
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DisplayEngine 드라이버에서 요구, Bug로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;li&gt;SecureBootConfigDxe 드라이버에서 요구, Vulnerability로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;li&gt;RamDiskDxe 드라이버에서 요구, Bug로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;li&gt;DriverHealthManagerDxe 드라이버에서 요구, Bug로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RqQUw/dJMcaadI2af/ENBWK3oBWLcezk4spsNgM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RqQUw/dJMcaadI2af/ENBWK3oBWLcezk4spsNgM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RqQUw/dJMcaadI2af/ENBWK3oBWLcezk4spsNgM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRqQUw%2FdJMcaadI2af%2FENBWK3oBWLcezk4spsNgM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1466&quot; height=&quot;1202&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SmbiosDxe
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;SmbiosPlatformDxe 드라이버에서 요구, Bug로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crVhT3/dJMcahDSNtt/C4xCmH4kIgMJbsYHNSKGi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crVhT3/dJMcahDSNtt/C4xCmH4kIgMJbsYHNSKGi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crVhT3/dJMcahDSNtt/C4xCmH4kIgMJbsYHNSKGi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrVhT3%2FdJMcahDSNtt%2FC4xCmH4kIgMJbsYHNSKGi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1294&quot; height=&quot;642&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SmmLockBox
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;BootScriptExecutorDxe 드라이버에서 요구, Vulnerability로 판정 =&amp;gt; 정탐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7Ybld/dJMcaiW4DAr/ArmkncKauDxoLY8O0xqhQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7Ybld/dJMcaiW4DAr/ArmkncKauDxoLY8O0xqhQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7Ybld/dJMcaiW4DAr/ArmkncKauDxoLY8O0xqhQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7Ybld%2FdJMcaiW4DAr%2FArmkncKauDxoLY8O0xqhQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1424&quot; height=&quot;622&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검증 결과 4개의 드라이버에 대해 0%의 오탐률을 확인하였다.&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/11</guid>
      <comments>https://manguu.tistory.com/11#entry11comment</comments>
      <pubDate>Thu, 2 Apr 2026 01:45:37 +0900</pubDate>
    </item>
    <item>
      <title>Edk2 빌드 (smm 드라이버 포함)</title>
      <link>https://manguu.tistory.com/12</link>
      <description>&lt;pre class=&quot;html xml&quot; style=&quot;background-color: #36373a; color: #bdc1c6; text-align: start;&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;# 1. 필수 패키지 설치
sudo apt update
sudo apt install build-essential uuid-dev acpica-tools git gcc g++ nasm python3 python3-setuptools

# 2. EDK2 소스코드 다운로드 및 폴더 이동
git clone https://github.com/tianocore/edk2.git
cd edk2

# 3. 안정화 버전 체크아웃 및 서브모듈 업데이트
git checkout edk2-stable202102
git submodule update --init --recursive

# 4. GCC 9 설치 및 기본 컴파일러로 등록 (명령어 분리 완료)
sudo apt update
sudo apt install gcc-9 g++-9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 100

# 5. BaseTools 컴파일 및 환경 변수 초기화
make -C BaseTools
source edksetup.sh

# 6. 펌웨어 빌드 (SMM 및 Secure Boot 포함)
build -a X64 -p OvmfPkg/OvmfPkgX64.dsc -b RELEASE -t GCC5 -D SECURE_BOOT_ENABLE=TRUE -D SMM_REQUIRE=TRUE

# 7. QEMU 실행
qemu-system-x86_64 \
  -machine q35,smm=on \
  -global ICH9-LPC.disable_s3=1 \
  -global driver=cfi.pflash01,property=secure,value=on \
  -m 1024M \
  -drive if=pflash,format=raw,unit=0,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd,readonly=on \
  -drive if=pflash,format=raw,unit=1,file=./test_VARS.fd \
  -vga std
  
  위 코드에서 OVMF.fd 부분에 자신이 조작한 fd 파일 넣어서 부팅도 가능&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/12</guid>
      <comments>https://manguu.tistory.com/12#entry12comment</comments>
      <pubDate>Thu, 2 Apr 2026 00:57:30 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 10주차 - Ghidra Script 수정</title>
      <link>https://manguu.tistory.com/10</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지난주에 Missing Protocol만 가지고 취약점 탐지를 하기로 정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 진행하던 방식인 &quot;기드라 Pcode 분석을 통한&quot; 프로토콜 설치 탐지를 진행했었는데, 정보과학회 논문 작성까지 오탐률 적은 스크립트가 나올 것 같지 않아 급하게 방향을 틀게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주말동안 팀원분들께 미리 말씀은 드려 놓았지만, 교수님의 의견이 중요할 것 같아서 상의가 필요하다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[현재 상황 및 교수님, 팀원분들과 상의하고 싶은 것]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;현재 DXE 드라이버가 설치하는 Protocol 탐지가 제대로 되지 않는 상황
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;UEFI 특유의 간접 호출 (ex. gBS-&amp;gt;InstallProtocolInterface(...))&lt;/li&gt;
&lt;li&gt;GUID 추적이 데이터플로우인 문제 (프로토콜을 찾으려면 InstallProtocolInterface(&amp;amp;Handle, &amp;amp;GUID, ...) 이런걸 해야 하는데 실제로는 GUID가 전역에 있고, 중간에 레지스터를 여러번 거치는 등)&lt;/li&gt;
&lt;li&gt;Protocol Install 자체가 Runtime event이므로 정적 분석만으로는 100% 탐지가 어려움
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Protocol Install은 &amp;ldquo;코드 구조&amp;rdquo;가 아니라 &amp;ldquo;실행 시점의 상태 변화(Runtime behavior)&amp;rdquo;이기 때문에, 바이너리만 보고는 확정할 수 없는 경우가 많다.&lt;/li&gt;
&lt;li&gt;UEFI에서 프로토콜 설치는 보통:&lt;br /&gt;gBS-&amp;gt;InstallProtocolInterface(...)&lt;br /&gt;gBS-&amp;gt;InstallMultipleProtocolInterfaces(...)&lt;br /&gt;를 통해 이루어짐. 이 호출 자체는 단순 API 호출일 뿐. 실제 의미는 'Handle Database 상태 변경'. 즉,&lt;br /&gt;Handle X&lt;br /&gt;&amp;nbsp;└── Protocol GUID 추가됨 (runtime에)&lt;br /&gt;이건 전역 런타임 객체 변화&lt;br /&gt;&lt;br /&gt;정적 분석은 코드 구조만 볼 뿐 실행 후 Handle DB 상태는&amp;nbsp;못&amp;nbsp;본다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;등등의 여러 이유 때문에 어렵다고 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그래서&amp;nbsp;논문에서는&amp;nbsp;지난번에&amp;nbsp;했던&amp;nbsp;것처럼&amp;nbsp;휴리스틱하게&amp;nbsp;하더라도,&amp;nbsp;EDK2를&amp;nbsp;타겟으로&amp;nbsp;잡고&amp;nbsp;EDK2에&amp;nbsp;들어있는&amp;nbsp;모든&amp;nbsp;DXE&amp;nbsp;드라이버가&amp;nbsp;설치하는&amp;nbsp;프로토콜을&amp;nbsp;수기로&amp;nbsp;정리해서&amp;nbsp;집어&amp;nbsp;넣는&amp;nbsp;방식으로&amp;nbsp;해서&amp;nbsp;오탐을&amp;nbsp;줄이는&amp;nbsp;것에&amp;nbsp;대해&amp;nbsp;어떻게&amp;nbsp;생각하는지&amp;nbsp;물어보고&amp;nbsp;싶습니다.&lt;/li&gt;
&lt;li&gt;일광이가 현재 제 스크립트 때문에 헤드리스 스크립트를 갈아 엎은 상태인데, 지금 하던 일이 의미가 없어지는 것이 아니냐 -&amp;gt; 아닙니다. 어차피 확장해야 하고, EDK2 뿐만 아니라 좀 더 general 하게 하려면 이번학기 안에 시도 했어야 할 문제이기 때문에, 의미가 없어지는 것은 아닙니다. 하지만 서두르게 한 점 죄송합니다.&lt;/li&gt;
&lt;li&gt;general 하게 하고싶지만 이건 제가 좀 더 깊게 공부를 해야 하는 상황인 것 같고 현재 논문 마감이 약 3주가량 남았기 때문에 3월 안에는 모든 스크립트에 대한 결과가 나와야 한다고 생각해서 내린 결정입니다. 또한 박사님께서 'general은 좀 위험한 발언인 것 같다' 라고 하셔서 EDK2를 타겟으로 하는 게 어떠신지 묻고싶습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 현재 저의 스크립트의 방향성에 대한 두가지 방법이 존재하는데,&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스크립트 갈아 엎기 전에 사용했던 방식을 EDK2의 모든 드라이버에 대해 적용(휴리스틱)&lt;/li&gt;
&lt;li&gt;현재 로직을 EDK2로 한정해서 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 2번의 방법으로 논문 쓰기 전에 완성할 수 있을지는 미지수임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 그래서 일단 1번 스크립트를 완성시키고 2번을 빠르게 진행해보면서, 3월 안(혹은 4월 첫째주까지)에 완성이 되면 논문으로 작성하는 방식으로 진행해야 할 것 같음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 1번 스크립트는 완성 되어 있는 상황.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[로직]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0. edk2 github에서 소스코드 다운 &amp;amp; UEFIExtract 툴로 덤프 폴더 추출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 파이썬 스크립트(generate_protocol_switch.py) 맨 아래 부분에 위 두 폴더 경로 설정 후 실행 -&amp;gt; JAVA switch-case문 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 생성된 switch-case문을 가지고 자바 스크립트(DepexHunter_v3_0_0)에 넣기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Headless.py 스크립트로 실행&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/yiGL2/dJMcahcMNAO/ZkKdhplOR77v47NkVPihB1/generate_protocol_switch.py?attach=1&amp;amp;knm=tfile.py&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;generate_protocol_switch.py&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bCkm4k/dJMcabp8DPw/QKDS2i17fke1nKU0u5nZ31/DepexHunter_v3_0_0.java?attach=1&amp;amp;knm=tfile.java&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;DepexHunter_v3_0_0.java&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.04MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/c2X1Qb/dJMcadnTAjD/y6veexzhnDu4UZqKWwUQTk/Headless.py?attach=1&amp;amp;knm=tfile.py&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Headless.py&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.07MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Python 파서(generate_protocol_switch.py)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SOMETIME_PRODUCES (오타 포함), SOMETIMES_PRODUCES, PRODUCED 계열 전부 provider로 인정&lt;/li&gt;
&lt;li&gt;# 단일 주석 스타일도 파싱 (# PROTOCOL ALWAYS_PRODUCED)&lt;/li&gt;
&lt;li&gt;Guid 접미사 제거로 GUID DB 이름과 매칭&lt;/li&gt;
&lt;li&gt;dump 폴더 교차검증으로 여러 후보 중 실제 펌웨어에 있는 드라이버 우선 선택&lt;/li&gt;
&lt;li&gt;MODULE_TYPE 필터로 라이브러리 .inf 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774831909645&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.inf 파일의 [Protocols] 섹션 파싱
&amp;darr;
PRODUCES tag만 선택
&amp;darr;
실제 firmware dump driver와 교차검증
&amp;darr;
provider 결정&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;heuristic보단 'knowledge-assisted dependency inference'라고 사용하는 것이 어떨지...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Java 스크립트(DepexHunter_v3_0_0.java)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;allDiscoveredSmmDrivers 분리로 SMM 드라이버(Subtype: SMM module) 별도 수집&lt;/li&gt;
&lt;li&gt;inferAllProviders()에서 DXE + SMM 둘 다 교차검증&lt;/li&gt;
&lt;li&gt;knownProtocolProvider()에 Guid 없는 버전과 있는 버전 둘 다 등록&lt;/li&gt;
&lt;li&gt;systemProtocols 이름을 GUID DB 형식에 맞게 수정&lt;/li&gt;
&lt;li&gt;findDriverNameFromParents()에 Subtype: SMM module 추가&lt;/li&gt;
&lt;li&gt;Vulnerability와 Bug 구분 (보안 드라이버 vs 일반 드라이버)&lt;/li&gt;
&lt;li&gt;Headless 환경 맞춤으로 수정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Headless 스크립트 (Headless.py)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;depex 스크립트 실행 시 필요한 cmd 인자 변경&lt;/li&gt;
&lt;li&gt;normalize_depex_report_records함수에 취약점/버그 구분 로직 추가&lt;/li&gt;
&lt;li&gt;DepexHunter 스크립트 3_0_0으로 버전 수정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/10</guid>
      <comments>https://manguu.tistory.com/10#entry10comment</comments>
      <pubDate>Sun, 29 Mar 2026 22:43:53 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 9주차 - 취약점 선정 및 Ghidra Script 수정</title>
      <link>https://manguu.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저번주에 언급했던 부분 중 &lt;b&gt;취약점 개수&lt;/b&gt;를 줄이는 방향으로 가는 것이 좋을 것 같다는 의견을 주셔서 1개로 줄여보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[선정된 취약점]&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Missing Protocol Vulnerability&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5&quot;&gt;취약점 정의&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;핵심 원인 :&lt;/b&gt; DXE 드라이버의 DEPEX가 요구하는 특정 프로토콜의 GUID를 제공(Install)하는 드라이버가 펌웨어 내에 존재하지 않는 상태.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;상태 정의 :&lt;/b&gt; 해당 드라이버는 실행 준비 단계인 &lt;b data-index-in-node=&quot;26&quot; data-path-to-node=&quot;6,1,0&quot;&gt;Scheduled&lt;/b&gt;로 전이되지 못하고, 무한히 &lt;b data-index-in-node=&quot;51&quot; data-path-to-node=&quot;6,1,0&quot;&gt;Dependent(대기)&lt;/b&gt; 상태에 머물게 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9&quot;&gt;일반 결함(Bug)과의 차별점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;일반 드라이버 :&lt;/b&gt; 주변 장치(마우스, 오디오 등) 작동 불능 &amp;rarr; &lt;b data-index-in-node=&quot;35&quot; data-path-to-node=&quot;10,0,0&quot;&gt;가용성 저하(기능적 결함).&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt;보안 드라이버 :&lt;/b&gt; 인증 및 검증 로직 생략 &amp;rarr; &lt;b data-index-in-node=&quot;25&quot; data-path-to-node=&quot;10,1,0&quot;&gt;기밀성 및 무결성 파괴(보안 취약점).&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7&quot;&gt;취약점 성립 근거 (보안 드라이버 중심)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;8&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,0,0&quot;&gt;보안 체인(Chain of Trust) 단절 :&lt;/b&gt; Secure Boot, TPM 초기화, 암호화 엔진 등 보안 필수 드라이버가 로드되지 않음으로써 전체 시스템 보호막이 형성되지 않음.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,1,0&quot;&gt;Fail-Open 구조 :&lt;/b&gt; 시스템이 보안 검사 실패 시 부팅을 중단(Fail-Safe)하는 것이 아니라, 검사 드라이버 자체의 누락을 무시하고 부팅을 강행(Fail-Open)하기 때문에 취약점이 됨.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,2,0&quot;&gt;권한 상승(Privilege Escalation) :&lt;/b&gt; 보안 드라이버가 부재한 틈을 타 공격자가 커널 권한으로 악성 코드를 실행하거나 보안 설정을 임의로 조작할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;상황 :&lt;/b&gt; SecureBootVerify라는 드라이버가 실행되려면 HashProtocol 필요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제 :&lt;/b&gt; 펌웨어 내에 HashProtocol을 설치해주는 드라이버 누락.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 :&lt;/b&gt; SecureBootVerify는 영원히 실행되지 않고 대기(&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Dependent&lt;/span&gt;) 상태가 됨. DXE Dispatcher는 이 드라이버를 건너뛰고 다음 부팅 단계로 넘어가 버릴 수 있으며, 결국 서명되지 않은 악성 코드가 실행될 수 있는 환경이 조성됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;b&gt;Cycle Vulnerability&lt;/b&gt;&lt;/s&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;s&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;취약점 정의&lt;/b&gt;&lt;/s&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;s&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;핵심 원인 :&lt;/b&gt; 두 개 이상의 DXE 드라이버가 DEPEX(의존성 식별자)를 통해 서로를 참조하거나(A&amp;rarr;B, B&amp;rarr;A), 복잡한 경로를 거쳐 자기 자신에게 돌아오는 순환 구조를 형성하는 상태.&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;상태 정의 :&lt;/b&gt; DXE Dispatcher가 의존성 그래프를 해석할 때 Deadlock에 빠져, 관련 드라이버들이 결코 &lt;b data-index-in-node=&quot;76&quot; data-path-to-node=&quot;5,1,0&quot;&gt;Scheduled&lt;/b&gt; 상태로 전이되지 못함.&lt;/s&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;- Cycle 취약점의 경우 Deadlock이 발생하는 것이 아니라, Cycle을 생성하는 드라이버가 실행되지 않는 문제로, 결국 1번 Missing Protocol 취약점으로 귀결되기 때문에 삭제&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[선정되지 않은 취약점]&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;bypass, dead, alwaystrue, alwaysfalse Vulnerability&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 경우 단순한 정적 분석 수준으로, UEFITool 등을 사용하게 되면 쉽게 눈으로도 직접 찾아낼 수 있기 때문에 이번 우선순위에서는 밀리게 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Before/After Vulnerability&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Missing Protocol의 탐지 로직과 유사하여, 이를 구현하면서 부가적으로 처리될 수 있는 취약점이라고 생각함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Malicious Vulnerability&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 수준은 단순한 '블랙리스트 매칭'이므로, 선정된 취약점을 처리하고 난 다음 단계에서 직접 드라이버를 분석하여 악성 드라이버인지 확인하는 로직을 추가하여 탐지할 예정.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[현재 진행 상태]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Missing Protocol 취약점을 탐지하기 위해 기존에 작성되어 있던 사용하지 않을 취약점 탐지 로직을 전부 삭제하고 두 취약점에 대한 로직은 기존대로 진행하려 하였으나, 기존 로직이 휴리스틱하게 탐지하는 것이 맘에 들지 않아 전부 수정에 들어감.&lt;/li&gt;
&lt;li&gt;Missing protocol의 경우, 각 드라이버가 생성하는 Protocol을 pcode 분석을 통해 알아내고, 그 설치되는 Protocol목록과 DEPEX에 적혀 있는 Protocol을 매칭하며, 리스트에 없는 Protocol이 없을 경우 탐지하는 로직을 생성중.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;1196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjkJo1/dJMcajhezf2/DBM744MhtJqapJzQPykkP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjkJo1/dJMcajhezf2/DBM744MhtJqapJzQPykkP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjkJo1/dJMcajhezf2/DBM744MhtJqapJzQPykkP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjkJo1%2FdJMcajhezf2%2FDBM744MhtJqapJzQPykkP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1438&quot; height=&quot;1196&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;1196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lNZqw/dJMb99MtgBR/XuiWpZgX3aKo8ykb9lI5N1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lNZqw/dJMb99MtgBR/XuiWpZgX3aKo8ykb9lI5N1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lNZqw/dJMb99MtgBR/XuiWpZgX3aKo8ykb9lI5N1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlNZqw%2FdJMb99MtgBR%2FXuiWpZgX3aKo8ykb9lI5N1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2008&quot; height=&quot;1114&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1114&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 edk2를 빌드할 때 생성된 OVMF.fd 파일에서 HiiDatabaseDxe 드라이버를 삭제하고 스크립트를 돌려보았을 때, 위와 같이 HiiDatabaseDxe 드라이버가 생성하는 EfiHiiDatabaseProtocol, EfiHiiStringProtocol, EfiHiiConfigRoutingProtocol, EfiHiiImageExProtocol이 존재하지 않다고 잘 잡아냈고, 보안 관련 드라이버가 필요한 Protocol이 없을 경우 취약점이 아니라 버그로 잡기로 로직을 생성해놔서 위와 같은 결과물이 나와있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 위의 EfiFirmwareVolumeBlock2Protocol은 FvbServicesRuntimeDxe 드라이버가 생성하는 프로토콜인 것 같은데, 잘못 탐지 된 것 같다. 왜 탐지 되었는지 좀 더 알아봐야 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 스크립트가 아니고, 로직 수정도 더 필요해서 코드 공유는 안할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음주에도 로직 보강에 힘을 써볼 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/9</guid>
      <comments>https://manguu.tistory.com/9#entry9comment</comments>
      <pubDate>Wed, 18 Mar 2026 15:30:07 +0900</pubDate>
    </item>
    <item>
      <title>[프로젝트]UEFI DXE 바이너리 취약점 분석기 8주차 - Ghidra Script 로직 보강</title>
      <link>https://manguu.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주에는 지난 주에 여러 취약점을 추가한 기드라 스크립트에 필요한 로직 보강과 추가 취약점 분석을 추가하는 방향으로 진행하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[수정 사항]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;논리식 평가 고도화&lt;/li&gt;
&lt;li&gt;빈 DEPEX (Empty DEPEX) 조기 탐지 로직 추가 및 Apriori 파일에 존재하는 드라이버일 경우 제외 처리 추가&lt;/li&gt;
&lt;li&gt;OP_SOR 오프코드 처리 방식 수정&lt;/li&gt;
&lt;li&gt;프로토콜 제공자(Provider) 추론 로직 경량화&lt;/li&gt;
&lt;li&gt;악성 코드가 들어있는 드라이버를 하나 정의하고, DEPEX에 그 드라이버의 GUID가 존재한다면 잡아내는 취약점 추가&lt;/li&gt;
&lt;li&gt;취약점 탐지라는 핵심 목적과 무관하게 폴더에 생성되던 dependency_graph.txt 및 protocol_providers.txt 관련 변수 (graphWriter, protocolWriter)와 생성 메서드 삭제&lt;/li&gt;
&lt;li&gt;이 외의 자잘하게 로직 보강&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bjYqZn/dJMcabKfZCP/YlUjt3qvfk0Au20epRkG2K/GhidraDepexHunter_v8.java?attach=1&amp;amp;knm=tfile.java&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;GhidraDepexHunter_v8.java&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 수정 사항 외에 필요한 부분은 아래와 같다. 다음주부터 보강할 계획이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[수정 예정 사항]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SOR 연산 로직 보강 필요 ( -&amp;gt; 굉장히 까다로움)&lt;/li&gt;
&lt;li&gt;bypass (TRUE OR), dead (FALSE AND)에 대해 좀 더 알아보기&lt;/li&gt;
&lt;li&gt;simplifyExpression 함수 로직 보강 필요 (AST 기반 parser 필요할듯)&lt;/li&gt;
&lt;li&gt;Missing protocol 로직 보강 필요 -&amp;gt; 많은 protocol이 DXE Driver가 제공하는 것은 맞지만, SMM core, PEI phase, Platform code 등에서 제공되는 경우도 존재. 이에 대한 보강 필요.&lt;/li&gt;
&lt;li&gt;currentProgram.getMemory().findBytes(...) 로직 보강 필요 (GUID Search 로직)&lt;/li&gt;
&lt;li&gt;Malicious GUID detection 로직 보강 필요(Protocol GUID와 Driver GUID 구분 필요 -&amp;gt; 일반적인 AND/OR 조합에서 쓰는 guid는 protocol, before/after 조함에서 쓰는 guid는 driver)&lt;/li&gt;
&lt;li&gt;protocol provider inference 로직 보강 필요 (휴리스틱함)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 8개의 취약점을 탐지하고 있는데, 가장 치명적이고 중요한 취약점을 소량 정하여 집중적으로 탐지하면서 오탐률을 줄이는 것이 좋을 것 같다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 앞으로 진행할 부분에 대해 정리를 해보자면,&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;성능 실험&lt;/li&gt;
&lt;li&gt;위 [수정 예정 사항] 부분 로직 보강 및 조사&lt;/li&gt;
&lt;li&gt;탐지하면 좋을만한 취약점 추가 조사 및 CVE 조사&lt;/li&gt;
&lt;li&gt;취약점 조사를 마치고, 그 중 4~5개정도 추려서 기준을 잡은 후 집중적으로 로직 보강 및 정확도 올려나가기&lt;/li&gt;
&lt;li&gt;타임스탬프 찍기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[교수님, 팀원분들과 상의할 내용]&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;지난주에 protocol_providers.txt 파일(protocol을 제공해주는 driver 정리)과 dependency_graph.txt 파일(DEPEX를 기반으로 한 의존성 그래프)을 생성 했었는데, &quot;취약점 탐지 스크립트&quot;라는 주제와는 살짝 멀어진 것 같아서 이번주에는 뺀 상황. 이를 복구시키는 것이 좋을지, 아니면 유지하는 것이 좋을지&lt;/li&gt;
&lt;li&gt;취약점 4~5개에 집중하는 것이 괜찮을지&lt;/li&gt;
&lt;li&gt;JSON 파일 형식 정확히 정하기&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;1094&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eCw20Y/dJMcabQY0uc/PNgKbWs5IkuWrlhBto4yH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eCw20Y/dJMcabQY0uc/PNgKbWs5IkuWrlhBto4yH0/img.png&quot; data-alt=&quot;dependency_graph.txt&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eCw20Y/dJMcabQY0uc/PNgKbWs5IkuWrlhBto4yH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeCw20Y%2FdJMcabQY0uc%2FPNgKbWs5IkuWrlhBto4yH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;548&quot; height=&quot;537&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;1094&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;dependency_graph.txt&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;1156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caG9Ta/dJMcaaEzCFG/YLRYDn2wBu8H17I9w9khM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caG9Ta/dJMcaaEzCFG/YLRYDn2wBu8H17I9w9khM1/img.png&quot; data-alt=&quot;protocol_providers.txt&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caG9Ta/dJMcaaEzCFG/YLRYDn2wBu8H17I9w9khM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaG9Ta%2FdJMcaaEzCFG%2FYLRYDn2wBu8H17I9w9khM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;1156&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;1156&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;protocol_providers.txt&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>2026_졸업프로젝트</category>
      <author>망구입니다</author>
      <guid isPermaLink="true">https://manguu.tistory.com/8</guid>
      <comments>https://manguu.tistory.com/8#entry8comment</comments>
      <pubDate>Mon, 16 Mar 2026 09:10:03 +0900</pubDate>
    </item>
  </channel>
</rss>