Reverse Engineering is no Rocket Science 3

Our Code
exampleCode

Code we don’t want to have in our C Code

All register Saving and stack initialization is not ported to our C Code, because the compiler will do it later for us in our function.
Loading the saved register is ignored too.

Examples from our Source Code from part 2.

// Initialize Stack frame
.text:0000000000010630                 stdu    %sp, -0x50(%sp)
// Saving Register
.text:0000000000010634                 std     %r31, 0x48(%sp)

Detecting Saving Register

First of all, all saved register are loaded before the blr instructions again… Else saving is senseless.
Second as you see in our example r31 is pushed on the stack without modifing it at all.

How do we start?

Since we always return r3 we can start of returning a 64-bit unsigned value, which get more precisly while we reverse but for not this is enough.

unsigned long long reversingFunction()
{
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

Finding count of parameters?

In our CPU parameters are saved in r3 – rN and mostly saved in other registers at the start of the function.
If we check our code we will see this.

// Initialize Stack frame
.text:0000000000010630                 stdu    %sp, -0x50(%sp)
// Saving Register
.text:0000000000010634                 std     %r31, 0x48(%sp)
// stackpointer is copied to r31 we have to know that for the future but it is nothing special
.text:0000000000010638                 mr      %r31, %sp
// First parameter is saved in r0
.text:000000000001063C                 mr      %r0, %r3
// Second parameter is saved in r9
.text:0000000000010640                 mr      %r9, %r4
// Third parameter is saved in r11
.text:0000000000010644                 mr      %r11, %r5

So what we know for now looks like this

#define uint64_t unsigned long long
uint64_t reversingFunction(uint64_t firstParameter, uint64_t secondParameter, uint64_t thirdParameter)
{
	r0 = firstParameter;
	r9 = secondParameter;
	r11 = thirdParameter;

	// It always returns r3 it is from the spec of our CPU
	return r3;
}

Guessing and sometimes it is wrong but mostly it is right (If not this is no stone)

I let the first part as it is and won’t repeat copying it here again. Since I try to not jump that much around in the code. It will be for now okay todo so the code here just comes after the top one.

.text:0000000000010648                 stw     %r0, 0x80(%r31)
.text:000000000001064C                 stw     %r9, 0x88(%r31)
.text:0000000000010650                 stw     %r11, 0x90(%r31)
.text:0000000000010654                 lwz     %r0, 0x90(%r31)
.text:0000000000010658                 stw     %r0, 0x38(%r31)
.text:000000000001065C                 lwz     %r0, 0x80(%r31)
.text:0000000000010660                 stw     %r0, 0x34(%r31)
.text:0000000000010664                 lwz     %r0, 0x88(%r31)
.text:0000000000010668                 stw     %r0, 0x30(%r31)

Actually they all use word size instead of double word size values. r0, r9 and r11 are used earlier to save the parameter. So we guess it is used unsigned int instead of long longs.
So we change our parameters to unsigned int und define local variables for the stack addresses used. Since they are not used to save register. They are local variables.

What we got is this.

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;
	
	r0 = firstParameter;
	r9 = secondParameter;
	r11 = thirdParameter;

//.text:0000000000010648                 stw     %r0, 0x80(%r31)
	sp80 = r0;
//.text:000000000001064C                 stw     %r9, 0x88(%r31)
	sp88 = r9;
//.text:0000000000010650                 stw     %r11, 0x90(%r31)
	sp90 = r11;
//.text:0000000000010654                 lwz     %r0, 0x90(%r31)
	r0 = sp90;
//.text:0000000000010658                 stw     %r0, 0x38(%r31)
	sp38 = r0;
//.text:000000000001065C                 lwz     %r0, 0x80(%r31)
	r0 = sp80;
//.text:0000000000010660                 stw     %r0, 0x34(%r31)
	sp34 = r0;
//.text:0000000000010664                 lwz     %r0, 0x88(%r31)
	r0 = sp88;
//.text:0000000000010668                 stw     %r0, 0x30(%r31)
	sp30 = r0;
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

The CPU can’t access memory and push it in another memory part directly it uses in our case r0 todo that. In C this is no problem. So we minimize the code.
To precisly it reads from stack saves in r0 and saves r0 to a new local variable (stack). This can be done in one line in C. I commented out the two lines that get one all the time.

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;
	
	r0 = firstParameter;
	r9 = secondParameter;
	r11 = thirdParameter;

	sp80 = r0;
	sp88 = r9;
	sp90 = r11;
//	r0 = sp90;
//	sp38 = r0;
	sp38 = sp90;
//	r0 = sp80;
//	sp34 = r0;
	sp34 = sp80;
//	r0 = sp88;
//	sp30 = r0;
	sp30 = sp88;
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

So weg got now:

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;
	
	r0 = firstParameter;
	r9 = secondParameter;
	r11 = thirdParameter;

	sp80 = r0;
	sp88 = r9;
	sp90 = r11;

	sp38 = sp90;
	sp34 = sp80;
	sp30 = sp88;
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

We can minify that again (not needed but okay).

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;
	
	r0 = firstParameter;
	r9 = secondParameter;
	r11 = thirdParameter;

	sp34 = sp80 = r0;
	sp30 = sp88 = r9;
	sp38 = sp90 = r11;
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

Since we are able to remove all register useage we do so.

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

Now we managed to use no register (except return, but we don’t use that). If you look at the code we have extracted all parameter and local variables so far.
I recommend if you see such minimization options do it instant and try to use at least register as possible 😉 so the code gets readable.

Let’s go on!

.text:000000000001066C                 b       loc_1079C

We convert simple in:

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

Now we investigate loc_1079C

.text:000000000001079C                 lwz     %r0, 0x38(%r31)
.text:00000000000107A0                 cmpwi   cr7, %r0, 0
.text:00000000000107A4                 bgt     cr7, loc_10670

Again it uses r0 just as local register because it can’t compare with a stack value directly we ignore that and use our sp38 variable. r31 is like sp it was assigned at the start we remember that and ignore that it is r31 and substitute it in our head with sp ;).

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
//.text:000000000001079C                 lwz     %r0, 0x38(%r31)
//.text:00000000000107A0                 cmpwi   cr7, %r0, 0
//.text:00000000000107A4                 bgt     cr7, loc_10670
	if(sp38 > 0)
	{
		loc_10670:
	}
	loc_107A8:
	
	
	// It always returns r3 it is from the spec of our CPU
	return r3;
}

