Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ func init() {
rootCmd.PersistentFlags().IntVar(&gconfig.BrkPid, "brk-pid", -1, "set hardware breakpoint pid, just keep default")
rootCmd.PersistentFlags().StringVar(&gconfig.BrkLib, "brk-lib", "", "as library base address, work with -p/--pid option")
rootCmd.PersistentFlags().Uint64Var(&gconfig.BrkLen, "brk-len", 4, "hardware breakpoint length, default 4, support [1, 8]")
rootCmd.PersistentFlags().StringArrayVar(&gconfig.BrkPoint, "brk-point", []string{}, "read args when hardware breakpoint hits, e.g. buf:128:x0 or [int:x1,buf:64:x0+8.ptr32+0x10]")
// 缓冲区大小设定 单位M
rootCmd.PersistentFlags().Uint32VarP(&gconfig.Buffer, "buffer", "b", 8, "perf cache buffer size, default 8M")
rootCmd.PersistentFlags().Uint32Var(&gconfig.MaxOp, "maxop", 64, "max operation count for uprobe, at least 192 for string array")
Expand All @@ -661,10 +662,11 @@ func init() {
rootCmd.PersistentFlags().StringVar(&gconfig.ParseFile, "parse", "", "parse perf data as json or readable format")
// 常规ELF库hook设定
rootCmd.PersistentFlags().StringVarP(&gconfig.Library, "lib", "l", "libc.so", "lib name or lib full path, default is libc.so")
rootCmd.PersistentFlags().StringArrayVarP(&gconfig.HookPoint, "point", "w", []string{}, "hook point config, e.g. strstr+0x0[str,str] write[int,buf:128,int]")
rootCmd.PersistentFlags().StringArrayVarP(&gconfig.HookPoint, "point", "w", []string{}, "hook point config, e.g. strstr+0x0[str,str] write[int,buf:128:x0+0x8.ptr32+0x10]")
rootCmd.PersistentFlags().StringVar(&gconfig.RegName, "reg", "", "get the offset of reg")
rootCmd.PersistentFlags().BoolVarP(&gconfig.DumpRet, "dumpret", "", false, "dump ret offset for symbol")
rootCmd.PersistentFlags().BoolVarP(&gconfig.DumpHex, "dumphex", "", false, "dump buffer as hex")
rootCmd.PersistentFlags().BoolVarP(&gconfig.DumpBase64, "dumpbase64", "", false, "dump buffer as base64")
rootCmd.PersistentFlags().BoolVarP(&gconfig.ShowPC, "showpc", "", false, "show origin pc register value")
rootCmd.PersistentFlags().BoolVarP(&gconfig.ShowTime, "showtime", "", false, "show event boot time info")
rootCmd.PersistentFlags().BoolVarP(&gconfig.ShowUid, "showuid", "", false, "show process uid info")
Expand Down
2 changes: 1 addition & 1 deletion src/common/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ static __always_inline int save_str_to_buf(event_data_t *event, void *ptr, u8 in
static __always_inline int save_utf16_to_buf(event_data_t *event, void *ptr, u8 index)
{
// UTF16 最大字节数(必须是偶数)
int max_bytes = 512;
int max_bytes = MAX_BUF_READ_SIZE;
// 直接调用 save_bytes_to_buf
return save_bytes_to_buf(event, ptr, max_bytes, index);
}
Expand Down
6 changes: 4 additions & 2 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ enum op_code_e
OP_READ_STD_STRING,
OP_READ_IL2CPP_STRING,
OP_SAVE_STRING16,
OP_SAVE_PTR_STRING16
OP_SAVE_PTR_STRING16,
OP_READ_POINTER32,
OP_READ_POINTER64
};

enum arm64_reg_e
Expand Down Expand Up @@ -290,4 +292,4 @@ typedef struct file_info {
u64 ctime;
} file_info_t;

#endif
#endif
26 changes: 26 additions & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,32 @@ static __noinline u32 read_args(program_data_t* p, point_args_t* point_args, op_
bpf_probe_read_user(&op_ctx->pointer_value, PTR_SIZE, (void*)op_ctx->read_addr);
}
break;
case OP_READ_POINTER32:
{
u32 ptr = 0;
if (op->pre_code == OP_ADD_OFFSET) {
bpf_probe_read_user(&ptr, sizeof(ptr), (void*)(op_ctx->read_addr + op->value));
} else if (op->pre_code == OP_SUB_OFFSET) {
bpf_probe_read_user(&ptr, sizeof(ptr), (void*)(op_ctx->read_addr - op->value));
} else {
bpf_probe_read_user(&ptr, sizeof(ptr), (void*)op_ctx->read_addr);
}
op_ctx->pointer_value = ptr;
break;
}
case OP_READ_POINTER64:
{
u64 ptr = 0;
if (op->pre_code == OP_ADD_OFFSET) {
bpf_probe_read_user(&ptr, sizeof(ptr), (void*)(op_ctx->read_addr + op->value));
} else if (op->pre_code == OP_SUB_OFFSET) {
bpf_probe_read_user(&ptr, sizeof(ptr), (void*)(op_ctx->read_addr - op->value));
} else {
bpf_probe_read_user(&ptr, sizeof(ptr), (void*)op_ctx->read_addr);
}
op_ctx->pointer_value = ptr;
break;
}
case OP_SAVE_POINTER:
save_to_submit_buf(p->event, (void *)&op_ctx->pointer_value, sizeof(op_ctx->pointer_value), op_ctx->save_index);
op_ctx->save_index += 1;
Expand Down
18 changes: 18 additions & 0 deletions tests/config_uprobe_test_base64.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"type": "uprobe",
"library": "libtest.so",
"points": [
{
"name": "testBytesBase64",
"params": [
{
"name": "buf_bytes",
"type": "buf",
"reg": "x0",
"size": "x1",
"format": "base64"
}
]
}
]
}
3 changes: 3 additions & 0 deletions user/argtype/argtype_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,9 @@ func (this *ARG_BUFFER) ParseArg(ptr uint64, buf *bytes.Buffer, parse_more, fmt_
(this.ParseImpl).(IArgBuffer).SetArgPayload(payload)
}
if !fmt_json {
if this.DumpBase64 {
return fmt.Sprintf("0x%x%s", ptr, this.ParseImpl.HexToBase64Format())
}
if this.DumpHex {
return fmt.Sprintf("0x%x%s", ptr, this.ParseImpl.HexFormat(this.Color))
}
Expand Down
22 changes: 22 additions & 0 deletions user/argtype/config_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"encoding/json"
"encoding/base64"
"fmt"
"net"
"stackplz/user/util"
Expand Down Expand Up @@ -50,6 +51,7 @@ type IParseStruct interface {
GetArgStruct() *Arg_struct
Format() string
HexFormat(bool) string
HexToBase64Format() string
}

// 结构体类型
Expand Down Expand Up @@ -115,6 +117,10 @@ func (this *Arg_buffer) HexFormat(color bool) string {
return "()"
}

func (this *Arg_buffer) HexToBase64Format() string {
return fmt.Sprintf(" (base64:%s)", base64.StdEncoding.EncodeToString(this.ArgPayload))
}

func (this *Arg_buffer) MarshalJSON() ([]byte, error) {
type ArgStructAlias Arg_struct
return json.Marshal(&struct {
Expand Down Expand Up @@ -143,6 +149,10 @@ func (this *Arg_string) HexFormat(color bool) string {
return this.Format()
}

func (this *Arg_string) HexToBase64Format() string {
return this.Format()
}

func (this *Arg_string) Format() string {
return fmt.Sprintf("(%s)", util.B2STrim(this.ArgPayload))
}
Expand Down Expand Up @@ -190,6 +200,10 @@ func (this *Arg_string16) HexFormat(color bool) string {
return this.Format()
}

func (this *Arg_string16) HexToBase64Format() string {
return this.Format()
}

func (this *Arg_string16) Format() string {
// UTF‑16LE → UTF‑8
s := utf16leToUtf8(this.ArgPayload)
Expand Down Expand Up @@ -237,6 +251,10 @@ func (this *Arg_Sigaction) HexFormat(color bool) string {
return this.Format()
}

func (this *Arg_Sigaction) HexToBase64Format() string {
return this.Format()
}

func (this *Arg_Sigaction) Format() string {
var fields []string
fields = append(fields, fmt.Sprintf("sa_handler=0x%x", this.Sa_handler))
Expand Down Expand Up @@ -288,6 +306,10 @@ func (this *Arg_Timespec) HexFormat(color bool) string {
return this.Format()
}

func (this *Arg_Timespec) HexToBase64Format() string {
return this.Format()
}

func (this *Arg_Timespec) Format() string {
var fields []string
fields = append(fields, fmt.Sprintf("sec=%d", this.Sec))
Expand Down
12 changes: 12 additions & 0 deletions user/argtype/iargtype.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ type IArgType interface {
GetTypeIndex() uint32
SetParentIndex(uint32)
SetDumpHex(bool)
SetDumpBase64(bool)
SetColor(bool)
GetDumpHex() bool
GetDumpBase64() bool
GetColor() bool
GetParentIndex() uint32
GetSize() uint32
Expand Down Expand Up @@ -54,6 +56,7 @@ type ArgType struct {
ParseCB ParseFN
ParseImpl IParseStruct
DumpHex bool
DumpBase64 bool
Color bool
}

Expand All @@ -77,6 +80,7 @@ func (this *ArgType) Clone() IArgType {
at.ParseCB = this.ParseCB
at.ParseImpl = this.ParseImpl
at.DumpHex = this.DumpHex
at.DumpBase64 = this.DumpBase64
at.Color = this.Color
return &at
}
Expand Down Expand Up @@ -105,6 +109,10 @@ func (this *ArgType) SetDumpHex(dump_hex bool) {
this.DumpHex = dump_hex
}

func (this *ArgType) SetDumpBase64(dump_base64 bool) {
this.DumpBase64 = dump_base64
}

func (this *ArgType) SetColor(color bool) {
this.Color = color
}
Expand All @@ -113,6 +121,10 @@ func (this *ArgType) GetDumpHex() bool {
return this.DumpHex
}

func (this *ArgType) GetDumpBase64() bool {
return this.DumpBase64
}

func (this *ArgType) GetColor() bool {
return this.Color
}
Expand Down
4 changes: 4 additions & 0 deletions user/argtype/op_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const (
OP_READ_IL2CPP_STRING
OP_SAVE_STRING16
OP_SAVE_PTR_STRING16
OP_READ_POINTER32
OP_READ_POINTER64
)

type BaseOpConfig struct {
Expand Down Expand Up @@ -299,6 +301,8 @@ var OPC_READ_STD_STRING = ROP("READ_STD_STRING", OP_READ_STD_STRING)
var OPC_READ_IL2CPP_STRING = ROP("READ_IL2CPP_STRING", OP_READ_IL2CPP_STRING)
var OPC_SAVE_STRING16 = ROP("OPC_SAVE_STRING16", OP_SAVE_STRING16)
var OPC_SAVE_PTR_STRING16 = ROP("SAVE_PTR_STRING16", OP_SAVE_PTR_STRING16)
var OPC_READ_POINTER32 = ROP("READ_POINTER32", OP_READ_POINTER32)
var OPC_READ_POINTER64 = ROP("READ_POINTER64", OP_READ_POINTER64)

func BuildReadRegBreakCount(reg_index uint64) *OpConfig {
op := OpConfig{}
Expand Down
2 changes: 2 additions & 0 deletions user/common/const_forarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package common

import "fmt"

const NativePointerSize = 4

func GetRegIndex(reg string) uint32 {
value, ok := RegsArmNameMap[reg]
if !ok {
Expand Down
2 changes: 2 additions & 0 deletions user/common/const_forarm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package common

import "fmt"

const NativePointerSize = 8

func GetRegIndex(reg string) uint32 {
value, ok := RegsNameMap[reg]
if !ok {
Expand Down
90 changes: 90 additions & 0 deletions user/config/config_brk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package config

import (
"errors"
"fmt"
"regexp"
"strings"

. "stackplz/user/common"
)

type BrkPointConfig struct {
ArgsStr string
PointArgs []*PointArg
DumpHex bool
DumpBase64 bool
Color bool
}

func (this *BrkPointConfig) IsEnable() bool {
return len(this.PointArgs) > 0
}

func (this *BrkPointConfig) SetDumpHex(dumpHex bool) {
this.DumpHex = dumpHex
}

func (this *BrkPointConfig) SetDumpBase64(dumpBase64 bool) {
this.DumpBase64 = dumpBase64
}

func (this *BrkPointConfig) SetColor(color bool) {
this.Color = color
}

func (this *BrkPointConfig) Parse_BrkPoint(configs []string) error {
if len(configs) == 0 {
return nil
}
parser := &StackUprobeConfig{}
parser.SetDumpHex(this.DumpHex)
parser.SetDumpBase64(this.DumpBase64)
parser.SetColor(this.Color)

var allArgs []string
for _, configStr := range configs {
configStr = strings.TrimSpace(configStr)
if configStr == "" {
continue
}
argsStr, err := extractBrkArgs(configStr)
if err != nil {
return err
}
for _, argStr := range strings.Split(argsStr, ",") {
argStr = strings.TrimSpace(argStr)
if argStr != "" {
allArgs = append(allArgs, argStr)
}
}
}

this.ArgsStr = strings.Join(allArgs, ",")
for argIndex, argStr := range allArgs {
argName := fmt.Sprintf("arg_%d", argIndex)
pointArg := NewUprobePointArg(argName, POINTER, uint32(argIndex))
if err := parser.ParseArgType(argStr, pointArg); err != nil {
return err
}
this.PointArgs = append(this.PointArgs, pointArg)
}
return nil
}

func extractBrkArgs(configStr string) (string, error) {
if strings.HasPrefix(configStr, "[") && strings.HasSuffix(configStr, "]") {
return strings.TrimSpace(configStr[1 : len(configStr)-1]), nil
}

reg := regexp.MustCompile(`\[(.+)\]`)
match := reg.FindStringSubmatch(configStr)
if len(match) == 2 {
return strings.TrimSpace(match[1]), nil
}

if strings.Contains(configStr, "[") || strings.Contains(configStr, "]") {
return "", errors.New(fmt.Sprintf("parse brk point args failed: %s", configStr))
}
return configStr, nil
}
Loading