浅谈VFP程序的破解Word格式.docx
《浅谈VFP程序的破解Word格式.docx》由会员分享,可在线阅读,更多相关《浅谈VFP程序的破解Word格式.docx(21页珍藏版)》请在冰豆网上搜索。
文件名列表地址
[目录名],00,文件名,00,文件名,00,...
文件说明结构列表地址
每个文件占用25个byte,总长度为文件数*25
0文件类型0为代码其他数据
1-4文件开始地址
5-8文件结束地址
9-12文件名相对文件名列表的首地址
其他不详
三、VFP的加密特点及脱壳
VFP的加密基本上可以分为两种—文件型加密和内存型加密,这两种加密的区分主要在APP文件的存放位置,存放在某个文件中就为文件型,存放在内存中就叫内存型。
但对解密者来说,关心的是算法。
以上的分类加不加以区别问题不大。
1、
文件头简单替换型
这种加密方式是比较早期的一种加密方式,能够阻止反编译软件,但APP代码在文件中以明码出现,如xx王5.05B()
脱壳方法:
打开HEX,查找FEF2找到后与APP文件的结构对比一下,发现没有问题,把从FEF2开始到文件尾的数据存成一个文件,取名XXX.app,脱壳完成。
2、文件隐藏型
这类加密在exe文件中已经没有app的明码了,app文件是由主程序运行过程中动态生成的,以文件形式存在硬盘的某处。
如xx通用计划管理系统6.02()
用TRW2000加载程序
下断bpxcreatefilea
createfilea的定义为:
HANDLECreateFile(
LPCTSTRlpFileName,//pointertonameofthefile
DWORDdwDesiredAccess,//access(read-write)mode
DWORDdwShareMode,//sharemode
LPSECURITY_ATTRIBUTESlpSecurityAttributes,//pointertosecurityattributes
DWORDdwCreationDisposition,//howtocreate
DWORDdwFlagsAndAttributes,//fileattributes
HANDLEhTemplateFile//handletofilewithattributestocopy
);
每次中断后观察打开的文件名,经过两次foxpro.int下面一个就是脱壳后的文件名了。
文件放在c:
\windows\history\…\…exe
因为c:
\windows\history\是windows的系统目录,下面的文件不可显示,程序运行结束后又会删除这个文件,所以必须在程序没有结束前得到这个文件
方法一:
用suspend将程序挂起,用procdumpkill现有进程,回dos利用xcopy/s将所有文件考出,处理
方法二、利用copyfilea函数
BOOLCopyFile(
LPCTSTRlpExistingFileName,
//pointertonameofanexistingfile
LPCTSTRlpNewFileName,//pointertofilenametocopyto
BOOLbFailIfExists//flagforoperationiffileexists
在上图的位置reax0rebx63e630redx63e660
将63e660地址的内容改成目的文件如d:
\ab\s.exe
然后编一段代码
aeip
pusheax
pushedx
pushebx
callcopyfilea
最后一句不能直接输入,要用exescope找到import中copyfilea的位置,计算相对地址用ff15xxxxxxxx填入
单步运行完copyfilea后,隐藏的文件就被考出来了。
考出的文件是exe文件,用1的方法就能得到app文件,但这个app文件可运行,用unfoxall反编译会出错,后面会讲到app文件的标准化处理。
3改变解释器动态解码
这种加密方式采用了狗的方式,用trw2000加载跟踪时,在文件开始运行的代码部分会看到大量的花指令,再将主文件加密的同时,它把解释动态连接库也进行了加壳,运行时用壳中的代码将app文件解码后执行。
因vfp6r.dll被改动,无法放到系统目录下,因此文件安装目录下能看到vfp6r.dll,用exescope文件观察此文件,能看到gtide段,这就是这种文件的特征。
例如:
xx建筑工程预结算系统6.6版()
处理方法:
采用2的方法下断createfilea,得到调用文件后,下断readfile,
readfile定义如下:
BOOLReadFile(
HANDLEhFile,//handleoffiletoread
LPVOIDlpBuffer,//pointertobufferthatreceivesdata
DWORDnNumberOfBytesToRead,//numberofbytestoread
LPDWORDlpNumberOfBytesRead,//pointertonumberofbytesread
LPOVERLAPPEDlpOverlapped//pointertostructurefordata
第3次读200byte时中断,在读出的代码处下断,bpmxxxxxxxx,观察程序如何解码
解码部分的指令
0167:
0C2FA505INCDWORD[EBP-04]已处理字节数
0C2FA508MOVEAX,[EBP+0C]要处理字节数
0C2FA50BCMP[EBP-04],EAX
0C2FA50EJNC0C2FA53A
0C2FA510MOVEAX,[EBP-04]
0C2FA513MOVECX,[EBP+08]要处理数据的首地址
0C2FA516XOREDX,EDX
0C2FA518MOVDL,[ECX+EAX]要处理的数据送DL
0C2FA51BMOVAL,[EDX+0C3352E2]0C3352E2—0C3354E2512个字节为密钥
0C2FA521MOV[EBP-08],AL
0C2FA524XOREAX,EAX
0C2FA526MOVAL,[EBP-08]
0C2FA529MOVAL,[EAX+0C3353E2]
0C2FA52FMOVECX,[EBP-04]
0C2FA532MOVEDX,[EBP+08]
0C2FA535MOV[EDX+ECX],AL
JMP0C2FA505
W0C3352E20C3354E2key.bin
记下读出的内容,用hexworkshop在主文件中查找,将到文件尾的内容写入另一个文件code.bin
用VB的语言,上述的解密算法为
Dimkeyfiledata(0to511)AsByte
Dimcodefiledata()AsByte
Dimmiddata()AsByte
DimkeyfilelenAsLong
Open"
Key.bin"
ForBinaryAs#1
Get#1,1,keyfiledata()
Close#1
keyfilelen=FileLen("
code.bin"
)
Redimkeyfiledata(0tokeyfilelen-1)asbyte
Redimmiddata(0tokeyfilelen-1)asbyte
ForBinaryAs#2
Get#2,i,codefiledata
Close#2
ForI=0tokeyfilelen-1
Middata(i)=keyfiledata(keyfiledata(codefiledata(i))+256)
Nexti
code.app"
Put#2,1,middata()
Close#2
MsgBox"
finish"
得到app文件
4改变解释器的加密方式
这种文件的加密方式的app文件是以加密app的方式出现,加密者将vfp6r.dll的解密部分代码和文件头标志加以改变,变成自己的动态连接库,这个库文件同样放在文件的安装目录下,但有的程序采用了一定的手段让用户看不到这个文件。
xx工程造价软件6.6版()
这个软件安装后,改变注册表HKEY_LOCAL_MACHINE\software\Microsoft\windows\currentversion\explorer\advanced\folder\hidden\showall\checkedvalue
将键值由0改为1,这样隐含系统文件你就看不到了,我认为这种方法是不可取得,文件加密的同时不应干扰用户其他的功能,利用这种方法有点缺德之嫌。
就以这个程序为例,首先比较一下正规的vfp6r.dll和程序用的vfp6r.dll有何不同
0C02102EMOVECX,02
0C021033MOVEDI,0C2F24C8[edi]为c4c5正常为fef2
0C021038MOVESI,EBX
0C02103AXOREDX,EDX
0C02103CREPECMPSB
0C02103EJNZNEAR0C0EF608不等则跳,与其它值比较
0C021044MOVAL,[EBX+02]
0C021047NOTEAX
0C021049TESTAL,01
0C02104BJNZ0C021096是加密的则跳
0C02104DMOVESI,01
0C021052MOVBYTE[0C30D2FC],00
0C021059MOVZXCX,[EBX+04]
0C02105EMOVZXAX,[EBX+03]
0C021063SHLECX,08
0C021066ADDEAX,ECX
0C021068MOVECX,[0C2F24C4]
0C02106EANDEAX,FFFF
0C021073CMPEAX,ECX比较文件的版本
0C021075JNZNEAR0C0EF5E8
0C02107BMOVECX,EBX
0C02107DCALL0C0210C6
0C021082CMPAX,[EBX+27]
0C021086JNZNEAR0C0EF5FB
0C02108CMOVEAX,ESI
0C02108EPOPEDI
0C02108FPOPESI
0C021090POPEBP
0C021091POPEBX
0C021092POPECX
0C021093RET0C
0C021096MOVECX,EBX
0C021098CALL0C0A863D解密部分0
0C02109DMOVECX,EBX
0C02109FCALL0C0A8727解密部分1
0C0210A4MOVESI,[ESP+1C]
0C0210A8MOVECX,[ESI]
0C0210AACALL0C005392解密部分2
0C0210AFMOVECX,EBX
0C0210B1CALL0C0A879D解密部分3
0C0210B6MOV[ESI],EAX
0C0210B8MOVBYTE[0C30D2FC],01
0C0210BFMOVESI,02
0C0210C4JMPSHORT0C021059
0C0A863DSUBESP,BYTE+10
0C0A8640MOVAL,[ECX+02]
0C0A8643PUSHEBX
0C0A8644NOTEAX
0C0A8646SHREAX,04
0C0A8649MOVBX,[ECX+25]25-26位解密的密钥
0C0A864DANDEAX,BYTE+01
0C0A8650MOV[ESP+10],EAX
0C0A8654LEAEAX,[ECX+25]
0C0A8657PUSHEBP
0C0A8658PUSHESI
0C0A8659XORESI,ESI
0C0A865BANDEBX,FFFF
0C0A8661PUSHEDI
0C0A8662MOV[ESP+14],ECX
0C0A8666MOV[ESP+18],EAX
0C0A866AMOV[0C3171EE],SI
0C0A8671MOV[ESP+10],EBX
0C0A8675MOVEBP,0F
0C0A867AMOVEAX,ESI
0C0A867CCDQ
0C0A867DXOREAX,EDX
0C0A867FSUBEAX,EDX
0C0A8681ANDEAX,BYTE+07
0C0A8684XOREAX,EDX
0C0A8686MOVEDI,EAX
0C0A8688MOVAL,[ESI+ECX+15]
0C0A868CSUBEDI,EDX
0C0A868EMOVEDX,01
0C0A8693MOVECX,EDI
0C0A8695SHLEDX,CL
0C0A8697MOVECX,EBP
0C0A8699ANDDL,AL
0C0A869BNEGDL
0C0A869DSBBEDX,EDX
0C0A869FNEGEDX
0C0A86A1SHLEDX,CL
0C0A86A3MOVECX,ESI
0C0A86A5OR[0C3171EE],DX计算的key1,以后还要用到
0C0A86ACMOVEDX,01
0C0A86B1SHLEDX,CL
0C0A86B3MOVECX,EDI
0C0A86B5ANDEDX,EBX
0C0A86B7MOVBL,01
0C0A86B9NEGEDX
0C0A86BBSBBEDX,EDX
0C0A86BDSHLBL,CL
0C0A86BFNEGEDX
0C0A86C1SHLDL,CL
0C0A86C3MOVECX,[ESP+14]
0C0A86C7NOTBL
0C0A86C9ANDBL,AL
0C0A86CBORDL,BL
0C0A86CDMOV[ESI+ECX+15],DL
0C0A86D1INCESI
0C0A86D2DECEBP
0C0A86D3CMPEBP,BYTE-01
0C0A86D6JNG0C0A86DE
0C0A86D8MOVEBX,[ESP+10]
0C0A86DCJMPSHORT0C0A867A
0C0A86DEMOVEDI,[ESP+18]
0C0A86E2LEAEAX,[ECX+03]
0C0A86E5CMPEAX,EDI
0C0A86E7MOVDL,FE
0C0A86E9JNC0C0A871F
0C0A86EBMOVESI,[ESP+1C]
0C0A86EFMOVCX,[0C3171EE]
0C0A86F6MOVBL,[EAX]
0C0A86F8XORDL,CL
0C0A86FAXORBL,DL
0C0A86FCTESTESI,ESI
0C0A86FEMOV[EAX],BL
0C0A8700MOVDL,BL
0C0A8702JZNEAR0C0D34C6
0C0A8708IMULCX,CX,273D正常为184d
0C0A870DADDECX,236D正常为347d
0C0A8713INCEAX
0C0A8714CMPEAX,EDI
0C0A8716JC0C0A86F6
0C0A8718MOV[0C3171EE],CX
0C0A871FPOPEDI
0C0A8720POPESI
0C0A8721POPEBP
0C0A8722POPEBX
0C0A8723ADDESP,BYTE+10
0C0A8726RET
其他几处call中也有改动,这里就不细说了,因为这部分代码很短写个解密程序处理最为方便,处理前首先用hexworkshop查找c4c5ee,将从这开始到最后的代码存成一个文件,处理完后将app文件中的c4c5全部改为fef2,注意这时文件的checksum值会变动,运行时会报告不是vfp的对象文件,动态跟踪一下,在上面第一段代码ret之后就是chexksum的比较,按正确的改过来就可以了.
5vfpexenc内存加密
vfpexenc的加密方式比较特殊,它把动态解出的加密app文件放在内存中而不是放在一个文件里,但这对解密者没有什么不同,难度是vfpexenc在代码中增加了anti-debug代码,发现有跟踪立即停止运行,报告”文件无法打开”,结束。
可是幸运的是,加密的vfp程序中并没有采用vfpexenc中的seh、sidt判断int1的技术,而只是简单地判断内存进程标题名,这种厚己薄彼的做法给破解者带来了极大的方便。
先看看程序是如何反跟踪的(vfpexenc3.7)
0041994APUSHDWORDFF
0041994FPUSHEDI
00419950PUSHEBX
00419951CALL`USER32!
GetClassNameA`
00419956TESTEAX,EAX
00419958JNG004199BC
0041995ALEAEDX,[EBP+FFFFFEF8]
00419960MOVEAX,EDI
00419962CALL00407E90
00419967MOVEAX,[EBP+FFFFFEF8]
0041996DLEAEDX,[EBP-04]
00419970CALL00407684
00419975MOVEAX,[EBP-04]
00419978MOVEDX,00419A70edx是要判断的文件名
0041997DCALL00404620
00419982JZ004199B1相等就结束了
00419984MOVEAX,[EBP-04]
00419987MOVEDX,00419A80比较第二个
0041998CCALL00404620
00419991JZ004199B1
00419993MOVEAX,[EBP-04]
00419996MOVEDX,00419A98比较第3个
0041999BCALL00404620
004199A0JZ004199B1
004199A2MOVEAX,[EBP-04]
004199A5MOVEDX,00419AA8比较第4个
004199AACALL00404620
004