2013年4月24日星期三

KeRegisterBugCheckReasonCallback.C

/*
文本就命名为:KeRegisterBugCheckReasonCallback.C吧!
made by correy
made at 2013.04.24
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
#define _In_
#define _Inout_
KBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord; //The structure must be in resident memory, such as nonpaged pool.
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    BOOLEAN b = 0;
    b = KeDeregisterBugCheckReasonCallback(&CallbackRecord);
    if (b == 0)
    {
        DbgPrint("the specified callback is not registered.\n");
    }
}
KBUGCHECK_REASON_CALLBACK_ROUTINE BugCheckSecondaryDumpDataCallback;
VOID BugCheckSecondaryDumpDataCallback(_In_     KBUGCHECK_CALLBACK_REASON Reason,
                                       _In_     struct _KBUGCHECK_REASON_CALLBACK_RECORD *Record,
                                       _Inout_  PVOID ReasonSpecificData,
                                       _In_     ULONG ReasonSpecificDataLength)
{
    //此时正在初始化磁盘,准备生成dump,但是还没有开始。
    //ReasonSpecificDataLength == 0x30
    //Reason == 2 (KbCallbackSecondaryDumpData) 即 KeRegisterBugCheckReasonCallback的第二个参数。
    //Record->Component = "correy" 即 KeRegisterBugCheckReasonCallback的最后一个参数。
    //等等,不说了。
    DbgPrint("发生蓝屏了,停下来看看吧!\n");
    KdBreakPoint();//总是停止在这里,上面下断点也停不了,难道是因为蓝屏了?
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    BOOLEAN b = 0;
    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
    DriverObject->DriverUnload = Unload;    
    KeInitializeCallbackRecord(&CallbackRecord);
    //这一这个函数可以注册3种类型的,还有KbCallbackDumpIo和KbCallbackAddPages(server 2008及以后使用)。
    b = KeRegisterBugCheckReasonCallback(&CallbackRecord, BugCheckSecondaryDumpDataCallback, KbCallbackSecondaryDumpData, "correy");
    if (b == 0)
    {
        DbgPrint("KeRegisterBugCheckReasonCallback fail!\n");   
    }
    return 0;//STATUS_SUCCESS
}

KeRegisterBugCheckCallback.C

/*
文本就命名为:KeRegisterBugCheckCallback.C吧!
made by correy
made at 2013.04.24
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
//#include <ntifs.h> 
#define _In_
KBUGCHECK_CALLBACK_RECORD CallbackRecord; //The structure must be in resident memory, such as nonpaged pool.
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
    BOOLEAN b = 0;
    //蓝屏了是不会运行到这里的,不蓝品会运行到这里。
    //Drivers can use the KeDeregisterBugCheckCallback routine to remove the callback.
    //Any driver that can be unloaded must remove all of its callbacks in its Unload routine.
    b = KeDeregisterBugCheckCallback(&CallbackRecord);
    if (b == 0)
    {
        DbgPrint("the specified callback is not registered.\n");
    }
}
KBUGCHECK_CALLBACK_ROUTINE BugCheckCallback;
VOID BugCheckCallback(_In_  PVOID Buffer, _In_  ULONG Length)
{
    //The BugCheckCallback routine is executed when the system issues a bug check. A driver can use the routine to reset the device to a known state.
    //没有工具生成蓝屏,可以输入在调试状态的调试器中输入.crash命令。
    //此时已经physical memory dump complete了。这是实验所得。不过这里也能做一些事。
    /*
    http://msdn.microsoft.com/en-us/library/windows/hardware/ff566401(v=vs.85).aspx
   
    On all NT-based operating systems, drivers can use the KeRegisterBugCheckCallback routine to register a BugCheckCallback routine,
    and KeDeregisterBugCheckCallback to remove the routine. Drivers can use a BugCheckCallback routine to reset their device to a known state.
    //上面这句话的作用是:通知自己的驱动发生蓝屏了,自己可以做一些事情。
   
    Prior to Windows XP Service Pack 1 (SP1) and Windows Server 2003, drivers could also use BugCheckCallback to store data in the crash dump file:
    the system called each BugCheckCallback routine before writing the crash dump file,
    so any data written to the buffer that was passed to BugCheckCallback was stored in the crash dump file.
    //发生蓝屏了,在生成dump文件之前调用回调?然后在dump文件中写入自己的信息?不过这是xp-sp1和2003的以前的版本。
   
    //XP SP1 and 2003 以后的系统:要想在dump文件中写入自己的信息的办法。
    In Windows XP SP1 and Windows Server 2003 and later, the system calls BugCheckCallback after the crash dump file is written.
    Instead,the system supports two additional types of bug check callback routines.
    A BugCheckSecondaryDumpDataCallback routine can be used to write secondary data to the crash dump file.
    A BugCheckDumpIoCallback routine can be used to copy the crash dump file to a device.   
   
    //2008之后的系统的做法:
    In Windows Server 2008 and later versions of Windows,
    a driver can implement a BugCheckAddPagesCallback routine to add pages of driver-specific data to the crash dump file.
    Unlike a BugCheckSecondaryDumpDataCallback routine, which appends data to the secondary crash dump region,
    a BugCheckAddPagesCallback routine adds pages of data to the primary crash dump region. During debugging,
    primary crash dump data is easier to access than secondary crash dump data.
    使用的注意事项:
    A bug check callback routine executes at IRQL = HIGH_LEVEL, which imposes strong restrictions on what it can do.
    A bug check callback routine cannot:
    Allocate memory
    Access pageable memory
    Use any synchronization mechanisms
    Call any routine that must execute at IRQL = DISPATCH_LEVEL or below
    Bug check callback routines are guaranteed to run without interruption, so no synchronization is required.
    (If the bug check routine does use any synchronization mechanisms, the system will deadlock.)
   
    A driver's bug check callback routine can safely use the READ_PORT_XXX, READ_REGISTER_XXX, WRITE_PORT_XXX,
    and WRITE_REGISTER_XXX routines to communicate with the driver's device.
    */
    DbgPrint("发生蓝屏了!\n");   
    KdBreakPoint();
    //此时Length的值大概等于0x40.
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    BOOLEAN b = 0;
    KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
    DriverObject->DriverUnload = Unload;    
    KeInitializeCallbackRecord(&CallbackRecord);
    //关于最后一个参数的说明:
    //The Component string is used to identify the driver during crash-dump debugging.
    //To display the crash dump data corresponding to any specified Component string, you can use the !bugdump debugger extension.
    //It is also possible to debug the bug check callback routine itself
    b = KeRegisterBugCheckCallback(&CallbackRecord, BugCheckCallback, &CallbackRecord, sizeof(KBUGCHECK_CALLBACK_RECORD), "correy");
    if (b == 0)
    {
        DbgPrint("KeRegisterBugCheckCallback fail!\n");   
    }
    return 0;//STATUS_SUCCESS
}
/*
更多信息:
KeRegisterBugCheckReasonCallback
KeDeregisterBugCheckReasonCallback
http://msdn.microsoft.com/en-us/library/windows/hardware/ff540677(v=vs.85).aspx
KBUGCHECK_REASON_CALLBACK_ROUTINE BugCheckDumpIoCallback;
VOID BugCheckDumpIoCallback(
                            _In_     KBUGCHECK_CALLBACK_REASON Reason,
                            _In_     struct _KBUGCHECK_REASON_CALLBACK_RECORD *Record,
                            _Inout_  PVOID ReasonSpecificData,
                            _In_     ULONG ReasonSpecificDataLength
                            )
{
}

http://msdn.microsoft.com/en-us/library/windows/hardware/ff540679(v=vs.85).aspx
KBUGCHECK_REASON_CALLBACK_ROUTINE BugCheckSecondaryDumpDataCallback;
VOID BugCheckSecondaryDumpDataCallback(
                                       _In_     KBUGCHECK_CALLBACK_REASON Reason,
                                       _In_     struct _KBUGCHECK_REASON_CALLBACK_RECORD *Record,
                                       _Inout_  PVOID ReasonSpecificData,
                                       _In_     ULONG ReasonSpecificDataLength
                                       )
{
}

http://msdn.microsoft.com/en-us/library/windows/hardware/ff540669(v=vs.85).aspx
KBUGCHECK_REASON_CALLBACK_ROUTINE BugCheckAddPagesCallback;
VOID BugCheckAddPagesCallback(
                              _In_     KBUGCHECK_CALLBACK_REASON Reason,
                              _In_     struct _KBUGCHECK_REASON_CALLBACK_RECORD *Record,
                              _Inout_  PVOID ReasonSpecificData,
                              _In_     ULONG ReasonSpecificDataLength
                              )
{
}
*/

