Power Redirect
Power Redirect
Your help is required to transfer energy to a critical power plant!
Introduction
Power Redirect is medium reverse challenge from the ECW 2025.
We have a binary. If you reverse it, you can get the following code. I added the comments to improve my understanding of what I have in front of me:
int32_t main(int32_t argc, char** argv, char** envp)
{
// [0+0,0+1,0+2,1+0,1+1,1+2,2+0,2+1,2+2]
// [0, 0, 3][ 0, 0, 2][ 0, 0, 1]
int32_t ct_3 = 3;
int32_t var_44 = 2;
int32_t ct_1 = 1;
int32_t var_3c;
__builtin_memset(&var_3c, 0, 24);
puts("Welcome! You can manage the energy stored in power plants by transferring it from one to "
"another.");
puts("A command contains two digits: the departure and the destination.");
puts("For example, command 12 transfers energy from power plant 1 to power plant 2.");
int32_t rsi;
int32_t* rdi;
int32_t useless_char;
int32_t r9;
rsi = puts("Your goal is to route all the energy to power plant number 3!");
while (true)
{
int32_t var_30;
int64_t var_70_1 = var_30;
int32_t var_28;
int32_t var_68_1 = var_28;
int32_t var_38;
if (checkstate(rdi, rsi, var_28, var_38, useless_char, r9, ct_3, ct_1, var_38) == 1)
break;
int64_t var_88_2 = ct_3;
int64_t var_80_2 = ct_1;
int64_t var_78_2 = var_38;
int64_t var_70_2 = var_30;
int32_t var_68_2 = var_28;
printState();
printf("Enter command:");
char id_2;
char id_1;
__isoc99_scanf("%c%c", &id_1, &id_2);
useless_char = getchar(); // consume '\n'
if (id_1 > '0' && id_1 <= '3' && id_2 > '0' && id_2 <= '3')
{
rdi = &ct_3;
int32_t rax_11;
rax_11 = updateState(rdi, id_1, id_2);
if (rax_11 != -1)
continue;
else
{
rsi = puts("Impossible to transfer energy.");
continue;
}
}
rsi = puts("Invalid command...");
}
puts("Well done! The flag is ECW{commands}, where commands is the shortest sequence of "
"instructions to complete the challenge!");
return 0;
}
int64_t checkstate(int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7, int32_t arg8, int32_t arg9) __pure
{
if (!arg1 && !arg2 && !arg3 && !arg4 && !arg5 && !arg6 && arg7 == 3 && arg8 == 2 && arg9 == 1)
return 1;
return 0;
}
int64_t printState()
{
int64_t result = puts("Energie disponible dans les centrales :");
// 3 states: 0, 1, 2 => Pour chaque centrale
for (int32_t i = 0; i <= 2; i++)
{
int32_t power_length = 0;
// 3 states: 0, 1, 2 => On va vérifier sa relation a chaque autre centrale dont elle même.
for (int32_t j = 0; j <= 2; j++)
{
void arg_8;
// ((i * 3) + j) / 4 + pointer_arg_8 est défini
// 2 ** arg_8[(i*3+j) / 4]
// 2 ** 1 = 2
// 2 ** 2 = 4
// 2 ** 3 = 8
// 12 + 2 = 14
// ##############.length == 14
if (*(&arg_8 + ((i * 3 + j) << 2)))
power_length += 1 << *(&arg_8 + ((i * 3 + j) << 2));
}
printf("Centrale %d : ", i + 1);
for (int32_t j = 0; j < power_length; j++)
putchar('#');
result = putchar('\n');
}
return result;
}
int64_t updateState(void* arg1, char arg2, char arg3)
{
int32_t var_c = 0;
int32_t i_3 = 0;
// 2, 1, 0
for (int32_t i = 2; i >= 0; i--)
{
// ascii to int -> If for that central, the connection to one of the three other
// is greater than 0, then var_c > 0 by taking its value.
// chaning i_3 to the other central id
if (*(arg1 + (((arg2 - '1') * 3 + i) << 2)) > 0)
{
var_c = *(arg1 + (((arg2 - '1') * 3 + i) << 2));
i_3 = i;
break;
}
}
// error
if (!var_c)
return -1;
int32_t var_18_1 = 0;
int32_t i_2 = 0;
// 2, 1, 0
for (int32_t i = 2; i >= 0; i--)
{
// if the destination central as relationship with i
if (*(arg1 + (((arg3 - '1') * 3 + i) << 2)) > 0)
{
var_18_1 = *(arg1 + (((arg3 - '1') * 3 + i) << 2));
i_2 = i;
break;
}
}
// two cases: var_18_1 => the central does not have any relationship
// var_18_1 < var_c => The destination central have less "power" than the original one
if (var_18_1 && var_18_1 < var_c)
return -1;
// set the relation central from i to arg2 to 0.
// like if we were chaning in an array of array:
// [[0,0,0],[0,0,0],[0,0,0]] or flatten [0,0,0,0,0,0,0,0,0]
// reset the original central value to 0
*(arg1 + (((arg2 - '1') * 3 + i_3) << 2)) = 0;
// So we store the [dest_central * 3 + original_central] = original_central_value
if (var_18_1)
*(arg1 + (((arg3 - '1') * 3 + i_2 + 1) << 2)) = var_c;
else
*(arg1 + (arg3 - '1') * 12) = var_c;
return 0;
}
After looking at it, you have basically 3 towers with different amount of energy for each.
It uses a stack system to move the energy between the 3 tower, only if the amount of energy was more than the one we want to move. The idea is to make the full transfer of energy with the less move as possible.
In other words, it looks like the hanoi tower problem. Each move can be made only on the two other towers, and if the other pieces where we put the piece is larger than the one we wanna put.
I followed that tutorial: https://accromath.uqam.ca/2016/02/les-tours-de-hanoi-et-la-base-trois/
And the following moves worked:
13 12 32 13 21 23 13