[分享]老文章系列:POOL驱动的梗
很多病毒木马,各种奇葩的ARK,RK,XXProtect把驱动代码放到POOL里执行,但由此会产生一个问题,在POOL里的驱动代码是不能出异常的,所有的异常处理都会失效。同理重载的内核也有同样的问题。
老文章的地址:http://www.langouster.com/HTML/116.html
原始作者提出了2种解决方式,不过我还是选择了hook RtlLookupXX的方式解决问题。因为操作那2个List如果没有进行锁操作是会蓝屏的!


#include <ntddk.h>
#include <WinDef.h>
#include <ntimage.h>
NTSTATUS NTAPI HookFunction(
ULONG_PTR Function,
ULONG_PTR NewFunction,
PVOID *pSaveFunction,
ULONG *pSaveFunctionSize);
NTSYSAPI
PVOID
NTAPI
RtlImageNtHeader (
IN PVOID BaseAddress
);
NTKERNELAPI
KIRQL
KeRaiseIrqlToSynchLevel (
VOID
);
//X86下!
typedef PVOID (NTAPI*T_RtlLookupFunctionTable)(
IN PVOID ControlPc,
OUT PVOID *ImageBase,
OUT PULONG SizeOfTable
);
typedef struct _TABLE_NODE_
{
PVOID ImageBase;
ULONG ImageSize;
ULONG SizeOfTable;
PVOID Table;
}TABLE_NODE,*PTABLE_NODE;
DWORD RtlLookupFunctionTable=0;//地址怎么获取请大家自己思考一下的说,符号或暴力搜索?想支持x64的话,这个DWORD要修改,另外还要过掉PG~
TABLE_NODE m_Table[0x10]={0};
UINT g_TableCount =0;
LONG g_TableLock=0;
T_RtlLookupFunctionTable OldRtlLookupFunctionTable=NULL;
ULONG RtlLookupFunctionTableSize=0;
PVOID
NTAPI OnRtlLookupFunctionTable (
IN PVOID ControlPc,
OUT PVOID *ImageBase,
OUT PULONG SizeOfTable
)
{
PVOID pRet = OldRtlLookupFunctionTable(
ControlPc,
ImageBase,
SizeOfTable
);
if (!pRet)
{
UINT nIndex=0;
KIRQL OldIrql;
OldIrql = KeGetCurrentIrql();
if (OldIrql < SYNCH_LEVEL) {
KeRaiseIrqlToSynchLevel();
}
while (InterlockedIncrement(&g_TableLock) > 0)
{
InterlockedDecrement(&g_TableLock);
_mm_pause();
}
for (nIndex=0;nIndex<g_TableCount;nIndex++)
{
ULONG_PTR Addr = (ULONG_PTR)ControlPc;
if (Addr>=(ULONG_PTR)m_Table[nIndex].ImageBase
&& Addr <= (ULONG_PTR)m_Table[nIndex].ImageBase+m_Table[nIndex].ImageSize)
{
*SizeOfTable = m_Table[nIndex].SizeOfTable;
pRet = m_Table[nIndex].Table;
*ImageBase = m_Table[nIndex].ImageBase;
break;
}
}
InterlockedDecrement(&g_TableLock);
KeLowerIrql(OldIrql);
}
return pRet;
}
VOID InitRtlSeh()
{
RtlZeroMemory(m_Table,sizeof(TABLE_NODE)*0x10);
g_TableCount = 0;
HookFunction((ULONG_PTR)RtlLookupFunctionTable,
(ULONG_PTR)OnRtlLookupFunctionTable,
(PVOID *)&OldRtlLookupFunctionTable,
&RtlLookupFunctionTableSize);
}
VOID InsertRtlTable(PVOID ImageBase)
{
UINT nIndex;
PIMAGE_NT_HEADERS NtHeader;
while (InterlockedIncrement(&g_TableLock) > 0)
{
InterlockedDecrement(&g_TableLock);
_mm_pause();
}
nIndex = InterlockedIncrement(&g_TableCount);
m_Table[nIndex].ImageBase = ImageBase;
NtHeader = RtlImageNtHeader(ImageBase);
m_Table[nIndex].ImageSize = NtHeader->OptionalHeader.SizeOfImage;
#if defined(_X86_)
if (NtHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH)
{
m_Table[nIndex].Table = (PVOID)LongToPtr(-1);
m_Table[nIndex].SizeOfTable = (ULONG)-1;
}
else
{
PIMAGE_LOAD_CONFIG_DIRECTORY32 LoadConfig;
ULONG LoadConfigSize;
if (IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG < NtHeader->OptionalHeader.NumberOfRvaAndSizes) {
LoadConfig = (PIMAGE_LOAD_CONFIG_DIRECTORY32)((PCHAR)ImageBase +
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress);
LoadConfigSize = NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size;
if (LoadConfig &&
LoadConfigSize &&
LoadConfig->Size >= RTL_SIZEOF_THROUGH_FIELD(IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerCount) &&
LoadConfig->SEHandlerTable &&
LoadConfig->SEHandlerCount
)
{
m_Table[nIndex].Table = (PVOID)LoadConfig->SEHandlerTable;
m_Table[nIndex].SizeOfTable = LoadConfig->SEHandlerCount;
} else {
m_Table[nIndex].Table = 0;
m_Table[nIndex].SizeOfTable = 0;
}
}
}
#else
if (IMAGE_DIRECTORY_ENTRY_EXCEPTION < NtHeader->OptionalHeader.NumberOfRvaAndSizes) {
m_Table[nIndex].Table = (PCHAR)ImageBase +
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
m_Table[nIndex].SizeOfTable =
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
}
#endif
InterlockedDecrement(&g_TableLock);
}
