WordLock… Easy to set, never forget.

So, I have one of these WordLock bicycle locks, and it was cool to learn how to set it up and change the combination.

The only problem is: I forgot what we set the combination to. #sadface

So, without further ado, to programming!

The Scenario:

Lets assume for a moment we know two things:

  1. We know there are 10,000 combinations, and that the combination that it is set to is a word in the english language.
  2. We have a good understanding of what the word might be if we saw it.

So, with those facts, we’ll need two things:

  1. A list of 4-letter words, which we’ll steal *cough* borrow from litscape.com
  2. Some programming that goes through every combination possible and compares it to the wordlist

So, the programming:

<?php

function make4($number)
{
        $num = intval($number);
        if (($num < 0) || ($num > 9999))
        {
                die("out of range");
        }
        $ret = "";

        if (strlen($num) == 4)
        {
                $ret = $num;
        }
        if (strlen($num) == 3)
        {
                $ret = "0${num}";
        }
        if (strlen($num) == 2)
        {
                $ret = "00${num}";
        }
        if (strlen($num) == 1)
        {
                $ret = "000${num}";
        }
        return $ret;
}

function combination($number)
{
        $letters = array(
                array('B', 'F', 'R', 'M', 'D', 'T', 'S', 'W', 'P', 'L'),
                array('Y', 'R', 'W', 'H', 'E', 'L', 'O', 'I', 'A', 'U'),
                array('S', 'N', 'T', 'M', 'R', 'E', 'L', 'A', 'O', 'K'),
                array('E', 'T', 'S', 'M', 'K', 'G', 'D', 'L', 'Y', 'P'),
        );
        $code = "";
        $combo = make4($number);
        for ($x = 0; $x < 4; $x++)
        {
                $digit = substr($combo, $x, 1);
                $letter = $letters[$x][$digit];
                $code .= $letter;
        }
        return $code;
}

$words = "";
include('words4.php');
$word = explode(' ', $words);
echo "Loaded " . count($word) . " words\n";

foreach ($word as $w)
{
        $possible = strtoupper($w);
        echo "Trying: $possible\n";
        for ($x = 0; $x < 10000; $x++)
        {
                $code = combination($x);
                if ($code == $possible)
                {
                        echo "Found: $possible\n";
                }
        }
}
?>

I’ve take the space-separated wordlist and saved it as an assignment to the $words variable in a separate file. vim doesn’t do justice with multi-lined non-carriage returned stuff, so I’m cool with that.

After executing the above, from a wordlist of 2404 items, i’m left with 732 possible items.

It is going to be a looooooooooooooooong day 🙁

