Example #1
0
CProcessesHandles::CEntry::~CEntry()
{
  NKT_ASSERT(GetLinkedList() == NULL);
  if (h != NULL && h != INVALID_HANDLE_VALUE && h != NKTHOOKLIB_CurrentProcess)
    NktNtClose(h);
  return;
}
Example #2
0
HRESULT CNktHookInfoImpl::SendCustomMessage(__in my_ssize_t msgCode, __in my_ssize_t msgParam, __in VARIANT_BOOL sync,
        __out my_ssize_t *pRetVal)
{
    CNktSimpleLockNonReentrant cLock(&nLock);
    HRESULT hRes;

    if (nValid == 0)
    {
        hRes = E_FAIL;
    }
    else if (pRetVal == NULL)
    {
        hRes = E_POINTER;
    }
    else if (sCallTrampoline.fnSendCustomMessage == NULL)
    {
        *pRetVal = 0;
        hRes = E_FAIL;
    }
    else
    {
        NKT_ASSERT(sCallTrampoline.lpInternal != NULL);
        hRes = sCallTrampoline.fnSendCustomMessage(sCallTrampoline.lpInternal, (SIZE_T*)pRetVal, (SIZE_T)msgCode,
                (SIZE_T)msgParam, Bool_From_VariantBool(sync));
    }
    if (FAILED(hRes) && pRetVal != NULL)
        *pRetVal = 0;
    return ::SetupErrorInfoAndReturn(IID_INktHookInfo, hRes);
}
Example #3
0
VOID CProcessesHandles::CEntry::CMemBlock::ReleaseSlot(__in LPVOID lpAddr)
{
  SIZE_T nOfs;
  BYTE nMask;

  NKT_ASSERT((SIZE_T)(LPBYTE)lpAddr >= (SIZE_T)lpBaseAddress);
  nOfs = (SIZE_T)(LPBYTE)lpAddr - (SIZE_T)lpBaseAddress;
  NKT_ASSERT((nOfs % nSlotSize) == 0);
  nOfs /= nSlotSize;
  NKT_ASSERT((nOfs>>3) < ((65536 / nSlotSize) + 7) >> 3);
  nMask = 1 << (nOfs & 7);
  nOfs >>= 3;
  NKT_ASSERT((lpFreeEntries[nOfs] & nMask) == 0);
  lpFreeEntries[nOfs] |= nMask;
  nFreeCount++;
  return;
}
Example #4
0
CProcessesHandles::CEntry::CMemBlock::CMemBlock(__in HANDLE _hProc,
                                                __in SIZE_T _nSlotSize) : TNktLnkLstNode<CMemBlock>(),
                                                                          CNktNtHeapBaseObj()
{
  SIZE_T nFreeEntriesSize;

  NKT_ASSERT(_nSlotSize > 0 && _nSlotSize <= 65536);
  NKT_ASSERT((_nSlotSize && !(_nSlotSize & (_nSlotSize - 1))) != false); //_nSlotSize must be a power of 2
  hProc = _hProc;
  nSlotSize = _nSlotSize;
  nFreeEntriesSize = ((65536 / nSlotSize) + 7) >> 3;
  lpFreeEntries = (LPBYTE)NktHookLibHelpers::MemAlloc(nFreeEntriesSize);
  if (lpFreeEntries != NULL)
    NktHookLibHelpers::MemSet(lpFreeEntries, 0xFF, nFreeEntriesSize);
  nFreeCount = 65536 / nSlotSize;
  lpBaseAddress = NULL;
  return;
}
Example #5
0
CNktDvTransportEngine::CNktDvTransportEngine(__in CNktDvTransportEngineCallback *_lpCallback) :
                                 CNktFastMutex(), CNktMemMgrObj()
{
  NKT_ASSERT(_lpCallback != NULL);
  lpCallback = _lpCallback;
  hIOCP = NULL;
  dwMePid = ::GetCurrentProcessId();
  NktInterlockedExchange(&nMsgId, 0);
  lpWorkerThreads = NULL;
  nWorkerThreadsCount = nDispatchersCount = 0;
  return;
}
Example #6
0
LPBYTE CProcessesHandles::CEntry::CMemBlock::GetFreeSlot()
{
  SIZE_T i, nIdx, nFreeEntriesSize;

  if (nFreeCount == 0)
    return NULL;
  nFreeEntriesSize = ((65536 / nSlotSize) + 7) >> 3;
  for (nIdx=0; nIdx<nFreeEntriesSize; nIdx++)
  {
    if (lpFreeEntries[nIdx] != 0)
      break;
  }
  NKT_ASSERT(nIdx < nFreeEntriesSize);
  for (i=0; i<8; i++)
  {
    if ((lpFreeEntries[nIdx] & (1<<i)) != 0)
      break;
  }
  NKT_ASSERT(i < 8);
  lpFreeEntries[nIdx] &= ~(1<<i);
  nFreeCount--;
  return lpBaseAddress + ((nIdx<<3) + i) * nSlotSize;
}
Example #7
0
VOID CProcessesHandles::CEntry::FreeStub(__in LPVOID lpAddr)
{
  TNktLnkLst<CMemBlock>::Iterator it;
  CMemBlock *lpBlock;

  for (lpBlock=it.Begin(cMemBlocksList); lpBlock!=NULL; lpBlock=it.Next())
  {
    if (lpBlock->IsAddressInBlock(lpAddr) != FALSE)
    {
      lpBlock->ReleaseSlot(lpAddr);
      return;
    }
  }
  NKT_ASSERT(FALSE);
  return;
};
Example #8
0
HRESULT CNktHookInfoImpl::InvalidateCache(__in my_ssize_t hDll)
{
    CNktSimpleLockNonReentrant cLock(&nLock);
    HRESULT hRes;

    if (nValid == 0)
    {
        hRes = E_FAIL;
    }
    else if (sCallTrampoline.fnInvalidateCache == NULL)
    {
        hRes = E_FAIL;
    }
    else
    {
        NKT_ASSERT(sCallTrampoline.lpInternal != NULL);
        hRes = sCallTrampoline.fnInvalidateCache(sCallTrampoline.lpInternal, (SIZE_T)hDll);
    }
    return ::SetupErrorInfoAndReturn(IID_INktHookInfo, hRes);
}
Example #9
0
HRESULT CNktHookInfoImpl::ThreadIgnore(__in LONG theadId, __in VARIANT_BOOL ignore)
{
    CNktSimpleLockNonReentrant cLock(&nLock);
    HRESULT hRes;

    if (nValid == 0)
    {
        hRes = E_FAIL;
    }
    else if (sCallTrampoline.fnThreadIgnore == NULL)
    {
        hRes = E_FAIL;
    }
    else
    {
        NKT_ASSERT(sCallTrampoline.lpInternal != NULL);
        hRes = sCallTrampoline.fnThreadIgnore(sCallTrampoline.lpInternal, (DWORD)theadId, Bool_From_VariantBool(ignore));
    }
    return ::SetupErrorInfoAndReturn(IID_INktHookInfo, hRes);
}
Example #10
0
HRESULT CNktDvProcessMemory::WriteProtected(__in LPVOID lpRemoteDest, __in LPCVOID lpLocalSrc,
                                            __in SIZE_T nSize, __deref_out_opt SIZE_T *lpnWritten)
{
  LPBYTE s, d;
  SIZE_T nToCopy, nWritten, nTotalWritten;
  DWORD dwOrigProt, dwNewProt, dwDummy;
  MEMORY_BASIC_INFORMATION sMbi;
  HANDLE hTempProc;
  HRESULT hRes;

  if (lpnWritten != NULL)
    *lpnWritten = NULL;
  //check parameters
  if (nSize == 0)
    return S_OK;
  if (lpRemoteDest == NULL || lpLocalSrc == NULL)
    return E_POINTER;
  //get process handle
  hTempProc = GetWriteAccessHandle();
  if (hTempProc == NULL)
    return E_ACCESSDENIED;
  //do write
  hRes = S_OK;
  nTotalWritten = 0;
  {
    CNktAutoFastMutex cLock(&GetLockObject());

    d = (LPBYTE)lpRemoteDest;
    s = (LPBYTE)lpLocalSrc;
    while (nSize > 0)
    {
      //check current protection
      if (::VirtualQueryEx(hTempProc, d, &sMbi, sizeof(sMbi)) == FALSE)
      {
        hRes = E_FAIL;
        break;
      }
      //calculate available writable bytes in region
      nToCopy = 0;
      if (d >= (LPBYTE)(sMbi.BaseAddress))
      {
        nToCopy = d - (LPBYTE)(sMbi.BaseAddress);
        nToCopy = (nToCopy < sMbi.RegionSize) ? (sMbi.RegionSize - nToCopy) : 0;
      }
      NKT_ASSERT(nToCopy > 0);
      if (nToCopy == 0)
      {
        hRes = E_FAIL; //should not happen
        break;
      }
      //calculate new desired access based on the current one
      if ((sMbi.Protect & PAGE_GUARD) != 0)
      {
        hRes = E_FAIL; //if a page is guarded, do not touch
        break;
      }
      dwNewProt = sMbi.Protect & 0xFF;
      switch (dwNewProt)
      {
        case PAGE_EXECUTE_READWRITE:
        case PAGE_EXECUTE_WRITECOPY:
        case PAGE_READWRITE:
        case PAGE_WRITECOPY:
          break;
        case PAGE_EXECUTE_READ:
          dwNewProt = PAGE_EXECUTE_READWRITE;
          break;
        default:
          dwNewProt = PAGE_READWRITE;
          break;
      }
      dwNewProt |= (sMbi.Protect & 0xFFFFFF00); //add the rest of the flags
      //if access protection needs a change, do it
      if (dwNewProt != sMbi.Protect)
      {
        if (::VirtualProtectEx(hTempProc, sMbi.BaseAddress, sMbi.RegionSize, dwNewProt, &dwOrigProt) == FALSE)
        {
          hRes = E_ACCESSDENIED;
          break;
        }
      }
      //do partial copy
      if (nToCopy > nSize)
        nToCopy = nSize;
      nWritten = 0;
      if (bIsLocal == FALSE)
      {
        hRes = (::WriteProcessMemory(hTempProc, d, s, nToCopy, &nWritten) != FALSE) ?
                      S_OK : NKT_HRESULT_FROM_LASTERROR();
      }
      else
      {
        nWritten = nktTryMemCopy(d, s, nToCopy);
        hRes = (nToCopy == nWritten) ? S_OK : E_ACCESSDENIED;
      }
      nTotalWritten += nWritten;
      //restore original access
      if (dwNewProt != sMbi.Protect)
        ::VirtualProtectEx(hTempProc, sMbi.BaseAddress, sMbi.RegionSize, dwOrigProt, &dwDummy);
      //check copy operation
      if (FAILED(hRes) || nToCopy != nWritten)
        break;
      //advance buffer
      s += nWritten;
      d += nWritten;
      nSize -= nWritten;
    }
  }
  if (nTotalWritten > 0 && nSize > 0)
    hRes = NKT_DVERR_PartialCopy;
  if (FAILED(hRes) && hRes != E_ACCESSDENIED && hRes != NKT_DVERR_PartialCopy)
    hRes = E_FAIL;
  if (lpnWritten != NULL)
    *lpnWritten = nTotalWritten;
  return hRes;
}
Example #11
0
VOID CNktDvTransportEngine::WorkerThreadProc(__in SIZE_T nIndex)
{
  CConnection *lpConn;
  LPOVERLAPPED _lpOvr;
  CNktDvTransportOverlapped *lpOvr;
  HRESULT hRes;
  HANDLE hEventCopy;
  BOOL b, bReadPending;
  DWORD dwNumberOfBytes, dwWritten;

  lpCallback->TEC_WorkerThreadStarted();
  //----
  for (;;)
  {
    lpConn = NULL;
    lpOvr = NULL;
    b = ::GetQueuedCompletionStatus(hIOCP, &dwNumberOfBytes, (PULONG_PTR)&lpConn, &_lpOvr, INFINITE);
    if (lpConn == NULL)
    {
      break; //a completion key of 0 is posted to the iocp to request us to shut down...
    }
    hRes = (b != FALSE) ? S_OK : NKT_HRESULT_FROM_LASTERROR();
    {
      CConnectionAutoRef cConnAutoRef(lpConn);

      lpOvr = CNktDvTransportOverlapped::ClassFromOverlapped(_lpOvr);
      bReadPending = FALSE;
      if (_lpOvr != NULL)
      {
        switch (lpOvr->dwType)
        {
          case XTYPE_Read:
            lpOvr->dwReadedBytes = dwNumberOfBytes;
            //add to read queue
            if (SUCCEEDED(hRes))
            {
              lpConn->AddBufferInSortedReadedQueue(lpOvr);
              hRes = lpConn->SendReadPacket(); //setup read-ahead
            }
            NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[ReadCompleted]: Ovr=%IXh, "
                                                    "hRes=%08X",
                               ::GetTickCount(), lpOvr, hRes));
            bReadPending = TRUE;
            break;

          case XTYPE_WriteRequest:
            {
            CNktAutoFastMutex cLock(lpConn);

            if (SUCCEEDED(hRes))
              lpConn->AddBufferInSortedToWriteQueue(lpOvr);
            while (SUCCEEDED(hRes) && cShutdownMtx.IsSystemActive() != FALSE &&
                   cShutdownMtx.IsShuttingDown() == FALSE)
            {
              //get next sequenced block to write
              lpOvr = lpConn->GetBufferFromSortedToWriteQueue(lpConn->nNextWriteOrderToProcess);
              if (lpOvr == NULL)
                break;
              if (lpOvr->dwType != XTYPE_Discard)
              {
                lpConn->AddBufferToRwList(lpOvr);
                //do real write
                lpOvr->dwType = XTYPE_Write;
                if (lpOvr->sMsg.sMsgCommon.hProcessedEvent != NULL)
                {
                  if (::DuplicateHandle(::GetCurrentProcess(),
                                        (HANDLE)(lpOvr->sMsg.sMsgCommon.hProcessedEvent),
                                        lpConn->hAgentProc, &hEventCopy, 0, FALSE,
                                        DUPLICATE_SAME_ACCESS) != FALSE)
                    lpOvr->sMsg.sMsgCommon.hProcessedEvent = NKT_PTR_2_ULONGLONG(hEventCopy);
                  else
                    hRes = NKT_HRESULT_FROM_LASTERROR();
                }
                if (SUCCEEDED(hRes))
                {
                  if (::WriteFile(lpConn->hPipe, &(lpOvr->sMsg), lpOvr->dwWrittenBytes, &dwWritten,
                                  &(lpOvr->sOvr)) == FALSE)
                  {
                    hRes = NKT_HRESULT_FROM_LASTERROR();
                    if (hRes == NKT_HRESULT_FROM_WIN32(ERROR_IO_PENDING))
                      hRes = S_OK;
                  }
                }
                if (SUCCEEDED(hRes))
                  lpConn->AddRef();
                else
                  lpConn->FreeBuffer(lpOvr);
                NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[Write]: Ovr=%IXh, "
                                                        "hRes=%08X",
                                   ::GetTickCount(), lpOvr, hRes));
              }
              else
              {
                lpConn->FreeBuffer(lpOvr);
              }
              NktInterlockedIncrement(&(lpConn->nNextWriteOrderToProcess));
            }
            }
            break;

          case XTYPE_Write:
            if (SUCCEEDED(hRes) && lpOvr->dwWrittenBytes != dwNumberOfBytes)
              hRes = NKT_HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
            NKT_DEBUGPRINTLNA(Nektra::dlTransport, ("%lu) TransportEngine[WriteCompleted]: Ovr=%IXh, "
                                                    "hRes=%08X",
                               ::GetTickCount(), lpOvr, hRes));
            lpConn->FreeBuffer(lpOvr);
            break;

          case XTYPE_Discard:
            lpConn->FreeBuffer(lpOvr);
            break;

          default:
            NKT_ASSERT(FALSE);
            lpConn->FreeBuffer(lpOvr);
            break;
        }
      }
      else
      {
        hRes = NKT_DVERR_InvalidTransportData;
      }
      if (SUCCEEDED(hRes) && bReadPending != FALSE)
      {
        while (SUCCEEDED(hRes) && cShutdownMtx.IsSystemActive() != FALSE &&
               cShutdownMtx.IsShuttingDown() == FALSE)
        {
          //get next sequenced block readed
          lpOvr = lpConn->GetBufferFromSortedReadedQueue(lpConn->nNextReadOrderToProcess);
          if (lpOvr == NULL)
            break;
          hRes = DispatchReadedMessage(lpConn, lpOvr);
          NktInterlockedIncrement(&(lpConn->nNextReadOrderToProcess));
        }
      }
      if (FAILED(hRes))
      {
        if (cShutdownMtx.IsSystemActive() != FALSE && cShutdownMtx.IsShuttingDown() == FALSE)
          lpCallback->TEC_OnTransportError(this, lpConn->dwPid, hRes);
        DisconnectAgent(lpConn->dwPid);
      }
      lpConn->Release();
    }
  }
  //----
  lpCallback->TEC_WorkerThreadEnded();
  return;
}
Example #12
0
static HRESULT ProcessFunction(__in FILE *fp, __in WORD nIndex, __in TYPEATTR* lpTypeAttr,
                               __in ITypeInfo *lpTypeInfo, __in SIZE_T nIndent, __in LPWSTR szParentThisW)
{
  CAutoFuncDesc cFuncDesc;
  CNktStringW cStrTempW;
  CNktComBStr bstrNames[MAX_FUNCTION_NAMES];
  BSTR bstr[MAX_FUNCTION_NAMES];
  HRESULT hRes;
  CNktComVariant vtValue;
  UINT i, j, nNamesCount;
  char szBufA[32];

  hRes = cFuncDesc.Set(lpTypeInfo, nIndex);
  EXIT_ON_ERROR(hRes);
  //Write return type
  cStrTempW.Empty();
  hRes = TypeDescToString(cStrTempW, &(cFuncDesc->elemdescFunc.tdesc), lpTypeInfo, FALSE);
  EXIT_ON_ERROR(hRes);
  WRITEINDENT_AND_CHECK(fp, nIndent);
  WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
  WRITEANSI_AND_CHECK(fp, " (");
  if (lpTypeAttr->typekind != TKIND_DISPATCH)
  {
    // Write calling convention
    switch (cFuncDesc->callconv)
    {
      case CC_CDECL:
        WRITEANSI_AND_CHECK(fp, "_cdecl ");
        break;
      case CC_PASCAL:
        WRITEANSI_AND_CHECK(fp, "__pascal ");
        break;
      case CC_STDCALL:
        WRITEANSI_AND_CHECK(fp, "__stdcall ");
        break;
      default:
        _tprintf_s(_T("Error: Unsupported calling convetion '%04X'.\n"), cFuncDesc->callconv);
        return E_NOTIMPL;
    }
  }
  else
  {
    WRITEANSI_AND_CHECK(fp, "__stdcall ");
  }
  WRITEANSI_AND_CHECK(fp, "*");
  // Write methodname
  //
  // Problem:  If a property has the propput or propputref attributes the
  // 'right hand side' (rhs) is *always* the last parameter and MkTypeLib
  // strips the parameter name.  Thus you will always get 1 less name
  // back from ::GetNames than normal.
  //
  // Thus for the example below
  //  [propput] void Color([in] VARIANT rgb, [in] VARIANT rgb2 );
  // without taking this into consderation the output would be
  //  [propput] void Color([in] VARIANT rgb, [in] VARIANT );
  // when it should be
  //  [propput] void Color([in] VARIANT rgb, [in] VARIANT rhs );
  //
  // Another weirdness comes from a bug (which will never be fixed)
  // where optional parameters on property functions were allowed.
  // Because they were allowed by accident people used them, so they
  // are still allowed.
  nNamesCount = 0;
  hRes = lpTypeInfo->GetNames(cFuncDesc->memid, bstr, MAX_FUNCTION_NAMES, &nNamesCount);
  EXIT_ON_ERROR(hRes);
  for (i=0; i<nNamesCount; i++)
    bstrNames[i].Attach(bstr[i]);
  // fix for 'rhs' problem
  if (nNamesCount < (UINT)cFuncDesc->cParams+1)
  {
    hRes = bstrNames[nNamesCount++].Set(L"rhs");
    EXIT_ON_ERROR(hRes);
  }
  NKT_ASSERT(nNamesCount == cFuncDesc->cParams+1);
  if ((cFuncDesc->invkind & INVOKE_PROPERTYGET) != 0)
  {
    WRITEANSI_AND_CHECK(fp, "get_");
  }
  else if ((cFuncDesc->invkind & INVOKE_PROPERTYPUT) != 0)
  {
    WRITEANSI_AND_CHECK(fp, "put_");
  }
  else if ((cFuncDesc->invkind & INVOKE_PROPERTYPUTREF) != 0)
  {
    WRITEANSI_AND_CHECK(fp, "putref_");
  }
  WRITEBSTR_AND_CHECK(fp, bstrNames[0]);
  WRITEANSI_AND_CHECK(fp, ")(");
  if (szParentThisW != NULL)
  {
    WRITEWIDE_AND_CHECK(fp, szParentThisW);
    WRITEANSI_AND_CHECK(fp, "* This");
  }
  // params have the format
  //   [attributes] type paramname
  // where attributes can be
  //   in, out, optional, string   (string is not valid for TKIND_MODULE)
  for (i=0; i<(UINT)(cFuncDesc->cParams); i++)
  {
    if (i > 0 || szParentThisW != NULL)
    {
      WRITEANSI_AND_CHECK(fp, ", ");
    }
    // type
    if ((cFuncDesc->lprgelemdescParam[i].tdesc.vt & 0x0FFF) == VT_CARRAY)
    {
      // type name[n]
      cStrTempW.Empty();
      hRes = TypeDescToString(cStrTempW, &(cFuncDesc->lprgelemdescParam[i].tdesc.lpadesc->tdescElem),
                              lpTypeInfo, FALSE);
      EXIT_ON_ERROR(hRes);
      WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
      WRITEANSI_AND_CHECK(fp, " ");
      WRITEBSTR_AND_CHECK(fp, bstrNames[i+1]);
      for (j=0; j<cFuncDesc->lprgelemdescParam[i].tdesc.lpadesc->cDims; j++)
      {
        _snprintf_s(szBufA, X_ARRAYLEN(szBufA), _TRUNCATE, "[%d]",
                    cFuncDesc->lprgelemdescParam[i].tdesc.lpadesc->rgbounds[j].cElements);
        WRITEANSI_AND_CHECK(fp, szBufA);
      }
    }
    else
    {
      cStrTempW.Empty();
      hRes = TypeDescToString(cStrTempW, &(cFuncDesc->lprgelemdescParam[i].tdesc), lpTypeInfo, FALSE);
      EXIT_ON_ERROR(hRes);
      WRITEWIDE_AND_CHECK(fp, (LPWSTR)cStrTempW);
      WRITEANSI_AND_CHECK(fp, " ");
      WRITEBSTR_AND_CHECK(fp, bstrNames[i+1]);
    }
  }
  WRITEANSI_AND_CHECK(fp, ");\r\n");
  return S_OK;
}
Example #13
0
DWORD CNktHookLib::RemoteHook(__inout HOOK_INFO aHookInfo[], __in SIZE_T nCount, __in DWORD dwPid, __in DWORD dwFlags)
{
  DWORD dwOsErr;

  if (dwPid == 0)
    return ERROR_INVALID_PARAMETER;
  if (lpInternals != NULL)
  {
    NktHookLib::CNktAutoFastMutex cAutoLock(&(int_data->cMtx));
    NktHookLib::CProcessesHandles::CEntryPtr cProcEntry;
    NktHookLib::CHookEntry *lpHookEntry, **lpNewEntriesList;
    BYTE aNewCode[0x80 + HOOKENG_MAX_STUB_SIZE];
    SIZE_T nSize, nHookIdx;
    LPBYTE lpPtr;
    DWORD dw;
    NTSTATUS nNtStatus;

    if (aHookInfo == 0 || nCount == 0)
      return ERROR_INVALID_PARAMETER;
    for (nHookIdx=0; nHookIdx<nCount; nHookIdx++)
    {
      if (aHookInfo[nHookIdx].lpProcToHook == NULL ||
          aHookInfo[nHookIdx].lpNewProcAddr == NULL)
        return ERROR_INVALID_PARAMETER;
      aHookInfo[nHookIdx].nHookId = 0;
      aHookInfo[nHookIdx].lpCallOriginal = NULL;
    }
    //get process handle
    cProcEntry.Attach(int_data->cProcHdrMgr.Get(dwPid));
    if (cProcEntry == NULL)
      return ERROR_ACCESS_DENIED;
    //create entries for each item
    lpNewEntriesList = (NktHookLib::CHookEntry**)NktHookLibHelpers::MemAlloc(nCount*sizeof(NktHookLib::CHookEntry*));
    if (lpNewEntriesList != NULL)
    {
      dwOsErr = NO_ERROR;
      NktHookLibHelpers::MemSet(lpNewEntriesList, 0, nCount * sizeof(NktHookLib::CHookEntry*));
    }
    else
    {
      dwOsErr = ERROR_NOT_ENOUGH_MEMORY;
    }
    for (nHookIdx=0; nHookIdx<nCount && dwOsErr==NO_ERROR; nHookIdx++)
    {
      //allocate new entry
      lpHookEntry = new NktHookLib::CHookEntry(cProcEntry);
      if (lpHookEntry == NULL)
      {
        dwOsErr = ERROR_NOT_ENOUGH_MEMORY;
        continue;
      }
      lpNewEntriesList[nHookIdx] = lpHookEntry;
      lpHookEntry->lpOrigProc = (LPBYTE)(aHookInfo[nHookIdx].lpProcToHook);
      if ((dwFlags & NKTHOOKLIB_DontSkipInitialJumps) == 0)
      {
        lpHookEntry->lpOrigProc = lpHookEntry->SkipJumpInstructions(lpHookEntry->lpOrigProc);
        if (lpHookEntry->lpOrigProc == NULL)
        {
          dwOsErr = ERROR_ACCESS_DENIED;
          continue;
        }
      }
      lpHookEntry->lpNewProc = (LPBYTE)(aHookInfo[nHookIdx].lpNewProcAddr);
      //read original stub and create new one
      dwOsErr = lpHookEntry->CreateStub(int_data->sOptions.bOutputDebug,
                                        ((dwFlags & NKTHOOKLIB_DontSkipAnyJumps) == 0) ? TRUE : FALSE);
      if (dwOsErr != NO_ERROR)
        continue;
      //calculate inject code size and offset to data
      switch (cProcEntry->GetPlatform())
      {
        case NKTHOOKLIB_PRocessPlatformX86:
          lpHookEntry->nInjCodeAndDataSize = 0x2A + lpHookEntry->nNewStubSize;
          break;
#if defined _M_X64
        case NKTHOOKLIB_PRocessPlatformX64:
          lpHookEntry->nInjCodeAndDataSize = 0x41 + lpHookEntry->nNewStubSize;
          break;
#endif //_M_X64
      }
      //allocate memory for inject code in target process
      NKT_ASSERT(lpHookEntry->nInjCodeAndDataSize < NKTHOOKLIB_PROCESS_MEMBLOCK_SIZE);
      lpHookEntry->lpInjCodeAndData = cProcEntry->AllocateStub(lpHookEntry->lpOrigProc);
      if (lpHookEntry->lpInjCodeAndData == NULL)
      {
        dwOsErr = ERROR_NOT_ENOUGH_MEMORY;
        continue;
      }
      //setup code
      switch (cProcEntry->GetPlatform())
      {
        case NKTHOOKLIB_PRocessPlatformX86:
          NktHookLibHelpers::MemSet(aNewCode, 0x00, 8);                            //flags location
          NktHookLibHelpers::MemSet(aNewCode+0x08, 0x90, 8);                       //NOPs for hotpatching double hooks
          aNewCode[0x10] = 0x50;                                                   //push  eax
          aNewCode[0x11] = 0xB8;                                                   //mov   eax, ADDR lpInjCode
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x12)) = (ULONG)(lpHookEntry->lpInjCodeAndData);
          aNewCode[0x16] = 0xF7;                                                   //test  dword ptr [eax], 00000101h
          aNewCode[0x17] = 0x00;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x18)) = 0x00000101;
          aNewCode[0x1C] = 0x75;                                                   //jne   @@1 ;if disabled/uninst
          aNewCode[0x1D] = 0x06;
          aNewCode[0x1E] = 0x58;                                                   //pop   eax
          aNewCode[0x1F] = 0xE9;                                                   //jmp   hooked proc
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x20)) = (ULONG)(lpHookEntry->lpNewProc) -
                                                     (ULONG)(lpHookEntry->lpInjCodeAndData) - 0x24;
          aNewCode[0x24] = 0x58;                                                   //@@1: pop   eax
          lpHookEntry->lpCall2Orig = lpHookEntry->lpInjCodeAndData + 0x25;
          NktHookLibHelpers::MemCopy(aNewCode+0x25, lpHookEntry->aNewStub, lpHookEntry->nNewStubSize); //new stub
          aNewCode[0x25+lpHookEntry->nNewStubSize] = 0xE9;                         //jmp original proc after stub
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x26+lpHookEntry->nNewStubSize)) =
                                         (ULONG)(lpHookEntry->lpOrigProc) + (ULONG)(lpHookEntry->nOriginalStubSize) -
                                         (ULONG)(lpHookEntry->lpInjCodeAndData+0x2A+lpHookEntry->nNewStubSize);
          break;