The Path splits

Since we have to reverse one way first we just take the shorter one here and this will fix the mysteri about the return value ;).

.text:00000000000107A8                 lwz     %r0, 0x90(%r31)
.text:00000000000107AC                 extsw   %r0, %r0
.text:00000000000107B0                 mr      %r3, %r0
.text:00000000000107B4                 ld      %r11, arg_0(%sp)
.text:00000000000107B8                 ld      %r31, -8(%r11)
.text:00000000000107BC                 mr      %sp, %r11
.text:00000000000107C0                 blr

Looks like this:

#define uint64_t unsigned long long
#define uint32_t unsigned int
uint64_t reversingFunction(uint32_t firstParameter, uint32_t secondParameter, uint32_t thirdParameter)
{
	uint32_t sp80, sp88, sp90, sp38, sp34, sp30;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
	}
	loc_107A8:
// load sp90 in r0
//.text:00000000000107A8                 lwz     %r0, 0x90(%r31)
// this is a sign that r0 is a signed integer because it extense the signed value from 32 bit to the full 64 bit register so r0 is a signed 32 bit integer value
//.text:00000000000107AC                 extsw   %r0, %r0
// Assign our return value. Since r0 is a signed int return value is a signed int. 
// I would guess sp90 is a signed int now too so we change that
//.text:00000000000107B0                 mr      %r3, %r0
// Loading the old stack pointer in r11 we ignore that  (we can IGNORE THAT, just remember that it was done).
//.text:00000000000107B4                 ld      %r11, arg_0(%sp)

// Loading the saved register. Let me explain this in detail (/// = Explain this in detail)
/// The top line were like this 
/// newSP = oldSP - 0x50;
/// newSP + 0x48 = r31
/// The oldSP is loaded so it is like
/// oldSP = newSP + 0x50 
/// oldSP - 0x08 = newSP + 0x48
/// oldSP - 0x08 = (oldSP - 0x50) + 0x48 
/// They are equal so it definitly loads the old saved r31 back in r31
//.text:00000000000107B8                 ld      %r31, -8(%r11)

// Restoring old stack (we can IGNORE THAT)
//.text:00000000000107BC                 mr      %sp, %r11
//.text:00000000000107C0                 blr
	return r3;
}

Okay we change the commented lines now we know sp90 is a signed int. I conclude all related to sp90 is signed too. SP90 get returned so a signed int as return and we know the return value…
Looks like this (we got quite far already):

