Search This Blog

Wednesday, October 30, 2013

Some simple change to prevent future problem

This sounds so basic but I think we always want to have a second look on our code to see if we can improve the code. For instance, I had a piece of code that takes index as input and return the value from the array. The following is hypothetical example.

 int map_func(ULONG index)  
 {  
   assert(index < max);  
   return array[index];  
 }  

When I call this function, I make sure that index is within the range. But my code interfaces with other code and as the time goes on, the code becomes pretty complicated that I had a case where input 'index' was out of range and hence, the program crashed.
So I fixed that and after a few months later, the similar issue occurred. Only then, I realized that I should have changed 'assert' to the check that would survive even in free build.
Here is the new change.
 int map_func(ULONG index)  
 {  
   if (index >= max) {  
     assert(FALSE);  
     log("error occurred: %d\n", index);  
     return -1;  
   }  
   return array[index];  
 }  

Now, I can avoid program crash in free build and also have the assert in checked build. I know this is such a simple case but I only came up with this resolution when I stopped and thought about the fix one more time.

I think I will need this stop and think moment for all my works.

Saturday, November 10, 2012

Toaster device - installing wdm driver

I have been trying to understand how toaster wdm device works and apparently I spent so much time trying to install these drivers on my VM. First of all, its readme file is helpful but I found it lacking in some of its explanations. At first, I used devcon.exe to install bus driver but I bumped into a couple of issues so I could not install bus driver properly.
I searched online and found this msdn page where on the bottom it explains how to install toaster bus driver.

So that was helpful and on to the next issue: function driver. I could start up toaster by using enum.exe but it could not find some files that function driver was not installed. The message was not really helpful in that it does not say which files missing and part of it is that I do not fully understand what's needed for this install to happen. I could have spent time understanding installing package requirement but my goal was to understand Power management using this toaster before anything else.
Then, again from online I learned that I can look at setupapi.dev.log for more clue. By the way, this file is located in C:\Windows\inf directory.
Here is the error message I found from log file:
!!!  flq:                               Error installing file (0x00000002)
!!!  flq:                               Error 2: The system cannot find the file specified.
!    flq:                                    SourceFile   - 'c:\work\toaster\device\amd64\tostrco2.dll'
!    flq:                                    TargetFile   - 'C:\Users\ILHOYE~1.RED\AppData\Local\Temp\{6d5b7b46-959d-0823-c45e-094dc5a9816c}\amd64\tostrco2.dll'


By now, it is clear that I am missing tostrco2.dll. I don't know what file is for but I know that I need it. So I grabbed this from WDK and after that I could install toaster function driver. Now, I can happily debug toaster to understand the code flow.

How about traces? Is there any traces available with toaster driver? Yes, many of kernel drivers use either ETW or WPP tracing and hence by providing appropriate information you can turn on/off debug messages. These messages can be captured and saved to the file or you can actually see them if you have the debugger attached to your target machine/VM. In fact, toaster driver readme file describes the steps to do it but let me repeat that here. First of all, start the trace session by executing the following command where toaster.ctl contains "C56386BD-7C67-4264-B8D9-C4A53B93CBEB toaster"

c:\temp>tracelog -start toaster -rt -kd -ft 1 -guid toaster.ctl -flags 0xff

After that, in the kernel debugger you need to set the wmi path to refer to the TMF file location. What's TMF file? It is the file that contains information to translate the debug message to human readable strings. You can generate tmf file from pdb file by running 'tracepdb -f toaster.pdb' Here is how to set the path and enable debugging message.

kd>!wmitrace.searchpath + path_of_TMF_files
kd> !wmitrace.strdump
(WmiTracing)StrDump Generic
  LoggerContext Array @ 0x80BF1760 [64 Elements]
    Logger Id  2 @ 0x820C5000 Named 'MSDTC_TRACE_SESSION'
    Logger Id  3 @ 0x81AAF000 Named 'toaster'

kd> !wmitrace.enable 3
With that, you should be able to see the trace messages. Of course, you can always set the breakpoint where you are interested in to look into more details but knowing how to leverage existing traces should be helpful.

For toaster bus driver, if you want to see the debug messages, you will need to use chk build and use dbgview to enable kernel verbose debugging. However, once you turn on kernel verbose debugging, it will generate all sorts of debugging messages that you may not care about. Toaster bus driver uses DbgPrint for debug messages and that is essentially same as the following.

DbgPrintEx ( DPFLTR_DEFAULT_ID, DPFLTR_INFO_LEVEL, Format, arguments )

