2015-09-04 119 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()。由於參數相同,代碼進入無限循環。

爲了做到這一點,你可能需要找一些小配件其設置棧和之前打電話給他們返回到上述啓動代碼(可能只清洗將需要承擔的主要論點被動清理約定)。

請更新我們與您的結果。