Cant hook CreateDCA

Feb 22, 2010 at 3:03 PM

Hi please can somebody help i am battling to hook CreateDC because when i use the process monitor demo and i change the code to hook gdi32.dll and the CreateDC when i run the app and i open the printer properties i get a callback but it is to OnCreateFile and it keeps bringing back the same Data the file that is bieng accessed i dont know what i am doing wrong i think it must be something small here is my code if it may help

demointerface.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace ProcessMonitor
{
    internal class MonitorEntry
    {
        public readonly String Access;
        public readonly DateTime Timestamp = DateTime.Now;
        public readonly Int32 ClientPID;

        public MonitorEntry(
            Int32 InClientPID,
            String InAccess)
        {
            ClientPID = InClientPID;
            Access = InAccess;
        }
    }

    /*
     * This is the class where our clients will connect to!
     *
     * Please note that setting any breakpoint here will cause the related
     * thread in the client process to block until you continue execution!
     * So don't wonder if your browser (for example) hangs when you set a
     * breakpoint ;-)... Let's say you can debug a part of the code the client
     * is executing (that's not technically correct)
     *
     * In Windows 2000 debugging the following seems to cause problems.
     */
    public class DemoInterface : MarshalByRefObject
    {
        public void ReportError(
            Int32 InClientPID,
            Exception e)
        {
            MessageBox.Show(e.ToString(), "A client process (" + InClientPID + ") has reported an error...", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        }
        public void Ei()
        {
            MessageBox.Show("test");

        }
        public bool Ping(Int32 InClientPID)
        {
            return true;
        }

        public void OnCreateFile(Int32 InClientPID,String[] data)
        {
            //something happened
            MessageBox.Show("something happened");
        }

                   
    }

}

main.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;
using EasyHook;
using System.Windows.Forms;


namespace ProcessMonitor
{

    public struct DEVMODE // i need because CreateDCA structure
    {

        public const int CCHDEVICENAME = 32;
        public const int CCHFORMNAME = 32;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
        public string dmDeviceName;
        public short dmSpecVersion;
        public short dmDriverVersion;
        public short dmSize;
        public short dmDriverExtra;
        public int dmFields;

        public short dmOrientation;
        public short dmPaperSize;
        public short dmPaperLength;
        public short dmPaperWidth;

        public short dmScale;
        public short dmCopies;
        public short dmDefaultSource;
        public short dmPrintQuality;
        public short dmColor;
        public short dmDuplex;
        public short dmYResolution;
        public short dmTTOption;
        public short dmCollate;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
        public string dmFormName;
        public short dmLogPixels;
        public int dmBitsPerPel;    // Declared wrong in the full framework
        public int dmPelsWidth;
        public int dmPelsHeight;
        public int dmDisplayFlags;
        public int dmDisplayFrequency;

        public int dmICMMethod;
        public int dmICMIntent;
        public int dmMediaType;
        public int dmDitherType;
        public int dmReserved1;
        public int dmReserved2;
        public int dmPanningWidth;
        public int dmPanningHeight;

        public int dmPositionX; // Using a PointL Struct does not work
        public int dmPositionY;
    }

    public class DemoInjection : EasyHook.IEntryPoint
    {
        public DemoInterface Interface = null;
        public LocalHook CreateDCAHook = null;

        Stack<String> Queue = new Stack<string>();

        public DemoInjection(
            RemoteHooking.IContext InContext,
            String InChannelName)
        {
            Interface = RemoteHooking.IpcConnectClient<DemoInterface>(InChannelName);

            Interface.Ping(RemoteHooking.GetCurrentProcessId());
        }

        public void Run(
            RemoteHooking.IContext InContext,
            String InArg1)
        {
            try
            {
                CreateDCAHook = LocalHook.Create(LocalHook.GetProcAddress("gdi32.dll", "CreateDCA"),new DCCreateDCA(CreateDCA_Hooked),this);

                /*
                 * Don't forget that all hooks will start deaktivated...
                 * The following ensures that all threads are intercepted:
                 */
                CreateDCAHook.ThreadACL.SetExclusiveACL(new Int32[1]);
            }
            catch (Exception e)
            {
                /*
                    Now we should notice our host process about this error...
                 */
                Interface.ReportError(RemoteHooking.GetCurrentProcessId(), e);

                return;
            }


            // wait for host process termination...
            try
            {
                while (Interface.Ping(RemoteHooking.GetCurrentProcessId()))
                {
                    Thread.Sleep(500);

                    // transmit newly monitored file accesses...
                    lock (Queue)
                    {
                        if (Queue.Count > 0)
                        {
                            String[] Package = null;
                            Package = Queue.ToArray();

                            Queue.Clear();

                            Interface.OnCreateFile(RemoteHooking.GetCurrentProcessId(), Package);
                         }
                    }
                }
            }
            catch
            {
                // NET Remoting will raise an exception if host is unreachable
            }
        }

        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
        delegate IntPtr DCCreateDCA([System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InDriver, [System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InDevice, [System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InOutput, IntPtr InInitData);

       [DllImport("gdi32.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        public static extern System.IntPtr CreateDCA([System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InDriver, [System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InDevice, [System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InOutput, IntPtr InInitData);


        // this is where we are intercepting all file accesses!
        // "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String,
        //              ByVal lpOutput As String, lpInitData As DEVMODE) As Long
        static IntPtr CreateDCA_Hooked([System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InDriver, [System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InDevice, [System.Runtime.InteropServices.InAttribute()]
            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            string InOutput, IntPtr InInitData)
        {

            //IntPtr ret = IntPtr.Zero;

            try
            {
                DemoInjection This = (DemoInjection)HookRuntimeInfo.Callback;

                lock (This.Queue)
                {
                    if (This.Queue.Count < 1000)
                        This.Queue.Push(InDevice);

                }

                //ret = CreateDCA(InDriver, InDevice, InOutput, InInitData);

            }
            catch
            {
                //This.Queue.Push("ops, erro");
            }

            // call original API...
            return CreateDCA(
                InDriver,
                InDevice,
                InOutput,
                InInitData);

            //return ret;
                      
        }
    }
}

and this is how i start the hook

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;
using System.Security.Principal;
using System.Security;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Threading;
using EasyHook;

namespace ProcessMonitor
{
    public partial class Form2 : Form
    {

        private List<Process> LastProcesses = new List<Process>();
        static internal List<Int32> HookedProcesses = new List<Int32>();
        private String ChannelName = null;
        private IpcServerChannel DemoServer;

        /*
         * Please note that we have obtained this information with system privileges.
         * So if you get client requests with a process ID don't try to open the process
         * as this will fail in some cases. Just search the ID in the following list and
         * extract information that is already there...
         *
         * Of course you can change the way this list is implemented and the information
         * it contains but you should keep the code semantic.
         */
        //internal static List<ProcessInfo> ProcessList = new List<ProcessInfo>();
        private static List<Int32> ActivePIDList = new List<Int32>();
        //private static System.Threading.Timer ProcessTimer = null;

        /*
         * In general you shouldn't access the GUI directly from other threads,
         * so we are using an asynchronous approach!
         */
        static internal Queue<MonitorEntry> MonitorQueue = new Queue<MonitorEntry>();
        static internal Boolean IsMonitoring = true;

        public Form2()
        {
            InitializeComponent();

            DemoServer = RemoteHooking.IpcCreateServer<DemoInterface>(ref ChannelName,WellKnownObjectMode.Singleton);

        }

        private void button1_Click(object sender, EventArgs e)
        {

            try
            {
                HookedProcesses.Add(1988); // this will ensure that Ping() returns true...

                RemoteHooking.Inject(
                    1988,
                    "ProcMonInject.dll", // 32-bit version (the same because AnyCPU)
                    "ProcMonInject.dll", // 64-bit version (the same because AnyCPU)
                    // the optional parameter list...
                    ChannelName);
            }
            catch (Exception Msg)
            {
                HookedProcesses.Remove(1988);
               
                MessageBox.Show(Msg.Message, "An error has occurred...", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }

        }
    }
}

 

please if somebody could help me in the right direction because i am going mad and i dont know what to do anymore because why does it always give the same data back the filename

Dec 30, 2010 at 4:11 AM

Hi,

I wonder if you got your problem solved? Thank you.

Jan 3, 2011 at 1:27 PM

yup i solved my problem i was hooking the wrong process ID