飞天信使企业版数据库分析- -tag: 飞天信使 数据库 手机归属地
filename : crkftxs.txt
title : 飞天信使企业版数据库分析
author :
vt220@hotmail.comblog :
http://erosion.bokee.comdate : 2004-12-19
software : 飞天信使企业版
version : v4.0
company : 成都众山科技有限公司
homepage :
http://www.zstel.com 飞天信使企业版v4.0是一个多功能的电话、短信、名片管理系统,可以利用 gsm modem
在线接收发送短信,还具有手机归属地查询功能,自带手机归属地信息 59117条。本文讲述
的就是如何获取飞天信使企业版v4.0手机归属地数据库中的内容。
安装这个软件后,很明显目录里有一个 7,106,560 bytes 的数据库文件 dblsms.mdb,
是microsoft access db格式估计八成这些信息就在里面了。打开microsoft access 2003,
调入这个文件,不幸的是让我输入密码。密码会是什么呢?试了几个比较弱的密码都不成功
之后还是决定用现成的软件破解。上网下了个advanced access password recovery v2.5,
最经典的破 access密码的软件了,果然一下子就破出来了,密码的确不复杂是"xuntian",
真不知道为什么office 系列密码都这么脆弱。再次打开 dblsms.mdb,输入密码,ok!果然
进去了,里面有很多表,挨个点点看吧。发现城市邮编存放在city里,手机卡的类型存放在
cardtype里,所有手机号都存放在numindex里,然后用一个共同的index 把手机号与城市关
联起来。可是问题又来了,所有的手机号码都是用21位数字表示的,分析来分析去我也没看
明白这 21 位数字与手机号的关系。哎,还是运行一下人家的软件瞧瞧吧。于是打开飞天信
使,点击号码查询,在查询旁边写着"至少输入前七位",也就是说只判断手机的前七位号码
了。可数据库里表示的手机号却是21位,显然是经过某种运算的结果。这下可要使出咱们
cracker 的看家本领了,嘿嘿。习惯性的用peid看了看加了什么壳,嘿嘿!又让我高兴了一
次,什么壳都没有啊,是用delphi写的。下面开始该进入跟踪的正题了,打开 ollydbg,调
入文件,断点设什么好呢...点击searchfor name in current modules,里面既没有
messagebox也没有strcmp 之类的东西,看来delphi 编译出来的东西有点类似微软的 mfc,
函数的调用都是 call 飞天信使.00484acc 这样的,比较麻烦,还是想其它的办法吧。于是
我输入了一个错误的手机号,哈哈,有了,"对不起,没有找到这个卡号的归属地",就拦截
这个字符串的引用吧。用ultra edit打开飞天信使企业版.exe,找到这个字符串的位置是
163234h,转换成va是563e34h,break point, memory on access。go!程序停在:
77f7b484 |. 0fb602 movzx eax,byte ptr ds:[edx]
是ntdll模块中,一路ctrl + f9,回到飞天信使企业版.exe中,经过一段时间的分析,
终于发现了重要的函数调用:
00563bac |. e8 07f8ffff call 飞天信使.005633b8
这个调用就是将 7位手机号变为21位数字的地方,进去仔细瞧瞧:
00563424 |. bb da000000 mov ebx,0da
00563429 |. be 06020000 mov esi,206
0056342e |. bf 96030000 mov edi,396
;edi = 396,参数1
00563433 |. 57 push edi
00563434 |. 8d45 e4 lea eax,dword ptr ss:[ebp-1c]
00563437 |. 50 push eax
;ecx = 206,参数2
00563438 |. 8bce mov ecx,esi
;edx = 0da,参数3
0056343a |. 8bd3 mov edx,ebx
;eax -> 输入的手机号
0056343c |. 8b45 fc mov eax,dword ptr ss:[ebp-4]
0056343f |. e8 fcfbffff call 飞天信使.00563040
这个函数调用对手机号进行了变换,继续进取跟踪:
;求输入的手机号长度
00563071 |. e8 9618eaff call 飞天信使.0040490c
00563076 |. 84c0 test al,al
00563078 |. 76 43 jbe short 飞天信使.005630bd
;[ebp-9]保存输入的手机号长度
0056307a |. 8845 f7 mov byte ptr ss:[ebp-9],al
;初始化计数器,不妨计作:i = 1
0056307d |. b3 01 mov bl,1
0056307f |> 8d45 f0 /lea eax,dword ptr ss:[ebp-10]
00563082 |. 33d2 |xor edx,edx
00563084 |. 8ad3 |mov dl,bl
;ecx -> 输入的手机号
00563086 |. 8b4d fc |mov ecx,dword ptr ss:[ebp-4]
;str[i-1]
00563089 |. 8a5411 ff |mov dl,byte ptr ds:[ecx+edx-1]
;esi = 0da,上面提到的参数3用上了
0056308d |. 8bce |mov ecx,esi
0056308f |. c1e9 08 |shr ecx,8
;str[i-1] ^= (esi >> 8)
00563092 |. 32d1 |xor dl,cl
;将计算出的字符考被
00563094 |. e8 9b17eaff |call 飞天信使.00404834
00563099 |. 8b55 f0 |mov edx,dword ptr ss:[ebp-10]
0056309c |. 8bc7 |mov eax,edi
0056309e |. e8 7118eaff |call 飞天信使.00404914
005630a3 |. 33c0 |xor eax,eax
005630a5 |. 8ac3 |mov al,bl
005630a7 |. 8b17 |mov edx,dword ptr ds:[edi]
005630a9 |. 0fb64402 ff |movzx eax,byte ptr ds:[edx+eax-1]
;esi += str[i-1];
005630ae |. 03f0 |add esi,eax
;esi *= 206,参数2也用上了
005630b0 |. 0faf75 f8 |imul esi,dword ptr ss:[ebp-8]
;esi += 396,参数3!
005630b4 |. 0375 0c |add esi,dword ptr ss:[ebp+c]
;i++
005630b7 |. 43 |inc ebx
;手机号长度 - 1
005630b8 |. fe4d f7 |dec byte ptr ss:[ebp-9]
005630bb |.^75 c2 \jnz short 飞天信使.0056307f
以上的计算公式的 c语言描述就是:
uint sum;
uchar in[7] = 输入的手机号;
uchar out[7];
sum = 0xda;
for(int i = 0; i < 7; i++)
{
out
= in ^ ((sum >> 8) & 0xff);
sum = (sum + str) * 0x206 + 0x396;
}
这样,经过上面计算,就把输入的 7位手机号转换为另外的 7位字符串。还需要继续跟
踪,看看怎么把这转换出来的 7位变为21位。回到上面这个转换之前的函数,下面是:
;eax -> 转换之后的字符
00563444 |. 8b45 e4 mov eax,dword ptr ss:[ebp-1c]
00563447 |. 8b55 f8 mov edx,dword ptr ss:[ebp-8]
;这个函数对刚刚转换出来的 7字节进行运算
0056344a |. e8 fdfdffff call 飞天信使.0056324c
进入函数内部看看:
;eax = out,就是刚转换出来的字符
005632b2 |. 0fb64402 ff |movzx eax,byte ptr ds:[edx+eax-1]
;一个指针
005632b7 |. 8d4d f4 |lea ecx,dword ptr ss:[ebp-c]
;长度3
005632ba |. ba 03000000 |mov edx,3
;很明显是将out转换为 3个字节
005632bf |. e8 c0feffff |call 飞天信使.00563184
去edx指向的地址看看算出来的数字,哈哈,竟然是将out 转换为10进制,这段转换
代码用 c语言表示如下:
uchar num21[22] = {0}; //存放算出来的21位数字
for(int i = 0; i < 7; i++)
{
uchar buf[4] = {0};
sprintf((char *)buf, "%03d", out);
strcat(num21, buf);
}
因为上面只用到了异或变换,所以再异或一次就可以将数据还原了。
encode(1364401) = 049044253017003094010
decode(049044248042195035000) = 1331212