단서에 맞는 검색 도구 선택하기
Ghidra에서 문자열 검색을 시작하기 전에 Ghidra가 이미 정의한 데이터를 찾는지, 프로그램 모델에 표시된 텍스트를 찾는지, 로드된 메모리의 원시 바이트를 찾는지, 정확한 주소로 이동하려는지 결정하세요. Defined Strings는 유용한 목록이지만 모든 문자열을 보장하지는 않습니다. 짧은 문자열은 아직 정의되지 않았을 수 있고 Unicode 표현이 다를 수 있으며 현재 범위 밖의 메모리 블록은 같은 창에서 보이지 않을 수 있습니다.
주소 단위 확인에서는 Listing을 기준으로 삼습니다. 검색으로 근거를 찾은 뒤 Decompiler를 사용해 함수를 설명하고 검색 자체를 Decompiler로 대신하지 마세요. 전체 CodeBrowser 흐름은 공식 초보자 문서에서 확인할 수 있으며, 이 페이지는 처음 사용할 때 헷갈리는 검색 판단에 집중합니다.
분석 권한이 있는 소프트웨어와 시스템만 확인하세요. 검색 결과는 파일에 대한 근거일 뿐, 리버스 엔지니어링 허가나 안전성 보증이 아닙니다.
- 읽을 수 있는 텍스트: Defined Strings 또는 Search for Strings에서 시작하고 참조를 확인합니다.
- 이름, 심볼, 함수, 주석: Search Program Text 또는 Symbol Tree를 사용합니다.
- 정확한 주소: Go To로 이동한 뒤 로드된 블록과 명령어를 확인합니다.
- 바이트열이나 패턴: 올바른 범위로 Search Memory를 사용합니다.
- 결과를 사용하는 함수: XREF를 따라 Listing, Function Graph, Decompiler를 비교합니다.
Decompiler에서 추측하기 전에 문자열 검색하기
메시지, URL, 파일 경로, 명령어, 오류 일부를 알고 있다면 수백 개의 함수를 읽기 전에 텍스트를 검색하세요. Ghidra가 이미 인식한 문자열을 보고 싶을 때는 Defined Strings를 엽니다. 값이 나오지 않으면 문자열 검색을 사용하고 인코딩, 최소 길이, 정렬, 널 종료, 메모리 블록 범위를 확인합니다. 결과가 없다는 것은 텍스트가 없다는 뜻보다 정의나 검색 범위가 맞지 않다는 뜻일 때가 많습니다.
주소를 확인해야 검색 결과가 의미를 가집니다. Listing에서 일치 항목을 열어 바이트와 주변 데이터를 보고 로드된 블록 안에 있는지 확인하세요. Ghidra가 정의되지 않은 데이터로 표시하면 정렬과 가까운 참조를 확인한 뒤 정의합니다. 여러 데이터를 한 번에 정의할 때는 프로젝트 원본을 보관하고 복사본에서 작업하세요.
- 1
구별되는 단서로 시작
전체 URL, 특징적인 문구, 드문 확장자는 일반적인 단어나 초기화 이름보다 오탐이 적습니다.
Defined Strings / Search for Strings - 2
인코딩과 범위 확인
ASCII, UTF-8, UTF-16 등 대상에 맞는 표현을 시도하고 로드된 블록, 전체 블록, 선택 영역 중 범위를 정합니다.
Encoding + memory block scope - 3
Listing에서 주소 열기
바이트, 데이터 형식, 주변 문자열, 참조를 확인합니다. 강조 표시만으로 함수의 역할을 단정하지 않습니다.
Open in Listing - 4
유용한 참조 하나 따라가기
References 또는 XREF를 사용해 비교, 호출, 포맷팅, 분기 코드로 이동하고 문자열의 역할을 확인합니다.
References / Show XRefs