2013年4月19日星期五

CreateProcessWithLogonW.cpp

/*
本文摘自:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682431(v=vs.85).aspx
略有修改。

命令行的配置如下:
correy 123456 notepad.exe
*/

#include <windows.h>
#include <stdio.h>
#include <userenv.h>

#pragma comment (lib,"Userenv.lib")

void DisplayError(LPWSTR pszAPI)
{
    LPVOID lpvMessageBuffer;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpvMessageBuffer, 0, NULL);

    //... now display this string
    wprintf(L"ERROR: API        = %s.\n", pszAPI);
    wprintf(L"       error code = %d.\n", GetLastError());
    wprintf(L"       message    = %s.\n", (LPWSTR)lpvMessageBuffer);

    // Free the buffer allocated by the system
    LocalFree(lpvMessageBuffer);
    ExitProcess(GetLastError());
}

void wmain(int argc, WCHAR *argv[])
{
    DWORD     dwSize;
    HANDLE    hToken;
    LPVOID    lpvEnv;
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = L"";

    si.cb = sizeof(STARTUPINFO);

    if (argc != 4) {
        wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
        wprintf(L"\n\n");
        return;
    }

    // TO DO: change NULL to '.' to use local account database
    if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken))
        DisplayError(L"LogonUser");

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        DisplayError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        DisplayError(L"GetUserProfileDirectory");

    // TO DO: change NULL to '.' to use local account database
    if (!CreateProcessWithLogonW(argv[1], NULL, argv[2], LOGON_WITH_PROFILE, NULL, argv[3], CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, &si, &pi))
        DisplayError(L"CreateProcessWithLogonW");

    if (!DestroyEnvironmentBlock(lpvEnv))
        DisplayError(L"DestroyEnvironmentBlock");

    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}