12.6 Merging Scalar Variables
12.6.1 Problem
Scalar variables with
constant or initialized values disclose information about ranges of
values.
12.6.2 Solution
Merging multiple scalar values into a single, larger scalar value can
make simple, unrelated values appear to be a large value or bit
field. Two 8-bit values can be merged into a single 16-bit value, and
two 16-bit values can be merged into a single 32-bit value.
12.6.3 Discussion
Merging scalar variables is a light obfuscation. When used in a loop,
a debugger can set a watch on the counter variable and make obvious
the fact that the upper or lower half of the variable is being
incremented with each iteration of the loop.
The following macros merge two char values into a
single short value, and two
short values into a single int
value. This is accomplished by shifting the shorter values into the
larger value that contains them, and by masking half of the larger
value and shifting as appropriate to retrieve the shorter value.
/* x and y are chars, returns a short */
/* x is in position 0, y is in position 1 */
#define MERGE_CHAR(x, y) (((y) << 8 ) | (x))
/* s is a short and c is position -- 0 or 1 */
#define GET_CHAR(s, c) (char)(((s) >> (8 * (c))) & 0x00FF)
/* s is a short, c is a position, and val is a char value */
#define SET_CHAR(s, c, val) (((s) & (0xFF00 >> (8 * (c)))) | ((val) << (8 * (c))))
/* x and y are shorts. returns an int */
/* x is in position 0, y is in position 1 */
#define MERGE_SHORT(x, y) (((y) << 16 ) | (x))
/* i is an int and s is position -- 0 or 1 */
#define GET_SHORT(i, s) (short)(((i) >> (16 * (s))) & 0x0FFFF)
/* i is an int, s is position, and val is a short value */
#define SET_SHORT(i, s, val) (((i) & (0xFFFF0000 >> (16 * (s)))) | \
((val) << (16 * (s))))
These macros can be used to obfuscate the conditions of a loop:
int xy = MERGE_SHORT(0x1010, 0xFEEF);
char i;
short ij = MERGE_CHAR(1, 12);
for (i = GET_CHAR(ij, 0); i < GET_CHAR(ij, 1); i++) {
xy = SET_SHORT(xy, 0, (GET_SHORT(xy, 0) + i));
printf("x %#04hX y %#04hX\n", GET_SHORT(xy, 0), GET_SHORT(xy, 1));
}
|