据悉御安全APK加固的嬉戏反外挂方案

简介

 一、 前言

SQLite简介

    SQLite,是一款轻型的关系型数据库。它的布置目标是嵌入式

   
它亦可支持Windows/Linux/Unix等等主流的操作系统,同时可以跟很多程序语言相结合,比如
C++、C#、Object-C、PHP、Java等。

    笔者是做手游开发的,在表弟大上应用SQLite 存储数据是很有利的。 

乘胜活动互连网的兴起,移动游戏墟市近几年突然从天而降,收入规模飞速增进。依据第壹方数据计算,国内移动游戏二零一五年市面层面已达514.6亿。由于手游商场强势兴起,而且延续拉长势头会愈加猛烈。火热的市场背后隐藏的题目也更多,其中手游外挂就是三个例证。近年来移动游戏市镇上,有多方面须求在催促外挂的进步,大批量屌丝玩家,想花少量的钱到手更大快感;竞品集团恐怕恶意玩家,想恶意破坏游戏不荒谬活动运行。那类外挂会影响到游戏开发商的纯收入及许多好端端游玩玩家的感受,因而一定要求一种反外挂的手段,来确保游戏开发商的合法利益。可是有个别有实力的小卖部投入了成千上万能源来反外挂,尽管也使得,但也大大增加了本金;一些实力相对弱小的营业所则尚未能力反外挂,这么些铺面的玩耍很不难被外挂市集搞垮。就是在那种情景下,御安全加固平台推出了一种便利,高效以及费用低的基于APK加固的反外挂艺术,来保证好手游免受外挂软件的打扰。

System.Data.SqLite实践早先时期准备

  1. System.Data.SQLite
    库下载,用于C#操作SQLite的dll文件。下载地址:http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki
  2. SQLite可视化工具下载,用于查看SQLite库数据表数据。下载地址:http://www.sqliteexpert.com/download.html

Tips:

    1.基于自身的处理器是64bit只怕32bit 以及采取的.NET
Freamwork版本下载相应的的System.Data.SQLite。    下载解压文件如:

美高梅4688.com 1

 

     安装在指定目录后生成三个dll文件:

美高梅4688.com 2

     本文测试用的唯有 System.Data.SQLite.dll
。对于SQLite库数据的增删改查已经够用用了。

 

    2.SQLite数据库文件以.db为后缀。安装SQLite可视化工具后如图:

美高梅4688.com 3

     mydb是小编测试用的数据库。

 

实践

    对SQLite的增、删、改、查。

    测试环境:VS二零一五  语言:C#

 

    创设控制台新工程,引入System.Data.SQLite.dll 文件。   

    1.编辑SQLite 操作类,
