Turing Complete, Mostly

bbbbloat

Project Honeynet challenges in 2010 were the first forensic challenges I stumbled across. Since then many of these platforms sprang up. There are so many to choose from; hack the box, try hack me, PicoCTF, and hundreds of other CTFs and leetcode programming challenges. Not to mention Advent of Code.

I've always found security and reverse engineering interesitng though I haven't had time to commit to learning it to the extent that I would have liked. Prior to this I've completed a singular challenge from https://crackmes.one/.

Enter PicoCTF

I found a few minutes to try the bbbbloat reverse engineering challenge from PicoCTF.

I'm currently using an M1 Mac. All of my tools are arm64 but bbbbloat is a amd64 binary. I came across box64 which can be used to run amd64 on an arm architecture.

Running the program prompts for the input of a number.

My assembly experience might be pretty much limited to 8080 assembly in school 2 decades ago though I've always appreciated its application in exploit development.

The methodology?

Open Ghidra and Scroll around to find the the entry function, what would be main(). This function contains an if statement that compares against a number. This took less than a minute to find. Enter the number and the flag is printed out! Luck had nothing to do with it...

xlimage xlimage

Enter the flag - Success!

xlimage

This challenge has a 96% solve rate!

Wow! Phew, confidence still in tact!


Minimum viable blog

For many years I would enjoy working through various diverse projects (setting up routers and firewalls, a NAS, an eggdrop bot etc...). I would finish the project and maybe need to come back to it some time later finding that I have forgotten key details about the implementation. With no documentation to refresh my memory revisiting projects was arduous.

Keeping a blog seems like one way to fill this requirement.

Personally I wouldn't be one for a blogging platform. I'd like to retain some control over content, design and avoid platform/vendor lockin. Three separate but related philosophies generally drive my approach to projects; minimum viable product, suckless philosophy and the unix philosophy. And also cheapness.

Initially I attempted to use a a $1 FreeBSD server which I maintained on atlantic.net. It already hosted OpenVPN that I used as an endpoint for Netflix traffic/content. At the time wordpress was the blogging standard and $1 got you 256MB of memory. Cramming FreeBSD, OpenVPN, PHP-FPM, nginx, and MySQL into such a limited memory footprint proved a tad unstable. The database was really the killer. Most wordpress sites should not only really be read only, but also static sites.

The above afformentioned reasons also prevented me from using a managed service. I'd like to keep this as simple as possible. Somewhat of a contradiction to the unfortunate direction of modern day web development. I explored several options. Being fairly vendor/brand agnostic I looked for a platform that fulfilled the following criteria;

  1. Is a static site generator.
  2. Has no database dependancy.
  3. Was written in PHP as I have PHP experience.
  4. Uses blade templates.

Without a database content can be stored in markdown. I still want the ability to post media such as photos, videos, and pdfs on my blog. Jamstack provides a convenient interface to compare static site generators.

Cleaver looked like the best option. A blade template PHP based static site generator. It also has tailwind built in along with support for Vue and jQuery if you need such things.

Oh yes, FOSS.

Cleaver seemed like the best option, but Unfortunately it also seems like abandon ware. After cloning the repository and following the process documentation results in errors.

Building Site
=============
+ hello-world.json rendered to /

» 1 page built in 58.41ms

