Didier Stevens

Thursday 24 July 2014

Stoned Bitcoin: My Analysis Tools

Filed under: Encryption,Forensics,Malware,My Software — Didier Stevens @ 0:00

The most interesting thing about Stoned Bitcoin for me, was to work out a method to find these Bitcoin transactions.

When this was mentioned on Twitter, I did a string search through the Bitcoin blockchain for string STONED: no hits.

Some time later I used my find-file-in-file tool. I got a copy of the Stoned Virus (md5 74A6DBB7A60915FE2111E580ACDEEAB7) and searched through the blockchain: again, no hits.

Although this means the blockchain doesn’t contain the start bytes of the Stoned Virus, it could still contain other parts of the virus. So I randomly selected a sequence of bytes from the virus, and used my tool again: I got a hit!

The command: find-file-in-file.py -s 0xFC 74A6DBB7A60915FE2111E580ACDEEAB7.vir blk00129.dat

The output:

0171c33d 00000010 (6%)
Remaining 244 (93%)

These are the bytes I found: 07 00 BA 80 00 CD 13 EB 49 90 B9 03 00 BA 00 01

How to find the transaction containing this byte sequence? A Bitcoin transaction (binary form) starts with a version number (unsigned 32 bit integer, little-endian), this number is currently 1. The ID of a transaction is the SHA-256 hash of the SHA-256 hash of all the bytes in the transaction, and this reversed and expressed in hexadecimal notation. Armed with this information, I was able to find the transaction: f09904aaa4fa4a8ec7da06f5e3d318a9b6a218e1a215f9307416fbbadf5a1c8e.

Finally, I updated my find-file-in-file tool so that I could do partial searches (and a couple of other features), and I wrote a Python script to parse and search the Bitcoin blockchain.

This is what you can do with the new version of find-file-in-file:

20140723-234257

Option partial allows you to search for parts of the file.

Option hexdump does a hexdump of the found bytes.

And options rangebegin and rangeend allow you to limit what you are searching for by specifying the range to search for. This is necessary for the Stoned Virus, because it ends with a sequence of 0x00 bytes, and such sequences are certainly not specific to the Stoned Virus, but omni-present in the blockchain.

Soon I will release these tools.

Monday 30 June 2014

Update: Stoned Bitcoin

Filed under: Encryption,Forensics,Malware,Update — Didier Stevens @ 0:04

kurt wismer pointed me to this post on pastebin after he read my Stoned Bitcoin blogpost. The author of this pastebin post works out a method to spam the Bitcoin blockchain to cause anti-virus (false) positives.

I scanned through all the Bitcoin transactions (until 24/06/2014) for the addresses listed in this pastebin post (the addresses represent antivirus signatures for 400+ malwares).

All these “malicious” Bitcoin addresses, designed to generate anti-virus false positives,  have been exclusively used in the 8 Bitcoin transactions I mentioned in my previous post.

The pastebin entry was posted on 2014/04/02 19:01:08 UTC.

And here are the 8 transactions with the UTC timestamp of the block in which they appear:

Block: 2014/04/03 23:12:48
Transaction: edb83f04e68bfe78bbfe7ce80d33e85acb9335c96ead5712517b8c70d1f27b38
Block: 2014/04/04 01:10:45
Transaction: 7e49504c7cecea7ea95d78ff14687878ba581a21dc0772805d2925c617514129
Block: 2014/04/04 01:43:25
Transaction: f65895220f04aa0084d9abae938d3f517893e3afbffe25fc9e7073e02331b9ed
Block: 2014/04/04 02:58:13
Transaction: 8a445d12f225a21d36bb78da747efd2e74861fcd033757da572c0434d423acd1
Block: 2014/04/04 04:32:24
Transaction: fcf5cf9893a142897598edfc753bd6162e3638e138fc2feaf4a3477c0cfb65eb
Block: 2014/04/04 04:32:24
Transaction: 2814673f0952b936d578d73197bfd371cefbd73c6294bab16de1575a4c3f6e80
Block: 2014/04/04 09:36:29
Transaction: f09904aaa4fa4a8ec7da06f5e3d318a9b6a218e1a215f9307416fbbadf5a1c8e
Block: 2014/04/04 09:36:29
Transaction: 5dbb9df056c36457228a841d6cc98ac90967bc88411c95372d3c2d92c18060f8

So it took a bit more than 24 hours before someone spammed the Bitcoin blockchain with these transactions designed to trigger false positives.

Monday 23 June 2014

Stoned Bitcoin

Filed under: Encryption,Forensics,Malware — Didier Stevens @ 20:29

There are reports of anti-virus false positive detections of Bitcoin files. More precisely for the old Stoned computer virus.

I found the smoking gun! These reports should not be dismissed as hoaxes.

I’ve identified 2 Bitcoin transactions that contain byte sequences found in the Stoned computer virus. Here they are:

Both transactions appear in blocks dated 2014-04-04.

The first transaction has byte sequences of the Stoned computer virus in the address of transaction outputs 1, 2, 3 and 4:

Txout 1:
 value: 1
 txOutScriptLength: 25
 txOutScript: 'OP_DUP OP_HASH160 0700ba8000cd13eb4990b90300ba000100000000 OP_EQUALVERIFY OP_CHECKSIG'
 Stoned virus byte sequence:     0700ba8000cd13eb4990b90300ba0001
Txout 2:
 value: 1
 txOutScriptLength: 25
 txOutScript: 'OP_DUP OP_HASH160 b8010333dbb10133d29c00000000000000000000 OP_EQUALVERIFY OP_CHECKSIG'
 Stoned virus byte sequence:     b8010333dbb10133d29c
Txout 3:
 value: 1
 txOutScriptLength: 25
 txOutScript: 'OP_DUP OP_HASH160 750e33c08ed8a03f04a8017503e8070000000000 OP_EQUALVERIFY OP_CHECKSIG'
 Stoned virus byte sequence:     750e33c08ed8a03f04a8017503e80700
Txout 4:
 value: 1
 txOutScriptLength: 25
 txOutScript: 'OP_DUP OP_HASH160 b8010333dbb10133d29c00000000000000000000 OP_EQUALVERIFY OP_CHECKSIG'
 Stoned virus byte sequence:     b8010333dbb10133d29c

I’ve submitted this transaction to VirusTotal: 16 detections. I also submitted the block containing this transaction: 5 detections.

The second transaction has a byte sequence of the Stoned computer virus in the address of transaction output 43:

Txout 43:
 value: 10
 txOutScriptLength: 25
 txOutScript: 'OP_DUP OP_HASH160 0400b801020e07bb000233c98bd1419c00000000 OP_EQUALVERIFY OP_CHECKSIG'
 Stoned virus byte sequence:     0400b801020e07bb000233c98bd1419c

I’ve submitted this transaction to VirusTotal: 14 detections. I also submitted the block containing this transaction: 4 detections.

This is a likely explanation why there were “Stoned Virus” anti-virus alerts for Bitcoin blockchain files reported in the news.

Stuffing messages in the address of the output(s) of a transaction is a well known method to insert messages in the Bitcoin blockchain. The drawback is that the Bitcoins send to these addresses are irrevocably lost, because these addresses have no (known) private key. That is why only very small amounts will be transferred (1 and 10 Satoshis in these transactions). The message is limited to 20 bytes (the size of the raw address used in the output).

But I believe that all output addresses in these transactions (except for the last output) are byte sequences found in malware.

When I run ClamAV’s sigtool on these transactions (with a recent database), a lot of signatures are found:

