Saturday, December 7, 2013

Debugging Map using Windbg

Here is the script which we can use for displaying the MAP:

.if ($sicmp("${$arg1}", "-n") == 0) {
    .if (@@(@$t0->_Isnil) == 0) {
        .if (@$t2 == 1) {
            .printf /D "%p\n", @$t0, @$t0
            .printf "key = "
            ?? @$t0->_Myval.first
            .printf "value = "
            ?? @$t0->_Myval.second
        } .else {
            r? $t9 = @$t0->_Myval
            command
        }
    }

    $$ Recurse into _Left, _Right unless they point to the root of the tree
    .if (@@(@$t0->_Left) != @@(@$t1)) {
        .push /r /q
        r? $t0 = @$t0->_Left
        $$>a< ${$arg0} -n
        .pop /r /q
    }
    .if (@@(@$t0->_Right) != @@(@$t1)) {
        .push /r /q
        r? $t0 = @$t0->_Right
        $$>a< ${$arg0} -n
        .pop /r /q
    }
} .else {
    r? $t0 = ${$arg1}

    .if (${/d:$arg2}) {
        .if ($sicmp("${$arg2}", "-c") == 0) {
            r $t2 = 0
            aS ${/v:command} "${$arg3}"
        }
    } .else {
        r $t2 = 1
        aS ${/v:command} " "
    }

    .printf "size = %d\n", @@(@$t0._Mysize)
   
    r? $t0 = @$t0._Myhead->_Parent
    r? $t1 = @$t0->_Parent

    $$>a< ${$arg0} -n

    ad command
}

traverse_map.script
A WinDbg script that traverses std::map objects.

Usage:

$$>a< traverse_map.script [-c "cmd"]

where cmd can reference @$t9, e.g. "?? @$t9.second" (this is the pair held by the map) and can also reference @$t0, which is the actual tree node pointer.

Examples:

$$>a< traverse_map.script my_map -c ".block { .echo ----; ?? @$t9.first; ?? @$t9.second; }"
$$>a< traverse_map.script m -c ".block { .if (@@(@$t9.first) == 8) { .echo ----; ?? @$t9.second } }"
$$>a< traverse_map.script my_map

Sample Program:-

class MapTest
{
public:
void PopulateMap();
private:
map m_Map1;
map m_Map2;
};

void MapTest::PopulateMap()
{
m_Map1[0] = 99;
m_Map1[1] = 100;

m_Map2[0] = wstring(L"Hello");
m_Map2[1] = wstring(L"World");

//stop the debugger here
__asm int 3
}

int _tmain(int argc, _TCHAR* argv[])
{

map  mm;
mm[1] = 1;
mm[2] = 2;

//stop the debugger
__asm int 3
MapTest mt;
mt.PopulateMap();
}


TestApp!wmain+0x8a:
0125203a 8d4d94          lea     ecx,[ebp-6Ch]
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script mm
size = 2
002e8a48
key = int 0n1
value = int 0n1
002e8aa0
key = int 0n2
value = int 0n2
0:000> g
(2f68.2260): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=7efde000 ecx=8c2cadb9 edx=65a7d238 esi=001af620 edi=001af784
eip=01251f26 esp=001af620 ebp=001af790 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
TestApp!MapTest::PopulateMap+0x186:
01251f26 cc              int     3
0:000> dv
           this = 0x001af8ec
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script this->m_Map1
size = 2
002e8bc0
key = int 0n0
value = int 0n99
002e8c18
key = int 0n1
value = int 0n100
0:000> $$>a<C:\Users\ankurm\Desktop\traverse_map1.script this->m_Map2
size = 2
002e8c70
key = int 0n0
value = class std::basic_string,std::allocator >
   +0x000 _Myfirstiter     : (null) 
   +0x004 _Alval           : std::allocator
   =01240000 npos             : 0x905a4d
   +0x008 _Bx              : std::basic_string,std::allocator >::_Bxty
   +0x018 _Mysize          : 5
   +0x01c _Myres           : 7