BAAS, BAKE, BALD, BALE, BALK, BALL, BALM, BAND, BANE, BANG, BANK, BANS, BARD, BARE, BARK, BARM, BARS, BASE, BASK, BASS, BATS, BEAD, BEAK, BEAM, BEAT, BEEP, BEES, BEET, BELL, BELT, BEND, BENT, BERK, BERM, BEST, BETS, BIAS, BIKE, BILE, BILK, BILL, BIND, BINS, BIOS, BIRD, BITE, BITS, BITT, BLAT, BLED, BLOG, BLOT, BOAS, BOAT, BOLD, BOLL, BOLT, BOND, BONE, BONK, BONY, BOOK, BOOM, BOOS, BOOT, BORE, BOSS, BOTS, BRAD, BRAG, BRAS, BRAT, BRAY, BRED, BULK, BULL, BUMP, BUMS, BUNK, BUNS, BUNT, BUOY, BURL, BURP, BURS, BURY, BUSK, BUST, BUSY, BUTS, BUTT, BYES, BYTE, DAME, DAMP, DAMS, DANK, DARE, DARK, DART, DATE, DEAD, DEAL, DEED, DEEM, DEEP, DEES, DELE, DELL, DEME, DEMY, DENE, DENS, DENT, DENY, DERE, DERM, DESK, DIAL, DIED, DIES, DIET, DILL, DIME, DIMS, DINE, DING, DINS, DIRE, DIRT, DISK, DOES, DOLE, DOLL, DOLT, DOME, DONE, DONS, DOOM, DORK, DORM, DOSE, DOTE, DOTS, DOTY, DRAG, DRAM, DREG, DROP, DUAL, DUEL, DUES, DUET, DUKE, DULL, DULY, DUMP, DUNE, DUNG, DUNK, DUOS, DUSK, DUST, DUTY, DYED, DYES, DYNE, FAKE, FALL, FAME, FANG, FANS, FARE, FARM, FAST, FATE, FATS, FEAT, FEED, FEEL, FEES, FEET, FELL, FELT, FEND, FENS, FILE, FILL, FILM, FIND, FINE, FINK, FINS, FIRE, FIRM, FIRS, FIST, FITS, FLAG, FLAP, FLAT, FLAY, FLED, FLEE, FLOE, FLOG, FLOP, FOAL, FOAM, FOES, FOLD, FOLK, FOND, FONT, FOOD, FOOL, FOOT, FORE, FORK, FORM, FORT, FRAY, FREE, FRET, FROG, FROM, FUEL, FULL, FUME, FUMY, FUND, FUNK, FURS, FURY, FUSE, FUSS, LAKE, LAME, LAMP, LAND, LANE, LANK, LARD, LARK, LASS, LAST, LATE, LEAD, LEAK, LEAP, LEAS, LEEK, LEES, LEKS, LEND, LENS, LENT, LESS, LEST, LETS, LIED, LIES, LIKE, LILY, LIME, LIMP, LIMY, LINE, LINK, LINT, LIRE, LISP, LIST, LITE, LOAD, LOAM, LOLL, LONE, LONG, LOOK, LOOM, LOOP, LOOS, LOOT, LORD, LORE, LOSE, LOSS, LOST, LOTS, LULL, LUMP, LUNG, LURE, LURK, LUST, LUTE, LYRE, MAKE, MALE, MALL, MALT, MANE, MANS, MANY, MARE, MARK, MARL, MARS, MART, MASK, MASS, MAST, MATE, MATS, MATT, MEAD, MEAL, MEAT, MEEK, MEET, MELD, MELT, MEME, MEND, MENS, MERE, MESS, MILD, MILE, MILK, MILL, MILS, MIME, MIND, MINE, MINK, MINT, MIRE, MISS, MIST, MITE, MITT, MOAT, MOLD, MOLE, MOLT, MOMS, MONK, MOOD, MOOS, MOOT, MORE, MOSS, MOST, MULE, MULL, MUMS, MURK, MUSE, MUSK, MUST, MUTE, MUTT, PALE, PALL, PALM, PALS, PANE, PANG, PANS, PANT, PARE, PARK, PARS, PART, PASS, PAST, PATE, PATS, PEAK, PEAL, PEAS, PEAT, PEEK, PEEL, PEEP, PELT, PEND, PENS, PENT, PERK, PERM, PERT, PEST, PETS, PIED, PIES, PIKE, PILE, PILL, PIMP, PINE, PING, PINK, PINS, PINT, PITS, PITY, PLAY, PLED, PLOD, PLOP, PLOT, PLOY, POEM, POET, POKE, POKY, POLE, POLL, POMP, POND, PONY, POOL, POOP, PORE, PORK, PORT, POSE, POST, POSY, POTS, PRAM, PRAY, PREP, PREY, PROD, PROM, PROP, PROS, PUKE, PULL, PULP, PUMP, PUNK, PUNS, PUNT, PUNY, PURE, PUTS, PUTT, PYRE, RAKE, RAMP, RAMS, RAND, RANG, RANK, RANT, RARE, RASP, RATE, RATS, READ, REAK, REAL, REAM, REAP, REED, REEK, REEL, RELY, REND, RENT, REST, RHOS, RIAL, RIEL, RILE, RILL, RILY, RIME, RIMS, RIND, RING, RINK, RIOT, RISE, RISK, RITE, ROAD, ROAM, ROES, ROLE, ROLL, ROMP, ROOD, ROOK, ROOM, ROOT, ROSE, ROSY, ROTE, ROTS, RUED, RUES, RULE, RUMS, RUNE, RUNG, RUNS, RUNT, RUSE, RUST, RUTS, SAKE, SALE, SALT, SAME, SAND, SANE, SANG, SANK, SASS, SATE, SEAL, SEAM, SEAS, SEAT, SEED, SEEK, SEEM, SEEP, SEES, SELL, SEND, SENT, SERE, SETS, SHAM, SHED, SHOE, SHOP, SHOT, SILK, SILL, SILT, SINE, SING, SINK, SINS, SIRE, SIRS, SITE, SITS, SLAM, SLAP, SLAT, SLAY, SLED, SLOE, SLOG, SLOP, SLOT, SOAK, SOAP, SOLD, SOLE, SOME, SOMS, SONG, SONS, SOOT, SORE, SORT, SOTS, SUED, SUES, SUET, SULK, SUMP, SUMS, SUNG, SUNK, SUNS, SURE, SWAG, SWAM, SWAP, SWAT, SWAY, TAKE, TALE, TALK, TALL, TAME, TAMP, TAMS, TANK, TANS, TARE, TARP, TARS, TART, TASK, TEAK, TEAL, TEAM, TEAS, TEED, TEEM, TEES, TELL, TEND, TENS, TENT, TERM, TEST, THAT, THEE, THEM, THEY, TIED, TIES, TIKE, TILE, TILL, TILT, TIME, TINE, TING, TINS, TINT, TINY, TIRE, TOAD, TOED, TOES, TOLD, TOLL, TOME, TONE, TONG, TONS, TOOK, TOOL, TOOT, TORE, TORT, TOSS, TOTE, TOTS, TRAM, TRAP, TRAY, TREE, TREK, TROD, TROT, TROY, TUMS, TUNE, TUSK, TWOS, TYKE, WAKE, WALK, WALL, WAND, WANE, WANT, WARD, WARE, WARM, WARP, WARS, WART, WARY, WASP, WATT, WEAK, WEED, WEEK, WEEP, WELD, WELL, WELT, WEND, WENT, WERE, WEST, WETS, WHAM, WHAT, WHET, WHEY, WHOM, WHOP, WILD, WILE, WILL, WILT, WILY, WIMP, WIND, WINE, WING, WINK, WINS, WIRE, WIRY, WISE, WISP, WIST, WITS, WOAD, WOES, WOKE, WOKS, WONS, WONT, WOOD, WOOL, WOOS, WORD, WORE, WORK, WORM, WORT, WRAP, WYES