#define uint64_t unsigned long long
#define uint32_t unsigned int
int reversingFunction(uint32_t firstParameter, uint32_t secondParameter, int thirdParameter)
{
	uint32_t sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
	}
	
	loc_107A8:
	return sp90;
}

Okay now loc_10670:

#define uint64_t unsigned long long
#define uint32_t unsigned int
int reversingFunction(uint32_t firstParameter, uint32_t secondParameter, int thirdParameter)
{
	uint32_t sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
// An simple if on sp38 again
//.text:0000000000010670                 lwz     %r0, 0x38(%r31)
//.text:0000000000010674                 cmpwi   cr7, %r0, 7
//.text:0000000000010678                 ble     cr7, loc_106BC
		if(sp38 <= 7)
		{
			loc_106BC:
		}
		loc_1067C:
	}
	
	loc_107A8:
	return sp90;
}

I will choose the if routes now so we got a basic structure of the code already. I will go on all of them in one hit now. Too shorten things it’s always the same.

#define uint64_t unsigned long long
#define uint32_t unsigned int
int reversingFunction(uint32_t firstParameter, uint32_t secondParameter, int thirdParameter)
{
	uint32_t sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
// An simple if on sp38 again
//.text:00000000000106BC                 lwz     %r0, 0x38(%r31)
//.text:00000000000106C0                 cmpwi   cr7, %r0, 3
//.text:00000000000106C4                 ble     cr7, loc_10708
			if(sp38 <= 3)
			{
				loc_10708:
// An simple if on sp38 again
//.text:0000000000010708                 lwz     %r0, 0x38(%r31)
//.text:000000000001070C                 cmpwi   cr7, %r0, 1
//.text:0000000000010710                 ble     cr7, loc_10754
				if(sp38 <= 1)
				{
					loc_10754:
// An simple if on sp38 again
//.text:0000000000010754                 lwz     %r0, 0x38(%r31)
//.text:0000000000010758                 cmpwi   cr7, %r0, 0
//.text:000000000001075C                 ble     cr7, loc_1079C
					if(sp38 <= 0)
					{
						goto loc_1079C; // this time we don't assigne a Label because we already have that one reversed at the top 😉
					}
					loc_10760:
				}
				loc_10714:
			}
			loc_106C8:
		}
		loc_1067C:
	}
	
	loc_107A8:
	return sp90;
}

Okay let’s look what we got here:

#define uint64_t unsigned long long
#define uint32_t unsigned int
int reversingFunction(uint32_t firstParameter, uint32_t secondParameter, int thirdParameter)
{
	uint32_t sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
			if(sp38 <= 3)
			{
				loc_10708:
				if(sp38 <= 1)
				{
					loc_10754:
					if(sp38 <= 0)
					{
						goto loc_1079C;
					}
					loc_10760:
				}
				loc_10714:
			}
			loc_106C8:
		}
		loc_1067C:
	}
	
	loc_107A8:
	return sp90;
}

Block loc_1067C

I will convert one block first. I choosed the highest one in the IDA graph that was missing.
All other parts are nearly as the same of that block after explained this one in detail I go through the rest faster. I know it since I know the real code too. It’s one of mine anyway, but normaly you would all do one by one. I just want to shorten things but you will understand what I mean soon.
Let’s start with one code block.

#define uint64_t unsigned long long
#define uint32_t unsigned int
int reversingFunction(uint32_t firstParameter, uint32_t secondParameter, int thirdParameter)
{
	uint32_t sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
			if(sp38 <= 3)
			{
				loc_10708:
				if(sp38 <= 1)
				{
					loc_10754:
					if(sp38 <= 0)
					{
						goto loc_1079C;
					}
					loc_10760:
				}
				loc_10714:
			}
			loc_106C8:
		}
		loc_1067C:
// Okay we save sp34 in r11 and sp30 in r0 lets mind that in our brain no need to write that down for now
//.text:000000000001067C                 lwz     %r11, 0x34(%r31)
//.text:0000000000010680                 lwz     %r0, 0x30(%r31)

// Since we just saved an int no need to write nulls to the top part of sp30... 
// Let me explain r0 is sp30 so this looks in c like this I don't write this down in real code just to explain
/// r9 = (r0 << 0) &amp; 0x00000000FFFFFFFF;
/// so just saves the int value of r0 (sp30) in r9 we keep that in mind
// so sp30 is casted in an int not interesting as long as we don't know what is done with the integer value
//.text:0000000000010684                 rldicl  %r9, %r0, 0,32

