-
-
[原创]Dr.com3.46客户端密码文件解密过程
-
发表于: 2008-4-11 13:26 19824
-
【文章标题】: Dr.com3.46客户端密码文件解密过程
【文章作者】: amour
【作者邮箱】: hongqy@cqu.edu.cn
【作者QQ号】: 59232271
【软件名称】: Dr.comV3.46
【软件大小】: 120K
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 无
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: IDA5.2+OD1.10+VC6
【操作平台】: xp sp2
【软件介绍】: 城市热点的Dr.COM校园用户认证客户端
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
前言
在看雪潜水好几年了,看着新人辈出,自己却依然原地踏步,实在汗颜......当前的大牛们早已将 ring3玩于鼓掌之间,纷纷遁入ring0,俺等菜菜还在ring3徘徊......看看自己的id,居然一个精华也没有,实在汗颜哪!希望早如实现这个梦想
算了废话不多说,进入正题吧.
问题是怎么开始的呢?Dr.com不用介绍了吧,高校一般都用这个做上网解决方案。而我们用户在使用客户端时一般都选择保存密码,可是时间长了,难免会忘掉,这时候只好求助网络中心了,再去找回密码,这可是个体力活,因为我们一般离网络中心都有几里地远=_=||,现在想想能不能自己解决这个问题呢?
登陆的时候,发现这么个对话框:然后点击登陆,就ok了。显然计算机是知道这个密码的。看见星号,顿时就想到星号查看器,密码明文等一连串让人翩翩遐思的东西......那么内存中果然 有这个明文么?我们来打开winhex,用它的内存工具来找密码是再顺理成章不过的事情了,自己的密码自 己心里有数,我们来搜....
注意,搜到2处。我们再用OD来找,用超级字符串参考插件,哇,好多!不过这些都是对winhex中那 两个地址的引用而已。看来果然是有密码明文的问题呀!那么我们以后要找密码就可以随身带着OD或 winhex之类的不就可以了么?不过很不专业的样子,我们来找点乐子,自己写个解密器吧!
目标有了,就要开始行动,首先,让我们整理一下思路吧!如果我们选择了保存密码,那么应用程序 一定将密码保存成文件放在硬盘上什么地方了,而且是加密后存放的(如果是明文的话,我也不用打这么 多字了)。每次登陆的时候,程序将检查是否存在保存的密码文件,有的话就将其解密后读入到内存中, 否则就请你自己输入。那我们的第一步就是找到存放密码的文件,找到解密过程,最后写出一个自己的解 密程序来。程序会怎么做呢?一定是打开文件,读文件,解密。有了思路我们行动吧!
follow me!第一步,先查主程序ishare_user.exe无加壳,Vc++6.0,呵呵,我们省了不少力气,要是加了个猛壳,就惨了!打开心爱的OD,加载,来到程序入口处,这里我们用超级字符串或是winhex都是找不到密码的,因为密码文件尚未载入。还记得上面的那两个地址么,我们在数据区ctrl+g来到0041b1c4,这里还是一片荒芜,空空如也,但是不久这里就会出现我们的密码明文,所以好好注意这里,尤其是程序在这里写入密码的时候。在命令行插件中下断bp CreateFileW,F9跑起来。我们会中断在好几个地方,都是打开文件的操作,但是打开后密码都没有出现,我们继续
F9,这时一定要注意力高度集中,不然就会错过 好戏哦!我曾经非常重视这个文件login2.dat,你看看名字都这么拉风,打开它还能看见用户名,但是, 打开后却没有密码出现,我们继续,下一个要打开的是micsystem.bin注意,,F9后密码出现了!在堆栈里我们看 到了返回的地址0040DF44,记下来。我们来硬盘上找找这个文件,打开一看,一堆乱码啊!还好不算长。难道 这就是传说中的密文?下面我们要更加精确的定位这个文件操作,因为我们要找的解密过程一定在此地址 后不远的地方,ctrl+F2重新开始程序,我们先禁掉刚才的断点,ctrl+g来到40DF44处,一步一步小心的 往下走,为了便于观察,我们需要将OD的几个窗口调的合适一点,特别是数据区要定位到0041b1c4的位置 ,以便随时查看密码存放区的变换,注意这就是动态跟的好处哇!这里开始读文件了,我们可以查看一下 ,果然,将那堆乱码读出来了,保持高度警觉,我们继续走,将这个乱码串压栈了!然后一个call,我们 先F8,看看返回了什么?密码明文!(想到一个笑话,有一台机器,你赶着猪进去,另一头就出来一堆香 肠)bingo!我们找到了!显然这个call就是那个机器,我们下面要做的就是好好研究这个机器的构造,然 后自己做一台出来。
下面来做静态分析,做这个当推我们的IDA老大。打开IDA,开始等吧,虽然IDA老大分析有点慢,但 那效果可不是盖的!一杯茶的功夫不到,分析完成了,我们按G,输入004011C0,呵呵,这就是那个机器的 内部了,好好研究吧!当然我们最好同时打开OD,和IDA同步跟,这样你可以随时对那些枯燥的变量名有 鲜明的认识。IDA的动态跟踪在我这里会出错,不知道是否有bug。在这个函数头我们可以按N,将其重命 名为passRead,这样的话,IDA会在全局认识这个函数,对分析整个程序的流程会很有帮助(我其实还在分 析其他的部分......后话暂时不提)。接下来是个耐心的活了,就看你的汇编功底了,手边一本汇编教程 ,打开MSDN,碰见不懂的函数就查,打开网页准备google,再放点music,最好再泡杯茶,crack是个要能 坐得住的活啊!分析整个函数我花了1天时间,没办法,人笨,就得多熬时间了。不像大牛们,看汇编代 码跟看报纸喝饮料一样,不知道何年何月才能到那个境界!
当然如果你不是菜鸟的话,你很可能直接就开着asm,vc,delphi之类的编译器写代码了。
下面的分析来自IDA。
.text:004011C0 passRead proc near ; CODE XREF: drComProc+415.p
.text:004011C0 ; drComProc+4ED.p ...
.text:004011C0
.text:004011C0 code = dword ptr -74h
.text:004011C0 var_70 = dword ptr -70h
.text:004011C0 var_6C = dword ptr -6Ch
.text:004011C0 var_68 = dword ptr -68h
.text:004011C0 var_64 = byte ptr -64h
.text:004011C0 binMiyao = dword ptr 4
.text:004011C0
.text:004011C0 sub esp, 74h
.text:004011C3 push ebp ; 64H
.text:004011C4 push esi ; 104H
.text:004011C5 push edi ; EDI=0012EA10, (ASCII "C:\WINDOWS\system32\micsystem.bin")
.text:004011C5 ;
.text:004011C6 mov ecx, 200h
.text:004011CB xor eax, eax
.text:004011CD mov edi, offset unk_41B1C4
.text:004011D2 rep stosd ; 设置一个512字节的缓冲区
.text:004011D4 push offset aTblrefreshcurm ; "TblRefreshCurMonthServiceUse" ;这是个种子字符串。是个常量。
.text:004011D9 call miyaoTrans ;00401390,这个函数要看看,我把它命名 为miyaoTrans,个人习惯而已。虽然暂时返回一个常量,但是也免得以后种子变了。返回的值在eax中, 这个call我们下面有分析。
.text:004011DE mov edi, [esp+84h+binMiyao] ; micsystem.bin中的内容,你可 以将它命名一下方便后面分析。这是个数组,编程的时候就很方便了。
.text:004011DE ; (ASCII "Oq/Ge~:TFo*")
.text:004011DE ; 这就是那个加密的乱码字符串了,你就 不要费心来找我的密码了哦,呵呵。
.text:004011DE ;
.text:004011E5 mov ebp, eax ; ebp中保存返回的miyao值
.text:004011E7 or ecx, 0FFFFFFFFh
.text:004011EA xor eax, eax
.text:004011EC add esp, 4 ; 弹栈去掉长密钥
.text:004011EF mov esi, eax ; esi=0
.text:004011F1 repne scasb
.text:004011F3 not ecx
.text:004011F5 dec ecx ; ecx=strlen((ASCII "Oq/Ge~:TFo*")=11
.text:004011F6 dec ecx ; ecx=strlen-1
.text:004011F7 mov [esp+80h+var_68], ecx
.text:004011FB js loc_401299
.text:00401201 mov eax, ebp ; eax=miyaotrans()
.text:00401203 xor edi, edi ; edi=0
.text:00401205 neg eax ; eax=eax取反
.text:00401207 push ebx
.text:00401208 mov [esp+84h+code], offset unk_41B1C4 ;出现要写的明文地址 了。命名为code。
.text:00401210 mov [esp+84h+var_6C], eax
.text:00401214
.text:00401214 loc_401214: ; CODE XREF: passRead+CA.j
.text:00401214 mov eax, [esp+84h+binMiyao]
.text:0040121B mov al, [esi+eax] ; binMiyao[i]这里是个典型的数组操作, 这个esi在编程时不妨设为int i
.text:0040121E movsx ebx, al ; 将密文的一个字节进行符号扩展并放入 ebx
.text:00401221 cmp ebx, 20h ; 比较该字节是否在0x20h到0x7Eh之间,不 在这个区间就跳过比较下一个字节,这个区间的才是可用的密码。
.text:00401224 mov [esp+esi+84h+var_64], al ; 这个赋值没发现有啥用
.text:00401228 jl short loc_401285 ;
.text:00401228 ;
.text:0040122A cmp ebx, 7Eh
.text:0040122D jg short loc_401285 ;
.text:0040122D ;
.text:0040122F add edi, ebp ; edi=edi+ebp,注意看第一次进入此循环 时的ebp值,往上看,原来是key
.text:00401231 mov ecx, 188B9h ; 这里每次都加,不妨设edi为sum
.text:00401236 mov eax, edi
.text:00401238 inc esi ; i++
.text:00401239 cdq ; 将eax符号扩展为32位,准备做除法运算
.text:0040123A idiv ecx ; eax=sum/0x188B9h
.text:0040123A ; edx=sum%0x188B9h
.text:0040123C mov [esp+84h+var_70], edx ; miyaotrans返回值
.text:0040123C ;
.text:00401240 fild [esp+84h+var_70] ; 将sum%0x188B9h的值装入ST(0),准备做 浮点运算
.text:00401244 fmul ds:dbl_411318 ; 好懒,这里是个常数
.text:00401244 ;
不妨设DOUBLE d318 = 9.946586828729721e-6;
.text:0040124A fmul ds:dbl_411310 ; 这里也是个常数
.text:0040124A ; 设DOUBLE d310 = 9.6e1 ;
.text:00401250 call _ftol ; 这个函数MSDN中没查到,好在很好猜, 因为执行完就看见eax返回一个值,但是编程的时候会有点麻烦,后话。
.text:00401250 ;
.text:00401255 mov edx, eax ; edx=浮点的返回值
.text:00401257 mov eax, ebx ; eax=binMiyao[i]
.text:00401259 sub eax, edx ; eax=binMiyao[i]-pedx
.text:0040125B mov ecx, 5Fh
.text:00401260 sub eax, 20h ; eax=binMiyao[i]-pedx-0x20
.text:00401263 cdq ; 再准备做除法
.text:00401264 idiv ecx ; edx=(binMiyao[i]-pedx-0x20)%0x5F
.text:00401266 test edx, edx ; edx大于等于0则继续,否则edx+0x5F
.text:00401268 jge short loc_40126C ;
.text:00401268 ; 这里的var_6c的赋值在上面,是返回key 的取反
.text:0040126A add edx, ecx
.text:0040126C
.text:0040126C loc_40126C: ; CODE XREF: passRead+A8.j
.text:0040126C mov eax, [esp+84h+var_6C] ;
.text:0040126C ; 这里的var_6c的赋值在上面,是返回key 的取反
.text:00401270 mov ecx, [esp+84h+var_68] ; 这里的var_68也是在上面的位置 赋值,是len-1
.text:00401274 add edi, eax ; sum+=-key;看上去好别扭啊,其实就是 sum=sum-key
.text:00401276 mov eax, [esp+84h+code] ; 这里出现我们要写的堆栈地址了,显 然准备出口成品了
.text:0040127A add dl, 20h ; edx的低16位+32,显然可以显示的ASCII 是从32开始的
.text:0040127D dec esi ; i--
.text:0040127E mov [eax], dl ; 这里code[i]=dl
.text:00401280 inc eax
.text:00401281 mov [esp+84h+code], eax ; 写完了就将指针指向下一位
.text:00401285
.text:00401285 loc_401285: ; CODE XREF: passRead+68.j
.text:00401285 ; passRead+6D.j
.text:00401285 inc esi ;
.text:00401285 ; i++
.text:00401286 add edi, ebp ; sum+=key
.text:00401288 cmp esi, ecx ; 比较是否解密完毕
.text:0040128A jle short loc_401214 ; 没解完继续
.text:0040128C pop ebx
.text:0040128D pop edi
.text:0040128E pop esi
.text:0040128F mov eax, offset unk_41B1C4 ; 将这个地址放入eax返回
.text:00401294 pop ebp
.text:00401295 add esp, 74h
.text:00401298 retn
.text:00401299 ; ---------------------------------------------------------------------------
我们再来看看这个401390吧。
.text:00401390 ; =============== S U B R O U T I N E =======================================
.text:00401390
.text:00401390
.text:00401390 miyaoTrans proc near ; CODE XREF: passRead+19.p
.text:00401390 ; passTrans+18.p
.text:00401390
.text:00401390 var_8 = dword ptr -8
.text:00401390 var_4 = dword ptr -4
.text:00401390 string_miyao = dword ptr 4
.text:00401390
.text:00401390 sub esp, 8
.text:00401393 push ebx
.text:00401394 push esi
.text:00401395 push edi ; pass
.text:00401395 ; Dr.com用户认证
.text:00401396 mov edi, [esp+14h+string_miyao] ;
.text:00401396 ; ASCII "TblRefreshCurMonthServiceUse"
.text:00401396 ;
.text:00401396 ; 这个串是个常量
.text:0040139A or ecx, 0FFFFFFFFh ; 看见这个你就该想起strlen了
.text:0040139D xor eax, eax ; eax=0
.text:0040139F xor ebx, ebx ; ebx=0
.text:004013A1 xor esi, esi ; esi=0
.text:004013A3 repne scasb ; 求出string_miyao串长度
.text:004013A5 not ecx
.text:004013A7 dec ecx ; ecx=strlen(string_miyao),作为下面循 环的次数计数器
.text:004013A8 xor edi, edi ; int v_esi=0
.text:004013AA cmp ecx, ebx ; strlen(string_miyao)要大于 0
.text:004013AC mov [esp+14h+var_8], ebx ; int v8=0
.text:004013B0 mov [esp+14h+var_4], ecx ; int v4=strlen (string_miyao)
.text:004013B4 jle short loc_40140C ; eax=var_8
.text:004013B4 ;
.text:004013B6 push ebp ; ebp=64H
.text:004013B6 ; 这里的值需要保存,为其他函数用的, 这里做解密我们不用管了
.text:004013B7
.text:004013B7 loc_4013B7: ; CODE XREF: miyaoTrans+79.j
.text:004013B7 mov eax, [esp+18h+string_miyao] ; 这个要做循环strlen (string_miyao)次
.text:004013B7 ;
.text:004013B7 ;
.text:004013B7 ; eax为string_miyao数组的首地址
.text:004013BB push esi ; 保存esi的值
.text:004013BB ; 首次做这个循环是esi=0
.text:004013BC movsx ebp, byte ptr [edi+eax] ;
.text:004013BC ; 符号扩展ebp为数组中第esi位的值
.text:004013BC ; ebp=string_miyao[i]
.text:004013C0 call mi_2 ; 这个call的地址是401430
.text:004013C0 ; 这个call很简单,跟进去看看就知道了 ,其实就是求2的esi次方。一会也分析一下。我将2 的esi次方记为2**esi。
.text:004013C5 imul eax, ebp ; eax=2**esi*string_miyao[i]
.text:004013C8 mov ecx, [esp+1Ch+var_8] ;
.text:004013C8 ; ecx=var_8
.text:004013CC push ebx ; 保存ebx
.text:004013CC ; 首次运算时ebx=0
.text:004013CD xor ecx, eax ; ecx=var_8 xor 2**esi*string_miyao [i]
.text:004013CD ; 注意:这是第一次异或
.text:004013CF mov [esp+20h+var_8], ecx ;
.text:004013CF ; var_8=var_8 xor 2**esi*string_miyao[i]
.text:004013CF ; 本次异或的结果被保存到var_8中
.text:004013D3 call mi_2 ; eax=2**ebx
.text:004013D3 ; 再取2**ebx,注意这次是取2**ebx
.text:004013D8 imul eax, ebp ;
.text:004013D8 ; eax=2**ebx*string_miyao[i]
.text:004013DB mov edx, [esp+20h+var_8] ;
.text:004013DB ; edx=var_8
.text:004013DF mov ecx, 13h ; ecx=19
.text:004013E4 xor edx, eax ; 再异或一次
.text:004013E6 lea eax, [esi+7] ; eax=esi+7
.text:004013E6 ;
.text:004013E9 mov [esp+20h+var_8], edx ;
.text:004013E9 ; var_8=var_8 xor 2**ebx*string_miyao[i]
.text:004013E9 ; 将两次异或的结果保存
.text:004013ED add esp, 8 ; 弹出堆栈,清掉ebx和esi
.text:004013F0 cdq ; 扩展eax准备除法
.text:004013F1 idiv ecx ; eax=(esi+7)/19
.text:004013F1 ; edx=(esi+7)%19
.text:004013F3 lea eax, [ebx+0Dh] ; eax=ebx+13
.text:004013F6 mov ecx, 17h ; ecx=23
.text:004013FB mov esi, edx ; esi=edx=(esi+7)%19
.text:004013FB ; 这个esi在下次运算做幂运算的时候就变 换了
.text:004013FD cdq
.text:004013FE idiv ecx ; edx=(ebx+13)%23
.text:004013FE ;
.text:00401400 mov eax, [esp+18h+var_4] ;
.text:00401400 ; eax=var_4=strlen(string_miyao)
.text:00401404 inc edi ; edi++
.text:00401405 cmp edi, eax ; edi<var_4则继续循环
.text:00401407 mov ebx, edx ; ebx=(ebx+13)%23
.text:00401407 ;
.text:00401409 jl short loc_4013B7 ; 这个要做循环strlen(string_miyao)次
.text:00401409 ;
.text:00401409 ;
.text:00401409 ; eax为string_miyao数组的首地址
.text:0040140B pop ebp
.text:0040140C
.text:0040140C loc_40140C: ; CODE XREF: miyaoTrans+24.j
.text:0040140C mov eax, [esp+14h+var_8] ; eax=var_8
.text:0040140C ; 最后得到一个异或了好多次的值,放入 eax,再处理
.text:00401410 mov ecx, 188B9h ; ecx=0x188B9H
.text:00401415 xor eax, 18901h ; eax=eax xor 0x18901H
.text:0040141A pop edi
.text:0040141B cdq
.text:0040141C idiv ecx ; 发现取余是个很频繁的操作
.text:0040141E pop esi
.text:0040141F pop ebx
.text:00401420 mov eax, edx ; 返回(eax xor 0x18901) % 100537
.text:00401422 add esp, 8
.text:00401425 retn
.text:00401425 miyaoTrans endp
.text:00401425
.text:00401425 ; ---------------------------------------------------------------------------
.text:00401426 align 10h
我们看下这个00401430吧!非常简单的函数。
.text:00401430 ; =============== S U B R O U T I N E =======================================
.text:00401430
.text:00401430 ;
.text:00401430 ; 取出传入的参数
.text:00401430
.text:00401430 mi_2 proc near ; CODE XREF: miyaoTrans+30.p
.text:00401430 ; miyaoTrans+43.p
.text:00401430
.text:00401430 arg_0 = dword ptr 4
.text:00401430
.text:00401430 mov ecx, [esp+arg_0]
.text:00401434 mov eax, 1
.text:00401439 cmp ecx, eax ; 传入的参数是否小于1,是就跳
.text:00401439 ; 否则就做下面的循环
.text:0040143B jl short locret_401442 ; 如果传进来的参数小于1,就返回1 ,否则就返回eax
.text:0040143D
.text:0040143D loc_40143D: ; CODE XREF: mi_2+10.j
.text:0040143D add eax, eax ; eax=eax*2
.text:0040143F dec ecx ; ecx--
.text:00401440 jnz short loc_40143D ; 循环ecx次
.text:00401442
.text:00401442 locret_401442: ; CODE XREF: mi_2+B.j
.text:00401442 retn ; 如果传进来的参数小于1,就返回1,否 则就返回eax
.text:00401442 mi_2 endp
.text:00401442
好了,分析的差不多了,总结一下,程序打开密文后,利用一个miyaoTrans的函数对一个字符串常量做了 个种子key,求取密文的长度后,循环长度次做明文解密。解密就是通过对密文的每位ASCII码做简单的减 一个key的浮点乘法运算后取整的值后再取余(噎死我了),(若为负数则加95),然后将该余数加上32,就得 到明文。
这是核心解密程序段,还是加上比较好,在附件没人看
xTiNtint mi_2(int a1)
{
signed int result;
signed int v2;
v2 = a1;
result = 1;
if ( a1 >= 1 )
{
do
{
result *= 2;
--v2;
}
while ( v2 );
}
return result;
}
//////////////////////////////////////////////////////
//写成函数,是防止以后字符串发生变化。
int miyao(const char *string_miyao)
{
int m,n,key,crypto;
m=n=key=crypto=0;
int length=strlen(string_miyao);
for ( int i=0 ; i < length;i++ )
{
key = string_miyao[i];
crypto ^= key * mi_2(n);
crypto ^= key * mi_2(m);
n = (n + 7) % 19;
m = (m + 13) % 23 ;
}
return (crypto ^ 0x18901) % 100537;
}
//////////////////////////////////////////////////////
//算法很简单,是吧!,原程序是返回一个明文区的指针,
//这里就省事了
/////////////////////////////////////////////////////
int ReadPass(const char *pcode)
{
char code[16]={0};
int i,tmp,dst,sum,key,len,st0,flag;
HINSTANCE LibHandle;
MYPROC _ftol;
i=sum=tmp=st0=flag=0;
DOUBLE d310 = 9.6e1 ;
DOUBLE d318 = 9.946586828729721e-6;
LibHandle=LoadLibrary("msvcrt.dll");
_ftol =(MYPROC)GetProcAddress(LibHandle,"_ftol");
key=miyao("TblRefreshCurMonthServiceUse");//其实这里是个很稳定的整数30137,因为这个字符串是常量.
len=strlen(pcode);
if(len<1)
{
return flag;
}
else
{
do
{
tmp=pcode[i];
if(tmp>=32&&tmp<=0x7E)
{
sum+=key;
st0=sum%0x188B9;
__asm
{
fild st0;
fmul d310;
fmul d318;
call _ftol;
mov dst,eax
}
dst=(tmp-dst-32)%0x5f;
if(dst<0) dst=dst+0x5F;
code[i]=dst+32;
i++;
}
}
while(i<=(len-1));
strcpy(password,code);
flag=1;
return flag;
}
}
程序很简单,各位凑合着看吧。老鸟飘过。不要拿来做坏事,因为这是个客户端,服务端哪里啥都查得到。我也已经发信给Dr.com了。最郁闷的是,我写完了程序后才发现,黑客防线上早就 有人发过类似的文章,惊出一身冷汗,不过作者并没有对解密过程做出分析,只是简单的找出明文。希望 这个问题在Dr.com的下一个版本中得到解决。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年04月10日 18:47:37
本代码由xTiNt自动着色 http://kbadboy.yeah.net
【文章作者】: amour
【作者邮箱】: hongqy@cqu.edu.cn
【作者QQ号】: 59232271
【软件名称】: Dr.comV3.46
【软件大小】: 120K
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 无
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: IDA5.2+OD1.10+VC6
【操作平台】: xp sp2
【软件介绍】: 城市热点的Dr.COM校园用户认证客户端
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
前言
在看雪潜水好几年了,看着新人辈出,自己却依然原地踏步,实在汗颜......当前的大牛们早已将 ring3玩于鼓掌之间,纷纷遁入ring0,俺等菜菜还在ring3徘徊......看看自己的id,居然一个精华也没有,实在汗颜哪!希望早如实现这个梦想
算了废话不多说,进入正题吧.
问题是怎么开始的呢?Dr.com不用介绍了吧,高校一般都用这个做上网解决方案。而我们用户在使用客户端时一般都选择保存密码,可是时间长了,难免会忘掉,这时候只好求助网络中心了,再去找回密码,这可是个体力活,因为我们一般离网络中心都有几里地远=_=||,现在想想能不能自己解决这个问题呢?
登陆的时候,发现这么个对话框:然后点击登陆,就ok了。显然计算机是知道这个密码的。看见星号,顿时就想到星号查看器,密码明文等一连串让人翩翩遐思的东西......那么内存中果然 有这个明文么?我们来打开winhex,用它的内存工具来找密码是再顺理成章不过的事情了,自己的密码自 己心里有数,我们来搜....
注意,搜到2处。我们再用OD来找,用超级字符串参考插件,哇,好多!不过这些都是对winhex中那 两个地址的引用而已。看来果然是有密码明文的问题呀!那么我们以后要找密码就可以随身带着OD或 winhex之类的不就可以了么?不过很不专业的样子,我们来找点乐子,自己写个解密器吧!
目标有了,就要开始行动,首先,让我们整理一下思路吧!如果我们选择了保存密码,那么应用程序 一定将密码保存成文件放在硬盘上什么地方了,而且是加密后存放的(如果是明文的话,我也不用打这么 多字了)。每次登陆的时候,程序将检查是否存在保存的密码文件,有的话就将其解密后读入到内存中, 否则就请你自己输入。那我们的第一步就是找到存放密码的文件,找到解密过程,最后写出一个自己的解 密程序来。程序会怎么做呢?一定是打开文件,读文件,解密。有了思路我们行动吧!
follow me!第一步,先查主程序ishare_user.exe无加壳,Vc++6.0,呵呵,我们省了不少力气,要是加了个猛壳,就惨了!打开心爱的OD,加载,来到程序入口处,这里我们用超级字符串或是winhex都是找不到密码的,因为密码文件尚未载入。还记得上面的那两个地址么,我们在数据区ctrl+g来到0041b1c4,这里还是一片荒芜,空空如也,但是不久这里就会出现我们的密码明文,所以好好注意这里,尤其是程序在这里写入密码的时候。在命令行插件中下断bp CreateFileW,F9跑起来。我们会中断在好几个地方,都是打开文件的操作,但是打开后密码都没有出现,我们继续
F9,这时一定要注意力高度集中,不然就会错过 好戏哦!我曾经非常重视这个文件login2.dat,你看看名字都这么拉风,打开它还能看见用户名,但是, 打开后却没有密码出现,我们继续,下一个要打开的是micsystem.bin注意,,F9后密码出现了!在堆栈里我们看 到了返回的地址0040DF44,记下来。我们来硬盘上找找这个文件,打开一看,一堆乱码啊!还好不算长。难道 这就是传说中的密文?下面我们要更加精确的定位这个文件操作,因为我们要找的解密过程一定在此地址 后不远的地方,ctrl+F2重新开始程序,我们先禁掉刚才的断点,ctrl+g来到40DF44处,一步一步小心的 往下走,为了便于观察,我们需要将OD的几个窗口调的合适一点,特别是数据区要定位到0041b1c4的位置 ,以便随时查看密码存放区的变换,注意这就是动态跟的好处哇!这里开始读文件了,我们可以查看一下 ,果然,将那堆乱码读出来了,保持高度警觉,我们继续走,将这个乱码串压栈了!然后一个call,我们 先F8,看看返回了什么?密码明文!(想到一个笑话,有一台机器,你赶着猪进去,另一头就出来一堆香 肠)bingo!我们找到了!显然这个call就是那个机器,我们下面要做的就是好好研究这个机器的构造,然 后自己做一台出来。
下面来做静态分析,做这个当推我们的IDA老大。打开IDA,开始等吧,虽然IDA老大分析有点慢,但 那效果可不是盖的!一杯茶的功夫不到,分析完成了,我们按G,输入004011C0,呵呵,这就是那个机器的 内部了,好好研究吧!当然我们最好同时打开OD,和IDA同步跟,这样你可以随时对那些枯燥的变量名有 鲜明的认识。IDA的动态跟踪在我这里会出错,不知道是否有bug。在这个函数头我们可以按N,将其重命 名为passRead,这样的话,IDA会在全局认识这个函数,对分析整个程序的流程会很有帮助(我其实还在分 析其他的部分......后话暂时不提)。接下来是个耐心的活了,就看你的汇编功底了,手边一本汇编教程 ,打开MSDN,碰见不懂的函数就查,打开网页准备google,再放点music,最好再泡杯茶,crack是个要能 坐得住的活啊!分析整个函数我花了1天时间,没办法,人笨,就得多熬时间了。不像大牛们,看汇编代 码跟看报纸喝饮料一样,不知道何年何月才能到那个境界!
当然如果你不是菜鸟的话,你很可能直接就开着asm,vc,delphi之类的编译器写代码了。
下面的分析来自IDA。
.text:004011C0 passRead proc near ; CODE XREF: drComProc+415.p
.text:004011C0 ; drComProc+4ED.p ...
.text:004011C0
.text:004011C0 code = dword ptr -74h
.text:004011C0 var_70 = dword ptr -70h
.text:004011C0 var_6C = dword ptr -6Ch
.text:004011C0 var_68 = dword ptr -68h
.text:004011C0 var_64 = byte ptr -64h
.text:004011C0 binMiyao = dword ptr 4
.text:004011C0
.text:004011C0 sub esp, 74h
.text:004011C3 push ebp ; 64H
.text:004011C4 push esi ; 104H
.text:004011C5 push edi ; EDI=0012EA10, (ASCII "C:\WINDOWS\system32\micsystem.bin")
.text:004011C5 ;
.text:004011C6 mov ecx, 200h
.text:004011CB xor eax, eax
.text:004011CD mov edi, offset unk_41B1C4
.text:004011D2 rep stosd ; 设置一个512字节的缓冲区
.text:004011D4 push offset aTblrefreshcurm ; "TblRefreshCurMonthServiceUse" ;这是个种子字符串。是个常量。
.text:004011D9 call miyaoTrans ;00401390,这个函数要看看,我把它命名 为miyaoTrans,个人习惯而已。虽然暂时返回一个常量,但是也免得以后种子变了。返回的值在eax中, 这个call我们下面有分析。
.text:004011DE mov edi, [esp+84h+binMiyao] ; micsystem.bin中的内容,你可 以将它命名一下方便后面分析。这是个数组,编程的时候就很方便了。
.text:004011DE ; (ASCII "Oq/Ge~:TFo*")
.text:004011DE ; 这就是那个加密的乱码字符串了,你就 不要费心来找我的密码了哦,呵呵。
.text:004011DE ;
.text:004011E5 mov ebp, eax ; ebp中保存返回的miyao值
.text:004011E7 or ecx, 0FFFFFFFFh
.text:004011EA xor eax, eax
.text:004011EC add esp, 4 ; 弹栈去掉长密钥
.text:004011EF mov esi, eax ; esi=0
.text:004011F1 repne scasb
.text:004011F3 not ecx
.text:004011F5 dec ecx ; ecx=strlen((ASCII "Oq/Ge~:TFo*")=11
.text:004011F6 dec ecx ; ecx=strlen-1
.text:004011F7 mov [esp+80h+var_68], ecx
.text:004011FB js loc_401299
.text:00401201 mov eax, ebp ; eax=miyaotrans()
.text:00401203 xor edi, edi ; edi=0
.text:00401205 neg eax ; eax=eax取反
.text:00401207 push ebx
.text:00401208 mov [esp+84h+code], offset unk_41B1C4 ;出现要写的明文地址 了。命名为code。
.text:00401210 mov [esp+84h+var_6C], eax
.text:00401214
.text:00401214 loc_401214: ; CODE XREF: passRead+CA.j
.text:00401214 mov eax, [esp+84h+binMiyao]
.text:0040121B mov al, [esi+eax] ; binMiyao[i]这里是个典型的数组操作, 这个esi在编程时不妨设为int i
.text:0040121E movsx ebx, al ; 将密文的一个字节进行符号扩展并放入 ebx
.text:00401221 cmp ebx, 20h ; 比较该字节是否在0x20h到0x7Eh之间,不 在这个区间就跳过比较下一个字节,这个区间的才是可用的密码。
.text:00401224 mov [esp+esi+84h+var_64], al ; 这个赋值没发现有啥用
.text:00401228 jl short loc_401285 ;
.text:00401228 ;
.text:0040122A cmp ebx, 7Eh
.text:0040122D jg short loc_401285 ;
.text:0040122D ;
.text:0040122F add edi, ebp ; edi=edi+ebp,注意看第一次进入此循环 时的ebp值,往上看,原来是key
.text:00401231 mov ecx, 188B9h ; 这里每次都加,不妨设edi为sum
.text:00401236 mov eax, edi
.text:00401238 inc esi ; i++
.text:00401239 cdq ; 将eax符号扩展为32位,准备做除法运算
.text:0040123A idiv ecx ; eax=sum/0x188B9h
.text:0040123A ; edx=sum%0x188B9h
.text:0040123C mov [esp+84h+var_70], edx ; miyaotrans返回值
.text:0040123C ;
.text:00401240 fild [esp+84h+var_70] ; 将sum%0x188B9h的值装入ST(0),准备做 浮点运算
.text:00401244 fmul ds:dbl_411318 ; 好懒,这里是个常数
.text:00401244 ;
不妨设DOUBLE d318 = 9.946586828729721e-6;
.text:0040124A fmul ds:dbl_411310 ; 这里也是个常数
.text:0040124A ; 设DOUBLE d310 = 9.6e1 ;
.text:00401250 call _ftol ; 这个函数MSDN中没查到,好在很好猜, 因为执行完就看见eax返回一个值,但是编程的时候会有点麻烦,后话。
.text:00401250 ;
.text:00401255 mov edx, eax ; edx=浮点的返回值
.text:00401257 mov eax, ebx ; eax=binMiyao[i]
.text:00401259 sub eax, edx ; eax=binMiyao[i]-pedx
.text:0040125B mov ecx, 5Fh
.text:00401260 sub eax, 20h ; eax=binMiyao[i]-pedx-0x20
.text:00401263 cdq ; 再准备做除法
.text:00401264 idiv ecx ; edx=(binMiyao[i]-pedx-0x20)%0x5F
.text:00401266 test edx, edx ; edx大于等于0则继续,否则edx+0x5F
.text:00401268 jge short loc_40126C ;
.text:00401268 ; 这里的var_6c的赋值在上面,是返回key 的取反
.text:0040126A add edx, ecx
.text:0040126C
.text:0040126C loc_40126C: ; CODE XREF: passRead+A8.j
.text:0040126C mov eax, [esp+84h+var_6C] ;
.text:0040126C ; 这里的var_6c的赋值在上面,是返回key 的取反
.text:00401270 mov ecx, [esp+84h+var_68] ; 这里的var_68也是在上面的位置 赋值,是len-1
.text:00401274 add edi, eax ; sum+=-key;看上去好别扭啊,其实就是 sum=sum-key
.text:00401276 mov eax, [esp+84h+code] ; 这里出现我们要写的堆栈地址了,显 然准备出口成品了
.text:0040127A add dl, 20h ; edx的低16位+32,显然可以显示的ASCII 是从32开始的
.text:0040127D dec esi ; i--
.text:0040127E mov [eax], dl ; 这里code[i]=dl
.text:00401280 inc eax
.text:00401281 mov [esp+84h+code], eax ; 写完了就将指针指向下一位
.text:00401285
.text:00401285 loc_401285: ; CODE XREF: passRead+68.j
.text:00401285 ; passRead+6D.j
.text:00401285 inc esi ;
.text:00401285 ; i++
.text:00401286 add edi, ebp ; sum+=key
.text:00401288 cmp esi, ecx ; 比较是否解密完毕
.text:0040128A jle short loc_401214 ; 没解完继续
.text:0040128C pop ebx
.text:0040128D pop edi
.text:0040128E pop esi
.text:0040128F mov eax, offset unk_41B1C4 ; 将这个地址放入eax返回
.text:00401294 pop ebp
.text:00401295 add esp, 74h
.text:00401298 retn
.text:00401299 ; ---------------------------------------------------------------------------
我们再来看看这个401390吧。
.text:00401390 ; =============== S U B R O U T I N E =======================================
.text:00401390
.text:00401390
.text:00401390 miyaoTrans proc near ; CODE XREF: passRead+19.p
.text:00401390 ; passTrans+18.p
.text:00401390
.text:00401390 var_8 = dword ptr -8
.text:00401390 var_4 = dword ptr -4
.text:00401390 string_miyao = dword ptr 4
.text:00401390
.text:00401390 sub esp, 8
.text:00401393 push ebx
.text:00401394 push esi
.text:00401395 push edi ; pass
.text:00401395 ; Dr.com用户认证
.text:00401396 mov edi, [esp+14h+string_miyao] ;
.text:00401396 ; ASCII "TblRefreshCurMonthServiceUse"
.text:00401396 ;
.text:00401396 ; 这个串是个常量
.text:0040139A or ecx, 0FFFFFFFFh ; 看见这个你就该想起strlen了
.text:0040139D xor eax, eax ; eax=0
.text:0040139F xor ebx, ebx ; ebx=0
.text:004013A1 xor esi, esi ; esi=0
.text:004013A3 repne scasb ; 求出string_miyao串长度
.text:004013A5 not ecx
.text:004013A7 dec ecx ; ecx=strlen(string_miyao),作为下面循 环的次数计数器
.text:004013A8 xor edi, edi ; int v_esi=0
.text:004013AA cmp ecx, ebx ; strlen(string_miyao)要大于 0
.text:004013AC mov [esp+14h+var_8], ebx ; int v8=0
.text:004013B0 mov [esp+14h+var_4], ecx ; int v4=strlen (string_miyao)
.text:004013B4 jle short loc_40140C ; eax=var_8
.text:004013B4 ;
.text:004013B6 push ebp ; ebp=64H
.text:004013B6 ; 这里的值需要保存,为其他函数用的, 这里做解密我们不用管了
.text:004013B7
.text:004013B7 loc_4013B7: ; CODE XREF: miyaoTrans+79.j
.text:004013B7 mov eax, [esp+18h+string_miyao] ; 这个要做循环strlen (string_miyao)次
.text:004013B7 ;
.text:004013B7 ;
.text:004013B7 ; eax为string_miyao数组的首地址
.text:004013BB push esi ; 保存esi的值
.text:004013BB ; 首次做这个循环是esi=0
.text:004013BC movsx ebp, byte ptr [edi+eax] ;
.text:004013BC ; 符号扩展ebp为数组中第esi位的值
.text:004013BC ; ebp=string_miyao[i]
.text:004013C0 call mi_2 ; 这个call的地址是401430
.text:004013C0 ; 这个call很简单,跟进去看看就知道了 ,其实就是求2的esi次方。一会也分析一下。我将2 的esi次方记为2**esi。
.text:004013C5 imul eax, ebp ; eax=2**esi*string_miyao[i]
.text:004013C8 mov ecx, [esp+1Ch+var_8] ;
.text:004013C8 ; ecx=var_8
.text:004013CC push ebx ; 保存ebx
.text:004013CC ; 首次运算时ebx=0
.text:004013CD xor ecx, eax ; ecx=var_8 xor 2**esi*string_miyao [i]
.text:004013CD ; 注意:这是第一次异或
.text:004013CF mov [esp+20h+var_8], ecx ;
.text:004013CF ; var_8=var_8 xor 2**esi*string_miyao[i]
.text:004013CF ; 本次异或的结果被保存到var_8中
.text:004013D3 call mi_2 ; eax=2**ebx
.text:004013D3 ; 再取2**ebx,注意这次是取2**ebx
.text:004013D8 imul eax, ebp ;
.text:004013D8 ; eax=2**ebx*string_miyao[i]
.text:004013DB mov edx, [esp+20h+var_8] ;
.text:004013DB ; edx=var_8
.text:004013DF mov ecx, 13h ; ecx=19
.text:004013E4 xor edx, eax ; 再异或一次
.text:004013E6 lea eax, [esi+7] ; eax=esi+7
.text:004013E6 ;
.text:004013E9 mov [esp+20h+var_8], edx ;
.text:004013E9 ; var_8=var_8 xor 2**ebx*string_miyao[i]
.text:004013E9 ; 将两次异或的结果保存
.text:004013ED add esp, 8 ; 弹出堆栈,清掉ebx和esi
.text:004013F0 cdq ; 扩展eax准备除法
.text:004013F1 idiv ecx ; eax=(esi+7)/19
.text:004013F1 ; edx=(esi+7)%19
.text:004013F3 lea eax, [ebx+0Dh] ; eax=ebx+13
.text:004013F6 mov ecx, 17h ; ecx=23
.text:004013FB mov esi, edx ; esi=edx=(esi+7)%19
.text:004013FB ; 这个esi在下次运算做幂运算的时候就变 换了
.text:004013FD cdq
.text:004013FE idiv ecx ; edx=(ebx+13)%23
.text:004013FE ;
.text:00401400 mov eax, [esp+18h+var_4] ;
.text:00401400 ; eax=var_4=strlen(string_miyao)
.text:00401404 inc edi ; edi++
.text:00401405 cmp edi, eax ; edi<var_4则继续循环
.text:00401407 mov ebx, edx ; ebx=(ebx+13)%23
.text:00401407 ;
.text:00401409 jl short loc_4013B7 ; 这个要做循环strlen(string_miyao)次
.text:00401409 ;
.text:00401409 ;
.text:00401409 ; eax为string_miyao数组的首地址
.text:0040140B pop ebp
.text:0040140C
.text:0040140C loc_40140C: ; CODE XREF: miyaoTrans+24.j
.text:0040140C mov eax, [esp+14h+var_8] ; eax=var_8
.text:0040140C ; 最后得到一个异或了好多次的值,放入 eax,再处理
.text:00401410 mov ecx, 188B9h ; ecx=0x188B9H
.text:00401415 xor eax, 18901h ; eax=eax xor 0x18901H
.text:0040141A pop edi
.text:0040141B cdq
.text:0040141C idiv ecx ; 发现取余是个很频繁的操作
.text:0040141E pop esi
.text:0040141F pop ebx
.text:00401420 mov eax, edx ; 返回(eax xor 0x18901) % 100537
.text:00401422 add esp, 8
.text:00401425 retn
.text:00401425 miyaoTrans endp
.text:00401425
.text:00401425 ; ---------------------------------------------------------------------------
.text:00401426 align 10h
我们看下这个00401430吧!非常简单的函数。
.text:00401430 ; =============== S U B R O U T I N E =======================================
.text:00401430
.text:00401430 ;
.text:00401430 ; 取出传入的参数
.text:00401430
.text:00401430 mi_2 proc near ; CODE XREF: miyaoTrans+30.p
.text:00401430 ; miyaoTrans+43.p
.text:00401430
.text:00401430 arg_0 = dword ptr 4
.text:00401430
.text:00401430 mov ecx, [esp+arg_0]
.text:00401434 mov eax, 1
.text:00401439 cmp ecx, eax ; 传入的参数是否小于1,是就跳
.text:00401439 ; 否则就做下面的循环
.text:0040143B jl short locret_401442 ; 如果传进来的参数小于1,就返回1 ,否则就返回eax
.text:0040143D
.text:0040143D loc_40143D: ; CODE XREF: mi_2+10.j
.text:0040143D add eax, eax ; eax=eax*2
.text:0040143F dec ecx ; ecx--
.text:00401440 jnz short loc_40143D ; 循环ecx次
.text:00401442
.text:00401442 locret_401442: ; CODE XREF: mi_2+B.j
.text:00401442 retn ; 如果传进来的参数小于1,就返回1,否 则就返回eax
.text:00401442 mi_2 endp
.text:00401442
好了,分析的差不多了,总结一下,程序打开密文后,利用一个miyaoTrans的函数对一个字符串常量做了 个种子key,求取密文的长度后,循环长度次做明文解密。解密就是通过对密文的每位ASCII码做简单的减 一个key的浮点乘法运算后取整的值后再取余(噎死我了),(若为负数则加95),然后将该余数加上32,就得 到明文。
这是核心解密程序段,还是加上比较好,在附件没人看
xTiNtint mi_2(int a1)
{
signed int result;
signed int v2;
v2 = a1;
result = 1;
if ( a1 >= 1 )
{
do
{
result *= 2;
--v2;
}
while ( v2 );
}
return result;
}
//////////////////////////////////////////////////////
//写成函数,是防止以后字符串发生变化。
int miyao(const char *string_miyao)
{
int m,n,key,crypto;
m=n=key=crypto=0;
int length=strlen(string_miyao);
for ( int i=0 ; i < length;i++ )
{
key = string_miyao[i];
crypto ^= key * mi_2(n);
crypto ^= key * mi_2(m);
n = (n + 7) % 19;
m = (m + 13) % 23 ;
}
return (crypto ^ 0x18901) % 100537;
}
//////////////////////////////////////////////////////
//算法很简单,是吧!,原程序是返回一个明文区的指针,
//这里就省事了
/////////////////////////////////////////////////////
int ReadPass(const char *pcode)
{
char code[16]={0};
int i,tmp,dst,sum,key,len,st0,flag;
HINSTANCE LibHandle;
MYPROC _ftol;
i=sum=tmp=st0=flag=0;
DOUBLE d310 = 9.6e1 ;
DOUBLE d318 = 9.946586828729721e-6;
LibHandle=LoadLibrary("msvcrt.dll");
_ftol =(MYPROC)GetProcAddress(LibHandle,"_ftol");
key=miyao("TblRefreshCurMonthServiceUse");//其实这里是个很稳定的整数30137,因为这个字符串是常量.
len=strlen(pcode);
if(len<1)
{
return flag;
}
else
{
do
{
tmp=pcode[i];
if(tmp>=32&&tmp<=0x7E)
{
sum+=key;
st0=sum%0x188B9;
__asm
{
fild st0;
fmul d310;
fmul d318;
call _ftol;
mov dst,eax
}
dst=(tmp-dst-32)%0x5f;
if(dst<0) dst=dst+0x5F;
code[i]=dst+32;
i++;
}
}
while(i<=(len-1));
strcpy(password,code);
flag=1;
return flag;
}
}
程序很简单,各位凑合着看吧。老鸟飘过。不要拿来做坏事,因为这是个客户端,服务端哪里啥都查得到。我也已经发信给Dr.com了。最郁闷的是,我写完了程序后才发现,黑客防线上早就 有人发过类似的文章,惊出一身冷汗,不过作者并没有对解密过程做出分析,只是简单的找出明文。希望 这个问题在Dr.com的下一个版本中得到解决。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年04月10日 18:47:37
本代码由xTiNt自动着色 http://kbadboy.yeah.net
赞赏
他的文章
谁下载
freecat
deanlh
forgot
FishSeeWater
ikki
yyjpcx
iCE
海风月影
poppig
csuthdy
LOVE
xingbing
bbzhu
ywb
PowerBoy
ghostkim
peterchen
verybigbug
needy
kylinpoet
脱脱
cd37ycs
llc1968
suolao
e5v
flysky88
crbb
dssz
yuanqs
decolor
xzchina
tom
pop
alastone
ViperDodge
zgz1979clh
warcraft
panxiaosen
peaceclub
舒克和贝塔
cnhhkk
jiangyyyy
gjianbo
执着我一生
满天星
阿健
shoooo
sinab
ww990
Fpc
6613066
EsoHurt
huoshan
rufus
Flashcqxg
qqeleven
elance
foxabu
modi
二毛
逍遥风
zengminggn
Intelfan
thdzhqg
amour
Pucua
windz
pathletboy
lorde
openall
jyzhqg
yeihua
孤独草人
RuShi
testttt
igxk
plutopluto
readreadqq
muyen
lionben
albeta
丛林小子
myqingniao
jeffcjh
huiyuan
我最帅
xyu
tkgs
msg
gustao
tnttools
落日一笑
slavelord
jzhr
哦也
wjkplx
jjr
爱琴海
qjzshnew
谁下载
freecat
deanlh
forgot
FishSeeWater
ikki
yyjpcx
iCE
海风月影
poppig
csuthdy
LOVE
xingbing
bbzhu
ywb
PowerBoy
ghostkim
peterchen
verybigbug
needy
kylinpoet
脱脱
cd37ycs
llc1968
suolao
e5v
flysky88
crbb
dssz
yuanqs
decolor
xzchina
tom
pop
alastone
ViperDodge
zgz1979clh
warcraft
panxiaosen
peaceclub
舒克和贝塔
cnhhkk
jiangyyyy
gjianbo
执着我一生
满天星
阿健
shoooo
sinab
ww990
Fpc
6613066
EsoHurt
huoshan
rufus
Flashcqxg
qqeleven
elance
foxabu
modi
二毛
逍遥风
zengminggn
Intelfan
thdzhqg
amour
Pucua
windz
pathletboy
lorde
openall
jyzhqg
yeihua
孤独草人
RuShi
testttt
igxk
plutopluto
readreadqq
muyen
lionben
albeta
丛林小子
myqingniao
jeffcjh
huiyuan
我最帅
xyu
tkgs
msg
gustao
tnttools
落日一笑
jzhr
哦也
wjkplx
jjr
爱琴海
qjzshnew
小子贼野
谁下载
freecat
deanlh
forgot
FishSeeWater
ikki
yyjpcx
iCE
海风月影
poppig
csuthdy
LOVE
xingbing
bbzhu
ywb
PowerBoy
ghostkim
peterchen
verybigbug
needy
kylinpoet
脱脱
cd37ycs
llc1968
suolao
e5v
flysky88
crbb
dssz
yuanqs
decolor
xzchina
tom
pop
alastone
ViperDodge
zgz1979clh
warcraft
panxiaosen
peaceclub
舒克和贝塔
cnhhkk
jiangyyyy
gjianbo
执着我一生
满天星
阿健
shoooo
sinab
ww990
Fpc
6613066
EsoHurt
huoshan
rufus
Flashcqxg
qqeleven
elance
foxabu
modi
二毛
逍遥风
zengminggn
Intelfan
thdzhqg
amour
Pucua
windz
pathletboy
lorde
openall
jyzhqg
yeihua
RuShi
testttt
igxk
plutopluto
readreadqq
muyen
lionben
albeta
丛林小子
myqingniao
jeffcjh
huiyuan
我最帅
xyu
tkgs
msg
gustao
tnttools
落日一笑
jzhr
哦也
wjkplx
jjr
爱琴海
qjzshnew
小子贼野
dzhsurf
谁下载
freecat
deanlh
forgot
FishSeeWater
ikki
yyjpcx
iCE
海风月影
poppig
csuthdy
LOVE
xingbing
bbzhu
ywb
PowerBoy
ghostkim
peterchen
verybigbug
needy
kylinpoet
脱脱
cd37ycs
llc1968
suolao
e5v
flysky88
crbb
dssz
yuanqs
decolor
xzchina
tom
pop
alastone
ViperDodge
zgz1979clh
warcraft
panxiaosen
peaceclub
舒克和贝塔
cnhhkk
jiangyyyy
gjianbo
执着我一生
满天星
阿健
sinab
ww990
Fpc
6613066
EsoHurt
huoshan
rufus
Flashcqxg
qqeleven
elance
foxabu
modi
二毛
逍遥风
zengminggn
Intelfan
thdzhqg
amour
Pucua
windz
pathletboy
lorde
openall
jyzhqg
yeihua
RuShi
testttt
igxk
plutopluto
readreadqq
muyen
lionben
albeta
丛林小子
myqingniao
jeffcjh
huiyuan
我最帅
xyu
tkgs
msg
gustao
tnttools
lifediy
落日一笑
jzhr
哦也
wjkplx
jjr
爱琴海
qjzshnew
小子贼野
dzhsurf
谁下载
freecat
deanlh
forgot
FishSeeWater
ikki
yyjpcx
iCE
海风月影
poppig
csuthdy
LOVE
xingbing
bbzhu
ywb
PowerBoy
ghostkim
peterchen
verybigbug
needy
kylinpoet
脱脱
cd37ycs
llc1968
suolao
e5v
flysky88
crbb
dssz
yuanqs
decolor
xzchina
tom
pop
alastone
ViperDodge
zgz1979clh
warcraft
panxiaosen
peaceclub
舒克和贝塔
cnhhkk
jiangyyyy
gjianbo
执着我一生
满天星
阿健
sinab
ww990
Fpc
6613066
EsoHurt
huoshan
rufus
Flashcqxg
qqeleven
elance
foxabu
modi
二毛
逍遥风
zengminggn
Intelfan
thdzhqg
amour
Pucua
windz
pathletboy
lorde
openall
jyzhqg
yeihua
RuShi
testttt
igxk
plutopluto
readreadqq
muyen
lionben
albeta
丛林小子
myqingniao
jeffcjh
huiyuan
我最帅
xyu
tkgs
msg
gustao
tnttools
落日一笑
jzhr
哦也
wjkplx
jjr
爱琴海
qjzshnew
小子贼野
dzhsurf
十指紧扣
看原图
赞赏
雪币:
留言: