stamp.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. *******************************************************************************
  3. \file stamp.c
  4. \brief Integrity control of Windows PE Executables
  5. \project bee2/apps/stamp
  6. \author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
  7. \created 2011.10.18
  8. \version 2017.01.12
  9. \license This program is released under the GNU General Public License
  10. version 3. See Copyright Notices in bee2/info.h.
  11. *******************************************************************************
  12. */
  13. /*
  14. *******************************************************************************
  15. Контрольная характеристика представляет собой строку из STAMP_SIZE октетов,
  16. которая должна быть добавлена в исполнимый файл как строковый ресурс
  17. с идентификатором STAMP_ID.
  18. *******************************************************************************
  19. */
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <bee2/core/blob.h>
  23. #include <bee2/core/err.h>
  24. #include <bee2/core/mem.h>
  25. #include <bee2/core/str.h>
  26. #include <bee2/core/util.h>
  27. #include <bee2/crypto/belt.h>
  28. /*
  29. *******************************************************************************
  30. Работа с PE-файлом
  31. *******************************************************************************
  32. */
  33. #include "stamp_pe.c"
  34. /*
  35. *******************************************************************************
  36. Вспомогательные функции
  37. *******************************************************************************
  38. */
  39. //! Справка о соглашениях
  40. void stampUsage(const char* prg_name)
  41. {
  42. // короткое имя программы
  43. const char* short_name = prg_name + strLen(prg_name);
  44. while (--short_name != prg_name && *short_name != '\\');
  45. if (*short_name == '\\')
  46. short_name++;
  47. // печать справки
  48. printf(
  49. "bee2/%s: Integrity control of PE-modules\n"
  50. "[bee2 version %s]\n"
  51. "Usage: %s -{s|c} name\n"
  52. " s -- set control stamp\n"
  53. " c -- check control stamp\n"
  54. " name -- name of PE-module (exe or dll)\n"
  55. "\\pre resource file of the target module must contains the string\n"
  56. " %d %d {\"0123456789ABCDEF0123456789ABCDEF\"}\n",
  57. short_name, utilVersion(), short_name, STAMP_ID, STAMP_TYPE);
  58. }
  59. //! Разбор командной строки
  60. /*! Разбирается командная строка:
  61. stamp -{s|с} name
  62. \return
  63. - 0 -- set;
  64. - 1 -- create;
  65. - -1 -- ошибка синтаксиса.
  66. */
  67. int stampParsing(int argc, const char* argv[])
  68. {
  69. // проверяем число аргументов
  70. if (argc != 3)
  71. {
  72. stampUsage(argv[0]);
  73. return -1;
  74. }
  75. // проверяем режим
  76. if (strEq(argv[1], "-s"))
  77. return 0;
  78. if (strEq(argv[1], "-c"))
  79. return 1;
  80. return -1;
  81. }
  82. void stampPrint(const octet* stamp, const char* stamp_name)
  83. {
  84. size_t pos;
  85. printf(stamp_name ? "[%s = " : "[", stamp_name);
  86. for (pos = 0; pos < STAMP_SIZE; ++pos)
  87. printf("%02X", stamp[pos]);
  88. printf("]\n");
  89. }
  90. /*
  91. *******************************************************************************
  92. Работа с контрольными характеристиками
  93. *******************************************************************************
  94. */
  95. // установить характеристику
  96. void stampSet(const char* name)
  97. {
  98. HANDLE hFile;
  99. DWORD size;
  100. HANDLE hMapping;
  101. octet* image;
  102. DWORD offset;
  103. void* hash_state;
  104. // открыть файл
  105. hFile = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
  106. 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  107. if (hFile == INVALID_HANDLE_VALUE)
  108. {
  109. printf("File \"%s\" was not found or could not be open.\n", name);
  110. return;
  111. }
  112. // длина файла
  113. size = SetFilePointer(hFile, 0, NULL, FILE_END);
  114. if (size == INVALID_SET_FILE_POINTER)
  115. {
  116. CloseHandle(hFile);
  117. printf("Error processing the file \"%s\".\n", name);
  118. return;
  119. }
  120. // проецировать файл в память
  121. hMapping = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
  122. if (hMapping == NULL)
  123. {
  124. CloseHandle(hFile);
  125. printf("Error processing the file \"%s\".\n", name);
  126. return;
  127. }
  128. // отобразить файл в память
  129. image = (octet*)MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
  130. if (image == NULL)
  131. {
  132. CloseHandle(hMapping);
  133. CloseHandle(hFile);
  134. printf("Error processing the file \"%s\".\n", name);
  135. return;
  136. }
  137. // найти смещение контрольной характеристики
  138. offset = stampFindOffset(image, size);
  139. if (offset == (DWORD)-1)
  140. {
  141. UnmapViewOfFile(image);
  142. CloseHandle(hMapping);
  143. CloseHandle(hFile);
  144. printf("Control stamp of \"%s\" was not found or corrupted.\n", name);
  145. return;
  146. }
  147. // подготовить место для контрольной характеристики
  148. CASSERT(STAMP_SIZE >= 32);
  149. memSetZero(image + offset, STAMP_SIZE);
  150. // стек хэширования
  151. hash_state = blobCreate(beltHash_keep());
  152. if (hash_state)
  153. {
  154. // хэшировать
  155. beltHashStart(hash_state);
  156. beltHashStepH(image, offset, hash_state);
  157. beltHashStepH(image + offset + STAMP_SIZE,
  158. size - offset - STAMP_SIZE, hash_state);
  159. beltHashStepG(image + offset, hash_state);
  160. blobClose(hash_state);
  161. // печать
  162. printf("Control stamp successfully added to \"%s\"\n", name);
  163. stampPrint(image + offset, "stamp");
  164. }
  165. else
  166. printf("Insufficient memory.\n");
  167. // очистка
  168. UnmapViewOfFile(image);
  169. CloseHandle(hMapping);
  170. CloseHandle(hFile);
  171. }
  172. // проверить характеристику
  173. void stampCheck(const char* name)
  174. {
  175. HANDLE hFile;
  176. DWORD size;
  177. HANDLE hMapping;
  178. octet* image;
  179. DWORD offset;
  180. octet stamp[STAMP_SIZE];
  181. void* hash_state;
  182. bool_t success;
  183. // открыть файл
  184. hFile = CreateFileA(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  185. FILE_ATTRIBUTE_NORMAL, NULL);
  186. if (hFile == INVALID_HANDLE_VALUE)
  187. {
  188. printf("File \"%s\" was not found or could not be open.\n", name);
  189. return;
  190. }
  191. // длина файла
  192. size = SetFilePointer(hFile, 0, NULL, FILE_END);
  193. if (size == INVALID_SET_FILE_POINTER)
  194. {
  195. CloseHandle(hFile);
  196. printf("Error processing the file \"%s\".\n", name);
  197. return;
  198. }
  199. // проецировать файл в память
  200. hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  201. if (hMapping == NULL)
  202. {
  203. CloseHandle(hFile);
  204. printf("Error processing the file \"%s\".\n", name);
  205. return;
  206. }
  207. // отобразить файл в память
  208. image = (octet*)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  209. if (image == NULL)
  210. {
  211. CloseHandle(hMapping);
  212. CloseHandle(hFile);
  213. printf("Error processing the file \"%s\".\n", name);
  214. return;
  215. }
  216. // найти смещение контрольной характеристики
  217. offset = stampFindOffset(image, size);
  218. if (offset == (DWORD)-1)
  219. {
  220. UnmapViewOfFile(image);
  221. CloseHandle(hMapping);
  222. CloseHandle(hFile);
  223. printf("Control stamp of \"%s\" was not found or corrupted.\n", name);
  224. return;
  225. }
  226. // подготовить место для контрольной характеристики
  227. CASSERT(STAMP_SIZE >= 32);
  228. memSet(stamp, 0, STAMP_SIZE);
  229. // состояние хэширования
  230. hash_state = blobCreate(beltHash_keep());
  231. if (hash_state)
  232. {
  233. // хэшировать
  234. beltHashStart(hash_state);
  235. beltHashStepH(image, offset, hash_state);
  236. beltHashStepH(image + offset + STAMP_SIZE,
  237. size - offset - STAMP_SIZE, hash_state);
  238. beltHashStepG(stamp, hash_state);
  239. blobClose(hash_state);
  240. // сравнить
  241. success = memEq(image + offset, stamp, STAMP_SIZE);
  242. printf("Integrity of \"%s\"... %s\n", name, success ? "OK" : "Failed");
  243. if (success)
  244. stampPrint(image + offset, "stamp");
  245. else
  246. stampPrint(image + offset, "read_stamp"),
  247. stampPrint(stamp, "calc_stamp");
  248. }
  249. else
  250. printf("Insufficient memory.\n");
  251. // очистка
  252. UnmapViewOfFile(image);
  253. CloseHandle(hMapping);
  254. CloseHandle(hFile);
  255. }
  256. /*
  257. *******************************************************************************
  258. main
  259. *******************************************************************************
  260. */
  261. void main(int argc, char* argv[])
  262. {
  263. int d;
  264. // разобрать командную строку
  265. d = stampParsing(argc, argv);
  266. // set?
  267. if (d == 0)
  268. stampSet(argv[2]);
  269. // create?
  270. else if (d == 1)
  271. stampCheck(argv[2]);
  272. }