无法更改函数x64的返回地址

时间:2019-05-17 11:33:53

标签: c gdb stack buffer-overflow

我正在尝试更改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);
}

1 个答案:

答案 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