Saturday, November 27, 2010

Make A Tiny Linux Distribution

Who hasn't wanted their own tiny Linux Distro that can run from a livecd?  Here is how to make one....



First things first, you will need a Linux system to build from.

Root Filesystem:
  1.  Create a new folder that will become the root filesystem for your new CD; I named mine rootfs.
  2. In rootfs add these folders: bin, dev, etc, proc, etc/init.d
  3. Download and build Busybox.  You want it to be statically linked, when you eventually compile it there should be an executable in the busybox build folder called busybox: run a file command on it, it should say something like this: 

    busybox: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.15, stripped
     

    Statically linked meaning that it has no dependencies, and stripped meaning that  all of the extra debugging code has been removed; this is what you want.
  4. Copy the Busybox executable to the bin folder of your new root.  In a terminal started in the bin folder run ./busybox  a list will be shown of all the functions available, we need to link all of these options to the busybox executable so the system can find them; Python to the rescue!  Just copy and paste all of the commands in to the appropriate location in the following script, then run it in a python interpriter (in the bin directory):

    import os

    names = '''[, [[, acpid, addgroup, ...and all the rest...'''

    names = names.replace(" ", "")
    names = names.replace("\n", "")
    names = names.replace("\t", "")

    names = names.split(",")

    for name in names:
    os.system("ln busybox "+name) #Link all of the programs to busybox
    </pre>


  5. Now we need to build the most basic of devices, we will need a console, a null device, a ramdisk and a tty. cd to the dev folder and run:
    sudo mknod console c 5 1
    sudo mknod null c 1 3
    sudo mknod ram0 b 1 0
    sudo mknod tty c 5 0
    This will create all of the devices.
  6. Three more files and the root filesystem will be complete: fstab, inittab, and rcS.
  7. fstab holds general information for the filesystems all it needs to do here is to mount the special filesystem proc:

    # /etc/fstab: static file system information.
    #
    #
    proc /proc proc defaults 0 0


  8. inittab is run by the init program, this should at minimum provide a way to shutdown the computer and the progrm to be run on startup (a login would be nice!)

    #/etc/inittab for linux (SysV)
    #Man page http://www.netadmintools.com/html/5inittab.man.html
    #Busybox inittab help: http://linuxembedded.blogspot.com/2006/11/understanding-busybox-inittab.html

    ::sysinit:/etc/init.d/rcS

    ::askfirst:/bin/sh

    # Stuff to do before rebooting or shutting down
    ::ctrlaltdel:/bin/reboot
    ::shutdown:/bin/umount -a -r
    ::shutdown:/bin/swapoff -a
     
  9. rcS is a script that starts all of your other stuff after inittab is run, start your daemons here and mount your filesystems.  You can see it is called in the /etc/inittab file right on startup.  It should be placed in the /etc/init.d folder.

    #!/bin/sh
    mount -a #Mount all of the filesystems in /etc/fstab

  10. Your root file-system is done, congratulations.
LiveCD:
Now we need to build the system in to a real LiveCD so it can be run from your favorite computer natively.
  1. Make a new folder outside of the root and name it livecd, inside this folder you need the folder ISOLINUX, and inside that put another folder named LINUX.
  2. ISOLINUX is a bootloader that runs from livecds to bootstrap your filesystem and the Kernel download the latest version.  I used version 4.03.
  3. Extract the file core/isolinux.bin to your ISOLINUX directory.
  4. Create the configuration file for ISOLINUX in the ISOLINUX directory and name it ISOLINUX.CFG.  Its contents should look like this:

    TIMEOUT 20
    DEFAULT linux
    LABEL linux
    KERNEL linux/bzimage
    APPEND root=/dev/ram0 initrd=fs

    This tells ISOLINUX to load the Linux kernel in the LINUX directory with the initial filesystem fs. You have created neither.
     
  5. Create a bzipped Linux kernel place it in the linux directory and name it bzimage (beyond the scope of this article).
  6. Make the initial file-system from the rootfs you created earlier by changing to the directory just outside of the romfs and run the command: genromfs -d rootfs -f fs  this will package up your root filesystem in to an image the Kernel can read.  Copy the created file in to the ISOLINUX folder.
  7. Now package everything together by changing to the directory just outside the iso folder by running:
    mkisofs -o output.iso    -b ISOLINUX/isolinux.bin -c ISOLINUX/boot.cat    -no-emul-boot -boot-load-size 4 -boot-info-table    cd
