奇怪,Linux 3.11.2-1-ARCH x86_64 居然還是可執行堆棧?

這個是系統架構,下面是測試代碼「hello.c」:

char shellCode[] = "\xeb\x1a\x5e\x48\x31\xff\x48\x31\xd2\x48\x31\xc0\x66\xff\xc7\xb2\x0d\xb0\x01\x0f\x05\x48\x31\xff\xb0\x3c\x0f\x05\xe8\xe1\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x0a";

int
main (void) {
        long p;
        *(&p+2) = (long)shellCode;
        return 0;
}

奇怪了就,gcc 生成目標文件,然後看了下節頭:


明擺着就就一個text 段可執行,居然真把shellcode 給執行了,這貨明擺着在「.data」 裏:



話說這地方真是費解了,寫這個程序主要是看BINARY HACKS 的GNU 編程HACK 那一章,說2.6 之後都已經打了補丁,成了不可執行棧了,需要用objcopy 爲數據所在的段增加X 標記纔可以。於是手賤參考shellcode 的原理試了下,結果成了這個樣子。。。

有空再回頭看下,今晚要補完《瀨戶之花嫁》。


另外自己寫的那段shellcode 是X86_64 版本的,就是調用了個write 系統調用,吐槽下X86_64 彙編系統調用的寄存器約定改的。。參數上來就用到rdi,給di 賦值1,爲了避免產生\x0 都要換成xorq 和incw。。。

對於字符串的地址的運行時定位,我用的下面的方法確定的地址:

_start:
        jmp     begin
shellCode:
        popq    %rsi            # 出棧字符串地址 
        # 操作字符串的代碼
begin:
        call shellCode          # 利用call 指令壓棧的特性把字符串地址壓棧
        .ascii "string"
完了之後編譯下,並且反彙編得到shellcode:

# as -o write.o write.s
# ld -o write write.o
# echo -e "\\\x""$(objdump -d write | perl -nE 's/.+:\s([a-f0-9 ]+).+/$1/g and s/\s+/\\\\x/g and print')""\b\b  "

執行後會得到shellcode:

\xeb\x1a\x5e\x48\x31\xff\x48\x31\xd2\x48\x31\xc0\x66\xff\xc7\xb2\x0d\xb0\x01\x0f\x05\x48\x31\xff\xb0\x3c\x0f\x05\xe8\xe1\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x0a 

話說X86 的架構得自己重寫代碼,因爲調用約定全改了。。它好好的爲什麼要改呢。。?


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章