[LayaAir 1.0]微信小游戏提审后,提示说代码侵权

微信小游戏提审后,提示说代码侵权,你们都是怎么解决的呢?
2款游戏都是自己开发的,所以有部分公共代码是一样的;
已邀请:

水手

赞同来自:

用同一个主体提交,貌似微信就不会说侵权。
如果一定要用不同主体,拿就混淆代码,,这里有个文章:https://blog.csdn.net/linguifa ... 87065

187*****978

赞同来自:

*文章的意图为解决工作中遇到的问题,请开发者把技术用到正确的方向**
文章原文
https://blog.csdn.net/koljy111 ... 55940
有时候多个游戏代码复用会被微信判断为代码抄袭,如何解决?



解决方案
修改类名,添加花指令,修改方法名和成员名

修改越多,通过率越高

显然人为修改是非常耗费时间的,所以制作了个软件

经测3个游戏,通过率为100%

需要的可以进群下载





微信小游戏代码侵权问题
微信代码侵权
微信小游戏代码侵权
小游戏代码侵权
小游戏侵权

涉嫌代码侵权,解决方案
微信小游戏侵权避开技巧
信小游戏代码包侵权解决方案升级版
 
随着微信小游戏平台的普及和完善,越来越多的游戏开发者加入到微信小游戏开发队伍中,很多公司开发者一个团队就开发了几十款游戏。
目前,微信小游戏同质化严重,大多是一套代码,换换皮肤就变成了一款新游戏。更有甚者,有些开发者直接反编译别人的游戏包进行简单修改,变成自己的产品申请上架。严重损害著作权所有人的利益和平台规则。
为了遏制和打击这种现象,微信小游戏平台有一个环节是机审,审查代码包的相似度,如果代码包相似度超过一定的比例就会被判定为“代码包侵权”,审核不予通过。
这本身是好事,但是却产生了大量“误杀”行为。很多公司开发团队用同一套自己研发的游戏引擎开发出不同的产品,申请上线的时候会判定为“侵权”。这就郁闷了,自己侵权自己。
虽然微信官方说可以申诉,但是时间不受控制,这不是一个上策。更好的方式是修改代码,混淆代码,让其看起来和别的项目不像,不要触发微信代码机审的“黑机关”。
好了,废话了半天,该上菜了!希望各位读者收获满满!混淆代码的思路:
1、修改所有代码Class 类名称不要重复
2、修改全部全局属性、和至少 1/3的方法名称不要重复(这部分可以写程序去批量改)
3、打乱那些基类、工具类里面的方法顺序, 举例 Class A里面有 Function B、C、D,在不同项目里面改乱顺序,项目1里面的 Class A中顺序是B、D、C;项目2里面的 Class A中顺序是D、C、B;
4、如果定义了 package包名,包名也改掉;
5、每个类里面 随机插入一些废代码(注意,不是直接复制独立的废代码文件到项目中,这种方式无效)
6、如果是白鹭引擎,记把exml里面的代码也改改,各种重用的组件比如按钮、Class名称和文件名都改一下。
7、如果是 Laya 2.0项目,class 前面 不要用default 定义。
按照以上思路,修改到位,经过作者30+款产品上线的经验,通过率99.99%。
以上修改思路是有一定工作量的,而且是枯燥的,所以最好写代码脚本去处理,作者一般是手动+自动相结合的方式去混淆代码,以下代码实现了部分混淆代码的功能:
[code]/* 为项目添加干扰代码,主要做这几件事:
1、修改每个类里面的私有方法,添加一个随机数
2、在代码里面随机一行插入一个随机命名的方法体
3、在代码里面随机一行插入一行没有意义的代码
*/
const LINENUM = 20;
const LINENUM_RADOM = 13;

var fs = require('fs');
var path = require('path');

var filterFils = ["Base64", "ThemeAdapter","AssetAdapter", "Platform", "wxgamesdk"];//忽略文件
var filterDirs = ["xxxx"];//忽略目录
var traceName = "xxxx";//添加的干扰代码
var funString = '_xxxx_fun(){ console.log("';//添加的方法体
var root_Url = "D:/code/project/src";//项目diam路径

fileDisplay(path.resolve(root_Url));

/**
* 文件遍历方法
* @param filePath 需要遍历的文件路径
*/
function fileDisplay(filePath){
//根据文件路径读取文件,返回文件列表
fs.readdir(filePath,function(err,files){
if(err){
console.warn(err)
}else{
//遍历读取到的文件列表
files.forEach(function(filename){
//获取当前文件的绝对路径
var filedir = path.join(filePath,filename);
//根据文件路径获取文件信息,返回一个fs.Stats对象
fs.stat(filedir,function(eror,stats){
if(eror){
console.warn('获取文件stats失败');
}else{
var isFile = stats.isFile();//是文件
var isDir = stats.isDirectory();//是文件夹
if(isFile){
console.log(filename,filedir);
let onlyName = filename.split(".")[0];
if(filename.indexOf(".ts") != -1 && filterFils.indexOf(onlyName) == -1){
changeDode(filedir);
}
}
if(isDir){
if(!filterDirs || filterDirs.indexOf(filename) == -1){
fileDisplay(filedir);//递归,如果是文件夹,就继续遍历该文件夹下面的文件
}
}
}
})
});
}
});
}

