branch: master
Switch branches/tags
Nothing to show
tom5760
file 383 lines (282 sloc) 13.514 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
#!/usr/bin/env python
'''
pylorcon2 - Python wrapper for LORCON 2
By: Tom Wambold <tom5760@gmail.com>
Home: http://github.com/tom5760/pylorcon2/
LORCON: http://802.11ninja.net/

'''

import ctypes
from ctypes.util import find_library

class LorconError(Exception): pass

class StructLorcon(ctypes.Structure): pass

# Function Pointers
LORCON_DRV_INIT = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.POINTER(StructLorcon))
LORCON_DRV_PROBE = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p)

# Forward declare this struct
class StructDriver(ctypes.Structure):
    pass

# We need to do this since this struct references itself
StructDriver._fields_ = (
        ('name', ctypes.c_char_p),
        ('details', ctypes.c_char_p),

        ('init_func', LORCON_DRV_INIT),
        ('probe_func', LORCON_DRV_PROBE),

        ('next', ctypes.POINTER(StructDriver)),
    )

class Lorcon(object):
    'Represents the LORCON library.'

    def __init__(self, lib_path=None):
        '''Instantiate the LORCON library.

lib_path - Path to LORCON shared library. If None, it is autodetected.

'''

        if lib_path is None:
            # Look for -lorcon2
            lib_path = find_library('orcon2')

        self.lib = ctypes.cdll.LoadLibrary(lib_path)

        # Set argument and return types for functions
        self.lib.lorcon_list_drivers.argtypes = None
        self.lib.lorcon_list_drivers.restype = ctypes.POINTER(StructDriver)

        self.lib.lorcon_find_driver.argtypes = [ctypes.c_char_p]
        self.lib.lorcon_find_driver.restype = ctypes.POINTER(StructDriver)

        self.lib.lorcon_auto_driver.argtypes = [ctypes.c_char_p]
        self.lib.lorcon_auto_driver.restype = ctypes.POINTER(StructDriver)

        self.lib.lorcon_free_driver_list.argtypes = [ctypes.POINTER(StructDriver)]
        self.lib.lorcon_free_driver_list.restype = None

        self.lib.lorcon_create.argtypes = [ctypes.c_char_p,
                ctypes.POINTER(StructDriver)]
        self.lib.lorcon_create.restype = ctypes.POINTER(StructLorcon)

        self.lib.lorcon_free.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_free.restype = None

        self.lib.lorcon_get_error.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_error.restype = ctypes.c_char_p

        self.lib.lorcon_get_timeout.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_timeout.restype = ctypes.c_int

        self.lib.lorcon_set_timeout.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.c_int]
        self.lib.lorcon_set_timeout.restype = None

        self.lib.lorcon_set_timeout.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_set_timeout.restype = ctypes.c_int

        self.lib.lorcon_open_inject.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_open_inject.restype = ctypes.c_int
        self.lib.lorcon_open_inject.errcheck = self._errcheck_int

        self.lib.lorcon_open_monitor.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_open_monitor.restype = ctypes.c_int
        self.lib.lorcon_open_monitor.errcheck = self._errcheck_int

        self.lib.lorcon_get_vap.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_vap.restype = ctypes.c_char_p

        self.lib.lorcon_set_vap.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.c_char_p]
        self.lib.lorcon_set_vap.restype = None

        self.lib.lorcon_get_capiface.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_capiface.restype = ctypes.c_char_p

        self.lib.lorcon_get_driver_name.argtypes = [
                ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_driver_name.restype = ctypes.c_char_p

        # TODO: These are not implemented in Lorcon2 yet
        #self.lib.lorcon_get_datalink.argtypes = [ctypes.POINTER(StructLorcon)]
        #self.lib.lorcon_get_datalink.restype = ctypes.c_int

        #self.lib.lorcon_set_datalink.argtypes = [ctypes.POINTER(StructLorcon),
        # ctypes.c_int]
        #self.lib.lorcon_set_datalink.restype = ctypes.c_int
        #self.lib.lorcon_set_datalink.errcheck = self._errcheck_int

        self.lib.lorcon_get_channel.argtypes = [ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_channel.restype = ctypes.c_int

        self.lib.lorcon_set_channel.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.c_int]
        self.lib.lorcon_set_channel.restype = ctypes.c_int
        self.lib.lorcon_set_channel.errcheck = self._errcheck_int

        self.lib.lorcon_get_hwmac.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.POINTER(ctypes.POINTER(ctypes.c_uint8))]
        self.lib.lorcon_get_hwmac.restype = ctypes.c_int
        self.lib.lorcon_get_hwmac.errcheck = self._errcheck_int

        self.lib.lorcon_set_hwmac.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.c_int, ctypes.POINTER(ctypes.c_uint8)]
        self.lib.lorcon_set_hwmac.restype = ctypes.c_int
        self.lib.lorcon_set_hwmac.errcheck = self._errcheck_int

        self.lib.lorcon_get_pcap.argtypes = [ctypes.POINTER(StructLorcon)]
        # TODO: Maybe make a real ctypes type for this? Should be struct pcap_t
        self.lib.lorcon_get_pcap.restype = ctypes.c_void_p

        self.lib.lorcon_get_selectable_fd.argtypes = [
                ctypes.POINTER(StructLorcon)]
        self.lib.lorcon_get_selectable_fd.restype = ctypes.c_int

        # TODO: lorcon_next_ex goes here

        self.lib.lorcon_set_filter.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.c_char_p]
        self.lib.lorcon_set_filter.restype = ctypes.c_int
        self.lib.lorcon_set_filter.errcheck = self._errcheck_int

        # TODO: lorcon_set_compiled_filter goes here
        # TODO: lorcon_pcap_loop goes here
        # TODO: lorcon_pcap_dispatch goes here

        self.lib.lorcon_breakloop.argtypes = None
        self.lib.lorcon_breakloop.restype = None

        # TODO: Wrap the lorcon_packet stuff
        #self.lib.lorcon_inject.argtypes = [ctypes.POINTER(StructLorcon),
        # ctypes.POINTER(StructPacket)]
        #self.lib.lorcon_inject.restype = ctypes.c_int
        #self.lib.lorcon_inject.errcheck = self._errcheck_int

        self.lib.lorcon_send_bytes.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.c_int, ctypes.POINTER(ctypes.c_ubyte)]
        self.lib.lorcon_send_bytes.restype = ctypes.c_int
        self.lib.lorcon_send_bytes.errcheck = self._errcheck_int

        self.lib.lorcon_get_version.argtypes = None
        self.lib.lorcon_get_version.restype = ctypes.c_ulong

        self.lib.lorcon_add_wepkey.argtypes = [ctypes.POINTER(StructLorcon),
                ctypes.POINTER(ctypes.c_ubyte), ctypes.POINTER(ctypes.c_ubyte)]
        self.lib.lorcon_add_wepkey.restype = ctypes.c_int
        self.lib.lorcon_add_wepkey.errcheck = self._errcheck_int

    def list_drivers(self):
        'List all drivers LORCON is compiled with.'
        return _generate_driver_list(self.lib, self.lib.lorcon_list_drivers())

    def find_driver(self, driver):
        return Driver(self.lib, self.lib.lorcon_find_driver(driver))

    def auto_driver(self, interface):
        return Driver(self.lib, self.lib.lorcon_auto_driver(interface))

    def create(self, interface, driver):
        return Context(self.lib, self.lib.lorcon_create(interface, driver))

    def _errcheck_int(self, result, func, args):
        'Raises an exception if the return value is less than 0'
        if result < 0:
            raise LorconError(self.lib.lorcon_get_error(args[0]))
        return result

