boofuzz icon indicating copy to clipboard operation
boofuzz copied to clipboard

Can't update a primitive value, runtime error in s_update()

Open lgrangeia opened this issue 6 years ago • 7 comments

I'm not sure I'm doing this right. I wish to have a primitive that will change its value depending on the fuzz run.

For example, beforoe calling fuzz() I want to change the value of the static primitive "stuff":

    s_initialize("encryption_req")
    with s_block("encryption_payload"):
        s_static("value", name="stuff")

...


    s_switch("encryption_req")
    s_update("stuff", "new_value") # this throws an error, why?

I get the following error:

  File "./test.py", line 53, in <module>
    main()
  File "./test.py", line 41, in main
    s_update("encryption_payload", "1")
  File "/home/lgrangeia/.local/lib/python2.7/site-packages/boofuzz/__init__.py", line 328, in s_update
    if name not in blocks.CURRENT:
TypeError: argument of type 'Request' is not iterable

Edit: tested in 0.0.8 and latest from git (0.0.12)

lgrangeia avatar Jun 19 '18 10:06 lgrangeia

Looks like a bug in boofuzz. I don't have your full sample code to test, but you can try replacing line 328 with:

    if name not in blocks.CURRENT.walk():

jtpereyda avatar Jun 19 '18 19:06 jtpereyda

@lgrangeia PS let me know if it works so we can get it patched.

jtpereyda avatar Jun 20 '18 02:06 jtpereyda

It didn't work (new error though).

Here's the full code for my test case:

#!/usr/bin/env python

import argparse
import socket
import time
from boofuzz import *

def main():
    parser = argparse.ArgumentParser()

    connection = Target(SocketConnection(host="1.2.3.4", port=1))
    session = sessions.Session(sleep_time=3, fuzz_data_logger=None)
    session.add_target(connection)

    s_initialize("request")
    s_string(name="stuff", value="value")

    print s_render()

    s_switch("request")
    s_update(name="stuff", value="newvalue")

    print s_render()

    #session.fuzz()

if __name__ == "__main__":
    main()

Let me know if you need more info. Thank you for helping.

Regards,

LG

lgrangeia avatar Jun 20 '18 09:06 lgrangeia

Looks like the following line works:

    if name not in map(lambda o: o.name, blocks.CURRENT.walk()):

It's likely this used to work before a major refactor.

Thanks for the issue! Please let me know if this fix works for you. I've uploaded it on the branch fix-s-update and made a pull request (#190).

Edit: Note: I tried it with your script and it at least seems to run now. I haven't tested the functionality any further than that.

jtpereyda avatar Jun 22 '18 03:06 jtpereyda

Hello Joshua,

Yes, the script runs, but not with the expected output. My idea is:

    s_initialize("request")
    s_string(name="stuff", value="value")

    print s_render()

    s_switch("request")
    s_update(name="stuff", value="newvalue")

    print s_render()

This should render different values. my idea is to call fuzz() twice, first before s_update() then after, in order to fuzz with different default string values. Does that make sense?

right now s_update is not updating the default value of the string primitive:

$ ./test.py
value
value

lgrangeia avatar Jun 25 '18 12:06 lgrangeia

@lgrangeia please pardon me for the long delay. I was not aware of s_update before.

The String class (boofuzz/boofuzz/primitives/string.py) does not have a value property but rather a private _value property. This was part of me trying to incorporate the programming practice of encapsulation. Apparently I missed this case.

That said, s_update is rather and unusual and it could end up going away.

Given your description of wanting to fuzz once and then fuzz again, I think we can find another approach. Have you considered creating different messages? The code for this would look something like:

s_initialize("request")
s_string(name="stuff", value="value")

s_initialize("newrequest")
s_update(name="newstuff", value="newvalue")

And when connecting to your Session:

session.connect(s_get("request"))
session.connect(s_get("newrequest"))

This adds two nodes off of root -- two independent protocol messages. See http://boofuzz.readthedocs.io/en/latest/user/quickstart.html for more context for this kind of example.

Let me know if this seems like a good fit for your use case. If not, maybe we should fix s_update, or look into other options.

In case you're wondering why I lean away from s_update, it's because the protocol definition itself should be static, and in the ideal case a close mapping to the actual protocol. Using different default values makes me wonder if this is:

  1. A different kind of message in the same protocol.
  2. A special, specifically requested mutation.
  3. Or something else.

jtpereyda avatar Jul 11 '18 06:07 jtpereyda

@lgrangeia I also merged the PR. Thank you for the bug report!

jtpereyda avatar Jul 11 '18 06:07 jtpereyda