TC官方合作论坛

 找回密码
 立即注册
楼主: kevinqq

[TC5.0源码] 天使插件4.019版VC源码开源-类大漠插件

    [复制链接]
发表于 2014-9-29 20:55:19 | 显示全部楼层
11111
回复

使用道具 举报

发表于 2014-9-29 21:07:36 | 显示全部楼层
太牛了,感谢感谢感谢
回复 支持 反对

使用道具 举报

发表于 2014-9-29 22:04:15 | 显示全部楼层
这个大杀器啊
回复 支持 反对

使用道具 举报

发表于 2014-9-29 22:09:26 | 显示全部楼层
学习邪恶
回复

使用道具 举报

发表于 2014-9-29 23:09:00 | 显示全部楼层
哟!!!!重量级源码都开房了,强!!!!
回复 支持 反对

使用道具 举报

发表于 2014-9-30 00:31:08 | 显示全部楼层
真的要顶一下了。。这个很好
回复 支持 反对

使用道具 举报

发表于 2014-9-30 00:57:50 | 显示全部楼层
看了代码。很精彩,学了不少东西
关于那个注入的和保护自己不被访问的方案有些过时,在做逆向分析中的,这些手法不太高明。(大胆直说,呵呵别介意~!)
有几个方案可以参考下吧。
1. 伪造 EPROCESS 和注入目标同源,利用目标程序自身信任机制。
2.跳板注入,利用信任白名单机制。。比方说: 注入目标进程为 nP.exe      nP.exe 信任 server.exe 服务   于是乎 注入一个my.dll 到 server.exe ,然后 由 my.dll 再用memoryloader 的方式注入到 nP.exe
3.用驱动实现memoryload 功能,直接写入目标进程。

VOID Get_AVA_PEPROCESS()
{

        ANSI_STRING Str_A,Str_B;

        if (AVA_EPROCESS==NULL)
        {
                RtlInitAnsiString(&Str_A,AVA_EXE);//转换字符串

                RtlInitAnsiString(&Str_B,(c**t char*)PsGetProcessImageFileName(CurrentProcessEPROCESS));//转换字符串

                DbgPrint("PEPROCESS 结构指针: 0x%08X     进程:  %s  \n", CurrentProcessEPROCESS,(c**t char*)PsGetProcessImageFileName(CurrentProcessEPROCESS));

                if (RtlCompareString(&Str_A,&Str_B,TRUE)==0)//对比字符串
                {
                        DbgPrint("PEPROCESS 结构指针: 0x%08X     进程:  %s  \n", CurrentProcessEPROCESS,(c**t char*)PsGetProcessImageFileName(CurrentProcessEPROCESS));

                        AVA_EPROCESS=CurrentProcessEPROCESS;
                       
                        Un_IoGetCurrentProcessHok();
                       
                        TesSafe_IoGetCurrentProcessHok();

                        GetTesSafeResert();

                        TesSafe_MmIsAddressValidHok();

                        Fcuk_DebugPortZero();

                        PassKiAttachProcess();

                        SetnGetContextHook();
                }

        }
}
回复 支持 反对

使用道具 举报

发表于 2014-9-30 00:59:02 | 显示全部楼层
#include "stdafx.h"
#include "SysBase.h"



#define AVA_EXE "DNF.exe"
//#define AVA_EXE "QQ賣.exe"
//#define AVA_EXE "XClient.exe"

//////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif


void OnUnload(IN PDRIVER_OBJECT DriverObject);

void WaitTesSafeThread(IN PVOID pContext);

NTSTATUS GetTesSafeInfo();

NTSTATUS GetSysBaseInfo();

NTSTATUS ExitHook();

NTSTATUS StartHook();

NTSTATUS IoGetCurrentProcessHok();

NTSTATUS IoGetCurrentProcessHok();//开始挂勾

VOID Un_IoGetCurrentProcessHok();//卸载代码

DWORD GetTesSafeIoGetCurrentProcess_Prt();//得到TesSafe 调用 IoGetCurrentProcess 指针

NTSTATUS TesSafe_IoGetCurrentProcessHok();//开始挂勾TesSafe

NTSTATUS TesSafe_MmIsAddressValidHok();//开始挂勾

VOID Fcuk_DebugPortZero();

void PassKiAttachProcess();

DWORD GetTesSafeResert();

VOID SetnGetContextHook();

VOID UnSetnGetContextHook();


/////////////////////////////////////////////////////////////////////////////////////////////////////

HANDLE hThreadWait        =        NULL;                //临听等待线程句柄

ULONG TesSafe_Base        =        NULL;                //腾迅驱动基址

ULONG ntoskrnl_Base        =        NULL;

ULONG ntkrnlpa_Base        =        NULL;

ULONG NTKL64G_Base        =        NULL;

ULONG KDCOM_Base        =        NULL;

ULONG ntoskrnl_Size        =        0;

ULONG ntkrnlpa_Size        =        0;

ULONG NTKL64G_Size        =        0;

ULONG TesSafe_Size        =        0;

ULONG KDCOM_Size        =        0;


BOOLEAN IoGetCurrentProcess_Mark = FALSE;

DWORD IoGetCurrentProcess_Addr        =        0;

DWORD IoGetCurrentProcess_Addr_Ret;

unsigned char IoGetCurrentProcess_Code[]        =        {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};//原始IoGetCurrentProcess的代码

PEPROCESS AVA_EPROCESS = NULL;

PEPROCESS CurrentProcessEPROCESS=NULL;

DWORD TesSafeIoGetCurrentProcess_Prt        =        0;

BOOLEAN TesSafe_IoGetCurrentProcess_Mark = FALSE;

DWORD MmIsAddressValid_Addr        =        0;

