blabberer

  1. The xxx project - looking under the hoods of guids

    The xxx project - looking under the hoods of guids
    In the olden golden times things were simple and humanely understandable

    Todays machines don't like humans and their understandability

    All they want is garbage to produce more garbage that requires more powerful machine with a higher processing power running multiple cores in parallel and utilizing multi petaabyte memory

    In the olden times we wrote a simple void main (void ) { printf ("hello world \n"); } and all we needed was a 9 MB package that came with almost everything an hobbyist would ever want to write programs with.

    Yes bcc 5.5 command line tools with / includes / libs / resource compilers / make utility / all combined was just a measly 9 MB

    One fine day it went bust and ended up �embarcing� kylie or was it kulfi

    Let it rest in peace in the museum where it may live forever.

    So now comes in express editions of visual studio multi mega byte goliaths that didn�t compile and link but built

    as long as it was a simple hello world build built it and there was no fiddling required and we could live with a 11 MB directory for a simple hello world

    Yes we have to cough up more space than what was required for complete tool-set

    don�t believe me let me dir /s for you one simple hello world

    Code:
     :\>cd
     C:\Documents and Settings\Admin\My Documents\Visual Studio 2010\Projectsweight_of_hello_from_express_to_the_world
    :\>set blah
    blah="f:\SysinternalsSuite\du.exe"
    :\>%blah% -q .
    Files:        61
    Directories:  4
    Size:         11,051,453 bytes
    Size on disk: 11,051,453 bytes
    :\>

    A simple hello world.cpp compiled and linked to hello world.exe needs a 2 GB tool set and 61 intermediate files and obviously 500 GB hard disk get filled with litter in two months flat

    hey bcc 5.5 you didn�t need anything more than a 4 GB hard disk and 128 MB ram machine that was running windows 98 for you to make a tiny little helloworld.exe you are sorely missed.

    Enough nostalgia let�s get on because the history of evolution is that life escapes all barriers. Life breaks free. Life expands to new territories. Painfully, perhaps even dangerously. But life finds a way
    Guru Goldblum
    let�s find a way out of this madness lets break free even if it is painful to become a simple /one cpp /one make file /one compiler and /one linker project and no not using bcc but using visual studio

    It can it did and it will but we have to coax an eighty million year old mosquito embedded in amber to become a Tyrannosaurus Rex

    Lets open the mighty big hello world project and monitor it with process explorer to find clues to its operation

    First clue we get is that once f7 or build is clicked in vcexpress we see msbuild.exe is spawned from vcexpress.exe which calls tracker.exe which calls cl.exe and linker.exe

    Code:
    Command line: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /nologo /nodemode:1 /nr

    Code:
    Command line: "C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\Tracker.exe" @"C:\Documents and Settings\Admin\Local Settings\Temp\2855c911ce6c4f5a83da3ea06bb3f4e9.tmp" /c "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\CL.exe"  @"C:\Documents and Settings\Admin\Local Settings\Temp\aee14f5ff66544339403c2d0532a6b68.rsp"

    Code:
    Command line: "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\CL.exe" "@C:\Documents and Settings\Admin\Local Settings\Temp\aee14f5ff66544339403c2d0532a6b68.rsp"

    Code:
    Command line: mspdbsrv.exe -start -spawn

    Code:
    Command line: "C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\Tracker.exe" /a @"C:\Documents and Settings\Admin\Local Settings\Temp\0dca85d2d11f41dd86f25cdc7fd79dde.tmp" /c "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\link.exe"  /ERRORREPORT:PROMPT @"C:\Documents and Settings\Admin\Local Settings\Temp\dd9954c18a824badb990e11888b528da.rsp"
    lets check out msbuild whats it is ?

    From process explorer command line we know msbuild is in c:\windows\......\\

    though if you have several .net framework installed each .net version comes with its own msbuild.exe

    Code:
    C:\Program Files\Microsoft Visual Studio 10.0>ndff msbuild.exe
            Total filerecords to scan: 315232
    \WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe
    \WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe
    \WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
            Scanned 310259 filerecord(s) in 25.735 s.
            Found 3 file(s), 0 directory(ies), 0 alternate path(s).
    ok it seems this is a command line tool

    Code:
    C:\Program Files\Microsoft Visual Studio 10.0>msbuild /?
    Microsoft (R) Build Engine Version 4.0.30319.1
    [Microsoft .NET Framework, Version 4.0.30319.1]
    Copyright (C) Microsoft Corporation 2007. All rights reserved.
     
    Syntax:              MSBuild.exe [options] [project file]
     
    Description:         Builds the specified targets in the project file. If
                         a project file is not specified, MSBuild searches the
                         current working directory for a file that has a file
                         extension that ends in "proj" and uses that file.

    so it looks for a file with proj extension

    lets check out hello world

    Code:
    :\>dir /s /b *.*proj
    C:\Documents and Settings\Admin\My Documents\Visual Studio 2010\Projects\weight_of_hello_from_express_to_the_world\weight_of_hello_from_express_to_the_world.vcxproj
    :\>
    so there is only one file a .vcxproj

    so as a reverser the first instinct is to cut off all the shit and try only this file

    Code:
    :\>cd C:\Documents and Settings\Admin\Desktop\testvcxproj
    :\>copy "..\..\My Documents\Visual Studio 2010\Projects\ weight_of_hello_from_express_to_the_world\weight_of_hello_from_express_to_the_world.vcxproj".
            1 file(s) copied.
    :\>msbuild
    c1xx : fatal error C1083: Cannot open source file: 'stdafx.cpp':
    Build FAILED.
        1 Error(s)
    Time Elapsed 00:00:00.70

    \> so it is looking for stdafx.cpp providing stdafx.cpp it looks for source.cpp then stdafx.h then targetvar.h lets copy all these 4 files


    :
    Code:
    \>copy "..\..\My Documents\Visual Studio 2010\Projects\weight_of_hello_from_express_to_the_world\stdafx.cpp" .
            1 file(s) copied.    and so on
    :\>dir /s /b
    C:\Documents and Settings\Admin\Desktop\testvcxproj\stdafx.cpp
    C:\Documents and Settings\Admin\Desktop\testvcxproj\stdafx.h
    C:\Documents and Settings\Admin\Desktop\testvcxproj\targetver.h
    C:\Documents and Settings\Admin\Desktop\testvcxproj\weight_of_hello_from_express_to_the_world.cpp
    C:\Documents and Settings\Admin\Desktop\testvcxproj\weight_of_hello_from_express_to_the_world.vcxproj
    :\>msbuild
    Build started 03/04/2014 00:51:57.
    Build succeeded.
        0 Warning(s)
        0 Error(s)
    Time Elapsed 00:00:01.70
    :\>Debug\weight_of_hello_from_express_to_the_world.exe
     h   y  ello  world
     ya    mma
    :\>

    so it worked it seems we don�t want all the file except one vcxproj file to compile link and build we are back to one cpp one make file

    but we see only Debug Folder how to do a Release

    Code:
    :\>msbuild /p:Configuration=Release


    Code:
    :\>Release\weight_of_hello_from_express_to_the_world.exe
      h   y  ello  world
     ya    mma
    so Debug and Release is possible from one proj file

    if we need to clean the directory

    Code:
    /t:Clean /p:Configuration=<config>
    :\>ls -l


    total 24
    drw-rw-rw- 2 Admin 0 0 2014-04-03 00:51 Debug
    drw-rw-rw- 2 Admin 0 0 2014-04-03 00:58 Release
    -rw-rw-rw- 1 Admin 0 328 2014-03-31 00:46 stdafx.cpp
    -rw-rw-rw- 1 Admin 0 320 2014-03-31 00:46 stdafx.h
    -rw-rw-rw- 1 Admin 0 314 2014-03-31 00:46 targetver.h
    -rw-rw-rw- 1 Admin 0 273 2014-03-31 02:48 weight_of_hello_from_express_to_the_
    world.cpp
    -rw-rw-rw- 1 Admin 0 4434 2014-03-31 00:46 weight_of_hello_from_express_to_the_
    world.vcxproj

    now that we have cut away the masks let�s check what�s inside of this project file so that if need arises we can tweak and fiddle with it.


    Opening this is WordPad we find it is written in some kind of markup language called xml

    Some Google reveals xml is kind of html that enforces certain rules that html winks and let goes

    Working with this file in notepad / WordPad is clumsy who want to write < > </>

    Further Google yields an editor from ms xml notepad 2007

    downloading xml notepad 2007 and opening this vcxproject in xml notepad 2007

    We get a nice tree view in the left and text view in the right and handy controls to edit the file with undo redo / font and all other fancy beagles and buttons.



    It is time to start exploring the project file (that is delete everything inside it and start with single line and stop when it seems it works. ...

    Updated April 2nd, 2014 at 19:51 by blabberer

    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  2. addsym windbg extension (extension to load names from ida to windbg)

    Analysing unknown binaries especially malware drivers without symbols is a very tedious affair.

    this windbg extension is an effort to reduce the tediousness by transferring the names ida generated to windbg

    run the idc script to dump names to a sym file
    and use the extension in windbg to resolve the symbols from that file

    the idc script is posted below (tested in ida free 5 only and hacks are ida free 5 based if a chris eagle sees the script and knows of a better function that works seamlessly across the versions please comment back )

    it loads the inputfile and gets IMAGE_NT_HEADERS->OptionalHeader->BaseofCode and creates a variable to subtract which is the difference between idc function FirstSeg()-BaseofCode (namely ImageBase)

    then enumarates Name from FirstSeg() to MaxEA(); and dumps the bare offsets (RVA - IMAGEBASE ) and names to a file c:\\idasym\\GetInputFile().idasym in a format compatible to strtoul&sprintf()

    like

    00000300,DriverEntry
    00017ce5,SomeCrapFunction()
    00100000,aURLhttp://malwarebasedotcom/malware/foo.exe

    bare offsets are dumped because it doesnt require rebasing in ida and wouldnt have to worry about aslr in windbg

    also bare offsets can help in naming virtual allocated blocks
    manually create an idasymfile
    with offset,name
    point it with an address in windbg and all offsets relative to that address will be named appropriately

    simply analyse with ida and MakeName (visible in names window | publics) run the idc script in ida to overwrite an existing idasym file or create a new one

    do !addsym <modname> <path> in windbg for an updated disassembly

    idc script follows

    Code:
    #include <idc.idc>
    static main(void)
    {
        auto temp,elfaw_new ,baseofcode,tosubtract,symfile,segstart,segend,i,outfile,symname;
        // idafree doesnt seem to know anything about pe header HACK to get stuff
        temp = fopen(GetInputFilePath(),"rb");
        fseek(temp,0x3c,0);                 //to Read IMAGE_DOS_HEADER->elfaw_new
        elfaw_new = readlong(temp,0);
        fseek(temp,(elfaw_new+0x2c),0);     //to read  _IMAGE_NT_HEADERS->OptionalHeader->BaseofCode
        baseofcode = readlong(temp,0);
        tosubtract = FirstSeg()-baseofcode;
        fclose(temp);
    
        symfile = "c:\\IDASYM\\" + GetInputFile() + ".idasym";    
        outfile = fopen( symfile,"w");
        if (!outfile)
        {
            Message("failed to create file %s\n check if c:\\idasym folder exists",symfile);
        }
        else
        {
            Message("creating idasym file %s\n",symfile);
            segstart = 0;
            do
            {
                segstart = NextSeg(segstart);
                segend = SegEnd(segstart);
                for ( i = 0 ; i < segend-segstart ; i++)
                {
                    symname = Name( segstart+i ) ;
                    // discarding DOC AND UNDOC dummy names (does pro ida have convinience funcs ? 
                    //must be tedious without them :( )             
                    if (   
                        (symname != "" )                    &&  
                        (substr(symname,0,4) != "sub_")     &&  
                        (substr(symname,0,7) != "locret_")  && 
                        (substr(symname,0,4) != "loc_" )    && 
                        (substr(symname,0,4) != "off_" )    &&  
                        (substr(symname,0,4) != "seg_" )    &&  
                        (substr(symname,0,4) != "asc_" )    &&
                        (substr(symname,0,5) != "byte_" )   &&
                        (substr(symname,0,5) != "word_" )   &&       
                        (substr(symname,0,6) != "dword_" )  &&
                        (substr(symname,0,5) != "qword_" )  &&
                        (substr(symname,0,4) != "flt_" )    &&  
                        (substr(symname,0,4) != "dbl_" )    &&  
                        (substr(symname,0,6) != "tbyte__" ) &&
                        (substr(symname,0,5) != "stru_" )   &&  
                        (substr(symname,0,5) != "algn_" )   &&
                        (substr(symname,0,6) != "oword_" )  &&      
                        (substr(symname,0,4) != "unk_" ) 
                        )
                    { 
                        fprintf(outfile,"%08x,%s\n", ((segstart+i)-tosubtract)  , Name(  segstart+i ) );
                    }
                }
            }while (segend != BADADDR);
            fclose(outfile);
        }
    }

    source code for windbg extension follows

    Code:
    #include <engextcpp.hpp>
    #include < iostream >
    #include < fstream >
    #include < string >
    #include <tchar.h>
    
    using namespace std;
    
    class EXT_CLASS : public ExtExtension
    {
    public:
        EXT_COMMAND_METHOD(addsym);
    };
    
    EXT_DECLARE_GLOBALS();
    
    // takes two arguments first is an exprssion second is a string (path of idasymbol file)
    // !addsym   modulename viz nt / address viz 0x804d7200 etc  c:\idasym\xxx.idasym
    
    EXT_COMMAND( 
        addsym,
        "windbg extension to use names that are generated by ida \n do .reload /f MODULE.ext=base,size 
         prior to using this extension",
        "{;e;MODULE;An expression or address like nt / 0x804d7000 }{;x;path;path to idasym file \n
         viz c:\\idasym\\MODULE.EXT.idasym}" 
        )
    {
        ULONG offset;    
        ifstream ifs ,fs;
        char *symoff;
        string inbuff,buff;
        int i = 0;
        int j = 1;
        ULONG64 imagebase = GetUnnamedArgU64(0);    
        ifs.open(GetUnnamedArgStr(1));
        if ( (ifs.rdstate() & ifstream::failbit ) != 0)
        {
            Out("failed to open idasym file\n");
            goto exit;
        }
        do
        {
            i++;
        }while ( getline(ifs,inbuff) != NULL);
        Out("total symbols in idasym file is %d press ctrl+break to interrupt symbol resolving \n",i-1);
        ifs.close();
        fs.open(GetUnnamedArgStr(1));
        if ( (fs.rdstate() & ifstream::failbit ) != 0)
        {
            Out("failed to open idasym file\n");
            goto exit;
        }
        i = 0;
        while ( getline(fs,buff) != NULL)
        {
            i++;
            if (m_Control3->GetInterrupt() == S_OK)
            {
                break;
            }
            offset = strtoul(buff.c_str(),&symoff,16);
            m_Symbols3->AddSyntheticSymbol((imagebase + offset ),4,symoff+1,DEBUG_ADDSYNTHSYM_DEFAULT,NULL);  
            if (i == 500)
            {
                Out("%d symbols resolved\n",i*j);
                i = 0;
                j++;
            }
        }
        Out("total %d symbols resolved \n",((500*(j-1))+i) );
        fs.close();
    exit: 
        Out("done\n");
    }
    usage of extesnion follows (aswsp.sys of avastfree picked at random )

    Code:
    lkd> .load addsym
    lkd> !addsym
    ERROR: !addsym: extension exception 0x80070057.
        "Missing required argument '<MODULE>'"
    lkd> !addsym /?
    !addsym <MODULE> <path>
      <MODULE> - An expression or address like nt / 0x804d7000 
      <path> - path to idasym file 
               viz c:\idasym\MODULE.EXT.idasym (consumes remainder of input string)
    windbg extension to use names that are generated by ida 
    do .reload /f MODULE.ext=base,size prior to using this extension
    lkd> !addsym aswsp
    ERROR: !addsym: extension exception 0x80040205.
        "Unable to evaluate expression 'aswsp'"
    lkd> lm m aswsp*
    start    end        module name
    lkd> .reload /f aswsp.sys
    ERROR: Module load completed but symbols could not be loaded for \??\C:\WINDOWS\system32\drivers\aswSP.sys
    lkd> lm m aswsp*
    start    end        module name
    a968e000 a96ef600   aswSP      (no symbols)           
    lkd> x aswsp!*
    lkd> !addsym aswsp
    ERROR: !addsym: extension exception 0x80070057.
        "Missing required argument '<path>'"
    lkd> !addsym aswsp c:\idasym\aswsp.sys.idasy
    failed to open idasym file
    done
    lkd> !addsym aswsp c:\idasym\aswsp.sys.idasym
    total symbols in idasym file is 1457 press ctrl+break to interrupt symbol resolving 
    500 symbols resolved
    1000 symbols resolved
    total 1457 symbols resolved 
    done
    lkd> lm m aswsp*
    start    end        module name
    a968e000 a96ef600   aswSP      (no symbols)           
    lkd> x aswsp!*
    a969be30 aswSP!nullsub_1 = <no type information>
    a96a980e aswSP!nullsub_2 = <no type information>
    a96b6ed4 aswSP!memcpy = <no
    ...

    Updated March 18th, 2014 at 17:02 by blabberer

    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  3. winapihelp plugin for ollydbg 1.10

    WinApiHelp plugin for ollydbg 1.10

    I had been a big fan of compiled html help (*.chm) and with its demise i used to resort to various methods
    to create help files (basically for ollydbg usage) as Microsoft's latest help thingies never matched the ease
    that chm file offered especially for offline mode usage

    chm was simple you download the package double click and there you have everything in front of you
    but the hhx hhc were never standalone
    they required monstrous packages accompanying them to run and weren't adaptable even then

    recently out of sheer circumstances
    (i had ~ 600 mb data left on a prepaid and expiry date was closing in had to keep awake few nights
    soothing a little bundle of frayed nerves and i ended up downloading the offline content for visual studio 2010 express
    (win32 and com development and windows driver kit)

    help -> manage help settings -> settings -> i want to use local help
    install content from online add add update

    and once it was there i clicked F1 on MessageBoxA in editor

    a few seconds elapsed one tray icon popped up (help library agent ) and Firefox opened with the help file

    now curiosity always kills the cat it is said

    wtf is help lib agent ? why should i keep it open ? why it complains links will die and all help will cease to exist for me if i close it ?
    what is the queer protocol in Firefox 127.0.0.1:\\ no http:\\ / ftp:\\ ?? Local-host ??

    who is looking for that ? the big daddy at ms wants to know how i am helping myself ??

    and last but not least of the question can i use it in a standalone mode without having to run umpteen components in the background ?


    ollydbg by default used winhelp.chm (circa 19XX) for resolving symbolic help and it is damn outdated though quiet useful still

    never saw a good substitute for it (there is a plugin by iirc mario vilas but it patched ollydbg and sort of leeched online help when i saw it )

    no good offline substitute

    thus this plugin was born

    if you have installed any ms products (vs2010 express etc etc it installs help library for context sensitive help (F1 help))

    use the help library manger to install contents locally (cute manager can update the content to latest version of the page on MSDN )

    provide the path of the HelpLibraryAgent.exe to this plugin
    provide the path of your default browser to this plugin
    and simply hit F1 voila api help will be on screen in a jiffy

    and surprise surprise surprise

    you can even add your own help file to the local store and get it back with F1

    i have tested this plugin on v1.0 (vs2010 express MS-HELP) on xp sp3 vm only

    if anyone having vs2012 / vs2013 v1 . v2 . v3 etc and facing a few features leave back comments it will be appreciated.


    SURPRISE DETAILS

    supposing you are working on a ollydbg 2.10 h plugin and for all api help you are forced to visit ollydbg.de online everytime
    (more surprise once you have the contents locally it will show up in both ollydbg with this plugin and visual-studio directly )
    highlight and F1 in vs2010 on say Absolutizepath and you have it in screen
    select the line with Absolutizepath in ollydbg and F1 you have it on screen

    by adding all the help files to your local store you can have all the api details offline

    wget the help files from ollydbg.de

    wget -c -np -mirror http://www.ollydbg.de/Help/Absolutizepath.htm

    this wilL fetch around ~175 files navigate the downloaded tree to HELP folder and

    run this bat file (should be self explanatory ) you would need gnuwin32 sed / 7zip and html tidy in path

    html tidy to convert the html files to be xml compliant
    sed to delete the <DOCTYPE declaration insert xml header and add meta tags in <head> </head>
    7zip to zip the converted files (zip is renamed to mshc )
    create an msha file which help library manager recognizes for installing local content)
    update and you have all the F1 help for available apis

    mshc created thus have one wrinkle still left behind
    the relative links do not work

    the problem is each html help file needs an unique id for which i provide the file name
    but relative links needs to be fixed in each file to a valid ms-xhelp:// protocol

    i got bored hacking sed to look for <a href ="t_disasm.htm">t_disasm</a>
    and convert it to <a href="ms-xhelp://<uniqueid><text></a> in each and every file


    anyone wishing to contribute are welcome

    a substitute sed one liner added to convert relative links to ms-xhelp protocol

    relative links will work properly now

    toc and style sheet remains

    attachment modfied with latest bat file



    Code:
    xcopy help odbg2pluginhelp /EVQI
    
    cd odbg2pluginhelp 
    
    for /F %%I in ('dir /b *.htm') do tidy -quiet -wrap 0 -modify -numeric -utf8 -asxml  %%I 
    
    for /F %%I in ('dir /b *.htm') do sed -i "s/href=\"/href=\"ms-xhelp:\/\/\/?Id=/g" %%I
    del sed*
    
    for /F %%I in ('dir /b *.htm') do sed -i "1,2d" %%I
    del sed*
    for /F %%I in ('dir /b *.htm') do sed -i "1,1s/^/<?xml version=\"1.0\" encoding=\"utf-8\"?>\n/" %%I
    del sed*
    for /F %%I in ('dir /b *.htm') do sed -i "/<head>/a <meta name=\"Microsoft.Help.F1\" content=\"%%~nI\" />\n<meta name=\"Microsoft.Help.Id\" content=\"%%~nI%%~xI\" />\n" %%I
    del sed*
    "c:\Program Files\7-Zip\7z.exe" a odbg2pluginhelp.zip
    
    ren odbg2pluginhelp.zip odbg2pluginhelp.mshc
    
    echo ^<html xmlns="http://www.w3.org/1999/xhtml"^>  > helpcontentsetup.msha
    echo ^<head^>  >> helpcontentsetup.msha
    echo   ^<title^>odbg2pluginhelp^</title^>  >> helpcontentsetup.msha
    echo ^</head^>  >> helpcontentsetup.msha
    echo ^<body class="vendor-book"^>  >> helpcontentsetup.msha
    echo   ^<div class="details"^>  >> helpcontentsetup.msha
    echo     ^<span class="vendor"^>odbg^</span^>  >> helpcontentsetup.msha
    echo     ^<span class="locale"^>en-us^</span^>  >> helpcontentsetup.msha
    echo     ^<span class="product"^>ollydbg2.01h^</span^>  >> helpcontentsetup.msha
    echo     ^<span class="name"^>odbgpluginhelp^</span^>  >> helpcontentsetup.msha
    echo   ^</div^>  >> helpcontentsetup.msha
    echo   ^<div class="package-list"^>  >> helpcontentsetup.msha
    echo     ^<div class="package"^>  >> helpcontentsetup.msha
    echo       ^<span class="name"^>odbg2pluginhelp^</span^>  >> helpcontentsetup.msha
    echo       ^<a class="current-link" href="odbg2pluginhelp.mshc"^>Help.mshc^</a^>  >> helpcontentsetup.msha
    echo     ^</div^>  >> helpcontentsetup.msha
    echo   ^</div^>  >> helpcontentsetup.msha
    echo ^</body^>  >> helpcontentsetup.msha
    echo ^</html^>  >> helpcontentsetup.msha
    the source code for the plugin is shown below

    a compiled binary and src also attached at the end


    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <psapi.h>
    #include <iphlpapi.h>
    #include "plugin.h"
    
    #pragma warning(disable : 6335)
    
    #pragma comment(lib, "iphlpapi.lib")
    #pragma comment(lib, "psapi.lib")
    #pragma comment(lib, "ws2_32.lib")
    
    HINSTANCE	hinst; 
    HWND		hwmain;
    DWORD       pid = NULL;
    u_short     LocalPort = NULL;
    char        pathtohelplib[MAX_PATH];
    char        pathtodefbrowser[MAX_PATH];
    PMIB_TCPTABLE_OWNER_PID pTcpTable = NULL;
    
    DWORD findhelplibagent(void)
    {
        DWORD ProcessIds[1024], BytesReturned, TotalProcesses,Status;
        unsigned int i;
        if ( !EnumProcesses( ProcessIds, sizeof(ProcessIds), &BytesReturned ) )
        {
            Addtolist(0,1,"Enum Process Failed\n");
            Status = 0xffffffff;
            return Status;
        }
        TotalProcesses = BytesReturned / sizeof(DWORD);
        for ( i = 0; i < TotalProcesses; i++ )
        {
            if( ProcessIds[i] != 0 )
            {
                char ProcessName[MAX_PATH] = {"unknown"};
                HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessIds[i] );
                if (NULL != hProcess )
                {
                    HMODULE hMod;
                    DWORD cbNeed;
                    if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeed) )
                    {
                        GetModuleBaseNameA( hProcess, hMod, ProcessName, sizeof(ProcessName)/sizeof(char) );
                        if (_strnicmp("HelpLibAgent.exe",ProcessName,sizeof("HelpLibAgent.exe")
    ...

    Updated July 23rd, 2013 at 14:55 by blabberer

    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  4. Dbgeng based handles (PART 2 .............)


    Dbgeng based Handles (PART 2 .............)


    in part 1 we saw how to retrieve the handle details of all running process in a system using usermode handle

    in this article we will see how to retrieve the same info in kernel mode (we use local kernel mode in this example
    but there is no stopping you from using a real kernel debugging session and retrieving handles from a target

    in usermode the handles are real handles and we attached to each process to retrieve the handle details

    but in kernel mode there is a single virtual implicit process and we cant attach to any running process
    we can only set the implicit process

    but the extension kdexts.dll has done all this work internally so we can simply use it to retrieve the handle details

    the !handle extension in kernel mode takes an EPROCESS or Pid as a third parameter so we dont have to much with setting the implicit process everytime

    the code is similar to what we saw in part 1 of dbgeng handles

    read the previous (links below) articles for explanation of the implementation

    http://www.woodmann.com/forum/entry.php?246-A-Simple-Dbgeng-Based-User-Mode-Debugger
    http://www.woodmann.com/forum/entry.php?248-DbgEng-Based-Debugger-(PART2)
    http://www.woodmann.com/forum/entry.php?249-DbgEng-Based-Debugger-(PART2-Contd-)
    http://www.woodmann.com/forum/entry.php?250-DbgEng-based-Kernel-Debugger
    http://www.woodmann.com/forum/entry.php?251-Dbgeng-based-Handles



    a small summary of the implementation

    we start as usual by creating a client then query for interface
    implement output callback methods
    then get the pids and thier description (refer to dbgengHandle part 1)
    the nattach to kernel ad extesnion kdexts.dll and call extions handle
    handle in kernel mode takes EPROCESS or Cid as third param
    so we sprintf_s the argument and pass it a buffer
    also we set a Boolean to skip attaching to kernel on every iteration
    and that is it


    Code:
    #include <stdio.h>
    #include <dbgeng.h>
    IDebugClient2*          g_Client2       = NULL;
    IDebugControl*          g_Control       = NULL;
    HRESULT                 Status          = NULL;
    void Exit(int Code, PCSTR Format, ...)
    {
        if (g_Control != NULL)
        {
            g_Control->Release();
            g_Control = NULL;
        }
        if (g_Client2 != NULL)
        {
            g_Client2->EndSession(DEBUG_END_PASSIVE);
            g_Client2->Release();
            g_Client2 = NULL;
        }
        if (Format != NULL)
        {
            va_list Args;
            va_start(Args, Format);
            vfprintf(stderr, Format, Args);
            va_end(Args);
        }
        exit(Code);
    };
    class StdioOutputCallbacks : public IDebugOutputCallbacks
    {
    public:
        STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface );
        STDMETHOD_(ULONG, AddRef)( THIS );
        STDMETHOD_(ULONG, Release)(THIS );
        STDMETHOD(Output)( THIS_ IN ULONG Mask, IN PCSTR Text );
    };
    STDMETHODIMP StdioOutputCallbacks::QueryInterface( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ) 
    {
        *Interface = NULL;
        if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
            IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
        {
            *Interface = (IDebugOutputCallbacks *)this;
            AddRef();
            return S_OK;
        }
        else
        {
            return E_NOINTERFACE;
        }
    }
    STDMETHODIMP_(ULONG) StdioOutputCallbacks::AddRef( THIS    )
    {
        return 1;
    }
    STDMETHODIMP_(ULONG) StdioOutputCallbacks::Release(    THIS )
    {
        return 0;
    }
    STDMETHODIMP StdioOutputCallbacks::Output( THIS_ IN ULONG Mask, IN PCSTR Text )
    {
        UNREFERENCED_PARAMETER(Mask);
        fputs(Text, stdout);
        return S_OK;
    }
    StdioOutputCallbacks    g_OutputCb;
    void CreateInterfaces (void)
    {
        if ((Status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client2)) != S_OK)
        {
            Exit(1, "DebugCreate failed, 0x%X\n", Status);
        }
        if ((Status = g_Client2->QueryInterface(__uuidof(IDebugControl),    (void**)&g_Control))    != S_OK )
        {
            Exit(1, "g_Client2->QueryInterface(__uuidof(IDebugControl) failed, 0x%X\n", Status);
        }
        return ;
    }
    void __cdecl main(int Argc, char* Argv[])
    {
        ULONG Ids[0x100];
        char Exename[0x100];
        ULONG ActualCount = 0;
        ULONG64 Handle = 0;
        BOOL IsAttached =FALSE;
        memset(&Ids,0,sizeof(Ids));
        memset(&Exename,0,sizeof(Exename));
        CreateInterfaces();
        if ((Status = g_Client2->GetRunningProcessSystemIds(NULL,
            Ids,_countof(Ids),&ActualCount) ) != S_OK) 
        {
            Exit(1,"g_Client2->GetRunningProcessSystemIds failed, 0x%X\n", Status);
        }
        printf ("No of Running Process is 0n%d\n\nSRNo\tPID\tProcessName\n\n", ActualCount);
        for (ULONG i = 0; i < ActualCount;i++)
        {
            if (( g_Client2->GetRunningProcessDescription( 
                NULL, Ids[i], 
                DEBUG_PROC_DESC_NO_PATHS | DEBUG_PROC_DESC_NO_SERVICES | 
                DEBUG_PROC_DESC_NO_MTS_PACKAGES | DEBUG_PROC_DESC_NO_COMMAND_LINE,
                Exename, sizeof(Exename),NULL,NULL,NULL,NULL  ) ) != S_OK) 
            {
                Exit(1,"g_Client2->GetRunningProcessDescription Failed, 0x%X\n", Status);
            }
            printf("%02d\t0n%04d\t%s\n",i+1,Ids[i],Exename);
            if( Ids[i] == 0)
            {
                continue;
            }
            if (IsAttached == TRUE)
            {
                if ((Status = g_Client2->SetOutputCallbacks    (&g_OutputCb))    != S_OK)
                {
                    Exit(1,"g_Client2->SetOutputCallbacks failed, 0x%X\n", Status);
                }
                char *HandArg = (char *) malloc(0x40);
                sprintf_s(HandArg,0x40,"%d %d %X",0,3,Ids[i]);
                if (( Status = g_Control->CallExtension(Handle,"handle",HandArg)) != S_OK)
                {
                    Exit(1,"g_Control->CallExtension failed,0x%X\n",Status);
                }
                free(HandArg);
                if ((Status = g_Client2->SetOutputCallbacks    (0))    != S_OK)
                {
                    Exit(1,"g_Client2->SetOutputCallbacks failed, 0x%X\n", Status);
                }
                continue;
            }
            if (( Status = g_Client2->AttachKernel(DEBUG_ATTACH_LOCAL_KERNEL,NULL )) != S_OK)
            {
                Exit(1,"g_Client2->AttachKernel Failed, 0x%X\n", Status);
            }
            if (( Status = g_Control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE))!=S_OK)
            {
                Exit(1,"g_Control->WaitForEvent Failed, 0x%X\n", Status);
            }
            if (( Status = g_Control->AddExtension("kdexts.dll",0,&Handle)) != S_OK)
            {
                Exit(1,"g_Control->AddExtension failed,0x%X\n",Status);
            }
            if ((Status = g_Client2->SetOutputCallbacks    (&g_OutputCb))    != S_OK)
            {
                Exit(1,"g_Client2->SetOutputCallbacks failed, 0x%X\n", Status);
            }
            char *HandArg = (char *) malloc(0x40);
            sprintf_s(HandArg,0x40,"%d %d %x",0,3,Ids[i]);
            if (( Status = g_Control->CallExtension(Handle,"handle",HandArg)) != S_OK)
            {
                Exit(1,"g_Control->CallExtension failed,0x%X\n",Status);
            }
            free(HandArg);
            if ((Status = g_Client2->SetOutputCallbacks    (0))    != S_OK)
            {
                Exit(1,"g_Client2->SetOutputCallbacks failed, 0x%X\n", Status);
            }
            IsAttached = TRUE;
        }
        Exit(0, "Finished Debugging Quitting\n");
    }

    result as follows

    Code:
    No of Running Process is 0n32
    
    SRNo    PID    ProcessName
    
    01    0n0000    System Process
    02    0n0004    System
    
    Searching for Process with Cid == 4
    PROCESS 86dc69c8  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 002f4000  ObjectTable: e1000d18  HandleCount: 2659.
        Image: System
    
    Kernel handle table at e1cdd000 with 2659 entries in use
    
    0004: Object: 86dc69c8  GrantedAccess: 001f0fff Entry: e1002008
    Object: 86dc69c8  Type: (86dc6040) Process
        ObjectHeader: 86dc69b0 (old version)
            HandleCount: 2  PointerCount: 93
    
    0008: Object: 86dc6308  GrantedAccess: 00000000 Entry: e1002010
    Object: 86dc6308  Type: (86dc6e70) Thread
        ObjectHeader: 86dc62f0 (old version)
            HandleCount: 1  PointerCount: 1
    
    000c: Object: e1797518  GrantedAccess: 000f003f Entry: e1002018
    Object: e1797518  Type: (86dbf980) Key
        ObjectHeader: e1797500 (old version)
            HandleCount: 1  PointerCount: 1
            Directory Object: 00000000  Name: \REGISTRY\MACHINE\SYSTEM\CONTROLSET001\CONTROL\SESSION MANAGER\MEMORY MANAGEMENT\PREFETCHPARAMETERS
    ...
    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  5. Dbgeng based Handles


    Dbgeng based Handles


    most of those who are reading this article would be aware of Sysinternal's (mark russinovich) handle.exe
    it provides the details of all handles that are open in a system

    this article is an attempt to retrieve the same information using dbgeng interfaces and its allied extensions

    this article also builds upon previous articles that uses dbgeng interfaces and has components copy pasted
    as it is so if you are suggested to glance these articles too for ease of understanding

    http://www.woodmann.com/forum/entry.php?246-A-Simple-Dbgeng-Based-User-Mode-Debugger
    http://www.woodmann.com/forum/entry.php?248-DbgEng-Based-Debugger-(PART2)
    http://www.woodmann.com/forum/entry.php?249-DbgEng-Based-Debugger-(PART2-Contd-)
    http://www.woodmann.com/forum/entry.php?250-DbgEng-based-Kernel-Debugger



    so you are required to make a DbgEngHandle.cpp use visual studio to make a new project from existing code
    and use wdk7 xpfre build to compile and link and have a test folder filled with windbg dlls to test the resulting binary

    in the cpp
    we create a client query for interfaces implement an output callback attach non invasively to each running process
    recursively and get the handle details using an extension call

    handle details in usermode are exported from ExtensionFunction handle in ntsdexts.dll
    handle details in kernelmode are exported from ExtensionFunction handle in kdexts.dll

    lets see the implementations

    these are standard global declarations we want a client and a control interface only to get handle details

    Code:
    #include <stdio.h>  
    #include <dbgeng.h>
    
    IDebugClient2*          g_Client2       = NULL;
    IDebugControl*          g_Control       = NULL;
    HRESULT                 Status          = NULL;
    these below are standard exit and output callback implementation (resusable code]

    Code:
    void Exit(int Code, PCSTR Format, ...)
    {
        if (g_Control != NULL)
        {
            g_Control->Release();
            g_Control = NULL;
        }
        if (g_Client2 != NULL)
        {
            g_Client2->EndSession(DEBUG_END_PASSIVE);
            g_Client2->Release();
            g_Client2 = NULL;
        }
        if (Format != NULL)
        {
            va_list Args;
            va_start(Args, Format);
            vfprintf(stderr, Format, Args);
            va_end(Args);
        }
        exit(Code);
    };
    
    class StdioOutputCallbacks : public IDebugOutputCallbacks
    {
    public:
        STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface );
        STDMETHOD_(ULONG, AddRef)( THIS );
        STDMETHOD_(ULONG, Release)(THIS );
        STDMETHOD(Output)( THIS_ IN ULONG Mask, IN PCSTR Text );
    };
    STDMETHODIMP StdioOutputCallbacks::QueryInterface( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ) 
    {
        *Interface = NULL;
        if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
            IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
        {
            *Interface = (IDebugOutputCallbacks *)this;
            AddRef();
            return S_OK;
        }
        else
        {
            return E_NOINTERFACE;
        }
    }
    STDMETHODIMP_(ULONG) StdioOutputCallbacks::AddRef( THIS    )
    {
        return 1;
    }
    STDMETHODIMP_(ULONG) StdioOutputCallbacks::Release(    THIS )
    {
        return 0;
    }
    STDMETHODIMP StdioOutputCallbacks::Output( THIS_ IN ULONG Mask, IN PCSTR Text )
    {
        UNREFERENCED_PARAMETER(Mask);
        fputs(Text, stdout);
        return S_OK;
    }
    
    StdioOutputCallbacks    g_OutputCb;
    we start out main function by creating interface

    Code:
    void CreateInterfaces (void)
    {
        if ((Status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client2)) != S_OK)
        {
            Exit(1, "DebugCreate failed, 0x%X\n", Status);
        }
        if ((Status = g_Client2->QueryInterface(__uuidof(IDebugControl),    (void**)&g_Control))    != S_OK )
        {
            Exit(1, "g_Client2->QueryInterface(__uuidof(IDebugControl) failed, 0x%X\n", Status);
        }
        return ;
    }
    then use the

    Code:
    g_Client2->GetRunningProcessSystemIds
    g_Client2->GetRunningProcessDescription
    we skip system idle process from attaching and querying the handle details
    
            if( Ids[i] == 0)
            {
                continue;
            }
    for all other process that are currently running  we attach to them non invasively non suspending
    g_Client2->AttachProcess(NULL,
                Ids[i],DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND ))
    and wait for event
    g_Control->WaitForEvent
    
    then add the extension
    g_Control->AddExtension("ntsdexts.dll",0,&Handle))
    
    call the extension function
    g_Control->CallExtension  (the output call back recieves the output from this call)
    
    and detach from the process 
    g_Client2->DetachCurrentProcess(
    in a for loop for getting handle details from all running process

    it is then built using wdk xp fre environemnt

    and the resulting binary is executed from test folder that contains all the windbg dlls

    full source

    Code:
    #include <stdio.h>
    #include <dbgeng.h>
    
    IDebugClient2*          g_Client2       = NULL;
    IDebugControl*          g_Control       = NULL;
    HRESULT                 Status          = NULL;
    
    void Exit(int Code, PCSTR Format, ...)
    {
        if (g_Control != NULL)
        {
            g_Control->Release();
            g_Control = NULL;
        }
        if (g_Client2 != NULL)
        {
            g_Client2->EndSession(DEBUG_END_PASSIVE);
            g_Client2->Release();
            g_Client2 = NULL;
        }
        if (Format != NULL)
        {
            va_list Args;
            va_start(Args, Format);
            vfprintf(stderr, Format, Args);
            va_end(Args);
        }
        exit(Code);
    };
    
    class StdioOutputCallbacks : public IDebugOutputCallbacks
    {
    public:
        STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface );
        STDMETHOD_(ULONG, AddRef)( THIS );
        STDMETHOD_(ULONG, Release)(THIS );
        STDMETHOD(Output)( THIS_ IN ULONG Mask, IN PCSTR Text );
    };
    STDMETHODIMP StdioOutputCallbacks::QueryInterface( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ) 
    {
        *Interface = NULL;
        if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
            IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
        {
            *Interface = (IDebugOutputCallbacks *)this;
            AddRef();
            return S_OK;
        }
        else
        {
            return E_NOINTERFACE;
        }
    }
    STDMETHODIMP_(ULONG) StdioOutputCallbacks::AddRef( THIS    )
    {
        return 1;
    }
    STDMETHODIMP_(ULONG) StdioOutputCallbacks::Release(    THIS )
    {
        return 0;
    }
    STDMETHODIMP StdioOutputCallbacks::Output( THIS_ IN ULONG Mask, IN PCSTR Text )
    {
        UNREFERENCED_PARAMETER(Mask);
        fputs(Text, stdout);
        return S_OK;
    }
    
    StdioOutputCallbacks    g_OutputCb;
    
    void CreateInterfaces (void)
    {
        if ((Status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client2)) != S_OK)
        {
            Exit(1, "DebugCreate failed, 0x%X\n", Status);
        }
        if ((Status = g_Client2->QueryInterface(__uuidof(IDebugControl),    (void**)&g_Control))    != S_OK )
        {
            Exit(1, "g_Client2->QueryInterface(__uuidof(IDebugControl) failed, 0x%X\n", Status);
        }
        return ;
    }
    
    void __cdecl main(int Argc, char* Argv[])
    {
        ULONG Ids[0x100];
        char Exename[0x100];
        ULONG ActualCount = 0;
        ULONG64 Handle = 0;
    
        memset(&Ids,0,sizeof(Ids));
        memset(&Exename,0,sizeof(Exename));
        CreateInterfaces();
        if ((Status = g_Client2->GetRunningProcessSystemIds(NULL,
            Ids,_countof(Ids),&ActualCount) ) != S_OK) 
        {
            Exit(1,"g_Client2->GetRunningProcessSystemIds failed, 0x%X\n", Status);
        }
        printf ("No of Running Process is 0n%d\n\nSRNo\tPID\tProcessName\n\n", ActualCount);
        for (ULONG i = 0; i < ActualCount;i++)
        {
            if (( g_Client2->GetRunningProcessDescription( 
                NULL, Ids[i], 
                DEBUG_PROC_DESC_NO_PATHS | DEBUG_PROC_DESC_NO_SERVICES | 
                DEBUG_PROC_DESC_NO_MTS_PACKAGES | DEBUG_PROC_DESC_NO_COMMAND_LINE,
                Exename, sizeof(Exename),NULL,NULL,NULL,NULL  ) ) != S_OK) 
            {
                Exit(1,"g_Client2->GetRunningProcessDescription Failed, 0x%X\n", Status);
            }
            printf("%02d\t0n%04d\t%s\n",i+1,Ids[i],Exename);
            if( Ids[i] == 0)
            {
                continue;
            }
            if (( Status = g_Client2->AttachProcess(NULL,
                Ids[i],DEBUG_ATTACH_NONINVASIVE | DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND
    ...
    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  6. DbgEng based Kernel Debugger

    DbgEng based Kernel Debugger

    refer to the prior articles discussing how to use dbgeng functions and make a simple user mode debugger in part 1
    building upon it attaching to a local kernel and peeking around kernel memory was discussed in part 2 and part 2 contd...

    lets see how to make a real kernel debugger (KD clone) using dbgeng interfaces
    remember the steps we used to create a user mode debugger ? if not refresh by visiting
    http://www.woodmann.com/forum/entry.php?246-A-Simple-Dbgeng-Based-User-Mode-Debugger
    Creating A client using DebugCreate querying other required interfaces ,implementing the callbacks Setting a console ctrl+c handler a common exit releasing the interfaces and a main
    where a process was created and an infinte loop waiting for events and exiting when debuggee exits


    now copy paste the whole folder you created in the part 1 example
    (dbgengdbg.cpp , sources file , makefile , prebuild.bat the test folder that contains all windbg dlls )
    rename dbgengdbg.cpp to dbgengKD.cpp change the sources file to reflect the renaming

    and make one simple change in the dbgengKD.cpp

    Code:
    
    
    Code:
    Comparing files dbgengdbg.cpp and ..\DBGENGKD\DBGENGKD.CPP
    ***** dbgengdbg.cpp
            SetConsoleCtrlHandler(&HandlerRoutine,TRUE);  // Set control +c handler 
            if ((Status = g_Client->CreateProcess(0, Argv[1], DEBUG_ONLY_THIS_PROCESS)) != S_OK)  // create a process 
            {
    ***** ..\DBGENGKD\DBGENGKD.CPP
            SetConsoleCtrlHandler(&HandlerRoutine,TRUE);  // Set control +c handler 
            if ((Status = g_Client->AttachKernel(DEBUG_ATTACH_KERNEL_CONNECTION, "com:pipe,port=\\\\.\\pipe\\debugPipe,resets=0,recnnect")) != S_OK)  // create a process 
            {
    *****
    and build

    the resulting binary is now capable of attaching to a real machine via any of the connection methods

    the connection method i have provided in this example is to connect to a virtual machine using serial interface redirected to a NamedPipe
    "com:pipe,port=\\\\.\\pipe\\debugPipe,resets=0,recnnect"

    provide appropriate connection strings and you can connect via 1394 \ vmkd \ usb\ the new win8 network protocol apart from the trusty old serial and null modem cable

    just start the binary and it will wait for a kernel connection on com port 1
    start the vm on kernel debugging mode and connect for real kernel debugging session

    or if you have a vm running in debug mode hit the ctrl+sysreq in the vm and connect to the binary for a kd session

    see below

    Code:
    dbgengkd:\>dbgengKD.exe
    
    Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
    Copyright (c) Microsoft Corporation. All rights reserved.
    
    Opened \\.\pipe\debugPipe
    Waiting to reconnect...
    Connected to Windows XP 2600 x86 compatible target at (Sat Jan 26 03:46:12.656 2
    013 (UTC + 5:30)), ptr64 FALSE
    Kernel Debugger connection established.
    Symbol search path is: SRV*F:\symbols*http://msdl.microsoft.com/download/symbols
    
    Executable search path is:
    Windows XP Kernel Version 2600 (Service Pack 3) UP Free x86 compatible
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 2600.xpsp.080413-2111
    Machine Name:
    Kernel base = 0x804d7000 PsLoadedModuleList = 0x8055b1c0
    Debug session time: Sat Jan 26 03:40:03.650 2013 (UTC + 5:30)
    System Uptime: 0 days 2:54:32.638
    Break instruction exception - code 80000003 (first chance)
    *******************************************************************************
    *                                                                             *
    *   You are seeing this message because you pressed either                    *
    *       CTRL+C (if you run kd.exe) or,                                        *
    *       CTRL+BREAK (if you run WinDBG),                                       *
    *   on your debugger machine's keyboard.                                      *
    *                                                                             *
    *                   THIS IS NOT A BUG OR A SYSTEM CRASH                       *
    *                                                                             *
    * If you did not intend to break into the debugger, press the "g" key, then   *
    * press the "Enter" key now.  This message might immediately reappear.  If it *
    * does, press "g" and "Enter" again.                                          *
    *                                                                             *
    *******************************************************************************
    nt!RtlpBreakWithStatusInstruction+0x1:
    804e3593 c20400          ret     4
    kd>!process 0 0 letsreversewomen.exe
    PROCESS ffad4960  SessionId: 0  Cid: 01d8    Peb: 7ffde000  ParentCid: 0114
        DirBase: 03d77000  ObjectTable: e119d860  HandleCount:  48.
        Image: letsreversewomen.exe
    
    kd>.process /p /r ffad4960
    Implicit process is now ffad4960
    .cache forcedecodeuser done
    Loading User Symbols
    ............................
    nt!RtlpBreakWithStatusInstruction+0x1:
    804e3593 c20400          ret     4
    kd>s -[l 7]sa 12f500 L?9000
    0012fa34  "{FF24CF9A-EE48-4cde-AC10-15D1CE2"
    0012fa54  "C272C}.dat"
    0012fa97  "|{83D33F3A-9482-446f-ABFF-7B69D5"
    0012fab7  "8C1634}"
    0012fc78  "C:\DOCUME~1\rr\LOCALS~1\Temp\"
    0012fd2c  "C:\Documents and Settings\rr\Des"
    0012fd4c  "ktop\letsreversewomen\letsrevers"
    0012fd6c  "ewomen.exe"
    0012fdcc  "{A37340FD-F043-41e3-9C16-2F26323"
    0012fdec  "87199}"
    kd>.echo ollydbgs ghost is creating a file named <guid>.dat in temp folder and
    
    ollydbgs ghost is creating a file named <guid>.dat in temp folder and
    kd>
    i have attached the cpp . sources and make file tweak the connection string to your preference build and enjoy your own KD.exe:)

    code for ready reference

    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <dbgeng.h>
    IDebugClient*        g_Client        = NULL; // globals
    IDebugControl*        g_Control        = NULL; // globals
    IDebugBreakpoint*    g_Breakpoint    = NULL; // globals
    bool                State            = NULL; // globals
    void Exit(int Code, PCSTR Format, ...)        // release the interfaces on last in first out  basis
    {
        if (g_Control != NULL)                    // print message if given 
        {
            g_Control->Release();                // and exit the program
            g_Control = NULL;
        }
        if (g_Client != NULL)
        {
            g_Client->EndSession(DEBUG_END_PASSIVE);
            g_Client->Release();
            g_Client = NULL;
        }
        if (Format != NULL)
        {
            va_list Args;
            va_start(Args, Format);
            vfprintf(stderr, Format, Args);
            va_end(Args);
        }
        exit(Code);
    };
    class EventCallbacks : public DebugBaseEventCallbacks   // event callback class has 16 methods
    {
    public:
        STDMETHOD_(ULONG, AddRef)        ( THIS );
        STDMETHOD_(ULONG, Release)        ( THIS );
        STDMETHOD(Breakpoint)            ( THIS_ IN PDEBUG_BREAKPOINT Bp );
        STDMETHOD(ChangeDebuggeeState)    ( THIS_ IN ULONG Flags, IN ULONG64  Argument );
        STDMETHOD(ChangeEngineState)    ( THIS_ IN ULONG Flags, IN ULONG64  Argument );
        STDMETHOD(ChangeSymbolState)    ( THIS_ IN ULONG Flags, IN ULONG64  Argument );
        STDMETHOD(CreateThread)            ( THIS_ IN ULONG64  Handle, IN ULONG64  DataOffset,IN ULONG64  StartOffset);
        STDMETHOD(Exception)            ( THIS_ IN PEXCEPTION_RECORD64 Exception, IN ULONG FirstChance );
        STDMETHOD(ExitProcess)            ( THIS_ IN ULONG  ExitCode );
        STDMETHOD(ExitThread)            ( THIS_ IN ULONG  ExitCode );
        STDMETHOD(GetInterestMask)        ( THIS_ OUT PULONG Mask );
        STDMETHOD(SessionStatus)        ( THIS_ IN ULONG Status );
        STDMETHOD(SystemError)            ( THIS_ IN ULONG  Error, IN ULONG  Level );
        STDMETHOD(UnloadModule)            ( THIS_ IN PCSTR  ImageBaseName, IN ULONG64  BaseOffset );
        STDMETHOD(LoadModule)            ( 
            THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 BaseOffset, IN ULONG ModuleSize,
            IN PCSTR ModuleName,IN PCSTR ImageName,  IN ULONG CheckSum, IN ULONG TimeDateStamp );
        STDMETHOD(CreateProcess)        ( 
            THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 Handle, IN ULONG64 BaseOffset, IN ULONG ModuleSize,
            IN PCSTR ModuleName, IN PCSTR ImageName, IN ULONG CheckSum, IN ULONG TimeDateStamp, 
            IN ULONG64 InitialThreadHandle,    IN ULONG64 ThreadDataOffset, IN ULONG64 StartOffset );
    };
    class StdioOutputCallbacks : public IDebugOutputCallbacks  // output callback class 3 methods
    {
    public:
        STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface );
        STDMETHOD_(ULONG, AddRef)( THIS );
        STDMETHOD_(ULONG,
    ...
    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  7. DbgEng Based Debugger (PART2 Contd......)


    DbgEng Based Debugger (PART2 Contd......)


    continuing from part 2 where we discussed about peeking into kernel mode we saw how we can make dbgeng read DataSpaces and get details about key kernel mode addresses
    now in this example lets make dbgeng retrieve us some machine parameters
    exactly what ?

    shall we try CMOS Ram Map ?

    that could be as basic as it could get prior to that a box is all silicon and plastics
    i think (to debug silicon and plastic one may need to get into smelting furnaces and moulding machines and windbg isnt designed to be in that environment)

    if you are not aware of basics that we assume you understand in this article refer to the following 2 urls

    part 1 http://www.woodmann.com/forum/entry.php?246-A-Simple-Dbgeng-Based-User-Mode-Debugger
    part 2 http://www.woodmann.com/forum/entry.php?248-DbgEng-Based-Debugger-(PART2)

    ok so we want cmos rammap

    remove or comment out the ReadDebuggerData() code in your sample no 2 and inset this in its space

    Code:
        ULONG BusDataType = 0; //Cmos
        ULONG BusNumber = 0;
        ULONG SlotNumber = 0;
        ULONG StartOffset = 0;
        BYTE Buff[0x100];
        memset(&Buff,0,sizeof(Buff));
        ULONG BytesRead = 0;
        if ((g_DataSpaces->ReadBusData(
            BusDataType,
            BusNumber,
            SlotNumber,
            StartOffset,
            &Buff,
            (_countof(Buff)/2),
            &BytesRead
            )) == S_OK)
        {
            printf("Bytes Read From CMOS Bus is %d\n",BytesRead);
            int l = 0;
            printf("************************DUMP*************************************\n");
            while( l < sizeof(Buff) )
            {
                for (int i = l+0; i < l+0x10 ;i++)
                {
                    printf("%02x ",Buff[i]);
                }
                for (int i = l+0; i < l+0x10 ;i++)
                {
                    printf("%c",Buff[i]);
                }
                printf("\n");
                l+= 0x10;
            }
            printf("************************DUMP*************************************\n");
            for (int i = 0; i< _countof(CMosData); i++)
            {
                printf( "%40s = %02x\n",CMosData[i] , Buff[i]);
            }
    
    
        }
    
        Exit(0, "Finished Debugging Quitting\n");
    }

    and voila we got cmos ram map from the machine we ran this program on
    no need for what old dos junkies did to get it all of it in one go and what newer
    .net doesn't probably have access to

    Code:
    in port 70 magic 
    out port 71 genie
    does it work ?

    [code]
    Bytes Read From CMOS Bus is 128
    ************************DUMP*************************************
    41 45 13 16 13 11 05 25 01 13 26 42 00 80 00 00 AE‼▬‼◄♣%☺‼&B
    00 ee df e5 0a 80 02 00 fc e9 be 37 ea f7 ed 3a ε▀σ☻ ⁿΘ╛7Ω≈φ:
    6d ef ff af fe ff ff e3 fa fc ff 7d f9 46 14 ba m∩ ■ πⁿ }∙F║
    00 fc 20 d9 fc ff 00 9f 1d ff df df e7 b9 df df ⁿ ┘ⁿ ↔ ▀▀τ╣▀▀
    fe ef be fb 79 57 ff d3 ff bf 72 d6 fb f9 bf f6 ■∩╛√yW ╙ ┐r╓√∙┐
    fb fe db ae fb f7 ff 1f ff 7e e4 76 ef 6b ea f5 √■█√≈ ▼ ~Σv∩kΩ⌡
    db f7 eb 7d fe fd e9 02 f7 f9 d7 ef 00 53 f4 6c █≈δ}■Θ☻≈∙╫∩ S⌠l
    1f ff fe fe bf fb ee f1 76 fd ff bd fe 33 f3 fe ▼ ■■┐√εv ╜■3≤■
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    ************************DUMP*************************************
    RTCSeconds = 41
    RTCSecondsAlarm = 45
    RTCMinutes = 13
    RTCMinutesAlarm = 16
    RTCHours = 13
    RTCHoursAlarm = 11
    RTCDayofWeek = 05
    RTCDateDay = 25
    RTCDateMonth = 01
    RTCDateYear = 13
    StatusRegisterA = 26
    StatusRegisterB = 42
    StatusRegisterC = 00
    StatusRegisterD = 80
    DiagnosticStatus = 00
    CMOSShutdownStatus = 00
    FloppyDiskDriveTypes = 00
    SystemConfigurationSettings = ee
    HardDiskTypes = df
    TypematicParameters = e5
    InstalledEquipment = 0a
    BaseMemoryLowOrderByte = 80
    BaseMemoryHighOrderByte = 02
    ExtendedMemoryLowOrderByte = 00
    ExtendedMemoryHighOrderByte = fc
    HardDisk0ExtendedType = e9
    HardDisk1ExtendedType = be
    CNumberofcylindersLSB = 37
    CNumberofcylindersMSB = ea
    CNumberofheads = f7
    CWriteprecompcylinderLSB = ed
    CWriteprecompcylinderMSB = 3a
    CControlbyte = 6d
    CLandingzoneLSB = ef
    CLandingzoneMSB = ff
    CNumberofsectors = af
    DNumberofcylindersLSB = fe
    DNumberofcylindersMSB = ff
    DNumberofheads = ff
    DWriteprecompcylinderLSB = e3
    DWriteprecompcylinderMSB = fa
    DControlbyte = fc
    DLandingzoneLSB = ff
    DLandingzoneMSB = 7d
    DNumberofsectors = f9
    SystemOperationalFlags = 46
    CMOSChecksumHighOrderByte = 14
    CMOSChecksumLowOrderByte = ba
    ActualExtendedMemoryLoByte = 00
    ActualExtendedMemoryHiByte = fc
    CenturyDateBCD = 20
    POSTInformationFlags = d9
    BIOSandShadowOptionFlags = fc
    BIOSandShadowOptionFlags = ff
    ChipsetSpecificInformation = 00
    PasswordSeedandColorOption = 9f
    EncryptedPassword1bytes = 1d
    EncryptedPassword2bytes = ff
    EncryptedPassword3bytes = df
    EncryptedPassword4bytes = df
    EncryptedPassword5bytes = e7
    EncryptedPassword6bytes = b9
    ExtendedCMOSChecksum = df
    ExtendedCMOSChecksum = df
    ModelNumberByte = fe
    FirstSerialNumber = ef
    SecondSerialNumber = be
    ThirdSerialNumber = fb
    FourthSerialNumber = 79
    FifthSerialNumber = 57
    SixthSerialNumber = ff
    CRCByte = d3
    CenturyByte = ff
    DateAlarm = bf
    ExtendedControlRegister4A = 72
    ExtendedControlregister4B = d6
    Reserved = fb
    Reserved = f9
    RealTimeClockAddress2 = bf
    RealTimeClockAddress3 = f6
    ExtendedRAMAddress = fb
    ExtendedRAMAddress = fe
    Reserved = db
    ExtendedRAMDataPort = ae
    Reserved = fb
    Finished Debugging Quitting

    the details of the array CmosData is taken from bob hurts bios central cmos memory map page
    google bob hurt cmos and it is first hit on first page

    you can also check with time /t & date /t clubbed with this binary

    Code:
    13:19
    25/01/2013
    
    RTCSeconds = 11
    RTCMinutes = 19
    RTCHours = 13
    RTCDayofWeek = 05
    RTCDateDay = 25
    RTCDateMonth = 01
    RTCDateYear = 13
    nice and clean isnt it ?
    windbg itself doesnt seem to be able to display this
    no dont get me wrong i just now during research for this article learnt windbg does have the functionality to retrieve this and display (i tried coaxing windbg display this but either i must have been doing something wrong
    or this functionality is truly broken in windbg

    to make windbg display this you need to open the memory window (gui only) right click properties on memory window select the BUS tab and provide it bus / slot / offset details

    a screen shot below

    Name:  cmosmemory.JPG
Views: 6224
Size:  63.9 KB

    also attached the files used to compile this open the bat file and read before building it
    LKDCMOS.zip
    Categories
    Uncategorized
  8. DbgEng Based Debugger (PART2)

    DbgEng Based Debugger (PART2)

    Continuing from (part 1) where I described the usage of dbgeng interfaces and utilized them for coding a simple user mode debugger.
    I now describe the dbgeng interfaces that would let you peek into kernel aka the mighty ring3

    Are you ready if you are not familiar with dbgeng interfaces please refer to this
    http://www.woodmann.com/forum/entry.php?246-A-Simple-Dbgeng-Based-User-Mode-Debugger

    A short summary of the link for those of you too bored to click a link and read the dry pages


    1. To start with any DbgEng Interfaces you need to create a client
    2. A client may be created using DebugCreate() Function;
    3. Once you Created a client you can Query that client for other interfaces
    4. To Query for interfaces you use QueryInterface() Function
    5. Each of these interfaces implements few methods
    6. Methods that don�t depend on other interfaces can be called directly
    7. Methods that depend on other interfaces can be called after querying them
    8. All interfaces must be released before exiting the program
    9. Release the interfaces on last in first out basis ie (Client will be released last )
    10. There are 3 callbacks available (EVENT , INPUT and OUTPUT) (optional)
    11. The Dbgeng engine uses these callbacks to communicate with your program handlers
    12. A callback consist of a base class, implementation of the methods and a declaration
    13. Event Callback implements 14 optional methods and 2 mandatory methods
    14. Output Callback implements 1 optional method and 2 mandatory methods
    15. Input Callback implements 2 optional methods and 2 mandatory methods
    16. The mandatory methods are AddRef() and Release()
    17. The main program mostly consists of
    18. Argument / Program Input parsing routine
    19. Interfaces creating routine ,
    20. Implementation of callbacks (optinal)
    21. Infinite loop waiting for events to be handled by the cal1back handlers and exit when done



    lets gets our hands wet in kernel mode

    it should be clear now that we can code a basic barebones kernel peeking code with just
    a client and a few required interfaces

    and that is what we will do in this example

    DebugCreate()
    QueryInterface () IDebugControl() for attaching to kernel
    QueryInterface () IDebugDataSpaces() for Reading Debugger Data
    Attach to kernel
    Wait for event
    ReadDebuggerData()
    Print Results
    Exit()


    The code as follows

    Code:
    #include "dbgengdecl.h"
    
    IDebugClient*          g_Client            = NULL;
    IDebugControl*        g_Control         = NULL;
    IDebugDataSpaces*  g_DataSpaces  = NULL;
    HRESULT Status = NULL;
    
    void Exit(int Code, PCSTR Format, ...)
    {
        if (g_Control != NULL)
        {
            g_Control->Release();
            g_Control = NULL;
        }
        if (g_Client != NULL)
        {
            g_Client->EndSession(DEBUG_END_PASSIVE);
            g_Client->Release();
            g_Client = NULL;
        }
        if (Format != NULL)
        {
            va_list Args;
            va_start(Args, Format);
            vfprintf(stderr, Format, Args);
            va_end(Args);
        }
        exit(Code);
    };
    
    void __cdecl main(int Argc, char* Argv[])
    {
        if ((Status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client)) != S_OK)    
        {
            Exit(1, "DebugCreate failed, 0x%X\n", Status);
        }
        if ((Status = g_Client->QueryInterface(__uuidof(IDebugControl),    (void**)&g_Control))    != S_OK )
        {
            Exit(1, "g_Client->QueryInterface(IDebugControl) failed, 0x%X\n", Status);
        }
        if ((Status = g_Client->QueryInterface(__uuidof(IDebugDataSpaces),    (void**)&g_DataSpaces))    != S_OK )
        {
            Exit(1, "g_Client->QueryInterface(IDebugDataSpace) fail, 0x%X\n", Status);
        }
        if ((Status = g_Client->AttachKernel( DEBUG_ATTACH_LOCAL_KERNEL,    NULL)) != S_OK)      
        {
            Exit(1, "AttachKernel failed, 0x%X\n", Status);
        }
        if ((Status = g_Control->WaitForEvent( DEBUG_WAIT_DEFAULT, INFINITE ) ) != S_OK)      
        {
            Exit(1, "g_Control->WaitForEvent failed, 0x%X\n", Status);
        }
        ULONG64 Buffer    = 0;
        ULONG    DataSize = 0;
        for (int i =0; i<_countof(DataSpaceIndex);i++)
        {
            if ((g_DataSpaces->ReadDebuggerData( DataSpaceIndex[i].a , (PVOID)&Buffer, 8, &DataSize) ) ==S_OK)
            {
                printf("%40s  =  %I64x\n",DataSpaceIndex[i].b,Buffer);
                continue;
            }
            printf("cant retrieve data for %d\n",i);
        }
        Exit(0, "Finished Debugging Quitting\n");
    }
    simple and clean
    a common exit routine that releases the interfaces prints message and quits
    DebugCreate
    QueryInterface
    Call methods needed ( AttachKernel, WaitForEvent, ReadDebuggerData )
    Prints results
    And exit


    Since this is a simple use case we haven�t implemented any callbacks and as described earlier they are optional
    Peeking into kernel is as simple as 65 lines of c code with dbgeng interface.

    Now on looking again you might wonder there is an include file that is
    Not in include path but in local directory dbgengdecl.h
    and an array of structure DataSpaceIndex that doesn�t seem to be defined
    what is it and Does it contain any magic ?

    No absolutely not it is copy paste of some #defines From dbgeng.h
    Into a structure so that we can printf the results
    See below
    And the grunt work was done using gnuwin32 ports of unix tools
    Grep sed and paste

    In dbgeng.h
    We have #defines for all indices of DEBUG_DATA defined like below

    // Indices for ReadDebuggerData interface
    #define DEBUG_DATA_KernBase 24


    the grep �I �define DEBUG_DATA.*[0-9] regexp

    gathers all of them from dbgeng.h and passes it to sed

    sed "1,8 d" deletes first 8 lines and is redirected to sed again

    sed "114,$ d" deletes any lines till end from line 114 onwards and redirects the output again to sed

    sed s/"#define DEBUG"/"{ DEBUG"/g substitutes all #defines with opening brace { and passes it sed again

    sed s/" .*[0-9]"/","/g substitutes the space and numbers in the end with a comma , and stores it in a temp file tmp1.txt

    similarly the second line in bat replaces #define DEBUG_DATA_ with a double quote (\x22) at start and replaces the space and numerals with a double quote closing brace
    and comma � }, to a file tmp2.txt

    paste concatenates both the file line by line into another file

    and the finished file will contain

    { DEBUG_DATA_KernBase, "KernBase" }, instead of

    #define DEBUG_DATA_KernBase 24


    kind of kludge work but I am used to it so I don�t feel any pain
    any better ideas that makes sense are welcome and I would say this kludge is far better than initializing the array manually with 113 structure members defined in dbgeng.h


    Code:
    grep -i "#define  DEBUG_DATA.*[0-9]" %DBGSDK_INC_PATH%\dbgeng.h | sed "1,8 d" | sed "114,$  d" | sed s/"#define DEBUG"/"{ DEBUG"/g | sed s/"  .*[0-9]"/","/g  >tmp1.txt
    grep -i "#define DEBUG_DATA.*[0-9]" %DBGSDK_INC_PATH%\dbgeng.h | sed  "1,8 d" | sed "114,$ d" | sed s/"#define DEBUG_DATA_"/\x22/g | sed s/"   .*[0-9]"/"\x22 },"/g >tmp2.txt
    
    paste tmp1.txt tmp2.txt > finished.txt
    
    del tmp*.*
    the finished file hand modified to remove the last comma
    declare a structure and array include the required include files and renamed into dbgengdecl.h is as below

    Code:
    #include <stdio.h>
    #include <dbgeng.h>
    
    typedef struct _FOO
    {
        ULONG a;
        PSTR  b;
    }Foo , *PFoo;
    
    Foo DataSpaceIndex[] =
    {
        { DEBUG_DATA_KernBase,    "KernBase" },
        { DEBUG_DATA_BreakpointWithStatusAddr,    "BreakpointWithStatusAddr" },
        { DEBUG_DATA_SavedContextAddr,    "SavedContextAddr" },
        { DEBUG_DATA_KiCallUserModeAddr,    "KiCallUserModeAddr" },
        { DEBUG_DATA_KeUserCallbackDispatcherAddr,    "KeUserCallbackDispatcherAddr" },
        { DEBUG_DATA_PsLoadedModuleListAddr,    "PsLoadedModuleListAddr" },
        { DEBUG_DATA_PsActiveProcessHeadAddr,    "PsActiveProcessHeadAddr" },
        { DEBUG_DATA_PspCidTableAddr,    "PspCidTableAddr" },
        { DEBUG_DATA_ExpSystemResourcesListAddr,    "ExpSystemResourcesListAddr" },
        { DEBUG_DATA_ExpPagedPoolDescriptorAddr,    "ExpPagedPoolDescriptorAddr" },
        { DEBUG_DATA_ExpNumberOfPagedPoolsAddr,    "ExpNumberOfPagedPoolsAddr" },
        { DEBUG_DATA_KeTimeIncrementAddr,    "KeTimeIncrementAddr" },
        { DEBUG_DATA_KeBugCheckCallbackListHeadAddr,    "KeBugCheckCallbackListHeadAddr" },
        { DEBUG_DATA_KiBugcheckDataAddr,    "KiBugcheckDataAddr" },
        { DEBUG_DATA_IopErrorLogListHeadAddr,    "IopErrorLogListHeadAddr"
    ...
    Categories
    Uncategorized
  9. A Simple Dbgeng Based User Mode Debugger



    A Simple Dbgeng Based User Mode Debugger


    I wrote a simple plugin to ollydbg v 2.0 it is called olly_lkd it mimics the windbg local kernel debugging functionality I simply had hooked and hacked and used lot of magic constants while I wrote it though it works ( I hope so no real feedback on its bugs / problems were received in spite of it being downloaded quite a few times ) I did not post the source as it was a mess

    this tutorial is an attempt to demystify the magic behind dbgeng and its com based sorcery
    once you shed the fear of com /c++ / its magic interfaces and classes you will appreciate
    how good the framework is and why windbg survives the latest tech when its contemporaries have withered away

    the documentation to these functions are also dry in either the help (debugger.chm) that comes along with the windbg documentation or in MSDN and you don�t get a lot of help in the wild alleys of internet on how to use these functions only obscure
    *i<template foo **ppv pWhatever = QuerySomecrap (** Scooby doo) snippets surface and understanding them is a task in itself and even if you believe you understood the snippet you are still left scratching your head on implementing it to your present task.

    Okay enough whining.
    Lets get to the task in hand

    As they say the whole journey starts with a single step (yep single stepping is basic requirement for traveling any where or debugging anything )

    The first step you put out is IDebugClient I wont bore you by copy pasting the lines from windbg.chm or msdn read them yourself and read it several times they aren�t easy to digest if you have coded only asm or simple c programs and aren�t familiar with the component object model (COM ) interfaces

    See what the document says about client objects

    Almost all interaction with the debugger engine is through client objects, often simply referred to as clients. Each client provides an implementation of the top-level engine interfaces. Each interface provides a different set of methods, which can be used to interact with the engine and, through the engine, the targets An instance of the engine can have many clients, each with its own state.
    so you first create a client and to create a client you use DebugCreate ();


    if you have a bit of reversing spirit in your blood stream then you might know that DebugCreate() is one of the few Functions Exported by Dbgeng.dll
    Code:
    HRESULT
      DebugCreate(
        IN REFIID  InterfaceId,
        OUT PVOID *  Interface
        );
    Code:
    ParametersInterfaceIdSpecifies the interface identifier (IID) of the desired debugger engine client interface. This is the type of the interface that will be returned in Interface. For information about the interface identifier, see COM Interfaces 
    Interface
    Receives an interface pointer for the new client. The type of this interface is specified by InterfaceId.
    


    this is how you call it
    #include <dbgeng.h>
    declare a pointer to IDebugClient and receive the interface pointer from DebugCreate()

    Code:
    IDebugClient*    g_Client                        = NULL;
    HRESULT                   Status                           = 0;
     
                if ((Status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client)) != S_OK)
                {
                            Exit(1, "DebugCreate failed, 0x%X\n", Status);
                }
    so the lines above call DebugCreate with the interface id of IDebugClient and receive a pointer to it in g_Client if the Function failed it exits the program by returning a code
    freeing any prior resources that were allotted and printing a message

    the exit function is shown below


    Code:
    void Exit(int Code, PCSTR Format, ...)
    {
           if (g_Client != NULL)
           {
                  g_Client->EndSession(DEBUG_END_PASSIVE);
                  g_Client->Release();
                  g_Client = NULL;
           }
           if (Format != NULL)
           {
                  va_list Args;
                  va_start(Args, Format);
                  vfprintf(stderr, Format, Args);
                  va_end(Args);
           }
           exit(Code);
    }
    at the moment it is enough to say you have an IUnknown Com Interface in g_Client

    Code:
    DEFINE_GUID(IID_IDebugClient, 0x27fe5639, 0x8407, 0x4f47, 0x83, 0x64, 0xee, 0x11, 0x8f, 0xb0, 0x8a, 0xc8);
    /* edbed635-372e-4dab-bbfe-ed0d2f63be81 */
     
    typedef interface DECLSPEC_UUID("27fe5639-8407-4f47-8364-ee118fb08ac8")
        IDebugClient* PDEBUG_CLIENT;

    and you can use QueryInterface to query these com interfaces from g_Client

    Code:
    IDebugAdvanced
    IDebugClient
    IDebugControl
    IDebugDataSpaces
    IDebugRegisters
    IDebugSymbols
    IDebugSystemObjects
    so if you want IDebugControl

    you simply query for it by declaring a pointer to IDebugControl

    Code:
                IDebugControl* g_Control = NULL;
     
           if ((Status = g_Client->QueryInterface(__uuidof(IDebugControl),      (void**)&g_Control)) != S_OK )
           {
                  Exit(1, "QueryInterface failed, 0x%X\n", Status);
           }
    notice we exit using the same old Exit() Function
    so obviously you need to release g_Control as well when you are done with it

    Code:
    void Exit(int Code, PCSTR Format, ...)
    {
           if (g_Control != NULL)
           {
                  g_Control->Release();
                  g_Control = NULL;
           }
           if (g_Client != NULL)
           {
                  g_Client->EndSession(DEBUG_END_PASSIVE);
                  g_Client->Release();
                  g_Client = NULL;
           }
           if (Format != NULL)
           {
                  va_list Args;
                  va_start(Args, Format);
                  vfprintf(stderr, Format, Args);
                  va_end(Args);
           }
           exit(Code);
    }
    each of these interfaces implement few methods
    one of it is Addref() and another one is Release()

    if you have noticed g_Control is released first and g_Client is released later
    the reason behind being quoted verbatim from docs


    The reference count will be initialized to one when the client object is created using DebugCreate

    When IUnknown::QueryInterface is called, the reference count is incremented, so when a client interface pointer is no longer needed IUnknown::Release should be called to decrement the reference count.
    we start by calling DebugCreate() for a Client and then call QueryInterface for further interfaces

    Apart from
    Code:
    #define INTERFACE IDebugClient
    DECLARE_INTERFACE_(IDebugClient, IUnknown)
    {
        // IUnknown.
        STDMETHOD(QueryInterface)(
            THIS_
            __in REFIID InterfaceId,
            __out PVOID* Interface
            ) PURE;
        STDMETHOD_(ULONG, AddRef)(
            THIS
            ) PURE;
        STDMETHOD_(ULONG, Release)(
            THIS
            ) PURE;
    IDebugClient has a few other methods too read the doc or MSDN for various methods
    There are also enhanced version of
    IDebugClient named

    DECLARE_INTERFACE_(IDebugClient2, IUnknown) till
    DECLARE_INTERFACE_(IDebugClient5, IUnknown)


    We will discuss IDebugClient::CreateProcess in this tutorial

    You will absorb further methods and enhancements when you start traveling down the road

    Lets now try coding a simple exe that gets only g_Client and uses one of its methods.
    GetIdentity();

    Code:
     
    HRESULT
      IDebugClient::GetIdentity(
        OUT OPTIONAL PSTR  Buffer,
        IN ULONG  BufferSize,
        OUT OPTIONAL PULONG  IdentitySize
        );


    create a new folder named JustClient
    create a new file named JustClient.cpp inside the newly created folder
    you can use notepad / wordpad / vim / your own text editor/ but I would use Visual Studio Express to code and will compile and link it using a batch file and wdk separately

    C:\>md JustClient
    C:\>cd JustClient
    C:\JustClient>copy con JustClient.cpp
    ^Z
    1 file(s) copied.
    C:\JustClient>"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\VCExpress.exe"
    C:\JustClient>
    In vcexpress2010 using
    new
    project from existing code
    project file location c:\justClient
    project name JustClient
    next next....... finish
    in the source files you will have JustClient.cpp already added and you can start coding

    #include <windows.h>
    #include <DbgEng.h>

    void __cdecl main(void)
    {
    IDebugClient * g_Client = NULL;
    HRESULT Status = NULL;
    if (( Status = g_Client->Get
    and at this point using a visual studio project for coding shows up
    Name:  vchelp.JPG
Views: 7356
Size:  24.8 KB

    lets finish the code

    Code:
    
    
    ...
    Categories
    Uncategorized
  10. Reversing RunDialog (Start+Run or Winkey+R) to Add a 27th entry to RunMRU list

    Mint77 posted in the forum asking how to increase the run dialog
    (Start => Run / Winkey + R) MRU (Most Recently Used ) contents

    It is aptly named MRU which implies it holds only a few entries and not all the entries from times immemorial

    It seems he had earlier been told by someone at MSDN that the max limit was 26 entries and the older entries drop out on FIFO (First In First Out) basis

    So if the MRU list is full the and we have a new contender the oldest entry drops out and the latest entry is dropped in

    Logically right and practically right

    But logic and practicality never works when it comes to reversing

    He posted that he was told there was no way to increase the limit and was looking for some ideas to realize his fantasy

    So I tossed in a some time and took a look.

    A few minutes in procmon / windbg and the 27th entry is overloaded into RunMruList

    Name:  runmrubiggerthan_26.JPG
Views: 6746
Size:  142.7 KB

    WARNING:

    do not mimic the methods shown. Without understanding the implications of various locks held like spinlocks , critical sections, , interlocked cmpexchg in critical system processes it may crash and may cause BSOD


    RUN Dialog is handled by explorer.exe
    Lets fire procmon and capture pertinent events in explorer.exe

    (be sure to configure symbols in procmon prior to capturing events so that stack is properly displayed you can point it to your _NT_SYMBOL_PATH cache )

    a default procmon captures too much events

    procmon monitors file events , registry events network event and profiling events
    apart from process / thread events

    an enormous amount of spew ensues as a result

    we need to set a filter

    we know we are interested in explore.exe events only

    we also are interested in MRU so set a filter for MRU in path

    click filter menu and select filter submenu (ctrl + L hotkey)

    process monitor filter will popup



    1st time 2nd time
    in the 1st drop down select process path
    in the 2nd drop down select is contains
    in the 3rd drop down type in explorer.exe MRU
    in the 4th drop down select include include



    click add after each time if all went well the pane should look like this

    Name:  procmon filter.PNG
Views: 6678
Size:  80.6 KB

    click apply and let procmon roll

    goto start => hit run or do Winkey+R and execute a program

    preferably one which is not available in MRU

    or clear the MRU via taskbar and start menu properties and type in a new program
    so that we have a complete log

    a fresh run will see the following entries notice RegSetValue that is highlighted
    we are interested in its stack which is shown below

    Name:  procmonstk.jpg
Views: 6671
Size:  125.0 KB

    so AddMruStringW is where something interesting might be available lets close procmon for now and run a debugger to check the AddMruStringW function in explorer.exe

    Code:
    
    windbg -pn explorer.exe -c "bp Shell32!AddMruStringW;g"
    
    -pn attaches to a running process by specifying the process name

    -c Specifies the initial debugger command to run at start-up.



    In the initial command we are setting breakpoint on the api we saw in procmon and ask windbg to continue its execution

    We now go to start=>run and enter any program to execute so that we shall break in windbg and we can examine the state

    Code:
    Breakpoint 0 hit
    eax=0274ee20 ebx=00000000 ecx=7c9c95ba edx=000000fb esi=01c73ff8 edi=00000009 eip=7ca2b28d esp=0274ebf8 ebp=0274f0b0 iopl=0         nv up ei pl zr na pe nc cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000 efl=00000246
    SHELL32!AddMRUStringW:
    7ca2b28d 8bff            mov     edi,edi
    lets check the stack

    Code:
    0:017> kb
    ChildEBP RetAddr  Args to Child              
    039bebf4 7ca408e2 00139220 039bee20 00150202 SHELL32!AddMRUStringW
    039bf0b0 7ca4073f 039bf128 7ca40091 039bf0ec SHELL32!CRunDlg::OKPushed+0x1ce
    039bf0c0 7e418734 00150202 00000111 00000001 SHELL32!RunDlgProc+0x121
    039bf0ec 7e423ce4 7ca40091 00150202 00000111 USER32!InternalCallWinProc+0x28
    039bf158 7e423b30 0009e158 7ca40091 00150202 USER32!UserCallDlgProcCheckWow+0x146
    039bf1a0 7e423d5c 00000000 00000111 00000001 USER32!DefDlgProcWorker+0xa8
    039bf1bc 7e418734 00150202 00000111 00000001 USER32!DefDlgProcW+0x22
    039bf1e8 7e418816 7e423d3a 00150202 00000111 USER32!InternalCallWinProc+0x28
    039bf250 7e42927b 0009e158 7e423d3a 00150202 USER32!UserCallWinProcCheckWow+0x150
    039bf28c 7e4292e3 005aa750 00566d80 00000001 USER32!SendMessageWorker+0x4a5
    039bf2ac 7e431cde 00150202 00000111 00000001 USER32!SendMessageW+0x7f
    039bf2dc 7e42763c 00150202 0057edc0 00170222 USER32!IsDialogMessageW+0x41f
    039bf318 7e4249c4 00150202 00170222 00000001 USER32!DialogBox2+0x144
    039bf340 7e424a06 7c9c0000 7cc26c50 00170222 USER32!InternalDialogBox+0xd0
    039bf360 7e4247ea 7c9c0000 7cc26c50 00170222 USER32!DialogBoxIndirectParamAorW+0x37
    039bf384 7ca4033c 7c9c0000 000003eb 00170222 USER32!DialogBoxParamW+0x3f
    039bf3cc 7ca402c8 7c9c0000 000003eb 00170222 SHELL32!SHFusionDialogBoxParam+0x3b
    039bf400 0102129f 00170222 00000000 039bf834 SHELL32!RunFileDlg+0xc4
    039bfa40 010210f3 00170222 00000000 01be80c0 Explorer!_RunFileDlg+0x12f
    039bfee0 77f69598 000003b8 01be71e0 77f6957b Explorer!CTray::_RunDlgThreadProc+0x29a
    039bfef8 7c927ac2 01be71e0 7c97e440 00160a70 SHLWAPI!ExecuteWorkItem+0x1d
    039bff40 7c927b03 77f6957b 01be71e0 0009f298 ntdll!RtlpWorkerCallout+0x70
    039bff60 7c927bc5 00000000 01be71e0 00160a70 ntdll!RtlpExecuteWorkerRequest+0x1a
    039bff74 7c927b9c 7c927ae9 00000000 01be71e0 ntdll!RtlpApcCallout+0x11
    039bffb4 7c80b729 00000000 0274ec60 0274ec60 ntdll!RtlpWorkerThread+0x87
    039bffec 00000000 7c910250 00000000 00000000 kernel32!BaseThreadStart+0x37
    it looks the same as in procmon

    lets check the arguments to the function

    since this is x86 32bit three arguments are shown in stack if we want more we need to play with esp register

    note: be aware in x64 the first three four args are passed in registers thanks for the comment by evlncrn8


    the first three args as per kb

    Code:
    ChildEBP RetAddr  Args to Child              
    039bebf4 7ca408e2  00139220 039bee20 00150202 SHELL32!AddMRUStringW
    what is the first argument

    0:017> dd poi(esp+4) l4
    00139220 00000002 0000001a 7c80aa36 00000828

    you should recognize the 0x1a

    0:017> .formats 1a
    Evaluate expression:
    Hex: 0000001a
    Decimal: 26 <--------------------

    0:017> du poi(esp+8)
    039bee20 "cmd\1" <------------- yes this is our input

    so since this is an argument check who pushed it

    ub return address in stack viz

    Code:
    0:017> ub 7ca408e2
    
    7ca408c2 68b4959c7c     	push    offset SHELL32!`string' (7c9c95b4)
    7ca408c7 8d8570fdffff    	lea     eax,[ebp-290h]
    7ca408cd 50              	push    eax
    7ca408ce ff15341c9c7c	call    dword ptr [SHELL32!_imp__StrCatBuffW (7c9c1c34)]
    7ca408d4 8d8570fdffff    	lea     eax,[ebp-290h]
    7ca408da 50            	push    eax
    7ca408db 56              	push    esi <-------------------
    7ca408dc ff1584b2a27c    call    dword ptr [SHELL32!_imp__AddMRUStringW (7ca2b284)]
    what is in esi

    0:017> r esi
    esi=00139220

    where did esi get that value

    ub retn_address length > default on trial and error till we locate esi
    or use ida
    or ollydbg register highlighting functionality


    we see esi got the value from the return value of a Function

    Code:
    0:017> ub 7ca408e2 l40 
    
    7ca408b2 e8b2faffff      call    SHELL32!OpenRunDlgMRU (7ca40369)
    7ca408b7 8bf0            mov     esi,eax <------------------------
    7ca408b9 3bf3            cmp     esi,ebx
    7ca408bb 742b            je      SHELL32!CRunDlg::OKPushed+0x1d4 (7ca408e8)
    7ca408bd 6806010000      push    106h
    7ca408c2 68b4959c7c      push    offset SHELL32!`string' (7c9c95b4)
    7ca408c7 8d8570fdffff    lea     eax,[ebp-290h]
    7ca408cd 50              push    eax
    7ca408ce ff15341c9c7c    call    dword ptr [SHELL32!_imp__StrCatBuffW (7c9c1c34)]
    7ca408d4 8d8570fdffff    lea     eax,[ebp-290h]
    7ca408da 50              push    eax
    7ca408db 56              push    esi
    7ca408dc ff1584b2a27c    call    dword ptr [SHELL32!_imp__AddMRUStringW (7ca2b284)]
    so we would need to check this function

    Code:
    0:016> uf SHELL32!OpenRunDlgMRU
    SHELL32!OpenRunDlgMRU+0x19:
    7ca4002f 2145fc          and     dword ptr
    ...

    Updated January 7th, 2013 at 00:56 by blabberer

    Categories
    Uncategorized
  11. ollydbg 2.x plugin OLLY_LKD

    a small sample plugin for ollydbg 2.01f using windbgs dbgeng functions especially
    local kernel debugging output

    the plugin is at alpha - Z stage and uses ollydbg version 2.01f plugin kit

    and is built by winddk (windows 7 wdk C:\WinDDK\7600.16385.1)

    there is a modification required to plugin.h as follows to
    avoid crashing due to stack unbalance

    (the same source compiled with vs 2010 and unmodified plugin.h
    works ok

    it seems the wdk compiler is behaving differently

    the modification to plugin.h is as follows (added a _cdecl so that stack is cleaned up properly)


    C:\ollydbg2beta\plug201ft\Visual C>fc plugin.h d:\Plugin_Template_For_ODBG_20001_WDK\plugin.h
    Comparing files plugin.h and D:\PLUGIN_TEMPLATE_FOR_ODBG_20001_WDK\PLUGIN.H
    ***** plugin.h

    typedef int MENUFUNC(struct t_table *,wchar_t *,ulong,int);

    ***** D:\PLUGIN_TEMPLATE_FOR_ODBG_20001_WDK\PLUGIN.H

    typedef int _cdecl MENUFUNC(struct t_table *,wchar_t *,ulong,int);

    *****
    C:\ollydbg2beta\plug201ft\Visual C>

    the source is gibberish on top of the template i posted
    earlier for vs2010 at the moment so i am not posting

    refer to kayakers blog about ollydb.lib


    a compiled binary is attached

    any comments/ feedback / sugestions / criticisms are welcome

    to use it
    copy plugin dll to 2.01f version of ollydbg.exe folder

    copy the following windbgs extensions / dlls (6.12 ) to the folder where ollydbg.exe resides

    uext , symsrv , ntsdexts , kext , kdexts , exts , ext , dbghelp , dbgeng


    click the menu

    a getstring dialog will be presented assuming your debugee is msgbox.exe

    if you type in "!process 0 0 msgbox.exe " without the quotes you will be presented with the
    following details


    Code:
    Log data
    Address   Message
              Connected to Windows XP 2600 x86 compatible target at (Thu Sep  6 05:58:23.578 2012 (UTC + 5:30)), ptr64 FALSE
              Symbol search path is:
              SRV*F:\symbols*http://msdl.microsoft.com/download/symbols
              Executable search path is:
              *******************************************************************************
              WARNING: Local kernel debugging requires booting with kernel
              debugging support (/debug or bcdedit -debug on) to work optimally.
              *******************************************************************************
              Windows XP Kernel
              Version 2600
               (Service Pack 3)
               UP
              Free x86 compatible
              Product:
              WinNt
              , suite:
               TerminalServer
               SingleUserTS
              Built by: 2600.xpsp_sp3_gdr.100216-1514
              Machine Name:
              Kernel base = 0x804d7000 PsLoadedModuleList = 0x80554040
              Debug session time: Thu Sep  6 05:58:23.656 2012 (UTC + 5:30)
              System Uptime: 0 days 17:45:57.225
              PROCESS 86ba98e0
                SessionId: 0  Cid: 0ce8    Peb: 7ffd8000  ParentCid: 0894
                  DirBase: 0f8c0420  ObjectTable: e2a8ea90  HandleCount:  14.
                  Image: msgbox.exe
                  VadRoot 85f24388 Vads 36 Clone 0 Private 104. Modified 0. Locked 0.
                  DeviceMap e30a2340
                  Token                             e172e040
                  ElapsedTime                       00:04:07.015
                  UserTime                          00:00:00.031
                  KernelTime                        00:00:00.000
                  QuotaPoolUsage[PagedPool]         26588
                  QuotaPoolUsage[NonPagedPool]      1440
                  Working Set Sizes (now,min,max)  (583, 50, 345) (2332KB, 200KB, 1380KB)
                  PeakWorkingSetSize                583
                  VirtualSize                       12 Mb
                  PeakVirtualSize                   13 Mb
                  PageFaultCount                    609
                  MemoryPriority                    BACKGROUND
                  BasePriority                      8
                  CommitCharge                      124
                  DebugPort                         85f25ec0
                  Setting context for this process...
    
                                                     
            THREAD 863f7b08  Cid 0ce8.063c  Teb: 7ffdf000 Win32Thread: e4262e10 WAIT: (Executive) KernelMode Non-Alertable
                          a8eb87d4  SynchronizationEvent
                      Not impersonating
                      DeviceMap                 e30a2340
                      Owning Process            0       Image:         <Unknown>
                      Attached Process          86ba98e0       Image:         msgbox.exe
                      Wait Start TickCount      4077495        Ticks: 15786 (0:00:04:06.656)
                      Context Switch Count      92                 LargeStack
                      UserTime                  00:00:00.015
                      KernelTime                00:00:00.000
              *** WARNING: Unable to verify checksum for C:\Documents and Settings\Admin\My Documents\ollydbg2beta\odbg201ft\msgbox.exe
              *** ERROR: Module load completed but symbols could not be loaded for C:\Documents and Settings\Admin\My Documents\ollydbg2beta\odbg201ft\msgbox.exe
                      Win32 Start Address msgbox (0x00401000)
                      Start Address kernel32!BaseProcessStartThunk (0x7c810705)
                      Stack Init a8eb9000 Current a8eb8758 Base a8eb9000 Limit a8eb5000 Call 0
                      Priority 10 BasePriority 8 PriorityDecrement 0 DecrementCount 0
                      ChildEBP RetAddr
                      a8eb8770 80500cf0 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
                      a8eb877c 804f9d72 nt!KiSwapThread+0x46 (FPO: [0,0,0])
                      a8eb87a4 80638fc4 nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])
                      a8eb8884 8063a099 nt!DbgkpQueueMessage+0x17c (FPO: [Non-Fpo])
                      a8eb88a8 8063a1cb nt!DbgkpSendApiMessage+0x45 (FPO: [Non-Fpo])
                      a8eb8934 804fcb42 nt!DbgkForwardException+0x8f (FPO: [Non-Fpo])
                      a8eb8cf4 8053e0a1 nt!KiDispatchException+0x1f4 (FPO: [Non-Fpo])
                      a8eb8d5c 8053e7b1 nt!CommonDispatchException+0x4d (FPO: [0,20,0])
                      a8eb8d5c 00401001 nt!KiTrap03+0xad (FPO: [0,0] TrapFrame @ a8eb8d64)
              WARNING: Stack unwind information not available. Following frames may be wrong.
                      0013fff0 00000000 msgbox+0x1001
  12. connect two virtual machines on one physical host and use wdeb386 to debug win98 app

    i started reversing and during my first few days i somehow installed softice 4.05 which never worked in windows 2000 then i got to know about ollydbg that was version 1.04 then and it has been my favourite since then

    but ollydbg is a ring 3 debugger and at times when you needed to know what is happening on the other side i felt handicapped

    i didnt want to use softice and windbg needed two machines which was not feasible

    then i used the Poor man's Kernel Debugger livekd from sysinternals

    then i got to know about microsoft virtual pc and i was quiet happy to use it for kernel debugging

    connected to the physical machine using NamedPipe

    if you notice my statements you will find all the software i used were freeware i never had to
    patch or use keygens or scour the net for warej


    but on and off i would be in a situation where my physical host being xp wasnt able to kernel debug some old app in an old os
    like windows 98

    in situations like this it was softice in say 98 vm which i disliked

    so on and off i was trying to connect two virtual machines and use windbg

    but i never succeded in connecting two virtual machine on a single physical host using
    microsoft virtual pc

    vmware was known to me but vmware was either 30 day trial or an endless scouring on bottomless net

    vmware in the meantime released thier player which was freeware but when i looked at it then
    it didnt have the ability to create a vm

    recently i needed to debug some win98 app and i started searching the net for any pointers

    while searching i got to know about vmware player 4.01 which is a freeware and which had the ability to create a vm

    my interest was thus aroused

    and i downloaded the vmware player 4.01 and installed it and started playing with it to create a guest os

    and there by i got to know that vmware has a convertor wherby i can use my old virtual hard disks made by microsoft virtual pc

    so i downloaded the vmware vcenter convertor and installed it

    fed it with a win98.vmc

    and it happily converted the .vmc into a .vmx file and .vhd file into a .vmkd file

    and it loaded perfectly well into vmware (vmware says supported guest os starts from NT )

    after some found newhardware restart routine (omg how many restarts win98 needs )

    i was able to play loderunner on this win98 )

    now moving on to the real purpose

    i fed the convertor another win98se.vmc and got it converted to vmkd and started this too

    i used old ms vpc vhds because i already had lots of craps installed inside them including RTERM98 and WDEB386
    while i fruitlessly tried to use them earlier

    now i had two vms running side by side on a single physical host

    one vm win98 was installed with win98se os and had windows98ddk installed on it

    i had edited the system.ini located in c:\windows

    and added the following in
    Code:
    [386en] section
    
    Device= c:\windows\wdeb98.exe
    DebugPort = 1
    DebugBaud = 115200
    DebugSym="full path to sym file" viz "c:\sym\krnl386.sym" "etc etc "
    "
    "
    "
    on the other vm i had a win98se os and in that i had RTERM98 open connected to comport 1

    on both vmware player i added a serial port
    asked vmware to use named pipe \\.\pipe\com_1 on both vms

    assigned one end as server and other end as virtual machine in first vm
    assigned one end as cilent and other end as virtual machine in second vm

    and restarted the first vm which had WDEB98 installed and kept the finger crossed

    but to my surprise rterm98 on the other vm sprang to life and started spouting up

    the time was well spent i can now set a int 3 in some .com file or LE or NE or VXD and stop in kernel debugger

    and all freeware at that

    i post below a few screen shots for clarity and some debug spew from rterm

    i opened up my fav iczelion tut 02 msgbox.exe plopped an int aka 0xcc at 0x401000
    double clciked it and got it trapped in wdeb386 see screen shot
    Attached Thumbnails Attached Images    
  13. Simple Dll Compiled From Commandline Unlike what google returns vc++ proj

    Sometimes Google in its infinite wisdom will never get you what you remember you saw earlier in the same Google come what may or use whatever search term you may imagine

    so i was searching for this simple dll tutorial which i vividly remember and i couldn't find it

    and hence this blog

    so you want to create a dll and you want to do it in command line
    not using start->program->vs->new->project->name->win32->console->crap>dll>bs->whatever->magic->finish->stdafx.h->pch->build f7->search the whole comp for dll

    ok here is how you do it

    make a new directory somewhere the dir i created is named NOFIXED

    add these files to the directory

    Code:
    NOFIXED:\>cd NOFIXED
    
    NOFIXED:\>dir /b
    AddNumbers.bat
    AddNumbers.c
    AddNumbers.def
    AddNumbers.h
    CallAddNum.c
    NOFIXED:\>
    AddNumbers.c is the source code for dll and it contains

    Code:
    NOFIXED:\>type AddNumbers.c
    #include <windows.h>
    #include "AddNumbers.h"
    
    
    BOOL WINAPI DllMain(
        HINSTANCE hinstDLL,
        DWORD fdwReason,
        LPVOID lpReserved ){
                    switch( fdwReason ){
                            case DLL_PROCESS_ATTACH:
                                    break;
                            case DLL_THREAD_ATTACH:
                                    break;
                            case DLL_THREAD_DETACH:
                                    break;
                            case DLL_PROCESS_DETACH:
                                    break;
                    }
                    return TRUE;
    }
    
    
    _declspec (dllexport) ULONG AddNumbers(ULONG a, ULONG b){
        return((ULONG)(a+b));
    }
    
    NOFIXED:\>
    AddNumbers.h is the Header File You Would Need To Link To The Dll when You Create An EXE and it contains

    Code:
    NOFIXED:\>type AddNumbers.h
    #include <windows.h>
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpReserved );
    _declspec (dllexport) ULONG  AddNumbers(ULONG a, ULONG b);
    
    NOFIXED:\>
    AddNumbers.def is the module definition File that is required to Build a Dll and it contains

    Code:
    NOFIXED:\>type AddNumbers.def
    EXPORTS
    AddNumbers
    NOFIXED:\>
    CallAddNum.c is the source code for the exe that links to the AddNumbers.dll that you are going to Build and Call the function in the dll and it contains

    Code:
    NOFIXED:\> type CallAddNum.c
    #include <stdio.h>
    #include "AddNumbers.h"
    
    int main (void){
    
            printf("3 + 5 = %x\n" , AddNumbers(3,5));
            return 0;
    }
    NOFIXED:\>
    and finally AddNumbers.Bat contains the command line to build the exe and dll

    and it contains the following commands
    cl is the compiler
    /nologo suppresses copyright message
    /c compiles only no linking
    /LD tells the compiler to create a dll and not an exe
    link is the linker
    /dll tells the linker to link the compiled obj code into a dll
    def:"AddNumbers.def" is the module def file which creates AddNumbers.Lib And AddNumbers.Exp which you use when you compile any exe to link to the dll

    Code:
    
    NOFIXED:\>type AddNumbers.bat
    cl  /nologo /c /LD AddNumbers.c
    link /NOLOGO /dll /def:"AddNumbers.def" AddNumbers.obj
    cl /nologo CallAddNum.c AddNumbers.lib
    NOFIXED:\>
    now open vs2008commandprompt

    start -> program -> microsoft visual c++ 2008 Express Edition -> visual studio tools -> visual studio 2008 command prompt

    navigate to the present NOFIXED Directory
    and run the AddNumbers.bat you should get you dll and exe compiled

    Code:
    NOFIXED:\>dir /b & AddNumbers.bat & dir /b
    AddNumbers.bat
    AddNumbers.c
    AddNumbers.def
    AddNumbers.h
    CallAddNum.c
    
    NOFIXED:\>cl  /nologo /c /LD AddNumbers.c
    AddNumbers.c
    
    NOFIXED:\>link /NOLOGO /dll /def:"AddNumbers.def" AddNumbers.obj
       Creating library AddNumbers.lib and object AddNumbers.exp
    
    NOFIXED:\>cl /nologo CallAddNum.c AddNumbers.lib
    
    CallAddNum.c
    AddNumbers.bat
    AddNumbers.c
    AddNumbers.def
    AddNumbers.dll
    AddNumbers.exp
    AddNumbers.h
    AddNumbers.lib
    AddNumbers.obj
    CallAddNum.c
    CallAddNum.exe
    CallAddNum.obj
    
    NOFIXED:\>
    run the exe to check if you have succeeded

    Code:
    NOFIXED:\>CallAddNum.exe
    3 + 5 = 8
    
    NOFIXED:\>
    that is all for now
  14. How To Add TypeInfo So That Dt Commands Work Properly In Windbg

    How To Add TypeInfo So That Dt Commands Work Properly In Windbg

    preface

    SomeTimes When You use Certain Dt Commands In windbg You Are Faced With The Type Information Not Available error

    like below

    Code:
    lkd> !ca 8657c600
    
    ControlArea  @ 8657c600
      Segment      00000010  Flink      00000010  Blink        85c4e7a0
      Section Ref         0  Pfn Ref           0  Mapped Views c4000001
      User Ref     31447341  WaitForDel 86c7969c  Flush Count       a08
      File Object  865a3818  ModWriteCount  c66c  System Views     8657
    
      Flags (1) BeingDeleted 
    
          No name for file
    
    Segment @ 00000010
    Type nt!_MAPPED_FILE_SEGMENT not found.
    if we google around we can find this above struct is unoffiicially documented in bits and pieces in several sites
    like Moonsols, msdn.mirt , nirsoft etc

    and most of these structures were pieced together from pdbs themselves

    like we can see this struct in ntkrnlmp.pdb

    Code:
    F:\SYMBOLS\ntkrnlmp.pdb\998A3472EEA6405CB8C089DE868F26222>grep -i MAPPED_FILE_SE
    GMENT  -b1 -U *.*
    Binary file ntkrnlmp.pdb matches
    
    F:\SYMBOLS\ntkrnlmp.pdb\998A3472EEA6405CB8C089DE868F26222>grep -i MAPPED_FILE_SE
    GMENT  -a1 -U *.*
    
    
    ♥ ↔  ♦ OwnerTable ≤≥: ♣☻  ☻↔         _CM_INTENT_LOCK U_CM_INTENT_LOCK@@ ≤≥
    ♫ ♥#   "     R ♣  ☻              _PROC_IDLE_STATE_ACCOUNTING U_PROC_IDLE_ST
    ♥ ↔   State F ♣♠  ☻↔          └☻_PROC_IDLE_ACCOUNTING U_PROC_IDLE_ACCOUNTIN
    ♥ ▬∟  $ ActiveTripPoint ≥B ♣HERMAL_INFORMATION U_THERMAL_INFORMATION@@ →☺♥↕
      ☻↔          L _THERMAL_INFORMATION U_THERMAL_INFORMATION@@ B ♣  ☻
         _MAPPED_FILE_SEGMENT U_MAPPED_FILE_SEGMENT@@ 6 ♣  ☻              _SEGMEN
    Code:
    
    _MAPPED_FILE_SEGMENT.U_MAPPED_FILE_SEGMENT@@.6....................
    _SEGMENT_FLAGS.U_SEGMENT_FLAGS@@........5.....ControlArea.....".....
    TotalNumberOfPtes..........SegmentFlags.....".....
    NumberOfCommittedPages.....#.....
    SizeOfSegment.....C.....
    ExtendInfo...........
    BasedAddress...........
    SegmentLock.B..................
     ._MAPPED_FILE_SEGMENT.U_MAPPED_FILE_SEGMENT@@.
    even though it is there windbg cant find it because this struct is probably not referanced

    anyway back to topic

    i had posted a while back how to put the typeinfo back into the respective pdb using wdk

    in this post


    that method is for putting the type info back to respective pdb

    but some times you dont have a pdb to put back

    in situations like this you can use the following approach


    suppose

    you are on winxp and you are debugging via kd a win 7 vm

    you think the code you are looking at is similar to fastfat in winddk srcs

    an you want the type info for

    PACKED_BOOT_SECTOR

    in that case


    just compile the following code lets say helloworld.c

    Code:
    #include	<ntddk.h>
    
    DRIVER_INITIALIZE				DriverEntry;
    DRIVER_UNLOAD					DriverUnload;
    
    
    void 
    DriverUnload(
    			 PDRIVER_OBJECT DriverObject
    			 )
    			 {
    				 DbgPrint("Driver unloading\n");
    }
    
    
    
    NTSTATUS 
    DriverEntry(
    			__in PDRIVER_OBJECT DriverObject,
    			__in PUNICODE_STRING RegistryPath
    			)
    			{
    				DriverObject->DriverUnload = DriverUnload;
    				DbgPrint("Hello World!\n");
    				return STATUS_SUCCESS;
    }
    this is code for a simple driver that you can load with osr loader and operate with either osrloader or net start / stop "servicename"

    the sources file contains

    Code:
    TARGETNAME=helloworld
    TARGETTYPE=DRIVER
    TARGETPATH=obj
    
    INCLUDES=..\..\inc
    
    SOURCES = HelloWorld.c

    the make file conatins

    Code:
    C:\WinDDK\7600.16385.1\src\HelloWorld>type makefile
    !INCLUDE $(NTMAKEENV)\makefile.def
    C:\WinDDK\7600.16385.1\src\HelloWorld>

    build this with win 7 fre build environemt

    Code:
    C:\WINDOWS\system32\cmd.exe /k C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ fre x86 WIN7
    cd %COMPILEDIR% 
    build
    copy the driver to win7 vm use osrloader to register the sevice and start the service

    if you used auto the driver will load during boot stage and you can simply see the dbg print while booting

    if you enable DEBUG PRINT FILTER mask in kd

    like below

    kd> ed nt!Kd_DEFAULT_Mask 0xf

    Hello World!

    now we want to add type info for

    PACKED_BOOT_SECTOR

    which does not exist in any pdbs

    kd> dt *!*boot*
    ntkrnlmp!_ARBITER_BOOT_ALLOCATION_PARAMETERS
    ntkrnlmp!_TPM_BOOT_ENTROPY_LDR_RESULT
    ntkrnlmp!_TPM_BOOT_ENTROPY_RESULT_CODE
    pci!_ARBITER_BOOT_ALLOCATION_PARAMETERS



    change the earlier code to fatexam.c with the following addition

    Code:
    #include	<ntddk.h>
    #include	"fat.h"   \\<------------ C:\WinDDK\7600.16385.1\src\filesys\fastfat\Win7
    
    PACKED_BOOT_SECTOR				packboot;  \\ <---------------------- declaration 
    DRIVER_INITIALIZE				DriverEntry;
    DRIVER_UNLOAD					DriverUnload;
    
    
    void 
    DriverUnload(
    			 PDRIVER_OBJECT DriverObject
    			 )
    			 {
    				 DbgPrint("Driver unloading\n");
    }
    
    
    
    NTSTATUS 
    DriverEntry(
    			__in PDRIVER_OBJECT DriverObject,
    			__in PUNICODE_STRING RegistryPath
    			)
    			{
    				DriverObject->DriverUnload = DriverUnload;
    				DbgPrint("Hello World!\n called from fatexam.sys\n "); 
    				DbgPrint("Testing To See If .Kdfiles Work Dynamically!\n");
    				DbgPrint("use dt fatexam!* to look for typeinfo you just added\n");
    				return STATUS_SUCCESS;
    }
    change the sources file to reflect names and build it

    now about how to transfer the newly built sys to vm via debugger

    we can use the debuggers .kdfiles command

    .kdfiles is a command (Driver Replacement Map) which will replace an existing driver in the target computer being debugged with a
    new one from host computer that is running Windbg

    to use .kdfiles

    make a foo.txt file (may be foo.ini or blah.yuk or whatever.crap file) in any directory

    in that file add the following contents
    Code:
    C:\WinDDK\7600.16385.1\src>type kdfiles.ini
    
    map
    \??\C:\Windows\System32\drivers\fatexam.sys
    C:\WinDDK\7600.16385.1\src\HelloWorld\fatexam\objfre_win7_x86\i386\fatexam.sys

    if it didnt work first time you may have to change \??\ to just c:\Windows\system32 or maybe %systemroot%\system32

    use ctrl+alt+d to view the debug spew to find the error


    go to windbg command window and type

    .kdfiles C:\WinDDK\7600.16385.1\src\kdfiles.ini (use the directory and filename you chose not what i typed here)


    windbg should say
    Code:
    kd> .kdfiles C:\WinDDK\7600.16385.1\src\kdfiles.ini
    KD file assocations loaded from 'C:\WinDDK\7600.16385.1\src\kdfiles.ini'
    
    
    if you run the .kdfiles without any argument you should see something similar to this
    
    kd> .kdfiles
    KD file assocations loaded from 'C:\WinDDK\7600.16385.1\src\kdfiles.ini'
    \??\C:\Windows\System32\drivers\fatexam.sys -> C:\WinDDK\7600.16385.1\src\HelloWorld\fatexam\objfre_win7_x86\i386\fatexam.sys
    and thats all

    now if you go to vm and use net start service name
    before the driver is accessed it will be replace by the new one and your type info should be available



    like below

    Code:
     Driver unloading
    KD: Accessing 'C:\WinDDK\7600.16385.1\src\HelloWorld\fatexam\objfre_win7_x86\i386\fatexam.sys' (\??\C:\Windows\System32\drivers\fatexam.sys)
      File size 4KKdPullRemoteFile(83DE4A70): About to overwrite \??\C:\Windows\System32\drivers\fatexam.sys and preallocate to e00
    KdPullRemoteFile(83DE4A70): Return from ZwCreateFile with status 0
    .
    Hello World!
     called from helloworld.sys
     Testing To See If .Kdfiles Work Dynamically!
    use dt fatexam!* to look for typeinfo you just added

    the results of the ealier command now shows added info

    Code:
    kd> dt *!*boot*
              ntkrnlmp!_ARBITER_BOOT_ALLOCATION_PARAMETERS
              ntkrnlmp!_TPM_BOOT_ENTROPY_LDR_RESULT
              ntkrnlmp!_TPM_BOOT_ENTROPY_RESULT_CODE
              pci!_ARBITER_BOOT_ALLOCATION_PARAMETERS
    ...
  15. gee mail patented algorithm

    i was reading the mails from older to newer
    and here is what happens when i finish off mail no 96-51
    51- 50 of 50 hurrah
    Categories
    Uncategorized
    Attached Thumbnails Attached Images