BuildStubShellcode patches the embedded 428-byte stub with the zygote pid, target app uid, original setArgV0 address (for the parent path + stage call-through), stage file path, and the stage's data-slot offsets.
(zygotePid int, origHookAddr uint64, stagePath string, targetUID int)
| 110 | // target app uid, original setArgV0 address (for the parent path + stage |
| 111 | // call-through), stage file path, and the stage's data-slot offsets. |
| 112 | func BuildStubShellcode(zygotePid int, origHookAddr uint64, stagePath string, targetUID int) ([]byte, error) { |
| 113 | if len(customStubBin) != CUSTOM_TRAP_SIZE { |
| 114 | return nil, fmt.Errorf("custom stub binary size mismatch: got %d want %d", len(customStubBin), CUSTOM_TRAP_SIZE) |
| 115 | } |
| 116 | if len(stagePath)+1 > STUB_STAGE_PATH_SIZE { |
| 117 | return nil, fmt.Errorf("stage path too long for stub path slot: %d > %d", len(stagePath), STUB_STAGE_PATH_SIZE-1) |
| 118 | } |
| 119 | trap := make([]byte, len(customStubBin)) |
| 120 | copy(trap, customStubBin) |
| 121 | binary.LittleEndian.PutUint32(trap[CUSTOM_PID_PATCH_OFF:], 0x52800001|(uint32(zygotePid&0xffff)<<5)) |
| 122 | binary.LittleEndian.PutUint32(trap[STUB_TARGET_UID_OFF:], uint32(targetUID)) |
| 123 | binary.LittleEndian.PutUint64(trap[STUB_ORIG_HOOK_OFF:], origHookAddr) |
| 124 | binary.LittleEndian.PutUint64(trap[STUB_STAGE_DATA_OFF_OFF:], STAGE_DATA_EMBED_OFF) |
| 125 | binary.LittleEndian.PutUint64(trap[STUB_STAGE_DATA_SLOT_OFF_OFF:], STAGE_DATA_TABLE_SLOT_OFF) |
| 126 | binary.LittleEndian.PutUint64(trap[STUB_STAGE_ORIG_SLOT_OFF_OFF:], STAGE_ORIG_HOOK_SLOT_OFF) |
| 127 | for i := range STUB_STAGE_PATH_SIZE { |
| 128 | trap[STUB_STAGE_PATH_OFF+i] = 0 |
| 129 | } |
| 130 | copy(trap[STUB_STAGE_PATH_OFF:], []byte(stagePath)) |
| 131 | return trap, nil |
| 132 | } |