Lee S. nodded gently as she re-read the message-board post.

Someone named Robbie had created a posting asking for assistance in resolving a problem with a simple Visual Basic .NET console application. It was used to retrieve and process product registrations and credit card transactions via the Internet for a piece of niche shareware.

"Bottom line, I do FORTRAN and C++, I don't know or want to know Visual Basic .NET," the post explained. "All I know is that I have an app with the 2KB source file for it that I need fixed so I can earn money. I will happily send $100 to the person who can fix this."

Naturally, Lee felt a little bit cautious dealing with some guy (or gal) from the Internet, but the promise of an easy $100 tempted her to take a chance.

Processing over the Internet ... Kind Of

Within minutes of crafting and sending out a professionally worded missive, Lee received a reply.

After graciously thanking Lee for her e-mail, Robbie explained that the attached .exe file normally would run on a daily basis with the output directed to a text file that would, in turn, get loaded into a spreadsheet. Written years ago, it had worked perfectly until the other day when it started choking.

A quick run of the executable revealed the error: Invalid length for a Base-64 char array.

Drawing on her professional experience with troubleshooting Base-64 encoding issues, Lee was positive that the problem would be a cinch to solve. Eager to test her mettle, Lee jumped straight into the attached .vb source file. She was quickly caught off guard:

Imports System.Net.Sockets
Imports System.IO
Imports Confidential

Module EmailApp

  Sub Main()

    Dim ProcessPayment As New Secret
    Dim Server As TcpClient
    Dim ns As NetworkStream
    Dim sr As StreamReader

    Dim s1 As String = "pop3.initech.com"
    Dim user As String = "[email protected]"
    Dim pass As String = "l&28a%"

    Server = New TcpClient(s1, 110)
    ns = Server.GetStream
    sr = New StreamReader(Server.GetStream)
    Dim data As String = "USER " + user + vbCrLf + "PASS " + pass + _
               vbCrLf + "STAT" + vbCrLf + "STAT" + vbCrLf
    Dim enc1() As Byte = _
          System.Text.Encoding.ASCII.GetBytes(data.ToCharArray())
    ns.Write(enc1, 0, enc1.Length)

    Dim x As Integer = CInt(String.Concat(sr.ReadLine + sr.ReadLine + _
               sr.ReadLine + sr.ReadLine).Split(" ")(6))
    Dim tmp As String
    
    For i As Integer = x To x
      data = "RETR " & i.ToString & vbCrLf
      enc1 = System.Text.Encoding.ASCII.GetBytes(data.ToCharArray())
      ns.Write(enc1, 0, enc1.Length)
      tmp = sr.ReadLine

      While (tmp <> ".")
        If tmp.StartsWith("Subject") Then
          data = tmp.Substring(9, tmp.Length - 9)
        End If
        tmp = sr.ReadLine
      End While

      Console.WriteLine(i.ToString + "," + ProcessPayment.DeCrypt(data))

      data = "DELE " & i.ToString & vbCrLf
      enc1 = System.Text.Encoding.ASCII.GetBytes(data.ToCharArray())
      ns.Write(enc1, 0, enc1.Length)

    Next
    data = "QUIT " + vbCrLf
    enc1 = System.Text.Encoding.ASCII.GetBytes(data.ToCharArray())
    ns.Write(enc1, 0, enc1.Length)

  End Sub

End Module

Lee's mind was reeling. The way the program "worked" was almost unthinkable. Processing payments over e-mail in the 21st century ... and in the subject field?! Exactly what kind of madness had she walked into?

Reality Sets In

After Lee calmed down, she thought back to what Robbie had said before realizing, "Ah ha! This must be a data problem!" She proceeded to take a peek at the e-mail messages backed up in the account listed in the source code.

The majority of the messages, at least five per day, had subjects that looked like this: H4sIAJ4qnU0AA4vML1VIyy /NS1EoyUhVCE5NLkotUQgN8lFUyCgpKbDS10 /KLNHLqdRPyw3LcXLjAgDGBcb9LwAA

However, a Web marketer had apparently discovered the "hidden" account, poisoning it with amazing deals for quasi-legal mail-order pharmaceuticals, which caused the program to choke. Lee figured that she would've choked too.

Because adding a heuristic spam filter to the program was not only out of scope, but also outside of the $100, Lee took the quick and easy route by wrapping the "DeCrypt" function within a Try...Catch block. A quick test revealed that the program could now download and export user registrations as it had before. User names, e-mail addresses, telephone numbers and credit card information all appeared, arranged in neat, comma-delimited fields. Lee sent her revision back to Robbie, who, in return, offered to meet up for coffee.

When they met, Lee did her best to explain why the process failed when it did and what she did to fix it. Robbie appeared to be receptive. Following some additional chit-chat, the payment was handed over and Lee asked one question that still gnawed at her.

"The third file you sent me -- the Confidential.DLL file -- what does that do? Is that ..."

"Sorry, no idea," Robbie cut in with palms opened in front of her. "Not my area of expertise, remember?"

"Besides," Lee chuckled, "everything works exactly as it did before if not better, and that's what counts, right?"

Lee held her breath for a second before extending a hand thanking Robbie for the opportunity. Her sense of developer responsibility was screaming in her head: "Are you crazy, lady?! Yeah, it works today, but what if something else changes? What if you get hacked?"

On the way home, Lee resolved to put off saving the world until another day. Meanwhile, she was going to find out what that DLL did.

Shrouded in Secrecy?

Two main obstacles prevented Lee from seeing how the DLL worked. The lack of program source and the file named "Confidential," which had a class named "Secret." Despite these obstacles, Lee was able to easily decompile the binary file to see the truth that lay therein:

Public Function DeCrypt(ByVal strInput As String) As String
  Dim ms As New MemoryStream(Convert.FromBase64String(strInput))
  Dim gz As Stream = New GZipStream(ms, CompressionMode.Decompress)
  Dim sr As New StreamReader(gz)
  Return sr.ReadLine
End Function

Because the initial shock of the calling application had subsided, all that Lee could muster was, "At least they didn't use ROT-13." Somehow, this implementation of decryption fit.

A few months passed before Lee heard from Robbie; payment processing was throwing another fit. The cause this time, though, was the small ISP that had kept the registration e-mail address afloat. It had finally been swallowed by a large telecom prompting them to rename their e-mail servers.


Tale of the Cryptic Encoding was originally published in the May 2011 edition of Visual Studio Magazine. VSM is the leading site for enterprise .NET developers, and offers a free magazine subscription for influential readers.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!