
IDA Pro 플러그인: 바이너리 내에서 쿼리 기반 검색을 수행하며, 주로 취약점 연구에 유용합니다.
VulFi(취약점 찾기) 도구는 IDA Pro의 플러그인으로, 바이너리에서 버그 헌팅을 지원하는 데 사용할 수 있습니다. 주요 목표는 가장 흥미로운 함수(예: strcpy, sprintf, system 등)에 대한 모든 상호 참조를 단일 보기로 제공하는 것입니다. Hexrays 디컴파일러를 사용할 수 있는 경우, 취약점 연구 관점에서 흥미롭지 않은 함수 호출(예: strcpy(dst,"Hello World!"))을 걸러내려고 시도합니다. 디컴파일러가 없는 경우 규칙은 훨씬 더 간단하며(아키텍처에 의존하지 않기 위해) 가장 명백한 경우만 걸러냅니다.
업데이트에 대한 자세한 내용은 변경 로그를 참조하세요.
vulfi.py, vulfi_prototypes.json 및 vulfi_rules.json 파일을 IDA 플러그인 폴더에 넣습니다(cp vulfi* <IDA_PLUGIN_FOLDER>).
VulFi를 실행하기 전에 작업 중인 바이너리에 대해 잘 이해하고 있는지 확인하세요. 모든 표준 함수(strcpy, memcpy 등)를 식별하고 그에 따라 이름을 지정하세요. 플러그인은 대소문자를 구분하지 않으므로 MEMCPY, Memcpy 및 memcpy 모두 유효한 이름입니다. 그러나 함수 검색에는 정확히 일치해야 합니다. 즉, memcpy? 또는 std_memcpy(또는 다른 변형)는 표준 함수로 감지되지 않으므로 잠재적 취약점을 찾을 때 고려되지 않습니다. 알 수 없는 바이너리로 작업하는 경우 먼저 컴파일러 옵션을 설정해야 합니다(Options > Compiler). 그 후 VulFi는 명백한 거짓 양성(예: 첫 번째 매개변수가 상수 문자열인 printf 호출)을 최대한 걸러냅니다. 플러그인은 특정 아키텍처와 관련 없이 만들어졌지만 일부 프로세서는 유형 지정을 완전히 지원하지 않으며, 이 경우 VulFi는 잠재적으로 위험한 표준 함수에 대한 모든 상호 참조를 표시하여 수동 분석을 진행할 수 있도록 합니다. 이러한 경우 플러그인의 추적 기능을 활용할 수 있습니다.
스캔을 시작하려면 상단 바 메뉴에서 Search > VulFi 옵션을 선택하세요. 이렇게 하면 새 스캔이 시작되거나 idb/i64 파일에 저장된 이전 결과를 읽어옵니다. 데이터는 데이터베이스를 저장할 때마다 자동으로 저장됩니다.
스캔이 완료되거나 이전 결과가 로드되면 다음 열이 포함된 테이블 뷰가 표시됩니다.
Not Checked가 할당됩니다. 다른 상태는 False Positive, Suspicious 및 Vulnerable입니다. 해당 항목을 마우스 오른쪽 버튼으로 클릭하여 설정할 수 있으며, 주어진 함수 호출의 수동 검토 결과를 반영해야 합니다.High, Medium 및 Low입니다(스캐너가 모든 매개변수를 제대로 식별하지 못한 경우 Info도 있음). 우선순위는 vulfi_rules.json 파일의 다른 규칙과 함께 정의됩니다.idb/i64 파일에 데이터가 없거나 사용자가 새 스캔을 수행하기로 결정한 경우, 플러그인은 기본 포함 규칙을 사용하여 스캔을 실행할지 아니면 사용자 정의 규칙 파일을 사용할지 묻습니다. 이미 존재하는 데이터로 새 스캔을 실행해도 이전에 저장된 결과와 동일한 이름의 규칙으로 식별된 이전에 찾은 항목을 덮어쓰지 않습니다. 따라서 스캔을 다시 실행해도 기존 주석과 상태 업데이트가 삭제되지 않습니다.

