{ V.X Pascal Polymorphic Engine 32bit By Anskya[2010] [说明]: 目前基于BPE32[By Benny]实现的加密方式,未来会加入更多的KME32或者其他MMXE实现. [0.2]: [*]基于BPE32的原理完成的版本. [0.1]: first version... } {$ifndef VXL_INLINE_MODE} unit VxPPE32; interface uses VxSystem, VxCodeGen32; {$endif} {.$define PPE32_NOJUNK} {$ifndef VXL_INLINE_MODE} // 获取PPE32加密后存储内存空间最大尺寸 function PPE32_GetMaxSize(nSize: SIZE_T): SIZE_T; { 函数功能: 将lpInput代码多态加密后存储在lpOutput内存中 参数: lpOutput = 输出内存 nOutputSize = 输出内存大小(GetBPE32MaxSize(nInputSize)) lpInput = 原始代码或数据 nInputSize = 代码长度 返回数据: 实际生成的多态加密代码大小 } function PPE32_Engine(lpOutput: Pointer; nOutputSize: SIZE_T; lpInput: Pointer; nInputSize: SIZE_T): SIZE_T; implementation {$endif} const PPE32_Derypter_SIZE = $400; // 最大会增加$200字节(根据引擎产生的代码确定) // 返回一个小于nMod的随机数,0=任意数字 function PPE32_Random(nMod: LongWord): LongWord; var nLow, nHigh: LongWord; begin asm push edx rdtsc mov [nLow], eax mov [nHigh], edx pop edx end; Result := nLow xor nHigh; if (nMod = 0) then Exit; Result := Result mod nMod; end; function get_reg(): VX_REG32; begin repeat Result := VX_REG32(PPE32_Random(8)); until ((Result <> REG32_EAX) and (Result <> REG32_ESP)); end; // 生成1字节垃圾指令 function junk1(lpDst: Pointer; nSize: SIZE_T): SIZE_T; const CODE_LENGTH = 1; var nType: LongWord; begin Result := 0; if (nSize < CODE_LENGTH) then Exit; nType := PPE32_Random(8); if (nType = 0) then Result := nop(lpDst, nSize) else if (nType = 1) then Result := dec__reg32(lpDst, nSize, REG32_EAX) else if (nType = 2) then Result := salc(lpDst, nSize) else if (nType = 3) then Result := inc__reg32(lpDst, nSize, REG32_EAX) else if (nType = 4) then Result := clc(lpDst, nSize) else if (nType = 5) then Result := cwde(lpDst, nSize) else if (nType = 6) then Result := stc(lpDst, nSize) else Result := cld(lpDst, nSize); end; // 生成2字节垃圾指令 function junk2(lpDst: Pointer; nSize: SIZE_T): SIZE_T; const CODE_LENGTH = 2; var nType: LongWord; // 随机指令 nReg: VX_REG32; // 随机寄存器 begin Result := 0; if (nSize < CODE_LENGTH) then Exit; nType := PPE32_Random(9); nReg := VX_REG32(PPE32_Random(8)); if (nType = 0) then Result := mov__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 1) then Result := add__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 2) then Result := adc__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 3) then Result := sub__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 4) then Result := sbb__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 5) then Result := or__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 6) then Result := xor__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else if (nType = 7) then Result := and__reg32__reg32_x(lpDst, nSize, REG32_EAX, nReg) else Result := test__reg32__reg32(lpDst, nSize, REG32_EAX, nReg); end; // 生成3字节垃圾指令 function junk3(lpDst: Pointer; nSize: SIZE_T): SIZE_T; const CODE_LENGTH = 3; var nType: LongWord; // 随机指令 nNum: Byte; begin Result := 0; if (nSize < CODE_LENGTH) then Exit; nType := PPE32_Random(17); nNum := PPE32_Random(0); if (nType = 0) then Result := rol__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 1) then Result := shl__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 2) then Result := ror__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 3) then Result := shr__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 4) then Result := rcl__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 5) then Result := sar__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 6) then Result := rcr__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 7) then Result := add__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 8) then Result := or__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 9) then Result := adc__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 10) then Result := sbb__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 11) then Result := and__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 12) then Result := sub__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 13) then Result := xor__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 14) then Result := cmp__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 15) then Result := add__reg32__imm8(lpDst, nSize, REG32_EAX, nNum) else if (nType = 16) then begin Result := clc(lpDst, nSize); Inc(PByte(lpDst), Result); Dec(nSize, Result); if (Result > 0) then Result := Result + jb__rel8(lpDst, nSize, nNum); end else begin Result := stc(lpDst, nSize); Inc(PByte(lpDst), Result); Dec(nSize, Result); if (Result > 0) then Result := Result + jnb__rel8(lpDst, nSize, nNum); end; end; // 生成5字节垃圾指令 function junk5(lpDst: Pointer; nSize: SIZE_T): SIZE_T; const CODE_LENGTH = 5; var nType: LongWord; // 随机指令 nNum: LongWord; begin Result := 0; if (nSize < CODE_LENGTH) then Exit; nType := PPE32_Random(10); nNum := PPE32_Random(0); if (nType = 0) then Result := mov__reg32__imm32(lpDst, nSize, REG32_EAX, nNum) else if (nType = 1) then Result := add__eax__imm32(lpDst, nSize, nNum) else if (nType = 2) then Result := adc__eax__imm32(lpDst, nSize, nNum) else if (nType = 3) then Result := sub__eax__imm32(lpDst, nSize, nNum) else if (nType = 4) then Result := sbb__eax__imm32(lpDst, nSize, nNum) else if (nType = 5) then Result := or__eax__imm32(lpDst, nSize, nNum) else if (nType = 6) then Result := xor__eax__imm32(lpDst, nSize, nNum) else if (nType = 7) then Result := and__eax__imm32(lpDst, nSize, nNum) else if (nType = 8) then Result := test__eax__imm32(lpDst, nSize, nNum) else Result := cmp__eax__imm32(lpDst, nSize, nNum); end; // 只会根据nType类型生成代码 function junkOnly(lpDst: Pointer; nSize: SIZE_T; nType: LongWord): SIZE_T; const CODE_LENGTH = 5; begin Result := 0; if (nSize < CODE_LENGTH) then Exit; // (0=5, 1=1+2, 2=2+1, 3=1, 4=2, 5=3, 6=none) if (nType = 0) then Result := junk5(lpDst, nSize) else if (nType = 1) then begin Result := junk1(lpDst, nSize); Inc(PByte(lpDst), Result); Dec(nSize, Result); if (Result > 0) then junk2(lpDst, nSize); end else if (nType = 2) then begin Result := junk2(lpDst, nSize); Inc(PByte(lpDst), Result); Dec(nSize, Result); if (Result > 0) then junk1(lpDst, nSize); end else if (nType = 3) then Result := junk1(lpDst, nSize) else if (nType = 4) then Result := junk2(lpDst, nSize) else if (nType = 5) then Result := junk3(lpDst, nSize); end; // 生成无Dummy Jump模式垃圾代码 function junkNoJump(lpDst: Pointer; nSize: SIZE_T): SIZE_T; begin Result := junkOnly(lpDst, nSize, PPE32_Random(7)); end; // 生成干扰跳转 // 内存空间最大占用: 41字节--请保持空间有41字节 function junkDummyJumpAndCall(lpDst: Pointer; nSize: SIZE_T): SIZE_T; var lpSeek, lpCall, lpJump, lpLabel1, lpLabel2: Pointer; nLen: SIZE_T; begin Result := 0; if ((lpDst = nil) or (nSize = 0)) then Exit; lpSeek := lpDst; { 1. junk+junk 2. call label1 3. junk 4. jmp label2 5. junk 6. label1: 7. junk 8. ret 9. label2: A. junk } // 1.生成垃圾干扰代码 nLen := junkNoJump(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); nLen := junkNoJump(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); // 2.记录下call rel32地址 lpCall := lpSeek; Inc(PByte(lpSeek), 5); // call rel32指令长5字节 Dec(nSize, 5); // 3.生成垃圾代码 nLen := junkNoJump(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); // 4.记录下jmp rel32地址 lpJump := lpSeek; Inc(PByte(lpSeek), 5); // jmp rel32指令长度5字节 Dec(nSize, 5); // 5.生成垃圾代码 nLen := junkNoJump(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); // 6.记录下label1地址 lpLabel1 := lpSeek; // 7.生成垃圾代码 nLen := junkNoJump(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); // 8.生成ret代码 nLen := ret(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); // 9.记录下label2地址 lpLabel2 := lpSeek; // A.生成垃圾代码 nLen := junkNoJump(lpSeek, nSize); Inc(PByte(lpSeek), nLen); Dec(nSize, nLen); // 2.生成call代码 call__rel32(lpCall, nSize, SIZE_T(lpLabel1) - SIZE_T(lpCall) - 5); // 4.生成Jmp代码 jmp__rel32(lpJump, nSize, SIZE_T(lpLabel2) - SIZE_T(lpJump) - 5); Result := SIZE_T(lpSeek) - SIZE_T(lpDst); end; { 函数功能: 模仿PPE32b多态变形引擎的垃圾代码产生器重新实现 输入参数: lpDst = 输出内存 nSize = 内存大小(不保证每次都输入满,只会比这个小) 返回数据: 指令长度 } function junk(lpDst: Pointer; nSize: SIZE_T; nLoop: Integer = 1): SIZE_T; var nType: LongWord; lpPos: PByte; nLen: SIZE_T; begin Result := 0; {$ifndef VXL_INLINE_MODE} if ((lpDst = nil) or (nSize = 0)) then Exit; if (Not Vx_IsWritePtr(lpDst, nSize)) then Exit; {$endif} lpPos := lpDst; while (nLoop > 0) do begin nType := PPE32_Random(8); // (0=5, 1=1+2, 2=2+1, 3=1, 4=2, 5=3, 6=none, 7=dummy jump and call) if (nType = 7) then nLen := junkDummyJumpAndCall(lpPos, nSize) else nLen := junkNoJump(lpPos, nSize); if (nLen = 0) then Break; Inc(lpPos, nLen); Dec(nSize, nLen); Dec(nLoop); end; Result := SIZE_T(lpPos) - SIZE_T(lpDst); end; // ============================================================================ function make_xor(lpDst: Pointer; nSize: SIZE_T; nReg: VX_REG32; bNotMov: Boolean = False): SIZE_T; var nRand: LongWord; begin if (bNotMov) then nRand := PPE32_Random(1) else nRand := PPE32_Random(3); case nRand of 0: // sub begin Result := sub__reg32__reg32(lpDst, nSize, nReg, nReg); end; 1: // mov begin Result := mov__reg32__imm32(lpDst, nSize, nReg, 0); end; else // xor Result := xor__reg32__reg32(lpDst, nSize, nReg, nReg); end; end; { function greg0(lpDst: Pointer; nSize: SIZE_T): SIZE_T; begin Result := 0; end; function greg1(lpDst: Pointer; nSize: SIZE_T): SIZE_T; begin Result := 0; end; } // Poly_Mov__reg32__imm32 function greg2(lpDst: Pointer; nSize: SIZE_T; var nReg: VX_REG32; nImm: VX_IMM32): SIZE_T; var nRandReg: VX_REG32; lpPos: PByte; nRandValue: VX_IMM32; nLen: Integer; begin Result := 0; if ((lpDst = nil) or (nSize = 0)) then Exit; // random register repeat nRandReg := get_reg(); until ((nRandReg <> nReg) and (nRandReg <> REG32_ESP) and (nRandReg <> REG32_EAX)); nReg := nRandReg; lpPos := lpDst; case PPE32_Random(5) of 0: begin nRandValue := PPE32_Random(0); // PUSH random_value nLen := push__imm32(lpPos, nSize, nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // POP reg nLen := pop__reg32(lpPos, nSize, nRandReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XOR reg, value nLen := xor__reg32__imm32(lpPos, nSize, nRandReg, nImm xor nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} // result = random_value xor value end; 1: begin nRandValue := PPE32_Random(0); // MOV EAX, random_value nLen := mov__reg32__imm32(lpPos, nSize, REG32_EAX, nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // MOV reg, EAX nLen := mov__reg32__reg32(lpPos, nSize, nRandReg, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // sub reg, value nLen := sub__reg32__imm32(lpPos, nSize, nRandReg, nRandValue - nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} // result = random_value - value end; 2: begin // XOR reg, reg nLen := make_xor(lpPos, nSize, nRandReg, False); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XOR reg, random_value nRandValue := PPE32_Random(0); nLen := xor__reg32__imm32(lpPos, nSize, nRandReg, nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // ADD reg, value nLen := add__reg32__imm32(lpPos, nSize, nRandReg, nImm - nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} // result = random_value + value end; 3: begin // XOR reg, reg nLen := make_xor(lpPos, nSize, nRandReg, False); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // ADD reg, random_value nRandValue := PPE32_Random(0); nLen := add__reg32__imm32(lpPos, nSize, nRandReg, nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XOR reg, value nLen := xor__reg32__imm32(lpPos, nSize, nRandReg, nImm xor nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} // result = random_value xor value end; else nRandValue := PPE32_Random(0); // MOV reg, random_value nLen := mov__reg32__imm32(lpPos, nSize, nRandReg, nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XOR reg, value nLen := xor__reg32__imm32(lpPos, nSize, nRandReg, nImm xor nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} // param = random_value xor value end; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nSize, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); {$endif} Result := (SIZE_T(lpPos) - SIZE_T(lpDst)); end; // Poly_Mov__reg32__imm32 function greg3(lpDst: Pointer; nSize: SIZE_T; SourceReg, CountReg: VX_REG32; var KeyReg: VX_REG32; nImm: VX_IMM32): SIZE_T; var nRandReg: VX_REG32; lpPos: PByte; nLen: Integer; begin Result := 0; if ((lpDst = nil) or (nSize = 0)) then Exit; // random register repeat nRandReg := get_reg(); until ((nRandReg <> SourceReg) and (nRandReg <> CountReg) and (nRandReg <> REG32_ESP) and (nRandReg <> REG32_EAX)); KeyReg := nRandReg; lpPos := lpDst; case PPE32_Random(3) of 0: // MOV reg, value begin nLen := mov__reg32__imm32(lpPos, nSize, KeyReg, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; 1: // PUSH value, POP reg begin nLen := push__imm32(lpPos, nSize, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); nLen := pop__reg32(lpPos, nSize, KeyReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; else // XOR reg, reg nLen := make_xor(lpPos, nSize, nRandReg, False); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // OR, ADD, XOR reg, value case PPE32_Random(3) of 0: begin nLen := xor__reg32__imm32(lpPos, nSize, KeyReg, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; 1: begin nLen := or__reg32__imm32(lpPos, nSize, KeyReg, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; else nLen := add__reg32__imm32(lpPos, nSize, KeyReg, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; end; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nSize, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); {$endif} Result := (SIZE_T(lpPos) - SIZE_T(lpDst)); end; // GREG4 - key incremention function greg4(lpDst: Pointer; nSize: SIZE_T; KeyReg: VX_REG32; nImm: VX_IMM32): SIZE_T; var lpPos: PByte; nLen: Integer; begin Result := 0; if ((lpDst = nil) or (nSize = 0)) then Exit; lpPos := lpDst; case PPE32_Random(3) of 0: begin // ADD reg, value nLen := add__reg32__imm32(lpPos, nSize, KeyReg, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; 1: begin // MOV EAX, value nLen := mov__reg32__imm32(lpPos, nSize, REG32_EAX, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // ADD reg, EAX nLen := add__reg32__reg32(lpPos, nSize, KeyReg, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; 2: begin // MOV EAX, reg nLen := mov__reg32__reg32_x(lpPos, nSize, REG32_EAX, KeyReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // ADD EAX, value nLen := add__eax__imm32(lpPos, nSize, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XCHG EAX, reg nLen := xchg__eax__reg32(lpPos, nSize, KeyReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; else // XCHG EAX, reg nLen := xchg__eax__reg32(lpPos, nSize, KeyReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XOR reg, reg nLen := make_xor(lpPos, nSize, KeyReg, False); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // OR reg, EAX nLen := or__reg32__reg32_x(lpPos, nSize, KeyReg, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // ADD reg, value nLen := add__reg32__imm32(lpPos, nSize, KeyReg, nImm); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nSize, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); {$endif} Result := (SIZE_T(lpPos) - SIZE_T(lpDst)); end; // GREG5 - source incremention function greg5(lpDst: Pointer; nSize: SIZE_T; SourceReg: VX_REG32): SIZE_T; var lpPos: PByte; nLen: Integer; begin Result := 0; if ((lpDst = nil) or (nSize = 0)) then Exit; lpPos := lpDst; if (PPE32_Random(2) <> 0) then begin // 4x inc reg nLen := inc__reg32(lpPos, nSize, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); nLen := inc__reg32(lpPos, nSize, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); nLen := inc__reg32(lpPos, nSize, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); nLen := inc__reg32(lpPos, nSize, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end else begin nLen := greg4(lpPos, nSize, SourceReg, 4); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nSize, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); {$endif} Result := (SIZE_T(lpPos) - SIZE_T(lpDst)); end; // GREG6 - count decremention function greg6(lpDst: Pointer; nSize: SIZE_T; CountReg: VX_REG32): SIZE_T; var lpPos: PByte; nLen: Integer; nRandValue: VX_IMM32; begin Result := 0; if ((lpDst = nil) or (nSize = 0)) then Exit; lpPos := lpDst; case PPE32_Random(5) of 0: begin // DEC reg nLen := dec__reg32(lpPos, nSize, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; 1: begin // MOV EAX, random_value nRandValue := PPE32_Random(0); nLen := mov__reg32__imm32(lpPos, nSize, REG32_EAX, nRandValue); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // SUB reg, EAX nLen := sub__reg32__reg32(lpPos, nSize, CountReg, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // ADD reg, random_value-1 nLen := add__reg32__imm32(lpPos, nSize, CountReg, nRandValue - 1); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; 2: begin // XCHG EAX, reg nLen := xchg__eax__reg32(lpPos, nSize, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // DEC EAX nLen := dec__reg32(lpPos, nSize, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nSize, nLen); // XCHG EAX, reg nLen := xchg__eax__reg32(lpPos, nSize, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; else // SUB reg, 1 nLen := sub__reg32__imm8(lpPos, nSize, CountReg, 1); if (nLen = 0) then Exit; Inc(lpPos, nLen); {$ifndef PPE32_NOJUNK} Dec(nSize, nLen); {$endif} end; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nSize, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); {$endif} Result := (SIZE_T(lpPos) - SIZE_T(lpDst)); end; // ============================================================================ // 加密数据(xor + add) procedure CryptData(lpDst, lpSrc: Pointer; nSize: SIZE_T; nXorKey, nIncKey: UInt32); var nKey: LongWord; nLoop: LongWord; begin if ((lpDst = nil) or (lpSrc = nil) or (nSize = 0)) then Exit; nKey := nXorKey; nLoop := nSize div SizeOf(LongWord); while (nLoop > 0) do begin PLongWord(lpDst)^ := PLongWord(lpSrc)^ xor nKey; nKey := nKey + nIncKey; Inc(PLongWord(lpDst)); Inc(PLongWord(lpSrc)); Dec(nLoop); end; end; // 将lpSrc代码多态加密后存储在lpDst内存中 function PPE32_Engine(lpOutput: Pointer; nOutputSize: SIZE_T; lpInput: Pointer; nInputSize: SIZE_T): SIZE_T; var lpPos: PByte; nPos: SIZE_T; lpDataOffset: Pointer; nKeyXor, nKeyInc: LongWord; nLen: Integer; RandReg: VX_REG32; lpDelta: Pointer; DeltaReg, SourceReg, CountReg, KeyReg: VX_REG32; lpDecrypter: Pointer; begin Result := 0; if ((lpOutput = nil) or (lpInput = nil) or (nInputSize = 0) or (PPE32_GetMaxSize(nInputSize) > nOutputSize)) then Exit; lpPos := lpOutput; nPos := nOutputSize; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 5); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // 生成CALL @F + pop reg指令(@F里面包含的是加密后的原始代码) nKeyXor := PPE32_Random(0); nKeyInc := PPE32_Random(0); nLen := call__rel32(lpPos, nPos, nInputSize); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // 加密数据后保存 lpDataOffset := lpPos; CryptData(lpPos, lpInput, nInputSize, nKeyXor, nKeyInc); Inc(lpPos, nInputSize); Dec(nPos, nInputSize); // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 3); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // pushad(保存寄存器信息) nLen := pushad(lpPos, nPos); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // =========================================== // generate SEH handler // call $+6 // mov esp, dword ptr [esp+8] // jmp $+0C nLen := call__rel32(lpPos, nPos, 6); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := mov__reg32__mem32_reg32_Idx8(lpPos, nPos, REG32_ESP, REG32_ESP, 8); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := jmp__rel8(lpPos, nPos, $0C); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // =========================================== // sub reg32, reg32 | xor reg32, reg32 | mov reg32, 0 (reg32不能是EBP) // push fs:[reg32] // mov fs:[reg32], esp // inc dword ptr[reg32] | inc byte ptr[reg32] // jmp $-24d (这个地址没什么意义,因为肯定会被SEH捕获的) repeat RandReg := get_reg(); until (RandReg <> REG32_EBP); // sub reg32, reg32 nLen := make_xor(lpPos, nPos, RandReg, True); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // push fs:[reg32] nLen := prefix_fs(lpPos, nPos); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := push__mem32_reg32(lpPos, nPos, RandReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // mov fs:[reg32], esp nLen := prefix_fs(lpPos, nPos); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := mov__mem32_reg32__reg32(lpPos, nPos, RandReg, REG32_ESP); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // inc dword ptr[reg32] | inc byte ptr[reg32] if (PPE32_Random(2) = 0) then nLen := inc__mem8_reg32(lpPos, nPos, RandReg) else nLen := inc__mem32_reg32(lpPos, nPos, RandReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // jmp $-24d (这个地址没什么意义,因为肯定会被SEH捕获的) nLen := jmp__rel8(lpPos, nPos, -24); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // =========================================== // sub reg32, reg32 | xor reg32, reg32 | mov reg32, 0 (reg32不能是EBP) // pop fs:[reg32] // pop reg32 repeat RandReg := get_reg(); until (RandReg <> REG32_EBP); SourceReg := RandReg; // sub reg32, reg32 nLen := make_xor(lpPos, nPos, RandReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // pop fs:[reg32] nLen := prefix_fs(lpPos, nPos); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := pop__mem32_reg32(lpPos, nPos, RandReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // pop reg32 nLen := pop__reg32(lpPos, nPos, RandReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // =========================================== // 生成重定位代码获取加密数据 // call $ // junk // @@: // pop reg32 | mov reg32, [esp], pop eax // sub reg32, @F // call $ nLen := call__rel32(lpPos, nPos, 0); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); lpDelta := lpPos; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // 生成随机寄存器 DeltaReg := get_reg(); // pop reg32 | mov reg32, [esp], pop eax if (PPE32_Random(1) = 0) then begin nLen := pop__reg32(lpPos, nPos, DeltaReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end else begin nLen := mov__reg32__mem32_reg32(lpPos, nPos, DeltaReg, REG32_ESP); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := pop__reg32(lpPos, nPos, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; // sub reg32, @F nLen := sub__reg32__imm32(lpPos, nPos, DeltaReg, VX_IMM32(lpDelta)); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // generate MOV sourcereg, ... SourceReg := DeltaReg; nLen := greg2(lpPos, nPos, SourceReg, VX_IMM32(lpDataOffset)); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // generate ADD sourcereg, deltaoffset nLen := add__reg32__reg32(lpPos, nPos, SourceReg, DeltaReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // generate MOV countreg, ... CountReg := SourceReg; nLen := greg2(lpPos, nPos, CountReg, VX_IMM32(nInputSize div SizeOf(LongWord))); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // generate MOV keyreg, ... nLen := greg3(lpPos, nPos, SourceReg, CountReg, KeyReg, nKeyXor); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // store this position for jump to decryptor lpDecrypter := lpPos; // generate XOR [sourcereg], keyreg nLen := xor__mem32_reg32__reg32(lpPos, nPos, SourceReg, KeyReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); case PPE32_Random(6) of 0: begin // greg6 nLen := greg6(lpPos, nPos, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg5 nLen := greg5(lpPos, nPos, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg4 nLen := greg4(lpPos, nPos, KeyReg, nKeyInc); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; 1: begin // greg4 nLen := greg4(lpPos, nPos, KeyReg, nKeyInc); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg6 nLen := greg6(lpPos, nPos, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg5 nLen := greg5(lpPos, nPos, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; 2: begin // greg5 nLen := greg5(lpPos, nPos, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg4 nLen := greg4(lpPos, nPos, KeyReg, nKeyInc); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg6 nLen := greg6(lpPos, nPos, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; 3: begin // greg5 nLen := greg5(lpPos, nPos, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg6 nLen := greg6(lpPos, nPos, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg4 nLen := greg4(lpPos, nPos, KeyReg, nKeyInc); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; 4: begin // greg6 nLen := greg6(lpPos, nPos, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg4 nLen := greg4(lpPos, nPos, KeyReg, nKeyInc); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg5 nLen := greg5(lpPos, nPos, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; else // greg4 nLen := greg4(lpPos, nPos, KeyReg, nKeyInc); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg5 nLen := greg5(lpPos, nPos, SourceReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // greg6 nLen := greg6(lpPos, nPos, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; // ====================================== // GREG7 - decryption loop if (PPE32_Random(2) > 0) then begin // PUSH ECX nLen := push__reg32(lpPos, nPos, REG32_ECX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // MOV ECX, reg nLen := mov__reg32__reg32(lpPos, nPos, REG32_ECX, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // JECXZ label nLen := jecxz__rel8(lpPos, nPos, $03); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // POP ECX nLen := pop__reg32(lpPos, nPos, REG32_ECX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // JMP decrypt_loop nLen := jmp__rel8(lpPos, nPos, VX_IMM8(lpDecrypter) - VX_IMM8(lpPos) - 2); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // label: // POP ECX nLen := pop__reg32(lpPos, nPos, REG32_ECX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end else begin nLen := make_xor(lpPos, nPos, REG32_EAX, False); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := dec__reg32(lpPos, nPos, REG32_EAX); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := add__reg32__reg32_x(lpPos, nPos, REG32_EAX, CountReg); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); nLen := jns__rel8(lpPos, nPos, VX_IMM8(lpDecrypter) - VX_IMM8(lpPos) - 2); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); end; // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // ====================================== // popad nLen := popad(lpPos, nPos); if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); // 生成垃圾代码 {$ifndef PPE32_NOJUNK} nLen := junk(lpPos, nPos, 1); //if (nLen = 0) then Exit; Inc(lpPos, nLen); Dec(nPos, nLen); {$endif} // ret nLen := ret(lpPos, nPos); if (nLen = 0) then Exit; //Inc(lpPos, nLen); Dec(nPos, nLen); Result := nOutputSize - nPos; end; // 获取APE32加密后存储内存空间最大尺寸 function PPE32_GetMaxSize(nSize: SIZE_T): SIZE_T; begin Result := 0; if (nSize = 0) then Exit; Result := nSize + PPE32_Derypter_SIZE; end; end.