Process Viewer 1.0.7.0

(UPDATED on 18/09/2008)
    Added: Child Windows on Window Tooltip, Opacity setting for Tooltip Window
(UPDATED on 15/09/2008)
    Added: Window Tooltip, shows window information during 'Find Window' 
(UPDATED on 09/09/2008)
    Added: Modifications and ModifiedMsg added to the Breakpoints.
    Modification: Indicates that which sections of the message will be modified if the Action is AutoChangeParameters.
    ModifiedMsg: If a breakpoint's action is AutoChangeParameters and Modification has the Message bit,
                          then PV will change the incoming message to the given message.
                          For ex: You can change the WM_LBUTTONDOWN to WM_RBUTTONDOWN automatically for the target window.
    Multilanguage: (English, Turkish)

Process Viewer 1.0.7.0 (PV) is ready to download. Download Source Codes | Watch Sample Movie (v1.0.5.0)
Below I try to explain what is PV and how it is working. Also I put some screenshots of the PV.
Breakpoints management window

I finished PV 2 days ago, but I was really very sleepy (it was about 4 AM and I had to go to work in the morning) so I postpone this writing to a later time. Anyway today I have some time to write something about PV. What it is? What it is for? How it works?
First I will explain what PV is then I will try to explain its codes a little bit more.

 What is PV?

I can say that PV is a program like Microsoft Spy++. Unlikely to Spy++ it allows you to edit some properties of the Controls and also allows you to manage its window messages. You can change Text, Visibility, Enabled, Window Styles and Window Ex Styles properties of a control by using PV during runtime. Therewithal you can ignore window messages, change incoming message to a different message or edit parameters of any window messages by putting breakpoints to the control’s window procedure with PV.



How can I use PV?
It is really very simple to use PV. Run PV.exe and you will see the active Processes, currently running in your desktop, in the Windows List at the left of the program. Expand any process which you are interested in. You will see the Windows (Controls) which are belong to that process in a hierarchical list. Whenever you select a Window from the list PV will highlight its area in the screen even the window is not visible at the moment. If a Window is a container window which contains inner windows in it you will see inner windows under the owner (parent) window node, so you can expand parent window and see inner windows of it.

