我有一个结构变量,其传递方式如下:
//function definition
void function1(const Node* aVAR1)
{
Node* value=NULL;
.....
}
int main()
{
Node* aVAR=NULL;
aVAR=x.value;
function1(aVAR);
}
[这里,当我在gdb中运行它并进入function1()
时,我看到为变量aVAR
创建了一个临时内存地址。
GDB:
21 aVAR=x.value;
(gdb) p aVAR
$5 = (Node *) 0x654321
(gdb) n
Breakpoint 1, function1(aVAR1=0x7ffffffffebcdf ) at debug/../abc.c:12
12 {
(gdb) p aVAR1
$6 = (const Node *) 0x7ffffffffebcdf
例如,
0x654321
function1()
中的第一条指令,aVAR1
会保留在某些临时地址中,例如0x7ffffffffebcdf
。Node* value=NULL;
中的第一条指令function1()
后,aVar1
的地址再次为0x654321
。0x7ffffffffebcdf
)地址没有被清除:即使在函数退出后,0x7ffffffffebcdf
也不会被清除我希望在函数退出后清除0x7ffffffffebcdf
,但是0x7ffffffffebcdf
地址没有指针,我可以通过该指针访问该内存。在GCC中进行链接时是否可以防止这种情况?
如果我为aVAR添加一个malloc并稍后使用memset和free将其清除,则当我看到时,该问题将在逻辑上得以解决,但我丢失了对malloc()分配的内存块的引用,而我将无法free()分配的内存(导致内存泄漏)。
我希望在函数退出后清除0x7ffffffffebcdf ...
我的想象力有限,但是我可以想像您想要的原因之一是:
因此,给定[3],有两种选择;在主返回之前将代码更改为零;或将main()更改为mymain():
int mymain() {
Node* aVAR=NULL;
aVAR=x.value;
function1(aVAR);
return something;
}
void clearstack() {
int data[1000];
int fd;
if ((fd = open("/dev/zero", O_RDONLY)) != -1) {
read(fd, data, sizeof data);
close(fd);
}
}
int main() {
int r = mymain();
clearstack();
return r;
}
this works,因为堆栈地址将在两个函数调用之间重叠,因此您的0x7f-febcdf将落在data []的中间。实现定义的行为合唱团现在应该热身了。但实际上,您最好使用:
int mymain() {
Node* aVAR=NULL;
aVAR=x.value;
function1(aVAR);
aVAR = 0;
dummyfunction(&aVAR);
return aVAR == 0;
}
请注意,通过将aVAR的地址提供给虚拟函数,您会干扰编译器删除可能认为无用的内容的能力。但是,这种行为很难预测,因为它将您的程序源绑定到您可以使用的任何版本的编译器。前景不大。
如果volatile在定义上有严格的要求,在这里会很有用,但没有。
一个更好的方法是使用malloc()来获取变量,然后您受一个合同约束,该合同是内存[而局部变量只能是寄存器],可以在释放之前对其进行清理它。编译器优化清理工作将处于无法接受的行为的外部。它仍然可能使数据保留在某些寄存器中,这可能会泄漏出去。
所有这些都说;如果攻击者真的想发现程序中的纯文本机密,则可能无法阻止它们。他们可以在调试器或管理程序下启动您的程序,然后随意检查数据。
[在某些现代处理器中,有一些概念,CPU可以构造一种安全区域,可以安全地解开秘密;但是有很多缺陷。 ARM TrustZone's Secure/Normal world vs. OS's kernel/user mode or x86's Ring0/1/2/3?有更多信息。
在您呈现的内容中,您有两个称为aVAR
的变量。第一个是main
中的局部变量,第二个是function1
的参数。两者都位于自动存储(或您所说的“临时”存储)中,因此当包含它们的函数退出时将不复存在。无需任何特殊操作即可释放它们。
[仅需要释放指向的结构(假设它是malloc
的,并且只需要执行一次,无论在其生命周期中有多少个指针指向它。
总之,您只需要每个free
/ malloc
一个calloc
。 (尽管请记住,strdup
将调用malloc
,并且将NULL
传递给realloc
实际上是malloc
。)