当前位置:   article > 正文

站在巨人的肩膀上学习ctf vm_vmcontext

vmcontext

0x00 前言

本文提到的vm是ctf里的vm,最近vm还是很热门的,最近的虎符,de1ctf,再到网鼎杯都有vm的身影,但是vm的知识在网上挺散的(我只找到了绿盟那篇比较系统),vm的wp也相对比较简单,所以身为小白的我就在这里归纳一下网上大佬们的文章,和我的思考和学习总结,希望可以给各位看官一些帮助。

参考文章:

虚拟机保护逆向入门

虚拟机保护技术浅谈

《加密与解密》第四版 P592 ~P593

0x01 简单结构

《加密与解密》“中说ctf_vm不是VMware,,它类似于 P-CODE ,将一系列指令解释成bytecode 后放到一个解释引擎中执行,从而对软件进行保护。”简单来说,就是先设立一个一个不重复的标志(一个字节就是一个标志),然后每个标志通过分发器(dispatcher),寻找到对应的解释(handler),之后把这些标志通过不同的排列组合,并把组合后的标志存到一个固定的地方(这个大数组就是opcode),而组合后的逻辑与将保护程序逻辑相同,实现替换,从而进行保护。

一下是图解:

说明:在ctf_vm中 分发器(dispatcher) 与解释器 (handler)通常是用switch和case实现的,通常有如下结构

  1. switch(opcode)
  2. {
  3. case 1: // handler1
  4. ......
  5. break;
  6. case 2: // handler2
  7. ......
  8. break;
  9. case 3: // handler3
  10. ......
  11. break;
  12. }

为了更好的理解,我们来看一道类似vm思想的题(伪虚拟机)南邮的一道ctf

本文着重看vm保护,其他本文不再赘述。进入vm_protect。

一般分为两个部分,在分发器之前(红框),会先对一些辅助的值进行赋值(这个下文具体讲解),第二部分(紫框)就是具体的分发,和每一个handler,

在这道伪虚拟机

1)handler的含义非常好理解,所以也没有什么必要去理解红框里辅助的值,

2)本道题所保护的flag算法只是最简单的+ - * /,所以没必要通过opcode的顺序自己来还原(15000个也不可能自己还原)

小结:本题并没有逆向虚拟机最重要的东西(翻译handler含义,翻译所保护代码的含义),放在这是为了初步认识ctf_vm的结构。

放上师傅写的脚本(拿idapython跑一下):

  1. adr1 = 0x6010C0
  2. adr2 = 0x601060
  3. flag =[]
  4. for i in range(0,24*4,4):
  5. print "%x"%Dword(adr2+i)
  6. flag.append(Dword(adr2+i))
  7. for i in range(14997,-1,-3):
  8. a = Byte(adr1+i)
  9. b = Byte(adr1+i+1)
  10. c = Byte(adr1+i+2)
  11. if(a == 1):
  12. flag[b] -= c
  13. flag[b] = flag[b]&0xff
  14. if(a == 2):
  15. flag[b] += c
  16. flag[b] = flag[b] & 0xff
  17. if(a == 3):
  18. flag[b] ^= c
  19. flag[b] = flag[b] & 0xff
  20. if(a == 4):
  21. flag[b] /= c
  22. flag[b] = flag[b] & 0xff
  23. if(a == 5):
  24. flag[b] ^= flag[c]
  25. flag[b] = flag[b] & 0xff
  26. print(''.join(map(chr,flag)))

flag: nctf{Embr4ce_Vm_j0in_R3}  嘿嘿嘿,很简单吧,我们来进入下一个阶段。

0x02 网鼎_2020

具体的wp可以看这位师傅写的:网鼎杯2020 伪虚拟机逆向 wp

咱们直接看vm_protect的部分:

  1. v10 = 0;
  2. v9 = 0;
  3. v8 = 0;
  4. v7 = 0;
  5. v6 = 0;
  6. while ( 1 )
  7. {
  8. result = v10;
  9. if ( v10 >= size )
  10. return result;
  11. switch ( opcode[v10] )
  12. {
  13. case 1:
  14. v4[v7] = v5;
  15. ++v10;
  16. ++v7;
  17. ++v9;
  18. break;
  19. case 2:
  20. v5 = opcode[v10 + 1] + flag[v9];
  21. v10 += 2;
  22. break;
  23. case 3:
  24. v5 = flag[v9] - LOBYTE(opcode[v10 + 1]);
  25. v10 += 2;
  26. break;
  27. case 4:
  28. v5 = opcode[v10 + 1] ^ flag[v9];
  29. v10 += 2;
  30. break;
  31. case 5:
  32. v5 = opcode[v10 + 1] * flag[v9];
  33. v10 += 2;
  34. break;
  35. case 6:
  36. ++v10;
  37. break;
  38. case 7:
  39. if ( v4[v8] != opcode[v10 + 1] )
  40. {
  41. printf("what a shame...");
  42. exit(0)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/509235
推荐阅读
相关标签
  

闽ICP备14008679号