There is also Find Window button at the top of the PV which will help you to find Controls and select them easily. Just click to the Find Window button and Drag it over the Controls while you are pushing the Left mouse button. PV will highlight the Control region which mouse currently on it. To select a window, release mouse button when the mouse cursor is on that control. Window will be selected automatically in the Windows List. If window is not in the list (this might be, because PV generates Windows List while it is opening so if the window you try to select was created after you opened PV then this window won't be in the list), PV will shows an alert to you that the window is not in the windows list at the moment, if you chose “Yes” button it will automatically refreshes the Windows List and finds your control.

When you select a window from the windows list you will see its properties in the PropertyGrid at the right. You can change Visible, Enabled, Text, WindowStyles and WindowExStyles properties of that window by using PropertyGrid. Also you can change the window’s Bounds, Size and Location by the same way. If you wish to see the Messages of that control, click to the Listen Messages button at the top toolbar. A panel which contains a TextBox will appear at the bottom of the PV which will shows you the messages of that control. If you want to put breakpoints to the current window’s message procedure click to the Edit Breakpoints button. Breakpoint Management window will be shown and you can add breakpoints to that window by using this window. Select a window message from the list (you can filter messages by writing your message name to the filter textbox) to see breakpoint properties for that message. Select your action (None, Ignore, Manuel Edit, Auto Change) by using PropertyGrid for the selected message(s). You can do same things for the other messages which you are interested in. To remove a message breakpoint just set its action to “None”. After you finished you can close the Breakpoints window by clicking “Okey” button. From now on your breakpoints will be activated and whenever a message, which you define an action for that, arrives to that window PV will do the action which you select for that message.

For example; If you chose WM_LBUTTONDOWN, which system sends to the control when mouse left button is down on that control, from the message list and select ‘Ignore’ action then WM_LBUTTONDOWN message will never send to the control. Or if you choose ManuelEditParameters action for the WM_LBUTTONDOWN then PV will shows you Edit Parameters Window to choose your action against this message when this message arrives to the control. Either you can ignore this message or you can change the wParam and lParam parameters of the message. WPARAM (4 bytes) and LPARAM (4 bytes) of a message contain message specific parameters and they have different meanings according to the Message. If we speak about the WM_LBUTTONDOWN message, the parameters will be;
wParam: Indicates whether various Virtual Keys (MK_LBUTTON, MK_RBUTTON, MK_CONTROL, MK_MBUTTON, MK_XBUTTON1, MK_XBUTTON2) are down. WParam can be one or more of these values.
lParam: Lo-Order of the lParam specifies the X-Coordinate of the cursor and Hi-Order of the lParam indicates the Y-Coordinate of the cursor. Here Lo-Order means first 2 bytes of the lParam and Hi-Order means the last 2 bytes of the lParam.
If you choose Manuel Edit Parameters action for the WM_LBUTTONDOWN then you can change the parameters of It whenever system sends this message to the target window. If you choose AutoChangeParameters action then PV will change wParam and lParam of that message automatically as you defined.

Examples with Breakpoints;

Example 1:
 1 – Open Visual Studio .NET
 2 – Select Main Menu of the VS.NET by using Find Window button of the PV.
 3 – Click “Listen Messages” button to start message hook for the main menu
 4 – Click “Edit Breakpoints” button to set breakpoints
 5 – Select WM_LBUTTONDOWN from the message list and select AutoChangeParameters action for this message.
       Set Modifications to the WParam and LParam (Indicates PV will modify only WParam and LParam of a message before it send to the hooked window)
       Set XParam to the 1 (LoWord:1, HiWord:0) and LParam to the 851998 (LoWord:30, HiWord:13). Click Okey button.
 6 – Click anywhere in the Main Menu, you will see that always File menu is shown.
This is because PV change the LParam to the HiWord:13 and LoWord:30 which means (X=30, Y=13) the cursor position is over the File menu. So main menu opens File menu always because it thinks that File menu has been clicked.

Example 2:
1 – Open Visual Studio .NET
 2 – Select Main Menu of the VS.NET by using Find Window button of the PV.
 3 – Click “Listen Messages” button to start message hook for the main menu
 4 – Click “Edit Breakpoints” button to set breakpoints
 5 – Select WM_LBUTTONDOWN from the message list and select AutoChangeParameters action for this message.
       Set Modifications to the Message and set ModifiedMsg to the WM_RBUTTONDOWN. Click Okey button to set the breakpoints.
 6 – Click anywhere in the Main Menu, you will see that even you click to the Left button of the mouse the main menu always opens its Context Menu.
This is because PV change the WM_LBUTTONDOWN message to he WM_RBUTTONDOWN.




I think this is enough for “How We Use PV?” Let us speak about the “How PV do this?”
We can split this question in to two sections. One is “How PV finds Windows?” and second is “How PV Listens and Edit Messages of a Control?”
For the first question PV uses EnumChildWindows method to enumerate child windows of a Window. It first tries to find the Desktop Window’s child windows and then it finds the inner windows. After it finds the windows, it uses GetClassName, GetWindowThreadProcessId and GetParent methods to find the ClassName, ProcessId, ThreadId and Parent Window Handle of these windows. 



For the second question “How PV Listen and Edit Messages of a Control?”; it is a little bit harder than the first section. To make this, first I wrote a C++ (Native) dll which sets hook on WH_CALLWNDPROC for the given window’s thread. Why I wrote this dll with C++? Actually listening a control’s Windows Messages, is simple. Every control has a Window Procedure method which system sends messages to that method. We can learn the address of this method by using GetWindowLong method with the GWL_WNDPROC option. To change the window procedure method of a control is also very simple;
SetWindowLong(windowHandle, GWL_WNDPROC, [our procedure Method]). By using this method we can replace the message procedure method of a control to our method. So whenever system sends a message to this control it will comes to our method and we can do anything we want in this method. To redirect this message to the original window procedure, we can use CallWindowProc function. But the problem with this is; SetWindowLong method works only for the windows which are belongs to same process. It means that we can use this method for the controls which are in the same process with us. So if we want to change windows procedure of a control we have to be in the same process. How we can handle this problem? To handle this problem I wrote a native dll which will be injected to the target process and we will run the SetWindowLong function from that dll within the target process. Injecting a dll to another application is also a pain for us. There are some solutions for this problem;
1 – We can use SetWindowsHookEx method to set a WH_CALLWNDPROC hook. By setting a hook Windows will automatically Loads our hook dll to all processes. But the problem with this method is, we don’t know the target process is .NET or not. So we have to write a native dll for this hook operation. Because if the target process is not .NET this means there is no CLR attached to that process and our .NET dll won’t be worked within this process. When we call SetWindowsHookEx function systems attach the dll, which contains the hook method, to all processes. At this point; you have to know that for each process, system creates a new instance of our dll and attach it to every process.
2 – LoadLibrary method which is in kernel32.dll loads a library to the caller application. So if we make a call to that function within the target process we can load our library to the target application. How we can call LoadLibrary function within another application? To solve this problem we can use CreateRemoteThread function which is in the kernel32.dll. CreateRemoteThread function creates a remote thread within a given process and runs the given method. To use CreateRemoteThread function we have to also know the address of the target method which we want to run in the target processes memory block. Actually this is hard to find the address of a function in a remote application. GetProcAddress function returns the address of a method, but when we call this method this will be the address of that method within our application because again GetProcAddress will return the address of the function according to the caller process memory. But here is a good trick with the LoadLibrary. LoadLibrary method is in the kernel32.dll and kernel32.dll will always load to the same address for all the windows applications according to nature of windows. So if we take the address of the LoadLibrary function within our application’s memory, this address also will be same for other applications too. So we can take the address of the LoadLibrary and call this method by using CreateRemoteThread method within target process. This will load our dll to the target procedure.

Anyway there are too many details about dll injection so I pass it simply for now. May be we can talk about this later more detailed. In PV I have been used the first way to make dll injection. I wrote a C++ (Native) dll which starts WH_CALLWNDPROC hook on the target process. WH_CALLWNDPROC installs a hook procedure which monitors the messages before the system sends them to the destination window. When the first time that system sends a message to our target window we changed the target window’s message procedure method by using SetWindowLong function. Actually we are using hook operation for two cases; one is injecting our native dll to the target process and second triggering procedure changing method (calling SetWindowLong) from that dll. Therefore SetWindowLong function will be called by the target process. As I said above we can do this in some different ways but I chose this way. Because this way needs less native codes than the others and I want to write less native codes in this example.

// In the PV
[DllImport("ProcessViewer.Hooks.dll")]
public static extern int StartHook(IntPtr hWnd, IntPtr notifyWindow);
 
[DllImport("ProcessViewer.Hooks.dll")]
public static extern void EndHook();

// In the native dll

PROCESSVIEWERHOOKS_API int WINAPI StartHook(HWND hWnd, HWND notifyParent)
{
       originalWindowProcedure = 0;
 
       // Load our libary and get its handle
       HINSTANCE phookDll = LoadLibrary((LPCTSTR)_T("ProcessViewer.Hooks.dll"));
 
       EndHook();
 
       hookWindow = hWnd;
       notifyWindow = notifyParent;
 
       // get Thread Id of the Window, which we will hook
       DWORD threadId = GetWindowThreadProcessId(hWnd, NULL);
       // get address of our Hook method in this dll
       HOOKPROC proc = (HOOKPROC)GetProcAddress(phookDll, "MessageHookProcedure");
       // set Hook (This will injects our dll in to all process
       // which are created by the given thread)
       hhk = SetWindowsHookEx(WH_CALLWNDPROC,
                                               proc,
                                               phookDll,
                                               threadId);
 
       return (DWORD)hhk;
}


// this is our WH_CALLWNDPROC hook method
LRESULT CALLBACK MessageHookProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
       if (originalWindowProcedure == 0)
       {
             // the first time this method is called
             // for the our hooked window, replace its window procedure
             // to our procedure method
             // do this just for the control which we wnat to listen its messages
             CWPSTRUCT* str = (CWPSTRUCT*)lParam;
             if (str->hwnd == hookWindow)
             {
                    // take original windows procedure of this control
                    originalWindowProcedure = GetWindowLong(hookWindow, GWL_WNDPROC);
                    // set new windows procedure
                    SetWindowLong(hookWindow, GWL_WNDPROC, (LONG)OnMessage);
             }
       }
       return CallNextHookEx(hhk, nCode, wParam, lParam);
}

