} PIDTGATE readIDT() { IDTR idtr;__asm { sidt idtr; }return(PIDTGATE) idtr.base; } NTSTATUS klisterDeviceControl( IN PDEVICE_OBJECT pDeviceObject, IN ULONG IoControlCode, IN PVOID pInputBuffer, IN ULONG InputBufferLength, OUT PVOID pOutputBuffer, IN ULONG OutputBufferLength, OUT PIO_STATUS_BLOCK IoStatus
STn = *(int*)pInputBuffer; // no of ST to dump KdPrint ((" STn: %#x\n", STn)); n = sizeof (int) * (SrvTables[STn].n); KdPrint(("klister: n = %d\n", n));
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
下有一个AppInit_DLLs的键值,添上你的dll路径,这样当任何一个gui的exe启动时,都会加载你的dll,但是控制台的程序不加载,比如cmd.exe。这个比较毒啊。
我要做的就是隐藏进程啊。比如,我的dll可以在Explorer启动的时候注入Explorer,那么就不容易被人发现了啊。
//#include <ntddk.h>
#include <windef.h>typedef PVOID *PPVOID;
#include "w2k_def_jr.h"
#include "kmodule.h"const WCHAR devLink[] = L"\\??\\Myklister";
const WCHAR devName[] = L"\\Device\\Myklister";ServiceTableInfo SrvTables[MAX_SERVICETABLES];
DWORD nSrvTables = 0;KLISTER_PROCINFO procs[MAX_PROCS];
ULONG gOsMajorVersion = 0;
ULONG gOsMinorVersion = 0;DWORD gThreadsProcessOffset =0x44;
DWORD gCidOffset =0;DWORD gNprocs = 0;
PEPROCESS gDeletedEProcess = NULL;
PEPROCESS gBakDeletedEProcess = NULL;
#define SYSNAME "System"#define IS_WINDOWS2000() \
((gOsMajorVersion == 5) && (gOsMinorVersion == 0))#define IS_WINDOWSXP() \
((gOsMajorVersion == 5) && (gOsMinorVersion == 1))#define IS_WINDOWSXP_OR_LATER() \
(((gOsMajorVersion == 5) && (gOsMinorVersion >= 1)) || \
(gOsMajorVersion > 5))#define IS_WINDOWSDOTNET_OR_LATER() \
(((gOsMajorVersion == 5) && (gOsMinorVersion >= 2)) || \
(gOsMajorVersion > 5))
NTKERNELAPI
NTSTATUS
NTAPI
PsLookupThreadByThreadId (
IN PVOID UniqueThreadId,
OUT PETHREAD *Thread
);
NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess);
void insertProc (PKLISTER_PROCINFO obAddr);
void deleteProc (PEPROCESS obAddr);ULONG ProcessNameOffset = 0;
ULONG GetProcessNameOffset()
{
PEPROCESS curproc;
int i;curproc = PsGetCurrentProcess();//
// Scan for 12KB, hopping the KPEB never grows that big!
//
for( i = 0; i < 3*PAGE_SIZE; i++ ) { if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) { return i;
}
}//
// Name not found - oh, well
//
return 0;
}
///////////////////////////////////////////////////////////////////
void __stdcall ProcessData(DWORD * pEthread)
{
// NOTICE: WinDbg gives offsets in BYTEs, we use DWORDS
DWORD * pEprocess = (DWORD *)*(DWORD *)((PUCHAR)pEthread+gThreadsProcessOffset);//(pEthread->ThreadsProcess);
DWORD * pCid = (DWORD *)((PUCHAR)pEthread+gCidOffset);//&(pEthread->Cid);
DWORD key;
KLISTER_PROCINFO data; /*PETHREAD pethread = (PETHREAD)pEthread;
DWORD * ServiceTable =(DWORD *)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable;
DWORD nServiceLimit = pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit;*//*insertServTable ((int)*(pCid+1);,
(int)pEthread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
(int)pEthread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit);*/ if(gDeletedEProcess!= NULL)
{
gBakDeletedEProcess = gDeletedEProcess;
deleteProc(gDeletedEProcess);
gDeletedEProcess = NULL;
return;
}
if((DWORD*)gBakDeletedEProcess == pEprocess) return;
// FIXME: A thread could be hidden by setting threadsProcess or CID
// field as NULL!
if (pEprocess != NULL && pCid != NULL)
{
data.obAddr = (DWORD)pEprocess;
data.pid = *(pCid);
data.tid = *(pCid+1);
//data.imageName = (pEprocess->ImageFileName);
//strncpy(data.imageName,pEprocess->ImageFileName,16);
strncpy(data.name,((PUCHAR)pEprocess+ProcessNameOffset),16);
DbgPrint("pID:%08x tID:%8x %s\n",data.pid,data.tid,data.name);
insertProc(&data);
// The thread is terminated so remove it from the
// hashtable.
/*if (*(pEthread + offsets.crossThreadFlags) & 1)
{
Remove(key, pHashTable);
}
else
{
Insert(key, &data, pHashTable);
}*/
}
}PBYTE GoBackAddr = NULL;
PBYTE ChangAddr = NULL;
PBYTE CallContextAddr = NULL;
DWORD CallContextOffset = 0;
__declspec(naked) VOID HookSwap()
{
_asm
{
pushad
pushfd
cli
}
//DbgPrint("Switch out!\n");
_asm
{
// EDI holds the thread whose context we will switch out.
push edi
call ProcessData
}
//DbgPrint("Switch in!\n");
_asm
{
// ESI holds the thread whose context we will switch in.
push esi
call ProcessData
}_asm
{
sti
popfd
popad
}
_asm jmp DWORD PTR[GoBackAddr]
}NTSYSAPI WORD NtBuildNumber;
PCHAR GetSwapAddr()
{
PCHAR res = 0;
NTSTATUS Status;
PETHREAD Thread;if (NtBuildNumber <= 2195)
Status = PsLookupThreadByThreadId((PVOID)4, &(PETHREAD)Thread);
else
Status = PsLookupThreadByThreadId((PVOID)8, &(PETHREAD)Thread);if (NT_SUCCESS(Status))
{
if (MmIsAddressValid(Thread))
{
res = (PCHAR)(Thread->Tcb.KernelStack);
if(IS_WINDOWSDOTNET_OR_LATER())
res = (PCHAR)*(DWORD*)((PCHAR)Thread+0x20);//add for win2003 Tcb.KernelStack
}
if (MmIsAddressValid(res+8))
//res = *(PULONG(res+8));
{
_asm
{
mov eax,res
add eax,8
mov eax,[eax]
mov res,eax
}
}
else
{
res = 0;
return NULL;
}
}
_asm
{
mov eax,res
sub eax,5
mov ChangAddr,eax
mov edx,[eax+1]
mov CallContextOffset,edx
add eax,edx
add eax,5
mov GoBackAddr,eax
mov res,eax}
return res;
}BOOL HookSwapFunction(BOOL flag)
{
if (flag == TRUE)
{
KIRQL OldIrql=0;
DWORD NewOffset;//HookSwap-ChangAddr-5;
_asm
{
mov eax,HookSwap
mov edx,ChangAddr
sub eax,edx
sub eax,5
mov NewOffset,eax
}
KeRaiseIrql(2,&OldIrql);
_asm
{
mov eax,ChangAddr
push NewOffset
pop dword ptr[eax+1]
}
KeLowerIrql(OldIrql);
}
else
{
KIRQL OldIrql=0;
KeRaiseIrql(2,&OldIrql);
_asm
{
mov eax,ChangAddr
push CallContextOffset
pop dword ptr[eax+1]
}
KeLowerIrql(OldIrql);
}
}void insertProc (PKLISTER_PROCINFO pdata)
{
DWORD i;
KIRQL OldIrql=0;
if( gNprocs >= MAX_PROCS)
return;
KeRaiseIrql(2,&OldIrql);
for (i = 0; i < gNprocs; i++)
if (procs[i].obAddr == pdata->obAddr) return;procs [gNprocs].pid = pdata->pid;
procs [gNprocs].tid = pdata->tid;
procs [gNprocs].obAddr = pdata->obAddr;
strncpy (procs [gNprocs].name, pdata->name, 16);
gNprocs++;
KeLowerIrql(OldIrql);
}
void deleteProc (PEPROCESS obAddr)
{
DWORD i;
KIRQL OldIrql=0;
if( gNprocs == 0)
return;
KeRaiseIrql(2,&OldIrql);
for (i = 0; i < gNprocs; i++)
if (procs[i].obAddr == (int)obAddr)
{
procs [i].pid = 0;
procs [i].tid = 0;
procs [i].obAddr = 0;
RtlZeroMemory (procs [i].name, 16);
break;
}
if(i == gNprocs) return;
memmove(&procs[i],&procs[i+1],(gNprocs-i-1)*sizeof(KLISTER_PROCINFO));procs [gNprocs-1].pid = 0;
procs [gNprocs-1].tid = 0;
procs [gNprocs-1].obAddr = 0;
RtlZeroMemory (procs [gNprocs-1].name, 16);
gNprocs--;
KeLowerIrql(OldIrql);
}void insertServTable (int tid, DWORD addr, int n) {
DWORD i;
for (i = 0; i < nSrvTables; i++)
if (SrvTables[i].addr == addr) {
// we ignore buffer overflow here ;)
// if (SrvTables[i].nthreads < MAX_THREADS)
// SrvTables[i].threads[SrvTables[i].nthreads] = tid;
SrvTables[i].n = n;
SrvTables[i].nthreads++;
return;
}SrvTables[nSrvTables].addr = addr;
SrvTables[i].n = n;
//SrvTables[nSrvTables].threads[0] = tid;
SrvTables[nSrvTables].nthreads = 1;
nSrvTables++;
}
PEPROCESS processObject (PETHREAD ethread) {
return (PEPROCESS)(ethread->Tcb.ApcState.Process);
}/*
char* processName (PEPROCESS eprocess) {return &eprocess->ImageFileName[0];
}
*/ void createProcList () {
int i;
PVOID obj;
PETHREAD pethread;gNprocs = 0;
nSrvTables = 0;/*for (obj = pKiWaitInListHead->Flink;
obj && obj != pKiWaitInListHead; obj = ((PLIST_ENTRY)obj)->Flink) { pethread = (PETHREAD) ((char*)obj - WAITLIST_OFFSET);
insertServTable ((int)pethread->Cid.UniqueThread,
(int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
(int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit); insertProc (processObject (pethread));
}for (obj = pKiWaitOutListHead->Flink;
obj && obj != pKiWaitOutListHead; obj = ((PLIST_ENTRY)obj)->Flink) { pethread = (PETHREAD) ((char*)obj - WAITLIST_OFFSET);
insertServTable ((int)pethread->Cid.UniqueThread,
(int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
(int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit); insertProc (processObject (pethread));
}for (i = 0; i < 32; i++)
for (obj = pKiDispatcherReadyListHead[i].Flink;
obj != &pKiDispatcherReadyListHead[i];
obj = ((PLIST_ENTRY)obj)->Flink) {
pethread = (PETHREAD) ((char*)obj - WAITLIST_OFFSET);
insertServTable ((int)pethread->Cid.UniqueThread,
(int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
(int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit);
insertProc (processObject (pethread));
}*/
}
PIDTGATE readIDT() {
IDTR idtr;__asm {
sidt idtr;
}return(PIDTGATE) idtr.base;
}
NTSTATUS klisterDeviceControl(
IN PDEVICE_OBJECT pDeviceObject,
IN ULONG IoControlCode,
IN PVOID pInputBuffer,
IN ULONG InputBufferLength,
OUT PVOID pOutputBuffer,
IN ULONG OutputBufferLength,
OUT PIO_STATUS_BLOCK IoStatus
)
{ DWORD maxnproc, maxTbls, n, i, STn;
PKLISTER_INIT pkl_init;IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = 0; switch ( IoControlCode )
{case IOCTL_KLISTER_INIT: if ((InputBufferLength != sizeof(KLISTER_INIT) ) || (pInputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
pkl_init = (PKLISTER_INIT) pInputBuffer; /*pKiWaitInListHead = (PLIST_ENTRY) pkl_init->pKiWaitInListHead_addr;
pKiWaitOutListHead = (PLIST_ENTRY) pkl_init->pKiWaitOutListHead_addr;
pKiDispatcherReadyListHead = (PLIST_ENTRY) pkl_init->pKiDispatcherReadyListHead_addr; KdPrint ((" pKiWaitInListHead: %#x\n", pKiWaitInListHead));
KdPrint ((" pKiWaitOutListHead: %#x\n", pKiWaitOutListHead));
KdPrint ((" pKiDispatcherReadyListHead: %#x\n", pKiDispatcherReadyListHead));*/ /*for (i = 0; i < MAX_PROCS; i++)
procs[i].pid = 0;*/
//RtlZeroMemory(procs,sizeof(KLISTER_PROCINFO)*MAX_PROCS); for (i = 0; i < MAX_SERVICETABLES; i++)
SrvTables[i].addr = 0;break;
case IOCTL_KLISTER_LISTPROC:
if ((OutputBufferLength < sizeof (KLISTER_PROCINFO)) || (pOutputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
maxnproc = OutputBufferLength/sizeof (KLISTER_PROCINFO);
//createProcList();
if (gNprocs > maxnproc)
n = maxnproc*sizeof (KLISTER_PROCINFO);
else
n = gNprocs * sizeof (KLISTER_PROCINFO); if (OutputBufferLength < n)
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break; }
memcpy (pOutputBuffer, (PVOID) &procs, n);
IoStatus->Information = n;break; case IOCTL_KLISTER_DUMP_IDT:
if ((OutputBufferLength < sizeof (IDTGATE)*IDT_NGATES)
|| (pOutputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
n = sizeof (IDTGATE) * IDT_NGATES;
memcpy (pOutputBuffer, (PVOID) readIDT(), n);
IoStatus->Information = n; break;case IOCTL_KLISTER_FIND_ST:
if ((OutputBufferLength < sizeof (ServiceTableInfo))
|| (pOutputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
maxTbls = OutputBufferLength/sizeof(ServiceTableInfo);
createProcList(); if (nSrvTables > maxTbls) n = maxTbls*sizeof (ServiceTableInfo);
else n = nSrvTables * sizeof (ServiceTableInfo);
memcpy (pOutputBuffer, (PVOID) SrvTables, n);
IoStatus->Information = n;break;case IOCTL_KLISTER_DUMP_ST:
if ((InputBufferLength != sizeof(int) ) || (pInputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
if ((OutputBufferLength < sizeof (int))
|| (pOutputBuffer == NULL))
{
IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
break;
}
STn = *(int*)pInputBuffer; // no of ST to dump
KdPrint ((" STn: %#x\n", STn)); n = sizeof (int) * (SrvTables[STn].n);
KdPrint(("klister: n = %d\n", n));
n = (n > OutputBufferLength) ? OutputBufferLength : n;
KdPrint(("klister: n = %d\n", n)); memcpy (pOutputBuffer, (PVOID) SrvTables[STn].addr, n);
KdPrint (("memcpy (pOutputBuffer, (PVOID) SrvTables[STn].addr, n)"));
KdPrint (("pOutputBuffer = %#x\n", pOutputBuffer));
KdPrint (("SrvTables[STn].addr = %#x\n", SrvTables[STn].addr));
IoStatus->Information = n; break;
default:
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
break;
} return IoStatus->Status;
}
需要再次申明的是:我已经可以注入dll了!
但是,问题是,我仍然需要另一个exe去做“注入dll”的工作。
这样的话,事实上“任务管理器”是有办法监测到我的进程的,哪怕仅仅只是“注入dll”的数秒种。或许我可以修改已存在的exe来达到这一目的……