Edit:

For the sake of justice, none of the above words looked familiar.

I headed over to the wordlock FAQ and did the following:

I can’t open my lock. What combination does my lock open to?
Try of the following factory-set default combinations to open your lock: BOLT, SPELL, PACK, SHED, TREE, GYMS, WORDS.

Seems the factory default worked, which means I NEVER SET THE DAMN LOCK IN THE FIRST PLACE :/

Upgrades and good grades

What is now:

 15:39:17 up  5:27,  1 user,  load average: 0.01, 0.04, 0.01

Ah, the uptime. One of the things we aspire to make as large as possible, and love every minute of it.

I did do a reboot today due to a mass of updates that I’ve lacked to do for 250+ days. Regardless, it’s a fresh uptime, and i’ll go with that.

With all these mass updates included SSL attacks such as poodle and heartbleed. I don’t typically run my server on https for public facing stuff, but right now I do for specific URLs and all that is presented is a self-signed certificate. You can go ahead and try https://www.unliterate.net to get the typical browser warnings.

So, with all the updates ssllabs SSL Server Test has given me a “T” (or A-), which I’m pretty proud of after reconfiguring. Maybe I’ll end up buying that cheap SSL cert and going for broke.

What used to be:

I happened to get really curious and find out if some old websites and documents existed from when I was originally fumbling around computers myself. Lo and behold, yes, I found ’em.

RBIL / Ralf Browns Interrupt List (wikipedia, cmu)

The de-facto bread and butter of my machine language learning. For every piece of hardware that downloaded its ROM into RAM, or any software that made hooks into the IVT, this list was just awesome.

I can’t recall how I located it back in the day, but what I do remember is that I was excited to get the updates to it online. Back in the modem days i’d wait upwards to 5 minutes to download 1 of the zip files, and then maybe an entire minute to load one of the text files into Windows 95’s notepad.