// ends hook operation
PROCESSVIEWERHOOKS_API void WINAPI EndHook()
{
       // if we have been taken procedure of the window,
       // set its procedure to the its original
       if (originalWindowProcedure)
             SetWindowLong(hookWindow, GWL_WNDPROC, originalWindowProcedure);
       if (hhk != NULL)
             UnhookWindowsHookEx(hhk);
       originalWindowProcedure = 0;
       hhk = NULL;
}

From now on any message that system sends to the target window will come to our method because system thinks that window procedure method for that control is our method. Now we need to send this message to the PV to process it. At this point I used VM_COPYDATA message to transfer message to the PV. But to whom I will send this message? I wrote a Listener Control in the PV and I pass its handle to the hook dll while PV starts the hook operation. Hook dll sets this passed handle to a shared variable in it. This way every instance of the native dll has the same value for that variable. So native dll in the target process also has the same variable which holds our listener controls handle. From the native dll which handles the target window’s messages I redirect messages to the Listener Control which is in the PV. Whenever a new WM_COPYDATA messages send to the Listener Control it resolves the original message from the LParam of that message and process it according to our Breakpoints. LParam of the WM_COPYDATA message contains a COPYDATASTRUCT which has original message in it is lpData field.

private class ListenerControl : Control
{
       static int HM_MESSAGE_RESULT;
 
