Arsen Zahray
Arsen Zahray

Reputation: 25287

How to get EasyHook to work?

I'm trying to learn how easyhook works for an upcoming project. For this, I decided to try and hijack GetMonitorInfoW and GetDeviceCaps in firefox.exe process to get window.screen.width and height to return crazy values.

Here is what I did:

injectorHelperLib.dll:

public class GetDisplayParamsInterface : MarshalByRefObject
{
    // Methods
    public void IsInstalled(int InClientPID)
    {
        Console.WriteLine("Display params injector has been installed in target {0}.\r\n", InClientPID);
    }

    public void Ping()
    {
    }        
}

injectorLib.dll:

/// <summary>
/// based on interception of calls in nsScreenWin.cpp
/// </summary>
public class InjectorClass : IEntryPoint
{
    #region relevant functions
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left, Top, Right, Bottom;

        public RECT(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }

        public RECT(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }

        public int X
        {
            get { return Left; }
            set { Right -= (Left - value); Left = value; }
        }

        public int Y
        {
            get { return Top; }
            set { Bottom -= (Top - value); Top = value; }
        }

        public int Height
        {
            get { return Bottom - Top; }
            set { Bottom = value + Top; }
        }

        public int Width
        {
            get { return Right - Left; }
            set { Right = value + Left; }
        }

        public System.Drawing.Point Location
        {
            get { return new System.Drawing.Point(Left, Top); }
            set { X = value.X; Y = value.Y; }
        }

        public System.Drawing.Size Size
        {
            get { return new System.Drawing.Size(Width, Height); }
            set { Width = value.Width; Height = value.Height; }
        }

        public static implicit operator System.Drawing.Rectangle(RECT r)
        {
            return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
        }

        public static implicit operator RECT(System.Drawing.Rectangle r)
        {
            return new RECT(r);
        }

        public static bool operator ==(RECT r1, RECT r2)
        {
            return r1.Equals(r2);
        }

        public static bool operator !=(RECT r1, RECT r2)
        {
            return !r1.Equals(r2);
        }

        public bool Equals(RECT r)
        {
            return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
        }

        public override bool Equals(object obj)
        {
            if (obj is RECT)
                return Equals((RECT)obj);
            else if (obj is System.Drawing.Rectangle)
                return Equals(new RECT((System.Drawing.Rectangle)obj));
            return false;
        }

        public override int GetHashCode()
        {
            return ((System.Drawing.Rectangle)this).GetHashCode();
        }

