procedure
AppendText(hWndDlg: DWORD; txt:
String
); forward;
type
PHeaderWand = ^THeaderWand;
THeaderWand =
record
szBlock: DWORD;
szKey: DWORD;
Key:
array
[
0..7
]
of
Byte
;
end
;
const
WND_CLASS_NAME =
'DeCryptWand'
;
IDC_EDIT =
2000
;
var
Instance: HWnd;
WindowClass: TWndClass;
Handle: HWnd;
msg: TMsg;
function
OffsetMem(lpBase:
Pointer
; Offset:
Cardinal
):
Pointer
;
asm
add eax,edx
end
;
function
Swap32(Value:
LongWord
):
LongWord
; assembler;
asm
bswap eax
end
;
function
LastPos(Needle:
Char
; Haystack:
String
):
integer
;
begin
for
Result := Length(Haystack)
downto
1
do
if
Haystack[Result] = Needle
then
Break;
end
;
function
GetHash(Data:
Pointer
; nSize:
Cardinal
; HashType:
Cardinal
):
Pointer
;
var
hProv: HCRYPTPROV;
hHash: HCRYPTHASH;
begin
Result:=
nil
;
if
CryptAcquireContext(hProv,
nil
,
nil
, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
then
try
if
CryptCreateHash(hProv, HashType,
0
,
0
, hHash)
then
try
if
CryptHashData(hHash, Data, nSize,
0
)
then
begin
if
CryptGetHashParam(hHash, HP_HASHVAL,
nil
, nSize,
0
)
then
begin
GetMem(Result,nSize);
if
not
CryptGetHashParam(hHash, HP_HASHVAL, Result, nSize,
0
)
then
begin
FreeMem(Result);
Result:=
nil
;
end
;
end
;
end
;
finally
CryptDestroyHash(hHash);
end
;
finally
CryptReleaseContext(hProv,
0
);
end
;
end
;
function
GetMD5(Data:
Pointer
; nSize:
Cardinal
):
Pointer
;
begin
Result:= GetHash(Data, nSize, CALG_MD5);
end
;
function
Decrypt3DES(Data, Key, IV:
Pointer
;
var
DataOut:
Pointer
; nSize:
Cardinal
):
Pointer
;
var
hProv: HCRYPTPROV;
hKey: HCRYPTKEY;
keyHeader: TBLOBHeader;
bKey:
array
[
0..35
]
of
Byte
;
desMode: DWORD;
begin
Result:=
nil
;
CryptAcquireContext(hProv,
nil
,
nil
, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
if
CryptAcquireContext(hProv,
nil
,
nil
, PROV_RSA_FULL, CRYPT_NEWKEYSET)
then
try
keyHeader
.
bType:= PLAINTEXTKEYBLOB;
keyHeader
.
bVersion:= CUR_BLOB_VERSION;
keyHeader
.
reserved:=
0
;
keyHeader
.
aiKeyAlg:= CALG_3DES;
FillChar(bKey[
0
], SizeOf(bKey),
0
);
Move(keyHeader,bKey[
0
],SizeOf(keyHeader));
bKey[SizeOf(keyHeader)]:=
24
;
Move(Key^, bKey[SizeOf(keyHeader)+
4
],
24
);
if
CryptImportKey(hProv, @bKey[
0
], sizeof(keyHeader) + sizeof(DWORD) +
24
,
0
,
0
, hKey)
then
try
desMode:= CRYPT_MODE_CBC;
CryptSetKeyParam(hKey, KP_MODE, @desMode,
0
);
desMode:= ZERO_PADDING;
CryptSetKeyParam(hKey, KP_PADDING, @desMode,
0
);
CryptSetKeyParam(hKey, KP_IV, IV,
0
);
desMode:= nSize;
if
not
CryptDecrypt(hKey,
0
,
True
,
0
, data, nSize)
then
Result:=
nil
else
begin
Move(data^, DataOut^, desMode);
Result:= DataOut;
end
;
finally
CryptDestroyKey(hKey);
end
;
finally
CryptReleaseContext(hProv,
0
);
end
;
end
;
procedure
OperaDecrypt(key:
Pointer
; data, dataout:
Pointer
; len:
Cardinal
);
var
out_1, out_2:
array
[
0..63
]
of
Byte
;
digest_1, digest_2:
Pointer
;
des_key:
array
[
0..23
]
of
Byte
;
const
magic:
array
[
0..10
]
of
Byte
= (
$83
,
$7D
,
$FC
,
$0F
,
$8E
,
$B3
,
$E8
,
$69
,
$73
,
$AF
,
$FF
);
szMagic = SizeOf(magic);
begin
Move(magic, out_1, szMagic);
Move(key^, out_1[szMagic],
8
);
digest_1:= GetMD5(@out_1,szMagic +
8
);
Move(digest_1^, des_key,
16
);
Move(digest_1^, out_2,
16
);
Move(magic, out_2[
16
], szMagic);
Move(key^, out_2[
16
+ szMagic],
8
);
digest_2:= GetMD5(@out_2,szMagic +
24
);
Move(digest_2^, des_key[
16
],
8
);
Decrypt3DES(data, @des_key, OffsetMem(digest_2,
8
), dataout, len);
FreeMem(digest_1);
FreeMem(digest_2);
end
;
function
DecryptWandPass(
const
Key, Data:
String
):
String
;
begin
Result :=
''
;
if
Length(Key) <>
8
then
Exit;
if
(Length(Data) <
8
)
or
(Length(Data)
mod
8
<>
0
)
then
Exit;
SetLength(Result, Length(Data));
OperaDecrypt(@Key[
1
], @Data[
1
], @Result[
1
], Length(Data));
SetLength(Result, Length(Result)- Ord(Result[Length(Result)]));
Result:= WideCharToString(@(Result+#
0
#
0
)[
1
]);
end
;
procedure
ParsingWandDat(hWndDlg: DWORD; WandDat:
PChar
);
var
hFileMap, hFile: THandle;
pData:
Pointer
;
szFile, blockLength, wandOffset, dataLength: DWORD;
Header: PHeaderWand;
sKey, sData:
String
;
begin
hFile:= CreateFileA(WandDat,
GENERIC_WRITE
or
GENERIC_READ,
FILE_SHARE_READ
or
FILE_SHARE_WRITE,
nil
,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
);
if
hFile <> INVALID_HANDLE_VALUE
then
begin
szFile:= GetFileSize(hFile,
nil
);
hFileMap:= CreateFileMappingA(hFile,
nil
, PAGE_READWRITE ,
0
, szFile,
nil
);
if
hFileMap <> INVALID_HANDLE_VALUE
then
begin
CloseHandle(hFile);
pData:= MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS,
0
,
0
, szFile);
if
pData <>
nil
then
try
wandOffset:=
0
;
while
(wandOffset < szFile)
do
begin
while
(wandOffset< szFile -
4
)
do
begin
if
DWORD(OffsetMem(pData, wandOffset)^) = DWORD(
$08000000
)
then
Break
else
wandOffset:= wandOffset +
1
;
end
;
Header:= OffsetMem(pData, wandOffset -
4
);
blockLength:= Swap32(Header^.szBlock);
dataLength:= Swap32(Header^.szKey);
SetLength(sKey,
8
);
SetLength(sData, blockLength -
$10
);
CopyMemory(@sKey[
1
], @Header^.Key,
8
);
CopyMemory(@sData[
1
], OffsetMem(pData, wandOffset +
$10
), blockLength -
$10
);
AppendText(hWndDlg, DecryptWandPass(sKey, sData));
wandOffset:= wandOffset + dataLength +
$10
;
end
;
finally
UnmapViewOfFile(pData);
end
;
CloseHandle(hFileMap);
end
;
end
;
end
;
procedure
AppendText(hWndDlg: DWORD; txt:
String
);
var
dBuff:
array
[
0..4047
]
of
Char
;
begin
ZeroMemory(@dBuff, SizeOf(dBuff));
lstrcpyn(dBuff,
PChar
(txt),
4045
);
lstrcat(dBuff, #
13
#
10
#
0
);
SendDlgItemMessage(hWndDlg, IDC_EDIT, EM_REPLACESEL,
0
,
integer
(@dBuff));
SendDlgItemMessage(hWndDlg, IDC_EDIT, EM_SETSEL, -
1
,
0
);
end
;
procedure
DropFiles(hwndDlg, wParam: DWORD);
var
n:
Cardinal
;
lpszFile:
array
[
0..
MAX_PATH]
of
Char
;
FFile:
String
;
begin
ZeroMemory(@lpszFile, sizeof(lpszFile));
n:= DragQueryFile(wParam,
0
, lpszFile, sizeof(lpszFile));
if
n<>
0
then
begin
FFile:= Copy(lpszFile,
0
, n);
AppendText(hWndDlg, FFile);
ParsingWandDat(hWndDlg,
PChar
(FFile));
end
;
DragFinish(wParam);
end
;
function
WindowProc(hwndDlg, Msg, wParam, lParam: DWORD):
LongInt
; stdcall;
begin
Result:=
0
;
case
Msg
of
WM_DROPFILES: DropFiles(hWndDlg, wParam);
WM_DESTROY:
begin
PostQuitMessage(
0
);
Result:=
0
;
end
;
else
Result:= DefWindowProc(hwndDlg, Msg, wParam, lParam);
end
;
end
;
begin
instance:= GetModuleHandle(
nil
);
WindowClass
.
style:= CS_PARENTDC
or
CS_DBLCLKS;
WindowClass
.
Lpfnwndproc:= @WindowProc;
WindowClass
.
Hinstance:= Instance;
WindowClass
.
HbrBackground:= HBRUSH(COLOR_3DFACE +
1
);
WindowClass
.
LpszClassName:= WND_CLASS_NAME;
WindowClass
.
Hcursor:= LoadCursor(
0
, IDC_ARROW);
WindowClass
.
hIcon:= LoadIcon(
0
, IDI_APPLICATION);
WindowClass
.
lpszMenuName:=
nil
;
RegisterClass(WindowClass);
Handle:= CreateWindowEx(WS_EX_ACCEPTFILES,
WND_CLASS_NAME,
'DeCrypt wand.dat'
,
WS_MINIMIZEBOX
or
WS_POPUPWINDOW
or
WS_VISIBLE
or
WS_CAPTION,
0
,
0
,
400
,
300
,
0
,
0
, instance,
nil
);
ShowWindow(Handle, SW_SHOWNORMAL);
UpdateWindow(Handle);
CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
'Edit'
,
''
,
$502118C4
,
8
,
8
,
376
,
256
, Handle, HMENU(IDC_EDIT), instance,
nil
);
while
(GetMessage(msg,
0
,
0
,
0
))
do
begin
translatemessage(msg) ;
dispatchmessage(msg);
end
;
end
.