吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 914|回复: 6
收起左侧

[学习记录] 驱动方式向进程注入DLL(主要参考国外网友代码)

[复制链接]
syw6616 发表于 2023-3-15 12:06
本帖最后由 syw6616 于 2023-3-15 12:13 编辑

用驱动方式实现DLL注入活动进程,网上有一些教程,但没有完整代码,现把自己学习测试完成的代码完整上传,喜欢的朋友可以参考

/*代码主要参考国外网友的,可在win7 64位系统下使用,win10下没有测试过,测试用的DLL发到回复贴上*/
#include <Ntifs.h>
#include <ntimage.h>
#include <ntstrsafe.h>

#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER      0x00000004


NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process);
NTKERNELAPI PVOID NTAPI PsGetProcessWow64Process(IN PEPROCESS Process);
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL);

typedef NTSTATUS(NTAPI* LPFN_NTCREATETHREADEX)(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN PVOID ObjectAttributes, IN HANDLE ProcessHandle, IN PVOID StartAddress, IN PVOID Parameter, IN ULONG Flags, IN SIZE_T StackZeroBits, IN SIZE_T SizeOfStackCommit, IN SIZE_T SizeOfStackReserve, OUT PVOID ByteBuffer);

typedef struct _INJECT_BUFFER{
        UCHAR Code[0x200];
        union{
                UNICODE_STRING Path;
                UNICODE_STRING32 Path32;
        };

        wchar_t Buffer[488];
        PVOID ModuleHandle;
        ULONG Complete;
        NTSTATUS Status;
} INJECT_BUFFER, *PINJECT_BUFFER;
typedef struct _PEB32{
        UCHAR InheritedAddressSpace;
        UCHAR ReadImageFileExecOptions;
        UCHAR BeingDebugged;
        UCHAR BitField;
        ULONG Mutant;
        ULONG ImageBaseAddress;
        ULONG Ldr;
        ULONG ProcessParameters;
        ULONG SubSystemData;
        ULONG ProcessHeap;
        ULONG FastPebLock;
        ULONG AtlThunkSListPtr;
        ULONG IFEOKey;
        ULONG CrossProcessFlags;
        ULONG UserSharedInfoPtr;
        ULONG SystemReserved;
        ULONG AtlThunkSListPtr32;
        ULONG ApiSetMap;
} PEB32, *PPEB32;
typedef struct _PEB_LDR_DATA{
        ULONG Length;
        UCHAR Initialized;
        PVOID SsHandle;
        LIST_ENTRY InLoadOrderModuleList;
        LIST_ENTRY InMemoryOrderModuleList;
        LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _PEB{
        UCHAR InheritedAddressSpace;
        UCHAR ReadImageFileExecOptions;
        UCHAR BeingDebugged;
        UCHAR BitField;
        PVOID Mutant;
        PVOID ImageBaseAddress;
        PPEB_LDR_DATA Ldr;
        PVOID ProcessParameters;
        PVOID SubSystemData;
        PVOID ProcessHeap;
        PVOID FastPebLock;
        PVOID AtlThunkSListPtr;
        PVOID IFEOKey;
        PVOID CrossProcessFlags;
        PVOID KernelCallbackTable;
        ULONG SystemReserved;
        ULONG AtlThunkSListPtr32;
        PVOID ApiSetMap;
} PEB, *PPEB;
typedef struct _PEB_LDR_DATA32{
        ULONG Length;
        UCHAR Initialized;
        ULONG SsHandle;
        LIST_ENTRY32 InLoadOrderModuleList;
        LIST_ENTRY32 InMemoryOrderModuleList;
        LIST_ENTRY32 InInitializationOrderModuleList;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;
typedef struct _LDR_DATA_TABLE_ENTRY32{
        LIST_ENTRY32 InLoadOrderLinks;
        LIST_ENTRY32 InMemoryOrderLinks;
        LIST_ENTRY32 InInitializationOrderLinks;
        ULONG DllBase;
        ULONG EntryPoint;
        ULONG SizeOfImage;
        UNICODE_STRING32 FullDllName;
        UNICODE_STRING32 BaseDllName;
        ULONG Flags;
        USHORT LoadCount;
        USHORT TlsIndex;
        LIST_ENTRY32 HashLinks;
        ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
typedef struct _LDR_DATA_TABLE_ENTRY{
        LIST_ENTRY InLoadOrderLinks;
        LIST_ENTRY InMemoryOrderLinks;
        LIST_ENTRY InInitializationOrderLinks;
        PVOID DllBase;
        PVOID EntryPoint;
        ULONG SizeOfImage;
        UNICODE_STRING FullDllName;
        UNICODE_STRING BaseDllName;
        ULONG Flags;
        USHORT LoadCount;
        USHORT TlsIndex;
        LIST_ENTRY HashLinks;
        ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef struct _THREAD_BASIC_INFORMATION{
        NTSTATUS ExitStatus;
        PVOID TebBaseAddress;
        CLIENT_ID ClientId;
        ULONG_PTR AffinityMask;
        LONG Priority;
        LONG BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
typedef struct _NT_PROC_THREAD_ATTRIBUTE_ENTRY{
        ULONG Attribute;    // PROC_THREAD_ATTRIBUTE_XXX
        SIZE_T Size;
        ULONG_PTR Value;
        ULONG Unknown;
} NT_PROC_THREAD_ATTRIBUTE_ENTRY, *NT_PPROC_THREAD_ATTRIBUTE_ENTRY;
typedef struct _NT_PROC_THREAD_ATTRIBUTE_LIST{
        ULONG Length;
        NT_PROC_THREAD_ATTRIBUTE_ENTRY Entry[1];
} NT_PROC_THREAD_ATTRIBUTE_LIST, *PNT_PROC_THREAD_ATTRIBUTE_LIST;


//----------------------------------------------------------------------------------------------------------
ULONG GetSSDTRVA(UCHAR *funcname) {

        NTSTATUS Status;
        HANDLE FileHandle;
        IO_STATUS_BLOCK ioStatus;
        FILE_STANDARD_INFORMATION FileInformation;
        //Set NTDLL path
        UNICODE_STRING uniFileName;
        RtlInitUnicodeString(&uniFileName, L"\\SystemRoot\\system32\\ntoskrnl.exe");

        //Initialize the attributes of the open file
        OBJECT_ATTRIBUTES objectAttributes;
        InitializeObjectAttributes(&objectAttributes, &uniFileName,
                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
        ////Create a file

        Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes,
                &ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT,
                NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);
        if (!NT_SUCCESS(Status))
                return 0;
        //Get file information

        Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation,
                sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
        if (!NT_SUCCESS(Status)) {
                ZwClose(FileHandle);
                return 0;
        }
        //Determine whether the file size is too large
        if (FileInformation.EndOfFile.HighPart != 0) {
                ZwClose(FileHandle);
                return 0;
        }
        //Fetch the file size
        ULONG uFileSize = FileInformation.EndOfFile.LowPart;


        //Allocate memory
        PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize + 0x100, (ULONG)"PGu");
        if (pBuffer == NULL) {
                ZwClose(FileHandle);
                return 0;
        }

        //Read the file from the beginning
        LARGE_INTEGER byteOffset;
        byteOffset.LowPart = 0;
        byteOffset.HighPart = 0;
        Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL);
        if (!NT_SUCCESS(Status)) {
                ZwClose(FileHandle);
                return 0;
        }
        //Remove the export table
        PIMAGE_DOS_HEADER  pDosHeader;
        PIMAGE_NT_HEADERS  pNtHeaders;
        PIMAGE_SECTION_HEADER pSectionHeader;
        ULONGLONG FileOffset;//Here are 64 digits, so here is not 32 bytes
        PIMAGE_EXPORT_DIRECTORY pExportDirectory;
        //The DLL memory data is converted into DOS header structure
        pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
        //Remove the PE head structure
        pNtHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)pBuffer + pDosHeader->e_lfanew);
        //Determine whether the PE header export table is empty


        if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
                return 0;

        //Remove the export table offset
        FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

        //Remove the section header structure
        pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONGLONG)pNtHeaders + sizeof(IMAGE_NT_HEADERS));
        PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;
        //Traverse the section structure to perform address calculation
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }

        //Export table address
        pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONGLONG)pBuffer + FileOffset);
        //Remove the export table function address
        PULONG AddressOfFunctions;
        FileOffset = pExportDirectory->AddressOfFunctions;
        //Traverse the section structure to perform address calculation
        pSectionHeader = pOldSectionHeader;
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }
        AddressOfFunctions = (PULONG)((ULONGLONG)pBuffer + FileOffset);//Here we pay attention to foa and rva

        //Remove the name of the export table function
        PUSHORT AddressOfNameOrdinals;
        FileOffset = pExportDirectory->AddressOfNameOrdinals;

        //Traverse the section structure to perform address calculation
        pSectionHeader = pOldSectionHeader;
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }
        AddressOfNameOrdinals = (PUSHORT)((ULONGLONG)pBuffer + FileOffset);//Note foa and rva

        //Remove the serial number of the export table function
        PULONG AddressOfNames;
        FileOffset = pExportDirectory->AddressOfNames;

        //Traverse the section structure to perform address calculation
        pSectionHeader = pOldSectionHeader;
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }
        AddressOfNames = (PULONG)((ULONGLONG)pBuffer + FileOffset);//Note that foa and rva

        //DbgPrint("\n AddressOfFunctions %llX AddressOfNameOrdinals %llX AddressOfNames %llX  \n", (ULONGLONG)AddressOfFunctions- (ULONGLONG)pBuffer, (ULONGLONG)AddressOfNameOrdinals- (ULONGLONG)pBuffer, (ULONGLONG)AddressOfNames- (ULONGLONG)pBuffer);
        //DbgPrint("\n AddressOfFunctions %llX AddressOfNameOrdinals %llX AddressOfNames %llX  \n", pExportDirectory->AddressOfFunctions, pExportDirectory->AddressOfNameOrdinals, pExportDirectory->AddressOfNames);

        //Analyze the export table
        ULONG uNameOffset;
        ULONG uOffset;
        LPSTR FunName;
        ULONG uAddressOfNames;
        ULONG TargetOff = 0;
        for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++) {
                uAddressOfNames = *AddressOfNames;
                pSectionHeader = pOldSectionHeader;
                for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                        if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                                uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
                }
                FunName = (LPSTR)((ULONGLONG)pBuffer + uOffset);
                //DbgPrint("%s\n", FunName);
                if (!_stricmp((const char *)funcname, FunName)) {
                        TargetOff = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];
                        //DbgPrint("index %llX,function name: %s   funcRva %llX \n", *AddressOfNameOrdinals, FunName, TargetOff);
                }

        }

        ExFreePoolWithTag(pBuffer, (ULONG)"PGu");
        ZwClose(FileHandle);
        return TargetOff;
}
//Get the base address of ntos
ULONGLONG GetOsBaseAddress(PDRIVER_OBJECT pDriverObject) {

        UNICODE_STRING osName = { 0 };
        WCHAR wzData[0x100] = L"ntoskrnl.exe";

        RtlInitUnicodeString(&osName, wzData);

        LDR_DATA_TABLE_ENTRY *pDataTableEntry, *pTempDataTableEntry;
        //Double cycle list definition
        PLIST_ENTRY        pList;
        //DriverSection pointing to the drive object
        pDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;
        // judge whether it is empty
        if (!pDataTableEntry)
                return 0;

        /*
        Start traversing the linked list of driven objects
        */
        //Get the linked list address
        pList = pDataTableEntry->InLoadOrderLinks.Flink;

        //Determine whether it is equal to the head
        while (pList != &pDataTableEntry->InLoadOrderLinks) {
                pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY *)pList;
                //DbgPrint("name  :%wZ , dll:%llx\n", &pTempDataTableEntry->BaseDllName, pTempDataTableEntry->DllBase);
                if (RtlEqualUnicodeString(&pTempDataTableEntry->BaseDllName, &osName, TRUE))
                        return (ULONGLONG)pTempDataTableEntry->DllBase;
                pList = pList->Flink;
        }
        return 0;
}
//Get the address of the ssdt exported function

typedef struct _SYSTEM_SERVICE_TABLE {
        PVOID       ServiceTableBase;
        PVOID       ServiceCounterTableBase;
        ULONGLONG   NumberOfServices;
        PVOID       ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
//Get the base address of the ssdt table
ULONGLONG GetKeServiceDescriptorTable64(PDRIVER_OBJECT DriverObject) {

        char KiSystemServiceStart_pattern[14] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";

        ULONGLONG CodeScanStart = GetSSDTRVA((UCHAR *)"_stricmp") + GetOsBaseAddress(DriverObject);//This is the address of the real function

        ULONGLONG i, tbl_address, b;
        for (i = 0; i < 0x50000; i++) {
                if (!memcmp((char*)(ULONGLONG)CodeScanStart + i,
                        (char*)KiSystemServiceStart_pattern, 13)) {

                        for (b = 0; b < 50; b++) {
                                tbl_address = ((ULONGLONG)CodeScanStart + i + b);
                                if (*(USHORT*)((ULONGLONG)tbl_address) == (USHORT)0x8d4c)
                                        return ((LONGLONG)tbl_address + 7) + *(LONG*)(tbl_address + 3);
                        }
                }
        }
        return 0;
}
ULONG GetIndexByName(UCHAR *sdName) {

        NTSTATUS Status;
        HANDLE FileHandle;
        IO_STATUS_BLOCK ioStatus;
        FILE_STANDARD_INFORMATION FileInformation;
        //Set NTDLL path
        UNICODE_STRING uniFileName;
        RtlInitUnicodeString(&uniFileName, L"\\SystemRoot\\system32\\ntdll.dll");

        //Initialize the attributes of the open file
        OBJECT_ATTRIBUTES objectAttributes;
        InitializeObjectAttributes(&objectAttributes, &uniFileName,
                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
        ////Create a file

        Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes,
                &ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT,
                NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);
        if (!NT_SUCCESS(Status))
                return 0;
        //Get file information

        Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation,
                sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
        if (!NT_SUCCESS(Status)) {
                ZwClose(FileHandle);
                return 0;
        }
        //Determine whether the file size is too large
        if (FileInformation.EndOfFile.HighPart != 0) {
                ZwClose(FileHandle);
                return 0;
        }
        //Fetch the file size
        ULONG uFileSize = FileInformation.EndOfFile.LowPart;


        //Allocate memory
        PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize + 0x100, (ULONG)"Ntdl");
        if (pBuffer == NULL) {
                ZwClose(FileHandle);
                return 0;
        }

        //Read the file from the beginning
        LARGE_INTEGER byteOffset;
        byteOffset.LowPart = 0;
        byteOffset.HighPart = 0;
        Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL);
        if (!NT_SUCCESS(Status)) {
                ZwClose(FileHandle);
                return 0;
        }
        //Remove the export table
        PIMAGE_DOS_HEADER  pDosHeader;
        PIMAGE_NT_HEADERS  pNtHeaders;
        PIMAGE_SECTION_HEADER pSectionHeader;
        ULONGLONG FileOffset;//Here are 64 digits, so here is not 32 bytes
        PIMAGE_EXPORT_DIRECTORY pExportDirectory;
        //The DLL memory data is converted into DOS header structure
        pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
        //Remove the PE head structure
        pNtHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)pBuffer + pDosHeader->e_lfanew);
        //Determine whether the PE header export table is empty


        if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
                return 0;

        //Remove the export table offset
        FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

        //Remove the section header structure
        pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONGLONG)pNtHeaders + sizeof(IMAGE_NT_HEADERS));
        PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;
        //Traverse the section structure to perform address calculation
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }

        //Export table address
        pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONGLONG)pBuffer + FileOffset);
        //Remove the export table function address
        PULONG AddressOfFunctions;
        FileOffset = pExportDirectory->AddressOfFunctions;
        //Traverse the section structure to perform address calculation
        pSectionHeader = pOldSectionHeader;
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }
        AddressOfFunctions = (PULONG)((ULONGLONG)pBuffer + FileOffset);//Here we pay attention to foa and rva

        //Remove the name of the export table function
        PUSHORT AddressOfNameOrdinals;
        FileOffset = pExportDirectory->AddressOfNameOrdinals;

        //Traverse the section structure to perform address calculation
        pSectionHeader = pOldSectionHeader;
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }
        AddressOfNameOrdinals = (PUSHORT)((ULONGLONG)pBuffer + FileOffset);//Note foa and rva

        //Remove the serial number of the export table function
        PULONG AddressOfNames;
        FileOffset = pExportDirectory->AddressOfNames;

        //Traverse the section structure to perform address calculation
        pSectionHeader = pOldSectionHeader;
        for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                        FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
        }
        AddressOfNames = (PULONG)((ULONGLONG)pBuffer + FileOffset);//Note that foa and rva

        //DbgPrint("\n AddressOfFunctions %llX AddressOfNameOrdinals %llX AddressOfNames %llX  \n", (ULONGLONG)AddressOfFunctions- (ULONGLONG)pBuffer, (ULONGLONG)AddressOfNameOrdinals- (ULONGLONG)pBuffer, (ULONGLONG)AddressOfNames- (ULONGLONG)pBuffer);
        //DbgPrint("\n AddressOfFunctions %llX AddressOfNameOrdinals %llX AddressOfNames %llX  \n", pExportDirectory->AddressOfFunctions, pExportDirectory->AddressOfNameOrdinals, pExportDirectory->AddressOfNames);

        //Analyze the export table
        ULONG uNameOffset;
        ULONG uOffset;
        LPSTR FunName;
        PVOID pFuncAddr;
        ULONG uServerIndex;
        ULONG uAddressOfNames;
        for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++) {
                uAddressOfNames = *AddressOfNames;
                pSectionHeader = pOldSectionHeader;
                for (UINT32 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                        if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                                uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
                }
                FunName = (LPSTR)((ULONGLONG)pBuffer + uOffset);
                if (FunName[0] == 'Z' && FunName[1] == 'w') {
                        pSectionHeader = pOldSectionHeader;
                        uOffset = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];
                        for (UINT32 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {
                                if (pSectionHeader->VirtualAddress <= uOffset && uOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                                        uNameOffset = uOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
                        }
                        pFuncAddr = (PVOID)((ULONGLONG)pBuffer + uNameOffset);
                        uServerIndex = *(PULONG)((ULONGLONG)pFuncAddr + 4);
                        FunName[0] = 'N';
                        FunName[1] = 't';
                        if (!_stricmp(FunName, (const char *)sdName)) {//Get the specified number
                                ExFreePoolWithTag(pBuffer, (ULONG)"Ntdl");
                                ZwClose(FileHandle);
                                return uServerIndex;
                        }
                }
        }

        ExFreePoolWithTag(pBuffer, (ULONG)"Ntdl");
        ZwClose(FileHandle);
        return 0;
}
ULONGLONG GetSSDTFuncCurAddr(ULONG id) {
        /*
        mov rax, rcx; rcx=Native API index
        lea r10,[rdx] ;rdx=ssdt base address
        mov edi,eax ;index
        shr edi,7
        and edi,20h
        mov r10, qword ptr [r10+rdi]//Get ServiceTableBase here
        movsxd r11,dword ptr [r10+rax]//I get the address of the fake ssdt without right shift here
        mov rax,r11
        sar r11,4
        add r10,r11
        mov rax,r10
        ret
        */
        LONG dwtmp = 0;
        PULONG ServiceTableBase = NULL;
        ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
        dwtmp = ServiceTableBase[id];
        dwtmp = dwtmp >> 4;
        return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;//You need to shift right by 4 bits and add the base address to get the address of ssdt
}
//----------------------------------------------------------------------------------------------------------

