The ELF Virus Writing HOWTO: sparc-sunos5.7
Prev |  | Next

# 1. Variables & packages

| Once it hits the fan, the only rational choice is to sweep it up, package it, and sell it as fertilizer.
| anonymous

This document tries to cover multiple platforms through conditional compilation. There is a `configure.pl` that determines the host type and sets up a `config.sh` containing environment variable definitions. There also are equivalent `config.csh`, `config.h`, `config.mak`, `config.sed`, and `config.xml`. The `Makefile` then uses individual sub-directories for each platform. The name of these directories (and some other platform specific values) is retrieved through environment variables. The directory structure is not without meaning.

- `src/` is for source code, i.e. text files written and maintained by humans.

- `pre/sparc-sunos5.7/` is directory `src/` pre-processed with `config.sed`. In `pre/` all program names are absolute. Magic numbers and platform specific constants are verbatim.

- `tmp/sparc-sunos5.7/` is the only place to hold binaries, i.e. executables and `.o` files.

- `out/sparc-sunos5.7/` is for the output of executables, hex dumps, disassembly listings, text processing.

## 1.1. Variables prefixed with `TEVWH_`

The files in `src/` are obfuscated with obscene amounts of variable references like `${TEVWH_ELF_BASE}` or even `${TEVWH_PATH_LS}`. I admit that using variables instead of plain program names makes shell scripts harder to read. But this is necessary to maintain a minimum level of reproducibility on SunOS. Anyway, directory `pre/` makes that `10000` and `/usr/xpg4/bin/ls`, so you will probably never encounter this syntax nightmare. An almost complete list of used variables is given below.

Table 1. Variables prefixed with `TEVWH_`

Variable name | Value on this platform | Variable name | Value on this platform
--- | --- | --- | ---
`AFLAGS` | `-I . -D _ASM` | `ARCH` | `sparc`
`ASM` | `sparc_SunOS_att` | `ASM_COMMENT` | `!`
`ASM_FLAVOR` | `` | `ASM_RETURN` | `(restore|unimp)`
`ASM_STYLE` | `att` | `BYTE_ORDER` | `M`
`CFLAGS` | `-Wall -O1 -I . -I out/sparc-sunos5.7 -D NDEBUG` | `ELF_ADDR` | `Elf32_Addr`
`ELF_ADDR_SIZE` | `32` | `ELF_ALIGN` | `10000`
`ELF_BASE` | `10000` | `ELF_EHDR` | `Elf32_Ehdr`
`ELF_MAGIC` | `10001` | `ELF_OFF` | `Elf32_Off`
`ELF_PAGE_SIZE` | `1000` | `ELF_PHDR` | `Elf32_Phdr`
`ELF_SHDR` | `Elf32_Shdr` | `HOSTTYPE` | `SunOS/sparc`
`OS_CODE` | `sparc-sunos5.7` | `OS_NAME` | `SunOS 5.7`
`OS_PKG_SYS` | `SunOS` | `OS_VERSION` | `5.7`
`OUT` | `out/sparc-sunos5.7` | `OUT_XML` | `out/sparc-sunos5.7/xml`
`PRE` | `pre/sparc-sunos5.7` | `PROC_EXE` | `/proc/self/object/a.out`
`TMP` | `tmp/sparc-sunos5.7` | `UNAME` | `SunOS`

Note that hexadecimal shell variables actually miss the leading `0x` to simplify calculations with `bc`. These values are also available to C code through corresponding `#define` statements after `#include <config.h>`. Values are not quoted, but hexadecimal values are correctly prefixed by `0x`.

## 1.2. Variables prefixed with `TEVWH_PATH_`

Table 2. Variables prefixed with `TEVWH_PATH_`

