请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
我就是这个意思,只是还没完成
|

