1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
/*****************************************************************************/
/* Storm_test.cpp Copyright (c) Ladislav Zezula 2014 */
/*---------------------------------------------------------------------------*/
/* Test module for storm.dll (original Blizzard MPQ dynalic library */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 24.08.14 1.00 Lad The first version of Storm_test.cpp */
/*****************************************************************************/
#define _CRT_NON_CONFORMING_SWPRINTFS
#define _CRT_SECURE_NO_DEPRECATE
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#ifdef _MSC_VER
#include <crtdbg.h>
#endif
#define STORM_ALTERNATE_NAMES // Use Storm* prefix for functions
#include "storm.h" // Header file for Storm.dll
#pragma comment(lib, "storm.lib")
//-----------------------------------------------------------------------------
// List of files
const char * IntToHexChar = "0123456789ABCDEF";
LPCSTR DefFilesToOpen[] =
{
"music\\tdefeat.wav",
"setupdat\\inst.vis",
"setupdat\\audio\\mouseover.wav",
"files\\font\\font12.fnt",
"music\\zvict.wav",
"files\\readme.txt",
"music\\zerg2.wav",
"music\\zerg1.wav",
"setupdat\\inst_regs.ins",
"files\\font\\font50.fnt",
"files\\msv2all.vxp",
"setupdat\\scr_options.vis",
"setupdat\\font\\font16x.fnt",
"setupdat\\setup.vis",
"maps\\128x128_wasteland4.scm",
"setupdat\\scr_main.vis",
"music\\pvict.wav",
"music\\zdefeat.wav",
};
//-----------------------------------------------------------------------------
// Main
static void CalculateMD5(LPBYTE md5_digest, LPBYTE pbData, DWORD cbData)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hCryptHash = NULL;
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if(CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash))
{
DWORD dwHashLen = 0x10;
CryptHashData(hCryptHash, pbData, cbData, 0);
CryptGetHashParam(hCryptHash, HP_HASHVAL, md5_digest, &dwHashLen, 0);
CryptDestroyHash(hCryptHash);
}
CryptReleaseContext(hCryptProv, 0);
}
}
template <typename XCHAR>
DWORD BinaryToString(XCHAR * szBuffer, size_t cchBuffer, LPCVOID pvBinary, size_t cbBinary)
{
LPCBYTE pbBinary = (LPCBYTE)pvBinary;
// The size of the string must be enough to hold the binary + EOS
if(cchBuffer < ((cbBinary * 2) + 1))
return ERROR_INSUFFICIENT_BUFFER;
// Convert the string to the array of MD5
// Copy the blob data as text
for(size_t i = 0; i < cbBinary; i++)
{
*szBuffer++ = IntToHexChar[pbBinary[0] >> 0x04];
*szBuffer++ = IntToHexChar[pbBinary[0] & 0x0F];
pbBinary++;
}
// Terminate the string
*szBuffer = 0;
return ERROR_SUCCESS;
}
int main(int argc, char * argv[])
{
LPCSTR szArchiveName;
LPCSTR szFormat;
HANDLE hMpq = NULL;
HANDLE hFile = NULL;
LPBYTE pbBuffer = NULL;
DWORD dwBytesRead = 0;
DWORD dwFileSize = 0;
BOOL bResult;
BYTE md5_digest[0x10];
char md5_string[0x40];
// Check parameters
if(argc == 1)
{
printf("Error: Missing MPQ name\nUsage: storm_test.exe MpqName [FileName [FileName]]\n");
return 3;
}
// Get both arguments
SetLastError(ERROR_SUCCESS);
szArchiveName = argv[1];
// Break for kernel debugger
//__debugbreak();
// Put Storm.dll to the current folder before running this
//printf("[*] Opening archive '%s' ...\n", szArchiveName);
if(StormOpenArchive(szArchiveName, 0, 0, &hMpq))
{
LPCSTR * FilesToOpen = DefFilesToOpen;
size_t nFilesToOpen = _countof(DefFilesToOpen);
// Set the list of files
if(argc > 2)
{
FilesToOpen = (LPCSTR *)(&argv[2]);
nFilesToOpen = argc - 2;
}
// Attempt to open all files
for(size_t i = 0; i < nFilesToOpen; i++)
{
//printf("[*] Opening file '%s' ...\n", FilesToOpen[i]);
if(StormOpenFileEx(hMpq, FilesToOpen[i], 0, &hFile))
{
//printf("[*] Retrieving file size ... ");
dwFileSize = StormGetFileSize(hFile, NULL);
szFormat = (dwFileSize == INVALID_FILE_SIZE) ? ("(invalid)\n") : ("(%u bytes)\n");
//printf(szFormat, dwFileSize);
// Allocate the buffer for the entire file
//printf("[*] Allocating buffer ...\n");
if((pbBuffer = new BYTE[dwFileSize]) != NULL)
{
//printf("[*] Moving to begin of the file ...\n");
StormSetFilePointer(hFile, 0, NULL, FILE_BEGIN);
//printf("[*] Reading file ... ");
bResult = StormReadFile(hFile, pbBuffer, dwFileSize, &dwBytesRead, NULL);
szFormat = (bResult != FALSE && dwBytesRead == dwFileSize) ? ("(OK)\n") : ("(error %u)\n");
//printf(szFormat, GetLastError());
//printf("[*] Calculating MD5 ... ");
CalculateMD5(md5_digest, pbBuffer, dwFileSize);
BinaryToString(md5_string, _countof(md5_string), md5_digest, sizeof(md5_digest));
printf("%s *%s\n", md5_string, FilesToOpen[i]);
delete[] pbBuffer;
}
//printf("[*] Closing file ...\n");
StormCloseFile(hFile);
}
}
//printf("[*] Closing archive ...\n");
StormCloseArchive(hMpq);
}
//printf("Done.\n\n");
return 0;
}
|