前言

移动端最好的播放器非云播君莫属了,极速而方便,高清而无码,可惜最近资源被和谐,每次有美剧更新需要用浏览器手工添加播放源或者pc端添加,很是麻烦的说。于是就简单diy了下云播1.9 for Android使其支持自定义搜索引擎(比如人人影视,xxx资源站等),并且修复了原来搜索结果列表页标题的bug,为了迎接Game of Thrones Season 4 的回归,特记录下修改过程。

添加yyets.com搜索引擎

反编译搜索引擎代码
com\xunlei\cloud\action\search\AdviseEngine.java 89 行

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
try
{
str = SearchAdviceEngineListResp.getDomainName(paramString);
if (str.equalsIgnoreCase("btdigg.org"))
{
localAdviseEngine.url_pattern = "http://btdigg.org/search?q={searchTerms}&p={page}";
localAdviseEngine.multi_page = true;
localAdviseEngine.page_start_point = 0;
return localAdviseEngine;
}
if (str.equalsIgnoreCase("so.com"))
{
localAdviseEngine.url_pattern = "http://www.so.com/s?q={searchTerms}+site%3Abtdigg.org&pn={page}";
localAdviseEngine.multi_page = true;
localAdviseEngine.page_start_point = 1;
return localAdviseEngine;
}
}
catch (URISyntaxException localURISyntaxException)
{
localURISyntaxException.printStackTrace();
return localAdviseEngine;
}
if (str.equalsIgnoreCase("torrentkitty.com"))
{
localAdviseEngine.url_pattern = "http://www.torrentkitty.com/search/{searchTerms}/{page}";
localAdviseEngine.multi_page = true;
localAdviseEngine.page_start_point = 1;
return localAdviseEngine;
}
if (str.equalsIgnoreCase("kuaichuanmirror.com"))
{
localAdviseEngine.url_pattern = "http://www.kuaichuanmirror.com/search/{searchTerms}/";
localAdviseEngine.multi_page = false;
localAdviseEngine.page_start_point = 1;
}

挖槽 竟然内置四大毛片搜索引擎 !!!
随便改掉一个即可
由于内置引擎只识别磁力链接 需要一个脚本文件来做中转(代码见最后链接)
输出格式为

1
2
magnet:?xt=urn:btih:hash1&title1</br>
magnet:?xt=urn:btih:hash2&title2</br>

修改 smali\com\xunlei\cloud\action\search\AdviseEngine.smali 239 行

1
2
3
4
5
6
7
8
9
10
11
.line 127 
:cond_1
const-string v2, "yyets.com"
invoke-virtual {v0, v2}, Ljava/lang/String;->equalsIgnoreCase(Ljava/lang/String;)Z
move-result v2
if-eqz v2, :cond_2
.line 128
const-string v0, "http://www.ttst.com/y2c.php?keyword={searchTerms}&page={page}"
iput-object v0, v1, Lcom/xunlei/cloud/action/search/AdviseEngine;->url_pattern:Ljava/lang/String;
.line 129
const/4 v0, 0x1

修正标题bug

云播在使用第三方搜索引擎时,发现结果列表页面的标题全部是随机的字符串

查看对应的dalvik代码
smali\com\xunlei\cloud\action\search\AdviseEngine.smali 990行

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
const-string v0, "magnet:\\?xt=urn:btih:([A-Za-z\\d]{32,})&?"      //批量正则   遍历结果数组
.....
invoke-static {v0, v1}, Ljava/util/regex/Pattern;->compile(Ljava/lang/String;I)Ljava/util/regex/Pattern;
.....
invoke-virtual {v5}, Ljava/util/regex/Matcher;->find()Z
move-result-object v0
.line 88
invoke-virtual {v0}, Ljava/lang/String;->length()I
move-result v1
add-int/lit8 v1, v1, -0x1
invoke-virtual {v0, v1}, Ljava/lang/String;->charAt(I)C
move-result v1
.line 89
const/16 v6, 0x26
if-ne v1, v6, :cond_4
.line 90
invoke-virtual {v0}, Ljava/lang/String;->length()I
move-result v1
add-int/lit8 v1, v1, -0x1
invoke-virtual {v0, v3, v1}, Ljava/lang/String;->substring(II)Ljava/lang/String;
move-result-object v0
move-object v1, v0
.line 92
:goto_1
const/16 v0, 0x14
invoke-virtual {v1}, Ljava/lang/String;->length()I
move-result v6
invoke-virtual {v1, v0, v6}, Ljava/lang/String;->substring(II)Ljava/lang/String;
move-result-object v0
.line 93
invoke-static {v0, v2}, Lcom/xunlei/cloud/action/search/g;->a(Ljava/lang/String;I)Ljava/lang/String; // str2.substring(20, str2.length())
move-result-object v6
......
.line 105
iput-object v6, v0, Lcom/xunlei/cloud/action/search/SnifferData;->title:Ljava/lang/String;
.line 106
iput-object v1, v0, Lcom/xunlei/cloud/action/search/SnifferData;->url:Ljava/lang/String;
.line 107
iput-object v6, v0, Lcom/xunlei/cloud/action/search/SnifferData;->hash:Ljava/lang/String;

对应的 Java 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Matcher localMatcher = Pattern.compile("magnet:\\?xt=urn:btih:([A-Za-z\\d]{32,})&?", 2).matcher(paramString);
if (!localMatcher.find())
return localArrayList;
String str1 = localMatcher.group();
if (str1.charAt(-1 + str1.length()) == '&');
for (String str2 = str1.substring(0, -1 + str1.length()); ; str2 = str1)
{
String str3 = a(str2.substring(20, str2.length()), 1);
.........
SnifferData localSnifferData = new SnifferData();
localSnifferData.title = str3;
localSnifferData.url = str2;
localSnifferData.hash = str3;
localArrayList.add(localSnifferData);
break;
......
}

