Hi, >My program try to modified one of its sections (.plt) >loaded into the memory. But it got a SIGSEGV >signal. Again, I think this is a misunderstanding about the way ELF works. On Sparc machines the PLT is directly patched (see long discussion in previous email) to redirect to the correct dynamic function, on IA32 machines the PLT is never changed since it references an entry in the GOT, only the GOT is changed to dynamically bind the function. Thus on Solaris machines the PLT is always writable but on IA32 it shouldn't ever be. >The .plt section marked READONLY CODE when I >used objdump -h myprogram, I am wondering >whether this readonly attribute can be changed or >not? The key is that sections are used only at link time, at run time _segments_ are used to load the process image into memory and set the memory permissions. Don't use objdump, use readelf instead and check out the output of the -l option: readelf -l /bin/ls ... Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4 INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x0a100 0x0a100 R E 0x1000 LOAD 0x00a100 0x08053100 0x08053100 0x00270 0x00508 RW 0x1000 DYNAMIC 0x00a2c8 0x080532c8 0x080532c8 0x000a8 0x000a8 RW 0x4 NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.got .rel.bss .rel. plt .init .plt .text .fini .rodata 03 .data .eh_frame .ctors .dtors .got .dynamic .bss 04 .dynamic 05 .note.ABI-tag So we can see that the section .plt is in segment 2 which as expected has permissions R-E (or more obviously R-X). >I have tried editing it in several places in the file >but haven't success yet. Anybody done this before? Yep, you need to modify the segment table permissions, the source for a program that does just that follows, I just quickly hacked it up so no promises as to quality. You might find the ELF specification an interesting read in regards to all of this stuff. Cheers, Shaun #include <stdio.h> #include <elf.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> /* Change the permissions on a segment */ int main(int argc, char *argv[]) { char *sInFile; unsigned long ulPerm = 0; int iSegNo, iInFd, i; char *pcFileAddr; struct stat tStatBuf; off_t tMapSize; Elf32_Ehdr *ptElfHdr; Elf32_Phdr *ptElfPHdr; char sElfMagic[] = "\x7f" "ELF"; if (argc != 4) { fprintf(stderr, "Usage: %s <file> <segment no> <segment permissions (e.g rwx)>\n", argv[0]); exit(1); } i = 0; while (argv[3][i]) { switch(argv[3][i]) { case 'x': ulPerm |= PF_X; case 'r': ulPerm |= PF_R; case 'w': ulPerm |= PF_W; } i++; } sInFile = argv[1]; iSegNo = atoi(argv[2]); if (-1 == (iInFd = open(sInFile, O_RDWR))) { fprintf(stderr, "Could not open %s, %d %s\n", sInFile, errno, strerror(errno)); exit(-1); } if (fstat(iInFd, &tStatBuf)) { fprintf(stderr, "Could not stat %s, %d %s\n", sInFile, errno, strerror(errno)); exit(-1); } tMapSize = tStatBuf.st_size; if (!(pcFileAddr = mmap(0, tMapSize, PROT_READ | PROT_WRITE, MAP_SHARED, iInFd, 0))) { fprintf(stderr, "Could not mmap %s, %d %s\n", sInFile, errno, strerror(errno)); exit(-1); } printf("File %s mapped at %p for %lu bytes\n", sInFile, pcFileAddr, tMapSize); ptElfHdr = (Elf32_Ehdr *) pcFileAddr; if (memcmp(&(ptElfHdr->e_ident), sElfMagic, sizeof(sElfMagic) - 1)) { fprintf(stderr, "File %s does not appear to be an ELF file\n", sInFile); exit(-1); } /* Does this file have the segment they requested? */ if ((iSegNo < 0) || (iSegNo >= ptElfHdr->e_phnum)) { printf("Segment %d does not exist in the executable\n", iSegNo); exit(-1); } /* Get the segment header for the specified segment */ ptElfPHdr = (Elf32_Phdr *) ((char *) pcFileAddr + ptElfHdr->e_phoff + (ptElfHdr->e_phentsize * iSegNo)); /* Set the permissions as specified */ ptElfPHdr->p_flags = ulPerm; munmap(pcFileAddr, tMapSize); close(iInFd); return(0); }
This archive was generated by hypermail 2b30 : Mon Dec 31 2001 - 19:41:38 PST