编辑“︁
虚拟机分析
”︁(章节)
跳转到导航
跳转到搜索
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
== 虚拟机指令分析 == 说实话, 虚拟机的分析部分是一个比较枯燥的还原过程, 你需要比对各个小部分的操作来判断这是一个怎样的指令, 使用的是哪些寄存器. 像这个crackme中, vm进行的是一个<code>取指-译码-执行</code>的循环. <code>译码</code>过程可给予我们的信息最多, 不同的指令都会在这里, 根据它们各自的<code>opcode</code>, 使用<code>if-else if-else</code>分支进行区分. 实际的还原过程并不复杂, 但有可能会因为虚拟机实现的指令数量而显得有些乏味. 最后分析出的结果如下: {| class="wikitable" |- ! opcode ! value |- | push | 0x0a |- | pop | 0x0b |- | mov | 0x0c |- | cmp | 0x0d |- | inc | 0x0e |- | dec | 0x0f |- | and | 0x1b |- | or | 0x1c |- | xor | 0x1d |- | check | 0xff |} 我们再来看分析后的<code>initVM</code>函数 <syntaxhighlight lang="c">int initVM() { int result; // eax@1 r1 = 0; r2 = 0; r3 = 0; result = (unsigned __int8)inputName[(unsigned __int8)cur_index]; r4 = (unsigned __int8)inputName[(unsigned __int8)cur_index]; vm_sp = 0x32; vm_pc = 0; vm_flags_zf = 0; vm_flags_sf = 0; ++cur_index; return result; }</syntaxhighlight> 这里有4个通用寄存器(<code>r1/r2/r3/r4</code>), 1个<code>sp</code>指针和1个<code>pc</code>指针, 标志<code>zf</code>和<code>sf</code>. 先前我们不知道的<code>var_a</code>也被重命名为<code>cur_index</code>, 指向的是<code>inputName</code>当前正在处理的字符索引. 对于VM实现的多个指令我们就不再多说, 重点来看下<code>check</code>部分的操作. <syntaxhighlight lang="c">int __fastcall check(int a1) { char v1; // al@1 int result; // eax@4 v1 = r1; if ( (unsigned __int8)r1 < 0x21u ) v1 = r1 + 0x21; LOBYTE(a1) = cur_index; if ( v1 == inputKey[a1] ) { if ( (unsigned __int8)cur_index >= (unsigned __int8)lenOfName ) result = MessageBoxA(0, aGoodJobNowWrit, Caption, 0); else result = initVM(); } else { result = MessageBoxA(0, Text, Caption, 0); } return result; }</syntaxhighlight> 如果<code>r1</code>中的值跟<code>inputKey[cur_index]</code>相等, 那么会继续判断是否已经检查完了整个<code>inputName</code>, 如果没有出错且比对结束, 那么就会弹出<code>Good job! Now write a keygen.</code>的消息框. 否则会继续<code>initVM</code>进入下一轮循环.(出错了当然是弹出消息框提示错误了. ) <code>cur_index</code>会在<code>initVM</code>中自增1, 那么还记得之前在<code>process_input</code>里有执行2次<code>initVM</code>吗. 因为有执行2次<code>initVM</code>, 所以我们的<code>inputKey</code>的前2位可以是任意字符. <syntaxhighlight lang="c"> unk_4031CE = i; opcode = vm_pc; initVM(); initVM(); __debugbreak(); JUMPOUT(*(_DWORD *)&word_4012CE);</syntaxhighlight> 故而我们分析完了整个虚拟机, 便可以开始着手编写<code>Keygen</code>. 对应的<code>keygenme</code>可以点击此处下载: [https://github.com/ctf-wiki/ctf-challenges/blob/master/reverse/vm/fuelvm/fuelvm_keygen.py fuelvm_keygen.py] <syntaxhighlight lang="bash">$ python2 fuelvm_keygen.py ctf-wiki [*] Password for user 'ctf-wiki' is: 4mRC*TKJI</syntaxhighlight> 对应的<code>IDA数据库</code>可以点击此处下载: [https://github.com/ctf-wiki/ctf-challenges/blob/master/reverse/vm/fuelvm/FuelVM.idb FuelVM.idb] [[Category: Reverse_Overview]]
摘要:
请注意,所有对gamedev的贡献均可能会被其他贡献者编辑、修改或删除。如果您不希望您的文字作品被随意编辑,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源(详情请见
Gamedev:著作权
)。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
导航菜单
个人工具
未登录
讨论
贡献
创建账号
登录
命名空间
页面
讨论
不转换
不转换
简体
繁體
大陆简体
香港繁體
澳門繁體
大马简体
新加坡简体
臺灣正體
查看
阅读
编辑
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息