Therefore, we need to enable mask and level according to our mask and level. We can do this either updating registry or updating values via kernel debugger. For more information, please refer to MSDN page 'Reading and Filtering Debugging Messages' that describes how to enable certain component.


Sunday, October 14, 2012

Knowing what to practice

This week I read a book called "Talent is overrated". In the book author talks about how important it is to be deliberate in our practice to enhance our skills but what's even more important is to "KNOW" what to practice. Author said that many people do not have a clear picture of KNOWING what to practice. But those who accomplished knew exactly what they need to practice as they knew where they are lacking. I remember that my high school teacher said that the more you study, the more things that you see the needs to study. But if you do not study, you do not even know what to study. I think that it's a nice book to read and it does challenge the reader to be aware of one's status in terms of their achievement in their fields.


Just looking into where I am at right now, I feel that I do not really have a clear goal and I do not even know what to practice. Of course, there are many things out there I can/should study but my problem is that I do not see the needs so even though I may start out, I became lame and lose the passion to continually practice. I've got several books in front of me. C#, C++, Java Script and some OS/kernel books. I've looked at them to a degree but I've never mastered any of them. When I look at one subject, I feel like I should try another subject. That's pretty bad.

I hope and pray that I will be more consistent in my practice/study and be deliberate as the book suggests. I will keep posting my progress in my blog here so that I can keep track of my status. At this point, let me pick up one language and OS/kernel for the next one month. Perhaps I can write some simple apps like some command line tools, weather app, or stopwatch app. Hopefully, I will have a positive result in the next month.


Friday, October 12, 2012

String permutation with backtracking

This is probably one of classic interview questions. There are many solutions for this problem out there but today, a friend of mine mentioned this problem and I know that I solved this long time ago but my memory was fading so I decided to try this out.

As I thought about the problem, I decided to tackle this with backtracking. Basically the idea is that I take one character out from the initial word and mark that character to note that the character has been taken out for permutation. All along, I am passing just one character array and each time I reach the end, I simply print out the resulted string.

So let me show my code.
void perm_internal(string word, char *output, int n, int k)
{
    if (n == k) {
        cout << "[" << output << "]" << endl;
        return;
    }

    for (int i = 0; i < n; i++) {
        if (word[i] == 0) {
            continue;
        }
        char tmp = word[i];
        output[k] = tmp;
        word[i] = 0;
        perm_internal(word, output, n, k+1);
        word[i] = tmp;
    }
}

void perm(string word)
{
    int n = word.length();
    char *output;

    if (n == 0)
        return;
    output = (char *)malloc(n+1);
    memset(output, 0x0, n+1); 
    cout << "input word: " << word << "(" << n << ")" << endl;
    perm_internal(word, output, n, 0);
}


I want to try out different approaches to solve this problem but it's getting late so I will do that next time.

Wednesday, October 10, 2012

windbg init script

There are a couple of commands that I always run every time I start up windbg and it just dawns on me that perhaps it's time to put these commands to the script and have windbg execute it automatically.

So in this post, let me show you how to do that.
First, create a file that will contain all the commands that you would like to run.
For this example, let me create a file called 'dbg-prep.cmd'

C:\Users\ilhoye\Desktop\WinDbg> type dbg-prep.cmd
.symfix
.reload
.load mex
.load kdexts
aS !pr !process

Once we have this, we can just launch windbg with '-c' option. '-c' is a command to execute when windbg starts up but for our case, we want to execute several command and that is why I created a script in the first place.
To do that, we still use '-c' option but now this time we want to provide file path as follows.

windbg.exe -c "$$>< C:\Users\ilhoye\Desktop\WinDbg\dbg-prep.cmd

Please note that '-c' option needs to be quoted like the above.
Of course, it is cumbersome to type all these so it would be best to create a shortcut for this and in fact, as for me here is my shortcut command which also specifies the connection for kernel debugging.

"C:\Program Files\Debugging Tools for Windows (x64)\windbg.exe" -k 1394:channel=2 -c "$$>< C:\Users\ilhoye\Desktop\WinDbg\dbg-prep.cmd"

You can also add arguments to the script and for more information, please refer to msdn.

Monday, October 8, 2012

WINDBG: Setting breakpoints for user-mode process from kernel mode debugger

When working with kernel debugger, sometimes we may want to set a breakpoint in the user-mode. Can we do it? Yes, we can. :)

So in this post let me show you how to do that using notepad as an example.
First, let us connect to kernel debugger and in my case I use 1394 debugger connection. Once we are connected, look for a process that we want to set a breakpoint for.

