SysTools
/*
2017 addendum:
Microsoft Enhanced RSA and AES Cryptographic Service Provider (PROV_RSA_AES)
available only under Windows XP and newer so use this tool instead:
http://systools.losthost.org/?misc#kiesconv
*/
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#ifdef TINYFILE
#include "tinyfile.h"
#endif
#ifndef PROV_RSA_AES
#define PROV_RSA_AES 24
#endif
#ifndef ALG_SID_AES_256
#define ALG_SID_AES_256 16
#endif
#ifndef CALG_AES_256
#define CALG_AES_256 (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | ALG_SID_AES_256)
#endif
#ifndef PLAINTEXTKEYBLOB
#define PLAINTEXTKEYBLOB 0x8
#endif
static char s_key[] = "epovviwlx,dirwq;sor0-fvksz,erwog";
static char s_iv[] = "afie,crywlxoetka";
#define CRYPT_BLOCK_LEN 0x110
#define CRYPT_BLOCK_PAD 0x010
/*
PHP:
$data .= substr(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, fread($fl, 272), MCRYPT_MODE_CBC, $iv), 0, 256);
References and documentation links for this code:
http://stackoverflow.com/questions/9188045
http://stackoverflow.com/questions/24513020
http://etutorials.org/Programming/secure+programming/Chapter+5.+Symmetric+Encryption/5.25+Using+Symmetric+Encryption+with+Microsoft+s+CryptoAPI/
http://www.onicos.com/staff/iz/formats/gzip.html
*/
typedef struct {
PUBLICKEYSTRUC bh;
DWORD dwKeyLen;
BYTE bytes[32];
} blob_key;
/* not optimized, because handles initializes everytime */
BOOL AES256Decode(BYTE *buf, DWORD sz, BYTE *key, BYTE *iv) {
BOOL result;
HCRYPTPROV hProv;
HCRYPTKEY hKey;
DWORD dwMode;
blob_key bk;
result = FALSE;
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
ZeroMemory(&bk, sizeof(bk));
bk.dwKeyLen = 32;
CopyMemory(bk.bytes, key, bk.dwKeyLen);
bk.bh.bType = PLAINTEXTKEYBLOB;
bk.bh.reserved = 0;
bk.bh.bVersion = CUR_BLOB_VERSION;
bk.bh.aiKeyAlg = CALG_AES_256;
if (CryptImportKey(hProv, (BYTE *) &bk, sizeof(bk), 0, 0, &hKey)) {
dwMode = CRYPT_MODE_CBC;
if (CryptSetKeyParam(hKey, KP_MODE, (BYTE *) &dwMode, 0)) {
if (CryptSetKeyParam(hKey, KP_IV, (BYTE *) iv, 0)) {
if (CryptDecrypt(hKey, 0, TRUE, 0, buf, &sz)) {
result = TRUE;
}
}
}
CryptDestroyKey(hKey);
}
CryptReleaseContext(hProv, 0);
}
return(result);
}
char *basename(char *s) {
char *r;
for (r = s; *s; s++) {
if ((*s == '/') || (*s == '\\')) {
r = &s[1];
}
}
return(r);
}
char *cutfileext(char *s) {
char *r;
for (r = s; *s; s++) {
if (*s == '.') {
r = s;
}
}
r = (*r == '.') ? r : s;
*r = 0;
return(r);
}
int main(int argc, char *argv[]) {
BYTE p[CRYPT_BLOCK_LEN];
char s[MAX_PATH];
HANDLE fl, f;
DWORD i, sz, dw;
printf("Samsung Kies .SSC / .SPB decrypter v1.0\n(c) SysTools 2016\nhttp://systools.losthost.org/?misc\n\n");
if ((argc < 2) || (argc > 3)) {
printf(
"Usage: %s <filename.ext> [0|1]\n"\
"The last parameter optional and must be one of the following values:\n"\
"0 - save decrypted block as is in .BIN format\n"\
"1 - same as above, but without padding blocks\n"\
"Output *.XML.GZ files can be unpacked with gzip or any compatible software.\n\n",
basename(argv[0])
);
} else {
printf("Input: %s\n", argv[1]);
fl = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (fl == INVALID_HANDLE_VALUE) {
printf("\nERROR: can\'t open input file.\n");
} else {
sz = GetFileSize(fl, NULL);
if ((sz % CRYPT_BLOCK_LEN) || (sz <= (CRYPT_BLOCK_LEN*2))) {
printf("\nERROR: invalid file format.\n");
} else {
lstrcpyn(s, basename(argv[1]), MAX_PATH);
cutfileext(s);
i = lstrlen(s);
lstrcpyn(&s[i], (argc == 2) ? ".xml.gz" : ".bin", MAX_PATH - i);
printf("Output: %s\n", s);
f = CreateFile(s, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (f == INVALID_HANDLE_VALUE) {
printf("\nERROR: can\'t create output file.\n");
} else {
sz /= CRYPT_BLOCK_LEN;
for (i = 0; i < sz; i++) {
ReadFile(fl, p, CRYPT_BLOCK_LEN, &dw, NULL);
if (!AES256Decode(p, CRYPT_BLOCK_LEN, (BYTE *) s_key, (BYTE *) s_iv)) {
printf("\nERROR: can\'t decrypt block #%lu (Cryptographic Service Provider failed?).\n", i);
break;
}
if ((argc == 3) || (i >= 2)) {
WriteFile(f, p, CRYPT_BLOCK_LEN - CRYPT_BLOCK_PAD*((argc == 2) || (argv[2][0] != '0')), &dw, NULL);
}
}
CloseHandle(f);
if (i) { printf("\ndone\n"); }
}
}
CloseHandle(fl);
}
printf("\n");
}
return(0);
}
2016.08.20