summaryrefslogtreecommitdiff
path: root/other/burneye2/morph.c
diff options
context:
space:
mode:
authorRoot THC2026-02-24 12:42:47 +0000
committerRoot THC2026-02-24 12:42:47 +0000
commitc9cbeced5b3f2bdd7407e29c0811e65954132540 (patch)
treeaefc355416b561111819de159ccbd86c3004cf88 /other/burneye2/morph.c
parent073fe4bf9fca6bf40cef2886d75df832ef4b6fca (diff)
initial
Diffstat (limited to 'other/burneye2/morph.c')
-rw-r--r--other/burneye2/morph.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/other/burneye2/morph.c b/other/burneye2/morph.c
new file mode 100644
index 0000000..3fcc71c
--- /dev/null
+++ b/other/burneye2/morph.c
@@ -0,0 +1,324 @@
1/* morph.c - burneye code morphing functionality
2 *
3 * by scut
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <assert.h>
9
10#include <common.h>
11#include <ia32-decode.h>
12#include <ia32-function.h>
13#include <morph.h>
14
15
16/*** static prototypes
17 */
18
19static void
20morph_br_fix_front (morph *mr, ia32_function *func, ia32_bblock *br);
21
22static void
23morph_br_fix_inst (ia32_function *func, ia32_bblock *br, int endbr_num);
24
25static int
26morph_func_sort_2 (void *e1, void *e2);
27
28static int
29morph_br_sort_2 (void *e1, void *e2);
30
31
32/*** implementation
33 */
34
35unsigned int
36morph_abstract (morph *mr)
37{
38 unsigned int n;
39 unsigned int newsize,
40 allsize = 0;
41 unsigned char * newdata;
42
43
44 for (n = 0 ; n < mr->flist_count ; ++n) {
45 newsize = mr->flist[n]->end - mr->flist[n]->start;
46
47 newdata = xcalloc (1, newsize);
48 memcpy (newdata, mr->flist[n]->mem, newsize);
49 mr->flist[n]->mem = newdata;
50
51 allsize += newsize;
52 }
53
54 return (allsize);
55}
56
57
58void
59morph_br_extend (morph *mr, int len)
60{
61 unsigned int n, /* temporary index */
62 bn, /* bblock index into bblock array (pivot) */
63 fn; /* function index into array (pivot) */
64 ia32_function * func; /* function that contains the morphed bblock */
65 ia32_bblock ** brl; /* bblock list of function, brl_count items */
66 unsigned int brl_count;
67
68
69 if (len == 0)
70 return;
71
72 morph_func_sort (mr);
73 assert (mr->flist_count < 2 || mr->flist[0]->start <= mr->flist[1]->start);
74
75 for (fn = 0 ; fn < mr->flist_count &&
76 ia32_trace_range (mr->flist[fn]->start, mr->flist[fn]->end,
77 mr->bblock->start) == 0 ; ++fn)
78 ;
79 assert (fn < mr->flist_count);
80
81 /* now we have located the function the bblock-extension is occuring
82 * in, lets get all bblockes and find the modified one
83 */
84 func = mr->flist[fn];
85 brl = ia32_br_get_all (func->br_root, &brl_count);
86 morph_br_sort (brl, brl_count);
87
88 for (bn = 0 ; bn < brl_count && ia32_trace_range (brl[bn]->start,
89 brl[bn]->end, mr->bblock->start) == 0 ; ++bn)
90 ;
91 assert (bn < brl_count);
92
93 /* extend current bblock, zero extended space and then move all
94 * bblockes that come after it
95 */
96 if (len > 0)
97 func->mem = xrealloc (func->mem,
98 func->end - func->start + len);
99
100 memmove (&func->mem[mr->bblock->end - func->start + len],
101 &func->mem[mr->bblock->end - func->start],
102 func->end - mr->bblock->end);
103
104 if (len > 0)
105 memset (&func->mem[mr->bblock->end - func->start],
106 0x90, len);
107
108
109 mr->bblock->end += len;
110 assert (mr->bblock->start < mr->bblock->end);
111 mr->bblock->last_unused = len;
112
113 for (n = bn + 1 ; n < brl_count ; ++n) {
114 brl[n]->start += len;
115 brl[n]->end += len;
116 }
117
118 /* the bblockes are relocated for now, but still dangle by instruction.
119 * first move all following functions, then fixup first the bblockes,
120 * then all functions.
121 */
122 for (n = fn + 1 ; n < mr->flist_count ; ++n) {
123 mr->flist[n]->start += len;
124 mr->flist[n]->end += len;
125 }
126
127 morph_br_fix (mr, func);
128/*FIXME morph_func_fix (mr); */
129
130 free (brl);
131
132 return;
133}
134
135
136void
137morph_br_fix (morph *mr, ia32_function *func)
138{
139 unsigned int n,
140 bn;
141 ia32_bblock ** brl; /* bblock list of function, brl_count items */
142 unsigned int brl_count;
143
144
145 brl = ia32_br_get_all (func->br_root, &brl_count);
146 morph_br_sort (brl, brl_count);
147
148 for (bn = 0 ; bn < brl_count && ia32_trace_range (brl[bn]->start,
149 brl[bn]->end, mr->bblock->start) == 0 ; ++bn)
150 ;
151 assert (bn < brl_count);
152
153 for (n = 0 ; n < brl_count ; ++n) {
154 if (n == bn && brl[bn]->last_unused < 0) {
155 fprintf (stderr, "cannot fix last instruction, negative dangling\n");
156 continue;
157 }
158
159 morph_br_fix_front (mr, func, brl[n]);
160 }
161}
162
163
164static void
165morph_br_fix_front (morph *mr, ia32_function *func, ia32_bblock *br)
166{
167 switch (br->endtype) {
168 case (BR_END_IF):
169 morph_br_fix_inst (func, br, 1);
170 break;
171
172 case (BR_END_TRANSFER):
173 morph_br_fix_inst (func, br, 0);
174 break;
175
176 /* cases we can safely ignore
177 * BR_END_IF_INTER we can ignore because the control flow change
178 * happens to another function, not at bblock level
179 */
180 case (BR_END_RET):
181 case (BR_END_PASS):
182 case (BR_END_CALL):
183 case (BR_END_FUNCPTR_CALL):
184 case (BR_END_FUNCPTR_JUMP):
185 case (BR_END_IF_INTER):
186 case (BR_END_TRANSFER_INTER):
187 case (BR_END_UNPREDICT):
188 case (BR_END_CTRL_SYSCALL):
189 case (BR_END_CTRL_SYSCALL_END):
190 default:
191 break;
192 }
193}
194
195
196static void
197morph_br_fix_inst (ia32_function *func, ia32_bblock *br, int endbr_num)
198{
199 unsigned char * dest;
200 unsigned int vaddr_inst;
201 unsigned int daddr_current,
202 daddr_correct;
203 ia32_instruction * inst,
204 inst_s;
205 unsigned int displ_relofs,
206 displ_size;
207 int displ_new;
208
209
210 vaddr_inst = br->end - br->last_unused - br->last_ilen;
211 dest = &func->mem[vaddr_inst - func->start];
212 inst = ia32_decode_instruction (dest, &inst_s);
213 assert (inst != NULL);
214
215 daddr_current = ia32_trace_control (inst, dest, vaddr_inst, NULL,
216 NULL);
217 daddr_correct = br->endbr[endbr_num]->start;
218
219 if (daddr_current == daddr_correct)
220 return;
221
222 fprintf (stderr, "_fix_inst: instruction at 0x%08x\n"
223 "\tdestaddr current = 0x%08x\n"
224 "\tdestaddr correct = 0x%08x\n"
225 "\tbblock unused = 0x%08x\n",
226 vaddr_inst, daddr_current, daddr_correct, br->last_unused);
227
228 /* get the position and size of the displacement, then adjust it
229 * in-place
230 */
231 displ_relofs = ia32_has_displacement (inst, &displ_size);
232 assert (displ_relofs != 0);
233
234 fprintf (stderr, "\t%d bit displacement at: 0x%08x + %d\n",
235 displ_size, vaddr_inst, displ_relofs);
236
237 displ_new = daddr_correct;
238 displ_new -= vaddr_inst + inst->length;
239 fprintf (stderr, "\told displacement: 0x%08x\n"
240 "\tnew displacement: 0x%08x\n",
241 inst->opc.displ_value, displ_new);
242
243 assert (morph_displ_boundcheck (displ_new, displ_size) == 0);
244 ia32_encode_value (dest + displ_relofs, displ_size, displ_new);
245
246 return;
247}
248
249
250int
251morph_displ_boundcheck (int displ_val, unsigned int displ_size)
252{
253 int bytes;
254 int valid_up[] = { 0, 0x7f, 0x7fff, 0, 0x7fffffff };
255 int valid_down[] = { 0, -0x80, -0x8000, 0, -0x80000000 };
256
257
258 bytes = ia32_bit_to_byte (displ_size);
259
260 if (displ_val > valid_up[bytes])
261 return (1);
262
263 if (displ_val < valid_down[bytes])
264 return (1);
265
266 return (0);
267}
268
269
270void
271morph_func_fix (morph *mr)
272{
273}
274
275
276void
277morph_func_sort (morph *mr)
278{
279 qsort (mr->flist, mr->flist_count, sizeof (mr->flist[0]),
280 (int (*)(const void *,const void*)) morph_func_sort_2);
281}
282
283
284static int
285morph_func_sort_2 (void *e1, void *e2)
286{
287 ia32_function * f1 = *((ia32_function **) e1);
288 ia32_function * f2 = *((ia32_function **) e2);
289
290
291 if (f1->start == f2->start)
292 return (0);
293
294 if (f1->start < f2->start)
295 return (-1);
296
297 return (1);
298}
299
300
301void
302morph_br_sort (ia32_bblock **brlist, unsigned int br_len)
303{
304 qsort (brlist, br_len, sizeof (brlist[0]),
305 (int (*)(const void *, const void *)) morph_br_sort_2);
306}
307
308
309static int
310morph_br_sort_2 (void *e1, void *e2)
311{
312 ia32_bblock * b1 = *((ia32_bblock **) e1);
313 ia32_bblock * b2 = *((ia32_bblock **) e2);
314
315
316 if (b1->start == b2->start)
317 return (0);
318
319 if (b1->start < b2->start)
320 return (-1);
321
322 return (1);
323}
324