Challenges.re - RE 03#

The Challenges.re is a website with compilation of Reverse Engineering exercises, I’m writing this document for me only, to exercise my knowledge with assembly and reverse engineering. If you want to solve these exercises by yourself one day, please do not read my solution, try for yourself, my answer can be wrong, so don’t trust me, trust the process.

Question#

Reverse Engineering challenge #3. Tags: . What does this code do? The function has array of 64 32-bit integers, I removed it in each assembly code snippet to save space. The array is:

int v[64]=
	{ -1,31, 8,30, -1, 7,-1,-1, 29,-1,26, 6, -1,-1, 2,-1,
	  -1,28,-1,-1, -1,19,25,-1, 5,-1,17,-1, 23,14, 1,-1,
	   9,-1,-1,-1, 27,-1, 3,-1, -1,-1,20,-1, 18,24,15,10,
	  -1,-1, 4,-1, 21,-1,16,11, -1,22,-1,12, 13,-1, 0,-1 };

Assembly Code#

f:
	mov	edx, edi
	shr	edx
	or	edx, edi
	mov	eax, edx
	shr	eax, 2
	or	eax, edx
	mov	edx, eax
	shr	edx, 4
	or	edx, eax
	mov	eax, edx
	shr	eax, 8
	or	eax, edx
	mov	edx, eax
	shr	edx, 16
	or	edx, eax
	imul	eax, edx, 79355661 ; 0x4badf0d
	shr	eax, 26
	mov	eax, DWORD PTR v[0+rax*4]
	ret

With comments each line:

f: 									; Function method
	mov	edx, edi					; Move data from EDI to EDX
	shr	edx 						; Shift right EDX 1 bit (EDX / 2) 0x2
	or	edx, edi 					; Make and OR comparison EDX with EDI and store in EDX
	mov	eax, edx 					; Move data from EDX to EAX
	shr	eax, 2 						; Shift right EAX 2 bits (EDX / 4) 0x4
	or	eax, edx 					; Make and OR comparison EAX with EDX and store in EAX
	mov	edx, eax 					; Move data from EAX to EDX
	shr	edx, 4 						; Shift right EDX 4 bits (EDX / 16) 0x10
	or	edx, eax 					; Make and OR comparison EDX with EAX and store in EDX
	mov	eax, edx 					; Move data from EDX to EAX
	shr	eax, 8 						; Shift right EAX 8 bits (EDX / 256) 0x100
	or	eax, edx 					; Make and OR comparison EAX with EDX and store in EAX
	mov	edx, eax 					; Move data from EAX to EDX
	shr	edx, 16 					; Shift right EDX 16 bits (EDX / 65536) 0x10000
	or	edx, eax 					; Make and OR comparison EDX with EAX and store in EDX
	imul	eax, edx, 79355661 		; (0x4badf0d) Multiply EDX with 79355661 and store in EAX
	shr	eax, 26  					; Shift right EAX 26 bits (EAX / 67108864) 0x4000000
	mov	eax, DWORD PTR v[0+rax*4] 	; Move v[0+RAX*4] DWORD to EAX
	ret

Making a table of pseudo-code, it looks something like:

OPArg1Arg2Arg3Pseudo-code
MOVEDXEDIEDX = EDI
SHREDX1EDX = EDX » 1
OREDXEDIEDX = EDI | EDX
MOVEAXEDXEAX = EDX
SHREAX2EAX = EAX » 2
OREAXEDXEAX = EDX | EAX
MOVEDXEAXEDX = EAX
SHREDX4EDX = EDX » 4
OREDXEAXEDX = EAX | EDX
MOVEAXEDXEAX = EDX
SHREAX8EAX = EAX » 8
OREAXEDXEAX = EDX | EAX
MOVEDXEAXEDX = EAX
SHREDX16EDX = EDX » 16
OREDXEAXEDX = EAX | EDX
IMULEAXEDX79355661EAX = EDX * 0x4badf0d
SHREAX26EAX = EAX » 26
MOVEAXDWORD PTR v[0+rax*4]EAX = (int)v[RAX]
RETreturn EAX

And trying to reverse into c code:

// Type your code here, or load an example.
int v[64]=
	{ -1,31, 8,30, -1, 7,-1,-1, 29,-1,26, 6, -1,-1, 2,-1,
	  -1,28,-1,-1, -1,19,25,-1, 5,-1,17,-1, 23,14, 1,-1,
	   9,-1,-1,-1, 27,-1, 3,-1, -1,-1,20,-1, 18,24,15,10,
	  -1,-1, 4,-1, 21,-1,16,11, -1,22,-1,12, 13,-1, 0,-1 };

int f(int num) {

    num|=(num>>1);
    num|=(num>>2);
    num|=(num>>4);
    num|=(num>>8);
    num|=(num>>16);

    num*=79355661;

    num>>=26;

    return v[num];
}

With that information we can make a table of possible results:

inputoutputdecimalIn Array
00x00-1
10x1131
2-30x3330
4-70x8829
8-150x111728
16-310x243627
32-630x0a1026
64-1270x162225
128-2550x2d4524
256-5110x1c2823
512-10230x395722
1024-20470x345221
And so go on

What the code does#

It takes the most valuable Left bit, expand to be filled all the way to the right, the result is then multiplied by a magic number : 79355661.

This number make a result that is filtered by shifting 26 bits to the right. Making it range from 0 to 63, the possible numbers to gather in the v[] array.

The result will then gather a value inside the array. In this case the value 1 returns 31, the value 2 and 3 returns 30, etc.

It’s decrementing a value in each bit reached to the left. (check table above)

This could be used as an obfuscation type of code. Putting malware to be read in an unusual order, tricking known antivirus database standards.