首页
社区
课程
招聘
[原创]破解NetKeeper本地密码读取
发表于: 2013-10-29 23:00 37863

[原创]破解NetKeeper本地密码读取

2013-10-29 23:00
37863

原文来自:【Tracy‘Blog】——www.purpleroc.com

      有了在涉外混迹四年,写下的《校园网那些事》的经历后,写这篇文章似乎要比以前容易些。来重庆也有1个半月了,一直昏昏忽忽的,总提醒自己要打起精神来,却总打不起精神。可能是很久没什么能够刺激自己、给自己增加自信心吧,于是决定看看学校的客户端。

      以前做过类似的事,于是,也就有些思维固定,不想再去做同类型的事了,属于眼高手低型。然而账号到期了,又想起了以前做过的事。那,来找找自信吧~~不过,这客户端比涉外的安腾高级了好几倍~~~~                                      

      其实,先前也看过这个客户端,不过,一直想的是能够实现linux下拨号上网。好了,废话不多说了,进入正文吧。

      先说目的:从文件中还原出我们拨号时输入的账号、密码。那先从文件看起,看看是哪个文件保存了这些信息。

      打开netkeeper的安装目录,看看每个文件是干嘛用的:


      这个应该是没可以理解的。那,保存密码的文件应该是在bin或者是config文件夹中了(省去推论文字,没看懂的可以先看看《校园网那些事》……)。其实,我们对比刚安装好程序,和拨号一次之后文件夹中的内容就可以清楚的看到,在bin文件中多了一个Credit文件。那,它很有可能就是我们要找的文件了。 
    ok,我们拿出peid看看程序有没加壳,

    提示没找到,不过,看区段就知道vmp的壳。我等菜鸟是没想过要去挑战它的。那,带壳运行来调试吧。

    OD载入(忽略所有异常),直接对下断bp CreateFileA(分析见《校园网那些事》),F9跑起来,发现了类似如下call

0018785C   7266C4A4  つfr   /CALL 到 CreateFileA 来自 AcLayers.7266C4A1
00187860   00187CA0  爘.   |FileName = "\\.\Global\NPF_{C97F955E-E47F-4270-9432-764A2C7C41D3}"

      我们暂且把它当作是vmp壳对程序自解压时的一些操作吧(知道的还麻烦告知一声),这也是为什么在我们确定了读取文件的位置后不能直接对地址下断,而必须每次都跑完对类似这些|FileName = "\\.\Global\NPF_文件的操作的原因。我理解为,因为程序还没解压完,你直接下断,会引起程序解压出错,而导致程序出错。
    一直F9到FileName为C:\ChinaNetSn\时就要注意了。

    一下下的摁F9,到出现读取Credit文件:

    取消断点,Alt+F9返回用户代码区。我看到的是非常乱的数据:

    没关系,CTRL+A分析一下。就出现了我们可爱的汇编代码了:

    我们可以看到,刚才程序仅仅是访问Credit文件,而还没进行读取。一下是读取片段。

为了节省篇幅,直接复制代码吧:

0041B049   > \817C24 0C 8C1>cmp dword ptr ss:[esp+C],168C            ;  文件完整性校验
0041B051   .  74 17         je short NetKeepe.0041B06A
……
0041B06A   > \56            push esi                                 ; /hObject
0041B06B   .  FF15 30425000 call dword ptr ds:[504230]               ; \CloseHandle
0041B071   .  6A 00         push 0
0041B073   .  57            push edi
0041B074   .  8BCB          mov ecx,ebx
0041B076   .  E8 25000000   call NetKeepe.0041B0A0                   ;  加解密入口
void encode(char *buffer, int len)
{
   char *p;
   while (len)
   {
       p = encode1(buffer);//位置交换
       encode2(buffer, p);//解密
       encode3(buffer);//顺序改回
       len = len - 8;
       buffer = buffer + 8;
   }
}
最难的问题应该在于第二步了,为了偷懒,少写点代码,就直接用C语言嵌套asm来实现。
不过这样做的最困难的地方应该在于,保护现场以及,匹配好各传入参数。我们来对比一下C和反汇编的代码。
在反汇编代码中,进行第二步加密中 mov eax, dword ptr [ecx]前,push了以下参数:

