2015-09-04 180 views
-2

我的目标是写一个无限循环。我必须无限地打印这个字符串“Hello World%s”,我可以使用ROP(面向回程的编程)。如何做无限循环

gcc -fno-stack-protector loop.c -o loop 

我可以编译,如图所示。我如何做ROP?

#include<stdio.h> 
#include<string.h> 

main(char argc, char ** argv){ 
    char buffer[80]; 
    strcpy(buffer,argv[1]); 
    printf("Hello World %s",buffer); 
    return 1; 
} 
+1

作业的重点不在于学习如何做到这一点? –

+1

当你说你的目的是“无限循环”时,这是什么意思?你在无限循环中需要哪部分代码?无论如何,'while(1)'可能是最简单的方法。 –

+1

另外,你为什么'返回1'?非零退出代码表示程序因错误而终止。 –

回答

1

所以,粗糙的方法:

buffer位于堆栈,其中main function -callee的返回地址位于。由于事实上,堆栈向后增长,您可以覆盖返回地址,因为它之前被附加。堆栈应该是这样的:

[buffer data][ebp save][callee return address]...anything 

这不是十分清楚,但很可能的是,该被叫方的返回地址位于ebp保存的值,它位于缓冲区中的数据后之后,所以你需要给一个84字节长的数据数组(不包含0x00,因为这会终止字符串),然后是返回地址。地址需要指向某个地方,你的“黑客”位于内存中。一个可能的位置是堆栈本身,所以你可能想要在返回地址后追加无限循环的机器码。

重要的是要注意,您必须生成机器码,不包含空字节。参数字符串的布局示例应该如下所示:

[84 byte data][return address][machine code] 

这应该适用于较旧的Linux内核。此外,这假定您正在使用32位系统,所以指针长度为4个字节。在64位系统上,它将是8个字节。

+0

嗯。 OP想要使用ROP,因此我认为DEP处于活动状态。这意味着它不可能执行*自己的*代码。 – splotz90

+0

@ splotz90在这种情况下,您可以使用main的地址进行覆盖,直到堆栈完全耗尽为止。可悲的是,这不会是无限的,只有在编译器通过寄存器传递调用者参数并且'argv'没有在堆栈附近的堆栈上分配时才有效。 – qwertz

+0

是的,我有同样的想法。但我没有写在这里,因为它(如你所说)并非真正无限。不幸的是,现在我还没有其他想法。 – splotz90

0

我不精通这一点,但(理论上)你的最终目标是返回到启动代码(或_start或如的glibc的__libc_start_main),这将反过来使用相同的参数再次拨打您的main()。由于参数相同,代码进入无限循环。

为了做到这一点,你可能需要找一些小配件其设置栈和之前打电话给他们返回到上述启动代码(可能只清洗将需要承担的主要论点被动清理约定)。

请更新我们与您的结果。