14 Commits

Author SHA1 Message Date
MoonLeeeaf
b8246657d1 feat: 谋权篡位 & 强制置顶评论
Some checks failed
Android CI / build (push) Failing after 14m58s
2024-07-07 21:01:02 +08:00
满月叶
6b886b3182 docs: docs
Some checks failed
Android CI / build (push) Failing after 19m57s
2024-06-29 22:06:53 +08:00
满月叶
0f8c30b6c6 Update readme.md
Some checks failed
Android CI / build (push) Failing after 14m59s
2024-06-14 12:38:36 +08:00
满月叶
1a25a90358 chore: non-Chinese users tip 2024-06-14 12:37:43 +08:00
MoonLeeeaf
54f1597235 chore: desc, v1.2.1 released
Some checks failed
Android CI / build (push) Failing after 19m57s
2024-06-09 12:51:13 +08:00
MoonLeeeaf
68b3d96fdd fix: No updatrs 2024-06-09 12:48:17 +08:00
MoonLeeeaf
c6a3f015e5 feat: No updates, chore: screenshots 2024-06-09 11:06:17 +08:00
MoonLeeeaf
05f2d3915c chore: better toast
Some checks failed
Android CI / build (push) Failing after 14m58s
2024-06-08 20:57:11 +08:00
MoonLeeeaf
9543727c7a chore: no toasts 2024-06-08 19:16:12 +08:00
MoonLeeeaf
7a529652c5 chore: code 401 -> null 2024-06-08 18:16:23 +08:00
MoonLeeeaf
d43f1091d4 chore: readme 2024-06-08 18:06:55 +08:00
MoonLeeeaf
2b59a3a84d chore: 1.0.1 -> 1.1.0 2024-06-08 18:05:36 +08:00
MoonLeeeaf
7469415b2a feat: 反防抓包,强显再创按钮,不跟踪 2024-06-08 18:04:27 +08:00
MoonLeeeaf
5bc2e427df chore: readme 2024-06-08 14:46:52 +08:00
7 changed files with 306 additions and 39 deletions

View File

@@ -0,0 +1,35 @@
{
"allFiles": [
{
"file": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java",
"selection": {
"end": {
"column": 59,
"index": 9189,
"line": 224
},
"start": {
"column": 59,
"index": 9189,
"line": 224
}
}
},
{
"file": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/res/xml/config.xml",
"selection": {
"end": {
"column": 0,
"index": 0,
"line": 0
},
"start": {
"column": 0,
"index": 0,
"line": 0
}
}
}
],
"selectedFile": "/storage/emulated/0/MoonLeaf/Projects/FuckMaoNemo/app/src/main/java/io/github/moonleeeaf/fuckmaonemo/Hook.java"
}

BIN
.github/1.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 391 KiB

View File

@@ -12,8 +12,8 @@ android {
applicationId "io.github.moonleeeaf.fuckmaonemo" applicationId "io.github.moonleeeaf.fuckmaonemo"
minSdk 21 minSdk 21
targetSdk 33 targetSdk 33
versionCode 10100 versionCode 13000
versionName "1.0.1" versionName "1.3.p"
vectorDrawables { vectorDrawables {
useSupportLibrary true useSupportLibrary true

View File

@@ -31,6 +31,15 @@ public class ConfigActivity extends PreferenceActivity {
return false; return false;
}); });
findPreference("see_miao").setOnPreferenceClickListener((p) -> {
new AlertDialog.Builder(this)
.setTitle("屏蔽词列表")
.setMessage("当期列表:\n" + Hook.MIAO_LIST)
.show();
return false;
});
} }
} }

View File

