mandibule
mandibule copied to clipboard
"base_seg" variable is incorrect
for(int i=0; i<ehdr->e_phnum; i++)
{
phdr = (elf_phdr *)(elf_buf + ehdr->e_phoff + i * ehdr->e_phentsize);
// printf("> seg[%d] load: %d addr 0x%llx size 0x%llx\n", i, phdr->p_type == PT_LOAD, phdr->p_vaddr, phdr->p_memsz);
if(phdr->p_type == PT_LOAD && load_segment(elf_buf, ehdr, phdr, base_off))
return -1;
if(!base_seg)
base_seg = phdr->p_vaddr;
base_next = phdr->p_vaddr + phdr->p_memsz > base_next ? phdr->p_vaddr + phdr->p_memsz : base_next;
}
ALIGN_PAGE_DOWN(base_seg);
if(ehdr->e_type == ET_DYN)
base_seg += base_off;
// printf("> program base: 0x%llx\n", base_seg);
Now the code to get the base address is written like this, get the non-zero offset of any segment (phdr->p_vaddr). But when I compile the program with the "-static-pie" option, the section information is as follows.
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000e6965 0x00000000000e6965 R E 0x200000
LOAD 0x00000000000e7188 0x00000000002e7188 0x00000000002e7188
0x0000000000007360 0x000000000000b550 RW 0x200000
DYNAMIC 0x00000000000ed8e8 0x00000000002ed8e8 0x00000000002ed8e8
0x0000000000000170 0x0000000000000170 RW 0x8
TLS 0x00000000000e7188 0x00000000002e7188 0x00000000002e7188
0x0000000000000000 0x0000000000000010 R 0x8
GNU_EH_FRAME 0x00000000000bb650 0x00000000000bb650 0x00000000000bb650
0x000000000000697c 0x000000000000697c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x00000000000e7188 0x00000000002e7188 0x00000000002e7188
0x0000000000006e78 0x0000000000006e78 R 0x1
You can see that the first segment is LOAD, but its virtual address is 0, then the program is judging that "if (!base_seg)" will enter the branch, so the final value of "base_seg" is "2e7188", the second Load segment Virtual address. "base_seg" should take the virtual address of the first LOAD segment, whether it is zero or not.
int base_set = 0;
for(int i=0; i<ehdr->e_phnum; i++)
{
phdr = (elf_phdr *)(elf_buf + ehdr->e_phoff + i * ehdr->e_phentsize);
// printf("> seg[%d] load: %d addr 0x%llx size 0x%llx\n", i, phdr->p_type == PT_LOAD, phdr->p_vaddr, phdr->p_memsz);
if(phdr->p_type == PT_LOAD)
{
if(!base_set)
{
base_set = 1;
base_seg = phdr->p_vaddr;
}
if (load_segment(elf_buf, ehdr, phdr, base_off))
return -1;
}
base_next = phdr->p_vaddr + phdr->p_memsz > base_next ? phdr->p_vaddr + phdr->p_memsz : base_next;
}
nice catch :)