class Driver(object):
    '''Represents a driver struct.

Automatically frees memory when this object is garbage collected.

'''
    def __init__(self, lib, ptr):
        '''lib = reference to the lorcon library
ptr = ctypes pointer to a StructDriver

'''
        self.lib = lib
        self._as_parameter_ = ptr
        self.contents = ptr.contents

    def __del__(self):
        self.lib.lorcon_free_driver_list(self)

    def __str__(self):
        return self.name

    name = property(lambda self: self.contents.name)
    details = property(lambda self: self.contents.details)

class Context(object):
    'Represents a LORCON context struct.'

    def __init__(self, lib, ptr):
        '''lib = reference to the lorcon library
ptr = ctypes pointer to a StructLorcon

'''
        self.lib = lib
        self._as_parameter_ = ptr
        self.contents = ptr.contents

    def __del__(self):
        self.lib.lorcon_free(self)

    def open_inject(self):
        'Open an interface for inject.'
        self.lib.lorcon_open_inject(self)

    def open_monitor(self):
        'Open an interface in monitor mode (may also enable injection).'
        self.lib.lorcon_open_monitor(self)

    def open_injmon(self):
        'Open an interface in inject+monitor mode.'
        self.lib.lorcon_open_injmon(self)

    def close(self):
        'Close interface.'
        self.lib.lorcon_close(self)

    def fileno(self):
        'For use in the "select" package'
        return self.selectable_fd

    def next_ex(self):
        raise NotImplementedError()

    def set_filter(self, filter):
        self.lib.lorcon_set_filter(self, filter)

    def set_compiled_filter(self, filter):
        raise NotImplementedError()

    def pcap_loop(self, count, callback):
        raise NotImplementedError()

    def pcap_dispatch(self, count, callback):
        raise NotImplementedError()

    def pcap_breakloop(self):
        self.lib.lorcon_breakloop(self)

    def inject(self, packet):
        # TODO: Wrap the lorcon_packet stuff
        raise NotImplementedError()
        #return self.lib.lorcon_inject(self, packet)

    def send_bytes(self, data):
        buf = (ctypes.c_ubyte * len(data))(*[ord(x) for x in data])
        return self.lib.lorcon_send_bytes(self, len(buf), buf)

    def add_wepkey(self, bssid, key):
        return self.lib.lorcon_add_wepkey(self, bssid, key, len(key))

    # Properties (Replaces getters/setters

    version = property(lambda self: self.lib.lorcon_get_version(self))

    error = property(lambda self: self.lib.lorcon_get_error(self),
            doc='Return the most recent error.')

    timeout = property(
            lambda self: self.lib.lorcon_get_timeout(self),
            lambda self, x: self.lib.lorcon_set_timeout(self, x),
            doc='''Set a capture timeout (equivalent to the timeout value in
pcap_open, but with implications for non-pcap sources as well).
Timeout value is in ms.''')

    vap = property(
            lambda self: self.lib.lorcon_get_vap(self),
            lambda self, x: self.lib.lorcon_set_vap(self, x),
            doc='Set/Get the VAP (if we use VAPs).')

    capiface = property(
            lambda self: self.lib.lorcon_get_capiface(self),
            doc='Get the interface we\'re capturing from.')

    driver_name = property(
            lambda self: self.lib.lorcon_get_driver_name(self),
            doc='Get the driver.')

    # TODO: This isn't defined in Lorcon2 yet
    #datalink = property(
    # lambda self: self.lib.lorcon_get_datalink(self),
    # lambda self, x: self.lib.lorcon_set_datalink(self, x),
    # doc='Datalink layer info')

    channel = property(
            lambda self: self.lib.lorcon_get_channel(self),
            lambda self, x: self.lib.lorcon_set_channel(self, x),
            doc='Get/set channel/frequency')

    pcap = property(
            lambda self: self.lib.lorcon_get_pcap(self),
            doc='Get a pcap_t')

    selectable_fd = property(
            lambda self: self.lib.lorcon_get_selectable_fd(self))

    # These properties are a bit more complicated, so define them using
    # decorators

    @property
    def hwmac(self):
        '''Get/set MAC address, returns length of MAC and allocates in **mac,
caller is responsible for freeing this memory. Different PHY types may
have different MAC lengths.

For 802.11, MAC is always 6 bytes.

A length of 0 indicates no set MAC on this PHY. Negative numbers
indicate error fetching MAC from hardware.

'''
        mac = ctypes.POINTER(ctypes.c_uint8)()
        maclen = self.lib.lorcon_get_hwmac(self, ctypes.byref(mac))
        if maclen:
            return mac[0:maclen]
        raise LorconError('No MAC on this PHY')

    @hwmac.setter
    def hwmac(self, mac):
        'mac should be a list of 8 bit integers'
        mac_array = (ctypes.c_uint8 * len(mac))(*mac)
        return self.lib.lorcon_set_hwmac(self, len(mac_array), mac_array)

def _generate_driver_list(lib, ptr):
    '''Creates a list of Driver objects from a pointer to a driver list from
lorcon_list_drivers.

This makes sure each Driver object can be independently garbage collected.

'''
    driver_list = []
    while True:
        try:
            driver_list.append(Driver(lib, ptr))
        except ValueError:
            break
        ptr = ptr.contents.next

    # Remove the "next" pointers in each driver, so that they can be garbage
    # collected independently
    for driver in driver_list:
        driver.contents.next = None

    return driver_list

if __name__ == '__main__':
    l = Lorcon('/tmp/lorcon/lib/liborcon2.so')
    driver = l.auto_driver('wlan0')
    context = l.create('wlan0', driver)
    context.open_inject()
    context.send_bytes('Hello World')

Markdown Cheat Sheet

Format Text

Headers

# This is an <h1> tag
## This is an <h2> tag
###### This is an <h6> tag

Text styles

*This text will be italic*
_This will also be italic_
**This text will be bold**
__This will also be bold__

*You **can** combine them*

Lists

Unordered

* Item 1
* Item 2
  * Item 2a
  * Item 2b

Ordered

1. Item 1
2. Item 2
3. Item 3
   * Item 3a
   * Item 3b

Miscellaneous

Images

![GitHub Logo](/images/logo.png)
Format: ![Alt Text](url)

Links

http://github.com - automatic!
[GitHub](http://github.com)

Blockquotes

As Kanye West said:

> We're living the future so
> the present is our past.

Code Examples in Markdown

Syntax highlighting with GFM

```javascript
function fancyAlert(arg) {
  if(arg) {
    $.facebox({div:'#foo'})
  }
}
```

Or, indent your code 4 spaces

Here is a Python code example
without syntax highlighting:

    def foo:
      if not bar:
        return true

Inline code for comments

I think you should use an
`<addr>` element here instead.
Something went wrong with that request. Please try again.

Looking for the GitHub logo?