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.

229 lines
8.6 KiB

  1. #include <windows.h>
  2. #include "stdtypes.h"
  3. /*
  4. ** VIRWINN.C
  5. **
  6. ** This is an attempt at virus detection. The routine FVirCheck
  7. ** should be called sometime during the boot process, and takes
  8. ** one argument, a handle to the application instance. The
  9. ** ComplainAndQuit() call should be replaced with code appropriate
  10. ** to your application. It is recommended that this bring up
  11. ** a dialog with an error message, and give the user the option of
  12. ** continuing (defaults to terminating). If the user chooses to
  13. ** terminate (or if the option is not given), ComplainAndQuit()
  14. ** should clean up anything that has been done so far, and exit.
  15. */
  16. /* WARNING!! Do not change WHashGood at all!!
  17. ** WARNING!! WHashGood must be a near procedure, compiled native.
  18. */
  19. /*
  20. ** EXE header format definitions. Lifted from linker.
  21. */
  22. #define EMAGIC 0x5A4D /* Old magic number */
  23. #define ERES2WDS 0x000A /* No. of reserved words in e_res2 */
  24. struct exe_hdr /* DOS 1, 2, 3 .EXE header */
  25. {
  26. unsigned short e_magic; /* Magic number */
  27. unsigned short e_cblp; /* Bytes on last page of file */
  28. unsigned short e_cp; /* Pages in file */
  29. unsigned short e_crlc; /* Relocations */
  30. unsigned short e_cparhdr; /* Size of header in paragraphs */
  31. unsigned short e_minalloc; /* Minimum extra paragraphs needed */
  32. unsigned short e_maxalloc; /* Maximum extra paragraphs needed */
  33. unsigned short e_ss; /* Initial (relative) SS value */
  34. unsigned short e_sp; /* Initial SP value */
  35. unsigned short e_csum; /* Checksum */
  36. unsigned short e_ip; /* Initial IP value */
  37. unsigned short e_cs; /* Initial (relative) CS value */
  38. unsigned short e_lfarlc; /* File address of relocation table */
  39. unsigned short e_ovno; /* Overlay number */
  40. unsigned long e_sym_tab; /* offset of symbol table file */
  41. unsigned short e_flags; /* old exe header flags */
  42. unsigned short e_res; /* Reserved words */
  43. unsigned short e_oemid; /* OEM identifier (for e_oeminfo) */
  44. unsigned short e_oeminfo; /* OEM information; e_oemid specific */
  45. unsigned short e_res2[ERES2WDS]; /* Reserved words */
  46. long e_lfanew; /* File address of new exe header */
  47. };
  48. /*
  49. ** NEW EXE format definitions. Lifted from linker
  50. */
  51. #define NEMAGIC 0x454E /* New magic number */
  52. #define NERESBYTES 8 /* Eight bytes reserved (now) */
  53. #define NECRC 8 /* Offset into new header of NE_CRC */
  54. struct new_exe /* New .EXE header */
  55. {
  56. unsigned short ne_magic; /* Magic number NE_MAGIC */
  57. unsigned char ne_ver; /* Version number */
  58. unsigned char ne_rev; /* Revision number */
  59. unsigned short ne_enttab; /* Offset of Entry Table */
  60. unsigned short ne_cbenttab; /* Number of bytes in Entry Table */
  61. long ne_crc; /* Checksum of whole file */
  62. unsigned short ne_flags; /* Flag word */
  63. unsigned short ne_autodata; /* Automatic data segment number */
  64. unsigned short ne_heap; /* Initial heap allocation */
  65. unsigned short ne_stack; /* Initial stack allocation */
  66. long ne_csip; /* Initial CS:IP setting */
  67. long ne_sssp; /* Initial SS:SP setting */
  68. unsigned short ne_cseg; /* Count of file segments */
  69. unsigned short ne_cmod; /* Entries in Module Reference Table */
  70. unsigned short ne_cbnrestab; /* Size of non-resident name table */
  71. unsigned short ne_segtab; /* Offset of Segment Table */
  72. unsigned short ne_rsrctab; /* Offset of Resource Table */
  73. unsigned short ne_restab; /* Offset of resident name table */
  74. unsigned short ne_modtab; /* Offset of Module Reference Table */
  75. unsigned short ne_imptab; /* Offset of Imported Names Table */
  76. long ne_nrestab; /* Offset of Non-resident Names Table */
  77. unsigned short ne_cmovent; /* Count of movable entries */
  78. unsigned short ne_align; /* Segment alignment shift count */
  79. unsigned short ne_cres; /* Count of resource entries */
  80. unsigned char ne_exetyp; /* Target operating system */
  81. unsigned char ne_flagsothers; /* Other .EXE flags */
  82. char ne_res[NERESBYTES];
  83. /* Pad structure to 64 bytes */
  84. };
  85. /*
  86. ** WHashGood()
  87. **
  88. ** This returns the correct hash value.
  89. **
  90. ** WARNING!! This routine must not be altered in ANY way. It gets
  91. ** patched and/or rewritten by VIRPATCH!!
  92. */
  93. unsigned near WHashGood ( void );
  94. unsigned near WHashGood ()
  95. {
  96. return (0x1234);
  97. }
  98. /*
  99. ** WHash(wHash, rgb, cb)
  100. **
  101. ** Update hash value to account for cb new bytes pointed to by rgb.
  102. ** Old hash value is wHash; returns new hash value.
  103. **
  104. ** We do the hash on a word basis; the hash function is a simple
  105. ** rotate and add.
  106. */
  107. unsigned WHash ( unsigned wHash, BYTE rgb[], int cb );
  108. unsigned WHash ( unsigned wHash, BYTE rgb[], int cb )
  109. {
  110. while (cb > 1)
  111. {
  112. #pragma warning(disable:4213) /* nonstandard extension : cast on l-value */
  113. wHash = (wHash << 3) + (wHash >> 13) + *((int *)rgb)++;
  114. #pragma warning(default:4213)
  115. cb -= 2;
  116. }
  117. if (cb != 0)
  118. wHash = (wHash << 3) + (wHash >> 13) + *rgb;
  119. return (wHash);
  120. }
  121. /*
  122. ** FVirCheck(hinst)
  123. **
  124. ** This is the main virus detection routine. It should be called
  125. ** during boot, with a handle to the application instance.
  126. ** The detection method used is to hash the EXE headers; this
  127. ** hash value will change if the number or type of segments change,
  128. ** or if their length changes.
  129. */
  130. BOOL FVirCheck ( HANDLE hinst );
  131. BOOL FVirCheck ( HANDLE hinst )
  132. {
  133. int fh;
  134. unsigned wHash;
  135. unsigned cb, cbT;
  136. long lPos;
  137. char sz[256+1];
  138. BYTE rgb[512];
  139. #define pehdr ((struct exe_hdr *)rgb)
  140. #define pnex ((struct new_exe *)rgb)
  141. /* First we have to get a handle to the executable file.
  142. Unfortunately, although Windows already has this file open,
  143. there's no way to use its handle. Instead we have to reopen
  144. the file. */
  145. if (GetModuleFileName(hinst, (char far *)sz, 256) == 0)
  146. return TRUE; //This shouldn't happen but still continue loading
  147. if ((fh = OpenFile((LPSTR)sz, (LPOFSTRUCT)rgb, OF_READ)) == -1)
  148. {
  149. /* We can't open the file. This should never happen; if
  150. it does, it means we're in a weird state, and probably
  151. did something wrong in this code. We'll just say
  152. everything is OK, and continue the boot. */
  153. return TRUE;
  154. }
  155. /* Read old header */
  156. if (_lread(fh, (LPSTR)rgb, sizeof (struct exe_hdr)) != sizeof (struct
  157. exe_hdr) ||
  158. pehdr->e_magic != EMAGIC)
  159. goto Corrupted;
  160. /* Hash old header */
  161. wHash = WHash(0, rgb, sizeof (struct exe_hdr));
  162. lPos = pehdr->e_lfanew;
  163. /* Read new header (and some more) */
  164. if (lPos == 0 || _llseek(fh, lPos, 0) != lPos ||
  165. _lread(fh, (LPSTR)rgb, 512) != 512 || pnex->ne_magic != NEMAGIC)
  166. goto Corrupted;
  167. /* Figure out size of total header; nonresident table is last part
  168. of header. */
  169. cb = (unsigned)(pnex->ne_nrestab - lPos) + pnex->ne_cbnrestab;
  170. /* Do hash on buffer basis */
  171. while (cb > 512)
  172. {
  173. /* Hash this buffer */
  174. wHash = WHash(wHash, rgb, 512);
  175. cb -= 512;
  176. cbT = (cb > 512 ? 512 : cb);
  177. /* and read in next */
  178. if (_lread(fh, (LPSTR)rgb, cbT) != cbT)
  179. goto Corrupted;
  180. }
  181. /* Update hash for final partial buffer, and compare with good value. */
  182. if (WHash(wHash, rgb, cb) != WHashGood())
  183. {
  184. Corrupted:
  185. /* We've got an error reading the file or, more likely,
  186. a hash mismatch. Close the file, give an error, and
  187. quit. */
  188. _lclose(fh);
  189. /* CHANGE THE FOLLOWING LINE TO CODE APPROPRIATE TO YOUR
  190. ** APPLICATION!!
  191. ** This should be replaced with code giving an error message (such as
  192. ** "Application file is corrupted"). It is recommended that this
  193. ** bring up
  194. ** a dialog with an error message, and give the user the option of
  195. ** continuing (defaults to terminating). If the user chooses to
  196. ** terminate (or if the option is not given), ComplainAndQuit()
  197. ** should clean up anything that has been done so far, and exit.
  198. */
  199. /* MessageBox(NULL, "Executable File Corrupted",
  200. * "WARNING", MB_ICONSTOP | MB_OK);
  201. */
  202. /* ComplainAndQuit();
  203. */
  204. /* END OF CHANGE */
  205. return FALSE;
  206. }
  207. /* Everything's OK. Just close the file, and continue. */
  208. _lclose(fh);
  209. return TRUE;
  210. #undef pehdr
  211. #undef pnex
  212. }