我正在尝试更改C中某些函数的返回地址,以跳过一条指令。我正在使用Ubuntu Server的虚拟机上执行此操作(因为在Mac gcc上不允许关闭堆栈保护)。
我正在用gcc编译代码:
gcc –g –fno-stack-protector –z execstack –o bufover bufover.c
这是代码:
$query = $conn->prepare( "INSERT INTO ReserveerCursusCursisten
(Geslacht, Achternaam, Voorletters, Geboortedatum) VALUES (:geslachten, :achternamen, :voornamen, :geboortedata, 0, 0)");
for($i = 0; $i < count($achternamen); $i++)
{
$stmt->bindValue(':geslachten', $geslachten);
$stmt->bindValue(':achternamen', $achternamen);
$stmt->bindValue(':voornamen', $voornamen);
$stmt->bindValue(':geboortedata', $geboortedata);
$stmt->execute();
}
if ($stmt->execute())
{
echo "query is gelukt";
}
else
{
echo "query is niet gelukt";
}
我向 buff 的地址添加了256(buff的大小)和8(%RBP的大小)。在此之前,堆栈应该是返回地址。 接下来,我向该地址添加了5个字节,因为我使用gdb检查了下一条指令在5个字节中。
但这不起作用... 我正在使用gdb逐步分析变量(地址),但没有看到任何错误。 有想法吗?
编辑:汇编代码:
void foo(int a, int b, int c) {
char buff[256];
long *ret, *ret2;
ret = buff + 256 + 8;
(*ret) += 5;
}
int main() {
char x;
x = '0';
foo(1,2,3);
x = '1';
printf("%c\n",x);
}
答案 0 :(得分:0)
您应该使用__builtin_frame_address
或__builtin_return_address
之类的GCC return-address related内置函数,并且应该仔细研究x86-64 ABI specification以便详细了解相关的 x86 calling conventions。
尝试通过在foo.c
中编写一些C代码并用gcc -O -fverbose-asm -S foo.c
进行编译,然后查看生成的foo.s
最后,堆栈段通常是不可执行的(这对于某些trampoline技术而言可能很重要)。了解NX bit。在Linux上,学习使用mprotect(2),mmap(2),backtrace(3)。
不能保证GCC甚至使用任何call stack。它可以进行优化以避免使用它(有时可能发生tail-call优化 ),并且您的代码甚至可能不需要其他调用框架。因此,当然,您无法在标准C中实现目标,或者在您的特定GCC编译器上没有其他假设(GCC 8和GCC 9的优化可能会有所不同)。
当然,更改寄信人地址为undefined behavior。