仔细看了这道题之后,觉得这道题不应该成为VM,他没有VM的结构和各种handler,但是他反而是有了很多的混淆,那么我们第一步先根据文章修改function size。
    文章链接:https://www.dllhook.com/post/217.html

    IDAPro F5出现too big function 解决-macOS-优雅人生.pdf

    将这个标记位修改完成之后,我们就能正常查看整个函数和进行F5反编译了,但是速度很慢。
    耐性等待就好,只反编译一次就够用了。
    image.png
    反编译完成之后我们可以看到,基础的输入输出,判断长度和运算都没变,而且确实没有了VM结构。反而多了一堆异或运算。那么我们先确定这些异或运算会不会影响我们的输入输出。
    image.png
    随便点击几个可以发现他是迭代异或下去的,然而数据在我们对比的数据后门很多,那么就说明这是不影响我们输入输出的东西,就可以当做垃圾代码除掉了。(先将F5得到的代码全选保存成TXT文档)

    1. import struct
    2. import os
    3. import re
    4. f = open("origin_source.txt", "r")
    5. wf = open("de_source.txt", "w")
    6. for i in range(25036):
    7. tmp = f.readline().strip()
    8. if "byte_6941" in tmp:
    9. wf.write(tmp + "\n")
    10. print tmp
    11. f.close()
    12. wf.close()

    image.png

    除去之后就只剩这些与运算相关的数据了,但是这里因为他用的全局变量来存储的flag字符串,所以我们没有办法吧byte_xxxxx合并为一个数组,那么我们就用正则去匹配合并好了,同样也是只有简单运算,合并好了之后倒着运算一遍就出来结果了。

    1. import struct
    2. import os
    3. import re
    4. byte_overflow = lambda x: x & 0xff
    5. cipher_arr = [192, 133, 249, 108, 226, 20, 187, 228, 13, 89, 28, 35, 136, 110, 155, 202, 186, 92, 55, 255, 72, 216, 31,
    6. 171, 0xa5]
    7. op_switch = {'+=': lambda eindex, data: cipher_arr[eindex] - data, '-=': lambda eindex, data: cipher_arr[eindex] + data,
    8. '^=': lambda eindex, data: cipher_arr[eindex] ^ data, '++': lambda eindex, data: cipher_arr[eindex] - 1,
    9. '--': lambda eindex, data: cipher_arr[eindex] + 1}
    10. f = open("de_source.txt", "r")
    11. instruction = []
    12. for i in range(2415):
    13. tmp = f.readline().strip()
    14. result = re.findall("byte_6941(.{2})\s(.{2})\s(.+);|(.{2})byte_6941(.{2})", tmp)[0]
    15. if len(result) == 5:
    16. # print result
    17. instruction.append(list(result))
    18. else:
    19. print tmp
    20. # print instruction
    21. instruction = instruction[::-1]
    22. for i in range(len(instruction)):
    23. if instruction[i][0] != '':
    24. vm_index = int(instruction[i][0], 16)
    25. else:
    26. vm_index = int(instruction[i][4], 16)
    27. if instruction[i][1] != '':
    28. vm_optation = instruction[i][1]
    29. else:
    30. vm_optation = instruction[i][3]
    31. if instruction[i][2] != '':
    32. if instruction[i][2].startswith("0x"):
    33. vm_data = int(instruction[i][2].strip("u"), 16)
    34. else:
    35. vm_data = int(instruction[i][2].strip("u"), 10)
    36. else:
    37. vm_data = None
    38. cipher_arr[vm_index] = op_switch[vm_optation](vm_index, vm_data)
    39. print "".join(map(chr, map(byte_overflow, cipher_arr)))
    40. f.close()