Everest数据文件解密一则
标 题: Everest数据文件解密一则
作 者: pathletboy
时 间: 2009-10-27
链 接: http://www.unpack.cn/viewthread.php?tid=41852&extra=page%3D1
打开Everest所在目录,一目了然,确定everest.dat为数据文件。
Everest主程序Everest.exe(版本为4.60.1540 Beta)加了UPX,用upx.exe -d everrest.exe就能正常脱壳,脱壳后用IDA加载,进行分析完成后,OD加载后下断CreateFileA。运行,不停断下运行,直到参数为 xxxxx/everest.dat后经过多次返回来到50E726,如50E70F,50E721所CALL都是经过IDA识别+人工校验后确定其作用。
代码:
0050E708 |. B2 01 mov dl,1
0050E70A |. A1 C4A14100 mov eax,dword ptr ds:[41A1C4]
0050E70F |. E8 E05DEFFF call <everest.CreateClass>
0050E714 |. A3 9C5D9300 mov dword ptr ds:[935D9C],eax
0050E719 |. 8B55 F4 mov edx,[local.3]
0050E71C |. A1 9C5D9300 mov eax,dword ptr ds:[935D9C]
0050E721 |. E8 D210F1FF call <everest.TStream.LoadFromFile>
0050E726 |. B2 01 mov dl,1
仔细分析该段函数如下:
代码:
0050E6AC /$ 55 push ebp
0050E6AD |. 8BEC mov ebp,esp
0050E6AF |. 83C4 F0 add esp,-10
0050E6B2 |. 53 push ebx
0050E6B3 |. 56 push esi
0050E6B4 |. 57 push edi
0050E6B5 |. 33C0 xor eax,eax
0050E6B7 |. 8945 F0 mov [local.4],eax
0050E6BA |. 8945 F4 mov [local.3],eax
0050E6BD |. 33C0 xor eax,eax
0050E6BF |. 55 push ebp
0050E6C0 |. 68 5EE85000 push everest.0050E85E
0050E6C5 |. 64:FF30 push dword ptr fs:[eax]
0050E6C8 |. 64:8920 mov dword ptr fs:[eax],esp
0050E6CB |. 33DB xor ebx,ebx
0050E6CD |. A1 EC2F9300 mov eax,dword ptr ds:[<En&DecryptAddressTable>]
0050E6D2 |. 33C9 xor ecx,ecx
0050E6D4 |. BA 40000000 mov edx,40
0050E6D9 |. E8 E64EEFFF call <everest.FillChar>
0050E6DE |. 8D55 F0 lea edx,[local.4]
0050E6E1 |. 33C0 xor eax,eax
0050E6E3 |. E8 3845EFFF call <everest.ParamStr> ; ParamStr(0) 获取进程参数0 为进程完整路径
0050E6E8 |. 8B45 F0 mov eax,[local.4]
0050E6EB |. 8D4D F4 lea ecx,[local.3]
0050E6EE |. BA 78E85000 mov edx,everest.0050E878 ; ASCII ".dat"
0050E6F3 |. E8 70C5EFFF call <everest.ChangeFileExt>
0050E6F8 |. 8B45 F4 mov eax,[local.3] ; 更改后缀,此时字串为xxxxx/everest.dat
0050E6FB |. E8 98C2EFFF call <everest.FileExists> ; 检查数据文件是否存在
0050E700 |. 84C0 test al,al
0050E702 |. 0F84 3B010000 je everest.0050E843
0050E708 |. B2 01 mov dl,1
0050E70A |. A1 C4A14100 mov eax,dword ptr ds:[41A1C4]
0050E70F |. E8 E05DEFFF call <everest.CreateClass>
0050E714 |. A3 9C5D9300 mov dword ptr ds:[935D9C],eax
0050E719 |. 8B55 F4 mov edx,[local.3]
0050E71C |. A1 9C5D9300 mov eax,dword ptr ds:[935D9C]
0050E721 |. E8 D210F1FF call <everest.TStream.LoadFromFile> ; 加载数据文件
0050E726 |. B2 01 mov dl,1
0050E728 |. A1 C4A14100 mov eax,dword ptr ds:[41A1C4]
0050E72D |. E8 C25DEFFF call <everest.CreateClass>
0050E732 |. A3 A05D9300 mov dword ptr ds:[935DA0],eax
0050E737 |. 8B0D 9C5D9300 mov ecx,dword ptr ds:[935D9C]
0050E73D |. B2 01 mov dl,1
0050E73F |. A1 607B5000 mov eax,dword ptr ds:[507B60]
0050E744 |. E8 6F9AFFFF call everest.005081B8
0050E749 |. A3 985D9300 mov dword ptr ds:[935D98],eax
0050E74E |. 6A 00 push 0
0050E750 |. 6A 00 push 0
0050E752 |. 8B15 985D9300 mov edx,dword ptr ds:[935D98]
0050E758 |. A1 A05D9300 mov eax,dword ptr ds:[935DA0]
0050E75D |. E8 FE0AF1FF call <everest.ZDecompressStream> ; ZLib解压
0050E762 |. A1 985D9300 mov eax,dword ptr ds:[935D98]
0050E767 |. E8 B85DEFFF call <everest.TObject.Free>
0050E76C |. A1 9C5D9300 mov eax,dword ptr ds:[935D9C]
0050E771 |. E8 AE5DEFFF call <everest.TObject.Free>
0050E776 |. 66:B9 0200 mov cx,2 ; Seek(-$1658,soFromEnd)
0050E77A |. BA A8E9FFFF mov edx,-1658
0050E77F |. A1 A05D9300 mov eax,dword ptr ds:[935DA0]
0050E784 |. 8B30 mov esi,dword ptr ds:[eax]
0050E786 |. FF56 14 call dword ptr ds:[esi+14] ; TCustomMemoryStream.Seek
0050E789 |. 8B15 1C289300 mov edx,dword ptr ds:[93281C] ; Read(Buf,8)
0050E78F |. B9 08000000 mov ecx,8
0050E794 |. A1 A05D9300 mov eax,dword ptr ds:[935DA0]
0050E799 |. 8B30 mov esi,dword ptr ds:[eax]
0050E79B |. FF56 0C call dword ptr ds:[esi+C] ; TCustomMemoryStream.Read
0050E79E |. 83F8 08 cmp eax,8
0050E7A1 |. 0F8C 92000000 jl everest.0050E839
0050E7A7 |. 8B15 8C279300 mov edx,dword ptr ds:[<HeadList>] ; Read(HeadList,$1650)
0050E7AD |. B9 50160000 mov ecx,1650 ; 此处看出HeadList数组维数为21($1650 / $110 = $15)
0050E7B2 |. A1 A05D9300 mov eax,dword ptr ds:[935DA0]
0050E7B7 |. 8B30 mov esi,dword ptr ds:[eax]
0050E7B9 |. FF56 0C call dword ptr ds:[esi+C] ; TCustomMemoryStream.Read
0050E7BC |. 3D 50160000 cmp eax,1650
0050E7C1 |. 7C 76 jl short everest.0050E839
0050E7C3 |. 33C0 xor eax,eax
0050E7C5 |. 8945 FC mov [local.1],eax
0050E7C8 |. 8B1D 8C279300 mov ebx,dword ptr ds:[<HeadList>] ; 数据索引列表
0050E7CE |. 83C3 04 add ebx,4
0050E7D1 |. 8B35 EC2F9300 mov esi,dword ptr ds:[<En&DecryptAddressTable>] ; 加密解密数据地址表
0050E7D7 |> 833B 00 /cmp dword ptr ds:[ebx],0 ; THeadList.size
0050E7DA |. 74 49 |je short everest.0050E825
0050E7DC |. 33C9 |xor ecx,ecx ; 根据数据索引列表中指示的偏移进行文件流指针移动
0050E7DE |. 8B53 FC |mov edx,dword ptr ds:[ebx-4] ; THeadList.offset
0050E7E1 |. A1 A05D9300 |mov eax,dword ptr ds:[935DA0]
0050E7E6 |. 8B38 |mov edi,dword ptr ds:[eax]
0050E7E8 |. FF57 14 |call dword ptr ds:[edi+14] ; TCustomMemoryStream.Seek
0050E7EB |. 8B03 |mov eax,dword ptr ds:[ebx]
0050E7ED |. 8945 F8 |mov [local.2],eax
0050E7F0 |. 8B45 F8 |mov eax,[local.2]
0050E7F3 |. E8 FC3FEFFF |call <everest.GetMem> ; 根据数据索引列表中指示的大小分配内存
0050E7F8 |. 8BF8 |mov edi,eax ; 读取数据
0050E7FA |. 893E |mov dword ptr ds:[esi],edi
0050E7FC |. 8BD7 |mov edx,edi
0050E7FE |. 8B4D F8 |mov ecx,[local.2]
0050E801 |. A1 A05D9300 |mov eax,dword ptr ds:[935DA0]
0050E806 |. 8B38 |mov edi,dword ptr ds:[eax]
0050E808 |. FF57 0C |call dword ptr ds:[edi+C] ; TCustomMemoryStream.Read
0050E80B |. 3B45 F8 |cmp eax,[local.2]
0050E80E |. 7D 0D |jge short everest.0050E81D
0050E810 |. 8B06 |mov eax,dword ptr ds:[esi]
0050E812 |. E8 FD3FEFFF |call <everest.FreeMem>
0050E817 |. 33C0 |xor eax,eax
0050E819 |. 8906 |mov dword ptr ds:[esi],eax
0050E81B |. EB 08 |jmp short everest.0050E825
0050E81D |> 8B45 FC |mov eax,[local.1]
0050E820 |. E8 DFE31800 |call <everest.DeCrypt> ; 进行解密
0050E825 |> FF45 FC |inc [local.1]
0050E828 |. 83C6 04 |add esi,4
0050E82B |. 81C3 10010000 |add ebx,110 ; 此处看出THeadList结构大小
0050E831 |. 837D FC 10 |cmp [local.1],10
0050E835 |.^ 75 A0 /jnz short everest.0050E7D7
0050E837 |. B3 01 mov bl,1
0050E839 |> A1 A05D9300 mov eax,dword ptr ds:[935DA0]
0050E83E |. E8 E15CEFFF call <everest.TObject.Free>
0050E843 |> 33C0 xor eax,eax
0050E845 |. 5A pop edx
0050E846 |. 59 pop ecx
0050E847 |. 59 pop ecx
0050E848 |. 64:8910 mov dword ptr fs:[eax],edx
0050E84B |. 68 65E85000 push everest.0050E865
0050E850 |> 8D45 F0 lea eax,[local.4]
0050E853 |. BA 02000000 mov edx,2
0050E858 |. E8 FF6AEFFF call everest.0040535C
0050E85D /. C3 retn
再接着看解密函数:
代码:
0069CC04 <eve>/$ 55 push ebp ; DeCrypt
0069CC05 |. 8BEC mov ebp,esp
0069CC07 |. 51 push ecx
0069CC08 |. 56 push esi
0069CC09 |. 8B3485 ACE5AC00 mov esi,dword ptr ds:[eax*4+ACE5AC] ; 加密解密地址指针
0069CC10 |. 6BC0 22 imul eax,eax,22
0069CC13 |. 8B0CC5 F0E5AC00 mov ecx,dword ptr ds:[eax*8+ACE5F0] ; 数据长度
0069CC1A |. 49 dec ecx
0069CC1B |. 85C9 test ecx,ecx
0069CC1D |. 7C 20 jl short everest.0069CC3F ; 如果数据长度小于1则跳出不解密。
0069CC1F |. 41 inc ecx
0069CC20 |. 33D2 xor edx,edx
0069CC22 |> 8A0416 /mov al,byte ptr ds:[esi+edx]
0069CC25 |. 8845 FF |mov byte ptr ss:[ebp-1],al
0069CC28 |. 50 |push eax
0069CC29 |. 8A45 FF |mov al,byte ptr ss:[ebp-1]
0069CC2C |. 34 2D |xor al,2D ; xor $2D
0069CC2E |. C0C0 03 |rol al,3 ; ROL 3
0069CC31 |. 8845 FF |mov byte ptr ss:[ebp-1],al
0069CC34 |. 58 |pop eax
0069CC35 |. 8A45 FF |mov al,byte ptr ss:[ebp-1]
0069CC38 |. 880416 |mov byte ptr ds:[esi+edx],al
0069CC3B |. 42 |inc edx
0069CC3C |. 49 |dec ecx
0069CC3D |.^ 75 E3 /jnz short everest.0069CC22
0069CC3F |> 5E pop esi
0069CC40 |. 59 pop ecx
0069CC41 |. 5D pop ebp
0069CC42 /. C3 retn
解密算法很简单,以下为Delphi解密代码:
代码:
procedure Decrypt(var Buf; size: Cardinal);
var
pBuf: PByteArray;
i: Integer;
b: Byte;
begin
if size >= 1 then
begin
pBuf := @Buf;
for i := 0 to size - 1 do
begin
b := pBuf[i] xor $2D;
asm
rol b,3
end;
pBuf[i] := b;
end;
end;
end;
解密出的数据和Everest检测后显示出来的数据对比图:
解密工程主要代码:
代码:
{*******************************************************}
{ }
{ DeEverest }
{ }
{ 版权所有 (C) 2009 pathletboy }
{ }
{*******************************************************}
program DeEverest;
{$APPTYPE CONSOLE}
uses
SysUtils,
Classes,
ZLibEx in 'zlib/ZLibEx.pas';
type
THeadList = packed record
offset: Cardinal;
size: Cardinal;
unk: array[0..263] of byte;
end;
var
x: TMemoryStream;
o: TMemoryStream;
unk: Int64;
headlist: array[0..20] of THeadList;
i: Integer;
s: TMemoryStream;
procedure Decrypt(var Buf; size: Cardinal);
var
pBuf: PByteArray;
i: Integer;
b: Byte;
begin
if size >= 1 then
begin
pBuf := @Buf;
for i := 0 to size - 1 do
begin
b := pBuf[i] xor $2D;
asm
rol b,3
end;
pBuf[i] := b;
end;
end;
end;
begin
x := TMemoryStream.Create;
o := TMemoryStream.Create;
s := TMemoryStream.Create;
try
try
x.LoadFromFile('./everest.dat');
x.Seek(0, soFromBeginning);
o.Seek(0, soFromBeginning);
ZDecompressStream(x, o);
o.Seek(-$1658, soFromEnd);
o.Read(unk, 8);
o.Read(headlist[0], SizeOf(headlist));
for i := 0 to 9 do
begin
if headlist[i].size <> 0 then
begin
o.Seek(headlist[i].offset, soFromBeginning);
s.Clear;
s.CopyFrom(o, headlist[i].size);
Decrypt(s.Memory^, s.Size);
s.SaveToFile(Format('de%d.txt', [i]));
end;
end;
Writeln('Successed.');
except
Writeln('Raise a exception.');
end;
finally
s.Free;
x.Free;
o.Free;
end;
end.