Austin Altmann

Austin has a BS in Computer Science from the University of Minnesota with emphases in systems and security. He specializes in web application and thick application penetration testing as well as on-site and phone-based social engineering assessments. Austin also contributes to the development of applications and tools for the NetSPI penetration testing team.
More by Austin Altmann
WP_Query Object
(
    [query] => Array
        (
            [post_type] => Array
                (
                    [0] => post
                    [1] => webinars
                )

            [posts_per_page] => -1
            [post_status] => publish
            [meta_query] => Array
                (
                    [relation] => OR
                    [0] => Array
                        (
                            [key] => new_authors
                            [value] => "49"
                            [compare] => LIKE
                        )

                    [1] => Array
                        (
                            [key] => new_presenters
                            [value] => "49"
                            [compare] => LIKE
                        )

                )

        )

    [query_vars] => Array
        (
            [post_type] => Array
                (
                    [0] => post
                    [1] => webinars
                )

            [posts_per_page] => -1
            [post_status] => publish
            [meta_query] => Array
                (
                    [relation] => OR
                    [0] => Array
                        (
                            [key] => new_authors
                            [value] => "49"
                            [compare] => LIKE
                        )

                    [1] => Array
                        (
                            [key] => new_presenters
                            [value] => "49"
                            [compare] => LIKE
                        )

                )

            [error] => 
            [m] => 
            [p] => 0
            [post_parent] => 
            [subpost] => 
            [subpost_id] => 
            [attachment] => 
            [attachment_id] => 0
            [name] => 
            [pagename] => 
            [page_id] => 0
            [second] => 
            [minute] => 
            [hour] => 
            [day] => 0
            [monthnum] => 0
            [year] => 0
            [w] => 0
            [category_name] => 
            [tag] => 
            [cat] => 
            [tag_id] => 
            [author] => 
            [author_name] => 
            [feed] => 
            [tb] => 
            [paged] => 0
            [meta_key] => 
            [meta_value] => 
            [preview] => 
            [s] => 
            [sentence] => 
            [title] => 
            [fields] => 
            [menu_order] => 
            [embed] => 
            [category__in] => Array
                (
                )

            [category__not_in] => Array
                (
                )

            [category__and] => Array
                (
                )

            [post__in] => Array
                (
                )

            [post__not_in] => Array
                (
                )

            [post_name__in] => Array
                (
                )

            [tag__in] => Array
                (
                )

            [tag__not_in] => Array
                (
                )

            [tag__and] => Array
                (
                )

            [tag_slug__in] => Array
                (
                )

            [tag_slug__and] => Array
                (
                )

            [post_parent__in] => Array
                (
                )

            [post_parent__not_in] => Array
                (
                )

            [author__in] => Array
                (
                )

            [author__not_in] => Array
                (
                )

            [search_columns] => Array
                (
                )

            [ignore_sticky_posts] => 
            [suppress_filters] => 
            [cache_results] => 1
            [update_post_term_cache] => 1
            [update_menu_item_cache] => 
            [lazy_load_term_meta] => 1
            [update_post_meta_cache] => 1
            [nopaging] => 1
            [comments_per_page] => 50
            [no_found_rows] => 
            [order] => DESC
        )

    [tax_query] => WP_Tax_Query Object
        (
            [queries] => Array
                (
                )

            [relation] => AND
            [table_aliases:protected] => Array
                (
                )

            [queried_terms] => Array
                (
                )

            [primary_table] => wp_posts
            [primary_id_column] => ID
        )

    [meta_query] => WP_Meta_Query Object
        (
            [queries] => Array
                (
                    [0] => Array
                        (
                            [key] => new_authors
                            [value] => "49"
                            [compare] => LIKE
                        )

                    [1] => Array
                        (
                            [key] => new_presenters
                            [value] => "49"
                            [compare] => LIKE
                        )

                    [relation] => OR
                )

            [relation] => OR
            [meta_table] => wp_postmeta
            [meta_id_column] => post_id
            [primary_table] => wp_posts
            [primary_id_column] => ID
            [table_aliases:protected] => Array
                (
                    [0] => wp_postmeta
                )

            [clauses:protected] => Array
                (
                    [wp_postmeta] => Array
                        (
                            [key] => new_authors
                            [value] => "49"
                            [compare] => LIKE
                            [compare_key] => =
                            [alias] => wp_postmeta
                            [cast] => CHAR
                        )

                    [wp_postmeta-1] => Array
                        (
                            [key] => new_presenters
                            [value] => "49"
                            [compare] => LIKE
                            [compare_key] => =
                            [alias] => wp_postmeta
                            [cast] => CHAR
                        )

                )

            [has_or_relation:protected] => 1
        )

    [date_query] => 
    [request] => SELECT   wp_posts.ID
					 FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
					 WHERE 1=1  AND ( 
  ( wp_postmeta.meta_key = 'new_authors' AND wp_postmeta.meta_value LIKE '{1604c323e3a1f1c9e5e75b819be077ed5398faf1df5f9ced5fb39049318ef8da}\"49\"{1604c323e3a1f1c9e5e75b819be077ed5398faf1df5f9ced5fb39049318ef8da}' ) 
  OR 
  ( wp_postmeta.meta_key = 'new_presenters' AND wp_postmeta.meta_value LIKE '{1604c323e3a1f1c9e5e75b819be077ed5398faf1df5f9ced5fb39049318ef8da}\"49\"{1604c323e3a1f1c9e5e75b819be077ed5398faf1df5f9ced5fb39049318ef8da}' )
) AND wp_posts.post_type IN ('post', 'webinars') AND ((wp_posts.post_status = 'publish'))
					 GROUP BY wp_posts.ID
					 ORDER BY wp_posts.post_date DESC
					 
    [posts] => Array
        (
            [0] => WP_Post Object
                (
                    [ID] => 11668
                    [post_author] => 49
                    [post_date] => 2020-06-18 07:00:27
                    [post_date_gmt] => 2020-06-18 07:00:27
                    [post_content] => 

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Overview

Welcome to the final installment of Introduction to Hacking Thick Clients! What a journey. We've learned a lot, but there's just one last thing to mention - the memory!

Viewing Data

If a system is compromised by an attacker, values stored in memory may be exposed. Of course, if an attacker has compromised a system to the point of analyzing memory, there are a lot of other issues. But it is my opinion that an application should take responsibility for its security as much as possible and not rely on the security of the system it resides on. I go further into some solutions and their practicalities in my freshman blog post, but most of them are focused on limiting exposure, not eliminating exposure. If possible, assign sensitive data to mutable data types, such as arrays. Immutable data types like strings cannot be cleared from memory on command, but an array can be cleared from memory as soon as its values are no longer needed.

So let's see how Beta Bank handles its sensitive data. I'll let it slide if I've logged in and the password is still in memory. But in this example, I've already authenticated to the application, logged out, and meandered through my studio apartment for a few minutes. That's enough leeway - time to examine the application's memory. First, find the application in Task Manager, right click, and click "Create dump file."

Dump

Now, a likely massive file has been generated. That's everything from that process's memory. And thankfully, friendly neighborhood Mark Russinovich has created a tool called Strings that will help to analyze this data by retrieving only the string values. I've taken the liberty of running the following line in PowerShell:

.strings.exe .BetaBank.DMP | Out-File -FilePath .BetaBank.DMP.txt

The resultant file should be a much more manageable size, and any text editor worth its salt can search for values of choice. The password I used when logging in was NetSPI1!. And it shows up a lot.

Dump

Another choice is to just open the entire dump file in a hex editor like HxD. The password appears just as easily and visibly, but so does a lot of other data.

Dump

Modifying Data

As I was coming up with examples for this portion of the blog, I realized that I first began modifying data in memory as a delinquent child. If you were at all like me growing up and wanted to impress people with lies, you may remember Cheat Engine. Just like my Beta Bank password, game data such as item counts, experience points, and high scores may be in memory plain as day. And these values could be located through a simple search, and the data at that address could be changed to a new value. That level 25 character was a few clicks away from being level 2,147,483,647.

These days, it is much more difficult to earn the admiration of my peers through lies. But gosh darn it, I'm going to try. I've heard from previous installments in this blog series that there's a user named The_Chairman who has a lot of money. I'm going to withdraw a lot of it. The plan is to change my username in memory to The_Chairman. Since the space for the username will already be allocated, I've created an account with the same username length - The_Flairman.

Memory Edit

This account is going to be swamped with overdraft fees. In Wireshark, a SQL statement to withdraw money is being sent with the username The_Flairman. For the sake of this example, let's just use this as verification and pretend the traffic is encrypted. And that a bunch of other security vulnerabilities are patched while still allowing me to do something like this.

Memory Edit E

HxD is just as usable for editing memory as it is viewing, so we'll stick with what we know. With Beta Bank running, click Open RAM to view the live memory for the process.

Memory Edit

Searching for The_Flairman shows a number of locations where the username is referenced in memory.

Memory Edit

I went ahead and replaced every instance of The_Flairman with The_Chairman.

Memory Edit

Below is one of these instances.

Memory Edit

Saving these edits will overwrite the current live memory.

Memory Edit

Back in the application, it's clear that these changes went into effect. But were they functional?

Memory Edit

Using Wireshark, I was able to verify that the Withdraw button will now send a SQL command to withdraw a large amount of money with the username The_Chairman.

Memory Edit

This wouldn't be an issue at all if the SQL command wasn't written with a complete lack of security awareness. In this application, there's not a lot going on that would be "vulnerable" to memory values changing since authorization and storage is all on the server. Others may have simple boolean controls that can be bypassed through memory editing. Plenty of client-side control logic could be bypassed. I even found a simple example involving WinRAR, everyone's favorite application, and how to bypass its registration control.

Further Reading

This blog post barely scratched the surface of memory analysis. The techniques outlined above are a few that are used during our routine testing of thick client applications. But they're also entry points for diving further into malware analysis and reverse engineering. The following resources may be helpful starting points for additional learning:

Introduction to Hacking Thick Clients: The Conclusion

This series outlined quite a few thick client application testing methods and tools at a high level. While it never went especially deep on any one topic, I hope that it, along with BetaFast and Beta Bank, have opened the door for people to develop new security testing skills while having a bit of fun. This is a service line that really pushes creative thinking. Some of the exploitation steps I've seen in reports have made me reach out to coworkers and ask how they even thought to try them. Every once in a while, they unmute me and reply. But I digress . . .

[post_title] => Introduction to Hacking Thick Clients: Part 6 – The Memory [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-6-the-memory [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:01:25 [post_modified_gmt] => 2021-06-08 22:01:25 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11668 [menu_order] => 495 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [1] => WP_Post Object ( [ID] => 11620 [post_author] => 49 [post_date] => 2020-06-11 07:00:53 [post_date_gmt] => 2020-06-11 07:00:53 [post_content] =>

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Information Gathering

When testing any application, it's important to have a good understanding of what's going on beneath the surface. Consider the largest desktop application you've ever seen - that's like half of the thick client applications I test. They're monuments to teamwork and the human spirit. I once had six hours of demos for a test, and the scope didn't even cover the entire application. Even if the code isn't obfuscated, there's no way I can read through and understand everything that's going on. Thankfully, people have made tools to help.

API Monitor

One tool in our arsenal is API Monitor. This application monitors all of the API calls in a process and displays their parameters. In this example, the Summary is a list of API calls made during the authentication to BetaFast. Note the API Filter on the left. When I had all of them checked and authenticated to BetaFast, the Summary almost immediately had over 500,000 API calls logged. And that takes up some serious resources.

Apimonitor

Monitoring BetaFast with API Monitor didn't highlight any particular vulnerabilities from my experience, and almost all of the main functionality is contained to a single assembly, so API monitor won't find the most sensitive data being sent between libraries. But it's a valuable tool for displaying information on which system resources are being used, which files are being referenced or created, network calls, security calls, etc. Moving beyond information gathering and into attacks, it is possible to intercept and modify data before encryption, or to gather cleartext passwords and connection strings as they're passed between libraries.

Issuing Calls

Welcome back to the high level. It's much nicer up here. There's a tool called .net SmokeTest that can be used to load and run individual method calls. No need to load the program and search for where a method call takes place, attach the application to a debugger, or write a single line of code. If a test requires writing a method, .net SmokeTest is an easy way to execute it rather than finding the right spot for it to be called in the application. But it's especially useful for testing various data inputs in prewritten methods.

Take this encrypt method . . . please! Using a decompiler as outlined in the previous blog post, I found a hardcoded encrypted password in BetaFast.exe. Specifically, in the LoginViewModel class. Upon login, the password from the login form is encrypted and compared to this stored value.

Encrypt

The method is written below.

Encrypt

Even further below is a Decrypt method, but it's never called in the application. Since the IV and Key are hardcoded in the application, it just needs a ciphertext input.

Decrypt

It makes sense that the next step would be calling Decrypt on the hardcoded encrypted password. First, start up .net SmokeTest and create an instance of the LoginViewModel class.

Smoketest

Open the LoginViewModel class and enter the stored password as the ciphertext parameter in the Decrypt method. The plaintext password is then displayed below.

Smoketest

There's a NetSPI blog post from years back that highlights a Powershell alternative. The following code can be run in to call specific methods.

# Load Assembly
$Assembly = [System.Reflection.Assembly]::LoadFile("C:UsersnetspiDesktopExamples3-TierBetaFast.exe")

# Create binding
$BindingFlags= [Reflection.BindingFlags] "NonPublic,Instance"

# Target the class
$Instance = new-object "BetaFast.ViewModel.LoginViewModel" 

# Call the methods
$Instance.GetType().GetMethod("Encrypt",$BindingFlags).Invoke($Instance,"Spring1980!")
$Instance.GetType().GetMethod("Decrypt",$BindingFlags).Invoke($Instance,"PE/jSP7tOGDLoZLXRvPtlA==")

Spring1980! is encrypted, and PE/jSP7tOGDLoZLXRvPtlA== is decrypted.

Powershell Betafast
[post_title] => Introduction to Hacking Thick Clients: Part 5 – The API [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-5-the-api [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:01:17 [post_modified_gmt] => 2021-06-08 22:01:17 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11620 [menu_order] => 498 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [2] => WP_Post Object ( [ID] => 11621 [post_author] => 49 [post_date] => 2020-05-28 07:00:33 [post_date_gmt] => 2020-05-28 07:00:33 [post_content] =>

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The Filesystem and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Assembly Controls

Libraries and executables can be compiled with some additional security measures to protect against code exploitation:

  • Address Space Layout Randomization (ASLR) - An application's locations in memory are randomized at load time, preventing attacks such as return-to-libc that lead to code execution by overwriting specific addresses.
  • SafeSEH - A list of safe exception handlers is stored within a binary, preventing an attacker from forcing the application to execute code during a call to a malicious exception.
  • Data Execution Prevention (DEP) - Areas of memory can be marked as non-executable, preventing an attacker from storing code for a buffer overflow attack in these regions.
  • Authenticode/Strong Naming - Assemblies can be protected by signing. If left unsigned, an attacker is able to modify and replace them with malicious content.
  • Controlflowguard - An extension of ASLR and DEP that limits the addresses where code can execute from.
  • HighentropyVA - A 64 bit application uses ASLR.

Thankfully, NetSPI's very own Eric Gruber has released a tool called PESecurity to check if a binary has been compiled with the above code execution preventions. Many of the thick client applications we test have installation directories filled to the brim with assemblies, and PESecurity is especially useful for checking a large number of files.

In the below example, PESecurity is used to check BetaBank.exe. It is compiled with ASLR and DEP. SafeSEH is only applicable for 32 bit assemblies. But the executable is unsigned.

Pesecurity Betabank

Decompiling

Decompiling is one of my favorite parts of testing thick clients. As someone who has made far too many programming mistakes, it's cathartic to find those of other programmers. By their very nature, .Net assemblies can be read as source code using tools such as the following:

This is because .Net assemblies are managed code. When a .Net application is compiled, it's compiled to Intermediate Language code. Only at runtime is Intermediate Language code finally compiled to machine code by a runtime environment. .Net assemblies are so easy to "reverse" into source code because the Intermediate Language contains so much information such as types and names.

Unmanaged code, such as C or C++, is compiled down to a binary. It doesn't run through a runtime like C# does with Common Language Runtime - it's loaded directly into memory.

Information Disclosures

Managed Code

The following example will use the aforementioned BetaBank.exe, found in our BetaFast GitHub. It will also be using dnSpy as the decompiler of choice.

One of the first things I look for when testing a thick client application is hardcoded sensitive information such as credentials, encryption keys, and connection strings. Decompiling isn't even required to find sensitive information - configuration files are great places to look. When a .Net assembly is run, it may search a configuration file for global values such as a connection string, web endpoints, or passwords that are referenced in the executable. Procmon and the steps outlined in the previous entry are very useful for identifying these files. There's a connection string stored right in the Beta Bank's config file. This can be used to authenticate directly to the database using a tool such as SQL Server Management Studio.

Connectionstring

If you're wondering about the 10.2.2.55 address, that's the VM I'm running Docker in.

Ssms

But for information disclosures in the source code, first decompile any of the application's binaries. BetaBank.exe is loaded into dnSpy.

Dnspy

dnSpy has a solid search feature. I type in terms like "key," "IV," "connection," "password," "encrypt," and "decrypt" to look for how the application handles encryption, authentication, and database connections. The application also has a filter in its search function. Below, I limited the search to only the Selected Files, but a search can also be limited to specific libraries and object types. Looks like there's a hardcoded key in BetaBank.ViewModel.RegisterViewModel and BetaBank.ViewModel.LoginViewModel.

Dnspy

And searching for "password" shows a hardcoded encrypted password. Apparently the developer(s) implemented an authorization check on the client side. The username "The_Chairman" is directly compared to the value in the Username textbox, and the encrypted password is directly compared to the encrypted value of the value in the Password textbox.

Dnspy

The BetaEncryption class can be decompiled, showing some very custom encryption logic.

Dnspy

Unmanaged Code

As I mentioned at the beginning of this section, it's not possible to have such a clean look at the source code when testing unmanaged code. Instead, we once again look to the CTO of Microsoft Azure for help. Strings is a tool in the Sysinternals suite that will output a list of strings saved in an executable. When analyzing memory dumps or unmanaged code binaries, I will retrieve the list of all the strings (most of them will probably look like nonsense), and then search for key terms like the ones above in a text editor of choice.

Modifying Assemblies

Using dnSpy, a class can actually be modified, and the binary can be recompiled. Below, I've reversed the Encrypt function, and I use a MessageBox to show the decrypted adminPassword when a user successfully authenticates to the application.

Dnspy E

Saving the module as a new executable . . .

Dnspy

Finally, when I authenticate as a user, the MessageBox prints The_Chairman's password.

Adminpassword

A MessageBox is very useful to add to the application when trying to gather information. It's like when I use a print statement instead of a debugger.

A Beta Bank developer may decide to patch this vulnerability by removing the hardcoded encryption key. However, Beta Bank's custom encryption can still be reverse engineered to gather the key for decryption. Below, I've added a function that performs an XOR on the plaintext password and the encrypted password, thus exposing the encryption key. In the Decrypt function, I retrieve the key by passing a known plaintext password (my own) and its encrypted value.

Dnspy

But that was actually too much work. If we don't need The_Chairman's password for later, the username and encrypted password can just be placed directly into the Login function. Boolean logic can also be modified so that anything verified server-side, such as IsAdmin(), can be modified to always return true.

Dnspy

Obfuscation

Source code isn't often this legible. Sometimes, code is obfuscated. And while there's no security through obscurity, it sure does make the job of a security consultant a little more difficult.

Below is the BetaEncryption class from earlier after I applied some custom obfuscation by mashing my keyboard to rename the class, methods, and parameters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public static class jinjnhglkjd
{
    public static string dsfggd(byte[] erttr, string dgfhfgi)
    {
        byte[] plaintextBytes = Encoding.ASCII.GetBytes(dgfhfgi);

        byte[] ciphertextBytes;

        int messageLength = plaintextBytes.Length;

        while (messageLength % erttr.Length != 0)
        {
            Array.Resize(ref plaintextBytes, plaintextBytes.Length + 1);
            plaintextBytes[plaintextBytes.Length - 1] = 0x00;
            messageLength += 1;
        }

        ciphertextBytes = new byte[messageLength];
        int startingIndex = 0;
        for (int i = 0; i < (messageLength / erttr.Length); i++)
        {
            for (int j = 0; j < erttr.Length; j++)
            {
                ciphertextBytes[j + startingIndex] = Convert.ToByte(plaintextBytes[j + startingIndex] ^ erttr[j]);
            }
            startingIndex++;
        }
        return Convert.ToBase64String(ciphertextBytes);
    }
}

All of the functionality is still there. Some obfuscation techniques may go even further to make code illegible. But what this does is makes it more difficult to search through and reverse engineer the source code. The Assembly Explorer of dnSpy would be full of nonsense class names, and searching for specific terms such as "Encrypt" would not yield any results.

There are various tools for deobfuscation such as de4dot. Below is an example of what a deobfuscator may interpret my keyboard mashing obfuscation as. The classes at least have some sense of legibility, and methods are named some variation of method rather than dsfggd.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public static class class_1
{
    public static string method_1(byte[] byte_1, string string_1)
    {
        byte[] plaintextBytes = Encoding.ASCII.GetBytes(string_1);

        byte[] ciphertextBytes;

        int messageLength = plaintextBytes.Length;

        while (messageLength % byte_1.Length != 0)
        {
            Array.Resize(ref plaintextBytes, plaintextBytes.Length + 1);
            plaintextBytes[plaintextBytes.Length - 1] = 0x00;
            messageLength += 1;
        }

        ciphertextBytes = new byte[messageLength];
        int startingIndex = 0;
        for (int i = 0; i < (messageLength / byte_1.Length); i++)
        {
            for (int j = 0; j < byte_1.Length; j++)
            {
                ciphertextBytes[j + startingIndex] = Convert.ToByte(plaintextBytes[j + startingIndex] ^ byte_1[j]);
            }
            startingIndex++;
        }
        return Convert.ToBase64String(ciphertextBytes);
    }
}

Obfuscation doesn't secure code. But it makes browsing the source code all around more of a headache than reading someone else's large codebase typically is.

[post_title] => Introduction to Hacking Thick Clients: Part 4 – The Assemblies [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-4-the-assemblies [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:01:04 [post_modified_gmt] => 2021-06-08 22:01:04 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11621 [menu_order] => 501 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [3] => WP_Post Object ( [ID] => 11619 [post_author] => 49 [post_date] => 2020-05-21 07:00:04 [post_date_gmt] => 2020-05-21 07:00:04 [post_content] =>

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Information Disclosure

Many applications have been written by developers who could not resist the sweet siren song of storing sensitive information in the file system and/or registry. This has included social security numbers, credit card numbers, database connection strings, credentials, etc. Developers may encrypt this data for an added sense of security, but there could be an insecure or custom encryption implementation. If it is a necessity to store encrypted data, the key must always be stored in a separate location, such as securely in a database.

Focusing the Test

Testing for information disclosures in the file system and registry is quite simple - you just need to look at the files and registry keys used by the application and make sure there isn't any sensitive information there. But applications often make an insane number of calls to files and registry keys. That's why it is crucial to focus on the areas of the application most likely to write or read sensitive data.

Installer

If it's possible to test the installation, always use this as an opportunity to look for writes to the file system or registry. It's the perfect time for data to be written that the application will later read. Will the application be connecting to a database? Maybe the installation process writes the database connection string to a registry key. Maybe default administrator credentials are being stored in the file system.

Application

In the actual application, identify functional areas that may create or modify sensitive information. This always includes the initial database connection and a login form. Plenty of applications save some information for a Remember Me function, so determine how that's being stored and retrieved. In the authenticated portion of the application, look for areas that specifically handle sensitive data.

Tools and Examples

The Sysinternals suite contains many helpful tools for testing Windows applications. The two tools I will be highlighting are AccessEnum and Process Monitor, written by the CTO of Microsoft Azure. The vulnerable application I will be highlighting is BetaFast, written by the owner of 32 Arnold Schwarzenegger movies.

Configuration

Process Monitor will try and show you more information than you thought was possible, so the first step is to set up a filter. One item that Process Monitor can filter by is the PID of the application you're testing, so be sure to check for that in Task Manager.

Pid

In this example, I also filtered by Event Class.

Procmon Filter
Registry

When opening BetaFast, a login form with a Remember Me function is immediately displayed.

Betafast Rememberme

With Process Monitor running, authenticate to the application and allow it to remember your credentials. Notice that two RegSetValue operations are performed - one for a username, another for a password. Also note how many events actually took place there but were ignored thanks to the filter.

Procmon Credentials

The registry paths might not be as obvious as CredentialsPassword, so it's more important to look for specific operations rather than paths. Registry Editor can be used to view the paths from the previous step, displaying cleartext credentials.

Registry Credentials

AccessEnum allows us to determine who can read and write registries and directories. The Credentials registry can only be read by Administrators and NT AUTHORITYRESTRICTED. Since this is in HKEY_CURRENT_USER, these credentials would only be exposed to highly privileged accounts and the current user. But they would still be exposed.

Accessenum Registry
File System

BetaFast also has a payment details form. Process Monitor can analyze what the Load Payment Details button is attempting to load.

Load Payment Details

The application is looking for a file in C:ProgramDataBetaFastPaymentDetails with the current user's name.

Procmon Load Payment Details

The next step is to submit the form with Save Payment Details checked and see what's happening in the file system.

Save Payment Details

Unsurprisingly, the file that Load Payment Details was looking for is now saved.

Procmon Save Payment Details

The file also unsurprisingly contains cleartext credit card information.

Saved Payment Details

AccessEnum shows that everyone can read this file.

Accessenum Filesystem

Of course, this shouldn't be surprising either. ProgramData is not user specific while the AppData folder is. Storing cleartext sensitive information in AppData would still show up in one of our reports, but it at least wouldn't be readable by everyone on the system.

DLL Hijacking

This topic could be a blog or two of its own, and we even have one from 2012. But it also has to do with the file system, so it's worth a brief overview here as well.

  1. Applications will search for DLLs to load.
  2. Some applications will not specify a fully qualified path.
  3. Windows will search a predefined order of directories for this DLL.
  4. Using Process Monitor, an attacker could identify this DLL because the application would be trying to open a .dll file that could not be found.
  5. An attacker could then place a malicious DLL in one of the directories in the search order, causing the application to execute malicious code.

The problem with DLL Hijacking is in step 5. The issue mostly comes down to configuration issues. Microsoft highlights a few different attack scenarios and their severities in this article. They also have an article on how to prevent and identify these attacks. For even more additional reading on attack scenarios, check out this article as well as this one.

The main point I wanted to cover is that file system vulnerabilities don't just come from writing data - they sometimes stem from what's being read. Also, Process Monitor is again very useful.

Referenced Articles:

[post_title] => Introduction to Hacking Thick Clients: Part 3 – The File System and Registry [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-3 [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:00:53 [post_modified_gmt] => 2021-06-08 22:00:53 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11619 [menu_order] => 503 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [4] => WP_Post Object ( [ID] => 11587 [post_author] => 49 [post_date] => 2020-05-14 07:00:17 [post_date_gmt] => 2020-05-14 07:00:17 [post_content] =>

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Overview

In this post, we'll cover network testing in thick client applications and how it's performed on different architectures. BetaFast is written with a three-tier architecture.

  • Tier 1: The client displays and collects data.
  • Tier 2: Web requests are sent to a server where business logic is handled.
  • Tier 3: A database server modifies and retrieves data for the application server.

Beta Bank is written with a two-tier architecture.

  • Tier 1: The client displays and collects data.
  • Tier 2: A database server handles business logic and performs data queries and modifications for the client.

One-tier architecture also exists, but it's not applicable to this blog post because the client, business logic, and data storage are all on the same system. There can be more than three tiers, but the same methods and tools outlined below will apply.

Two-Tier

Wireshark

One of the first things I like to do when I begin a thick client application test is see what's actually happening on the network. And to do that, I use a tool called Wireshark to capture and filter network traffic.

Wireshark

In this example, I'm testing the Beta Bank vulnerable application. With a proper capture filter in place, I'll typically begin by just sort of doing things in the thick client. I'll submit forms, navigate through the app, modify data, etc. Then, I'll look through Wireshark for anything sensitive.

  • Is the database connection unencrypted?
  • Is sensitive data, such as social security numbers or medical information, transmitted in cleartext?

At one point, I authenticated to the application with the username "blogger." Searching through the packet list in Wireshark, the name "blogger" appears in a Login procedure. The fact that this is even remotely legible means that the database connection is unencrypted, and anyone with access to this network is able to read this information just as easily. Thankfully, the password appears to be encrypted, so a hacker won't be able to access my account.

Wireshark

Or will they?!

Any form of a password sent from a client, whether it's cleartext, hashed, or encrypted, should be treated as the password itself. Sure, the password is encrypted. But knowing and sending this value to the server will authenticate this user to the application. There's no additional defense provided by only obscuring a parameter value and not securely encrypting an entire transmission. Another value observed through wireshark is the output parameter for the Login procedure - GUID. In an authenticated portion of the application, the procedures accept a GUID as a parameter.

Wireshark

This is what we in the business call a "session ID." Armed with only this value, an attacker will be able to perform authenticated actions as the blogger user as long as the session remains active.

But even that is making things more complicated than they need to be.

Echo Mirage

In this example, I am the harbinger of revolution -  a veteran of the computer who has had enough of the wealthy elite. While you were smelling the roses, I was sniffing the network. And I captured blogger's username and encrypted password from that Login procedure.

Now, a tool like Echo Mirage comes in handy. Echo Mirage allows TCP traffic to be intercepted and modified. I can authenticate to the application with the username "blogger" and an arbitrary password, then intercept the packet containing the Login procedure.

Echo Mirage

The encrypted password can be changed to the value captured by Wireshark.

Echo Mirage

As soon as I send this request, I'm in. Let's see how much money this big shot blogger has.

Blogger

Hmmm. Perhaps this blogging thing is more of a hobby. Let's see who else is banking with Beta Bank. Using the techniques from the previous post in the series, the Withdraw button can be enabled.

Withdraw

Wireshark shows that this function is sending a SQL query.

Wireshark

Echo Mirage can be used to directly modify the SQL statement. It can't change the length of the packet, but the remaining SQL can be commented out.

Echo Mirage Sql

The server responds with the Users table. The account connecting to the database clearly has excessive privileges, but we now have info on every user.

Wireshark

There's any number of attack vectors now. There's still much to explore and modify in the database. But The_Chairman sounds very wealthy and very elite, and their encrypted password is practically begging to be used.

Chairman

Hackers - 1

Wealthy Elite - 0

Three-Tier

Burp

Burp Suite is perhaps the tool I use most on the job. It's invaluable for any application assessment that deals with HTTP requests and responses. If you haven't heard of it or used it, there are going to be far more interesting guides out there than this on how powerful the tool can be.

If a thick client is built on a three-tier architecture, the network portion of the test will essentially be the same as testing a web application. First order of business is proxying the traffic. In the proxy tab of Burp, set up a listener on 127.0.0.1 and a port of choice.

Burp

Next, rather than proxying a browser through Burp, proxy the whole system.

Proxy E

There may be a lot of traffic that doesn't belong to the application being tested. But this is the time for determining which requests are originating from the thick client. I only restrict the scope in Burp once I know the complete set of hosts the app is reaching out to. With BetaFast, I've determined the application is only sending requests to https://www.betafast.net:8080.

Burp Cart

And now Burp can be used the same as in any web application test. Below, I sent a request to the Repeater tab and found SQL injection.

Burp Sql

Closing Remarks

A lot of important things happen over networks, so make sure not to focus only on the client when testing thick client applications! What could Beta Bank and BetaFast have done differently to protect their systems? Well, a good amount. But here are a few examples:

Beta Bank

  • Encrypt database connections - Encrypted connections hide sensitive data from wandering eyes on a network. They also ensure that traffic cannot be modified as long as the encryption is implemented securely.
  • Principle of least privilege - Since Beta Bank connects to the database as a highly-privileged user, an attacker has free rein of the database should an exploit be found. If the account connecting to the database had the least possible privilege, an attacker could not pivot beyond normal functionality.
  • Salted and hashed passwords - Encryption is by its nature reversible. This will be highlighted further in an upcoming entry in this series.
  • Authentication logic - The password being sent over the network should not be directly compared to the password stored in the database. Otherwise, the encrypted password doesn't even need to be decrypted or a hashed password cracked. The password should be sent as-is in an encrypted transmission. The server then salts and hashes the password and compares the resultant value to the salted and hashed password stored in the database.

BetaFast

  • Input validation and parameterized queries - Unlike Beta Bank, it's not an issue that traffic can be intercepted and modified. The issue is that vulnerabilities exist in the way the application server processes input. Anything sent from the client should be validated by the server, and SQL statements should have parameterized queries.

As always, be sure to check out our GitHub for copies of BetaFast and Beta Bank. And be sure to tune in for further guides on hacking thick client applications!

[post_title] => Introduction to Hacking Thick Clients: Part 2 – The Network [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-2-the-network [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:00:37 [post_modified_gmt] => 2021-06-08 22:00:37 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11587 [menu_order] => 506 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [5] => WP_Post Object ( [ID] => 11507 [post_author] => 49 [post_date] => 2020-04-30 07:00:21 [post_date_gmt] => 2020-04-30 07:00:21 [post_content] =>

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Overview

The thick clients we come across most often at NetSPI are written in C# and a bit long in the tooth. In these applications, there are two main GUI platforms: Windows Forms and Windows Presentation Foundation (WPF).

Windows Forms

Windows Forms was state of the art in 2002. And it's not half bad in 2020! Basically, a form is composed of controls, which are your typical Windows objects such as text boxes, labels, buttons, etc. And each of these objects has its own properties, methods, and events.

Consider the following Windows Forms login form:

Login

An administrator's credentials are saved. Nice! Let's steal those for later!

Not Allowed

Darn! Thankfully, there are some tools at our disposal that allow us to view and modify controls. The first is WinSpy. Simply target a control and note that the masked value is stored in plain text.

Login Winspy

Another similar tool for targeting Windows Forms objects is Window Detective. Selecting a control will highlight the object in the desktop window hierarchy. There, you can view its properties, including the elusive password.

Login Win Detective
Login Win Detective
Login Win Detective

Here's another Windows Forms example. This application verifies the Role on the client-side and has the text box disabled so it cannot be changed.

Disabled

But with WinSpy and Window Detective, we can set the text property to Admin.

Disabled

And why not just change the Enabled property to true?

Disabled

Some applications attempt to ward off SQL injections or other attacks by limiting the length of input or the types of input characters. But relying on any client-side control is a clear security risk.

Windows Presentation Foundation

WPF was released a day before Tenacious D in The Pick of Destiny and has aged just as well. It's more complicated to work with than Windows Forms, but allows for a much more customizable design. A WPF-focused tool such as Snoop is needed for this platform.

Authenticate to BetaFast as a typical user and note that there are four menu items: Home, Shopping Cart, Settings, Logout.

Betafast Menu

By connecting Snoop to the application process, the design tree can be expanded to reveal an AdminVisibility property set to Hidden.

Snoop

Changing this value to Visible reveals additional menu items restricted to administrators.

Snoop

By itself, this is not a vulnerability. Any functionality in these restricted pages should have server-side authorization checks. However, this is often not the case. Below, a User is able to create an Admin account and view all of the accounts in the database.

Betafast User Management

The payment page of this application verifies the total rental cost in the client, not the server.

Betafast Payment

That means we can use Snoop to get a nice discount on these Betamax tapes - perhaps store credit?

Snoop Payment
Snoop Payment

Closing Remarks

Modifying GUI elements in thick clients is rather straightforward, especially with a set of polished tools. The remediation steps for any of these vulnerabilities are simple as well:

  • Perform authorization and input validation on the server
  • Do not hide sensitive data behind GUI designs

I'll add another link to our BetaFast GitHub repo here. Be sure to try some of these examples out yourself, and be sure to tune in for our next installment of Introduction to Hacking Thick Clients.

[post_title] => Introduction to Hacking Thick Clients: Part 1 - the GUI [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-1-the-gui [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:00:13 [post_modified_gmt] => 2021-06-08 22:00:13 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11507 [menu_order] => 512 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [6] => WP_Post Object ( [ID] => 11551 [post_author] => 49 [post_date] => 2020-04-27 07:00:41 [post_date_gmt] => 2020-04-27 07:00:41 [post_content] =>

Another vulnerable application is being unleashed into the world. Developed here at NetSPI, BetaFast is a vulnerable thick client application and valuable resource for practicing security testing.

History

Years ago, a NetSPI consultant was venturing into the basement of our office building to retrieve some fresh fingerless gloves from storage. Wandering through the scarcely lit corridors, littered with the forgotten remnants of tenants past, a treasure caught their eye. Tucked behind dust-caked boxes and an aged flock of Herman Miller Aerons, nestled under the flickering light of a bare incandescent bulb, a computer terminal stood proudly.

A team of NetSPI's best and brightest took it upon themselves to learn of its secrets. Created by a defunct and untraceable company called BetaFast, this machine's sole purpose was to dispense Betamax tapes, a medium from 1975. How long had it remained dormant? How long had it remained operational? Why?

Releases

The consultants worked tirelessly to reverse engineer the movie rental kiosk. Its software was written in a proprietary language and, unsurprisingly, was not secure.

The kiosk's front-end and back-end code has been rewritten in C#. Throughout the upcoming weeks, we will be releasing blog posts outlining the vulnerabilities found in the software. The code can be found on our GitHub. Additionally, our team was able to find and preserve the original BetaFast website, but with an added link to our GitHub: https://www.betafast.net/.

Vulnerabilities

Two vulnerable applications have been released. One is BetaFast, a premier Betamax rental kiosk, written with three-tier architecture. The other is Beta Bank, a premier finance application for the elite, written with two-tier architecture.

BetaFast contains but is not limited to the following vulnerabilities:

  • Hardcoded Encryption Data
  • Hardcoded Encrypted Password
  • SQL Injection
  • Authorization Bypass
  • Missing server-side input validation
  • Cleartext Password Stored - Registry
  • Cleartext Sensitive Data Stored - Files
  • Weak File Upload Controls
  • Weak Input Validation
  • No Code Obfuscation

Beta Bank was written to include many of the above findings while highlighting some additional security flaws:

  • Unencrypted Database Connection
  • Hardcoded Connection String
  • Weak Password Storage
  • Custom Encryption Implementation

Published Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Instructions

https://www.youtube.com/embed/joVF53aOXX0
[post_title] => Introducing BetaFast - NetSPI's Vulnerable Thick Client [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introducing-betafast [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:00:21 [post_modified_gmt] => 2021-06-08 22:00:21 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11551 [menu_order] => 514 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [7] => WP_Post Object ( [ID] => 10788 [post_author] => 49 [post_date] => 2019-10-24 07:00:25 [post_date_gmt] => 2019-10-24 07:00:25 [post_content] =>

One vulnerability that we frequently look for when testing thick client applications is plain text passwords that are exposed in memory. Microsoft provides the SecureString to help protect passwords in memory, but what it does not provide is a perfect solution to actually using the SecureString when sending web requests. And as you'll see below, there is none, but there are some safer ways to operate.

NetworkCredential Might Be Good Enough

If you're handling passwords in forms other than the login, NetworkCredential won't be the best tool for the job. But if you want to use an authentication scheme like Basic or Digest, you might be satisfied implementing a CredentialCache and NetworkCredential as seen here. After all, there's a NetworkCredential constructor with a SecureString password argument. However, the password will be exposed in memory as a string when preparing to send a WebRequest with the credentials. Each authentication scheme makes a call to the NetworkCredential's InternalGetPassword function which will return the password in plain text.

internal string InternalGetPassword() {
    string decryptedString = UnsafeNclNativeMethods.SecureStringHelper.CreateString(m_password);
    return decryptedString;
}

The String Problem

The entire point of using a SecureString is to limit the exposure of the plain text password in memory (see the blog title). Strings are immutable and therefore cannot be cleared on command. Their values will exist in memory until the garbage collector rolls around. If strings are used to handle the plain text password, it may exist in more addresses and for longer than anticipated.

The String Solution

Don't use strings. Use a character or byte array - arrays are mutable!

The Code

Below is some of my code to log into the application. The basic idea of it comes from some Microsoft examples as well as this StackOverflow post. SecureStringLogin accepts the username, password (as a SecureString), and the login function itself which accepts the username as a string and the password as a byte array. GCHandle.Alloc is called to pin the byte array of the future plain text password, ensuring that it stays fixed in one memory location.

public static async Task SecureStringLogin(string username, SecureString password, Func<string, byte[], Task> Login)
{
    byte[] plaintext = null;
    GCHandle gcHandle = GCHandle.Alloc(plaintext, GCHandleType.Pinned);

    IntPtr unmanagedPtr = IntPtr.Zero;

    try
    {
        SecureStringToByteArray(unmanagedPtr, password, ref plaintext);
        await Login(username, plaintext);
    }
    finally
    {
        ClearPasswordFromMemory(unmanagedPtr, ref plaintext, password, gcHandle);
    }
}

And to convert the SecureString to a byte array, we'll need the SecureString password itself,  a reference to the byte array, and to set that IntPtr to the location of the SecureString's contents.

private static void SecureStringToByteArray(IntPtr ptr, SecureString ciphertext, ref byte[] plaintext) 
{ 
    ptr= Marshal.SecureStringToBSTR(ciphertext);
    plaintext = new byte[ciphertext.Length];
    unsafe
    { 
        // Copy without null bytes
        byte* bstr = (byte*)ptr;
        for (int i = 0; i < plaintext.Length; i++)
        { 
            plaintext[i] = *bstr ++;
            *bstr = *bstr++;
        } 
    } 
}

Once the login is completed, the byte array will need to be cleared and unpinned.

private static void ClearPasswordFromMemory(IntPtr ptr, ref byte[] plaintext, SecureString password, GCHandle gcHandle)
{
    password.Dispose();
    Array.Clear(plaintext, 0, plaintext.Length);
    gcHandle.Free();
    if (ptr != IntPtr.Zero)
        Marshal.ZeroFreeBSTR(ptr);
}

Finally, whether you're using streams or an HttpClient for your requests, you'll just need to craft the body as a byte array and remember to clear and dispose of everything as usual. And there you go!

Closing Thoughts

The system that the application is running on could be compromised, and I believe the application should therefore be designed as securely as possible independent of where it is running. But this code is only cutting down on the time the plain text password is in memory and providing control over when it's cleared rather than depending on the garbage collector. If the password's value is going to be used for anything on another machine, it will need to be exposed as plain text, and there's no way around it.
Microsoft says a SecureString is a little better than using a string. But if you're set on using a PasswordBox in some sort of form, those are your two choices.

Source Code

[post_title] => Limiting The Exposure of Plain Text Passwords in C# [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => thick-application-penetration-testing-limiting-the-exposure-of-plain-text-passwords-in-c [to_ping] => [pinged] => [post_modified] => 2023-04-07 09:21:21 [post_modified_gmt] => 2023-04-07 14:21:21 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=10788 [menu_order] => 553 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) ) [post_count] => 8 [current_post] => -1 [before_loop] => 1 [in_the_loop] => [post] => WP_Post Object ( [ID] => 11668 [post_author] => 49 [post_date] => 2020-06-18 07:00:27 [post_date_gmt] => 2020-06-18 07:00:27 [post_content] =>

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.

Installments:

  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory

Overview

Welcome to the final installment of Introduction to Hacking Thick Clients! What a journey. We've learned a lot, but there's just one last thing to mention - the memory!

Viewing Data

If a system is compromised by an attacker, values stored in memory may be exposed. Of course, if an attacker has compromised a system to the point of analyzing memory, there are a lot of other issues. But it is my opinion that an application should take responsibility for its security as much as possible and not rely on the security of the system it resides on. I go further into some solutions and their practicalities in my freshman blog post, but most of them are focused on limiting exposure, not eliminating exposure. If possible, assign sensitive data to mutable data types, such as arrays. Immutable data types like strings cannot be cleared from memory on command, but an array can be cleared from memory as soon as its values are no longer needed.

So let's see how Beta Bank handles its sensitive data. I'll let it slide if I've logged in and the password is still in memory. But in this example, I've already authenticated to the application, logged out, and meandered through my studio apartment for a few minutes. That's enough leeway - time to examine the application's memory. First, find the application in Task Manager, right click, and click "Create dump file."

Dump

Now, a likely massive file has been generated. That's everything from that process's memory. And thankfully, friendly neighborhood Mark Russinovich has created a tool called Strings that will help to analyze this data by retrieving only the string values. I've taken the liberty of running the following line in PowerShell:

.strings.exe .BetaBank.DMP | Out-File -FilePath .BetaBank.DMP.txt

The resultant file should be a much more manageable size, and any text editor worth its salt can search for values of choice. The password I used when logging in was NetSPI1!. And it shows up a lot.

Dump

Another choice is to just open the entire dump file in a hex editor like HxD. The password appears just as easily and visibly, but so does a lot of other data.

Dump

Modifying Data

As I was coming up with examples for this portion of the blog, I realized that I first began modifying data in memory as a delinquent child. If you were at all like me growing up and wanted to impress people with lies, you may remember Cheat Engine. Just like my Beta Bank password, game data such as item counts, experience points, and high scores may be in memory plain as day. And these values could be located through a simple search, and the data at that address could be changed to a new value. That level 25 character was a few clicks away from being level 2,147,483,647.

These days, it is much more difficult to earn the admiration of my peers through lies. But gosh darn it, I'm going to try. I've heard from previous installments in this blog series that there's a user named The_Chairman who has a lot of money. I'm going to withdraw a lot of it. The plan is to change my username in memory to The_Chairman. Since the space for the username will already be allocated, I've created an account with the same username length - The_Flairman.

Memory Edit

This account is going to be swamped with overdraft fees. In Wireshark, a SQL statement to withdraw money is being sent with the username The_Flairman. For the sake of this example, let's just use this as verification and pretend the traffic is encrypted. And that a bunch of other security vulnerabilities are patched while still allowing me to do something like this.

Memory Edit E

HxD is just as usable for editing memory as it is viewing, so we'll stick with what we know. With Beta Bank running, click Open RAM to view the live memory for the process.

Memory Edit

Searching for The_Flairman shows a number of locations where the username is referenced in memory.

Memory Edit

I went ahead and replaced every instance of The_Flairman with The_Chairman.

Memory Edit

Below is one of these instances.

Memory Edit

Saving these edits will overwrite the current live memory.

Memory Edit

Back in the application, it's clear that these changes went into effect. But were they functional?

Memory Edit

Using Wireshark, I was able to verify that the Withdraw button will now send a SQL command to withdraw a large amount of money with the username The_Chairman.

Memory Edit

This wouldn't be an issue at all if the SQL command wasn't written with a complete lack of security awareness. In this application, there's not a lot going on that would be "vulnerable" to memory values changing since authorization and storage is all on the server. Others may have simple boolean controls that can be bypassed through memory editing. Plenty of client-side control logic could be bypassed. I even found a simple example involving WinRAR, everyone's favorite application, and how to bypass its registration control.

Further Reading

This blog post barely scratched the surface of memory analysis. The techniques outlined above are a few that are used during our routine testing of thick client applications. But they're also entry points for diving further into malware analysis and reverse engineering. The following resources may be helpful starting points for additional learning:

Introduction to Hacking Thick Clients: The Conclusion

This series outlined quite a few thick client application testing methods and tools at a high level. While it never went especially deep on any one topic, I hope that it, along with BetaFast and Beta Bank, have opened the door for people to develop new security testing skills while having a bit of fun. This is a service line that really pushes creative thinking. Some of the exploitation steps I've seen in reports have made me reach out to coworkers and ask how they even thought to try them. Every once in a while, they unmute me and reply. But I digress . . .

[post_title] => Introduction to Hacking Thick Clients: Part 6 – The Memory [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => introduction-to-hacking-thick-clients-part-6-the-memory [to_ping] => [pinged] => [post_modified] => 2021-06-08 22:01:25 [post_modified_gmt] => 2021-06-08 22:01:25 [post_content_filtered] => [post_parent] => 0 [guid] => https://blog.netspi.com/?p=11668 [menu_order] => 495 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [comment_count] => 0 [current_comment] => -1 [found_posts] => 8 [max_num_pages] => 0 [max_num_comment_pages] => 0 [is_single] => [is_preview] => [is_page] => [is_archive] => [is_date] => [is_year] => [is_month] => [is_day] => [is_time] => [is_author] => [is_category] => [is_tag] => [is_tax] => [is_search] => [is_feed] => [is_comment_feed] => [is_trackback] => [is_home] => 1 [is_privacy_policy] => [is_404] => [is_embed] => [is_paged] => [is_admin] => [is_attachment] => [is_singular] => [is_robots] => [is_favicon] => [is_posts_page] => [is_post_type_archive] => [query_vars_hash:WP_Query:private] => 9c9d6f05e459d394398905523c41f6db [query_vars_changed:WP_Query:private] => [thumbnails_cached] => [allow_query_attachment_by_filename:protected] => [stopwords:WP_Query:private] => [compat_fields:WP_Query:private] => Array ( [0] => query_vars_hash [1] => query_vars_changed ) [compat_methods:WP_Query:private] => Array ( [0] => init_query_flags [1] => parse_tax_query ) )

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.

X