Ejemplo n.º 1
0
BOOL Dasm_GetInstructionSize (BYTE * pInst, UINT * pnSize, UINT * pnSizeIfMoved) 
{
  int nSize = 0 ;  
  int nSizeIfMoved = 0 ;

  ASSERT (pInst!=NULL) ;

  switch( pInst[0] )
    {
    case 0x71:
    case 0x72:	// JB rel8
    case 0x73:	// JAE rel8
    case 0x74:
    case 0x75:
    case 0x76:
    case 0x77:	// JA rel8
    case 0x78:
    case 0x79:
    case 0x7A:
    case 0x7B:
    case 0x7C:
    case 0x7D:
    case 0x7E:
    case 0x7F:	// JG rel8
    case 0xE3:	// JECXZ rel8      
      nSize = 2 ;
      nSizeIfMoved = 5 ;
      break ;

    case 0x0F:
      switch( pInst[1] )
	{
	case 0x81:
	case 0x82:
	case 0x83:
	case 0x84:
	case 0x85:
	case 0x86:
	case 0x87:
	case 0x88:
	case 0x89:
	case 0x8A:
	case 0x8B:
	case 0x8C:
	case 0x8D:
	case 0x8E:
	case 0x8F:
	  nSize = 6 ;
	  break ;
	}
      break ;

    case 0x48:	// DEC EAX
    case 0x49:  // DEC ECX
    case 0x4A:	// DEC EDX
    case 0x4B:	// DEC EBX
    case 0x4C:	// DEC ESP
    case 0x4D:  // DEC EBP
    case 0x4E:	// DEC ESI
    case 0x4F:	// DEC EDI
    case 0x50:	// PUSH EAX    
    case 0x51:	// PUSH ECX
    case 0x52:	// PUSH EDX
    case 0x53:  // PUSH EBX
    case 0x54:  // PUSH ESP
    case 0x55:	// PUSH EBP
    case 0x56:	// PUSH ESI
    case 0x57:	// PUSH EDI
    case 0x58:	// POP	EAX
    case 0x59:	// POP	ECX
    case 0x5A:	// POP	EDX
    case 0x5B:	// POP	EBX
    case 0x5C:	// POP	ESP
    case 0x5D:	// POP	EBP
    case 0x5E:	// POP	ESI
    case 0x5F:	// POP	EDI
    case 0x60:	// PUSHAD
    case 0x61:	// PUSHAD
    case 0x90:	// NOP
    case 0x91:  // XCHG EAX,ECX
    case 0x92:	// XCHG EAX,EDX
    case 0x93:	// XCHG EAX,EBX
    case 0x94:	// XCHG EAX,ESP
    case 0x95:  // XCHG EAX,EBP
    case 0x96:	// XCHG EAX,ESI
    case 0x97:	// XCHG EAX,EDI
    case 0xC3:	// RET (near)
    case 0xCB:	// RET (far)
    case 0xCC:	// INT 3
    case 0xCE:	// INTO
      nSize = 1 ;
      break ;

    case 0x0C:	// OR AL,imm8
    case 0x3F:	// CMP AL,imm8
    case 0x6A:	// PUSH imm8
    case 0xA0:	// MOV AL,moffs8
    case 0xA2:	// MOV moffs8,AL
    case 0xB0:  // MOV AL, imm8
    case 0xB1:  // MOV CL, imm8
    case 0xB2:  // MOV DL, imm8
    case 0xB3:  // MOV BL, imm8
    case 0xB4:  // MOV AH, imm8
    case 0xB5:  // MOV CH, imm8
    case 0xB6:  // MOV DH, imm8
    case 0xB7:  // MOV BH, imm32
    case 0xCD:	// INT imm8
      nSize = 2 ;
      break ;

    case 0xC2:	// RET imm16 (near)
    case 0xCA:	// RET imm16 (far)
      nSize = 3 ;
      break ;

    case 0x0D:	// OR EAX, imm32
    case 0x3D:	// CMP EAX,imm32
    case 0x68:	// PUSH imm32
    case 0xA1:	// MOV EAX,moffs32
    case 0xA3:	// MOV moffs32,EAX
    case 0xB8:  // MOV EAX, imm32
    case 0xB9:  // MOV ECX, imm32
    case 0xBA:  // MOV EDX, imm32
    case 0xBB:  // MOV EBX, imm32
    case 0xBC:  // MOV ESP, imm32
    case 0xBD:  // MOV EBP, imm32
    case 0xBE:  // MOV ESI, imm32
    case 0xBF:  // MOV EDI, imm32
    case 0xE8:	// CALL rel32
    case 0xE9:	// JMP rel32
      nSize = 5 ;
      break ;

    case 0x00:	// ADD r/m8,r8
    case 0x01:	// ADD r/m32,r32
    case 0x02:	// ADD r8,r/m8
    case 0x03:	// ADD r32,r/m32
    case 0x08:	// OR r/m8,r8
    case 0x09:	// OR r/m16,r16
    case 0x0A:	// OR r8,r/m8
    case 0x0B:	// OR r32,m/r32
    case 0x33:	// XOR r32,r/m32
    case 0x38:	// CMP r/m8,r8
    case 0x39:	// CMP r/m32,r32
    case 0x3A:	// CMP r8,r/m8
    case 0x3B:	// CMP r32,r/m32
    case 0x85:	// TEST r/m32,r32
    case 0x88:	// MOV r/m8,r8
    case 0x89:	// MOV r/m32,r32
    case 0x8A:	// MOV r8,r/m8
    case 0x8B:	// MOV r32,r/m32
    case 0x8C:	// MOV r/m16,Sreg
    case 0x8D:	// LEA r32,m
    case 0x8E:	// MOV Sreg,r/m16
      nSize = _Dasm_ReadModRmAndSid (1, pInst) ;
      break ;

    case 0x64:  // FS instruction prefix
      if( Dasm_GetInstructionSize(pInst+1,&nSize,&nSizeIfMoved) )
	{
	  nSize += 1 ;
	  nSizeIfMoved += 1 ;
	}
      break ;

    case 0xC6:
      switch( OPCODE(pInst[1]) )
	{
	case 0:		// MOV r/m8,imm8
	  nSize = _Dasm_ReadModRmAndSid (1, pInst) + 1 ;
	  break ;
	}
      break ;

    case 0xC7:
      switch( OPCODE(pInst[1]) )
	{
	case 0:		// MOV r/m32,imm32
	  nSize = _Dasm_ReadModRmAndSid (1, pInst) + 4 ;
	  break ;
	}
      break ;

    case 0x80:      
      switch( OPCODE(pInst[1]) )
	{
	case 1:		// OR r/m8,imm8
	case 7:		// CMP r/m8,imm8 
	  nSize = _Dasm_ReadModRmAndSid (1, pInst) + 1 ;
	  break ;
	}
      break ;

    case 0x81:
      switch( OPCODE(pInst[1]) )
	{
	case 1:		// OR r/m32,imm32
	case 5:		// SUB r/m32,imm32
	case 7:		// CMP r/m32,imm32 
	  nSize = _Dasm_ReadModRmAndSid (1, pInst) + 4 ;
	  break ;
	}
      break ;

    case 0x83:      
      switch( OPCODE(pInst[1]) )
	{
	case 1:		// OR r/m32,imm8
	case 5:		// SUB r/m32,imm8
	case 7:		// CMP r/m32,imm8
	  nSize = _Dasm_ReadModRmAndSid (1, pInst) + 1 ;
	  break ;	  
	}
      break ;

    case 0xFF:	
      switch( OPCODE(pInst[1]) )
	{
	case 6: // PUSH r/m32
	  nSize = _Dasm_ReadModRmAndSid (1, pInst) ;
	  break ;
	}
      break ;

    default:
      TRACE_ERROR (TEXT("Unknown instruction 0x%02X\n"), pInst[0]) ;
      break ; 
    }

  if( nSizeIfMoved==0 ) nSizeIfMoved = nSize ;
  
  if( pnSize ) *pnSize = nSize ;
  if( pnSizeIfMoved ) *pnSizeIfMoved = nSizeIfMoved ;

  return nSize != 0 ;
}
Ejemplo n.º 2
0
BOOL  Dasm_MoveProgram (BYTE * pSrc, UINT nSrcSize,
			BYTE * pDst, UINT * pnDstSize, UINT nDstMax)
{
  int		nReadBytes = 0 ;
  int		nWritBytes = 0 ;
  int		nReadInstSize ;
  int		nWritInstSize ;
  BYTE		*pReadInst, *pWritInst ;
  DWORD		dwAddress ;
  BOOL		bSuccess ;

  if( nDstMax < nSrcSize ) {
    TRACE_ERROR (TEXT("Destination buffer too small\n")) ;
    return FALSE ;
  }

  while( nReadBytes < nSrcSize )
    {
      pReadInst = pSrc + nReadBytes ;
      pWritInst = pDst + nWritBytes ;

      bSuccess = Dasm_GetInstructionSize (pReadInst, &nReadInstSize, &nWritInstSize) ;
      
      if( ! bSuccess ) {
	TRACE_ERROR (TEXT("GetInstructionSize failed\n")) ;
	return FALSE ;
      }
      
      if( nReadBytes+nReadInstSize > nSrcSize ) {
	TRACE_ERROR (TEXT("Invalid source size\n")) ;
	return FALSE ;
      }

      if( nWritBytes+nWritInstSize > nDstMax ) {
	TRACE_ERROR (TEXT("Insufficient destination size\n")) ;
	return FALSE ;
      }

      if( pReadInst[0]==0xE8 || pReadInst[0]==0xE9 )
	{
	  // CALL rel32
	  // JMP rel32

	  ASSERT (nReadInstSize==nWritInstSize) ;

	  dwAddress = *(DWORD*)(pReadInst+1) ;	// get source relative
	  dwAddress += (DWORD)pReadInst ;	// convert to absolute
	  dwAddress -= (DWORD)pWritInst ;	// convert to relative

	  pWritInst[0] = pReadInst[0] ;
	  memcpy (pWritInst+1, &dwAddress, sizeof(DWORD)) ;

	  TRACE_WARNING (TEXT("JMP rel32 or CALL rel32 instruction patched (0x%02X)\n"), pReadInst[0]) ;
	}
      else if( ( pReadInst[0]==0x0F && pReadInst[1]>=0x81 && pReadInst[1]<=0x8F ) || pReadInst[0]==0xE3 )
	{
	  // Jxx rel32

	  ASSERT (nReadInstSize==nWritInstSize) ;
	  
	  dwAddress = *(DWORD*)(pReadInst+2) ;	// get source relative
	  dwAddress += (DWORD)pReadInst ;	// convert to absolute
	  dwAddress -= (DWORD)pWritInst ;	// convert to relative

	  pWritInst[0] = pReadInst[0] ;
	  pWritInst[1] = pReadInst[1] ;
	  memcpy (pWritInst+2, &dwAddress, sizeof(DWORD)) ;

	  TRACE_WARNING (TEXT("Jxx rel32 instruction patched (0x%02X)\n"), pReadInst[0]) ;
	}
      else if( pReadInst[0]>=0x71 && pReadInst[0]<=0x7F )
	{
	  // Jxx rel8

	  ASSERT (nReadInstSize+3==nWritInstSize) ;
	  
	  dwAddress = *(BYTE*)(pReadInst+1) ;	// get source relative
	  dwAddress += (DWORD)pReadInst ;	// convert to absolute
	  dwAddress -= (DWORD)pWritInst ;	// convert to relative

	  pWritInst[0] = 0x0F ;
	  pWritInst[1] = pReadInst[0] + 0x10 ;
	  memcpy (pWritInst+2, &dwAddress, sizeof(DWORD)) ;

	  TRACE_WARNING (TEXT("Jxx rel8 instruction patched (0x%02X)\n"), pReadInst[0]) ;
	}
      else
	{
	  // Any other instruction

	  ASSERT (nReadInstSize==nWritInstSize) ;

	  memcpy (pWritInst, pReadInst, nReadInstSize) ;
	}
      
      nReadBytes += nReadInstSize ;
      nWritBytes += nWritInstSize ;
    }
  
  ASSERT (nReadBytes==nSrcSize) ;

  *pnDstSize = nWritBytes ;

  return TRUE ;
}
Ejemplo n.º 3
0
NTSTATUS Hook_InstallHook (HOOKSTRUCT * pHook) 
{
  DWORD		dwJmpDst ;
  int		nInstSize, nInstSizeIfMoved ;
  int		i ;
  DWORD		nOldCr0, nNewCr0 ;
  BOOL		bSuccess ;
  
  ASSERT (pHook!=NULL) ;
  ASSERT (pHook->pTargetFunc!=NULL) ;

  //
  // Mesure head size and stub size
  // ------------------------------

  TRACE_INFO (TEXT("Measure head size (target=0x%08X)\n"), pHook->pTargetFunc) ;

  pHook->nHeadSize = 0 ;
  pHook->nStubSize = 5 ; // == sizeof(JMP rel32)

  while( pHook->nHeadSize < 5 ) // need at least 5 char to path
    {
      bSuccess = Dasm_GetInstructionSize (pHook->pTargetFunc+pHook->nHeadSize, 
					  &nInstSize, 
					  &nInstSizeIfMoved) ;
      
      if( ! bSuccess ) {
	TRACE_ERROR (TEXT("GetInstructionSize failed (target=0x%08X)\n"), pHook->pTargetFunc) ;
	return STATUS_UNSUCCESSFUL ;
      }
      
      pHook->nHeadSize += nInstSize ;
      pHook->nStubSize += nInstSizeIfMoved ;
      
      if( pHook->nStubSize >= MAX_STUB_SIZE ) {
	TRACE_ERROR (TEXT("Stub too big (target=0x%08X)\n"), pHook->pTargetFunc) ;
	return STATUS_UNSUCCESSFUL ;
      }      
    }

  TRACE_INFO (TEXT("Head size = %d\n"), pHook->nHeadSize) ;
  TRACE_INFO (TEXT("Stub size = %d\n"), pHook->nStubSize) ;


  //
  // Backup the function head
  // ------------------------

  TRACE_INFO (TEXT("Backup function head\n")) ;

  memcpy (pHook->pHead, pHook->pTargetFunc, pHook->nHeadSize) ;
  
 
  //
  // Create stub
  // -----------

  TRACE_INFO (TEXT("Create stub (stub=0x%08X)\n"), pHook->pStub) ;
  
  // create stub
  bSuccess = Dasm_MoveProgram (pHook->pTargetFunc, pHook->nHeadSize,
			       pHook->pStub, &pHook->nStubSize, MAX_STUB_SIZE) ;
  if( ! bSuccess ) 
    {
      TRACE_ERROR (TEXT("MoveProgram failed (target=0x%08X)\n"), pHook->pTargetFunc) ;
      return STATUS_UNSUCCESSFUL ;
    }
  
  // add jmp at the end of the stub
  dwJmpDst = (DWORD)pHook->pTargetFunc - (DWORD)pHook->pStub - pHook->nStubSize ;
  pHook->pStub[pHook->nStubSize] = 0xE9 ; // JMP rel32
  memcpy (&pHook->pStub[pHook->nStubSize+1], &dwJmpDst, 4) ; 
  pHook->nStubSize += 5 ;

  TRACE_INFO (TEXT("Stub created (stub=0x%08X, size=%u)\n"),
	      pHook->pStub, pHook->nStubSize) ;
  
  
  //
  // Remove target protection
  // ------------------------

  TRACE_INFO (TEXT("Removing write protection\n")) ;
  
  GET_CR0 (nOldCr0) ;
  nNewCr0 = nOldCr0 & ~0x10000 ;
  SET_CR0 (nNewCr0) ;

  //
  // Patch target
  // ------------

  TRACE_INFO (TEXT("Patching target\n")) ;

  // overwrite head with a jmp to spy function
  pHook->pTargetFunc[0] = 0xE9 ; // JMP rel32
  dwJmpDst = (DWORD)pHook->pHookFunc - (DWORD)pHook->pTargetFunc - 5 ; // 5==sizeof(JMP rel32)
  memcpy (pHook->pTargetFunc+1, &dwJmpDst, 4) ;
  
  // complete head with NOPs
  for( i=5 ; i<pHook->nHeadSize ; i++ )
    pHook->pTargetFunc[i] = 0x90 ; // NOP

  //
  // Restore target protection
  // -------------------------

  TRACE_INFO (TEXT("Restoring write protection\n")) ;
  SET_CR0 (nOldCr0) ;
   
  return STATUS_SUCCESS ;  
}