看流星社区

 找回密码
 注册账号
查看: 2131|回复: 0

驱动 进程回调中修改导入表插入DLL (只做了一点儿修正不算原创)

[复制链接]

该用户从未签到

发表于 2017-6-3 11:06:41 | 显示全部楼层 |阅读模式

//虽然现在对很多程序的注入都一点儿问题 ,不过一般的程序还是能注入的 最好建议使用zwCreateThreadEX来注入 好处你懂的= =我修正了判断EXE名字 因为 直接用PsGetImageFileNmae 会获取名字不完整因为某结构中只保存了16 char的 内容 不同系统 还不一样= = 所有就用这个 还有就是 卸载驱动会蓝屏= =因为 系统在回调数组中找到了指向我们这里回调函数的指针 却无法调用 所以蓝屏= =因为回调中已经在 上下文 只需要 keattachstack....
//通用WIN8.1-WIN8-WIN7-WINXP#include <ntifs.h>
#include <windef.h>
// 进程名
NTKERNELAPI
UCHAR *
PsGetProcessImageFileName(
__in PEPROCESS Process
);


typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;

typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader; // 0x18
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
// 输入表
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;


typedef struct _IMAGE_THUNK_DATA {
union {
PDWORD Function;
PIMAGE_IMPORT_BY_NAME AddressOfData;
} u1;
} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;

PIMAGE_IMPORT_DESCRIPTOR g_psaveDes = NULL;
PVOID g_eprocess = NULL;
ULONG g_ulPid = 0;

ULONG ulBaseImage;
ULONG oldCr0;
PIMAGE_DOS_HEADER pDos;
PIMAGE_NT_HEADERS pHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
PVOID lpBuffer = NULL;
PVOID lpDllName = NULL;
PVOID lpExportApi = NULL;
PVOID lpTemp = NULL;
PVOID lpTemp2=NULL;
VOID Start (
IN PUNICODE_STRING FullImageName,
IN HANDLE ProcessId, // where image is mapped
IN PIMAGE_INFO ImageInfo
)
{
NTSTATUS ntStatus;
PIMAGE_IMPORT_DESCRIPTOR pImportNew;
HANDLE hProcessHandle;
int nImportDllCount = 0;
int size;

// PID改变时,可以说明已经注入DLL了。
if(g_ulPid != (ULONG)ProcessId &amp;&amp; g_ulPid != 0 &amp;&amp; g_psaveDes != NULL)
{
KAPC_STATE apcState;
BOOLEAN bAttached = FALSE;
//_asm int 3;
if(g_psaveDes!= NULL)
{
if(PsGetCurrentProcess() != g_eprocess) {
KeStackAttachProcess((PRKPROCESS)g_eprocess, &amp;apcState);
bAttached = TRUE;
}
//
__asm {
cli;
mov eax, cr0;
mov oldCr0, eax;
and eax, not 10000h;
mov cr0, eax
}
// 改导出表
pHeader->OptionalHeader.DataDirectory[1].Size -= sizeof(IMAGE_IMPORT_DESCRIPTOR);
pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)g_psaveDes - ulBaseImage;
__asm {
mov eax, oldCr0;
mov cr0, eax;
sti;
}
g_psaveDes = NULL;
if(bAttached)
KeUnstackDetachProcess(&amp;apcState);

}

return ;
}
// 注入进程没退出。
if(g_eprocess != NULL)
return;
KdPrint((PsGetProcessImageFileName(PsGetCurrentProcess())));
if(wcsstr(FullImageName->Buffer,L"calc.exe")!=NULL)
{
//_asm int 3;
g_eprocess = PsGetCurrentProcess();
g_ulPid = (ULONG )ProcessId;

ulBaseImage = (ULONG)ImageInfo->ImageBase;// 进程基地址
pDos =(PIMAGE_DOS_HEADER) ulBaseImage;
pHeader = (PIMAGE_NT_HEADERS)(ulBaseImage+(ULONG)pDos->e_lfanew);
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)pHeader->OptionalHeader.DataDirectory[1].VirtualAddress + ulBaseImage);

// 导入DLL个数
nImportDllCount = pHeader->OptionalHeader.DataDirectory[1].Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
// 把原始值保存。
g_psaveDes = pImportDesc;

ntStatus = ObOpenObjectByPointer(g_eprocess, OBJ_KERNEL_HANDLE, NULL, 0x008, //PROCESS_VM_OPERATION
NULL, KernelMode, &amp;hProcessHandle);
if(!NT_SUCCESS(ntStatus))
return ;
//加上一个自己的结构。
size = sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nImportDllCount + 1);
// 分配导入表
ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &amp;lpBuffer, 0, &amp;size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!NT_SUCCESS(ntStatus)) {
ZwClose(hProcessHandle);
return ;
}
RtlZeroMemory(lpBuffer,sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nImportDllCount + 1));
size = 20;
// 分配当前进程空间。
ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &amp;lpDllName, 0, &amp;size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!NT_SUCCESS(ntStatus)) {
ZwClose(hProcessHandle);
return ;
}
RtlZeroMemory(lpDllName,20);

/* 分配导出函数的进程地址空间。
注意这里是分配高位地址的。如分配低位地址,得到PIMAGE_IMPORT_BY_NAME结构的地址会以,如ff等开头的负数地址,
这样,系统就会默认按序号查找API地址,会弹出找不到序号的框框。
*/
size = 20;
ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &amp;lpExportApi, 0, &amp;size,
MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
if(!NT_SUCCESS(ntStatus)) {
ZwClose(hProcessHandle);
return ;
}
RtlZeroMemory(lpExportApi,20);
// 分配当前进程空间。
size = 20;
ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &amp;lpTemp, 0, &amp;size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!NT_SUCCESS(ntStatus)) {
ZwClose(hProcessHandle);
return ;
}
RtlZeroMemory(lpTemp,20);
// 分配当前进程空间。
size = 20;
ntStatus = ZwAllocateVirtualMemory(hProcessHandle, &amp;lpTemp2, 0, &amp;size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(!NT_SUCCESS(ntStatus)) {
ZwClose(hProcessHandle);
return ;
}
RtlZeroMemory(lpTemp2,20);

pImportNew = lpBuffer;
// 把原来数据保存好。
RtlCopyMemory(pImportNew+1, pImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nImportDllCount );

// 构造自己的DLL IMAGE_IMPORT_DESCRIPTOR结构
{
IMAGE_IMPORT_DESCRIPTOR Add_ImportDesc;
PULONG ulAddress;
ULONG oldCr0;
ULONG Func;
PIMAGE_IMPORT_BY_NAME ptmp;
IMAGE_THUNK_DATA*pThunkData=(PIMAGE_THUNK_DATA)lpTemp2;

//_asm int 3;
//
// ThunkData结构的地址
//
ptmp=(PIMAGE_IMPORT_BY_NAME)lpExportApi;
ptmp->Hint=0;
// 至少要一个导出API
RtlCopyMemory(ptmp->Name,"ExportedFunction",18);
*(PULONG)lpTemp =(DWORD)ptmp-ulBaseImage;
pThunkData->u1.AddressOfData=(DWORD)ptmp-ulBaseImage;
//pThunkData[1].u1.AddressOfData=0;//导出函数截断
Add_ImportDesc.Characteristics = (DWORD)pThunkData-ulBaseImage;
Add_ImportDesc.TimeDateStamp = 0;
Add_ImportDesc.ForwarderChain = 0;
//
// DLL名字的RVA
//
RtlCopyMemory(lpDllName,"q.dll",20);
Add_ImportDesc.Name = (DWORD)lpDllName-ulBaseImage;
Add_ImportDesc.FirstThunk = Add_ImportDesc.Characteristics;

RtlCopyMemory(pImportNew, &amp;Add_ImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));


__asm {
cli;
mov eax, cr0;
mov oldCr0, eax;
and eax, not 10000h;
mov cr0, eax
}
// 改导出表
pHeader->OptionalHeader.DataDirectory[1].Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)pImportNew - ulBaseImage;

__asm {
mov eax, oldCr0;
mov cr0, eax;
sti;
}
}
ZwClose(hProcessHandle);
hProcessHandle = NULL;
}
}

VOID ProcessExitRoutine (
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
)
{
PVOID eprocess = NULL;
NTSTATUS ntStatus;

ntStatus = PsLookupProcessByProcessId(ProcessId, (PEPROCESS*)&amp;eprocess);
if(!NT_SUCCESS(ntStatus))
return;
if(!Create)
{

if(eprocess == g_eprocess)
{
//_asm int 3;
if(g_psaveDes != NULL )
{
__asm {
cli;
mov eax, cr0;
mov oldCr0, eax;
and eax, not 10000h;
mov cr0, eax
}
// 改导出表
pHeader->OptionalHeader.DataDirectory[1].Size -= sizeof(IMAGE_IMPORT_DESCRIPTOR);
pHeader->OptionalHeader.DataDirectory[1].VirtualAddress = (ULONG)g_psaveDes - ulBaseImage;
__asm {
mov eax, oldCr0;
mov cr0, eax;
sti;
}
g_psaveDes = NULL;
}
// 标志注入进程已经关闭了。
g_eprocess = NULL;
}
}
ObDereferenceObject(eprocess);
}

void DriverUnload(PDRIVER_OBJECT obj){
PsRemoveLoadImageNotifyRoutine(Start);
PsSetCreateProcessNotifyRoutine(ProcessExitRoutine, TRUE);
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{

PsSetLoadImageNotifyRoutine(Start);
PsSetCreateProcessNotifyRoutine(ProcessExitRoutine, FALSE);
DriverObject->DriverUnload=DriverUnload;
return STATUS_SUCCESS;
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 13:20

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

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