VIRUS NAME: Gen.600;MATCH: ** YES ** (1 match at offset: 1321)
VIRUS NAME: Gen.696;MATCH: ** YES ** (1 match at offset: 1356)
VIRUS NAME: Gen.801;MATCH: ** YES ** (1 match at offset: 1798)
VIRUS NAME: Stoned.1;MATCH: ** YES ** (1 match at offset: 200)
VIRUS NAME: Stoned.2;MATCH: ** YES ** (1 match at offset: 266)
VIRUS NAME: Syslock.1;MATCH: ** YES ** (1 match at offset: 369)
VIRUS NAME: Syslock.2;MATCH: ** YES ** (2 matches at offsets: 404 368)
VIRUS NAME: Ten-Bytes;MATCH: ** YES ** (1 match at offset: 606)
VIRUS NAME: Terminator.1;MATCH: ** YES ** (1 match at offset: 642)
VIRUS NAME: Terror.1;MATCH: ** YES ** (1 match at offset: 675)
VIRUS NAME: Terror.2;MATCH: ** YES ** (1 match at offset: 709)
VIRUS NAME: Terror.4;MATCH: ** YES ** (1 match at offset: 744)
VIRUS NAME: Terror;MATCH: ** YES ** (1 match at offset: 810)
VIRUS NAME: Tiny-163.A;MATCH: ** YES ** (1 match at offset: 845)
VIRUS NAME: Tiny-163.C;MATCH: ** YES ** (1 match at offset: 879)
VIRUS NAME: Tiny-A;MATCH: ** YES ** (1 match at offset: 912)
VIRUS NAME: Tori-1;MATCH: ** YES ** (1 match at offset: 1014)
VIRUS NAME: Tree;MATCH: ** YES ** (1 match at offset: 1050)
VIRUS NAME: TUQ.RPVS;MATCH: ** YES ** (1 match at offset: 538)
VIRUS NAME: USSR-1049.A;MATCH: ** YES ** (1 match at offset: 1083)
VIRUS NAME: USSR-2144.B;MATCH: ** YES ** (1 match at offset: 1117)
VIRUS NAME: USSR-3103;MATCH: ** YES ** (1 match at offset: 1152)
VIRUS NAME: USSR-311.B;MATCH: ** YES ** (1 match at offset: 1184)
VIRUS NAME: USSR-311.D;MATCH: ** YES ** (1 match at offset: 1219)
VIRUS NAME: USSR-311.E;MATCH: ** YES ** (1 match at offset: 1252)
VIRUS NAME: USSR-516.B;MATCH: ** YES ** (1 match at offset: 1287)
VIRUS NAME: USSR-601;MATCH: ** YES ** (1 match at offset: 1320)
VIRUS NAME: USSR-707.B;MATCH: ** YES ** (1 match at offset: 1390)
VIRUS NAME: USSR-707.C;MATCH: ** YES ** (1 match at offset: 1422)
VIRUS NAME: USSR-711.C;MATCH: ** YES ** (1 match at offset: 1458)
VIRUS NAME: USSR-830;MATCH: ** YES ** (1 match at offset: 1490)
VIRUS NAME: USSR-948.B;MATCH: ** YES ** (1 match at offset: 1525)
VIRUS NAME: V1244;MATCH: ** YES ** (1 match at offset: 1661)
VIRUS NAME: V191;MATCH: ** YES ** (1 match at offset: 1697)
VIRUS NAME: V-1L;MATCH: ** YES ** (1 match at offset: 1594)
VIRUS NAME: V200.B;MATCH: ** YES ** (1 match at offset: 1729)
VIRUS NAME: Vacsina.2;MATCH: ** YES ** (1 match at offset: 1900)
VIRUS NAME: Vacsina.3;MATCH: ** YES ** (1 match at offset: 1934)
VIRUS NAME: Vacsina.4;MATCH: ** YES ** (1 match at offset: 1966)
VIRUS NAME: VCS (Clam);MATCH: ** YES ** (1 match at offset: 1830)
VIRUS NAME: VHP-361.A;MATCH: ** YES ** (1 match at offset: 1864)
VIRUS NAME: Vienna-1028;MATCH: ** YES ** (1 match at offset: 2172)
VIRUS NAME: Vienna.1;MATCH: ** YES ** (2 matches at offsets: 2068 2034)
VIRUS NAME: Vienna.1-1;MATCH: ** YES ** (1 match at offset: 2068)
VIRUS NAME: Vienna.2;MATCH: ** YES ** (1 match at offset: 2102)
VIRUS NAME: Vienna-62.B;MATCH: ** YES ** (1 match at offset: 2205)
VIRUS NAME: Vienna.7;MATCH: ** YES ** (1 match at offset: 2137)
VIRUS NAME: TinyFamily2;MATCH: ** YES ** (1 match at offset: 946)
VIRUS NAME: TinyFamily3;MATCH: ** YES ** (1 match at offset: 980)

