The Network is susceptible to security violations

RFC602 published in December 1973:

           "The Stockings Were Hung by the Chimney with Care"


The ARPA Computer Network is susceptible to security violations for at least
the three following reasons:

(1)  Individual sites, used to physical limitations on machine access, have
     not yet taken sufficient precautions toward securing their systems
     against unauthorized remote use.  For example, many people still use
     passwords which are easy to guess:  their fist names, their initials,
     their host name spelled backwards, a string of characters which are
     easy to type in sequence (e.g. ZXCVBNM).

(2)  The TIP allows access to the ARPANET to a much wider audience than
     is thought or intended.  TIP phone numbers are posted, like those
     scribbled hastily on the walls of phone booths and men's rooms.  The
     TIP required no user identification before giving service.  Thus,
     many people, including those who used to spend their time ripping off
     Ma Bell, get access to our stockings in a most anonymous way.

(3)  There is lingering affection for the challenge of breaking
     someone's system.  This affection lingers despite the fact that
     everyone knows that it's easy to break systems, even easier to
     crash them.

All of this would be quite humorous and cause for raucous eye
winking and elbow nudging, if it weren't for the fact that in
recent weeks at least two major serving hosts were crashed
under suspicious circumstances by people who knew what they
were risking; on yet a third system, the system wheel password
was compromised -- by two high school students in Los Angeles
no less.

We suspect that the number of dangerous security violations is
larger than any of us know is growing.  You are advised
not to sit "in hope that Saint Nicholas would soon be there".

via


Reading: Babylon's Ashes, Cryptonomicon

VR Shit

You'll be sick!


Reading: Babylon's Ashes, Cryptonomicon

Binary Image Analysis

I have gotten to the point with the MT76x0U driver where I need to load the firmware image onto the MCU. Unlike the older hardware on which the driver is based, the firmware image is much more complicated. The old images are 4KB and can be directly DMA'd across to the MCU, the newer image is around 80KB, contains 2 sections and the reference driver does a complicated dance to copy them across.

There is quite a lot of pointer magic in setting up the DMA buffers in the reference image, I need to understand the firmware layout to know what this is trying to accomplish.

First thing, binwalk is of no help:

$ binwalk mcu/bin/MT7610_formal_2.6.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
-------------------------------------------------------------------------------

The image size is:

$ ls -l 
-rw-r--r--  1 hacker hacker  80288 Dec 21 19:40 mcu/bin/MT7610_formal_2.6.bin

The reference code does some work to extract out build info from the 32 byte header, I put together this python script to do the same:

import sys
import struct

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("usage: {} firmware.bin".format(sys.argv[0]))
        exit()

    filename = sys.argv[1]
    data = None
    with open(filename, "rb") as f:
        data = f.read()

    print("Image size: {}".fomrat(len(data)))

#    ilm_len   4 bytes
#    dlm_len   4 bytes
#    fw_ver    2 bytes
#    build_ver 2 bytes
#
#    4 bytes of something?
#
#    build_time 16 byte str starting from byte 16 (base+16) """
    hdr = data[:32]

    ilm_len, dlm_len, fw_ver, build_ver, something, build_time = struct.unpack("<IIHH4s16s", hdr)

    print("ilm_len:    {}".format(ilm_len))
    print("dlm_len:    {}".format(dlm_len))
    print("fw_ver:     {}".format(fw_ver))
    print("build_ver:  {}".format(build_ver))
    print("something:  {}".format(something))
    print("build_time: {}".format(build_time))

    print("fw version: {}.{}.{}"
        .format(
            (fw_ver & 0xf000) >> 8,
            (fw_ver & 0x0f00) >> 8,
            fw_ver & 0x00ff))

I know from the reference driver that there are two images shipped in the firmware, called ILM and DLM ( accoring to this Instruction and Data Local Memory).

$ python3.5 parsefirmware.py mcu/bin/MT7610_formal_2.6.bin 
Image size: 80288
ilm_len:    68780
dlm_len:    11476
fw_ver:     30272
build_ver:  256
something:  b'Bv\x11\x02'
build_time: b'201308221655____'
fw version: 112.6.64

The build time is happily just an ascii string, the first output in strings

$ strings ../../mcu/bin/MT7610_formal_2.6.bin| head -n 5 
201308221655____H
s@!
ELq@'P
ELq@
<@!H

and easy to spot in a hexdump

