stamp.c 8.0 KB

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