/app/webpack.mix.js:30
                    command.get('php cleaver build', (error, stdout, stderr) => {
                            ^

TypeError: command.get is not a function
    at Object.fn (/app/webpack.mix.js:30:29)
    at FSWatcher.emit (node:events:527:28)
    at FSWatcher.emitWithAll (/app/node_modules/chokidar/index.js:541:32)
    at FSWatcher._emit (/app/node_modules/chokidar/index.js:632:8)
    at listener (/app/node_modules/chokidar/lib/nodefs-handler.js:370:20)

Node.js v17.9.0

An existing issue on Github hasn't been tended to in months. Fortunately it was a simple fix. The great thing about FOSS is you can send patches. So I submitted a pull request... which also remained disregarded for months. But at least I'm able to still use the free open software I patched myself.

xlimage

I also took the opportunity to add a feature to the markdown compiler. In the blade template I wanted the ability to access the title as its own entity. This would make things more flexible and let me embed the title in an anchor tag. To do this simply use regex to extract and replace the first level 1 heading occurance and assign the value to a variable in the $json object.

        /*
        *   Extract title from markdown
        */
        $pattern = '/^#\s+(.+)$/m';

        if (preg_match($pattern, $body, $matches)) 
        {
            $json->title = $matches[1];
            $body = preg_replace($pattern, '', $body);
        }    

        $parsedown = new \ParsedownExtra();
        $json->body = $parsedown->text($body);

        return $json;

Whichever features I need in a simple static site I can then define conventions for on top of what Cleaver provides. It's fairly versatile and a good product, I just wish it were actively maintained.

Hosting a static site on Github pages seems natural. Whats more effcient than not hosting your own server platform. I run Cleaver in a docker container locally and when it is committed and pushed to git, a Github action runs the build and deployment process, which commits the generated content to a new branch - gh-pages.

And voila! a wild blog appears!

The repository lives here; https://github.com/aaftre/blog.aftre.net/ and contains everything needed to run the local docker container using docker-compose, through to the Github action responsible for building the site and publishing the content to Github pages.


Properly Sciolistic Security

While consolidating the many many MySQL and MSSQL servers I inherited I was tasked with migrating a home grown application that supported processing and chargeback of returned mail. What it was used for is immaterial. But when I say that it was bespoke, it was bespoke. Very Bespoke VB. No documentation ofcourse. That's a given.

First step would be to figure out which of the 24 different SQL servers are implicated and find out how the application is configured on which server to use. When reviewing the file structure Application\ConfigSQL.ini seemed like a natural place to look. Oh good, a .ini. This should be straight forward.

After opening the file I'm confronted with this;

[server]JanetSQL[Cnn_Server]ïîòø¡íèõõíä¡ãôææäó­¡àóäï¦õ¡øà¾ïîòø¡íèõõíä¡ãôææäó­¡àóäï¦õ¡øà¾ïîòø¡íèõõíä¡ãôææäó­¡àóäï¦õ¡øà¾°
*[server]JanetSQL[Cnn_Server]ïîòø¡íèõõíä¡ãôææäó­¡àóäï¦õ¡øà¾ïîòø¡íèõõíä¡ãôææäó­¡àóäï¦õ¡øà¾ïîòø¡íèõõíä¡ãôææäó­¡àóäï¦õ¡øà¾° 

What the hell is that? Do I need Some obscure Windows process/tool? A hexeditor? A drink? A new job? This is unlike any .ini i've ever seen. Why is there an asterisk? Maybe I missed something in my 30 years of doing this. And does Janet have her own SQL server? When you have SQL servers provisioned and named after employees, you're in a special place.

I managed to find a copy of the application source on a NAS drive, because why would it be in Git when you can zip it onto a locally administered (administered by no one) NAS drive with no backups.

After grep-ing the code base for a few things and clutching at straws this turns up.

Public Sub LoadSQLServerSettings()
    Dim oRead As New StreamReader(Application.StartupPath 
        & "\ConfigSQL.ini", System.Text.Encoding.UTF7)
    ...
    utConfig.sCnnCurrent = EncryptDecryptString(sLine.Substring(sLine.IndexOf("Cnn_Server]") + 11))
    ...

What the hell is UTF-7? And why on earth would anyone want to use that? I haven't heard of this encoding before. According to Wikipedia; a dead format. Much like the rest of the technology used in this company. But half of the .ini was legible. So was half of the file UTF-8 and the other half UTF-7?

This gets even better because it's an even more (ob)secure-ified .ini. Obviously we need to EncryptDecryptString() this "UTF-7".

Public Function EncryptDecryptString(ByVal sTXT As String) As String
    ...
    For iCount = 0 To sTXT.Length - 1
        sTmp = sTmp & Chr(Asc(sTXT.Substring(iCount, 1)) Xor 129)
    Next
    EncryptDecryptString = sTmp
End Function

And then I laughed and I laughed. If anything work should be fun.

Thankfully the configuration details are kept secured using XOR "encryption". Phew. Good thing. Evidently the data is sensitive enough to protect, but not sensitive enough to implement any actual protection. We're just making things up as we go here.

So is there a tool to decode"crypt" and edit the configuration file?

While scouring the various databases to which I only happen to have access to thanks to a saved password in Microsoft SQL Management Studio almost a dozen stored procedures turn up. One function stands out: fn_EncryptDecryptString().

The tool used to modify the VB application configuration file (using XOR) is an MSSQL stored procedure. You need an SQL server to XOR a string.

CREATE FUNCTION [dbo].[fn_EncryptDecryptString] ( @pClearString VARCHAR(1000) )
    --RETURNS NVARCHAR(1000) WITH ENCRYPTION AS --(use this line to hide the code)
    RETURNS NVARCHAR(1000)  AS
    BEGIN

    DECLARE @vEncryptedString NVARCHAR(1000)
    DECLARE @vIdx INT
    DECLARE @vBaseIncrement INT

    SET @vIdx = 1
    SET @vBaseIncrement = 128
    SET @vEncryptedString = ''

    WHILE @vIdx <= LEN(@pClearString) 
    BEGIN 
        SET @vEncryptedString = @vEncryptedString 
            + NCHAR(ASCII( SUBSTRING(@pClearString, @vIdx, 1)) ^129) 
        SET @vIdx = @vIdx + 1 
    END 

    RETURN @vEncryptedString 
END 

So what configuration secrets does the XOR hide? Copy and paste the illegible encoded portion into the SQL function.

Data Source=DarthVador\SQLFJ;Initial Catalog=DataProcessingV2;Persist Security Info=True;User ID=USERNAME;Password=USERPASSWORD

Ofcourse a Star Wars reference. In a .ini semicolons are comments right? No no, not here, not now. We're in a galaxy far far away. Currently semicolons are used as field delimiters. Asterisks are used to denote the presently active configuration line. UTF-7 is meaningless, XOR is encryption and editing .inis passes for entertainment.

    While oRead.Peek <> -1
        sLine = oRead.ReadLine()
        If sLine.Substring(0, 1) = "*" Then Exit While
    End While

Oh, and the referenced MSSQL server turned out to be running on a laptop. Of a user (Janet ofcourse) that had long left the company. But I'm still here.


More Posts

Trilemmic Paradigms as Applied to Forced Induction

The Path to Solder Reflow

What the Tic Tac?

Timing belt maintenance

How to save 13¢ per day