首页
社区
课程
招聘
[原创]64位驱动的asm与c混合编译
发表于: 2013-6-5 21:24 16910

[原创]64位驱动的asm与c混合编译

2013-6-5 21:24
16910
前言:
2013年是vs2012+wdk8.0的时代.
这是去年的实验品,实验环境是:WinDDK\7600.16385.1

还好vs2012+wdk8.0有一键转换的功能,但是要编译vista以前的驱动有点麻烦.

废话不多,进入正题:

首先看汇编文件:
摘自:http://uninformed.org/index.cgi?v=3&a=3&p=17

.data

EXTERN OrigKeBugCheckExRestorePointer:PROC
EXTERN KeBugCheckExHookPointer:PROC

.code

;
; Points the stack pointer at the supplied argument and returns to the caller.
;
public AdjustStackCallPointer
AdjustStackCallPointer PROC
    mov rsp, rcx
    xchg r8, rcx
    jmp rdx
AdjustStackCallPointer ENDP

;
; Wraps the overwritten preamble of KeBugCheckEx.
;
public OrigKeBugCheckEx
OrigKeBugCheckEx PROC
    mov [rsp+8h], rcx
    mov [rsp+10h], rdx
    mov [rsp+18h], r8
    lea rax, [OrigKeBugCheckExRestorePointer]
    jmp qword ptr [rax]
OrigKeBugCheckEx ENDP

END

关于64位汇编的驱动环境的搭建就不说了,这不是本主题。

编译命令:
ml64 lib.asm
link /lib lib.obj

上面可能有一些警告(我用ida64打开一看少了一个函数),我忽略了。

c文件如下:
摘自:http://uninformed.org/index.cgi?v=3&a=3&p=17

#include <ntddk.h>
#include <ntifs.h>
#include <wdm.h>

DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{

}

// Both of these routines reference the assembly code described above
extern VOID OrigKeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR

BugCheckParameter4);
extern VOID AdjustStackCallPointer(IN ULONG_PTR NewStackPointer, IN PVOID StartAddress, IN PVOID Argument);

// mov eax, ptr
// jmp eax
static CHAR HookStub[] = "\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xe0";

// The offset into the ETHREAD structure that holds the start routine.
static ULONG ThreadStartRoutineOffset = 0;

// The pointer into KeBugCheckEx after what has been overwritten by the hook.
PVOID OrigKeBugCheckExRestorePointer;

