DevDisasters

Tale of the Cryptic Encoding

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.

Robbie offered Lee another $100 to help figure out a potential fix. Lee replied that she didn't have the time to dedicate to such a task. "In the meantime," she said, "perhaps you'd like to investigate other options for handling secure online transactions," and forwarded a set of links.

About the Author

Mark Bowytz is a contributor to the popular Web site The Daily WTF. He has more than a decade of IT experience and is currently a systems analyst for PPG Industries.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube