[分享]重读老文章:DLL注入的又一个梗
上回的梗是APC,但是遗憾的是不支持x64,而且嵌入会被某些15年战斗力的人鄙视~
那么这回的梗要高端大气一点了~,可以支持x64,而且没有汇编~
其实说白了就是靠传说中的KeUserModeCallBack调用来搞定的~
而且不是用KeUserModeCallBack注入shellcode,而是直接调用内核层的ClientLoadlibrary实现~其实更懒的方法是直接找到Win32k.sys里的那个

这里提一下比较好玩的地方主要是KeUserModeCallBack的参数,这里我偷了个懒,使用了小技巧的方式来进行参数初始化
具体代码如下
NTSYSAPI NTSTATUS NTAPI
KeUserModeCallback(
IN ULONG ApiNumber,
IN PVOID InputBuffer,
IN ULONG InputLength,
OUT PVOID *OutputBuffer,
IN PULONG OutputLength
);
typedef struct _CLientLoadLibraryParam
{
DWORD dwSize;//+0
DWORD dwStringLength; //+4
DWORD ReservedZero1;//+8
DWORD ReservedZero2;//+C
DWORD ReservedZero3;//+10
DWORD ReservedZero4;//+14
DWORD ReservedZero5;//+18 () +1A () //不需要!
DWORD ptrDllString;//+1C
DWORD ReservedZero6;//+20
DWORD ptrApiString;//+24
WCHAR szDllName[MAX_PATH];
WCHAR szApiName[MAX_PATH];
}CLientLoadLibraryParam,*PCLientLoadLibraryParam;
NTSTATUS InjectDll(LPCWSTR lpszDll,LPCWSTR lpszApi)
{
PVOID Return;
ULONG RetLen;
PVOID BaseAddress = NULL;
SIZE_T size = sizeof(CLientLoadLibraryParam);
NTSTATUS ns;
ns = ZwAllocateVirtualMemory(NtCurrentProcess(),
&BaseAddress,
0,
&size,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (NT_SUCCESS(ns))
{
PCLientLoadLibraryParam p = (PCLientLoadLibraryParam)BaseAddress;
RtlZeroMemory(p,sizeof(CLientLoadLibraryParam));
p->dwSize = sizeof(CLientLoadLibraryParam);
p->ReservedZero4 = 1;//这样子就是平滑模式了!
wcsncpy(p->szApiName,lpszApi,MAX_PATH);
wcsncpy(p->szDllName,lpszDll,MAX_PATH);
p->ptrApiString = (DWORD)p->szApiName;
p->ptrDllString = (DWORD)p->szDllName;
ns = KeUserModeCallback(0x42,//Win7上是0x41
BaseAddress,
sizeof(CLientLoadLibraryParam),
&Return,
&RetLen
);
}
return ns;
}
但是这里有个问题DLL被Load后,立刻被Free掉了~
所以DLL还要导出一个函数,函数的样子:
DWORD WINAPI XXXX(DWORD Arg0,DWORD Arg1);
这样就和谐了~
