Management task: Remote shutdown utility

I run a simple web server to serve as a storage medium for my mobile devices (I don’t like using dropbox or other online storage solutions because they don’t offer much space and they hogs up bandwidth unnecessarily). Before I go to sleep I usually shut down the server to save energy, but in order to do so, I have to have another computer turned on to perform remote access into the server and shut it down via command line. Occasionally, I would turn off my work computer before I remember that I want to shut down the server and I’m too lazy by then to turn on my work computer again.

That’s why I wanted an application that is capable of shutting down Windows on my behalf. The scenario is like this: because I can access FTP service from my phone, I will create a file, namely ‘shutdown’; when the server sees this file, it will delete the file and initiate shutdown. Quite simple.

To shut down, I use Windows management interface (System.Management namespace in C#)

        static void Shutdown()
        {
            ManagementBaseObject mboShutdown = null;
            ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
            mcWin32.Get();

            // You can't shutdown without security privileges
            mcWin32.Scope.Options.EnablePrivileges = true;
            ManagementBaseObject mboShutdownParams =
                     mcWin32.GetMethodParameters("Win32Shutdown");

            // Flag 1 means we want to shut down the system. Use "2" to reboot.
            mboShutdownParams["Flags"] = "1";
            mboShutdownParams["Reserved"] = "0";
            foreach (ManagementObject manObj in mcWin32.GetInstances())
            {
                mboShutdown = manObj.InvokeMethod("Win32Shutdown",
                                               mboShutdownParams, null);
            }
        }

From here

And the rest is just a loop to check if the file exists

        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            while (true)
            {
                if (!System.IO.File.Exists("D:\Shutdown"))
                {
                    Thread.Sleep(500);
                }
                else
                {
                    System.IO.File.Delete("D:\Shutdown");
                    Shutdown();
                    return;
                }
            }
        }

That’s it, I run the application and it will wait until I create a file named ‘shutdown’ in D:, it will perform shutdown and quit

Here’s the sample code and binary

Recover encrypted home folder under Ubuntu / Kubuntu

The community documentation can be of great help, namely the following section

  1. If you use encrypted filenames (standard in Ubuntu >= 9.04) you have to do the following first:
    •  sudo ecryptfs-add-passphrase --fnek 
    •  Passphrase:  (Enter the mount passphrase you recorded when you setup the mount–this passphrase is different from your login passphrase.)
    • You should now get two lines looking like this:
    •  Inserted auth tok with sig [9986ad986f986af7] into the user session keyring 
    •  Inserted auth tok with sig [76a9f69af69a86fa] into the user session keyring  (write down the second value in the square brackets)
  2. Mount using sudo:
    •  sudo mkdir -p /home/username/Private  
    •  sudo mount -t ecryptfs /home/username/.Private /home/username/Private 
    •  Selection: 3  (use a passphrase key type)
    •  Passphrase:  (Enter the mount passphrase you recorded when you setup the mount–this passphrase is different from your login passphrase.)
    •  Selection: aes  (use the aes cipher)
    •  Selection: 16  (use a 16 byte key)
    •  Enable plaintext passthrough: n 
    •  Enable filename encryption: y  (This and the following options only apply if you are using filename encryption)
    •  Filename Encryption Key (FNEK) Signature:  (the value you wrote down from the second line above)

Problem is, like some folks at the Ubuntu forums, I encounted the following error when trying sudo mount -t encryptfs /source /destination:

Attempting to mount with the following options:
  ecryptfs_unlink_sigs
  ecryptfs_fnek_sig=xxx
  ecryptfs_key_bytes=16
  ecryptfs_cipher=aes
  ecryptfs_sig=xxx
Error mounting eCryptfs: [-2] No such file or directory
Check your system logs; visit

After fiddling around for a whole day, I finally figured out the problem: the blind confidence in Linux developers’ ability. You see, I used to believe Linux’s symlink always point to the same directory on the drive event after it was mounted somewhere else. So say if a link from your old drive, say ~/etc points to /etc, when you mount the root filesystem on another machine, it should now point to /media/mount/etc right? Wrong!

Problem is, the hidden .Private in the encrypted folder is only one such symlink, and when you attempted to mount it in another system, the symlink is broken. If you do a ls -l, you can see the symlink points to /home/.ecryptfs/<yourusername>/.Private relative to your old directory structure, so to successfully mount your encrypted folder, you shouldn’t mount /home/<yourusername>/.Private like mentioned in the tutorial, but instead

