吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 22692|回复: 72
收起左侧

[原创] 某网站的分析,得到加密文件,并使用C#编写工具解密文件,重点讲解C#的编写

  [复制链接]
cdj68765 发表于 2015-6-20 22:12
本帖最后由 cdj68765 于 2015-6-25 20:00 编辑

说实话,我都不知道这篇帖子的内容该放在破解区还是编程语言区了,因为在我脑中的大纲里面,破解过程是一笔带过的,重点全是c#里面的事情。

先说下我要干什么吧
一个日本的模型网站,会提供上传者上传模型的展示,有些模型很精美,我想要下载到这些模型
为了防止被某些搜索网站搜索到,给自己带来不必要的麻烦,我在全程会规避网站的网址以及相关的关键词,能用图片替代的尽量用图片吧。


该网站的分析过程我就不再冗述,我就流水线带过
通过Fiddle这个工具分析网站加载了什么
QQ截图20150620210322.png
从上往下看,第一个黑色框里面,加载了一个components.json,在这个json里面记载着
QQ截图20150620210852.png
加密模型的下载地址,贴图的下载地址以及贴图的文件名,我在接下来写C#工具的时候,重点处理对象就是这个json
然后接下来在紫框里,加载了一个Unity3D的文件,模型解密过程,以及显示过程等等,我想都是通过这个U3D的webplayer打包文件实现的
然后青色框里面,以及红色框里面,就是加载了模型数据和贴图数据了,这没啥好讲的

然后我使用Procmon软件,查看模型数据被加载到了哪里
QQ截图20150620211937.png
万幸,数据都被下载到了IE的缓存文件夹里面(我用IE浏览器打开的网站)
只不过比起在JSON里面显示的文件名,下载到本地的文件名都多了个[1],这个需要注意

我们先把要处理的重点文件,加密的模型文件拷贝出来吧
QQ截图20150620212529.png 后缀的文件,嘛,对我们来说,后缀名是什么并没有意义,重点是里面的数据,尤其是头文件数据
QQ截图20150620212644.png
很明显,都是没有意义的数据,我们先不管吧

