您的位置:首页 > 运维架构 > Shell

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");

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];

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: