Introduction
This article was written by Adam Palmer, a Linux Consultant. It covers the first few steps in basic Linux forensic work – investigating unknown files. Linux provides a range of powerful tools to investigate files and filesystems.
Preparing an Environment
First and foremost, before performing any kind of forensics work on Linux, it’s important to set up a usable environment. Even if you intend to perform ‘read only’ actions, and not run any binaries for example, buffer overflows and other exploit vectors have existed in the tools we’ll be using and so running them on maliciously crafted files could result in a system compromise.
If you intend to analyze files, I recommend using a sandboxed virtual machine with no networking access. The virtual machine should be destroyed and recreated as required. If you plan to analyze a hard disk, I recommend using a write blocker to ensure that nothing can physically be altered on the disk under investigation.
Finding File Type & Status
Using the `file’ utility, we can match the file’s header to a known database:
root@kali:~# file rack.png
rack.png: PNG image data, 576 x 576, 8-bit/color RGBA, non-interlaced |
root@kali:~# file rack.png
rack.png: PNG image data, 576 x 576, 8-bit/color RGBA, non-interlaced
Using the `stat’ utility, we can find out permissions, as well as disk, inode and meta information on the file:
root@kali:~# stat rack.png
File: `/opt/metasploit/apps/pro/ui/vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/contrib/rack.png'
Size: 23805 Blocks: 48 IO Block: 4096 regular file
Device: 801h/2049d Inode: 6165 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2014-12-04 23:45:51.087400697 +0000
Modify: 2013-04-17 20:50:40.000000000 +0100
Change: 2013-04-27 18:10:38.317049114 +0100
Birth: - |
root@kali:~# stat rack.png
File: `/opt/metasploit/apps/pro/ui/vendor/bundle/ruby/1.9.1/gems/rack-1.4.5/contrib/rack.png'
Size: 23805 Blocks: 48 IO Block: 4096 regular file
Device: 801h/2049d Inode: 6165 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2014-12-04 23:45:51.087400697 +0000
Modify: 2013-04-17 20:50:40.000000000 +0100
Change: 2013-04-27 18:10:38.317049114 +0100
Birth: -
Hexdump
Let’s confirm the `file’ output. According to Wikipedia’s entry on PNGs, a PNG begins with an 8-byte signature: 89 50 4E 47 0D 0A 1A 0A. Let’s use `hexdump’ to confirm this:
root@kali:~# hexdump -C -n8 rack.png
00000000 89 50 4e 47 0d 0a 1a 0a |.PNG....| |
root@kali:~# hexdump -C -n8 rack.png
00000000 89 50 4e 47 0d 0a 1a 0a |.PNG....|
Note the arguments provided. -C will print the ASCII data alongside the hexdecimal output, whilst -n8 displays 8 bytes.
Strings
Using `strings’, we are able to locate any ASCII printable strings within a file:
root@kali:~# strings rack.png
IHDR
sRGB
bKGD
pHYs
tIME
[...] |
root@kali:~# strings rack.png
IHDR
sRGB
bKGD
pHYs
tIME
[...]
In this case, there’s little of interest to see, however let’s look at running `strings’ on an executable binary:
root@kali:~# strings /bin/ls
[...]
Try `%s --help' for more information.
Usage: %s [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options too.
-a, --all do not ignore entries starting with .
-A, --almost-all do not list implied . and ..
[...] |
root@kali:~# strings /bin/ls
[...]
Try `%s --help' for more information.
Usage: %s [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options too.
-a, --all do not ignore entries starting with .
-A, --almost-all do not list implied . and ..
[...]
Interesting.. strings can be used to uncover hidden printable ASCII.
Linked Libraries
Using `ldd’, we can investigate any shared libraries that have been linked in:
root@kali:~# ldd /bin/ls
linux-gate.so.1 => (0xb77a7000)
libselinux.so.1 => /lib/i386-linux-gnu/libselinux.so.1 (0xb776c000)
librt.so.1 => /lib/i386-linux-gnu/i686/cmov/librt.so.1 (0xb7763000)
libacl.so.1 => /lib/i386-linux-gnu/libacl.so.1 (0xb7758000)
libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb75f5000)
libdl.so.2 => /lib/i386-linux-gnu/i686/cmov/libdl.so.2 (0xb75f1000)
/lib/ld-linux.so.2 (0xb77a8000)
libpthread.so.0 => /lib/i386-linux-gnu/i686/cmov/libpthread.so.0 (0xb75d8000)
libattr.so.1 => /lib/i386-linux-gnu/libattr.so.1 (0xb75d2000) |
root@kali:~# ldd /bin/ls
linux-gate.so.1 => (0xb77a7000)
libselinux.so.1 => /lib/i386-linux-gnu/libselinux.so.1 (0xb776c000)
librt.so.1 => /lib/i386-linux-gnu/i686/cmov/librt.so.1 (0xb7763000)
libacl.so.1 => /lib/i386-linux-gnu/libacl.so.1 (0xb7758000)
libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb75f5000)
libdl.so.2 => /lib/i386-linux-gnu/i686/cmov/libdl.so.2 (0xb75f1000)
/lib/ld-linux.so.2 (0xb77a8000)
libpthread.so.0 => /lib/i386-linux-gnu/i686/cmov/libpthread.so.0 (0xb75d8000)
libattr.so.1 => /lib/i386-linux-gnu/libattr.so.1 (0xb75d2000)
Tracing system calls
Using `strace’ we are able to trace system calls. If running an unknown binary, it is especially important to perform this step within a safe sandboxed environment. `strace’ sends its output to stderr, and so we’ll need to redirect that to stdout before being able to work with it using standard stream utilities such as `grep’. Let’s look at any open calls made when running `/bin/ls’:
root@kali:~# strace -f /bin/ls 2>&1|grep "open"
open("/etc/ld.so.cache", O_RDONLY) = 3
open("/lib/i386-linux-gnu/libselinux.so.1", O_RDONLY) = 3
open("/lib/i386-linux-gnu/i686/cmov/librt.so.1", O_RDONLY) = 3
[...] |
root@kali:~# strace -f /bin/ls 2>&1|grep "open"
open("/etc/ld.so.cache", O_RDONLY) = 3
open("/lib/i386-linux-gnu/libselinux.so.1", O_RDONLY) = 3
open("/lib/i386-linux-gnu/i686/cmov/librt.so.1", O_RDONLY) = 3
[...]
The listed entries are required libraries being opened
Further research
Further steps in debugging binaries can be achieved through `ltrace’, `gdb’, `objdump’ and `ndisasm’. Some of these tools have a significant learning curve however enable detailed debugging of unknown binaries