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));