$ head -c 64 ../../mcu/bin/MT7610_formal_2.6.bin| hexdump -C
00000000  ac 0c 01 00 d4 2c 00 00  40 76 00 01 42 76 11 02  |.....,..@v..Bv..|
00000010  32 30 31 33 30 38 32 32  31 36 35 35 5f 5f 5f 5f  |201308221655____|
00000020  48 00 00 78 48 00 00 1e  48 00 00 1c 48 00 00 1a  |H..xH...H...H...|
00000030  48 00 00 18 48 00 00 16  48 00 00 14 48 00 00 12  |H...H...H...H...|

The ILM and DLM sizes are also very useful, with the header they add up to the firmware size!

Image size = hdr_size + ilm_len + dlm_len
80288 = 32 + 68780 + 11476

Currently I think the reference driver skips some further data in the ILM, I need to see if there is documentation for the format so I can make an informed guess.


Reading: Babylon's Ashes, Cryptonomicon

Some Posters


Reading: Babylon's Ashes, Cryptonomicon

Tracing Call Graphs

Modern IDEs have a load of functionality to help trace function call and data accesses through large code bases. cscope is an interactive command line tool that helps with searching codebases based on C symbols. With cscope you can find all the callers of a function, every function a function calls, or by C type.

$ cd code/repo
$ cscope -R

Working on this wireless I have spent a lot of time digging down the callgraph with cscope manually figuring out how things tie together. Today I looked to see if there was a tool I could use to generate a callgraph from the cscope database files.

I found a stackoverflow thread with the recommendation of a shell script that could generate a dot file with the callgraph. The script is unfortunately very basic, rather that something to run against a code base it is a set of bash functions.

$ . ~/tmp/calltree.sh               # load functions in
$ _relate rt28xx_open RTUSBWriteMACRegister| dot2png out.png

The graph below was ( generated from this repo) took about 1 minute to generate on my reasonably fast laptop. You will need to install the graphviz tools to generate the png.

I had to make some modifications to get the script to run, here is my version:

#!/bin/bash

echo "loading calltree.sh functions"

#use cscope to build reference files (./cscope.out by default, use set_graphdb to override name or location)
set_graphdb() { export GRAPHDB=$1; }
unset_graphdb() { unset GRAPHDB; }
build_graphdb() { cscope -bkRu ${GRAPHDB:+-f $GRAPHDB} && echo Created ${GRAPHDB:-cscope.out}...; }

# cscope queries
lsyms() { cscope -R ${GRAPHDB:+-f $GRAPHDB} -L0 $1 | grep -v "<global>" | grep "="; }
fdefine() { cscope -R ${GRAPHDB:+-f $GRAPHDB} -L1 $1; }
callees() { cscope -R ${GRAPHDB:+-f $GRAPHDB} -L2 $1; }
callers() { cscope -R ${GRAPHDB:+-f $GRAPHDB} -L3 $1; }

# show which functions refer to a set of symbols
filter_syms() { local sym cscope_line
    while read -a sym; do
        lsyms $sym | while read -a cscope_line; do
            printf "${cscope_line[1]}\n"
        done
    done
}

# given a set of function names, find out how they're related
filter_edges() { local sym cscope_line
    while read -a sym; do
        fdefine $sym | while read -a cscope_line; do
            grep -wq ${cscope_line[1]} ${1:-<(echo)} &&
            printf "${cscope_line[1]}\t[href=\"${cscope_line[0]}:${cscope_line[2]}\"]\t/*fdefine*/\n"
        done
        callees $sym | while read -a cscope_line; do
            grep -wq ${cscope_line[1]} ${1:-<(echo)} &&
            printf "$sym->${cscope_line[1]}\t[label=\"${cscope_line[0]}:${cscope_line[2]}\"]\t/*callee*/\n"
        done
        callers $sym | while read -a cscope_line; do
            grep -wq ${cscope_line[1]} ${1:-<(echo)} &&
            printf "${cscope_line[1]}->$sym\t[label=\"${cscope_line[0]}:${cscope_line[2]}\"]\t/*caller*/\n"
        done
    done
}

# dump args one-per-line
largs() { for a; do echo $a; done; }
toargs() { local symbol
    while read -a symbol; do
        printf "%s " $symbol
    done
    echo
}

# present list of symbols to filter_syms properly
refs() { local tfile=/tmp/refs.$RANDOM
    cat ${1:+<(largs $@)} > $tfile
    filter_syms $tfile <$tfile | sort -u
    rm $tfile
}

# present list of function names to filter_edges properly
edges() { local tfile=/tmp/edges.$RANDOM
    cat ${1:+<(largs $@)} > $tfile
    filter_edges $tfile <$tfile
    rm $tfile
}

