// // Public API of jtrace for third parties // // License: Absolutely free for NON-COMMERCIAL use. // // If you want to use this commercially, Please talk to me. // // You might want to consider reading my books, or going // to a training at www.technologeeks.com, where we teach // this stuff and lots more. // // #include #include #ifndef JTRACE_API_H #define JTRACE_API_H // // New, far simpler API: // // No more regs! Registers are stashed in thread local storage and entirely abstracted by getRegValue(#) // so you don't need to concern yourself with arch differences. Also, is_32() gets bitness from TLS as well, // so getRegValue needs just one argument - the register number! // int ignoreAllSyscalls(void); uint32_t hexDumpToBuffer (char *OutputBuf, int OutputLen, char *Buffer, int Len, uint64_t Address, int Indent); #ifndef _32 typedef unsigned long uint64_t; #endif #ifdef _32 #define arch_int uint32_t #else #define arch_int uint64_t #endif // // Abstracting the calling convention: // // JTrace will automatically translate these register "numbers" into the corresponding // registers of the underlying architecture, as per the ABI. In the ARM64 case, these // are straightforward noops - ARG_0...ARG_7 are X0..X7. In ARM32, X0..X3 are 0..3, // but jtrace is smart enough to get the other "register" values from the stack. In the // Intel case, the mapping is between rdi/rsi/rdx/rcx/r8/r9 or the stack. // // Likewise, the syscall number - in Intel, that's eax/rax. In ARM32/ARM64 r7/r8 respectively // // This enables you to get the arguments in a plugin without bothering to consider how the // calling convention works! #define REG_ARG_0 0 #define REG_ARG_1 1 #define REG_ARG_2 2 #define REG_ARG_3 3 #define REG_ARG_4 4 // ARM32: stack #define REG_ARG_5 5 #define REG_ARG_6 6 // Probably won't need more than this since syscalls have max 6.. #define REG_ARG_7 7 // these are intentionally values greater than ARM64's registers, // so we are guaranteed to map them by ABI #define REG_ARG_RETVAL 33 #define REG_ARG_SYSCALL_NUM 34 // The actual register representation is the per architecture pt_regs, // but that's made opaque by this here struct typedef struct jtregs regs_t; // the opaque structure will be provided for you (by reference) when jtrace // calls your callback handler, which needs to be implemented as: typedef enum { DO_NOTHING = 0, // You want JTrace to continue as normal BLOCK = 1, // You want JTrace to block this system call NOT_HANDLED = 2, // You didn't handle the syscall } syscall_handler_ret_t; typedef syscall_handler_ret_t (*syscall_handler_func) (int exit, int pid); enum syscallHandlerFlags { HANDLER_ENTRY_ONLY = 1, HANDLER_EXIT_ONLY = 2, HANDLER_OVERRIDE_DEFAULT = 1024, }; // piece de resistance int registerSyscallHandler (char *SyscallName, // must exist or you'll get -1 syscall_handler_func Handler, // Your callback, per above int Bitness, // 32, 64 or 0 (both) int Flags); // as per flags, above #define ERR_SYSCALL_NOT_FOUND (-1) // The idea is to then leave the regs_t opaque, and use the accessor: // And to ensure that's the case, JTrace no longer exports regs. long getRegValue (int num); // setRegValue - calls GETREGS, changes your value, then calls SETREGS void setRegValue (int num, uint64_t value); // Stash register values between calls. // Use this primarily for REG_ARG_0, which will be often destroyed // on syscall exit. Note the saved registers are also on TLS, but // may be different from the "real" ones (i.e. getRegValue ! necessarily = getSavedRegValue) // void saveRegValue (uint32_t Reg) ; uint64_t getSavedRegValue (uint32_t Reg); // This conveniently hides process_vm_readv, /proc/pid/mem, or ptrace int readProcessMemory (int Pid, arch_int Addr, int Size, char *MyAddr); //--- 3/30/2017 ---- // And this can set the process memory, writing Size bytes from MyAddr to Addr! int writeProcessMemory (int Pid, arch_int Addr, int Size, char *MyAddr); // Get an FD name. This is useful for operating in read/write hooks only // if the fd is connected to a certain file char *getFDName(int fd); //--- 3/26/2018 One year later -- typedef int binderHook_t (char *Parcel , size_t Size, int Code); int registerBinderIoctlHook(char *interface, // UTF-8 or UTF-16 OK binderHook_t Hook); // -- 3/07/2020 Two years further: Back to Android Internals, full steam! // Returns jtrace verbosity level, as per user specified "-v" arguments. // You can use this to have your plugin print more (or less) information accordingly int getVerbosityLevel (); char *getIOVecDataFromMsgHdr (struct msghdr *MsgHdr, unsigned int *BytesRead, pid_t Pid); // Resolve name (from cmdline) for a given PID. // hides /proc//cmdline, and possible caching char *getProcNameForPid (pid_t pid); // Is JTrace's current config colorful? int config_color() ; int config_debug() ; //-------------------------------------------------------------------- // Other APIs I use for testing //----------------------------- // Get a system call number by providing its name. This is especially useful // for testing, because God only knows why the numbers keep changing across // various platforms. int getSyscallNum (char *); // New - Rather than printf() char *getOutputBuffer (); void updateOutputBufferPos(int byHowMuch); // For testing void dumpArgumentsForSyscall (char *); void dumpAllSyscalls(int); int get_is32(void); #endif