//Start thread
NTSTATUS NTAPI SeCreateThreadEx(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN PVOID ObjectAttributes, IN HANDLE ProcessHandle, IN PVOID StartAddress, IN PVOID Parameter, IN ULONG Flags, IN SIZE_T StackZeroBits, IN SIZE_T SizeOfStackCommit, IN SIZE_T SizeOfStackReserve, IN PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList){
        NTSTATUS Status = STATUS_SUCCESS;
        LPFN_NTCREATETHREADEX NtCreateThreadEx = (LPFN_NTCREATETHREADEX)(GetSSDTFuncCurAddr(GetIndexByName((UCHAR *)"NtCreateThreadEx")));

        //DbgPrint("adddress %llX       staredaddress    %llX     \n", NtCreateThreadEx, StartAddress);

        if (NtCreateThreadEx){
                //If the previous mode is user mode, the address passed to ZwCreateThreadEx must be in user mode space
                //Switch to kernel mode allows to use kernel mode address
                //Windows10 PrevMode = 0x232
                /*
                +0x1c8 Win32Thread      : Ptr64 Void
                + 0x140 WaitBlockFill11 : [176] UChar
                + 0x1f0 Ucb : Ptr64 _UMS_CONTROL_BLOCK
                + 0x1f8 Uch : Ptr64 _KUMS_CONTEXT_HEADER
                + 0x200 Spare21 : Ptr64 Void
                + 0x208 QueueListEntry : _LIST_ENTRY
                + 0x218 NextProcessor : Uint4B
                + 0x218 NextProcessorNumber : Pos 0, 31 Bits
                + 0x218 SharedReadyQueue : Pos 31, 1 Bit
                + 0x21c QueuePriority : Int4B
                + 0x220 Process : Ptr64 _KPROCESS
                + 0x228 UserAffinity : _GROUP_AFFINITY
                + 0x228 UserAffinityFill : [10] UChar
                + 0x232 PreviousMode : Char
                */
                PUCHAR pPrevMode = (PUCHAR)PsGetCurrentThread() + 0x232;
                //64-bit pPrevMode = 01
                UCHAR prevMode = *pPrevMode;
                *pPrevMode = KernelMode;//Kernel mode

                //Create thread
                Status = NtCreateThreadEx(
                        ThreadHandle, DesiredAccess, ObjectAttributes,
                        ProcessHandle, StartAddress, Parameter,
                        Flags, StackZeroBits, SizeOfStackCommit,
                        SizeOfStackReserve, AttributeList
                        );
                //Restore the previous thread mode
                *pPrevMode = prevMode;
        }
        else
                Status = STATUS_NOT_FOUND;

        return Status;
}