对SQLite数据操作进行打包为 SqLiteHelper,代码如下:

    /// <summary>
    /// SQLite 操作类
    /// </summary>
    class SqLiteHelper
    {

        /// <summary>
        /// 数据库连接定义
        /// </summary>
        private SQLiteConnection dbConnection;

        /// <summary>
        /// SQL命令定义
        /// </summary>
        private SQLiteCommand dbCommand;

        /// <summary>
        /// 数据读取定义
        /// </summary>
        private SQLiteDataReader dataReader;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connectionString">连接SQLite库字符串</param>
        public SqLiteHelper(string connectionString)
        {
            try
            {
                dbConnection = new SQLiteConnection(connectionString);
                dbConnection.Open();
            }catch(Exception e)
            {
                Log(e.ToString());
            }
        }
        /// <summary>
        /// 执行SQL命令
        /// </summary>
        /// <returns>The query.</returns>
        /// <param name="queryString">SQL命令字符串</param>
        public SQLiteDataReader ExecuteQuery(string queryString)
        {
            try
            {
                dbCommand = dbConnection.CreateCommand();
                dbCommand.CommandText = queryString;
                dataReader = dbCommand.ExecuteReader();
            }catch(Exception e)
            {
                Log(e.Message);
            }

            return dataReader;
        }
        /// <summary>
        /// 关闭数据库连接
        /// </summary>
        public void CloseConnection()
        {
            //销毁Commend
            if(dbCommand !=null)
            {
                dbCommand.Cancel();
            }
            dbCommand = null;
            //销毁Reader
            if(dataReader != null)
            {
                dataReader.Close();
            }
            dataReader = null;
            //销毁Connection
            if(dbConnection != null)
            {
                dbConnection.Close();
            }
            dbConnection = null;

        }

        /// <summary>
        /// 读取整张数据表
        /// </summary>
        /// <returns>The full table.</returns>
        /// <param name="tableName">数据表名称</param>
        public SQLiteDataReader ReadFullTable(string tableName)
        {
            string queryString = "SELECT * FROM " + tableName;
            return ExecuteQuery(queryString);
        }


        /// <summary>
        /// 向指定数据表中插入数据
        /// </summary>
        /// <returns>The values.</returns>
        /// <param name="tableName">数据表名称</param>
        /// <param name="values">插入的数值</param>
        public SQLiteDataReader InsertValues(string tableName, string[] values)
        {
            //获取数据表中字段数目
            int fieldCount = ReadFullTable(tableName).FieldCount;
            //当插入的数据长度不等于字段数目时引发异常
            if (values.Length != fieldCount)
            {
                throw new SQLiteException("values.Length!=fieldCount");
            }

            string queryString = "INSERT INTO " + tableName + " VALUES (" + "'"+ values[0]+"'";
            for (int i = 1; i < values.Length; i++)
            {
                queryString += ", " + "'"+values[i] + "'";
            }
            queryString += " )";
            return ExecuteQuery(queryString);
        }

        /// <summary>
        /// 更新指定数据表内的数据
        /// </summary>
        /// <returns>The values.</returns>
        /// <param name="tableName">数据表名称</param>
        /// <param name="colNames">字段名</param>
        /// <param name="colValues">字段名对应的数据</param>
        /// <param name="key">关键字</param>
        /// <param name="value">关键字对应的值</param>
        /// <param name="operation">运算符:=,<,>,...,默认“=”</param>
        public SQLiteDataReader UpdateValues(string tableName, string[] colNames, string[] colValues, string key, string value, string operation="=")
        {
            //当字段名称和字段数值不对应时引发异常
            if (colNames.Length != colValues.Length)
            {
                throw new SQLiteException("colNames.Length!=colValues.Length");
            }

            string queryString = "UPDATE " + tableName + " SET " + colNames[0] + "=" + "'" + colValues[0] + "'";
            for (int i = 1; i < colValues.Length; i++)
            {
                queryString += ", " + colNames[i] + "=" + "'" + colValues[i] + "'";
            }
            queryString += " WHERE " + key + operation + "'" + value + "'";
            return ExecuteQuery(queryString);
        }

        /// <summary>
        /// 删除指定数据表内的数据
        /// </summary>
        /// <returns>The values.</returns>
        /// <param name="tableName">数据表名称</param>
        /// <param name="colNames">字段名</param>
        /// <param name="colValues">字段名对应的数据</param>
        public SQLiteDataReader DeleteValuesOR(string tableName, string[] colNames, string[] colValues, string[] operations)
        {
            //当字段名称和字段数值不对应时引发异常
            if (colNames.Length != colValues.Length || operations.Length != colNames.Length || operations.Length != colValues.Length)
            {
                throw new SQLiteException("colNames.Length!=colValues.Length || operations.Length!=colNames.Length || operations.Length!=colValues.Length");
            }

            string queryString = "DELETE FROM " + tableName + " WHERE " + colNames[0] + operations[0] + "'" + colValues[0] + "'";
            for (int i = 1; i < colValues.Length; i++)
            {
                queryString += "OR " + colNames[i] + operations[0] + "'" + colValues[i] + "'";
            }
            return ExecuteQuery(queryString);
        }

        /// <summary>
        /// 删除指定数据表内的数据
        /// </summary>
        /// <returns>The values.</returns>
        /// <param name="tableName">数据表名称</param>
        /// <param name="colNames">字段名</param>
        /// <param name="colValues">字段名对应的数据</param>
        public SQLiteDataReader DeleteValuesAND(string tableName, string[] colNames, string[] colValues, string[] operations)
        {
            //当字段名称和字段数值不对应时引发异常
            if (colNames.Length != colValues.Length || operations.Length != colNames.Length || operations.Length != colValues.Length)
            {
                throw new SQLiteException("colNames.Length!=colValues.Length || operations.Length!=colNames.Length || operations.Length!=colValues.Length");
            }

            string queryString = "DELETE FROM " + tableName + " WHERE " + colNames[0] + operations[0] + "'" + colValues[0] + "'";
            for (int i = 1; i < colValues.Length; i++)
            {
                queryString += " AND " + colNames[i] + operations[i] + "'" + colValues[i] + "'";
            }
            return ExecuteQuery(queryString);
        }


        /// <summary>
        /// 创建数据表
        /// </summary> +
        /// <returns>The table.</returns>
        /// <param name="tableName">数据表名</param>
        /// <param name="colNames">字段名</param>
        /// <param name="colTypes">字段名类型</param>
        public SQLiteDataReader CreateTable(string tableName, string[] colNames, string[] colTypes)
        {
            string queryString = "CREATE TABLE IF NOT EXISTS " + tableName + "( " + colNames[0] + " " + colTypes[0];
            for (int i = 1; i < colNames.Length; i++)
            {
                queryString += ", " + colNames[i] + " " + colTypes[i];
            }
            queryString += "  ) ";
            return ExecuteQuery(queryString);
        }

        /// <summary>
        /// Reads the table.
        /// </summary>
        /// <returns>The table.</returns>
        /// <param name="tableName">Table name.</param>
        /// <param name="items">Items.</param>
        /// <param name="colNames">Col names.</param>
        /// <param name="operations">Operations.</param>
        /// <param name="colValues">Col values.</param>
        public SQLiteDataReader ReadTable(string tableName, string[] items, string[] colNames, string[] operations, string[] colValues)
        {
            string queryString = "SELECT " + items[0];
            for (int i = 1; i < items.Length; i++)
            {
                queryString += ", " + items[i];
            }
            queryString += " FROM " + tableName + " WHERE " + colNames[0] + " " + operations[0] + " " + colValues[0];
            for (int i = 0; i < colNames.Length; i++)
            {
                queryString += " AND " + colNames[i] + " " + operations[i] + " " + colValues[0] + " ";
            }
            return ExecuteQuery(queryString);
        }

        /// <summary>
        /// 本类log
        /// </summary>
        /// <param name="s"></param>
        static void Log(string s)
        {
            Console.WriteLine("class SqLiteHelper:::" + s);
        }
    }

     Tips:1.别忘了引入:using System.Data.SQLite;

            2.引入System.Data.SQLite.dll的同时,需要将
