好吧,据我所知ET_EXEC用于表示该文件是可执行文件,而ET_DYN表示该文件是一个共享库。所以可以肯定的是,我用 C 编写了一个简单的程序,但问题是readelf -h产生了以下内容:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
.
.
.
Run Code Online (Sandbox Code Playgroud)
我认为这与我使用的编译器有关,所以我对/bin 中的一些实用程序做了同样的事情,但不幸的是得到了相同的结果。那么问题来了:为什么 readelf 将可执行文件识别为共享库?
该OSDev维基说:
在每个用户进程中映射内核是传统的并且通常很好
那为什么呢?这个过程不能单独映射到内存吗?映射内核有什么好处,这不会浪费空间吗?
此外,是否可以从用户空间访问内核空间,为什么我会这样做?
我很难理解这一点。
我正试图通过e_entry
字段直接修补ELF文件的入口点:
Elf64_Ehdr *ehdr = NULL;
Elf64_Phdr *phdr = NULL;
Elf64_Shdr *shdr = NULL;
if (argc < 2)
{
printf("Usage: %s <executable>\n", argv[0]);
exit(EXIT_SUCCESS);
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
perror("open");
exit(EXIT_FAILURE);
}
if (fstat(fd, &st) < 0)
{
perror("fstat");
exit(EXIT_FAILURE);
}
/* map whole executable into memory */
mapped_file = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mapped_file < 0)
{
perror("mmap");
exit(EXIT_FAILURE);
}
// check for an ELF file
check_elf(mapped_file, argv); …
Run Code Online (Sandbox Code Playgroud) 我有一个驱动程序,由于某些未知原因导致错误检查 0x0000003b。
因此,我决定设置一个 Hyper-V 虚拟机并使用内核调试来查看到底发生了什么。我已经使用bcdedit启用测试签名,并检查驱动程序确实已加载并使用sc query运行。问题是我希望 WinDbg 仅在调用有问题的驱动程序时介入,而不是在 Windows 调试程序启动时介入,我该怎么做?如何指示 Windbg 在驱动程序的 DriverEntry 函数处暂停?
我正在尝试了解有关 ELF 格式的更多信息,特别是节标题,我刚刚遇到了以下内容:
Elf32_Ehdr *ehdr = (Elf32_Ehdr*)p;
Elf32_Shdr *shdr = (Elf32_Shdr *)(p + ehdr->e_shoff);
int shnum = ehdr->e_shnum;
Elf32_Shdr *sh_strtab = &shdr[ehdr->e_shstrndx];
const char *const sh_strtab_p = p + sh_strtab->sh_offset;
for (int i = 0; i < shnum; ++i) {
printf("%2d: %4d '%s'\n", i, shdr[i].sh_name,
sh_strtab_p + shdr[i].sh_name);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在,我知道这基本上是遍历节表并打印节名称,但我仍然对sh_offset字段感到困惑。它到底有什么作用?如果e_shstrndx已经指向字符串表部分,为什么我们需要sh_offset?
我试图弄清楚这两个部分之间的区别,这似乎是这个问题的重复,但那里给出的答案没有解释太多,所以我想要更详细和简洁的解释。
ELF 文件包含两个结构来处理重定位:
Elf64_Rel
:
typedef struct {
Elf64_Addr r_offset;
Uint64_t
r_info;
} Elf64_Rel;
Run Code Online (Sandbox Code Playgroud)
和Elf64_Rela
:
typedef struct {
Elf64_Addr r_offset;
uint64_t
r_info;
int64_t
r_addend;
} Elf64_Rela;
Run Code Online (Sandbox Code Playgroud)
我想看一下重定位条目,但我不确定该使用哪一个。手册页对此非常含糊。每种都有具体的用途吗?
这个问题与这个问题相关,但它没有填补我的一些空白,所以我决定再次询问它并提供更多细节,也许可以对此给予赏金。
无论如何,通常如果您在 ntdll 上查找 Nt/Zw 函数,您会看到类似以下内容的内容:
ZwClose proc near
mov r10, rcx
mov eax, 0Fh
test byte ptr ds:7FFE0308h, 1
jnz short loc_a
syscall
retn
loc_a:
int 2Eh
retn
NtClose endp
Run Code Online (Sandbox Code Playgroud)
现在我知道这是比较KUSER_SHARED_DATA的偏移量并决定是否执行系统调用与INT 2E。起初我认为如果正在运行的程序是 32 位应用程序,则会执行 INT 2E,但在阅读了一些有关 WOW64 的内容后,这些应用程序似乎会使用 32 位版本的 ntdll,它不执行 int 2e 而是执行穿过天堂之门到达内核:
public ZwClose
ZwClose proc near
mov eax, 3000Fh ; NtClose
mov edx, offset j_Wow64Transition
call edx ; j_Wow64Transition
retn 4
ZwClose endp
Run Code Online (Sandbox Code Playgroud)
据我了解,Wow64Transition最终会跳转到我首先列出的 ntdll 的 64 …