// Okay we decided just the line above is a cast of sp30 as int saved in r9 
// which is used as pointer to load a double word so it is in uint64_t pointer here 😉
// Our CPU uses 32 bit addresses mostly so we ignore the int conversion here.
// we could write this
// r0 = *((uint64_t*)(int)sp30);
// but the int cast is done from compiler anyway so we ignore it 😉
// Look what we got:
//.text:0000000000010688                 ld      %r0, 0(%r9)
r0 = *((uint64_t*)sp30);

// Same as above just with sp34 now
//.text:000000000001068C                 rldicl  %r9, %r11, 0,32

// instead of load it writes the double word to the adress of r9 (sp34)
//.text:0000000000010690                 std     %r0, 0(%r9)
*((uint64_t*)sp34) = r0;

// load our pointer sp34 to r9
//.text:0000000000010694                 lwz     %r9, 0x34(%r31)
// increase the pointer by 8 and save the result in r0
//.text:0000000000010698                 addi    %r0, %r9, 8
// store the by 8 increased pointer back to sp34
//.text:000000000001069C                 stw     %r0, 0x34(%r31)
// We do it like this for example
sp34 = ((uint64_t*)sp34) + 1;

// Same as above just with sp30
//.text:00000000000106A0                 lwz     %r9, 0x30(%r31)
//.text:00000000000106A4                 addi    %r0, %r9, 8
//.text:00000000000106A8                 stw     %r0, 0x30(%r31)
sp30 = ((uint64_t*)sp30) + 1;

// oh sp38 gets decreased by 8
// same as above with sp38 just -8 instead of +8
// we know already that this is not a pointer because never is data loaded from it
// you may have a clue now what this is
//.text:00000000000106AC                 lwz     %r9, 0x38(%r31)
//.text:00000000000106B0                 addi    %r0, %r9, -8
//.text:00000000000106B4                 stw     %r0, 0x38(%r31)
sp38 -= 8;

// simple go back to the top 🙂
//.text:00000000000106B8                 b       loc_1079C
		goto loc_1079C;
	}
	
	loc_107A8:
	return sp90;
}

NOTE: Since we know now that sp34 is a pointer to some address we can assign (uint64_t*) to all sp34 and sp30 assoziated variables now

We got something like this now:

#define uint64_t unsigned long long
#define uint32_t unsigned int
int reversingFunction(uint64_t* firstParameter, uint64_t* secondParameter, int thirdParameter)
{
	uint64_t* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
			if(sp38 <= 3)
			{
				loc_10708:
				if(sp38 <= 1)
				{
					loc_10754:
					if(sp38 <= 0)
					{
						goto loc_1079C;
					}
					loc_10760:
				}
				loc_10714:
			}
			loc_106C8:
		}
		loc_1067C:
		*((uint64_t*)sp34) = *((uint64_t*)sp30);
		sp34 = ((uint64_t*)sp34) + 1;
		sp30 = ((uint64_t*)sp30) + 1;
		sp38 -= 8;
		goto loc_1079C;
	}
	
	loc_107A8:
	return sp90;
}

The other 3 Blocks

Now the other 3 parts we go fast through since they are nearly the same as the loc_1067C block. Normaly you would investigate in detail, but I shorten here.

#define uint64_t unsigned long long
#define uint32_t unsigned int
// I changed it to void* because you will see the other blocks use the pointers as other pointers than uint64_t*
int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;

	loc_10760:
// look at Block loc_1067C it's the same just byte is used instead of double word
//.text:0000000000010760                 lwz     %r11, 0x34(%r31)
//.text:0000000000010764                 lwz     %r0, 0x30(%r31)
//.text:0000000000010768                 rldicl  %r9, %r0, 0,32
//.text:000000000001076C                 lbz     %r0, 0(%r9)
//.text:0000000000010770                 rldicl  %r9, %r11, 0,32
//.text:0000000000010774                 stb     %r0, 0(%r9)
	*((char*)sp34) = *((char*)sp30);

// look at Block loc_1067C it's the same just byte is used instead of double word
//.text:0000000000010778                 lwz     %r9, 0x34(%r31)
//.text:000000000001077C                 addi    %r0, %r9, 1
//.text:0000000000010780                 stw     %r0, 0x34(%r31)
	sp34 = ((char*) sp34) + 1;
	