//Execution thread
NTSTATUS ExecuteInNewThread(IN PVOID BaseAddress, IN PVOID Parameter, IN ULONG Flags, IN BOOLEAN Wait, OUT PNTSTATUS ExitStatus){
        HANDLE ThreadHandle = NULL;
        OBJECT_ATTRIBUTES ObjectAttributes = { 0 };
        //Initialize object properties
        InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

        //Create thread
        NTSTATUS Status = SeCreateThreadEx(
                &ThreadHandle, THREAD_QUERY_LIMITED_INFORMATION, &ObjectAttributes,
                ZwCurrentProcess(), BaseAddress, Parameter, Flags,
                0, 0x1000, 0x100000, NULL
                );//The thread start is successful here


        // Wait for the thread to complete
        if (NT_SUCCESS(Status) && Wait != FALSE) {
                //60s
                LARGE_INTEGER Timeout = { 0 };
                Timeout.QuadPart = -(60ll * 10 * 1000 * 1000);

                Status = ZwWaitForSingleObject(ThreadHandle, TRUE, &Timeout);
                if (NT_SUCCESS(Status)) {
                        //Query thread exit code
                        THREAD_BASIC_INFORMATION ThreadBasicInfo = { 0 };
                        ULONG ReturnLength = 0;

                        Status = ZwQueryInformationThread(ThreadHandle, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), &ReturnLength);
                        if (NT_SUCCESS(Status) && ExitStatus)
                                *ExitStatus = ThreadBasicInfo.ExitStatus;//Here is to query whether the current dll injection is successful
                        else if (!NT_SUCCESS(Status))
                                DbgPrint("%s: ZwQueryInformationThread failed with status 0x%X\n", __FUNCTION__, Status);
                }
                else
                        DbgPrint("%s: ZwWaitForSingleObject failed with status 0x%X\n", __FUNCTION__, Status);
        }
        else
                DbgPrint("%s: ZwCreateThreadEx failed with status 0x%X\n", __FUNCTION__, Status);

        if (ThreadHandle)
                ZwClose(ThreadHandle);

        return Status;
}

