├── README.md
└── app
└── src
└── main
├── AndroidManifest.xml
├── assets
└── xposed_init
├── java
└── com
│ └── unexpected
│ └── capture
│ └── uc
│ ├── IniFile.java
│ └── MainHook.java
└── res
└── values
├── arrays.xml
└── strings.xml
/README.md:
--------------------------------------------------------------------------------
1 | # UCProxyCapture
2 | UC 浏览器代理抓取
3 |
4 | # 简介
5 | UC 浏览器自启动后会抓取已开启的免流代理信息
6 |
7 | # 文件路径
8 | - /storage/emulated/0/UCDownloads
9 | - /storage/emulated/0/Download/UCDownloads
10 | - /storage/emulated/0/Android/data/包名/UCDownloads
11 |
12 | # 支持浏览器的版本
13 | UC浏览器:
14 | - 16.2.7.1278
15 |
16 | UC浏览器极速版:
17 | - 15.5.2.1242(仅电信)
18 |
19 | # 使用教程
20 | - 1.在 Xposed 框架找到模块并开启,打开模块作用域设置,勾选“UC 浏览器”。
21 | - 2.打开“UC 浏览器”,打开设置→高级设置→浏览器专享流量,填写你的手机号,并点击开启
22 | - 3.打开“文件管理”,打开配置保存路径: 可以看到 xxx.ini 文件,那个就是代理信息文件
23 |
24 | **注意:**
25 | - 现在联通也是动态生成的验证
26 | - 电信代理抓取到也没什么用
27 | - 如果抓取到的配置不会使用不要问我!!!
28 |
29 | # 停止维护
30 | 不再对这个项目进行更新
31 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
19 |
20 |
23 |
26 |
29 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | com.unexpected.capture.uc.MainHook
2 |
--------------------------------------------------------------------------------
/app/src/main/java/com/unexpected/capture/uc/IniFile.java:
--------------------------------------------------------------------------------
1 | package com.unexpected.capture.uc;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import de.robv.android.xposed.XposedBridge;
6 | import de.robv.android.xposed.XposedHelpers;
7 | import java.io.BufferedWriter;
8 | import java.io.File;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.io.OutputStream;
12 | import java.io.OutputStreamWriter;
13 | import java.util.Enumeration;
14 | import java.util.Properties;
15 |
16 |
17 | public class IniFile {
18 | private final Properties mProperties = new Properties();
19 | private final File mFile;
20 |
21 | public IniFile(@NonNull File file) {
22 | mFile = file;
23 | }
24 |
25 | @Nullable
26 | public Object set(@NonNull String key, @NonNull String value) {
27 | return mProperties.setProperty(key, value);
28 | }
29 |
30 | public boolean write() {
31 | FileOutputStream fos = null;
32 | try {
33 | fos = new FileOutputStream(mFile);
34 | store(mProperties, fos, null);
35 | return true;
36 | } catch(IOException e) {
37 | XposedBridge.log("Failed to write .ini file " + mFile + " error: " + e);
38 | } finally {
39 | if(fos != null) {
40 | try {
41 | fos.close();
42 | } catch(IOException e) {
43 | e.printStackTrace();
44 | }
45 | }
46 | }
47 | return false;
48 | }
49 |
50 | public static void store(@NonNull Properties properties, @NonNull OutputStream out, @Nullable String comments) throws IOException {
51 | store0(properties,
52 | new BufferedWriter(new OutputStreamWriter(out, "8859_1")),
53 | comments,
54 | true);
55 | }
56 |
57 | private static void store0(@NonNull Properties properties, @NonNull BufferedWriter bw, @Nullable String comments, boolean escUnicode) throws IOException {
58 | if(comments != null) {
59 | XposedHelpers.callStaticMethod(Properties.class, "writeComments", bw, comments);
60 | }
61 | //bw.write("#" + new Date().toString());
62 | //bw.newLine();
63 | synchronized(properties) {
64 | for(Enumeration> e = properties.keys(); e.hasMoreElements();) {
65 | String key = (String) e.nextElement();
66 | String val = (String) properties.get(key);
67 | key = (String) XposedHelpers.callMethod(properties, "saveConvert", key, true, escUnicode);
68 | /* No need to escape embedded and trailing spaces for value, hence
69 | * pass false to flag.
70 | */
71 | val = (String) XposedHelpers.callMethod(properties, "saveConvert", val, false, escUnicode);
72 | bw.write(key + "=" + val);
73 | bw.newLine();
74 | }
75 | }
76 | bw.flush();
77 | }
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/unexpected/capture/uc/MainHook.java:
--------------------------------------------------------------------------------
1 | package com.unexpected.capture.uc;
2 |
3 | import android.util.Base64;
4 | import de.robv.android.xposed.IXposedHookLoadPackage;
5 | import de.robv.android.xposed.XC_MethodHook;
6 | import de.robv.android.xposed.XposedHelpers;
7 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
8 | import java.io.File;
9 | import java.net.Inet4Address;
10 | import java.net.InetAddress;
11 | import java.net.NetworkInterface;
12 | import java.util.Enumeration;
13 | import java.util.Locale;
14 |
15 |
16 | public class MainHook implements IXposedHookLoadPackage {
17 | public static final String PACKAGE_NAME = "com.UCMobile";
18 |
19 | @Override
20 | public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
21 | if(PACKAGE_NAME.contains(lpparam.packageName)) {
22 |
23 | XposedHelpers.findAndHookConstructor("com.uc.browser.business.freeflow.a.b.b",
24 | lpparam.classLoader, byte[].class, new XC_MethodHook(){
25 | @Override
26 | protected void afterHookedMethod(final XC_MethodHook.MethodHookParam param) throws Throwable {
27 | new Thread(new Runnable(){
28 | @Override
29 | public void run() {
30 | Object pXP = XposedHelpers.getObjectField(param.thisObject, "pXP");
31 | Object aVar = null;
32 | boolean b = pXP != null && (aVar = XposedHelpers.getObjectField(pXP, "qat")) != null;
33 | IniFile file = new IniFile(getFile("telecom"));
34 | long millis = System.currentTimeMillis();
35 | file.set("time", "" + millis);
36 | file.set("date", String.format(Locale.ENGLISH, "%tF %tT", millis, millis));
37 | if(b) {
38 | file.set("server", (String) XposedHelpers.callMethod(aVar, "getDomain"));
39 | file.set("port", (String) XposedHelpers.callMethod(aVar, "duH"));
40 | file.set("uid", (String) XposedHelpers.callMethod(pXP, "getOrderId"));
41 | file.set("token", (String) XposedHelpers.callMethod(aVar, "duI"));
42 | } else {
43 | file.set("server", "");
44 | file.set("port", "");
45 | file.set("uid", "");
46 | file.set("token", "");
47 | }
48 | file.write();
49 | }
50 | }).start();
51 | }
52 | });
53 |
54 | XposedHelpers.findAndHookConstructor("com.uc.browser.business.freeflow.a.b.e",
55 | lpparam.classLoader, byte[].class, new XC_MethodHook(){
56 | @Override
57 | protected void afterHookedMethod(final XC_MethodHook.MethodHookParam param) throws Throwable {
58 | new Thread(new Runnable(){
59 | @Override
60 | public void run() {
61 | Object pXZ = XposedHelpers.getObjectField(param.thisObject, "pXZ");
62 | IniFile file = new IniFile(getFile("unicom"));
63 | long millis = System.currentTimeMillis();
64 | file.set("time", "" + millis);
65 | file.set("date", String.format(Locale.ENGLISH, "%tF %tT", millis, millis));
66 | if(pXZ != null) {
67 | file.set("server", (String) XposedHelpers.callMethod(pXZ, "getIp"));
68 | file.set("port", String.valueOf(XposedHelpers.getIntField(pXZ, "port")));
69 | String account = "uc".concat(getIp());
70 | String password = (String) XposedHelpers.callMethod(pXZ, "getPassword");
71 | file.set("account", account);
72 | file.set("password", password);
73 | file.set("base64", Base64.encodeToString(account.concat(":").concat(password).getBytes(), Base64.NO_WRAP));
74 | } else {
75 | file.set("server", "");
76 | file.set("port", "");
77 | file.set("account", "");
78 | file.set("password", "");
79 | file.set("base64", "");
80 | }
81 | file.write();
82 | }
83 | }).start();
84 | }
85 | });
86 | }
87 | }
88 |
89 | public static File getFile(String fileName) {
90 | return new File("/storage/emulated/0/UCDownloads", fileName.concat(".ini"));
91 | }
92 |
93 | /*public static String getHost(String str) {
94 | if(!StringUtils.isEmpty(str)){
95 | if(!str.contains("://")){
96 | str="http://".concat(str);
97 | }
98 | try {
99 | return new URL(str).getHost();
100 | } catch(Throwable ignore) {
101 | }
102 | }
103 | return "";
104 | }*/
105 |
106 | public static String getIp() {
107 | try {
108 | Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();
109 | while(networkInterfaces != null && networkInterfaces.hasMoreElements()) {
110 | NetworkInterface nextElement = networkInterfaces.nextElement();
111 | Enumeration inetAddresses;
112 | if(nextElement != null && (inetAddresses = nextElement.getInetAddresses()) != null) {
113 | while(inetAddresses.hasMoreElements()) {
114 | InetAddress nextElement2 = inetAddresses.nextElement();
115 | if(nextElement2 != null && !nextElement2.isLoopbackAddress() && nextElement2 instanceof Inet4Address) {
116 | return nextElement2.getHostAddress();
117 | }
118 | }
119 | }
120 | }
121 | } catch(Throwable ignore) {
122 | }
123 | return "10.1.10.1";
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - com.UCMobile
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | UC Proxy Capture
4 | Testing only
5 |
6 |
--------------------------------------------------------------------------------