// look at Block loc_1067C it's the same just byte is used instead of double word
//.text:0000000000010784                 lwz     %r9, 0x30(%r31)
//.text:0000000000010788                 addi    %r0, %r9, 1
//.text:000000000001078C                 stw     %r0, 0x30(%r31)
	sp30 = ((char*) sp30) + 1;

// look at Block loc_1067C it's the same just byte is used instead of double word
//.text:0000000000010790                 lwz     %r9, 0x38(%r31)
//.text:0000000000010794                 addi    %r0, %r9, -1
//.text:0000000000010798                 stw     %r0, 0x38(%r31)
	sp38 -= 1;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
			if(sp38 <= 3)
			{
				loc_10708:
				if(sp38 <= 1)
				{
					loc_10754:
					if(sp38 <= 0)
					{
						goto loc_1079C;
					}
					// IMPROTANT!!!: To stay at the code flow you see in text line this block is just above loc_1079C
					// In graph view of IDA we couldn't see that but in text view the code will continue after the execution at
					// loc_1079C
					// How to solve this
					// 1. create a Label above loc_1079C and jump to that label with
					// like this
					goto loc_10760;
				}
				loc_10714:
// look at Block loc_1067C it's the same just half word is used instead of double word
//.text:0000000000010714                 lwz     %r11, 0x34(%r31)
//.text:0000000000010718                 lwz     %r0, 0x30(%r31)
//.text:000000000001071C                 rldicl  %r9, %r0, 0,32
//.text:0000000000010720                 lhz     %r0, 0(%r9)
//.text:0000000000010724                 rldicl  %r9, %r11, 0,32
//.text:0000000000010728                 sth     %r0, 0(%r9)
				*((unsigned short*)sp34) = *((unsigned short*)sp30);

// look at Block loc_1067C it's the same just half word is used instead of double word
//.text:000000000001072C                 lwz     %r9, 0x34(%r31)
//.text:0000000000010730                 addi    %r0, %r9, 2
//.text:0000000000010734                 stw     %r0, 0x34(%r31)
				sp34 = ((unsigned short*)sp34) + 1;

// look at Block loc_1067C it's the same just half word is used instead of double word
//.text:0000000000010738                 lwz     %r9, 0x30(%r31)
//.text:000000000001073C                 addi    %r0, %r9, 2
//.text:0000000000010740                 stw     %r0, 0x30(%r31)
				sp30 = ((unsigned short*)sp30) + 1;

// look at Block loc_1067C it's the same just half word is used instead of double word
//.text:0000000000010744                 lwz     %r9, 0x38(%r31)
//.text:0000000000010748                 addi    %r0, %r9, -2
//.text:000000000001074C                 stw     %r0, 0x38(%r31)
				sp38 -= 2;
//.text:0000000000010750                 b       loc_1079C
				goto loc_1079C;
			}
			loc_106C8:
// look at Block loc_1067C it's the same just word is used instead of double word
//.text:00000000000106C8                 lwz     %r11, 0x34(%r31)
//.text:00000000000106CC                 lwz     %r0, 0x30(%r31)
//.text:00000000000106D0                 rldicl  %r9, %r0, 0,32
//.text:00000000000106D4                 lwz     %r0, 0(%r9)
//.text:00000000000106D8                 rldicl  %r9, %r11, 0,32
//.text:00000000000106DC                 stw     %r0, 0(%r9)
// Explained in Block loc_1067C just this time word instead of double word
			*((uint32_t*)sp34) = *((uint32_t*)sp30);

// look at Block loc_1067C it's the same just word is used instead of double word
//.text:00000000000106E0                 lwz     %r9, 0x34(%r31)
//.text:00000000000106E4                 addi    %r0, %r9, 4
//.text:00000000000106E8                 stw     %r0, 0x34(%r31)
			sp34 = ((uint32_t*)sp34) + 1;
// look at Block loc_1067C it's the same just word is used instead of double word
//.text:00000000000106EC                 lwz     %r9, 0x30(%r31)
//.text:00000000000106F0                 addi    %r0, %r9, 4
//.text:00000000000106F4                 stw     %r0, 0x30(%r31)
			sp30 = ((uint32_t*)sp30) + 1;
// look at Block loc_1067C it's the same just word is used instead of double word
//.text:00000000000106F8                 lwz     %r9, 0x38(%r31)
//.text:00000000000106FC                 addi    %r0, %r9, -4
//.text:0000000000010700                 stw     %r0, 0x38(%r31)
			sp38 -= 4;