//Create injection code 64-bit target process
PINJECT_BUFFER GetNativeCode(IN PVOID LdrLoadDll, IN PUNICODE_STRING DllFullPath) {
        NTSTATUS Status = STATUS_SUCCESS;
        PINJECT_BUFFER InjectBuffer = NULL;//This structure is customized
        SIZE_T Size = PAGE_SIZE;

        UCHAR Code[] = {
                0x48, 0x83, 0xEC, 0x28,                 // sub rsp, 0x28
                0x48, 0x31, 0xC9,                       // xor rcx, rcx
                0x48, 0x31, 0xD2,                       // xor rdx, rdx
                0x49, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,     // mov r8, ModuleFileName   offset +12
                0x49, 0xB9, 0, 0, 0, 0, 0, 0, 0, 0,     // mov r9, ModuleHandle     offset +28
                0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0,     // mov rax, LdrLoadDll      offset +32
                0xFF, 0xD0,                             // call rax
                0x48, 0xBA, 0, 0, 0, 0, 0, 0, 0, 0,     // mov rdx, COMPLETE_OFFSET offset +44
                0xC7, 0x02, 0x7E, 0x1E, 0x37, 0xC0,     // mov [rdx], CALL_COMPLETE
                0x48, 0xBA, 0, 0, 0, 0, 0, 0, 0, 0,     // mov rdx, STATUS_OFFSET   offset +60
                0x89, 0x02,                             // mov [rdx], eax
                0x48, 0x83, 0xC4, 0x28,                 // add rsp, 0x28
                0xC3                                    // ret
        };

        Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &InjectBuffer, 0, &Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (NT_SUCCESS(Status)) {
                PUNICODE_STRING UserPath = &InjectBuffer->Path;
                UserPath->Length = 0;
                UserPath->MaximumLength = sizeof(InjectBuffer->Buffer);
                UserPath->Buffer = InjectBuffer->Buffer;

                RtlUnicodeStringCopy(UserPath, DllFullPath);

                // Copy code
                memcpy(InjectBuffer, Code, sizeof(Code));

                // Fill stubs
                *(ULONGLONG*)((PUCHAR)InjectBuffer + 12) = (ULONGLONG)UserPath;
                *(ULONGLONG*)((PUCHAR)InjectBuffer + 22) = (ULONGLONG)&InjectBuffer->ModuleHandle;
                *(ULONGLONG*)((PUCHAR)InjectBuffer + 32) = (ULONGLONG)LdrLoadDll;
                *(ULONGLONG*)((PUCHAR)InjectBuffer + 44) = (ULONGLONG)&InjectBuffer->Complete;
                *(ULONGLONG*)((PUCHAR)InjectBuffer + 60) = (ULONGLONG)&InjectBuffer->Status;

                return InjectBuffer;
        }

        UNREFERENCED_PARAMETER(DllFullPath);
        return NULL;
}