#if defined _M_X64
        case NKTHOOKLIB_PRocessPlatformX64:
          NktHookLibHelpers::MemSet(aNewCode, 0x00, 8);                            //flags location
          NktHookLibHelpers::MemSet(aNewCode+0x08, 0x90, 8);                       //NOPs for hotpatching double hooks
          aNewCode[0x10] = 0x50;                                                   //push  rax
          aNewCode[0x11] = 0x48;                                                   //mov   rax, ADDR lpInjCode
          aNewCode[0x12] = 0xB8;
          *((ULONGLONG NKT_UNALIGNED*)(aNewCode+0x13)) = (ULONGLONG)(lpHookEntry->lpInjCodeAndData);
          aNewCode[0x1B] = 0xF7;                                                   //test  dword ptr [rax], 00000101h
          aNewCode[0x1C] = 0x00;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x1D)) = 0x00000101;
          aNewCode[0x21] = 0x75;                                                   //jne   @@1 ;if disabled/uninst
          aNewCode[0x22] = 0x0F;
          aNewCode[0x23] = 0x58;                                                   //pop   rax
          aNewCode[0x24] = 0xFF;                                                   //jmp   hooked proc
          aNewCode[0x25] = 0x25;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x26)) = 0;
          *((ULONGLONG NKT_UNALIGNED*)(aNewCode+0x2A)) = (ULONGLONG)(lpHookEntry->lpNewProc);
          aNewCode[0x32] = 0x58;                                                   //@@1: pop   rax
          lpHookEntry->lpCall2Orig = lpHookEntry->lpInjCodeAndData+0x33;
          NktHookLibHelpers::MemCopy(aNewCode+0x33, lpHookEntry->aNewStub, lpHookEntry->nNewStubSize); //new stub
          aNewCode[0x33+lpHookEntry->nNewStubSize] = 0xFF;                         //jmp original proc after stub
          aNewCode[0x34+lpHookEntry->nNewStubSize] = 0x25;
          *((ULONG NKT_UNALIGNED*)(aNewCode+0x35+lpHookEntry->nNewStubSize)) = 0;
          *((ULONGLONG NKT_UNALIGNED*)(aNewCode+0x39+lpHookEntry->nNewStubSize)) =
                                             (ULONGLONG)(lpHookEntry->lpOrigProc + lpHookEntry->nOriginalStubSize);
          break;
#endif //_M_X64
      }
      if (NktHookLibHelpers::WriteMem(cProcEntry->GetHandle(), lpHookEntry->lpInjCodeAndData, aNewCode,
                                      lpHookEntry->nInjCodeAndDataSize) == FALSE)
      {
        dwOsErr = ERROR_ACCESS_DENIED;
        continue;
      }
      //replace original proc with a jump
      dw = (DWORD)(lpHookEntry->lpInjCodeAndData+8) - (DWORD)(lpHookEntry->lpOrigProc) - 5;
      lpHookEntry->aJumpStub[0] = 0xE9; //JMP
      lpHookEntry->aJumpStub[1] = (BYTE)( dw        & 0xFF);
      lpHookEntry->aJumpStub[2] = (BYTE)((dw >>  8) & 0xFF);
      lpHookEntry->aJumpStub[3] = (BYTE)((dw >> 16) & 0xFF);
      lpHookEntry->aJumpStub[4] = (BYTE)((dw >> 24) & 0xFF);
      //set id
#if defined _M_IX86
      lpHookEntry->nId = (SIZE_T)lpHookEntry ^ 0x34B68363UL; //odd number to avoid result of zero
#elif defined _M_X64
      lpHookEntry->nId = (SIZE_T)lpHookEntry ^ 0x34B68364A3CE19F3ui64; //odd number to avoid result of zero