00404256  |.  68 80755400   push NetKeepe.00547580                   ;  要用到的pass
0040425B  |.  52            push edx                                 ;  放入地址
0040425C  |.  E8 DF000000   call NetKeepe.00404340                                ;  解密第二步
                       
               00404340  /$  51            push ecx
               00404341  |.  8B4C24 08     mov ecx,dword ptr ss:[esp+8]
               00404345  |.  53            push ebx
               00404346  |.  55            push ebp
               00404347  |.  56            push esi

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 5
支持
分享
最新回复 (39)
雪    币: 1392
活跃值: (5212)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
2
shanxun真是垃圾中的垃圾。
不过话说现在人家需要的应该破解是路由限制吧~
2013-10-29 23:37
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
3
所以说,要找心跳包原理啊。。。
2013-10-29 23:48
0
雪    币: 1392
活跃值: (5212)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
4
我主要是去掉共享限制。因为自己没有路由器。WIN7 WIFI热点开起来就好了,能手机玩一玩。
2013-10-30 09:16
0
雪    币: 73
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
以前也尝试去解这个文件得到密码,后来没耐心就Hook RasDial了。WinHex也能看见
2013-10-30 13:44
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
直接读取内存就能得到账号和密码。
2013-10-30 13:50
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
分析心跳包太复杂,我目前用的是另一种办法破解共享限制。
拨号成功之后,NetKeeper会循环把连接设置为 不共享 的状态。
设置共享需要调用 NetSharingManager 接口。
所以,注入一个DLL,hook CoCreateInstance 函数。如果 CLSID 是  NetSharingManager 就返回 False

ps: 偶然发现 WIN7下 NetKeeper 在没有管理员权限的时候,就能共享。因为,NetSharingManager 接口需要管理员权限。
2013-10-30 13:59
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
8
嗯,是的,最原先我是用过rasdial实现了。之后,截取内存也实现了。
只是,再次捉摸下,试试通过文件获取。
这套程序,总会有用的。
2013-10-30 19:45
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
9
嗯。是的,前面也有大神发过内存截获账号密码的。
2013-10-30 19:46
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
10
应该是挺复杂的,毕竟那么多人在弄,网上也还没找到有成功的。
我的想法是,能够彻底摆脱客户端,用其他的工具拨号上网。或者说,在其他平台上实现拨号上网。
2013-10-30 19:48
0
雪    币: 73
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
其实不难的,知道的人都不说,过驱动可以在系统里随便找个DLL改名为XLPPPoePCIoctl.dll放到他的Bin目录下,有技术含量点的DeviceIoControl把驱动里的开关关了,应用层删除共享的可以Hook RasDial改连接的名称,或者KillTimer一个定时器,ID多少忘记了,这些方法都试过都是可行的。
2013-10-31 09:35
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
12
嗯,实现共享的话,应该是比较容易实现的,不过,我只是想找出它的运行原理。

完全脱离这个客户端,用自己的程序生成动态用户名、拨号、发送心跳包维持在线状态。

其实,先前有人,不知道通过什么方法,能够实现,同一账号多人拨号上网,而且,网速都是10M/s

相当于VIP

我估计应该是在服务器端做的手脚。

因为整个重庆都是可以用我们开通的账号拨号上网的。
2013-10-31 16:12
0
雪    币: 3380
活跃值: (1373)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
13
---期待包的分析-- 有点意犹未尽啊--
2013-11-3 13:07
0
雪    币: 72
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
我是用暂停线程的方式,实现共享的
2013-11-3 13:57
0
雪    币: 280
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
winhex读取内存的还是原来的帐号和密码的,难道是我打开方式不对?
2013-11-3 14:04
0
雪    币: 280
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
winhex读取内存的还是原来的帐号和密码的,难道是我打开方式不对?
2013-11-3 14:05
0
雪    币: 72
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
他就是读内存的账号好吧
2013-11-3 14:11
0
雪    币: 1392
活跃值: (5212)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
18
我是Hook DeviceIoControl。所有的控制码都拦截掉。至于manageshare没研究过。
2013-11-3 17:48
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
19
话说,暂停线程了,就不会有心跳包发出,10分钟左右会断线吧
2013-11-3 20:26
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
20
有可能获取到两种形式的账号
1、你输入的
2、通过你输入的+动态字符
2013-11-3 20:29
0
雪    币: 72
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
不会的,心跳包继续发送,它是单独的线程
2013-11-4 15:32
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
22
哦?  这个我还真没发现,等下试试。。。
2013-11-5 00:40
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
虽然拦截了控制码,但是它有定时器,一直循环设为非共享状态。。。。
2013-11-5 10:51
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
NetKeeper 建立了N个 UDP连接。。。
2013-11-5 10:54
0
雪    币: 329
活跃值: (235)
能力值: ( LV13,RANK:320 )
在线值:
发帖
回帖
粉丝
25
是的。分别发送到服务器的443、444、445、446。端口
其中,服务器回复两个数据包,看似都是对第一个数据包的回复。
2013-11-5 13:45
0
游客
登录 | 注册 方可回帖
返回
//