//Create injection code 32-bit target process
PINJECT_BUFFER GetWow64Code(IN PVOID LdrLoadDll, IN PUNICODE_STRING DllFullPath) {
        NTSTATUS Status = STATUS_SUCCESS;
        PINJECT_BUFFER InjectBuffer = NULL;
        SIZE_T Size = PAGE_SIZE;

        // Code
        UCHAR Code[] = {
                0x68, 0, 0, 0, 0,                       // push ModuleHandle            offset +1
                0x68, 0, 0, 0, 0,                       // push ModuleFileName          offset +6
                0x6A, 0,                                // push Flags  
                0x6A, 0,                                // push PathToFile
                0xE8, 0, 0, 0, 0,                       // call LdrLoadDll              offset +15
                0xBA, 0, 0, 0, 0,                       // mov edx, COMPLETE_OFFSET     offset +20
                0xC7, 0x02, 0x7E, 0x1E, 0x37, 0xC0,     // mov [edx], CALL_COMPLETE     
                0xBA, 0, 0, 0, 0,                       // mov edx, STATUS_OFFSET       offset +31
                0x89, 0x02,                             // mov [edx], eax
                0xC2, 0x04, 0x00                        // ret 4
        };

        Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &InjectBuffer, 0, &Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (NT_SUCCESS(Status)) {
                // Copy path
                PUNICODE_STRING32 pUserPath = &InjectBuffer->Path32;
                pUserPath->Length = DllFullPath->Length;
                pUserPath->MaximumLength = DllFullPath->MaximumLength;
                pUserPath->Buffer = (ULONG)(ULONG_PTR)InjectBuffer->Buffer;

                // Copy path
                memcpy((PVOID)pUserPath->Buffer, DllFullPath->Buffer, DllFullPath->Length);

                // Copy code
                memcpy(InjectBuffer, Code, sizeof(Code));

                // Fill stubs
                *(ULONG*)((PUCHAR)InjectBuffer + 1) = (ULONG)(ULONG_PTR)&InjectBuffer->ModuleHandle;//This parameter is an output parameter, return handle
                *(ULONG*)((PUCHAR)InjectBuffer + 6) = (ULONG)(ULONG_PTR)pUserPath;
                *(ULONG*)((PUCHAR)InjectBuffer + 15) = (ULONG)((ULONG_PTR)LdrLoadDll - ((ULONG_PTR)InjectBuffer + 15) - 5 + 1);
                *(ULONG*)((PUCHAR)InjectBuffer + 20) = (ULONG)(ULONG_PTR)&InjectBuffer->Complete;//This is useless, this is a fixed value, it may be to check whether the current execution is here, integrity check ? From the name
                *(ULONG*)((PUCHAR)InjectBuffer + 31) = (ULONG)(ULONG_PTR)&InjectBuffer->Status;

                return InjectBuffer;
        }

        UNREFERENCED_PARAMETER(DllFullPath);
        return NULL;
}