        public override string ToString()
        {
            return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private class MONITORINFO
    {
        public int cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public uint dwFlags;
    }

    [DllImport("user32.dll")]
    static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

    [UnmanagedFunctionPointer(CallingConvention.StdCall,
        CharSet = CharSet.Unicode,
        SetLastError = true)]
    private delegate bool DGetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

    bool GetMonitorInfo_Hook(IntPtr hMonitor, ref MONITORINFO lpmi)
    {
        var r=GetMonitorInfo(hMonitor, ref lpmi);

        //doctor the data
        lpmi.rcMonitor.Right = lpmi.rcMonitor.Left + displaySize.Width;
        lpmi.rcMonitor.Bottom = lpmi.rcMonitor.Top + displaySize.Height;

        lpmi.rcWork.Right = lpmi.rcWork.Left + workAreaSize.Width;
        lpmi.rcWork.Bottom = lpmi.rcWork.Top + workAreaSize.Height;

        //let's consider the call successfull
        return true;
    }



    [DllImport("gdi32.dll")]
    static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

    [UnmanagedFunctionPointer(CallingConvention.StdCall,
        CharSet = CharSet.Unicode,
        SetLastError = true)]
    delegate int DGetDeviceCaps(IntPtr hdc, int nIndex);

    int GetDeviceCaps_Hook(IntPtr hdc, int nIndex)
    {
        if (nIndex==(int)DeviceCap.BITSPIXEL)
        {
            return PixelDepth;
        }
        if (nIndex==(int)DeviceCap.HORZRES)
        {
            return displaySize.Width;
        }
        if(nIndex==(int)DeviceCap.VERTRES)
        {
            return displaySize.Height;
        }

        return GetDeviceCaps(hdc, nIndex);
    }

    enum DeviceCap
    {
        /// <summary>
        /// Device driver version
        /// </summary>
        DRIVERVERSION = 0,
        /// <summary>
        /// Device classification
        /// </summary>
        TECHNOLOGY = 2,
        /// <summary>
        /// Horizontal size in millimeters
        /// </summary>
        HORZSIZE = 4,
        /// <summary>
        /// Vertical size in millimeters
        /// </summary>
        VERTSIZE = 6,
        /// <summary>
        /// Horizontal width in pixels
        /// </summary>
        HORZRES = 8,
        /// <summary>
        /// Vertical height in pixels
        /// </summary>
        VERTRES = 10,
        /// <summary>
        /// Number of bits per pixel
        /// </summary>
        BITSPIXEL = 12,
        /// <summary>
        /// Number of planes
        /// </summary>
        PLANES = 14,
        /// <summary>
        /// Number of brushes the device has
        /// </summary>
        NUMBRUSHES = 16,
        /// <summary>
        /// Number of pens the device has
        /// </summary>
        NUMPENS = 18,
        /// <summary>
        /// Number of markers the device has
        /// </summary>
        NUMMARKERS = 20,
        /// <summary>
        /// Number of fonts the device has
        /// </summary>
        NUMFONTS = 22,
        /// <summary>
        /// Number of colors the device supports
        /// </summary>
        NUMCOLORS = 24,
        /// <summary>
        /// Size required for device descriptor
        /// </summary>
        PDEVICESIZE = 26,
        /// <summary>
        /// Curve capabilities
        /// </summary>
        CURVECAPS = 28,
        /// <summary>
        /// Line capabilities
        /// </summary>
        LINECAPS = 30,
        /// <summary>
        /// Polygonal capabilities
        /// </summary>
        POLYGONALCAPS = 32,
        /// <summary>
        /// Text capabilities
        /// </summary>
        TEXTCAPS = 34,
        /// <summary>
        /// Clipping capabilities
        /// </summary>
        CLIPCAPS = 36,
        /// <summary>
        /// Bitblt capabilities
        /// </summary>
        RASTERCAPS = 38,
        /// <summary>
        /// Length of the X leg
        /// </summary>
        ASPECTX = 40,
        /// <summary>
        /// Length of the Y leg
        /// </summary>
        ASPECTY = 42,
        /// <summary>
        /// Length of the hypotenuse
        /// </summary>
        ASPECTXY = 44,
        /// <summary>
        /// Shading and Blending caps
        /// </summary>
        SHADEBLENDCAPS = 45,

        /// <summary>
        /// Logical pixels inch in X
        /// </summary>
        LOGPIXELSX = 88,
        /// <summary>
        /// Logical pixels inch in Y
        /// </summary>
        LOGPIXELSY = 90,

        /// <summary>
        /// Number of entries in physical palette
        /// </summary>
        SIZEPALETTE = 104,
        /// <summary>
        /// Number of reserved entries in palette
        /// </summary>
        NUMRESERVED = 106,
        /// <summary>
        /// Actual color resolution
        /// </summary>
        COLORRES = 108,

        // Printing related DeviceCaps. These replace the appropriate Escapes
        /// <summary>
        /// Physical Width in device units
        /// </summary>
        PHYSICALWIDTH = 110,
        /// <summary>
        /// Physical Height in device units
        /// </summary>
        PHYSICALHEIGHT = 111,
        /// <summary>
        /// Physical Printable Area x margin
        /// </summary>
        PHYSICALOFFSETX = 112,
        /// <summary>
        /// Physical Printable Area y margin
        /// </summary>
        PHYSICALOFFSETY = 113,
        /// <summary>
        /// Scaling factor x
        /// </summary>
        SCALINGFACTORX = 114,
        /// <summary>
        /// Scaling factor y
        /// </summary>
        SCALINGFACTORY = 115,

        /// <summary>
        /// Current vertical refresh rate of the display device (for displays only) in Hz
        /// </summary>
        VREFRESH = 116,
        /// <summary>
        /// Horizontal width of entire desktop in pixels
        /// </summary>
        DESKTOPVERTRES = 117,
        /// <summary>
        /// Vertical height of entire desktop in pixels
        /// </summary>
        DESKTOPHORZRES = 118,
        /// <summary>
        /// Preferred blt alignment
        /// </summary>
        BLTALIGNMENT = 119
    }

    private static Size displaySize = new Size(666, 766);
    private static Size workAreaSize = new Size(777, 877);
    private int pixelDepth = 666;

    public static Size DisplaySize
    {
        get { return displaySize; }
        set { displaySize = value; }
    }

    public static Size WorkAreaSize
    {
        get { return workAreaSize; }
        set { workAreaSize = value; }
    }

    public int PixelDepth
    {
        get { return pixelDepth; }
        set { pixelDepth = value; }
    }

    #endregion

    GetDisplayParamsInterface Interface;
    private LocalHook getMonitorInfoHook,getDeviceCapsHook;

        // Methods
    public InjectorClass(RemoteHooking.IContext InContext, string InChannelName)
    {
        this.Interface = RemoteHooking.IpcConnectClient<GetDisplayParamsInterface>(InChannelName);
        this.Interface.Ping();
    }

    public void Run(RemoteHooking.IContext InContext, string InChannelName)
    {
        try
        {
            this.getMonitorInfoHook = LocalHook.Create(LocalHook.GetProcAddress("user32.dll", "GetMonitorInfoW"), new DGetMonitorInfo(GetMonitorInfo_Hook), this);
            this.getDeviceCapsHook = LocalHook.Create(LocalHook.GetProcAddress("gdi32.dll", "GetDeviceCaps"), new DGetDeviceCaps(GetDeviceCaps_Hook), this);
            this.getMonitorInfoHook.ThreadACL.SetExclusiveACL(new int[1]);
        }
        catch (Exception exception)
        {
            this.Interface.ReportException(exception);
            return;
        }
        this.Interface.IsInstalled(RemoteHooking.GetCurrentProcessId());
        RemoteHooking.WakeUpProcess();
        try
        {
            while (true)
            {
                Thread.Sleep(500);

                this.Interface.Ping();
            }
        }
        catch
        {
        }
    }
}

text.exe:

    static void Main(string[] args)
    {
        int pid = 15332;
        try
        {                
            RemoteHooking.IpcCreateServer<GetDisplayParamsInterface>(ref ChannelName, WellKnownObjectMode.SingleCall, new WellKnownSidType[0]);
            RemoteHooking.Inject(pid, "injectorLib.dll", "injectorLib.dll", new object[] { ChannelName });
            Console.ReadLine();
        }
        catch (Exception exception)
        {
            Console.WriteLine("There was an error while connecting to target:\r\n{0}", exception.ToString());
        }
}

The app seems to start and reports attaching to the process, but there is no effect on window.screen.width or any other variables I wanted to influence.

What did I do wrong?

Upvotes: 2

Views: 1487

Answers (1)

Justin Stenning
Justin Stenning

Reputation: 1837

You only applied the thread ACL to one of your hooks. I'm not sure if this is the cause of the problem you are experiencing, but with that code your getDeviceCapsHook will not execute.

this.getDeviceCapsHook.ThreadACL.SetExclusiveACL(new int[1]);

Upvotes: 1

Related Questions