@@ -1,6 +1,8 @@
package io.github.moonleeeaf.fuckmaonemo; package io.github.moonleeeaf.fuckmaonemo;
import android.app.Activity; import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Toast; import android.widget.Toast;
import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.IXposedHookLoadPackage;
@@ -11,10 +13,21 @@ import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage; import de.robv.android.xposed.callbacks.XC_LoadPackage;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.Proxy;
import java.util.HashMap;
import java.util.Map;
public class Hook implements IXposedHookLoadPackage { public class Hook implements IXposedHookLoadPackage {
private static boolean isHooked = false; private static boolean isHooked = false;
private XSharedPreferences xsp; private XSharedPreferences xsp;
private ClassLoader classLoader;
private int nohengheng;
private int aaaa;
public static final String MIAO_LIST = "妈 马 操 草 傻 艹 牛 逼 P 槽 涩 色 m";
public static final String[] MIAO = MIAO_LIST.split(" ");
private XC_MethodHook.Unhook force_set_work_myown_unhook;
@Override @Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam param) throws Throwable { public void handleLoadPackage(XC_LoadPackage.LoadPackageParam param) throws Throwable {
@@ -29,15 +42,15 @@ public class Hook implements IXposedHookLoadPackage {
protected void afterHookedMethod(MethodHookParam mParam) throws Throwable { protected void afterHookedMethod(MethodHookParam mParam) throws Throwable {
super.afterHookedMethod(mParam); super.afterHookedMethod(mParam);
Object initApp = XposedHelpers.getObjectField(mParam.thisObject, "mInitialApplication"); Object initApp = XposedHelpers.getObjectField(mParam.thisObject, "mInitialApplication");
hook(param, initApp.getClass().getClassLoader()); classLoader = initApp.getClass().getClassLoader();
hook(param);
} }
} }
); );
} }
} }
public static Method getMethod(Class clazz, String name, Class... args) throws NoSuchMethodException { public static Method getMethod(Class clazz, String name, Class<?>... args) throws NoSuchMethodException {
return clazz.getDeclaredMethod(name, args); return clazz.getDeclaredMethod(name, args);
} }
@@ -45,18 +58,26 @@ public class Hook implements IXposedHookLoadPackage {
return (Application) XposedHelpers.callStaticMethod(Class.forName("android.app.ActivityThread"), "currentApplication"); return (Application) XposedHelpers.callStaticMethod(Class.forName("android.app.ActivityThread"), "currentApplication");
} }
public void hook(XC_LoadPackage.LoadPackageParam param, ClassLoader classLoader) throws Exception { public static String fuck屏蔽词(String str) {
for (String i : MIAO) {
str = str.replaceAll(i, "" + i + "");
}
return str;
}
public void hook(XC_LoadPackage.LoadPackageParam param) throws Exception {
if (isHooked) return; if (isHooked) return;
else isHooked = true; else isHooked = true;
int nohengheng = 0; nohengheng = 0;
aaaa = 0;
xsp = new XSharedPreferences("io.github.moonleeeaf.fuckmaonemo", "config"); xsp = new XSharedPreferences("io.github.moonleeeaf.fuckmaonemo", "config");
XposedBridge.log("[FuckMaoNemo] 注入中..."); XposedBridge.log("[FuckMaoNemo] 注入中...");
// 拦截40x码 // 拦截40x码
if (xsp.getBoolean("fuck_40x", false)) { load("fuck_40x", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_拦截40x码"); XposedBridge.log("[FuckMaoNemo] Hook_拦截40x码");
XposedBridge.hookMethod( XposedBridge.hookMethod(
getMethod( getMethod(
@@ -72,53 +93,207 @@ public class Hook implements IXposedHookLoadPackage {
if(code >= 400 && code <500) { if(code >= 400 && code <500) {
Object rawRes = XposedHelpers.getObjectField(res, "rawResponse"); Object rawRes = XposedHelpers.getObjectField(res, "rawResponse");
XposedHelpers.setIntField(rawRes, "code", 200); XposedHelpers.setIntField(rawRes, "code", 200);
XposedBridge.log("[FuckMaoNemo] 拦截响应 40x"); XposedBridge.log("[FuckMaoNemo] 拦截响应 " + code + "");
String t = ""; String t = "响应码 " + code;
switch (code) { switch (code) {
case 401: case 401:
t = "拦截异常登出"; t = "阻止异常登出";
break;
case 422:
t = "已拦截封号页面替换资料卡";
break; break;
case 405: case 405:
t = "评论接口被禁止"; case 422:
t = "API 访问被拒绝,评论区或者已封禁账号?";
break; break;
default:
t = "未知拦截,响应码为 " + code;
} }
Toast.makeText(getApplication(), "[FuckMaoNemo] " + t, Toast.LENGTH_SHORT).show(); Toast.makeText(getApplication(), "[FuckMaoNemo] " + t, Toast.LENGTH_SHORT).show();
} }
} }
} }
); );
nohengheng++; });
}
// 绕过防沉迷 // 绕过防沉迷
if (xsp.getBoolean("fuck_fcm", false)) { load("fuck_fcm", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_绕过防沉迷"); XposedBridge.log("[FuckMaoNemo] Hook_绕过防沉迷");
XposedBridge.hookMethod( methodToVoid(getMethod(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.activity.WorkDetailActivity", classLoader), XposedHelpers.findClass("com.codemao.nemo.activity.WorkDetailActivity", classLoader),
"checkAntiAddictionState", "checkAntiAddictionState",
null null
));
});
// 强制显示再创作按钮
load("force_show_rework", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_强制显示再创作按钮");
XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.creativecenter.utils.bcm.bean.CreativeWorkDetailInfo", classLoader),
"isFork_enable",
null
), ),
new XC_MethodReplacement() { new XC_MethodReplacement() {
@Override @Override
protected Object replaceHookedMethod(MethodHookParam arg0) throws Throwable { protected Object replaceHookedMethod(MethodHookParam arg0) throws Throwable {
XposedBridge.log("[FuckMaoNemo] 拦截防沉迷方法调用"); return true;
return null;
} }
} }
); );
nohengheng++; });
// 不追踪
load("no_records", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_不追踪");
methodToVoid(getMethod(
XposedHelpers.findClass("cn.codemao.android.stat.CodeMaoStat", classLoader),
"recordEvent",
String.class,
Map.class
));
});
// 反防抓包
load("fuck_no_proxy", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_反防抓包");
// TODO其实可以从 OkHttp 底层去Hook的
methodToVoid(
getMethod(
XposedHelpers.findClass("okhttp3.OkHttpClient$Builder", classLoader),
"proxy",
Proxy.class
)
);
});
// 屏蔽更新
load("fuck_update", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_屏蔽更新");
methodToVoid(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.sdk.update.NetChangeReceiver", classLoader),
"onReceive",
Context.class,
Intent.class
)
);
});
// 强制置顶评论
load("force_top_comment", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_强制置顶评论");
XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.view.CommentOptionDialogV2", classLoader),
"checkIsSelf",
null
),
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam mp) throws Throwable {
XposedHelpers.setBooleanField(mp.thisObject, "isOwnWork", true);
} }
}
);
});
// 谋权篡位
load("force_set_work_myown", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_谋权篡位");
XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.activity.WorkDetailActivity", classLoader),
"setWorkDetailData",
null
),
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam mp) throws Throwable {
force_set_work_myown_unhook = XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.creativecenter.utils.bcm.bean.AuthorInfo", classLoader),
"getId",
null
),
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam hp) throws Throwable {
Method m = getMethod(XposedHelpers.findClass("com.codemao.nemo.util.LocalUserHelper", classLoader), "getUserInfo", null);
m.setAccessible(true);
Object usrInfo = m.invoke(null, null);
m = getMethod(usrInfo.getClass(), "getId", null);
m.setAccessible(true);
force_set_work_myown_unhook.unhook(); // 希望人没事
return m.invoke(usrInfo, null); // long 类型
}
});
}
}
);
});
// 防止屏蔽屏蔽词
load("fuck_miao", () -> {
XposedBridge.log("[FuckMaoNemo] Hook_反屏蔽");
XC_MethodHook hook = new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam mp) throws Throwable {
XposedHelpers.setObjectField(mp.thisObject, "content", fuck屏蔽词((String) XposedHelpers.getObjectField(mp.thisObject, "content")));
}
};
XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.fragment.WorkCommentFragment", classLoader),
"sendReply",
null
),
hook
);
XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.fragment.WorkCommentFragment", classLoader),
"sendComment",
null
),
hook
);
XposedBridge.hookMethod(
getMethod(
XposedHelpers.findClass("com.codemao.nemo.activity.CommentDetailActivity", classLoader),
"send",
null
),
hook
);
});
XposedBridge.log("[FuckMaoNemo] 执行完毕"); XposedBridge.log("[FuckMaoNemo] 执行完毕");
Toast.makeText(getApplication(), "[FuckMaoNemo] 加载成功 (≧▽≦)\n" + nohengheng + " 个功能加载", Toast.LENGTH_LONG).show(); Toast.makeText(getApplication(), "[FuckMaoNemo] 加载成功 (≧▽≦)\n" + nohengheng + " 个功能加载成功, " + aaaa + " 个失败", Toast.LENGTH_LONG).show();
}
public interface Callback {
public void onCallback() throws Exception;
}
public void methodToVoid(Method m) {
XposedBridge.hookMethod(m, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam arg0) throws Throwable {
return null;
}
});
}
public void load(String pref, Callback cb) {
if (xsp.getBoolean(pref, false)) {
try {
cb.onCallback();
nohengheng++;
} catch (Exception e) {
XposedBridge.log(e);
aaaa++;
}
}
} }
} }