//Get module export function
PVOID GetModuleExport(IN PVOID ModuleBase, IN PCCHAR FunctionName, IN PEPROCESS EProcess) {
        PIMAGE_DOS_HEADER ImageDosHeader = (PIMAGE_DOS_HEADER)ModuleBase;
        PIMAGE_NT_HEADERS32 ImageNtHeaders32 = NULL;
        PIMAGE_NT_HEADERS64 ImageNtHeaders64 = NULL;
        PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = NULL;
        ULONG ExportDirectorySize = 0;
        ULONG_PTR FunctionAddress = 0;

        if (ModuleBase == NULL)
                return NULL;

        if (ImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
                return NULL;
        }
        ImageNtHeaders32 = (PIMAGE_NT_HEADERS32)((PUCHAR)ModuleBase + ImageDosHeader->e_lfanew);
        ImageNtHeaders64 = (PIMAGE_NT_HEADERS64)((PUCHAR)ModuleBase + ImageDosHeader->e_lfanew);

        if (ImageNtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
                ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ImageNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)ModuleBase);
                ExportDirectorySize = ImageNtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
        }
        else {
                ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(ImageNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)ModuleBase);
                ExportDirectorySize = ImageNtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
        }
        PUSHORT pAddressOfOrds = (PUSHORT)(ImageExportDirectory->AddressOfNameOrdinals + (ULONG_PTR)ModuleBase);
        PULONG  pAddressOfNames = (PULONG)(ImageExportDirectory->AddressOfNames + (ULONG_PTR)ModuleBase);
        PULONG  pAddressOfFuncs = (PULONG)(ImageExportDirectory->AddressOfFunctions + (ULONG_PTR)ModuleBase);

        for (ULONG i = 0; i < ImageExportDirectory->NumberOfFunctions; ++i) {
                USHORT OrdIndex = 0xFFFF;
                PCHAR  pName = NULL;
                // Find by index
                if ((ULONG_PTR)FunctionName <= 0xFFFF) {
                        OrdIndex = (USHORT)i;
                }
                // Find by name
                else if ((ULONG_PTR)FunctionName > 0xFFFF && i < ImageExportDirectory->NumberOfNames) {
                        pName = (PCHAR)(pAddressOfNames + (ULONG_PTR)ModuleBase);
                        OrdIndex = pAddressOfOrds;
                }
                // Weird params
                else
                        return NULL;
                if (((ULONG_PTR)FunctionName <= 0xFFFF && (USHORT)((ULONG_PTR)FunctionName) == OrdIndex + ImageExportDirectory->Base) ||
                        ((ULONG_PTR)FunctionName > 0xFFFF && strcmp(pName, FunctionName) == 0)) {
                        FunctionAddress = pAddressOfFuncs[OrdIndex] + (ULONG_PTR)ModuleBase;
                        break;
                }
        }
        return (PVOID)FunctionAddress;
}

