某公司泄露版IDA pro6.8去除局域网检测
12月6号金山公司员工失误造成IDA pro6.8的正式个人版完全泄露,里面包含正版的安装包,安装密码以及7月份的授权(这个要比hackteam放出来的那个时间短,hackteam授权时间是2016.4.8),不过授权时间并不影响使用,只是停止升级而已,不过按照IDA公司的一贯做法,该员工应该是被放到黑名单了。
0x01局域网检测
该Windows版本的IDA启动后,它会在端口23945上广播一个UDP包,并等待响应,看相同子网中是否有其他使用相同许可证密钥的IDA实例在运行。然后,IDA会将得到的响应数量与使用该许可证的用户数量进行比较,如果发现网络中存在过多的IDA实例,IDA会拒绝启动。
因此我把这处简单的限制给去除掉了,当然在吾爱破解上面早已经出现了该绿色版本的,下载地址。去除局域网验证方法很多,吾爱上hellotong88和看雪上都有基本的破解思路。针对6.8其实思路也差不多。
0x02 思路过程
按照最基本的破解思路,查找关键字符串,找到提示信息
很轻松就能找到提示信息,看看是哪个函数调用的
上图的sub_5533c0应该是最终的调用结果函数,因此还得往上继续逆,找到调用sub_5533c0的函数(由于图片太大,这里贴代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
int
__usercall
sub_553410
@
<
eax
>
(
SOCKET
*
a1
@
<
ecx
>
,
int
a2
@
<
esi
>
)
{
int
v2
;
// edi@1
SOCKET
v3
;
// ST08_4@1
int
result
;
// eax@1
int
v5
;
// ebx@4
_DWORD
*
v6
;
// ecx@4
int
v7
;
// eax@4
int
v8
;
// esi@4
int
v9
;
// esi@9
char
*
v10
;
// eax@9
unsigned
int
v11
;
// ecx@9
char
*
v12
;
// eax@16
unsigned
int
v13
;
// ecx@16
SOCKET
v14
;
// ST00_4@20
int
v15
;
// [sp-4h] [bp-4Ch]@2
int
fromlen
;
// [sp+8h] [bp-40h]@1
struct
sockaddr
from
;
// [sp+Ch] [bp-3Ch]@1
char
buf
;
// [sp+1Ch] [bp-2Ch]@1
int
v19
;
// [sp+20h] [bp-28h]@6
char
v20
[
16
]
;
// [sp+24h] [bp-24h]@10
char
v21
[
16
]
;
// [sp+34h] [bp-14h]@17
v2
=
a1
;
v3
=
*
a1
;
fromlen
=
16
;
result
=
recvfrom
(
v3
,
&buf
,
40
,
0
,
&from
,
&fromlen
)
;
if
(
result
!=
-
1
)
{
v15
=
a2
;
do
{
if
(
result
==
40
)
{
v5
=
*
(
v2
+
316
)
;
qmutex_lock
(
*
(
v2
+
316
)
,
v15
)
;
v7
=
*
(
v2
+
312
)
;
v8
=
0
;
if
(
v7
>
0
)
{
v6
=
(
v2
+
24
)
;
do
{
if
(
v19
==
*
v6
)
break
;
++
v8
;
v6
+=
18
;
}
while
(
v8
<
v7
)
;
}
v15
=
v5
;
qmutex_unlock
(
v6
)
;
if
(
v8
!=
*
(
v2
+
312
)
)
{
v9
=
v2
+
72
*
v8
+
24
;
v10
=
(
v9
+
8
)
;
v11
=
16
;
while
(
*
&v10
[
&v20
[
-
v9
-
8
]
]
==
*
v10
)
{
v11
-=
4
;
v10
+=
4
;
if
(
v11
<
4
)
goto
LABEL_20
;
}
if
(
v19
)
{
*
(
v9
+
4
)
=
0
;
sendto
(
*
v2
,
v9
,
40
,
0
,
&from
,
16
)
;
}
else
if
(
time64
(
0
)
-
*
(
v9
+
48
)
<=
3
)
{
v12
=
(
v9
+
24
)
;
v13
=
16
;
while
(
*
&v12
[
&v21
[
-
v9
-
24
]
]
==
*
v12
)
{
v13
-=
4
;
v12
+=
4
;
if
(
v13
<
4
)
{
++
*
(
v9
+
40
)
;
sub_5533C0
(
v2
,
v9
)
;
break
;
}
}
}
}
}
LABEL_20
:
v14
=
*
v2
;
fromlen
=
16
;
result
=
recvfrom
(
v14
,
&buf
,
40
,
0
,
&from
,
&fromlen
)
;
}
while
(
result
!=
-
1
)
;
}
return
result
;
}
|
上述代码中,能看到调用了sendto()和recvfrom()这两个跟UDP通信很关键的函数,sendto()是把UDP数据报发给指定地址;recvfrom()是从指定地址接收UDP数据报。我们结合UDP的通讯过程来看上述代码能更快理解(图片来自网络)
对照上图和代码,能够看出IDA的局域网检测大概就是,作为接收端,调用bind()函数绑定IP,接收来自任意IP、任意网卡的发给指定端口的数据。作为发送端,调用bind()函数绑定IP,使用网卡号最低的网卡进行发送数据,也就是UDP数据广播,通过多次循环判断是否存在相同的IDA实例。按道理,这里是校验的关键了,可以改相应的条件判断,实现patch。事实上也是可以的,不过为了使得补丁损伤最少,还能够有更小的改动,再往上回溯两三层
可以看到如果sub_552120()函数return 0的话,接下来所有的函数都不会执行了,进入 sub_552120()看看return 0的条件
上图很明显,要使sub_552120 return 0,则 WSAStartup(2u, &v1)函数必须调用失败。
WSAStartup原型:int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
wVersionRequested是Windows Sockets API提供的调用方可使用的最高版本号。
lpWSAData 是指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节。
只要这两个参数任何一个出现错误则调用失败。
更详细的说明,参见这篇博客。
0x03 patch过程
查看 WSAStartup(2u, &v1)函数传参,再做相应修改,可以看到这里只需要更改一个字节。
最后,Edit->Patch program->Change byte即可。