找回密码
 注册
搜索
热搜: 回贴

超星PDG转换(10千字),超星PDG,逆向工程技术

2010-1-30 18:39| 发布者: admin| 查看: 525| 评论: 0|原作者: 韩菱纱


超星PDG转换(10千字),超星PDG,逆向工程技术
2008年06月28日 星期六 下午 07:56
======================================

“超星读书卡”持卡用户可以通过Internet下载超星数字图书馆中的数字图书。 令很多用户困扰的是在一台机器上下载的文件,在另一台机器上无法直接阅读。
虽然可以通过获取离线注册码的方式解决,但总感觉不尽方便,能否妥善解决?
也许我们注意到在线阅读时是不分那台机器的,可以想象其PDG文件在从网上传
到机器内时是不具备机器识别特征的,这些文件是下载到本地时在本地加密后存
盘的。
因此我们有可能在分析出其本地加密算法,然后推演出其逆算法,将其还原
成原始文件,那么就可以实现自由的离线阅读了。
经过算法分析,证明此方法是可行的,并做出这个demo版的小工具:
1. 此工具暂没有批量转换功能,一次只能转换一个选定文件
2. 我只做了不全面的简单测试,不一定适用于所有的PDG文件
3. 我用的是SSReader3.6及以前版下载的PDG文件,通过测试
4. 现在SSReader3.7的加密方式已经改变,肯定不支持,有待以后分析
======================================
以下论述是我跟踪分析的大致结果,表述不是很精确,有些是猜测

所有分析是基于3.6版的,新版的格式可能会增加内容或有所改变,

我的分析是针对于两种主要类型(格式)的,其实也是目前绝大部分

图书所采用的类型,一种是我们在线阅览的那种pdgtype=02h

另一种是下载存储到本地硬盘文件的那种pdgtype=10h

因此以下描述的结构只能保证对这两种文件有效,其它类型的还需

进一步的分析验证.



==========================================================================================

1. PDG文件的大致结构:



PDG2_file STRUCT

HH_header<>

optional header<>

PDG_data<>

PDG2_file ENDS



HH_header STRUCT

dw 4848h ;超星文件特征标志

db 02h ;PDG_VERSION=2

db 00h ;我见到的PDG2这里都是0,就算默认吧

dd ? ;不知道,对我们似乎没有价值

dd offset_optional_header ;optional_header在文件中的偏移地址,应该等于0Ch吧

HH_header ENDS



optional_header STRUCT

db 80h,00h,00h ;没什么好说的,算是标志吧

db pdgtype ;文档类型,我只分析02h和10h两种类型

dw x_pix ;扫描图像的横向参数

dw y_pix ;扫描图像的纵向参数

db 01h,00h,00h,00h ;按默认算吧

dd offset_PDG_data ;扫描图像数据在文件中的偏移地址,大概都是8Ch吧

dd size_PDG_data ;扫描图像数据的字节数

dd 8 dup (?) ;作用可能不大,把它们添上0不影响页面的显示

key_data<>

db 1Ch dup (?) ;作用可能不大,把它们添上0不影响页面的显示

optional_header ENDS



key_data STRUCT

db 1Eh dup (?) ;这里有时是一个有关超星公司字符信息,有时为空(全0)

dw ? ;我不清楚什么含义

db 8 dup (?) ;可能有几处默认是0

dd SS_user_key ;重要的数据,可用于解码还原x_pix和y_pix

dd ? ;

key_data ENDS

==========================================================================================

2. 我所想象的图书阅览管理过程(基于简单的分析,未必准确,仅供参考)

超星图书服务器上所存储的图书是扫描生成的(废话,大家都知道),是按pdgtype=02h存储的,

文件结构与上述结构相符,单其扫描数据PDG_data是经过加密的,加密过程如下:

30h字节长的key_data经过md5运算得到128位即16字节的数据,此16字节的数据作为密钥,采用

一种分组加密算法以16字节为单位进行加密运算,直到数据结束,此分组加密算法我根据手头的不多

的密码学算法比较,我没有识别出来,我暂且称之为encode_sub,我将它放在后面了,大家有兴趣的可

以帮忙看一下,有知道可以的告诉我,万分感谢.

当我们在线阅览时,ssreader.exe中的相对应decode_sub将数据解码后,就可以显示出来了.



在下载到本地硬盘时,文件存储成pdgtype=10h类型的了,PDG_data扫描数据是用解码后的原始