//.text:0000000000010704                 b       loc_1079C
			goto loc_1079C;
		}
		loc_1067C:
		*((uint64_t*)sp34) = *((uint64_t*)sp30);
		sp34 = ((uint64_t*)sp34) + 1;
		sp30 = ((uint64_t*)sp30) + 1;
		sp38 -= 8;
		goto loc_1079C;
	}
	
	loc_107A8:
	return sp90;
}

Okay we are done and it looks like this:

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;

	loc_10760:
	*((char*)sp34) = *((char*)sp30);
	sp34 = ((char*) sp34) + 1;
	sp30 = ((char*) sp30) + 1;
	sp38 -= 1;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
			if(sp38 <= 3)
			{
				loc_10708:
				if(sp38 <= 1)
				{
					loc_10754:
					if(sp38 <= 0)
					{
						goto loc_1079C;
					}
					goto loc_10760;
				}
				loc_10714:
				*((unsigned short*)sp34) = *((unsigned short*)sp30);
				sp34 = ((unsigned short*)sp34) + 1;
				sp30 = ((unsigned short*)sp30) + 1;
				sp38 -= 2;
				goto loc_1079C;
			}
			loc_106C8:
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
			goto loc_1079C;
		}
		loc_1067C:
		*((uint64_t*)sp34) = *((uint64_t*)sp30);
		sp34 = ((uint64_t*)sp34) + 1;
		sp30 = ((uint64_t*)sp30) + 1;
		sp38 -= 8;
		goto loc_1079C;
	}
	
	loc_107A8:
	return sp90;
}

Okay now two things we can do. Replace spXX with more speaking names by investigating what this code does, but I recommend to sort the code with the next part. Called Code Flow…

Code Flow

We are lucky since the code under every if (if the condition is false) always jumps somewhere different so we can inject else there for sure without damaging the code flow.

This will look like this:

NOTE: Only inject else clauses if you are sure it don’t disturbe the code flow.

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;

	loc_10760:
	*((char*)sp34) = *((char*)sp30);
	sp34 = ((char*) sp34) + 1;
	sp30 = ((char*) sp30) + 1;
	sp38 -= 1;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		if(sp38 <= 7)
		{
			loc_106BC:
			if(sp38 <= 3)
			{
				loc_10708:
				if(sp38 <= 1)
				{
					loc_10754:
					if(sp38 <= 0)
					{
						goto loc_1079C;
					}
					else
					{
						goto loc_10760;
					}
				}
				else
				{
					loc_10714:
					*((unsigned short*)sp34) = *((unsigned short*)sp30);
					sp34 = ((unsigned short*)sp34) + 1;
					sp30 = ((unsigned short*)sp30) + 1;
					sp38 -= 2;
					goto loc_1079C;
				}
			}
			else
			{
				loc_106C8:
				*((uint32_t*)sp34) = *((uint32_t*)sp30);
				sp34 = ((uint32_t*)sp34) + 1;
				sp30 = ((uint32_t*)sp30) + 1;
				sp38 -= 4;
				goto loc_1079C;
			}
		}
		else
		{
			loc_1067C:
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
			goto loc_1079C;
		}
	}
	
	loc_107A8:
	return sp90;
}

Sometimes switching the blocks if code block with else code block AND inverting the condition check will make a more common structure.

I guess you will directly see when you see this code transformation now:

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;

	loc_10760:
	*((char*)sp34) = *((char*)sp30);
	sp34 = ((char*) sp34) + 1;
	sp30 = ((char*) sp30) + 1;
	sp38 -= 1;
	
	loc_1079C:
	if(sp38 > 0)
	{
		loc_10670:
		//if(sp38 <= 7)
		if(sp38 > 7)
		{
			loc_1067C:
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
			goto loc_1079C;
		}
		else
		{
			loc_106BC:
			//if(sp38 <= 3)
			if(sp38 > 3)
			{
				loc_106C8:
				*((uint32_t*)sp34) = *((uint32_t*)sp30);
				sp34 = ((uint32_t*)sp34) + 1;
				sp30 = ((uint32_t*)sp30) + 1;
				sp38 -= 4;
				goto loc_1079C;
			}
			else
			{
				loc_10708:
				//if(sp38 <= 1)
				if(sp > 1)
				{
					loc_10714:
					*((unsigned short*)sp34) = *((unsigned short*)sp30);
					sp34 = ((unsigned short*)sp34) + 1;
					sp30 = ((unsigned short*)sp30) + 1;
					sp38 -= 2;
					goto loc_1079C;
				}
				else
				{
					loc_10754:
					if(sp38 > 0)
					{
						goto loc_10760;
					}
					else
					{
						goto loc_1079C;
					}
				}
			}
		}
	}
	
	loc_107A8:
	return sp90;
}

