- 論壇徽章:
- 0
|
創(chuàng)建時(shí)間:2006-08-23
文章屬性:原創(chuàng)
文章提交:7all (sgh81_at_163.com)
==www.cciss.cn.==
==bbs.cciss.cn.==
簡析Linux與FreeBSD的syscall與shellcode
|=---------------=[ 簡析Linux與FreeBSD的syscall與shellcode ]=------=|
|=-----------------------------------------------------------------=|
|=---------------=[ 7all<bloodfall_at_msn.com> ]=------------------=|
|=-----------------------------------------------------------------=|
|=---------------=[ 版權(quán)所有:www.cciss.cn ]=-----------------------=|
--]概述
又是一個(gè)不眠的夜晚,其實(shí)這篇文檔是不應(yīng)該發(fā)表的,因?yàn)楸C艿脑瓌t吧,但是我仔細(xì)
google了下,沒有類似的文章,而且發(fā)表的這部分文檔也不至于被認(rèn)為是什么絕密資料,
但是我還是隱藏了很多發(fā)現(xiàn)的內(nèi)核級別可能存在的問題 單純從匯編代碼的結(jié)構(gòu)來闡述
下linux與freebsd到底那個(gè)更好玩一些.或者說那個(gè)運(yùn)行速度會(huì)更快一些
我想大家看完這個(gè)文檔以后,或許會(huì)知道到底是Linux穩(wěn)固?還是FreeBSD穩(wěn)固?
在本文的最后部分,附加了shellcode的問題,但沒有專門的論述.
備注:本文觀點(diǎn)僅代表個(gè)人觀點(diǎn),如有不對的地方,歡迎大家指正 以提高本人的水平.
--]編譯調(diào)試
A:編譯選項(xiàng)
Linux :gcc -gdwarf-2 ***.c -o ***
FreeBSD: cc -gdwarf-2 ***.c -o ***
為了調(diào)試方便,我使用了上面的選項(xiàng).
--------------------------------------
對于一般書寫shellcode的編譯選項(xiàng)一般為:
Linux :gcc -static -o *** ***.c
FreeBSD: cc -static -o *** ***.c
B:調(diào)試工具
Linux/Unix下面的調(diào)試工具為GDB,但是GDB基于內(nèi)核的調(diào)試有些力不從心,因?yàn)镚DB的調(diào)試是
基于用戶模式(User mode).
這里我使用了其它的調(diào)試工具,所以下面大家看到的調(diào)試代碼比較特殊,在這里事先聲明.
--]Linux的syscall跟蹤
寫過shellcode的人都知道syscall是寫shellcode的必需品 當(dāng)然這種概念只在Linux/Unix
的OS下才存在.最近這段時(shí)間因?yàn)橐粋(gè)"小小的問題"對Linux內(nèi)核與FreeBSD的內(nèi)核級別進(jìn)行了
跟蹤和調(diào)試,然后發(fā)現(xiàn)一個(gè)蠻有意思的問題,自己感覺這個(gè)問題可能會(huì)與Linux下shellcode與
FreeBSD下shellcode的不同有關(guān)系,當(dāng)然也和系統(tǒng)架構(gòu)存在一些細(xì)微的關(guān)系.下面的內(nèi)容是Linux
下面syscall的一些匯編代碼.
在Linux下面,Application調(diào)用syscall的代碼如下:
420D4330 55 PUSH EBP |
420D4331 89E5 MOV EBP,ESP |->堆?蚣
420D4333 83EC18 SUB ESP,00000018 |
420D4336 897DFC MOV dword ptr [EBP]-04,EDI |
420D4339 8B4D0C MOV ECX,dword ptr [EBP]+0c |
420D433C 8B7D08 MOV EDI,dword ptr [EBP]+08 |->syscall參數(shù)
420D433F 8975F8 MOV dword ptr [EBP]-08,ESI |
420D4342 8B5510 MOV EDX,dword ptr [EBP]+10 |
420D4345 895DF4 MOV dword ptr [EBP]-0c,EBX
420D4348 E81014F4FF CALL near32 ptr 4201575d
420D434D 81C3835F0500 ADD EBX,00055f83
420D4353 8D77FF LEA ESI,dword ptr [EDI]-01
420D4356 83FE02 CMP ESI,00000002
420D4359 8D75F0 LEA ESI,dword ptr [EBP]-10
420D435C 0F477514 CMOVA ESI,dword ptr [EBP]+14
420D4360 53 PUSH EBX
420D4361 89FB MOV EBX,EDI
420D4363 B81A000000 MOV EAX,0000001c //system call number value
420D4368 CD80 INT 80 //調(diào)用0x80
420D436A 5B POP EBX
420D436B 3D00F0FFFF CMP EAX,fffff000
420D4370 89C6 MOV ESI,EAX
420D4372 760E JBE short ptr 420d4382
420D4374 F7DE NEG ESI
420D4376 E8C912F4FF CALL near32 ptr 42015644
420D437B 8930 MOV dword ptr [EAX],ESI
420D437D BEFFFFFFFF MOV ESI,ffffffff
420D4382 85F6 TEST ESI,ESI
420D4384 782A JS short ptr 420d43b0
420D4386 85FF TEST EDI,EDI
420D4388 7426 JE short ptr 420d43b0
420D438A 83FF03 CMP EDI,00000003
420D438D 7721 JA short ptr 420d43b0
420D438F E8B012F4FF CALL near32 ptr 42015644
420D4394 C70000000000 MOV dword ptr [EAX],00000000
420D439A 8B45F0 MOV EAX,dword ptr [EBP]-10
420D439D 8B5DF4 MOV EBX,dword ptr [EBP]-0c
420D43A0 8B75F8 MOV ESI,dword ptr [EBP]-08
420D43A3 8B7DFC MOV EDI,dword ptr [EBP]-04
420D43A6 89EC MOV ESP,EBP
420D43A8 5D POP EBP
420D43A9 C3 RETN
---------------------------------------------------------------------
為了簡單分析,我們就看這里的代碼:
420D4330 55 PUSH EBP |
420D4331 89E5 MOV EBP,ESP |->堆棧框架
420D4333 83EC18 SUB ESP,00000018 |
420D4336 897DFC MOV dword ptr [EBP]-04,EDI |
420D4339 8B4D0C MOV ECX,dword ptr [EBP]+0c |
420D433C 8B7D08 MOV EDI,dword ptr [EBP]+08 |->syscall參數(shù)
420D433F 8975F8 MOV dword ptr [EBP]-08,ESI |
420D4342 8B5510 MOV EDX,dword ptr [EBP]+10 |
420D4345 895DF4 MOV dword ptr [EBP]-0c,EBX
420D4348 E81014F4FF CALL near32 ptr 4201575d
420D434D 81C3835F0500 ADD EBX,00055f83
420D4353 8D77FF LEA ESI,dword ptr [EDI]-01
420D4356 83FE02 CMP ESI,00000002
420D4359 8D75F0 LEA ESI,dword ptr [EBP]-10
420D435C 0F477514 CMOVA ESI,dword ptr [EBP]+14
420D4360 53 PUSH EBX
420D4361 89FB MOV EBX,EDI
420D4363 B81A000000 MOV EAX,0000001c //system call number value
420D4368 CD80 INT 80 //調(diào)用0x80
----------------------------------------------------------------------
當(dāng)然從上面的代碼,我們只能看到Linux在更深的一層調(diào)用syscall的一個(gè)匯編代碼過程,換句話
說,可能上面的這些代碼都是廢話 OK,我們繼續(xù)看下面的內(nèi)容.
--]FreeBSD的syscall
FreeBSD下面的syscall我進(jìn)行了兩次跟進(jìn)的操作才進(jìn)入到內(nèi)部,所以下面使用了兩個(gè)過程來演示
代碼,不過從下面的代碼來看FreeBSD的短了很多很多
trace into one step:
28080D98: 31C0 XOR EAX,EAX
28080D9A: 53 PUSH EBX
28080D9B: E800000000 CALL near32 ptr 28080da0
-------------------------------------------------------------------
trace into two step:
28080DA0: 5B POP EBX
28080DA1: 81C3AC980600 ADD EBX,000698ac
28080DA7: 8B934C0A0000 MOV EDX,dword ptr [EBX]+00000a4c
28080DAD: 8902 MOV dword ptr [EDX],EAX
28080DAF: 5B POP EBX
28080DB0: 8D051A000000 LEA EAX,dword ptr [0000001c]//system call number value
28080DB6: CD80 INT 80
28080DB8: 7201 JC short ptr 28080dbb
28080DBA: C3 RETN
--------------------------------------------------------------------
從上面的代碼來看,FreeBSD的syscall代碼比Linux的短了很多很多,但是僅僅是短還是不夠的,如果在看
這個(gè)文檔前你熟悉破解技術(shù) or 溢出技術(shù) or Intel匯編語言.我想可能大家有這樣的感覺,FreeBSD的調(diào)用
syscall的過程比Linux的要安全了很多很多,為什么這么說呢?請?jiān)俜祷刈屑?xì)看上面的Linux/FreeBSD的匯
編代碼 下面我們也會(huì)大概的論證下,但僅僅是猜測而已
--]FreeBSD比Linux安全?
學(xué)過破解技術(shù)的朋友,都知道通過一些跳轉(zhuǎn)指令來實(shí)現(xiàn)對于軟件的破解,當(dāng)然使用跳轉(zhuǎn)指令可能僅僅對一些
簡單的軟件是有用處.突然發(fā)現(xiàn)我上面說的這句話是廢話,和本文沒有任何的關(guān)系,郁悶...看來腦袋里面裝的
東西多也不是什么好事情
言歸正傳,我們來大體的分析下為什么說BSD比Linux要安全些!請看下面的代碼:
Linux的syscall調(diào)用:
420D4336 897DFC MOV dword ptr [EBP]-04,EDI |
420D4339 8B4D0C MOV ECX,dword ptr [EBP]+0c |
420D433C 8B7D08 MOV EDI,dword ptr [EBP]+08 |->syscall參數(shù)
420D433F 8975F8 MOV dword ptr [EBP]-08,ESI |
420D4342 8B5510 MOV EDX,dword ptr [EBP]+10 |
-----------------------------------------------------------------------------
420D435C 0F477514 CMOVA ESI,dword ptr [EBP]+14 |
420D4360 53 PUSH EBX |->syscall參數(shù)
420D4361 89FB MOV EBX,EDI |
420D4363 B81A000000 MOV EAX,0000001c //system call number value
420D4368 CD80 INT 80 //調(diào)用0x80
-----------------------------------------------------------------------------
從上面的代碼我們可以看到這樣一種情況,這里我們假設(shè)調(diào)用系統(tǒng)函數(shù)write來寫輸出
write(filehandle, buf, buf_length)
其匯編代碼的函數(shù)調(diào)用,基本如下:
push buf_length
push buf
push filehandle
call write
然后進(jìn)入到write函數(shù)后,我們就知道Linux的syscall的一個(gè)完整過程如下:
高級語言調(diào)用系統(tǒng)函數(shù)|
->jump syscall(即系統(tǒng)對系統(tǒng)函數(shù)的標(biāo)識(shí))|
->把syscall的參數(shù)賦給寄存器|
->mov eax,0x**(及上面write函數(shù)針對syscall的數(shù)值)|
->int 0x80|
->返回|
基本過程如上所示,那么如果我們spoof(欺騙)這些傳遞參數(shù)的寄存器呢?假設(shè)spoof是成功的,
那么很容易就會(huì)把一些壞變量值傳遞到syscall的系統(tǒng)調(diào)用,緊接著系統(tǒng)內(nèi)核可能在接收到一些
壞信息的時(shí)候,處理不當(dāng),導(dǎo)致系統(tǒng)出現(xiàn)異;蛘呦到y(tǒng)發(fā)生溢出.當(dāng)然這些僅僅是猜測,本文的很
多內(nèi)容都是在猜測,至于答案嘛,可能永遠(yuǎn)都沒有...
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
FreeBSD的syscall調(diào)用:
28080D98: 31C0 XOR EAX,EAX
28080D9A: 53 PUSH EBX
28080D9B: E800000000 CALL near32 ptr 28080da0
28080DA0: 5B POP EBX
28080DA1: 81C3AC980600 ADD EBX,000698ac
28080DA7: 8B934C0A0000 MOV EDX,dword ptr [EBX]+00000a4c
28080DAD: 8902 MOV dword ptr [EDX],EAX
28080DAF: 5B POP EBX
28080DB0: 8D051A000000 LEA EAX,dword ptr [0000001c]//system call number value
28080DB6: CD80 INT 80
28080DB8: 7201 JC short ptr 28080dbb
28080DBA: C3 RETN
從上面的代碼我們也可以看到這樣一種情況,這里我們假設(shè)調(diào)用系統(tǒng)函數(shù)write來寫輸出:)
write(filehandle, buf, buf_length)
其匯編代碼的函數(shù)調(diào)用,基本如下:
push buf_length
push buf
push filehandle
call write
然后進(jìn)入到write函數(shù)后,我們就知道Linux的syscall的一個(gè)完整過程如下:
高級語言調(diào)用系統(tǒng)函數(shù)|
->jump syscall(即系統(tǒng)對系統(tǒng)函數(shù)的標(biāo)識(shí))|
->mov eax,0x**(及上面write函數(shù)針對syscall的數(shù)值)|
->int 0x80|
->返回|
根據(jù)我的跟蹤分析,發(fā)現(xiàn)FreeBSD使用了程序里面的參數(shù)變量,這樣的情況就是FreeBSD省去了一個(gè)寄存器調(diào)用
函數(shù)參數(shù)的過程,這樣就禁止了可能存在spoof寄存器的問題,從這點(diǎn)上來看,FreeBSD的確比Linux要安全很多.
------------------------------------------------------------------------------------------------
雖然Linux的這個(gè)syscall會(huì)調(diào)用寄存器保存參數(shù)值,可能有其好處(最起碼我感覺看代碼和分析一些內(nèi)核的時(shí),
舒服了很多:)),但是如果有些高人能夠spoof寄存器,那么可能會(huì)引起一些麻煩,當(dāng)然這樣的麻煩還需要和特定的
程序掛鉤,不是說spoof就spoof成功的:)
FreeBSD的就優(yōu)良了很多,我不得不佩服FreeBSD的優(yōu)點(diǎn),開始的時(shí)候我也經(jīng)常被FreeBSD這樣的調(diào)用方式搞的頭大
的厲害,但是就這么看啊看的,反而習(xí)慣了.在之前的時(shí)候,一直是一段時(shí)間Linux,一段時(shí)間BSD;只有在最近交叉跟
蹤的時(shí)候,才發(fā)現(xiàn)上面這個(gè)自己感覺比較有意思的問題:)
--]FreeBSD的程序比Linux的運(yùn)行速度快?
這個(gè)問題很難說,如果從上面的代碼來看的話,少了這么多的匯編代碼,說FreeBSD比Linux慢估計(jì)誰都不會(huì)相信的.
當(dāng)然我沒有針對FreeBSD的系統(tǒng)架構(gòu)與Linux的系統(tǒng)架構(gòu)進(jìn)行更深入的對比分析,所以也不敢枉自下如此不清晰的結(jié)
論:)如果那位有興趣,能不能在相同的硬件平臺(tái)下,對這倆OS做下測試?
再繼續(xù)羅嗦一個(gè)問題,雖然FreeBSD比Linux少了些匯編代碼,但是syscall的參數(shù)FreeBSD肯定也是獲取的,只不過
獲取的方式比Linux更直接了一些:)
--]FreeBSD與Linux的shellcode
先廢話一下,說到syscall如果不說些shellcode的故事,好像的確是少了那么一點(diǎn)點(diǎn)事情...So,我們來看看FreeBSD
與Linux的shellcode.我書寫了一些簡單的shellcode,看到網(wǎng)上很多關(guān)于shellcode的中文教程都是拿GDB不斷調(diào)試出
來的,感覺好麻煩 個(gè)人認(rèn)為既然熟悉GDB調(diào)試技術(shù),肯定熟悉匯編,也肯定熟悉syscall,不熟悉找下頭文件看看不就得
了...于是我一直用匯編來寫這些可愛的shellcode,剛學(xué)會(huì)幾天,不對的地方大家明示:)
到底是先說FreeBSD的shellcode,還是先說Linux的呢?我拿硬幣拋了下,至于為什么拋硬幣...困了...找點(diǎn)刺激自己
神經(jīng)的方法:)).好了,硬幣拋完了,先說FreeBSD下面的.
編譯:nasm -f elf ***.asm
ld -s -o *** ***.o
A: FreeBSD下面的shellcode(hello.asm):
section .text
global _start
_start:
xor eax,eax
cdq
push 0x0a216472
push 0x6f57206f
push 0x6c6c6548
mov ebx,esp
push byte 0xc
push ebx
push byte 0x1
push eax
mov al,0x4
int 0x80
xor eax,eax
push eax
mov al,0x1
int 0x80
------------------------------------------------------------------------------------------------
上面的的匯編代碼可以直接編譯來獲取shellcode,按照前面說的編譯辦法編譯,然后:
objdump -D hello > hello.txt
把獲得的機(jī)器碼copy出來就是一個(gè)freebsd下面的shellcode了.
B: Linux下面的shellcode(hello.asm):
global _start
_start:
xor eax,eax
jmp short string
code:
pop esi
push byte 15
push esi
push byte 1
push eax
int 0x80
xor eax,eax
push eax
push eax
mov al,1
int 0x80
string:
call code
db "Hello word!", 0x0a
------------------------------------------------------------------------------------------------
上面的的匯編代碼可以直接編譯來獲取shellcode,按照前面說的編譯辦法編譯,然后:
objdump -D hello > hello.txt
把獲得的機(jī)器碼copy出來就是一個(gè)linux下面的shellcode了.
C: 為什么FreeBSD與Linux下面的shellcode不同?
這個(gè)問題,我想留給大家先思考下,然后再看我的下文.如果你看了我的下文還是不了解的話...那么可能的情況
是你根本還不會(huì)匯編和Unix類型的編程...還有一個(gè)情況是,你太笨了
C-1: Linux的syscall的系統(tǒng)調(diào)用是如下的過程:
高級語言調(diào)用系統(tǒng)函數(shù)|
->jump syscall(即系統(tǒng)對系統(tǒng)函數(shù)的標(biāo)識(shí))|
->把syscall的參數(shù)賦給寄存器|
->mov eax,0x**(及上面write函數(shù)針對syscall的數(shù)值)|
->int 0x80|
->返回|
那么,我們的shellcode在push參數(shù)的時(shí)候,就比較隨便一些了,因?yàn)樵诤竺娴南到y(tǒng)級別的syscall又對參數(shù)進(jìn)行了二
次的賦值,賦值給各個(gè)寄存器,然后才調(diào)用syscall.
C-2: FreeBSD的syscall系統(tǒng)調(diào)用是如下的過程:
高級語言調(diào)用系統(tǒng)函數(shù)|
->jump syscall(即系統(tǒng)對系統(tǒng)函數(shù)的標(biāo)識(shí))|
->mov eax,0x**(及上面write函數(shù)針對syscall的數(shù)值)|
->int 0x80|
看到?jīng)]有,或者說前面的內(nèi)容記憶起來了吧?freebsd的syscall調(diào)用是在進(jìn)入系統(tǒng)syscall前就push進(jìn)來的,所以我們的shellcode必須得把參數(shù)的值先push進(jìn)來,而不是象linux那樣的隨意.
總結(jié)
其實(shí),最后這部分關(guān)于shellcode的不同之處,真正要寫的話,估計(jì)還得整整的一篇內(nèi)容.但是...人是鐵飯是鋼,一頓不吃餓的慌.于是準(zhǔn)備做下逃兵,先去添飽肚子,然后美美的睡一覺.順便做個(gè)美夢,在夢中,偶的"老大"又開始欺負(fù)偶了... |
|