DWORD TesSafe_MmIsAddressValid_Addr        =        0;

DWORD TesSafe_MmIsAddressValid_Mark        =        FALSE;


DWORD OldNGCTServerID;//保存写的服务ID
DWORD OldNSCTServerID;//保存读的服务ID
DWORD GctID=0;
DWORD SctID=0;

/////////////////////////////////////////勾子得到DNF.exe PE结构指针函数//////////////////////////////////////////////////

VOID Get_AVA_PEPROCESS()
{

        ANSI_STRING Str_A,Str_B;

        if (AVA_EPROCESS==NULL)
        {
                RtlInitAnsiString(&Str_A,AVA_EXE);//转换字符串

                RtlInitAnsiString(&Str_B,(c**t char*)PsGetProcessImageFileName(CurrentProcessEPROCESS));//转换字符串

                DbgPrint("PEPROCESS 结构指针: 0x%08X     进程:  %s  \n", CurrentProcessEPROCESS,(c**t char*)PsGetProcessImageFileName(CurrentProcessEPROCESS));

                if (RtlCompareString(&Str_A,&Str_B,TRUE)==0)//对比字符串
                {
                        DbgPrint("PEPROCESS 结构指针: 0x%08X     进程:  %s  \n", CurrentProcessEPROCESS,(c**t char*)PsGetProcessImageFileName(CurrentProcessEPROCESS));

                        AVA_EPROCESS=CurrentProcessEPROCESS;
                       
                        Un_IoGetCurrentProcessHok();
                       
                        TesSafe_IoGetCurrentProcessHok();

                        GetTesSafeResert();

                        TesSafe_MmIsAddressValidHok();

                        Fcuk_DebugPortZero();

                        PassKiAttachProcess();

                        SetnGetContextHook();
                }

        }
}



///////////////////////////////去除硬件断点////////////////////////////////////////
NTSTATUS _declspec(naked) Nakd_NtGetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
        __asm
        {
                jmp DWORD ptr[OldNGCTServerID]
        }
}

NTSTATUS _declspec(naked)  Nakd_NtSetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
        __asm
        {
                jmp DWORD ptr[OldNSCTServerID]
        }
}


NTSTATUS MyNtGetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
        if (_stricmp((c**t char*)PsGetProcessImageFileName(PsGetCurrentProcess()),AVA_EXE))
        {
                return Nakd_NtGetThreadContext(hThread, pContext);
        }
        return STATUS_SUCCESS;


}

NTSTATUS MyNtSetThreadContext(HANDLE hThread, PCONTEXT pContext)
{
        if (_stricmp((c**t char*)PsGetProcessImageFileName(PsGetCurrentProcess()),AVA_EXE))
        {
                return Nakd_NtSetThreadContext(hThread, pContext);
        }
        return STATUS_SUCCESS;

}


VOID SetnGetContextHook()
{
        if (!GctID)
        {
                return;
        }
        DWORD Addr_NGCT;
        DWORD Addr_NSCT;
        Addr_NGCT = (ULONG)KeServiceDescriptorTable->ServiceTableBase + GctID   * 4;   //0x80        为NtGetContextThread        服务ID
        Addr_NSCT = (ULONG)KeServiceDescriptorTable->ServiceTableBase + SctID  * 4;   //0x80        为NtSetContextThread        服务ID

        OldNGCTServerID=*((DWORD*)Addr_NGCT);//保存旧的SSDT服务ID
        OldNSCTServerID=*((DWORD*)Addr_NSCT);//保存旧的SSDT服务ID

        KIRQL oldIrql;
        oldIrql = KeRaiseIrqlToDpcLevel();
        WPOFF();
        *((ULONG*)Addr_NGCT) = (ULONG)MyNtGetThreadContext;        //HOOK SSDT
        *((ULONG*)Addr_NSCT) = (ULONG)MyNtSetThreadContext;        //HOOK SSDT
        WPON();
        KeLowerIrql(oldIrql);

}


VOID UnSetnGetContextHook()
{
        if (!GctID)
        {
                return;
        }
        DWORD Addr_NGCT;
        DWORD Addr_NSCT;
        Addr_NGCT = (ULONG)KeServiceDescriptorTable->ServiceTableBase + GctID   * 4;   //0x80        为NtGetContextThread        服务ID
        Addr_NSCT = (ULONG)KeServiceDescriptorTable->ServiceTableBase + SctID  * 4;   //0x80        为NtSetContextThread        服务ID

        KIRQL oldIrql;
        oldIrql = KeRaiseIrqlToDpcLevel();
        WPOFF();
        *((ULONG*)Addr_NGCT) = OldNGCTServerID;        //UNHOOK SSDT
        *((ULONG*)Addr_NSCT) = OldNSCTServerID;        //UNHOOK SSDT
        WPON();
        KeLowerIrql(oldIrql);

}




//这个是为了得到白名单的PEPROCESS用的//当得到AVA的EPROCESS后这个勾子卸载掉
void __declspec(naked) My_IoGetCurrentProcess() //替代函数
{
        __asm
        {
                mov eax, dword ptr fs:[0x124]

                mov eax, dword ptr [eax+0x44]

                pushad

                mov CurrentProcessEPROCESS,eax

                call Get_AVA_PEPROCESS

                popad

                jmp IoGetCurrentProcess_Addr_Ret
        }
}