sudo mount -t ecryptfs /media/[old drive mount point]/home/.ecryptfs/[your old username]/.Private /home/[your new username]/[new mount point]

Problem solved!

(Very) crude .NET wrapper for Tesseract 3

I was searching for a quick way to recognize license plates and stumbled upon EmguCV’s sample code. But this code requires Tesseract OCR (An open source OCR engine currently sponsored by Google) and its .NET wrapper. Unfortunately, this code was written when Tesseract was still at version 2, so is the .NET wrapper so none of them will work for me (I need Tesseract 3 to use a new language supported by this version), worse still, the original wrapper developer has stated that he won’t touch Tesseract code again, so the only way to proceed would be to write my own wrapper.

As you may have know, writing and debugging a wrapper for another language is a tedious and painstaking process, so I opted for the easy way out: use Tesseract command line version to recognize text without digging into the source code.

And here’s the result: A wrapper class for Tesseract on .NET – it will write your bitmap to a temporary file, execute Tesseract and extract the result back into the code. Note that this will run very slow, and that’s why I say it’s crude, a better way would be to analyze Tesseract code and write an interop DLL, but i just don’t have time for that 🙂

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;

namespace PlateDetection
{
    class Tesseract
    {
        string Language = "eng";
        const string Program = @"C:Program Files (x86)Tesseract-OCRtesseract";

        /// <summary>
        /// Changes language
        /// </summary>
        /// <param name="language">Language code</param>
        /// <param name="NotUsed">Not used but kept for compatibitily with Tesseract.net old wrapper</param>
        internal void Init(string language, bool NotUsed)
        {
            Language = language;
        }

        /// <summary>
        /// Main function, recognize any text in the bitmap
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="rectangle">Not used, you may change that easily by cutting the bitmap</param>
        /// <returns></returns>
        internal List<string> DoOCR(System.Drawing.Bitmap bmp, System.Drawing.Rectangle rectangle)
        {
            bmp.Save("temp.png", System.Drawing.Imaging.ImageFormat.Png);
            System.Diagnostics.Process.Start(Program, "temp.png temp -l " + Language);
            
            string [] Words = new string[0];
            // The application may need some time to process, file is not ready yet,
            // or the application may still writing
            while (true)
            {
                try
                {
                    Words = File.ReadAllText("temp.txt").Split(new char[] { ' ', 'r', 'n', 't' }, StringSplitOptions.RemoveEmptyEntries);
                    break;
                }
                catch
                {

                }
            }
            File.Delete("temp.png");
            File.Delete("temp.txt");
            List<string> Result = new List<string>(Words);
            return Result;
        }

        /// <summary>
        /// Currently not used as there is no allocation done
        /// </summary>
        internal void Dispose()
        {
            
        }
    }
}

And here’s the full plate detection class

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.Util;
using System.Diagnostics;
using Emgu.CV.Structure;

namespace PlateDetection
{
    /// <summary>
    /// A license plate detector
    /// </summary>
    public class LicensePlateDetector : DisposableObject
    {

        private Tesseract _ocr;

        /// <summary>
        /// Create a license plate detector
        /// </summary>
        public LicensePlateDetector()
        {
            //create OCR
            _ocr = new Tesseract();

            //You can download more language definition data from
            //http://code.google.com/p/tesseract-ocr/downloads/list
            //Languages supported includes:
            //Dutch, Spanish, German, Italian, French and English
            _ocr.Init("eng", false);
        }

        /// <summary>
        /// Create a license plate detector
        /// </summary>
        public LicensePlateDetector(string language)
        {
            //create OCR
            _ocr = new Tesseract();

            //You can download more language definition data from
            //http://code.google.com/p/tesseract-ocr/downloads/list
            //Languages supported includes:
            //Dutch, Spanish, German, Italian, French and English
            _ocr.Init(language, false);
        }

