1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
/* objwriter.c - ELF relocateable/relinkable object file writing code
* include file
*
* by scut / teso
*/
#ifndef OBJWRITER_H
#define OBJWRITER_H
#include <elf/elf_base.h>
#include <ia32/ia32-function.h>
/* parameters passing structure used when doing obfuscation. will grow over
* time.
*/
typedef struct {
/* entangle_basic = flag, when set, basic blocks of functions are
* randomized in order, thus making the functions overlapping. will
* break basic cfg analysis for code which is suspected to be compiler
* generated. the cfg's are not merged though, and are easily
* seperateable with a more hostile-orientied cfg analysis.
*/
unsigned int entangle_basic;
/* insert junk instructions between instructions
* junk_rate is the instruction spill rate.
*/
unsigned int junk_instructions;
double junk_rate;
/* if non-zero, junk instructions are marked by prepending a nop
* before each one
*/
unsigned int junk_debug;
/* if non-zero, random basic block splitting will be done
*/
unsigned int split_blocks;
/* if 'split_blocks' is non-zero, this factor gives the rate at which
* splitting will be done for each split step. it is in the range of
* 0.0 to 1.0, where 0.0 means no blocks will be split and 1.0 means
* every block will be split.
*/
double split_factor;
/* for every split a coin with probability 'split_opaque_cond_copy' is
* thrown. if it hits, the rest of the otherwise splitted basic block
* is duplicated and a random conditional jump is inserted.
*/
int split_opaque_cond_copy_set;
double split_opaque_cond_copy;
/* for every basic block the number of possible instruction swaps are
* considered if 'instruction_swap' is non-zero. then, of all possible
* swaps, 'instruction_swap_rate' exchanges are performed.
*/
int instruction_swap;
double instruction_swap_rate;
} obfuscation_param;
/* obj_write
*
* create a new ELF object file. the center of this operation is the correct
* writeout of the functions listed in `flist' (and only those will be written
* out). also the data segments, given through `base', will be written out. a
* minimal but working symbol table is created. this is intended for small
* link-time objects only, not for entire self-contained binary-like objects.
* the file will be created as `filename'.
*
* return 0 in case of success
* return non-zero in case of failure
*/
int
obj_write (char *filename, elf_base *base,
ia32_function **flist, unsigned int flist_count,
obfuscation_param *obf);
/* obj_bblist_build
*
* build a list of all basic blocks for all functions in `flist'. return the
* size of the created list through `count'.
*
* return the list on success
* return NULL on failure
*/
ia32_bblock **
obj_bblist_build (ia32_function **flist, unsigned int flist_count,
unsigned int *count);
/* obj_write_func
*
* write a single broken up function `func' to the file `fp'. use `base' as
* helper information. note that we clobber stuff in both the function header
* and the basic block headers. `code_sec_start' is the absolute file position
* this code section starts at.
*
* return zero on success
* return non-zero on failure
*/
int
obj_write_func (FILE *fp, elf_base *base, ia32_function *func,
unsigned int code_sec_start);
/* obj_flist_memlift
*
* lift all basic blocks in all functions `flist', which is `flist_count'
* items long. this allocates memory for all basic blocks, so they can be
* freely moved.
*
* return in any case
*/
void
obj_flist_memlift (ia32_function **flist, unsigned int flist_count);
/* obj_write_funclist
*
* pedant to obj_write_func, but for multiple functions. this function
* streamlines all the functions mentioned in `flist', with the basic block
* order randomized. `flist' is `flist_count' items long. also, the symbol
* entry for each function will be set to the correct function entry point,
* but with a zero size, as there are no clear function borders anymore.
* the functions are written to `fp'. the current position of `fp' within the
* current code section is given by `code_sec_start'.
*
* return zero on success
* return non-zero on failure
*/
int
obj_write_funclist (FILE *fp, elf_base *base, ia32_function **flist,
unsigned int flist_count, unsigned int code_sec_start,
obfuscation_param *obf);
/* obj_bblock_copy_reloc
*
* copy all other_xref relocations of basic block `bb' over to a new array.
*
* return the new array on success
* return NULL if there was nothing to copy
*/
ia32_xref **
obj_bblock_copy_reloc (ia32_bblock *bb);
/* obj_bblock_split_reloc
*
* if `bb1' was just shortened and still holds relocation information
* belonging to `bb2', the relocations are distributed among `bb1' and `bb2'.
*
* return in any case
*/
void
obj_bblock_split_reloc (ia32_bblock *bb1, ia32_bblock *bb2);
/* obj_bblock_move_reloc
*
* move all relocations of the basic block `bb' that lie inbetween `i_start'
* and `i_start' + `i_len' by `move_offset' bytes to the left/right. if
* `dont_touch' is non-NULL, an integer boolean like array is kept and
* relocations with non-zero at their index in the bb->other_xref array will
* be ignored. a non-zero value will be stored in the array for each
* relocation moved.
*
* return in any case
*/
void
obj_bblock_move_reloc (ia32_bblock *bb, unsigned int i_start,
unsigned int i_len, int move_offset, int *dont_touch);
/* obj_func_find_syment
*
* find the symbol table entry of function `func' within the elf object
* `base'.
*
* return the direct in-section-memory pointer to the matching symbol table
* entry.
*/
Elf32_Sym *
obj_func_find_syment (elf_base *base, ia32_function *func);
/* obj_ia32_instruction_expand
*
* grow the displacement part of the instruction found at `mem' to full 32
* bits. when simple expansion is impossible, translate instructions to
* equivalent ones. then store the displacement. the basic block `bb' is given
* to correct its information upon translation, such as the last instruction
* length. the new displacement `displ_new' is corrected and stored into
* memory.
*
* return the positive number of bytes grown on success.
* return the negative number of bytes needed in case there is not enough
* room.
*/
int
obj_ia32_instruction_expand (ia32_bblock *bb, unsigned char *mem,
int displ_new);
/* obj_calculate_bblock_mem
*
* insert the ia32_bblock.mem element into each basic block of every function
* within `flist', which is `flist_count' items long.
*
* return in any case
*/
void
obj_calculate_bblock_mem (ia32_function **flist, unsigned int flist_count);
#endif
|