VulFi 뷰 내의 오른쪽 클릭 컨텍스트 메뉴에서 결과에서 항목을 삭제하거나 모든 항목을 제거할 수도 있습니다. 이 작업을 수행하면 모든 주석 또는 상태 업데이트가 손실됩니다.
버전 2.1부터 VulFi는 한 번에 여러 선택된 항목에 대한 작업도 지원합니다. 이를 통해 여러 항목에 특정 상태를 표시하거나, 삭제하거나, 여러 행에 동일한 주석을 추가할 수 있습니다. 때로는 작업이 올바르게 새로고침되지 않는 경우가 있습니다. 이런 경우 변경 사항이 반영될 때까지 UI를 여러 번 새로고침(Ctrl+U)하세요.
감지된 취약 함수 인스턴스를 검사하려면 원하는 행의 아무 곳이나 더블 클릭하면 IDA가 잠재적으로 흥미로운 것으로 식별된 메모리 위치로 이동합니다. 마우스 오른쪽 버튼을 클릭하고 Set Vulfi Comment 옵션을 사용하면 해당 인스턴스에 대한 주석을 입력할 수 있습니다(예: 상태를 정당화하기 위해).
플러그인은 사용자 정의 규칙 생성도 지원합니다. 이러한 규칙은 IDA 인터페이스에서 정의하거나(단일 함수에 이상적), 사용자 정의 규칙 파일로 제공할 수 있습니다(여러 함수를 포함하는 규칙에 이상적).
분석 중에 식별된 사용자 정의 함수를 추적하려면 함수 본문 내 아무 곳이나 마우스 오른쪽 버튼으로 클릭하고 Add <name> function to VulFi를 선택하세요. 또한 현재 디스어셈블리/디컴파일러 뷰에서 함수 이름을 강조 표시하고 마우스 오른쪽 버튼을 클릭하여 함수 본문으로 전환하지 않고도 추가할 수 있습니다.

여러 규칙 집합이 포함된 사용자 정의 파일을 로드할 수도 있습니다. 아래 구조의 사용자 정의 규칙 파일을 생성하려면 포함된 템플릿 파일 여기를 사용할 수 있습니다.
[ // An array of rules
{
"name": "RULE NAME", // The name of the rule
"function_names":[
"function_name_to_look_for" // List of all function names that should be matched against the conditions defined in this rule
],
"wrappers":true, // Look for wrappers of the above functions as well (note that the wrapped function has to also match the rule)
"mark_if":{
"High":"True", // If evaluates to True, mark with priority High (see Rules below)
"Medium":"False", // If evaluates to True, mark with priority Medium (see Rules below)
"Low": "False" // If evaluates to True, mark with priority Low (see Rules below)
}
}
]
다음은 함수 malloc에 대한 모든 상호 참조를 찾고 해당 매개변수가 상수가 아닌지, 함수의 반환 값이 확인되었는지 확인하는 예제 규칙입니다.
{
"name": "Possible Null Pointer Dereference",
"function_names":[
"malloc"
],
"wrappers":false,
"mark_if":{
"High":"not param[0].is_constant() and not function_call.return_value_checked()",
"Medium":"False",
"Low": "False"
}
}
Loop Check - 모든 루프를 표시합니다. 이 경우 param[0]은 루프 카운터(감지된 경우)이고 param[1]은 루프를 종료하기 위해 카운터가 확인되는 조건입니다.Array Access - 모든 배열 액세스를 표시합니다. 이 경우 param[0]은 배열이고 param[1]은 인덱스입니다.일반 함수 매개변수와 동일한 함수를 규칙 생성 시 사용할 수 있습니다(param[<index>]에서 호출할 수 있는 모든 것).
param[<index>]: 함수 호출의 매개변수에 접근하는 데 사용됩니다(인덱스는 0부터 시작).function_call: 함수 호출 이벤트에 접근하는 데 사용됩니다.param_count: 함수에 전달된 매개변수의 개수를 저장합니다.param[<index>].is_constant()param[<index>].number_value()param[<index>].string_value()param[<index>].set_to_null_after_call()function_call.return_value_checked(<constant_to_check>)param[<index>].used_in_call_<before|after>(["function1","function2"])function_call.reachable_from("<function_name>")param[<index>].is_sign_compared()param[<index>].used_as_index()param[2].number_value() > 5"%s" in param[1].string_value()not param[1].is_constant()function_call.return_value_checked(param_count)function_call.return_value_checked()all(not p.is_constant() for p in param[2:])any(p.is_constant() for p in param)Truestrlen으로 확인되지 않는 함수 호출을 모두 표시: not param[1].is_constant() and not param[1].used_in_call_before(["strlen"])read 함수에서 도달 가능한 함수 호출을 모두 표시: Low 우선순위로 표시됩니다. 이는 모든 매개변수를 올바르게 가져올 수 없는 경우(주로 디스어셈블리 모드에 적용됨) 상호 참조를 놓치지 않기 위한 방법입니다.Ctrl+U 단축키를 사용하여 수동으로 뷰를 여러 번 새로고침하세요.function_call.reachable_from("read")