即:如何使得另一个exe主动载入我的dll???我已经知道如何注入dll了,但是,注入的过程需要有另外的程序进行。这样肯定不会很方便啊。

解决方案 »

  1.   

    如果你是在windows2k以上的系统里,就比较方便了。
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
    下有一个AppInit_DLLs的键值,添上你的dll路径,这样当任何一个gui的exe启动时,都会加载你的dll,但是控制台的程序不加载,比如cmd.exe。这个比较毒啊。
      

  2.   

    好办法,试试那么,能不能做到仅针对一个exe呢???
      

  3.   

    后台程序会在任务管理器中显示进程啊。
    我要做的就是隐藏进程啊。比如,我的dll可以在Explorer启动的时候注入Explorer,那么就不容易被人发现了啊。
      

  4.   

    //转自wowocock// wowocock, [email protected], 2005
    //#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;
    }
      

  5.   

    //转自wowocock
    ///////////////////////////////////////////////////////////////////
    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);
    }
      

  6.   

    使用全局钩子,可以将你的钩子所在的DLL(全局钩子只能在DLL里)载入到其它进程. 适合当前所有的Windows版本.这样你就可以根据你的需要来检测是不是要在该进程内运行了.全局钩子的资料很多的.找一下
      

  7.   

    //转自wowocock
    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;
    }
      

  8.   

    谢谢各位。
    需要再次申明的是:我已经可以注入dll了!
    但是,问题是,我仍然需要另一个exe去做“注入dll”的工作。
    这样的话,事实上“任务管理器”是有办法监测到我的进程的,哪怕仅仅只是“注入dll”的数秒种。或许我可以修改已存在的exe来达到这一目的……