NTSTATUS IoGetCurrentProcessHok()//开始挂勾
{

        //标记勾子
        IoGetCurrentProcess_Mark = TRUE;

        //计算返回地址
        IoGetCurrentProcess_Addr_Ret = IoGetCurrentProcess_Addr + 0x9;

        //备份挂勾函数代码
        RtlCopyMemory(IoGetCurrentProcess_Code,(PVOID)IoGetCurrentProcess_Addr,0xA);

        KIRQL oldIrql;

        ULONG JmpCode        =        (ULONG)My_IoGetCurrentProcess        -        IoGetCurrentProcess_Addr        -        0x5;//计算跳转代码

        oldIrql = KeRaiseIrqlToDpcLevel();

        WPOFF();

        __asm
        {
                MOV EBX,IoGetCurrentProcess_Addr

                MOV DL,0xE9

                MOV BYTE PTR [EBX],DL

                ADD EBX,0x1

                MOV EDX,JmpCode

                MOV DWORD PTR [EBX],EDX
        }

        WPON();

        KeLowerIrql(oldIrql);

        return STATUS_SUCCESS;
}


VOID Un_IoGetCurrentProcessHok()//卸载代码
{
        KIRQL oldIrql;

        oldIrql = KeRaiseIrqlToDpcLevel();


       
        if (IoGetCurrentProcess_Mark)
        {
                WPOFF();
               
                memcpy((PVOID)IoGetCurrentProcess_Addr,IoGetCurrentProcess_Code,0xA);
               
                WPON();
        }
       

        IoGetCurrentProcess_Mark = FALSE;

        KeLowerIrql(oldIrql);
}

/////////////////////////////////////////得到DNF.exe 调用函数IoGetCurrentProcess指针//////////////////////////////////////////////////

//得到系TesSafe调用的IoGetCurrentProcess内核函数地址
DWORD GetTesSafeIoGetCurrentProcess_Prt()
{
        DWORD pMemoryStart        = TesSafe_Base;

        DWORD pMemoryEnd        = (TesSafe_Base + TesSafe_Size);

        DWORD Begin;

        DWORD End;

        for(pMemoryStart;  pMemoryStart != pMemoryEnd; pMemoryStart += 1024)
        {
                Begin = pMemoryStart;

                End = pMemoryStart + 1024;

                for(Begin; Begin != End; Begin += 4)
                {
                        if (*(DWORD*)Begin==IoGetCurrentProcess_Addr)
                        {
                                return Begin;
                        }
                }
        }
        return 0;
}



DWORD GetTesSafeResert()
{
        DWORD pMemoryStart        = TesSafe_Base;

        DWORD pMemoryEnd        = (TesSafe_Base + TesSafe_Size);

        DWORD Begin;

        DWORD End;

        for(pMemoryStart;  pMemoryStart != pMemoryEnd; pMemoryStart += 1024)
        {
                Begin = pMemoryStart;

                End = pMemoryStart + 1024;

                for(Begin; Begin != End; Begin += 1)
                {
                        if (*(BYTE*)Begin==0x8B&&
                                *(BYTE*)(Begin + 2)==0x53&&
                                *(BYTE*)(Begin + 3)==0x56&&
                                *(BYTE*)(Begin + 4)==0x57&&
                                *(BYTE*)(Begin + 5)==0xEB&&
                                *(BYTE*)(Begin + 7)==0xFF)
                        {

                                DbgPrint("TesSafeResert 指针: 0x%08X \n", Begin);
                                WPOFF();
                                *(DWORD*)(Begin) = 0x900004C2;
                                WPON();
                                return Begin;
                        }
                }
        }
        return 0;
}



//这个是给TesSaft.sys专用的
void __declspec(naked) TesSafe_IoGetCurrentProcess()      
{
        __asm
        {
                mov eax,AVA_EPROCESS
               
                retn
        }
}

NTSTATUS TesSafe_IoGetCurrentProcessHok()//开始挂勾
{

        TesSafeIoGetCurrentProcess_Prt = GetTesSafeIoGetCurrentProcess_Prt();
        DbgPrint("TesSafeIoGetCurrentProcess_Prt 指针: 0x%08X \n", TesSafeIoGetCurrentProcess_Prt);
       
        if (TesSafeIoGetCurrentProcess_Prt)
        {
                WPOFF();
                *(DWORD*)TesSafeIoGetCurrentProcess_Prt =        (DWORD)TesSafe_IoGetCurrentProcess;
                WPON();
                TesSafe_IoGetCurrentProcess_Mark = TRUE;
        }
       
        return STATUS_SUCCESS;
}

VOID Un_TesSafe_IoGetCurrentProcessHok()//卸载代码
{
        if (TesSafe_IoGetCurrentProcess_Mark && GetModBase("TesSafe.sys"))
        {
                WPOFF();
                *(DWORD*)TesSafeIoGetCurrentProcess_Prt =        (DWORD)IoGetCurrentProcess_Addr;
                WPON();
                TesSafe_IoGetCurrentProcess_Mark = FALSE;
        }
       
}

/////////////////////////////////////////得到DNF.exe 调用函数MmIsAddressValid指针//////////////////////////////////////////////////

//得到系TesSafe调用的 MmIsAddressValid 内核函数地址
DWORD GetTesSafeIoGetMmIsAddressValid_Prt()
{


        DWORD pMemoryStart        = TesSafe_Base;

        DWORD pMemoryEnd        = (TesSafe_Base + TesSafe_Size);

        DWORD Begin;

        DWORD End;

        for(pMemoryStart;  pMemoryStart != pMemoryEnd; pMemoryStart += 1024)
        {
                Begin = pMemoryStart;

                End = pMemoryStart + 1024;

                for(Begin; Begin != End; Begin += 4)
                {
                        if (*(DWORD*)Begin==MmIsAddressValid_Addr)
                        {
                                return Begin;
                        }

                }
               
        }
        return 0;



}

//这个是给TesSaft.sys专用的//不同系统有所区别在retn
void __declspec(naked) TesSafe_MmIsAddressValid()      
{
        __asm
        {
                xor al, al

                retn 4
        }
}

