C# 实现shellcode 进程启动注入eip注入
2018-01-07 17:13
591 查看
首先说下代码原理
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");
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)) { re 4000 turn 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]; } }
相关文章推荐
- 利用注入进程shellcode实现程序自删除
- C#实现进程管理的启动和停止实例
- C#实现启动,关闭与查找进程的方法
- c#.net实现Smartphone,PocketPC进程启动
- c#.net实现Smartphone,PocketPC进程启动
- C#判断当前启动程序进程是否存在
- c#读取进程列表判断程序是否已经启动(转)
- 进程注入的研究与实现(转)
- -----------如何实现开机启动、清缓存、杀进程、悬浮窗口单双击区分,附源码
- C# 启动线程后,关闭form窗体,进程未关闭问题
- c# 启动关闭进程
- C#实现程序开机启动的方法
- c#实现简单的注入容器,认识注入容器的基本原理
- C#设置自定义文件图标实现双击启动(修改注册表)
- C#实现杀掉MSSQL中数据库当前连接的所有进程(进行数据还原的时候需要用到)
- 守护进程(简单实现)--程序关闭后自动启动
- 编程实现木马的ActiveX启动和注入IE的启动方式
- C#实现IIS的启动、停止、重启
- 用VBS实现脚本结束进程与防止进程启动
- c#下实现程序开机自动启动