提问,Misc的派系地图生成器mod上古卷轴5无法载入mod工作是怎么回事

&p&我也来简单回答一下题主。
首先, 外挂是一门很大很注重实践的一门技术大类。
在这个技术大类之下还分很多小类。
一般来说分逆向,编写逻辑 这2方面
所谓逆向,也就是分析游戏的客户端,寻找相关功能的函数
而编写逻辑,如掉线重登,自动打怪,自动吃药 之类等等等。
但是实际上, 写一个挂,远远不止上述的2方面
比如说还要过游戏的保护,这个需要运用Window内核的知识。
以前的大神写挂都是单独一人完成的,这个需要懂的内容非常非常多。
我列举一下成为一个全能大神所需的知识:
首先,汇编的基础知识必须过硬,有良好的逆向经验。了解常用的数据结构(因为游戏的背包或者怪物之类的多用二叉树或者数组, 连基本的数据结构都不懂……那玩个蛋)
了解API,R3(Native API),R0(内核),Socket。熟悉一门编程语言(只会汇编也可以)
如果你能把上述的学精,就有成为大神(外挂类)的潜质。
-------------------------写着写着突然不想写了,以后再补充吧--------------------------------------
竟然有人评论……那我继续写了。&/p&&p&如果是对编译原理比较了解的基友,应该就知道。
一个静态函数是一个固定的CALL,一个struct的结构内容都是用偏移可以算出来所有成员的。
所以逆向游戏客户端,分析出游戏中的某些功能函数的地址,再加以分析出所传递的参数,模拟调用。这样一个简单的功能就完成了。
当然,这中间还牵扯到其他不少的东西, 比如说必须熟悉结构,
举个栗子:
当你看到一个参数他的内存形式如下:
0x11114&/p&&p&这样的玩意,就很快可以联想到这是一个数组,还是一个vector。
这些除了要有逆向的功底以外,还需要有“逆向游戏的经验”, 因为游戏的参数都那德行,万变不离其宗。
除此之外, 游戏现在都有防多开的干涉。
在不谈驱动保护的前提下, 你需要熟悉Window的工作机制,特别是互斥的工作原理,当然,现在游戏保护不止是互斥判断多开,比如说进程路径重复,类名,窗口名,互斥,内存映射,判断文件是否存在等等之类的……所以你至少要把那本Window核心编程给看熟。
这方面的书籍, 我也没有太多的介绍, 现在有不少人是熟悉逆向,而不会过多的编程的“外挂作者”。 他们都并非靠对编译原理的理解去逆向游戏数据,而且靠“经验”去逆向游戏数据。
总的来说,我看他们都是在网上找教程看下,再加以练习,就能达到这个水准了。&/p&&p&那么接下来再讲讲编程这块。
因为需要稳定不需要过多的人工量去看的挂机,所以你需要写得非常“智能”,简化操作流程,还要把角色的伤害跟玩家相提并论, 此过程听起来很简单, 操作起来非常麻烦。
首先多线程你要懂吧? 比如说你必须无时无刻都在判断人物Hp低于某个程度就得啃药了吧?总不能每写一句代码就写if判断一次血量吧?
还有某些全局数组或者vector之类的多线程操作,比较基础的互斥啊,临界区之类的你要用吧?
总而言之,多线程这块就是麻烦!这类书籍我也就不班门弄斧了,想必各种大神的推荐应该更有力。
接下去还需要懂Native API。 就是俗称的R3. 亦是巨硬没公开的API, 需要用这层去隐藏自己的DLL,防止游戏的检测。 还有多开之类的,一般都在这层完成的。
你需要懂一点PE文件格式,把大部分的Native API的运行方法,调用方式给弄懂。
还需要懂Socket网络编程.
因为 你需要怎么“验证”自己,达到给工作室收费的目的,
还有你需要怎么“验证”自己,达到防止被别人破解的目的
当然,牵扯到socket了,我是看了,会socket的,大部分都会数据库操作的。
要嘛是MSSQL,要嘛是MySQL。 这个方便查询和管理。(这个数据库对写挂木有硬性要求)
socket无非就是粘包之类的,超时之类的判断。 赶脚不需要学到很深。
当然,如果你还要弄脱机挂,底层的TCP协议是必须会的。
还有加密和解密算法得杠杠的,逆向功底也要杠杠的。&/p&&p&我想下,编程这块应该就剩下个脚本了吧? 会一门脚本语言这个应该很easy。
还有应该懂一点算法, 比如说A*, dijkstra,之类的。&/p&&p&剩下就是Window内核了,就是俗称的R0,驱动层。
就先写到这里了……以后想多了再补充。&/p&&br&&p&------------------8.24号更新--------------------------------
有兄台问: 为何要精通汇编……
这……难道还有游戏的源码供你调试?
在木有游戏的源码下,只能看汇编……&/p&&p&有兄台问:现在外挂的行情如何:
我只能说, 没几年前那么好赚了, 几年前在DNF大火的时候,养了一大批中国的外挂作者和工作室。 但是现在的游戏,防得越来越严了。
新人最难的就是入门, 而真正赚钱的东西,都被各家的前辈捂得严严实实的。
哪怕你是一个编程高手,逆向高手。 当你真正写出一个挂的时候,会发现,玛德被封号了。 为何不稳定? 5分钟掉一次线? 为何总是跟不上工作室的需求, 不知道弄什么功能出来才是工作室所需的,而工作室本身就不是很懂技术,说的东西总是含糊其词的…… 恨不得直接可以刷软妹币到他们的口袋。&/p&&p&这个行业很讲经验, 对付封号的经验,跟工作室配合的经验,熟悉游戏的经验, 怎么才能用最短的时间,写出工作室最需要的功能。 &/p&&p&顺便一提, 就是这些经验,都是需要时间的日积月累。 然而新人入门都倒在了这个门槛上,很少有人能够坚持个几年去不断摸索学习。
当然现在也有很多写挂的教程视频,请允许我对这种视频说一句:然并卵!&/p&&p&真正赚到钱的作者,根本不会去在乎那点小钱,也不会拿这种共享的心态去分享这些经验,这些经验对于他们来说就是收入,他们公开了这些经验,很多人知道,就意味着很多游戏公司的反外挂部门也知道, 那就是打破自己的饭碗。 &/p&&p&知乎很多大神,有很多反外挂的大神,也有很多写挂的大神都混在这里(所以我才匿名,免得被认出来)&/p&&p&很多人进这行1年都能赚百万,有人5年都赚不到10万。 总是有高有低,有起有落的。&/p&&p&就如同在国家严打黑客前,当年的刷钻盗号,入侵教程如春笋般在各种网站上公开叫卖, 肆意挥霍的年代, 很多大神就是从那个(相对于现在这个年代的环境已经是超级好了)年代成长起来,以前是年代也是“相对”比较单纯,现在学渗透,不如以前的学习环境好, 但是长江后浪推前浪,后浪死在沙滩上,依然有人在这种国家要严打的环境下 还是成长到媲美 上一代大神的境界。&/p&&p&最后给各位读者一句衷心的劝言:
没有一颗沉得住寂寞的心,不要轻易进这个行业
没有一颗2年都赚不到钱的觉悟,不要轻易进这个行业
没有一颗坚强的心(偷摸拐骗在这个行业处处可见),不要轻易进这个行业&/p&&p&我也比较认同楼下的说法, :
技术的成长路线 全看个人,虽然这条路很偏,这门技术在“正统”的领域中,很少有用得上的。&/p&&p&最后总结一下这门技术, 是非常注重“实践”和“调试”,
如果想增强一下对语言底层的理解,逻辑思维的增强,调试功底, 可以稍微浅入这个领域去学习一下。&/p&&p&特别是调试功底~!
在木有源码,无法调试的情况下,甚至在不知道,出错是你的锅,还是游戏的锅。不知道为何运行一段时间崩溃后,疯狂查日志的寂寞。&/p&&p&这个行业 也确实是比较“浮躁”的一个行业,功利心很强, 大家都是向着利益看齐。因为利益而解散的写挂团队我也见过太多了。 可以这么说,写挂团队解散有60%是赚不到钱,35%是利益纷争,5%是其他原因。&/p&&p&---------先写到这里,虽然木有大神在行业混了8年的经验,也曾呆过这个行业一段时间,比较了解。 也很乐意分享各种见闻(经验分享我就不说了:毕竟这是灰色产业,明目张胆的说,会坑爹的。)---------------------------------&/p&&br&&p&----------------------------------------------------------------
嘿嘿, 好长时间没来更新了, 发现挺多赞的。
那就再更一发。
老夫来说一下, 如果要完成一个“完整的工作室内存外挂”, 需要什么功能, 需要哪些技术。&/p&&p&首先:老夫只拿我自己做过的例子来举例, 不代表其他人的做法也是一样
第一步: 写一个控制台。 我是用C#来写(MFC太烂了, 又长又臭。), 方便工作室操作, 一般是存放帐号,还有操作一些配置文件(比如说设置低于%? 就吃药, 设置了收货【邮件或者交易】角色名之类等等诸如此类)。 为了防止别人认出来, 就不丢图了。 老夫找一张类似的图片&/p&&img src=&/fa128a1cdfcff3bed4ad_b.png& data-rawwidth=&554& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&554& data-original=&/fa128a1cdfcff3bed4ad_r.png&&&br&&p&基本就做这个玩意。 大部分都是读取配置文件, 做一些界面交互的功能。 写好List。 和一些界面操作之类的。
基本就是dataGridview操作, StreamReader, StreamWriter, 各种拖拉控件。 完事。&/p&&br&&p&第二步:
然后老夫会用cpp写一个DLL。 用来跟C#的界面交互。 利用内存共享来和游戏的DLL交互信息.
基本这个就用到内存共享, CreateFileMapping, MapViewOfFile, OpenProcess, 诸如此类。
然后基本就是各种判断, 比如说掉线呐, 超时呐, 状态呐。 还有对在线帐号做各种判断操作, 比如说刷完 的角色要保存日志, 该删的删, 该留的留。 还要做登录初始化处理之类的。 &/p&&p&第三步:
写注入(基本都有现成的, 为了流程规范! 还是单独列出来好了。 OOP思想已经祸害了老夫了)
一般常用的注入很多, 比如说APC注入,输入法注入, DLL劫持。 OEP改入口。 远线程注入。 无模块注入(一般是申请一块内存, 然后把整个DLL复制过去。 修复导入表,重定位后,加载dllmain), 还有驱动级的一大堆就不一一细说了。
注入方法五花八门,不管是哪种方法, 只要有效, 能防止游戏检测到,又可以用。 那就是一个成功的注入。&/p&&p&第四步:
逆向游戏功能(其实这个才是第二步,注入是第一步)
这里也分2种, 一种是先找遍历, 一种是先找发包
找游戏的明文发包, 这个可以大概说一下, 因为一般来说, 建立tcp连接, 都是需要connect, 然后send 或者 recv之类的。
但是一般来说, 基本都是send都是经过单次或者多次加密后的密文封包, 所以并没有太大意思, 有些甚至是搞了多线程, 一个线程检查一个全局队列之类的然后send, 另一个线程负责push。
比如说基三就是这样干的!
当然往上回溯之类的现在已经不怎么好用了。
这里面的篇幅太长太长了, 就不一一细说了, 因为里面还有很多小技巧的东西, 很多关于经验, 感觉之类的事。
遍历一般是指, 周围怪物, Npc, 技能, 背包, UI之类的。 从林林种种的数据结构中, 找到自己想要的数据。
比如说怪物是用树状结构保存的, 但是每一个CMonster 都是一个超级大的结构。 他里面还包含了很多类,结构, 也可能继承了N个类, 也有N个指针,N个虚函数。
很多我们都是不需要的, 所以需要一一细分, 比如说, 只要怪物HP,MP, 角度, 坐标,之类的。 像怪物的形状, 外形, 颜色之类的,我们根本不care!
然后就可以和明文发包结合了。
举个栗子, 使用技能函数
static UseSkill(dwSkillId, dwTargetId)
send(............)
所以你找到你明文发包的CALL。
那么你只需要在CALL头部下一个断点即可。
基本内容就是只要SkillId和TargetId,
卖, 也一般就只有NpcId, ItemId, Count之类的。 游戏不一样, 可能做法不一样。&/p&&p&从这一步, 可以实现相当多的功能, 比如说自身的HP&? 就使用物品。
可以实现自动打怪,捡物, 做任务之类的………………
这一步其实需要的功能很复杂, 但是技术含量我认为并不高。
时间做久了, 就是写业务逻辑的事。&/p&&p&第五步:
就应该来到脚本这块了。 如果是用lua写脚本的话。 那基本就是封装几个函数的事。 比如说交任务, 接任务, Move, Npc对话之类的。 反正大部分游戏不都那个尿性嘛?整天跑来跑去, 跟几个Npc对对话, 虐虐小怪, 跟Npc美女谈笑风生。
这块就是体力活了。&/p&&p&第六步:
把控制台, 控制台DLL, 游戏DLL结合起来。 比如说血量控制呐, 超时判断呐, 怪物过滤表之类的要与控制台交互起来。&/p&&p&第七步:
socket, 要给工作室写收费系统。
这一步工作量也不少。
前面几步是跟游戏斗智斗力, 这一步是跟破解者斗智斗力, 比如说有很多阴险的检测. 什么删系统, 格式化之类的。
&/p&&p&第八步:
基本这一步就可以到封号的步骤了,
以前游戏封号五花八门, 也有很多规则可循的。
比如说某个区域就检测加速, 某个时间段就检测一次。 检测到就晾个几天再把你封号。 还有CRC校验代码段, 上传DLL, 按键检测, API检测………………
我说几个例子, 某游戏, 就在检测你模拟鼠标, 比如说正常人的鼠标, 是有轨迹的移动过去的。 他就给你检测你的鼠标是否“瞬移”出现在某处, 还有键盘的按下和弹起时间, 太快了要遭殃!(这种都有权值的, 大意就是分数。 超过及格线, 基本就晾个几天就必封了!)
比如说还有堆栈回溯, 查看调用CALL是否在本模块中………………
据说TX跟暴雪 学了一个新招, 做一个Loader加载器。
然后随机从服务器下载一段shellcode。 然后运行这段代码, 把结果返回给服务器。
本地毫无痕迹! 而且下载回来的代码全部是vm混淆过的。
咳咳, 里面还有各种奇招, 就不一一阐述了!&/p&&p&回头一想, 也发现漏了很多步骤, 比如说TX的就有TP保护。 盛大网易的有HS和NP保护。 所以还需要驱动层说。 比如说TP是DebugPort清0之类的。 NP老版本可以解密配置文件剥离。
还有重载内核, 用VT, 自己重写异常处理之类的一大堆手段可以过保护。&/p&&p&也有游戏多开没说, 还有隐藏自身这块也没说……
发现写了N多了。 就先说到这里了。
有空下次再更新!
赞多了再更!&/p&&p&------------------------------------------------------------------
长夜漫漫, 无心睡眠。 那就来更一发吧!
这次直接上教程和代码(用TX的某游戏来演示, 只进行技术研究, 禁止用于非法用途! )&/p&&img src=&/5b97ad17aa9fcfa0e08fc_b.png& data-rawwidth=&530& data-rawheight=&612& class=&origin_image zh-lightbox-thumb& width=&530& data-original=&/5b97ad17aa9fcfa0e08fc_r.png&&&p&祭出CE!
开始从人物HP下手&/p&&img src=&/534e304ceb8_b.png& data-rawwidth=&310& data-rawheight=&512& class=&content_image& width=&310&&&br&&p&开始找小怪攻击自己来掉血&/p&&img src=&/2f64f0db7b9ded3f970f94e_b.png& data-rawwidth=&876& data-rawheight=&355& class=&origin_image zh-lightbox-thumb& width=&876& data-original=&/2f64f0db7b9ded3f970f94e_r.png&&&p&找到了!&/p&&p&索引第0,1,3个是当前HP
2,4是MAXHP&/p&&p&接下来打开OD! (怎么附加进程这里略过……这个又可以说一个一本书那么厚的文章的如何对抗TP反调试)&/p&&img src=&/7acc812cf5a82c9f87104bcaab918b62_b.png& data-rawwidth=&294& data-rawheight=&246& class=&content_image& width=&294&&&p&0x2E70=11888(因为已经回满血了) &/p&&img src=&/eb754b5ad3d0da79c0476e_b.png& data-rawwidth=&498& data-rawheight=&573& class=&origin_image zh-lightbox-thumb& width=&498& data-original=&/eb754b5ad3d0da79c0476e_r.png&&&p&下一个硬件访问断点!&/p&&br&&br&&img src=&/d7d78c37ed4cba918d93e9bcc7a7d997_b.png& data-rawwidth=&1070& data-rawheight=&835& class=&origin_image zh-lightbox-thumb& width=&1070& data-original=&/d7d78c37ed4cba918d93e9bcc7a7d997_r.png&&&br&&div class=&highlight&&&pre&&code class=&language-ca65&&&span class=&mi&&004705&/span&&span class=&n&&E1&/span&
&span class=&mi&&8&/span&&span class=&n&&B87&/span& &span class=&n&&C0000000&/span&
&span class=&n&&MOV&/span& &span class=&n&&EAX&/span&&span class=&p&&,&/span&&span class=&n&&DWORD&/span& &span class=&n&&PTR&/span& &span class=&nl&&DS:&/span&&span class=&p&&[&/span&&span class=&n&&EDI&/span&&span class=&o&&+&/span&&span class=&n&&C0&/span&&span class=&p&&]&/span&
&/code&&/pre&&/div&&p&从这句代码可以看出, 这个角色当前HP 是 EDI + 0xC0.&/p&&p&那么你可以猜EDI就是当前人物角色指针.&/p&&img src=&/e16ed4f3037a_b.png& data-rawwidth=&337& data-rawheight=&229& class=&content_image& width=&337&&&p&那么我们继续回溯这个指针是怎么来的!&/p&&img src=&/f10aba3bd7bcd32c3d96fdb_b.png& data-rawwidth=&1208& data-rawheight=&567& class=&origin_image zh-lightbox-thumb& width=&1208& data-original=&/f10aba3bd7bcd32c3d96fdb_r.png&&&div class=&highlight&&&pre&&code class=&language-ca65&&&span class=&mi&&&/span&
&span class=&mi&&8&/span&&span class=&n&&BB8&/span& &span class=&mi&&&/span&
&span class=&n&&MOV&/span& &span class=&n&&EDI&/span&&span class=&p&&,&/span&&span class=&n&&DWORD&/span& &span class=&n&&PTR&/span& &span class=&nl&&DS:&/span&&span class=&p&&[&/span&&span class=&n&&EAX&/span&&span class=&o&&+&/span&&span class=&mi&&80&/span&&span class=&p&&]&/span&
&/code&&/pre&&/div&&img src=&/5d22df156ed81f513ccd3c_b.png& data-rawwidth=&1224& data-rawheight=&578& class=&origin_image zh-lightbox-thumb& width=&1224& data-original=&/5d22df156ed81f513ccd3c_r.png&&&p&继续往上翻。 就可以得出人物血量= [[[11B0A9C]+34]+80]+0C0&/p&&img src=&/97a3b6b8eee64e89ae0c219f360fe665_b.png& data-rawwidth=&321& data-rawheight=&338& class=&content_image& width=&321&&&p&这里11B0A9C 是一个全局静态类&/p&&p&如果对C++这块稍微有点了解的就知道了。 这种情况不过是类里面有类/结构 变量/指针&/p&&p&比如说&/p&&div class=&highlight&&&pre&&code class=&language-cpp&&&span class=&k&&class&/span& &span class=&nc&&CBns2&/span&
&span class=&p&&{&/span&
&span class=&p&&...........&/span&
&span class=&p&&}&/span&
&span class=&k&&struct&/span& &span class=&n&&strcut1&/span&
&span class=&p&&{&/span&
&span class=&p&&........&/span&
&span class=&p&&}&/span&
&span class=&k&&class&/span& &span class=&nc&&CBns1&/span&
&span class=&p&&{&/span&
&span class=&p&&.......&/span&
&span class=&p&&.......&/span&
&span class=&n&&CBns2&/span& &span class=&n&&CBns2_&/span&&span class=&p&&;&/span&
&span class=&n&&strcut1&/span& &span class=&n&&strcut1_&/span&&span class=&p&&;&/span&
&span class=&n&&CBns2&/span&&span class=&o&&*&/span& &span class=&n&&pCBns2_&/span&&span class=&p&&;&/span&
&span class=&n&&strcut1&/span&&span class=&o&&*&/span& &span class=&n&&pstrcut1_&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&br&&br&&p&当然也不一定是这样的。 推测罢了。&/p&&p&// 注意, 这里的11B0A9C 是静态指针, 一般来说是不会变的。 如果会变的。 他有可能是属于DLL的全局指针, 因为win7有地址随机。 所以不能这样直接写。暂时先说这个情况&/p&&p&// 把DLL注入到游戏的情况下, 否则只能用OpenProcess + ReadProcMemory的方式读取&/p&&p&然后就可以写代码来实时获取人物血量了! &/p&&div class=&highlight&&&pre&&code class=&language-cpp&&&span class=&n&&DWORD&/span& &span class=&nf&&ReadDWORD&/span&&span class=&p&&(&/span&&span class=&n&&_In_&/span& &span class=&n&&DWORD&/span& &span class=&n&&dwAddr&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&DWORD&/span& &span class=&n&&dwValue&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&n&&IsBadCodePtr&/span&&span class=&p&&(&/span&&span class=&n&&FARPROC&/span&&span class=&p&&(&/span&&span class=&n&&dwAddr&/span&&span class=&p&&)))&/span&
&span class=&n&&dwValue&/span& &span class=&o&&=&/span& &span class=&o&&*&/span&&span class=&p&&(&/span&&span class=&n&&DWORD&/span&&span class=&o&&*&/span&&span class=&p&&)&/span&&span class=&n&&dwAddr&/span&&span class=&p&&;&/span&
&span class=&k&&return&/span& &span class=&n&&dwValue&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&n&&DWORD&/span& &span class=&n&&WINAPI&/span& &span class=&nf&&_WorkThread&/span&&span class=&p&&(&/span&&span class=&n&&LPVOID&/span& &span class=&n&&lpParm&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&while&/span& &span class=&p&&(&/span&&span class=&nb&&true&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&DWORD&/span& &span class=&n&&dwHp&/span& &span class=&o&&=&/span& &span class=&n&&ReadDWORD&/span&&span class=&p&&(&/span&&span class=&n&&ReadDWORD&/span&&span class=&p&&(&/span&&span class=&n&&ReadDWORD&/span&&span class=&p&&(&/span&&span class=&n&&ReadDWORD&/span&&span class=&p&&(&/span&&span class=&mh&&0x11B0A9C&/span&&span class=&p&&)&/span& &span class=&o&&+&/span& &span class=&mh&&0x34&/span&&span class=&p&&)&/span& &span class=&o&&+&/span& &span class=&mh&&0x80&/span&&span class=&p&&)&/span& &span class=&o&&+&/span& &span class=&mh&&0xC0&/span&&span class=&p&&);&/span&
&span class=&o&&::&/span&&span class=&n&&Sleep&/span&&span class=&p&&(&/span&&span class=&mi&&100&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&br&&p&这里就可以获取到人物HP了! MAXHP略过, 方法同上!
接下去就可以继续逆向游戏功能
比如说要做一个吃药的功能。 当HP & %50的时候, 就自动吃药. 伪代码如下
while(true)
::Sleep(100);
if(GetPercentHp() & 50 && ExistItem(回血道具) && GetItemCD(回血道具) == 0)
UseItem(回血道具)
}&/p&&p&……不知不觉已经凌晨2点了。 下次有机会再把上面的逆向和代码写完。
记得点赞!&/p&&p&///////////////////////////////////////////////////////////////////////////////////////&/p&&p&继续更!&/p&&p&接下来做找明文发包CALL。 一般游戏处理是 明文打包-&加密包-&send&/p&&p&过程略……发包就在这里&/p&&img src=&/1fa2d69e5677e1caf6daf8d_b.png& data-rawwidth=&1055& data-rawheight=&841& class=&origin_image zh-lightbox-thumb& width=&1055& data-original=&/1fa2d69e5677e1caf6daf8d_r.png&&&br&&p&啃一瓶药. &/p&&p&下断点!&/p&&img src=&/772cbbe51149d62cfbfb31ae6b2d0def_b.png& data-rawwidth=&1065& data-rawheight=&851& class=&origin_image zh-lightbox-thumb& width=&1065& data-original=&/772cbbe51149d62cfbfb31ae6b2d0def_r.png&&&p&从调用堆栈可以看到调用的函数地址&/p&&img src=&/6f727e48a54c5e248de2c2_b.png& data-rawwidth=&986& data-rawheight=&691& class=&origin_image zh-lightbox-thumb& width=&986& data-original=&/6f727e48a54c5e248de2c2_r.png&&&p&然后一个一个分析参数。 &/p&&p&首先逆向游戏是需要先对游戏的数据结构有一定了解才能模拟调用。 &/p&&p&比如说这里的&/p&&p&PUSH 30&/p&&p&CALL 00CDF02E&/p&&p&就是申请 0x30大小的内存大小嘛&/p&&img src=&/a95a56fbfc7_b.png& data-rawwidth=&963& data-rawheight=&1009& class=&origin_image zh-lightbox-thumb& width=&963& data-original=&/a95a56fbfc7_r.png&&&p&然后从这一层可以看到代码大概如下, 只要把0x30的参数按原来的形式填进去, 就能send&/p&&p&那个10002从其他地方分析(略)可以得出, 1是指背包位置, 最后一个2是指类型。 2是指背包.
所以如果背包第二个物品就是20002, 背包第三个物品就是30002.
EAX && 0x10就是获取背包位置
申请的内存是MOV ESI,EAX.
所以MOV WORD PTR DS:[ESI+10],AX
*(WORD*)(ESI + 0x10) = 背包位置;&/p&&p&然后接下去看看别的参数&/p&&img src=&/afe5c5fe62c416_b.png& data-rawwidth=&907& data-rawheight=&708& class=&origin_image zh-lightbox-thumb& width=&907& data-original=&/afe5c5fe62c416_r.png&&&p&先将申请的内存清0&/p&&img src=&/00bed15fbe3fc35c5abf36c0c27c5221_b.png& data-rawwidth=&1143& data-rawheight=&937& class=&origin_image zh-lightbox-thumb& width=&1143& data-original=&/00bed15fbe3fc35c5abf36c0c27c5221_r.png&&&p&可以看出来这个0x30大小的数组内容是这些.
基本上就是0x10是填物品位置。
然后0x28和0x2C填0xFFFFFFFF
然后干货就是0x18,0x1C,0x20了&/p&&p&然后接下去继续返回上一层继续找EBX的来源会发现他其实就是[[[11F57AC]+34]+80]
*(DWORD*)(ESI + 0x18) = [[[[11F57AC]+34]+80]+8]
*(DWORD*)(ESI + 0x1C) = [[[[11F57AC]+34]+80]+C]&/p&&p&至于0x29嘛, 刚刚准备写的时候发现&/p&&img src=&/bdfbba95be9cf50d4e97f51_b.png& data-rawwidth=&331& data-rawheight=&152& class=&content_image& width=&331&&&p&算了。 就写到这里啦。 &/p&&p&感觉下次得上欧美服或者韩服去才行。 国服真是越来越难调试了。&/p&&p&// by 7.29
想要我私信的自己先想好问什么问题好嘛?
前面一大堆人我都私信过了, 结果一大堆都是连问问题都问不清的人, 剩下的一堆就是无视了我的私信。
最后还有1个想让我教他的,我也教了差不多2个星期。 结果两天打渔三天晒网.
劝各位一句:只要是学编程相关的, 自认不是天才的情况下, 还是老老实实每天敲8个小时代码(看书), 不然你这样学到30岁都不知道能不能学有所成。&/p&&p&// by 8.13
我挺可以分享行业见闻的, 但是不代表也可以分享我个人的隐私, 跟其他人交流过经常都问你赚了多少钱, 搞了哪些游戏之类的……等等诸如此类的问题, 我拒绝回答敏感性的问题!&/p&&br&&p&// by 8.17&/p&&p&论如何修改魔兽3的攻击为混乱攻击, 护甲是神圣护甲&/p&&img src=&/f556b3ebfc74abbc70e3_b.png& data-rawwidth=&1228& data-rawheight=&356& class=&origin_image zh-lightbox-thumb& width=&1228& data-original=&/f556b3ebfc74abbc70e3_r.png&&&p&改成&/p&&img src=&/8d8fba476fd78f977166f_b.png& data-rawwidth=&1235& data-rawheight=&469& class=&origin_image zh-lightbox-thumb& width=&1235& data-original=&/8d8fba476fd78f977166f_r.png&&&br&&br&&p&0x1:&/p&&p&在做之前要想好'切入点',
就是游戏在哪会调用到攻击类型这个玩意呢?&/p&&p&比如说可以在使用技能(包括普通攻击)之后, 造成伤害之前是需要获取的。&/p&&p&但是也不好入手, 因为使用技能的判断太多了, 不好区分。&/p&&p&又或者说。 可以这样!&/p&&img src=&/7bfc2cbcf5fc8e643b7d1da_b.png& data-rawwidth=&1117& data-rawheight=&285& class=&origin_image zh-lightbox-thumb& width=&1117& data-original=&/7bfc2cbcf5fc8e643b7d1da_r.png&&&p&把鼠标放到攻击上面, 他'应该'会获取当前的攻击类型,然后转换成Text -& Update 到界面
, 好, 接下去就试试这招!&/p&&p&………………
但是在获取这个攻击类型之前, 还要获取一个东西, 就是获取该英雄的Object.
如何在茫茫人海里面把该英雄找出来, 因为每一个英雄都有自己的攻击种类, 所以第一件事就是要找到自身的Object指针!&/p&&p&从人物HP入手, 买点装备丢装备来达到人物HP不断变化的目的. 最终找到了&/p&&img src=&/397e13b912ba4e3e10dbd544de1d83de_b.png& data-rawwidth=&1099& data-rawheight=&549& class=&origin_image zh-lightbox-thumb& width=&1099& data-original=&/397e13b912ba4e3e10dbd544de1d83de_r.png&&&p&一个是HP一个是MAXHP
随便掉点血就知道第一个是HP, 第二个是MAXHP.
附加OD, 在HP下访问断点&/p&&img src=&/4f6bd8f297fc34a_b.png& data-rawwidth=&659& data-rawheight=&789& class=&origin_image zh-lightbox-thumb& width=&659& data-original=&/4f6bd8f297fc34a_r.png&&&img src=&/e698c4edbc37e_b.png& data-rawwidth=&886& data-rawheight=&534& class=&origin_image zh-lightbox-thumb& width=&886& data-original=&/e698c4edbc37e_r.png&&&br&&p&看上一层, &/p&&div class=&highlight&&&pre&&code class=&language-asy&&&span class=&mo&&023&/span&&span class=&n&&C8C1B&/span&
&span class=&o&&|&/span&&span class=&p&&.&/span&
&span class=&mi&&8&/span&&span class=&n&&BBE&/span& &span class=&mi&&&/span& &span class=&n&&mov&/span&
&span class=&n&&edi&/span&&span class=&p&&,&/span& &span class=&n&&dword&/span& &span class=&n&&ptr&/span& &span class=&p&&[&/span&&span class=&n&&esi&/span&&span class=&o&&+&/span&&span class=&mi&&248&/span&&span class=&p&&]&/span&
&span class=&p&&;&/span&
&span class=&n&&HP&/span&
&/code&&/pre&&/div&&p&ESI就是人物指针. 往上回溯, 看下ESI是怎么传递的&/p&&p&一直翻啊翻, 翻到函数头了&/p&&img src=&/69ee98ac198f1ea80a4c39c4411aed68_b.png& data-rawwidth=&753& data-rawheight=&341& class=&origin_image zh-lightbox-thumb& width=&753& data-original=&/69ee98ac198f1ea80a4c39c4411aed68_r.png&&&p&ESI=ECX. 一般ECX或者ESI传递的, 都是this指针, 就是类指针.&/p&&p&比如说 Class::AAA() 里面默认有一个参数传递this指针. 汇编自动生成, 但是代码省略.&/p&&img src=&/fdbb8485fa_b.png& data-rawwidth=&753& data-rawheight=&120& class=&origin_image zh-lightbox-thumb& width=&753& data-original=&/fdbb8485fa_r.png&&&p&同理, 顺便做个记号, 因为你总不可能记0x????? 老夫记忆力不行.&/p&&img src=&/68a2a78a40e6e3ad2b194e9c23cce62f_b.png& data-rawwidth=&912& data-rawheight=&135& class=&origin_image zh-lightbox-thumb& width=&912& data-original=&/68a2a78a40e6e3ad2b194e9c23cce62f_r.png&&&p&继续回溯!&/p&&img src=&/c18ac5a4dca7_b.png& data-rawwidth=&1210& data-rawheight=&142& class=&origin_image zh-lightbox-thumb& width=&1210& data-original=&/c18ac5a4dca7_r.png&&&br&&p&函数头&/p&&img src=&/304ce33fcf15dd01b5dec3ec9cc9f099_b.png& data-rawwidth=&928& data-rawheight=&107& class=&origin_image zh-lightbox-thumb& width=&928& data-original=&/304ce33fcf15dd01b5dec3ec9cc9f099_r.png&&&p&继续回溯&/p&&img src=&/2f93cbfd4c_b.png& data-rawwidth=&817& data-rawheight=&554& class=&origin_image zh-lightbox-thumb& width=&817& data-original=&/2f93cbfd4c_r.png&&&br&&p&发现了这样! 很明显就是一个递归嘛!&/p&&p&先不管这个递归, 直接先找到上一层, 因为如果你一直卡在这个递归里面, 万一你上一层也是N个递归或者说是一条死路呢? 所以你得先寻找到根源, 再做详细分析!&/p&&p&继续函数头部下断点, 那么你会发现&/p&&img src=&/eb83c7c7b2bdaf7e2df805_b.png& data-rawwidth=&1498& data-rawheight=&539& class=&origin_image zh-lightbox-thumb& width=&1498& data-original=&/eb83c7c7b2bdaf7e2df805_r.png&&&br&&p&他的[ESP]=266E02B&/p&&img src=&/86ede7c5455_b.png& data-rawwidth=&718& data-rawheight=&156& class=&origin_image zh-lightbox-thumb& width=&718& data-original=&/86ede7c5455_r.png&&&br&&p&也就是这里. 所以要过滤这个!使用条件断点!&/p&&p&[ESP]!=266E02B&/p&&img src=&/3bc417d71d_b.png& data-rawwidth=&1504& data-rawheight=&419& class=&origin_image zh-lightbox-thumb& width=&1504& data-original=&/3bc417d71d_r.png&&&br&&img src=&/93be7dab7c174be1cc3946b_b.png& data-rawwidth=&883& data-rawheight=&149& class=&origin_image zh-lightbox-thumb& width=&883& data-original=&/93be7dab7c174be1cc3946b_r.png&&&p&总算找到Base了.&/p&&p&那么我们再来分析这个递归&/p&&img src=&/358a346ccd8a_b.png& data-rawwidth=&1031& data-rawheight=&719& class=&origin_image zh-lightbox-thumb& width=&1031& data-original=&/358a346ccd8a_r.png&&&br&&p&好了。然后就可以动手了写代码了.&/p&&p&首先因为这个RootBase是在DLL里面的, 因为DLL的加载地址不同, 所以解析出的Base也不同, 这个需要知道PE文件的如何计算偏移的。&/p&&p&我就直接粗暴一点, 暴力搜索内存&/p&&img src=&/843b49bc92c166ab34952_b.png& data-rawwidth=&941& data-rawheight=&416& class=&origin_image zh-lightbox-thumb& width=&941& data-original=&/843b49bc92c166ab34952_r.png&&&img src=&/6a6e3e2edec8aabdafdb_b.png& data-rawwidth=&791& data-rawheight=&490& class=&origin_image zh-lightbox-thumb& width=&791& data-original=&/6a6e3e2edec8aabdafdb_r.png&&&img src=&/bd4d5c4d70_b.png& data-rawwidth=&385& data-rawheight=&502& class=&content_image& width=&385&&&img src=&/a9ecea3038ecc_b.png& data-rawwidth=&971& data-rawheight=&628& class=&origin_image zh-lightbox-thumb& width=&971& data-original=&/a9ecea3038ecc_r.png&&&p&MFC做个注入DLL…… 不要问我为嘛用MFC,因为它是VS自带的,方便立马用。反正关了灯都一样. &/p&&img src=&/9f95ee250ee1_b.png& data-rawwidth=&824& data-rawheight=&650& class=&origin_image zh-lightbox-thumb& width=&824& data-original=&/9f95ee250ee1_r.png&&&br&&br&&img src=&/edf87de1aa13b323c3a995b5620200dd_b.png& data-rawwidth=&583& data-rawheight=&209& class=&origin_image zh-lightbox-thumb& width=&583& data-original=&/edf87de1aa13b323c3a995b5620200dd_r.png&&&p&随便写一个。 不要太讲究了。 &/p&&p&编译! 注入! 测试! 结果如下:&/p&&img src=&/afbf90b6f7cdd_b.png& data-rawwidth=&121& data-rawheight=&418& class=&content_image& width=&121&&&p&好啦。然后发现了辣么多个Base, 然后找名字!&/p&&br&&p&从名字入手. 这个英雄叫'虚入梦'. 顺便这个游戏是UTF-8编码(略过如何求证的).&/p&&p&所以这个英雄名称对应的编码是=EE6A2A6&/p&&img src=&/fc7ecf9d39ad_b.png& data-rawwidth=&243& data-rawheight=&190& class=&content_image& width=&243&&&p&打开CE, 搜一下&/p&&img src=&/d4dff0a32b1e0eeafc7121c_b.png& data-rawwidth=&515& data-rawheight=&404& class=&origin_image zh-lightbox-thumb& width=&515& data-original=&/d4dff0a32b1e0eeafc7121c_r.png&&&p&务必要记住把 扫'只读'内存勾上&/p&&p&然后直接一个一个修改这个Text, 看下哪个是对应的名称. 比如说&/p&&img src=&/72f7aa6ad384d9adf29a1d_b.png& data-rawwidth=&362& data-rawheight=&183& class=&content_image& width=&362&&&p&手动修改一个&/p&&img src=&/c42ce206a4acc93b7a0b_b.png& data-rawwidth=&619& data-rawheight=&268& class=&origin_image zh-lightbox-thumb& width=&619& data-original=&/c42ce206a4acc93b7a0b_r.png&&&img src=&/eedca09cbd5a7bbfaba7d0_b.png& data-rawwidth=&559& data-rawheight=&194& class=&origin_image zh-lightbox-thumb& width=&559& data-original=&/eedca09cbd5a7bbfaba7d0_r.png&&&p&运气好, 第一个就是。
如果没变化, 那就一个一个往下改。 记得如果不是的话, 要改回去. 再改下一个。
也可以用二分&修改&(查找)法, 直接一次性改一半. 如果不存在的话, 那肯定在另一半。时间复杂度O()=O(logn) 必须学以致用!!!&/p&&p&接下来就是开启OD, 附加游戏.&/p&&img src=&/862b689f27c3d0eede9459_b.png& data-rawwidth=&617& data-rawheight=&625& class=&origin_image zh-lightbox-thumb& width=&617& data-original=&/862b689f27c3d0eede9459_r.png&&&p&下一个访问断点.&/p&&img src=&/a17eeef91b896_b.png& data-rawwidth=&556& data-rawheight=&594& class=&origin_image zh-lightbox-thumb& width=&556& data-original=&/a17eeef91b896_r.png&&&p&断下来了, 就是一个字符串循环复制, 返回到上一层CALL&/p&&img src=&/536fd04b7de658af7ef3e_b.png& data-rawwidth=&921& data-rawheight=&213& class=&origin_image zh-lightbox-thumb& width=&921& data-original=&/536fd04b7de658af7ef3e_r.png&&&p&eax就是人物对象指针.
edi就是一个缓冲区, 把人物指针的Name复制到缓冲区.&/p&&img src=&/362e6daff3_b.png& data-rawwidth=&960& data-rawheight=&464& class=&origin_image zh-lightbox-thumb& width=&960& data-original=&/362e6daff3_r.png&&&p&继续回溯&/p&&img src=&/1df162ddac6647d73abceb_b.png& data-rawwidth=&903& data-rawheight=&180& class=&origin_image zh-lightbox-thumb& width=&903& data-original=&/1df162ddac6647d73abceb_r.png&&&p&这个CALL就可以用了。
&/p&&div class=&highlight&&&pre&&code class=&language-asy&&&span class=&n&&PUSH&/span& &span class=&mh&&0x200&/span&
&span class=&n&&PUSH&/span& &span class=&n&&Buffer&/span&
&span class=&n&&MOV&/span& &span class=&n&&ECX&/span&&span class=&p&&,&/span& &span class=&n&&pObjectPointer&/span&
&span class=&n&&CALL&/span& &span class=&mf&&235F&/span&&span class=&mi&&640&/span&
&/code&&/pre&&/div&&br&&p&然而我在观察地址的时候, 就观察出来&/p&&img src=&/20a94d93dba_b.png& data-rawwidth=&1225& data-rawheight=&136& class=&origin_image zh-lightbox-thumb& width=&1225& data-original=&/20a94d93dba_r.png&&&br&&p&因为他们2个地址是一毛一样的!&/p&&img src=&/5dd3beaaceea9c75a5383_b.png& data-rawwidth=&1457& data-rawheight=&435& class=&origin_image zh-lightbox-thumb& width=&1457& data-original=&/5dd3beaaceea9c75a5383_r.png&&&p&ECX=[ESI+238]
0DDF3CC4=[14C]&/p&&img src=&/33b1a3785ceadcb3b5e81b6_b.png& data-rawwidth=&1375& data-rawheight=&624& class=&origin_image zh-lightbox-thumb& width=&1375& data-original=&/33b1a3785ceadcb3b5e81b6_r.png&&&p&其实往上跟也有可能可以关联起来, 但是我懒得继续回溯了……&/p&&img src=&/afd08d1cb851_b.png& data-rawwidth=&119& data-rawheight=&373& class=&content_image& width=&119&&&p&所以……&/p&&img src=&/5bbca7a1da_b.png& data-rawwidth=&680& data-rawheight=&292& class=&origin_image zh-lightbox-thumb& width=&680& data-original=&/5bbca7a1da_r.png&&&br&&img src=&/987ba2c5c9d8d6a14159_b.png& data-rawwidth=&439& data-rawheight=&81& class=&origin_image zh-lightbox-thumb& width=&439& data-original=&/987ba2c5c9d8d6a14159_r.png&&&br&&img src=&/3df9dfafcfa41e_b.png& data-rawwidth=&192& data-rawheight=&374& class=&content_image& width=&192&&&p&发现了有些地址可能是其他分类的吧? &/p&&p&分类判断懒得写了。 干脆&/p&&img src=&/2daa296d0bfadeb6b7cf_b.png& data-rawwidth=&328& data-rawheight=&43& class=&content_image& width=&328&&&br&&img src=&/62f088a5daca02cdb92a5_b.png& data-rawwidth=&1454& data-rawheight=&750& class=&origin_image zh-lightbox-thumb& width=&1454& data-original=&/62f088a5daca02cdb92a5_r.png&&&p&结果就是&/p&&img src=&/b915effcf48ed_b.png& data-rawwidth=&532& data-rawheight=&386& class=&origin_image zh-lightbox-thumb& width=&532& data-original=&/b915effcf48ed_r.png&&&p&好啦。 至少有一个是对的.
因为刚才游戏不小心被我弄崩了。我就顺便重开而且换了个游戏.
暂时目的达到了. 获取到当前角色. (遍历所有英雄小兵之类的暂时没这个需求,不做)&/p&&p&下一步就是修改攻击种类:&/p&&img src=&/b4fb55e45f299d440f178923_b.png& data-rawwidth=&1205& data-rawheight=&547& class=&origin_image zh-lightbox-thumb& width=&1205& data-original=&/b4fb55e45f299d440f178923_r.png&&&p&按照刚才的步骤, 搜索显示的Text&/p&&img src=&/177cd69cd55aa98b9173c_b.png& data-rawwidth=&921& data-rawheight=&477& class=&origin_image zh-lightbox-thumb& width=&921& data-original=&/177cd69cd55aa98b9173c_r.png&&&br&&p&2分搜索大法好, 3次即可到达。&/p&&p&下访问断点&/p&&img src=&/1ccd89e8ceb913e9630e65_b.png& data-rawwidth=&721& data-rawheight=&802& class=&origin_image zh-lightbox-thumb& width=&721& data-original=&/1ccd89e8ceb913e9630e65_r.png&&&p&惯例的字符串复制操作, 返回到上一个函数!&/p&&br&&img src=&/60ca3f8dd396f_b.png& data-rawwidth=&914& data-rawheight=&421& class=&origin_image zh-lightbox-thumb& width=&914& data-original=&/60ca3f8dd396f_r.png&&&br&&p&EAX就是Text, &/p&&img src=&/128c6e8b61bc01e7b4d289ebcfe286af_b.png& data-rawwidth=&1185& data-rawheight=&675& class=&origin_image zh-lightbox-thumb& width=&1185& data-original=&/128c6e8b61bc01e7b4d289ebcfe286af_r.png&&&p&上面的MOV EAX, [ESP+14]. 就是从上一个函数传递过来的参数. 返回去看好一下.&/p&&p&上一层CALL看参数&/p&&img src=&/22f933ffa35e7906ddb9c6aea623edcf_b.png& data-rawwidth=&1169& data-rawheight=&736& class=&origin_image zh-lightbox-thumb& width=&1169& data-original=&/22f933ffa35e7906ddb9c6aea623edcf_r.png&&&p&第一个参数&/p&&br&&p&第二个参数&/p&&img src=&/2fae35e0c4_b.png& data-rawwidth=&627& data-rawheight=&462& class=&origin_image zh-lightbox-thumb& width=&627& data-original=&/2fae35e0c4_r.png&&&p&就是上上张图, 就懒得复制了&/p&&p&第三个参数&/p&&img src=&/563aada8d9b5e5f51ac9e8f_b.png& data-rawwidth=&977& data-rawheight=&816& class=&origin_image zh-lightbox-thumb& width=&977& data-original=&/563aada8d9b5e5f51ac9e8f_r.png&&&img src=&/b7e6b24bec2_b.png& data-rawwidth=&426& data-rawheight=&136& class=&origin_image zh-lightbox-thumb& width=&426& data-original=&/b7e6b24bec2_r.png&&&p&就是这个玩意。 那么我们要找的是种类。 也就是第二个参数=[ESP+0BC]
然后往上分析……过程略, 多断点几次的事, 我就不废话了。 &/p&&p&然后往上慢慢下断看参数, 直到……&/p&&img src=&/1afec82ac1c30c17a8bf9_b.png& data-rawwidth=&1461& data-rawheight=&832& class=&origin_image zh-lightbox-thumb& width=&1461& data-original=&/1afec82ac1c30c17a8bf9_r.png&&&br&&img src=&/edc41b96e8e8_b.png& data-rawwidth=&1511& data-rawheight=&446& class=&origin_image zh-lightbox-thumb& width=&1511& data-original=&/edc41b96e8e8_r.png&&&p&mov
edx, dword ptr [esp+10]
ecx, dword ptr [edx+2ADD3B0]&/p&&img src=&/eba612405eecc7b1abca41cefe4314f2_b.png& data-rawwidth=&1212& data-rawheight=&198& class=&origin_image zh-lightbox-thumb& width=&1212& data-original=&/eba612405eecc7b1abca41cefe4314f2_r.png&&&p&接下去就找[ESP+34]&/p&&img src=&/db2bbe2282910_b.png& data-rawwidth=&1203& data-rawheight=&529& class=&origin_image zh-lightbox-thumb& width=&1203& data-original=&/db2bbe2282910_r.png&&&p&既然这样, 那么我们试试.&/p&&p&首先&/p&&img src=&/a6b9a79c7ef98edf798b9_b.png& data-rawwidth=&648& data-rawheight=&150& class=&origin_image zh-lightbox-thumb& width=&648& data-original=&/a6b9a79c7ef98edf798b9_r.png&&&br&&p&所以 [0F923CC4] + 1E8 = EDI&/p&&p&EAX = 攻击种类 = [EDI + 0 * 4 + 0xF4]. (已经探明EBX=0)&/p&&p&所以……&/p&&img src=&/587fff5c99ac6b1dba5e543d15263d50_b.png& data-rawwidth=&583& data-rawheight=&357& class=&origin_image zh-lightbox-thumb& width=&583& data-original=&/587fff5c99ac6b1dba5e543d15263d50_r.png&&&br&&p&我们换一个有混乱攻击的号就知道。 混乱攻击的时候。 这个值是=5的。&/p&&p&所以我们改成5试试。&/p&&img src=&/41b71650bfd81153feed8de_b.png& data-rawwidth=&1126& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&1126& data-original=&/41b71650bfd81153feed8de_r.png&&&p&嘿嘿!&/p&&p&然后是不是有效。 最上面的那2张图有数值测试!&/p&&p&顺便…… 肯定是联网无效的, 因为有数值校验的。可以单机爽一下!&/p&&p&而且……哪怕你用各种作弊图, 暂时老夫还没发现哪个可以改攻击类型!&/p&&p&神圣护甲同理, 我就多此一举了。&/p&&p&还有几张图顺便贴了&/p&&img src=&/23ed798ab3b_b.png& data-rawwidth=&663& data-rawheight=&359& class=&origin_image zh-lightbox-thumb& width=&663& data-original=&/23ed798ab3b_r.png&&&img src=&/fb60ffb7ca984e6a25d6028_b.png& data-rawwidth=&1210& data-rawheight=&783& class=&origin_image zh-lightbox-thumb& width=&1210& data-original=&/fb60ffb7ca984e6a25d6028_r.png&&&br&&p&这篇文章到这里就结束了。 以后在这篇文章也不会更新技术类的话题了。
不知哪位英语比较好? 最近学英语陷入死循环, 各种不爽背单词, 但是不背也不行。
有没有能拯救我……必有酬谢!&/p&&p&很多人都问怎么学, 其实嘛&/p&&a href=&///?target=http%3A///forumdisplay.php%3Ff%3D20& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&『求助问答』&i class=&icon-external&&&/i&&/a&&img src=&/44e74fcc4f0d96deaf086e_b.png& data-rawwidth=&1055& data-rawheight=&206& class=&origin_image zh-lightbox-thumb& width=&1055& data-original=&/44e74fcc4f0d96deaf086e_r.png&&&p&我并非推荐你们去参加培训, 而是这里有课程目录。
按照这个目录去学就好了。
例如:&a href=&///?target=http%3A///portal.php%3Fmod%3Dview%26aid%3D10& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&游戏安全工程师培训介绍-WebMaster-15PB信息安全教育&i class=&icon-external&&&/i&&/a&&/p&&p&老夫的git项目,无聊的时候写的LOL刷金币。 可以参考一下。
强调一下: 只做技术交流。 不要瞎搞!
&a href=&///?target=https%3A///VideoCardGay/LOL_China& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - VideoCardGay/LOL_China&i class=&icon-external&&&/i&&/a&&/p&&p&给各位想自学的人一点学习方向的建议。
一般分2种, 一种是为了编程而学外挂, 一种是为了学外挂而编程。
第一种就是以编程为主, 对外挂技术了解一下。 这里就不谈了, 正统道路的学习方法多得是。 我就不一一举例了。
第二种方法, 我以0编程基础来举例。
1:要熟悉C/C++语法, 可以做一些像模像样的小玩意, 比如说控制台下的XX管理系统, 读写文件, 什么银行存取金币系统之类这样的小玩意。
这部分后面就要应用在你的外挂控制台上
如:&a href=&/p/& class=&internal&&知乎专栏&/a&
2:学习完上面的,我个人建议开始学习socket,
功能大概就要激活CDK,校验CDK的时间, 用长连接。 大概就是生成CDK, 把CDK保存到Server, 然后Client激活CDK要去Server校验, 并且用心跳来保持连接。
这一步后面要应用到 防破解, 收费系统, 还有一些比如说组队, 交易, 邮寄都可以丢到Server上完成, 比如说不同电脑下, 如何让他们同一个大区同一个地图下如何分配组队和交易, 而且还能进一步锻炼你的编程能力。 建议要用非阻塞的异步socket。(用HTTP来做验证的可以忽略这一步)
3: 这个时候可以做点有意思的, 比如说先学会用模拟按键+识图 去做某个游戏的登录。就用LOL来举例子, 可以做LOL的客户端登录。 用模拟按键+鼠标操作, 然后用识图来判断当前在哪个步骤了。 图片识别可以用OpenCv库&a href=&///?target=http%3A//docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Template Matching&i class=&icon-external&&&/i&&/a&,然后如果出现验证码, 可以用网上那种打码系统,QQ游戏的验证码挺便宜的, 最多几分钱一次。
如:&a href=&///?target=https%3A///VideoCardGuy/AutoLoginByBnsChina& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&VideoCardGuy/AutoLoginByBnsChina&i class=&icon-external&&&/i&&/a&
4: 这个时候你可以写一个控制台(Console模式), 保存帐号, 读取帐号, 开始登录。 如何判断到游戏登录完毕, 就登录下一个帐号, 保存登录失败(如密码错误)的日志, 操作完毕的日志。 如何再下一次启动的时候忽略已经成功的帐号。 中间的种种操作, 自己做一遍就知道了。
如:&a href=&///?target=https%3A///VideoCardGuy/AutoLoginByBnsChina& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&VideoCardGuy/AutoLoginByBnsChina&i class=&icon-external&&&/i&&/a&
5: 这个时候建议把Console模式的控制台改成UI, UI可以用C#来做,也可以用MFC/QT来做, 用哪个语言来做无所谓,
学习一下多线程的操作, 如何刷新数据到UI, 如何从Server查询CDK返回到控制台, 比如说剩余时间对吧.
6:这个时候就开始学习简单的汇编指令, 学习如何使用调试器, 怎么去逆向游戏的人物属性, 把基本的HP,MP,攻击力之类的逆向出来, 然后显示到控制台, 这里需要比较多的API知识, 比如如何注入DLL到游戏, 比如运用指针读取游戏的数据. 这一步做完你已经可以自己写一个UI注入到游戏里面, 显示出人物各种属性,周围怪物,Npc。 你也需要一些基本的数据结构知识,比如链表,二叉树,数组,std::vector,std::string在汇编的表现形式。
7:可以逆向游戏的功能, 找到游戏的明文组包函数, 然后下断后就能断下绝大部分游戏的功能, 然后想办法模拟调用, 你就可以做到吃药, 释放技能,交接任务。 这一步我就不多说了,反正完成了几乎是搞完了。
8: 把所有功能和UI控制台和Server端关联起来。 就是一个完整版的挂了。 下面就是一步一步添加更多的功能了,要考虑用脚本去写主线了,要考虑框架的问题了,要学习如何反反调试,如何多开,防检测,过游戏保护,做资源优化,写导航寻路等等……当你都学完之后,那么恭喜你,你已经成功获得&外挂全能大神&的称号了。&/p&&p&&a href=&/people/wu-you-wu-qiu-wu-you-wu-qiu/pins/posts& class=&internal&&无忧无求 - 知乎&/a& 偶尔抽空写几篇教程&/p&&p&&b&如果是妹子,请私信我探讨如何学习编程,&/b&&/p&&p&&b&如果是汉子,拜托,网上这么多学习资源,你都没法自学。我也是没有人教的啊!!!那你自生自灭吧!&/b&&/p&&br&&p&&b&---------------------------------&/b&&/p&&p&感觉不少人挺急功近利的, 都想着写挂是一门快速入门,快速赚大钱的行业。 我真是呵呵了。特别是大一或者大二的学生。&/p&&p&我就想说几点:&/p&&p&第一,你要达到一个正常可以上班的程序员的水平, 从0开始你要花多久?&/p&&p&第二,你要学习Window API的一些简单处理,搭建属于自己的工具,需要花多久?&/p&&p&第三,你学习汇编,逆向要花多久?&/p&&p&第四,你要学习逆向游戏来分析多开,代码检测要多久?&/p&&p&第五,当你进入到游戏外挂的大门后, 你会发现你的数学抽象概念知识严重缺乏,我就说几个问题,你怎么转换成数学问题。一个BOSS向它脸朝向的方向的前面和后面放了一个激光炮,你必须躲开这个技能,首先你如何判断你是否在这个激光炮的范围, 如果在的话, 怎么躲开?
如果这个激光炮是全屏的, 只有BOSS的左边和右边3m的地方是一个很小范围的圆形安全点, 如何计算出这个安全点?
如果BOSS还随机在地图放了一些比如说是圆形的障碍物, 如何计算出一条路线可以绕过这些随机的圆形走到安全点上?&/p&&p&那就也来一个比较入门的题好了。已知BOSS的坐标和朝向, 怎么计算出BOSS的左边和右边, 也就是BOSS脸朝向的90°和270°, 距离是3m的那2个坐标?
&/p&&p&如果你可以瞬移,但是游戏检测瞬移的距离不能过远, 给你2个任意的坐标.
每次瞬移我只能瞬移3m。 请列出一个公式, 如何获取2点之间的所有的瞬移坐标。&/p&&p&再来一个比较抽象的问题。这个是程序和数学结合的问题:在游戏上古世纪里面, 那个拉货车只能按键盘AD来转向, W来前进。 在没寻路的情况下, 假设我有几百上千个从 起点到终点的坐标(每个坐标的距离不固定,而且起点和终点不一定是直线)。 已知你当前的角度和当前的坐标, 按一次A或者D的角度并不稳定的情况下,怎么编写这个拉货从起点到终点的程序?&/p&&p&其实这些问题基本都是高中问题, 要是抽象出数学问题.90%高中生的感觉都能解决。 但是这种从实际问题抽象成数学问题的经验, 可不是1天2天就能练成的。&/p&&p&第六、假设你把上述所有问题都解决了, 你会发现一个挡在了无数能写挂,而且写得很完美很完善,但是赚不了钱的问题, 就是封号!
行为检测,代码检测,堆栈检测,IP检测,游戏区域检测,这些怎么过?怎么测试? 要知道像LOL,梦幻西游这种游戏, 你要是能完美解决封号的话, 年收入百万已经是很低调的说法。实际上整个中国能做到的,又有几个&&b&敢做&&/b&呢?&/p&&br&&p&第七、假设你解决了封号的问题, 如果你写了1级-满级的主线, 你最后发现, 完成了没几天,游戏官方直接把游戏主线给的金币和物品全和谐了, 你花尽心思写了组队副本刷BOSS,游戏官方直接把副本任务和给的物品直接全和谐了,怎么找出钱路线?你要考虑你每个号都不是神装, 有些副本你输出不够, 根本打不了。 只能玩家去打。&/p&&br&&br&&p&---------------------------&/p&&p&有苏州的资深吃货老司机吗?
&/p&&p&有的话请务必私信带带我!
&/p&&p&PS: 一个人出去点菜好尴尬!1,2个菜嫌少。3个菜就是浪费。&/p&
我也来简单回答一下题主。
首先, 外挂是一门很大很注重实践的一门技术大类。
在这个技术大类之下还分很多小类。
一般来说分逆向,编写逻辑 这2方面
所谓逆向,也就是分析游戏的客户端,寻找相关功能的函数
而编写逻辑,如掉线重登,自动打怪,自动吃药 之类…
&p&最近看到国内网络上突然Magic Leap的话题火了,并且跟着很多人无理由和根据的赞或黑Magic Leap。我在斯坦福计算机系上学的时候,对Magic Leap很好奇,正好在学校能接触到各路和Magic Leap相关的大神,所以在这方面做了些研究,我觉得可以分享点技术性干货,解释一些原理,让大家有点材料来赞或黑。&/p&&p&目前Magic Leap只有一个公开视频是实际拍摄的: &a href=&///?target=https%3A///watch%3Fv%3Dkw0-JRa9n94& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&/watch?&/span&&span class=&invisible&&v=kw0-JRa9n94&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& (桌腿后的机器人和太阳系)(youku: &a href=&///?target=http%3A///v_show/id_XMTM2NjM0MjE1Ng%3D%3D.html%3Ffrom%3Ds1.8-1-1.2& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Magic Leap Demo&i class=&icon-external&&&/i&&/a&),本文只以这个视频的例子来做阐释。 &/p&&p&-------------------------
&/p&&p&先说一下我关于Magic Leap的信息来源:
1. 日,Magic Leap在2014年9月融了5个亿以后,来Stanford招人,开了一个Info Session,标题是&The World is Your New Desktop” (世界就是你的新桌面)多么霸气!当时是Magic Leap 感知研究的高级副总裁 (VP of Perception) Gary Bradski 和 计算视觉的技术负责人 (Lead of Computer Vision) Jean-Yves Bouguet 来作演讲。Gary是计算机视觉领域的领军人物,在Intel和柳树车库(Willow Garage)创造并发展了OpenCV(计算视觉工具库),也是ROS(机器人操作系统)的创始团队之一,同时也是Stanford顾问教授。Jean-Yves原来在Google负责谷歌街景车(Street View Car)的制造,是计算视觉技术的大牛。他们加入Magic Leap是非常令人震惊的。我参加了这次Info Session, 当时Gary来介绍Magic Leap在感知部分的技术和简单介绍传说中的数字光场Cinematic Reality的原理,并且在允许录影的部分都有拍照记录。本文大部分的干货来自这次演讲。
&/p&&img src=&/6cce90efa139afe3f436196_b.png& data-rawwidth=&696& data-rawheight=&980& class=&origin_image zh-lightbox-thumb& width=&696& data-original=&/6cce90efa139afe3f436196_r.png&&&br&&br&&img src=&/e2de646e37237bad40bb13_b.png& data-rawwidth=&690& data-rawheight=&630& class=&origin_image zh-lightbox-thumb& width=&690& data-original=&/e2de646e37237bad40bb13_r.png&&&br&&br&&p&2. 我今年年初上了 Stanford 计算摄影和数字光场显示的大牛教授Gordon Wetzstein的一门课:EE367 Computational Imaging and Display(计算影像和显示器) :其中第四周的Computational illumination,Wearable displays
和 Displays Blocks(light field displays) 这三节都讲到Magic Leap的原理。现在大家也可以去这个课程网站上看到这些资料,&a href=&///?target=http%3A//stanford.edu/class/ee367/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&EE367 / CS448I: Computational Imaging and Display&i class=&icon-external&&&/i&&/a&&/p&&p&顺便介绍一下 Gordon 所在的Stanford 计算图形组,由Marc Levoy(后来跑去造Google Glass的大牛教授)一直致力于光场的研究,从Marc Levoy提出光场相机,到他的学生Ren Ng开创Lytro公司制造光场相机,到现在Gordon教授制造光场显示器(裸眼光场3D显示器),这个组在光场方面的研究一直是世界的领头羊。而Magic Leap可能正在成为光场显示器的最大应用。
&a href=&///?target=http%3A//putationalimaging.org/research-overview/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Computational Imaging
Research Overview&i class=&icon-external&&&/i&&/a&&/p&&img src=&/7cf6ba49c74b600a24e9_b.png& data-rawwidth=&1954& data-rawheight=&788& class=&origin_image zh-lightbox-thumb& width=&1954& data-original=&/7cf6ba49c74b600a24e9_r.png&&&br&&br&&p&3. 今年参加了光场影像技术的研讨会 Workshop on Light Field Imaging ,现场有很多光场技术方面的展示,我和很多光场显示技术的大牛交流了对Magic Leap的看法。特别的是,现场体验了接近Magic Leap的光场技术Demo,来自Nvidia的Douglas Lanman的 Near-Eye Light Field Displays 。&a href=&///?target=https%3A///publication/near-eye-light-field-displays& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Near-Eye Light Field Displays&i class=&icon-external&&&/i&&/a&&/p&&img src=&/fcbe71ebf3a4_b.png& data-rawwidth=&135& data-rawheight=&135& class=&content_image& width=&135&&&br&&br&&p&4. 今年年中去了微软研究院Redmond访问,研究院的首席研究员Richard Szeliski (计算机视觉大神,计算机视觉课本的作者,&a href=&///?target=http%3A//szeliski.org/book& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Computer Vision: Algorithms and Applications&i class=&icon-external&&&/i&&/a&)让我们试用了Hololens。感受了Hololens牛逼无比的定位感知技术。有保密协议,本文不提供细节,但提供与Magic Leap原理性的比较。
&/p&&p&==========
下面是干货。
&/p&&p&首先呢,科普一下 Magic Leap 和 Hololens 这类AR眼镜设备,都是为了让你看到现实中不存在的物体和现实世界融合在一起的图像并与其交互。从技术上讲,可以简单的看成两个部分:1. 对现实世界的感知 (Perception)
2. 一个头戴式显示器以呈现虚拟的影像 (Display) 。
&/p&&p&我会分感知部分和显示部分来分别阐释Magic Leap的相关技术。
&/p&&p&先简单回答这个问题:
&/p&&p&==== 显示部分 =====
&b&Q1. Hololens和Magic Leap有什么区别?Magic Leap的本质原理是什么?
&/b&&/p&&br&&p&感知部分其实Hololens和Magic Leap从技术方向上没有太大的差异,都是空间感知定位技术。本文之后会着重介绍。Magic Leap 与 Hololens 最大的不同应该来自显示部分,Magic Leap是用光纤向视网膜直接投射整个数字光场(Digital Lightfield)产生所谓的Cinematic Reality(电影级的现实)。Hololens采用一个半透玻璃,从侧面DLP投影显示,虚拟物体是总是实的,与市场上Espon的眼镜显示器或Google Glass方案类似,是个2维显示器,视角还不大,40度左右,沉浸感会打折扣。
&/p&&p&本质的物理原理是:光线在自由空间中的传播,是可以由4维光场唯一表示的。成像平面每个像素中包含到这个像素所有方向的光的信息,对于成像平面来讲方向是二维的,所以光场是4维的。平时成像过程只是对四维光场进行了一个二维积分(每个像素上所有方向的光的信息都叠加到一个像素点上),传统显示器显示这个2维的图像,是有另2维方向信息损失的。而Magic Leap是向你的视网膜直接投射整个4维光场, 所以人们通过Magic Leap看到的物体和看真实的物体从数学上是没有什么区别的,是没有信息损失的。理论上,使用Magic Leap的设备,你是无法区分虚拟物体和现实的物体的。
&/p&&p&使用Magic Leap的设备,最明显的区别于其他技术的效果是&b&人眼可以直接选择聚焦&/b&(主动选择性聚焦)。比如我要看近的物体,近的物体就实,远的就虚。注意这不需要任何的人眼跟踪技术,因为投射的光场还原了所有信息,所以使用者直接可以做到人眼看哪实哪,和真实物体一样。举个例子:在虚拟太阳系视频的27秒左右(如这个gif图),摄影机失焦了,然后又对上了,这个过程只发生在摄影机里,和Magic Leap的设备无关。换句话说,虚拟物体就在那,怎么看是观察者自己的事。这就是Magic Leap牛逼的地方,所以Magic Leap管自己的效果叫Cinematic Reality。
&/p&&br&&img src=&/6b57a9ae7308bcfcc8869acd0e44b0c3_b.jpg& data-rawwidth=&260& data-rawheight=&146& class=&content_image& width=&260&&&img src=&/245cac1c46be651bd282a528f37e8ba6_b.jpg& data-rawwidth=&260& data-rawheight=&146& class=&content_image& width=&260&&&br&&br&&p&&b&Q2. 主动选择性聚焦有什么好处?传统的虚拟显示技术中,为什么你会头晕?Magic Leap是怎么解决这个问题的?
&/b&&/p&&p&众所周知,人类的眼睛感知深度主要是靠两只眼睛和被观察物体做三角定位(双目定位, triangulation cue)来感知被观察物体的与观察者的距离的。但三角定位并不是唯一的人类感知深度的线索,人脑还集成了另一个重要的深度感知线索:人眼对焦引起的物体锐度(虚实)变化(sharpness or focus cue) 。但传统的双目虚拟显示技术(如Oculus Rift或Hololens) 中的物体是没有虚实的。举个例子,如下图,当你看到远处的城堡的时候,近处的虚拟的猫就应该虚了,但传统显示技术中,猫还是实的,所以你的大脑就会引起错乱,以为猫是很远的很大的一个物体。但是这和你的双目定位的结果又不一致,经过几百万年进化的大脑程序一会儿以为猫在近处,一会儿以为猫在远处,来来回回你大脑就要烧了,于是你要吐了。而Magic Leap投影了整个光场,所以你可以主动选择性聚焦,这个虚拟的猫就放在了近处,你看它的时候就是实的,你看城堡的时候,它就是虚的,和真实情况一样,所以你不会晕。演讲中Gary调侃对于Jean-Yves这种带10分钟Oculus就吐的家伙来说,现在他一天带16个小时Magic Leap都不会晕。谁用谁知道,巴扎嘿!
&/p&&img src=&/b562a40aa859a47c59be_b.png& data-rawwidth=&544& data-rawheight=&638& class=&origin_image zh-lightbox-thumb& width=&544& data-original=&/b562a40aa859a47c59be_r.png&&&br&&br&&p&补充:有人问为什么网上说虚拟现实头晕是因为帧率不够原因?
帧率和延时虽然是目前的主要问题,但都不是太大的问题,也不是导致晕得决定性因素。这些问题用更快的显卡,好的IMU和好的屏幕,还有头部动作预测算法都能很好解决。我们要关心一些本质的晕眩问题。&/p&&p&这里要说到虚拟现实和增强现实的不同。
虚拟现实中,使用者是看不到现实世界的,头晕往往是因为人类感知重力和加速度的内耳半规管感受到的运动和视觉看到的运动不匹配导致的。所以虚拟现实的游戏,往往会有晕车想吐的感觉。这个问题的解决不是靠单一设备可以搞定的,如果使用者的确坐在原定不动,如果图像在高速移动,什么装置能骗过你的内耳半规管呢?一些市场上的方案,比如Omni VR,或者HTC Vive这样的带Tracking的VR系统让你实际行走才解决这个不匹配的问题,但这类系统是受场地限制的。不过THE VOID的应用就很好的利用了VR的局限,不一定要跑跳,可以用很小的空间做很大的场景,让你以为你在一个大场景里就好了。现在大部分虚拟现实的体验或全景电影都会以比较慢得速度移动视角,否则你就吐了。&/p&&p&但是Magic Leap是AR增强现实,因为本来就看的到现实世界,所以不存在这个内耳半规管感知不匹配的问题。对于AR来讲,主要挑战是在解决眼前投影的物体和现实物体的锐度变化的问题。所以Magic Leap给出的解决方案是很好的解决这个问题的。但都是理论上的,至于实际工程能力怎么样就靠时间来证明了。&/p&&p&&b&Q3. 为什么要有头戴式显示器?为什么不能裸眼全息?Magic Leap是怎么实现的?
&/b&&/p&&p&人类希望能凭空看到一个虚拟物体,已经想了几百年了。各种科幻电影里也出现了很多在空气中的全息影像。
但其实想想本质就知道,这事从物理上很难实现的:纯空气中没有可以反射或折射光的介质。显示东西最重要的是介质。很多微信上的疯传,以为Magic Leap不需要眼镜,我估计是翻译错误导致的,视频中写了Shot directly through Magic Leap tech.,很多文章错误的翻译成”&b&直接看到”或”裸眼全息&,&/b&其实视频是相机透过Magic Leap的技术拍的。
&/p&&p&目前全息基本还停留在全息胶片的时代(如下图,我在光场研讨会上看到的这个全息胶片的小佛像),或者初音未来演唱会那种用投影阵列向特殊玻璃(只显示某一特定角度的图像,而忽略其他角度的光线)做的伪全息。
&/p&&img src=&/87cb1454cfbbe936b67bef9b24bed34b_b.jpg& data-rawwidth=&260& data-rawheight=&195& class=&content_image& width=&260&&&img src=&/ad16fb55ffeb542a83dd1_b.jpg& data-rawwidth=&260& data-rawheight=&195& class=&content_image& width=&260&&&img src=&/e375f5efbfb9d410c77d1_b.jpg& data-rawwidth=&260& data-rawheight=&195& class=&content_image& width=&260&&&br&&p&Magic Leap想实现的是把整个世界变成你的桌面这样的愿景。所以与其在世界各个地方造初音未来那样的3D全息透明屏做介质或弄个全息胶片,还不如直接从人眼入手,直接在眼前投入整个光场更容易。其实Nvidia也在做这种光场眼镜,
&/p&&img src=&/fcbe71ebf3a4_b.png& data-rawwidth=&135& data-rawheight=&135& class=&content_image& width=&135&&&br&&p&Nvidia采用的方法是在一个二维显示器前加上一个微镜头阵列 Microlens array 来生成4维光场。相当于把2维的像素映射成4维,自然分辨率不会高,所以这类光场显示器或相机(Lytro) 的分辨率都不会高。本人亲测,效果基本就是在看马赛克画风的图案。
&/p&&p&而 Magic Leap 采用完全不同的一个方法实现光场显示,它采用光纤投影。不过,Magic Leap用的光纤投影的方式也不是什么新东西。在Magic Leap做光纤投影显示( Fiber optic projector) 的人是Brian Schowengerdt ,他的导师是来自华盛顿大学的教授Eric Seibel,致力于做超高分辨率光纤内窥镜8年了。简单原理就是光纤束在一个1mm直径管道内高速旋转,改变旋转的方向,然后就可以扫描一个较大的范围。Magic Leap的创始人比较聪明的地方,是找到这些做高分辨率光纤扫描仪的,由于光的可逆性,倒过来就能做一个高分辨率投影仪。如图,他们6年前的论文,1mm宽9mm长的光纤就能投射几寸大的高清蝴蝶图像。现在的技术估计早就超过那个时候了。&/p&&p&而这样的光纤高分辨率投影仪还不能还原光场,需要在光纤的另一端放上一个微镜头阵列microlens array,来生成4维光场。你会疑问这不就和Nvidia的方法一样了么?不,因为光纤束是扫描性的旋转,这个microlens array不用做的很密很大,只要显示扫描到的区域就好了。相当与把大量数据在时间轴上分布开了,和通讯中的分时一样,因为人眼很难分辨100帧上的变化,只要扫描帧率够高,人眼就分辨不出显示器是否旋转显示的。所以Magic Leap的设备可以很小,分辨率可以很高。&/p&&img src=&/2fff6d0e04ae072ea26e155f7d77d218_b.png& data-rawwidth=&602& data-rawheight=&390& class=&origin_image zh-lightbox-thumb& width=&602& data-original=&/2fff6d0e04ae072ea26e155f7d77d218_r.png&&&br&&br&&p&他本人也来Stanford给过一个Talk,Near-to-Eye Volumetric 3D Displays using Scanned Light。这个Talk讲的应该就是Magic Leap早期的原型。参考: &a href=&///?target=https%3A//depts.washington.edu/hplab/research/scanning-displays/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Fiber Scanned Displays&i class=&icon-external&&&/i&&/a&&/p&&br&&p&=== 感知部分 ===
&/p&&p&&b&Q4. 首先为什么增强现实要有感知部分?
&/b&&/p&&p&是因为设备需要知道自己在现实世界的位置(定位),和现实世界的三维结构(地图构建),才能够在显示器中的正确位置摆放上虚拟物体。举个最近的Magic Leap Demo视频的例子,比如桌子上有一个虚拟的太阳系,设备佩戴者的头移动得时候,太阳系还呆在原地,这就需要设备实时的知道观看者视角的精确位置和方向,才能反算出应该在什么位置显示图像。同时,可以看到桌面上还有太阳的反光,这就要做到设备知道桌子的三维结构和表面信息,才能正确的投射一个叠加影像在桌子的影像层上。难点是如何做到整个感知部分的实时计算,才能让设备穿戴者感觉不到延时。如果定位有延时,佩戴者会产生晕眩,并且虚拟物体在屏幕上漂移会显得非常的虚假,所谓Magic Leap宣称的电影级的真实(Cinematic Reality)就没有意义了。
&/p&&img src=&/ccade908239_b.jpg& data-rawwidth=&260& data-rawheight=&146& class=&content_image& width=&260&&&br&&br&&p&三维感知部分并不是什么新东西,计算机视觉或机器人学中的SLAM(Simultaneous Localization And Mapping,即时定位与地图构建)就是做这个的,已经有30年的历史了。设备通过各种传感器(激光雷达,光学摄像头,深度摄像头,惯性传感器)的融合将得出设备自己在三位空间中的精确位置,同时又能将周围的三位空间实时重建。
&/p&&img src=&/a0cce4f0e7b17f60a55c627ff3efbf6d_b.jpg& data-rawwidth=&200& data-rawheight=&112& class=&content_image& width=&200&&&br&&br&&p&最近 SLAM 技术尤其火爆,去年到今年两年时间内巨头们和风投收购和布局了超级多做空间定位技术的公司。因为目前最牛逼的3大科技技术趋势:无人车,虚拟现实,无人机,他们都离不开空间定位。SLAM是完成这些伟大项目基础中的基础。我也研究SLAM技术,所以接触的比较多,为了方便大家了解这个领域,这里简单提几个SLAM界最近的大事件和人物:
&/p&&p&1. (无人车)Stanford的机器人教授Sebastian Thrun是现代SLAM技术的开创者,自从赢了DARPA Grand Challenge的无人车大赛后,去了Google造无人车了。SLAM学术圈的大部分研究派系都是Sebastian徒子徒孙。
(无人车)Uber在今年拿下了卡耐基梅隆CMU的NREC(国家机器人工程研发中心),合作成立高等技术研发中心ATC。 这些原来做火星车的定位技术的研究人员都去Uber ATC做无人车了。
3. (虚拟现实)最近Surreal Vision被Oculus Rift收购,其中创始人Richard Newcombe是大名鼎鼎的DTAM,KinectFusion(HoloLens的核心技术)的发明人。Oculus Rift还在去年收购了13th Labs(在手机上做SLAM的公司)。
4.(虚拟现实)Google Project Tango 今年发布世界上第一台到手就用的商业化SLAM功能的平板。Apple五月收购Metaio AR,Metaio AR 的 SLAM 很早就用在了AR的app上了。Intel 发布Real Sense,一个可以做SLAM的深度摄像头,在CES上Demo了无人机自动壁障功能和自动巡线功能。
5. (无人机)由原来做Google X Project Wing 无人机的创始人MIT机器人大牛Nicholas Roy 的学生Adam Bry创办的Skydio,得到A16z的两千万估值的投资,挖来了Georgia Tech的SLAM大牛教授Frank Dellaert 做他们的首席科学家。&a href=&///?target=http%3A//www.cc.gatech.edu/%7Edellaert/FrankDellaert/Frank_Dellaert/Frank_Dellaert.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cc.gatech.edu/~dellaert&/span&&span class=&invisible&&/FrankDellaert/Frank_Dellaert/Frank_Dellaert.html&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&SLAM作为一种基础技术,其实全世界做SLAM或传感器融合做的好的大牛可能不会多于100人,并且大都互相认识。这么多大公司抢这么点人,竞争激烈程度可想而知,所以Magic Leap作为一个创业公司一定要融个大资,才能和大公司抢人才资源。
&/p&&p&&b&Q5. Magic Leap的感知部分的技术是怎么样的?
&/b&&/p&&p&这张照片是Gary教授在Magic Leap Stanford 招聘会中展示了Magic Leap在感知部分的技术架构和技术路线。可以看到以Calibration为中心,展开成了4支不同的计算机视觉技术栈。
&/p&&img src=&/58d3c3a0af4b04dbde1c47_b.png& data-rawwidth=&780& data-rawheight=&1186& class=&origin_image zh-lightbox-thumb& width=&780& data-original=&/58d3c3a0af4b04dbde1c47_r.png&&&br&&br&&p&1. 从图上看,整个Magic Leap感知部分的核心步骤是Calibration(图像或传感器校准),因为像Magic Leap或Hololens这类主动定位的设备,在设备上有各种用于定位的摄像头和传感器, 摄像头的参数和摄像头之间关系参数的校准是开始一切工作的第一步。这步如果摄像头和传感器参数都不准,后面的定位都是无稽之谈。从事过计算机视觉技术的都知道,传统的校验部分相当花时间,需要用摄像头拍摄Chess Board,一遍一遍的收集校验用的数据。但Magic Leap的Gary,他们发明了一种新的Calibration方法,直接用一个形状奇特的结构体做校正器,摄像头看一遍就完成了校正,极为迅速。这个部分现场不让拍照。&/p&&p&2. 有了Calibration部分后,开始最重要的三维感知与定位部分(左下角的技术栈),分为4步。
&/p&&p&2.1 首先是 Planar Surface Tracking (平面表面跟踪)。大家可以在虚拟太阳系的Demo中看到虚拟太阳在桌子上有反光,且这个反光会随着设备佩戴者的移动而改变位置,就像是太阳真的悬在空中发出光源,在桌子表面反射产生的。这就要求设备实时的知道桌子的表面在哪里,并且算出虚拟太阳与平面的关系,才能将太阳的反光的位置算出来,叠在设备佩戴者眼镜相应的位子上,并且深度信息也是正确的。难点在平面检测的实时性和给出平面位置的平滑性(否则反光会有跳变)从Demo中可以看出Magic Leap在这步上完成的很好。
&/p&&img src=&/588f877c639284fab49f6e8f0ac91e17_b.png& data-rawwidth=&792& data-rawheight=&660& class=&origin_image zh-lightbox-thumb& width=&792& data-original=&/588f877c639284fab49f6e8f0ac91e17_r.png&&&br&&br&&p&2.2 然后是 Sparse SLAM(稀疏SLAM); Gary在Info Session上展示了他们实时的三维重构与定位算法。为了算法的实时性,他们先实现了高速的稀疏或半稀疏的三维定位算法。从效果上看,和目前开源的LSD 算法差不了太多。
&/p&&img src=&/8ca593d2efe8dec562e9e_b.png& data-rawwidth=&702& data-rawheight=&822& class=&origin_image zh-lightbox-thumb& width=&702& data-original=&/8ca593d2efe8dec562e9e_r.png&&&br&&br&&p&2.3 接着是 S Vision and IMU(视觉和惯性传感器融合 )。
&/p&&p&导弹一般是用纯惯性传感器做主动定位,但同样的方法不能用于民用级的低精度惯性传感器,二次积分后一定会漂移。而光靠视觉做主动定位,视觉部分的处理速度不高,且容易被遮档,定位鲁棒性不高。将视觉和惯性传感器融合是最近几年非常流行的做法。
&/p&&p&举例:
Google Tango在这方面就是做IMU和深度摄像头的融合,做的很好;大疆的无人机Phantom 3或Inspire 1将光流单目相机和无人机内的惯性传感器融合,在无GPS的情况下,就能达到非常惊人的稳定悬停;Hololens可以说在SLAM方面是的做的相当好,专门定制了一个芯片做SLAM,算法据说一脉相承了KinectFusion的核心,亲自测试感觉定位效果很赞(我可以面对白色无特征的墙壁站和跳,但回到场中心后定位还是很准确的,一点都不飘。)&/p&&p&2.4 最后是 3D Mapping and Dense SLAM (3D地图重建 )。下图展示了Magic Leap 山景城办公室的3D地图重建:仅仅是带着设备走了一圈,就还原了整个办公室的3D地图,并且有很精致的贴图。书架上的书都能重建的不变形。&/p&&img src=&/547edc1e06c6d08774a4_b.png& data-rawwidth=&804& data-rawheight=&788& class=&origin_image zh-lightbox-thumb& width=&804& data-original=&/547edc1e06c6d08774a4_r.png&&&br&&br&&p&因为AR的交互是全新的领域,为了让人能够顺利的和虚拟世界交互,基于机器视觉的识别和跟踪算法成了重中之重。全新人机交互体验部分需要大量的技术储备做支持。
&/p&&p&接下来的三个分支,Gary没有细讲,但是可以看出他们的布局。我就随便加点注解,帮助大家理解。
&/p&&p&3.1 Crowdsourcing 众包。用于收集数据,用于之后的机器学习工作,要构建一个合理的反馈学习机制,动态的增量式的收集数据。
3.2 Machine Learning & Deep Learning 机器学习与深度学习。需要搭建机器学习算法架构,用于之后的识别算法的生产。
3.3 Scenic Object Recognition
场景物体识别。识别场景中的物体,分辨物体的种类,和特征,用于做出更好的交互。比如你看到一个小狗的时候,会识别出来,然后系统可以把狗狗p成个狗型怪兽,你就可以直接打怪了。
3.4 Behavior Recognition
行为识别 。识别场景中的人或物的行为,比如跑还是跳,走还是坐,可能用于更加动态的游戏交互。顺便提一下,国内有家Stanford校友办的叫格林深瞳的公司也在做这个方面的研究。
&/p&&p&跟踪方面
4.1 Gesture Recognition 手势识别。用于交互,其实每个AR/VR公司都在做这方面的技术储备。
4.2 Object Tracking 物体追踪。这个技术非常重要,比如Magic Leap的手捧大象的Demo,至少你要知道你的手的三维位置信息,实时Tracking,才能把大象放到正确的位子。
4.3 3D Scanning 三维扫描。能够将现实物体,虚拟化。比如你拿起一个艺术品,通过三维扫描,远处的用户就能够在虚拟世界分享把玩同样的物体。
4.4 Human Tracking 人体追踪。比如:可以将现实中的每个人物,头上可以加个血条,能力点之类。
&/p&&p&5.1 Eye Tracking 眼动跟踪。Gary解释说,虽然Magic Leap的呈像不需要眼动跟踪,但因为要计算4维光场,Magic Leap的渲染计算量巨大。如果做了眼动跟踪后,就可以减少3D引擎的物体渲染和场景渲染的压力,是一个优化的绝佳策略。
5.2 Emotion Recognition 情感识别。如果Magic Leap要做一个 Her 电影中描绘的人工智能操作系统,识别主人得情感,可以做出贴心的情感陪护效果。
5.3 Biometrics 生物识别。比如要识别现实场景中的人,在每个人头上显示个名字啥的。人脸识别是其中一种,国内有家清华姚班师兄弟们开得公司 Face++ 就是干这个干的最好的。
&/p&&p&总结,简单来讲感知这个部分Magic Leap其实和很多其他的公司大同小异,虽然有了Gary的加盟,野心非常的宽广,但这部分竞争非常激烈。
&/p&&p&&b&Q6: 就算Magic Leap已经搞定了感知和显示,那么接下来的困难是什么?
&/b&&/p&&p&1. 计算设备与计算量。
Magic Leap要计算4维光场,计算量惊人。不知道Magic Leap现在是怎么解决的。如果Nvidia不给造牛逼的移动显卡怎么办?难道自己造专用电路?背着4块泰坦X上路可不是闹着玩的。
&/p&&p&下图是,今年我参加SIGGraph 2015里,其中一个VR 演示,每个人背着个大电脑包玩VR。10年后的人类看今天的人类追求VR会不会觉得很好笑,哈哈。
&/p&&img src=&/e69c3cf7c9d8c840bf2077_b.png& data-rawwidth=&1650& data-rawheight=&838& class=&origin_image zh-lightbox-thumb& width=&1650& data-original=&/e69c3cf7c9d8c840bf2077_r.png&&&br&&br&&p&2. 电池!电池!电池! 所有电子设备的痛。
&/p&&p&3. 一个操作系统。说实话,如果说“世界就是你的新桌面”是他们的愿景,现在的确没有什么操作系统可以支持Magic Leap愿景下的交互。他们必须自己发明轮子。
&/p&&p&4. 为虚拟物体交互体验增加}

我要回帖

更多关于 上古卷轴5无法载入mod 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信