System.Data.SQLite.dll.config
文件放在同级目录下。否则加载dll文件时报错。

 

    2.在工程主函数Main里面添加测试代码

class Program
    {
        private static SqLiteHelper sql;
        static void Main(string[] args)
        {
            sql = new SqLiteHelper("data source=mydb.db");


            //创建名为table1的数据表
            sql.CreateTable("table1", new string[] { "ID", "Name", "Age", "Email" }, new string[] { "INTEGER", "TEXT", "INTEGER", "TEXT" });
            //插入两条数据
            sql.InsertValues("table1",new string[]{"1","张三","22","Zhang@163.com" });
            sql.InsertValues("table1", new string[] { "2", "李四", "25", "Li4@163.com" });

            //更新数据,将Name="张三"的记录中的Name改为"Zhang3"
            sql.UpdateValues("table1", new string[] { "Name" }, new string[] { "ZhangSan" }, "Name", "Zhang3");

            //删除Name="张三"且Age=26的记录,DeleteValuesOR方法类似
            sql.DeleteValuesAND("table1", new string[] { "Name", "Age" }, new string[] { "张三", "22" }, new string[] { "=", "=" });


            //读取整张表
            SQLiteDataReader reader = sql.ReadFullTable("table1");
            while (reader.Read())
            {
                //读取ID
                Log(""+reader.GetInt32(reader.GetOrdinal("ID")));
                //读取Name
                Log(""+reader.GetString(reader.GetOrdinal("Name")));
                //读取Age
                Log(""+reader.GetInt32(reader.GetOrdinal("Age")));
                //读取Email
                Log(reader.GetString(reader.GetOrdinal("Email")));
            }

            while (true)
            {
                Console.ReadLine();
            }
        }

        static void Log(string s)
        {
            Console.WriteLine(""+s);
        }
    }

    Tips:1.别忘了引入:using System.Data.SQLite;

 

 

    欢迎讨论!

