Thursday, July 5, 2012

先進Shellcoding技術 - 由Darawk


先進Shellcoding技術 - 由Darawk
介紹
本文假定一個基本shellcoding技術的工作經驗,和x86彙編,我不會老調重彈,在本文這些。我希望教給你,我拿起一些鮮為人知shellcoding的技術,這將使你寫的更小,更好的shellcodes。我不聲稱已經發明了這些技術,除使用DIV指令。



MUL多重
這種技術最初的開發Sorbo darkircop.net。 MUL指令,可能表面上看起來很平常,它的目的明顯。然而,當面對困難的挑戰你的shellcode萎縮,它被證明是非常有用的。首先,一些MUL指令本身的背景資料。
MUL執行兩個整數無符號乘法。它只有一個操作數,另一種是隱式指定%eax寄存器。因此,一個共同的MUL指令可能看起來像這樣:
MOVL 0x0A返回$,%eax中MUL美元0x0A返回
這將乘以MUL操作,在這種情況下,將是10 * 10存儲在%eax的值。結果,然後含蓄地存儲在EDX:EAX中。結果存儲跨度超過兩個寄存器,因為它有可能要大大高於以前的值較大,可能超過一個寄存器的能力(這也是浮動點是如何存儲在某些情況下,作為一個有趣的旁注)
所以,現在來的日益重要的問題。我們如何使用這些屬性來寫shellcode時,我們的優勢?好吧,讓我們覺得第二,指令只需要一個操作數,因此,因為它是一個很常見的指​​令,它會產生我們最終的shellcode中只有兩個字節。它乘以無論是通過存儲在%eax的值,並存儲在%EDX和%eax中的值,完全覆蓋兩個寄存器的內容,不論是否這樣做是必要的,以存儲乘法的結果。讓我們把我們數學家帽子上的第二,並認為這是,由0相乘的唯一可能的結果是什麼?答案,你可能已經猜到,是0。我認為它是一些示例代碼的時間,所以在這裡它是:
xorl%ECX%ECXMUL%ECX
這是什麼的shellcode做呢?那麼,它的0%ecx寄存器使用XOR指令,所以我們現在知道%ECX是0。然後,它做了MUL%ecx中,正如我們剛剛獲悉,乘以它的操作數在%eax的值,然後繼續存儲,這在EDX中的乘法結果:EAX中。所以,不論%eax中的以前的內容,%eax中,現在必須為0。但是這不是全部,EDX%是0'd現在,因為即使沒有發生溢出,它仍然覆蓋%edx寄存器%eax中的符號位(最左邊的位)。使用這種技術,我們可以為零,只有三個字節三個寄存器,而任何其他的方法(我知道),它會採取至少6個。

DIV指令
Div是MUL,非常相似,它只有一個操作數和隱含操作數除以在%eax的值。也很喜歡,MUL它存儲在%eax的鴻溝的結果。再次,我們將要求我們的大腦在數學方面,要弄清楚如何,我們可以利用這個指令。但首先,讓我們覺得什麼通常存儲在%eax寄存器。 %eax寄存器保存的功能和/或系統調用的返回值。大部分,在shellcoding使用的系統調用將返回-1(失敗)或某種形式的積極價值,只有很少他們將返回0(儘管它發生)。因此,如果我們知道%eax中,執行一個系統調用後,將有一個非零的值,並指令divl%eax中,將劃分本身的%eax中,然後將其存儲在%eax的結果,我們可以說,執行divl%eax中一個系統調用指令後,將投入到%eax中的值1。所以......這是怎麼到shellcoding?嗯,他們是%eax中用於另一個重要的事情,那就是通過特定的系統調用,你想打電話到int $ 0x80的。碰巧的是,值1對應的syscall是exit()。現在的一個例子:

       
xorl%ebx中,%ebx中MUL%ebx中推%EDXpushl $ 0x3268732fpushl $ 0x6e69622f%MOV ESP,EBX%推%EDX推%ebx中%MOV ESP,ECX%MOVB $ 0xb,%]#調用execve()系統調用,不返回,除非它失敗,在這種情況下返回-1為int $ 0x80的
divl%eax中#-1 / -1 = 1為int $ 0x80的
現在,我們有一個3字節的退出功能,像以前一樣,這是5個字節。然而,有一個陷阱,如果一個系統調用返回0?井奇在可能發生的情況,你可以做許多不同的事情一樣,INC%eax中,DEC%eax中,%eax中,這將使%eax中非零的任何。有些人說出口的並不重要,在shellcode,因為你的代碼被執行,不論是否退出不乾淨。他們是正確的,如果你真的需要保存3個字節的地方,以適應你的shellcode的exit()是不值得保留。然而,當你的代碼沒有完成,它會嘗試執行後,你的最後一條指令,將最有可能產生一個SIG館際互借(非法指令)這是一個相當奇怪的錯誤,將被系統記錄。因此,退出()只是增加了額外的一層隱形的漏洞,因此,即使失敗或你不能消滅所有的日誌你的存在,至少這部分將是明確的。


萊亞爾電源解鎖
萊亞爾指令是在shellcode常常被忽視的指令,即使它是非常有用的。認為這一小段的shellcode。
xorl%ECX%ECX萊亞爾為0x10(ECX),%eax中
這將加載到eax的值17,清除所有EAX無關位。這是因為萊亞爾指令加載到它的輸出地址的操作數的類型長的變量。在它的正常使用,這將載入到寄存器變量的地址,從而創造了各種各樣的指針。然而,因為ECX是0'd和0 +17 = 17,我們加載到eax的值17,而不是任何實際地址。在一個正常的shellcode,我們會做這樣的事情,完成同樣的事情:
xorl%eax中,%eax中MOVB美元為0x10,%eax中
我可以聽到你說,但說的shellcode是字節比萊亞爾一短,你說得對。然而,在一個真正的shellcode,你可能已經有了比0淘汰像ECX(或任何其他寄存器)寄存器,所以不計算在萊亞爾的shellcode xorl指令。下面是一個例子:
xorl%eax中,%eax中xorl%ebx中,%ebx中MOVB $ 0x17,%人為int $ 0x80的
       
xorl%ebx中,%ebx中萊亞爾0x17(%ebx中),%]為int $ 0x80的
這些shellcodes調用setuid(0),但在7個字節,而其他8。再次,我聽到你說,但是,它沒有多大的差別,只有一個字節,你說得對,在這裡它不使多大的差別(除的shellcode大小撒尿比賽= P) ,但應用到更大的的shellcodes,其中有許多函數調用和需要做的事情這樣頻繁時,它可以節省相當多的空間位。


結論
我希望你們都學到了一些東西,將走出去,運用你的知識,創造較小的和更好shellcodes的。如果你知道是誰發明的萊亞爾技術,請告訴我,我會記入他/她。