       public ListenerControl()
       {
             HM_MESSAGE_RESULT = NativeMethods.RegisterWindowMessage(
                                                        "ProcessViewer_MessageResult");

             Parent = MainForm;
       }
 
       protected override void WndProc(ref Message m)
       {
             if (m.Msg == (int)NativeMethods.Msgs.WM_COPYDATA)
             {
                    // message was sended by ProcessViewer.Hooks.dll from the Hooked application when
                    // a new message comes to that window
 
                    // LPARAM of this message contains a COPYDATASTRUCT which has HOOK_MSG struct in it
                    NativeMethods.COPYDATASTRUCT cdata = 
                           (NativeMethods.COPYDATASTRUCT)m.GetLParam(
                                             typeof(NativeMethods.COPYDATASTRUCT));
                    // This is the information of the message which is sended to the hooked window
                    NativeMethods.HOOK_MSG msg = (NativeMethods.HOOK_MSG)
                                             Marshal.PtrToStructure(cdata.lpData,
                                                  typeof(NativeMethods.HOOK_MSG));
 
                    // process message and set its result (0 ignore, 1 do nothing,
                    // other values replace parameters)
                    m.Result = MainForm._SubClass.ProcessMessage(m.WParam, ref msg);
                    Marshal.DestroyStructure(m.LParam, typeof(NativeMethods.COPYDATASTRUCT));
             }
             else if (m.Msg == HM_MESSAGE_RESULT 
                    && Properties.Settings.Default.HandleMessageResults)
             {
                    // this message sended by hooked window to give
                    // information about the result of a message
                    MainForm._SubClass.ProcessMessageResult(m.WParam.ToInt32(), m.LParam);
             }
             else
             {
                    base.WndProc(ref m);
             }
       }
}



While PV processing message native dll is waiting for the result and does its action according to this result which comes from the PV. If we don’t have a breakpoint for that message PV returns 1 which means “send message to the original window procedure”.  If we have a breakpoint for this message which the action is “Ignore message”, then PV returns 0 to the native dll and it ignores that message. The hard section of breakpoints is what if we have the “Edit Parameters Manually“ or “Auto Change Parameters” actions for that message. It is hard because we need to transfer changed parameters to the native dll which is running in the target application. We solve this problem by allocating a memory block in the target applications memory by using VirtualAllocEx function. Then we write our changed values to that block by using WriteProcessMemory function. These functions allow us to allocate a memory block in the target application memory block and write to this block. Now we have the address of that memory so we can pass this address to the native dll as the address of new wParam and lParam values. If native dll takes a return value differs from 1 and 0 it knows that this is a memory address which contains new wParam and lParam values. So it reads new values of the parameters from this address and redirects message to the original window procedure by using these parameters. This way we changed the parameters of the message. We can also use this WriteProcessMemory and VirtualAllocEx methods to transfer message from native dll to PV instead of using VM_COPYDATA. But I transfer data by using VM_COPYDATA because VM_COPYDATA message is for transferring data between two processes. Why I don’t use WM_COPYDATA message for transferring result of the message from PV to the native dll instead of using WriteProcessMemory function? The answer is simple. Because I send the incoming message to the PV, by using SendMessage function from window procedure method in the native dll. Thread which calls the SendMessage function will block until it takes a result. So if I try to send return value by using SendMessage to the target window this will be a deadlock.

IntPtr WriteToTargetProcessMemory(IntPtr wParam, IntPtr lParam, NativeMethods.Msgs modifiedMsg)
{
       // Open hooked window's process
       IntPtr hProcess = NativeMethods.OpenProcess( 
                                                 NativeMethods.PROCESS_VM_OPERATION 
                                                 | NativeMethods.PROCESS_VM_READ 
                                                 | NativeMethods.PROCESS_VM_WRITE,
                                                 false, _Window.ProcessId);
       // allocate memory from target proces's memory block
       // 12 bytes : 4 modified msg + 4 wParam + 4 lParam
       IntPtr memAddress = NativeMethods.VirtualAllocEx(hProcess, IntPtr.Zero, 
             12, NativeMethods.MEM_COMMIT, 
             NativeMethods.PAGE_READWRITE);
       if (memAddress == IntPtr.Zero)
             return IntPtr.Zero;
 
       int written = 0;
       // write our new parameter values to the tarhet process memory
       bool hr = NativeMethods.WriteProcessMemory(hProcess, memAddress, 
                                                  new int[] {(int)modifiedMsg, wParam.ToInt32(), 
                                                              lParam.ToInt32()}, 
                                                      12, out written);
       // close handle
       NativeMethods.CloseHandle(hProcess);
 
       if (!hr)
             return IntPtr.Zero;
       return memAddress;
}


