See what a program asks for
ltrace and strace are tracing tools: they print each call a program makes, with its arguments, while it runs.
That matters because a program's requests, such as which file it opens, show what it needs. You do not have to read any assembly. You will trace a practice program that you run yourself.
By the end of this lesson
Note
I can see what a program asks the library and the system.
Key words
| Word | What it means | Example |
|---|---|---|
| Library call | a request to ready-made code that comes with Linux | fopen |
| System call | a request from a program to the operating system | openat |
| Kernel | the core of the operating system, which does the work | |
| Trace | a printed list of the calls a program made | |
| Return value | the answer a call gives back | |
| ENOENT | the error for a file that does not exist |
The cells students fill in are left blank in this preview.
Two tools watch two layers
A program asks for things in two layers. A library call goes to ready-made code, such as fopen, which opens a file. A system call goes to the kernel, which does the real work. Opening a file ends in the system call openat.
ltrace prints the library calls. strace prints the system calls. Neither one needs you to read any assembly.
Worked example: one file, two views
| Tool | It watches | A line it prints for the practice program |
|---|---|---|
| ltrace | Library calls | fopen("/tmp/shop-settings.txt", "r") = nil |
| strace | System calls | openat(AT_FDCWD, "/tmp/shop-settings.txt", O_RDONLY) = -1 ENOENT (No such file or directory) |
The cells students fill in are left blank in this preview.
Write the practice program
printf '#include <stdio.h>\nint main(void) {\n FILE *f = fopen("/tmp/shop-settings.txt", "r");\n if (f) { fclose(f); puts("Settings found."); return 0; }\n puts("Settings missing.");\n return 1;\n}\n' > reader.cShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Compile it
gcc -O0 -no-pie -fno-stack-protector -o reader reader.cShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Watch the library call
ltrace ./reader 2>&1 | grep fopenShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Watch the system call
strace -e trace=openat ./reader 2>&1 | grep shopShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A missing file is a clue
A result of -1 ENOENT means the file the program asked for is not there. A program that looks for a settings file, a data file or a licence file names it in its own request.
A defender can use that: the missing name shows what the program expects to find. The next Runs make the file, run the program, trace it again and tidy up.
Make the file the program wants
touch /tmp/shop-settings.txtShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Run the program again
./readerShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Trace the call again
strace -e trace=openat ./reader 2>&1 | grep shopShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Remove the file again
rm /tmp/shop-settings.txtShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think a trace shows every function in the program. It does not. strace shows only requests to the kernel, and ltrace only calls into shared libraries. A function inside the program itself appears in neither.