-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrc2decode.cpp
More file actions
82 lines (68 loc) · 2.52 KB
/
Copy pathrc2decode.cpp
File metadata and controls
82 lines (68 loc) · 2.52 KB
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
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: https://pvs-studio.com
#include <iostream>
#include <format>
#include <fstream>
#include <vector>
#include <windows.h>
#include <wincrypt.h>
#define THROW_IF_FALSE(winbool, where) if (winbool == FALSE) \
throw std::runtime_error(std::format(where " failed with error {}", GetLastError()))
const char *VERSION = "2024.0423";
void
usage()
{
std::cerr << "Usage:\nrc2decode.exe <infile> <key> [outfile]" << std::endl;
}
int
main( int argc, char* argv[])
{
char *file_in;
std::string file_out = "out.txt";
LPCSTR key;
const LPCSTR CRYPTO_PROVIDER = "Microsoft Base Cryptographic Provider v1.0";
std::cerr << std::format("rc2 Subaru PAK decrypt utility v{}", VERSION) << std::endl;
if (argc < 2 or argc > 4)
{
std::cerr << "Wrong number of arguments." << std::endl;
usage();
return 1;
}
file_in = argv[1];
key = argv[2];
if (argc == 4)
file_out = argv[3];
HCRYPTPROV *phProv = new HCRYPTPROV;
WINBOOL r;
r = CryptAcquireContextA(phProv, NULL, CRYPTO_PROVIDER, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
THROW_IF_FALSE(r, "CryptAcquireContextA");
HCRYPTHASH *phHash = new HCRYPTHASH;
r = CryptCreateHash(*phProv, CALG_MD5, 0, 0, phHash);
THROW_IF_FALSE(r, "CryptCreateHash");
r = CryptHashData(*phHash, (BYTE *) key, strlen(key), 0);
THROW_IF_FALSE(r, "CryptHashData");
HCRYPTKEY *phKey = new HCRYPTKEY;
r = CryptDeriveKey(*phProv, CALG_RC2, *phHash, 0, phKey);
THROW_IF_FALSE(r, "CryptDeriveKey");
std::vector<BYTE> buffer (1024, 0);
std::ifstream inFile(file_in, std::ifstream::binary);
if (!inFile)
throw std::runtime_error(std::format("Error opening file {}", file_in));
std::ofstream outFile(file_out, std::ios::out | std::ios::binary);
if (!outFile)
throw std::runtime_error(std::format("Error opening file {}", file_out));
WINBOOL final;
while (!inFile.eof())
{
inFile.read((char *)buffer.data(), buffer.size());
//How much did we read
DWORD len = inFile.gcount();
//Is this final pass?
final = (len < buffer.size());
r = CryptDecrypt(*phKey, 0, final, 0, (BYTE *)&buffer[0], &len);
THROW_IF_FALSE((r || final), "CryptDecrypt");
outFile.write((const char*)&buffer[0], len);
}
std::cout << std::format("Wrote to {}", file_out) << std::endl;
return 0;
}