Done!  Start it up in Virtualbox.

Sunday, November 21, 2010

Make A Hackintosh

Sometimes the best tool for a job is a Mac, chiefly when you are doing testing for your Mac users.  For some reason the people at Apple computer company vastly overvalue their computers, they can still easily charge four times what any other manufacturer would for the same hardware.  Because of this, many developers cringe at the thought of supporting Apple computers.  Never fear though, Hacintoshes are quite easy to make nowadays, read on to find out how.

Materials:
  • Snow OSX Universal
  • An old Intel computer
Procedure:
  1. Download and burn Snow OSX Universal, you know where to find it....
  2. Put it in your computer and boot from the CD.
    1. If you get a cryptography error try booting in to safe mode, that will sometimes work around the error.
  3. Once the CD boots create a Mac Journaled file-system on your computer using the disk utility (it is in one of the menus at the top).
  4. Finish the install.
  5. Reboot and enjoy.  Or maybe not, as sometimes with laptops the OS removes drivers after the first shutdown, like those for your mouse and keyboard; maybe you should shut down by holding the power button if this happens to you.
Conclusion:
Testing your cross platform applications can be a mess, but made a little cheaper by using this method, as long as you don't mind the pain of playing with a half working Mac system.  But hey, who doesn't like tinkering with operating systems?

Wednesday, November 17, 2010

Windows Recovery

There is a time in every computer lovers life where you find out that Windows has gone awry.  It may not even be your computer, if you are fortunate enough to not need a Windows partition, but how many of us are really that lucky?  Here are a set of tools that can help you out in those situations:


Prevention:
It is unlikely that you are actually at this step, but next time you install Windows (or get a new computer) it may be a good idea to start this way.
  1. Save the product key, I swear those stickers are designed to wear off.
  2. Save all the other hidden keys using The Magical Jellybean Keyfinder.
  3. Create a backup disk, many new systems come with a backup partition, but I still recommend creating backup DVDs, your computer should come with some software to do this, but if you don't trust it, you can always use good ol' partimage, or if you are feeling really adventurous and have a drive of the same size as your original, dd.
When your computer goes bad next it should be a simple thing to just re-install it from source without needing to go through the dreaded blue-screen Windows XP setup process.

Why is it that Win 9x had a graphical setup and with XP they digressed in to something you might expect from DOS?

Current Fixes:
Bootloader Problems:
Sometimes [read always] if you play with bootloaders on your system things get mucked up.  They don't play nicely with each other, and oftentimes not even with themselves.  I have found that you can quickly fix this by either installing grub from your favorite Linux distro, or using the files in fix NTLDR.

Malicious Software:
After the machine is running and before attempting cleanup all of the malware must be removed.  This can be done by using an AV on the machine, but oftentimes these are slow and can be shut down by the malware itself, if you can boot from a Linux livecd with an antivirus on it, like Clam, and have it scan first.

Startup Tasks:
Do you really need Adobe to search for updates every time your computer starts?  You probably don't even need Adobe Reader at all, but we'll get to that later.  Once your machine is free from malware use CCleaner to remove those useless startup entries.  It does have a standalone version too.  If you don't know what something does, a fast Google on the name is usually enough to help you decide.

Unnecessary Programs:
Now we come to Adobe Reader and crowd.  Adobe Reader is plagued with security vulnerabilities and is slow, why not go with Foxit?  Last time I checked it takes 20Mb vs 200Mb for Adobe.

Still using Internet Explorer?  I hope not, if you are a sandboxing nut you should try Chrome, or better yet use Firefox.  Why do I say Firefox is better?  The add-ons are a giant plus, it has fewer new security vulnerabilities, and uses slightly less ram than Chrome on the systems I have compared them on.

You might also want to disable that eye candy too, trust me it helps.

Overall:
Remember that Windows updates are your friend, unless you are trying to catch a cold.  Yes sometimes they install stuff like Genuine Advantage, but that doesn't matter because your copy is legit, right?

System Rescue Cd is a great livecd utility that can help with Windows troubleshooting, it even has a snazzy GUI!

Friday, November 12, 2010

Espeak Fun

