Decodificación y comprensión del código ensamblador.
gdb assemblies (1)
Así que un poco de historia. Soy un principiante con c y código de ensamblaje, tenemos una asignación de "bomba" (escrita en c) que llama a métodos que requieren ciertas contraseñas, pero el código no es visible y necesito determinar la contraseña correcta mirando el código de ensamblaje .
El código indica que la contraseña para este método es de 6 números, que se pasa como "entrada" a la fase 2 del método (estoy tratando de evitar el disparo).
La parte en la que me estoy confundiendo es saltar de +64 a +42. Parece ser un bucle, pero no estoy seguro de cómo se afecta la pila con cada pase. Parece que el bucle sale si los dos últimos números son iguales, y tiene algo que ver con sumar y restar 4, pero no estoy seguro de cómo se cruzan las direcciones. Si alguien puede traducir lo que está sucediendo exactamente, o si necesito buscar en algún registro / ubicación en particular, sería de gran ayuda. Hay 4 fases más, cada una de las cuales se supone que son más complejas, por lo que quiero obtener una buena comprensión de cómo abordarlas.
Además, si alguien tiene un buen recurso (como una tabla imprimible) con palabras clave de código de ensamblaje que también sería útil, y también si hay alguna diferencia entre los registros de 32 y 64 bits, debo preocuparme por otros que no sean los nombres de registro. .
82 phase_2(input);
(gdb) disas phase_2
Dump of assembler code for function phase_2:
0x000000000040106b <phase_2+0>: push %rbp
0x000000000040106c <phase_2+1>: push %rbx
0x000000000040106d <phase_2+2>: sub $0x28,%rsp
0x0000000000401071 <phase_2+6>: mov %rsp,%rsi
0x0000000000401074 <phase_2+9>: callq 0x401457 <read_six_numbers>
0x0000000000401079 <phase_2+14>: cmpl $0x0,(%rsp)
0x000000000040107d <phase_2+18>: jne 0x401086 <phase_2+27>
0x000000000040107f <phase_2+20>: cmpl $0x1,0x4(%rsp)
0x0000000000401084 <phase_2+25>: je 0x40108b <phase_2+32>
0x0000000000401086 <phase_2+27>: callq 0x401421 <explode_bomb>
0x000000000040108b <phase_2+32>: lea 0x8(%rsp),%rbx
0x0000000000401090 <phase_2+37>: lea 0x18(%rsp),%rbp
0x0000000000401095 <phase_2+42>: mov -0x8(%rbx),%eax
0x0000000000401098 <phase_2+45>: add -0x4(%rbx),%eax
0x000000000040109b <phase_2+48>: cmp %eax,(%rbx)
0x000000000040109d <phase_2+50>: je 0x4010a4 <phase_2+57>
0x000000000040109f <phase_2+52>: callq 0x401421 <explode_bomb>
0x00000000004010a4 <phase_2+57>: add $0x4,%rbx
0x00000000004010a8 <phase_2+61>: cmp %rbp,%rbx
0x00000000004010ab <phase_2+64>: jne 0x401095 <phase_2+42>
0x00000000004010ad <phase_2+66>: add $0x28,%rsp
0x00000000004010b1 <phase_2+70>: pop %rbx
0x00000000004010b2 <phase_2+71>: pop %rbp
0x00000000004010b3 <phase_2+72>: retq
Aquí hay un C equivalente de fase2:
int t[6];
read_six_numbers (t);
if ((t[0] != 0) || (t[1] != 1)) {
explode_bomb();
}
for (int i = 2; i < 6; i++) {
if (t[i] != t[i - 2] + t[i - 1]) {
explode_bomb();
}
}
Entonces la contraseña es 0, 1, 1, 2, 3, 5.
¿Cómo hice esto? Reemplazando gradualmente el conjunto con C.
Notarás que el puntero de pila (rsp) nunca cambia. Puede ver la pila como una matriz t de números de 32 bits. Es decir, cada vez que se mueve por 4 bytes, se mueve al siguiente elemento. es decir, 0 (% rsp), 4 (% rsp), ... son equivalentes a t [0], t [1], ...
Te mostraré una posible transformación gradual del bit con el que tienes problemas:
lea 0x8(%rsp),%rbx
lea 0x18(%rsp),%rbp
<phase_2+42>: mov -0x8(%rbx),%eax
add -0x4(%rbx),%eax
cmp %eax,(%rbx)
je <phase_2+57>
callq explode_bomb
<phase_2+57>: add $0x4,%rbx
cmp %rbp,%rbx
jne phase_2+42
------------------------------------------------------
rbx = rsp + 8;
rbp = rsp + 24;
<phase_2+42>: eax = [rbx - 8];
eax += [rbx - 4];
if (eax == [rbx]) goto <phase_2+57>;
explode_bomb();
<phase_2+57>: rbx += 4;
if (rbx != rbp) goto phase_2+42;
------------------------------------------------------
rbx = rsp + 8;
rbp = rsp + 24;
do {
eax = [rbx - 8] + [rbx - 4];
if (eax != [rbx]) {
explode_bomb();
}
rbx += 4;
} while (rbx != rbp);
------------------------------------------------------
rbx = 8;
do {
eax = [rsp + rbx - 8] + [rsp + rbx - 4];
if (eax != [rsp + rbx]) {
explode_bomb();
}
rbx += 4;
} while (rbx < 24);
------------------------------------------------------
i = 2;
do {
eax = t[i - 2] + t[i - 1];
if (eax != t[i]) {
explode_bomb();
}
i += 1;
} while (i < 6);
------------------------------------------------------
for (int i = 2; i < 6; i++) {
if (t[i] != t[i - 2] + t[i - 1]) {
explode_bomb();
}
}
Si se toma el tiempo para comprender estas transformaciones, podrá transformar y entender cualquier pieza de ensamblaje.