// In the native dll
// new window procedure for the selected window
LRESULT CALLBACK OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
       // prepare message information, for sending it to our ProcessViewer program
       HOOK_MSG message;
       message.msg = msg;
       message.wParam = wParam;
       message.lParam = lParam;
 
       // this is for the WM_COPYDATA message,
       // WM_COPYDATA transfers data between 2 process by using this structure
       COPYDATASTRUCT cdata;
       cdata.dwData = 0;
       cdata.cbData = sizeof(message);
       cdata.lpData = &message;
 
 
       // send a WM_COPYDATA to our ProcessViewer which will give information about the message
       // to our program
       LRESULT result = SendMessage(notifyWindow, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cdata);
       // return values, 1: ignore message, 0 do nothing,
 
      // different from 0 and 1 : memory address of data which contains the changed wParam and lParam
       if (result == 1)
             return 0;
       if (result != 0)
       {
             // if result is not 0 or 1
             // this means we are going to change the wParam and lParam
             // which we write new values of these variables to the
             // address (result indicates this address) in the hooked program's memory
             HOOK_RESULT* hr = (HOOK_RESULT*)result;
             msg = hr->msg;
             wParam = hr->wParam;
             lParam = hr->lParam;
       }
       // send message to original window procedure
       LRESULT ret = CallWindowProc((WNDPROC)originalWindowProcedure, hWnd, msg, wParam, lParam);
       // send message to the ProcessViewer application which 
       // give information about the result of the message
       SendMessage(notifyWindow, HM_MESSAGE_RESULT, msg, ret);
       return ret;
}

This is simply how PV works. Of course we can write this procedure in different ways but as I said above I’m trying to write this example by using .NET.

Anyway it is just a two night’s code and I think it is a good start for Spying windows. Have fun!!!


FlagsEditor: Suport for <Enum> : uint

If an enum's underlying type is uint, FlagsEditor threw an invalidcast exception. I have been fixed it and upload new version of the FlagsEditor to the Server. You can download it from here...


Lutz Roeder’s .NET Reflector

Bundan 3 yıl kadar once Xenocode’dan Kenji Obata benle irtibata geçip o zamanlar henüz daha Beta aşamasında olan Fox’u satın almak istediğinde çok bocalamıştım. Acaba Fox’u satsam mı? Yoksa open source yapıp kodlarını mı dağıtsam? Yada hiç bir sey yapmayıp aynen devam edip Fox’u tekbaşıma geliştirme devam mı etsem?

O zamanlar Lutz Roederle de bu konuyu konuşmuştuk, o Fox gibi bir decompile aracının Open Source olmasını çok mantıklı bulmuyordu. Hatta bu tarz tool ların mümkünse kodlarının yayılmamasından yanaydı. Her neyse o zamanlar şartlar beni Fox’u Xenocode’a satmaya mecbur bıraktı diyebilirim. Bu satış sonrasında Fox’un iki yeni sürümünü Xenocode için yazdıktan sonra Fox’un geldiği yeri görünce sattığıma pişman bile olmuştum. Hiç beklemediğim kadar gelişmişti Fox ve keşke satmasaydım demiştim.
More...

Extending PropertyGrid: Adding custom PropertyTab and PropertyDescritors

Property Tab Example  Download Example
Most of the programmers who uses Visual Studio .NET knows PropertyGrid which is the main control in the Properties Window of the Visual Studio.

PropertyGrid’s default PropertyTab (System.Windows.Forms.PropertyGridInternal.PropertiesTab) shows properties and their current values of the given object. If we want to make some customizations we can use Browsable, DefaultValue, Description, Category, Localizable etc. attributes. For example you can hide a Property by adding Localizable(false) attribute to that property.

If you want to make more customization which you cannot do with these attributes you can create your own PropertyTab and add it to the PropertyGrid.  I made an example which filters properties according to my custom attribute(OzcanPropertyAttribute). Withal it shows hidden properties as a read-only property in the PropertyGrid. You can download example with the source codes here.