Make the entire GNU GPL be read to the user when they log on to the computer!  This is a rather simple hack, but could be immensely funny when done to a friend you don't mind losing. 

Just add the command:
espeak < /usr/share/common-licenses/GPL-2
To the user's startup applications on Ubuntu.

Maybe you could play with adding netcat support so you could just talk to them whenever you wanted.

Monday, November 8, 2010

Making Very Simple Honeypots in Python

If you've ever wondered how Honeypots work, or needed a small implementation of a standard protocol (like SMTP) to test your program on; Python is the answer.  This tutorial will show you how to write a simple implementation of a protocol in 100 lines of Python!
Essentially what you need three things to create a simple honeypot:
  • A way to listen
  • A way to log
  • A way to answer
The listener will wait for connections from an outside source, then depending on the protocol either wait for information or send some initial information.  Each time the client sends some data the program will look up how to answer, then send back the answer.  The logger should document the entire conversation.

The entire code is at the end, but first I'll go over each bit:

#!/usr/bin/env python
import socket
import time

First you will need two basic imports, socket is used to create TCP/UDP sockets on your system, and time is used for logging (you did expect the logfiles to have time right?)

Next we need some default variables:

TCP_IP = socket.gethostname()&nbsp; #Bind externally 
TCP_PORT = 25&nbsp; #25 is the standard for smtp.
BUFFER_SIZE = 1024
LOG_FILENAME = "SMTP.log"

The IP here is actually the hostname for your computer, this makes sure that when the socket is bound it becomes externally visible.  The BUFFER_SIZE could be smaller, but slows the program down because each time the buffer fills the program assumes it is your turn to talk back.  Obviously the log file will be stored in a file named SMTP.log .

Next we define a class called SMTP.  In it will be four functions, start, proc_data, log and log_time.
The log function will open the log file, write the given input and close, the log_time function will output the current time to the logfile, the proc_data function will parse data received from the client and return a response.  Finally the start function will create the socket, listen for connections, log data, and return responses.

log_time function:
def log_time(self): 
'''Logs the current time.'''
self.log('Time UTC: ' + str(time.asctime(time.gmtime())) + "\n")
self.log('Time Local: ' + str(time.asctime(time.localtime())) + "\n")

The function logs both UTC (GMT) time and Local time to provide you and anyone you send your logs to information about the connection.

log function:

def log(self, data):
'''Logs any data sent to the file specified by LOG_FILENAME.'''
print str( data.replace("\n", "") ) #Give visual feedback.

log_file = open(LOG_FILENAME, 'a')
log_file.write( str(data) )
log_file.close()

This function simply opens the logfile writes to it and closes it, the print statement is for visual feedback in the terminal, this is handy while testing.


proc_data function:
def proc_data(self, data):
''' Processes the data. '''
data = data.replace("\n", " ")
data = data.replace("\r", " ")
data_array = data.split(" ")
#Do HELO
if data_array[0] == "HELO":
try:
return "250 Hello " + data_array[1] + ", I am glad to meet you\n"
except:
return "250 Hello, I am glad to meet you\n"

#I added EHLO for newer clients.
if data_array[0] == "EHLO":
return "250 SIZE 1000000\n"

if data_array[0] == "MAIL":
return "250 Ok\n"

if data_array[0] == "RCPT":
return "250 Ok\n"

if data_array[0] == "DATA":
return "354 End data with <CR><LF>.<CR><LF>\n"

if data_array[0] == "." or data_array[-1].endswith("."):
return "250 Ok\n"

if data_array[0] == "RSET":
return "250 Ok\n"

if data_array[0] == "QUIT":
return "221 Bye\n"

if data_array[0] == "HELP": #I learned this one from the Gmail servers.
return "214 http://www.ietf.org/rfc/rfc2821.txt\n"
else:
#Return nothing if the request was unintelligible, this
#usually means that the user is inputting data.
return ""

This function is the real workhorse of the program, it first removes all newlines and carriage returns; this is important for parsing.  It then splits the client's information and uses the first part to figure out what the client wanted and returns a fake response based off that information.  I used if statements because they were more readable than a large dictionary.  I implemented the main commands from the RFC 2821 (SMTP).  Most of the commands are the same HELO should be taken note of though, many times a connector will give you their name, if so it is customary to return it to them, although the second return would be just fine.


start function:

