📄 rarvm.cpp
字号:
#include "rar.hpp"#include "rarvmtbl.cpp"RarVM::RarVM(){ Mem=NULL;}RarVM::~RarVM(){ delete Mem;}void RarVM::Init(){ if (Mem==NULL) Mem=new byte[VM_MEMSIZE+4];}inline uint RarVM::GetValue(bool ByteMode,uint *Addr){ if (ByteMode) return(*(byte *)Addr); else {#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) byte *B=(byte *)Addr; return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));#else return UINT32(*Addr);#endif }}#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) #define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr)#else #define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):UINT32(*(uint *)(Addr)))#endifinline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value){ if (ByteMode) *(byte *)Addr=Value; else {#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32) ((byte *)Addr)[0]=(byte)Value; ((byte *)Addr)[1]=(byte)(Value>>8); ((byte *)Addr)[2]=(byte)(Value>>16); ((byte *)Addr)[3]=(byte)(Value>>24);#else *(uint32 *)Addr=Value;#endif }}#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32) #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value)#else #define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=(Value)):(*(uint32 *)(Addr)=((uint32)(Value))))#endifvoid RarVM::SetValue(uint *Addr,uint Value){ SetValue(false,Addr,Value);}inline uint* RarVM::GetOperand(VM_PreparedOperand *CmdOp){ if (CmdOp->Type==VM_OPREGMEM) return((uint *)&Mem[(*CmdOp->Addr+CmdOp->Base)&VM_MEMMASK]); else return(CmdOp->Addr);}void RarVM::Execute(VM_PreparedProgram *Prg){ memcpy(R,Prg->InitR,sizeof(Prg->InitR)); unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE); if (GlobalSize) memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize); unsigned int StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize); if (StaticSize) memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize); R[7]=VM_MEMSIZE; Flags=0; VM_PreparedCommand *PreparedCode=Prg->AltCmd ? Prg->AltCmd:&Prg->Cmd[0]; if (!ExecuteCode(PreparedCode,Prg->CmdCount)) PreparedCode[0].OpCode=VM_RET; uint NewBlockPos=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20])&VM_MEMMASK; uint NewBlockSize=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c])&VM_MEMMASK; if (NewBlockPos+NewBlockSize>=VM_MEMSIZE) NewBlockPos=NewBlockSize=0; Prg->FilteredData=Mem+NewBlockPos; Prg->FilteredDataSize=NewBlockSize; Prg->GlobalData.Reset(); uint DataSize=Min(GET_VALUE(false,(uint*)&Mem[VM_GLOBALMEMADDR+0x30]),VM_GLOBALMEMSIZE); if (DataSize!=0) { Prg->GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE); memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE); }}#define SET_IP(IP) \ if ((IP)>=CodeSize) \ return(true); \ if (--MaxOpCount<=0) \ return(false); \ Cmd=PreparedCode+(IP);bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize){ int MaxOpCount=25000000; VM_PreparedCommand *Cmd=PreparedCode; while (1) { uint *Op1=GetOperand(&Cmd->Op1); uint *Op2=GetOperand(&Cmd->Op2); switch(Cmd->OpCode) {#ifndef NORARVM case VM_MOV: SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); break;#ifdef VM_OPTIMIZE case VM_MOVB: SET_VALUE(true,Op1,GET_VALUE(true,Op2)); break; case VM_MOVD: SET_VALUE(false,Op1,GET_VALUE(false,Op2)); break;#endif case VM_CMP: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); } break;#ifdef VM_OPTIMIZE case VM_CMPB: { uint Value1=GET_VALUE(true,Op1); uint Result=UINT32(Value1-GET_VALUE(true,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); } break; case VM_CMPD: { uint Value1=GET_VALUE(false,Op1); uint Result=UINT32(Value1-GET_VALUE(false,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); } break;#endif case VM_ADD: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:(Result<Value1)|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break;#ifdef VM_OPTIMIZE case VM_ADDB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)+GET_VALUE(true,Op2)); break; case VM_ADDD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)+GET_VALUE(false,Op2)); break;#endif case VM_SUB: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break;#ifdef VM_OPTIMIZE case VM_SUBB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)-GET_VALUE(true,Op2)); break; case VM_SUBD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)-GET_VALUE(false,Op2)); break;#endif case VM_JZ: if ((Flags & VM_FZ)!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JNZ: if ((Flags & VM_FZ)==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_INC: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1); SET_VALUE(Cmd->ByteMode,Op1,Result); Flags=Result==0 ? VM_FZ:Result&VM_FS; } break;#ifdef VM_OPTIMIZE case VM_INCB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)+1); break; case VM_INCD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)+1); break;#endif case VM_DEC: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1); SET_VALUE(Cmd->ByteMode,Op1,Result); Flags=Result==0 ? VM_FZ:Result&VM_FS; } break;#ifdef VM_OPTIMIZE case VM_DECB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)-1); break; case VM_DECD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)-1); break;#endif case VM_JMP: SET_IP(GET_VALUE(false,Op1)); continue; case VM_XOR: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_AND: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_OR: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_TEST: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; } break; case VM_JS: if ((Flags & VM_FS)!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JNS: if ((Flags & VM_FS)==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JB: if ((Flags & VM_FC)!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JBE: if ((Flags & (VM_FC|VM_FZ))!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JA: if ((Flags & (VM_FC|VM_FZ))==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JAE: if ((Flags & VM_FC)==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_PUSH: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],GET_VALUE(false,Op1)); break; case VM_POP: SET_VALUE(false,Op1,GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); R[7]+=4; break; case VM_CALL: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1); SET_IP(GET_VALUE(false,Op1)); continue; case VM_NOT: SET_VALUE(Cmd->ByteMode,Op1,~GET_VALUE(Cmd->ByteMode,Op1)); break; case VM_SHL: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(Value1<<Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1<<(Value2-1))&0x80000000 ? VM_FC:0); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SHR: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(Value1>>Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SAR: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(((int)Value1)>>Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_NEG: { uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1)); Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break;#ifdef VM_OPTIMIZE case VM_NEGB: SET_VALUE(true,Op1,-GET_VALUE(true,Op1)); break; case VM_NEGD: SET_VALUE(false,Op1,-GET_VALUE(false,Op1)); break;#endif case VM_PUSHA: { const int RegCount=sizeof(R)/sizeof(R[0]); for (int I=0,SP=R[7]-4;I<RegCount;I++,SP-=4) SET_VALUE(false,(uint *)&Mem[SP & VM_MEMMASK],R[I]); R[7]-=RegCount*4; } break; case VM_POPA: { const int RegCount=sizeof(R)/sizeof(R[0]); for (uint I=0,SP=R[7];I<RegCount;I++,SP+=4) R[7-I]=GET_VALUE(false,(uint *)&Mem[SP & VM_MEMMASK]); } break; case VM_PUSHF: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Flags); break; case VM_POPF: Flags=GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK]); R[7]+=4; break; case VM_MOVZX: SET_VALUE(false,Op1,GET_VALUE(true,Op2)); break; case VM_MOVSX: SET_VALUE(false,Op1,(signed char)GET_VALUE(true,Op2)); break; case VM_XCHG: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); SET_VALUE(Cmd->ByteMode,Op2,Value1); } break; case VM_MUL: { uint Result=GET_VALUE(Cmd->ByteMode,Op1)*GET_VALUE(Cmd->ByteMode,Op2); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_DIV: { uint Divider=GET_VALUE(Cmd->ByteMode,Op2); if (Divider!=0) { uint Result=GET_VALUE(Cmd->ByteMode,Op1)/Divider; SET_VALUE(Cmd->ByteMode,Op1,Result); } } break; case VM_ADC: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint FC=(Flags&VM_FC); uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC); Flags=Result==0 ? VM_FZ:(Result<Value1 || Result==Value1 && FC)|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SBB: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint FC=(Flags&VM_FC); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC); Flags=Result==0 ? VM_FZ:(Result>Value1 || Result==Value1 && FC)|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break;#endif case VM_RET: if (R[7]>=VM_MEMSIZE) return(true); SET_IP(GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); R[7]+=4; continue;#ifdef VM_STANDARDFILTERS case VM_STANDARD: ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data); break;#endif case VM_PRINT:#ifdef DEBUG PrintState(Cmd-PreparedCode);#endif break; } Cmd++; --MaxOpCount; }}void RarVM::PrintState(uint IP){#if defined(DEBUG) && !defined(GUI) && !defined(SILENT) mprintf("\n"); for (int I=0;I<sizeof(R)/sizeof(R[0]);I++) mprintf("R%d=%08X\t%s",I,R[I],I==3 ? "\n":""); mprintf("\nIP=%08X\tFlags: C=%d S=%d",IP,(Flags & VM_FC)!=0,(Flags & VM_FS)!=0); mprintf("\n");#endif}void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg){ InitBitInput(); memcpy(InBuf,Code,Min(CodeSize,BitInput::MAX_SIZE)); byte XorSum=0; for (int I=1;I<CodeSize;I++) XorSum^=Code[I]; faddbits(8); Prg->CmdCount=0; if (XorSum==Code[0]) {#ifdef VM_STANDARDFILTERS VM_StandardFilters FilterType=IsStandardFilter(Code,CodeSize); if (FilterType!=VMSF_NONE) { Prg->Cmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++]; CurCmd->OpCode=VM_STANDARD; CurCmd->Op1.Data=FilterType; CurCmd->Op1.Addr=&CurCmd->Op1.Data; CurCmd->Op2.Addr=&CurCmd->Op2.Data; CodeSize=0; }#endif uint DataFlag=fgetbits(); faddbits(1); if (DataFlag&0x8000) { int DataSize=ReadData(*this)+1; for (int I=0;InAddr<CodeSize && I<DataSize;I++) { Prg->StaticData.Add(1); Prg->StaticData[I]=fgetbits()>>8; faddbits(8); } } while (InAddr<CodeSize) { Prg->Cmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -