bool EmitProlog(CxProgram program) { bool rc = true; switch (PrologOrder[program.GetRandom() % 3]) { case 2: // MOV EAX, (Random() & 0x3ff) // MOV EAX, EncryptionControlBlock[EAX] rc = program.EmitNop (5) // 0xbe && program.Emit (CxByteCode.MOV_EAX_IMMED, 2) // 0x8b 0x86 && program.EmitUInt32 (program.GetRandom() & 0x3ff) && program.Emit (CxByteCode.MOV_EAX_INDIRECT, 0); break; case 1: rc = program.Emit (CxByteCode.MOV_EAX_EDI, 2); // 0x8b 0xc7 break; case 0: // MOV EAX, Random() rc = program.Emit (CxByteCode.MOV_EAX_IMMED) // 0xb8 && program.EmitRandom(); break; } return rc; }
CxProgram GenerateProgram(uint seed) { var program = new CxProgram (seed, ControlBlock); for (int stage = 5; stage > 0; --stage) { if (EmitCode (program, stage)) return program; // Trace.WriteLine (string.Format ("stage {0} failed for seed {1}", stage, seed), "GenerateProgram"); program.Clear(); } throw new CxProgramException ("Overly large CxEncryption bytecode"); }
bool EmitOddBranch(CxProgram program) { bool rc = true; switch (OddBranchOrder[program.GetRandom() % 6]) { case 0: rc = program.Emit (CxByteCode.PUSH_ECX) // 0x51 && program.Emit (CxByteCode.MOV_ECX_EBX, 2) // 0x89 0xd9 && program.Emit (CxByteCode.AND_ECX_0F, 3) // 0x83 0xe1 0x0f && program.Emit (CxByteCode.SHR_EAX_CL, 2) // 0xd3 0xe8 && program.Emit (CxByteCode.POP_ECX); // 0x59 break; case 1: rc = program.Emit (CxByteCode.PUSH_ECX) // 0x51 && program.Emit (CxByteCode.MOV_ECX_EBX, 2) // 0x89 0xd9 && program.Emit (CxByteCode.AND_ECX_0F, 3) // 0x83 0xe1 0x0f && program.Emit (CxByteCode.SHL_EAX_CL, 2) // 0xd3 0xe0 && program.Emit (CxByteCode.POP_ECX); // 0x59 break; case 2: rc = program.Emit (CxByteCode.ADD_EAX_EBX, 2); // 0x01 0xd8 break; case 3: rc = program.Emit (CxByteCode.NEG_EAX, 2) // 0xf7 0xd8 && program.Emit (CxByteCode.ADD_EAX_EBX, 2); // 0x01 0xd8 break; case 4: rc = program.Emit (CxByteCode.IMUL_EAX_EBX, 3); // 0x0f 0xaf 0xc3 break; case 5: rc = program.Emit (CxByteCode.SUB_EAX_EBX, 2); // 0x29 0xd8 break; } return rc; }
bool EmitEvenBranch(CxProgram program) { bool rc = true; switch (EvenBranchOrder[program.GetRandom() & 7]) { case 0: rc = program.Emit (CxByteCode.NOT_EAX, 2); // 0xf7 0xd0 break; case 1: rc = program.Emit (CxByteCode.DEC_EAX); // 0x48 break; case 2: rc = program.Emit (CxByteCode.NEG_EAX, 2); // 0xf7 0xd8 break; case 3: rc = program.Emit (CxByteCode.INC_EAX); // 0x40 break; case 4: rc = program.EmitNop (5) // 0xbe && program.Emit (CxByteCode.AND_EAX_IMMED) // 0x25 && program.EmitUInt32 (0x3ff) && program.Emit (CxByteCode.MOV_EAX_INDIRECT, 3); // 0x8b 0x04 0x86 break; case 5: rc = program.Emit (CxByteCode.PUSH_EBX) // 0x53 && program.Emit (CxByteCode.MOV_EBX_EAX, 2) // 0x89 0xc3 && program.Emit (CxByteCode.AND_EBX_IMMED, 2) // 0x81 0xe3 && program.EmitUInt32 (0xaaaaaaaa) && program.Emit (CxByteCode.AND_EAX_IMMED) // 0x25 && program.EmitUInt32 (0x55555555) && program.Emit (CxByteCode.SHR_EBX_1, 2) // 0xd1 0xeb && program.Emit (CxByteCode.SHL_EAX_1, 2) // 0xd1 0xe0 && program.Emit (CxByteCode.OR_EAX_EBX, 2) // 0x09 0xd8 && program.Emit (CxByteCode.POP_EBX); // 0x5b break; case 6: rc = program.Emit (CxByteCode.XOR_EAX_IMMED) // 0x35 && program.EmitRandom(); break; case 7: if (0 != (program.GetRandom() & 1)) rc = program.Emit (CxByteCode.ADD_EAX_IMMED); // 0x05 else rc = program.Emit (CxByteCode.SUB_EAX_IMMED); // 0x2d rc = rc && program.EmitRandom(); break; } return rc; }
bool EmitCode(CxProgram program, int stage) { return program.EmitNop (5) // 0x57 0x56 0x53 0x51 0x52 && program.Emit (CxByteCode.MOV_EDI_ARG, 4) // 0x8b 0x7c 0x24 0x18 && EmitBody (program, stage) && program.EmitNop (5) // 0x5a 0x59 0x5b 0x5e 0x5f && program.Emit (CxByteCode.RETN); // 0xc3 }
bool EmitBody2(CxProgram program, int stage) { if (1 == stage) return EmitProlog (program); bool rc = true; if (0 != (program.GetRandom() & 1)) rc = EmitBody (program, stage - 1); else rc = EmitBody2 (program, stage - 1); return rc && EmitEvenBranch (program); }
bool EmitBody(CxProgram program, int stage) { if (1 == stage) return EmitProlog (program); if (!program.Emit (CxByteCode.PUSH_EBX)) // 0x53 return false; if (0 != (program.GetRandom() & 1)) { if (!EmitBody (program, stage - 1)) return false; } else if (!EmitBody2 (program, stage - 1)) return false; if (!program.Emit (CxByteCode.MOV_EBX_EAX, 2)) // 0x89 0xc3 return false; if (0 != (program.GetRandom() & 1)) { if (!EmitBody (program, stage - 1)) return false; } else if (!EmitBody2 (program, stage - 1)) return false; return EmitOddBranch (program) && program.Emit (CxByteCode.POP_EBX); // 0x5b }