欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]新手对07年某强删工具sys的逆向学习

[原创]新手对07年某强删工具sys的逆向学习

新手对07年某强删工具sys的逆向学习
[前置说明] 纯新手的动手过程,事无巨细,大牛飘过
[使用工具] IDA,WinDbg,wsyscheck
[系统环境] windows xp sp3
打开该程序后,用wsyscheck观察驱动模块,发现它平时并不加载驱动。于是自己写一个hook_NtLoadDriver的sys,发
现只有点击程序界面的“删除文件”后,才会加载驱动,并且删除完成后会删掉该驱动。于是在hook_NtLoadDriver里
加入copyfile,顺利复制到该驱动。附件中包含hook_NtLoadDriver,早期代码,没有考虑hook时多核安全性。
将该sys拖入IDA,到入口点,

观察到以下字样,
INIT:0001268A                 mov     eax, dword_12604
INIT:0001268F                 test    eax, eax
INIT:00012691                 mov     ecx, 0BB40h
......
INIT:0001269C                 mov     edx, ds:KeTickCount
INIT:000126A2                 mov     eax, offset dword_12604
此段可google "/gs Cookie" 得到一些解释,推荐阅读:
http://advdbg.org/blogs/advdbg_system/articles/432.aspx
该驱动主要功能如下:首先是对FSD的hook的处理,
一、RemoveAttachedDevice:
void __stdcall RemoveAttachedDevice(PCWSTR pwStr)    // L"\\FileSystem\\Ntfs" & L"\\FileSystem\\Fastfat"
{
    UNICODE_STRING DestinationString;
    PDRIVER_OBJECT pDrvObj;
    RtlInitUnicodeString(&DestinationString, pwStr);
    if (ObReferenceObjectByName(&DestinationString,
        OBJ_CASE_INSENSITIVE,
        0,
        0,
        *IoDriverObjectType,
        KernelMode,
        0,
        &pDrvObj))
    {
        return;
    }
    if (pDrvObj)
    {
        PDEVICE_OBJECT pDevObj = NULL;
        KIRQL Irql;
        Irql = KfAcquireSpinLock(&SpinLock);
        __asm
        {
            mov eax, cr0
                and eax, not 10000h
                mov cr0, eax
                cli
        }
        for ( pDevObj = pDrvObj->DeviceObject; pDevObj; pDevObj = pDevObj->NextDevice )
            pDevObj->AttachedDevice = NULL;
        ObfDereferenceObject(pDrvObj);
        __asm
        {
            sti
                mov eax, cr0
                or eax, 10000h
                mov cr0, eax
        }
        KfReleaseSpinLock(&SpinLock, Irql);
    }
}
注意IDA5.5附带的Hex-Rays Decompiler plugin,貌似是1.1版,会忽略cli与sti指令。
二、RestoreFSDDispatchRoutine
分别获取当前内存中FSD的DispatchRoutine地址,和根据实际文件中(Fastfat.sys & Ntfs.sys)计算得到的DispatchRoutine,比较之,不同则恢复。
其中,从文件中获取DispatchRoutine的方法是,先根据PE结构查到进入点,然后匹配opcode来查找DispatchRoutine地址,就是所谓的硬编码。
PE结构参考“新手入门文章 by 野男孩.CHM”,还有从网上找的一张PE图,附件提供该图。
弄清PE相关偏移时有用的windbg命令:
1. dt STRUCT (显示某结构)
   dt STRUCT -r
   dt STRUCT -r1(或-r2 -r3。。。)
2. ??sizeof(STRUCT) (计算某结构大小)
opcode参考“http://www.luocong.com/learningopcode/index.htm”,
比如:        if ( *((UCHAR *)pBuf + x) == 0xC7    // opcode C7 mov
            &&  *((UCHAR *)pBuf + x + 2) == v36 
            &&  *((UCHAR *)pBuf + x + 7) == 0xC7
            && (*((UCHAR *)pBuf + x + 1) == 0x46 || *((UCHAR *)pBuf + x + 1) == 0x43)
            )