#endif
      //done
      aHookInfo[nHookIdx].nHookId = lpHookEntry->nId;
      aHookInfo[nHookIdx].lpCallOriginal = lpHookEntry->lpCall2Orig;
    }
    //hook new items
    if (dwOsErr == NO_ERROR)
    {
      NktHookLib::CNktThreadSuspend::CAutoResume cAutoResume(&(int_data->cThreadSuspender));
      NktHookLib::CNktThreadSuspend::IP_RANGE sIpRanges[MAX_SUSPEND_IPRANGES];
      SIZE_T k, k2, nThisRoundSuspCount;
      MEMORY_BASIC_INFORMATION sMbi;
      HOOK_INFO sHooks[64];
      DWORD dwNewProt, dwOldProt;

      for (nHookIdx=nThisRoundSuspCount=0; nHookIdx<nCount && dwOsErr==NO_ERROR; )
      {
        if (nThisRoundSuspCount == 0)
        {
          //suspend threads
          nThisRoundSuspCount = (nCount-nHookIdx > MAX_SUSPEND_IPRANGES) ? MAX_SUSPEND_IPRANGES : (nCount-nHookIdx);
          for (k=0; k<nThisRoundSuspCount; k++)
          {
            sIpRanges[k].nStart = (SIZE_T)(lpNewEntriesList[nHookIdx+k]->lpOrigProc);
            sIpRanges[k].nEnd = sIpRanges[k].nStart + HOOKENG_JUMP_TO_HOOK_SIZE;
          }
          dwOsErr = NO_ERROR;
          if (int_data->sOptions.bSuspendThreads != FALSE)
            dwOsErr = int_data->cThreadSuspender.SuspendAll(cProcEntry->GetPid(), sIpRanges, nThisRoundSuspCount);
          if (dwOsErr != NO_ERROR)
          {
err_uninstall_and_destroy:
            for (nHookIdx=k2=0; nHookIdx<nCount; nHookIdx++)
            {
              if (lpNewEntriesList[nHookIdx]->nInstalledCode != 0)
              {
                sHooks[k2++].nHookId = lpNewEntriesList[nHookIdx]->nId;
                if (k2 >= X_ARRAYLEN(sHooks))
                {
                  Unhook(sHooks, k2);
                  k2 = 0;
                }
              }
            }
            if (k2 > 0)
              Unhook(sHooks, k2);
            continue;
          }
        }
        for (k=0; k<nThisRoundSuspCount; k++)
        {
          k2 = 0;
          lpPtr = lpNewEntriesList[nHookIdx+k]->lpOrigProc;
          NktHookLibHelpers::MemSet(&sMbi, 0, sizeof(sMbi));
          nNtStatus = NktHookLib::NktNtQueryVirtualMemory(cProcEntry->GetHandle(), lpPtr, MyMemoryBasicInformation,
                                                         &sMbi, sizeof(sMbi), &k2);
          dwNewProt = PAGE_EXECUTE_WRITECOPY;
          if (NT_SUCCESS(nNtStatus))
          {
            switch (sMbi.Protect & 0xFF)
            {
              case PAGE_NOACCESS:
              case PAGE_READONLY:
              case PAGE_READWRITE:
                dwNewProt = PAGE_READWRITE;
                break;
              case PAGE_WRITECOPY:
                dwNewProt = PAGE_WRITECOPY;
                break;
              case PAGE_EXECUTE:
              case PAGE_EXECUTE_READ:
              case PAGE_EXECUTE_READWRITE:
                dwNewProt = PAGE_EXECUTE_READWRITE;
                break;
            }
          }
          //change protection if needed
          if (dwNewProt != (sMbi.Protect & 0xFF))
          {
            dwOldProt = 0;
            nSize = HOOKENG_JUMP_TO_HOOK_SIZE;
            nNtStatus = NktHookLib::NktNtProtectVirtualMemory(cProcEntry->GetHandle(), (PVOID*)&lpPtr, &nSize,
                                                             dwNewProt, &dwOldProt);
            if (!NT_SUCCESS(nNtStatus))
            {
              dwOsErr = NktHookLib::NktRtlNtStatusToDosError(nNtStatus);
              if (dwOsErr == 0)
                dwOsErr = ERROR_NOT_SUPPORTED;
              int_data->cThreadSuspender.ResumeAll();
              goto err_uninstall_and_destroy;
            }
          }
          //replace each entry point
          k2 = (NktHookLibHelpers::WriteMem(cProcEntry->GetHandle(), lpNewEntriesList[nHookIdx+k]->lpOrigProc,
                                            lpNewEntriesList[nHookIdx+k]->aJumpStub,
                                            HOOKENG_JUMP_TO_HOOK_SIZE) != FALSE) ? 1 : 0;
          //restore protection
          if (dwNewProt != (sMbi.Protect & 0xFF))
          {
            lpPtr = lpNewEntriesList[nHookIdx+k]->lpOrigProc;
            nSize = HOOKENG_JUMP_TO_HOOK_SIZE;
            NktHookLib::NktNtProtectVirtualMemory(cProcEntry->GetHandle(), (PVOID*)&lpPtr, &nSize, dwOldProt, &dw);
          }
          //check write operation result
          if (k2 == 0)
          {
            dwOsErr = ERROR_ACCESS_DENIED;
            int_data->cThreadSuspender.ResumeAll();
            goto err_uninstall_and_destroy;
          }
          //flush instruction cache
          NktHookLib::NktNtFlushInstructionCache(cProcEntry->GetHandle(), lpNewEntriesList[nHookIdx+k]->lpOrigProc, 32);
          //mark as installed
          lpNewEntriesList[nHookIdx+k]->nInstalledCode = 1;
        }
        //advance count
        nHookIdx += nThisRoundSuspCount;
        //check if we can proceed with the next hook with this
        nThisRoundSuspCount = 0;
        for (k=nHookIdx; k<nCount; k++)
        {
          k2 = (SIZE_T)(lpNewEntriesList[k]->lpOrigProc);
          if (int_data->cThreadSuspender.CheckIfThreadIsInRange(k2, k2+HOOKENG_JUMP_TO_HOOK_SIZE) == FALSE)
            break;
          nThisRoundSuspCount++;
        }
        if (nThisRoundSuspCount == 0)
        {
          //resume threads
          int_data->cThreadSuspender.ResumeAll();
        }
      }
    }
    //done... move to the final list or delete on error
    if (dwOsErr == NO_ERROR)
    {
      for (nHookIdx=0; nHookIdx<nCount; nHookIdx++)
      {
        lpNewEntriesList[nHookIdx]->dwFlags = dwFlags;
        if (int_data->sOptions.bOutputDebug != FALSE)
        {
          NktHookLibHelpers::DebugPrint("NktHookLib: Hook installed. Proc @ 0x%IX -> 0x%IX (Stub @ 0x%IX) \r\n",
                    (SIZE_T)(lpNewEntriesList[nHookIdx]->lpOrigProc), (SIZE_T)(lpNewEntriesList[nHookIdx]->lpNewProc),
                    (SIZE_T)(lpNewEntriesList[nHookIdx]->lpInjCodeAndData));
        }
        int_data->cHooksList.PushTail(lpNewEntriesList[nHookIdx]);
      }
    }
    else
    {
      for (nHookIdx=0; nHookIdx<nCount; nHookIdx++)
        delete lpNewEntriesList[nHookIdx];
    }
    if (lpNewEntriesList != NULL)
      NktHookLibHelpers::MemFree(lpNewEntriesList);
  }
Example #14
0
VOID CNktWorkerThread::ThreadProc()
{
  NKT_ASSERT(lpStartRoutine != NULL);
  lpStartRoutine(this, lpParam);
  return;
}