[NCTF 2018]wcyvm

本文描述了一个初学者在尝试解决一道涉及虚拟机逆向工程的题目时的经历,包括参考前人代码、遇到的问题和解决过程,最终解密flag。
摘要由CSDN通过智能技术生成

虚拟机题目,到现在还没做过,依据前人的智慧学习一波。

有前人用angr跑出来了,试了下还真行,绷。

网上疑似搜到了源码NCTF2018/Reverse/wcyvm/wcyvm.c at master · NJUPT-coding-gay/NCTF2018 (github.com)

参照着写

虚拟机的函数长这样

有点折磨

照着前人写了一波,加了些自己的理解,干出死循环了。

悲。

发现原因了,把i+2写成了opcode[i+2],还是没理解透。

乱掉了,决定不做了

决定再做做。

发现做这题时得把类型转换隐藏掉,看着头疼。

#include<stdio.h>
unsigned int opcode[100] = {
    0x00000008, 0x00000001, 0x00000000, 0x00000008, 0x00000003, 0x00000046, 0x0000000E, 0x00000015,
    0x0000000A, 0x00000001, 0x00000009, 0x00000002, 0x0000000B, 0x0000000A, 0x00000001, 0x0000000A,
    0x00000002, 0x00000009, 0x00000001, 0x00000011, 0x00000001, 0x0000000D, 0x00000001, 0x00000003,
    0x0000000F, 0x00000008, 0x00000008, 0x00000001, 0x00000000, 0x00000008, 0x00000003, 0x00000047,
    0x0000000E, 0x00000046, 0x0000000A, 0x00000001, 0x0000001A, 0x00000002, 0x00000006, 0x0000001D,
    0x00000001, 0x00000004, 0x00000014, 0x00000002, 0x00000001, 0x00000019, 0x00000001, 0x00000002,
    0x0000001B, 0x00000001, 0x00000001, 0x0000001D, 0x00000001, 0x0000006E, 0x00000013, 0x00000001,
    0x00000063, 0x00000015, 0x00000001, 0x00000074, 0x00000013, 0x00000001, 0x00000066, 0x0000001C,
    0x00000002, 0x00000001, 0x00000009, 0x00000001, 0x00000011, 0x00000001, 0x0000000D, 0x00000001,
    0x00000003, 0x0000000F, 0x00000022, 0x00000064, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000
};
int main()
{
    int v1=0;
    for (int i = 0;i < 75;)
    {
        if (opcode[i] == 8)
        {
            printf("%d mov R%d %d\n", i , opcode[i + 1] - 1, opcode[i + 2]);
            i += 3;
            continue;
        }
        if (opcode[i] == 9)
        {
            printf("%d pop R%d\n", i , opcode[i + 1] - 1);
            i += 2;
            continue;
        }
        if (opcode[i] == 0xA)
        {
            printf("%d push R%d\n", i , opcode[i + 1] - 1);
            i += 2;
        }
        if (opcode[i] == 0xB)
        {
            printf("%d R0=getchar()\n", i );
            i += 1;
            continue;
        }
        if (opcode[i] == 0xC)
        {
            printf("%d R0=putchar()\n", i );
            i += 1;
            continue;
        }
        if (opcode[i] == 0xD)
        {
            printf("%d if R%d==R%d v1=128\n", i ,opcode[i+2]-1,opcode[i+1]-1);
            printf("   if R%d>R%d  v1=64\n", opcode[i + 2] - 1, opcode[i + 1] - 1);
            printf("   if R%d<R%d  v1=32\n", opcode[i + 2] - 1, opcode[i + 1] - 1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0xE)
        {
            printf("%d jmp %d\n", i , opcode[i + 1]);
            i += 2;
            continue;
        }
        if (opcode[i] == 0xF)
        {
            printf("%d if v1&0x80!=0 jmp %d\n", i , i+2);
            printf("   else jmp %d\n", opcode[i + 1]);
            i += 2;
            continue;
        }
        if (opcode[i] == 0x10)
        {
            printf("%d if v1&0x80!=0 jmp %d\n", i , opcode[i + 1]);
            printf("   else jmp %d\n", i+2);
            i += 2;
            continue;
        }
        if (opcode[i] == 0x11)
        {
            printf("%d inc R%d\n", i , opcode[i + 1] - 1);
            i += 2;
            continue;
        }
        if (opcode[i] == 0x12)
        {
            printf("%d dec R%d\n", i , opcode[i + 1] - 1);
            i += 2;
            continue;
        }
        if (opcode[i] == 0x13)
        {
            printf("%d add R%d %d\n", i , opcode[i + 1] - 1,opcode[i+2]);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x14)
        {
            printf("%d sub R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2]-1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x15)
        {
            printf("%d xor R%d %d\n", i , opcode[i + 1] - 1, opcode[i + 2]);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x16)
        {
            printf("%d and R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2]-1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x17)
        {
            printf("%d or R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x19)
        {
            printf("%d mov R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x1A)
        {
            printf("%d lea R%d [R%d]\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x1B)
        {
            printf("%d mov R%d [R%d]\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x1C)
        {
            printf("%d mov [R%d] R%d\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
            i += 3;
            continue;
        }
        if (opcode[i] == 0x1D)
        {
            printf("%d mul R%d %d\n", i , opcode[i + 1] - 1, opcode[i + 2]);
            i += 3;
            continue;
        }



    }
}

运行结果

0 mov R0 0
3 mov R2 70
6 jmp 21
8 push R0
10 pop R1
12 R0=getchar()
13 push R0
15 push R1
17 pop R0
19 inc R0
21 if R2==R0 v1=128
   if R2>R0  v1=64
   if R2<R0  v1=32
24 if v1&0x80!=0 jmp 26
   else jmp 8
26 mov R0 0
29 mov R2 71
32 jmp 70
34 push R0
36 lea R1 [R5]
39 mul R0 4
42 sub R1 R0
45 mov R0 R1
48 mov R0 [R0]
51 mul R0 110
54 add R0 99
57 xor R0 116
60 add R0 102
63 mov [R1] R0
66 pop R0
68 inc R0
70 if R2==R0 v1=128
   if R2>R0  v1=64
   if R2<R0  v1=32
73 if v1&0x80!=0 jmp 75
   else jmp 34

36行有个R5,对应的应该是栈底。

flag=[0x000036D3, 0x00002AFF, 0x00002ACB, 0x00002B95, 0x00002B95, 0x00002B95, 0x0000169F, 0x0000186D, 0x000018D7, 0x00001611, 0x000018D7, 0x00002B95, 0x00002C23, 0x00002CA9, 0x00001611, 0x00001611, 0x000018D7, 0x00002AFF, 0x00001849, 0x000018FB, 0x00002ACB, 0x00002A71, 0x00001735, 0x000018D7, 0x00001611, 0x00002ACB, 0x000015DD, 0x000018D7, 0x00002C23, 0x0000169F, 0x000015DD, 0x00002B95, 0x0000169F, 0x0000156B, 0x0000186D, 0x00002AFF, 0x00001611, 0x00001611, 0x000015DD, 0x00002AFF, 0x00002C23, 0x00002ACB, 0x000015DD, 0x000015DD, 0x0000186D, 0x00001849, 0x00002B95, 0x0000156B, 0x00001735, 0x000018FB, 0x000018FB, 0x00002A71, 0x00002AFF, 0x00001735, 0x00002C23, 0x000015DD, 0x000018D7, 0x00002A71, 0x000018D7, 0x000018D7, 0x00002C23, 0x00002AFF, 0x0000156B, 0x00002C23, 0x0000169F, 0x000035AF, 0x00002CA9, 0x000032B5, 0x00002AFF, 0x00003039]
for i in range(len(flag)-1,-1,-1):
    flag[i]=(((flag[i]-102)^116)-99)//110
    print(chr(flag[i]),end='')
#nctf{3e1ce77b70e4cb9941d6800aec022c813d03e70a274ba96c722fed72783dddac}

遭不住。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值