View File

@@ -8,7 +8,7 @@
<Preference <Preference
android:title="作者" android:title="作者"
android:summary="编程猫 @满月叶\nGitHub @MoonLeeeaf" /> android:summary="编程猫 @满月叶\nGitHub @MoonLeeeaf\n喵呜~" />
</PreferenceCategory> </PreferenceCategory>
@@ -17,7 +17,42 @@
<SwitchPreference <SwitchPreference
android:key="fuck_40x" android:key="fuck_40x"
android:title="阻止服务端响应 40x 码" android:title="阻止服务端响应 40x 码"
android:summary="启用此开关后,将可以:\n拦截 401 码强制登出账号\n强制浏览已封禁账号的资料卡\n评论接口检测\n其他作用" /> android:summary="拦截 401 码强制登出账号\n强制浏览已封禁账号的资料卡\n评论接口检测\n获得调试信息?" />
<SwitchPreference
android:key="no_records"
android:title="不要追踪我"
android:summary="启用后,模块将会拦截 CodeMaoStat.recordEvent(str, map) 调用(比如点击创作按钮都会发送一个 collect 请求),风险未知" />
<SwitchPreference
android:key="fuck_update"
android:title="屏蔽更新"
android:summary="主页不会弹更新对话框,不会拦截设置里手动查看的更新" />
<SwitchPreference
android:key="fuck_no_proxy"
android:title="反防抓包"
android:summary="目前只发现账号相关的有反防抓包,真无法抓包就去刷原生安卓吧,亲测有效" />
</PreferenceCategory>
<PreferenceCategory android:title="评论">
<SwitchPreference
android:key="force_top_comment"
android:title="强制置顶评论"
android:summary="灵感来源于 CodeCat可以无视作品作者直接置顶评论注意只支持 Nemo 作品其它无效响应406码" />
<SwitchPreference
android:key="fuck_miao"
android:title="别屏蔽我词语!"
android:summary="让部分屏蔽词无法再被屏蔽,请勿用于恶语相向,否则被举报不要来找我!!\n可能会导致缩短评论字数上限算法有待优化" />
<Preference
android:key="see_miao"
android:title="查看支持防屏蔽的词汇"
android:summary="对应上面的 防屏蔽" />
</PreferenceCategory> </PreferenceCategory>
@@ -26,13 +61,20 @@
<SwitchPreference <SwitchPreference
android:key="fuck_fcm" android:key="fuck_fcm"
android:title="绕过防沉迷" android:title="绕过防沉迷"
android:summary="滞空防沉迷检测方法的调用实现无伤速通破解防沉迷,无需 Player 链接" /> android:summary="滞空防沉迷检测方法的调用实现无伤速通破解防沉迷,无需 Player 链接不支持叽叽猫砸进里面的岛3不支持内嵌社区网页的防沉迷那不属于我的能力范围" />
<SwitchPreference <SwitchPreference
android:key="force_rework" android:key="force_set_work_myown"
android:title="强制显示再创作" android:title="谋权篡位"
android:enabled="false" android:summary="伪装任意作品是你自己的,可以:\n直接编辑作品源码\n其他用途" />
android:summary="使作品的 再创作 按钮永远显示即使作品并未设置为开放源代码未制作QWQ" />
</PreferenceCategory>
<PreferenceCategory android:title="实验">
<SwitchPreference
android:key="force_show_rework"
android:title="强制显示再创作图标"
android:summary="使作品的 再创作 按钮永远显示,即使作品并未设置为开放源代码(显示了也没啥用,服务端给你拦截了,报错信息为 作品未开源,亲测无效)" />
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -2,11 +2,17 @@
弥补 编程猫Nemo/点个猫 的不合理特性,功能增强等特性(。・ω・。) 弥补 编程猫Nemo/点个猫 的不合理特性,功能增强等特性(。・ω・。)
提示:本项目只在 GitHub 存在, **严禁任何人或任何组织在没有得到我的书面许可、公告明示许可及社交账号发帖许可的情况下照搬本仓库** <!-- GitCode, 说的就是你, 到时候如果被我发现你搬我仓库我迟早要找你算账 -->
### For non-Chinese users
This project is for Codemao Nemo. Most of the time, you needn't use this Xposed module.
### 使用 ### 使用
0. 已安装 LSPosed 框架(由于使用了 XSharedPreferences免 Root 的 Xposed 框架不支持?) 0. 建议点个猫版本为 4.3.4已安装 LSPosed 框架(由于使用了 XSharedPreferences故免 Root 的 Xposed 框架貌似无法正常运作)
1. 从 [Releases](./releases/) 或 [Actions](./actions/) 下载(注:签名不同,除非你有核心破解),普通用户建议下载 Releases 版本 1. 从 [Releases](../../releases/) 或 [Actions](../../actions/) 下载(注:签名不同,除非你有核心破解),普通用户建议下载 Releases 版本
2. 安装并激活此模块,作用域选择 点个猫(com.codemao.nemo),强制停止 2. 安装并激活此模块,作用域选择 点个猫(com.codemao.nemo),强制停止
@@ -14,7 +20,7 @@
4. 打开点个猫,然后 Enjoy it (≧▽≦) 4. 打开点个猫,然后 Enjoy it (≧▽≦)
5. 使用过程中存在任何问题欢迎提到 [Issues](./issues/)(需要 GitHub 账号) 或者是我的发布页[评论区](https://shequ.codemao.cn/work/227492197)(需要编程猫账号),建议点个猫版本为 4.5.0 5. 使用过程中存在任何问题欢迎提到 [Issues](../../issues/)(需要 GitHub 账号) 或者是我的发布页[评论区](https://shequ.codemao.cn/work/227492197)(需要编程猫账号)
小声BB我相信各位猫友大多都不晓得这些东西因此它可能并不适合你 小声BB我相信各位猫友大多都不晓得这些东西因此它可能并不适合你