C# 实现shellcode 进程启动注入eip注入

4 篇文章 0 订阅
4 篇文章 1 订阅

首先说下代码原理  

1.使用CreateProcess 创建一个带 CREATE_SUSPENDED标记的进程

自然进程创建加载完DLL后会被挂起。 CREATE_SUSPENDED 标记本是为调试器准备的。

2.然后用GetThreadContext获取该进程的线程上下文,保存下来(重要)。。。。

3.用VirtualAllocEx 在进程空间申请一段 dll路径长度 + 32字节的内存(这里直接申请了1k) 用来存放shellcode 

和dll路径。 

4.把 DLL路径用 WriteProcessMemory 写入到申请的内存空间地址 

5.然后组合计算shellcode代码(这里将不解释计算,具体看代码注释)

6.把shellcode用WriteProcessMemory 写入到申请的内存空间地址

7.修改上下文状态的 Eip为刚用VirtualAllocEx 申请的内存地址

8.用 SetThreadContext 设置线程上下文状态

9.用 ResumeThread 恢复线程。


下面给出代码 两个类  一个 注入, 一个API

使用方式

 Win32.Injection.EipInject EI = new Win32.Injection.EipInject();

EI.CreateProcess(@"D:\Test.exe",@"D:\Test.dll");

using System;
using System.Runtime.InteropServices;

namespace Win32.Injection
{
    public static class WinApi
    {
        public const int CREATE_SUSPENDED = 0x00000004;
        public const UInt32 MEM_COMMIT = 0x00001000;
        public const UInt32 CONTEXT_i386 = 0x00010000;   // this assumes that i386 and
        public const UInt32 CONTEXT_CONTROL = (CONTEXT_i386 | 0x00000001); // SS:SP, CS:IP, FLAGS, BP

        [DllImport("kernel32")]
        public static extern IntPtr LoadLibrary(string lpLibFileName);
        [DllImport("kernel32")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
        [DllImport("kernel32", EntryPoint = "VirtualAllocEx")]
        public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, UInt32 flAllocationType, PAGE_EXECUTE_ENUM flProtect);
        [DllImport("kernel32", EntryPoint = "GetThreadContext")]
        public static extern int GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
        [DllImport("kernel32")]
        public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBassAddress, byte[] lpBuffer, Int32 nSize, IntPtr lpNumberOfBytesRead);
        [DllImport("kernel32", EntryPoint = "SetThreadContext")]
        public static extern int SetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
        [DllImport("kernel32", EntryPoint = "ResumeThread")]
        public static extern int ResumeThread(IntPtr hThread);


        public enum PAGE_EXECUTE_ENUM
        {
            PAGE_EXECUTE_READ = 0x20,
            PAGE_EXECUTE_READWRITE = 0x40
        }

        public struct STARTUPINFO
        {
            public int cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public int dwX;
            public int dwY;
            public int dwXSize;
            public int dwYSize;
            public int dwXCountChars;
            public int dwYCountChars;
            public int dwFillAttribute;
            public int dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public int lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }

        [DllImport("kernel32", EntryPoint = "CreateProcess")]
        public static extern int CreateProcess(
            string lpApplicationName,
            string lpCommandLine,
            IntPtr lpProcessAttributes,
            IntPtr lpThreadAttributes,
            bool bInheritHandles,
            int dwCreationFlags,
            IntPtr lpEnvironment,
            String lpCurrentDriectory,
            ref STARTUPINFO lpStartupInfo,
            ref PROCESS_INFORMATION lpProcessInformation);

        public struct FLOATING_SAVE_AREA
        {
            public UInt32 ControlWord;
            public UInt32 StatusWord;
            public UInt32 TagWord;
            public UInt32 ErrorOffset;
            public UInt32 ErrorSelector;
            public UInt32 DataOffset;
            public UInt32 DataSelector;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
            public Byte[] RegisterArea;
            public UInt32 Spare0;
        }
        /// <summary>
        /// 寄存器上下文
        /// </summary>
        public struct CONTEXT
        {
            public UInt32 ContextFlags;
            //
            // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
            // set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT
            // included in CONTEXT_FULL.
            //
            public UInt32 Dr0;
            public UInt32 Dr1;
            public UInt32 Dr2;
            public UInt32 Dr3;
            public UInt32 Dr6;
            public UInt32 Dr7;

            //
            // This section is specified/returned if the
            // ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
            //

            public FLOATING_SAVE_AREA FloatSave;

            //
            // This section is specified/returned if the
            // ContextFlags word contians the flag CONTEXT_SEGMENTS.
            //

            public UInt32 SegGs;
            public UInt32 SegFs;
            public UInt32 SegEs;
            public UInt32 SegDs;

            //
            // This section is specified/returned if the
            // ContextFlags word contians the flag CONTEXT_INTEGER.
            //

            public UInt32 Edi;
            public UInt32 Esi;
            public UInt32 Ebx;
            public UInt32 Edx;
            public UInt32 Ecx;
            public UInt32 Eax;

            //
            // This section is specified/returned if the
            // ContextFlags word contians the flag CONTEXT_CONTROL.
            //

            public UInt32 Ebp;
            public UInt32 Eip;
            public UInt32 SegCs;              // MUST BE SANITIZED
            public UInt32 EFlags;             // MUST BE SANITIZED
            public UInt32 Esp;
            public UInt32 SegSs;

            //
            // This section is specified/returned if the ContextFlags word
            // contains the flag CONTEXT_EXTENDED_REGISTERS.
            // The format and contexts are processor specific
            //

