├── .vs ├── ProjectSettings.json ├── Simple-Mutation-Base │ └── v15 │ │ ├── .suo │ │ └── Browse.VC.db ├── VSWorkspaceState.json └── slnx.sqlite ├── MyPolymorpher.vcxproj ├── MyPolymorpher.vcxproj.filters ├── MyPolymorpher.vcxproj.user ├── ld32.c ├── ld32.h ├── main.c ├── polymorph.c └── polymorph.h /.vs/ProjectSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CurrentProjectSetting": null 3 | } -------------------------------------------------------------------------------- /.vs/Simple-Mutation-Base/v15/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D34Dspy/Simple-Mutation-Base/c468081710a4248ce3314508aa5cd91592de3df6/.vs/Simple-Mutation-Base/v15/.suo -------------------------------------------------------------------------------- /.vs/Simple-Mutation-Base/v15/Browse.VC.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D34Dspy/Simple-Mutation-Base/c468081710a4248ce3314508aa5cd91592de3df6/.vs/Simple-Mutation-Base/v15/Browse.VC.db -------------------------------------------------------------------------------- /.vs/VSWorkspaceState.json: -------------------------------------------------------------------------------- 1 | { 2 | "ExpandedNodes": [ 3 | "" 4 | ], 5 | "PreviewInSolutionExplorer": false 6 | } -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D34Dspy/Simple-Mutation-Base/c468081710a4248ce3314508aa5cd91592de3df6/.vs/slnx.sqlite -------------------------------------------------------------------------------- /MyPolymorpher.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {8A67A8A7-AEB5-41C8-BA5D-E5A66BEC6BB9} 23 | Win32Proj 24 | MyPolymorpher 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | 116 | 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | Disabled 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | Level3 134 | 135 | 136 | MaxSpeed 137 | true 138 | true 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /MyPolymorpher.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /MyPolymorpher.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ld32.c: -------------------------------------------------------------------------------- 1 | /* 2 | x86 Length Disassembler. 3 | Copyright (C) 2013 Byron Platt 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "ld32.h" 20 | 21 | /* length_disasm */ 22 | uint32_t get_instruction_length (uint8_t* opcode) 23 | { 24 | 25 | uint8_t* start = opcode; 26 | 27 | uint32_t flag = 0; 28 | uint32_t ddef = 4, mdef = 4; 29 | uint32_t msize = 0, dsize = 0; 30 | 31 | uint8_t op, modrm, mod, rm; 32 | 33 | op = *opcode++; 34 | 35 | /* prefix */ 36 | while (CHECK_PREFIX (op)) 37 | { 38 | if (CHECK_PREFIX_66 (op)) 39 | ddef = 2; 40 | else if (CHECK_PREFIX_67 (op)) 41 | mdef = 2; 42 | op = *opcode++; 43 | } 44 | 45 | if (CHECK_0F (op)) // two byte opcode 46 | { 47 | op = *opcode++; 48 | if (CHECK_MODRM2 (op)) 49 | flag++; 50 | if (CHECK_DATA12 (op)) 51 | dsize++; 52 | if (CHECK_DATA662 (op)) 53 | dsize += ddef; 54 | } 55 | else // one byte opcode 56 | { 57 | if (CHECK_MODRM (op)) 58 | flag++; 59 | if (CHECK_TEST (op) && !(*opcode & 0x38)) 60 | dsize += (op & 1) ? ddef : 1; 61 | if (CHECK_DATA1 (op)) 62 | dsize++; 63 | if (CHECK_DATA2 (op)) 64 | dsize += 2; 65 | if (CHECK_DATA66 (op)) 66 | dsize += ddef; 67 | if (CHECK_MEM67 (op)) 68 | msize += mdef; 69 | } 70 | 71 | /* modrm */ 72 | if (flag) 73 | { 74 | modrm = *opcode++; 75 | mod = modrm & 0xc0; 76 | rm = modrm & 0x07; 77 | if (mod != 0xc0) 78 | { 79 | if (mod == 0x40) 80 | msize++; 81 | if (mod == 0x80) 82 | msize += mdef; 83 | if (mdef == 2) 84 | { 85 | if ((mod == 0x00) && (rm == 0x06)) 86 | msize += 2; 87 | } 88 | else 89 | { 90 | if (rm == 0x04) 91 | rm = *opcode++ & 0x07; 92 | if (rm == 0x05 && mod == 0x00) 93 | msize += 4; 94 | } 95 | } 96 | } 97 | 98 | opcode += msize + dsize; 99 | 100 | return opcode - start; 101 | } -------------------------------------------------------------------------------- /ld32.h: -------------------------------------------------------------------------------- 1 | /* 2 | x86 Length Disassembler. 3 | Copyright (C) 2013 Byron Platt 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | You should have received a copy of the GNU General Public License 13 | along with this program. If not, see . 14 | */ 15 | 16 | #ifndef __LD32_H__ 17 | #define __LD32_H__ 18 | 19 | // https://github.com/greenbender/lend/blob/master/ 20 | 21 | #include 22 | 23 | /* implemented tables */ 24 | #define PREFIX_T 1 25 | #define MODRM2_T 2 26 | #define MODRM_T 4 27 | #define DATA1_T 8 28 | #define DATA2_T 16 29 | #define DATA66_T 32 30 | 31 | /* configure tables */ 32 | #ifndef USE_T 33 | #define USE_T (MODRM2_T|MODRM_T|DATA1_T|DATA66_T) 34 | #endif 35 | 36 | /* length_disasm */ 37 | uint32_t get_instruction_length (uint8_t* start); 38 | 39 | /* table macros */ 40 | #ifdef USE_T 41 | #define BITMASK32( \ 42 | b00,b01,b02,b03,b04,b05,b06,b07, \ 43 | b08,b09,b0a,b0b,b0c,b0d,b0e,b0f, \ 44 | b10,b11,b12,b13,b14,b15,b16,b17, \ 45 | b18,b19,b1a,b1b,b1c,b1d,b1e,b1f \ 46 | ) ( \ 47 | (b00<<0x00)|(b01<<0x01)|(b02<<0x02)|(b03<<0x03)| \ 48 | (b04<<0x04)|(b05<<0x05)|(b06<<0x06)|(b07<<0x07)| \ 49 | (b08<<0x08)|(b09<<0x09)|(b0a<<0x0a)|(b0b<<0x0b)| \ 50 | (b0c<<0x0c)|(b0d<<0x0d)|(b0e<<0x0e)|(b0f<<0x0f)| \ 51 | (b10<<0x10)|(b11<<0x11)|(b12<<0x12)|(b13<<0x13)| \ 52 | (b14<<0x14)|(b15<<0x15)|(b16<<0x16)|(b17<<0x17)| \ 53 | (b18<<0x18)|(b19<<0x19)|(b1a<<0x1a)|(b1b<<0x1b)| \ 54 | (b1c<<0x1c)|(b1d<<0x1d)|(b1e<<0x1e)|(b1f<<0x1f) \ 55 | ) 56 | #define CHECK_TABLE(t, v) ((t[(v)>>5]>>((v)&0x1f))&1) 57 | #endif 58 | 59 | /* CHECK_PREFIX */ 60 | #if defined(USE_T) && (USE_T & PREFIX_T) 61 | const static unsigned int prefix_t[] = { 62 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 63 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 0 */ 64 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 1 */ 65 | BITMASK32 (0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, /* 2 */ 66 | 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0), /* 3 */ 67 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 4 */ 68 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 5 */ 69 | BITMASK32 (0,0,0,0,1,1,1,1, 0,0,0,0,0,0,0,0, /* 6 */ 70 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 7 */ 71 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 8 */ 72 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 9 */ 73 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* a */ 74 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* b */ 75 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* c */ 76 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* d */ 77 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* e */ 78 | 1,0,1,1,0,0,0,0, 0,0,0,0,0,0,0,0) /* f */ 79 | }; 80 | #define CHECK_PREFIX(v) CHECK_TABLE(prefix_t, v) 81 | #else 82 | #define CHECK_PREFIX(v) \ 83 | (((v)&0xe7)==0x26||((v)&0xfc)==0x64||(v)==0xf0||(v)==0xf2||(v)==0xf3) 84 | #endif 85 | 86 | /* CHECK_PREFIX_66 */ 87 | #define CHECK_PREFIX_66(v) ((v)==0x66) 88 | 89 | /* CHECK_PREFIX_67 */ 90 | #define CHECK_PREFIX_67(v) ((v)==0x67) 91 | 92 | /* CHECK_0F */ 93 | #define CHECK_0F(v) ((v)==0x0f) 94 | 95 | /* CHECK_MODRM2 */ 96 | #if defined(USE_T) && (USE_T & MODRM2_T) 97 | const static unsigned int modrm2_t[] = { 98 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 99 | BITMASK32 (1,1,1,1,0,0,0,0, 0,0,0,0,0,0,0,0, /* 0 */ 100 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 1 */ 101 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 2 */ 102 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 3 */ 103 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 4 */ 104 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 5 */ 105 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 6 */ 106 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 7 */ 107 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 8 */ 108 | 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1), /* 9 */ 109 | BITMASK32 (0,0,0,1,1,1,0,0, 0,0,0,1,1,1,0,1, /* a */ 110 | 1,1,1,1,1,1,1,1, 0,0,1,1,1,1,1,1), /* b */ 111 | BITMASK32 (1,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* c */ 112 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* d */ 113 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* e */ 114 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0) /* f */ 115 | }; 116 | #define CHECK_MODRM2(v) CHECK_TABLE(modrm2_t, v) 117 | #else 118 | #define CHECK_MODRM2(v) (__extension__ ({ \ 119 | register BYTE __a=(v)&0xfc, __b=(v)&0xfe; \ 120 | ((v)&0xf0)==0x90||((v)&0xf8)==0xb0||((v)&0xf6)==0xa4|| \ 121 | __a==0x00||__a==0xbc||__b==0xba||__b==0xc0|| \ 122 | (v)==0xa3||(v)==0xab||(v)==0xaf; \ 123 | })) 124 | #endif 125 | 126 | /* CHECK_DATA12 */ 127 | #define CHECK_DATA12(v) ((v)==0xa4||(v)==0xac||(v)==0xba) 128 | 129 | /* CHECK_DATA662 */ 130 | #define CHECK_DATA662(v) (((v)&0xf0)==0x80) 131 | 132 | /* CHECK_MODRM */ 133 | #if defined(USE_T) && (USE_T & MODRM_T) 134 | const static unsigned int modrm_t[] = { 135 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 136 | BITMASK32 (1,1,1,1,0,0,0,0, 1,1,1,1,0,0,0,0, /* 0 */ 137 | 1,1,1,1,0,0,0,0, 1,1,1,1,0,0,0,0), /* 1 */ 138 | BITMASK32 (1,1,1,1,0,0,0,0, 1,1,1,1,0,0,0,0, /* 2 */ 139 | 1,1,1,1,0,0,0,0, 1,1,1,1,0,0,0,0), /* 3 */ 140 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 4 */ 141 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 5 */ 142 | BITMASK32 (0,0,1,1,0,0,0,0, 0,1,0,1,0,0,0,0, /* 6 */ 143 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 7 */ 144 | BITMASK32 (1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, /* 8 */ 145 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 9 */ 146 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* a */ 147 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* b */ 148 | BITMASK32 (1,1,0,0,1,1,1,1, 0,0,0,0,0,0,0,0, /* c */ 149 | 1,1,1,1,0,0,0,0, 1,1,1,1,1,1,1,1), /* d */ 150 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* e */ 151 | 0,0,0,0,0,0,1,1, 0,0,0,0,0,0,1,1) /* f */ 152 | }; 153 | #define CHECK_MODRM(v) CHECK_TABLE(modrm_t, v) 154 | #else 155 | #define CHECK_MODRM(v) (__extension__ ({ \ 156 | register BYTE __a=(v)&0xfc, __b=(v)&0xfe; \ 157 | ((v)&0xc4)==0x00||((v)&0xf0)==0x80||((v)&0xf8)==0xd8||((v)&0xf6)==0xf6|| \ 158 | __a==0xc4||__a==0xd0||__b==0x62||__b==0xc0|| \ 159 | (v)==0x69||(v)==0x6b; \ 160 | })) 161 | #endif 162 | 163 | /* CHECK_TEST */ 164 | #define CHECK_TEST(v) ((v)==0xf6||(v)==0xf7) 165 | 166 | /* CHECK_DATA1 */ 167 | #if defined(USE_T) && (USE_T & DATA1_T) 168 | const static unsigned int data1_t[] = { 169 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 170 | BITMASK32 (0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, /* 0 */ 171 | 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0), /* 1 */ 172 | BITMASK32 (0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, /* 2 */ 173 | 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0), /* 3 */ 174 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 4 */ 175 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 5 */ 176 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,1,1,0,0,0,0, /* 6 */ 177 | 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1), /* 7 */ 178 | BITMASK32 (1,0,1,1,0,0,0,0, 0,0,0,0,0,0,0,0, /* 8 */ 179 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 9 */ 180 | BITMASK32 (0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, /* a */ 181 | 1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0), /* b */ 182 | BITMASK32 (1,1,0,0,0,0,1,0, 1,0,0,0,0,1,0,0, /* c */ 183 | 0,0,0,0,1,1,0,0, 0,0,0,0,0,0,0,0), /* d */ 184 | BITMASK32 (1,1,1,1,1,1,1,1, 0,0,0,1,0,0,0,0, /* e */ 185 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0) /* f */ 186 | }; 187 | #define CHECK_DATA1(v) CHECK_TABLE(data1_t, v) 188 | #else 189 | #define CHECK_DATA1(v) (__extension__ ({ \ 190 | register BYTE __a=(v)&0xf8, __b=(v)&0xfe; \ 191 | ((v)&0xf0)==0x70||((v)&0xc7)==0x04|| \ 192 | __a==0xb0||__a==0xe0||__b==0x6a||__b==0x82||__b==0xc0||__b==0xd4|| \ 193 | (v)==0x80||(v)==0xa8||(v)==0xc6||(v)==0xc8||(v)==0xcd||(v)==0xeb; \ 194 | })) 195 | #endif 196 | 197 | /* CHECK_DATA2 */ 198 | #if defined(USE_T) && (USE_T & DATA2_T) 199 | const static unsigned int data2_t[] = { 200 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 201 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 0 */ 202 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 1 */ 203 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 2 */ 204 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 3 */ 205 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 4 */ 206 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 5 */ 207 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 6 */ 208 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 7 */ 209 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 8 */ 210 | 0,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,0), /* 9 */ 211 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* a */ 212 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* b */ 213 | BITMASK32 (0,0,1,0,0,0,0,0, 1,0,1,0,0,0,0,0, /* c */ 214 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* d */ 215 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, /* e */ 216 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0) /* f */ 217 | }; 218 | #define CHECK_DATA2(v) CHECK_TABLE(data2_t, v) 219 | #else 220 | #define CHECK_DATA2(v) \ 221 | ((v)==0x9a||(v)==0xc2||(v)==0xc8||(v)==0xca||(v)==0xea) 222 | #endif 223 | 224 | /* CHECK_DATA66 */ 225 | #if defined(USE_T) && (USE_T & DATA66_T) 226 | const static unsigned int data66_t[] = { 227 | /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 228 | BITMASK32 (0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, /* 0 */ 229 | 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0), /* 1 */ 230 | BITMASK32 (0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, /* 2 */ 231 | 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0), /* 3 */ 232 | BITMASK32 (0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 4 */ 233 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 5 */ 234 | BITMASK32 (0,0,0,0,0,0,0,0, 1,1,0,0,0,0,0,0, /* 6 */ 235 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* 7 */ 236 | BITMASK32 (0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 8 */ 237 | 0,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,0), /* 9 */ 238 | BITMASK32 (0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, /* a */ 239 | 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1), /* b */ 240 | BITMASK32 (0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,0, /* c */ 241 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0), /* d */ 242 | BITMASK32 (0,0,0,0,0,0,0,0, 1,1,1,0,0,0,0,0, /* e */ 243 | 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0) /* f */ 244 | }; 245 | #define CHECK_DATA66(v) CHECK_TABLE(data66_t, v) 246 | #else 247 | #define CHECK_DATA66(v) \ 248 | (((v)&0xc7)==0x05||((v)&0xf8)==0xb8||((v)&0x7e)==0x68|| \ 249 | (v)==0x81||(v)==0x9a||(v)==0xa9||(v)==0xc7||(v)==0xea) 250 | #endif 251 | 252 | /* CHECK_MEM67 */ 253 | #define CHECK_MEM67(v) (((v)&0xfc)==0xa0) 254 | 255 | #endif -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "polymorph.h" 5 | 6 | uintptr_t _my_virtual_alloc(size_t length) 7 | { 8 | return (uintptr_t)VirtualAlloc (NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 9 | } 10 | void _my_virtual_free(uintptr_t addr, size_t len) 11 | { 12 | VirtualFree ((LPVOID)addr, len, 0); 13 | } 14 | void _my_set_is_writable(uintptr_t addr, size_t length, uint32_t* old) 15 | { 16 | VirtualProtect ((LPVOID)addr, length, GENERIC_ALL, (PDWORD)old); 17 | } 18 | void _my_restore_mprot(uintptr_t addr, size_t length, uint32_t flags) 19 | { 20 | uint32_t old; 21 | VirtualProtect ((LPVOID)addr, length, flags, (PDWORD)&old); 22 | } 23 | 24 | typedef void (*set_is_writable_t) (uintptr_t address, size_t length, uint32_t* old_flags); 25 | typedef void (*restore_mprot_t) (uintptr_t address, size_t length, uint32_t flags); 26 | 27 | typedef uint32_t (*show_message_t)(const char* nigga); 28 | uint32_t _my_show_message (const char* nigga) 29 | { 30 | MessageBoxA (NULL, nigga, nigga, 0); 31 | return 0; 32 | } 33 | typedef uint32_t (*print_message_t)(const char* nigga); 34 | uint32_t _my_print_message (const char* nigga) 35 | { 36 | printf_s (nigga); 37 | return 0; 38 | } 39 | typedef void (*initialize_t)(struct _function_table* table); 40 | void _my_initialize (struct _function_table* table); 41 | 42 | typedef struct _function_table 43 | { 44 | initialize_t initialize; 45 | show_message_t show_message; 46 | print_message_t print_message; 47 | }function_table_t; 48 | 49 | void _my_initialize (struct _function_table* table) 50 | { 51 | table->print_message ("nigga\n"); 52 | 53 | // test if statement 54 | if(0 == 1) 55 | { 56 | table->print_message ("something went wrong!\n"); 57 | } 58 | 59 | if(1 != 0) 60 | { 61 | table->print_message ("test jcc success!\n"); 62 | } 63 | if (1 == 1) 64 | { 65 | table->print_message ("test jcc success!\n"); 66 | } 67 | if (1 >= 1) 68 | { 69 | table->print_message ("test jcc success!\n"); 70 | } 71 | if (1 <= 1) 72 | { 73 | table->print_message ("test jcc success!\n"); 74 | } 75 | if (1 > 0) 76 | { 77 | table->print_message ("test jcc success!\n"); 78 | } 79 | if (0 < 1) 80 | { 81 | table->print_message ("test jcc success!\n"); 82 | } 83 | } 84 | 85 | LARGE_INTEGER _frequency; 86 | void test_table (struct _function_table* table, const char* tbl) 87 | { 88 | LARGE_INTEGER from, to; 89 | 90 | QueryPerformanceCounter (&from); 91 | table->initialize (table); 92 | QueryPerformanceCounter (&to); 93 | 94 | double dur = (double)(to.QuadPart - from.QuadPart) * 1000.0 / (double)_frequency.QuadPart; 95 | 96 | printf_s ("table \"%s\" took %.2fms\n", tbl, dur); 97 | } 98 | 99 | int main () 100 | { 101 | srand (GetTickCount ()); 102 | QueryPerformanceFrequency (&_frequency); 103 | 104 | mutation_context_t* ctx_initialize = create_morpher (0x1000); 105 | ctx_initialize->original.address = (uintptr_t)_my_initialize; 106 | mutation_context_t* ctx_show_message = create_morpher (0x1000); 107 | ctx_show_message->original.address = (uintptr_t)_my_show_message; 108 | mutation_context_t* ctx_print_message = create_morpher (0x1000); 109 | ctx_print_message->original.address = (uintptr_t)_my_print_message; 110 | 111 | size_t size_initialize = prepare_mutations (ctx_initialize); 112 | size_t size_show_message = prepare_mutations (ctx_show_message); 113 | size_t size_print_message = prepare_mutations (ctx_print_message); 114 | 115 | size_t needed_size = 116 | size_initialize + 117 | size_show_message + 118 | size_print_message + 0x30; 119 | 120 | uintptr_t map_address = _my_virtual_alloc (needed_size); 121 | memset ((void*)map_address, 0x90, needed_size); 122 | 123 | printf_s ("sizeof _my_initialize %d bytes\n", size_initialize); 124 | printf_s ("sizeof _my_show_message %d bytes\n", size_show_message); 125 | printf_s ("sizeof _my_print_message %d bytes\n", size_print_message); 126 | printf_s ("code will be mapped at %p ( %d bytes )\n", (void*)map_address, needed_size); 127 | 128 | function_table_t mutated_table; 129 | mutated_table.initialize = post_mutations (ctx_initialize, map_address + 0x1); 130 | mutated_table.show_message = post_mutations (ctx_show_message, map_address + 0x1 + size_initialize); 131 | mutated_table.print_message = post_mutations (ctx_print_message, map_address + 0x1 + size_initialize + size_show_message); 132 | printf_s ("_my_initialize got mapped at %p\n", mutated_table.initialize); 133 | printf_s ("_my_show_message got mapped at %p\n", mutated_table.show_message); 134 | printf_s ("_my_print_message got mapped at %p\n", mutated_table.print_message); 135 | 136 | function_table_t orig_table; 137 | orig_table.initialize = _my_initialize; 138 | orig_table.show_message = _my_show_message; 139 | orig_table.print_message = _my_print_message; 140 | 141 | test_table (&orig_table, "original"); 142 | test_table (&mutated_table, "mutated"); 143 | 144 | dispose_morpher (ctx_initialize); 145 | dispose_morpher (ctx_show_message); 146 | dispose_morpher (ctx_print_message); 147 | 148 | _my_virtual_free (map_address, needed_size); 149 | 150 | while (1); 151 | 152 | return 0; 153 | } -------------------------------------------------------------------------------- /polymorph.c: -------------------------------------------------------------------------------- 1 | #include "polymorph.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include "ld32.h" 7 | 8 | #define _my_rnd_min 0x50 9 | #define _my_rnd_max 0x100 10 | #define _my_junk_min 0 11 | #define _my_junk_max 15 12 | 13 | typedef struct _instruction 14 | { 15 | uint8_t length; 16 | uint8_t* data; 17 | uint8_t* orig_addr; 18 | uint8_t* new_addr; 19 | }instruction_t; 20 | 21 | uint32_t _my_random (uint32_t begin, uint32_t end) 22 | { 23 | uint32_t range = (end - begin) + 1; 24 | uint32_t limit = (RAND_MAX + 1) - ((RAND_MAX + 1) % range); 25 | 26 | uint32_t randVal = rand (); 27 | while (randVal >= limit) randVal = rand (); 28 | 29 | return (randVal % range) + begin; 30 | } 31 | 32 | uint8_t* _my_malloc (size_t size) 33 | { 34 | uint8_t* ret = malloc (size + 10); 35 | memset (ret, 0, size); 36 | //printf_s ("_my_malloc\t%p (%d bytes)\n", ret, size); 37 | return ret; 38 | } 39 | 40 | void _my_free(uint8_t* addr) 41 | { 42 | //printf_s ("_my_free\t%p\n", addr); 43 | free (addr); 44 | } 45 | 46 | // ma (dis)assembler 47 | typedef enum _registerbase 48 | { 49 | rb_eax, 50 | rb_ecx, 51 | rb_edx, 52 | rb_ebx, 53 | rb_esp, 54 | rb_ebp, 55 | rb_esi, 56 | rb_edi, 57 | }regbase_t; 58 | typedef enum _modtype 59 | { 60 | mt_to_mem, 61 | mt_to_reg 62 | }modtype_t; 63 | typedef enum _valsize 64 | { 65 | vs_byte, 66 | vs_dword 67 | }valsize_t; 68 | typedef struct _opcode 69 | { 70 | union 71 | { 72 | struct 73 | { 74 | /* 75 | struct 76 | { 77 | // Optional Scaled Indexed Byte 78 | // if the instruction uses a scaled 79 | // indexed memory addressing mode 80 | uint8_t sib : 1; 81 | 82 | // This byte is only required 83 | // if the instruction supports 84 | // register or memory operands 85 | // 1 = add r/m to reg | 0 = add reg to r/m 86 | uint8_t rm : 1; 87 | 88 | // One or two byte instruction 89 | // opcode (two bytes if the special 90 | // 0x0F opcode expansion is present 91 | uint8_t opc : 2; 92 | 93 | // Prefix bytes, zero to four special 94 | // prefix values that affect the 95 | // operation of the instruction 96 | //uint8_t pb_sp : 1;// Segment override Prefix 97 | //uint8_t pb_op : 1;// Operand-size Prefix 98 | //uint8_t pb_ap : 1;// Address-size Prefix 99 | //uint8_t pb_ip : 1;// Instruction-size Prefix 100 | uint8_t pb; 101 | }primary; 102 | struct 103 | { 104 | // "Right Operand Indicator" 105 | uint8_t rm_rop : 3; 106 | 107 | // "Left Operand Indicator" 108 | uint8_t lop : 3; 109 | 110 | // Immediate (constant) data. 111 | // This is a zero, one, two, or 112 | // four byte constant value if the 113 | // instruction has an immediate operand 114 | uint8_t imm : 1; 115 | 116 | // Displacement. This is a zero 117 | // or one, two or four byte value 118 | // that specifies a memory address 119 | // displacement for the instruction 120 | uint8_t disp : 1; 121 | }secondary; 122 | */ 123 | 124 | // sub al 00101100 125 | // add al 00000100 126 | 127 | struct 128 | { 129 | uint8_t s : 1; 130 | uint8_t d : 1; 131 | uint8_t sib : 2; 132 | //uint8_t prefix : 4; 133 | uint8_t p4 : 1; 134 | uint8_t p3 : 1; 135 | uint8_t p2 : 1; 136 | uint8_t p1 : 1; 137 | }primary; 138 | 139 | struct 140 | { 141 | uint8_t rm : 3; 142 | uint8_t reg : 3; 143 | uint8_t mod : 2; 144 | }secondary; 145 | }; 146 | 147 | struct 148 | { 149 | uint8_t encoded_primary; 150 | uint8_t encoded_secondary; 151 | }; 152 | }; 153 | }opcode_t; 154 | typedef enum _jccbase 155 | { 156 | jb_jo, 157 | jb_jno, 158 | jb_jb, 159 | jb_jnb, 160 | jb_jz, 161 | jb_jnz, 162 | jb_jbe, 163 | jb_jna, 164 | jb_ja, 165 | jb_js, 166 | jb_jns, 167 | jb_jp, 168 | jb_jnp, 169 | jb_jl, 170 | jb_jle, 171 | jb_jg 172 | }jccbase_t; 173 | 174 | void add_instruction (mutation_context_t* context, const instruction_t* instruction) 175 | { 176 | memcpy ((instruction_t*)context->instruction_cache.data + context->instruction_cache.count, instruction, sizeof (instruction_t)); 177 | context->instruction_cache.count++; 178 | } 179 | 180 | void get_registers(uint8_t pack, regbase_t* left, regbase_t* right) 181 | { 182 | opcode_t opc; 183 | memset (&opc, 0, sizeof (opcode_t)); 184 | opc.encoded_secondary = pack; 185 | if (left) 186 | *left = opc.secondary.reg; 187 | if (right) 188 | *right = opc.secondary.rm; 189 | return opc.encoded_secondary; 190 | } 191 | uint8_t encode_registers(regbase_t left, regbase_t right) 192 | { 193 | opcode_t opc; 194 | memset (&opc, 0, sizeof (opcode_t)); 195 | opc.secondary.mod = 0xFF; 196 | opc.secondary.reg = left; 197 | opc.secondary.rm = right; 198 | return opc.encoded_secondary; 199 | } 200 | uint8_t encode_regdisp (regbase_t reg) 201 | { 202 | opcode_t op; 203 | op.secondary.mod = 0xFF; 204 | op.secondary.reg = reg; 205 | op.secondary.rm = 5; // 1 0 1 206 | return op.encoded_secondary; 207 | } 208 | 209 | uint32_t jmp_get_offset (uint32_t from, uint32_t to) 210 | { 211 | return to - from - 5; 212 | } 213 | uint32_t jmp_get_dst (uint32_t origin, uint32_t offset) 214 | { 215 | return origin + offset + 5; 216 | } 217 | 218 | // assembler functions 219 | void pushr (mutation_context_t* context, regbase_t regbase) 220 | { 221 | instruction_t instr; 222 | instr.orig_addr = 0; 223 | instr.data = _my_malloc (1); 224 | instr.length = 1; 225 | *instr.data = 0x50 + regbase; 226 | add_instruction (context, &instr); 227 | } 228 | void popr (mutation_context_t* context, regbase_t regbase) 229 | { 230 | instruction_t instr; 231 | instr.orig_addr = 0; 232 | instr.data = _my_malloc (1); 233 | *instr.data = 0x58 + regbase; 234 | instr.length = 1; 235 | add_instruction (context, &instr); 236 | } 237 | void push32 (mutation_context_t* context, uint32_t value) 238 | { 239 | instruction_t instr; 240 | instr.orig_addr = 0; 241 | instr.data = _my_malloc (5); 242 | instr.length = 5; 243 | *instr.data = 0x68; 244 | *(uint32_t*)(instr.data + 1) = value; 245 | add_instruction (context, &instr); 246 | } 247 | void jmp8 (mutation_context_t* context, uint8_t offset) 248 | { 249 | instruction_t instr; 250 | instr.orig_addr = 0; 251 | instr.data = _my_malloc (2); 252 | instr.length = 2; 253 | *instr.data = 0xEB; 254 | *(instr.data + 1) = offset; 255 | add_instruction (context, &instr); 256 | } 257 | void jmp32 (mutation_context_t* context, uint8_t* orig, uint32_t offset) 258 | { 259 | instruction_t instr; 260 | instr.orig_addr = orig; 261 | instr.data = _my_malloc (5); 262 | instr.length = 5; 263 | *instr.data = 0xE9; 264 | *(uint32_t*)(instr.data + 1) = offset; 265 | add_instruction (context, &instr); 266 | } 267 | void call32 (mutation_context_t* context, uint8_t* orig, uint32_t offset) 268 | { 269 | instruction_t instr; 270 | instr.orig_addr = orig; 271 | instr.data = _my_malloc (5); 272 | instr.length = 5; 273 | *instr.data = 0xE8; 274 | *(uint32_t*)(instr.data + 1) = offset; 275 | add_instruction (context, &instr); 276 | } 277 | void insert_random_data (mutation_context_t* context, uint8_t length) 278 | { 279 | instruction_t instr; 280 | instr.orig_addr = 0; 281 | instr.data = _my_malloc (length); 282 | instr.length = length; 283 | for (uint32_t i = 0; i < length; i++) 284 | *(instr.data + i) = _my_random (0, 255); 285 | add_instruction (context, &instr); 286 | } 287 | void jcc8 (mutation_context_t* context, uint8_t* orig, jccbase_t jccbase, uint8_t offset) 288 | { 289 | instruction_t instr; 290 | instr.orig_addr = orig; 291 | instr.data = _my_malloc (2); 292 | instr.length = 2; 293 | *instr.data = 0x70 + jccbase; 294 | *(instr.data + 1) = offset; 295 | add_instruction (context, &instr); 296 | } 297 | void jcc32 (mutation_context_t* context, uint8_t* orig, jccbase_t jccbase, uint32_t offset) 298 | { 299 | instruction_t instr; 300 | instr.orig_addr = orig; 301 | instr.data = _my_malloc (2); 302 | instr.length = 2; 303 | *(instr.data) = 0x0F; 304 | *(instr.data + 1) = 0x70 + 0x10 + jccbase; 305 | *(uint32_t *)(instr.data + 2) = offset; 306 | add_instruction (context, &instr); 307 | } 308 | void xorr (mutation_context_t* context, regbase_t left, regbase_t right) 309 | { 310 | instruction_t instr; 311 | instr.orig_addr = 0; 312 | instr.data = _my_malloc (2); 313 | *instr.data = 0x33; 314 | *(instr.data + 1) = encode_registers (left, right); 315 | instr.length = 2; 316 | add_instruction (context, &instr); 317 | } 318 | void andrd (mutation_context_t* context, regbase_t reg, uint32_t value) 319 | { 320 | instruction_t instr; 321 | instr.orig_addr = 0; 322 | instr.data = _my_malloc (5); 323 | *instr.data = 0x25; 324 | *(instr.data + 1) = encode_regdisp (reg); 325 | *(uint32_t*)(instr.data + 2) = value; 326 | instr.length = 5; 327 | add_instruction (context, &instr); 328 | } 329 | void copy_instr (mutation_context_t* context, uint32_t length, uint8_t* data) 330 | { 331 | instruction_t instr; 332 | instr.orig_addr = data; 333 | instr.data = _my_malloc (length); 334 | memcpy (instr.data, data, length); 335 | instr.length = length; 336 | add_instruction (context, &instr); 337 | } 338 | void pushfd (mutation_context_t* context) 339 | { 340 | instruction_t instr; 341 | instr.orig_addr = 0; 342 | instr.data = _my_malloc (1); 343 | instr.length = 1; 344 | *instr.data = 0x9C; 345 | add_instruction (context, &instr); 346 | } 347 | void popfd (mutation_context_t* context) 348 | { 349 | instruction_t instr; 350 | instr.orig_addr = 0; 351 | instr.data = _my_malloc (1); 352 | instr.length = 1; 353 | *instr.data = 0x9D; 354 | add_instruction (context, &instr); 355 | } 356 | void incr (mutation_context_t* context, regbase_t reg) 357 | { 358 | instruction_t instr; 359 | instr.orig_addr = 0; 360 | instr.data = _my_malloc (1); 361 | *instr.data = 0x40 + reg; 362 | instr.length = 1; 363 | add_instruction (context, &instr); 364 | } 365 | void decr (mutation_context_t* context, regbase_t reg) 366 | { 367 | instruction_t instr; 368 | instr.orig_addr = 0; 369 | instr.data = _my_malloc (1); 370 | *instr.data = 0x48 + reg; 371 | instr.length = 1; 372 | add_instruction (context, &instr); 373 | } 374 | void testrr (mutation_context_t* context, valsize_t valsize, regbase_t dst, regbase_t src) 375 | { 376 | instruction_t instr; 377 | instr.orig_addr = 0; 378 | instr.data = _my_malloc (2); 379 | opcode_t* opc = (opcode_t*)instr.data; 380 | opc->encoded_primary = 0x85; 381 | opc->primary.s = (uint8_t)valsize; 382 | opc->primary.d = 0; 383 | opc->secondary.mod = 0xFF; 384 | opc->secondary.rm = dst; 385 | opc->secondary.reg = src; 386 | 387 | instr.length = 2; 388 | add_instruction (context, &instr); 389 | } 390 | void addrr (mutation_context_t* context, valsize_t valsize, regbase_t dst, regbase_t src) 391 | { 392 | instruction_t instr; 393 | instr.orig_addr = 0; 394 | instr.data = _my_malloc (2); 395 | 396 | opcode_t* opc = (opcode_t*)instr.data; 397 | opc->encoded_primary = 0x00; 398 | opc->primary.s = (uint8_t)valsize; 399 | opc->primary.d = 0; 400 | opc->secondary.mod = 0xFF; 401 | opc->secondary.rm = dst; 402 | opc->secondary.reg = src; 403 | 404 | instr.length = 2; 405 | add_instruction (context, &instr); 406 | } 407 | void addrd (mutation_context_t* context, valsize_t valsize, regbase_t reg, uint32_t disp) 408 | { 409 | instruction_t instr; 410 | instr.orig_addr = 0; 411 | instr.length = valsize == vs_byte ? 3 : 6; 412 | instr.data = _my_malloc (instr.length); 413 | 414 | opcode_t* opc = (opcode_t*)instr.data; 415 | opc->encoded_primary = 0; 416 | opc->primary.s = (uint8_t)valsize; 417 | opc->primary.d = 0; 418 | opc->primary.p1 = 1; 419 | 420 | opc->secondary.mod = 0xFF; 421 | opc->secondary.reg = 0; 422 | opc->secondary.rm = reg; 423 | 424 | if (valsize == vs_byte) 425 | *(uint8_t*)(instr.data + 2) = (uint8_t)disp; 426 | else *(uint32_t*)(instr.data + 2) = (uint32_t)disp; 427 | 428 | add_instruction (context, &instr); 429 | } 430 | void subrr (mutation_context_t* context, valsize_t valsize, regbase_t dst, regbase_t src) 431 | { 432 | instruction_t instr; 433 | instr.orig_addr = 0; 434 | instr.data = _my_malloc (2); 435 | 436 | opcode_t* opc = (opcode_t*)instr.data; 437 | opc->encoded_primary = 0x29; 438 | opc->primary.s = (uint8_t)valsize; 439 | opc->primary.d = 0; 440 | opc->secondary.mod = 0xFF; 441 | opc->secondary.rm = dst; 442 | opc->secondary.reg = src; 443 | 444 | instr.length = 2; 445 | add_instruction (context, &instr); 446 | } 447 | void subrd (mutation_context_t* context, valsize_t valsize, regbase_t reg, uint32_t disp) 448 | { 449 | instruction_t instr; 450 | instr.orig_addr = 0; 451 | instr.length = valsize == vs_byte ? 3 : 6; 452 | instr.data = _my_malloc (instr.length); 453 | 454 | opcode_t* opc = (opcode_t*)instr.data; 455 | opc->encoded_primary = 0; 456 | opc->primary.s = (uint8_t)valsize; 457 | opc->primary.d = 0; 458 | opc->primary.p1 = 1; 459 | 460 | opc->secondary.mod = 0xFF; 461 | opc->secondary.reg = 5; 462 | opc->secondary.rm = reg; 463 | 464 | // sub EA 11101010 465 | // add C2 11000010 466 | 467 | if (valsize == vs_byte) 468 | *(uint8_t*)(instr.data + 2) = (uint8_t)disp; 469 | else *(uint32_t*)(instr.data + 2) = (uint32_t)disp; 470 | 471 | add_instruction (context, &instr); 472 | } 473 | 474 | uint8_t* get_function_end(uint8_t* start_address, size_t* instruction_count) 475 | { 476 | *instruction_count = 0; 477 | uint8_t* highest_code_point = start_address; 478 | while (1) 479 | { 480 | size_t length = get_instruction_length (start_address); 481 | 482 | if (highest_code_point > start_address) 483 | highest_code_point = start_address; 484 | 485 | uint8_t* new_code_point = 0; 486 | if (*start_address >= 0x70 && *start_address <= 0x7F) // convert it to 32 bit jump 487 | { 488 | int8_t offset = *(start_address + 1); 489 | new_code_point = get_function_end (start_address + offset, instruction_count); 490 | } 491 | else if (*start_address == 0xEB) 492 | { 493 | int8_t offset = *(start_address + 1); 494 | new_code_point = get_function_end (start_address + offset, instruction_count); 495 | } 496 | else if (*start_address == 0xE9) 497 | { 498 | uint32_t offset = *(start_address + 2); 499 | new_code_point = get_function_end ((uint8_t*)jmp_get_dst ((uint32_t)start_address + 1, offset), instruction_count); 500 | } 501 | else if (*start_address == 0x0F && *(start_address + 1) >= 0x80 && *(start_address + 1) <= 0x8F) 502 | { 503 | uint32_t offset = *(start_address + 2); 504 | new_code_point = get_function_end ((uint8_t*)jmp_get_dst ((uint32_t)start_address + 1, offset), instruction_count); 505 | } 506 | 507 | if (new_code_point > highest_code_point) 508 | highest_code_point = new_code_point; 509 | 510 | *(instruction_count) = *(instruction_count)+1; 511 | 512 | if(*start_address == 0xC2 || 513 | *start_address == 0xC3 || 514 | *start_address == 0xCA || 515 | *start_address == 0xCB) 516 | { 517 | if (start_address + length > highest_code_point) 518 | highest_code_point = start_address + length; 519 | break; 520 | } 521 | 522 | start_address += length; 523 | } 524 | return highest_code_point; 525 | } 526 | 527 | // mutation and that stuff.. 528 | regbase_t random_reg (void) 529 | { 530 | regbase_t ret = _my_random (0, 7); 531 | while(ret == rb_ebp || ret == rb_esp) 532 | ret = _my_random (0, 7); 533 | return ret; 534 | } 535 | void random_set_reg (mutation_context_t* context, regbase_t reg, uint32_t value) 536 | { 537 | uint8_t type = _my_random (0, 3); 538 | 539 | push32 (context, value); 540 | popr (context, reg); 541 | return; 542 | if(type == 0) 543 | { 544 | // wooo spammin like shit :) 545 | regbase_t rl; 546 | if (reg == rb_eax) 547 | rl = rb_ecx; 548 | else rl = reg - 1; 549 | pushr (context, rl); 550 | 551 | uint32_t xw = _my_random (_my_rnd_min, _my_rnd_max); 552 | push32 (context, value ^ xw); 553 | popr (context, reg); 554 | 555 | pushr (context, xw); 556 | popr (context, rl); 557 | 558 | xorr (context, rl, reg); 559 | pushr (context, rl); 560 | popr (context, reg); 561 | 562 | popr (context, rl); 563 | } 564 | else if(type == 1) 565 | { 566 | push32 (context, value); 567 | popr (context, reg); 568 | } 569 | else 570 | { 571 | // wooo spammin like shit :) 572 | regbase_t rl; 573 | if (reg == rb_eax) 574 | rl = rb_ecx; 575 | else rl = reg - 1; 576 | pushr (context, rl); 577 | 578 | uint32_t xw = _my_random (_my_rnd_min, _my_rnd_max); 579 | push32 (context, value ^ xw); 580 | popr (context, reg); 581 | 582 | pushr (context, xw); 583 | popr (context, rl); 584 | 585 | xorr (context, reg, rl); 586 | 587 | popr (context, rl); 588 | } 589 | } 590 | void random_add_reg (mutation_context_t* context, regbase_t reg, uint32_t value, uint8_t runs) 591 | { 592 | uint32_t added = 0; 593 | uint32_t step_total = _my_random (1, value + 0x50); 594 | for (size_t i = 0; i < runs; i++) 595 | { 596 | uint8_t add = step_total / runs; 597 | addrd (context, vs_dword, reg, add); 598 | added += add; 599 | } 600 | if(added > value) 601 | { 602 | subrd (context, vs_dword, reg, added - value); 603 | } 604 | else 605 | { 606 | addrd (context, vs_dword, reg, value - added); 607 | } 608 | } 609 | void random_sub_reg (mutation_context_t* context, regbase_t reg, uint32_t value, uint8_t runs) 610 | { 611 | uint32_t subtracted = 0; 612 | uint32_t step_total = _my_random (1, value + 0x50); 613 | for (size_t i = 0; i < runs; i++) 614 | { 615 | uint8_t add = step_total / runs; 616 | subrd (context, vs_dword, reg, add); 617 | subtracted += add; 618 | } 619 | if (subtracted > value) 620 | { 621 | addrd (context, vs_dword, reg, subtracted - value); 622 | } 623 | else 624 | { 625 | subrd (context, vs_dword, reg, value - subtracted); 626 | } 627 | } 628 | 629 | typedef struct _rjjc8r_t 630 | { 631 | mutation_context_t* ctx; 632 | uint8_t num_regs; 633 | regbase_t* regs; 634 | }rjjc8r_t; 635 | void ref_reg (rjjc8r_t* ref, regbase_t reg) 636 | { 637 | if(ref->regs == 0) 638 | ref->regs = (regbase_t*)_my_malloc (sizeof(regbase_t) * 10); 639 | ref->num_regs++; 640 | *(ref->regs + ref->num_regs - 1) = reg; 641 | pushr (ref->ctx, reg); 642 | } 643 | void begin_random_jcc8 (uint8_t offset, rjjc8r_t* storage) 644 | { 645 | jccbase_t type = jb_jl;// _my_random (0, jb_jg); 646 | 647 | uint32_t value; 648 | regbase_t left; 649 | regbase_t right; 650 | 651 | switch (type) 652 | { 653 | default: 654 | // 2lazy2implement 655 | jmp8 (storage->ctx, offset); 656 | break; 657 | 658 | case jb_jl: 659 | left = random_reg (); 660 | right = random_reg (); 661 | while (right == left) 662 | right = random_reg (); 663 | ref_reg (storage, left); 664 | ref_reg (storage, right); 665 | value = _my_random (_my_rnd_min, _my_rnd_max); 666 | random_set_reg (storage->ctx, left, value); 667 | random_set_reg (storage->ctx, right, value + _my_random (1, 0x40)); 668 | testrr (storage->ctx, vs_dword, left, right); 669 | jcc8 (storage->ctx, 0, jb_jl, offset); 670 | break; 671 | 672 | case jb_jnb: 673 | left = random_reg (); 674 | right = random_reg (); 675 | while (right == left) 676 | right = random_reg (); 677 | ref_reg (storage, left); 678 | ref_reg (storage, right); 679 | value = _my_random (_my_rnd_min, _my_rnd_max); 680 | random_set_reg (storage->ctx, left, value); 681 | random_set_reg (storage->ctx, right, value - _my_random (1, 0x40)); 682 | testrr (storage->ctx, vs_dword, left, right); 683 | jcc8 (storage->ctx, 0, jb_jnb, offset); 684 | break; 685 | 686 | case jb_jz: 687 | left = random_reg (); 688 | right = random_reg (); 689 | ref_reg (storage, left); 690 | ref_reg (storage, right); 691 | while (right == left) 692 | right = random_reg (); 693 | value = _my_random (_my_rnd_min, _my_rnd_max); 694 | random_set_reg (storage->ctx, left, value); 695 | random_set_reg (storage->ctx, right, value); 696 | testrr (storage->ctx, vs_dword, left, right); 697 | jcc8 (storage->ctx, 0, jb_jz, offset); 698 | break; 699 | case jb_jnz: 700 | left = random_reg (); 701 | right = random_reg (); 702 | while (right == left) 703 | right = random_reg (); 704 | ref_reg (storage, left); 705 | ref_reg (storage, right); 706 | value = _my_random (_my_rnd_min, _my_rnd_max); 707 | random_set_reg (storage->ctx, left, value); 708 | random_set_reg (storage->ctx, right, !value); 709 | testrr (storage->ctx, vs_dword, left, right); 710 | jcc8 (storage->ctx, 0, jb_jnz, offset); 711 | break; 712 | case jb_jna: 713 | case jb_jbe: 714 | left = random_reg (); 715 | right = random_reg (); 716 | while (right == left) 717 | right = random_reg (); 718 | ref_reg (storage, left); 719 | ref_reg (storage, right); 720 | value = _my_random (_my_rnd_min, _my_rnd_max); 721 | random_set_reg (storage->ctx, left, value); 722 | random_set_reg (storage->ctx, right, value - _my_random (0, 0x40)); 723 | testrr (storage->ctx, vs_dword, left, right); 724 | jcc8 (storage->ctx, 0, jb_jbe, offset); 725 | break; 726 | case jb_ja: 727 | left = random_reg (); 728 | right = random_reg (); 729 | while (right == left) 730 | right = random_reg (); 731 | ref_reg (storage, left); 732 | ref_reg (storage, right); 733 | value = _my_random (_my_rnd_min, _my_rnd_max); 734 | random_set_reg (storage->ctx, left, value); 735 | random_set_reg (storage->ctx, right, value - _my_random (1, 0x40)); 736 | testrr (storage->ctx, vs_dword, left, right); 737 | jcc8 (storage->ctx, 0, jb_ja, offset); 738 | break; 739 | } 740 | } 741 | void end_random_jcc8 (rjjc8r_t* storage) 742 | { 743 | if(storage->num_regs > 0) 744 | { 745 | for (size_t n = 0; n < storage->num_regs; n++) 746 | { 747 | size_t inv = (storage->num_regs - 1) - n; 748 | popr (storage->ctx, *(storage->regs + inv)); 749 | } 750 | _my_free ((uint8_t*)storage->regs); 751 | } 752 | } 753 | 754 | void insert_junkcode(mutation_context_t* context) 755 | { 756 | // insert some junk 757 | uint32_t junk = _my_random (_my_junk_min, _my_junk_max); 758 | if (junk > 0) 759 | { 760 | pushfd (context); 761 | rjjc8r_t random_jump; 762 | memset (&random_jump, 0, sizeof (rjjc8r_t)); 763 | random_jump.ctx = context; 764 | if(_my_random(0,1) == 1) 765 | { 766 | uint8_t* opcodes = _my_malloc(junk); 767 | uint32_t* lengths = _my_malloc(sizeof(uint32_t)*junk); 768 | 769 | size_t length = 0; 770 | 771 | size_t n; 772 | for (n = 0; n < junk; n++) 773 | { 774 | opcode_t opc; 775 | opc.encoded_primary = _my_random (0, 255); 776 | opc.encoded_secondary = 0; 777 | opc.primary.d = mt_to_reg; 778 | opc.primary.sib = 0; 779 | opc.primary.s = vs_byte; 780 | 781 | *(opcodes + n) = opc.encoded_primary; 782 | 783 | uint32_t len = get_instruction_length (&opc); 784 | *(lengths + n) = len; 785 | length += len; 786 | } 787 | 788 | begin_random_jcc8 ((uint8_t)length, &random_jump); 789 | for (n = 0; n < junk; n++) 790 | { 791 | instruction_t instr; 792 | 793 | instr.length = *(lengths + n); 794 | 795 | instr.data = _my_malloc (instr.length); 796 | memset (instr.data, 0, instr.length); 797 | *instr.data = *(opcodes + n); 798 | 799 | add_instruction (context, &instr); 800 | } 801 | end_random_jcc8 (&random_jump); 802 | 803 | _my_free (opcodes); 804 | _my_free ((uint8_t*)lengths); 805 | } 806 | else 807 | { 808 | begin_random_jcc8 (junk, &random_jump); 809 | instruction_t instr; 810 | instr.length = junk; 811 | instr.data = _my_malloc (junk); 812 | for (size_t n = 0; n < junk; n++) 813 | *(instr.data + n) = _my_random (0, 255); 814 | add_instruction (context, &instr); 815 | end_random_jcc8 (&random_jump); 816 | } 817 | popfd (context); 818 | } 819 | } 820 | 821 | size_t prepare_mutations (mutation_context_t * context) 822 | { 823 | size_t pos; 824 | size_t instructions; 825 | uint8_t* data = (uint8_t*)context->original.address; 826 | 827 | if (context->original.length == 0) 828 | context->original.length = (uint32_t)(get_function_end (data, &instructions) - data); 829 | 830 | for (pos = 0; pos < instructions; pos++) 831 | { 832 | uint32_t length = get_instruction_length (data); 833 | 834 | // insert some junk 835 | insert_junkcode (context); 836 | 837 | if (*data == 0x33) // mutate xor eax, eax 838 | { 839 | regbase_t left; 840 | regbase_t right; 841 | get_registers (*(data + 1), &left, &right); 842 | if (left == right) // the register is being set to 0, lets change it to a basically equavilent operation 843 | random_set_reg (context, left, 0); 844 | else copy_instr (context, length, data); 845 | } 846 | else if (*data >= 0x70 && *data <= 0x7F) // convert it to 32 bit jump, store the destination in the offset bytes 847 | { 848 | int8_t offset = *(data + 1); 849 | jcc32 (context, data, *data - 0x70, data + offset); 850 | } 851 | else if (*data == 0xEB) // convert it to 32 bit jump, store the destination in the offset bytes 852 | { 853 | int8_t offset = *(data + 1); 854 | jmp32 (context, data, (uint32_t)(data + offset)); 855 | } 856 | else if (*data == 0xE8) // prepare jump for fix, store the destination in the offset bytes 857 | { 858 | uint32_t offset = *(uint32_t*)(data + 1); 859 | call32 (context, data, jmp_get_dst (data, offset)); 860 | } 861 | else if (*data == 0xE9) // prepare jump for fix, store the destination in the offset bytes 862 | { 863 | uint32_t offset = *(uint32_t*)(data + 1); 864 | jmp32 (context, data, jmp_get_dst (data, offset)); 865 | } 866 | else if (*data == 0x0F && *(data + 1) >= 0x80 && *(data + 1) <= 0x8F) // prepare jump for fix, store the destination in the offset bytes 867 | { 868 | uint32_t offset = *(uint32_t*)(data + 1); 869 | jcc32 (context, data, *(data + 1) - 0x80, jmp_get_dst (data + 1, offset)); 870 | } 871 | else copy_instr (context, length, data); 872 | 873 | data += length; 874 | } 875 | 876 | size_t size = 0; 877 | for (pos = 0; pos < context->instruction_cache.count; pos++) 878 | size += ((instruction_t*)context->instruction_cache.data + pos)->length; 879 | 880 | return size; 881 | } 882 | 883 | uintptr_t post_mutations (mutation_context_t * context, uintptr_t map_address) 884 | { 885 | size_t pos; 886 | 887 | uint8_t* data = (uint8_t*)map_address; 888 | 889 | // insert the mutated instructions 890 | for (pos = 0; pos < context->instruction_cache.count; pos++) 891 | { 892 | instruction_t* instr = ((instruction_t*)context->instruction_cache.data + pos); 893 | instr->new_addr = data; 894 | memcpy (data, instr->data, instr->length); 895 | data += instr->length; 896 | } 897 | 898 | // fix all mutated instructions 899 | for (pos = 0; pos < context->instruction_cache.count; pos++) 900 | { 901 | instruction_t* instr = ((instruction_t*)context->instruction_cache.data + pos); 902 | 903 | uint8_t opc = *instr->data; 904 | uint8_t opc2 = *(instr->data + 1); 905 | 906 | if (opc == 0xE8 || // call 907 | opc == 0xE9 || // jump 908 | (opc == 0x0F && opc2 >= 0x80 && opc2 <= 0x8F) // conditional jump 909 | ) 910 | { 911 | uint32_t* offset = instr->new_addr + 1; 912 | 913 | if (opc == 0x0F) 914 | offset = (uint8_t*)offset + 1; 915 | 916 | *offset = jmp_get_offset (instr->new_addr, *offset); 917 | } 918 | 919 | _my_free (instr->data); 920 | 921 | data += instr->length; 922 | } 923 | 924 | return map_address; 925 | } 926 | 927 | void dispose_original (mutation_context_t * context, set_is_writable_t set_is_writable, restore_mprot_t restore_mprot) 928 | { 929 | uint32_t flags; 930 | set_is_writable (context->original.address, context->original.length, &flags); 931 | memset (context->original.address, 0x90, context->original.length); 932 | restore_mprot (context->original.address, context->original.length, flags); 933 | } 934 | 935 | mutation_context_t* create_morpher (uint32_t max_instructions) 936 | { 937 | mutation_context_t* ctx = _my_malloc (sizeof (mutation_context_t)); 938 | ctx->instruction_cache.data = _my_malloc (sizeof (instruction_t) * max_instructions); 939 | ctx->instruction_cache.count = 0; 940 | return ctx; 941 | } 942 | 943 | void dispose_morpher (mutation_context_t * context) 944 | { 945 | _my_free (context->instruction_cache.data); 946 | _my_free (context); 947 | } 948 | -------------------------------------------------------------------------------- /polymorph.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPOLYMORPHER__POLYMORPH_H 2 | #define MYPOLYMORPHER__POLYMORPH_H 3 | 4 | #include 5 | 6 | typedef struct _mutation_context 7 | { 8 | struct 9 | { 10 | uintptr_t address; 11 | size_t length; 12 | }original; 13 | 14 | struct 15 | { 16 | void* data; 17 | size_t count; 18 | }instruction_cache; 19 | 20 | }mutation_context_t; 21 | 22 | typedef void (*set_is_writable_t) (uintptr_t address, size_t length, uint32_t* old_flags); 23 | typedef void (*restore_mprot_t) (uintptr_t address, size_t length, uint32_t flags); 24 | 25 | //size_t morph_function (uintptr_t original, size_t instructions, uintptr_t map_address); 26 | 27 | size_t prepare_mutations (mutation_context_t* context); 28 | uintptr_t post_mutations (mutation_context_t * context, uintptr_t map_address); 29 | void dispose_original (mutation_context_t* context, set_is_writable_t set_is_writable, restore_mprot_t restore_mprot); 30 | 31 | mutation_context_t* create_morpher (uint32_t max_instructions); 32 | void dispose_morpher (mutation_context_t* context); 33 | 34 | #endif // !MYPOLYMORPHER__POLYMORPH_H --------------------------------------------------------------------------------