linux kernel image strings extraction

Viewed 168

I'm trying to extract the strings from a binary linux kernel image (this specific phenomena happens in all types of images I've tried: bzImage, vmlinuz, vmlinux, .... and not a specific one)

Simply running 'strings ' prints many strings with a prefix character, for example: "4netlink: %d bytes leftover after parsing attributes in process `%s'."

However, looking at the kernel sources, the current string should not include the "4" prefix. While opening the file using some HEX editor, I've seen that the string actually also includes: '\x00\x01' and only then '\x34' ("4") My guess is this is some kind of pointer to a special section, or something of the sorts, because many other strings include "3" and other numbers (and even characters).

Would appreciate any information in the matter Thanks!

1 Answers

The prefixes OP is seeing are KERN_<LEVEL> prefixes. These are special string literals to be added before the main printk format specifier, using C's concatenation of adjacent string literals. For example:

    printk(KERN_ERR "Something has gone wrong!\n");

From kernel version 3.6 onwards, these KERN_<LEVEL> prefix macros are defined in "include/linux/kern_levels.h" and begin with the ASCII SOH character "\001" followed by the log level as an ASCII digit for the numeric levels, or some other ASCII character for special meanings. The string for KERN_DEFAULT changed from "\001" "d" to "" (empty string) in kernel version 5.1. The string for KERN_CONT changed from "" (empty string) to "\001" "c" in kernel version 4.9.

From kernel version 2.6.37 to 3.5.x, the KERN_<LEVEL> prefix macros were defined in "include/linux/printk.h" and used a different format with the level specified between angle brackets, for example KERN_WARNING was defined as "<4>", KERN_DEFAULT was defined as "<d>", and KERN_CONT was defined as "<c>".

Besides printk, there are other macros for generating kernel logs, some of which specify the KERN_<LEVEL> part implicitly. OP's example from "lib/nlattr.c":

        pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
                    rem, current->comm);

Here, the pr_warn_ratelimited macro is defined in "include/linux/printk.h" as:

#define pr_warn_ratelimited(fmt, ...)                   \
    printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)

There is a lot going on there, but pr_fmt(fmt) is one or more string literals including fmt macro parameter, so the string passed to printk_ratelimited is constructed from some concatenated string literals beginning with those from the expansion of KERN_WARNING.

Related