12月6号金山公司员工失误造成IDA pro6.8的正式个人版完全泄露,里面包含正版的安装包,安装密码以及7月份的授权(这个要比hackteam放出来的那个时间短,hackteam授权时间是2016.4.8),不过授权时间并不影响使用,只是停止升级而已,不过按照IDA公司的一贯做法,该员工应该是被放到黑名单了。
0×01局域网检测
该Windows版本的IDA启动后,它会在端口23945上广播一个UDP包,并等待响应,看相同子网中是否有其他使用相同许可证密钥的IDA实例在运行。然后,IDA会将得到的响应数量与使用该许可证的用户数量进行比较,如果发现网络中存在过多的IDA实例,IDA会拒绝启动。
因此我把这处简单的限制给去除掉了,当然在吾爱破解上面早已经出现了该绿色版本的,下载地址。去除局域网验证方法很多,吾爱上hellotong88和看雪上都有基本的破解思路。针对6.8其实思路也差不多。
0×02 思路过程
按照最基本的破解思路,查找关键字符串,找到提示信息
很轻松就能找到提示信息,看看是哪个函数调用的
上图的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实现的细节。
只要这两个参数任何一个出现错误则调用失败。
更详细的说明,参见这篇博客。
0×03 patch过程
查看 WSAStartup(2u, &v1)函数传参,再做相应修改,可以看到这里只需要更改一个字节。
最后,Edit->Patch program->Change byte即可。
【via@91ri团队-Leon】 注:本文系91ri团队原创文,转载请注明出处。
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号