This list also got me into direct port access programming. Some of the interrupts and combinations needed for RS232 programming seemed slow to me, especially when trying to go faster than 9600 baud, so I had to turn to a different reference to learn to actually drive the serial controller.

Beyond Logic (retired)

Craig Peacock wrote awesome manuals on how to talk to the RS232 controller (specifically the 8250 and 16450/16550 UARTS), and also the Parallel Ports as well. It wasn’t until I read his manual about the parallel ports that realized that the bidirectional capability had quite a faster transfer rate over the cable than serial. His manuals helped deepened my knowledge on “how things worked”, cause who wouldn’t wanna know how things worked.

PHG Opcode (phg.chat.ru)

From Ralf Browns INTERRUP.LSTs came OPCODE.LST, which was a separate list created and maintained by Alex Potemkin. This list itself, when read entirely, gives you so much in-depth knowledge on how a processor works. From Intel and AMD, to Cyrix, you got instruction times, bugs, incompatibilities, and more than the whole nine yards. It was from this that I understood that 0F A2 means “Identity Yourself!”

From my memory this actually used to be at www.chat.ru/~phg, but as times change URLs have to change.

In a nutshell:

It’s been 20+ years that I’ve been using a keyboard and digging into computer guts, both software and hardware. I’ve been in and out of technology-related occupations, stepped into many hats, and accomplished so much, and I feel good about it.

Sometimes it feels good to take a step back and wonder how you got there, cause all you see is the progress you’ve had and know there is more to accomplish.

email.heick.email

Yays!

Today i’ve done it. I’ve acquired my email dream!

I’m talking about a nearly-automated @heick.email

…to explain…

For years, if you ever wanted to send me an email I would say:

“Just put your name at the front of @unliterate.net, and i’ll get it.”

Ever since I setup my email @unliterate.net wrong as a catch-all SPAM domain, I’ve had to deal with the following rigmarole when getting new email setup:

  1. Get the name@unliterate.net figured out
  2. Setup a folder in Thunderbird, my email client
  3. Setup a mail filter rule in my email client to move the received message from my Inbox to that folder

Which things have been working for years, and it’s been a fairly straightforward approach.

Until I got married, and we decided to get the heick.email domain and have all our mail shared.

…how to share the email…

So, the @unliterate.net experiment utilized POP3 as the server for me to get all my catch-all. This was easy to configure, and was fairly straightforward.

We needed to be able to share email across computers and devices, though, and still have the flexibility to do the “folder structure”-thingy that I’ve grown comfortable with the @unliterate.net “mail filter” rules.

So, the only solution is to go from POP3 to IMAP.

IMAP gives us the flexibility of folders on the server, not on the client. It also stores all the mail there, and the protocol (after swallowing that it’s not like POP3) is actually quite orderly and simple.

So, i’ve employed dovecot as my IMAP server, which was also my POP3 server, and configured it simply to enable IMAP and know where I want my users mailboxes to be stored.

After setting up DNS for mail, i’ve got email coming into @heick.email, and I’m happy.

I just need to be able to now do the mail filtering…

How to automate folder-making for IMAP

This was a basic challenge, and I love challenges.

I had to use my programming language of choice (PHP) with the php-imap module loaded, and fancy up a script that runs on a */1 (1 minute) cron task.

The script is as follows:

<?php
/**
 * The whole purpose of this script is to perform the following:
 * 1) Open an IMAP connection to an INBOX
 * 2) Look through all the messages
 * 3) Grab all messages and look for the first "To: " header in each message
 * 4) If the person in the "To: " is in the allowed domain
 * - We grab the user
 * - We check to see if their is a mailbox for that user, and move the messge there
 * - We delete the message
 * 5) If the person is not in the allowed domain
 * - We move the message to a default folder
 */

function get_imap_folders($resource, $config)
{
 // Get a list of mailboxes
 $original_folders = imap_listmailbox($resource, "{" . $config['server'] . ":" . $config['port'] . "}", "*");
 // these come through as {server:port}mailbox, so we just clean them up a bit
 $new_folders = array();
 $to_remove = "{" . $config['server'] . ":" . $config['port'] . "}";
 $folders = str_replace($to_remove, "", $original_folders);
 return $folders;
}