Okay we remove all none called labels and restructure the else { if { } } structures to else ifs:

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		if(sp38 > 7)
		{
			loc_1067C:
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
			goto loc_1079C;
		}
		else if(sp38 > 3)
		{
			loc_106C8:
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
			goto loc_1079C;
		}
		else if(sp > 1)
		{
			loc_10714:
			*((unsigned short*)sp34) = *((unsigned short*)sp30);
			sp34 = ((unsigned short*)sp34) + 1;
			sp30 = ((unsigned short*)sp30) + 1;
			sp38 -= 2;
			goto loc_1079C;
		}
		else if(sp38 > 0)
		{
// Since this is the only place the loc_10760 Code is called and executed we copy it here
//			goto loc_10760;
			loc_10760:
			*((char*)sp34) = *((char*)sp30);
			sp34 = ((char*) sp34) + 1;
			sp30 = ((char*) sp30) + 1;
			sp38 -= 1;
// AND we preserve the code flow with a goto to the code executed after loc_10760
			goto loc_1079C;
		}
		else
		{
			goto loc_1079C;
		}
	}
	
	return sp90;
}

Nearly finish…

We got this now looks quite nice already:

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		if(sp38 > 7)
		{
			loc_1067C:
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
			goto loc_1079C;
		}
		else if(sp38 > 3)
		{
			loc_106C8:
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
			goto loc_1079C;
		}
		else if(sp > 1)
		{
			loc_10714:
			*((unsigned short*)sp34) = *((unsigned short*)sp30);
			sp34 = ((unsigned short*)sp34) + 1;
			sp30 = ((unsigned short*)sp30) + 1;
			sp38 -= 2;
			goto loc_1079C;
		}
		else if(sp38 > 0)
		{
			loc_10760:
			*((char*)sp34) = *((char*)sp30);
			sp34 = ((char*) sp34) + 1;
			sp30 = ((char*) sp30) + 1;
			sp38 -= 1;
			goto loc_1079C;
		}
		else
		{
			goto loc_1079C;
		}
	}
	
	return sp90;
}

No matter what if or else if is executed all end with a jump to loc_1079C so we can just put it out of the ifs

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	goto loc_1079C;
	
	loc_1079C:
	if(sp38 > 0)
	{
		if(sp38 > 7)
		{
			loc_1067C:
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
		}
		else if(sp38 > 3)
		{
			loc_106C8:
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
		}
		else if(sp > 1)
		{
			loc_10714:
			*((unsigned short*)sp34) = *((unsigned short*)sp30);
			sp34 = ((unsigned short*)sp34) + 1;
			sp30 = ((unsigned short*)sp30) + 1;
			sp38 -= 2;
		}
		else if(sp38 > 0)
		{
			loc_10760:
			*((char*)sp34) = *((char*)sp30);
			sp34 = ((char*) sp34) + 1;
			sp30 = ((char*) sp30) + 1;
			sp38 -= 1;
		}
		goto loc_1079C;
	}
	
	return sp90;
}

While?

You have to know that, it’s hard to explain if you go into an if and the condition is true.
If that if body code jumps back to the if this is by definition a while clause.
Think about it makes totaly sense 😉

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	
//	loc_1079C:
//	if(sp38 > 0)
	while(sp38 > 0)
	{
		if(sp38 > 7)
		{
			loc_1067C:
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
		}
		else if(sp38 > 3)
		{
			loc_106C8:
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
		}
		else if(sp > 1)
		{
			loc_10714:
			*((unsigned short*)sp34) = *((unsigned short*)sp30);
			sp34 = ((unsigned short*)sp34) + 1;
			sp30 = ((unsigned short*)sp30) + 1;
			sp38 -= 2;
		}
		else if(sp38 > 0)
		{
			loc_10760:
			*((char*)sp34) = *((char*)sp30);
			sp34 = ((char*) sp34) + 1;
			sp30 = ((char*) sp30) + 1;
			sp38 -= 1;
		}
//		goto loc_1079C;
	}
	
	return sp90;
}

