Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
7.6 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. webblade.c
  5. Abstract:
  6. This module contains the main routine and
  7. helper routines to enforce software restrictions
  8. for the Web Blade SKU.
  9. exe's whose hash values test positive w.r.t
  10. the hardcoded hash array in webblade.h will
  11. be disallowed from executing.
  12. Author:
  13. Vishnu Patankar (VishnuP) 01-May-2001
  14. Revision History:
  15. --*/
  16. #include "basedll.h"
  17. #pragma hdrstop
  18. #include "webbladep.h"
  19. #include "webbladehashesp.h"
  20. #define WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, HexNibbleMask) ((bLeastSignificantNibble) ? (HexNibbleMask) : ((HexNibbleMask) << 4))
  21. BYTE WebBladeDisallowedHashes[][WEB_BLADE_MAX_HASH_SIZE*2+1] = {
  22. WEBBLADE_SORTED_ASCENDING_HASHES
  23. };
  24. #define WEB_BLADE_NUM_HASHES sizeof(WebBladeDisallowedHashes)/(WEB_BLADE_MAX_HASH_SIZE * 2 + 1)
  25. NTSTATUS
  26. BasepCheckWebBladeHashes(
  27. IN HANDLE hFile
  28. )
  29. /*++
  30. Routine Description:
  31. This routine computes the web blade hash for the candidate file
  32. and checks for membership in the hardcoded WebBladeDisallowedHashes[].
  33. If the hash is present, the code should not be allowed to execute.
  34. Arguments:
  35. hFile - the file handle of the exe file to check for allow/disallow.
  36. Return Value:
  37. NTSTATUS - if disallowed, this is STATUS_ACCESS_DENIED else
  38. it is the internal status of other APIs
  39. --*/
  40. {
  41. NTSTATUS Status = STATUS_SUCCESS;
  42. BYTE FileHashValue[WEB_BLADE_MAX_HASH_SIZE];
  43. DWORD dwIndex;
  44. static BOOL bConvertReadableHashToByteHash = TRUE;
  45. //
  46. // Optimization: Half of the same array is used since the CHARs can
  47. // be compressed 2:1 into actual hash'ish BYTES (e.g. two readable
  48. // CHARS "0E" is actually one BYTE 00001110) i.e. each 32 CHAR hash
  49. // becomes a 16 BYTE hash
  50. //
  51. if (bConvertReadableHashToByteHash) {
  52. for (dwIndex = 0;
  53. dwIndex < WEB_BLADE_NUM_HASHES;
  54. dwIndex++) {
  55. Status = WebBladepConvertStringizedHashToHash( WebBladeDisallowedHashes[dwIndex] );
  56. if (!NT_SUCCESS(Status)) {
  57. goto ExitHandler;
  58. }
  59. }
  60. //
  61. // This conversion should be done only once per process (otherwise we
  62. // would be doing a fixed point computation)
  63. //
  64. bConvertReadableHashToByteHash = FALSE;
  65. }
  66. //
  67. // Compute the limited hash
  68. //
  69. #define ITH_REVISION_1 1
  70. Status = RtlComputeImportTableHash( hFile, FileHashValue, ITH_REVISION_1 );
  71. if (!NT_SUCCESS(Status)) {
  72. goto ExitHandler;
  73. }
  74. //
  75. // Check for membership of the computed hash in the sorted disallowed hash array
  76. // Use binary search for O (log n) complexity
  77. //
  78. if ( bsearch (FileHashValue,
  79. WebBladeDisallowedHashes,
  80. WEB_BLADE_NUM_HASHES,
  81. WEB_BLADE_MAX_HASH_SIZE * 2 + 1,
  82. pfnWebBladeHashCompare
  83. )) {
  84. //
  85. // FileHashValue tested positive for membership in WebBladeDisallowedHashes[][]
  86. //
  87. Status = STATUS_ACCESS_DENIED;
  88. }
  89. ExitHandler:
  90. return Status;
  91. }
  92. int
  93. __cdecl pfnWebBladeHashCompare(
  94. const BYTE *WebBladeFirstHash,
  95. const BYTE *WebBladeSecondHash
  96. )
  97. /*++
  98. Routine Description:
  99. This routine byte-lexically compares two WebBladeHashes.
  100. Essentially, it wraps memcmp.
  101. Arguments:
  102. WebBladeHashFirst - the first web blade hash
  103. WebBladeHashSecond - the second web blade hash
  104. Return Value:
  105. 0 if equal,
  106. -ve if WebBladeHashFirst < WebBladeHashSecond
  107. +ve if WebBladeHashFirst > WebBladeHashSecond
  108. --*/
  109. {
  110. return memcmp(WebBladeFirstHash, WebBladeSecondHash, WEB_BLADE_MAX_HASH_SIZE);
  111. }
  112. NTSTATUS WebBladepConvertStringizedHashToHash(
  113. IN OUT PCHAR pStringizedHash
  114. )
  115. /*++
  116. Routine Description:
  117. This routine converts a readable 32 CHAR hash into a 16 BYTE hash.
  118. As an optimization, the conversion is done in-place.
  119. Optimization: Half of the same array is used since the CHARs can
  120. be compressed 2:1 into actual hash'ish BYTES (e.g. two readable
  121. CHARS "0E" is actually one BYTE 00001110) i.e. each 32 CHAR hash
  122. becomes a 16 BYTE hash
  123. One byte is assembled by looking at two characters.
  124. Arguments:
  125. pStringizedHash - Pointer to the beginning of a 32 CHAR (in) 16 BYTE (out) hash.
  126. Return Value:
  127. STATUS_SUCCESS if the hash value was computed, else the error in
  128. hash computation (if any)
  129. --*/
  130. {
  131. DWORD dwHashIndex = 0;
  132. DWORD dwStringIndex = 0;
  133. BYTE OneByte = 0;
  134. BOOL bLeastSignificantNibble = FALSE;
  135. NTSTATUS Status = STATUS_SUCCESS;
  136. if (pStringizedHash == NULL) {
  137. Status = STATUS_INVALID_PARAMETER;
  138. goto ExitHandler;
  139. }
  140. for (dwStringIndex=0; dwStringIndex < WEB_BLADE_MAX_HASH_SIZE * 2; dwStringIndex++ ) {
  141. switch (pStringizedHash[dwStringIndex]) {
  142. case '0':
  143. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x0);
  144. break;
  145. case '1':
  146. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x1);
  147. break;
  148. case '2':
  149. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x2);
  150. break;
  151. case '3':
  152. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x3);
  153. break;
  154. case '4':
  155. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x4);
  156. break;
  157. case '5':
  158. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x5);
  159. break;
  160. case '6':
  161. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x6);
  162. break;
  163. case '7':
  164. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x7);
  165. break;
  166. case '8':
  167. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x8);
  168. break;
  169. case '9':
  170. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0x9);
  171. break;
  172. case 'a':
  173. case 'A':
  174. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0xa);
  175. break;
  176. case 'b':
  177. case 'B':
  178. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0xb);
  179. break;
  180. case 'c':
  181. case 'C':
  182. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0xc);
  183. break;
  184. case 'd':
  185. case 'D':
  186. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0xd);
  187. break;
  188. case 'e':
  189. case 'E':
  190. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0xe);
  191. break;
  192. case 'f':
  193. case 'F':
  194. OneByte |= WEB_BLADEP_EXTRACT_NIBBLE(bLeastSignificantNibble, 0xf);
  195. break;
  196. default:
  197. ASSERT(FALSE);
  198. Status = STATUS_INVALID_PARAMETER;
  199. goto ExitHandler;
  200. }
  201. if (bLeastSignificantNibble) {
  202. pStringizedHash[dwHashIndex++] = OneByte;
  203. OneByte = 0;
  204. }
  205. bLeastSignificantNibble = !bLeastSignificantNibble;
  206. }
  207. ExitHandler:
  208. return Status;
  209. }