数据存储的,但它把optional_header中部分数据加密了,加密过程如下:

跟据每台机器的硬盘C:分区的卷序列号和空间大小对应此机器的SS机器码,由SS机器码可以算

出一个word值,暂时称为SS_w,这段算法我没去分析,对我们用处也不大.在下载存盘时还需要一个随

机word值RANDOM_w,RANDOM_w实际就作为SS_user_key的高16位,由SS_w和RANDOM_w再算出一个word

值作为SS_user_key的低16位,因其算法可逆,所以可以用SS_user_key还原出原来的SS_w,这也是原程

序用来检测当前硬盘的SS_w和下载文件的SS_w是否一致的方法,不一致则提示你用户不对不是无法阅

读.

接下来用SS_user_key(用SS_w和RANDOM_w算法稍变也可以)算出两个word值,分别去减x_pix和

y_pix,最后把pdgtype添上10h.这样与我们有用的处理就算结束了,存盘后就可以了.

==========================================================================================

3. 我们需要做的工作

我们只要把pdgtype=10h的文件转变成pdgtype=02h的文件,就可以实现不受硬盘的限制脱机自由

阅读了.过程大致这样吧,大家也应该可以想到了,我用语言描述很费尽的,因此这里用汇编代码描述吧:



下面这段算法在pdg2.dll可以找到,我贴的稍有调整,并去掉了SS_w的检测



mov ebp,SS_user_key

shr eax, 10h

xor edx, edx

mov esi,1FFh

div esi

mov ecx, edx

mov eax,ebp

shr eax,10h

xor edx, edx

mov esi,0DBh

div esi

imul ecx, edx

lea edx, dword ptr [ecx-000050EEh]

mov ebx, ebp

sub ebx, edx

and ebx, 0000FFFFh

shr ebp, 10h

mov eax, ebx

xor edx, edx

mov ecx, 000003FBh

mov edi, 00000083h

div ecx

imul ebx, ebp

mov eax, ebp

mov ecx, edx

xor edx, edx

div edi

mov eax, edx

sub eax, ebx

sub eax, ecx

sub ecx, ebx

sub ecx, edx

add x_pix,ax ;还原x_pix

add y_pix,cx ;还原y_pix



为了看起来干净利索,我们把key_data区域都清0,不这样也没问题,不过有几处可能不要乱数

lea edi,key_data

mov ecx,30h

xor eax,eax

rep stosb

然后对30h字节长度的key_data进行一次md5,md5我就不贴在这里了,太费篇幅了,大家都可以

找到,我们下面要用到这128位(16字节)的结果作为分组加密算法的密钥,实际上我们的key_data

已经是清0的了,结果也是固定不变的了,也可以直接用现成的结果.我假设结果存在key_128处.



为转成pdgtype=02h文件,PDG_data要用encode_sub加密



mov edi, size_PDG_data ;数据长度

cmp edi, 10h

jl data_encode_end

mov ebx, key_128

mov esi, offset PDG_data

shr edi, 4

@@: push ebx ;密钥指针

push esi ;数据指针,加密结果也存储在这里

call sub_encode ;分组算法,每次加密10h字节

add esp, 8

add esi, 10h

dec edi

jnz @B

data_encode_end: ;处理结束



;下面是完整的分组加密算法,在********.exe中可以找到

;其中注释是我分析时加的,不尽准确,本想删去,后来一想算了,献丑也罢,只当交流了

;开始看时感觉上有点象RC5族算法,但越看越不象,资料有限,还是确认不了,望高手指教



encode_sub proc near

var_2C = dword ptr -2Ch

var_28 = dword ptr -28h

var_24 = dword ptr -24h

var_20 = dword ptr -20h

var_1C = dword ptr -1Ch

var_18 = dword ptr -18h

var_14 = dword ptr -14h

var_10 = dword ptr -10h

var_C = dword ptr -0Ch

var_8 = dword ptr -8

var_4 = dword ptr -4

arg_0 = dword ptr 8 ;pData

arg_4 = dword ptr 0Ch ;pKey

push ebp

mov ebp, esp

add esp, 0FFFFFFD4h

mov eax, [ebp arg_0] ;pData

mov edx, [eax] ;A

mov [ebp var_4], edx ;sa=A

mov edx, [eax 4] ;B

mov [ebp var_8], edx ;sb=B

mov edx, [eax 8] ;C

mov [ebp var_C], edx ;sc=C

mov edx, [eax 0Ch] ;D

mov [ebp var_10], edx ;sd=D