//Get user module
PVOID GetUserModule(IN PEPROCESS EProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN IsWow64) {
        if (EProcess == NULL)
                return NULL;
        __try {
                LARGE_INTEGER Time = { 0 };
                Time.QuadPart = -250ll * 10 * 1000;                        //250 ms.
                if (IsWow64) {
                        PPEB32 Peb32 = (PPEB32)PsGetProcessWow64Process(EProcess);
                        if (Peb32 == NULL) {
                                DbgPrint("%s: No PEB present. Aborting\n", __FUNCTION__);
                                return NULL;
                        }
                        for (INT i = 0; !Peb32->Ldr && i <10; i++) {//This should be the reason for lazy loading, it may not be updated in time, so it will wait
                                DbgPrint(" %s: Loader not intialiezd, waiting\n", __FUNCTION__);
                                KeDelayExecutionThread(KernelMode, TRUE, &Time);
                        }
                        // Still no loader
                        if (!Peb32->Ldr) {
                                DbgPrint(" %s: Loader was not intialiezd in time. Aborting\n", __FUNCTION__);
                                return NULL;
                        }
                        // Search in InLoadOrderModuleList
                        for (PLIST_ENTRY32 ListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList.Flink;
                                ListEntry != &((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList;
                                ListEntry = (PLIST_ENTRY32)ListEntry->Flink) {
                                UNICODE_STRING UnicodeString;
                                PLDR_DATA_TABLE_ENTRY32 LdrDataTableEntry32 = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
                                RtlUnicodeStringInit(&UnicodeString, (PWCH)LdrDataTableEntry32->BaseDllName.Buffer);
                                if (RtlCompareUnicodeString(&UnicodeString, ModuleName, TRUE) == 0)
                                        return (PVOID)LdrDataTableEntry32->DllBase;
                        }
                }
                else {
                        PPEB Peb = PsGetProcessPeb(EProcess);
                        if (!Peb) {
                                DbgPrint("%s: No PEB present. Aborting\n", __FUNCTION__);
                                return NULL;
                        }
                        for (INT i = 0; !Peb->Ldr && i < 10; i++) {

                                DbgPrint("%s: Loader not intialiezd, waiting\n", __FUNCTION__);
                                KeDelayExecutionThread(KernelMode, TRUE, &Time);
                        }
                        if (!Peb->Ldr) {
                                DbgPrint("%s: Loader was not intialiezd in time. Aborting\n", __FUNCTION__);
                                return NULL;
                        }

                        //Traverse the linked list
                        for (PLIST_ENTRY ListEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
                                ListEntry != &Peb->Ldr->InLoadOrderModuleList;
                                ListEntry = ListEntry->Flink) {
                                PLDR_DATA_TABLE_ENTRY LdrDataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
                                if (RtlCompareUnicodeString(&LdrDataTableEntry->BaseDllName, ModuleName, TRUE) == 0)
                                        return LdrDataTableEntry->DllBase;
                        }
                }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
                DbgPrint("%s: Exception, Code: 0x%X\n", __FUNCTION__, GetExceptionCode());
        }

        return NULL;
}

//Switch to the target process to create a kernel thread for injection, mainly the switch of cr3
NTSTATUS AttachAndInjectProcess(IN HANDLE ProcessID) {
        PEPROCESS EProcess = NULL;
        KAPC_STATE ApcState;
        NTSTATUS Status = STATUS_SUCCESS;

        if (ProcessID == NULL) {
                Status = STATUS_UNSUCCESSFUL;
                return Status;
        }
        //Get EProcess
        Status = PsLookupProcessByProcessId(ProcessID, &EProcess);
        if (Status != STATUS_SUCCESS) {
                DbgPrint("PsLookupProcessByProcessId  Failed\n");
                return Status;
        }
        //Judge the target process x86 or x64
        BOOLEAN IsWow64 = (PsGetProcessWow64Process(EProcess) != NULL) ? TRUE : FALSE;

        //KeStackAttachProcess routine connects the current thread to the address space of the target process.
        KeStackAttachProcess((PRKPROCESS)EProcess, &ApcState);
        __try {
                PVOID NtdllAddress = NULL;
                PVOID LdrLoadDll = NULL;
                UNICODE_STRING NtdllUnicodeString = { 0 };
                UNICODE_STRING DllFullPath = { 0 };

                //Get the base address of the ntdll module
                RtlInitUnicodeString(&NtdllUnicodeString, L"Ntdll.dll");
                NtdllAddress = GetUserModule(EProcess, &NtdllUnicodeString, IsWow64);//This mainly gets the base address of the specified string dll
                if (!NtdllAddress) {
                        DbgPrint("%s: Failed to get Ntdll base\n", __FUNCTION__);
                        Status = STATUS_NOT_FOUND;
                }

                //Get LdrLoadDll
                if (NT_SUCCESS(Status)) {
                        LdrLoadDll = GetModuleExport(NtdllAddress, "LdrLoadDll", EProcess);
                        if (!LdrLoadDll) {
                                DbgPrint("%s: Failed to get LdrLoadDll address\n", __FUNCTION__);
                                Status = STATUS_NOT_FOUND;
                        }
                }
                PINJECT_BUFFER InjectBuffer = NULL;

        //        PVOID pDLLpath32 = L"C:\\vs2013\\testdll\\Debug\\testdll32.dll";
        //        PVOID pDLLpath64 = L"C:\\vs2013\\testdll\\x64\\Debug\\testdll64.dll";

                if (IsWow64) {//Write your own dll path here
                        RtlInitUnicodeString(&DllFullPath, L"G:\\vs2013\\testdll\\Debug\\testdll32.dll");//<------- here is changed to the dll you want to inject
                        InjectBuffer = GetWow64Code(LdrLoadDll, &DllFullPath);
                }
                else {
                        RtlInitUnicodeString(&DllFullPath, L"G:\\vs2013\\testdll\\x64\\Debug\\testdll64.dll");//<------- here is changed to the dll you want to inject
                        InjectBuffer = GetNativeCode(LdrLoadDll, &DllFullPath);//Build your own shellcode here, write to memory to load dll
                }

                ExecuteInNewThread(InjectBuffer, NULL, THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, TRUE, &Status);//Create a thread and execute the constructed shellcode

                if (!NT_SUCCESS(Status)) {
                        DbgPrint("ExecuteInNewThread Failed\n");
                }

        }
        __except (EXCEPTION_EXECUTE_HANDLER) {

                Status = STATUS_UNSUCCESSFUL;
        }
        KeUnstackDetachProcess(&ApcState);
        //Release EProcess
        ObDereferenceObject(EProcess);
        return Status;
}


VOID Unload(PDRIVER_OBJECT pDriverObj) {


        DbgPrint("See you! \n");
}



NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath) {
        DriverObject->DriverUnload = Unload;


        KeServiceDescriptorTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64(DriverObject);
        AttachAndInjectProcess((HANDLE)7944);//选定一个已经找开的应用程序,填入进程号,编译生成驱动后再加载启动,即可弹出注入DLL中的窗口提示。



        return STATUS_SUCCESS;
}

inject.png

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| syw6616 发表于 2023-3-15 12:09
/*test.dll  代码*/

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <Windows.h>

using doFun = void(*)();
void fun() {
        MessageBoxA(NULL, "千辛万苦,想尽办法,注入成功!", "提示", MB_OK);
        auto handle = GetModuleHandle(L"ntdll.dll");
//        auto addr = GetProcAddress(handle, "DbgBreakPoint");
//        (doFun)addr();
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
                fun();
                break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

L59452027 发表于 2023-3-15 14:50
bnjzzheng 发表于 2023-3-15 15:05
FeiChang21 发表于 2023-3-15 19:24
谢谢分享
gailium 发表于 2023-3-16 07:09
驱动方式注入会过不了签名吗
 楼主| syw6616 发表于 2023-3-16 08:13
我是驱动编译完成后签名一次即可
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止回复与主题无关非技术内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-23 19:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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