NTSTATUS TesSafe_MmIsAddressValidHok()//开始挂勾
{

        TesSafe_MmIsAddressValid_Mark = TRUE;
        TesSafe_MmIsAddressValid_Addr = GetTesSafeIoGetMmIsAddressValid_Prt();

        DbgPrint("TesSafe_MmIsAddressValid_Addr 指针: 0x%08X  to 0x%08X\n", TesSafe_MmIsAddressValid_Addr,(DWORD)TesSafe_MmIsAddressValid);
        WPOFF();
        *(DWORD*)TesSafe_MmIsAddressValid_Addr = (DWORD)TesSafe_MmIsAddressValid;
        WPON();
        return STATUS_SUCCESS;
}


VOID Un_TesSafe_MmIsAddressValidHok()//卸载代码
{
        if (TesSafe_MmIsAddressValid_Mark && GetModBase("TesSafe.sys"))
        {
                WPOFF();
                *(DWORD*)TesSafe_MmIsAddressValid_Addr =        (DWORD)MmIsAddressValid_Addr;
                WPON();
                TesSafe_MmIsAddressValid_Mark = FALSE;
        }

}


////////////////////////////////干掉DebugPort清零//////////////////////////////////
VOID Fcuk_DebugPortZero()
{
        ULONG DebugPortOffset=0;

        DWORD pMemoryStart        = TesSafe_Base;

        DWORD pMemoryEnd        = (TesSafe_Base + TesSafe_Size);

        DWORD Begin;

        DWORD End;

        for(pMemoryStart;  pMemoryStart != pMemoryEnd; pMemoryStart += 1024)
        {
                Begin = pMemoryStart;

                End = pMemoryStart + 1024;

                for(Begin; Begin != End; Begin += 1)
                {
                        if (*(BYTE*)Begin==0x8B&&
                                *(BYTE*)(Begin + 3)==0x8B&&
                                *(BYTE*)(Begin + 5)==0xA1&&
                                *(BYTE*)(Begin + 10)==0x8B&&
                                *(BYTE*)(Begin + 13)==0x8B)
                        {

                                DebugPortOffset=*(ULONG*)(Begin+0x6);

                                DbgPrint("DebugPortOffset 指针: 0x%08X \n", DebugPortOffset);

                                DebugPortOffset=*(ULONG*)DebugPortOffset+4;

                                DbgPrint("DebugPortOffset 指针: 0x%08X \n", DebugPortOffset);


                                DebugPortOffset=*(ULONG*)(*(ULONG*)(Begin+0x6))+4;
                                DbgPrint("DebugPortOffset 指针: 0x%08X \n", DebugPortOffset);
                                WPOFF();
                                *(ULONG*)DebugPortOffset=0x70;
                                WPON();
                                return;
                        }
                }
        }
        return;

}


void PassKiAttachProcess()
{
        ULONG addr_KiAttachProcess=0;
        UNICODE_STRING u_KeAttachProcess;
        BYTE _bp1[]={0x8B,0xFF,0x55,0x8B,0xEC,0x53,0x56};
        BYTE* _bp=NULL;
        RtlInitUnicodeString(&u_KeAttachProcess,L"KeAttachProcess");
        _bp=(BYTE*)MmGetSystemRoutineAddress(&u_KeAttachProcess);

        while(1)
        {
                if((*(_bp-6)==0x50)&&(*(_bp-5)==0xFF)&&(*(_bp)==0xE8)&&(*(_bp+5)==0x5F)&&(*(_bp+8)==0xC2))
                {
                        addr_KiAttachProcess=(ULONG)_bp;
                        __asm
                        {
                                push eax
                                        push ebx
                                        mov eax,addr_KiAttachProcess
                                        mov ebx,[eax+1]
                                add eax,ebx
                                        add eax,5
                                        mov addr_KiAttachProcess,eax
                                        pop ebx
                                        pop eax
                        }
                        break;
                }
                _bp++;
        }
        WPOFF();
        RtlCopyBytes((void*)addr_KiAttachProcess,_bp1,7);
        WPON();
}



///////////////////////////////////////////////////////////////////////////////////////////////////
//驱动入口
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{

        DbgPrint("驱动加载...\n");

        DriverObject->DriverUnload = OnUnload;

        NTSTATUS ntStatus = PsCreateSystemThread(&hThreadWait,0,NULL,(HANDLE)0,NULL,WaitTesSafeThread,NULL);

        KdPrint(("创建线程...\n", ntStatus));

        return STATUS_SUCCESS;
}



void WaitTesSafeThread(IN PVOID pContext)
{
        LARGE_INTEGER liInterval;

        liInterval.QuadPart = - 10 * 1000 * 1000;

        do
        {
                DbgPrint("等待 TesSafe.sys ...\n");

                TesSafe_Base  = GetModBase("TesSafe.sys");

                KeDelayExecutionThread(KernelMode,TRUE,&liInterval);

        }while(!TesSafe_Base);

        DbgPrint("定位 TesSafe.sys ...\n");

        GetSysBaseInfo();

        GetTesSafeInfo();

        StartHook();
}

//驱动卸载
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
        PVOID objtowait        =        0;

        if (hThreadWait)
        {
                TesSafe_Base=1;

                ObReferenceObjectByHandle(hThreadWait,THREAD_ALL_ACCESS,NULL,KernelMode,&objtowait,NULL);

                KeWaitForSingleObject(objtowait,Executive,KernelMode,FALSE,NULL);

                ObDereferenceObject(&objtowait);
        }

        ExitHook();

        DbgPrint("卸载驱动...\n");

}

NTSTATUS GetTesSafeInfo()
{
        TesSafe_Base  = GetModBase("TesSafe.sys");

        TesSafe_Size  = GetModSize("TesSafe.sys");

        DbgPrint("地址: 0x%08X        大小: 0x%08X --- TesSafe.sys\n", TesSafe_Base,TesSafe_Size);

        return STATUS_SUCCESS;
}