0: kd> !process 0 0 notepad.exe
PROCESS fffffa8012256980
    SessionId: 1  Cid: 0990    Peb: 7f72f0bf000  ParentCid: 07ac
    DirBase: 1babb8000  ObjectTable: fffff8a007c7a040  HandleCount:  68.
    Image: notepad.exe


Once we have located the process that we are interested in. Follow these steps.

0: kd> .process /i fffffa8012256980
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
0: kd> g
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff802`46e8f930 cc

.process command will set a process context to notepad and '/i' option means that the target process is to be debugged invasively. In other words, once we execute this command, it prompts us to type 'g'. When we type 'g', it will set the target process to be active process and in this context, we can set a user-mode breakpoint.

For instance, let us set a breakpoint at NtCreateFile of ntdll but before we do that, we need to reload the symbols. This will not only reload kernel symbols but it will also reload user-mode symbols which we need to set a breakpoint for.

3: kd> .reload
Connected to Windows 8 9200 x64 target at (Mon Oct  8 18:10:21.107 2012 (UTC - 7:00)), ptr64 TRUE
Loading Kernel Symbols
...............................................................
................................................................
...................
Loading User Symbols
.........................
Loading unloaded module list
......
3: kd> bp /p fffffa8012256980 ntdll!ntcreatefile


Now, let us resume and this time the debugger should be able to break into the user-mode process.

3: kd> g
Breakpoint 3 hit
ntdll!ZwCreateFile:
0033:000007fb`891a30f0 4c8bd1          mov     r10,rcx
1: kd> kcn
 # Call Site
00 ntdll!ZwCreateFile
01 ntdll!LdrpNtCreateFileUnredirected
02 ntdll!LdrpMapResourceFile
03 ntdll!LdrLoadAlternateResourceModuleEx
04 ntdll!LdrpLoadResourceFromAlternativeModule
05 ntdll!LdrpSearchResourceSection_U
06 ntdll!LdrFindResource_U
07 KERNELBASE!FindResourceExW
08 COMDLG32!FindResourceExFallback
09 COMDLG32!FindResourceExMirrorFallback
0a COMDLG32!CFileOpenSave::_GetDialogTemplate
0b COMDLG32!CFileOpenSave::Show
0c notepad!ShowOpenSaveDialog


You can see from the above that the breakpoint was hit and the callstack is actually from the user-mode.
This technique can be used in many different places and one of the place could be when we want to break into certain function of the service process when it was being loaded. I guess that there are probably other places but this will definitely save you from some work of coordinating two different debuggers.

Thursday, October 4, 2012

Second Level Address Translation - EPT/NPT

This post is more or less to summarize what I have found out so that I can refer to it once I forget. (I know that I will forget this)

A few posts earlier I described how page table walk occurs and here let me briefly describe how that occurs with virtualization software such as Hyper-V. In this post. I will just describe the overall process without any debugger examples.

First of all, overall page walk with virtualization is similar to regular page table walk. Let me put out the regular page table walk diagram from the wiki page.



However, with virtualization things are a bit different. Keep in mind that whatever guest physical address that the OS thinks cannot be real physical address as hypervisor is the one that manipulates the real hardware. So what has to happen is another set of translations from the guest physical addresses to system physical addresses. Both Intel and AMD provides a solution to this address translation and they call these in two different names i.e. EPT and NPT but they are essentially the same thing.

So with guest physical addresses in our hand, we can traverse the similar data structures to obtain the system physical addresses. On Intel, these data structures are traversed via PML4 table - Page Directory Pointer table(PDPT) - Page Directory(PD) - Page Table(PT).

There are a couple of twists here to watch out though.

  • If bit 7 of the EPT PDPT entry is '1', the EPT PDPTE maps 1-Gbyte page. Otherwise, it maps to 2-Mbyte page.
  • For each entry of the table, we need to know the processor's physical-address width to obtain the physical address of the next table. 

We can get processor's address width by executing __cpuid with 0x80000008 in EAX and the the physical address width is returned in bits 7:0 of EAX. Well, that does not sound easy. Here is what I did. Just go to MSDN __cpuid page and copy the code and create a C++ source file and use that to obtain the value. On my machine, I got 36 so I know that my machine supports upto 36bit width.

So once we have the guest physical address and EPTP, it is just a matter of translating each address using the entry that we get to and the interpretation for each entry is subject to the tables given in chapter 28. VMX Support for Address Translation of Intel Manual.

In order to verify this page table walk, we need EPTP address and guest physical address but I have not found a way to obtain VMCS from the debugger easily. I will follow up on this if I find a way to obtain this pointer. But for now, everything is still in theory.