标题被直接赋值给 magnet 的 hash 了 …..
修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ArrayList localArrayList = new ArrayList();
Matcher localMatcher = Pattern.compile(".*?</br>", 2).matcher( //中转脚本每行用</br> 分割
paramString);
if (!localMatcher.find()) {
return;
}
String str1;
str1 = localMatcher.group();
for (String str2 = str1.substring(0, 60);; str2 = str1) {
String str3 = str2.substring(20, 60);
String str4 = str1.substring(61, str1.length() - 5);
SnifferData localSnifferData = new SnifferData();
localSnifferData.title = str4;
localSnifferData.url = str2;
localSnifferData.hash = str3;
localArrayList.add(localSnifferData);
break;
}

对应的dalvik 代码

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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
locals 15 //15个寄存器

const-string v0, ".*?</br>"
const/4 v10, 0x0
const/16 v11, 0x3c // 60
const/16 v12, 0x3d //61

const/4 v1, 0x2

invoke-static {v0, v1}, Ljava/util/regex/Pattern;->compile(Ljava/lang/String;I)Ljava/util/regex/Pattern;

move-result-object v0

.line 80
invoke-virtual {v0, p0}, Ljava/util/regex/Pattern;->matcher(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;

move-result-object v5

.line 81
:cond_0
:goto_0
invoke-virtual {v5}, Ljava/util/regex/Matcher;->find()Z

move-result v0

if-nez v0, :cond_1

.line 112
return-object v4

.line 86
:cond_1
invoke-virtual {v5}, Ljava/util/regex/Matcher;->group()Ljava/lang/String;

move-result-object v0

.line 88
invoke-virtual {v0}, Ljava/lang/String;->length()I

move-result v1

add-int/lit8 v1, v1, -0x1

invoke-virtual {v0, v1}, Ljava/lang/String;->charAt(I)C

move-result v1

.line 89
const/16 v6, 0x26

if-ne v1, v6, :cond_4

.line 90
invoke-virtual {v0}, Ljava/lang/String;->length()I

move-result v1

invoke-virtual {v0, v10, v11}, Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-object v8
move-object v1, v8

.line 92
:goto_1
move-object v9, v0 // copy 一份v0 magnet:?xt=urn:btih:hash&title
const/16 v0, 0x14

invoke-virtual {v1}, Ljava/lang/String;->length()I

move-result v6

invoke-virtual {v1, v0, v6}, Ljava/lang/String;->substring(II)Ljava/lang/String;

move-result-object v0

.line 93
invoke-static {v0, v2}, Lcom/xunlei/cloud/action/search/g;->a(Ljava/lang/String;I)Ljava/lang/String;

move-result-object v6

.line 96
invoke-virtual {v4}, Ljava/util/ArrayList;->iterator()Ljava/util/Iterator;

move-result-object v7

:cond_2
invoke-interface {v7}, Ljava/util/Iterator;->hasNext()Z

move-result v0

if-nez v0, :cond_3

move v0, v3

.line 103
:goto_2
if-nez v0, :cond_0

.line 104
new-instance v0, Lcom/xunlei/cloud/action/search/SnifferData;

invoke-direct {v0}, Lcom/xunlei/cloud/action/search/SnifferData;-><init>()V

invoke-virtual {v9}, Ljava/lang/String;->length()I
move-result v13
add-int/lit8 v13, v13, -0x5

invoke-virtual {v9, v12, v13}, Ljava/lang/String;->substring(II)Ljava/lang/String;
move-result-object v14

.line 105
iput-object v14, v0, Lcom/xunlei/cloud/action/search/SnifferData;->title:Ljava/lang/String;

.line 106
iput-object v1, v0, Lcom/xunlei/cloud/action/search/SnifferData;->url:Ljava/lang/String;

.line 107
iput-object v6, v0, Lcom/xunlei/cloud/action/search/SnifferData;->hash:Ljava/lang/String;

回编译

错误处理

1
2
3
java -jar apktool.jar b CloudPlay_ybappgw c1.apk
libpng error: Not a PNG file
ERROR: Failure processing PNG image F:\Pentest\Ya Tools\pendroid\apktool1.5.2\CloudPlay_ybappgw\res\drawable-hdpi\local_list_view_item_color.png

不是真正的png文件 看了下文件头 bmp… 改过来 继续

1
ERROR: 9-patch image F:\Pentest\Ya Tools\pendroid\apktool1.5.2\CloudPlay_ybappgw\res\drawable-hdpi\progressbar_local_item.9.png malformed.

把三个文件全部改成普通 png格式 progressbar_local_item.9.png => progressbar_local_item.png

1
2
3
4
5
apktool b CloudPlay_ybappgw c1.apk
I: Checking whether sources has changed...
I: Smaling...
I: Checking whether resources has changed...
I: Building apk file...

成功编译成apk 文件

测试成功

java -jar signapk.jar testkey.x509.pem testkey.pk8 c1.apk c1_s.apk
adb install -r c1_s.apk
截图:

链接

中转脚本: https://github.com/yaseng/pentest/blob/master/project/diy_cloudplay/y2c.php
g.smali : https://github.com/yaseng/pentest/blob/master/project/diy_cloudplay/g.smali
smali 语法 : https://code.google.com/p/smali/w/list
Av Top 10: http://movie.douban.com/doulist/3822549