美高梅4688.com, 

二、 外挂种类及原理

移动游戏上曾经出现过大批量外挂样本,根据其天性可以分为以下二种:

一,内存修改。

搜索修改游戏内存数据,利用修改器搜索相应数值,再依据数值变化规律数十四回搜寻排除定位到对应属性在内存中的地方,直接修改成夸张效果值。在Android平台上较为主流,有烧饼、葫芦侠等优良代表.

二,时间修改

加紧游戏节奏,节省玩家时间;恐怕减慢游戏节奏,减低操作难度。其影响游戏帧更新频率,可完成加速过关、减速躲技能等外挂功用.

三,财富修改

修改安装包中第贰数据配置,修改替换游戏设置后的能源文件,破解或涂改安装包财富(例如图片/音乐),重用游戏能源或创设广告版本.

4、代码修改

可以通过修改客户端代码重新包装公布外挂版本,达到扩张受益、去除限制、降低游戏难度的目的。修改代码库文件,直接交流安装后先后的库文件,可以通过hook情势动态修改内存中的实践代码.

5、模拟器操作

让玩家可在PC上运转手游。PC上的模拟器,近期主要流行的是Android模拟器,其具体产品有TGP、海马玩、每天等模拟器.

六,商谈修改

用户修改上传数据,达到上报虚假数据作弊目的用户重复上传获取收益的新闻,达到取得额外收入的目标用户上传不符合条件的信息,达到跳过客户端限制目标用户修改协议完成上传攻击音讯的目标.

 

三、 反外挂系统

幸存的反外挂系统首要分为终端侧反外挂系统以及劳动器侧反外挂系统。

1)服务器端防外挂系统

 1、游戏时间相关校验。客户端计时不可靠,必要在服务器校验客户端上传的时刻参数是或不是站得住,校验游戏进程数据和时间之间的涉及是还是不是创设(例如里程、时间、速度关系)

二,游戏宗旨逻辑校验。每一遍操作均经过协议上传,服务器认同后再实际履行操作,每趟操作服务器均要开展客观判断,且判断结果实时报告。

三,玩家间数据交互校验。各玩家的操作经过服务器中转对其他玩家一起,如果基本逻辑在每一种客户端单独统计,各玩家需定时上传各自游戏风浪数据,服务器举办相比校验,假如基本逻辑在一些客户端统计,其余玩家需从该客户端同步时局数据,服务器需求校验主逻辑数据是或不是创造。

四,游戏操作时序相关校验。部分操作有明显的时序要求,打乱时序或者引致额外获益。服务器端通过对客户端发送的操作时序举办校验,来判定客户端发送的请求时序是不是成立。

服务器端防外挂的瑕疵:

(1)不难导致误杀

当前多如牛毛娱乐的反外挂系统采取范围性的数值验证,由于自身的设计原因依然弱网络的因由,很多时候会促成误杀。

(2) 服务器端的筹划万分复杂

鉴于服务器端的数据及流程校验和玩耍的代码逻辑巢倾卵破,所以服务器端防外挂的数目以及代码逻辑必要基于客户端的代码逻辑及数量进行规划和支出,那样会招致服务器端防外挂设计和客户端的代码逻辑举行紧耦合。客户端只要举办代码逻辑的修改,也有只怕导致服务器端的防外挂系统开展改动。