VIRUS NAME: Italian.1;MATCH: ** YES ** (1 match at offset: 231)
VIRUS NAME: Italian-Generic;MATCH: ** YES ** (1 match at offset: 266)
VIRUS NAME: Jerusalem.1;MATCH: ** YES ** (1 match at offset: 301)
VIRUS NAME: Jerusalem-1361;MATCH: ** YES ** (1 match at offset: 469)
VIRUS NAME: Jerusalem.2.Nemesis;MATCH: ** YES ** (2 matches at offsets: 1592 334)
VIRUS NAME: Jerusalem.5;MATCH: ** YES ** (1 match at offset: 368)
VIRUS NAME: Jerusalem.7;MATCH: ** YES ** (1 match at offset: 403)
VIRUS NAME: Jerusalem.9;MATCH: ** YES ** (1 match at offset: 436)
VIRUS NAME: Jerusalem-Family.1;MATCH: ** YES ** (1 match at offset: 504)
VIRUS NAME: Jerusalem-USA;MATCH: ** YES ** (1 match at offset: 572)
VIRUS NAME: Kharkov-1024;MATCH: ** YES ** (1 match at offset: 605)
VIRUS NAME: Label.1;MATCH: ** YES ** (1 match at offset: 674)
VIRUS NAME: Label.2;MATCH: ** YES ** (1 match at offset: 707)
VIRUS NAME: Leech.1;MATCH: ** YES ** (1 match at offset: 741)
VIRUS NAME: Leprosy.1;MATCH: ** YES ** (1 match at offset: 777)
VIRUS NAME: Leprosy.2;MATCH: ** YES ** (1 match at offset: 809)
VIRUS NAME: Leprosy.4;MATCH: ** YES ** (1 match at offset: 843)
VIRUS NAME: Leprosy-A;MATCH: ** YES ** (1 match at offset: 879)
VIRUS NAME: LOL;MATCH: ** YES ** (1 match at offset: 641)
VIRUS NAME: Lozinsky.2;MATCH: ** YES ** (1 match at offset: 913)
VIRUS NAME: Macho;MATCH: ** YES ** (1 match at offset: 1015)
VIRUS NAME: Minnow;MATCH: ** YES ** (1 match at offset: 1081)
VIRUS NAME: Mirror.1;MATCH: ** YES ** (1 match at offset: 1117)
VIRUS NAME: Mis-Speller;MATCH: ** YES ** (1 match at offset: 1149)
VIRUS NAME: MIX1;MATCH: ** YES ** (1 match at offset: 1217)
VIRUS NAME: MIX1-B;MATCH: ** YES ** (1 match at offset: 1251)
VIRUS NAME: Mixer-1A;MATCH: ** YES ** (1 match at offset: 1319)
VIRUS NAME: Mixer-1B;MATCH: ** YES ** (1 match at offset: 1354)
VIRUS NAME: Mix-I;MATCH: ** YES ** (1 match at offset: 1286)
VIRUS NAME: MLTI.1;MATCH: ** YES ** (1 match at offset: 945)
VIRUS NAME: MLTI.2;MATCH: ** YES ** (1 match at offset: 981)
VIRUS NAME: Mummy;MATCH: ** YES ** (1 match at offset: 1422)
VIRUS NAME: New-COM.1;MATCH: ** YES ** (1 match at offset: 1659)
VIRUS NAME: Nomenclatura.2;MATCH: ** YES ** (1 match at offset: 1693)
VIRUS NAME: Nothing;MATCH: ** YES ** (1 match at offset: 1729)
VIRUS NAME: NPox-1;MATCH: ** YES ** (1 match at offset: 1491)
VIRUS NAME: NV-71;MATCH: ** YES ** (1 match at offset: 1525)
VIRUS NAME: Ontario.3;MATCH: ** YES ** (1 match at offset: 1932)
VIRUS NAME: Orion-263;MATCH: ** YES ** (1 match at offset: 1966)
VIRUS NAME: Oropax.1;MATCH: ** YES ** (1 match at offset: 2001)
VIRUS NAME: Oropax.2;MATCH: ** YES ** (1 match at offset: 2035)
VIRUS NAME: OV;MATCH: ** YES ** (1 match at offset: 1762)
VIRUS NAME: PC-Bandit;MATCH: ** YES ** (1 match at offset: 2067)
VIRUS NAME: PRSC1024;MATCH: ** YES ** (1 match at offset: 2203)
VIRUS NAME: Boot.OneHalf;MATCH: ** YES ** (1 match at offset: 1898)
VIRUS NAME: Jerusalem-PuertoExe;MATCH: ** YES ** (1 match at offset: 537)
VIRUS NAME: Mistake.TypoBoot;MATCH: ** YES ** (1 match at offset: 1183)
VIRUS NAME: MtE.mem.2-staticsig;MATCH: ** YES ** (1 match at offset: 1387)
VIRUS NAME: MutationEng-NE;MATCH: ** YES ** (1 match at offset: 1455)
VIRUS NAME: OldYankee.1;MATCH: ** YES ** (1 match at offset: 1796)
VIRUS NAME: OldYankee.2;MATCH: ** YES ** (1 match at offset: 1829)
VIRUS NAME: OldYankee.3;MATCH: ** YES ** (1 match at offset: 1863)
VIRUS NAME: Stoned-B;MATCH: ** YES ** (1 match at offset: 1625)
VIRUS NAME: Nado.Lover.602-1;MATCH: ** YES ** (1 match at offset: 1557)