VOID KeBugCheckExHook(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
{
    PUCHAR LockedAddress;
    PCHAR  ReturnAddress;
    PMDL   Mdl = NULL;

    // Call the real KeBugCheckEx if this isn't the bug check code we're looking for.
    if (BugCheckCode != 0x109)
    {
        //DebugPrint(("Passing through bug check %.4x to %p.", BugCheckCode, OrigKeBugCheckEx));
        OrigKeBugCheckEx(BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4);
    }
    else
    {
        PCHAR CurrentThread = (PCHAR)PsGetCurrentThread();
        PVOID StartRoutine  = *(PVOID **)(CurrentThread + ThreadStartRoutineOffset);
        PVOID StackPointer  = IoGetInitialStack();

        //DebugPrint(("Restarting the current worker thread %p at %p (SP=%p, off=%lu).", PsGetCurrentThread(), StartRoutine, StackPointer, ThreadStartRoutineOffset));
        DbgPrint("拦截了0x109号蓝屏\n");
        DbgPrint("Restarting the current worker thread %p at %p (SP=%p, off=%lu).\n", PsGetCurrentThread(), StartRoutine, StackPointer, ThreadStartRoutineOffset);

        // Shift the stack pointer back to its initial value and call the routine.  
        //We subtract eight to ensure that the stack is aligned properly as thread entry point routines would expect.
        AdjustStackCallPointer((ULONG_PTR)StackPointer - 0x8, StartRoutine, NULL);
    }

    // In either case, we should never get here.
    __debugbreak();
}

VOID DisablePatchProtectionSystemThreadRoutine(IN PVOID Nothing)
{
    UNICODE_STRING SymbolName;
    NTSTATUS       Status = STATUS_SUCCESS;
    PUCHAR         LockedAddress;
    PUCHAR         CurrentThread = (PUCHAR)PsGetCurrentThread();
    PCHAR          KeBugCheckExSymbol;
    PMDL           Mdl = NULL;

    RtlInitUnicodeString(&SymbolName, L"KeBugCheckEx");

    do
    {
        // Find the thread's start routine offset.
        for (ThreadStartRoutineOffset = 0; ThreadStartRoutineOffset < 0x1000; ThreadStartRoutineOffset += 4)
        {
                    //DisablePatchProtection2SystemThreadRoutine
            if (*(PVOID **)(CurrentThread + ThreadStartRoutineOffset) == (PVOID)DisablePatchProtectionSystemThreadRoutine) {
                break;
                        }
        }

        //DebugPrint(("Thread start routine offset is 0x%.4x.", ThreadStartRoutineOffset));

        // If we failed to find the start routine offset for some strange reason, then return not supported.
        if (ThreadStartRoutineOffset >= 0x1000)
        {
            Status = STATUS_NOT_SUPPORTED;
            break;
        }

        // Get the address of KeBugCheckEx.
        if (!(KeBugCheckExSymbol = MmGetSystemRoutineAddress(&SymbolName)))
        {
            Status = STATUS_PROCEDURE_NOT_FOUND;
            break;
        }

        // Calculate the restoration pointer.
        OrigKeBugCheckExRestorePointer = (PVOID)(KeBugCheckExSymbol + 0xf);

        // Create an initialize the MDL.
        if (!(Mdl = MmCreateMdl(NULL, (PVOID)KeBugCheckExSymbol, 0xf)))
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        MmBuildMdlForNonPagedPool(Mdl);

        // Probe & Lock.
        if (!(LockedAddress = (PUCHAR)MmMapLockedPages(Mdl, KernelMode)))
        {
            IoFreeMdl(Mdl);
            Status = STATUS_ACCESS_VIOLATION;
            break;
        }

        // Set the aboslute address to our hook.
        *(PULONG64)(HookStub + 0x2) = (ULONG64)KeBugCheckExHook;

        //DebugPrint(("Copying hook stub to %p from %p (Symbol %p).", LockedAddress, HookStub, KeBugCheckExSymbol));

        // Copy the relative jmp into the hook routine.
        RtlCopyMemory(LockedAddress, HookStub, 0xf);

        // Cleanup the MDL.
        MmUnmapLockedPages(LockedAddress, Mdl);

        IoFreeMdl(Mdl);
    } while (0);
   
    KeBugCheckEx(0x109,0,0,0,0);//测试专用。
}

// A pointer to KeBugCheckExHook
PVOID KeBugCheckExHookPointer = KeBugCheckExHook;

NTSTATUS DisablePatchProtection()
{
    OBJECT_ATTRIBUTES Attributes;
    NTSTATUS          Status;
    HANDLE            ThreadHandle = NULL;

    InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

    // Create the system worker thread so that we can automatically find the offset inside the ETHREAD structure to the thread's start routine.
    Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &Attributes, NULL, NULL, DisablePatchProtectionSystemThreadRoutine, NULL);

    if (ThreadHandle)
        ZwClose(ThreadHandle);

    return Status;
}

//自己添加的.
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT  * DriverObject, __in PUNICODE_STRING  RegistryPath)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    //KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
    DriverObject->DriverUnload = Unload;
   
    DisablePatchProtection();
   
    return 0;
}

关键是在source文件里面加入一行:
TARGETLIBS=lib.lib  估计obj文件也行.
那个文件也要复制到相应的位置。与源文件在一个目录里面。

打开64位的编译环境,键入bld
enter!
ok!
你看效果吧。

其实还有更简单的:

第一个办法:
在source文件中直接加入:
AMD64_SOURCES = amd64\asm.asm   #这是64位的,32位的可以改为I386_SOURCES
但是SOURCES里面就不要再加入asm.asm了。

第二个办法:
工程目录下新建一个名为amd64的文件夹,里面放置汇编文件,
然后再source里面直接添加汇编文件即可。

注意:
如果出现下面的情况:
1>d:\winddk\work\c\amd64\asm.asm(1) : error A2039:line too long
1>d:\winddk\work\c\amd64\asm.asm(1) : error A2088:END directive required at end of file
google一下说是某个版本的ml.exe问题,可能后来改进了。解决办法是:
用系统自带的记事本打开文件,一看源代码只有一行。注释:用别的编辑工具都是好好的。
解决办法:在记事本里面手工格式化代码就ok!

made by correy
made at 2013.02.18
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com

不当之处,敬请指出.

[课程]Android-CTF解题方法汇总!

收藏
免费 5
支持
分享
最新回复 (6)
雪    币: 203
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
izc
2
沙发出售~
2013-6-6 08:52
0
雪    币: 110
活跃值: (522)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
看不懂。
2013-6-6 11:37
0
雪    币: 81
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark  学习了
2013-6-6 17:36
0
雪    币: 328
活跃值: (154)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
5
老爷机(待更新),表示跑不动,VS2012……果断围观
2013-6-7 08:52
0
雪    币: 89
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
羡慕嫉妒恨啊 !我还停留在在vs2008
2013-6-7 19:50
0
雪    币: 59
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼主,这是C还是C++啊?
2013-6-11 18:48
0
游客
登录 | 注册 方可回帖
返回
//