Ghidra: import a binary you are allowed to read
Import copies a file you may study into the project and records how Ghidra intends to decode it. The language and the compiler spec you accept here decide whether the next screen is instructions or noise.
Import is a copy into the project
File > Import File reads a file you are allowed to study and creates a program inside the open project. From that moment the workbench is looking at its own database. Saving, renaming, and commenting update that database. They do not patch the executable. If you want a portable copy of the database later, you export a Ghidra zip. That archive is still analysis, and it is still separate from the binary.
The destination folder in the dialog is a folder inside the project, like a directory in the catalog. You can group harbor-check builds under a folder named harbor. The folder is organizational. It does not change the decode.
Format, language, and compiler spec
A structured binary carries a header. Ghidra recognizes ELF, PE, Mach-O, and a long list of other containers, and it proposes a language id such as x86:LE:64:default. The language id is the processor, the endianness, and the address size. The compiler spec beside it, gcc or windows or another name in that list, tells analysis which calling convention and which startup code to expect. Accept the proposal when it matches the machine you compiled for. If you built a 64-bit Linux ELF with gcc, that is the row to keep.
A wrong language still produces a listing. The listing is nonsense: operands that do not correspond to the instruction set, calls into the middle of the file, a decompiler that cannot keep a thought. The repair is to delete the program from the project and import it again with the language the header, or the lab notes, actually describe. Fixing a bad language one instruction at a time is how a morning disappears.
When the file has no header
A raw dump, a carved blob, or a microcontroller image often has no container header. The import format is Raw Binary. You set the language and the base address yourself, from the lab notes or the datasheet, and you name the memory block. Those three facts are the entire loader. Get the endianness backward and every multi-byte value is swapped. Get the base address wrong and every absolute pointer lands off the block.
There is an option about loading external libraries. Pointing the import at a libc you trust can give external calls their real names. Use libraries that belong to the same lab image as the binary. For a file you compiled on this machine, the system libraries are a fair choice. For a sample that must stay on an isolated virtual machine, keep the project and any libraries you load on that machine too.
/* harbor-check.c — compile this yourself. It is the lab program. */
#include <stdio.h>
static int load_config(const char *path, char *host, int host_len, int *port) {
FILE *file;
char line[128];
file = fopen(path, "r");
if (!file) return 1;
if (!fgets(line, (int)sizeof line, file)) { fclose(file); return 1; }
if (sscanf(line, "%63s %d", host, port) != 2) { fclose(file); return 2; }
fclose(file);
if (*port < 1 || *port > 65535) return 2;
(void)host_len;
return 0;
}
static const char *status_text(int code) {
switch (code) {
case 0: return "ok";
case 1: return "missing";
case 2: return "bad-config";
default: return "unknown";
}
}
int main(int argc, char **argv) {
const char *path = argc > 1 ? argv[1] : "/etc/harbor/check.conf";
char host[64];
int port = 0;
int code = load_config(path, host, 64, &port);
printf("%s %s %d\n", status_text(code), code ? "-" : host, port);
return code;
}Lab: import the program you just compiled
Save the source as harbor-check.c and compile it with gcc -O0 -o harbor-check harbor-check.c. Import that file into harbor-lab. In the dialog, confirm the format is ELF, the language is 64-bit little-endian x86, and the compiler spec is gcc, then accept. When CodeBrowser opens, you should see a program name, a memory map with an executable block, and an entry point. If auto-analysis starts on its own, let it finish. The next lesson explains what it just claimed.
Record these four lines: file name, format, language, compiler spec. Keep the source and the binary next to the project, outside the .rep directory. Later lessons strip a copy, rebuild with -O2, and import a second version. This first program is the baseline, so leave it imported under a clear name.
Write these four lines down at import File: Format Ghidra detected: Language you accepted: Compiler spec you accepted:
Diagram
The language you accept becomes the instruction stream
- File
You choose a binary you compiled, or one the lab explicitly handed you.
- Opinion
Ghidra reads the header and proposes a format, a language, and a compiler spec.
- Accept
You accept the proposal only when it matches the file you built. A raw blob has no header, so you type the base address and the language yourself.
- Program
The project gains a program. Opening it launches CodeBrowser on that database.
What the import dialog is deciding
Format. ELF, PE, or Mach-O, detected from the header.
Language. Processor, endianness, and size agree with that header.
Listing. The executable block shows a plausible prologue and real call targets.
Format. The header was right, and the processor choice was not.
Language. A 32-bit decode of a 64-bit file, or the wrong endianness.
Listing. Operands look random. Re-import with the header’s real language.
File: Format Ghidra detected: Language you accepted: Compiler spec you accepted:
Check yourself
1. You import harbor-check into harbor-lab and then rename a function inside CodeBrowser. What changed on disk?
2. The import dialog proposes x86, little-endian, 64-bit, compiler spec gcc for a binary you just built with gcc on that machine. What do you do?
3. You are handed a raw firmware image with no ELF or PE header, and the lab notes say it is little-endian ARM at base 0x80000000. How does that import differ?