.. _examples:
Examples
========================
This page includes some basic examples of creating and parsing CybOX content.
There are a couple things we do in these examples for purposes of demonstration
that shouldn't be done in production code:
* When calling ``to_xml()``, we use ``include_namespaces=False``. This is to
make the example output easier to read, but means the resulting output
cannot be successfully parsed. The XML parser doesn't know what namespaces
to use if they aren't included. In production code, you should explicitly
set ``include_namespaces`` to ``True`` or omit it entirely (``True`` is the
default).
* We use ``set_id_method(IDGenerator.METHOD_INT)`` to make IDs for Objects and
Observables easier to read and cross-reference within the XML document. In
production code, you should omit this statement, which causes random UUIDs to
be created instead, or create explicit IDs yourself for objects and
observables.
Creating Objects
-------------------
The easiest way to create an object is to construct one and then set various
properties on it.
.. testcode::
from cybox.objects.file_object import File
f = File()
f.file_name = "malware.exe"
f.file_path = "C:\Windows\Temp\malware.exe"
print f.to_xml(include_namespaces=False)
Which outputs:
.. testoutput::
malware.exe
C:\Windows\Temp\malware.exe
For some objects, such as the AddressObject, you can pass parameters direcly
into the constructor.
.. testcode::
from cybox.objects.address_object import Address
a = Address("1.2.3.4", Address.CAT_IPV4)
print a.to_xml(include_namespaces=False)
.. testoutput::
1.2.3.4
Creating Observables
--------------------
Full CybOX documents are expected to have ``Observables`` as the root element.
You can pass any object to the ``Observables`` constructor to generate the
proper XML.
.. testcode::
from cybox.core import Observables
from cybox.objects.file_object import File
from cybox.utils import IDGenerator, set_id_method
set_id_method(IDGenerator.METHOD_INT)
f = File()
f.file_name = "malware.exe"
f.file_path = "C:\Windows\Temp\malware.exe"
print Observables(f).to_xml(include_namespaces=False)
.. testoutput::
malware.exe
C:\Windows\Temp\malware.exe
To include multiple objects as individual Observables within one document, you
can pass them as a list to the Observables constructor.
.. testcode::
from cybox.core import Observables
from cybox.objects.address_object import Address
from cybox.objects.uri_object import URI
from cybox.utils import IDGenerator, set_id_method
set_id_method(IDGenerator.METHOD_INT)
a = Address("1.2.3.4", Address.CAT_IPV4)
u = URI("http://cybox.mitre.org/")
print Observables([a, u]).to_xml(include_namespaces=False)
.. testoutput::
1.2.3.4
http://cybox.mitre.org/
HTTP Message Body
-----------------
When outputing XML, by default, reserved XML characters such as < and > are
escaped by default.
.. testcode::
from cybox.objects.http_session_object import HTTPMessage
m = HTTPMessage()
m.message_body = "
An HTML pageBody text
"
m.length = len(m.message_body.value)
print m.to_xml(include_namespaces=False)
.. testoutput::
69
<html><title>An HTML page</title><body><p>Body text</p></body></html>
When you parse this content, these characters are converted back.
.. testcode::
from cybox.bindings.http_session_object import parseString
m2 = HTTPMessage.from_obj(parseString(m.to_xml()))
print m2.message_body
.. testoutput::
An HTML pageBody text
HTTP User Agent
---------------
.. testcode::
from cybox.objects.http_session_object import *
fields = HTTPRequestHeaderFields()
fields.user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0'
header = HTTPRequestHeader()
header.parsed_header = fields
request = HTTPClientRequest()
request.http_request_header = header
req_res = HTTPRequestResponse()
req_res.http_client_request = request
session = HTTPSession()
session.http_request_response = [req_res]
print session.to_xml(include_namespaces=False)
.. testoutput::
Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0
Objects with DateTime properties
--------------------------------
When setting DateTime properties on objects, you can either use a native Python
``datetime.datetime`` or a string. The ``python-dateutil`` library is used
to parse strings into dates, so a wide variety of formats is supported.
.. testcode::
import datetime
from cybox.objects.email_message_object import EmailMessage
e = EmailMessage()
e.from_ = "spammer@spam.com"
e.subject = "This is not spam"
e.date = datetime.datetime(2012, 1, 17, 8, 35, 6)
print e.to_xml(include_namespaces=False)
.. testoutput::
spammer@spam.com
This is not spam
2012-01-17T08:35:06
.. testcode::
from cybox.objects.email_message_object import EmailMessage
e = EmailMessage()
e.date = "Mon, 14 Oct, 2013 12:32:03 -0500"
print e.to_xml(include_namespaces=False)
.. testoutput::
2013-10-14T12:32:03-05:00
Hashes
------
In many cases you can pass a dictionary or a list to create an instance of a
CybOX type.
.. testcode::
from cybox.common import HashList
h = HashList.from_list([{'type' : 'MD5', 'simple_hash_value' : 'FFFFFF'},
{'type' : 'SHA1', 'simple_hash_value' : 'FFFFFF'}])
print h.to_xml(include_namespaces=False)
.. testoutput::
MD5
FFFFFF
SHA1
FFFFFF
This can easily be incorporated into constructing objects as well.
.. testcode::
from cybox.objects.win_file_object import WinFile
f = WinFile()
f.file_name = "foo.exe"
f.drive = "C:\\"
f.hashes = h
print f.to_xml(include_namespaces=False)
.. testoutput::
foo.exe
MD5
FFFFFF
SHA1
FFFFFF
C:\
Object Subclasses
-----------------
The WindowsFile object is a subclass of the File object. As you can see,
the correct namepaces for the various properties are set.
.. testcode::
from cybox.objects.win_file_object import WinFile
f = WinFile()
f.file_name = "blah.exe"
f.drive = "C:\\"
print f.to_xml(include_namespaces=False)
.. testoutput::
blah.exe
C:\
As another example, the WinUser object is a refinement of the UserAccount
object, which itself is a refinement of the Account object. As with Hashes,
these can be constructed from a dictionary representation.
.. testcode::
from cybox.objects.win_user_object import WinUser
winuser_dict = {
# Account-specific fields
'disabled': False,
'domain': u'ADMIN',
# UserAccount-specific fields
'password_required': True,
'full_name': u"Steve Ballmer",
'home_directory': u"C:\\Users\\ballmer\\",
'last_login': "2011-05-12T07:14:01+07:00",
'username': u"ballmer",
'user_password_age': u"P180D",
# WinUser-specific fields
'security_id': u"S-1-5-21-3623811015-3361044348-30300820-1013",
'security_type': "SidTypeUser",
'xsi:type': 'WindowsUserAccountObjectType',
}
print WinUser.from_dict(winuser_dict).to_xml(include_namespaces=False)
.. testoutput::
:options: +NORMALIZE_WHITESPACE
ADMIN
Steve Ballmer
C:\Users\ballmer\
2011-05-12T07:14:01+07:00
ballmer
P180D
S-1-5-21-3623811015-3361044348-30300820-1013
SidTypeUser
ObservableCompositions
----------------------
.. testcode::
from cybox.core import Observable, Observables, ObservableComposition
from cybox.objects.file_object import File
from cybox.objects.process_object import Process
from cybox.utils import IDGenerator, set_id_method
set_id_method(IDGenerator.METHOD_INT)
observables = Observables()
proc = Process.from_dict(
{"name": "cmd.exe",
"image_info": {"command_line": "cmd.exe /c blah.bat"}})
proc.name.condition = "Equals"
proc.image_info.command_line.condition = "Contains"
oproc = Observable(proc)
observables.add(oproc)
f = File.from_dict({"file_name": "blah", "file_extension": "bat"})
f.file_name.condition = "Contains"
f.file_extension.condition = "Equals"
ofile = Observable(f)
observables.add(ofile)
oproc_ref = Observable()
oproc_ref.id_ = None
oproc_ref.idref = oproc.id_
ofile_ref = Observable()
ofile_ref.id_ = None
ofile_ref.idref = ofile.id_
o_comp = ObservableComposition(operator="OR")
o_comp.add(oproc_ref)
o_comp.add(ofile_ref)
observables.add(Observable(o_comp))
print observables.to_xml(include_namespaces=False)
.. testoutput::
cmd.exe
cmd.exe /c blah.bat
blah
bat
Parsing example
---------------
Just as you can call ``to_xml()`` to generate XML, you can call ``parseString``
to parse an XML string.
.. doctest::
>>> import cybox.bindings.file_object as file_binding
>>> from cybox.objects.file_object import File
>>> a = """
...
... bad.exe
...
... """
>>> file_obj = file_binding.parseString(a)
>>> type(file_obj)
>>> f = File.from_obj(file_obj)
>>> f.file_name.value
'bad.exe'
>>> str(f.file_name)
'bad.exe'
>>> f.file_name.condition
'Contains'
Comparisons
-----------
CybOX objects can be compared for equality using the standard Python equality
operator. By default, every field must be equal between the two objects.
However, you can explicitly say that some fields should not be considered.
.. doctest::
>>> from cybox.objects.file_object import File
>>> file_1 = File.from_dict({'file_name': 'abcd.dll', 'size_in_bytes': '25556'})
>>> file_2 = File.from_dict({'file_name': 'abcd.dll', 'size_in_bytes': '25556'})
>>> file_3 = File.from_dict({'file_name': 'abcd.dll', 'size_in_bytes': '1337'})
# First, disable the use of ``size_in_bytes`` comparisons.
>>> File.size_in_bytes.comparable = False
>>> file_1 == file_2
True
>>> file_1 == file_3
True
# Now, set it back to True (the default).
>>> File.size_in_bytes.comparable = True
>>> file_1 == file_2
True
>>> file_1 == file_3
False