(3)服务器端防外挂作用不能通用

每一款游戏都有温馨的代码逻辑以及各样数据,所以服务器端的防外挂作用不可以形成统一标准,对每一款游戏都使用。往往是不得不针对一定的游玩展开定制化开发防外挂作用。

(4) 服务器端外挂系统保障开支高

总结,由于服务端外挂系统的扑朔迷离以及定制化的多样性,必然造成开发开支以及维护开销持续增加。其它要求在劳动器端举办各类逻辑和数目的校验,随着游戏的增添,系统装备的扩容以及系统的总结财富消耗也会进一步大,必然造成硬件开支及数码流量费用的增多。

 

2) 客户端防外挂系统

针对服务器端防外挂系统的欠缺,御安全加固系统开发出了一种基于客户端加固的防外挂系统,它是一种基于APK加固和防外挂系统相结合的一种防外挂方案。

御安全APK加固技术首要作用:

1、DEX文书保养。

拔取分片式按需加载技术,攻击者不可以在内存中拿到完整的DEX文件,再拉长DEX内存分散作用,攻击者不能从一片一连的内存中Dump出DEX文件,大大加大了攻击者获取DEX的难度

二,SO文件爱惜。

御安全加固爱抚逻辑,通过源码级的歪曲,接纳三种歪曲形式,攻击者不能逆向其代码逻辑,别的,基于动态加载的SO加壳技术,也使得攻击者不或然逆向拥戴逻辑以及原APK中SO的代码逻辑。

三,资源文件尊敬。

御安全加固系统,可以针对APK的Assets,Raw及Res目录下的兼具文件举办加密体贴并进行完整性校验,经过御安全加固系统加固后的APK,能源不或者被曲解,例如不能伸张广告界面,也束手无策盗版APK里面的能源。可以很好地爱惜开发者的知识产权。

肆,内存保护。

严防通过动态调试的点子对APK进行调试,加固APK在被调剂,或许其内存被篡改后,加固APK将活动退出。也得避防患通过进度调试的措施对加固APK进行进程调试,加固APK被进度调试的时候,加固APK也将电动退出。经过御安全加固系统加固后的APK,可以预防市面上全体主流的外挂软件对加固APK举办内存修改,如火烧修改器,八门神器,叉叉修改器等上十种主流外挂软件。

伍,预防内存dump。

APK在运作时候,会在内存中放出全体恐怕部分源码,攻击者可以在运行时刻利用dump命令把这一个源码导出。御安全加固后的APK,可以使得幸免攻击者从内存中复制源代码。

6、防游戏加快。

攻击者只怕游戏玩家,通过市面上的外挂软件,可以加速游戏速度,破坏游戏平衡,用于加速应战速度照旧等待时间等景色。御安全加固后的APK,一旦发现玩家或然攻击者有加速只怕减速游戏的行事,APK将活动终止运营。

御安全的共同体APK珍视方案以及对协商首要代码的保安,可防止患攻击者逆向协议的流水线还是算法,幸免攻击者对协议举办抨击,幸免外挂软件通过破解协议的法子,攻击加固后的玩乐。

 

四、 云-端结合防外挂攻击

相对于服务器端的防外挂软件系统,终端侧的防外挂方法也有其缺点,因为攻击者可以赢得终极侧防外挂作用的逻辑实体,固然大家对其做了严格的维护,但是也在所难免大概被攻击者绕过防外挂功用。由此假设御安全加固系统能和服务器端防外挂系统的管用结合,就能够很好地拦阻外挂软件对巩固游戏的攻击,从而缩小游戏开发商的损失。其它御安全加固APK,接纳一键式的爱抚形式,能够一本万利,飞速地为游乐开发商提供珍爱服务器。加固后的APK,包容性接近百分之百,加固后的APK运营Crash率控制在0.02%之内。运营速度以及别的性质影响,对用户无其余感知。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注