Variable name | Value on this platform | Variable name | Value on this platform
--- | --- | --- | ---
`BASH` | `/usr/bin/bash` | `BC` | `/usr/bin/bc`
`CAT` | `/usr/bin/cat` | `CC` | `/usr/local/bin/gcc`
`CHMOD` | `/usr/bin/chmod` | `CSH` | `/usr/bin/csh`
`CUT` | `/usr/bin/cut` | `DD` | `/usr/bin/dd`
`DISTID` | `/etc/release` | `DU` | `/usr/xpg4/bin/du`
`DUMP` | `/usr/ccs/bin/dump` | `ECHO` | `/usr/bin/echo`
`ELFDUMP` | `/usr/ccs/bin/elfdump` | `EXPAND` | `/usr/bin/expand`
`FILE` | `/usr/bin/file` | `FIND` | `/usr/bin/find`
`FMT` | `/usr/bin/fmt` | `GDB` | `/usr/local/bin/gdb`
`GREP` | `/usr/xpg4/bin/grep` | `KILL` | `/usr/bin/kill`
`LD` | `/usr/local/bin/ld` | `LDD` | `/usr/bin/ldd`
`LS` | `/usr/xpg4/bin/ls` | `MAKE` | `/usr/xpg4/bin/make`
`MAN` | `/usr/bin/man` | `MT` | `/usr/bin/mt`
`NICE` | `/usr/xpg4/bin/nice` | `NM` | `/usr/xpg4/bin/nm`
`OBJDUMP` | `/usr/local/bin/objdump` | `OD` | `/usr/xpg4/bin/od`
`PERL` | `/usr/bin/perl` | `PKGCHK` | `/usr/sbin/pkgchk`
`PKGINFO` | `/usr/bin/pkginfo` | `READELF` | `/usr/local/bin/readelf`
`SED` | `/usr/xpg4/bin/sed` | `SH` | `/usr/xpg4/bin/sh`
`SORT` | `/usr/xpg4/bin/sort` | `STRACE` | `/usr/bin/strace`
`STRINGS` | `/usr/bin/strings` | `STRIP` | `/usr/local/bin/strip`
`TAIL` | `/usr/xpg4/bin/tail` | `TEE` | `/usr/bin/tee`
`TR` | `/usr/xpg4/bin/tr` | `TRUSS` | `/usr/bin/truss`
`UNIQ` | `/usr/bin/uniq` | `WC` | `/usr/bin/wc`
`XARGS` | `/usr/bin/xargs` |  |

## 1.3. The name of the X

Command: src/packages/uname.sh

    #!/bin/sh
    uname -mprs
    echo "[${HOSTTYPE}]"
    echo "[${VENDOR}]"
    echo "[${OSTYPE}]"
    echo "[${MACHTYPE}]"

Output: out/sparc-sunos5.7/packages/uname

    SunOS 5.7 sun4m sparc
    [sparc]
    []
    [solaris2.7]
    [sparc-sun-solaris2.7]

While most Linux distributions ship with slightly modified kernels, no vendor has ever dared to mess with the values returned by uname(2). Instead the tradition of distribution dependent text files in directory `/etc` was established.

Command: pre/sparc-sunos5.7/packages/distid.sh

    #!/usr/xpg4/bin/sh
    # We need this script to copy the id-file into directory out/.
    # I use many machines to test examples, but only one to render the document.

    /usr/bin/cat /etc/release

Output: out/sparc-sunos5.7/packages/distid

                          Solaris 7 s998s_SunServer_21al2b SPARC
               Copyright 1998 Sun Microsystems, Inc.  All Rights Reserved.
                                Assembled 06 October 1998

## 1.4. The owner of files

One of the lesser known features of package management is self-reflection. How do we determine the package owning a file if we have the canonical path name?

The package format used by SunOS 5.7 is called "pkg Datastream (SVR4)" by a recent file(1). Relevant information is stored as a set of text files in directory `/var/sadm`. For each installed package there is a sub directory in `/var/sadm/pkg` that includes a description.