mov eax, [ebp arg_4] ;pKey

mov edx, [eax] ;ka

mov [ebp var_14], edx ;ka

mov edx, [eax 4] ;kb

mov [ebp var_18], edx ;kb

mov edx, [eax 8] ;kc

mov [ebp var_1C], edx ;kc

mov edx, [eax 0Ch] ;kd

mov [ebp var_20], edx ;kd

xor edx, edx ;c1

mov [ebp var_24], edx ;c1

mov [ebp var_28], 9E3779B9h ;c0

mov [ebp var_2C], 10h ;r

@@: mov ecx, [ebp var_28] ;c0

add [ebp var_24], ecx ;c1 c0

mov eax, [ebp var_8] ;sb

shl eax, 4 ;sb<<4

add eax, [ebp var_14] ;sb<<4 ka

mov edx, [ebp var_8] ;sb

add edx, [ebp var_24] ;sb c1

xor eax, edx ;(sb<<4 ka) xor (sb c1)

mov ecx, [ebp var_8] ;sb

shr ecx, 5 ;sb>>5

add ecx, [ebp var_18] ;sb>>5 kb

xor eax, ecx ;(sb<<4 ka) xor (sb c1) xor (sb>>5 kb)

add [ebp var_4], eax ;sa=sa [(sb<<4 ka) xor (sb c1) xor (sb>>5 kb)]

mov eax, [ebp var_C] ;sc

shl eax, 4 ;sc<<4

add eax, [ebp var_1C] ;sc<<4 kc

mov edx, [ebp var_C] ;sc

add edx, [ebp var_24] ;sc c1

xor eax, edx ;(sc<<4 kc) xor (sc c1)

mov ecx, [ebp var_C] ;sc

shr ecx, 5 ;sc>>5

add ecx, [ebp var_20] ;sc>>5 kd

xor eax, ecx ;(sc<<4 kc) xor (sc c1) xor (sc>>5 kd)

add [ebp var_8], eax ;sb=sb [(sc<<4 kc) xor (sc c1) xor (sc>>5 kd)]

mov eax, [ebp var_10] ;sd

shl eax, 4 ;sd<<4

add eax, [ebp var_14] ;sd<<4 ka

mov edx, [ebp var_10] ;sd

add edx, [ebp var_24] ;sd c1

xor eax, edx ;(sd<<4 ka) xor (sd c1)

mov ecx, [ebp var_10] ;sd

shr ecx, 5 ;sd>>5

add ecx, [ebp var_20] ;sd>>5 kd

xor eax, ecx ;(sd<<4 ka) xor (sd c1) xor (sd>>5 kd)

add [ebp var_C], eax ;sc=sc [(sd<<4 ka) xor (sd c1) xor (sd>>5 kd)]

mov eax, [ebp var_4] ;sa

shl eax, 4 ;sa<<4

add eax, [ebp var_1C] ;sa<<4 kc

mov edx, [ebp var_4] ;sa

add edx, [ebp var_24] ;sa c1

xor eax, edx ;(sa<<4 kc) xor (sa c1)

mov ecx, [ebp var_4] ;sa

shr ecx, 5 ;sa>>5

add ecx, [ebp var_18] ;sa>>5 kb

xor eax, ecx ;(sa<<4 kc) xor (sa c1) xor (sa>>5 kb)

add [ebp var_10], eax ;sd=sd [(sa<<4 kc) xor (sa c1) xor (sa>>5 kb)]

mov eax, [ebp var_2C] ;r

dec eax ;r-1

mov [ebp var_2C], eax ;r=r-1

jnz @B

mov eax, [ebp arg_0] ;pData

mov edx, [ebp var_4] ;sa

mov [eax], edx ;A=sa

mov edx, [ebp var_8] ;sb

mov [eax 4], edx ;B=sb

mov edx, [ebp var_C] ;sc

mov [eax 8], edx ;C=sc

mov edx, [ebp var_10] ;sd

mov [eax 0Ch], edx ;D=sd

mov esp, ebp

pop ebp

retn

encode_sub endp

==========================================================================================

后记:文章我是最懒得写的,写起来真是辛苦,花了数个小时,总感觉表述的不是很满意,无奈已经尽力了

分析水平有限,错误之处在所难免,唯恐误人子弟,读者朋友们见谅了,希望大家能提出自己的主见.

==========================================================================================

heXer/iPB

2002.10.26


最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-29 09:19 , Processed in 0.309002 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部