Comprensión/decodificación del código de ensamblaje oscuro
Pregunta
Al igual que mi pregunta anterior, esto implica una tarea en la que se llama un método que requiere una determinada contraseña, el código está oculto y tenemos que inferir la contraseña del código de ensamblaje (quiero evitar la presentación. He completado algunas fases así lejos y estoy mejorando en la comprensión, sin embargo, esta fase tiene algunos aspectos con los que tengo problemas. Hasta ahora sé que la contraseña de esta fase es dos enteros. El retroceso ha sido mi método GOTO para algunos de estos, pero no es muy útil para esta fase.
- Entiendo que CLTQ expande EAX (RAX) a 4 palabras, pero no estoy seguro de cómo esto afecta los cálculos, y tampoco estoy seguro de qué sucede si esa línea se presiona varias veces.
- La fase5+82 -> fase5+65 (¿un bucle?) ¿Qué valores estoy tratando de comenzar con SO ECX (RCX) puede pasar la comparación final?
- MOV 0X402600 (,%RAX, 4),%EAX <- ¿Qué hace esta línea exactamente? El espacio en blanco me está tirando, ¿es un blanco = 0?
Cualquier otra ayuda para comprender lo que está sucediendo y cómo debo acercarme a averiguar la entrada sería útil, he intentado volver a convertir esto en código C, como las fases anteriores.
0x00000000004010b4 <phase_5+0>: sub $0x18,%rsp 0x00000000004010b8 <phase_5+4>: lea 0x10(%rsp),%rcx 0x00000000004010bd <phase_5+9>: lea 0x14(%rsp),%rdx 0x00000000004010c2 <phase_5+14>: mov $0x4026aa,%esi 0x00000000004010c7 <phase_5+19>: mov $0x0,%eax 0x00000000004010cc <phase_5+24>: callq 0x400b80<sscanf@plt> 0x00000000004010d1 <phase_5+29>: cmp $0x1,%eax 0x00000000004010d4 <phase_5+32>: jg 0x4010db<phase_5+39> 0x00000000004010d6 <phase_5+34>: callq 0x401421(explode_bomb) 0x00000000004010db <phase_5+39>: mov 0x14(%rsp),%eax 0x00000000004010df <phase_5+43>: and $0xf,%eax 0x00000000004010e2 <phase_5+46>: mov %eax,0x14(%rsp) 0x00000000004010e6 <phase_5+50>: cmp $0xf,%eax 0x00000000004010e9 <phase_5+53>: je 0x40111b <phase_5+103> 0x00000000004010eb <phase_5+55>: mov $0x0,%edx 0x00000000004010f0 <phase_5+60>: mov $0x0,%ecx 0x00000000004010f5 <phase_5+65>: add $0x1,%edx 0x00000000004010f8 <phase_5+68>: cltq 0x00000000004010fa <phase_5+70>: mov 0x402600(,%rax,4),%eax 0x0000000000401101 <phase_5+77>: add %eax,%ecx 0x0000000000401103 <phase_5+79>: cmp $0xf,%eax 0x0000000000401106 <phase_5+82>: jne 0x4010f5 <phase_5+65> 0x0000000000401108 <phase_5+84>: movl $0xf,0x14(%rsp) 0x0000000000401110 <phase_5+92>: cmp $0xf,%edx 0x0000000000401113 <phase_5+95>: jne 0x40111b <phase_5+103> 0x0000000000401115 <phase_5+97>: cmp %ecx,0x10(%rsp) 0x0000000000401119 <phase_5+101>: je 0x401120 <phase_5+108> 0x000000000040111b <phase_5+103>: callq 0x401421 <explode_bomb> 0x0000000000401120 <phase_5+108>: add $0x18,%rsp 0x0000000000401124 <phase_5+112>: retq
Solución
El código se traduce a esto:
0x402600: int table[15];
0x4026aa: const char *format;
void func (const char *str)
{
int a, b, count, sum;
if (sscanf (str, format, &a, &b) != 2) {
explode_bomb();
}
a = a & 0xF;
if (a == 0xF) {
explode_bomb();
}
sum = 0;
count = 0;
while (a != 0xF) {
a = table[a];
sum += a;
count++;
}
if ((count != 0xF) || (sum != b)) {
explode_bomb ();
}
}
Para responder a sus puntos específicos:
CLTQ se usa para borrar los 4 bytes más significativos de RAX para no interferir con el cálculo de la dirección en la siguiente instrucción. No tiene impacto en el cálculo.
MOV 0X402600 (,%RAX, 4),%EAX <- ¿Qué hace esta línea exactamente? El espacio en blanco me está tirando, ¿es un blanco = 0?
Sí, esto es solo mov dword eax, [0x402600 + 0 + rax * 4
Una vez que tenga el equivalente C, es fácil descubrir cómo encontrar una solución.