Skip to content

Commit 9f952d3

Browse files
committed
Add cmplog realization (afl++-style)
1 parent fb3d215 commit 9f952d3

File tree

2 files changed

+186
-17
lines changed

2 files changed

+186
-17
lines changed

include/cmplog.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
american fuzzy lop++ - cmplog header
3+
------------------------------------
4+
5+
Originally written by Michal Zalewski
6+
7+
Forkserver design by Jann Horn <[email protected]>
8+
9+
Now maintained by Marc Heuse <[email protected]>,
10+
Heiko Eissfeldt <[email protected]>,
11+
Andrea Fioraldi <[email protected]>,
12+
Dominik Maier <[email protected]>
13+
14+
Copyright 2016, 2017 Google Inc. All rights reserved.
15+
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
16+
17+
Licensed under the Apache License, Version 2.0 (the "License");
18+
you may not use this file except in compliance with the License.
19+
You may obtain a copy of the License at:
20+
21+
https://www.apache.org/licenses/LICENSE-2.0
22+
23+
Shared code to handle the shared memory. This is used by the fuzzer
24+
as well the other components like afl-tmin, afl-showmap, etc...
25+
26+
*/
27+
28+
#ifndef _AFL_CMPLOG_H
29+
#define _AFL_CMPLOG_H
30+
31+
#include <stdint.h>
32+
#include "config.h"
33+
34+
#define CMPLOG_LVL_MAX 3
35+
36+
#define CMP_MAP_W 65536
37+
#define CMP_MAP_H 32
38+
#define CMP_MAP_RTN_H (CMP_MAP_H / 2)
39+
40+
#define SHAPE_BYTES(x) (x + 1)
41+
42+
#define CMP_TYPE_INS 0
43+
#define CMP_TYPE_RTN 1
44+
45+
struct cmp_header { // 16 bit = 2 bytes
46+
47+
unsigned hits : 6; // up to 63 entries, we have CMP_MAP_H = 32
48+
unsigned shape : 5; // 31+1 bytes max
49+
unsigned type : 1; // 2: cmp, rtn
50+
unsigned attribute : 4; // 16 for arithmetic comparison types
51+
52+
} __attribute__((packed));
53+
54+
struct cmp_operands {
55+
56+
uint64_t v0;
57+
uint64_t v0_128;
58+
uint64_t v0_256_0; // u256 is unsupported by any compiler for now, so future use
59+
uint64_t v0_256_1;
60+
uint64_t v1;
61+
uint64_t v1_128;
62+
uint64_t v1_256_0;
63+
uint64_t v1_256_1;
64+
uint8_t unused[8]; // 2 bits could be used for "is constant operand"
65+
66+
} __attribute__((packed));
67+
68+
struct cmpfn_operands {
69+
70+
uint8_t v0[32];
71+
uint8_t v0_len;
72+
uint8_t v1[32];
73+
uint8_t v1_len;
74+
75+
} __attribute__((packed));
76+
77+
typedef struct cmp_operands cmp_map_list[CMP_MAP_H];
78+
79+
struct cmp_map {
80+
81+
struct cmp_header headers[CMP_MAP_W];
82+
struct cmp_operands log[CMP_MAP_W][CMP_MAP_H];
83+
84+
};
85+
86+
/* Execs the child */
87+
88+
struct afl_forkserver;
89+
void cmplog_exec_child(struct afl_forkserver *fsrv, char **argv);
90+
91+
#endif
92+

unicornafl.cpp

Lines changed: 94 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "unicornafl.h"
22
#include "config.h"
33
#include "priv.h"
4+
#include "cmplog.h"
45

56
#include <cstdio>
67
#include <cstdlib>
@@ -398,9 +399,7 @@ class UCAFL {
398399
}
399400
}
400401

401-
void _uc_hook_sub_impl(uint64_t cur_loc, uint64_t arg1, uint64_t arg2,
402-
uint32_t size) {
403-
402+
void _uc_hook_cmpcov(uint64_t cur_loc, uint64_t arg1, uint64_t arg2, uint32_t size) {
404403
if (size >= 64) {
405404
if (unlikely(MAP_SIZE - cur_loc < 8))
406405
cur_loc -= 8;
@@ -416,6 +415,53 @@ class UCAFL {
416415
}
417416
}
418417

418+
void _uc_hook_cmplog(uint64_t cur_loc, uint64_t arg1, uint64_t arg2, uint32_t size) {
419+
struct cmp_map* map = this->cmpmap_;
420+
421+
uintptr_t k = (uintptr_t)cur_loc & (CMP_MAP_W - 1);
422+
uint32_t shape = 0;
423+
switch (size) {
424+
case 16:
425+
shape = 1;
426+
break;
427+
case 32:
428+
shape = 3;
429+
break;
430+
case 64:
431+
shape = 7;
432+
break;
433+
default:
434+
break;
435+
}
436+
437+
// get hits count
438+
uint16_t hits;
439+
if (map->headers[k].type != CMP_TYPE_INS) {
440+
map->headers[k].type = CMP_TYPE_INS;
441+
map->headers[k].hits = 1;
442+
map->headers[k].shape = shape;
443+
hits = 0;
444+
} else {
445+
hits = map->headers[k].hits++;
446+
if (map->headers[k].shape < shape) {
447+
map->headers[k].shape = shape;
448+
}
449+
}
450+
451+
hits &= CMP_MAP_H - 1;
452+
map->log[k][hits].v0 = arg1;
453+
map->log[k][hits].v1 = arg2;
454+
}
455+
456+
void _uc_hook_sub_impl(uint64_t cur_loc, uint64_t arg1, uint64_t arg2,
457+
uint32_t size) {
458+
if (this->has_cmplog_) {
459+
return _uc_hook_cmplog(cur_loc, arg1, arg2, size);
460+
}
461+
462+
_uc_hook_cmpcov(cur_loc, arg1, arg2, size);
463+
}
464+
419465
static void _uc_hook_sub_cmp(uc_engine* uc, uint64_t address, uint64_t arg1,
420466
uint64_t arg2, uint32_t size,
421467
void* user_data) {
@@ -462,23 +508,27 @@ class UCAFL {
462508
exit(1);
463509
}
464510

465-
// These two hooks are for compcov and may not be supported by the arch.
466-
err = uc_hook_add(this->uc_, &this->h3_, UC_HOOK_TCG_OPCODE,
467-
(void*)_uc_hook_sub, (void*)this, 1, 0, UC_TCG_OP_SUB,
468-
UC_TCG_OP_FLAG_DIRECT);
511+
// If we should use Laf-Intel or Red-Queen do add CMP hooks
512+
if (this->has_cmpcov_ || this->has_cmplog_) {
469513

470-
if (err) {
471-
ERR("Failed to setup UC_TCG_OP_SUB direct hook.\n");
472-
exit(1);
473-
}
514+
// These two hooks may not be supported by the arch.
515+
err = uc_hook_add(this->uc_, &this->h3_, UC_HOOK_TCG_OPCODE,
516+
(void*)_uc_hook_sub, (void*)this, 1, 0, UC_TCG_OP_SUB,
517+
UC_TCG_OP_FLAG_DIRECT);
474518

475-
err = uc_hook_add(this->uc_, &this->h4_, UC_HOOK_TCG_OPCODE,
476-
(void*)_uc_hook_sub_cmp, (void*)this, 1, 0,
477-
UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP);
519+
if (err) {
520+
ERR("Failed to setup UC_TCG_OP_SUB direct hook.\n");
521+
exit(1);
522+
}
478523

479-
if (err) {
480-
ERR("Failed to setup UC_TCG_OP_SUB cmp hook.\n");
481-
exit(1);
524+
err = uc_hook_add(this->uc_, &this->h4_, UC_HOOK_TCG_OPCODE,
525+
(void*)_uc_hook_sub_cmp, (void*)this, 1, 0,
526+
UC_TCG_OP_SUB, UC_TCG_OP_FLAG_CMP);
527+
528+
if (err) {
529+
ERR("Failed to setup UC_TCG_OP_SUB cmp hook.\n");
530+
exit(1);
531+
}
482532
}
483533
}
484534

@@ -528,6 +578,29 @@ class UCAFL {
528578

529579
this->has_afl_ = false;
530580
}
581+
582+
char* cmplog_map_id_str = getenv(CMPLOG_SHM_ENV_VAR);
583+
this->has_cmpcov_ = !!getenv("UNICORN_AFL_CMPCOV");
584+
585+
if (cmplog_map_id_str) {
586+
if (this->has_cmpcov_) {
587+
ERR("CMPLOG and CMPCOV turned on at the same time!\n");
588+
ERR("I'll turn off CMPCOV.\n");
589+
this->has_cmpcov_ = false;
590+
}
591+
592+
int cmplog_map_id = atoi(cmplog_map_id_str);
593+
this->cmpmap_ = (struct cmp_map*)shmat(cmplog_map_id, NULL, 0);
594+
595+
if (this->cmpmap_ == (void*)-1) {
596+
ERR("Can't get the afl cmp-mapping area.\n");
597+
exit(0);
598+
}
599+
600+
this->has_cmplog_ = true;
601+
} else {
602+
this->has_cmplog_ = false;
603+
}
531604
}
532605

533606
uc_afl_ret _fksrv_start() {
@@ -867,6 +940,10 @@ class UCAFL {
867940
uint32_t afl_inst_rms_;
868941
uint64_t afl_prev_loc_;
869942

943+
bool has_cmpcov_;
944+
bool has_cmplog_;
945+
struct cmp_map* cmpmap_;
946+
870947
// Fake signal value
871948
int wifsignaled_;
872949

0 commit comments

Comments
 (0)