Skip to content

Commit c362747

Browse files
authored
Merge pull request #480 from 4B5F5F4B/master
enable TinyInst instrumentation mode for winafl-cmin.py
2 parents 92311a1 + 23bc808 commit c362747

File tree

3 files changed

+124
-37
lines changed

3 files changed

+124
-37
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ add_executable(afl-showmap
7373
afl-showmap.c
7474
)
7575

76+
if (${TINYINST})
77+
target_link_libraries(afl-showmap winafl_tinyinst)
78+
endif()
79+
7680
project(afl-tmin)
7781

7882
add_executable(afl-tmin

afl-showmap.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@
5050
#include <sys/stat.h>
5151
#include <sys/types.h>
5252

53+
#ifdef TINYINST
54+
int tinyinst_init(int argc, char** argv);
55+
void tinyinst_set_fuzzer_id(char* fuzzer_id);
56+
int tinyinst_run(char** argv, uint32_t timeout);
57+
void tinyinst_killtarget();
58+
#endif
59+
60+
5361
static s32 child_pid; /* PID of the tested program */
5462

5563
static HANDLE child_handle,
@@ -87,6 +95,7 @@ static u8 quiet_mode, /* Hide non-essential messages? */
8795
cmin_mode, /* Generate output in afl-cmin mode? */
8896
binary_mode, /* Write output as a binary map */
8997
drioless = 0; /* Running without DRIO? */
98+
use_tinyinst = 0; /* Using TinyInst instrumentation */
9099

91100
static volatile u8
92101
stop_soon, /* Ctrl-C pressed? */
@@ -572,6 +581,13 @@ static void destroy_target_process(int wait_exit) {
572581
STARTUPINFO si;
573582
PROCESS_INFORMATION pi;
574583

584+
#ifdef TINYINST
585+
if (use_tinyinst) {
586+
tinyinst_killtarget();
587+
return;
588+
}
589+
#endif
590+
575591
EnterCriticalSection(&critical_section);
576592

577593
if(!child_handle) {
@@ -675,6 +691,13 @@ static int is_child_running() {
675691

676692
static void run_target(char** argv) {
677693

694+
695+
#ifdef TINYINST
696+
if (use_tinyinst) {
697+
return tinyinst_run(argv, exec_tmout);
698+
}
699+
#endif
700+
678701
char command[] = "F";
679702
DWORD num_read;
680703
char result = 0;
@@ -963,15 +986,24 @@ int main(int argc, char** argv) {
963986
optind = 1;
964987
dynamorio_dir = NULL;
965988
client_params = NULL;
989+
use_tinyinst = 0;
966990

967991
#ifdef USE_COLOR
968992
enable_ansi_console();
969993
#endif
970994

971-
while ((opt = getopt(argc, argv, "+o:m:t:A:D:eqZQbY")) > 0)
972-
995+
while ((opt = getopt(argc, argv, "+o:m:t:A:D:eqyZQbY")) > 0)
973996
switch (opt) {
974997

998+
case 'y':
999+
#ifdef TINYINST
1000+
use_tinyinst = 1;
1001+
#else
1002+
FATAL("afl-fuzz was not compiled with TinyInst support");
1003+
#endif
1004+
break;
1005+
1006+
9751007
case 'D': /* dynamorio dir */
9761008

9771009
if(dynamorio_dir) FATAL("Multiple -D options not supported");
@@ -1094,13 +1126,30 @@ int main(int argc, char** argv) {
10941126

10951127
if(!out_file) usage(argv[0]);
10961128
if(!drioless) {
1097-
if(optind == argc || !dynamorio_dir) usage(argv[0]);
1129+
if(optind == argc || (!dynamorio_dir && !use_tinyinst)) usage(argv[0]);
10981130
}
10991131

1100-
extract_client_params(argc, argv);
1132+
if (use_tinyinst) {
1133+
#ifdef TINYINST
1134+
int tinyinst_options = tinyinst_init(argc - optind, argv + optind);
1135+
if (!tinyinst_options) usage(argv[0]);
1136+
optind += tinyinst_options;
1137+
#endif
1138+
} else {
1139+
extract_client_params(argc, argv);
1140+
}
11011141
optind++;
11021142

11031143
setup_shm();
1144+
1145+
if (use_tinyinst) {
1146+
#ifdef TINYINST
1147+
tinyinst_set_fuzzer_id(fuzzer_id);
1148+
#endif
1149+
}
1150+
1151+
1152+
11041153
setup_watchdog_timer();
11051154
setup_signal_handlers();
11061155

winafl-cmin.py

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -66,23 +66,27 @@ def _to_showmap_options(args, trace_name = '-'):
6666
if args.static_instr:
6767
r.append('-Y')
6868
else:
69-
r.extend(['-D', args.dynamorio_dir])
70-
r.append('--')
71-
r.extend(['-target_module', args.target_module])
69+
if args.tinyinst_instr:
70+
r.append('-y')
71+
r.append('--')
72+
for mod in args.instrument_modules:
73+
r.extend(['-instrument_module', mod])
74+
else:
75+
r.extend(['-D', args.dynamorio_dir])
76+
r.append('--')
77+
for mod in args.coverage_modules:
78+
r.extend(['-coverage_module', mod])
7279

80+
r.extend(['-target_module', args.target_module])
7381
if args.target_method is None:
7482
r.extend(['-target_offset', '0x%x' % args.target_offset])
7583
else:
7684
r.extend(['-target_method', args.target_method])
77-
7885
r.extend(['-nargs', '%d' % args.nargs])
7986
r.extend(['-covtype', args.covtype])
8087
if args.call_convention is not None:
8188
r.extend(['-call_convention', args.call_convention])
8289

83-
for mod in args.coverage_modules:
84-
r.extend(['-coverage_module', mod])
85-
8690
r.append('--')
8791
r.extend(args.target_cmdline)
8892
return r
@@ -179,6 +183,9 @@ def setup_argparse():
179183
180184
* Typical use with static instrumentation
181185
winafl-cmin.py -Y -t 100000 -i in -o minset -- test.instr.exe @@
186+
187+
* Typical use with TinyInst mode instrumentation
188+
winafl-cmin.py -y -t 100000 -i in -o minset -instrument_module m.dll -target_module test.exe -target_method fuzz -nargs 2 -- test.exe @@
182189
'''
183190
), 100, replace_whitespace = False))
184191
)
@@ -227,6 +234,26 @@ def setup_argparse():
227234
metavar = 'dir', help = 'directory containing DynamoRIO binaries (drrun, drconfig)'
228235
)
229236

237+
instr_type.add_argument(
238+
'-y', '--tinyinst_instr', action = 'store_true',
239+
help = 'use the TinyInst instrumentation mode'
240+
)
241+
242+
243+
instr_module = group.add_mutually_exclusive_group(required = True)
244+
instr_module.add_argument(
245+
'-coverage_module', dest = 'coverage_modules', default = None,
246+
action = 'append', metavar = 'module', help = 'module for which to record coverage.'
247+
' Multiple module flags are supported'
248+
)
249+
250+
instr_module.add_argument(
251+
'-instrument_module', dest = 'instrument_modules', default = None,
252+
action = 'append', metavar = 'module', help = 'module for which to record coverage.'
253+
' Multiple module flags are supported'
254+
)
255+
256+
230257
group.add_argument(
231258
'-covtype', choices = ('edge', 'bb'), default = 'bb',
232259
help = 'the type of coverage being recorded (defaults to bb)'
@@ -235,15 +262,12 @@ def setup_argparse():
235262
'-call_convention', choices = ('stdcall', 'fastcall', 'thiscall', 'ms64'),
236263
default = 'stdcall', help = 'the calling convention of the target_method'
237264
)
238-
group.add_argument(
239-
'-coverage_module', dest = 'coverage_modules', default = None,
240-
action = 'append', metavar = 'module', help = 'module for which to record coverage.'
241-
' Multiple module flags are supported'
242-
)
265+
243266
group.add_argument(
244267
'-target_module', default = None, metavar = 'module',
245268
help = 'module which contains the target function to be fuzzed'
246269
)
270+
247271
group.add_argument(
248272
'-nargs', type = int, default = None, metavar = 'nargs',
249273
help = 'number of arguments the fuzzed method takes. This is used to save/restore'
@@ -261,6 +285,7 @@ def setup_argparse():
261285
help = 'offset of the method to fuzz from the start of the module'
262286
)
263287

288+
264289
group = parser.add_argument_group('execution control settings')
265290
group.add_argument(
266291
'-t', '--time-limit', type = int, default = 0,
@@ -370,35 +395,44 @@ def validate_args(args):
370395
return False
371396

372397
if not args.static_instr:
373-
# Make sure we have all the arguments we need
374-
if len(args.coverage_modules) == 0:
375-
logging.error(
376-
'[!] -coverage_module is a required option to use'
377-
'the dynamic instrumentation'
378-
)
379-
return False
380-
381398
if None in [args.target_module, args.nargs]:
382-
logging.error(
383-
'[!] , -target_module and -nargs are required'
384-
' options to use the dynamic instrumentation mode.'
385-
)
386-
return False
387-
399+
logging.error(
400+
'[!] , -target_module and -nargs are required'
401+
' options to use the dynamic instrumentation mode.'
402+
)
403+
return False
404+
388405
if args.target_method is None and args.target_offset is None:
389406
logging.error(
390407
'[!] -target_method or -target_offset is required to use the'
391408
' dynamic instrumentation mode'
392409
)
393410
return False
411+
412+
if not args.tinyinst_instr:
413+
# Make sure we have all the arguments we need
414+
if len(args.coverage_modules) == 0:
415+
logging.error(
416+
'[!] -coverage_module is a required option to use'
417+
'the dynamic instrumentation'
418+
)
419+
return False
394420

395-
# If we are using DRIO, one of the thing we need is the DRIO client
396-
winafl_path = os.path.join(args.working_dir, 'winafl.dll')
397-
if not os.path.isfile(winafl_path):
398-
logging.error(
399-
'[!] winafl.dll needs to be in %s.', args.working_dir
400-
)
401-
return False
421+
# If we are using DRIO, one of the thing we need is the DRIO client
422+
winafl_path = os.path.join(args.working_dir, 'winafl.dll')
423+
if not os.path.isfile(winafl_path):
424+
logging.error(
425+
'[!] winafl.dll needs to be in %s.', args.working_dir
426+
)
427+
return False
428+
else:
429+
# Make sure we have all the arguments we need
430+
if len(args.instrument_modules) == 0:
431+
logging.error(
432+
'[!] -instrument_module is a required option to use'
433+
'the dynamic instrumentation'
434+
)
435+
return False
402436

403437
if args.file_read is not None and '@@' not in args.file_read:
404438
# When a particular input file is specified, first

0 commit comments

Comments
 (0)