$config = array(
 'server' => 'localhost',
 'port' => '143',
 'username' => 'redacted',
 'password' => 'redacted',
 'folder' => 'INBOX',
 'spam' => 'SPAM',
 'debug' => true,
);
$debug_message = "";

$res = imap_open("{" . $config['server'] . ":" . $config['port'] . "/service=imap/novalidate-cert" . "}" . $config['folder'], $config['username'], $config['password']);
if (!$res)
{
 if ($config['debug'])
 {
 $debug_message = "IMAP Stream Failure";
 }
 die($debug_message);
}

$folders = get_imap_folders($res, $config);

// Lets get all the mail messages in the $config['folder']
$mbox = imap_check($res);
$number_messages = $mbox->Nmsgs;
if ($number_messages == 0)
{
 if ($config['debug'])
 {
 $debug_message = "No Messages";
 }
 die($debug_message);
}
$range = "1:" . $number_messages;

// now, we'll get the messages
$messages = imap_fetch_overview($res, $range);
foreach ($messages as $msg)
{
 $msgno = $msg->msgno;
 $to = $msg->to;

echo "Message: " . $msg->subject . "\n";
 if (strpos($to, "@"))
 {
 $array_to = explode("@", $to);
 $to = $array_to[0];
 }

// do we need to create a folder to move this message into?
 $destination_mbox = "{" . $config['server'] . ":" . $config['port'] . "}" . $to;
 if (!in_array($to, $folders))
 {
 if (imap_createmailbox($res, $destination_mbox))
 {
 echo "> Created folder [$to]\n";
 }
 else
 {
 echo "> Failed to create folder [$to]\n";
 }

}
 $folders = get_imap_folders($res, $config);
 if (imap_mail_move($res, $msgno, $to))
 {
 echo "+ Moved successfully\n";
 }
 else
 {
 echo "- Failed to move message\n";
 }
}
imap_expunge($res);
imap_close($res);
?>

To explain, basically this access my IMAP server, gets all the folders, then gets all the mail. It goes though the “to:” portions of the email addresses and sees if I have a folder that matches what’s in the name part of the email address in the “to:” portion. If it doesn’t exist, it makes the folder. Then, as a final result, it moves the mail to that folder and aborts.

So, this script now runs every minute, checking for new mail, creating the folders necessary and moving the messages.

vivre heick.email!

Basic DVD Ripping 101

Well, it came time where I got my Wedding DVD, and I had to convert to to Digital Video. I had to dig deep deep into my history, since I used to order DVDs from Netflix back in 2006, Rip them, convert them, and then enjoy them later on.

So, fast forward to 2017, from Windows XP to Windows 10, and awaaaaaaaaaaaaaaay we go.

Software Needed

SmartRipper 2.41

Optional: VLC Media Player from http://www.videolan.org

flaskmpeg from http://www.flaskmpeg.net/

XVid codec from https://www.xvid.com

Fraunhofer IIS MPEG Layer-3 Codec (professional) from the Radium MP3 “copy”.

What to do

  1. Install XVid and the MP3 codec. Fairly straightforward. Without these, you won’t be able to convert your DVD rip to a final copy.
  2. Install SmartRipper and VLC. VLC is only used by SmartRipper to help unlock copy-protected DVDs. Since my Wedding DVD wasn’t copy-protected, I didn’t really need this step.
  3. Extract flaskmpeg. Works out of the box.

Insert the DVD, run SmartRipper. In SmartRipper, you’ll need to isolate the actual film you want, make sure all Chapters and Cells are selected, and Rip. Sit and wait until it’s done.

Load up flaskmpeg, select the .ifo that would contain your DVD. flaskmpeg is smart enough to read it and ask you what you want of it. Select Output and Configure Output Module to select the XVid video codec and the MP3 audio codec, and configure as necessary. Once you’re all configured, FlasK It!.

Without configuring a codec in flask, you’ll get an uncompressed DVD rip. In my initial case, a 1GB MP2 compressed A/V file was 30GB uncompressed on my hard drive, and a laughable matter. After selecting the right options to my taste, a 1GB MP2 turned into a 450MB XVid/MP3 video.

Fruits of the labor

After all that done, I present to you: