HexHive / T-Fuzz

247 stars 39 forks source link

tfuzz did not consider cannot-renamed programs #14

Open zjuchenyuan opened 5 years ago

zjuchenyuan commented 5 years ago

There is a type of programs whose behaviour depend to which name they are. busybox is a good example, only one file is real ELF file and others are just symlink to it.

In this scenario, it's important for fuzzer to keep the original ELF filename, otherwise desired program behaviour will not be triggered and fuzzed.

I want to fuzz infotocap, which is a symlink to tic

But tfuzz actually runs: (which means it has been renamed to infotocap_tfuzz)

 /usr/bin/afl-unix/afl-fuzz -i /d/output/reruninfotocap_tfuzz6_1/fuzzing_infotocap_tfuzz/infotocap_tfuzz/input -o /d/output/reruninfotocap_tfuzz6_1/fuzzing_infotocap_tfuzz/infotocap_tfuzz/sync -m 8G -M fuzzer-master -x /d/output/reruninfotocap_tfuzz6_1/infotocap.dict -- /d/output/reruninfotocap_tfuzz6_1/infotocap_tfuzz/infotocap_tfuzz -o /dev/null @@

Could you consider this type of program? Thanks~

gannimo commented 5 years ago

When preparing the fuzzing environment, why don't you rename the binary to tic, solving the problem by setting up the environment instead of changing tfuzz?

(Changing tfuzz to observe and keep the filename is somewhat harder, it would be easier to simply rename the binaries during setup. Another option is to fudge the arguments as they are passed to main).

Let me know if any of these work for you.

benquike commented 5 years ago

@zjuchenyuan let me clarify a little bit. So your problem is that the target program you are running is a symbolic link to another file. When T-Fuzz generates modified (transformed) program, it does not handle symbolic links properly and only handles the link file, not the target file the link file points to.

Am I correct? If yes, the quick way to solve it is to use the target binary directly during fuzzing.

zjuchenyuan commented 5 years ago

Thanks for your reply, let me clarify the problem. @gannimo @benquike

The target program need to be named as infotocap exactly, and cannot be changed during the fuzzing process.

The behaviour of this program depends to what the name is it, different name leads to different behaviour:

# echo "123456">/tmp/a.txt
# cp infotocap x
# cp infotocap tic
# ./infotocap /tmp/a.txt
123456:\
        :bl=^G:cr=\r:do=\n:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:ta=^I:
# ./tic /tmp/a.txt
# ./x /tmp/a.txt

I want to fuzz infotocap, and compiled the tic ELF binary, and renamed it to infotocap, no symlink is involved here.

I want fuzzer to keep the original ELF name rather than renaming it before fuzzing.


More detailed strace output: infotocap just read the file, but tic write an output file.

# strace ./infotocap /tmp/a.txt
execve("./infotocap", ["./infotocap", "/tmp/a.txt"], 0x7fffffffe638 /* 21 vars */) = 0
brk(NULL)                               = 0x712000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=42733, ...}) = 0
mmap(NULL, 42733, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7fec000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fea000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff79e4000
mprotect(0x7ffff7bcb000, 2097152, PROT_NONE) = 0
mmap(0x7ffff7dcb000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7ffff7dcb000
mmap(0x7ffff7dd1000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dd1000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7ffff7feb540) = 0
mprotect(0x7ffff7dcb000, 16384, PROT_READ) = 0
mprotect(0x70f000, 4096, PROT_READ)     = 0
mprotect(0x7ffff7ffc000, 4096, PROT_READ) = 0
munmap(0x7ffff7fec000, 42733)           = 0
stat("/tmp/a.txt", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
brk(NULL)                               = 0x712000
brk(0x733000)                           = 0x733000
openat(AT_FDCWD, "/tmp/a.txt", O_RDONLY) = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
read(3, "123456\n", 4096)               = 7
lseek(3, 0, SEEK_CUR)                   = 7
lseek(3, 0, SEEK_CUR)                   = 7
read(3, "", 4096)                       = 0
lseek(3, 0, SEEK_SET)                   = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
write(1, "123456:\\\n", 9123456:\
)              = 9
write(1, "\t:bl=^G:cr=\\r:do=\\n:kb=^H:kd=\\n:"..., 59  :bl=^G:cr=\r:do=\n:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:ta=^I:
) = 59
lseek(3, 0, SEEK_SET)                   = 0
read(3, "123456\n", 4096)               = 7
read(3, "", 4096)                       = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
# strace ./tic /tmp/a.txt
execve("./tic", ["./tic", "/tmp/a.txt"], 0x7fffffffe638 /* 21 vars */) = 0
brk(NULL)                               = 0x712000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=42733, ...}) = 0
mmap(NULL, 42733, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7fec000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fea000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff79e4000
mprotect(0x7ffff7bcb000, 2097152, PROT_NONE) = 0
mmap(0x7ffff7dcb000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7ffff7dcb000
mmap(0x7ffff7dd1000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dd1000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7ffff7feb540) = 0
mprotect(0x7ffff7dcb000, 16384, PROT_READ) = 0
mprotect(0x70f000, 4096, PROT_READ)     = 0
mprotect(0x7ffff7ffc000, 4096, PROT_READ) = 0
munmap(0x7ffff7fec000, 42733)           = 0
stat("/tmp/a.txt", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
brk(NULL)                               = 0x712000
brk(0x733000)                           = 0x733000
openat(AT_FDCWD, "/tmp/a.txt", O_RDONLY) = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
read(3, "123456\n", 4096)               = 7
lseek(3, 0, SEEK_CUR)                   = 7
lseek(3, 0, SEEK_CUR)                   = 7
read(3, "", 4096)                       = 0
stat("/d/prog/6infotocap.afl/bin/share/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/d/prog/6infotocap.afl/bin/share/terminfo", R_OK|W_OK|X_OK) = 0
chdir("/d/prog/6infotocap.afl/bin/share/terminfo") = 0
getcwd("/d/prog/6infotocap.afl/bin/share/terminfo", 4096) = 42
stat("1", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("1", R_OK|W_OK|X_OK)             = 0
access("1/123456", W_OK)                = 0
openat(AT_FDCWD, "1/123456", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(4, "\32\1\7\0\0\0\0\0\207\0\23\000123456\0\0\377\377\0\0\2\0\377\377\377\377\377\377"..., 309) = 309
close(4)                                = 0
stat("1/123456", {st_mode=S_IFREG|0644, st_size=309, ...}) = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
zjuchenyuan commented 5 years ago

I would suggest change this 2 lines:

https://github.com/HexHive/T-Fuzz/blob/14777b03c96129965081834ae1f1841c5de631a2/tfuzz/tfuzz_sys.py#L53-L54

change to:

        original_tprogram_path = os.path.join(original_tprogram_dir,
                                              self.origin_binary_name)

https://github.com/HexHive/T-Fuzz/blob/14777b03c96129965081834ae1f1841c5de631a2/tfuzz/tfuzz_sys.py#L198

change to:

transformed_program_path = os.path.join(transformed_program_dir, self.origin_binary_name)