My conclusion: these transactions are a deliberate attempt to generate as much false positive anti-virus detections as possible on systems that store Bitcoin transactions on disk. Virus signatures were stuffed in the address of the outputs of these transactions.

And I don’t think the attempt was limited to these 2 transactions. Around the same time, I find other transactions were the output addresses also ends with null bytes:

Hash: edb83f04e68bfe78bbfe7ce80d33e85acb9335c96ead5712517b8c70d1f27b38
Hash: 7e49504c7cecea7ea95d78ff14687878ba581a21dc0772805d2925c617514129
Hash: f65895220f04aa0084d9abae938d3f517893e3afbffe25fc9e7073e02331b9ed
Hash: 8a445d12f225a21d36bb78da747efd2e74861fcd033757da572c0434d423acd1
Hash: 2814673f0952b936d578d73197bfd371cefbd73c6294bab16de1575a4c3f6e80
Hash: 5dbb9df056c36457228a841d6cc98ac90967bc88411c95372d3c2d92c18060f8

You can also look at the input addresses of these transactions to find other, similar transactions:

 

I plan to discuss the methods and tools I used to find and analyze these transactions in an upcoming blog post.

Friday 14 March 2014

Handling McAfee Quarantine Files

Filed under: Malware — Didier Stevens @ 10:46

Last time I opened a McAfee quarantine file (.bup) with a hex editor, I saw something I didn’t notice before: D0 CF 11 E0

The fileformat used for McAfee quarantine files is the Compound File Binary Format (also used for .doc, .xls, .msi, …).

With this new info and Google’s help I found @herrcore‘s punbup Python program. This program uses a Python module to handle CFB files, it does not rely on 7-zip for this. This has a big advantage: one is no longer required to write the quarantined files to disk to analyze them.

For example, with option -c md5 you can get the md5 hashes of the quarantined files, without these files being written to disk.

I added a couple of extra features which @herrcore has kindly merged into his repository. These new options allow one to perform a hexdump (-x -X), ASCII dump (-a -A) or dump (-f) of the quarantined file(s). Here is a usage example:

punbup.py -f quarantine.bup | pdfid.py

This command performs an analysis with pdfid of the quarantined PDF file, without writing the malicious PDF file to disk.

Monday 3 March 2014

Forensic Use of CAT Files

Filed under: Encryption,Forensics,Malware — Didier Stevens @ 0:16

I found this executable A0000623.sys with 6 detections on VirusTotal. Are these false positives or true positives?

The file was found in the _restore system folder. It looks like it is a Windows system file (tcp.sys), but maybe it is infected. It has no digital signature.

With the help of Google, I was able to trace it back to MS05-019: WindowsXP-KB893066-x86-ENU.exe. But unfortunately, WindowsXP-KB893066-x86-ENU.exe can no longer be downloaded from Microsoft’s site, as they published a new release for this patch: WindowsXP-KB893066-v2-x86-ENU.exe.

Fortunately, I found another file in this _restore folder: A0000615.cat. This is a catalog file that Microsoft uses to sign Windows executables. With Sysinternals’ sigcheck tool and this catalog file, I was able to confirm that this is a signed Windows executable and conclude that the detections are false positives.

I will release a new version of my AnalyzePESig tool that accepts an optional catalog file.

Saturday 14 December 2013

Update: virustotal-submit.py V0.0.3

Filed under: Malware,My Software,Update — Didier Stevens @ 0:21

There is extra error handling in this new version.

virustotal-search and virustotal-submit have their own page now: VirusTotal Tools.

