question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Testing driller with a program that reads a file

See original GitHub issue

Hi, all. I want to test the driller with a program that reads a file, like djpeg. First, I want to test a very simple example,

#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char** argv) {
  int fd = open(argv[1], O_RDONLY);
  int input = 0;
  read(fd, &input, sizeof(input));

  if (input == 0xdeadbeef)
    printf("Good");

  close(fd);
}

To do it, I modified the following line to get fs, and argv.

        s = p.factory.tracer_state(input_content=self.input, magic_content=r.magic, args=self.argv, fs=self._fs)                                                                                            

And run the driller as follows

    input_file = 'sample/input.bin'                                                                                                                                                                         
    binary = 'sample/main'                                                                                                                                                                                  
                                                                                                                                                                                                            
    with open(input_file, 'rb') as f:                                                                                                                                                                       
        inputs = f.read()                                                                                                                                                                                   
                                                                                                                                                                                                            
    fs = {input_file: simuvex.storage.file.SimFile(input_file, "rb", size=os.path.getsize(input_file))}                                                                                                     
    d = driller.Driller(binary, inputs, argv=[binary, input_file], fs=fs)                                                                                                                                   
    for drilled in d.drill_generator():                                                                                                                                                                     
        print(drilled)        

The input_file is just “AAAA”. But unfortunately, I couldn’t get 0xdeadbeef. Driller generates a testcase, but it was just empty string. I checked that open() returns SimFile. Could you let me know where do I have to take a look? Thanks.

Issue Analytics

  • State:open
  • Created 6 years ago
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
insuyuncommented, Apr 19, 2018

@agarciagonzalez FYI, this is my code for reading file input using driller. This uses kinda bug in the angr that it treats /dev/stdin as a normal file, and it lets us do file operations such as lseek. @salls Do you think it will be fine? I didn’t change any core part of driller, but the qemu part(to get file as input), and use /dev/stdin if we use angr.

import os
import copy
import logging

import angr
import driller
import tracer

l = logging.getLogger("driller.driller_file")

# logging.getLogger("angr.state_plugins.posix").setLevel(logging.DEBUG)

# commit: c536408e9d70b8b0743db55efb9aa2e7e96c5601

# NOTE: The file path should be absolute path!
# argv should be ['./binary', '@/tmp/input_file.txt']

def patch_argv_qemu(argv):
    patched_argv = copy.copy(argv)
    index = -1
    for i, arg in enumerate(argv):
        if arg.startswith("@"):
            patched_argv[i] = argv[i][1:]
            assert(index == -1)
            index = i
    return patched_argv


def patch_argv_angr(argv):
    patched_argv = copy.copy(argv)
    index = -1
    for i, arg in enumerate(argv):
        if arg.startswith("@"):
            patched_argv[i] = "/dev/stdin"
            assert(index == -1)
            index = i
    return patched_argv


class DrillerFile(driller.Driller):
    def _parse_size(self):
        input_file = None
        for i, arg in enumerate(self.argv):
            if arg.startswith("@"):
                assert(input_file is None)
                input_file = self.argv[i][1:]
 
        return os.path.getsize(input_file)


    def _drill_input(self):
        """
        Symbolically step down a path with a tracer, trying to concretize inputs for unencountered
        state transitions.
        """

        # initialize the tracer
        r = tracer.qemu_runner.QEMURunner(self.binary, self.input, argv=patch_argv_qemu(self.argv))
        p = angr.Project(self.binary)
        for addr, proc in self._hooks.items():
            p.hook(addr, proc)
            l.debug("Hooking %#x -> %s...", addr, proc.display_name)

        if p.loader.main_object.os == 'cgc':
            p.simos.syscall_library.update(angr.SIM_LIBRARIES['cgcabi_tracer'])

        files = {'/dev/stdin': angr.storage.file.SimFile("/dev/stdin", "r", size=self._parse_size())}
        s = p.factory.tracer_state(input_content=self.input, magic_content=r.magic, args=patch_argv_angr(self.argv), fs=files)

        simgr = p.factory.simgr(s, save_unsat=True, hierarchy=False, save_unconstrained=r.crash_mode)

        t = angr.exploration_techniques.Tracer(trace=r.trace)
        c = angr.exploration_techniques.CrashMonitor(trace=r.trace, crash_mode=r.crash_mode, crash_addr=r.crash_addr)
        self._core = angr.exploration_techniques.DrillerCore(trace=r.trace)

        simgr.use_technique(c)
        simgr.use_technique(t)
        simgr.use_technique(angr.exploration_techniques.Oppologist())
        simgr.use_technique(self._core)

        self._set_concretization s(simgr.one_active)

        l.debug("Drilling into %r.", self.input)
        l.debug("Input is %r.", self.input)

        while simgr.active and simgr.one_active.globals['bb_cnt'] < len(r.trace):
            simgr.step()

            # Check here to see if a crash has been found.
            if self.redis and self.redis.sismember(self.identifier + '-finished', True):
                return

            if 'diverted' not in simgr.stashes:
                continue

            while simgr.diverted:
                state = simgr.diverted.pop(0)
                l.debug("Found a diverted state, exploring to some extent.")
                w = self._writeout(state.history.bbl_addrs[-1], state)
                if w is not None:
                    yield w
                for i in self._symbolic_explorer_stub(state):
                    yield i
        print(r.trace, simgr.one_active.globals['bb_cnt'])
2reactions
sallscommented, Nov 7, 2017

Driller is heavily hardcoded to use stdin. You’ll have to find in tracer where it preconstrains the input and make it use the file instead. And you’ll have to look at where driller dumps inputs, because it’s also just dumping stdin. It will definitely require some work to change from using stdin to using an input file.

The other option, if it doesn’t use stdin. Is to hook/change the file reads so they read from stdin instead. Then you can use driller as is

Read more comments on GitHub >

github_iconTop Results From Across the Web

Drill and test software - The OLPC Wiki
1 Testing software for classroom evaluation (traditional exams) · 2 Drill software · 3 Software for scheduling constructionist activities or teaching vocabulary, ...
Read more >
Solved 1: Create a Java Program titled "Driller" Your - Chegg
Question: 1: Create a Java Program titled "Driller" Your program will read the drilling data file—a text file in which data fields are...
Read more >
Text Files: CSV, TSV, PSV - Apache Drill
Drill reads CSV, TSV, and PSV files into a list of VARCHARS, ... You can use code to achieve this, as you can...
Read more >
Disk Drill Data Recovery Software | Free Download | CleverFiles
Let us know if you are interested in helping us beta-test this feature. Recover All File Types. Disk Drill, a professional Windows data...
Read more >
Junit a application that reads a file and processes it
A simple solution: change your interfaces to be easy to test. Meaning: have one method that puts together a file name "in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found