這個是系統架構,下面是測試代碼「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 的架構得自己重寫代碼,因爲調用約定全改了。。它好好的爲什麼要改呢。。?