Source: pre/sparc-sunos5.7/packages/SunOS/du.sh

    #!/usr/xpg4/bin/sh
    /usr/bin/file /var/sadm/* | /usr/bin/expand -t 32
    /usr/xpg4/bin/ls -l /var/sadm/install/contents
    /usr/xpg4/bin/du -s /var/sadm/pkg /var/sadm/install

Output: out/sparc-sunos5.7/packages/du

    /var/sadm/README:               English text
    /var/sadm/install:              directory
    /var/sadm/install_data:         directory
    /var/sadm/patch:                directory
    /var/sadm/pkg:                  directory
    /var/sadm/softinfo:             directory
    /var/sadm/system:               directory
    -rw-r--r--   1 root     other    2993078 Dec  4 19:22 /var/sadm/install/contents
    79594 /var/sadm/pkg
    5882 /var/sadm/install

The first half of a query does a linear search trough text file `/var/sadm/install/contents`. The tricky part is to find the canonical name of a file. A lot of tools are provided in two different variations. The POSIX confirming ones are located in directory `/usr/xpg4/bin/`, as described by xpg4(5). The classic tools are installed in `/usr/bin`. But since `/bin` is a symbolic link to `/usr/bin`, a naive which(1) can give unexpected results.

Source: pre/sparc-sunos5.7/packages/SunOS/simple.sh

    #!/usr/xpg4/bin/sh
    query='/bin/sed /usr/bin/sed /usr/xpg4/bin/sed'
    /usr/xpg4/bin/ls -li ${query}
    /usr/sbin/pkgchk -l -p "${query}"

Output: out/sparc-sunos5.7/packages/simple

        279597 -r-xr-xr-x   1 bin      bin        27368 Oct  6  1998 /bin/sed
        279597 -r-xr-xr-x   1 bin      bin        27368 Oct  6  1998 /usr/bin/sed
        317464 -r-xr-xr-x   1 bin      bin        28068 Sep  1  1998 /usr/xpg4/bin/sed
    Pathname: /usr/bin/sed
    Type: regular file
    Expected mode: 0555
    Expected owner: bin
    Expected group: bin
    Expected file size (bytes): 27368
    Expected sum(1) of contents: 18227
    Expected last modification: Oct 06 09:45:42 1998
    Referenced by the following packages:
    	SUNWcsu
    Current status: installed

    Pathname: /usr/xpg4/bin/sed
    Type: regular file
    Expected mode: 0555
    Expected owner: bin
    Expected group: bin
    Expected file size (bytes): 28068
    Expected sum(1) of contents: 40692
    Expected last modification: Sep 01 13:04:13 1998
    Referenced by the following packages:
    	SUNWxcu4
    Current status: installed

The second part of the query works on a single file, `/var/sadm/pkg/*/pkginfo`:

Source: pre/sparc-sunos5.7/packages/SunOS/version.sh

    #!/usr/xpg4/bin/sh
    pkg=$( /usr/sbin/pkgchk -l -p /usr/xpg4/bin/sed \
    | /usr/xpg4/bin/grep -v '^[A-Z]' )
    /usr/bin/pkginfo -x ${pkg}

Output: out/sparc-sunos5.7/packages/SunOS/version

    SUNWxcu4        XCU4 Utilities
                    (sparc) 11.7.0,REV=1998.09.01.04.16

## 1.5. The source of man-pages

Option `-a` of `man` returns all matching entries, not just the lowest section. This behavior is identical between platforms.

Command: pre/sparc-sunos5.7/packages/man-all/SunOS.sh

    #!/usr/xpg4/bin/sh
    /usr/bin/man -a -d kill \
    | /usr/xpg4/bin/sed -ne 's/.*\<formatted = //p'

Output: out/sparc-sunos5.7/packages/man-all

    /usr/share/man/cat1/kill.1
    /usr/share/man/cat2/kill.2

Requesting a specific section requires option `-s `section`` on SunOS, while Linux and FreeBSD prefer a plain ``section``.

Command: pre/sparc-sunos5.7/packages/man-section/SunOS.sh

    #!/usr/xpg4/bin/sh
    /usr/bin/man -d -s 2 kill \
    | /usr/xpg4/bin/sed -ne 's/.*\<formatted = //p'

Output: out/sparc-sunos5.7/packages/man-section

    /usr/share/man/cat2/kill.2

## 1.6. Verifying installed packages

This chapter is not about checking the integrity of package files. See Intrusion detection systems for a general introduction.

SunOS uses checksums based on sum(1). pkgchk(1) lets you verify everything, complete packages or a list of files specified with option `-i `listfile``. Diagnostics are written to stderr and no news is good news.

Command: pre/sparc-sunos5.7/packages/SunOS/verify.sh

    #!/usr/xpg4/bin/sh
    pkg=$( /usr/sbin/pkgchk -l -p /etc/profile \
    | /usr/xpg4/bin/grep -v '^[A-Z]' )
    /usr/bin/echo pkg=[${pkg}]
    /usr/sbin/pkgchk ${pkg} 2>&1 | /usr/xpg4/bin/sed 11q
    /usr/bin/echo status=$?

Output: out/sparc-sunos5.7/packages/verify

    pkg=[ SUNWcsr ]
    ERROR: /etc/default/init
        file size <219> expected <605> actual
        file cksum <18231> expected <48341> actual
    ERROR: /etc/device.tab
        file size <1207> expected <1998> actual
        file cksum <37074> expected <37523> actual
    ERROR: /etc/devlink.tab
        group name <sys> expected <other> actual
        file size <4142> expected <4276> actual
        file cksum <38129> expected <50918> actual
    ERROR: /etc/dgroup.tab
    status=0

Option `-n` is advertised as "Do not check volatile or editable files". With option `-d `package_file`` you can verify against the checksums included in a package file, e.g. on the installation CD.

Prev | Home | Next
The ELF Virus Writing HOWTO |  | The magic of the Elf