NTSTATUS GetSysBaseInfo()
{
        ntoskrnl_Base  = GetModBase("ntoskrnl.exe");
        if (ntoskrnl_Base)
        {
                GctID=85;
                SctID=213;
        }

        ntoskrnl_Size  = GetModSize("ntoskrnl.exe");

       
        ntkrnlpa_Base  = GetModBase("ntkrnlpa.exe");
       
        ntkrnlpa_Size  = GetModSize("ntkrnlpa.exe");

        NTKL64G_Base  = GetModBase("NTKL64G.exe");

        NTKL64G_Size  = GetModBase("NTKL64G.exe");

        if (NTKL64G_Base)
        {
                GctID=85;
                SctID=213;
        }

       
        DbgPrint("地址: 0x%08X        大小: 0x%08X --- ntoskrnl.exe\n", ntoskrnl_Base,ntoskrnl_Size);
       
        DbgPrint("地址: 0x%08X        大小: 0x%08X --- ntkrnlpa.exe\n", ntkrnlpa_Base,ntkrnlpa_Size);

        DbgPrint("地址: 0x%08X        大小: 0x%08X --- NTKL64G.exe\n", NTKL64G_Base,NTKL64G_Size);



        //得到kdcom.dll 的镜像地址
        KDCOM_Base  = GetModBase("kdcom.DLL");

        KDCOM_Size  = GetModSize("kdcom.DLL");

        DbgPrint("地址: 0x%08X        大小: 0x%08X --- kdcom.DLL\n", KDCOM_Base,KDCOM_Size);



        //得到系统的IoGetCurrentProcess内核函数地址

        IoGetCurrentProcess_Addr        =        GetFunAddress(L"IoGetCurrentProcess");


        DbgPrint("地址: 0x%08X         --- IoGetCurrentProcess_Addr \n", IoGetCurrentProcess_Addr);



        //得到系统的IoGetCurrentProcess内核函数地址

        MmIsAddressValid_Addr        =        GetFunAddress(L"MmIsAddressValid");


        DbgPrint("地址: 0x%08X         --- MmIsaddressValid \n", MmIsAddressValid_Addr);


        return STATUS_SUCCESS;
}


NTSTATUS StartHook()
{
        IoGetCurrentProcessHok();//开始挂勾
        DbgPrint("加载勾子...\n");
        return STATUS_SUCCESS;
}

NTSTATUS ExitHook()
{
        DbgPrint("卸载勾子...\n");

        Un_IoGetCurrentProcessHok();

        Un_TesSafe_IoGetCurrentProcessHok();

        Un_TesSafe_MmIsAddressValidHok();

        UnSetnGetContextHook();

        return STATUS_SUCCESS;
}









回复 支持 反对

使用道具 举报

发表于 2014-9-30 01:07:33 | 显示全部楼层
#pragma once


#if !defined(AFX_MEMLOADDLL_H__750C4158_467F_454F_AC91_36C0501B39CD__INCLUDED_)
#define AFX_MEMLOADDLL_H__750C4158_467F_454F_AC91_36C0501B39CD__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


typedef   BOOL (__stdcall *ProcDllMain)(HINSTANCE, DWORD, LPVOID);

class CMemLoadDll
{
public:
        CMemLoadDll();
        ~CMemLoadDll();

public:
        BOOL MemLoadLibrary(void* lpFileData, int nDataLength);  // Dll file data buffer
        FARPROC MemGetProcAddress(LPCSTR lpProcName);

private:
        BOOL m_bIsLoadOk;
        BOOL CheckDataValide(void* lpFileData, int nDataLength);
        int  CalcTotalImageSize();
        void CopyDllDatas(void* pDest, void* pSrc);
        BOOL FillRavAddress(void* pImageBase);
        void DoRelocation(void* pNewBase);
        int  GetAlignedSize(int nOrigin, int nAlignment);

private:
        ProcDllMain m_pDllMain;

private:
        DWORD  m_pImageBase;
        PIMAGE_DOS_HEADER m_pDosHeader;
        PIMAGE_NT_HEADERS m_pNTHeader;
        PIMAGE_SECTION_HEADER m_pSectionHeader;
};

#endif // !defined(AFX_MEMLOADDLL_H__750C4158_467F_454F_AC91_36C0501B39CD__INCLUDED_)



//调试输出
void MyDebug(c**t char * sz, ...);
回复 支持 反对

使用道具 举报

发表于 2014-9-30 01:07:45 | 显示全部楼层
// MemLoadDll.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "MemLoadDll.h"

#include <stdio.h>

#define  DEBUGBUFSIZE 1024


void MyDebug(c**t char * sz, ...)
{
        char szData[DEBUGBUFSIZE]={0};

        memset(szData,0,1024);

        va_list args;

        va_start(args, sz);

        vsnprintf_s(szData, sizeof(szData) - 1, DEBUGBUFSIZE,sz, args);

        va_end(args);

        OutputDebugStringA(szData);

        OutputDebugStringA("\n");

        return;
}



#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// C**truction/Destruction
//////////////////////////////////////////////////////////////////////
CMemLoadDll::CMemLoadDll()
{
        m_bIsLoadOk = FALSE;
        m_pImageBase = NULL;
        m_pDllMain = NULL;
}

CMemLoadDll::~CMemLoadDll()
{
        if(m_bIsLoadOk)
        {
                // ASSERT(m_pImageBase != NULL);
                // ASSERT(m_pDllMain   != NULL);
                //脱钩,准备卸载dll
                m_pDllMain((HINSTANCE)m_pImageBase, DLL_PROCESS_DETACH, 0);
                VirtualFree((LPVOID)m_pImageBase, 0, MEM_RELEASE);
        }
}