def start(self):
'''Starts the SMTP honeypot and gets it listening.'''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind( (TCP_IP, TCP_PORT) )
s.listen(1)

while 1:#Accept Unlimited Connections
try: #If the connection closes before ready it will cause an error.
conn, addr = s.accept()

#Begin Log
self.log( "\n\n\n" )
self.log( "=" * 80 + "\n" ) #Log a horizontal separator.
self.log( 'Connection Address: ' + str(addr) + "\n" )

self.log_time()

#Send the headers
self.log("220 smtp.example.com ESMTP Postfix\n")
conn.send("220 smtp.example.com ESMTP Postfix\n")
while 1: #Accept unlimited data from a connection.
#Receive data
data = conn.recv(BUFFER_SIZE)
self.log(data)

if not data: break

data = self.proc_data( data )
self.log(data)
conn.send(data)

#Close on bye
if data.startswith("221"):
break
self.log("Connection Closed\n")
self.log_time()

conn.close()
except: #End Except
self.log("Connection error, possibly a portscan.")
self.log_time()

NMAP or other portscanners on your machine while this program is running it will cause an exception that is caught because portscanners don't normally cleanly exit.

Example Session:

220 smtp.example.com ESMTP Postfix
HELO onehourhacks.blogspot.com
250 Hello onehourhacks.blogspot.com, I am glad to meet you
MAIL FROM:<joe@onehourhacks.blogspot.com>
250 Ok
RCPT TO:<someone@example.com>             
250 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: "Joe" <joe@onehourhacks.blogspot.com>
To: "Someone" <someone@example.com>
Subject: Test message

Hello Someone.
This is a test message.
Your friend,
Joe
.
250 Ok
QUIT
221 Bye


The server's responses are in italics.  You may notice that the server didn't say anything during the DATA transmission, this is because it didn't recognize any of the first words, Hello, This, Your, Joe, Subject:, To:, or From:.  If I had typed HELO as the beginning word on a line, the server would have sent another HELO message, this tells any spammers right away that they are dealing with a fake system, however this is unlikely to happen because a) most of the spam sent is from automated services, and they don't have the time to check for reality, and b) it is quite unlikely that any of these lines occur in normal email.

If you want to preform more extensive tests on the server hook up your mail client to it, then attempt to send some mail.

Source Code:
#!/usr/bin/env python
'''
Copyright (c) 2010 Joseph Lewis &lt;joehms22@gmail.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
'''
import socket
import time

TCP_IP = socket.gethostname() #Bind externally
TCP_PORT = 25 #25 is the standard for smtp.
BUFFER_SIZE = 1024
LOG_FILENAME = "SMTP.log"

class SMTP():
''' This class is for creating a fake SMTP server, but is may be only
convincing to novices or bots. Hey I like bots though, and novices.'''

def start(self):
'''Starts the SMTP honeypot and gets it listening.'''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind( (TCP_IP, TCP_PORT) )
s.listen(1)

while 1:#Accept Unlimited Connections
try: #If the connection closes before ready it will cause an error.
conn, addr = s.accept()
self.log( "\n\n\n" )
self.log( "="*80+"\n" )
self.log( 'Connection Address: ' + str(addr) + "\n" )
self.log_time()

#Send the headders
self.log("220 smtp.example.com ESMTP Postfix\n")
conn.send("220 smtp.example.com ESMTP Postfix\n")
while 1: #Accept unlimited data from a connection.
#Receive data
data = conn.recv(BUFFER_SIZE)
self.log(data)

if not data: break

data = self.proc_data( data )
self.log(data)
conn.send( data )

#Close on bye
if data.startswith("221"):
break
self.log("Connection Closed\n")
self.log_time()

conn.close()
except: #End Except
self.log("Connection error, possibly a portscan.")
self.log_time()

def log_time(self):
'''Logs the current time.'''
self.log('Time UTC: ' + str(time.asctime(time.gmtime())) + "\n")
self.log('Time Local: ' + str(time.asctime(time.localtime())) + "\n")

def log(self, data):
'''Logs any data sent to the file specified by LOG_FILENAME.'''

print str( data.replace("\n", "") ) #Give visual feedback.

log_file = open(LOG_FILENAME, 'a')
log_file.write( str(data) )
log_file.close()