문자열이 사용되는 위치와 의미 찾기
URL이나 메시지를 찾는 것은 보통 조사 중간 단계입니다. 데이터 항목을 선택하고 참조를 확인하세요. URL은 네트워크 루틴에 전달되거나 로컬 값과 비교되거나 사용되지 않는 리소스로 남을 수 있습니다. 메시지는 오류 처리, 라이선스 확인, 메뉴, 디버그 분기에 속할 수 있습니다. 참조 주소는 값이 소비되는 곳을 알려 주고 호출자와 피호출자가 역할을 설명합니다.
복잡한 함수에 도달하면 Listing과 Decompiler를 오가세요. Listing은 실제로 디코딩된 명령어와 주소를 보여 주고 Decompiler는 제어 흐름과 변수 모델을 해석해 제안합니다. 증거가 충분할 때만 이름을 바꾸고 관찰한 사실과 추론을 분리해 기록하면 검색 결과를 과도하게 해석하는 일을 줄일 수 있습니다.
- 단순히 가까운 주소가 아니라 실제 코드 또는 데이터 참조인지 확인합니다.
- 기본 블록을 읽고 비교, 호출, 포맷팅 작업을 찾습니다.
- 기능적 의미를 부여하기 전에 호출자와 피호출자를 확인합니다.
- 선형 Listing에서 분기를 따라가기 어렵다면 Function Graph를 사용합니다.
- 의사 코드 해석이 문제라면 Decompiler 가이드를 참고합니다.
메모리 주소, 값, 바이트 패턴 찾기
“0x00421A3F는 어디에 있나요?”라는 질문은 먼저 탐색 문제입니다. Go To로 주소로 이동한 다음 Listing에 표시된 프로그램, 메모리 블록, 언어, 주소 공간을 확인하세요. 파일 오프셋, 가상 주소, 이미지 기준 주소, 재배치된 주소는 서로 바꿔 쓸 수 없습니다. 주소를 열 수 없다면 파일 오프셋인지, 디버거 트레이스인지, 로그인지, 재배치된 모듈의 주소인지 출처를 확인합니다.
원시 데이터에는 텍스트 검색보다 Search Memory가 적합합니다. 바이트 순서와 엔디언, 정렬을 고려하고 결과가 많으면 블록이나 선택 영역을 좁히세요. 일치한 값이 코드, 데이터, 패딩, 무관한 구조체에 있을 수 있으므로 주변 바이트와 참조를 확인한 뒤 의미를 판단합니다.
디버거, 파일 뷰어, Ghidra는 서로 다른 좌표계를 사용할 수 있습니다. 화면에 맞을 때까지 상수를 더하지 말고 주소의 출처를 기록한 뒤 의도적으로 변환하세요.
| 단서 | 먼저 사용할 도구 | 다음 확인 |
|---|---|---|
| 정확한 로드 주소 | Go To | 주소 공간, 블록, 대상 명령어 또는 데이터 |
| 16진 바이트열 | Search Memory | 엔디언, 정렬, 범위, 주변 참조 |
| URL 또는 메시지 | 문자열 검색 | 인코딩, 정의, XREF, 사용 함수 |
| 이름 또는 레이블 | Symbol Tree / Search Program Text | 네임스페이스, 종류, 호출 관계 |
| 로그나 디버거 값 | Go To + Listing | 리베이스, 모듈 기준 주소, 오프셋과 주소 차이 |
명령어와 명령어 패턴 검색하기
명령어 검색에는 “이 단어를 찾아 주세요”보다 구체적인 질문이 필요합니다. 니모닉, 레지스터 사용, 상수 피연산자, 명령어 순서, 컴파일러가 만든 바이트를 찾을 수 있습니다. Listing에 표시되는 명령어 텍스트가 안정적인 단서라면 Search Program Text를, 바이트 인코딩이 안정적인 단서라면 Search Memory를 사용하세요. 같은 바이트의 해석은 가져오기 때 선택한 아키텍처와 언어에 달려 있으므로 먼저 설정을 확인합니다.
Java 명령어 또는 플랫폼별 용어를 검색할 때 소스 언어와 디스어셈블리 표기를 섞지 마세요. Listing에 실제로 나타나는 표현을 검색하고 피연산자와 제어 흐름으로 한 건을 검증합니다. 반복 가능한 패턴이라면 아키텍처, 엔디언, 와일드카드, 검색 범위를 기록하세요.
- 1
패턴 정의
니모닉, 피연산자, 바이트, 레지스터, 상수를 적고 빌드마다 바뀔 수 있는 부분을 표시합니다.
Pattern = mnemonic + operands + optional wildcards - 2
텍스트와 바이트 중 선택
디코딩된 표시가 안정적이면 텍스트, 바이트 인코딩이 안정적이면 메모리 검색을 사용합니다.
Search Program Text / Search Memory - 3
일치 검증
결과를 열어 전체 명령어와 기본 블록을 읽고 참조와 호출자를 비교합니다.
Listing + XREF + Function Graph