            //BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public Byte[] ExtendedRegisters;
        }



    }
}

using System;
using System.Text;

namespace Win32.Injection
{
    public class EipInject
    {

        public EipInject()
        {
            // pushad  
            ShellCode[0] = 0x60;
            // pushfd  
            ShellCode[1] = 0x9c;
            // push  
            ShellCode[2] = 0x68;
            //call  
            ShellCode[7] = 0xE8;
            // popfd 
            ShellCode[12] = 0x9d;
            // popad
            ShellCode[13] = 0x61;
            // jmp 
            ShellCode[14] = 0xE9;
            hModule = WinApi.LoadLibrary("Kernel32.dll");
            //获取MessageBoxA地址
            LoadLibrary_addr = WinApi.GetProcAddress(hModule, "LoadLibraryA");
        }

        /// <summary>
        /// 创建指定进程并加载DLL
        /// </summary>
        /// <param name="AppPath"></param>
        /// <param name="DllPath"></param>
        /// <returns></returns>
        public bool CreateProcess(String AppPath, String DllPath)
        {

            WinApi.CONTEXT context = new WinApi.CONTEXT();
            Byte[] DllPathData = Encoding.Default.GetBytes(DllPath);
            if (!_CreateProcess(AppPath))
            {
                return false;
            }
            //获取线程上下文
            context.ContextFlags = WinApi.CONTEXT_CONTROL;
            if (WinApi.GetThreadContext(hThread, ref context) != 0)
            {
                Int32 dwSize = 1024;
                //申请内存
                IntPtr pProcessMem = AllocMemory(dwSize);
                if (pProcessMem == IntPtr.Zero)
                {
                    return false;
                }
                //DLL路径地址   pProcessMem + 0x100
                BuilderValue(ShellCode, 3, pProcessMem + 0x100);
                //LoadLibrary地址   地址等于   CALL绝对地址 - 下条指令地址
                BuilderValue(ShellCode, 8, LoadLibrary_addr - (pProcessMem.ToInt32() + 12));
                // 跳回 旧的 eip 地址   ct.Eip - (pProcessMem + 19);  (绝对地址-下条指令地址)
                BuilderValue(ShellCode, 15, (int)context.Eip - (pProcessMem.ToInt32() + 19));
                //先把 ShellCode 写进地址
                WinApi.WriteProcessMemory(hProcess, pProcessMem, ShellCode, ShellCode.Length, IntPtr.Zero);
                //把DLL路径写到内存里,从0x100(256)开始 
                WinApi.WriteProcessMemory(hProcess, (pProcessMem + 0x100), DllPathData, DllPathData.Length, IntPtr.Zero);
                //改写EIP
                context.Eip = (UInt32)pProcessMem;
                //把线程上下文写回去
                WinApi.SetThreadContext(hThread, ref context);
                //恢复挂起线程
                WinApi.ResumeThread(hThread);
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 负责创建一个被挂起的进程
        /// </summary>
        /// <param name="AppPath"></param>
        /// <returns></returns>
        private bool _CreateProcess(String AppPath)
        {
            WinApi.STARTUPINFO si = new WinApi.STARTUPINFO();
            WinApi.PROCESS_INFORMATION PI = new WinApi.PROCESS_INFORMATION();
            int HResult = WinApi.CreateProcess(
                null,
                //   程序路径       命令行
                AppPath,
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                //   挂起进程            只调试这个进程
                WinApi.CREATE_SUSPENDED,
                IntPtr.Zero,
                //工作目录
                System.IO.Path.GetDirectoryName(AppPath),
                ref si,
                ref PI);
            if (HResult == 0)
                return false;
            hProcess = PI.hProcess;
            hThread = PI.hThread;
            return true;
        }
        /// <summary>
        /// 负责申请一段内存
        /// </summary>
        /// <param name="Size"></param>
        /// <returns></returns>
        private IntPtr AllocMemory(Int32 Size)
        {
            return WinApi.VirtualAllocEx(hProcess, IntPtr.Zero, Size, WinApi.MEM_COMMIT, WinApi.PAGE_EXECUTE_ENUM.PAGE_EXECUTE_READWRITE);
        }

        /// <summary>
        /// 负责把四字节整数写进shellcode
        /// </summary>
        /// <param name="ShellCode"></param>
        /// <param name="Index"></param>
        /// <param name="Value"></param>
        private void BuilderValue(Byte[] ShellCode, Int32 Index, IntPtr Value)
        {
            Byte[] DATA = BitConverter.GetBytes(Value.ToInt32());
            Array.Copy(DATA, 0, ShellCode, Index, 4);
        }

        /// <summary>
        /// 负责把四字节整数写进shellcode
        /// </summary>
        /// <param name="ShellCode"></param>
        /// <param name="Index"></param>
        /// <param name="Value"></param>
        private void BuilderValue(Byte[] ShellCode, Int32 Index, Int32 Value)
        {
            Byte[] DATA = BitConverter.GetBytes(Value);
            Array.Copy(DATA, 0, ShellCode, Index, 4);
        }



        /// <summary>
        /// 创建进程句柄
        /// </summary>
        public IntPtr hProcess = IntPtr.Zero;
        /// <summary>
        /// 创建进程线程句柄
        /// </summary>
        public IntPtr hThread = IntPtr.Zero;
        private IntPtr hModule = IntPtr.Zero;
        private IntPtr LoadLibrary_addr = IntPtr.Zero;
        private Byte[] ShellCode = new byte[32];

    }
}







  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值