;------------------------------------------------------------------------------- ; DISCLAIMER : All these informations and documentations are given :REMIALCSID ; ; DISCLAIMER : to public in order to understand how is made a :REMIALCSID ; ; DISCLAIMER : virus, I'm not responsible of the use of this :REMIALCSID ; ; DISCLAIMER : (cool) paper. Virus writting is not forbiden! :REMIALCSID ; ; DISCLAIMER : but virus distribution is forbiden!!! :REMIALCSID ; ;------------------------------------------------------------------------------- ************************************************ * POLYMORPHISM AND INTEL INSTRUCTION FORMAT * ************************************************ 1 - INTRODUCTION 2 - INTEL INSTRUCTION FORMAT 3 - INSTRUCTION PREFIXE 4 - OP CODE 5 - ModR/M 6 - SIB 7 - DISPLACEMENT 8 - IMMEDIATE 9 - ALGO OF DISASSEMBLY 10 - HOW TO WRITE YOUR OWN ASSEMBLY PROCESS 11 - APPENDIX ( SCHEMAS AND TABLES ) ********************* *** *** ** INTRODUCTION ** *** *** ********************* This quick tutorial will help you to understood the way to disassemble opcodes. It is not an 'intel looks like' document...It is only an introduction to intel opcode, after reading this you should read intel doc, or all doc speaking about intel instruction format... NOTION REQUIRED before learning this tutorial: - asm, the only way to code nice vx... - english, only the bad english used to wrote vx tutorials ;-) - Encryption - Polymorphisme DOCUMENTS YOU SHOULD FIND: - The Art Of Assembly (pdf) http://aod.anticrack.de - Intel Architecture Manual http://intel.com - Code source of NASM (in C++) In the 'The Art Of Assembly Tutorial' you will find some exe prog to play with opcodes! In virus world there is a terrible war: Against virus writers and antivirus software. Most virus writters code for pleasure but AV company for money... I will not explain here the concept of polymorphism (see older zines!) The principe is simple: in a polymorph virus, the body of the virus is encrypted to avoid AV string scanning, and polymorphism is use in the 'decryptage' code. The part of the code which decrypt all the rest of the virus is'nt encrypted but his appeareance change in the next infection. There is severals ways to do that. If will explain here a cool technique: The virus is able to disasm the 'decryptage loop', change him, and re-asm it. example: ;---------------------------------------------------------------- lea esi,[VirusBody+ebp] ; (ebp=delta offset of course) mov ecx,EndOfVirusBody-VirusBody ; lenght of virus body mov al,byte[key+ebp] ; key to decrypte data Decrypt: xor byte[esi],al inc esi loop Decrypt VirusBody: . . . EndOfVirusBody: ;---------------------------------------------------------------- can be change in: ;---------------------------------------------------------------- mov esi,[VirusBody] add esi,ebp xor ebx,ebx mov bl,byte[key+ebp] xchg eax,ebx push dword EndOfVirusBody-VirusBody pop ecx Decrypt: xor byte[esi],al add esi,1 nop loop Decrypt VirusBody: . . . EndOfVirusBody: ;---------------------------------------------------------------- The problem is to Disasm, and Re-asm the code...To do this I will explain brievely the Intel Instruction Format: To know how to convert the hex string '40h' in his "humanly readeable code" 'inc eax' for example ******************************** *** *** ** INTEL INSTRUCTION FORMAT ** *** *** ******************************** An intel instruction has a specific format: INTEL INSTRUCTION FORMAT +-------------+--------+----------+---------+--------------+------------+ ; instruction ; opcode ; ModR/M ; SIB ; Displacement ; Immediate ; ; prefixe ; ; ; ; ; ; +-------------+--------+----------+---------+--------------+------------+ Up to four 1 or 2 1 byte(if 1 byte(if address immediate prefixe of bytes required) required) displacement data 1 byte each opcode / \ of 1,2 or 4 of 1,2 or 4 (optional) / \ bytes or none bytes or none / \ / \ / \ / \ 7 6 5 3 2 0 7 6 5 3 2 0 +-----+--------+-----+ +-------+-------+------+ ; Mod ; Reg/ ; R/M ; ; scale ; index ; base ; ; ; opcode ; ; ; ; ; ; +-----+--------+-----+ +-------+-------+------+ Intel instructions can vary in size, but they still have the same six groups. We need to understand each group , and know it is purpose in order to be able to learn the sizes of the diferent instructions. I will not describe all in detail because it's annoying, find doc about intel instruction format (see on intel web site) *************************** *** *** ** INSTRUCTION PREFIXE ** *** *** *************************** The instruction prefix is optional but they change the behavior of the instruction in many ways. an instruction can have (or not) 0,1,2,3 or 4 prefixes. There are 5 type of prefixes: - SEGMENT PREFIX : Prefixes that specify the segment 2E 36 3E 26 64 65 - Operand-Size Prefix : Prefix that changes the default operand size 66 - Address-Size Prefix : Prefix that changes the default address size 67 - REP/REPNE Prefixes : Prefixes that change the string operation n loops F3 F2 - Bus LOCK Prefix : Prefix that controls the processor BUS F0 * One opcode can have several prefix: none,1,2,3 or 4 * the order of the prefixes is not important * Each prefix is 1 byte size +----------------+ ; Segment prefix ; +----------------+ The segment prefix change the default segment of the instruction, the default segment prefix is DS: 2EH : CS segment override prefix. 36H : SS segment override prefix. 3EH : DS segment override prefix. 26H : ES segment override prefix. 64H : FS segment override prefix. 65H : GS segment override prefix. expl: 8B00 MOV EAX,DWORD PTR DS:[EAX] (none prefix) 2E:8B00 MOV EAX,DWORD PTR CS:[EAX] 8B00 MOV EAX,DWORD PTR DS:[EAX] (none prefix) 36:8B00 MOV EAX,DWORD PTR SS:[EAX] +---------------------+ ; OPERAND-SIZE PREFIX ; +---------------------+ The operand size prefix allows a programm to switch between 16 n' 32 bit operand sizes. This prefix select the non-default size...It is to say that if there is not the prefix 66h so it is the default operand size. It 's recommended not to use this prefix after MMX, SSE and/or SSE2 instructions! Quick example(in a win32 environement): 89 C0 MOV EAX,EAX (none prefix) 66 89 C0 MOV AX, AX (prefix=66h) +---------------------+ ; Address-Size Prefix ; +---------------------+ The address-size prefix allow a program to switch between 16 n' 32 bits addressing. the prefix select the non default size I will put here an example because it's no really use for us (I hope you code in win32...) expl: 8B00 MOV EAX,DWORD PTR DS:[EAX] 32bits addressing mode 67:8B00 MOV EAX,DWORD PTR DS:[BX+SI] 16bits adressing mode +--------------------+ ; REP/REPNE Prefixes ; +--------------------+ I will put here only examples: AD LODS DWORD PTR DS:[ESI] F3 AD REP LODS DWORD PTR DS:[ESI] F2 AD REPNE LODS DWORD PTR DS:[ESI] 3E F2 AD REPNE LODS DWORD PTR DS:[ESI] +-----------------+ ; Bus LOCK Prefix ; +-----------------+ No use for us...Execpt if you want to know all the mystery of intel instruction format in order to disasm the host, find a good place for the virus inside the disassembled host code and reassembly all the infected file... *************************** ** ** ** OP CODE ** ** ** *************************** +------------------+ ; One Byte Opcodes ; +------------------+ in intel doc you can find something like this for the description of the PUSH REG instruction: PUSH REG <------> 01010reg (where 'reg' are 3 bits) For the description of all instruction, I let you see the big pdf file from intel (I've put some description in APPENDIX about the most used instructions you can use in a decryptor LOOP) Let’s study this following instruction (it is 1byte instruction): PUSH EAX ---> 50h ---> 01010000 ---> 01010 000 / \ / \ / \ bits 7 6 5 4 3 2 1 0 +-----------+--------+ ; OPCODE ;REGISTER; +-----------+--------+ ; 0 1 0 1 0 ; 0 0 0 ; +-----------+--------+ The 5 bits (01010) on the left are responsible for the instruction 'push' The 3 bits (000) on the right are responsible for the register 'eax' (see register table) let's look at some instruction encoding: Little Opcode Table: Register Table: REG 8bit 16bit 32bit 01000reg : INC REG 000 : AL : AX : EAX 01001reg : DEC REG 001 : CL : CX : ECX 01010reg : PUSH REG 010 : DL : DX : EDX 01011reg : POP REG 011 : BL : BX : EBX 10010reg : XCHG EAX,REG 100 : AH : SP : ESP 10111reg : MOV REG,IMM32 101 : CH : BP : EBP 110 : DH : SI : ESI 111 : BH : DI : EDI One another (fun) example: 90h ---> 10010 000 ---> XCHG EAX,EAX (NOP) Only the instruction inc reg, dec reg, push reg, pop reg, xchg eax,reg, mov reg,imm32 can be decoded like this! for the others one byte instructions, I let you see an one-byte-opcode map... Let’s take a look at this opcode now, it is a another way to decode opcode: 89C1h ---> 1000100111000001b ---> mov ecx,eax It is still an one byte opcode: C1h is the [ModR/M] field! 89h C1h 10001001 11000001 [CODE] [ModR/M] / \ / \ / \ +----------------+ +------------------+ ; instr ; d ; w ; ; Mod; REG1 ; REG2 ; +--------+---+---; +----+------+------+ ; 100010 ; 0 ; 1 ; ; 11 ; 000 ; 001 ; +--------+---+---+ +----+------+------+ instr : responsible for the opcode instruction (d)bit: if (d)=0 then the order is REG2-REG1 if (d)=1 then the order is REG1-REG2 (w)bit: if (w)=0 we are in 8 bits mode in 32bits environement(Win32) if (w)=1 we are in 32 bits mode in 32bits environement(Win32) if (w)=0 we are in 8 bits mode in 16bits environement if (w)=1 we are in 16 bits mode in 16bits environement Mod : we will see it later... Ok, it's not very clear in your mind yet but you will understand with examples: ############################ # example for the (d) bit: # ############################ (in 32bits environement) [CODE] [ModR/M] [CODE] [ModR/M] +----------------;;------------------+ +----------------;;------------------+ ; instr ; d ; w ;; Mod; REG1 ; REG2 ; ; instr ; d ; w ;; Mod; REG1 ; REG2 ; +--------+---+---;;----+------+------+ +--------+---+---;;----+------+------+ ; 100010 ; 0 ; 1 ;; 11 ; 000 ; 001 ; ; 100010 ; 1 ; 1 ;; 11 ; 000 ; 001 ; +--------+---+---;;----+------+------+ +--------+---+---;;----+------+------+ ! ! \ EAX ECX ! ! \ EAX ECX ! ! ! or AX or CX ! ! ! or AX or CX \!/ ! \!/ or AL or CL \!/ ! \!/ or AL or CL ' ! ' ' ! ' MOV ! 32bits MOV ! 32bits \!/ \!/ ' the order the order is REG2-REG1 is REG1-REG2 \_______________ _________________/ \_______________ _________________/ \/ \/ MOV ECX,EAX MOV EAX,ECX ############################ # example for the (w) bit: # ############################ [CODE] [ModR/M] [CODE] [ModR/M] +----------------;;------------------+ +----------------;;------------------+ ; instr ; d ; w ;; Mod; REG1 ; REG2 ; ; instr ; d ; w ;; Mod; REG1 ; REG2 ; +--------+---+---;;----+------+------+ +--------+---+---;;----+------+------+ ; 100010 ; 0 ; 1 ;; 11 ; 000 ; 001 ; ; 100010 ; 0 ; 0 ;; 11 ; 000 ; 001 ; +--------+---+---;;----+------+------+ +--------+---+---;;----+------+------+ ! ! \ EAX ECX ! ! \ EAX ECX ! ! ! or AX or CX ! ! ! or AX or CX \!/ ! \!/ or AL or CL \!/ ! \!/ or AL or CL ' ! ' ' ! ' MOV ! 32bits MOV ! 8bits \!/ \!/ ' the order the order is REG2-REG1 is REG2-REG1 \_______________ _________________/ \_______________ _________________/ \/ \/ MOV ECX,EAX MOV CL,AL examples with 66h prefix: ;-------+-----------+----------+ ;-------+-----------+----------+ ; Pref. ; [CODE] ; [ModR/M] ; ; Pref. ; [CODE] ; [ModR/M] ; +-------+-----------+----------+ +-------+-----------+----------+ ; 66h ; 89h ; C1h ; ; ; 88h ; C1h ; +-------+-----------+----------+ +-------+-----------+----------+ ; 66h ; 10001001 ; 11000001 ; ; ; 10001000 ; 11000001 ; ; ; (w)=1 ; ; ; ; (w)=0 ; ; +-------+-----------+----------+ +-------+-----------+----------+ MOV CX,AX MOV CL,AL Little Instruction Opcode table: BINARY OPCODE ----------------------- 000010dw OR REG,REG 001000dw AND REG,REG 001010dw SUB REG,REG 001100dw XOR REG,REG 001110dw CMP REG,REG 100000dw ADD REG,REG 100010dw MOV REG,REG I Hope You see the interest of this part for us to code polymorphe instructions! NO !!!!!? Try to decode these two (hex) instructions: First Instruction : 8BF8 ---> mov edi, eax Second Instruction : 89C7 ---> mov edi, eax NICE! is'nt it? +-------------------+ ; Two Bytes Opcodes ; +-------------------+ Some instruction are 2 bytes long: expl: 0f22 c0 mov cr0,eax ****************** ** ** ** ModR/M ** ** ** ****************** If the instruction needs it, the [ModR/M] block tells to the processor which registers or memory locations to be used by the instruction. The [ModRM] Byte is decoded in a special way, the 8 Bits are divided into three groups (2:3:3). Most of the time. Let us understand each of them. 7 6 5 3 2 0 +-----+--------+-----+ ; Mod ; Reg/ ; R/M ; ; ; opcode ; ; +-----+--------+-----+ * [Mod]: 00 : memory address expl: eax, [eax] 01 : memory address with 1 byte displacement expl: [eax+00] 10 : memory address with 1 dword displacement expl: [eax+00000000] 11 : both operands are memory expl: eax,eax * [Reg/opcode]: This field can be considered as a Code extension field or as a Reg fielf. The processor knows which is the right decoding for this field. -If it is a Code extension: There are instructions that require 1-Operand and others that require 2-Operands. For example: ADD: instruction requires 2-Operands (add eax, eax) MUL: instruction requires only 1-Operand (mul eax) If we’re working with an instruction that requires only 1-operand then, the middle 3-Bits [Reg/opcode]field is Code extension bits. example: F7D0 : 11110111 11 010 000 not eax F7E0 : 11110111 11 100 000 mul eax F7F0 : 11110111 11 110 000 div eax they all have 0xF7 for the [CODE] byte, only [Reg/opcode] is different. (000 is for the reg eax!) -If it is a Reg field: example with the hex instruction: [CODE] [MorR/M] 39 d0 CMP \_ \ \ \ \ \ 7 6 5 4 3 2 1 0 bits \ +-----+--------+-------+ \ ; Mod ; Reg/ ; R/M ; \ ; ; opcode ; ; | +-----+--------+-------+ \ ; 1 1 ; 0 1 0 ; 0 0 0 ; \ +-----+--------+-------+ CMP EDX EAX So 39d0h is CMP EAX,EDX (because of the (d) bits in [CODE] field) * [R/M] Depending on the (Mode) Bits in the ModRM byte: - If [Mod]=00 and [R/M]=101 : then no register is used to calculate address, instead the address is in the DWORD after [ModR/M] Byte. expl: 3305 563412 xor eax,[12345678h] - If [Mod]=00 and [R/M]=100 : It means that there’s a SIB byte right after the [ModR/M] byte. - If [Mod]=01 and [R/M]=100 : It means that there’s a SIB byte right after the [ModR/M] byte. - If [Mod]=10 and [R/M]=100 : It means that there’s a SIB byte right after the [ModR/M] byte. - If [Mod]=11 : this field means --> registers exmpl: 89:C0 = mov eax, eax (P.S.: I've not verify this part, if [Mod]=xx then it means....) (Let's make your own mind about that) ****************** ** ** ** SIB ** ** ** ****************** SIB Stands for (Scale : Index :Base). The general Format Of The SIB Byte is ( Scale * Index + Base ). 7 6 5 4 3 2 1 0 bits +-----+--------+-------+ ;Scale; Index ; Base ; +-----+--------+-------+ Scale * Index + Base * Scale : can be considered as the multiplier (of the index register) 00:xxx:xxx = 2^0 = 1 (*1) 01:xxx:xxx = 2^1 = 2 (*2) 10:xxx:xxx = 2^2 = 4 (*4) 11:xxx:xxx = 2^3 = 8 (*8) * Index : it is a Register (All register except esp) * Base : it is a Base Register expl: [SIB] | ----------------+---------------------------- 00 : 000 : 001 | mov reg, [1 * eax + ecx] 01 : 001 : 010 | mov reg, [2 * ecx + edx] 01 : 110 : 111 | mov reg, [2 * edi + esi] 10 : 010 : 011 | mov reg, [4 * edx + ebx] 11 : 011 : 000 | mov reg, [8 * eax + ebx] - If Index register code is the code for (esp), then the index is IGNORED, and in this case, the value of the scale is also IGNORED, and only the Base register is used to calculate the address. - If we need to encode an instruction like (add reg, [esp]) it can’t be done with simply using an SIB byte. But it would be encoded like this: (add reg, [esp + DISPLACEMENT]) ****************** ** ** ** DISPLACEMENT ** ** ** ****************** Just a quik example with the instruction 8b bd 78563412 : 8b bd 78563412 [CODE] [MorR/M] [???] / \ / \ / \ / \ +----------------; +-----+--------+-------+ ; instr ; d ; w ; ; Mod ; Reg/ ; R/M ; +--------+---+---; ; ; opcode ; ; ; 100010 ; 1 ; 1 ; +-----+--------+-------+ +--------+---+---; ; 1 0 ; 1 1 1 ; 1 0 1 ; (d)=0 : the order is +-----+--------+-------+ REG1-REG2 EDI EBP (w)=1 : 32 bits mode or code instr : MOV r32,r/m32 extension [CODE] = 8b : opcode ---> MOV r32,r/m32 [Mod] = 10 : memory address with 1 dword displacement ---> MOV REG,[REG+DWORD] [Reg/opcode] = 111 : this instruction don't need an code extension so it is a register ---> MOV EDI,[EBP+DWORD] [R/M] = 101 : there is no [SIB] after the byte[ModR/M] [78563412] = 12345678h : it is the deplacement ---> MOV EDI,[EBP+12345678h] So the instruction 8b bd 78563412 is mov edi,[ebp+12345678h] ***************** ** ** ** IMMEDIATE ** ** ** ***************** expl: 05h is the opcode for ADD EAX,imm32 05h 00000010 is the instruction for add eax, 10000000 **************************** ** ** ** ALGO OF DISASSEMBLY ** ** ** **************************** ! \!/ +-----'-------+ ; Read 1 byte ; <--------- +-------------+ \ ! \ +------------------+ \!/ --------<----- ; Convert to ASCII ; +-----'------------+ +-------.----------+ ; Check for prefix ; /!\ +------------------+ ! ! ! \!/ +-----------------+ ;-----'----------------+ ; [IMMEDIATE] ; ; Decode [CODE] byte(s); +-----------------+ +----------------------+ ; [DISPLACEMENT] ; ! +-----------------+ \!/ ; decode [SIB] ; +-----'-----------------+ +-----------------+ ; JMP or CALL opcodes ? ; -------->------> ; decode [ModR/M] ; +-----------------------+ +-----------------+ ************************************************ ** ** ** HOW TO WRITE YOUR OWN DIS/ASSEMBLY PROCESS ** ** ** ************************************************ Of course you can code a process which is able to disassemble all the code of the virus, to morph all the code and to reassemble the virus. I think it is better to deal only with the decryptor LOOP because it is more speed and your code will be not too much big... You should choose first the opcodes and morphed opcodes you want to include in your decryptor LOOP. Next you can write a code which is able to disasm and reasm them. You will find a problem: JMP,LOOP and CALL instructions...Use your brain! You should considered your decryptor like inside a larger field: +-----------------+ +-----------------+ +-----------------+ ; POLY DECRYPTOR ; ; POLY DECRYPTOR ; ; POLY DECRYPTOR ; +-----------------+ because it ; MORPHED ; ; MORE MORPHED ; ; ; can looks like ; ;--->; ; ; EMPTY ; this next ------> +-----------------+ ; ; ; SPACE ; ; ; +-----------------+ ; (NOP or other) ; ; EMPTY SPACE ;--->; empty space ; +-----------------+ <- fixed offset -> +-----------------+ +-----------------+ ; ; ; ; ; ; ; VIRUS ; ; VIRUS ; ; VIRUS ; of course you should check if your 'reasm code' isn't larger than your empty space... +--------------------+ + MORPHING YOUR CODE + +--------------------+ There is 4 ways to do that: method 1 : change the code 'xor ecx,ecx' in 'mov ecx,0' for example method 2 : change the encoding of instruction: 8BF8 mov edi,eax 89C7 mov edi,eax (see the (d)bits in [CODE]field) 8b00 mov eax,dword ptr DS:[EAX] 3e8b00 mov eax,dword ptr DS:[EAX] (see default segment prefix) method 3 : insert instruction which don't change the result of your code method 4 : Change the registers used Decrypt: Decrypt: xor byte[esi],al xor byte[edx],bl inc esi inc edx loop Decrypt loop Decrypt ****************** ** ** ** APPENDIX ** ** ** ****************** ############################ # INTEL INSTRUCTION FORMAT # ############################ +-----------+--------+ +----------------; ; OPCODE ;REGISTER; ; instr ; d ; w ; +-----------+--------+ OR +--------+---+---; ; 0 1 0 1 0 ; 0 0 0 ; ; 100010 ; 0 ; 1 ; +-----------+--------+ +--------+---+---; \ / \ / \ / \ / \ / +-------------+--------+----------+---------+--------------+------------+ ; instruction ; opcode ; ModR/M ; SIB ; Displacement ; Immediate ; ; prefixe ; ; ; ; ; ; +-------------+--------+----------+---------+--------------+------------+ Up to four 1 or 2 1 byte(if 1 byte(if address immediate prefixe of bytes required) required) displacement data 1 byte each opcode / \ of 1,2 or 4 of 1,2 or 4 (optional) / \ bytes or none bytes or none / \ / \ / \ / \ 7 6 5 3 2 0 7 6 5 3 2 0 +-----+--------+-----+ +-------+-------+------+ ; Mod ; Reg/ ; R/M ; ; scale ; index ; base ; ; ; opcode ; ; ; ; ; ; +-----+--------+-----+ +-------+-------+------+ ############################ # PREFIX # ############################ - SEGMENT PREFIX : 2E(CS) 36(SS) 3E(DS) 26(ES) 64(FS) 65(GS) (default is DS) - Operand-Size Prefix : 66 (default is none) - Address-Size Prefix : 67 (default is none) - REP/REPNE Prefixes : F3 F2 - Bus LOCK Prefix : F0 ############################ # [CODE] # ############################ +-----------+--------+ Commone Opcode Table: Register Table: ; OPCODE ;REGISTER; REG 8bit 16bit 32bit +-----------+--------+ 01000 : INC REG 000 : AL : AX : EAX ; 0 1 0 1 0 ; 0 0 0 ; 01001 : DEC REG 001 : CL : CX : ECX +-----------+--------+ 01010 : PUSH REG 010 : DL : DX : EDX 01011 : POP REG 011 : BL : BX : EBX 10010 : XCHG EAX,REG 100 : AH : SP : ESP 10111 : MOV REG,IMM32 101 : CH : BP : EBP 110 : DH : SI : ESI 111 : BH : DI : EDI [CODE] [ModR/M] Common Instruction Opcode table: +----------------;;------------------+ ; instr ; d ; w ;; ; REG1 ; REG2 ; BINARY OPCODE +--------+---+---;;----+------+------+ ----------------------- ; 100010 ; 0 ; 1 ;; 11 ; 000 ; 001 ; 000010dw OR REG,REG +--------+---+---;;----+------+------+ 001000dw AND REG,REG 001010dw SUB REG,REG if (d)=0 , the order is REG2-REG1 001100dw XOR REG,REG if (d)=1 , the order is REG1-REG2 001110dw CMP REG,REG if (w)=0 we are in 8 bits mode(Win32) 100000dw ADD REG,REG if (w)=1 we are in 32 bits mode(Win32) 100010dw MOV REG,REG MORE ABOUT [CODE] : ENCODING MEANING ------------------------------+----------------------------+ 000010dw OR REG,REG ; or reg,reg ; 00000101 imm32 ; add eax,imm32 ; 000000dw Mod,R/M,Reg ; add reg,mem add mem,reg ; 001000dw AND REG,REG ; and reg,reg ; 001010dw Mod,R/M,Reg ; SUB reg,mem SUB mem, reg ; 00101101 imm32 ; sub eax,imm32 ; 001100dw Mod,r/m,Reg data ; xor reg,mem xor mem,reg ; 001110dw CMP REG,REG ; cmp reg,reg ; 01000reg ; inc reg32 ; 01001reg ; dec reg32 ; 01010reg PUSH REG ; push reg ; 01011reg POP REG ; pop reg ; 1000000w 11101reg data32 ; SUB reg, imm ; 1000000w 11000reg data32 ; add reg,imm ; 100010dw MdRegReg data32bit ; mov reg,reg/mem ; 10010reg XCHG EAX,REG ; xchg eax,reg ; 10111reg data32bits ; mov reg,imm32 ; 11100010 imm16 ; loop imm16 ; ------------------------------+----------------------------+ ############################ # [ModR/M] # ############################ 7 6 5 3 2 0 +-----+--------+-------+ ; Mod ; Reg/ ; R/M ; ; ; opcode ; ; +-----+--------+-------+ ; 0 0 ; 0 0 0 ; 0 0 0 ; +-----+--------+-------+ [Mod] : 00 : mem address expl: eax, [eax] 01 : mem address with 1 byte displ. expl: [eax+00] 10 : mem address with 1 dword displ. expl: [eax+00000000] 11 : both operands are memory expl: eax,eax [Reg/opcode] : Code extension field or Reg fielf [R/M] : Depending on the (Mode) Bits in the ModRM byte: - [Mod]=00 [R/M]=101 : the address is in the DWORD after [ModR/M] Byte. - [Mod]=00 [R/M]=100 : there’s a SIB byte after the [ModR/M] byte. - [Mod]=01 [R/M]=100 : there’s a SIB byte after the [ModR/M] byte. - [Mod]=10 [R/M]=100 : there’s a SIB byte after the [ModR/M] byte. - [Mod]=11 : this field means --> registers ========================================================================== ========================================================================== thanks to : Intel to make polymorph instructions Micro$oft Windows Let's give us more n' more exe food for our baby! 29A menbers For their zines!!! VIVA 29A!!! no thanks to : ME !!! for my bad english ;-) All destructiv virus writers I hope that this tutorial will help you but don't forget this: DON'T DESTROY ANYTHING !!! PEACE ! LiTlLe VxW December 2003