002e8ce0
key = int 0n1
value = class std::basic_string,std::allocator >
   +0x000 _Myfirstiter     : (null) 
   +0x004 _Alval           : std::allocator
   =01240000 npos             : 0x905a4d
   +0x008 _Bx              : std::basic_string,std::allocator >::_Bxty
   +0x018 _Mysize          : 5
   +0x01c _Myres           : 7


References:-
http://blogs.microsoft.co.il/sasha/2013/07/25/displaying-and-searching-stdmap-contents-in-windbg/
https://github.com/goldshtn/windbg-extensions

Monday, September 24, 2012

Description of the default C and C++ libraries that a program will link

Description of the default C and C++ libraries that a program will link with when built by using Visual C++

http://support.microsoft.com/kb/154753

Manually Verifing the stack

#define SAVE_EBP   static unsigned int dwValue1 = 0, dwValue2 = 0; __asm mov eax, [ebp] __asm mov dwValue1, eax
#define COPY_EBP  __asm mov eax, [ebp] __asm mov dwValue2, eax 
#define CHECK_EBP if(dwValue1 != dwValue2) { int i = 0; i = 1/i; }

e.g.

void function()
{
SAVE_EBP
.
.
.
.

COPY_EBP
CHECK_EBP
}

Inspecting CString, wstring, and static char buffer

    char *pString = new char[20];
    ::strcpy_s(pString, 20*sizeof(char), "Test string");
    CString *pStr = new CString("Hello World");
    std::wstring stdString = L"STD String";
    CDialogEx::OnOK(); <= Break point

0:000> dv /V /i /t

prv local  001af284 @ebp-0x3c class ATL::CStringT > > * pStr = 0x0097b830
prv local  001af290 @ebp-0x30 char * pString = 0x0097b7e0 "Test string"
prv local  001af25c @ebp-0x64 class std::basic_string,std::allocator > stdString = class std::basic_string,std::allocator >
0:000> dt -a11 0x0097b7e0 char
[0] @ 0097b7e0
---------------------------------------------
84 'T'

[1] @ 0097b7e1
---------------------------------------------
101 'e'
[2] @ 0097b7e2
---------------------------------------------
115 's'
[3] @ 0097b7e3
---------------------------------------------
116 't'
[4] @ 0097b7e4
---------------------------------------------
32 ' '
[5] @ 0097b7e5
---------------------------------------------
115 's'
[6] @ 0097b7e6
---------------------------------------------
116 't'
[7] @ 0097b7e7
---------------------------------------------
114 'r'
[8] @ 0097b7e8
---------------------------------------------
105 'i'
[9] @ 0097b7e9
---------------------------------------------
110 'n'
[10] @ 0097b7ea
---------------------------------------------
103 'g'
0:000> da 0x0097b7e0
0097b7e0  "Test string"
0:000> !stl -n (std::basic_string,std::allocator >) 001af25c
[du 0x97b920]
0097b920  "STD String"
0:000> dpu 001af25c L2
001af25c  0097b8d8 ".."
001af260  0097b920 "STD String"
0:000> !stl stdString
[du 0x97b920]
0097b920  "STD String"
0:000> !SDbgExt.stlwstring 001af25c
wstring size=10 reserved=15 buf=0097b920 "STD String"
0:000> dt 0x0097b830 CString
mfc_test_del!CString
   +0x000 m_pszData        : 0x0097b880  "Hello World"

Inspecting CObList using Windbg

void Cmfc_test_delDlg::OnBnClickedOk()
{
    CObList *pList = new CObList();
    pList->AddTail(new CAge(10));
    pList->AddTail(new CAge(20));
    pList->AddTail(new CAge(30));
    pList->AddTail(new CAge(40));
    pList->AddTail(new CAge(50));
    pList->AddTail(new CAge(60));
    // TODO: Add your control notification handler code here
    CDialogEx::OnOK();
}
0:000> *Beakpoint is at CDialogEx::OnOK() in Cmfc_test_delDlg::OnBnClickedOk()
0:000> bl
 0 e 00335010 [c:\vs\mfc_test_del\mfc_test_del\mfc_test_deldlg.cpp @ 158]    0001 (0001)  0:**** mfc_test_del!Cmfc_test_delDlg::OnBnClickedOk
0:000> *Lets look at local variable
0:000> dv /V /i /t
prv local  00a8ef58 @ebp-0x14 class Cmfc_test_delDlg * this = 0x00a8f864
prv local  00a8ef4c @ebp-0x20 class CObList * pList = 0x01e58cc8
0:000> *Display  the type for CObList
0:000> dt 0x01e58cc8 CObList
mfc_test_del!CObList
   +0x000 __VFN_table : 0x007f7f6c
   =007f7fb4 CObject::classCObject : CRuntimeClass
   =008b0c28 CObList::classCObList : CRuntimeClass
   +0x004 m_pNodeHead      : 0x01e5b5dc CObList::CNode  <= Pointer to linked list from Start
   +0x008 m_pNodeTail      : 0x01e5b618 CObList::CNode   <= Pointer to listed list from  End
   +0x00c m_nCount         : 0n6                                                <= Number of elements in the linked list
   +0x010 m_pNodeFree      : 0x01e5b624 CObList::CNode
   +0x014 m_pBlocks        : 0x01e5b5d8 CPlex
   +0x018 m_nBlockSize     : 0n10                                           <= memory reserved for 10 elements
0:000> *Find the head of the list
0:000> ?poi(0x01e58cc8+0x004 )
Evaluate expression: 31831516 = 01e5b5dc
0:000> *Display the list
0:000> dt CObList::CNode -l 0x01e5b5dc pNext
mfc_test_del!CObList::CNode
pNext at 0x1e5b5dc
---------------------------------------------
   +0x000 pNext            : 0x01e5b5e8 CObList::CNode
   +0x004 pPrev            : (null)
   +0x008 data             : 0x01e58d20 CObject
pNext at 0x1e5b5e8
---------------------------------------------
   +0x000 pNext            : 0x01e5b5f4 CObList::CNode
   +0x004 pPrev            : 0x01e5b5dc CObList::CNode
   +0x008 data             : 0x01e5b690 CObject
pNext at 0x1e5b5f4
---------------------------------------------
   +0x000 pNext            : 0x01e5b600 CObList::CNode
   +0x004 pPrev            : 0x01e5b5e8 CObList::CNode
   +0x008 data             : 0x01e5b6d8 CObject
pNext at 0x1e5b600
---------------------------------------------
   +0x000 pNext            : 0x01e5b60c CObList::CNode
   +0x004 pPrev            : 0x01e5b5f4 CObList::CNode
   +0x008 data             : 0x01e5b720 CObject
pNext at 0x1e5b60c
---------------------------------------------
   +0x000 pNext            : 0x01e5b618 CObList::CNode
   +0x004 pPrev            : 0x01e5b600 CObList::CNode
   +0x008 data             : 0x01e5b768 CObject
pNext at 0x1e5b618
---------------------------------------------
   +0x000 pNext            : (null)
   +0x004 pPrev            : 0x01e5b60c CObList::CNode
   +0x008 data             : 0x01e5b7b0 CObject
0:000> *Display the list from back
0:000> dt CObList::CNode -l 0x1e5b618 pPrev
mfc_test_del!CObList::CNode
pPrev at 0x1e5b618
---------------------------------------------
   +0x000 pNext            : (null)
   +0x004 pPrev            : 0x01e5b60c CObList::CNode
   +0x008 data             : 0x01e5b7b0 CObject
pPrev at 0x1e5b60c
---------------------------------------------
   +0x000 pNext            : 0x01e5b618 CObList::CNode
   +0x004 pPrev            : 0x01e5b600 CObList::CNode
   +0x008 data             : 0x01e5b768 CObject
pPrev at 0x1e5b600
---------------------------------------------
   +0x000 pNext            : 0x01e5b60c CObList::CNode
   +0x004 pPrev            : 0x01e5b5f4 CObList::CNode
   +0x008 data             : 0x01e5b720 CObject
pPrev at 0x1e5b5f4
---------------------------------------------
   +0x000 pNext            : 0x01e5b600 CObList::CNode
   +0x004 pPrev            : 0x01e5b5e8 CObList::CNode
   +0x008 data             : 0x01e5b6d8 CObject