上面参考资料的教程不全,看完后仍然没有解释C7是什么,那这里自己来找。其实在IDA里面双击这个驱动的DriverEntry,切到IDA View窗口,点击设置分发函数的那些mov,然后切到Hex View窗口,可见有的mov是B8,有的mov是89,有的mov是C7,肉眼观测C7的mov指令长度为7字节,后4字节是一个32位地址,也就是说C7是把一个32位立即数弄到XXX里去的mov指令,那个上面的代码里pBuf + x + 7就是下一条指令了,它也是个mov。
HANDLE __stdcall ItsOpenFile(PCWSTR SourceString, ACCESS_MASK DesiredAccess, ULONG ShareAccess)    // done!
{
    NTSTATUS status;
    //
    UNICODE_STRING    DestinationString;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE            FileHandle;
    IO_STATUS_BLOCK   IoStatusBlock;
    if ( KeGetCurrentIrql() )
        return 0;
    RtlInitUnicodeString(&DestinationString, SourceString);
    ObjectAttributes.RootDirectory = 0;
    ObjectAttributes.SecurityDescriptor = 0;
    ObjectAttributes.SecurityQualityOfService = 0;
    ObjectAttributes.Length = 24;
    ObjectAttributes.Attributes = 576;
    ObjectAttributes.ObjectName = &DestinationString;
    status = IoCreateFile(
        &FileHandle,
        DesiredAccess,
        &ObjectAttributes,
        &IoStatusBlock,
        0,
        0x80u,
        ShareAccess,
        1u,
        0,
        0,
        0,
        0,
        0,
        0x100u);
    if ( status )
    {
        return 0;
    }
    return FileHandle;
}
PULONG __stdcall SetFileAttributeNormal(HANDLE handle)      // done!
{
    NTSTATUS status;
    //
    PFILE_OBJECT    pFileObject;
    PDEVICE_OBJECT  pDevObj;
    IO_STATUS_BLOCK IoStatusBlock = {0};
    FILE_BASIC_INFORMATION  FileInformation = {0};
    KEVENT Event;
    PIRP   pIrp;
    PIO_STACK_LOCATION pIrpSp;
    status = ObReferenceObjectByHandle(
        handle,
        DELETE,
        *IoFileObjectType,
        0,
        (PVOID*)&pFileObject,
        0);
    if ( status )
    {
        return 0;
    }
    pDevObj = IoGetRelatedDeviceObject(pFileObject);
    pIrp = IoAllocateIrp(pDevObj->StackSize, TRUE);
    if ( pIrp )
    {
        KeInitializeEvent(&Event, SynchronizationEvent, 0);
        pIrp->AssociatedIrp.SystemBuffer = &FileInformation;
        pIrp->UserEvent = &Event;
        pIrp->UserIosb  = &IoStatusBlock;
        pIrp->Tail.Overlay.OriginalFileObject = pFileObject;
        pIrp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
        pIrp->RequestorMode = 0;
        FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
        pIrpSp = ((char *)pIrp->Tail.Overlay.CurrentStackLocation - 36);
        pIrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
        pIrpSp->DeviceObject = pDevObj;
        pIrpSp->FileObject = pFileObject;
        pIrpSp->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION);
        pIrpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
        pIrpSp->Parameters.SetFile.FileObject = pFileObject;
        pIrpSp->CompletionRoutine = SetFileAttributeCompletion;
        pIrpSp->Context = 0;
        pIrpSp->Control = 0xE0;
        IofCallDriver(pDevObj, pIrp);
        KeWaitForSingleObject(&Event, 0, 0, 1u, 0);
    }
    ObfDereferenceObject(pFileObject);
    return IoStatusBlock.Status;
}
PULONG __stdcall SetFileAttributeDelete(HANDLE handle)      // done!
{
    PFILE_OBJECT    pFileObject;
    PDEVICE_OBJECT  pDevObj;
    IO_STATUS_BLOCK IoStatusBlock = {0};
    FILE_DISPOSITION_INFORMATION FileInformation;
    PIRP   pIrp;
    KEVENT Event;
    PIO_STACK_LOCATION pIrpSp;
    if ( ObReferenceObjectByHandle(
        handle,
        DELETE,
        *IoFileObjectType,
        0,
        (PVOID*)&pFileObject,
        0) )
    {
        return 0;
    }
    pDevObj = IoGetRelatedDeviceObject(pFileObject);
    pIrp = IoAllocateIrp(pDevObj->StackSize, TRUE);
    if ( pIrp )
    {
        KeInitializeEvent(&Event, SynchronizationEvent, 0);
        pIrp->AssociatedIrp.SystemBuffer = &FileInformation;
        pIrp->UserEvent = &Event;
        pIrp->UserIosb  = &IoStatusBlock;
        pIrp->Tail.Overlay.OriginalFileObject = pFileObject;
        pIrp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
        pIrp->RequestorMode = 0;
        FileInformation.DeleteFile = TRUE;
        pIrpSp = ((char *)pIrp->Tail.Overlay.CurrentStackLocation - 36);
        pIrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
        pIrpSp->DeviceObject = pDevObj;
        pIrpSp->FileObject = pFileObject;
        pIrpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
        pIrpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
        pIrpSp->Parameters.SetFile.FileObject = pFileObject;
        pIrpSp->CompletionRoutine = SetFileAttributeCompletion;
        pIrpSp->Context = 0;
        pIrpSp->Control = 0xE0;
        IofCallDriver(pDevObj, pIrp);
        KeWaitForSingleObject(&Event, 0, 0, 1u, 0);
    }
    ObfDereferenceObject(pFileObject);
    return IoStatusBlock.Status;
}

上传的附件 1.PNG
hook_NtLoadDriver.7z

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功