def proc_data(self, data):
''' Processes the data. '''
data = data.replace("\n", " ")
data = data.replace("\r", " ")
data_array = data.split(" ")
#Do HELO
if data_array[0] == "HELO":
try:
return "250 Hello "+data_array[1]+", I am glad to meet you\n"
except:
return "250 Hello, I am glad to meet you\n"

#I added EHLO for newer clients.
if data_array[0] == "EHLO":
return "250 SIZE 1000000\n"

if data_array[0] == "MAIL":
return "250 Ok\n"

if data_array[0] == "RCPT":
return "250 Ok\n"

if data_array[0] == "DATA":
return "354 End data with &lt;cr&gt;&lt;lf&gt;.&lt;cr&gt;&lt;lf&gt;\n"

if data_array[0] == "." or data_array[-1].endswith("."):
return "250 Ok\n"

if data_array[0] == "RSET":
return "250 Ok\n"

if data_array[0] == "QUIT":
return "221 Bye\n"

if data_array[0] == "HELP": #I learned this one from the Gmail servers.
return "214 http://www.ietf.org/rfc/rfc2821.txt\n"
else:
#Return nothing if the request was unintelligible, this
#usually means that the user is inputting data.
return ""

if __name__ == "__main__":
SMTP().start()

Saturday, November 6, 2010

5.5 Gram Backpacking Stove

Backpacking stoves are insanely expensive, the first hit I got on that search was an 8.5oz (250g) stove for $75.00 (€53).  You can make a 0.2oz (5.5g) stove at home, from two aluminum cans, for free.

Actually the free part was somewhat misleading, you actually will need to pay $0.25 for the quarter.  The stove runs on alcohol, depending on the type your efficiency will vary.

Materials:
  • Two aluminum cans.
  • Pushpin
  • A Quarter
  • A sharpie
  • An utility knife.
  • A textbook.
  • A ruler
  • Tweezers / needle-nose pliers
Optional (aesthetic):
  • Sandpaper
Procedure:
  1. If you are going the sandpaper route, sand off the bottom inch of the paint on the cans, this is much easier to do while the cans are full and still have pressure, otherwise they will dent while you are sanding them, which is not good for the end result. 
  2. Open your book and lay it on a table so when the sharpie is placed on it, the tip of the sharpie is one inch above the table.  Open the sarpie, and with it's tip extending past the edge of the book, rotate one of your cans so a circular line is drawn around the can one inch above the bottom.  Repeat for the other can.
    Sanded Can With Mark
  3. Use your utility knife to cut along the circle for both cans, this is easy to do if you use a similar method to marking the cans.  The blade should have a large area where it is touching the can to produce the most work as you rotate the can.
    Cutting The Can
  4. Continue rotating the can until either (a) the knife breaks through, or (b) you get tired; in the case of b cut in to the can along the indentation made by the knife and begin to pull the can apart, it should separate cleanly where you scored the surface.
    Completed Cans
  5. Crimp one of the cans using tweezers (or needle nose pliers).
    Crimped Bottom Half (Inner Part of Stove)
  6. This can should now fit inside the other, slide the tops together, then push evenly until the cans slide entirely in to each other.  If this is not done carefully one of the cans may split and you will need to make another.  From here on I'll call with the most visible surface area the outer can; the other will be the inner can.
  7. The outer can may extend past the bottom of the inner can, if this happens roll the bottom on a hard flat surface and the outer can will form a lip over the bottom.
    Before and After Rolling Bottom Edge
  8. In the top center of the outer can punch five holes closely together using the pushpin. You should be able to cover all of them easily with the quarter.
    Filling Holes
  9. Around the outside of the top can punch eight holes equadistant from each other, this is easier if you begin by punching two that are opposite each other.
    Finished Stove
  10. Your stove is done, to fill it pour alcohol in to the middle, the five holes you punched should easily allow it in to the can.  Cover the holes with the quarter.  
  11. To light you will first need to heat up the alcohol inside until it turns in to a gas and begins exiting the jets.  I do this by pouring a small amount of alcohol on a lid lighting it, and placing my stove in the lid.  A tealight might work as well.
  12. If lighting is difficult, add more jets.

Conclusions:
I have read some articles about the efficiency of these devices, and it appears that they can heat water at the same rate as more conventional stoves, however they tend to use more fuel, which may make them less desirable while backpacking.
You may want to experiment with the number of holes. or the height of the cans.