Ghidra API

안상준·2026년 1월 15일

Reversing

목록 보기
9/16

Ghidra Strudy

Ghidra API

Ghidra Script 개발의 핵심 요소인 Ghidra API에 대하여 학습 하였다. 이전 블로그에서 Ghidra Script를 소개하였는데, Script 자주 사용하는 Ghidra API에 대해 알아 보았다.

API 문서


Ghidra는 API 문서를 제공해 준다. 위의 메뉴에서 Help > Ghidra API Help를 누르면 html 파일을 생성해 준다.

계층 구조 및 관계

Ghidra에는 Ghidra Program API, FlatProgram API, GhidraScript가 존재하는데 이름도 비슷하여 상당히 헷갈린다.

  • GhidraScript (최상위): 우리가 작성하는 모든 스크립트의 본체. currentProgram, currentAddress와 같은 상태변수와 println, popup같은 UI 제어 기능을 제공.
  • FlatProgramAPI (사용자 편의용): 초보자나 빠른 자동화를 위해 복합한 객체 호출을 한 단계 줄여놓은 지름길 모음집.
  • Program API (전문가용/내부 구조): Ghidra 바이너리의 데이터를 가장 밑바닥까지 정교하게 다룰 수 있는 원형 API
// __mingw_scanf 호출 지점을 찾고 인자 정보를 분석합니다.
//@author Gemini
//@category Analysis
//@runtime Java

import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;

public class FindInput extends GhidraScript {

    @Override
    public void run() throws Exception {
        String targetFunc = "__mingw_scanf";
        println("--- [분석 시작] " + targetFunc + " 추적 ---");

        SymbolTable symbolTable = currentProgram.getSymbolTable();
        SymbolIterator iter = symbolTable.getSymbols(targetFunc);

        while (iter.hasNext() && !monitor.isCancelled()) {
            Symbol sym = iter.next();
            if (sym.getSymbolType() == SymbolType.FUNCTION || sym.getSymbolType() == SymbolType.LABEL) {
                
                for (Reference ref : getReferencesTo(sym.getAddress())) {
                    if (ref.getReferenceType().isCall()) {
                        Address callAddr = ref.getFromAddress();
                        
                        // 호출 지점의 함수 정보 가져오기
                        Function caller = getFunctionContaining(callAddr);
                        if (caller != null && caller.getName().equals("main")) {
                            println("[!] 중요 입력 지점 발견 (in main)");
                        } else {
                            println("[+] 호출 발견: " + (caller != null ? caller.getName() : "Unknown"));
                        }

                        println("    - 주소: " + callAddr);
                        println("------------------------------------------");
                    }
                }
            }
        }
    }
}

이전에 작성한 Script를 간단하게 살펴 보면

  • GhidraScript (Base API: currentProgram: 이 변수는 GhidraScript 클래스에 정의된 필드

    • println(): 콘솔 출력을 담당하는 메서드

    • monitor: 작업 취소 상태 등을 확인하는 필드

  • FlatProgramAPI (편의용 메서드):

    • getReferencesTo(): 특정 주소를 참조하는 곳들을 바로 찾아주는 함수

    • getFunctionContaining(): 특정 주소가 포함된 부모 함수 객체를 바로 찾아주는 함수

    • 이 메서드들은 원래 복잡한 과정을 거쳐야 하지만, GhidraScript가 FlatProgramAPI를 상속받고 있기 때문에 위 코드처럼 짧게 호출 가능

  • Program API (Low-level):

    • currentProgram.getSymbolTable(): currentProgram이라는 객체를 통해 SymbolTable이라는 하위 매니저 객체를 직접 가져오는 방식입니다. 이는 객체 지향적인 Program API 사용법에 해당

FlatProgramAPI

Ghidra 스크립트 작성 시 빈번하게 사용되는 FlatProgramAPI 기반의 핵심 함수들을 용도별로 정리해 보았다.

1. 프로그램 정보 및 제어 (Program Info)

현재 분석 중인 바이너리의 전반적인 정보를 가져올 때 사용한다.

함수명설명
currentProgram.getName()현재 열린 프로그램의 이름을 반환
currentProgram.getExecutablePath()로컬 시스템상의 바이너리 파일 경로를 반환
currentProgram.getMinAddress()프로그램의 시작(최소) 주소를 반환
toAddr(long/string)숫자나 문자열을 Ghidra Address 객체로 변환

2. 메모리 및 데이터 탐색 (Search & Memory)

특정 바이트 패턴을 찾거나 데이터를 읽고 쓸 때 사용한다.

함수명설명
find(startAddr, bytes)특정 주소부터 지정한 바이트 패턴을 검색
getByte(addr)특정 주소에서 1바이트를 읽어옵니다.
setByte(addr, value)특정 주소에 바이트를 쓴다 (바이너리 패치).
createData(addr, type)특정 주소를 문자열, 정수 등의 데이터 타입으로 정의합니다.

3. 함수 관련 (Functions)

리버싱 자동화의 핵심인 함수 제어 API입니다.

함수명설명
getFunctionAt(addr)해당 주소에 있는 함수 객체를 가져옵니다.
getFunctionBefore(addr) / After현재 위치 인근의 함수를 탐색합니다.
createFunction(addr, name)특정 주소에 새로운 함수를 생성합니다.
func.setName(name, source)함수 객체의 이름을 변경합니다.
func.getEntryPoint()함수의 진입점(시작 주소)을 반환합니다.

4. 심볼 및 주석 (Symbols & Comments)

분석 내용을 기록하거나 레이블을 관리합니다.

함수명설명
createLabel(addr, name, true)특정 주소에 이름(레이블)을 부여합니다.
setEOLComment(addr, comment)코드 끝(End of Line) 줄에 주석을 추가합니다.
setPreComment(addr, comment)코드 윗줄에 주석을 추가합니다.
getSymbolAt(addr)특정 주소의 심볼(이름) 정보를 가져옵니다.

5. 사용자 상호작용 (UI Interaction)

스크립트 실행 중 사용자 입력을 받거나 메시지를 출력합니다.

함수명설명
askString(title, message)사용자로부터 문자열 입력을 받는 창을 띄웁니다.
askChoice(title, msg, choices)여러 선택지 중 하나를 고르게 합니다.
popup(message)알림 메시지 팝업을 띄웁니다.
println(string)Ghidra 하단 콘솔(Console)창에 메시지를 출력합니다.

6. 디컴파일러 API

분석된 C 코드를 문자열로 가져오는 과정입니다.

from ghidra.app.decompiler import DecompInterface

# 1. 디컴파일러 인터페이스 초기화
iface = DecompInterface()
iface.openProgram(currentProgram)

# 2. 분석할 함수 가져오기 (현재 주소 기준)
func = getFunctionAt(currentAddress)

# 3. 디컴파일 수행
results = iface.decompileFunction(func, 0, monitor)

if results.decompileCompleted():
    # 4. 결과에서 C 코드 소스 출력
    print(results.getDecompiledFunction().getC())

0개의 댓글