如何读取C程序的堆栈段?
我正在开发一个业余操作系统,因为我想知道Linux中的内存分配机制,为了理解这一点,我创建了一个简单的C程序,它定义了一些十六进制数的如何读取C程序的堆栈段?,c,linux,C,Linux,我正在开发一个业余操作系统,因为我想知道Linux中的内存分配机制,为了理解这一点,我创建了一个简单的C程序,它定义了一些十六进制数的无符号字符,然后在一个空的无限循环中运行,我这样做是为了让进程保持活力。然后我使用pmap获取页面映射信息。现在我知道了堆栈段的位置,我还创建了一个程序,使用process\u vm\u readvsyscall读取该地址的内容,当我最后读取堆栈段的内容和一些随机数时,我看到的都是00流,我怎样才能知道数组是如何存储在堆栈段中的 如果可能,我如何分析十六进制流以提
无符号字符
,然后在一个空的无限循环中运行,我这样做是为了让进程保持活力。然后我使用pmap
获取页面映射信息。现在我知道了堆栈段的位置,我还创建了一个程序,使用process\u vm\u readv
syscall读取该地址的内容,当我最后读取堆栈段的内容和一些随机数时,我看到的都是00
流,我怎样才能知道数组是如何存储在堆栈段中的
如果可能,我如何分析十六进制流以提取有意义的信息?这里我添加了一个用于访问远程进程地址空间的演示,有两个程序local.c将在另一个名为remote.c的程序中读取和写入变量(这些程序假定
sizeof(int)=4
)
本地的
#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int main()
{
char buf[4];
struct iovec local[1];
struct iovec remote[1];
int pid;
void *addr;
printf("Enter remote pid\n");
scanf("%d",&pid);
printf("Enter remote address\n");
scanf("%p", &addr);
local[0].iov_base = buf;
local[0].iov_len = 4;
remote[0].iov_base = addr;
remote[0].iov_len = 4;
if(syscall(SYS_process_vm_readv,pid,local,1,remote,1,0) == -1) {
perror("");
return -1;
}
printf("read : %d\n",*(int*)buf);
*(int*)buf = 4321;
if(syscall(SYS_process_vm_writev,pid,local,1,remote,1,0) == -1) {
perror("");
return -1;
}
return 0;
}
使用类似的方法,您可以将堆栈帧读取到io向量,但您需要知道堆栈帧结构格式,以便从堆栈帧解析局部变量的值。堆栈帧包含函数参数、返回地址、局部变量等是否使用指针?尝试从中写入和读取,看看堆栈的内容是否发生变化。@Gerhardh强制它进入堆栈的一种方法是获取其地址。我假设您有堆栈段的起始地址。您还需要知道堆栈帧结构,才能读取自动变量(无符号字符)内容。@NarasimhaPrasannaHN您可能希望将字符数组声明为volatile。如果没有,它可能会得到优化,因为编译器检测到您没有对数组中的数据执行任何操作。@NarasimhaPrasannaHN不清楚您试图实现什么。操作系统只为您的程序“分配”堆栈。诸如各个变量在堆栈中的位置或堆栈本身的组织方式等决策取决于程序本身。在您的情况下,这些决定是由编译器做出的。操作系统只为您分配一块内存并让您的程序运行。为什么要使用syscall而不是直接调用
process\u vm\u readv
?一些Linux发行版不公开process\u vm\u readv()
system call@chrisdd
#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int main()
{
int a = 1234;
printf("%d %p\n",getpid(),&a);
while(a == 1234);
printf ("'a' changed to %d\n",a);
return 0;
}
[ajith@localhost Desktop]$ gcc remote.c -o remote -Wall
[ajith@localhost Desktop]$ ./remote
4574 0x7fffc4f4eb6c
'a' changed to 4321
[ajith@localhost Desktop]$
[ajith@localhost Desktop]$ gcc local.c -o local -Wall
[ajith@localhost Desktop]$ ./local
Enter remote pid
4574
Enter remote address
0x7fffc4f4eb6c
read : 1234
[ajith@localhost Desktop]$