To create you custom PropertyTab for the PropertyGrid, you have to derive you class from PropertyTab class. Then you have to override its GetProperties method.
You can add your custom PropertyTab to your PropertyGrid like;

private class CustomPropertyTab : PropertyTab
{
    public
CustomPropertyTab()
    { }

    public override PropertyDescriptorCollection GetProperties(object component,
                                            Attribute
[] attributes)
    {
        PropertyInfo[] properties = component.GetType().GetProperties(
                                            BindingFlags.Instance | BindingFlags
.Public);
        List<PropertyDescriptor> filtereds = new List<PropertyDescriptor
>();
        PropertyDescriptorCollection propertyDescriptions = TypeDescriptor
.GetProperties(
                                                                component, attributes);
        Type myAttributeType = typeof(OzcanPropertyAttribute
);

        List<string> ignoreds = new List<string
>();
        for (int
i = 0; i < properties.Length; i++)
        {
            if (properties[i].IsDefined(myAttributeType, true
))
            {
                filtereds.Add(propertyDescriptions[properties[i].Name]);
            }
            else
            {
                ignoreds.Add(properties[i].Name);
            }
        }

        // now add a custom property descriptor to show hidden properties
        PropertyDescriptorCollection coll = new PropertyDescriptorCollection
(
                                                filtereds.ToArray());
        if (FormMain
.Instance._Settings.ShowHiddenProperties)
            coll.Add(new
CustomPropertyDescriptor(ignoreds.ToArray()));
        return
coll;
    }

    public override
Bitmap Bitmap
    {
        get
        {
            return
Properties.Resources.finance_16;
        }
    }

    public
override string TabName
    {
        get { return "Ozcan Properties Tab"
; }
    }
}

If you want to make more customization you can create your own PropertyDescriptors and create your own PropertyDescriptorCollection which contains these PropertyDescriptors. Check example source codes for how to implement custom PropertyDescriptors.

I think this is enough for now (it is 1:14 AM, i still have some other jobs to finish), in the future we can make more complicated example about this subject.


How to create TFS WorkItems programmatically

If you are using Team Foundation Server with Visual Studio, it will be useful for you to integrate your projects bug system with the TFS Work Items system. You can write a simple module for your program which will handles the exceptions and collects needed information and send them to the TFS.

So how can we do something like that? First you have to write an error management module which will handles exceptions, errors, etc. and generates understandable information from them. After generating this information lastly you have to send this information to the TFS.

In addition to this it will be helpful if you create your error information title unique in some cases to check that is this bug already entered as a Work Item Bug or not? For example you can combine type of the exception and last stack frame(s) which this error occurred in.

Anyway let us write a simple code which will enter our error as Work Item Bug to the TFS by programmatically. The code is so simple; you can also find more complicated codes on the web. 

const string USERNAME = "XXXX";
const string PASSWORD = "XXXX";
const string DOMAIN = "MyDomain";
const string TFS_SERVER = "http://mytfsserver:8080";
const string PROJECT = "LANCET";

protected void Page_Load(object sender, EventArgs e)
{
 string title = Request.QueryString["Title"];
 string description = Request.QueryString["Description"];
 string email = Request.QueryString["Email"];
 string force = Request.QueryString["Force"];
 if (string.IsNullOrEmpty(force))
  force = "1";

 try
 {
  NetworkCredential account = new NetworkCredential(USER_NAME, PASSWORD, DOMAIN);
  TeamFoundationServer server = new TeamFoundationServer(TFS_SERVER, account);
  Project project = null;

  server.Authenticate();
  WorkItemStore store = new WorkItemStore(server);
  project = store.Projects[PROJECT];
  if (project == null)
   throw new Exception("Project could not found");
  string wiql = "SELECT [System.Id], [System.Title], [System.Description] " +
     "FROM WorkItems " +
     "WHERE [System.TeamProject] = '" + PROJECT + "' " +
     "AND [System.Title] = '" + title + "'";
   
  WorkItemCollection collection = store.Query(wiql);
  StringBuilder tmp = new StringBuilder();
  tmp.Append(title);
  if (!string.IsNullOrEmpty(description))
  {
   tmp.Append("\r\n");
   tmp.Append("-----------------------------------------------------------------");
   tmp.AppendLine();
   tmp.AppendLine(description);
  }
  if (!string.IsNullOrEmpty(email))
  {
   tmp.AppendLine();
   tmp.Append("-----------------------------------------------------------------");
   tmp.AppendLine();
   tmp.AppendLine(email);
  }
  if (collection.Count == 0 || force == "1")
  {
   WorkItem item = new WorkItem(project.WorkItemTypes["bug"]);
   item.Title = title;
   item.AreaPath = @"CPM\Inbox";
   item.State = "Active";
   item.Description = tmp.ToString();
   item.Save();
  }
  else
  {
   WorkItem item = collection[0];
   item.Open();
   item.State = "Active";
   item.History += "\r\n\r\n" + DateTime.Now.ToString()
     + " ----------------------------------------------------\r\n" + tmp.ToString();
   item.Save();
  }
  Response.Write("SUCCESS - Bug successfully inserted to the TFS");
 }
 catch (Exception ex)
 {
  Response.Write("ERR-" + ex.Message);
 }
}

