11RIA 闪客社区 - 最赞 Animate Flash 论坛

搜索
楼主: general_clarke
上一主题 下一主题

[交流 & 讨论] AS3转码其他语言(本帖以 C#+Unity 举例),工具开发记录

[复制链接] TA的其它主题
 楼主| 发表于 2018-11-12 12:04:48 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-13 13:02 编辑

一个月后。

C语言程序员不干了。

这位同僚告诉我太难,搞不定。
我询问难在哪里,得到回复是“垃圾回收机制搞不定”

C语言并没有as3/java一样的垃圾回收机制,
这会导致不得不为对象设置手工释放。

我寻找迁就的方案,比如为每个类自动生成destroy方法,
这个工作在转成C语言前在AS端做完,工作量算我的。
同僚仍然表示不行,提出了很多其他问题,希望放弃这个项目,
准确地说,希望通过完成不了功能和提出难点让我主动放弃这个项目。

不为则易者亦难,
时值我司第一个手游项目《机战坦克》(现已停运)临近尾声,
继续做下去只会产生问题掣肘。
于是as3转c的工作暂停,
同僚改为负责新项目发布的工作。
回复

使用道具 举报

 楼主| 发表于 2018-11-13 13:09:06 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-14 14:21 编辑

【三】

AS3转换C语言已停止一段时间,
游戏上线工作如火如荼。

我们对素材图进行了一定的加密,代码也需要进行加密混淆。
破解无加密混淆的swf成本过低,
就算不担心有人私自架设服务器,对着清晰的代码可以轻易编写防不胜防的作弊软件。

我们出资数千购买国内最出名的SWF加密混淆工具。
工具虽好,无法满足我们的需求。
此工具对ANE和IOS发布支持不良。

我们另有一些基于反射的需求,故联系了工具作者,希望对工具添加定制的功能。
除额外的资金外,工具作者反馈添加支持的时间是两周,且“不确定”

我们可以理解工具作者也有自己的时间安排,不可能为每个购买者提供足够定制支持。
然一个即将上线公测的项目接受这个代价太难了。
这个“不确定”也让我们无法期待日后加密软件能得到良好维护。

将“AS3”转换为“加密后的AS3”,相当于代码转换,
求人不如求己,既然我们在做这个工具,
自己来做AS3混淆。


回复

使用道具 举报

 楼主| 发表于 2018-11-13 13:23:11 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-26 15:59 编辑

符号混淆没有性能代价。
这不能阻止反编译,但可以极大地增加破解成本,
难读代码能有效劝退以兴趣或小利为目的大多数破解者。

符号混淆,分为编译前对源码混淆,以及编译后解析SWF文件的Tags格式混淆其中的字符池。

var a:Sprite = new Sprite;
a.name = "A";
var b:ClassA = new ClassA;
b.name = "B";

应被混淆成
var _1_:Sprite = new Sprite;
a.name = "A";
var _2_:_3_ = new _3_
_2_._4_ = "B";

总结地说,
我们自行编写的类名和属性需要混淆,ClassA以及属于ClassA的"name"需要被混淆。AIR运行时和第三方类(主要是ANE对接类)则不混淆,Sprite的"name"属性是不能混淆的

为了完成上述工作,混淆工具必须了解每个类是否要加密,以及每个符号"name"的定义位置。
这比AS3转JS难了不少,只好投入额外的几周时间来升级。

回复

使用道具 举报

 楼主| 发表于 2018-11-13 15:38:19 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-26 16:00 编辑

几周后,方案完成了。
对文件的每个符号(AS3AtomSymbol)进行检查。
以符号a为例

如果在这个符号所在function里面找到了"var a"语句,那么它是局部变量。
如果在这个符号所在class里面找到了"public/protected/private var a"语句,它是成员变量。
如果在这个符号所在package的import语句导入类包含a类,它是类名。
如果a是一个顶层类,或当前文件同文件夹有其他as文件名字叫a.as,这个a也是类名。

在当前类找不到时递归去找其父类直到Object

诸如a.name这样的符号,用同上的办法检查到其中的a究竟是类名、是局部变量名还是成员变量名
并根据a的类型,是我们自行开发的还是官方或第三方类,决定name是否需要混淆。

经过这样的升级,
代码转换工具能成功地将AS转换成混淆AS。

比起第三方工具,
自制工具能随意地根据项目进行扩展,跳过应用反射的部分,
甚至可以在混淆前检查一遍代码或作出一些预处理。

为了使转换后的代码可读,我们实际加了注释

var a:ClassA = new ClassA;
a.name = "abc";
转换为
//var a:ClassA = new ClassA;
var v05234579:v024688945 = v024688945;
//a.name = "abc"
v05234579.v08343427 = "abc"

同时生成了一个字典文件,字典文件记录了符号与混淆后的符号对应关系。
于是,我们调试时和后台随时可以根据字典确定错误堆栈或者协议内正确的变量名,甚至可根据字典解除混淆,反编译成原始代码。

而破解者因为没有此字典和注释,阅读反编译代码事倍功半。




回复

使用道具 举报

 楼主| 发表于 2018-11-13 17:35:09 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-13 17:58 编辑

附一个类转换前后的效果,这个类制作的是弹出对话框右上角的关闭图标“X”。
看了一遍混淆后的代码,反正我自己读不懂,破解者不见得比我高明

  1. package tank2014x.mobile.panels.uiControls
  2. {
  3.         import flash.display.DisplayObject;
  4.         
  5.         import generalMVC.display.SOTSprite;
  6.         import generalMVC.ui.UIBase;
  7.         
  8.         import starling.display.STLSprite;
  9.         
  10.         public class UIClose extends UIBase
  11.         {
  12.                 public var bg:UI9GridGradual;
  13.                 public var fork:DisplayObject;
  14.                 public function UIClose(mc:*=null, initObj:Object=null)
  15.                 {
  16.                         if(!mc){
  17.                                 mc = new SOTSprite(new STLSprite);
  18.                         }
  19.                         super(mc, initObj);
  20.                         
  21.                         bg = new UI9GridGradual;
  22.                         bg.radius = 65;
  23.                         bg.setSize(130,130);
  24.                         bg.setColor(0xDEDEDE,0);
  25.                         //bg.visible = false;
  26.                         bg.x = bg.y = -65;
  27.                         bg.showOn(this.mc);
  28.                 }
  29.         }
  30. }
复制代码


  1. package v0326891.v0780146.v0264284.v0955421{
  2.         import flash.display.DisplayObject;
  3.         import v0263546.v0284825.v0284948;
  4.         import v0263546.v0264038.v0264161;
  5.         import starling.display.STLSprite;
  6.         public class v01167104 extends v0264161
  7.         {
  8.                 public var v0260225:v01061078;
  9.                 public var v01167227:DisplayObject;
  10.                 public function v01167104 (v0291590:* = null, v0480518:Object = null){
  11.                         if (!v0291590){
  12.                                 v0291590 = new v0284948(new STLSprite);
  13.                         }
  14.                         super(v0291590, v0480518);
  15.                         v0260225 = new v01061078;
  16.                         v0260225.v01063784 = 65;
  17.                         v0260225.v01063907(130, 130);
  18.                         v0260225.setColor(0xDEDEDE, 0);
  19.                         v0260225.x = v0260225.y = -65;
  20.                         v0260225.v0317543(this.v0291590);
  21.                 }
  22.         }
  23. }
复制代码

P.S.  cross写成fork,这个程序员晚上我去教育他。
回复

使用道具 举报

 楼主| 发表于 2018-11-14 16:25:40 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-14 17:24 编辑

【四】

和多数as3工程师一样,楼主平时在用FlashBuilder
有个很牛逼的编辑器叫做IntellIJ Idea,据说可以编辑as3,容我了解一下。

鼓吹Idea的同时一般会拉Eclipse出来批斗,
用词犀利颇有当年转cocos程序员批斗flash的架势。

这些多是跟风作,半桶水无有效内容的文章不少。
筛选阅读了约5篇有些营养文章后略有失望。

Idea编辑as3依赖于插件,此编辑器并未让我看到双眼一亮的功能。
比起Eclipse,Idea的核心优势似乎是调试输出变量的便利,以及更友好的代码提示。
还有相当数量的次要优势,例如对Git支持更好、支持javaScript边改边显示、更省力的代码模板、剪贴板能保存多次复制的内容等等。

同时我也搜索到了不少Idea编辑器编译和发布失败的例子。
对在线项目不值得冒险换编辑器。

对于优势这些,我认为只要为FlashBuilder/Eclipse编写插件可以实现。

Eclipse插件,届时我并没编写过这种东西。
FB用了这么久,是时候让它“升级”一下了。


回复

使用道具 举报

 楼主| 发表于 2018-11-14 16:44:33 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-14 17:17 编辑

因为插件是自己做的,所以一定符合自己的代码风格,也能针对项目架构表现出其他插件做不出智能。
此插件有且只有一个热键,这个热键的作用是“根据光标位置猜我要写什么,自动补出来”

那么先定几个小目标。
下面这些代码我们每天都在敲,浪费时间和脑力。

目标1:
光标在true上按某个键变false
光标在private上按某个键变public

目标2:
我希望在输入"mc.scaleX = 2;"之后按下某个键,程序能自动地补充后一句"mc.scaleY = 2;"
目标3:
光标在var i:int上按某个键变i(一段代码因复制或解除注释时出现两个以上var i,用于去除重复声明i的警告)

目标4:
func(123, "abc", a);
希望选中这一行之后按下某个键,在FB中产生模板,如下图
QQ截图20181114165413.png
就像FB自带的代码模板一样,之后可以按Table在func 123 "abc" a四个位置之间切换,
这样修改各个参数时不需要使用鼠标逐个点选定位或连续敲“→”


目标5:"|"表示光标位置,在如下代码中
if(a is MovieClip){
    |
}
绝大多数情况我要输入的是
var quote:MovieClip = a as MovieClip;
我认为上下文已经足够了,按下热键程序应自动为我补出这句。

与此同理还有
var b:MovieClip = event.target|
希望补充" as MovieClip"


再如
public var text:String;
public function setText(text:String):void{
    this|
}
希望补充".text = text;"


回复

使用道具 举报

 楼主| 发表于 2018-11-14 16:51:19 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-26 16:05 编辑

关于Eclipse插件,通过百度搜索教程自学,
做了这样的东西
http://www.11ria.com/forum.php?m ... d=23&extra=page%3D1
这是一个剪贴板和文件跳转的扩展插件。

我本人对java并不熟练,编写速度可能只有写as3的两成。
编写插件需要了解大量的库,学习和制作时间太长了。
为完成上述内容开销了大概一周。

为了完成楼上几个“小目标”,需要完整地了解AIRSDK对as3文件的整个处理过程

——开什么玩笑!

AIRSDK也有代码解析工具,首先将as3文本文件解析成语法树,
以某种数据结构保存起来。反编译AIRSDK的Java代码后,发现这部分巨长而且因为反编译导致脏乱差

为了完成楼上的“小目标”,我需要判断光标位置的上下文,

1,需要精通AIRSDK解析as3文件后的数据结构。
2,需要知道Eclipse用于生成模板、文件定位等的API,
3,需要知道swing框架,以及用来在FB编辑器窗口将结果字符串显示出来的API。

几个礼拜是学不完的。
就算上面的内容都学完了,
4,比起用来编写插件的Java并频繁扩展,我想写as3。





回复

使用道具 举报

 楼主| 发表于 2018-11-14 17:13:27 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-16 15:40 编辑

为了懒惰,必须设计一劳永逸的办法。
既然我已做了解析as3的工具,那么就不需要AIRSDK来解析as3。

只学习以下几个Eclipse的API:

1,选中若干个文字
2,插入或覆盖若干文字
3,编辑器跳转到指定文件的指定坐标位置
4,根据字符串产生一个模板并显示出来

前三个是Eclipse编辑器功能,搜其他插件开发者的例子马上就查到了。
最后一个as3模板是AIRSDK中的功能,通过反编译AIRSDK,搜索字符串"template",
在两天后整理清楚了用法。

之后,
做一个AIR程序,打包成exe
每次打开FlashBuilder时同时启动插件,插件调用打开这个AIR制作的exe程序。
AIR程序和插件之间用Socket连接,能相互发送信息。

执行逻辑如下:

1,在编辑器选中某位置
2,按下我希望的热键
3,插件通过Socket将当前文件地址和光标位置发给AIR
4,AIR程序根据文件地址,使用自制的as3解析工具将其解析成语法树
5,AIR程序根据光标位置和语法树知道光标所在单词及其上下文
6,AIR程序根据上下文进行处理,得出结果,结果是“用来插入或覆盖的字符串”,“跳转到某位置的命令”,或者“用于创建代码模板的字符串”
7,AIR程序通过Socket发送命令给插件,调用上述提到的4个API

藉此完成打开或跳转文件、选择某些字符、覆盖插入字符,或创建和显示代码模板。

因此
AIRSDK是如何编译as3文件的,这部分跳过不看。
Java制作的插件一经做好,在不增加API的前提下无需修改,
之后只需要修改与其对接的AIR程序,便可以抛弃Java愉快地继续写as。






回复

使用道具 举报

 楼主| 发表于 2018-11-15 17:21:08 | 显示全部楼层
本帖最后由 general_clarke 于 2018-11-16 15:46 编辑

从网上下载了一个最简单的Eclipse插件例子,其效果是菜单上多出一个按钮,点击此按钮会弹出HelloWorld弹窗。
修改此例,添加Ctrl+4作为触发插件函数的热键。
经过网上搜索和尝试,找到了获得当前正在编辑文件名、和光标位置的办法。
Socket的资料比较多,虽然和AS3的Socket中间经过个别编码转换,实现的也比较快。最后制订AS3从Socket发回4种命令的格式,以及在Java端对发回命令做解释器

为了方便调试,额外做了一条命令让插件弹出一个弹窗充当trace

经过两天时间,
按下Ctrl+4成功地将光标下的true转成false,将addEventListener转成removeEventListener


此插件经过多次改良,完成了前面提到的5个目标,并在根据个人的编码习惯继续进化
一些扩展我最初未能想到,但是做出后连自己也兴奋不已。
插件一键处理相当复杂语法,比如将同步的代码改成异步的。
插件一键从字符串跳转到类,比如根据“直线通常弹模型”这个字符串查文件,将编辑器跳转到"SimpleBullet.as"
根据玩家或测试师提供的报错信息,不用手工定位,直接将编辑器跳转到出错位置。

还有诸多便利的方法,每天在用,也一直在进化。如
aaa.bbb = 10;
光标停在aaa上按下Ctrl+4,这句会变成
if(aaa){
  aaa.bbb = 10;
}


a.arr[
在最后位置按下Ctrl+4,这句会变成
a.arr[a.arr.length-1]



var a:String = "abcd|efg"
光标位置按下Ctrl+4,变成
var a:String = "abcd"+变量+"efg"
"变量"位置利用模板处理,转换后被自动选中,直接输入要插入的变量、有代码提示。


var file:File = new File("C:\myFolder\myFile.txt");
其中的地址是从windows资源管理器复制的,出现转义字符问题。按下Ctrl+4直接处理成
var file:File = new File("C:\\myFolder\\myFile.txt");
这个转义字符之前少说手工加了一百次,现在并入工具中再不用考虑。



就还要编程5年、10年的程序员来讲,
我强烈推荐花上几周时间尽早制作自己的编辑器插件。
有了插件之后,实际编码速度保守估计翻了一倍,编码时思路不会再被一些反复出现的低级问题打断。自动生成代码不会出错,比如for(var j:int = 0;j<len_j;j++)后面自动生成var tmp:* = arr[j]不会把j错打成i
所以考虑调试代价,

我的插件是按照我的编码习惯做的其中不少功能针对我司项目框架,对非我司项目没有作用或会成为病句。
不适合,也不打算改成大众版本。

有制作Eclipse插件想法单独联系我。我的QQ是295363603。
我可以提供Eclipse插件的Java源码和配置,帮忙调通到插件和AIR互发信息花不了多久。
比从头研究能省下一两周的探坑时间。

AIR对as3文件处理的部分前面说过了,无法提供,
可直接分析字符串、使用正则等方式处理,或下定决心也搞一套一劳永逸的代码解析工具。




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

感谢所有支持论坛的朋友:下面展示最新的5位赞助和充值的朋友……更多赞助和充值朋友的信息,请查看:永远的感谢名单

SGlW(66139)、 anghuo(841)、 whdsyes(255)、 longxia(60904)、 囫囵吞澡(58054)

下面展示总排行榜的前3名(T1-T3)和今年排行榜的前3名的朋友(C1-C3)……更多信息,请查看:总排行榜今年排行榜

T1. fhqu1462(969)、 T2. lwlpluto(14232)、 T3. 1367926921(962)  |  C1. anghuo(147)、 C2. fdisker(27945)、 C3. 囫囵吞澡(58054)



快速回复 返回顶部 返回列表