gc格式的文件java gc是什么么

高级文件格式分析(原创) (申请邀请码) [文字模式]
- 看雪安全论坛
查看完整版本 :
phf峰廫榋栭偺壴壟丒懱尡斉(一个全日文小游戏) 图片文件(扩展名DET)分析及解密(原创)
可以向我索取EXE文件和IDB文件。---------- 本人QQ: ≮风々吉它≯
重绘时,一定会调用到图片。再往回找,从而发现源头
首先查找绘图函数
得到StretchDIBits
int __stdcall StretchDIBits(HDC,int,int,int,int,int,int,int,int,const void *,const BITMAPINFO *,UINT,DWORD)
extrn StretchDIBits:dword
;IDA中的流程缩略图关了,重打开的办法:View-Toolbars-Navigation-Graph overview
.text:0040AC3F
ebp, [esi]
.text:0040AC41
ebx, dword_43C208
.text:0040AC47
esi, [esi+0Ch]
.text:0040AC4A
SRCCOPY DWORD
.text:0040AC4F
.text:0040AC51
push BITMAPINFO *
.text:0040AC52
.text:0040AC54
push CONST VOID *lpBits
.text:0040AC55
.text:0040AC55
.text:0040AC57
.text:0040AC57 loc_40AC57:
CODE XREF: DrawBitMap+ADj
.text:0040AC57
eax, dword_43CB8C
.text:0040AC5C
ecx, dword_43CB80
.text:0040AC62
.text:0040AC64
eax, [edx+1]
.text:0040AC67
edx, dword_43CB88
.text:0040AC6D
.text:0040AC6E
.text:0040AC70
.text:0040AC71
.text:0040AC72
.text:0040AC73
.text:0040AC74
.text:0040AC75
.text:0040AC76
eax, dword_43CB8C
.text:0040AC7B
.text:0040AC7C
.text:0040AC7D
.text:0040AC7E
ecx, [esp+68h+arg_0]
.text:0040AC82
.text:0040AC83
ds:StretchDIBits
//拉伸图片
.text:0040AC89
.text:0040AC8A
查看lpBits的内容,记下里面的数据
跟踪到lpBits来源处:
WinProc(消息是WM_PAINT)-&SubDraw-&DrawBitMap-&StretchDIBits
edx, dword_4CBDD0背景数据
push lpBit
ds:ReleaseDC
发现从绘图出发,很难找到解密入口,改成从文件读取时查找解密入口
改变思路,从文件读取中查找,从而直接找到解密处
首先查找文件读取函数
中断CreateFile函数,直到是BMP文件(这个要通过OD动态分析)
然后再从OD的堆栈窗口中找到上级函数
Call stack of main thread
Procedure / arguments
Called from
Includes kernel32.CreateFileA
FileName = &pic\mlogo.bmp&
Access = GENERIC_READ
ShareMode = 0
pSecurity = NULL
Mode = OPEN_EXISTING
Attributes = NORMAL
hTemplateFile = NULL
廫榋栭偺.0040C17A
廫榋栭偺.00405D43
然后在处中断
8B35 C0004300 mov
esi, dword ptr [&&KERNEL32.Creat&;
kernel32.CreateFileA
/hTemplateFile = NULL
|Attributes = NORMAL
|Mode = OPEN_EXISTING
|pSecurity = NULL
|ShareMode = 0
|Access = GENERIC_READ
eax, dword ptr [esp+1C] |
CreateFile
\CreateFileA
先是pic\mlog.bmp,然后是bg\mlog.bmp.然后是parts\mlog.bmp
经过测试,发现这个函数,每次打开这些文件都失败。
这说明,解出来的BMP并不放在文件中。
查看目录下的小文件含有的信息,试着找到与pic\mlog.bmp相关的内容。
发现目录下有以pic,bg,parts开头的文件。
逐个查看,发现,NME扩展名中存的是BMP文件名。
parts.nme:(内容)
event.bmp hr.bmp logo_00.bmp logo_s_00.bmp mes.bmp mlogo.bmp name.bmp pph1_00.bmp pph2.bmp ppS1.bmp test04.bmp
test04c.bmp test04d.bmp test04e.bmp c_mink_00.bmp b201.bmp nowonsale02.bmp nowonsale01.bmp ??
所以肯定会打开parts.
重启动程序,再次跟踪CreateFile 直到出现parts.
发现先打开parts.atm,再打开parts.nme.在之前是打开Pic和bg开头的。
所以认为ATM中存放的是配置,而NME是名称
从OD的堆栈窗口中找到上级函数
Call stack of main thread
Procedure / arguments
Called from
Includes kernel32.CreateFileA
廫榋栭偺.0040C33A
FileName = &parts.nme&
Access = GENERIC_READ
ShareMode = 0
pSecurity = NULL
Mode = OPEN_EXISTING
Attributes = NORMAL
hTemplateFile = NULL
廫榋栭偺.00405D43
在40c33A处中断:
68 B8D04300
ASCII &parts&
ASCII &%s.nme&
68 B0CF4300
ASCII &parts.nme&
dword ptr [esp+2C], edx
;wsprintf
68 B0CF4300
ASCII &parts.nme&
createfile
然后分析堆栈;
Call stack of main thread
Procedure / arguments
Called from
廫榋栭偺.00405D43
Frame_ack-&GetBmpInfo
发现这个来自一个线程
好像是用于进行帧处理的
然后分析下如何对这个文件操作的
dword ptr [esp+18], 0
E8 3BFDFFFF
;分析文件
eax,成功与否
ebx, dword ptr [esp+30]
68 B0CF4300
ASCII &parts.nme&
E8 A5FDFFFF
ebp, dword ptr [esp+14]
/pFileSizeHigh = NULL
dword ptr [&&KERNEL32.GetFileSiz&; \GetFileSize
ebx, dword ptr [edi-4]
dword ptr [esp+1C], 0
E8 B75D0100
/pOverlapped = NULL
ecx, dword ptr [esp+10] |
|pBytesRead
|BytesToRead
ebx, dword ptr [&&KERNEL32.ReadF&; |kernel32.ReadFile
|Buffer 文件内容
dword ptr [ebp], |
/pOverlapped = NULL
edx, dword ptr [esp+10] |
|pBytesRead
|BytesToRead = 4
eax, dword ptr [esp+1C] |
|BUFFER 解密号
ecx, dword ptr [ebp]
new address
edx, dword ptr [edi-4]
ecx, dword ptr [esp+1C]
E8 21FFFFFF
通过文件内容算出加密号
eax, dword ptr [esp+14]
ecx, dword ptr [esp+1C]
比较两个加密号
eax, FFFFFFFF
加密号位置
分析后得出:
取出文件内容直到倒数第4个字节。最后4个字节再独立取出来。
我们认为这4个字节用于文件校验。称为加密号
接下来应该对NME文件进行处理,我们猜想可能是查mlog.bmp对应的数据
edx, dword ptr [ebx-8]
edx, dword ptr [esp+14]
取下一个OBJ
. |68 A8CE4300
ASCII &mlogo.bmp&
NME中的文件名
. |E8 EF5F0100
. |83C4 08
. |0F85 B9000000 jnz
. |68 B8D04300
ASCII &parts&
. |68 3C984300
ASCII &%s.det&
. |68 B0CF4300
ASCII &parts.nme&
; wspintf
. |83C4 0C
. |68 B0CF4300
ASCII &parts.nme&
open this file
/Origin = FILE_BEGIN
. |8B43 FC
eax, dword ptr [ebx-4] |
|pOffsetHi = NULL
. |FF15 0C014300 call
dword ptr [&&KERNEL32.SetFilePoi&; \SetFilePointer
esi, dword ptr [ebx]
. |E8 1A5A0100
. |83C4 04
/pOverlapped = NULL
. |8D4C24 2C
ecx, dword ptr [esp+2C] |
|pBytesRead
|BytesToRead
dword ptr [&&KERNEL32.ReadFile&] ; \ReadFile
. |FF15 D0004300 call
dword ptr [&&KERNEL32.CloseHandl&; \CloseHandle
查到mlog.bmp时,除了返回TRUE,还需要一些相关信息。这些信息可能记录在内存中。或一个对象中
要么是OBJ对象。要么是全局变量。所以需要跟踪 call
发现内部复杂,找不到有用的东西。暂时不管它。
我们又发现在不断的查找过程当中有个值在累加。是EBX
分析后面的代码发现:
& \8B4424 18
eax, dword ptr [esp+18]
ecx, dword ptr [esp+20]
dword ptr [esp+18], eax
.^ 0F8C 12FFFFFF jl
这说明信息并不是通过call 4223f1来得到的,而只是简单的一一对应方式。
mblog.bmp是parts.nme中的第6个,按0算,就是5*14h=64h; 14h一定是BMP的信息结构。
64h+8h是在parts.atm中的位置。也就是说,ATM文件中存放的是DEC文件中资源的定位信息。
parts.atm中头8个字节(值为0)可能有另用。
我们猜想接下来就是查看parts.det,并得到mlog.bmp对应的资源数据。
68 B8D04300
ASCII &parts&
68 3C984300
ASCII &%s.det&
68 B0CF4300
ASCII &parts.det&
68 B0CF4300
ASCII &parts.det&
;CreateFile
/Origin = FILE_BEGIN
edi, ea hFile
eax, dword ptr [ebx-4] 定位点 28f9d
|pOffsetHi = NULL
FF15 0C014300 call
dword ptr [&&KERNEL32.SetF&; \SetFilePointer
esi, dword ptr [ebx] SizeOfFile 7179
E8 1A5A0100
00421E6D new
/pOverlapped = NULL
ecx, dword ptr [esp+2C] |
|pBytesRead
|BytesToRead
dword ptr [&&KERNEL32.Read&; \ReadFile
FF15 D0004300 call
dword ptr [&&KERNEL32.Clos&; \CloseHandle
得到的BUFFER中就是BMP对应的加密数据。
试着构造下资源的结构:
struct BmpVerData //加密的BMP数据
SizeOfBmpF
//资源偏移
//表示未知,以后再改
三、资源分析
继续看下面的代码
.text:0040C46F
ecx, [esp+50h+@@pr_Key] ; 用来校验
[esp+50h+@@pr_Key], 0
.text:0040C47E
40c010CRC_Verify
.text:0040C47E
edx, [esp+50h+@@pr_Key]
eax, [ebx+4]
.text:0040C48A
.text:0040C48D
.text:0040C48F
short CleanMem
.text:0040C48F
.text: err:
esi, [esp+50h+@@if_use]
.text:0040C49B
.text:0040C49C
offset FileName
这些已加中文名称的CALL都是OD动态分析出来的
40c010前面已看到过了,是用来校验的
所以可以断定40c491处一定是错误显示。
我们跳过,看CleanMem:
.text: CleanMem:
CODE XREF: GetBmpInfo+31Fj
eax, [esp+4Ch+@@NumberOfBmp]
ecx, [esp+4Ch+@@ObjForDeCode]
ebx, [esp+4Ch+var_C]
.text:0040C50C
eax, [eax+eax*4]一个资源数据的大小
.text:0040C50F
eax, [ecx+eax*4+10h] ;10h处为数据的起始。前10h内容为文件头 7113
eax:数据大小。
.text:0040C51A
.text:0040C51B
.text:0040C51D
.text:0040C51D
edx, [esp+58h+@@ObjForDeCode]
.text:0040C52C
eax, [esp+5Ch+var_38]
NME数据删除
.text:0040C53A
.text:0040C53B
.text:0040C53D
.text:0040C53E
.text:0040C53F
后面有很多相同的CALL DELETE,我们在执行后发现,PUSH入的地址处数据无效,所以认为是DELETE
有理由认为我们已经到了解密代码处了。因为再后面就把不用的对象给释放了
E8 E65E0100
ecx, dword ptr [esp+10]
dword ptr [ebx], eax
ebx, dword ptr [ebx]
edx, dword ptr [esp+10]
cl, byte ptr [edi+edx]
FF时会重复前面的数据
short 0040BFF2
cl, byte ptr [edi+edx+1]
short 0040BFBE
ecx, dword ptr [ebx]
byte ptr [eax+ecx], 0FF
short 0040BFF7
short 0040BFD4
ecx, FFFFFFFC
short 0040BFF8
ecx, dword ptr [ecx]
esi, dword ptr [ebx]
cl, byte ptr [ecx+eax]
byte ptr [esi+eax], cl
short 0040BFE0
short 0040BFF8
edx, dword ptr [ebx]
byte ptr [eax+edx], cl
ecx, dword ptr [esp+14]
short 0040BFA0
分析后给出这一级解密的反C代码
for(i=0;i&DetSi++)
if(buf[i]==0xFF)
if(buf[i]!=0xff)
PreOffset=buf[i]&&2;
PreOffset++;
preNum=buf[i] & 0x;
if(preNum&0)
preNum |=0
preNum+=3;
if(preNum&0)
for(;preNum&0;preNum--)
nbuf[j]=nbuf[j-PreOffset];
nbuf[j]=buf[i];
紧接着发现这只是一级解密,数据还是不可直接读取
我们猜想数据还会继续解密,但是在它的上级函数中
直接返回,发现位于FindBmp中
.text: FindBmp
proc CODE XREF: Frame_ack+3EBp
.text: @@ptr_BmpInfo
= dword ptr -10Ch
.text: var_108
= byte ptr -108h
.text: var_4
= dword ptr -4
.text: arg_0
= dword ptr
.text: arg_4
= dword ptr
.text: arg_8
= dword ptr
eax, G_Key
.text:004183EB
eax, [esp+10Ch]
ebp, [esp+114h+arg_8]
.text:004183FB
.text:004183FC
esi, bmp type
.text:004183FE
.text:004183FF
[esp+11Ch+var_4], eax
eax, [esp+11Ch+var_108]
.text:0041840C
offset s_S_bmp_0 ; &%s.bmp&
push LPSTR
[ebx+4A4h], ebp
[ebx+4A0h], edi
.text:0041841E
ds:wsprintfA
ecx, [esp+124h+@@ptr_BmpInfo]
edx, [esp+128h+var_108]
.text:0041842D
.text:0041842E
[esp+12Ch+@@ptr_BmpInfo], 0
GetBmpInfo
.text:0041843B
esp, 14 BmpInfo还是加密的
.text:0041843E
eax, 数据的大小
short BmpDecode
.text: NotFound:
offset s_Gtg@gcglbuS_0 ; &僼傽僀儖乽%s乿偺撉傒崬傒偵幐攕偟傑偟偨&
offset byte_4C29D0 ; LPSTR
.text:0041844D
ds:wsprintfA
offset s_KgvUVN &奊偺撉傒崬傒&
ebx, offset byte_4C29D0
.text:0041845D
sub_41BBC0
.text:0041845D
short loc_4184E6
.text: ; ---------------------------------------------------------------------------
.text: BmpDecode:
CODE XREF: FindBmp+60j
esi, [esp+118h+@@ptr_BmpInfo]
.text:0041846B
.text:0041846D
short loc_4184E6
.text:0041846D
.text:0041846F
short loc_4184B9
al, [esi+1]
.text:0041847B
.text:0041847D
short loc_41849A
.text:0041847D
.text:0041847F
.text:0041847F FD_Type:
.text:0041847F
eax, [esp+118h+arg_4]
ecx, [esp+118h+arg_0]
.text:0041848D
.text:0041848E
.text:0041848F
short loc_4184DD
.text:0041849A ; ---------------------------------------------------------------------------
.text:0041849A
.text:0041849A loc_41849A:
CODE XREF: FindBmp+9Dj
.text:0041849A
.text:0041849C
short loc_4184B9
.text:0041849C
.text:0041849E
edx, [esp+118h+arg_4]
eax, [esp+118h+arg_0]
.text:004184AC
.text:004184AD
.text:004184AE
.text:004184AF
sub_417B70
short loc_4184DD
.text: ; ---------------------------------------------------------------------------
.text: loc_4184B9:
CODE XREF: FindBmp+94j
FindBmp+BCj
.text:004184BC
short loc_4184DD
.text:004184BC
.text:004184BE
byte ptr [esi+1], 'M'
short loc_4184DD
ecx, [esp+118h+arg_4]
.text:004184CB
edx, [esp+118h+arg_0]
sub_417EC0
.text:004184DD
.text:004184DD loc_4184DD:
CODE XREF: FindBmp+B8j
.text:004184DD
FindBmp+D7j
.text:004184DD
FindBmp+DCj
.text:004184DD
FindBmp+E2j
.text:004184DD
.text:004184DE
.text:004184DE
.text: loc_4184E6:
CODE XREF: FindBmp+85j
FindBmp+8Dj
ecx, [esp+118h+var_4]
.text:004184ED
ecx, [esp+118h]
Err_C 校对
.text:004184FC
.text: FindBmp
分析以上代码得出:
接下去会根据加密文件类型ID(BMP为FD),来具体的二级解码
要得到真正的位图数据,只能进入call
BmpObj中已存在相关信息
.text:00416E50
.text:00416E53
.text:00416E54
.text:00416E55
esi, BmpObj
.text:00416E57
ebp, word ptr [esi+4] ; BmpWidth
.text:00416E5B
eax, byte ptr [esi+2] ; BmpCell 调色板面数
.text:00416E5F
.text:00416E60
edi, word ptr [esi+6] ; BmpHeight
.text:00416E64
.text:00416E66
.text:00416E69
edx, ds:40h[ecx*4]
.text:00416E70
.text:00416E71
[esp+34h+@@BmpSize],对齐后的BMP大小 1d4c40h
.text:00416E75
.text:00416E75
.text:00416E7A
就是BMP位图对象,
.text:00416E7B
[esp+38h+@@BmpObj], eax
.text:00416E7F
eax, [esp+38h+@@BmpSize]
.text:00416E83
.text:00416E84
.text:00416E85
.text:00416E86
.text:00416E87
UnEntryBmpObj
;填充BMP位图对象
.text:00416E87
.text:00416E8C
eax, [esp+48h+arg_0]
.text:00416E90
.text:00416E92
.text:00416E95
.text:00416E97
[esp+30h+var_24], edx
.text:00416E9B
[esp+30h+var_1C], edx
.text:00416E9F
[esp+30h+var_20], ebp
.text:00416EA3
[esp+30h+var_18], edi
.text:00416EA7
short loc_416EB1
一般情况不要跟踪到CALL中,经过执行call
UnEntryBmpObj
发现参数BMP位图对象的内容已被填充
所以把这个CALL取名为UnEntryBmpObj
跟踪这个call
UnEntryBmpObj:
发现这个函数太过复杂
为了直接找到位图的填充代码,直接在BMP位图对象的内容处下硬件断点:
找到下面的代码
loc_416D75:
CODE XREF: UnEntryBmpObj+411j
.text:00416D75
edi, byte ptr [esi]
.text:00416D78
edx, byte ptr [esi+1]
.text:00416D7C
ecx, byte ptr [esi+2]
.text:00416D80
.text:00416D83
.text:00416D85
.text:00416D88
.text:00416D8A
cl, byte_4C2248[eax]
.text:00416D90
.text:00416D93
.text:00416D99
.text:00416D9B
.text:00416D9E
.text:00416DA0
.text:00416DA3
.text:00416DA5
eax, [esp+104h+var_F4]
.text:00416DA9
[eax],位图数据填充处
.text:00416DAB
.text:00416DAE
.text:00416DB4
.text:00416DB4
.text:00416DB7
.text:00416DB7 loc_416DB7:
CODE XREF: UnEntryBmpObj+5F3j
.text:00416DB7
[esp+104h+var_F4], eax
.text:00416DBB
[esp+104h+var_F0], edi
.text:00416DBB
.text:00416DBF
.text:00416DBF loc_416DBF:
CODE XREF: UnEntryBmpObj+3BCj
.text:00416DBF
UnEntryBmpObj+3E2j
.text:00416DBF
ebx, [esp+104h+var_F4]
.text:00416DBF
.text:00416DC3
.text:00416DC3 loc_416DC3:
CODE XREF: UnEntryBmpObj+3D7j
.text:00416DC3
UnEntryBmpObj+409j
.text:00416DC3
ebx, [esp+104h+var_E8]
.text:00416DC7
loc_4168C0
ebx, dword ptr [esp+10]
edx, dword ptr [eax]
dword ptr [ebx],数据相同的情况
也就是说数据被压缩了。
只有esi是对源数据定位的。
eax, byte ptr [esi]
. |0FB6&movzx
edx, byte ptr [eax*2+4C16F0]
. |0FB63C45 F116&movzx
edi, byte ptr [eax*2+4C16F1]
所以,源数据中存在的是4C16F0的偏移。实际数据在4c16f0中的
所以要查看4c16f0中的数据是何时写入的,这是张信息表
查看这张表发现是普通的数据表,从0001h到00FFh的奇数表
所以BMP数据是被压缩和加密处理过的。加密的方式是通过表来实现的。
由于这个函数特复杂。需进一步分析。
.text: @@CreateNewTable:
CODE XREF: UnEntryBmpObj+39j
short loc_4167AB
dword ptr [esp+104h+@@UnDeTable_1+4], 26
short loc_4167B6
.text:004167AB ; ---------------------------------------------------------------------------
.text:004167AB
.text:004167AB loc_4167AB:
CODE XREF: UnEntryBmpObj+23j
.text:004167AB
esi, ds:G_UnDeTable[eax*4]
dword ptr [esp+esi*4+104h+@@UnDeTable_1], 数组,4*26h
生成表G_UnDeTable[4*26h]
02 00 00 00 26 00 00 00
00 00 00 00 03 00 00 00
04 00 00 00 05 00 00 00
14 00 00 00 16 00 00 00
15 00 00 00 17 00 00 00
06 00 00 00 07 00 00 00
08 00 00 00 09 00 00 00
0A 00 00 00 0B 00 00 00
18 00 00 00 19 00 00 00
1A 00 00 00 1B 00 00 00
1C 00 00 00 1D 00 00 00
0C 00 00 00 0D 00 00 00
E 00 00 00 0F 00 00 00
00 00 00 11 00 00 00
00 00 00 13 00 00 00
E 00 00 00 1F 00 00 00
00 00 00 21 00 00 00
00 00 00 23 00 00 00
00 00 00 25 00 00 00
.text: loc_4167C0:
CODE XREF: UnEntryBmpObj+101j
ecx, ds:G_UnTable_1[eax]
ecx, edx:BmpWidth
ecx, ds:G_UnTable_0[eax] ; 0
.text:004167CF
dword ptr [esp+eax+104h+@@NT1_Dim], ecx
ecx, ds:(G_UnTable_1+4)[eax] ; 1
ebp, ds:(G_UnTable_0+4)[eax]
.text:004167DF
edi, ds:(G_UnTable_0+8)[eax] ; 2
.text:004167EA
dword ptr [esp+eax+104h+@@NT1_Dim+4], 1
.text:004167EE
ecx, ds:(G_UnTable_1+8)[eax]
esi, ds:(G_UnTable_0+0Ch)[eax] ; 3
.text:004167FF
dword ptr [esp+eax+104h+@@NT1_Dim+8], 2
ecx, ds:(G_UnTable_1+0Ch)[eax]
.text:0041680C
ebp, ds:(G_UnTable_0+10h)[eax] ; 4
dword ptr [esp+eax+104h+@@NT1_Dim+0Ch], 3
ecx, ds:(G_UnTable_1+10h)[eax]
.text:0041681E
edi, ds:(G_UnTable_0+14h)[eax] ; 5
dword ptr [esp+eax+104h+@@NT1_Dim+10h], 4
.text:0041682D
ecx, ds:(G_UnTable_1+14h)[eax]
esi, ds:(G_UnTable_0+18h)[eax] ; 6
.text:0041683C
.text:0041683E
dword ptr [esp+eax+104h+@@NT1_Dim+14h], 5
ecx, ds:(G_UnTable_1+18h)[eax]
ebp, ds:(G_UnTable_0+1Ch)[eax] ; 7
.text:0041684E
dword ptr [esp+eax+104h+@@NT1_Dim+18h], 6
ecx, ds:(G_UnTable_1+1Ch)[eax]
.text:0041685D
edi, ds:(G_UnTable_0+20h)[eax] ; 8
dword ptr [esp+eax+104h+@@NT1_Dim+1Ch], 7
.text:0041686C
ecx, ds:(G_UnTable_1+20h)[eax]
dword ptr [esp+eax+104h+@@NT1_Dim+20h], 8
.text:0041687B
.text:0041687E
loc_4167C0
这时出现了两张表。EDX都是BmpW
分析后,得出:
for(i=0;i&9;i++)
@@NT1_Dim[i]=(G_UnTable_1[i] * BmpWidth)+G_UnTable_0[i];
产生的表为:NT1_Dim[4*12h](BmpWidth=320h)
FF FF FF FF E0 FC FF FF
E1 FC FF FF DF FC FF FF
C0 F9 FF FF FE FF FF FF
A0 F6 FF FF FD FF FF FF
F3 FF FF FC FF FF FF
F0 FF FF FB FF FF FF
ED FF FF FA FF FF FF
EA FF FF F9 FF FF FF
E7 FF FF F8 FF FF FF
edx, [esp+104h+BmpHeight]BmpWidth*BmpHeight
.text:0041688F
esi, [esp+104h+BmpObj]
eax, [ebx+edx*4]到文件TAIL
.text:0041689C
相同表示图片0字节
.text:0041689E
[esp+104h+@@BmpObj_Offset10], esi
[esp+104h+var_F0], edi
.text:004168AB
[esp+104h+@@UdForBmp], ebx
.text:004168AF
[esp+104h+@@BmpSize], edx
[esp+104h+@@BmpTail], eax
loc_416DD1
接下来,又出现了两张新表。一张表有100h*2 (分奇数表和偶数表)
偶数表:G_BmpInfoTable1[200h]
01 00 01 02 01 04 01 06 01 08 01 0A 01 0C 01 0E
004C 01 12 01 14 01 16 01 18 01 1A 01 1C 01 1E
004C 01 22 01 24 01 26 01 28 01 2A 01 2C 01 2E
004C 01 32 01 34 01 36 01 38 01 3A 01 3C 01 3E
004C 01 42 01 44 01 46 01 48 01 4A 01 4C 01 4E
004C 01 52 01 54 01 56 01 58 01 5A 01 5C 01 5E
倁刁吁嘁堁威封币
004C 01 62 01 64 01 66 01 68 01 6A 01 6C 01 6E
态戁搁昁栁樁氁渁
004C 01 72 01 74 01 76 01 78 01 7A 01 7C 01 7E
瀁爁琁瘁码稁簁縁
004C 01 82 01 84 01 86 01 88 01 8A 01 8C 01 8E
老舁萁蘁蠁訁谁踁
004C 01 92 01 94 01 96 01 98 01 9A 01 9C 01 9E
送鈁鐁阁頁騁鰁鸁
004C 01 A2 01 A4 01 A6 01 A8 01 AA 01 AC 01 AE
01 B0 01 B2 01 B4 01 B6 01 B8 01 BA 01 BC 01 BE
01 C0 01 C2 01 C4 01 C6 01 C8 01 CA 01 CC 01 CE
01 D0 01 D2 01 D4 01 D6 01 D8 01 DA 01 DC 01 DE
01 E0 01 E2 01 E4 01 E6 01 E8 01 EA 01 EC 01 EE
01 F0 01 F2 01 F4 01 F6 01 F8 01 FA 01 FC 01 FE
01 00 02 04 02 08 02 0C 02 10 02 14 02 18 02 1C
004C 02 24 02 28 02 2C 02 30 02 34 02 38 02 3C
004C 02 44 02 48 02 4C 02 50 02 54 02 58 02 5C
????倂吂堂専
004C 02 64 02 68 02 6C 02 70 02 74 02 78 02 7C
怂搂栂氂瀂琂砂簂
004C 02 84 02 88 02 8C 02 90 02 94 02 98 02 9C
耂萂蠂谂适鐂頂鰂
004C 02 A4 02 A8 02 AC 02 B0 02 B4 02 B8 02 BC
004C 02 C4 02 C8 02 CC 02 D0 02 D4 02 D8 02 DC
004C 02 E4 02 E8 02 EC 02 F0 02 F4 02 F8 02 FC
004C 03 08 03 10 03 18 03 20 03 28 03 30 03 38
004C 03 48 03 50 03 58 03 60 03 68 03 70 03 78
??倃堃怃栃瀃砃
004C 03 88 03 90 03 98 03 A0 03 A8 03 B0 03 B8
考蠃逃頃????
03 C0 03 C8 03 D0 03 D8 03 E0 03 E8 03 F0 03 F8
03 00 04 10 04 20 04 30 04 40 04 50 04 60 04 70
????倄怄瀄
04 80 04 90 04 A0 04 B0 04 C0 04 D0 04 E0 04 F0
耄逄??????
04 00 05 20 05 40 05 60 05 80 05 A0 05 C0 05 E0
05 00 06 40 06 80 06 C0 06 00 07 80 07 00 08 00
奇数表:G_BmpInfoTable2[200h]
00 01 00 03 00 05 00 07 00 09 00 0B 00 0D 00 0F
004C 00 13 00 15 00 17 00 19 00 1B 00 1D 00 1F
004C 00 23 00 25 00 27 00 29 00 2B 00 2D 00 2F
004C 00 33 00 35 00 37 00 39 00 3B 00 3D 00 3F
004C 00 43 00 45 00 47 00 49 00 4B 00 4D 00 4F
004C 00 53 00 55 00 57 00 59 00 5B 00 5D 00 5F
儀匀唀圀夀嬀崀开
004C 00 63 00 65 00 67 00 69 00 6B 00 6D 00 6F
愀挀攀最椀欀洀漀
004C 00 73 00 75 00 77 00 79 00 7B 00 7D 00 7F
焀猀甀眀礀笀紀缀
004C 00 83 00 85 00 87 00 89 00 8B 00 8D 00 8F
脀茀蔀蜀褀謀贀輀
004C 00 93 00 95 00 97 00 99 00 9B 00 9D 00 9F
鄀錀销需餀鬀鴀鼀
004C 00 A3 00 A5 00 A7 00 A9 00 AB 00 AD 00 AF
00 B1 00 B3 00 B5 00 B7 00 B9 00 BB 00 BD 00 BF
00 C1 00 C3 00 C5 00 C7 00 C9 00 CB 00 CD 00 CF
00 D1 00 D3 00 D5 00 D7 00 D9 00 DB 00 DD 00 DF
00 E1 00 E3 00 E5 00 E7 00 E9 00 EB 00 ED 00 EF
00 F1 00 F3 00 F5 00 F7 00 F9 00 FB 00 FD 00 FF
01 02 01 06 01 0A 01 0E 01 12 01 16 01 1A 01 1E
004C 01 26 01 2A 01 2E 01 32 01 36 01 3A 01 3E
004C 01 46 01 4A 01 4E 01 52 01 56 01 5A 01 5E
???丁刁嘁威币
004C 01 66 01 6A 01 6E 01 72 01 76 01 7A 01 7E
戁昁樁渁爁瘁稁縁
004C 01 86 01 8A 01 8E 01 92 01 96 01 9A 01 9E
舁蘁訁踁鈁阁騁鸁
004C 01 A6 01 AA 01 AE 01 B2 01 B6 01 BA 01 BE
004C 01 C6 01 CA 01 CE 01 D2 01 D6 01 DA 01 DE
004C 01 E6 01 EA 01 EE 01 F2 01 F6 01 FA 01 FE
004C 02 0C 02 14 02 1C 02 24 02 2C 02 34 02 3C
004C 02 4C 02 54 02 5C 02 64 02 6C 02 74 02 7C
??吂専搂氂琂簂
004C 02 8C 02 94 02 9C 02 A4 02 AC 02 B4 02 BC
萂谂鐂鰂????
02 C4 02 CC 02 D4 02 DC 02 E4 02 EC 02 F4 02 FC
03 08 03 18 03 28 03 38 03 48 03 58 03 68 03 78
?????堃栃砃
03 88 03 98 03 A8 03 B8 03 C8 03 D8 03 E8 03 F8
蠃頃??????
04 10 04 30 04 50 04 70 04 90 04 B0 04 D0 04 F0
??倄瀄逄???
05 20 05 60 05 A0 05 E0 06 40 06 C0 07 80 08 00
这里是资源的读取和解密
.text:004168BD
ecx, [ecx+0]
.text:004168BD
.text: loc_4168C0:
CODE XREF: UnEntryBmpObj+647j
eax, G_BmpInfoTable1+1[edi*2] ; member1
.text:004168CA
ecx, G_BmpInfoTable1[edi*2] member0
short loc_4168EE
;不跳转说明还需查G_BmpInfoTable2
eax:G_BmpInfoTable1.member1;
如果不是第一次和最后一次,4168d4的代码不执行(意味着BmpOBj指针的位置不变)
ecx:偶数表中的member0 G_BmpInfoTable1[k].member0
eax, byte ptr [esi] Bmp数据(BmpObj+10h)
edx, G_BmpInfoTable2[eax*2] member0
.text:004168DF
eax, G_BmpInfoTable2+1[eax*2] ; member1
取BmpOBj下个数据
.text:004168EA
.text:004168EC
short loc_4168D4
eax:G_BmpInfoTable2.member1;
这说明BmpObj前10个字节都是文件头. 而且数据是以BYTE类型存放的
分析认为,如果G_BmpInfoTable1.member0+G_BmpInfoTable2.member0=0时。说明需继续取*Res。
继续代码:
又碰到了张表:G_UnDeForTable[100h]:100h大小
;用来比较用
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
02 07 06 07 05 07 06 07 04 07 06 07 05 07 06 07
03 07 06 07 05 07 06 07 04 07 06 07 05 07 06 07
00 07 06 07 05 07 06 07 04 07 06 07 05 07 06 07
03 07 06 07 05 07 06 07 04 07 06 07 05 07 06 07
02 07 06 07 05 07 06 07 04 07 06 07 05 07 06 07
03 07 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
004C 06 07 05 07 06 07 04 07 06 07 05 07 06 07
.text:004168EE loc_4168EE:
CODE XREF: UnEntryBmpObj+152j
.text:004168EE
edi, G_UnDeForTable[eax]
.text:004168FE
if(edx&edi)跳
short loc_416935跳表示不用RES来修正
分析:edi:G_UnDeForTable[G_BmpInfoTable2[i].member1]
edx:G_BmpInfoTable1.member0+G_BmpInfoTable2.member0
cl: G_BmpInfoTable1[k].member0+G_BmpInfoTable2[k].member0
ax: G_BmpInfoTable2[k].member1+100h
.text: loc_416935:
CODE XREF: UnEntryBmpObj+180j
ecx, e(ax&&cl)
ecx, 8(ax&&cl)/100h
.text:0041693C
ebp, dword ptr [esp+ecx*4+104h+@@UnDeTable_1+4]ecx&1h,否则出错
eax, 0FF 只取最后一字节,这样就不会超过ff
ebp, 14 4*6h才是14h
[esp+104h+@@TmpNum], ebp
.text:0041694C
loc_416B8E 小于第[6]的继续跳
.text:00416B8E loc_416B8E:
CODE XREF: UnEntryBmpObj+1CCj
.text:00416B8E
ebp, 2 和2再比较,就只[0]
0时是单独的数据
.text:00416B91
loc_416D75 小于的继续跳
eax: FFh && G_BmpInfoTable2[k].member1+100h
.text:00416D75 loc_416D75:
CODE XREF: UnEntryBmpObj+411j
.text:00416D75
edi, byte ptr [esi] 当前资源位 Res[i]
.text:00416D78
edx, byte ptr [esi+1] ; 当前资源位的下一位Res[i+1]
.text:00416D7C
ecx, byte ptr [esi+2] ; 当前资源位的二位 Res[i+2]
.text:00416D80
edi, 8 *100h
.text:00416D83
edi, Res[i]*100h+Res[i+1]
.text:00416D85
edi, 8 (Res[i]*100h+Res[i+1])*100h
.text:00416D88
edi, (Res[i]*100h+Res[i+1])*100h+Res[i+2]
.text:00416D8A
cl, G_UnDeForTable[eax]
.text:00416D90
edi, 8 (Res[i]*100h+Res[i+1])*100h+Res[i+2]*100h
.text:00416D93
((Res[i]*100h+Res[i+1])*100h+Res[i+2]*100h)xor h
.text:00416D99
edi, (((Res[i]*100h+Res[i+1])*100h+Res[i+2]*100h)xor h)&&G_UnDeForTable[j]
.text:00416D9B
eax, 10 j*10eh
.text:00416D9E
.text:00416DA0
edx, 8((((Res[i]*100h+Res[i+1])*100h+Res[i+2]*100h)xor h)&&G_UnDeForTable[j])/100h
.text:00416DA3
edx,(((((Res[i]*100h+Res[i+1])*100h+Res[i+2]*100h)xor h)&&G_UnDeForTable[j])/100h) xor j
.text:00416DA5
eax, [esp+104h+@@UdForBmp]
.text:00416DA9
[eax], F填充到图片数据中。
.text:00416DAB
eax, 4指向图像数据的下一个
.text:00416DAE
.text:00416DB4
.text:00416DB4
edi:FFh && (((Res[i]*100h+Res[i+1])*100h+Res[i+2]*100h)xor h)&&G_UnDeForTable[j]
.text:00416DB7
.text:00416DB7 loc_416DB7:
CODE XREF: UnEntryBmpObj+5F3j
.text:00416DB7
[esp+104h+@@ptr_ImageData], eax
.text:00416DBB
[esp+104h+@@TmpNum], edi
.text:00416DBB
.text:00416DBF
.text:00416DBF loc_416DBF:
CODE XREF: UnEntryBmpObj+3BCj
.text:00416DBF
UnEntryBmpObj+3E2j
.text:00416DBF
ebx, [esp+104h+@@ptr_ImageData]当前图像数据位置
.text:00416DBF
.text:00416DC3
.text:00416DC3 loc_416DC3:
CODE XREF: UnEntryBmpObj+3D7j
.text:00416DC3
UnEntryBmpObj+409j
.text:00416DC3
ebx, [esp+104h+@@BmpTail]是否读完了
.text:00416DC7
loc_4168C0 没完,继续
EBP值为26时,重复前面的一段数据
loc_416B1D:大量重复
edi, [edi+edi+1]双重复
loc_416B70:色偏分支
ebp, [ebx+edx*4] edx:取前面的ImageData 在NT1_Dim表中查找差距(这是用来对整行的数据进行复制)
ebp, [eax+edx*4]
ebp, [eax-4] EBP修正色偏
[ebx-4], FILL
short loc_416B70
反成C,就是
SubData=NT_Dim[(Od_value-0x14)];
for(int i=Offset_Vi&0;i--)
*(Image)=*(Image+SubData)-*(OffsetImage+SubData)+*(OffsetImage); //填充IMAGE数据
OffsetImage++;
loc_416B46: 填充前面的整段数据,不带色偏
edx, [eax]
[ebx], Fill
eax, 4 ecx:段大小
多次填充前面的一段数据
short loc_416B46
loc_416D75:
ebp&=2 不重复,不带色差的
edi, byte ptr [esi]同时取多个Res数据
edx, byte ptr [esi+1]
ecx, byte ptr [esi+2]
cl, G_UnDeForTable[eax]
eax, [esp+104h+@@ptr_ImageData]
[eax], Fill
if(Od_value&2)
//无修正,无重复,直接组合
ImageData=(((Res[0]&&8)+Res[1])&&8)+Res[2];
ImageData&&=8;
ImageData^=0x;
ImageData&&=G_UnDeForTable[FindCode];
TmpSave=FindC
FindCode=ImageData & 0xFF;
//取出下次用的FindCode,用于查表定位
ImageData&&=8;
ImageData^=(TmpSave&&0x10);
*Image=ImageD
//填充IMAGE数据
loc_416D48:14&ebp&2 不重复数据。可能带色差
edi,分别处理不同的Res数据。
ecx, 0FFFFFFFEh
eax, [esp+104h+@@ptr_ImageData]
[eax], Fill
short loc_416DB7
Exbt&&=Bt_
Old_Offv=(-((Exbt&&8) &1)^((Exbt&&8)-2));
if(Old_Offv&=0)
{adjsig=0;}
{adjsig=-1;}
Offset_Color+=(Old_Offv-adjsig)&&1;
//保留符号位
*Image=Offset_C
//填充IMAGE数据
FindCode=Exbt & 0xFF;
这个函数中的特殊代码讲解:
.text:004168EE
edi, G_UnDeForTable[eax]
eax, 100为下一轮作准备
.text:004168FE
short loc_416935
//如果edx&0时,就比表示要取*Res
ecx, byte ptr [esi]
eax, 0FFFFFF00h
.text:0041690E
.text:0041690F
short loc_41692F
//可能会了出现大量的重复
.text:0041691C
.text:0041691E
edx, [edx+edi*8]
.text: loc_416923:
CODE XREF: UnEntryBmpObj+1ADj
edi, byte ptr [esi]
.text:0041692B
.text:0041692C
.text:0041692D
short loc_416923
.text:0041692D
.text:0041692F
.text:0041692F loc_41692F:
CODE XREF: UnEntryBmpObj+195j
.text:0041692F
eax, [eax+eax+1]加倍重复
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;重复数*100h 或更大
Bt_num=prevId;
G_BmpInfoTable1s查到为0时,则要用新的*R
有多种修正方法
G_BmpInfoTable1.member0=0时,用ResG_BmpInfoTable2,来定位查G_BmpInfoTable2.还是0,就下一个,还在表中查,
,用Res数据来查。并且Res++,直到不是0。而且G_BmpInfoTable(1,2).member0=G_BmpInfoTable1.member0+G_BmpInfoTable2.member0;Res++
G_BmpInfoTable(1,2).member1用来定位G_UnDeForTable.
G_BmpInfoTable(1,2).member0用来比较G_UnDeForTable.
cdq:测试EDX是不是和EAX的进位标识一样,类似于 a?0:-1;
以下是动态跟踪中的过程:(不是很详细,仅提供参考,详细分析请参考反后的C代码)
经一级解密的BMP部分数据(还是加密的)
8F FE FD 64 00 88 01 04
资源中的数据用来定位G_BmpInfoTable2
00C0 12 D4 54 C9 46 90
00C0 D1 05 49 11 12 14
00C0 A4 CA 80 51 41 12
D4 54 D5 41 4D 21 38 6D
00C0D 40 4B 52 54 E1 84
C5 45 4D D4 D9 4A A4 80
00C0 4E 08 4C A1 2D 4D
00C0 30 84 A5 32 53 15
00C0D 4A 94 44 B5 38 54
00C0 13 58 41 4F C1 A5
8F 取出FEFD64 -&FEFD6480-&07EFD648 -&07EFD6
8F是第一个数据
cl(&&1(G_UnDeForTable))
F8-&F80000-&FEEFD6 (8 xor 7=F)
第一次填充完毕。
90-&190-&320(&&1)-&3 + 20
//20*2-&01 40(G_BmpInfoTable1) 和 G_UnDeForTable 比 (01=01)
20*2-&140(添加1)-&280(&&1)-&2 +
80*2-&01 00(G_BmpInfoTable1)
2-&0(取最后一位)-&-1
RES:00-&00 01 -&07(G_UnDeForTable)
01-&101(添加1)
101-&202(&&1)
202-&2 + 02
///////////////// 校正下。用于重复前面的某些数据
02*2-&01 04(G_BmpInfoTable1)-&05(G_UnDeForTable)
01 04-&104(添加1)-&208(&&cl)-&2 + 08(用于下轮1的查找)
2-&1(-1) //和0比
当前G_UnDeTable中的定位和26比 (26可能是种标志)
08*2-&01 10(G_BmpInfoTable1)-&03(G_UnDeForTable)
01 10-&110(添加1)-&220(&&cl)-&2 + 20(用于下轮2的查找)
G_UnDeTable用来比的,实现不同的分支 (现在用ebp=2-2定位)
用ebp定位NT1_D
20*2-&01 40(G_BmpInfoTable1) 和 G_UnDeForTable 比 (01=01)
01 40-&140(添加1)-&280(&&cl)-&2 + 80(用于下轮3的查找)
2-&0(取最后一位)-&0(~)
///////////////// 校正下。有时定位到IMage--;用于重复前面的某些数据
80*2-&01 00(G_BmpInfoTable1)
查G_BmpInfoTable2
88*2(Res)-&01 22(G_BmpInfoTable2)-&06(G_UnDeForTable)
01 22-&122(添加1)-&488(&&cl)-&4 + 88(用于下轮4的查找)
4-&0(取最后一位)-&0(~)(edx)
4-&2(-2)-&2(xor edx)-&100(&&7)
ebx+100;ebx:上个ImageData 07EFD6+100=07F0D6
88*2-&02 20(G_BmpInfoTable1)-&02(G_UnDeForTable)(edx)
02 20-&120(添加1)-&480(&&cl)-&4 + 80(查毕,用于下个ImageData)
4-&0(取最后一位)-&0(~)(eax)
4-&2(-2)-&2(xor eax)-&0(cdq)
2-&1(sar 1)
07FFD6+1=07F0D7
//填充Image
80*2-&01 00-&
Res(01)-& 00 03(G_BmpInfoTable1)-&07(G_UnDeForTable) Res++
00 03-&103(添加1)-&206(&&cl)-&2 + 06
ebp=2-2 G_UnDeTable(0):2
做下总结:
首先从.NME中找到图片的名称,并记录下序号。然后查找相应的.ATM文件。得到相关的信息。
(要验证加密号,以免数据已被修改)
包括DET文件中对应的位置和大小。然后先做下调整,也就是一级解密。(重复某些前面的数据)
然后根据文件前10H的文件头(里面包含宽度,高度,位数)算出图片的大小。把它解压缩,也就是
二级解密。
反汇编分析的总结:
通过IDA分析出函数的整体架构。
遇到CALL时别马上跟踪,先分析参数,再动态看CALL后的变化
做好注释,并把一些常数改成具体的API常数的表示。
加强静态分析能力,不要依赖于动态分析
寄存器也可能是变量或参数。在分析时要注意
尽可能减少变量的个数。变量多了,会大大增加分析难度
利用OD的堆栈和IDA的图表交叉来分析流程
熟悉各种CALL调用的方式,如STDCALL还是CDECL,FASTCALL等
特别要注意CDQ,SAR等汇编指令。这表明这是个有符号数
熟悉反汇编工具OD和IDA。以及能编写简单的脚本。
熟悉VC,BC,DELPH等常用编译器的风格
要确保每个环节都不出差错。否则到后面时不知道错在哪里
要思考如果是自己写的话,你会如何写这个程序。从而找到突破的地方
二级解密的流程:
创建所需要的5张表:
初始化FindCode为0x80,用它查找G_BmpInfoTable1;得到序号和值。如果值为0,取出加密数据中的值。
再用这个值拿来查表G_BmpInfoTable2。如果还是0,循环查表G_BmpInfoTable2。直到不是0。加密数据
的内容主要就是用来查表的.再用这个值查表G_UnDeForTable.得到的值和原来的序号比。如果小于就说明
要修正。这个值同时也是分支号。0时,表示只填充一次。而且直接对加密数据运算得到图素。0x26时,
重复填充前面的一段图素,2-0x14时,修正色差。并填充一次。0x14-0x26时,重复N行的图素。
详细内容请看下面的反C代码,代码在下面的帖子中。
请浏览/showthread.php?t=102499
phf峰下面试着反成C:(测试成功)
并用SDK来写:
struct Record
struct BmpRecord
char str[16];
struct BmpHeader
BYTE UNKNOW1;
BYTE UNKNOW2;
BYTE UNKNOW4;
//typedef char BYTE;
G_BmpInfoTable1[0x100];
G_BmpInfoTable2[0x100];
G_UnDeForTable[0x100];
G_UnDeTable[0x26];
NT_Dim[0x12];
OffsetImageD
*BmpData=0;
DWORD G_UnTable[0x26] =
{0x2, 0x1, 0x0, 0x3,
0x4, 0x5, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F,
0x16, 0x17, 0x18, 0x19,
0x1A, 0x1B, 0x1C,0x1D,
0x6, 0x8, 0x7, 0x9,
0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x1E, 0x1F,
0x20,0x21, 0x22, 0x23,
0x24,0x25};
DWORD G_UnTable_0[0x12]=
{-1,0,1,-1, 0,-2,0,-3,
0,-4,0,-5 ,0,-6,0,-7,0,-8};
DWORD G_UnTable_1[0x12]=
{0,-1,-1,-1,-2,0,-3,0,
-4,0,-5,0,-6,0,-7,0,-8,0};
DWORD G_UnTable_2[0x12] =
{-1 ,0 ,1 ,-1 ,-2, -2, -2, -1,0 ,1 ,2 ,2 ,-3, -3, -3, -3,
MapReader.cpp:
// MapReader.cpp : Defines the entry point for the application.
#include &stdafx.h&
#include &MyBmp.h&
#include &resource.h&
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hI
// current instance
TCHAR szTitle[MAX_LOADSTRING];
// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];
// The title bar text
// Foward declarations of functions included in this code module:
MyRegisterClass(HINSTANCE hInstance);
InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
FileRead();
LookBmpData(LPVOID lp,LPVOID nlp,int id);
InitTable(DWORD nWidth);
UnDecode(BYTE* lp,int BmpWidth);
DrawBmp(HWND hwnd,DWORD* lp);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
lpCmdLine,
// TODO: Place code here.
HACCEL hAccelT
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MAPREADER, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
return FALSE;
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MAPREADER);
FileRead();
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
TranslateMessage(&msg);
DispatchMessage(&msg);
return msg.wP
FUNCTION: MyRegisterClass()
PURPOSE: Registers the window class.
This function and its usage is only necessary if you want this code
to be compatible with Win32 systems prior to the 'RegisterClassEx'
function that was added to Windows 95. It is important to call this function
so that the application will get 'well formed' small icons associated
ATOM MyRegisterClass(HINSTANCE hInstance)
WNDCLASSEX
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style
= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndP
wcex.cbClsExtra
wcex.cbWndExtra
wcex.hInstance
wcex.hIcon
= LoadIcon(hInstance, (LPCTSTR)IDI_MAPREADER);
wcex.hCursor
= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_MAPREADER;
wcex.lpszClassName = szWindowC
wcex.hIconSm
= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
In this function, we save the instance handle in a global variable and
create and display the main program window.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
hInst = hI // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
Processes messages for the main window.
WM_COMMAND - process the application menu
WM_PAINT - Paint the main window
WM_DESTROY - post a quit message and return
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
int wmId, wmE
PAINTSTRUCT
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
case WM_COMMAND:
= LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
case IDM_EXIT:
delete BmpD
DestroyWindow(hWnd);
case IDC_TEST:
DrawBmp(hWnd,BmpData);
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
GetClientRect(hWnd, &rt);
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
case WM_DESTROY:
PostQuitMessage(0);
return DefWindowProc(hWnd, message, wParam, lParam);
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
return FALSE;
HRESULT FileRead()
int BmpId=0x5;
BmpRecord br[200];
dwSize,dwByR
hFile=CreateFile(&parts.nme&,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
if(INVALID_HANDLE_VALUE==hFile) return E_FAIL;
dwSize=GetFileSize(hFile,NULL);
dwSize-=4;
const DWORD nSize=dwS
BYTE *buf=new BYTE[dwSize];
ReadFile(hFile,buf,dwSize,&dwByRead,NULL);
memset(br,0,200*sizeof(BmpRecord));
for(int i=0;i&200;i++)
br[i].id=i;
while(buf[j]!=0)
br[i].str[k]=buf[j];
br[i].str[k]=0;
CloseHandle(hFile);
hFile=CreateFile(&parts.atm&,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
if(INVALID_HANDLE_VALUE==hFile) return E_FAIL;
dwSize=GetFileSize(hFile,NULL);
dwSize-=4;
buf=new BYTE[dwSize];
ReadFile(hFile,buf,dwSize,&dwByRead,NULL);
DWORD DetOffset,DetS
DetOffset=*(DWORD*)(buf+4+0x14*BmpId);
DetSize=*(DWORD*)(buf+8+0x14*BmpId);
DWORD uObjS
uObjSize=*(DWORD*)(buf+((BmpId+BmpId*4)*4)+16);
CloseHandle(hFile);
hFile=CreateFile(&parts.det&,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
if(INVALID_HANDLE_VALUE==hFile) return E_FAIL;
buf=new BYTE[DetSize];
SetFilePointer(hFile,DetOffset,0,FILE_BEGIN);
ReadFile(hFile,buf,DetSize,&dwByRead,NULL);
BYTE* nbuf=new BYTE [uObjSize];
memset(nbuf,0,uObjSize);
DWORD PreO
for(i=0;i&DetSi++)
if(buf[i]==0xFF)
if(buf[i]!=0xff)
PreOffset=buf[i]&&2;
PreOffset++;
preNum=buf[i] & 0x;
if(preNum&0)
preNum |=0
preNum+=3;
if(preNum&0)
for(;preNum&0;preNum--)
nbuf[j]=nbuf[j-PreOffset];
nbuf[j]=buf[i];
CloseHandle(hFile);
Bmp_Head=(BmpHeader*)
InitTable(Bmp_Head-&BmpWidth);
BmpData=UnDecode(nbuf,Bmp_Head-&BmpWidth);
memcpy(&G_BmpHead,Bmp_Head,0x10);
dwByRead=0x1d4c00;
DetSize=0x1d4c00;
hFile=CreateFile(&bmp.mem&,GENERIC_READ|GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
WriteFile(hFile,BmpData,DetSize,&dwByRead,NULL);
CloseHandle(hFile);
return S_OK;
DWORD* UnDecode(BYTE* lp,int BmpWidth)
DWORD prevId;
DWORD oldId;
DWORD OffsetPrevId;
long Old_O
DWORD Offset_V
DWORD Offset_C
DWORD SubD
BmpSize=(Bmp_Head-&BmpHeight)*(Bmp_Head-&BmpWidth)+0x10;
Image=new DWORD[BmpSize];
memset(Image,0,BmpSize*4);
ImageData=*I
Res=(lp+0x10);
Tail=Image+BmpSize-0x10;
FindCode=0x80;
OffsetImageData=ImageD
//if (Image==(DWORD*)(0xfb48)) _asm{int 3};
OffsetImage=I
Bt_value=G_BmpInfoTable1[FindCode].
=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
Exbt&&=Bt_
Od_value=(BYTE)G_UnDeTable[(Exbt&&8)-2];
FindCode=(BYTE)(Exbt & 0xFF);
if(Od_value&0x14)
if(Od_value&2)
//无修正,无重复,直接组合
ImageData=(((Res[0]&&8)+Res[1])&&8)+Res[2];
ImageData&&=8;
ImageData^=0x;
ImageData&&=G_UnDeForTable[FindCode];
TmpSave=FindC
FindCode=ImageData & 0xFF;
ImageData&&=8;
ImageData^=(TmpSave&&0x10);
*Image=ImageD
//填充IMAGE数据
Nt_value=NT_Dim[Od_value-2];
Offset_Color=*(Image+Nt_value);
//用于修正
Bt_value=G_BmpInfoTable1[FindCode].
=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
Exbt&&=Bt_
Offset_Color+=((0-((Exbt&&8)& 1) ^ ((Exbt&&8)-2))&&0xF);
FindCode=(BYTE)(Exbt & 0xFF);
Bt_value=G_BmpInfoTable1[FindCode].
Bt_num=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
Exbt&&=Bt_
Offset_Color+=((0-((Exbt&&8)& 1) ^ ((Exbt&&8)-2))&&0x7);
FindCode=(BYTE)(Exbt & 0xFF);
Bt_value=G_BmpInfoTable1[FindCode].
Bt_num=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
Exbt&&=Bt_
Old_Offv=(-((Exbt&&8) &1)^((Exbt&&8)-2));
if(Old_Offv&=0)
{adjsig=0;}
{adjsig=-1;}
Offset_Color+=(Old_Offv-adjsig)&&1; //保留符号位
*Image=Offset_C
//填充IMAGE数据
FindCode=Exbt & 0xFF;
Bt_value=G_BmpInfoTable1[FindCode].
Bt_num=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
Bt_num+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
Exbt&&=Bt_
oldId=Exbt&&8;
Offset_Value=((Exbt&&8)& 1)-1;
FindCode=(BYTE)(Exbt & 0xFF);
Bt_value=G_BmpInfoTable1[FindCode].
Bt_num=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
Bt_num+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
//SubData=Bt_value-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
DWROD CalcT
if(Bt_num&=0)
{CalcTmp=0;}
esle{CalcTmp=-1}
//Offset_Value^=(((Exbt&&Bt_num)&&8)-2)-(((((Exbt&&8)&&1)-CalceTmp)+Offset_Value)*BmpWidth);
Exbt&&=Bt_
if(oldId&=0)
{TmpSave=0;}
{TmpSave=-1;}
Old_Offv=(((oldId-TmpSave)&&1)+Offset_Value)*BmpW
Offset_Value^=(Exbt&&8)-2;
Offset_Value-=Old_O
//Offset_Value^=(((Exbt&&8)-2)-((((Exbt&&8)&&1)+Offset_Value)*BmpWidth));
OffsetImage+=Offset_V
FindCode=(BYTE)(Exbt & 0xFF);
Bt_value=G_BmpInfoTable1[FindCode].
Bt_num=G_BmpInfoTable1[FindCode].
if(!Bt_value)
Bt_value=G_BmpInfoTable2[*Res].
Bt_num+=G_BmpInfoTable2[*Res].
}while(!Bt_value);
Ud=G_UnDeForTable[Bt_value];
Exbt+=0x100;
prevId=Bt_num-Ud;
if(Bt_num&Ud)
Exbt&&=Ud;
Exbt=(Exbt & 0xFFFFFF00)+(*Res);
if(prevId&=8)
OffsetPrevId=prevId&&3;
prevId+=(0-OffsetPrevId)*8;
for(i=OffsetPrevId;i&0;i--)
Exbt &&=8;
Bt_num=prevId;
Exbt&&=Bt_
Offset_Value=(Exbt&&8);
Offset_Value--;
FindCode=(BYTE)(Exbt & 0xFF);
if(Od_value==0x26)
if(Offset_Value&0)
for(i=Offset_Vi&0;i--)
*Image=*OffsetI
//填充IMAGE数据
OffsetImage++;
if(Offset_Value&0)
SubData=NT_Dim[(Od_value-0x14)];
for(int i=Offset_Vi&0;i--)
*(Image)=*(Image+SubData)-*(OffsetImage+SubData)+*(OffsetImage); //填充IMAGE数据
OffsetImage++;
}while(Image&Tail);
数据未读完
Image-=(BmpSize-0x10);
void InitTable(DWORD nWidth)
char a,b,x;
for(BYTE y=0;y&=0xFF;y++)
}while(a&0);
if((a&&=1)==0) b--;
G_BmpInfoTable1[y].id=b;
G_BmpInfoTable1[y].value=a;
}while(a&0);
G_BmpInfoTable2[y].id=b;
G_BmpInfoTable2[y].value=a;
if(i & 0x7f)
}while(b & 0x7f);
G_UnDeForTable[y]=a;
if(y==0xff)
DWORD TmpN
for(i=0;i&0x26;i++)
TmpNum=G_UnTable[i];
G_UnDeTable[TmpNum]=i;
G_UnDeTable[1]=0x26;
for(i=0;i&18;i++)
NT_Dim[i]=(G_UnTable_1[i] * nWidth)+G_UnTable_0[i];
DrawBmp(HWND hwnd,DWORD* lp)
//仅用于测试
hdc=GetDC(hwnd);
LPBITMAPINFO pBit = (LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
//pBit-&bmiHeader.biWidth
DWORD tmp[5];
tmp[0]=0x28;
tmp[1]=0x320;
tmp[2]=0x258;
tmp[3]=0x;
pBit=(BITMAPINFO*)
StretchDIBits(hdc,0,0,0x320,0x258,0,0,0x320,0x258,lp,pBit,DIB_RGB_COLORS,SRCCOPY);
ReleaseDC(hwnd,hdc);
以上代码经测试,可完美的读出图片。
x敏m做沙发,学习。。
madsys非常详细的分析,楼主辛苦了
刚看到&廫榋栭偺壴壟丒懱尡斉&我还说,怎么一个字都不认识...
jerrynpc没看明白楼主这是在做虾米?
听听雨吧下面试着反成C:(测试成功)
并用SDK来写:
struct Record
struct BmpRecord
char str[16];
struct BmpHeader...
楼主这是在干什么..........
轩辕小聪“廫榋栭偺壴壟丒懱尡斉”改编码为日文之后-&“十六夜の花嫁?体験版”,Orz
轩辕小聪没看明白楼主这是在做虾米?
这是楼主对/showthread.php?t=102498中提到的程序分析的进一步。
phf峰由于文字太多,只好分成两个贴子。请见谅
phf峰今后将继续写出一些详细的逆向分析资料,请关注
phf峰今后将继续写出一些详细的逆向分析资料,请关注
zhangdaren不错不错,楼主辛苦了。。。
ybdao文章很经典!
prfhzyh嗯,嗯,思路很不错,学习中
wentiruhai恩,看看,好东西。

我要回帖

更多关于 java gc是什么 的文章

 

随机推荐