我们把目光转向那个Unity3D文件,至少Unity3D后缀我们是知道明确意义的(Unity3D编写的Webplaye封包文件),
谈到Unity3D封包,自然就应该想到解包,用什么解包?谷歌一下的你们,估计很快就找到了disunity这个工具,233.我说的没错吧
但是,我这里要提供另外一个玩意,一个国外大神写的,网址是(http://aluigi.altervista.org/quickbms.htm),使用方法是先下载上面的主程序,然后根据你要处理的文件类型,到下面寻找对应的脚本文件,然后打开主程序,先加载脚本,然后加载代处理的文件后,选择保存目录就开始解包过程了,我使用这个工具加载Unity Web Player脚本,然后解包Unity3D文件,得到
QQ截图20150620214503.png
这么些文件,然后猜测对模型的解密操作 等等都是在第一个dll,也就是Assembly-CSharp.dll里面执行的,标题很清楚,写着CSharp,也就是C#写的,我们用ILSpy对这个dll竟然反编译,得到了源码?
得到了很多cs的代码文件,那我们怎么知道,我想要找的方法在哪个代码文件里面呢
嘛,我使用的IDE是VS2013,于是我打开工程文件到VS2013,然后Ctrl+F,然后 QQ截图20150620220320.png ,方便吧,直接搜索我想处理对象的后缀,定位到了一个关键cs里面,
立马就看到了
QQ截图20150620220442.png
叫做LoadFile方法名的代码段,我知道我找对地方了,然后就是分析代码,写工具了,你说简单吧

真是可喜可贺,楼主这么快就找到关键代码段了,但是很遗憾的是,楼主在上个星期六分析的时候,找到这个地方后,就没辙了,原因很简单,楼主并不会C#的编程,根本没学过
于是楼主我恶补了C#的编程知识后,然后才着手分析代码,使用C#编写工具

好了,经过周日一个晚上的恶补C#编程基础知识以后,我对C#有个大致的了解了,不就是和C差不多的语言么,套用套用就行了,我们先看这个加密代码段干了什么吧
[C] 纯文本查看 复制代码
public void LoadFile(byte[] file)///调用时候,载入的是byte数据
                {
                                CGMLZMA cGMLZMA = new CGMLZMA(file.Length ^ 80128);///引用一个叫做CGMLZMA的子程序,对子程序输入的值是载入文件的数据大小按位与固定数值80128进行异或操作
                                using (MemoryStream memoryStream = new MemoryStream(file))///将文件数据存到名为memoryStream的内存流
                                {
                                        using (MemoryStream memoryStream2 = new MemoryStream())///建立一个名为memoryStream2的空内存流用来存处理后的数据,也就是说,我最后只要把这个内存流里面的数据导出成文件就行了,后面的算法都可以不用管
                                        {
                                                while (true)///开始循环操作,看来除非遇到break,不然是不打算结束循环了
                                                {
                                                        int num = (int)Math.Min(memoryStream.get_Length() - memoryStream.get_Position(), 4L);///定义一个整数,整数值的取值是调用数学方法里面的取最小值,取的是内存流大小减去当前内存流位置,与4进行取小操作
                                                        if (num <= 0)///当num取到的数值小于等于0就结束循环
                                                        {
                                                                break;
                                                        }
                                                        byte[] array = new byte[4];///建立一个大小为4的byte数组,
                                                        memoryStream.Read(array, 0, num);///从memoryStream的内存流读取4字节数据到array数组
                                                        if (num == 4)///这里没啥好讲的
                                                        {
                                                                uint num2 = BitConverter.ToUInt32(array, 0) ^ cGMLZMA.NextUInt32();\\将array数组里面的字节转换成整数值与应用的cGMLZMA类里面的NextUInt32方法进行异或操作,得到数据返回给新定义的整数变量num2
                                                                array = BitConverter.GetBytes(num2);///将整数变量num2里面的数值转换成字节传送给array
                                                        }
                                                        memoryStream2.Write(array, 0, num);///将array数组里面的数据写入到 memoryStream2内存流
                                                }
                                                memoryStream2.set_Position(0L);///将内存流memoryStream2的指针指向开头
                                }
                                return result;
                        }
public class CGMLZMA
        {
                private uint x;
                private uint y;
                private uint z;
                private uint w;
                public CGMLZMA(int seed)
                {
                        this.x = (uint)seed;
                        this.y = 362436069u;
                        this.z = 521288629u;
                        this.w = 88675123u;
                }
                public uint NextUInt32()
                {
                        uint num = this.x ^ this.x << 11;
                        this.x = this.y;
                        this.y = this.z;
                        this.z = this.w;
                        return this.w = (this.w ^ this.w >> 19 ^ (num ^ num >> 8));
                }
        });

至此我们已经知道代码对文件在数据层面上的操作了,我们需要做的,只是写一个读取方法,一个保存方法,然后调用这个方法就行了,期间甚至对源代码都可以不做任何修改
源代码里面,调用该方法,输入的参数是字节数组类型的,因此我们也应该使用字节数组读取文件,用什么方法呢,File.ReadAllBytes就行,C#实在是太人性化,打个file然后加个.,然后呢,你就随便挑方法就行了,不知道挑哪个就打个byte,然后蹦出这玩意给我看,简单易懂的英语,读取全部字节数据。
因此,开头我们就写个
[C#] 纯文本查看 复制代码
static void Main(string[] args)
        {
            byte[] file = File.ReadAllBytes("C:\\XX.XX");
LoadFile(file);
}
}

完事,多少方便,然后结尾下一个方法用来导出内存流里面的数据到文件
[C#] 纯文本查看 复制代码
FileStream fs = new FileStream("XX:\\XX.XX“, FileMode.OpenOrCreate);
                    BinaryWriter w = new BinaryWriter(fs);
                    w.Write(memoryStream2.ToArray());
                    fs.Close();

顺利导出,完毕,至此模型的解密工作全部完成,编译一下就可以食用了(误)

你们以为这样子就完了?如果仅仅只是这样的话就太没意思了,下面开始才是正题
上面的程序大家也看了,导入的时候,要手动填写文件的地址,导出文件地址也要手动填写,最重要的是,每次操作都要编译一次,烦不烦?于是,我着手开始编写完整的功能

在此,我会以一个刚接触C#一周不到的半吊子新手的角度,为大家讲解我写的C#里面,用到了哪些功能,是怎么实现这些功能的,(喂,你接触一个星期就来现学现卖了额,你确定你不是菜鸟一枚还在那班门弄斧?233)

文章的最后,我会贴出全部的代码,不过在此之前,我会一一慢慢讲解,反正估计没多少人看,我也就安心大胆的写了

凡事要有思路,编程也要有个流程,我写的这个工具,首先应该显示一个对话框用来让用户选择保存路径,然后获得文件方面,记不记得数据是保存在浏览器的缓存目录的?那我也去那里掏数据算了,然后还记不记得我上面那张json里面,数据的截图?

一个很明显是图片下载地址的东西,然后前面跟了个该图片文件所对应的文件名,我原本想的是,分析这个json,得到下载地址,然后使用下载的方法直接下载图片保存成对应的文件名,但是失败了,因为网站本身使用了自动秘钥,每15分钟生成一个自动秘钥导入到Cookie里面,如果秘钥不对将出现401,无权限访问的错误,本来我想写一个POST来突破这层验证的,但是想想,凭我才接触C#几天的功力,还是不要做这种吃力不讨好的事情了,还是分析json,然后从IE缓存得到文件比较方便。
综上所述,目前最重要的事情,就是先得到对应的json,然后分析json废话不多说,开始讲代码上面的事情吧

首先是显示一个对话框,让用户选择保存路径用的,用了以下代码
[C#] 纯文本查看 复制代码
FolderBrowserDialog folderDlg = new FolderBrowserDialog();///引用一个FolderBrowserDialog方法,命名folderDlg
            folderDlg.ShowDialog();///让命名为folderDlg的FolderBrowserDialog方法显示出来

好,文件保存地址的获得已经完毕了,以后想要调用该地址,只要folderDlg.SelectedPath就得到了

保存地址得到了,那么加载地址呢,我用了如下代码
[C#] 纯文本查看 复制代码
string Cachefoler = Convert.ToString(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache)));

很长是吧,其实原来没这么长的,只不过我为了那啥,就把代码全部嵌套在一起了,其实看到这么长的代码也不用慌,从里面往外面读总没错,这里就是从一个叫做IE缓存的特殊目录得到地址路径,并把路径名转换成字符串给新定义的字符串变量Cachefoler,(C#)里面,充斥着各种类型的数据,就用 Convert.ToString()就是用来把括号内的数据转换成对应数据类型的,这里是ToString,所以就是把括号内的数据转换成字符串,当然这个方法并不是万能的,很多情况下并不适用。因此请多加注意。


两个地址得到了,我们想下,还差个什么,哦对,得到json文件,通过观察我发现,网站会从一个固定的网址获得该json文件 QQ截图20150621105842.png
这个网址里面,唯一的变量就是红框里面的数值,
而,该变量就是
QQ图片20150621105953.png
网址最后的页面标号,因此,我的思路是让用户输入要处理的网址,然后我用程序分析得到这个标号,然后通过这个标号获得json的下载地址,得到json后,再进行进一步操作

弹出窗口,让用户输入网址方面,我是弄了个单独的窗口项,设计成酱紫的
QQ截图20150621110553.png
其中,我给确定按钮输入了以下代码
[C#] 纯文本查看 复制代码
private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                this.Text = textBox1.Text;///从输入栏获得字符串
                string[] downloadsArr = textBox1.Text.Split(Convert.ToChar("d"));///以字d为分割要素,分割获得的字符串
                int.Parse(downloadsArr[downloadsArr.Length - 1]);///将分割得到的字符串数组最后的数据转变成整数(这里用到downloadsArr.Length来获得数组的大小,因为根据网址,我知道我想要得到的那个数字一定是在最后面的,但是.Length获得的数组大小是从1开始计数的,而数组本身却是从0开始计数的,因此这里downloadsArr.Length - 1就是指向数组最后一位,没有-1的话,不仅无法读取,而且还是还会出现越界错误。而这句话的意义就是与try配合着用,根据网址我知道d后面的一定会是一串数字,如果不是数字,那么转变成整数型就一定会出错,因此我用try用来判断这句话是否出错了,如果出错,那么必定是输入的网址有误。
                this.td_num = downloadsArr[downloadsArr.Length - 1];///将分割字符串得到的字符串数组最后一位的数据传给全局变量,方便主程序里用到该数据。
                this.Close();///结束该窗体
            }
            catch(System.Exception)
            {
                MessageBox.Show("输入的网址有误","错误",MessageBoxButtons.OK,MessageBoxIcon.Error);
            };
        }

好,经过以上代码以后,我们就得到了页面编码了,存在td_num里
于是,接下来,我们怎么操作呢
首先回到主程序,然后在主程序的头,打一个using Json;我在这里打的这个Json是什么?其实是,我刚才编写的窗口项的命名空间
QQ截图20150621112222.png QQ截图20150621112243.png
这个很重要,不在主函数里面using该命名空间的话,主函数根本找不到
[C#] 纯文本查看 复制代码
Getjson fr = new Getjson();///引用引用窗体里面,类的名字给fr
            fr.ShowDialog();///显示窗体
            string num = fr.td_num;

从窗体的全局变量里面获得数值
然后我们才可以在主函数里面,写上面那段代码来调用刚才的窗体

紧接着,我调用了一个子程序,来从网站获得json到本地文件
[C#] 纯文本查看 复制代码
private static string Getjson(string num)
        {
            string temp="";
            try///用来判断接下来的操作有没有错误的,一旦出现错误,就可以判断是下载出问题了
            {
                WebClient client = new WebClient();引用WebClient
                temp = Convert.ToString(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache)));///之前已经出现过了,我打算把获得的Json文件,存到IE的缓存目录里面去 
                client.DownloadFile("[url=http://3d.nicovideo.jp/works/td&quot;]http://3d.nicovideo.jp/works/td"[/url] + num + "/components.json", temp + "\\components.json"); ///调用方法DownloadFile来下载文件到指定目录
            }
            catch(System.Exception)///要是上面出错就显示下面的对话框
            { 
                MessageBox.Show("网络异常", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
            return temp + "\\components.json";///返回路径字符串
        }

好,这样一来,我们从网站上面得到了需要的json了,接下来怎么操作呢首先吧,json是一种数据格式,有自己的数据格式规则,而我要做的,就是分析该文件里面的数据,得到自己想要的数据
怎么分析?自己根据json的规则写算法么?那太蠢了,在这里,我从网上找了个Newtonsoft.Json.dll,准备引用该dll里面的方法,帮我分析

解决方案里面添加引用没啥好讲的,其次需要在
QQ截图20150621114933.png
引用该程序集
然后我在主函数里面,写了这么一段代码来调用json的分析方法
[C#] 纯文本查看 复制代码
JsonReader reader = new JsonTextReader(new StringReader(new StreamReader(Getjson(urlnum), Encoding.GetEncoding("utf-8")).ReadToEnd()));

够长吧..其实原来没这么长的,纯属我无聊,把各种定义的变量取消,全部嵌套在一起了,还是从里往外读吧...首先是Getjson(urlnum),调用我上面写的子程序Getjson,输入的数值是从上面提到的窗口来的,然后经过该子程序后,返回的是json在本地的地址,也就是IE的缓存目录里面的地址,详情看上面的那个代码段,之后将该地址所指向的文件,以utf-8的格式写入数据流,然后使用 StringReader读取该数据流里面每一个字符数据,最后再调用JsonTextReader方法来分析所得到的json数据,至于怎么分析的,我并不知道,全部交给Newtonsoft.Json.dll完成了,分析得到的数据保存在reader里面,也就是说,之后我想调用json里面的数据,只要调用reader就行了
事不宜迟,让我们来看下,JsonTextReader方法将json数据分析成了什么样子了
[C#] 纯文本查看 复制代码
            while (reader.Read())///循环读取reader
            {
                Console.WriteLine(reader.Path + "\t" + reader.Value);///控制台显示reader地址和对应地址里面的值
            }
            Console.ReadLine();

QQ截图20150621142630.png

我们可以很清晰的看到,json的数据被分门别类的处理好了,我们需要做的,只有从里面取自己需要的数据罢了,上面红框里面就是图片应该取的文件名,下面红框里面,就是对应的下载地址,但是我们并不需要那么长,我们只需要紫框里面那一段,因为保存到本地的文件名就是紫框里面的文件名,等会儿我们从本地搜索当然也需要文件名对应喽
取法也很简单,用Split方法把reader.Value按照字符“/”分成几段,然后分割后得到的数组最后一位里面,就是需要的字符串了,在此不再冗述

经过以上方法,我们从json里面,得到了保存到IE缓存里面的文件名,那么,接下来,该怎么使用这些文件名找到对应的文件呢
于是我想了一个方法,用了以下代码
[C#] 纯文本查看 复制代码
            string[] tree = Directory.GetDirectories(path, "*.*", SearchOption.AllDirectories);///获得指定目录path下面包括字目录下面所有的目录路径
            string[] directories = new string[tree.Length+1];根据上面tree数组的大小再申请一个比tree数组大1的数组
            for (int i = 0; i < tree.Length - 1; i++)循环遍历tree数组,由于length是从1开始计数的,所以这里-1,为了和数组的计数方式对应
            {
                directories[i] = tree[i];将数组tree里面的数据,全部传给数组directories
            }
            directories[directories.Length - 1] = path;在数组directories的最后再把path添加进数组最后一位,做这一步操作是因为第一行代码,获得的所有目录是不包括自己本身的,所以要把目录本身给手动添加进去,本来这里应该用动态数组Array的,这样只要add(),就行了,根本不需要循环遍历什么的,但是没办法,学艺不精,对动态数组的操作,到现在还不熟练,以防万一还是用自己最熟悉的普通数组操作了            foreach (string dir in directories)///foreach循环遍历数组 directories里面的数据
 {
string[] fileNames = Directory.GetFiles(dir, "*.png");///从指定目录下面搜索定义类型的文件,并将结果返回给字符串数组fileNames
}

之后只要将fileNames数组里面的数据和json里面获得数据进行对比就行了,很简单吧
写这个遍历目录算法的时候,我在网上查找了不少的资料,发现大家几乎都用的递归算法来实现遍历的,虽然并不是不可以,但是要自己写一个递归的子程序实在麻烦,而后,我在百无聊赖的时候,在那边一个个方法的寻找,于是就找到这个方法了,立马调过来使用,发现还是很方便的。不过,如果指定C盘的话,这个算法会把整个盘符都遍历一遍,然后逐个寻找对应的文件倒是真的,慎用啊(按照我的思路,是两个表格在对比,简单地说,是左边表格里面一行数据,拿右边表格的全部数据进行对比寻找,右边找完以后,左边表格再换一行继续跟右边表格全部数据进行对比,幸好我这边对比的数据量很小,要是一旦数据量大起来,程序崩溃是迟早的事情,毕竟效率太低)
[C#] 纯文本查看 复制代码
System.IO.File.Copy(fileNames, path + @"\" + xx.jpg,true);
找到文件以后就没啥好说的了,从找到的位置复制到指定位置就完毕了(注意要在后面加上true或者false,代表是否需要覆盖,不加的话遇到重复复制的情况,会崩溃)

好了,程序大功能上的实现就讲到这里,还有很多细节上面的东西我就不讲了,一切我都会贴在下面的代码里面,有细节上面的不懂直接回复我就行
[C#] 纯文本查看 复制代码
namespace Netdownload
{
    class Program
    {
        public bool firsttimecheckModel = true;
        public bool checkModel = false;
        [STAThread]
        static void Main(string[] args)
        {
            EmbeddedAssembly.Load("readcomponents.Newtonsoft.Json.dll", "Newtonsoft.Json.dll");
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Program Bool = new Program();
            MessageBox.Show("请选择模型保存目录", "目录选择", MessageBoxButtons.OK, MessageBoxIcon.Information);
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            folderDlg.ShowDialog();
            string Cachefoler = Convert.ToString(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache)));
            Getjson fr = new Getjson();
            fr.ShowDialog();
            string num = fr.td_num;
            if (Dealwith(folderDlg.SelectedPath, Cachefoler, num) == false)
            {
                MessageBox.Show("请点击网页中间的播放按钮加载模型,当页面中的模型能正常显示后再进行下一步", "要求", MessageBoxButtons.OK, MessageBoxIcon.Question);
                System.Diagnostics.Process.Start("iexplore.exe", @"3d.nicovideo.jp/externals/embedded?id=td" + num);
                MessageBox.Show("是否已经加载完模型?", "确认", MessageBoxButtons.OK, MessageBoxIcon.Question);
                if (Dealwith(folderDlg.SelectedPath, Cachefoler, num) == false)
                {
                    if (MessageBox.Show("无法获得模型数据,是否手动指定缓存路径?", "错误", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes)
                    {
                        FolderBrowserDialog Cachepath = new FolderBrowserDialog();
                        Cachepath.ShowDialog();
                        if (Dealwith(folderDlg.SelectedPath, Cachepath.SelectedPath, num)==false)
                        {
                            MessageBox.Show("模型解析失败");
                        }
                    }else { MessageBox.Show("模型解析失败"); }
                }
            }
        }
        static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return EmbeddedAssembly.Get(args.Name);
        }
        private static string Getjson(string num)
        {
            string temp="";
            try
            {
                WebClient client = new WebClient();
                temp = Convert.ToString(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache)));//json保存目录  
                client.DownloadFile("[url=http://3d.nicovideo.jp/works/td&quot;]http://3d.nicovideo.jp/works/td"[/url] + num + "/components.json", temp + "\\components.json");  
            }
            catch(System.Exception)
            { 
                MessageBox.Show("网络异常", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
            return temp + "\\components.json";
        }

        private static bool Dealwith(string path, string getfoler, string urlnum)
        {
            string oldpath = path;
            string[,] modelinfo = new string[1000, 3];
            string[] MODEL = new string[3];
            string[] Texname = new string[1000];
            string[] Urlname = new string[1000];
            string[] Urlest = new string[1000];
            int count = 0;
            bool restex = false;
            string dispicurl = "";
            Getjson fr = new Getjson();
            string tex = fr.Text;
            if (urlnum == null)
            {
                System.Environment.Exit(0);
            }
            JsonReader reader = new JsonTextReader(new StringReader(new StreamReader(Getjson(urlnum), Encoding.GetEncoding("utf-8")).ReadToEnd()));
            while (reader.Read())
            {
                Console.WriteLine(reader.Path + "\t" + reader.Value);
                string stra = (string)reader.Path;
                string getname = Convert.ToString(reader.Value);
                string[] sArr = stra.Split(new char[] { '.' });
                if (restex)
                {
                    foreach (string s in sArr)
                    {
                        if (s.Equals("url"))
                        {
                            if (getname != "url")
                            {
                                string[] urlname = getname.Split(new char[] { '/' });
                                string[] texname = urlname[6].Split(new char[] { '.' });
                                Urlname[count] = texname[0] + "[1]";
                                Urlest[count] = texname[1];
                                count++;
                                restex = false;
                            }
                        }
                    }
                }
                foreach (string s in sArr)
                {
                    if (s.Equals("name"))
                    {
                        if (getname != "name")
                        {
                            Texname[count] = getname;
                            restex = true;
                        }
                    }
                }
                
                if (stra == "work.title")
                {
                    if (getname != "title")
                    {
                        MODEL[0] = getname;
                        DirectoryInfo dir = new DirectoryInfo(path);
                        dir.CreateSubdirectory(getname);
                        path = path + @"\" + getname;
                        WebClient client = new WebClient();
                        client.DownloadFile(dispicurl, path + @"\" + @"folder.jpg");
                    }
                }
                if (stra == "components[0].url")
                {
                    if (getname != "url")
                    {
                        string[] urlname = getname.Split(new char[] { '/' });
                        string[] name = urlname[6].Split(new char[] { '.' });
                        MODEL[1] = name[0] + "[1]";
                        MODEL[2] = name[1];
                    }
                }
                if (stra == "components[0].display_url")
                {
                    if (getname != "display_url")
                    {
                        dispicurl = getname;
                    }
                }
            }
            Console.ReadLine();
            for (int i = 0; i < count; i++)
            {
                modelinfo[i, 0] = Texname[i];
                modelinfo[i, 1] = Urlname[i];
                modelinfo[i, 2] = Urlest[i];
            }
            string[] tree = Directory.GetDirectories(getfoler, "*.*", SearchOption.AllDirectories);
            string[] directories = new string[tree.Length];
            for (int i = 0; i < tree.Length - 1; i++)
            {
                directories[i] = tree[i];
            }
            directories[directories.Length - 1] = getfoler;
            foreach (string dir in directories)
            {
                string[] fileNames = Directory.GetFiles(dir, "*.*");
                for (int i = 0; i < fileNames.Length; i++)
                {
                    string[] urlname = fileNames[i].Split(Convert.ToChar(@"\"));
                    for (int j = 0; j < count; j++)
                    {
                        if (urlname[urlname.Length - 1] == modelinfo[j, 1] + "." + modelinfo[j, 2])
                        {
                            bool check01 = true;
                            foreach (string s in Directory.GetFiles(path))
                            {
                                if (s.Equals(path + @"\" + modelinfo[j, 0]))
                                {
                                    check01 = false;
                                }
                            }
                            if (check01)
                            {
                                System.IO.File.Copy(fileNames[i], path + @"\" + modelinfo[j, 0],true);
                            }
                        }
                    }
                }
            }
            foreach (string dir in directories)
            {
                string modelpath = "";
                string[] ModelNames = Directory.GetFiles(dir, MODEL[1] + ".*");
                bool Check = false;
                foreach (string a in ModelNames)
                {
                    if (a != "")
                    {
                        modelpath = a;
                        Check = true;
                    }
                }
                if (Check)
                {
                    string extsion = System.IO.Path.GetExtension(modelpath);
                    int timeout = 0;
                    string saveextsion = "dat";
                    switch (extsion)//这里我讲一下,不同的文件对应不同的种子(也就是相当于特定的秘钥),我找到了所有加密文件的种子数据,然后根据加载文件后缀获得对应的种子文件以给解密算法用,当然为了防止被搜索网站搜索到,这里的参数我都改了。
                    {
                        case ".p": timeout = 3; saveextsion = "m"; break;
                        case ".x": timeout = 8; saveextsion = "px"; break;
                        case ".m": timeout = 2; saveextsion = "o"; break;
                        case ".px": timeout = 1; saveextsion = "Pd"; break;
                        case ".nc": timeout = 2; saveextsion = "c"; break;
                        case ".pm": timeout = 5; saveextsion = "p"; break;
                    }
                    byte[] file = File.ReadAllBytes(modelpath);
                    CGMLZMA cGMLZMA = new CGMLZMA(file.Length ^ timeout);
                    using (MemoryStream memoryStream = new MemoryStream(file))
                    {
                        using (MemoryStream memoryStream2 = new MemoryStream())
                        {
                            while (true)
                            {
                                int num = (int)Math.Min(memoryStream.Length - memoryStream.Position, 4L);
                                if (num <= 0)
                                {
                                    break;
                                }
                                byte[] array = new byte[4];
                                memoryStream.Read(array, 0, num);
                                if (num == 4)
                                {
                                    uint num2 = BitConverter.ToUInt32(array, 0) ^ cGMLZMA.NextUInt32();
                                    array = BitConverter.GetBytes(num2);
                                }
                                memoryStream2.Write(array, 0, num);
                            }
                            try
                            {
                                memoryStream2.Position = 0L;
                                string filename = path + @"\" + MODEL[0] + "." + saveextsion;
                                FileStream fs = new FileStream(filename, FileMode.OpenOrCreate);
                                BinaryWriter w = new BinaryWriter(fs);
                                w.Write(memoryStream2.ToArray());
                                fs.Close();
                            }
                            catch(System.Exception)
                            {
                                memoryStream2.Position = 0L;
                                string filename = oldpath + @"\" + MODEL[0] + "." + saveextsion;
                                FileStream fs = new FileStream(filename, FileMode.OpenOrCreate);
                                BinaryWriter w = new BinaryWriter(fs);
                                w.Write(memoryStream2.ToArray());
                                fs.Close();
                            }
                            MessageBox.Show("模型解析完毕");
                            return true;
                        }
                    }
                }
            }
            return false;//只要返回值不是void的子程序的,在子程序的最后必须要有一个return,而且,必须要在末尾处有一个
        }
    }
}


于是我们编译一下吧
编译通过,得到了
QQ截图20150621152125.png
一个可执行文件,还有个我应用的dll文件,额,我这么小的一个工具程序,为何还要带一个dll才能运行啊,难道就不能把这个dll封装到主程序里面去么
于是我在搜索的时候,搜索到了一个方法(http://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource),按照他的方法来讲,我应该这么做
QQ截图20150621152447.png
首先我应该在引用里面,把这货的属性,嵌入互操作类型改成true(虽然是嵌入到主程序里面,但还是要引入的)
然后把这个dll拖到解决里面,对,拖进去就行,也可以右键,添加现有项,不用指定放到什么目录里面,这不重要
QQ截图20150621152715.png
记得把属性里面的生成操作改成嵌入到资源就行了
然后上面那个网址里面的作者写了个代码项目 EmbeddedAssembly.txt (4.2 KB, 下载次数: 6) ,不用管把这货也拖到解决方案里面去(记得改下后缀,改成cs后缀)
然后回到主程序里面,
在主程序键入以下代码
[Asm] 纯文本查看 复制代码
        static void Main(string[] args)
        {
            EmbeddedAssembly.Load("XX.Newtonsoft.Json.dll", "Newtonsoft.Json.dll");
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            .............;//这里开始就可以写你自己的代码了
        }
        static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return EmbeddedAssembly.Get(args.Name);
        }

上面没啥特别需要讲的,有个地方值得注意一下就行,EmbeddedAssembly.Load("XX.Newtonsoft.Json.dll", "Newtonsoft.Json.dll");,这里调用的是那个网址里面作者写的子程序,子程序需要输入两个参数,后面那个是你引入dll全名这没问题,但前面那个是你引入dll的地址,这个地址是,你这个工程所在文件夹的名字.你引用dll的名字,在我这里就是
QQ截图20150621153942.png
”XX.Newtonsoft.Json.dll“,因为这个很重要所以我重点讲一下
编译一下,果然dll被嵌入到exe里面了,而且exe也能正常运行(别把所有的dll都嵌入到exe里面哦,不然打开你这个巨大的exe对电脑来讲会是一件很费事的事情)

好了,耗时一周的分析编写工作都结束了,C#果然是易学易用的语言啊(PS,很容易上瘾啊 有木有),我这种对编程一窍不通的人,也只要看下语法规则就能随便写小工具了
不过我写这篇文章的时候头脑里比较乱,不知道该写什么,不该写什么,所以先这样吧,以后我再慢慢改就是
最后希望大家能从一个接触C#一周不到的小白编写的代码当中,学到有用的玩意,233

点评

写的不错!  发表于 2015-7-22 17:42
  发表于 2015-7-9 13:15
啊啊啊啊,看不懂,小白的我真心吃屎。  发表于 2015-7-3 15:58
楼主前途无量  发表于 2015-7-3 15:10
http://www.52pojie.cn/thread-292090-1-1.html 快速入门C#视屏..挺不错的  发表于 2015-6-22 23:28

免费评分

参与人数 24吾爱币 +1 热心值 +24 收起 理由
flyCai + 1 + 1 用心讨论,共获提升!
悟空不悟 + 1 我没看明白,但是看完了!
ckj0101 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
alccc + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
420471419 + 1 谢谢@Thanks!
MoB + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
XQiang + 1 谢谢@Thanks!
XhyEax + 1 写的不错,支持!
huabian + 1 太牛了吧,一周就这水平了
筑龙建筑 + 1 谢谢@Thanks!
arryboom + 1 我很赞同!
asong + 1 谢谢@Thanks!
flowertea + 1 谢谢@Thanks!
磨______灭ヾ + 1 我很赞同!
cr7890 + 1 谢谢@Thanks!
追风筝的骇纸 + 1 谢谢@Thanks!
rainisa + 1 谢谢@Thanks!
colgate + 1 非常细致
vigers + 1 我很赞同!
mcevilrock + 1 http://www.52pojie.cn/thread-292090-1-1.
Anonymous、 + 1 我很赞同!
ql_zth + 1 谢谢@Thanks!
Monitor + 1 吾爱破解论坛因你更精彩!
Pizza + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

mcevilrock 发表于 2015-6-22 23:29
   为啥不能给你评分..今天还有分呀..怪事.
推荐个C#学习视屏
http://www.52pojie.cn/thread-292090-1-1.html
 楼主| cdj68765 发表于 2015-7-5 12:25
本帖最后由 cdj68765 于 2015-7-6 17:07 编辑
realzoc 发表于 2015-7-5 10:31
LZMA是压缩算法的名称..

说实话 我看不出这段解密过程和
LZMA算法有何关系,而且解密算法使用了几个固定的秘钥,而且说实话,这个解密过程就是各种亦或,不涉及压缩过程,所以也就是文字里面出现了LZMA,实际不搭边

lionshine 发表于 2015-6-20 23:55
艾莉希雅 发表于 2015-6-21 16:34
nico都不放过#(滑稽)
Hmily 发表于 2015-6-22 15:15
取个屌点的名字就更好了。
 楼主| cdj68765 发表于 2015-6-22 15:19
Hmily 发表于 2015-6-22 15:15
取个屌点的名字就更好了。

不不,我写这篇文章 就是为了低调低调再低调,万一被日本那边发现就233了
cmheia 发表于 2015-6-22 15:37
{:1_915:} 去围观了下 nico,果然 233 跟二次元密不可分
VENin__ 发表于 2015-6-22 22:05
向楼主学习。。。
 楼主| cdj68765 发表于 2015-6-23 00:43
mcevilrock 发表于 2015-6-22 23:29
为啥不能给你评分..今天还有分呀..怪事.
推荐个C#学习视屏
http://www.52pojie.cn/thread ...

谢谢分享,有空我一定去看
niuniu919 发表于 2015-6-23 05:54 来自手机
很详细的教程帖。学习了,谢谢楼主。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-16 14:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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