Source code of Windows XP (NT5)
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.

299 lines
7.3 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <stddef.h>
  8. #include <wincrypt.h>
  9. #include <imagehlp.h>
  10. #ifdef IN_TERMSRV
  11. #else
  12. #define MemAlloc malloc
  13. #define MemFree free
  14. #endif
  15. #ifdef SIGN_DEBUG
  16. #define SIGN_DBGP(x) printf x
  17. #else // SIGN_DEBUG
  18. #define SIGN_DBGP(x)
  19. #endif // SIGN_DEBUG
  20. #include "../inc/privblob.h"
  21. #define WIN_CERT_TYPE_STACK_DLL_SIGNATURE WIN_CERT_TYPE_TS_STACK_SIGNED
  22. BOOL SignFile( LPWSTR wszFile );
  23. /*****************************************************************************/
  24. void _cdecl main(int argc, char *argv[])
  25. {
  26. WCHAR szSourceFile[ MAX_PATH + 1];
  27. DWORD dwBc;
  28. if (argc != 2) {
  29. printf( "Usage: %s PE_File_Name\n", argv[0] );
  30. exit(1);
  31. }
  32. if(RtlMultiByteToUnicodeN( szSourceFile, sizeof(szSourceFile), &dwBc,
  33. argv[1], (strlen(argv[1]) + 1) ) == STATUS_SUCCESS)
  34. {
  35. if( szSourceFile == NULL || !SignFile(szSourceFile) ) {
  36. printf("Error signing file!\n");
  37. exit(1);
  38. }
  39. printf("Signature added successfully.\n");
  40. exit(0);
  41. }
  42. else
  43. {
  44. printf("Error conversion from Ansi to Unicode.\n");
  45. exit(1);
  46. }
  47. }
  48. typedef struct _DIGEST_PARA {
  49. HCRYPTHASH hHash;
  50. } DIGEST_PARA, *PDIGEST_PARA;
  51. BOOL
  52. WINAPI
  53. DigestFile(
  54. DIGEST_HANDLE hDigest,
  55. PBYTE pb,
  56. DWORD cb )
  57. {
  58. PDIGEST_PARA pdp = (PDIGEST_PARA)hDigest;
  59. if (pb == (PBYTE)-1) {
  60. return( TRUE );
  61. } else {
  62. return( CryptHashData(pdp->hHash, pb, cb, 0) );
  63. }
  64. }
  65. //////////////////////////////////////////////////////////////
  66. //
  67. // Open a file in the appropriate permissions / mode for doing
  68. // our signing stuff
  69. //
  70. //////////////////////////////////////////////////////////////
  71. HANDLE OpenImageFile( LPCWSTR wszFile, DWORD dwAccess )
  72. {
  73. HANDLE hFile;
  74. if (wszFile) {
  75. hFile = CreateFile( wszFile,
  76. dwAccess,
  77. FILE_SHARE_READ,
  78. NULL,
  79. OPEN_EXISTING,
  80. FILE_ATTRIBUTE_NORMAL,
  81. NULL
  82. );
  83. return hFile;
  84. } else {
  85. return INVALID_HANDLE_VALUE;
  86. }
  87. }
  88. ///////////////////////////////////////////////////////////////////////
  89. //
  90. // Sign Code, Data, and Resources of a PE image file, and add the
  91. // signature to the file in the form of a "WIN_CERTIFICATE".
  92. //
  93. ///////////////////////////////////////////////////////////////////////
  94. BOOL
  95. SignFile(
  96. LPWSTR wszFile
  97. )
  98. {
  99. HCRYPTPROV hProv;
  100. HCRYPTKEY hPrivateKeySig = 0;
  101. BOOL fResult = FALSE; // preset ERROR case
  102. HANDLE hFile;
  103. DWORD dwErr = ERROR_SUCCESS;
  104. DWORD dwSignatureLen;
  105. DWORD dwCert;
  106. DWORD dwCertIndex;
  107. DWORD cCert;
  108. DIGEST_PARA dp;
  109. PBYTE pbSignature;
  110. LPWIN_CERTIFICATE pCertHdr;
  111. if ( !(hFile = OpenImageFile( wszFile, GENERIC_WRITE | GENERIC_READ )) ) {
  112. printf("Error %x during OpenImageFile\n", GetLastError() );
  113. goto OpenImageFileError;
  114. }
  115. if (!CryptAcquireContext(
  116. &hProv,
  117. NULL,
  118. MS_DEF_PROV,
  119. PROV_RSA_FULL,
  120. CRYPT_VERIFYCONTEXT))
  121. {
  122. SIGN_DBGP( ("Error %x during CryptAcquireContext\n", GetLastError()) );
  123. goto CryptAcquireContextError;
  124. }
  125. if (!CryptImportKey(
  126. hProv,
  127. PrivateKeySigBlob, // from #include "../inc/privblob.h"
  128. sizeof( PrivateKeySigBlob ),
  129. 0,
  130. CRYPT_EXPORTABLE,
  131. &hPrivateKeySig)) {
  132. SIGN_DBGP( ("Error %x during CryptImportKey!\n", GetLastError()) );
  133. goto CryptImportKeyError;
  134. }
  135. memset( &dp, 0, sizeof(dp));
  136. if (!CryptCreateHash(
  137. hProv,
  138. CALG_MD5,
  139. 0,
  140. 0,
  141. &dp.hHash)) {
  142. SIGN_DBGP( ("Error %x during CryptCreateHash\n", GetLastError()) );
  143. goto CryptCreateHashError;
  144. }
  145. if (!ImageGetDigestStream(
  146. hFile,
  147. 0,
  148. DigestFile,
  149. (DIGEST_HANDLE)&dp)) {
  150. SIGN_DBGP( ("Error %x during ImageGetDigestStream\n", GetLastError()) );
  151. goto ImageGetDigestStreamError;
  152. }
  153. //
  154. // Sign hash object.
  155. //
  156. // Determine size of signature.
  157. dwSignatureLen = 0;
  158. if(!CryptSignHash(
  159. dp.hHash,
  160. AT_SIGNATURE,
  161. NULL,
  162. 0,
  163. NULL,
  164. &dwSignatureLen)) {
  165. SIGN_DBGP( ("Error %x during CryptSignHash 1! SigLen = %d\n",
  166. GetLastError(),
  167. dwSignatureLen) );
  168. goto CryptSignHash1Error;
  169. }
  170. // Allocate memory for 'pbSignature'.
  171. if((pbSignature = MemAlloc(dwSignatureLen)) == NULL) {
  172. SIGN_DBGP( ("Out of memory Sig!\n") );
  173. goto SigAllocError;
  174. }
  175. // Sign hash object (with signature key).
  176. if(!CryptSignHash(
  177. dp.hHash,
  178. AT_SIGNATURE,
  179. NULL,
  180. 0,
  181. pbSignature,
  182. &dwSignatureLen)) {
  183. SIGN_DBGP( ("Error %x during CryptSignHash 2!\n", GetLastError()) );
  184. goto CryptSignHash2Error;
  185. }
  186. SIGN_DBGP( ("Signature length = %d\n", dwSignatureLen) );
  187. dwCert = offsetof( WIN_CERTIFICATE, bCertificate ) + dwSignatureLen;
  188. if (NULL == (pCertHdr = (LPWIN_CERTIFICATE) MemAlloc(dwCert))) {
  189. SIGN_DBGP( ("Out of memory Cert!\n") );
  190. goto CertAllocError;
  191. }
  192. // Put the signature and key into the WIN_CERTIFICATE structure
  193. pCertHdr->dwLength = dwCert;
  194. pCertHdr->wRevision = WIN_CERT_REVISION_1_0;
  195. pCertHdr->wCertificateType = WIN_CERT_TYPE_STACK_DLL_SIGNATURE;
  196. memcpy( &pCertHdr->bCertificate[0], pbSignature, dwSignatureLen );
  197. {
  198. unsigned int cnt=0;
  199. while ( cnt < dwSignatureLen ) {
  200. int i;
  201. for ( i=0; (i < 16) && (cnt < dwSignatureLen); cnt++,i++) {
  202. SIGN_DBGP( ("%02x ", pCertHdr->bCertificate[cnt]) );
  203. }
  204. SIGN_DBGP( ("\n") );
  205. }
  206. }
  207. // Remove any and all Stack DLL Signature Certificates from PE file
  208. while (TRUE) {
  209. cCert = 0;
  210. dwCertIndex = 0;
  211. if (!ImageEnumerateCertificates(
  212. hFile,
  213. WIN_CERT_TYPE_STACK_DLL_SIGNATURE,
  214. &cCert,
  215. &dwCertIndex,
  216. 1 // IndexCount
  217. )) {
  218. break;
  219. }
  220. if (cCert == 0) {
  221. break;
  222. }
  223. if (!ImageRemoveCertificate(hFile, dwCertIndex)) {
  224. SIGN_DBGP( ("Error %x during ImageRemoveCertificate\n",
  225. GetLastError()) );
  226. goto ImageRemoveCertificateError;
  227. }
  228. }
  229. if (!ImageAddCertificate(
  230. hFile,
  231. pCertHdr,
  232. &dwCertIndex)) {
  233. SIGN_DBGP( ("Error %x during ImageAddCertificate\n", GetLastError()) );
  234. goto ImageAddCertificateError;
  235. }
  236. fResult = TRUE;
  237. ImageAddCertificateError:
  238. ImageRemoveCertificateError:
  239. MemFree( pCertHdr );
  240. CertAllocError:
  241. CryptSignHash2Error:
  242. MemFree( pbSignature );
  243. SigAllocError:
  244. CryptSignHash1Error:
  245. ImageGetDigestStreamError:
  246. CryptDestroyHash( dp.hHash );
  247. CryptCreateHashError:
  248. CryptDestroyKey(hPrivateKeySig);
  249. CryptImportKeyError:
  250. dwErr = GetLastError();
  251. CryptReleaseContext( hProv, 0 );
  252. SetLastError( dwErr );
  253. CryptAcquireContextError:
  254. CloseHandle( hFile );
  255. OpenImageFileError:
  256. return fResult;
  257. }