        /// <summary>
        /// Detect license plate from the given image
        /// </summary>
        /// <param name="img">The image to search license plate from</param>
        /// <param name="licensePlateList">A list of images where the detected license plate region is stored</param>
        /// <param name="filteredLicensePlateList">A list of images where the detected license plate region with noise removed is stored</param>
        /// <param name="boxList">A list where the region of license plate, defined by an MCvBox2D is stored</param>
        /// <returns>The list of words for each license plate</returns>
        public List<List<string>> DetectLicensePlate(Image<Bgr, byte> img, List<Image<Gray, Byte>> licensePlateList, List<Image<Gray, Byte>> filteredLicensePlateList, List<MCvBox2D> boxList)
        {
            //Stopwatch w = Stopwatch.StartNew();
            List<List<string>> licenses = new List<List<string>>();
            using (Image<Gray, byte> gray = img.Convert<Gray, Byte>())
            using (Image<Gray, Byte> canny = new Image<Gray, byte>(gray.Size))
            using (MemStorage stor = new MemStorage())
            {
                CvInvoke.cvCanny(gray, canny, 100, 50, 3);

                Contour<Point> contours = canny.FindContours(
                     Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                     Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE,
                     stor);
                FindLicensePlate(contours, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);
            }
            //w.Stop();
            return licenses;
        }

        private void FindLicensePlate(
           Contour<Point> contours, Image<Gray, Byte> gray, Image<Gray, Byte> canny,
           List<Image<Gray, Byte>> licensePlateList, List<Image<Gray, Byte>> filteredLicensePlateList, List<MCvBox2D> boxList,
           List<List<string>> licenses)
        {
            for (; contours != null; contours = contours.HNext)
            {
                Contour<Point> approxContour = contours.ApproxPoly(contours.Perimeter * 0.05, contours.Storage);

                if (approxContour.Area > 100 && approxContour.Total == 4)
                {
                    //img.Draw(contours, new Bgr(Color.Red), 1);
                    if (!IsParallelogram(approxContour.ToArray()))
                    {
                        Contour<Point> child = contours.VNext;
                        if (child != null)
                            FindLicensePlate(child, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);
                        continue;
                    }

                    MCvBox2D box = approxContour.GetMinAreaRect();

                    double whRatio = (double)box.size.Width / box.size.Height;
                    if (!(3.0 < whRatio && whRatio < 8.0))
                    {
                        Contour<Point> child = contours.VNext;
                        if (child != null)
                            FindLicensePlate(child, gray, canny, licensePlateList, filteredLicensePlateList, boxList, licenses);
                        continue;
                    }

                    Image<Gray, Byte> plate = gray.Copy(box);
                    Image<Gray, Byte> filteredPlate = FilterPlate(plate);

                    List<string> words;
                    using (Bitmap bmp = filteredPlate.Bitmap)
                        words = _ocr.DoOCR(bmp, filteredPlate.ROI);

                    licenses.Add(words);
                    licensePlateList.Add(plate);
                    filteredLicensePlateList.Add(filteredPlate);
                    boxList.Add(box);
                }
            }
        }

        /// <summary>
        /// Check if the four points forms a parallelogram
        /// </summary>
        /// <param name="pts">The four points that defines a polygon</param>
        /// <returns>True if the four points defines a parallelogram</returns>
        private static bool IsParallelogram(Point[] pts)
        {
            LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

            double diff1 = Math.Abs(edges[0].Length - edges[2].Length);
            double diff2 = Math.Abs(edges[1].Length - edges[3].Length);
            if (diff1 / edges[0].Length <= 0.05 && diff1 / edges[2].Length <= 0.05
               && diff2 / edges[1].Length <= 0.05 && diff2 / edges[3].Length <= 0.05)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// Filter the license plate to remove noise
        /// </summary>
        /// <param name="plate">The license plate image</param>
        /// <returns>License plate image without the noise</returns>
        private static Image<Gray, Byte> FilterPlate(Image<Gray, Byte> plate)
        {
            Image<Gray, Byte> thresh = plate.ThresholdBinaryInv(new Gray(120), new Gray(255));

            using (Image<Gray, Byte> plateMask = new Image<Gray, byte>(plate.Size))
            using (Image<Gray, Byte> plateCanny = plate.Canny(new Gray(100), new Gray(50)))
            using (MemStorage stor = new MemStorage())
            {
                plateMask.SetValue(255.0);
                for (
                   Contour<Point> contours = plateCanny.FindContours(
                      Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                      Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL,
                      stor);
                   contours != null; contours = contours.HNext)
                {
                    Rectangle rect = contours.BoundingRectangle;
                    if (rect.Height > (plate.Height >> 1))
                    {
                        rect.X -= 1; rect.Y -= 1; rect.Width += 2; rect.Height += 2;
                        rect.Intersect(plate.ROI);

                        plateMask.Draw(rect, new Gray(0.0), -1);
                    }
                }

                thresh.SetValue(0, plateMask);
            }

            thresh._Erode(1);
            thresh._Dilate(1);

            return thresh;
        }

        protected override void DisposeObject()
        {
            _ocr.Dispose();
        }
    }
}

Seeing is believing, here’s a sample of the algorithm run on a live feed off the camera:

And even though I say it’s slow, it’s still fast enough to process my movements and only goes into recognition when the plate is detected, so the performance is acceptable anyways :). The code above is for anyone who just want to test the algorithm to decide whether or not they will use it, I don’t think it’s a good idea to put these into production code 🙂