# append unknown symbol names out of lines of cscope output
filter_cscope_lines() { local cscope_line
    while read -a cscope_line; do
        grep -wq ${cscope_line[1]} ${1:-/dev/null} || echo ${cscope_line[1]}
    done 
}

# given a set of function names piped in, help spit out all their callers or callees that aren't already in the set
descend() { local symbol
    while read -a symbol; do
        $1 $symbol | filter_cscope_lines $2
    done
}

# discover functions upstream of initial set
all_callers() { local tfile=/tmp/all_callers.$RANDOM
    cat ${1:+<(largs $@)} > $tfile
    descend callers $tfile <$tfile >>$tfile
    cat $tfile; rm $tfile
}

# discover functions downstream of initial set
all_callees() { local tfile=/tmp/all_callees.$RANDOM
    cat ${1:+<(largs $@)} > $tfile
    descend callees $tfile <$tfile >>$tfile
    cat $tfile; rm $tfile
}

# all the ways to get from (a,b,...z) to (a,b,...z), i.e. intersect all_callers and all_callees of initial set
call_graph() { local tfile=/tmp/subgraph.$RANDOM; local args=/tmp/subgraph_args.$RANDOM
    cat ${1:+<(largs $@)} > $args
    cat $args | all_callers | sort -u > $tfile
    comm -12 $tfile <(cat $args | all_callees | sort -u)
    rm $tfile $args
}

# all functions downstream of callers of argument
all_callerees() { callers $1 | filter_cscope_lines | all_callees; }

# odd experimental set of calls that might help spot potential memory leaks
call_leaks() { local tfile=/tmp/graph_filter.$RANDOM
    all_callerees $1 | sort -u > $tfile
    comm -2 $tfile <(all_callers $2 | sort -u)
    rm $tfile
}

# wrap dot-format node and edge info with dot-format whole-graph description
graph() { printf "digraph iftree {\ngraph [rankdir=LR, ratio=compress, concentrate=true];\nnode [shape=record, style=filled]\nedge [color="navy"];\n"; cat | sort -u; printf "}\n"; }

# filter out unwanted (as specified in “~/calltree.deny”) and/or unnecessary edges
graph_filter() { local tfile=/tmp/graph_filter.$RANDOM
    cat > $tfile
    grep fdefine $tfile
    grep $1 $tfile | grep -v ~/calltree.deny | cut -f1,3
    rm $tfile
}

# how to invoke zgrviewer as a viewer
zgrviewer() { ~/bin/zgrviewer -Pdot $@; }
# how to invoke xfig as a viewer
figviewer() { xfig <(dot -Tfig $@); }
# how to create and view a png image
pngviewer() { dot -Tpng $@ -o /tmp/ct.png && gqview -t /tmp/ct.png; }

# specify a viewer
ctviewer() { pngviewer $@; }

# add color to specified nodes
colornodes() { (cat; for x in $@; do echo "$x [color=red]"; done;) }

# generate dot files
_upstream() { all_callers $1 | edges | graph_filter ${2:-caller} | colornodes $1 | graph; }
_downstream() { all_callees $1 | edges | graph_filter ${2:-callee} | colornodes $1 | graph; }
_upndown() { (all_callers $1; all_callees $1) | edges | graph_filter ${2:-callee} | colornodes $1 | graph; }
_relate() { call_graph $@ | edges | graph_filter callee | colornodes $@ | graph; }
_leaks() { call_leaks $1 $2 | edges | graph_filter ${3:-callee} | colornodes $1 $2 | graph; }

# generate dot files and invoke ctviewer
upstream() { _upstream $@ > /tmp/tfile; ctviewer /tmp/tfile; rm -f /tmp/tfile; }
downstream() { _downstream $@ > /tmp/tfile; ctviewer /tmp/tfile; rm -f /tmp/tfile; }
upndown() { _upndown $@ > /tmp/tfile; ctviewer /tmp/tfile; rm -f /tmp/tfile; }
relate() { _relate $@ > /tmp/tfile; ctviewer /tmp/tfile; rm -f /tmp/tfile; }
leaks() { _leaks $@ > /tmp/tfile; ctviewer /tmp/tfile; rm -f /tmp/tfile; }

# dot file conversions
dot2png() { dot -s36 -Tpng -o $1; }
dot2jpg() { dot -Tjpg -o $1; }
dot2html() { dot -Tpng -o $1.png -Tcmapx -o $1.map; (echo "<IMG SRC="$1.png" USEMAP="#iftree" />"; cat $1.map)  > $1.html; }

It is Sunday, so that makes seven days of writing .

Doing this I also found out about vim s cscope integration.

Reading: Babylon's Ashes, Cryptonomicon