//MemLoadLibrary函数从内存缓冲区数据中加载一个dll到当前进程的地址空间,缺省位置0x10000000
//返回值: 成功返回TRUE , 失败返回FALSE
//lpFileData: 存放dll文件数据的缓冲区
//nDataLength: 缓冲区中数据的总长度

BOOL CMemLoadDll::MemLoadLibrary(void* lpFileData, int nDataLength)
{

        if (m_pImageBase != NULL)
        {
                return FALSE;  //已经加载一个dll,还没有释放,不能加载新的dll
        }
        //检查数据有效性,并初始化
        if (!CheckDataValide(lpFileData, nDataLength))
        {
                return FALSE;
        }
        //计算所需的加载空间
        int nImageSize = CalcTotalImageSize();

        if (nImageSize == 0)
        {
                return FALSE;
        }
        // 分配虚拟内存
        void *pMemoryAddress = VirtualAlloc(NULL, nImageSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);

        if (pMemoryAddress == NULL)
        {
                return FALSE;
        }
        else
        {
                CopyDllDatas(pMemoryAddress, lpFileData); //复制dll数据,并对齐每个段
                //重定位信息
                if (m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress > 0
                        && m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0)
                {
                        DoRelocation(pMemoryAddress);
                }
                //填充引入地址表
                if (!FillRavAddress(pMemoryAddress)) //修正引入地址表失败
                {
                        VirtualFree(pMemoryAddress, 0, MEM_RELEASE);
                        return FALSE;
                }
                //修改页属性。应该根据每个页的属性单独设置其对应内存页的属性。这里简化一下。
                //统一设置成一个属性PAGE_EXECUTE_READWRITE
                unsigned long unOld;

                VirtualProtect(pMemoryAddress, nImageSize, PAGE_EXECUTE_READWRITE, &unOld);
               
        }

       

        //修正基地址
        m_pNTHeader->OptionalHeader.ImageBase = (DWORD)pMemoryAddress;

        DWORD dwOld=0;  
        VirtualProtect(pMemoryAddress,nImageSize,PAGE_EXECUTE_READWRITE,&dwOld);
        //VirtualProtect(pMemoryAddress,nImageSize,PAGE_EXECUTE_READ,&dwOld);

        //接下来要调用一下dll的入口函数,做初始化工作。
        m_pDllMain = (ProcDllMain)(m_pNTHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)pMemoryAddress);


        BOOL InitResult = m_pDllMain((HINSTANCE)pMemoryAddress, DLL_PROCESS_ATTACH, 0);


        if (!InitResult) //初始化失败
        {
                m_pDllMain((HINSTANCE)pMemoryAddress, DLL_PROCESS_DETACH, 0);
                VirtualFree(pMemoryAddress, 0, MEM_RELEASE);
                m_pDllMain = NULL;
                return FALSE;
        }

        //m_bIsLoadOk = TRUE;
        m_pImageBase = (DWORD)pMemoryAddress;
        return TRUE;
}

//MemGetProcAddress函数从dll中获取指定函数的地址
//返回值: 成功返回函数地址 , 失败返回NULL
//lpProcName: 要查找函数的名字或者序号
FARPROC CMemLoadDll::MemGetProcAddress(LPCSTR lpProcName)
{
        if (m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0 ||
                m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0)
        {
                return NULL;
        }
        if (!m_bIsLoadOk)
        {
                return NULL;
        }

        DWORD dwOffsetStart = m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
        DWORD dwSize = m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

        PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)m_pImageBase + m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
        int iBase = pExport->Base;
        int iNumberOfFuncti** = pExport->NumberOfFuncti**;
        int iNumberOfNames = pExport->NumberOfNames; //<= iNumberOfFuncti**
        LPDWORD pAddressOfFuncti** = (LPDWORD)(pExport->AddressOfFuncti** + m_pImageBase);
        LPWORD  pAddressOfOrdinals = (LPWORD)(pExport->AddressOfNameOrdinals + m_pImageBase);
        LPDWORD pAddressOfNames  = (LPDWORD)(pExport->AddressOfNames + m_pImageBase);

        int iOrdinal = -1;

        if (((DWORD)lpProcName & 0xFFFF0000) == 0) //IT IS A ORDINAL!
        {
                iOrdinal = (DWORD)lpProcName & 0x0000FFFF - iBase;
        }
        else  //use name
        {
                int iFound = -1;

                for (int i=0; i<iNumberOfNames; i++)
                {
                        char* pName= (char* )(pAddressOfNames[i] + m_pImageBase);
                        if (strcmp(pName, lpProcName) == 0)
                        {
                                iFound = i;
                                break;
                        }
                }
                if (iFound >= 0)
                {
                        iOrdinal = (int)(pAddressOfOrdinals[iFound]);
                }
        }

        if (iOrdinal < 0 || iOrdinal >= iNumberOfFuncti** )
        {
                return NULL;
        }
        else
        {
                DWORD pFunctionOffset = pAddressOfFuncti**[iOrdinal];

                if (pFunctionOffset > dwOffsetStart && pFunctionOffset < (dwOffsetStart + dwSize))//maybe Export Forwarding
                {
                        return NULL;
                }
                else
                {
                        return (FARPROC)(pFunctionOffset + m_pImageBase);
                }
        }

}

