/
turbodiff.cpp
7011 lines (5678 loc) · 228 KB
/
turbodiff.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright 2010 Core Security Technologies.
*
* This file is part of turbodiff, an IDA plugin for analyzing differences
* between binary files.
* The plugin was designed and developed by Nicolas Economou, from the
* Exploit Writers team of Core Security Technologies.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* For further details, see the file COPYING distributed with turbodiff.
*/
/****************************************************************************/
/****************************************************************************/
/* turbodiff.cpp */
/****************************************************************************/
/****************************************************************************/
/* Defines */
#define __NT__
#define COMPILE_IDA_FREE_49
/****************************************************************************/
/****************************************************************************/
/* Includes */
#include <ida.hpp>
#include <idp.hpp>
#include <loader.hpp>
#include <kernwin.hpp>
#include <bytes.hpp>
#include <auto.hpp>
#include <name.hpp>
#include <windows.h>
#include <ctype.h>
#include "list.cpp"
#include "string.cpp"
/****************************************************************************/
/****************************************************************************/
/* Defines */
#define TD_VERSION 0x101B
#define TD_RELEASE 0x01
#define TD_SUBRELEASE 0x01
#define VERSION ( TD_VERSION << 16 ) + ( TD_RELEASE << 8 ) + TD_SUBRELEASE
#define NAME_LEN 256
#define MAX_DISASM 4096
#define MAX_INT 0x7fffffff
#define MIN_INT 0x80000000
#define IDENTICAL_MATCH 0
#define CHANGED_1_MATCH 1
#define CHANGED_2_MATCH 2
#define CHANGED_3_MATCH 3
#define UNMATCHED1_MATCH 4
#define UNMATCHED2_MATCH 5
/****************************************************************************/
/****************************************************************************/
/* Estructuras */
typedef struct
{
unsigned int addr_inicial;
unsigned int addr_final;
unsigned int longitud;
unsigned int longitud_en_bytes;
unsigned int checksum;
int profundidad;
unsigned int profundidad2;
unsigned int peso;
unsigned int pos_file_disasm;
/* Properties usadas para recorrer el grafo */
int visitado;
int id;
/* Properties usadas para diffear funciones */
int association_id;
int change_type;
/* Creo una lista PERSISTENTE para guardar las conexiones con otros basic blocks */
List *basic_blocks_hijos;
/* Creo una lista para guardar las conexiones FUERTES ( llamados a funcion ) */
unsigned int cantidad_referencias;
List *funciones_hijas;
/* Creo una lista PERSISTENTE para guardar las conexiones DEBILES ( vtables ) */
List *ptr_funciones_hijas;
/* Concateno los basic blocks que estan conectados por JUMPs incodicionales */
List *cadena_basic_blocks;
} Basic_Block;
typedef struct
{
void *funcion;
unsigned int direccion_funcion;
unsigned int referencia;
unsigned int checksum;
} Basic_Block_Padre;
typedef struct
{
unsigned int address;
unsigned int pos;
} Referencia_Vtable;
typedef struct
{
/* Datos generales de la funcion */
char name [ NAME_LEN ];
char demangled_name [ NAME_LEN ];
unsigned int address;
unsigned int address_equivalente;
unsigned int longitud;
unsigned int checksum;
unsigned int checksum_real;
unsigned int peso;
char *graph_ecuation;
int identica;
int patcheada;
/* Geometria de la funcion */
unsigned int conexiones_internas;
unsigned int cantidad_basic_blocks;
Basic_Block **basic_blocks;
/* Todas las referencias padres */
unsigned int cantidad_referencias_padre;
Basic_Block_Padre *basic_blocks_padres;
/* Todas las referencias padres por vtables */
List *referencias_padre_x_vtable;
/* Todas las referencias hijas */
unsigned int cantidad_referencias_hijas;
/* Esto es solo decorativo, los valores se dumpean al file directamente */
Basic_Block volcado_basic_blocks [ 0 ];
Basic_Block_Padre volcado_basic_blocks_padres [ 0 ];
Referencia_Vtable volcado_referencias_x_vtable;
} Funcion;
/****************************************************************************/
/****************************************************************************/
/* Prototipos */
int comparar_analisis ( void );
int comparar_funciones ( int );
int get_viewers ( List & , List & );
char *get_substring ( char * , char * );
int analizar_programa ( int );
int analizar_funcion ( unsigned int , Funcion * );
int identificar_basic_blocks ( Funcion * , List & , unsigned int , unsigned int , unsigned int );
int compactar_basic_blocks ( Funcion * , List & );
int suprimir_basic_blocks_vacios ( Funcion * , List & );
int search_value_x_dicotomic_style ( List & , unsigned int );
int get_next_instruction ( unsigned int , unsigned int , unsigned int * );
int is_fin_basic_block ( unsigned int , unsigned int );
int is_referencia_interna ( unsigned int , unsigned int , unsigned int * );
int is_referencia_externa_por_codigo ( unsigned int );
int is_referencia_externa_por_dato ( unsigned int );
int is_call ( unsigned int , unsigned int * );
int is_llamado_a_funcion ( unsigned int , unsigned int * );
int is_funcion ( unsigned int );
int is_inicio_basic_block ( Funcion * , List & , unsigned int );
int tienen_un_mismo_padre ( Funcion * , Funcion * );
Basic_Block *get_basic_block ( List & , unsigned int );
Basic_Block *get_basic_block_from_array ( Basic_Block ** , unsigned int , unsigned int );
unsigned int calcular_longitud_funcion ( List & );
void calcular_checksum_funcion ( List & , unsigned int * , unsigned int * );
unsigned int calcular_cantidad_conexiones_internas ( Funcion * );
unsigned int calcular_cantidad_hijos ( Funcion * );
unsigned int get_cantidad_referencias_padre ( Funcion * , unsigned int );
int get_referencias_padre ( Funcion * );
unsigned int get_cantidad_basic_blocks_padres_from_list ( Funcion * , Basic_Block * , List & );
int get_basic_blocks_padres ( Funcion * , Basic_Block * , List & );
int get_basic_blocks_hijos ( Funcion * , Basic_Block * , List & );
Funcion *get_estructura_funcion ( List & , unsigned int );
Funcion *get_estructura_funcion2 ( List & , List & , unsigned int );
void actualizar_checksum_basic_blocks_padres ( List & , List & , Funcion * );
int get_funcion_padre ( unsigned int , unsigned int * );
int is_ptr_a_funcion ( unsigned int , unsigned int * );
int is_ptr_vtable ( unsigned int );
List *get_funciones_de_vtable ( unsigned int );
int get_funciones_undefined ( unsigned int , unsigned int , List & );
int get_referencias_fcode_from ( unsigned int , List & );
int get_referencias_data_from ( unsigned int , List & );
int get_referencias_to ( unsigned int , List & );
///////////////////////
void setear_profundidad_hacia_abajo ( int , Funcion * , Basic_Block * );
void setear_maxima_profundidad_hacia_abajo ( int , Funcion * , Basic_Block * );
void setear_profundidad_hacia_arriba ( int , Funcion * , Basic_Block * );
unsigned int setear_peso_a_basic_blocks ( unsigned int , Funcion * , Basic_Block * );
void poner_ids_a_basic_blocks ( int , Funcion * , Basic_Block * );
char *generar_ecuacion_de_grafo_de_funcion ( Funcion * );
Basic_Block *get_basic_block_by_id ( Funcion * , int );
Basic_Block *get_basic_block_by_association_id ( Funcion * , int );
void liberar_basic_blocks ( Funcion * );
///////////////////////
int guardar_analisis ( char * );
int guardar_desensamblado ( char * );
int guardar_desensamblado_de_funcion ( FILE * , Funcion * );
char *get_instruction ( unsigned int , char * , unsigned int );
///////////////////////
int comparar_files ( char * , char * , char * , int );
void get_formated_name ( Funcion * , char * , unsigned int , int );
int levantar_funciones ( FILE * , List & , List & );
int asociar_funciones ( int , Funcion * , Funcion * , List & , List & , List & , List & );
int tienen_el_mismo_nombre ( Funcion * , Funcion * );
int reconocer_funciones_con_misma_geometria ( List & , List & , List & , List & );
unsigned int reconocer_funciones_x_vtables ( List & , List & , List & , List & , List & , List & );
int son_funciones_equivalentes_x_vtables ( List & , List & , Funcion * , Funcion * );
int son_funciones_iguales ( Funcion * , Funcion * );
int son_funciones_cuasi_identicas ( Funcion * , Funcion * );
int es_funcion_patcheada ( Funcion * , List & , Funcion ** );
int get_funcion_equivalente_x_grafo ( int , Funcion * , Funcion * , Basic_Block * , List & , Funcion * , Funcion ** , Basic_Block * );
int is_condicion_invertida ( Funcion * , Funcion * , Basic_Block * , Basic_Block * );
int is_camino_confiable ( unsigned int , unsigned int , Funcion * , Funcion * , Basic_Block * , Basic_Block * );
int get_funcion_equivalente_x_hijos ( Funcion * , List & , List & , Funcion ** );
int get_funcion_equivalente_x_hijos_x_padres_en_comun ( Funcion * , List & , List & , Funcion ** );
int get_funcion_equivalente_x_hijos_x_unico_padre ( Funcion * , List & , List & , Funcion ** );
int clasificar_funciones_cambiadas ( List & , List & , List & , List & );
///////////////////////
/* Funciones asociadas con el muestreo de los resultados */
int armar_resultados ( void );
int guardar_resultados ( char * , char * );
int levantar_resultados ( char * , char * );
int mostrar_resultados ( char * , char * );
unsigned int mostrar_funciones ( unsigned int );
///////////////////////
int diffear_funciones ( int , char * , char * );
int diffear_y_mostrar_funciones ( char * , char * , Funcion * , Funcion * );
int diffear_funcion_por_grafo ( Funcion * , Funcion * );
int diffear_funcion_recorriendo_grafo ( Funcion * , Funcion * , Basic_Block * , Basic_Block * , unsigned int * );
int diffear_funcion_usando_ids ( Funcion * , Funcion * , unsigned int * );
int diffear_funcion_por_mejor_probabilidad ( Funcion * , Funcion * , unsigned int * );
unsigned int get_porcentaje_equivalencia ( unsigned int , unsigned int , Funcion * , Funcion * , Basic_Block * , Basic_Block * );
int recorrer_camino_de_equivalencia ( unsigned int , unsigned int , Funcion * , Funcion * , Basic_Block * , Basic_Block * , unsigned int * , unsigned int * , unsigned int * );
int is_reverted_condition ( Funcion * , Funcion * , Basic_Block * , Basic_Block * );
unsigned int get_change_type ( Basic_Block * , Basic_Block * );
int armar_grafo_salida ( char * , char * , char * , Funcion * );
void mostrar_grafo ( char * );
void mostrar_grafos ( char * , char * );
void get_ida_path ( unsigned int , char * );
///////////////////////
int buscar_funciones_equivalentes ( char * , char * );
/****************************************************************************/
/****************************************************************************/
/* Variables globales */
static char *comment = "turbodiff v1.01b r1.1";
static char *help = "...";
static char wanted_name[] = "turbodiff v1.01b r1.1";
static char wanted_hotkey[] = "Ctrl-F11";
// Version de la aplicacion
unsigned int turbodiff_version = VERSION;
// Puntero a la funcion que interfacea desde IDA con los usuarios
void *ptr_callui;
/* Ubicacion del IDB abierto */
char *idb_path;
// Lista donde voy a guardar la info de todas las funciones del programa
List indice_funciones;
List funciones;
List indice_funciones1;
List funciones1;
List indice_funciones2;
List funciones2;
// Listas donde guardo el resultado del analisis
List funciones1_reconocidas;
List funciones2_reconocidas;
List funciones1_matcheadas;
List funciones2_matcheadas;
List funciones1_geometricamente_identicas;
List funciones2_geometricamente_identicas;
List funciones1_cambiadas;
List funciones2_cambiadas;
List funciones1_irreconocidas;
List funciones2_irreconocidas;
List funciones1_levantadas;
List funciones2_levantadas;
List funciones1_intermedias;
List funciones1_intermedias2;
// Lista donde guardo las direcciones de file1 equivalentes a las funciones de file2
List address_equivalentes;
// Lista donde guardo las direcciones iniciales y finales de los basic blocks
List basic_blocks;
// Lista donde guardo los basic blocks que se unen con otros
List basic_blocks_compuestos [ 2 ];
// Lista donde guardo todas las referencias padre de codigo NO asociado a una funcion
List referencias_undefined;
// Lista donde guardo todas las funciones UNDEFINEDs
List undefined_functions;
// Listas donde guardo el CALL GRAPH de los programas
List *call_graph1;
List *call_graph2;
// Listas donde guardo, en orden, todos los matcheos
List matcheo_1_2;
List resultado1;
List resultado2;
// Archivo donde guarde los resultados
char result_file [ QMAXPATH ];
// Indica que visualizador usar
int visualizador = 0;
// Listas donde guardo el ID del visualizador + el path
List viewer_names;
List viewer_paths;
/****************************************************************************/
/****************************************************************************/
int my_msg ( const char *format , ... )
{
bool ( *my_callui ) ( int , const char * , ... );
int nbytes;
va_list va;
/* Resuelvo el simbolo */
( unsigned int ) my_callui = * ( unsigned int * ) ptr_callui;
/* Inicializo la lista para parsear los parametros */
va_start ( va , format );
/* Imprimo el mensaje */
nbytes = my_callui ( ui_msg , format , va );
/* Reseteo la lista */
va_end(va);
return ( nbytes );
}
/****************************************************************************/
int my_askaddr ( ea_t *addr , const char *format , ... )
{
bool ( *my_callui ) ( int , ea_t * , const char * , ... );
va_list va;
int ret;
/* Resuelvo el simbolo */
( unsigned int ) my_callui = * ( unsigned int * ) ptr_callui;
/* Inicializo la lista para parsear los parametros */
va_start ( va , format );
/* Imprimo el mensaje */
ret = my_callui ( ui_askaddr , addr , format , va );
/* Reseteo la lista */
va_end(va);
return ( ret );
}
/****************************************************************************/
int my_AskUsingForm ( const char *format , ... )
{
bool ( *my_callui ) ( int , const char * , ... );
va_list va;
int code;
/* Resuelvo el simbolo */
( unsigned int ) my_callui = * ( unsigned int * ) ptr_callui;
/* Inicializo la lista */
va_start ( va , format );
/* Muestro al usuario las opciones */
code = my_callui ( ui_form , format , va );
/* Reseteo la lista */
va_end(va);
return code;
}
/****************************************************************************/
// ui_askaddr, // * Ask an address
// Parameters:
// ea_t *answer
// const char *format
// va_list va
// Returns: bool success
// ui_askfile, // * Ask the user a file name
// Parameters:
// int savefile
// const char *default_answer
// const char *format
// va_list va
// Returns: file name
/****************************************************************************/
char *my_askfile ( int savefile , const char *default_answer , const char *format , ... )
{
char *( *my_callui ) ( int , int , const char * , const char * , ... );
va_list va;
char *file;
/* Resuelvo el simbolo */
( unsigned int ) my_callui = * ( unsigned int * ) ptr_callui;
/* Inicializo la lista para parsear los parametros */
va_start ( va , format );
/* Imprimo el mensaje */
file = my_callui ( ui_askfile , savefile , default_answer , format , va );
/* Reseteo la lista */
va_end(va);
return ( file );
}
/****************************************************************************/
void my_close_chooser ( char *title )
{
char *( *my_callui ) ( int , char * );
/* Resuelvo el simbolo */
( unsigned int ) my_callui = * ( unsigned int * ) ptr_callui;
/* Imprimo el mensaje */
my_callui ( ui_close_chooser , title );
}
/****************************************************************************/
unsigned int my_choose ( bool flags , int x1 , int y1 , int x2 , int y2 , void *obj , unsigned int columnas , int *ancho , void *size_function , void *description_function , void *enter_function , void *destroy_function , unsigned int pos )
{
int ( *my_callui ) ( int , int , int , ... );
unsigned int ret;
/* Resuelvo el simbolo */
( unsigned int ) my_callui = * ( unsigned int * ) ptr_callui;
/* Imprimo el mensaje */
ret = my_callui ( ui_choose,
chtype_generic2,
flags,
x1, y1, x2, y2,
obj,
columnas,
ancho,
size_function,
description_function,
"Turbodiff results",
-1,
pos,
NULL,
NULL,
NULL,
NULL,
enter_function,
destroy_function,
NULL,
NULL
);
return ( ret );
}
/****************************************************************************/
void get_actual_idb_name ( char *idb_name )
{
/* Copio el nombre del IDB */
qstrncpy ( idb_name , idb_path , strlen ( idb_path ) );
}
/****************************************************************************/
void change_extension ( char *filename , char *extension )
{
char *punto;
/* Busco el punto */
punto = strrchr ( filename , '.' );
/* Reemplazo las extenciones ".idb" por la nueva extension */
qstrncpy ( punto + 1 , extension , QMAXPATH - strlen ( filename ) );
}
/****************************************************************************/
char *version = " v1.01b r1.1";
static const char pantalla_inicial [] =
"Choose operation\n"
"turbodiff v1.01b r1.1\n"
"Created by Nicolas A. Economou ( neconomou@corest.com )\n"
"Buenos Aires, Argentina ( 2010 )\n"
"\n"
"options\n"
"<take info from this idb:R>"
"<compare with ...:R>"
"<load results from ...:R>"
"<free comparison with ...:R>>"
//"<search equivalent functions (experimental):R>>"
"\n\n\n\n\n\n";
static const char files_a_analizar [] =
"Take the analysis\n"
"turbodiff v1.01b r1.1\n"
"Created by Nicolas A. Economou ( neconomou@corest.com )\n"
"Buenos Aires, Argentina ( 2010 )\n"
"\n\n"
"Important: The analysis will be saved on the current idb path.\n"
"\n\n"
"<analize undefined functions:C>>"
"\n\n";
static const char files_a_comparar [] =
"Select options to compare\n"
"turbodiff v1.01b r1.1\n"
"Created by Nicolas A. Economou ( neconomou@corest.com )\n"
"Buenos Aires, Argentina ( 2010 )\n"
"\n"
//"<patterns\t:A:32:16::>"
"\n"
"<log file\t:A:256:16::>"
"\n"
"\t<use symbols:C>>"
"\n\n"
"\n\n";
static const char funciones_a_comparar [] =
"Write function addresses to compare\n"
"turbodiff v1.01b r1.1\n"
"Created by Nicolas A. Economou ( neconomou@corest.com )\n"
"Buenos Aires, Argentina ( 2010 )\n"
"\n\n"
"<function1\t:$:500:16:::>\n"
"\n"
"<function2\t:$:500:16:::>\n"
"\n\n";
static const char funciones_a_buscar [] =
"turbodiff v1.01b r1.1\n"
"Write only one address functions to search\n"
"\n"
"<function1\t:$:500:16:::>\n"
"\n"
"<function2\t:$:500:16:::>\n"
"\n";
/****************************************************************************/
/****************************************************************************/
int __stdcall init ( void )
{
return PLUGIN_OK;
}
/****************************************************************************/
void __stdcall run ( int arg )
{
String *menu;
String *viewer;
String *vname;
char current_path [ QMAXPATH ];
char fviewer [ QMAXPATH ];
char file1 [ QMAXPATH ];
char file2 [ QMAXPATH ];
char *file;
unsigned int initial_time;
unsigned int final_time;
unsigned int cont;
int tipo_operacion = 0;
int analizar_undefined_functions = FALSE;
int ret;
#ifndef COMPILE_IDA_FREE_49
/* Resuelvo el puntero a la funcion "callui" */
ptr_callui = GetProcAddress ( GetModuleHandle ( "ida.wll" ) , "callui" );
/* Averiguo el PATH del IDB actual */
idb_path = ( char * ) GetProcAddress ( GetModuleHandle ( "ida.wll" ) , "database_idb" );
#else
/* Resuelvo el puntero a la funcion "callui" */
ptr_callui = ( void * ) ( ( unsigned int ) GetModuleHandle ( "ida.wll" ) + 0xd2364 );
/* Averiguo el PATH del IDB actual */
idb_path = ( char * ) ( ( unsigned int ) GetModuleHandle ( "ida.wll" ) + 0xf9698 );
#endif
/////////////////////////
/* Obtengo la lista de viewers disponibles */
get_viewers ( viewer_names , viewer_paths );
/* String donde van a ir a parar la lista de visualizadores disponibles */
viewer = new ( String );
/* Si hay algun visualizador */
if ( viewer_names.Len () > 0 )
{
/* Visualizadores disponibles */
viewer -> Append ( "viewer\n" );
/* Recorro todos los viewers levantados del archivo de configuracion */
for ( cont = 0 ; cont < viewer_names.Len () ; cont ++ )
{
/* Obtengo el siguiente ID */
vname = ( String * ) viewer_names.Get ( cont );
/* Fabrico el TAG para el viewer */
qsnprintf ( fviewer , QMAXPATH , "<%s:R>" , vname -> Get () );
/* Agrego el siguiente viewer */
viewer -> Append ( fviewer );
}
/* Cierro la lista de viewers */
viewer -> Append ( ">" );
/* Agrego un ENTER por cada n lineas */
for ( cont = 0 ; cont < viewer_names.Len () ; cont ++ )
{
/* Por cada 4 lineas agrego un ENTER demas */
if ( cont % 4 == 0 )
{
/* Agrego dos ENTER */
viewer -> Append ( "\n\n" );
}
else
{
/* Agrego un ENTER */
viewer -> Append ( "\n" );
}
}
}
/* Fabrico las opciones */
menu = new ( String );
menu -> Set ( pantalla_inicial );
menu -> Append ( ( char * ) viewer -> Get () );
/* Menu inicio */
ret = my_AskUsingForm ( menu -> Get () , &tipo_operacion , &visualizador );
/* Si el usuario apreto ESC */
if ( ret != 1 )
{
/* Salgo */
return;
}
//////////////////////////
// do_unknown ( 0x40a9c0 , 0 );
// do_data_ex ( 0x40a9c0 , 0x20000400 , 4 , -1 );
// return;
//////////////////////////
/* Si el usuario quiere analizar files */
if ( tipo_operacion == 0 )
{
/* Pido al usuario la funcion a analizar */
ret = my_AskUsingForm ( files_a_analizar , &analizar_undefined_functions );
/* Si el usuario apreto ESC */
if ( ret != 1 )
{
/* Salgo */
return;
}
}
/* Si el usuario quiere diffear funciones */
else if ( tipo_operacion == 2 )
{
/* Comparo las funciones */
comparar_funciones ( TRUE );
/* Salgo porque el usuario apreto ESCAPE */
return;
}
/* Si el usuario quiere comparar cualquier funcion contra cualquier funcion */
else if ( tipo_operacion == 3 )
{
/* Comparo las funciones */
comparar_funciones ( FALSE );
/* Salgo porque el usuario apreto ESCAPE */
return;
}
/* Tomo el tiempo actual */
initial_time = GetTickCount ();
/* Mensaje para el usuario */
my_msg ( "\nworking ...\n" );
/* Si tengo que sacar un analisis */
if ( tipo_operacion == 0 )
{
/* Levanto todas las funciones del programa */
analizar_programa ( analizar_undefined_functions );
/* Obtengo el nombre del IDB actual */
get_actual_idb_name ( file1 );
/* Cambio la extension para guardar el desensamblado */
change_extension ( file1 , "dis" );
/* Mensaje al usuario */
my_msg ( "generating %s\n" , file1 );
/* Guardo el desensamblado */
guardar_desensamblado ( file1 );
/* Cambio la extension para guardar el desensamblado */
change_extension ( file1 , "ana" );
/* Mensaje al usuario */
my_msg ( "generating %s\n" , file1 );
/* Guardo el analisis */
guardar_analisis ( file1 );
}
else
{
/* Comparo los analisis tomados previamente */
comparar_analisis ();
/* Salgo */
return;
}
/* Tomo el tiempo final */
final_time = GetTickCount ();
/* Mensaje al usuario */
my_msg ( "elapsed time: %u.%u sec.\n" , ( final_time - initial_time ) / 1000 , ( final_time - initial_time ) % 1000 );
my_msg ( "done\n" );
}
/****************************************************************************/
int get_viewers ( List &viewer_names , List &viewer_paths )
{
FILE *fviewers;
String *viewer;
String *path;
char ida_path [ MAX_PATH ];
char buffer [ MAX_PATH ];
char *end_token;
char *token;
char *vname;
char *vpath;
int ret = TRUE;
/* Obtengo la ruta de IDA */
get_ida_path ( QMAXPATH , ida_path );
/* Apunto al file de configuracion en la carpeta de plugins */
qstrncat ( ida_path , "\\plugins\\turbodiff.cfg" , QMAXPATH );
/* Abro el archivo de configuracion de viewers */
fviewers = qfopen ( ida_path , "rt" );
/* Si pude abrir el archivo */
if ( fviewers != NULL )
{
/* Levanto la siguiente linea */
while ( qfgets ( buffer , MAX_PATH , fviewers ) != 0 )
{
/* Si es un comentario */
if ( buffer [ 0 ] == '#' )
{
/* Paso a la siguiente linea */
continue;
}
/* Apunto al inicio del buffer */
token = get_substring ( buffer , "::" );
/* Si pude obtener un token y es una declaracion del tipo "viewer" */
if ( ( token != NULL ) && ( strcmp ( token , "viewer" ) == 0 ) )
{
/* Obtengo el nombre del viewer */
token = get_substring ( NULL , "::" );
vname = token;
/* Si pude obtener el nombre del viewer */
if ( token != NULL )
{
/* Obtengo el path del viewer */
token = get_substring ( NULL , "\r\n" );
vpath = token;
/* Si pude obtener el path */
if ( token != NULL )
{
/* Creo los strings para guardar el nombre y el path del viewer */
viewer = new ( String );
path = new ( String );
/* Seteo el nombre del viewer */
viewer -> Set ( vname );
/* Seteo el nombre del viewer */
path -> Set ( vpath );
/* Agrego el viewer a la lista */
viewer_names.Add ( viewer );
viewer_paths.Add ( path );
}
}
}
}
}
/* Si NO pude abrir el archivo */
else
{
/* El archivo de configuracion NO existe */
ret = FALSE;
}
/* Cierro el archivo de configuracion */
qfclose ( fviewers );
return ( ret );
}
/****************************************************************************/
char *get_substring ( char *string , char *separator )
{
static char *ostring = NULL;
char *end_string = NULL;
char *substring;
/* Si tengo que procesar un string NUEVO */
if ( string != NULL )
{
/* Obtengo el inicio del string */
ostring = string;
}
/* String a retornar */
substring = ostring;
/* Si esta abierta la busqueda */
if ( ostring != NULL )
{
/* Busco el separador en el string */
end_string = strstr ( ostring , separator );
}
/* Si obtuve un substring */
if ( end_string != NULL )
{
/* Cierro el string donde empieza el separador */
*end_string = '\x00';
/* Me posiciono despues del separador */
ostring = end_string + strlen ( separator );
}
/* Si NO obtuve un substring */
else
{
/* Cierro la busqueda */
ostring = NULL;
}
return ( substring );
}
/****************************************************************************/
int comparar_analisis ( void )
{
char current_path [ QMAXPATH ];
char log_file [ QMAXPATH ];
char file1 [ QMAXPATH ];
char file2 [ QMAXPATH ];
char *file;
unsigned int initial_time;
unsigned int final_time;
int usar_simbolos = TRUE;
int ret = TRUE;
/* Obtengo el path del IDB actual */
get_actual_idb_name ( file1 );
/* Pregunto al usuario donde esta el file que quiero comparar */
file = my_askfile ( FALSE , "*.idb" , "Choose the file to compare" );
/* Si tengo el nombre del segundo file */
if ( file != NULL )
{
/* Hago una copia del path completo del idb */
qstrncpy ( current_path , file1 , QMAXPATH );
/* Busco la barra invertida */
if ( strrchr ( current_path , '\\' ) != NULL )
{
/* Cierro el string donde empieza la ultima barra */
* ( strrchr ( current_path , '\\' ) ) = '\0';
}
/* Seteo el nombre del archivo por default */
qsnprintf ( log_file , QMAXPATH , "%s\\results.txt" , current_path );
/* Mensaje al usuario con las opciones a comparar */
if ( my_AskUsingForm ( files_a_comparar , log_file , &usar_simbolos ) == TRUE )
{
/* Tomo el tiempo actual */
initial_time = GetTickCount ();
/* Me quedo con el nombre del segundo file */
qstrncpy ( file2 , file , strlen ( file ) );
/* Reemplazo las extenciones ".idb" por ".ana" */
change_extension ( file1 , "ana" );
change_extension ( file2 , "ana" );
/* Comparo el analisis de los 2 archivos */
if ( comparar_files ( file1 , file2 , log_file , usar_simbolos ) == FALSE )
{
/* Mensaje de ERROR */
MessageBox ( NULL , "cannot load analysis files" , "ERROR" , MB_ICONERROR | MB_TOPMOST );
/* Salgo */
return ( FALSE );
}
/* Tomo el tiempo final */
final_time = GetTickCount ();
/* Mensaje al usuario */
my_msg ( "elapsed time: %u.%u sec.\n" , ( final_time - initial_time ) / 1000 , ( final_time - initial_time ) % 1000 );
/* Armo los pares de funciones matcheadas en listas */