flxflx / weasel

Public repository of the dynamic binary analysis framework WEASEL. WEASEL's main purpose is the identification and elimination of backdoors in server applications.
15 stars 1 forks source link

Cannot get weasel to work with provided ProFTPD example #2

Open kokkonisd opened 5 months ago

kokkonisd commented 5 months ago

Hello!

Thank you for providing the sources of Weasel.

I have been trying to reproduce some results from your paper. I have managed to get the Python side working by using a 2.7.18 interpreter, installing an old version of pyelftools and modifying pygraph a bit (basically changing module names) to make all the imports work.

I've built the ProFTPD example in bdd-proftpd by running ./configure && make, and the server seems to work just fine by itself. Finally, I'm using the anonymous config for the ProFTPD server (found in the ProFTPD docs), and the Weasel configuration found in examples/proftpd_config.xml. I've also taken care to add a user jochen with password blub0r as described in the config.

It seems to work correctly at first, however it soon crashes:

$ python2.7 wiesel.py examples/proftpd_config.xml 0
[i] Connected to remote GDB server.
[!] Warning: No address of fork function specified. The debugger will not follow forks.
[i] Could not determine address of fork() (or the targets system's equivalent). Debugger will not follow forks.
[i] Resetting debugee (hard: False, keeping breakpoints: False).
[i] Could not determine address of fork() (or the targets system's equivalent). Debugger will not follow forks.
[i] Playing prologue of protocol.
[p] Received 220 ProFTPD 1.3.4a Server (ProFTPD Anonymous Server) [::ffff:127.0.0.1]
.
[p] Adding data USER jochen
.
[p] Sending USER jochen
.
[p] Received 331 Password required for jochen
.
[p] Adding data PASS blub0r
.
[p] Sending PASS blub0r
.
[p] Received 230 User jochen logged in
.
[p] Receive timed-out.
[p] Adding data CDUP.
[i] Stopping the debugger 1.
[i] Going to stop the debugee...
meep
moop
[e] Interrupt signal received for thread e18fe18f.
[e] Leaving the debug-loop. Debugee alive: True, go-on: False
[i] Starting tracer. Playing rest of protocol.
[!] Failed to read 1 bytes from 58686084abd8.
Traceback (most recent call last):
  File "wiesel.py", line 982, in <module>
    for processingGraphs in w.analyzeCmd(FILE_IO_MODE, OUT_DIR, protoStrings):
  File "wiesel.py", line 646, in analyzeCmd
    protoRuns, protoRunInvalid = self._getTracesCmd(self._getFunctionRecorder(fileIoAction, basePathTraceData), protoStrings=protoStrings)
  File "wiesel.py", line 717, in _getTracesCmd
    return self._collectTracesCmd(pl, ps, recorder)
  File "wiesel.py", line 677, in _collectTracesCmd
    run = recorder(procCmd, unrebaseTraces=True)
  File "wiesel.py", line 206, in <lambda>
    return lambda protoProcessor, unrebaseTraces: self.tr.recordCallgraph(protoProcessor, unrebaseTraces=unrebaseTraces, verbose=self.verbose, traceSelector=ThreadSelection.a0Single, basePathTraceData=basePathTraceData, fileIoAction=fileIoAction, maxHits=self.maxHitsFunction, tag=tag)
  File "/home/kokkonis/code/weasel/testbench/recorder.py", line 105, in recordCallgraph
    tr = self._record(ft, protoProcessor, verbose)
  File "/home/kokkonis/code/weasel/testbench/recorder.py", line 61, in _record
    tracer.setup()
  File "/home/kokkonis/code/weasel/pygdb/tracer.py", line 119, in setup
    self._setupCheckpoints(self.checkpoints, self.maxHits)
  File "/home/kokkonis/code/weasel/pygdb/tracer.py", line 127, in _setupCheckpoints
    self.replug()
  File "/home/kokkonis/code/weasel/pygdb/tracer.py", line 292, in replug
    SimpleTracer.replug(self)
  File "/home/kokkonis/code/weasel/pygdb/tracer.py", line 134, in replug
    self.pygdb.setBreakpoints(self.checkpoints.keys(), self._defaultBpHandler, self, GDB.THREADS.ALL)
  File "/home/kokkonis/code/weasel/pygdb/core.py", line 1612, in setBreakpoints
    if not self._setBreakpointRaw(addr, p):
  File "/home/kokkonis/code/weasel/pygdb/core.py", line 1328, in _setBreakpointRaw
    opOrig = self.readMemory(addr, len(opBp), cache=self.useCacheForBreakpoints, pid=pid, fetchLargerRegion=self.useCacheForBreakpoints)
  File "/home/kokkonis/code/weasel/pygdb/core.py", line 1899, in readMemory
    self.processes[_pid].memCache.setRange(addr, memory)
  File "/home/kokkonis/code/weasel/tools/memCache.py", line 84, in setRange
    newMemRange = self.MemRange(offset, data)
  File "/home/kokkonis/code/weasel/tools/memCache.py", line 14, in __init__
    self.update(data)
  File "/home/kokkonis/code/weasel/tools/memCache.py", line 18, in update
    self.size = len(data)
TypeError: object of type 'NoneType' has no len()

And on the gdbserver side:

$ sudo -E env "PATH=$PATH" gdbserver :2204 ./proftpd -c $PWD/anonymous.conf -n
Process ./proftpd created; pid = 57741
Listening on port 2204
Remote debugging from host <addr>, port 51926
GDBserver restarting
Process ./proftpd created; pid = 57743
<hostname> proftpd[57743] <hostname>: ProFTPD 1.3.4a (maint) (built jeu. juin 20 2024 11:39:02 CEST) standalone mode STARTUP
<hostname> proftpd[57745] <hostname> (localhost[127.0.0.1]): FTP session opened.
<hostname> proftpd[57745] <hostname> (localhost[127.0.0.1]): USER jochen: Login successful.
Remote side has terminated connection.  GDBserver will reopen the connection.
Listening on port 2204
<hostname> proftpd[57745] <hostname> (localhost[127.0.0.1]): ProFTPD terminating (signal 2)
<hostname> proftpd[57745] <hostname> (localhost[127.0.0.1]): FTP session closed.

Any ideas about what is causing this?

I realize that this is a very old project at this point, but any pointers would be welcome!