// 重定向PE用到的地址
void CMemLoadDll::DoRelocation( void *pNewBase)
{
        /* 重定位表的结构:
        // DWORD sectionAddress, DWORD size (包括本节需要重定位的数据)
        // 例如 1000节需要修正5个重定位数据的话,重定位表的数据是
        // 00 10 00 00   14 00 00 00      xxxx xxxx xxxx xxxx xxxx 0000
        // -----------   -----------      ----
        // 给出节的偏移  总尺寸=8+6*2     需要修正的地址           用于对齐4字节
        // 重定位表是若干个相连,如果address 和 size都是0 表示结束
        // 需要修正的地址是12位的,高4位是形态字,intel cpu下是3
        */
        //假设NewBase是0x600000,而文件中设置的缺省ImageBase是0x400000,则修正偏移量就是0x200000
        DWORD dwDelta = (DWORD)pNewBase - m_pNTHeader->OptionalHeader.ImageBase;

        //注意重定位表的位置可能和硬盘文件中的偏移地址不同,应该使用加载后的地址
        PIMAGE_BASE_RELOCATION pLoc = (PIMAGE_BASE_RELOCATION)((unsigned long)pNewBase
                + m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

        while ((pLoc->VirtualAddress + pLoc->SizeOfBlock) != 0) //开始扫描重定位表
        {
                WORD *pLocData = (WORD *)((int)pLoc + sizeof(IMAGE_BASE_RELOCATION));
                //计算本节需要修正的重定位项(地址)的数目
                int nNumberOfReloc = (pLoc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);

                for ( int i=0 ; i < nNumberOfReloc; i++)
                {
                        if ((DWORD)(pLocData[i] & 0xF000) == 0x00003000) //这是一个需要修正的地址
                        {
                                // 举例:
                                // pLoc->VirtualAddress = 0x1000;
                                // pLocData[i] = 0x313E; 表示本节偏移地址0x13E处需要修正
                                // 因此 pAddress = 基地址 + 0x113E
                                // 里面的内容是 A1 ( 0c d4 02 10)  汇编代码是: mov eax , [1002d40c]
                                // 需要修正1002d40c这个地址
                                DWORD * pAddress = (DWORD *)((unsigned long)pNewBase + pLoc->VirtualAddress + (pLocData[i] & 0x0FFF));
                                *pAddress += dwDelta;
                        }
                }
                //转移到下一个节进行处理
                pLoc = (PIMAGE_BASE_RELOCATION)((DWORD)pLoc + pLoc->SizeOfBlock);
        }
}

//填充引入地址表
BOOL CMemLoadDll::FillRavAddress(void *pImageBase)
{

       
        // 引入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组,全部是0表示结束
        // 数组定义如下:
        //
        // DWORD   OriginalFirstThunk;         // 0表示结束,否则指向未绑定的IAT结构数组
        // DWORD   TimeDateS**p;
        // DWORD   ForwarderChain;             // -1 if no forwarders
        // DWORD   Name;                       // 给出dll的名字
        // DWORD   FirstThunk;                 // 指向IAT结构数组的地址(绑定后,这些IAT里面就是实际的函数地址)
        unsigned long nOffset = m_pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress ;

        if (nOffset == 0)
        {
                return TRUE; //No Import Table
        }

        PIMAGE_IMPORT_DESCRIPTOR pID = (PIMAGE_IMPORT_DESCRIPTOR)((unsigned long)pImageBase + nOffset);

        while (pID->Characteristics != 0)
        {
                PIMAGE_THUNK_DATA pRealIAT = (PIMAGE_THUNK_DATA)((unsigned long)pImageBase + pID->FirstThunk);
                PIMAGE_THUNK_DATA pOriginalIAT = (PIMAGE_THUNK_DATA)((unsigned long)pImageBase + pID->OriginalFirstThunk);
                //获取dll的名字
#define NAME_BUF_SIZE 256

                char szBuf[NAME_BUF_SIZE] = ""; //dll name;
                BYTE* pName = (BYTE*)((unsigned long)pImageBase + pID->Name);

                int i=0;
                for (i=0; i<NAME_BUF_SIZE; i++)
                {
                        if (pName[i] == 0)
                        {
                                break;
                        }
                        szBuf[i] = pName[i];
                }
                if (i >= NAME_BUF_SIZE)
                {
                        return FALSE;  // bad dll name
                }
                else
                {
                        szBuf[i] = 0;
                }

                HMODULE hDll = GetModuleHandle(szBuf);

                if (hDll == NULL)
                {
                        return FALSE; //NOT FOUND DLL
                }
                //获取DLL中每个导出函数的地址,填入IAT
                //每个IAT结构是 :
                // union { PBYTE  ForwarderString;
                //   PDWORD Function;
                //   DWORD Ordinal;
                //   PIMAGE_IMPORT_BY_NAME  AddressOfData;
                // } u1;
                // 长度是一个DWORD ,正好容纳一个地址。
                for (i=0; ; i++)
                {
                        if (pOriginalIAT[i].u1.Function == 0)
                        {
                                break;
                        }

                        FARPROC lpFunction = NULL;

                        if (pOriginalIAT[i].u1.Ordinal & IMAGE_ORDINAL_FLAG) //这里的值给出的是导出序号
                        {
                                lpFunction = GetProcAddress(hDll, (LPCSTR)(pOriginalIAT[i].u1.Ordinal & 0x0000FFFF));
                        }
                        else //按照名字导入
                        {
                                //获取此IAT项所描述的函数名称
                                PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)
                                        ((DWORD)pImageBase + (DWORD)(pOriginalIAT[i].u1.AddressOfData));
                                //    if(pByName->Hint !=0)
                                //     lpFunction = GetProcAddress(hDll, (LPCSTR)pByName->Hint);
                                //    else
                                lpFunction = GetProcAddress(hDll, (char *)pByName->Name);
                        }
                        if (lpFunction != NULL)   //找到了!
                        {
                                pRealIAT[i].u1.Function = (DWORD)lpFunction;
                        }
                        else
                        {
                                return FALSE;
                        }
                }

                //move to next
                pID = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pID + sizeof(IMAGE_IMPORT_DESCRIPTOR));
        }

        return TRUE;
}

