重新认识两道题 骇极杯 cyvm 西湖论剑 junk_instruction

第一题 就是 cyvm 

这个vm题我记得 我看过 但是没有做   或者是没有做出来 关于vm指令的  但是现在看看  感觉难度和 ddctf的第三题的难度差别不多大    直接看 重要的函数

重新认识两道题 骇极杯 cyvm 西湖论剑 junk_instruction_第1张图片

 其实像这种的 vm指令自己多看看 模拟一下就好了 

首先 0xF  这个就是一开始的输入  oxE 就是最后的比较 这个都可以看出来

那么 我们继续看 0x10 这个 0x10 就是代表了

*(&v7 + vm[index + 1] - 0x14) = vm[index + 2]

其实我们这里可以转化成 v7[vm[index+1]-0x14]=vm[index+2] 

然后这里就等于了 v7[0]=vm[index+2]=0x20

下一个指令依然是  0x10  我们继续看 这里我们可以看出来是v7[2]=0x0 

然后 就直接 就0x9 然后 让index=0x24  直接执行0x24的地方

我们看一下   v9 = *(&v7 + vm[index + 1] - 0x14) != *(&v7 + vm[index + 2] - 0x14);

这里 紧接着的指令是0xC  如果 v9等于的话  直接就0xE 进行判断了

这里的判断就是我们上面的 v7[0] v[2]  我初步判断是一个 循环  循环0x20次   

然后  我们先让他不判断  发现我们的 index =0x9了 

然后 就是下一个命令  0x02

*(&v7 + vm[index + 1] - 0x14) = input[*(&v7 + vm[index + 2] - 0x14)]

v7[1]=input[0]   这里的0xe9 是一个无用指令 直接跳过

然后是 0x12  把 ++v7[2]    然后0x2 是 v7[3]=input[v7[2]]  =input[1]

0x13  --v7[2]     0x6   v7[1]^=v7[3]     0x6  v7[1]^=v7[2]     0x1  input[v7[2] ]=v7[1]   0x12 v7[2]++  

然后比较 v7[0] v7[2]   相等就跳回 这里可以看出 v7[2]在这个循环 只增加了1  

那么 整个过程可以用 这样表示

for(int i=0;i<0x20;i++)

{

     input[i]=input[i]^i^input[i+1]

}

然后我们反推回去就好了 

l=[  0x0A, 0x0C, 0x04, 0x1F, 0x48, 0x5A, 0x5F, 0x03, 0x62, 0x67, 
  0x0E, 0x61, 0x1E, 0x19, 0x08, 0x36, 0x47, 0x52, 0x13, 0x57, 
  0x7C, 0x39, 0x54, 0x4B, 0x05, 0x05, 0x45, 0x77, 0x15, 0x26, 
  0x0E, 0x62, 0x00]
flag=""
for i in range(31,-1,-1):
	l[i]^=i^l[i+1]
for i in l:
	flag+=chr(i)
print(flag)

虚拟指令不算难 只要精心下来好好做 就可以了

然后就是西湖论剑  junk_instruction  这个题一开始我做的时候也算做出了 但是很稀里糊涂

然后我就打算重新来一遍

一开始  我发现了 花指令 但是花指令分析的并不是很完全 加上自己idc脚本写的爆炸  然后就gg了

然后就厚颜无耻的去翻了一下 夜影大佬的博客

https://blog.csdn.net/whklhhhh/article/details/89078090

不得不说夜影大佬的 脚本写的真好

from ida_bytes import get_bytes, patch_bytes
import re
addr = 0x402400
end = 0x403000
buf = get_bytes(addr, end-addr)
def handler1(s):
    s = s.group(0)
    print("".join(["%02x"%ord(i) for i in s]))
    s = "\x90"*len(s)
    return s
p = r"\xe8\x00\x00\x00\x00.*?\xc3.*?\xc3"
buf = re.sub(p, handler1, buf, flags=re.I)
patch_bytes(addr, buf)
print("Done")

这里 用到了正则一把梭 真的好使  主要也分析到了  两个x\c3 还有 e8  我一开始就分析了 e8 0x3 0x0 0 0 0  eb ea  那种

去花去的并不完整 然后用大佬的脚本去花之后 就很get力了

然后这个题我还是经过了动态调试才get到了点

check 的数组在这

重新认识两道题 骇极杯 cyvm 西湖论剑 junk_instruction_第2张图片

然后 key在这

重新认识两道题 骇极杯 cyvm 西湖论剑 junk_instruction_第3张图片

 

  但是输入有转化的地方

重新认识两道题 骇极杯 cyvm 西湖论剑 junk_instruction_第4张图片

其实这样也很好做出来 只不过我一开始没有想想出来  这个加密算法是cr4  并没有太多了解过 但是 cr4 每次循环256 这个点 我还是知道的

import base64
check =[91, 214, 208, 38, 200, 221, 25, 126, 110, 62, 203, 22, 145, 125, 255, 175, 221, 118, 100, 176, 247, 229, 137, 87, 130, 159, 12, 0, 158, 208, 69, 250]
str_encrypt=""
for i in check:
	str_encrypt += chr(i)
base64_encrypt = base64.b64encode(str_encrypt)
print base64_encrypt

 

重新认识两道题 骇极杯 cyvm 西湖论剑 junk_instruction_第5张图片

strs= "f250e3d75820847d427f3af11a783379" 
flag = ['*']*32 
for i in range(16): 
    flag[i] = strs[31-i] 
    flag[31-i] = strs[i]
print "flag{%s"%("".join(flag))+'}'

 

你可能感兴趣的:(逆向之旅)