As you see here, first we try to connect to the TFS server with the given network credentials, then we search for the project which will own this bug. After that we are trying to search that is there any Work Item which has the same title (which is unique for us). If we find an existing entry than we re-activate that task and add a history to it. If we don’t find any entry for this title then we add a new Bug case for this. Actually as I said before the code is so simple, you can change it according to your necessity.

Finally we have to talk about one more thing. What if the machine which our program runs on and generates exception does not have any access privileges to the TFS server machine? Because of some security reasons you may don’t want to open your system. In this case you can use a Website to solve this problem. Create a local web page which takes needed information from Request and runs the code above. So you can call this web page from your program and everything will be worked fine.


How to protect an assembly from decompiling

When I was newbie in .NET, it was a shocked for me to learn that .NET assemblies can be decompile. But today I know that this is a normal situation for a language which is compiling to an intermediate language. As we know that, after compiling a .NET project the output will be in MSIL (Microsoft Intermediate Language). And during the application lifecycle this codes will be compiled to Native Codes by the JIT (Just-In-Time Compiler) when they first used and cached in that computer for the future usages. Anyway this is another subject for us how JIT works, but here the problem is our assemblies are in MSIL format which has about 229 opcodes and all these opcodes has a standard working procedure. So if we know these opcodes and how they are working, we can produce the .NET codes by reverse engineering. This is simply what decompilers do. But why there are no stable decompilers for the native exes? The answer is simple, because there are no metadata for the native exes. In the .NET I can say that, metadata of that assembly is really very important to resolve the Type and Member structures of that assembly. Anyway there are a lot of decompilers for the .NET which can decompile codes as same as with the original codes. Xenocode Fox Decompiler and Reflector are the most know ones.
Below is an example which shows us what a decompiler can do.

Original Code Decompiled Code
private void btnRun_Click(object sender, EventArgs e)
{
    Stopwatch watch = new Stopwatch();
   
    int iteration = 0;
    if (!int.TryParse(txtNumIteration.Text, out iteration))
        iteration = 10000000;
    int value = 0;
    if (!int.TryParse(txtNumParam.Text, out value))
        value = 50;
    IExample ex = null;
    int caseCount;
    switch (cmbCases.SelectedIndex)
    {
        case 0:
            caseCount = 5;
            ex = new Example5();
            break;
        case 1:
            caseCount = 10;
            ex = new Example10();
            break;
        case 2:
            caseCount = 20;
            ex = new Example20();
            break;
        case 3:
            caseCount = 50;
            ex = new Example50();
            break;
        default:
            caseCount = 99;
            ex = new Example99();
            break;
    }
    int r = 0;
    watch.Start();
    for (int i = 0; i < iteration; i++)
    {
        r = ex.GetSwitchResult(value);
    }
    watch.Stop();
    long swResult = watch.ElapsedMilliseconds;
    watch.Start();
    for (int i = 0; i < iteration; i++)
    {
        r = ex.GetIfResult(value);
    }
    watch.Stop();
    AppendItem(iteration, caseCount, value, swResult, watch.ElapsedMilliseconds);
}
private void btnRun_Click (object sender, EventArgs e)
{
     int caseCount;
     Stopwatch watch = new Stopwatch();
     int iteration = 0;
     if (!int.TryParse(txtNumIteration.Text, out iteration))
     {
          iteration = 10000000;
     }
     int value = 0;
     if (!int.TryParse(txtNumParam.Text, out value))
     {
          value = 50;
     }
     IExample ex = null;
     switch (cmbCases.SelectedIndex)
     {
          case 0:
          {
               caseCount = 5;
               ex = new Example5();
               break;
          }
          case 1:
          {
               caseCount = 10;
               ex = new Example10();
               break;
          }
          case 2:
          {
               caseCount = 20;
               ex = new Example20();
               break;
          }
          case 3:
          {
               caseCount = 50;
               ex = new Example50();
               break;
          }
          default:
          {
               caseCount = 99;
               ex = new Example99();
               break;
          }
     }
     int r = 0;
     watch.Start();
     for(int i = 0; i < iteration < i++)
     {
          r = ex.GetSwitchResult(value);
     }
     watch.Stop();
     long swResult = watch.ElapsedMilliseconds;
     watch.Start();
     for (int i = 0;i < iteration; i++)
     {
          r = ex.GetIfResult(value);
     }
     watch.Stop();
     AppendItem(iteration, caseCount, value, swResult, watch.ElapsedMilliseconds);
}
Decompiled code was generated by using Xenocode Fox



