总之,我该如何检查情况)当我移出堆栈而不触发一般保护时n错误?当前进程的堆栈空间)
#1 楼
因此,它完全未经测试,但是这是一些Internet浏览的结果。 />我查看了pstack命令的代码,该命令正在打印正在运行的进程的堆栈内容。此代码从
/proc/<pid>/maps
结构获取基地址并将其存储在字段link_map
中。此字段在函数l_addr
中设置:static void readLinkMap(int pid, ElfN_Addr base, struct link_map *lm,
char *name, unsigned int namelen)
{
/* base address */
lm->l_addr = (ElfN_Addr) ptrace(PTRACE_PEEKDATA, pid,
base + offsetof(struct link_map,l_addr), 0);
/* next element of link map chain */
if (-1 != (long) lm->l_addr || !errno)
lm->l_next = (struct link_map *) ptrace(PTRACE_PEEKDATA, pid,
base + offsetof(struct link_map, l_next), 0);
if ((-1 == (long) lm->l_addr || -1 == (long) lm->l_next) && errno) {
perror("ptrace");
quit("can't read target.");
}
loadString(pid, base + offsetof(struct link_map, l_name), name, namelen);
}
我想这是正确的方法。因此,我建议您看一下
readLinkMap()
命令的代码(文件不是很长),并从中获得启发,因为它的功能与您想要的非常相似(至少在我理解您说的内容的情况下)正确)。希望这篇简短的说明对您有所帮助。
评论
在用户问题的范围内,这似乎是足够的。但是,如果要实现回溯功能,则可能需要矮化cfi(如果要使其可靠)。
–百老汇
2013年6月5日16:11
@broadway:但是,矮化并不总是出现在所有可执行文件上。您可以从中获得一些帮助,但是,以我的拙见,完全依靠它是一个错误,而没有其他选择。
–恐怖
2013年6月5日17:46
是的,在这种情况下,您只需要接受破损即可。框架通常只是不在那里。不过,在某些常见情况下,您可以尝试启发式推断寄存器。
–百老汇
2013年6月5日18:03
评论
我猜您在Linux下工作。在这里显然需要指定OS,因为它确实在开始进程之前设置了堆栈基地址(是否带有ASLR偏移)。谢谢,我已经编辑了上面指定的答案-确实是linux。
强烈建议您阅读有关放卷的内容:第1部分,第2部分(面向OS X,但仍然适用许多内容)。
既然您知道intel / amd环境中的堆栈使用情况,就知道ebp值对于每次连续回滚(意味着,访问下一个父级)必定会增加值。另外,如果您正在研究Linux环境,则可以(有些安全)假定8MB(每个线程)的堆栈大小限制。此外,鉴于正在使用(最有可能的)4KB页面,您可以安全地读取ebp值,该ebp值的地址比当前到达一个不同(显然更高)的页面条目的UNTIL大。此时,您可以使用mmap()来查看页面是否存在...
另外,由于ESP / RSP和EBP / RSP值是4字节或2字节,因此您可以通过检查低2位(32位)或低3位(64位)来检测“损坏”的EBP / RBP值的某些形式分别对齐8字节。