A quick review of Microsoft SQL Server object types

  • Tables are the source of your data
  • Views are transformations of data. They are usually used to combine information from multiple tables, but they can’t have parameters in them, so they are not what to use if you want to filter your data
  • User defined function or Stored procedure is the Swiss knife of SQL server. They can do anything from automated transformation of data to data retrieval. Code generation tools usually support calling them

Pointers to defeat EAP

This post servers as kind of a note to myself 🙂 EAP stands for extensible authentication protocol. It may be used in 802.11x connections to provide a secure connection. My school currently uses this to provide internet access to various machines around campus; of which some I have access to.   Though, this doesn’t make the equation that much easier. “Hacking exposed wireless” said (page 213) the only practical way to defeat is to steal the key itself. This key is not a plain text the average user keyed in so it can’t be stolen using some wireless key tool. It is a certificate and the same book above suggested that I use metasploit. See also cheat sheet to use metasploit.

But metasploit has a commercial version, the framework typically does nothing much without separate exploit (which can also be downloaded for free, but takes a lot of time). It also requires you to turn off anti virus and firewall (which is something that really inconveniences me since I live in a campus with computer-literate people).

Furthermore, I can’t just walk to a public machine, hook it up for half an hour to install a 100-MB file.   After searching and poking around a bit more, I found the Wireless API (implemented in windows XP 3) which allowed you to interact with Wireless Zero Configuration service and extract the keys into XML files. A security guru from Symantec have developed a tool utilizing this interface so you don’t have to monkey around with Visual Studio.  

Capture phase:

  1. Enumerate Interfaces – wlan.exe ei
  2. There are 1 interfaces in the system.
  3. Interface 0: GUID: 89762a5d-bc6b-4ac6-8cf3-b0462b2bafef Intel(R) PRO/Wireless 3945ABG Network Connection – Teefer2 Miniport
  4. State: “disconnected”
  5. Command “ei” completed successfully.
  6. Get Profile List – wlan.exe gpl 89762a5d-bc6b-4ac6-8cf3-b0462b2bafefThere are 1 profiles on the interface. “Profile1”
  7. Command “gpl” completed successfully.
  8. Get Profile (profile name is case sensitive)
  9. wlan.exe gp Profile1The return profile xml is: <?xml version=”1.0″?> <WLANProfile xmlns=”http://www.microsoft.com/networking/WLAN/profile/v1″> <name>Profile1</name> <SSIDConfig> <SSID> <hex>574C414E2D445341444B</hex> <name>Profile1</name> </SSID> </SSIDConfig> <connectionType>ESS</connectionType> <MSM> <security> <authEncryption> <authentication>open</authentication> <encryption>WEP</encryption> <useOneX>false</useOneX> </authEncryption> <sharedKey> <keyType>networkKey</keyType> <protected>false</protected> <keyMaterial>76A3DEC BA383180E8A18E4E522</keyMaterial> </sharedKey> <keyIndex>0</keyIndex> </security> </MSM> </WLANProfile>
  10. Command “gp” completed successfully.

Deploy Phase (setting the profile):

wlan.exe sp 89762a5d-bc6b-4ac6-8cf3-b0462b2bafef C:Profile1.xml

  The post focused on extracting and redeploying keys on Windows XP, but you may find solutions for Windows 7 in the comments.