Yukikaze
18.08.2013, 16:57
В предыдущих статьях я показал один из способов внедрения управляемой сборки в адресное пространство неуправляемого приложения, а так же упоминал о некой библиотеки называемой WhiteMagic ([Ссылки могут видеть только зарегистрированные и активированные пользователи]), на этот раз я постараюсь описать процесс хука используя полученные ранее знания.
Для начала нам потребуется SlimDX с официального сайта ([Ссылки могут видеть только зарегистрированные и активированные пользователи]), а так же WhiteMagic ([Ссылки могут видеть только зарегистрированные и активированные пользователи]) из моего репозитория.
Теперь берем небольшой класс который поможет нам в дальнейшем
using System;
using System.Runtime.InteropServices;
using SlimDX.Direct3D9;
using WhiteMagic;
namespace D3DHook
{
public static class Helper
{
[UnmanagedFunctionPointer(CallingConvention.StdCall )]
private delegate int Direct3D9EndScene(IntPtr device); //Создали делегат с подходящей сигнатурой
private static readonly object _frameLock = new object();
public static event EventHandler<D3DEventArgs> OnFrame; //Событие кторое будет срабатывать при каждом срабатывании хука
private static Direct3D9EndScene _endSceneDelegate; //Экземпляр делегата, он будет вызывать оригинальную функцию
private static IntPtr EndScenePointer = IntPtr.Zero; //Указатель на оригинальную функцию
const int VMT_ENDSCENE = 42; //Смещение в VMTable
public static void Initialize()
{
using (var d3d = new Direct3D())
{
using (var tmpDevice = new Device(d3d, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1 }))
{
EndScenePointer = Magic.Instance.GetObjectVtableFunction(tmpDevice.C omPointer, VMT_ENDSCENE); //Получаем указатель на оригинальную функцию
}
}
_endSceneDelegate = Magic.Instance.RegisterDelegate<Direct3D9EndScene>(EndScenePointer); //Получаем делегат из указателя
Magic.Instance.Detours.CreateAndApply(_endSceneDel egate, new Direct3D9EndScene(EndSceneHook), "D9EndScene"); //Создаем и применяем хук
}
public static void Dispose()
{
Magic.Instance.Detours["D9EndScene"].Dispose();
}
private static int EndSceneHook(IntPtr device) //Обработчик хука прокидывает событие дальше, передавая указатель на устройство
{
lock (_frameLock)
{
if (OnFrame != null)
OnFrame(null, new D3DEventArgs(device));
}
return (int)Magic.Instance.Detours["D9EndScene"].CallOriginal(device); //Вызов оригинальной функции
}
}
public class D3DEventArgs : EventArgs
{
public IntPtr Device;
public D3DEventArgs(IntPtr device)
{
this.Device = device;
}
}
}
В принципе этого достаточно для реализации хука, теперь можно написать простое приложение
using System;
using System.Drawing;
using System.Windows.Forms;
using SlimDX;
using SlimDX.Direct3D9;
namespace D3DHook
{
public partial class Form1 : Form
{
private string _input = string.Empty;
public Form1()
{
InitializeComponent();
Helper.Initialize();
Helper.OnFrame += client_Frame;
}
private void client_Frame(object sender, D3DEventArgs e)
{
if (string.IsNullOrEmpty(_input)) return;
using (Device device = Device.FromPointer(e.Device))
{
using (var font = new SlimDX.Direct3D9.Font(device, 30, 0, FontWeight.Bold, 0, false, CharacterSet.Default,
Precision.TrueType, FontQuality.Antialiased, PitchAndFamily.DontCare, "Arial"))
{
font.DrawString(null, _input, new Rectangle(10, 10, 500, 30), DrawTextFormat.Top | DrawTextFormat.Left, new Color4(Color.Red));
}
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Helper.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
_input = textBox1.Text;
}
}
}
Компилируете его как x86 приложение, и инжектите как было описано в первой части, или можете воспользоваться инжектором приложенным ниже
Исходники проекта здесь ([Ссылки могут видеть только зарегистрированные и активированные пользователи]!JdNmgRqQ!U1Pzw3IquEV6JUc-U-71ExqBxLh9BNlpd4fMPByXfZw)
Инжектор здесь ([Ссылки могут видеть только зарегистрированные и активированные пользователи]!VdUHUQLQ!OpqEOB8t5_Byoz_v_0zrNwO-mloTOPBRc8_afJps2sk)
инжектор+пример здесь ([Ссылки могут видеть только зарегистрированные и активированные пользователи]!ZJkkTK7b!QXnU5Cq2pn8c6WiejUY86CyTIcJzRYwJOa5pi65 nTzQ)
Скриншот ([Ссылки могут видеть только зарегистрированные и активированные пользователи])
upd1: поправил код обработчика client_Frame, убран ненужный объект Sprite fontSprite
Для начала нам потребуется SlimDX с официального сайта ([Ссылки могут видеть только зарегистрированные и активированные пользователи]), а так же WhiteMagic ([Ссылки могут видеть только зарегистрированные и активированные пользователи]) из моего репозитория.
Теперь берем небольшой класс который поможет нам в дальнейшем
using System;
using System.Runtime.InteropServices;
using SlimDX.Direct3D9;
using WhiteMagic;
namespace D3DHook
{
public static class Helper
{
[UnmanagedFunctionPointer(CallingConvention.StdCall )]
private delegate int Direct3D9EndScene(IntPtr device); //Создали делегат с подходящей сигнатурой
private static readonly object _frameLock = new object();
public static event EventHandler<D3DEventArgs> OnFrame; //Событие кторое будет срабатывать при каждом срабатывании хука
private static Direct3D9EndScene _endSceneDelegate; //Экземпляр делегата, он будет вызывать оригинальную функцию
private static IntPtr EndScenePointer = IntPtr.Zero; //Указатель на оригинальную функцию
const int VMT_ENDSCENE = 42; //Смещение в VMTable
public static void Initialize()
{
using (var d3d = new Direct3D())
{
using (var tmpDevice = new Device(d3d, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1 }))
{
EndScenePointer = Magic.Instance.GetObjectVtableFunction(tmpDevice.C omPointer, VMT_ENDSCENE); //Получаем указатель на оригинальную функцию
}
}
_endSceneDelegate = Magic.Instance.RegisterDelegate<Direct3D9EndScene>(EndScenePointer); //Получаем делегат из указателя
Magic.Instance.Detours.CreateAndApply(_endSceneDel egate, new Direct3D9EndScene(EndSceneHook), "D9EndScene"); //Создаем и применяем хук
}
public static void Dispose()
{
Magic.Instance.Detours["D9EndScene"].Dispose();
}
private static int EndSceneHook(IntPtr device) //Обработчик хука прокидывает событие дальше, передавая указатель на устройство
{
lock (_frameLock)
{
if (OnFrame != null)
OnFrame(null, new D3DEventArgs(device));
}
return (int)Magic.Instance.Detours["D9EndScene"].CallOriginal(device); //Вызов оригинальной функции
}
}
public class D3DEventArgs : EventArgs
{
public IntPtr Device;
public D3DEventArgs(IntPtr device)
{
this.Device = device;
}
}
}
В принципе этого достаточно для реализации хука, теперь можно написать простое приложение
using System;
using System.Drawing;
using System.Windows.Forms;
using SlimDX;
using SlimDX.Direct3D9;
namespace D3DHook
{
public partial class Form1 : Form
{
private string _input = string.Empty;
public Form1()
{
InitializeComponent();
Helper.Initialize();
Helper.OnFrame += client_Frame;
}
private void client_Frame(object sender, D3DEventArgs e)
{
if (string.IsNullOrEmpty(_input)) return;
using (Device device = Device.FromPointer(e.Device))
{
using (var font = new SlimDX.Direct3D9.Font(device, 30, 0, FontWeight.Bold, 0, false, CharacterSet.Default,
Precision.TrueType, FontQuality.Antialiased, PitchAndFamily.DontCare, "Arial"))
{
font.DrawString(null, _input, new Rectangle(10, 10, 500, 30), DrawTextFormat.Top | DrawTextFormat.Left, new Color4(Color.Red));
}
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Helper.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
_input = textBox1.Text;
}
}
}
Компилируете его как x86 приложение, и инжектите как было описано в первой части, или можете воспользоваться инжектором приложенным ниже
Исходники проекта здесь ([Ссылки могут видеть только зарегистрированные и активированные пользователи]!JdNmgRqQ!U1Pzw3IquEV6JUc-U-71ExqBxLh9BNlpd4fMPByXfZw)
Инжектор здесь ([Ссылки могут видеть только зарегистрированные и активированные пользователи]!VdUHUQLQ!OpqEOB8t5_Byoz_v_0zrNwO-mloTOPBRc8_afJps2sk)
инжектор+пример здесь ([Ссылки могут видеть только зарегистрированные и активированные пользователи]!ZJkkTK7b!QXnU5Cq2pn8c6WiejUY86CyTIcJzRYwJOa5pi65 nTzQ)
Скриншот ([Ссылки могут видеть только зарегистрированные и активированные пользователи])
upd1: поправил код обработчика client_Frame, убран ненужный объект Sprite fontSprite