Now we got this:

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp80, sp88, sp34, sp30;
	int sp90, sp38;

	sp34 = sp80 = firstParameter;
	sp30 = sp88 = secondParameter;
	sp38 = sp90 = thirdParameter;
	
	while(sp38 > 0)
	{
		if(sp38 > 7)
		{
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
		}
		else if(sp38 > 3)
		{
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
		}
		else if(sp > 1)
		{
			*((unsigned short*)sp34) = *((unsigned short*)sp30);
			sp34 = ((unsigned short*)sp34) + 1;
			sp30 = ((unsigned short*)sp30) + 1;
			sp38 -= 2;
		}
		else if(sp38 > 0)
		{
			*((char*)sp34) = *((char*)sp30);
			sp34 = ((char*) sp34) + 1;
			sp30 = ((char*) sp30) + 1;
			sp38 -= 1;
		}
	}
	
	return sp90;
}

Rename Local Variables and Remove unused Local variables

First we remove unused variables. In our case sp88, sp80.
sp90 get assigned and returned but never modified so we can use the third Parameter for it.

#define uint64_t unsigned long long
#define uint32_t unsigned int

int reversingFunction(void* firstParameter, void* secondParameter, int thirdParameter)
{
	void* sp34, sp30;
	int sp90, sp38;

	sp34 = firstParameter;
	sp30 = secondParameter;
	sp38 = thirdParameter;
	
	while(sp38 > 0)
	{
		if(sp38 > 7)
		{
			*((uint64_t*)sp34) = *((uint64_t*)sp30);
			sp34 = ((uint64_t*)sp34) + 1;
			sp30 = ((uint64_t*)sp30) + 1;
			sp38 -= 8;
		}
		else if(sp38 > 3)
		{
			*((uint32_t*)sp34) = *((uint32_t*)sp30);
			sp34 = ((uint32_t*)sp34) + 1;
			sp30 = ((uint32_t*)sp30) + 1;
			sp38 -= 4;
		}
		else if(sp > 1)
		{
			*((unsigned short*)sp34) = *((unsigned short*)sp30);
			sp34 = ((unsigned short*)sp34) + 1;
			sp30 = ((unsigned short*)sp30) + 1;
			sp38 -= 2;
		}
		else if(sp38 > 0)
		{
			*((char*)sp34) = *((char*)sp30);
			sp34 = ((char*) sp34) + 1;
			sp30 = ((char*) sp30) + 1;
			sp38 -= 1;
		}
	}
	
	return thirdParameter;
}

Renaming the variables and all other names too…
Now look like this:

#define uint64_t unsigned long long
#define uint32_t unsigned int
#define uint16_t unsigned short
#define uint8_t  char

int memcpy(void* dst, void* src, int size)
{
	int sizeToCopy = size;
	void* dstCopy = dst;
	void* srcCopy = src;
	
	while(sizeToCopy > 0)
	{
		if(sizeToCopy >= 8)
		{
			*((uint64_t*)dstCopy) = *((uint64_t*)srcCopy);
			dstCopy = ((uint64_t*)dstCopy)+1;
			srcCopy = ((uint64_t*)srcCopy)+1;
			sizeToCopy -= 8;
		}
		else if(sizeToCopy >= 4)
		{
			*((uint32_t*)dstCopy) = *((uint32_t*)srcCopy);
			dstCopy = ((uint32_t*)dstCopy)+1;
			srcCopy = ((uint32_t*)srcCopy)+1;
			sizeToCopy -= 4;
		}
		else if(sizeToCopy >= 2)
		{
			*((unsigned short*)dstCopy) = *((unsigned short*)srcCopy);
			dstCopy = ((uint16_t*)dstCopy)+1;
			srcCopy = ((uint16_t*)srcCopy)+1;
			sizeToCopy -= 2;
		}
		else if(sizeToCopy >= 1)
		{
			*((uint8_t*)dstCopy) = *((uint8_t*)srcCopy);
			dstCopy = ((uint8_t*)dstCopy)+1;
			srcCopy = ((uint8_t*)srcCopy)+1;
			sizeToCopy -= 1;
		}
	}
	
	return size;
}

Ask me on twitter for questions this is a tough one I know. (@KDSBest on twitter 😉 )

Stay tuned,

KDSBest

Leave a Reply

Your email address will not be published. Required fields are marked *