本文章使用了javassist
,javaagent
对方法字节码进行动态修改。
从凌晨23:50开始研究这个问题,现在4:00成功
朋友玩服务器,发现从6.8日9:00开始1.16.5客户端无法进入多人模式
搜索发现好像是当天8号才出现这个问题
对mc不太熟,觉得是微软搞了什么动作,抓包啥的,没抓到。
在语言资源里找到这串字符串
简单说就是玩的离dao线ban模式,没权限给你多人模式。那为啥以前离线模式可以玩呢?不懂,研究一下Minecraft源代码
一开始我是直接jadx打开主程序,发现没什么东西。通过上面字符串引用的签名,直接搜索,发现有个引用的地方调用了账号验证方法,然后抛出异常:
找到jar包:
发现有个传统验证方法,但是应该已经弃用了:
一开始找到了一个项目:
但是我试了,不行,可能是版本啥的问题。
于是尝试去找反混淆的项目,比如MCP啥的,看MC的源码。
这里用了forge的开发环境,反混淆映射表是mapped_official频道的,可以看authlib包的源代码:
找来找去找到了mc主类和主界面类:
感觉不远了,继续找:
检查是否多人模式。跟进去,调用了authlib。socialInteractionsService
是一个接口,通过工厂方法创建一个com.mojang.authlib.yggdrasil.YggdrasilSocialInteractionsService
实例。发现这里就是判断是否允许多人登录的地方:
本来想用forge写一个mod修改,但是好像不行,或者我没找到文档。然后想着mod里写一个动态hook,尝试了一下没成功。最后想着用javaagent动态修改方法字节码。
找了一些教程,研究了一下,踩了很多坑,找了很多bug。
具体解决的问题:
ClassPool.getDefault()
报错java.lang.NoClassDefFoundError
,因为依赖冲突,加上shade插件。javassist.NotFoundException
:classname传进去的是左斜杠分隔路径的类名,跟了下javassist源码才知道类池用点分隔的类名查。
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
|
<project xmlns
=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0
.
0
<
/
modelVersion>
<groupId>org.example<
/
groupId>
<artifactId>agnet<
/
artifactId>
<version>
1.0
-
SNAPSHOT<
/
version>
<packaging>jar<
/
packaging>
<name>agnet<
/
name>
<url>http:
/
/
maven.apache.org<
/
url>
<properties>
<project.build.sourceEncoding>UTF
-
8
<
/
project.build.sourceEncoding>
<
/
properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins<
/
groupId>
<artifactId>maven
-
jar
-
plugin<
/
artifactId>
<version>
2.4
<
/
version>
<configuration>
<archive>
<!
-
-
打包时,设置MANIFEST.MF的信息
-
-
>
<manifestEntries>
<Premain
-
Class>org.example.PremainTest<
/
Premain
-
Class>
<Can
-
Redefine
-
Classes>true<
/
Can
-
Redefine
-
Classes>
<Can
-
Retransform
-
Classes>true<
/
Can
-
Retransform
-
Classes>
<
/
manifestEntries>
<
/
archive>
<
/
configuration>
<
/
plugin>
<plugin>
<groupId>org.apache.maven.plugins<
/
groupId>
<artifactId>maven
-
compiler
-
plugin<
/
artifactId>
<configuration>
<source>
8
<
/
source>
<target>
8
<
/
target>
<
/
configuration>
<
/
plugin>
<plugin>
<!
-
-
防止引用该jar的项目也使用javassist,与jar中javassist冲突
-
-
>
<artifactId>maven
-
shade
-
plugin<
/
artifactId>
<version>
3.1
.
0
<
/
version>
<executions>
<execution>
<phase>package<
/
phase>
<goals>
<goal>shade<
/
goal>
<
/
goals>
<configuration>
<createSourcesJar>true<
/
createSourcesJar>
<relocations>
<relocation>
<pattern>javassist<
/
pattern>
<shadedPattern>org.example.javassist<
/
shadedPattern>
<
/
relocation>
<
/
relocations>
<
/
configuration>
<
/
execution>
<
/
executions>
<
/
plugin>
<
/
plugins>
<
/
build>
<dependencies>
<dependency>
<groupId>junit<
/
groupId>
<artifactId>junit<
/
artifactId>
<version>
3.8
.
1
<
/
version>
<scope>test<
/
scope>
<
/
dependency><!
-
-
修改字节码时,使用javassist
-
-
>
<dependency>
<groupId>org.javassist<
/
groupId>
<artifactId>javassist<
/
artifactId>
<version>
3.27
.
0
-
GA<
/
version>
<
/
dependency>
<
/
dependencies>
<
/
project>
|
创建一个org.example.PremainTest
类:
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
|
package org.example;
import
javassist.ClassPool;
import
javassist.CtClass;
import
javassist.CtMethod;
import
java.lang.instrument.ClassFileTransformer;
import
java.lang.instrument.Instrumentation;
import
java.lang.instrument.UnmodifiableClassException;
import
java.security.ProtectionDomain;
public
class
PremainTest {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println(
"\n\n\n\nagent跑起来啦!====================================="
);
inst.addTransformer(new JavassistTransformer(), true);
}
public static void agentmain(String agentArgs, Instrumentation inst) throws UnmodifiableClassException {
inst.addTransformer(new JavassistTransformer(), true);
Class classes[]
=
inst.getAllLoadedClasses();
for
(
int
i
=
0
; i < classes.length; i
+
+
) {
if
(classes[i].getName().equals(
"YggdrasilSocialInteractionsService"
)) {
System.out.println(
"成功转换类:"
+
classes[i].getName());
inst.retransformClasses(classes[i]);
break
;
}
}
}
static
class
JavassistTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
if
(
"com/mojang/authlib/yggdrasil/YggdrasilSocialInteractionsService"
.equals(className)) {
try
{
System.out.println(
"正在转换类名:"
+
className);
ClassPool classPool
=
ClassPool.getDefault();
CtClass clazz
=
classPool.get(
"com.mojang.authlib.yggdrasil.YggdrasilSocialInteractionsService"
);
CtMethod method
=
clazz.getDeclaredMethod(
"checkPrivileges"
);
/
/
修改方法
method.setBody(
"{\n"
+
" chatAllowed = true;\n"
+
" serversAllowed = true;\n"
+
" realmsAllowed = true;\n"
+
" }"
);
System.out.println(
"成功修改checkPrivileges方法!方法签名:"
+
method.getLongName());
byte[] bytes
=
clazz.toBytecode();
clazz.detach();
return
bytes;
} catch (Throwable e) {
e.printStackTrace();
}
}
return
classfileBuffer;
}
}
}
|
mvn package
编译,生成jar包。
回到forge项目(或者启动器),运行参数加上-javaagent
:
修改方法成功:
多人游戏也开放了:
启动器命令行参数里加上这行:
完美
更多【MC禁止多人游戏引发的破解】相关视频教程:www.yxfzedu.com