Skip to content

Commit

Permalink
Merge pull request #144 from myzhan/master
Browse files Browse the repository at this point in the history
try to write memory with mach_vm_protect on mac
  • Loading branch information
agiledragon committed Nov 9, 2023
2 parents 6da80f5 + b93e20c commit 14b9a3c
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 20 deletions.
37 changes: 17 additions & 20 deletions modify_binary_darwin.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
package gomonkey

import "syscall"
import (
"fmt"
"reflect"
"syscall"
"unsafe"
)

func modifyBinary(target uintptr, bytes []byte) {
function := entryAddress(target, len(bytes))
err := mprotectCrossPage(target, len(bytes), syscall.PROT_READ|syscall.PROT_WRITE)
if err != nil {
panic(err)
}
copy(function, bytes)
err = mprotectCrossPage(target, len(bytes), syscall.PROT_READ|syscall.PROT_EXEC)
if err != nil {
panic(err)
}
func PtrOf(val []byte) uintptr {
return (*reflect.SliceHeader)(unsafe.Pointer(&val)).Data
}

func mprotectCrossPage(addr uintptr, length int, prot int) error {
pageSize := syscall.Getpagesize()
for p := pageStart(addr); p < addr+uintptr(length); p += uintptr(pageSize) {
page := entryAddress(p, pageSize)
if err := syscall.Mprotect(page, prot); err != nil {
return err
}
func modifyBinary(target uintptr, bytes []byte) {
targetPage := pageStart(target)
res := write(target, PtrOf(bytes), len(bytes), targetPage, syscall.Getpagesize(), syscall.PROT_READ|syscall.PROT_EXEC)
if res != 0 {
panic(fmt.Errorf("failed to write memory, code %v", res))
}
return nil
}

//go:cgo_import_dynamic mach_task_self mach_task_self "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic mach_vm_protect mach_vm_protect "/usr/lib/libSystem.B.dylib"
func write(target, data uintptr, len int, page uintptr, pageSize, oriProt int) int
64 changes: 64 additions & 0 deletions write_darwin_amd64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "textflag.h"

#define NOP8 BYTE $0x90; BYTE $0x90; BYTE $0x90; BYTE $0x90; BYTE $0x90; BYTE $0x90; BYTE $0x90; BYTE $0x90;
#define NOP64 NOP8; NOP8; NOP8; NOP8; NOP8; NOP8; NOP8; NOP8;
#define NOP512 NOP64; NOP64; NOP64; NOP64; NOP64; NOP64; NOP64; NOP64;
#define NOP4096 NOP512; NOP512; NOP512; NOP512; NOP512; NOP512; NOP512; NOP512;

#define protRW $(0x1|0x2|0x10)
#define mProtect $(0x2000000+74)

TEXT ·write(SB),NOSPLIT,$24
JMP START
NOP4096
START:
MOVQ mProtect, AX
MOVQ page+24(FP), DI
MOVQ pageSize+32(FP), SI
MOVQ protRW, DX
SYSCALL
CMPQ AX, $0
JZ PROTECT_OK
CALL mach_task_self(SB)
MOVQ AX, DI
MOVQ target+0(FP), SI
MOVQ len+16(FP), DX
MOVQ $0, CX
MOVQ protRW, R8
CALL mach_vm_protect(SB)
CMPQ AX, $0
JNZ RETURN
PROTECT_OK:
MOVQ target+0(FP), DI
MOVQ data+8(FP), SI
MOVQ len+16(FP), CX
MOVQ DI, to-24(SP)
MOVQ SI, from-16(SP)
MOVQ CX, n-8(SP)
CALL runtime·memmove(SB)
MOVQ mProtect, AX
MOVQ page+24(FP), DI
MOVQ pageSize+32(FP), SI
MOVQ oriProt+40(FP), DX
SYSCALL
JMP RETURN
NOP4096
RETURN:
MOVQ AX, ret+48(FP)
RET
63 changes: 63 additions & 0 deletions write_darwin_arm64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2022 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "textflag.h"

#define NOP64 WORD $0x1f2003d5; WORD $0x1f2003d5;
#define NOP512 NOP64; NOP64; NOP64; NOP64; NOP64; NOP64; NOP64; NOP64;
#define NOP4096 NOP512; NOP512; NOP512; NOP512; NOP512; NOP512; NOP512; NOP512;
#define NOP16384 NOP4096; NOP4096; NOP4096; NOP4096; NOP4096; NOP4096; NOP4096; NOP4096;

#define protRW $(0x1|0x2|0x10)
#define mProtect $(0x2000000+74)

TEXT ·write(SB),NOSPLIT,$24
B START
NOP16384
START:
MOVD mProtect, R16
MOVD page+24(FP), R0
MOVD pageSize+32(FP), R1
MOVD protRW, R2
SVC $0x80
CMP $0, R0
BEQ PROTECT_OK
CALL mach_task_self(SB)
MOVD target+0(FP), R1
MOVD len+16(FP), R2
MOVD $0, R3
MOVD protRW, R4
CALL mach_vm_protect(SB)
CMP $0, R0
BNE RETURN
PROTECT_OK:
MOVD target+0(FP), R0
MOVD data+8(FP), R1
MOVD len+16(FP), R2
MOVD R0, to-24(SP)
MOVD R1, from-16(SP)
MOVD R2, n-8(SP)
CALL runtime·memmove(SB)
MOVD mProtect, R16
MOVD page+24(FP), R0
MOVD pageSize+32(FP), R1
MOVD oriProt+40(FP), R2
SVC $0x80
B RETURN
NOP16384
RETURN:
MOVD R0, ret+48(FP)
RET

0 comments on commit 14b9a3c

Please sign in to comment.