//CheckDataValide函数用于检查缓冲区中的数据是否有效的dll文件
//返回值: 是一个可执行的dll则返回TRUE,否则返回FALSE。
//lpFileData: 存放dll数据的内存缓冲区
//nDataLength: dll文件的长度
BOOL CMemLoadDll::CheckDataValide(void* lpFileData, int nDataLength)
{
        //检查长度
        if (nDataLength < sizeof(IMAGE_DOS_HEADER))
        {
                return FALSE;
        }
        m_pDosHeader = (PIMAGE_DOS_HEADER)lpFileData;  // DOS头
        //检查dos头的标记
        if (m_pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
                return FALSE;  //0x5A4D : MZ
        }

        //检查长度
        if ((DWORD)nDataLength < (m_pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)))
        {
                return FALSE;
        }
        //取得pe头
        m_pNTHeader = (PIMAGE_NT_HEADERS)((unsigned long)lpFileData + m_pDosHeader->e_lfanew); // PE头
        //检查pe头的合法性
        if (m_pNTHeader->Signature != IMAGE_NT_SIGNATURE)
        {
                return FALSE;  //0x00004550 : PE00
        }
        if ((m_pNTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) //0x2000  : File is a DLL
        {
                return FALSE;  
        }
        if ((m_pNTHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0) //0x0002 : 指出文件可以运行
        {
                return FALSE;
        }
        if (m_pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
        {
                return FALSE;
        }

        //取得节表(段表)
        m_pSectionHeader = (PIMAGE_SECTION_HEADER)((int)m_pNTHeader + sizeof(IMAGE_NT_HEADERS));
        //验证每个节表的空间
        for (int i=0; i< m_pNTHeader->FileHeader.NumberOfSecti**; i++)
        {
                if ((m_pSectionHeader[i].PointerToRawData + m_pSectionHeader[i].SizeOfRawData) > (DWORD)nDataLength)
                {
                        return FALSE;
                }
        }

        return TRUE;
}

//计算对齐边界
int CMemLoadDll::GetAlignedSize(int nOrigin, int nAlignment)
{
        return (nOrigin + nAlignment - 1) / nAlignment * nAlignment;
}

//计算整个dll映像文件的尺寸
int CMemLoadDll::CalcTotalImageSize()
{
        int nSize;

        if (m_pNTHeader == NULL)
        {
                return 0;
        }

        int nAlign = m_pNTHeader->OptionalHeader.SectionAlignment; //段对齐字节数

        // 计算所有头的尺寸。包括dos, coff, pe头 和 段表的大小
        nSize = GetAlignedSize(m_pNTHeader->OptionalHeader.SizeOfHeaders, nAlign);
        // 计算所有节的大小
        for (int i=0; i < m_pNTHeader->FileHeader.NumberOfSecti**; ++i)
        {
                //得到该节的大小
                int nCodeSize = m_pSectionHeader[i].Misc.VirtualSize ;
                int nLoadSize = m_pSectionHeader[i].SizeOfRawData;
                int nMaxSize = (nLoadSize > nCodeSize) ? (nLoadSize) : (nCodeSize);
                int nSecti**ize = GetAlignedSize(m_pSectionHeader[i].VirtualAddress + nMaxSize, nAlign);

                if (nSize < nSecti**ize)
                {
                        nSize = nSecti**ize;  //Use the Max;
                }
        }

        return nSize;
}

//CopyDllDatas函数将dll数据复制到指定内存区域,并对齐所有节
//pSrc: 存放dll数据的原始缓冲区
//pDest:目标内存地址
void CMemLoadDll::CopyDllDatas(void* pDest, void* pSrc)
{
        // 计算需要复制的PE头+段表字节数
        int  nHeaderSize = m_pNTHeader->OptionalHeader.SizeOfHeaders;
        int  nSecti**ize = m_pNTHeader->FileHeader.NumberOfSecti** * sizeof(IMAGE_SECTION_HEADER);
        int  nMoveSize = nHeaderSize + nSecti**ize;
        //复制头和段信息
        memcpy(pDest, pSrc, nMoveSize);

        //复制每个节
        for (int i=0; i < m_pNTHeader->FileHeader.NumberOfSecti**; ++i)
        {
                if (m_pSectionHeader[i].VirtualAddress == 0 || m_pSectionHeader[i].SizeOfRawData == 0)
                {
                        continue;
                }
                // 定位该节在内存中的位置
                void *pSectionAddress = (void *)((unsigned long)pDest + m_pSectionHeader[i].VirtualAddress);
                // 复制段数据到虚拟内存
                memmove((void *)pSectionAddress,
                        (void *)((DWORD)pSrc + m_pSectionHeader[i].PointerToRawData), m_pSectionHeader[i].SizeOfRawData);
        }

        //修正指针,指向新分配的内存
        //新的dos头
        m_pDosHeader = (PIMAGE_DOS_HEADER)pDest;
        //新的pe头地址
        m_pNTHeader = (PIMAGE_NT_HEADERS)((int)pDest + (m_pDosHeader->e_lfanew));
        //新的节表地址
        m_pSectionHeader = (PIMAGE_SECTION_HEADER)((int)m_pNTHeader + sizeof(IMAGE_NT_HEADERS));
}
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条

关闭

小黑屋|TC官方合作论坛 (苏ICP备18045623号)

GMT+8, 2024-9-30 12:56 , Processed in 0.037427 second(s), 18 queries .

Powered by 海安简单软件服务部

© 2008-2019 版权所有 保留所有权利

快速回复 返回顶部 返回列表