virustotal-submit_V0_0_3.zip (https)
MD5: 3F9F5421F711E2930AB6F80D87DF9E2B
SHA256: 37CCE3E8469DE097912CB23BAC6B909C9C7F5A5CEE09C9279D32BDB9D6E23BCC

Monday 2 December 2013

4 Times Faster virustotal-search.py

Filed under: Malware,My Software,Update — Didier Stevens @ 0:26

This is an important update to virustotal-search.py.

Rereading the VT API, I noticed I missed the fact that the search query accepts up to 4 search terms.

This new version submits 4 hashes at a time, making it up to 4 times faster than previous versions.

virustotal-search_V0_1_0.zip (https)
MD5: 0141D3677F759317034C416EBF9FF30D
SHA256: FE07859C3FA09DA120D3104FF982AF0D78ADFCF099A10E46E254823502DF4EE4

Monday 21 October 2013

Update: Suspender V0.0.0.4

Filed under: Forensics,Malware,My Software,Update — Didier Stevens @ 10:19

Suspender is a DLL that suspends all threads of a process.

This new version adds an option to suspend a process when it exits. Rename the dll to suspenderx.dll to activate this option (x stands for eXit).

When DllMain is called with DLL_PROCESS_DETACH and the reserved argument is not NULL, the process is exiting. So that’s the trigger to suspend it.

20131021-121321

Suspender_V0_0_0_4.zip (https)
MD5: 629255337FE0CA9F631B1A7177D158F0
SHA256: 8E63152620541314926878D01469E2E922298C147740BDEAF7FC6B70EB9305EF

Sunday 4 August 2013

Quickpost: Rovnix PCAP

Filed under: Forensics,Malware,Networking,Quickpost — Didier Stevens @ 21:04

Microsoft’s Malware Protection Center has a blogpost on a version of Rovnix that uses its own TCP/IP stack.

I used Wireshark to capture the network traffic generated by this sample when it is executed in a VMware guest.

20130804-225716

I ran the sample on a XP SP3 guest machine in VMware. The hostname is XPPROSP3 (this name will appear in the HTTP GET request).
The guest uses NAT.
I ran the Wireshark capture on my host machine on the VMware Virtual Ethernet Adapter.
I removed some traffic coming from my host machine (NetBIOS Name Service and DHCPv6 to be precise).

When I executed the sample on XPPROSP3, it rebooted after a few seconds.

The trace:
The 37 second gap between packet 6 and 7 is due to the reboot of XPPROSP3
Packet 44: DNS request for youtubeflashserver
There are 3 HTTP requests. Notice User-Agent FWVersionTestAgent in all 3 GET requests.
Packet 50: first GET request with hostname XPPROSP3 as a parameter. Response: 404
Packet 61: second GET request, malformed. Response: 400
Packet 70: third GET request, malformed. Response: 400

rovnix-capture-filtered.zip (https)
MD5: C941D1716B6248C3FBFB4DFFA8AD2E86
SHA256: 51EDA61199DD9EDC1E50C5A9B5A4B69F32DB74E90CF098849554C56217D06EFD


Quickpost info


Friday 26 July 2013

MSI: The Case Of The Invalid Signature

Filed under: Forensics,Malware,Windows 7 — Didier Stevens @ 22:01

I found a suspicious file on a Windows XP machine. I was able to trace its origin back to a Windows Installer package (.msi). This package in c:\windows\installer had an invalid digital signature. Like this:

20130726-233848

Very suspicious.

A bit later I found another msi package containing the same suspicious file. But this time, the package had a valid digital signature. What’s going on?

After a deep dive into the internals of msi packages, I found the answer.

When an msi package is installed, it is cached inside the Windows Installer directory (%windir%\Installer). Prior to Windows Installer 5.0 (released with Windows 7), cached packages were stripped of their embedded cab files. But with digitally signed msi files, the signature remained inside the file: the digitally signed file was modified, hence the signature was invalidated. This behavior changed with Windows Installer 5.0: cached packages are no longer stripped, hence the signature remains valid.

This blogpost by Heath Stewart explains this change in more detail. Unfortunately, my Google-skills were not good enough to find this blogpost prior to my deep dive into msi files. Hindsight Googling FTW! ;-)

Next Page »

The Rubric Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 234 other followers