Blogs involving different aspects of the I.T. world

Category: C#

Using ICMP to deliver shellcode

While researching different methods of exfiltration, I came across a technique that utilized DNS. While writing up the proof of concept code, I noticed something interesting with the ping function I had implemented. What had caught my eye was the fact that you can supply a buffer that can hold 65,500 bytes. With a size limit that large, we can easily smuggle shellcode into our ICMP request and then inject it into a process on the listener’s end.

Starting off with the shellcode delivery, only a C# console application within Visual Studio is needed. Here, we must import our dependencies. The only one being needed is System.Net.NetworkInformation.

Importing System.Net.NetworkInformation

Next we need to create a public static void function and then call that from within Main().

Creating the function sendShellcode() and calling it from main().

Next, we create a local variable and use that to initialize an instance of the ping class, while also assigning a value to our timeout var.

Our next step will require us to move to a Kali VM instance. Within here we’re going to generate shellcode to open up a message box. we’re going to select a payload For Windows 64 bit. (payload/windows/x64/messagebox). after selecting the payload we can customize the title and the message body. After the customization, we need to generate our payload. To do this, type: generate -f csharp. We can copy the output and move it back to our Windows machine.

Crafting our shellcode
Pasting the shellcode and formatting it to fit one line.

Our last step is to assign our TTL, tell our request not to fragment, and then send the request. Our code should now look as such.
Args:
pingOptions(TTL, dontFragmentBool)
pingSender.Send(IP/Hostname, timeoutInt, shellcodeBuf, options)

Now that we can deliver the payload, we need to create a listener. Let’s move to our victim VM.

On the victim VM, we open another C# console application and import these four dependencies:
System
System.Net
System.Net.Sockets
System.Runtime.InteropServices

Next, we need to create two functions. One that will return shellcode from the ICMP request, as well as one that will inject it into a local process.

Imports + Skeleton functions

We need to start by creating a socket that will listen for raw data from IPv4 addresses using the ICMP protocol. This is done within the getShellcode function.

icmpListener

Next, we bind our local address to the socket with a port value of 0.

icmpListener.Bind

Next, we need to set the IOControl for the socket. To do this, we supply a control code (first arg) of ReceiveAll as well as two identical byte arrays containing {1, 0, 0, 0} as the value.

IOControl

Our next three lines are straight forward. First, we assign a buffer, allocating 4096 bytes. Then we create a remote endpoint that will listen for transmissions from any IP address from no specific port. Finally, we  initialize our shellcode byte array with the byte size of 4068.

My reasoning behind the shellcode size of 4068, is because when we receive the ICMP buffer, the user inputted data starts at the 28 byte. Hence, 4096 – 28 gives us 4068.

Buffer + remoteEndPoint + Shellcode allocation

To finish off this function, we start the listener, then copy the received buffer from the request into our shellcode array. After copying the buffer to our array, we can return the value.

Receive the bytes, copy the buffer into the array, then return the value

Our last step is to the pass our shellcode to our injection function. This process is the same method used within this article, and is explained in greater detail there. However, the key point here is that we are utilizing notepad as our injection point, so all we need to grab that process ID. Checking within task manager, we get the process ID of 5588, so let’s add this to our code

notepadPID

Following the instructions in my last article, our code should look like this.

ICMPListener

All that is left to do, is to run both applications. First, we start the listener, then we launch the injector. Going in that order, let’s check out our Notepad process.

Success!

Final source code can be found here: https://github.com/RomanRII/shellcode-through-ICMP

Base64 to 0 detections

After finishing up with my certification training/exams, I finally had free time to dive more in depth with an interest of mine, malware development. I wanted to get a better understanding of how to be able to get a meterpreter against a system that had an active AV/AM solution running. One source of inspiration was from IRed.team’s article about remote process shellcode injection.

I am not great enough at C++ to hit this goal just yet, so I wrote this out in C#. Source can be found here, and I’ll explain the steps needed here.

As seen in the ired write up, the main 4 functions we need to utilize are OpenProcess, VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread. So let’s import them from kernel32.dll.

Importing the needed DLL Functions

We can now focus on our main function. I commented on what each portion does to give everyone an idea of the flow, as well so I can remember what it does in the future. Running this just like this does work, but if you do so with just Microsoft Defender running, the shellcode will be detected and stop the execution.

We all know if there’s a will, there is a way. So let’s find a way to get past the defense and get our shellcode executed. One method of evasion is to obfuscate certain values and build them later, whether this is done by encoding, encryption, or web requests, the goal is the same. Hide the initial and deal with it later. I wanted to start simple and work my way up and find as many methods as I could, and to my surprise the first run was the golden ticket. While it isn’t hard to make your malware undetected if it’s home built, I found it intriguing that something as simple as Base64 encoding a value would throw off not only static scans, but as well as real time scans.

main()

To get the base64 value, all we need to do is set a breakpoint on the WritePorcessMemory function. (Do this on a VM without AV/AM running).

Setting a breakpoint at WriteProcessMemory and get the b64 value (Visual Studio 19)

Now that we have this value copy it, stop the current execution, edit a few lines. We can start off by removing our shellcode portion completely, un-commenting the b64DecodeMe line and the one below it, and lastly remove/comment out getB64FromByteArray.

The end result should look similar to this
Executiuon
Evading BitDefender
Evading Defender

© 2021 RomanRIIs Blogs

Theme by Anders NorenUp ↑