함수, 정의되지 않은 함수, 경계 확인하기
검색 결과가 코드를 가리키면 Symbol Tree, Function Window 또는 Listing의 현재 위치에서 Ghidra가 함수를 인식했는지 확인합니다. Undefined는 아직 함수 경계가 만들어지지 않았거나, 해당 주소가 데이터이거나, 가져온 아키텍처를 다시 확인해야 한다는 뜻일 수 있습니다. 주변 명령어가 익숙해 보인다는 이유만으로 함수를 만들지 말고 진입점, 참조, 호출 규약, 반환 흐름을 확인하세요.
검색 중심의 작업에서 함수는 증거를 정리하는 경계이지 동작에 대한 결론이 아닙니다. 주소, 일치한 데이터 또는 명령어, 둘을 연결하는 참조, 다음으로 값을 사용하는 함수를 기록하세요. 초보자 튜토리얼에서는 Auto Analysis와 Function Graph를 포함한 전체 흐름을 다룹니다.
| 결과 | 의미 | 안전한 다음 단계 |
|---|---|---|
| 이름이 있는 함수 | 심볼 경계가 있음 | 호출자, 피호출자, 시그니처, 참조 확인 |
| FUN_... 또는 이름 없는 함수 | 함수는 있으나 역할이 모름 | 이름을 바꾸기 전에 문자열, 호출, 데이터 흐름 확인 |
| 정의되지 않은 주소 | 신뢰할 함수 경계가 없음 | 코드/데이터 분류를 확인하고 복사본 분석 |
| 블록 안의 검색 결과 | 코드나 데이터 주변에 단서가 있음 | 전체 블록을 읽고 XREF 추적 |
| 참조 없음 | 간접 사용 또는 정의 불완전 | 포인터 테이블, 재배치, 분석 범위 확인 |
결과가 없거나 너무 많을 때 해결하기
가장 흔한 검색 실패는 단서와 프로그램 내부 표현이 서로 다르기 때문입니다. URL이 나뉘거나 인코딩·압축되어 있거나 UTF-16으로 저장되거나 실행 중에 조합될 수 있습니다. 주소는 다른 모듈 기준 주소에 속할 수 있고 명령어 패턴은 컴파일러가 다른 레지스터를 선택하는 것만으로도 달라집니다. 한 번에 하나의 조건만 바꾸고 원래 단서와 검색 설정을 함께 남겨 두세요.
결과가 너무 많으면 메모리 블록, 선택 영역, 데이터 형식, 최소 길이, 언어, 주소 범위를 좁힙니다. 결과가 없으면 조건 하나를 넓히고 주변 바이트, 다른 인코딩, 실제로 로드된 메모리를 확인합니다. 버전별 메뉴 차이는 오래된 캡처보다 현재 공식 도움말을 기준으로 확인하세요.
| 증상 | 가능한 원인 | 다음 확인 |
|---|---|---|
| 문자열 결과 없음 | 인코딩, 짧은 문자열, 정의되지 않은 데이터 | 맞는 인코딩을 시도하고 바이트 확인 |
| 텍스트 결과가 너무 많음 | 일반 단어나 넓은 범위 | 특징적인 구간과 제한된 블록 사용 |
| 주소를 열 수 없음 | 오프셋, 리베이스, 주소 공간 오류 | 좌표계와 모듈 기준 주소 확인 |
| 문자열에 XREF 없음 | 간접 사용이나 포인터 테이블 | 주변 포인터와 제한된 분석 확인 |
| 명령어 검색 누락 | 표기, 아키텍처, 컴파일러 차이 | 바이트나 안정적인 피연산자 검색 |
| Decompiler와 다름 | 의사 코드는 해석 결과 | Listing, 바이트, 참조, Function Graph로 돌아가기 |
Ghidra 검색에 대한 질문
Ghidra에서 문자열을 검색하는 가장 쉬운 방법은 무엇인가요?
목록을 보려면 Defined Strings에서 시작하고 값이 없거나 인코딩이 확실하지 않으면 문자열 검색을 사용하세요. Listing에서 주소를 확인하고 함수를 해석하기 전에 XREF를 따라갑니다.
Ghidra에서 URL 주소를 어떻게 찾나요?
URL의 특징적인 부분을 문자열로 검색하고 Listing에서 인코딩과 주소를 확인한 다음 값을 읽거나 비교하거나 전송하는 함수까지 참조를 따라갑니다.
Ghidra에서 특정 메모리 주소를 검색하려면 어떻게 하나요?
Go To로 로드된 주소로 이동하고 주소 공간, 메모리 블록, 디코딩된 명령어나 데이터를 확인합니다. 파일 오프셋이나 디버거 주소는 먼저 변환합니다.
Ghidra에서 특정 명령어를 어떻게 검색하나요?
디코딩된 Listing 텍스트가 안정적이면 Search Program Text를, 바이트 인코딩이 안정적이면 Search Memory를 사용합니다. 아키텍처와 엔디언을 확인하고 Listing과 Function Graph에서 검증하세요.
Ghidra 문자열 검색에서 결과가 나오지 않는 이유는 무엇인가요?
인코딩, 최소 길이, 정렬, 로드된 메모리 범위, 문자열이 분할되거나 실행 중 생성되는지 확인하세요. 조건은 하나씩 넓힙니다.
문자열 검색에 Decompiler를 사용해야 하나요?
보통 문자열이나 바이트를 먼저 검색하고 Decompiler는 결과를 참조하는 함수를 이해하는 데 사용합니다. 일치 자체의 근거는 Listing과 바이트가 더 직접적입니다.