function changeDode(phppath){
//const phppath = "D:/test/PlayGameCtrl.ts";
//phppath = "D:/test/HomeTop.ts";

console.log("执行文件:" + phppath);
let phpContent = fs.readFileSync(phppath, { encoding: "utf8" });
//console.log(phpContent);

//====修改私有方法名==================================================================
//let arr = phpContent.match(/function\s*(\w+)/);
let arr = phpContent.match(/private .*?\(/g);
console.log(arr);
if(arr){
let len = "private ".length;
for(var i=0; i<arr.length; i++){
let str = arr[i];
if(str.indexOf("private static") != -1) continue;
if(str.indexOf("private async") != -1) continue;
if(str.indexOf("private get") != -1) continue;
if(str.indexOf("private set") != -1) continue;
if(str.indexOf("= new ") != -1) continue; //过滤这种:private con:eui.Rect = new eui.Rect();
let name = str.substr(len, str.length - len - 1);
console.log(name);
let number = Math.floor(Math.random() * 9999);
let name2;
let lastIndex = name.lastIndexOf("_");
if(lastIndex == -1){
name2 = name + "_" + number;
}else{
name2 = name.substr(0, lastIndex) + "_" + number;
}
let name2s = name2 + "(";
//phpContent = phpContent.replace("private "+name + "(", "private " + name2s); //不能直接替换需要用正则,因为一个文件里面可能有多个类,可能存在多个同名方法
var regExp0 = new RegExp("private "+name + "\\(", 'gi');
phpContent = phpContent.replace(regExp0, "private " + name2s);

var regExp = new RegExp("this."+name + "\\(", 'gi');
phpContent = phpContent.replace(regExp, "this." + name2s);
regExp = new RegExp("this."+name + "\\," , 'gi');
phpContent = phpContent.replace(regExp, "this." + name2 + ",");
regExp = new RegExp("this."+name + "\\)" , 'gi');
phpContent = phpContent.replace(regExp, "this." + name2 + ")");

var regExp2 = new RegExp("self."+name + "\\(", 'gi');
phpContent = phpContent.replace(regExp2, "self." + name2s);
}
}

//====增加干扰代码==================================================================
let arr2 = phpContent.split("\n");
//console.log(arr2.length, arr2);
let isInterFace;
for(var i=LINENUM; i<arr2.length - 1; i++){
if(!arr2[i]) continue;
let formatStr = Trim(arr2[i], "g");
if(formatStr == "" || formatStr == "{") continue;
arr2[i] = String(arr2[i]);

if(arr2[i].indexOf("return") !=-1) continue;
if(arr2[i].indexOf("class ") !=-1) continue;
if(arr2[i].indexOf("super(") !=-1) continue;
if(arr2[i].indexOf("public constructor") !=-1) continue;
if(arr2[i].indexOf("else") !=-1) continue;
if(arr2[i].indexOf("else if") !=-1) continue;
if(arr2[i].indexOf("//") !=-1) continue;
if(arr2[i].indexOf("catch(") !=-1) continue;
if(arr2[i].indexOf(",") !=-1 && arr2[i].indexOf("(") ==-1) continue;//object里面的key value
if(arr2[i].indexOf("public ") !=-1 && arr2[i].indexOf("{") ==-1) continue;//属性
if(arr2[i].indexOf("private ") !=-1 && arr2[i].indexOf("{") ==-1) continue;//属性
if(arr2[i].indexOf("protected ") !=-1 && arr2[i].indexOf("{") ==-1) continue;//属性
if(arr2[i].indexOf("public ") !=-1 && arr2[i].indexOf("{") !=-1 && arr2[i].indexOf("=") !=-1) continue;//属性
if(arr2[i].indexOf("private ") !=-1 && arr2[i].indexOf("{") !=-1 && arr2[i].indexOf("=") !=-1) continue;//属性
if(arr2[i].indexOf("function") !=-1 && arr2[i].indexOf(":") !=-1) continue; //object里面的key value

if(!arr2[i-1]) continue;
let formatStr2 = Trim(arr2[i-1], "g");
arr2[i-1] = String(arr2[i-1]);
if(arr2[i-1].indexOf("return") !=-1) continue;
if(arr2[i-1].indexOf("if") !=-1 && arr2[i-1].indexOf("{") ==-1) continue;
if(arr2[i-1].indexOf("else") !=-1 && arr2[i-1].indexOf("{") ==-1) continue;
if(arr2[i-1].indexOf("for") !=-1 && arr2[i-1].indexOf("{") ==-1) continue;
if(arr2[i-1].indexOf(",") !=-1 && arr2[i-1].indexOf("(") ==-1) continue;//object里面的key value
if(formatStr == "})" && formatStr2 == "}") continue;
if(formatStr == "})" && formatStr2 == "") continue;

let isFun = (arr2[i].indexOf("private ") !=-1 && arr2[i].indexOf("(") !=-1) ||
(arr2[i].indexOf("public ") !=-1 && arr2[i].indexOf("(") !=-1) ||
(arr2[i].indexOf("/**") !=-1);
if(isFun && (formatStr2 == ""|| formatStr2 == "*/" || arr2[i-1].indexOf("}") != -1 || arr2[i-1].indexOf("//") != -1 || arr2[i-1].indexOf("class") != -1) ) continue;
if(isFun && arr2[i-1].indexOf("private ") !=-1 ) continue;
if(isFun && arr2[i-1].indexOf("public ") !=-1 ) continue;

if(arr2[i].indexOf("function") !=-1 && arr2[i-1].indexOf(",") !=-1) continue; //object里面的key value
if(arr2[i].indexOf("}") !=-1 && arr2[i-1].indexOf(":") !=-1) continue;

let formatStr3 = Trim(arr2[i+1], "g");
arr2[i+1] = String(arr2[i+1]);
if(formatStr == "}" && formatStr3 == "}") continue;
if(formatStr == "}" && formatStr3 == "") continue;

let str = getAddSpace(arr2[i]) + traceName + "(\"" + getRadomStr() + "\");";
arr2.splice(i,0,str);
let randomNum = Math.random();
i = i + LINENUM + ( Math.round(randomNum * LINENUM_RADOM) * (randomNum<0.5 ? 1:-1) );//随机行数添加
}

//====增加干扰代码 增加干扰方法 ==================================================================
let pbArr = phpContent.match(/public .*?\(/g);
let count = (arr ? arr.length : 0) + (pbArr ? pbArr.length : 0);
let rate = 0.5;
if(count > 5) rate = 0.4;
if(count > 10) rate = 0.25;
if(count > 20) rate = 0.15;
rate *= 0.75
for(var i=LINENUM; i<arr2.length - 1; i++){

let formatStr = Trim(arr2[i], "g");
arr2[i] = String(arr2[i]);
let formatStr2 = Trim(arr2[i-1], "g");
arr2[i-1] = String(arr2[i-1]);
let formatStr3 = Trim(arr2[i+1], "g");
arr2[i+1] = String(arr2[i+1]);

let canInsert = false;
let isFun = ( (arr2[i].indexOf("private ") !=-1 || arr2[i].indexOf("public ") !=-1) && arr2[i].indexOf("(") !=-1) && arr2[i].indexOf("=") ==-1;
var str = '';
if(isFun && formatStr2 == "}"){
canInsert = Math.random() < rate;
str = getAddSpace(arr2[i]) + 'private ' + getRadomStr(4, 1) + funString + getRadomStr() + '"); }' + '\n';
}
else{
let str3 = arr2[i+1];
isFun = ( (str3.indexOf("private ") !=-1 || str3.indexOf("public ") !=-1 || str3.indexOf("/**") !=-1) && str3.indexOf("(") !=-1) && str3.indexOf("=") ==-1;
if(formatStr == "" && isFun && formatStr2 == "}") {
canInsert = Math.random() < rate;
str = getAddSpace(arr2[i-1]) + 'private ' + getRadomStr(4, 1) + funString + getRadomStr() + '"); }';
}
}
if(canInsert){
arr2.splice(i,0,str);
}
}

phpContent = arr2.join("\n");
//console.log(phpContent);

fs.writeFileSync(phppath, phpContent, { encoding: "utf8" });
console.log("执行完成!--" + phppath);
}

function getAddSpace(str){
if(!str) return "";
let num = str.length - lTrim(str).length;
let formatStr = Trim(str, "g");
if(formatStr == "}")
num += 4;
let space = "";
while(num > 0){
space += " ";
num--;
}
return space;
}
function getRadomStr(len, type){
len = len || Math.floor(Math.random()*32) + 1;
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
if(type == 1) $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'; //非数字
var maxPos = $chars.length;
var pwd = '';
for (var i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
function Trim(str, is_global) {
//console.log("==", str)
str = String(str);
var result;
result = str.replace(/(^\s+)|(\s+$)/g,"");
if(is_global && is_global.toLowerCase()=="g"){
result = result.replace(/\s/g,"");
}
return result;
}
function lTrim(str) {
str = String(str);
var result = str.replace(/(^\s+)/g,"");
return result;
}
[/code]

要回复问题请先

商务合作
商务合作