방망이
[프로젝트]UEFI DXE 바이너리 취약점 분석기 14주차 - P-code Phase2 본문
[P-code 공부 커리큘럼]

Phase2에서 4, 5번에 대한 내용은 팀원들의 블로그를 참고한다.
- Phase2 - 4 (Varnode, PcodeOp) 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
Ghidra P-Code 알아보기 1
P-Code (사실 P-Code는 다들 너무 잘 알고 있을 것이라 생각한다…) P-Code는 Ghidra가 사용하는 IR로, 다양한 프로그래밍 언어들을 통일하기 위한 목적인 컴파일러 레벨의 IR들과 달리 P-Code는 MIPS, x86, ARM
ludence8.github.io
- Phase2 - 4 (SLEIGH, High Pcode vs Raw P-Code)
https://eatrawlife.github.io/posts/2026/05/17
UEFI 스터디 15차 - 기드라 p 코드 공부 (sleigh, high VS low pcode.)
sleigh
eatrawlife.github.io
- Phase2 - 5(P-code 연산자)
https://img1244.tistory.com/28
15차 전원회의 - p-code operator를! 공부해보자
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
img1244.tistory.com
이번 주에 내가 공부한 내용은 위 커리큘럼에서 Phase2에 6~7부분 중 SSA 정적 단일 할당과 데이터 흐름 추적 파트이다. 이 파트에서는 Varnode와 High Variable, 심볼 분류와 분석 소스 판정, Def-Use 체인에 대한 내용을 다룰 예정이다.
Varnode와 High Variable
- Varnode는 P-code에서 모든 값을 표현하는 기본 단위이다. 레지스터든, 메모리든, 상수든간에 전부 (address space, offset, size) 이렇게 세 필드로 표현된다.
- Raw P-code에서는 Varnode가 단순히 레지스터 위치((register, 0x0, 8)=RAX)를 가리키는 데 그친다. 하지만 High P-code로 올라오면 High Variable이라는 개념이 추가된다.
- High Variable은 SSA 변환 이후 여러 SSA 버전을 하나의 논리적 변수로 묶은 것.
예를 들어, 동일한 변수 x가 코드 흐름에서 세번 재정의되면 SSA에서는 x#0, x#1, x#2로 분리되는데, 이 세 개가 모두 같은 High Variable에 속한다.
Varnode (x#0) ─┐
Varnode (x#1) ─┼─→ HighVariable "x" (이름, 타입, 심볼 종류 보유)
Varnode (x#2) ─┘
(Ghidra 디컴파일러가 "이 두 SSA 버전은 결국 같은 논리적 변수다"라고 판단) - SSA는 분석을 위해 변수를 쪼개고, HighVariable은 사람이 이해할 수 있도록 다시 합쳐주는 역할
- API로는 varnode.getHigh()로 HighVariable에 접근하고, highVar.getInstances()를 호출하면 해당 HighVariable에 속한 모든 SSA 버전 Varnode 목록(x#0, x#1, x#2)이 반환.
- Taint 분석에서 변수의 모든 사용 지점을 빠짐없이 추적할 때 이 메서드 사용.

심볼 분류와 분석 소스 판정
- High Variable은 getSymbol() 메서드로 심볼 종류를 구분할 수 있음. 취약점 분석에서 이 분류가 중요한 이유는 Taint의 시작점(Taint source)을 정의할 수 있는 기준이 되기 때문.
종류 의미 Taint 관련성 HighParam 함수 선언부의 인자. int func(int a, char* buf)에서 a와 buf Taint source - 외부 입력 진입점 HighLocal 함수 내부에서 선언된 지역 변수. char buf[64] 같은 것 버퍼 위치 추적 HighGlobal 함수 밖에 선언된 전역/정적 변수 외부 상태 추적 HighOther 디컴파일러가 내부적으로 만들어낸 임시 변수. 소스 코드에 대응하는 변수가 없음 대부분 무시 - Taint source 판정 규칙
- HighParam → 즉시 Taint source (함수 인자는 외부 호출자가 넘겨준 값이라 신뢰할 수 없기 때문)
- getDef()를 역추적했을 때 read() / recv() / fgets() 같은 외부 입력 함수의 CALL output Varnode에 닿으면 → Taint source
- 이 규칙은 함수 인자가 아닌 로컬 변수가 외부 입력을 받는 경우를 잡기 위한 것
- ex.
- void func() {
char buf[64]; // HighLocal — 인자가 아님
recv(sock, buf, 64, 0); // 여기서 buf에 외부 데이터가 들어옴
strcpy(dst, buf); // buf가 tainted인지 알아야 함
} - 위와 같은 코드의 경우 buf가 HighParam이 아니기 때문에 규칙 1에서 잡히지 않음. 그래서 getDef()를 따라 역추적.
- strcpy가 위험한 이유 : strcpy(dst, src)는 src 문자열을 dst 버퍼에 복사하는데, src의 길이를 전혀 확인하지 않음 → 공격자가 64바이트보다 긴 데이터를 보내면 Buffer Overflow
- void func() {
- Java코드로는 아래와 같이 판정한다.
HighVariable hv = varnodeAST.getHigh();
if (hv != null && hv.getSymbol() != null) {
String kind = hv.getSymbol().getClass().getSimpleName();
if (kind.equals("HighParam")) {
// Taint source로 등록
}
}
Def-Use 체인 슬라이싱
- SSA의 핵심 장점은 각 변수가 딱 한 번만 정의된다는 것. 이 덕분에 어떤 Varnode든 그것을 만든 op와 그것을 사용하는 op를 바로 추적할 수 있음.
- 역방향 슬라이싱 - getDef()
- Varnode를 만든 op를 거슬러 올라갑니다. Taint가 어디서 시작됐는지 출처를 사용할 때 사용.
- strcpy의 src 인자
← INT_ADD (버퍼 + 오프셋)
← LOAD (메모리에서 읽기)
← CALL recv() ← [SOURCE] 외부 입력
- 순방향 슬라이싱 - getDescendant()
- Varnode가 이후 어디서 사용되는지 흐름을 따라감. Taint가 어디까지 전파되는지, 어떤 sink에 도달하는지 추적할 때 사용.
// 역방향
PcodeOp defOp = varnodeAST.getDef();
// 순방향
Iterator<PcodeOp> uses = varnodeAST.getDescendants();
while (uses.hasNext()) {
PcodeOp use = uses.next();
}
- MULTIEQUAL 처리
- 조건 분기가 있으면 합류점에서 MULTIEQUAL op가 생김. Taint 분석에서 이 노드를 처리하지 않으면 false negative가 발생하게 됨.
- 따라서 MULTIEQUAL을 처리하는 방법은 MULTIEQUAL의 입력 중 하나라도 tainted이면 출력도 tainted.
if (op.getMnemonic().equals("MULTIEQUAL")) {
for (Varnode inp : op.getInputs()) {
if (tainted.contains(inp)) {
tainted.add(op.getOutput()); // 전파
}
}
}'2026_졸업프로젝트' 카테고리의 다른 글
| [프로젝트]UEFI DXE 바이너리 취약점 분석기 16주차 - 스크립트 업데이트를 위하여.. (0) | 2026.07.23 |
|---|---|
| [프로젝트]UEFI DXE 바이너리 취약점 분석기 15주차 - P-code Phase3 (0) | 2026.07.02 |
| [프로젝트]UEFI DXE 바이너리 취약점 분석기 13주차 - P-code Phase1 (0) | 2026.05.12 |
| [프로젝트]UEFI DXE 바이너리 취약점 분석기 12주차 - P-code 이론 (0) | 2026.05.04 |
| [프로젝트]UEFI DXE 바이너리 취약점 분석기 11주차 - Ghidra Script 수정 및 검증 (0) | 2026.04.02 |