pPrev at 0x1e5b5e8
---------------------------------------------
   +0x000 pNext            : 0x01e5b5f4 CObList::CNode
   +0x004 pPrev            : 0x01e5b5dc CObList::CNode
   +0x008 data             : 0x01e5b690 CObject
pPrev at 0x1e5b5dc
---------------------------------------------
   +0x000 pNext            : 0x01e5b5e8 CObList::CNode
   +0x004 pPrev            : (null)
   +0x008 data             : 0x01e58d20 CObject
0:000> *Check the data field
0:000> dt 0x01e58d20 CAge
mfc_test_del!CAge
   +0x000 __VFN_table : 0x007f0c58
   =007f7fb4 CObject::classCObject : CRuntimeClass
   +0x004 m_years          : 0n10
0:000> *Same thing can be done using !list too.
0:000> !list -t CObList::CNode.pNext -x "dt" -a "CObList::CNode" -e 01e5b5dc

dt 0x1e5b5dc CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b5e8 CObList::CNode
   +0x004 pPrev            : (null)
   +0x008 data             : 0x01e58d20 CObject
dt 0x1e5b5e8 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b5f4 CObList::CNode
   +0x004 pPrev            : 0x01e5b5dc CObList::CNode
   +0x008 data             : 0x01e5b690 CObject
dt 0x1e5b5f4 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b600 CObList::CNode
   +0x004 pPrev            : 0x01e5b5e8 CObList::CNode
   +0x008 data             : 0x01e5b6d8 CObject
dt 0x1e5b600 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b60c CObList::CNode
   +0x004 pPrev            : 0x01e5b5f4 CObList::CNode
   +0x008 data             : 0x01e5b720 CObject
dt 0x1e5b60c CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : 0x01e5b618 CObList::CNode
   +0x004 pPrev            : 0x01e5b600 CObList::CNode
   +0x008 data             : 0x01e5b768 CObject
dt 0x1e5b618 CObList::CNode
mfc_test_del!CObList::CNode
   +0x000 pNext            : (null)
   +0x004 pPrev            : 0x01e5b60c CObList::CNode
   +0x008 data             : 0x01e5b7b0 CObject
0:000> !list -t CObList::CNode.pNext -x "dt" -a "CObList::CNode data" -e 01e5b5dc
dt 0x1e5b5dc CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e58d20 CObject
dt 0x1e5b5e8 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b690 CObject
dt 0x1e5b5f4 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b6d8 CObject
dt 0x1e5b600 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b720 CObject
dt 0x1e5b60c CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b768 CObject
dt 0x1e5b618 CObList::CNode data
mfc_test_del!CObList::CNode
   +0x008 data : 0x01e5b7b0 CObject
 

Tuesday, September 11, 2012

Windows: Transition from User to Kernel


1. Find the notepad process object
kd> !process 0 0 notepad.exe
PROCESS 859c29b8  SessionId: 1  Cid: 0914    Peb: 7ffd4000  ParentCid: 0600
    DirBase: 3ec4c420  ObjectTable: 921e3470  HandleCount:  57.
    Image: notepad.exe

2.Switch to notepad process context
kd> .process /i 859c29b8 
You need to continue execution (press 'g' ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
826b9394 cc              int     3

3. Disassemble the NtCreateFile
kd> uf ntdll!ntCreateFile
ntdll!NtCreateFile:
77234a10 b842000000      mov     eax,42h
77234a15 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
77234a1a ff12            call    dword ptr [edx]
77234a1c c22c00          ret     2Ch

4. Find the content at 7ffe0300
kd> dd 7ffe0300 L1
7ffe0300  772364f0

5. Disassemble the code at 7ffe0300
kd> uf 772364f0
ntdll!KiFastSystemCall:
772364f0 8bd4            mov     edx,esp
772364f2 0f34            sysenter
772364f4 c3              ret

6. Find the address of KiServiceTable
kd> x nt!KiServiceTable
826bd6f0 nt!KiServiceTable =

7. Now display the function in System Service Table
kd> dps 0x826bd6f0+0x4*0x42 L1
826bd7f8  82898e82 nt!NtCreateFile