As you see here, the output is nearly as same as the original code when we decompile the assembly with Xenocode Fox.

So the question is how we can protect our assemblies from decompiling. Actually the answers is simple, except we don’t make our .net assemblies native, we cannot. By one way or other decompilers can decompile our codes back to the source codes. But against the decompilers there are Obfuscators which helps us to protect our codes from decompiling. If we have to explain what an obfuscator do, simply, Obfuscators changes the names of our Types and Members (properties, methods, fields, events etc.) to unreadable or unmeaning full names in the metadata of our assembly. By this way when someone decompiles our codes they can only see the unmeaning full class and member names which is really hard to understand the code. Generally we make the type and member names as understandable. For example if we write a class which indicates a User’s information, we will probably make the class name as User. So after decompiling the person who decompiles the code, sees this User class and he/she understands that this class is for the user information. So if we change the name of this class to an understandable name (for ex: xbc3453vbgf345) then it will be really hard to understand what this class is for. Except from changing the type and member names some obfuscators also can make .net assemblies as native, or some of them can injects useless codes to our methods which cause our methods hard to understand.

There are a lot of Obfuscators like Xenocode PostBuild, CodeVeil, Salamander etc. I’m using PostBuild to obfuscate my codes and I can say that it is really enough to protect my assemblies. Not only changing the type and member names but also we can make our assemblies Native by using PostBuild, or we can allow it to injects some codes which protects our methods to be decompiled (by injecting some untargeted branches) etc. etc. Making our assemblies as native will stops cares about decompiling. Code injection will obstruct Reflector and Fox to decompile that methods. PostBuild also can make our assemblies smaller by compressing and removing unused metadata by dead code elimination. This will increase our assemblies’ performance. Anyway you can check PostBuild by downloading its trial version. More About Xenocode Postbuild | Download PostBuild Evaluation

As conclusion, I can say that using a good obfuscator is enough to protect our codes. There is no need to care about decompilers. Even I develop a decompiler, I still continue to develop my other projects by using .NET and I have no care about this.

Xenocode PostBuild - The application failed to initialize properly (0xc000007b)

In one of my public projects, I used Xenocode PostBuild to obfuscate my codes. PostBuild is a very popular and common Obfuscation Tool for the .NET assemblies. When I worked for the Xenocode, I saw that the developers of PostBuild are really very good at doing their jobs. Most of them had worked for the Microsoft before. So I can say that if you need an obfuscation tool, you can use Xenocode PostBuild obfuscation tool without thinking a second.

But after I obfuscated my binaries with Postbuild, I started to get an error as "The application failed to initialize properly (0xc0000077b)". Actually this error does not occur in all computers, it just occurs in computer which has .NET Framework 3.0. After working on this problem a little bit more, I finally solved the bug. The problem was because of the "Enable Output Compression" options in the Postbuild. By enabling this option, you will allow Postbuild to compress your assemblies and inject some codes to perform on-the-fly decompression. When I unchecked the Enable Output Compression option and re-obfuscate it, the problem is gone.

So the solution for this exception is simple. Just disable "Enable Output Compression" option and re-obfuscate your assemblies.
Also let me tell where this option is in the Postbuild. Go to the Optimize tab and it is there at the bottom of the page

!!! NOTE: Kenji, who is from Xenocode, wrotes a comment and said that this bug was fixed in the latest version of the Xenocode PostBuild. So if you are using a version newer than 5.2.6839, there won't be a problem. But if you got this error, then try to download the latest patch from the Xenocode, so you can obfuscate your assemblies with the compression option.


Search

Calendar

<<  October 2008  >>
MonTueWedThuFriSatSun
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
View posts in large calendar

Disclaimer

© 2007 - 2008
Ozcan DEGIRMENCI
All rights reserved. The content can be used elsewhere given that the source is properly acknowledged.