├── .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
--------------------------------------------------------------------------------