请CTFE高人指教编译时汇编器

oldrev 2007-04-04
我写了一个简单的堆栈式虚拟机用来加密一个程序的序列号算法,其中的 enum Instruction 的定义可以在编译时由 Ruby 脚本产生随机的操作码,大大增加破解难度。
我正在努力创建一个编译时汇编器,用于汇编这些代码,可是编译时的字符串处理功能很弱,如果谁有这方面的经验,欢迎赐教。
module vm;
import std.stdio;

class Stack
{
    private uint[1024]  m_data;
    private const uint m_bottom = m_data.length;
    private uint    m_top;

    this()
    {
        clear();
    }    

    public void clear()
    {
        m_top = m_bottom;
    }

    public void push(uint n)
    {
        m_top--;
        m_data[m_top] = n;
    }

    public uint count()
    {
        return m_bottom - m_top;
    }

    public uint pop()
    {
        return m_data[m_top++];
    }

    public uint top()
    {       
        assert(m_top < m_bottom);
        return m_data[m_top];
    }

}

enum Instruction : ushort
{
    Add = 1,
    Sub,
    Mul,
    Div,    
    Push,
    Pop,
    Load,
    Store,
    Jump,
    JE,
    JLE,
    JG,
    JGE,
    And,
    Not,
    Or,
    Xor,
    End
}

static Instruction getOp(uint Len)(char[Len] str)
{
    Instruction ins;
    for(uint i = 0; i < str.length; i++)
    {
        if(str[i] == ' ')
        {
            switch(str[0 .. i])
            {
                case "add":
                    ins = Instruction.Add;
                    break;

                case "sub":
                    ins = Instruction.Sub;
                    break;
            }

            break;
        }
    }

    return Instruction;
}

class VirtualMachine
{
    private Stack   m_stack;
    ubyte[] m_memory;
    uint        m_pc = 0;
    uint        m_progPtr = 0;
    bool        m_flag;    

    this(uint memSize = 1024)
    {
        m_memory.length = memSize;
        m_stack = new Stack;
        reset();
    }

    public void reset()
    {
        m_stack.clear();
        m_pc = 0;
        m_progPtr = 0;
    }

    void vasm(Instruction ins, uint oprand)
    {
        Instruction* iptr = cast(Instruction*)(m_memory.ptr + m_progPtr);
        vasm(ins);
        uint* ptr = cast(uint*)(m_memory.ptr + m_progPtr) ;
        *ptr = oprand;
        m_progPtr += uint.sizeof;
    }

    void vasm(Instruction ins)
    {
        Instruction* iptr = cast(Instruction*)(m_memory.ptr + m_progPtr);
        *iptr = ins;
        m_progPtr += Instruction.sizeof;
    }

    bool doInstruction()
    {
        Instruction* iptr = cast(Instruction*)(m_memory.ptr + m_pc);
        writefln("m_pc=%d   Ins=%d ",m_pc, *iptr);
        m_pc += Instruction.sizeof;
        uint* oprand = cast(uint*)(m_memory.ptr + m_pc);
        switch(*iptr)
        {
            case Instruction.Add:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x + y);
                break;

            case Instruction.Sub:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x - y);
                break;

            case Instruction.Mul:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x * y);
                break;

            case Instruction.Div:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x / y);
                break;

            case Instruction.Pop:
                m_stack.pop;
                break;

            case Instruction.Push:
                m_stack.push(*oprand);//get oprand);
                m_pc += uint.sizeof;
                break;

            case Instruction.Load:
                m_stack.push(m_memory[*oprand]);//get oprand);
                m_pc += uint.sizeof;
                break;

            case Instruction.Store:
                uint x = m_stack.pop();
                m_memory[*oprand] = x;
                m_pc += uint.sizeof;
                break;

            case Instruction.Jump:
                m_pc = *oprand;// get oprand 
                break;

            case Instruction.JE:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                if(x == y)m_pc = *oprand;
                else m_pc += uint.sizeof;
                break;

            case Instruction.JLE: // top <= bottom
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                if(x <= y)m_pc = *oprand;
                else m_pc += uint.sizeof;
                break;

            case Instruction.JG: // top > bottom
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                if(x > y)m_pc = *oprand;
                else m_pc += uint.sizeof;
                break;

            case Instruction.JGE:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                if(x >= y)m_pc = *oprand;
                else m_pc += uint.sizeof;
                break;                               

            case Instruction.And:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x & y);
                break;

            case Instruction.Or:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x | y);
                break;

            case Instruction.Not:
                uint x = m_stack.pop;
                m_stack.push(!x);
                break;

            case Instruction.Xor:
                uint x = m_stack.pop;
                uint y = m_stack.pop;
                m_stack.push(x ^ y);

            case Instruction.End:
                return true; //normal terminated
                break;

            default:
                throw new Exception("Invalid instruction");
                break;
        }

        return false;
    }

    uint top()
    {
        return m_stack.top;
    }

    uint run()
    {        
        reset;
        while(!doInstruction()){}
        return top;
    }

}

void main()
{
    auto s = new Stack;
    s.push(1);
    writefln(s.top);
    s.push(2);
    s.push(3);
    writefln(s.pop);
    writefln(s.pop);
    writefln(s.pop);
// 计算 (12+2)*3
    auto vm = new VirtualMachine();
    vm.vasm(Instruction.Push, 12);
    vm.vasm(Instruction.Push, 2);
    vm.vasm(Instruction.Add);
    vm.vasm(Instruction.Push, 3);
    vm.vasm(Instruction.Mul);
    vm.vasm(Instruction.End);
    vm.run;
    writefln("Result=", vm.top);

}
qiezi 2007-04-17
随机?编译时可供随机的东西不多,可以取时间,用__TIMESTAMP__和__FILE__再加上__LINE__生成吧。编译时字符串功能比较弱,不过还是可以做不少事的。
oldrev 2007-04-17
操作码是由Ruby脚本随机产生的
qiezi 2007-04-17
这个东西随机生成一下:
# enum Instruction : ushort  
# {  
#     Add = 1000,  
#     Sub = 3212341,  
#     Mul = 12345346,  
#     Div = 324554,      
#     Push = 23452377,  
#     Pop = 9045635,  
#     Load,  
#     Store,  
#     Jump,  
#     JE,  
#     JLE,  
#     JG,  
#     JGE,  
#     And,  
#     Not,  
#     Or,  
#     Xor,  
#     End  
# }  
oldrev 2007-04-17
就是这个了
qiezi 2007-04-17
把这一段用ruby生成,在D里面import+mixin弄进去就行咯。。
oldrev 2007-04-17
我就是这个意思,只是还没完成
Global site tag (gtag.js) - Google Analytics