From f75cf5666560a0d06448f410228ffbcaf3c94f2e Mon Sep 17 00:00:00 2001 From: netanel Date: Thu, 16 Nov 2023 09:44:43 -0800 Subject: [PATCH] Working handle_call --- src/protos/gpt_construct_rpc.proto | 185 --------------- src/protos/rpc.proto | 32 ++- src/rpcserver/rpcserver.c | 347 ++++++++++++++++------------- 3 files changed, 213 insertions(+), 351 deletions(-) delete mode 100644 src/protos/gpt_construct_rpc.proto diff --git a/src/protos/gpt_construct_rpc.proto b/src/protos/gpt_construct_rpc.proto deleted file mode 100644 index fe84eb6d..00000000 --- a/src/protos/gpt_construct_rpc.proto +++ /dev/null @@ -1,185 +0,0 @@ -syntax = "proto3"; - -// Enum for cmd_type_t -enum CmdType { - CMD_EXEC = 0; - CMD_DLOPEN = 1; - CMD_DLCLOSE = 2; - CMD_DLSYM = 3; - CMD_CALL = 4; - CMD_PEEK = 5; - CMD_POKE = 6; - CMD_REPLY_ERROR = 7; - CMD_REPLY_PEEK = 8; - CMD_GET_DUMMY_BLOCK = 9; - CMD_CLOSE = 10; - CMD_REPLY_POKE = 11; - CMD_LISTDIR = 12; - CMD_SHOWOBJECT = 13; - CMD_SHOWCLASS = 14; - CMD_GET_CLASS_LIST = 15; -} - -// Enum for arch_t -enum ArchType { - ARCH_UNKNOWN = 0; - ARCH_ARM64 = 1; -} - -// Struct for protocol_handshake_t -message ProtocolHandshake { - int32 magic = 1; - ArchType arch = 2; - string sysname = 3; - string machine = 4; -} - -// Struct for cmd_exec_t -message CmdExec { - int32 background = 1; - repeated string argv = 2; - repeated string envp = 3; -} - -// Struct for cmd_dlopen_t -message CmdDlopen { - string filename = 1; - int32 mode = 2; -} - -// Struct for cmd_dlclose_t -message CmdDlclose { - int64 lib = 1; -} - -// Struct for cmd_dlsym_t -message CmdDlsym { - int64 lib = 1; - string symbol_name = 2; -} - -// Enum for argument_type_t -enum ArgumentType { - INTEGER = 0; - DOUBLE = 1; -} - -// Struct for argument_t -message Argument { - ArgumentType type = 1; - oneof value { - int64 int_value = 2; - double double_value = 3; - } -} - -// Struct for cmd_call_t -message CmdCall { - int64 address = 1; - int64 va_list_index = 2; - repeated Argument argv = 3; -} - -// Struct for cmd_peek_t -message CmdPeek { - int64 address = 1; - int64 size = 2; -} - -// Struct for cmd_poke_t -message CmdPoke { - int64 address = 1; - int64 size = 2; - bytes data = 3; -} - -// Struct for cmd_dirlist_t -message CmdDirlist { - string filename = 1; -} - -// Struct for cmd_showobject_t -message CmdShowobject { - int64 address = 1; -} - -// Struct for cmd_showclass_t -message CmdShowclass { - int64 address = 1; -} - -// Struct for listdir_entry_stat_t -message ListdirEntryStat { - int64 errno = 1; - int64 st_dev = 2; - int64 st_mode = 3; - int64 st_nlink = 4; - int64 st_ino = 5; - int64 st_uid = 6; - int64 st_gid = 7; - int64 st_rdev = 8; - int64 st_size = 9; - int64 st_blocks = 10; - int64 st_blksize = 11; - int64 st_atime = 12; - int64 st_mtime = 13; - int64 st_ctime = 14; -} - -// Struct for listdir_entry_t -message ListdirEntry { - int64 d_type = 1; - int64 d_namlen = 2; - ListdirEntryStat lstat = 3; - ListdirEntryStat stat = 4; -} - -// Struct for protocol_message_t -message ProtocolMessage { - int32 magic = 1; - CmdType cmd_type = 2; - oneof data { - CmdExec cmd_exec = 3; - CmdDlopen cmd_dlopen = 4; - CmdDlclose cmd_dlclose = 5; - CmdDlsym cmd_dlsym = 6; - CmdCall cmd_call = 7; - CmdPeek cmd_peek = 8; - CmdPoke cmd_poke = 9; - CmdDirlist cmd_dirlist = 10; - CmdShowobject cmd_showobject = 11; - CmdShowclass cmd_showclass = 12; - } -} - -// Struct for reply_protocol_message_t -message ReplyProtocolMessage { - int32 magic = 1; - CmdType cmd_type = 2; -} - -// Enum for exec_chunk_type_t -enum ExecChunkType { - CMD_EXEC_CHUNK_TYPE_STDOUT = 0; - CMD_EXEC_CHUNK_TYPE_ERRORCODE = 1; -} - -// Struct for exec_chunk_t -message ExecChunk { - ExecChunkType chunk_type = 1; - int32 size = 2; -} - -// Struct for return_registers_arm_t -message ReturnRegistersArm { - repeated int64 x = 1; - repeated double d = 2; -} - -// Struct for call_response_t -message CallResponse { - oneof return_values { - ReturnRegistersArm arm_registers = 1; - int64 return_value - } -} \ No newline at end of file diff --git a/src/protos/rpc.proto b/src/protos/rpc.proto index e8397e48..6279f753 100644 --- a/src/protos/rpc.proto +++ b/src/protos/rpc.proto @@ -14,8 +14,8 @@ message Command { CmdPeek peek = 7; CmdPoke poke = 8; CmdListDir listdir = 9; - CmdShowObject showobject = 10; - CmdShowClass showclass = 11; + CmdShowObject show_object = 10; + CmdShowClass show_class = 11; CmdDummyBlock dummy_block = 12; CmdClose close = 13; CmdGetClassList class_list = 14; @@ -102,8 +102,11 @@ message CmdDlsym { } message Argument { - uint64 type = 1; - uint64 value=2; + oneof type{ + uint64 v_int = 1; + double v_double = 2; + string v_str = 3; + } } message CmdCall { @@ -113,8 +116,23 @@ message CmdCall { } message ReturnRegistersArm { - repeated uint64 x = 1; - repeated uint64 d = 2; + uint64 x0 = 1; + uint64 x1 = 2; + uint64 x2 = 3; + uint64 x3 = 4; + uint64 x4 = 5; + uint64 x5 = 6; + uint64 x6 = 7; + uint64 x7 = 8; + + double d0 = 9; + double d1 = 10; + double d2 = 11; + double d3 = 12; + double d4 = 13; + double d5 = 14; + double d6 = 15; + double d7 = 16; } message CmdPeek { @@ -125,7 +143,6 @@ message ResponsePeek{ bytes data =1; } - message CmdPoke { uint64 address = 1; bytes data = 3; @@ -172,7 +189,6 @@ message CmdShowClass { uint64 address = 1; } // Responses - message ResponseCmdExec { uint32 pid = 1; } diff --git a/src/rpcserver/rpcserver.c b/src/rpcserver/rpcserver.c index 1a9f0ff2..b12c90c7 100644 --- a/src/rpcserver/rpcserver.c +++ b/src/rpcserver/rpcserver.c @@ -64,7 +64,7 @@ Example usage: \n\ #define BUFFERSIZE (64 * 1024) #define INVALID_PID (0xffffffff) #define WORKER_CLIENT_SOCKET_FD (3) -#define BLACK_LIST_REGS "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7","x8" +#define CLOBBERD_LIST "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8","x24","x25","x19" extern char **environ; @@ -361,123 +361,145 @@ int test(int a, double b, int c) { return a + b + c; } -typedef struct state_registers { - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - uint64_t x23; - uint64_t x24; - uint64_t x25; - uint64_t x26; - uint64_t x27; - uint64_t x28; - uint64_t x29; - uint64_t x30; - uint64_t x31; -} state_registers; - -#include "stdio.h" -#include "stdbool.h" - -bool call_function(intptr_t address, size_t va_list_index, size_t argc, Rpc__Argument *p_argv, - uint64_t *pid) { - uint64_t address_v = address; - size_t va_list_index_v = va_list_index; - size_t argc_v = argc; - Rpc__Argument *p_argv_v = p_argv; -// uint64_t *out_regs_v = out_regs; - uint64_t *pid_v = pid; - return_registers_arm_t regs = {0}; - -// __asm__( -// // backup registers x19 -> x30 = 8*12 bytes = 0x60 bytes -// // according to arm abi, the stack is structured as follows: -// // ------------------------- -// // | x30(lr) | 0x58 -// // | x29(frame pointer) | 0x50 -// // | register backup | 0x00 -// // ------------------------- -// "stp x19, x20, %[x19_x20]\n" -// "stp x21, x22, %[x21_x22]\n" -// "stp x23, x24, %[x23_x24]\n" -// "stp x25, x26, %[x25_x26]\n" -// "stp x27, x28, %[x27_x28]\n" -// "stp x29, x30, %[x29_x30]\n" -// :: -// [x19_x20]"m"(regs.x19), -// [x21_x22]"m"(regs.x21), -// [x23_x24]"m"(regs.x23), -// [x25_x26]"m"(regs.x25), -// [x27_x28]"m"(regs.x27), -// [x29_x30]"m"(regs.x29) -// :); - - // x19 = argument = argv - // x24 = argc - // x28 = va_list_index - // x21 = integer_offset = 0 - // x22 = double_offset = 0 - // x23 = current_arg_index = 0 - // x26 = stack_offset = 0 - __asm__ ( - "mov x19, %[p_argv_v]\n" - "mov x24, %[argc_v]\n" - "mov x28, %[va_list_index_v]\n" - "mov x21, 0\n" - "mov x22, 0\n" - "mov x23, 0\n" - "mov x26, 0\n" - : - : - [p_argv_v] "r"(p_argv_v), - [argc_v] "r"(argc_v), - [va_list_index_v] "r"(va_list_index_v) - : BLACK_LIST_REGS - ); +//void test_print(char *str, int a, double b) { +// printf("test_print | %s | %d | %f\n", str, a, b); +//} + +// +//// Backup state +//"stp x0, x1, [%[regs_backup], #0]\n" +//"stp x2, x3, [%[regs_backup], #16]\n" +//"stp x4, x5, [%[regs_backup], #32]\n" +//"stp x6, x7, [%[regs_backup], #48]\n" +//"stp x8, x9, [%[regs_backup], #64]\n" +//"stp x10, x11, [%[regs_backup], #80]\n" +//"stp x12, x13, [%[regs_backup], #96]\n" +//"stp x14, x15, [%[regs_backup], #112]\n" +//"stp x16, x17, [%[regs_backup], #128]\n" +//"stp x18, x19, [%[regs_backup], #144]\n" +//"stp x20, x21, [%[regs_backup], #160]\n" +//"stp x22, x23, [%[regs_backup], #176]\n" +//"stp x24, x25, [%[regs_backup], #192]\n" +//"stp x26, x27, [%[regs_backup], #208]\n" +//"stp x28, x29, [%[regs_backup], #224]\n" + +// +//// Restore the rest +//"ldp x0, x1, [%[regs_backup], #0]\n" +//"ldp x2, x3, [%[regs_backup], #16]\n" +//"ldp x4, x5, [%[regs_backup], #32]\n" +//"ldp x6, x7, [%[regs_backup], #48]\n" +// +//// Restore upper registers state +//"ldp x8, x9, [%[regs_backup], #64]\n" +//"ldp x8, x9, [%[regs_backup], #64]\n" +//"ldp x10, x11, [%[regs_backup], #80]\n" +//"ldp x12, x13, [%[regs_backup], #96]\n" +//"ldp x14, x15, [%[regs_backup], #112]\n" +//"ldp x16, x17, [%[regs_backup], #128]\n" +//"ldp x18, x19, [%[regs_backup], #144]\n" +//"ldp x20, x21, [%[regs_backup], #160]\n" +//"ldp x22, x23, [%[regs_backup], #176]\n" +//"ldp x24, x25, [%[regs_backup], #192]\n" +//"ldp x26, x27, [%[regs_backup], #208]\n" +//"ldp x28, x29, [%[regs_backup], #224]\n" +//"ldp x30, x31, [%[regs_backup], #240]\n" +typedef struct exec_context { + return_registers_arm_t before; + return_registers_arm_t after; +} exec_context; + +typedef struct registers { + uint64_t r[30]; +} registers; + +int test_print(char *str) { + printf("FUCK MY LIFE\n"); +// printf("%s\n", str); +} +volatile bool call_function(intptr_t address, size_t va_list_index, size_t argc, Rpc__Argument **p_argv, + Rpc__ResponseCall *resp) { + exec_context ctx = {0}; + registers regs_backup = {0}; + uint32_t i = 0, j = 0, idx = 0; + + while (idx < argc && p_argv) { + switch (p_argv[idx]->type_case) { + case RPC__ARGUMENT__TYPE_V_DOUBLE: + ctx.before.d[i++] = p_argv[idx]->v_double; + break; + case RPC__ARGUMENT__TYPE_V_INT: + ctx.before.x[j++] = p_argv[idx]->v_int; + break; + case RPC__ARGUMENT__TYPE_V_STR: + ctx.before.x[j++] = (uint64_t) p_argv[idx]->v_str; + break; + } + idx++; + } __asm__ __volatile__( - // if (argv == NULL) goto 3 - "cmp x19, xzr\n" - "beq 3f\n" - ); - __asm__ __volatile__( - "1:\n" - // if (current_arg_index == argc) goto 3 - "cmp x23, x24\n" - "beq 3f\n" - ); - __asm __volatile__( - "3:\n" + // Backup + "mov x24,%[regs_backup]\n" + "stp x8, x9, [x24]\n" + "stp x10, x11, [x24, #16]\n" + "stp x12, x13, [x24, #32]\n" + "stp x14, x15, [x24, #48]\n" + "stp x16, x17, [x24, #64]\n" + "stp x18, x19, [x24, #80]\n" + "stp x20, x21, [x24, #96]\n" + "stp x22, x23, [x24, #112]\n" + "stp x24, x25, [x24, #128]\n" + "stp x26, x27, [x24, #144]\n" + + // Set call parameters + "ldp x0, x1, [%[ctx_before_x]]\n" + "ldp x2, x3, [%[ctx_before_x], #16]\n" + "ldp x4, x5, [%[ctx_before_x], #32]\n" + "ldp x6, x7, [%[ctx_before_x], #48]\n" + "ldp d0, d1, [%[ctx_before_d]]\n" + "ldp d2, d3, [%[ctx_before_d], #16]\n" + "ldp d4, d5, [%[ctx_before_d], #32]\n" + "ldp d6, d7, [%[ctx_before_d], #48]\n" + "mov x25, %[ctx_after_x]\n" + + // Call fucntion "ldr x19, %[address]\n" "blr x19\n" - "stp x0,x1, %[regs]\n" - "stp x0,x1, %[regs]\n" - "stp x0,x1, %[regs]\n" - "stp x0,x1, %[regs]\n" + + // Get return values + "mov %[ctx_after_x],x25\n" + "stp x0, x1, [%[ctx_after_x]]\n" + "stp x2, x3, [%[ctx_after_x], #16]\n" + "stp x4, x5, [%[ctx_after_x], #32]\n" + "stp x6, x7, [%[ctx_after_x], #48]\n" + "ldp d0, d1, [%[ctx_after_x], #64]\n" + "ldp d2, d3, [%[ctx_after_x], #80]\n" + "ldp d4, d5, [%[ctx_after_x], #96]\n" + "ldp d6, d7, [%[ctx_after_x], #112]\n" + + // Restore + "ldp x8, x9, [x24]\n" + "ldp x10, x11, [x24, #16]\n" + "ldp x12, x13, [x24, #32]\n" + "ldp x14, x15, [x24, #48]\n" + "ldp x16, x17, [x24, #64]\n" + "ldp x18, x19, [x24, #80]\n" + "ldp x20, x21, [x24, #96]\n" + "ldp x22, x23, [x24, #112]\n" + "ldp x24, x25, [x24, #128]\n" + "ldp x26, x27, [x24, #144]\n" : : - [address]"m"(address_v), - [regs]"m"(regs) - :BLACK_LIST_REGS); - - // Restore state -// __asm__( -// "ldp x19, x20, %[x19_x20]\n" -// "ldp x21, x22, %[x21_x22]\n" -// "ldp x23, x24, %[x23_x24]\n" -// "ldp x25, x26, %[x25_x26]\n" -// "ldp x27, x28, %[x27_x28]\n" -// "ldp x29, x30, %[x29_x30]\n" -// :: -// [x19_x20]"m"(regs.x19), -// [x21_x22]"m"(regs.x21), -// [x23_x24]"m"(regs.x23), -// [x25_x26]"m"(regs.x25), -// [x27_x28]"m"(regs.x27), -// [x29_x30]"m"(regs.x29) -// :); - + [regs_backup] "r"(®s_backup), + [ctx_before_x] "r"(&ctx.before.x[0]), + [ctx_before_d] "r"(&ctx.before.d[0]), + [address] "m"(address), + [ctx_after_x] "r"(&ctx.after.x[0]), + [ctx_after_d] "r"(&ctx.after.d[0]) + :CLOBBERD_LIST + ); + memcpy(&resp->arm_registers->x0, &ctx.after, sizeof(return_registers_arm_t)); return RPC_SUCCESS; } @@ -506,42 +528,33 @@ bool call_function(int sockfd, intptr_t address, size_t va_list_index, size_t ar #endif // __ARM_ARCH_ISA_A64 -void test_print(char *str, int a, double b) { - printf("test_print | %s | %d | %f\n", str, a, b); -} - -bool handle_call(int sockfd) { +bool handle_call(int sockfd, Rpc__CmdCall *cmd) { TRACE("enter"); - s64 err = 0; - int result = false; - argument_t *argv = NULL; -// Rpc__ReturnRegistersArm regs = RPC__RETURN_REGISTERS_ARM__INIT; - Rpc__CmdCall cmd = RPC__CMD_CALL__INIT; - Rpc__Argument args[3] = RPC__ARGUMENT__INIT; + int ret = RPC_FAILURE; + Rpc__Response response = RPC__RESPONSE__INIT; + Rpc__ResponseCall resp_call = RPC__RESPONSE_CALL__INIT; +#ifdef __ARM_ARCH_ISA_A64 Rpc__ReturnRegistersArm regs = RPC__RETURN_REGISTERS_ARM__INIT; + resp_call.arm_registers = ®s; + resp_call.return_values_case = RPC__RESPONSE_CALL__RETURN_VALUES_ARM_REGISTERS; +#else + resp_call.return_values_case = RPC__RESPONSE_CALL__RETURN_VALUES_RETURN_VALUE; +#endif + response.type_case = RPC__RESPONSE__TYPE_CALL; + TRACE("address: %p", cmd->address); + CHECK(call_function(cmd->address, cmd->va_list_index, cmd->n_argv, cmd->argv, &resp_call)); + response.call = &resp_call; + +#ifdef DEBUG + printf("x0 = %llu\n", resp_call.arm_registers->x0); +#else + send_response(sockfd, &response); +#endif + ret = RPC_SUCCESS; - args[0].type_case = RPC__ARGUMENT__TYPE_V_STR; - args[1].type_case = RPC__ARGUMENT__TYPE_V_DOUBLE; - args[2].type_case = RPC__ARGUMENT__TYPE_V_INT; - - args[0].v_int = 4096; - args[1].v_double = 4096; - args[2].v_int = 4096; - cmd.va_list_index = 0; - cmd.address = (uint64_t) getpid; - cmd.n_argv = 0; - bool res; - uint64_t pid; - printf("PID = %d\n", getpid()); - res = call_function(cmd.address, cmd.va_list_index, cmd.n_argv, args, &pid); - printf("res = %d \nx0 = %d\n", res, (pid_t) pid); - result = true; error: - if (argv) { - free(argv); - } - return result; + return ret; } bool handle_peek(int sockfd, Rpc__CmdPeek *cmd) { @@ -791,7 +804,7 @@ void handle_client(int sockfd) { switch (cmd->type_case) { case RPC__COMMAND__TYPE_EXEC: { - handle_exec(sockfd, cmd->exec); + handle_exec(sockfd, cmd->exec); // TODO: Not fully implemented break; } case RPC__COMMAND__TYPE_DLOPEN: { @@ -807,7 +820,7 @@ void handle_client(int sockfd) { break; } case RPC__COMMAND__TYPE_CALL: { -// handle_call(sockfd, cmd->call); // TODO: Not fully implemented + handle_call(sockfd, cmd->call); // TODO: Not fully implemented break; } case RPC__COMMAND__TYPE_PEEK: { @@ -823,15 +836,15 @@ void handle_client(int sockfd) { break; } case RPC__COMMAND__TYPE_LISTDIR: { - handle_listdir(sockfd); + handle_listdir(sockfd); // TODO: Not fully implemented break; } - case RPC__COMMAND__TYPE_SHOWOBJECT: { - handle_showobject(sockfd, cmd->showobject); + case RPC__COMMAND__TYPE_SHOW_OBJECT: { + handle_showobject(sockfd, cmd->show_object); break; } - case RPC__COMMAND__TYPE_SHOWCLASS: { - handle_showclass(sockfd, cmd->showclass); + case RPC__COMMAND__TYPE_SHOW_CLASS: { + handle_showclass(sockfd, cmd->show_class); break; } case RPC__COMMAND__TYPE_CLASS_LIST: { @@ -867,19 +880,37 @@ void signal_handler(int sig) { TRACE("entered with signal code: %d", sig); } + int main(int argc, const char *argv[]) { int opt; bool worker_spawn = false; bool debug = false; char port[MAX_OPTION_LEN] = DEFAULT_PORT; - int res; - res = handle_call(1); - printf("%d\n", res); - printf("main - %p\n", &main); - - printf("getpid - %p | res %d\n", &getpid, getpid()); - printf("test - %p \n", &test); - +#ifdef DEBUG +#define ARGC (2) + Rpc__CmdCall cmd; + Rpc__Argument *args[ARGC]; + printf("PID - %d\n", getpid()); + args[0] = (Rpc__Argument *) malloc(sizeof(Rpc__Argument)); + args[0]->type_case = RPC__ARGUMENT__TYPE_V_STR; + args[0]->v_str = "FUCK YOUA\n"; + + args[1] = (Rpc__Argument *) malloc(sizeof(Rpc__Argument)); + args[1]->type_case = RPC__ARGUMENT__TYPE_V_STR; + args[1]->v_str = "FUCK YOU\n"; + + cmd.address = (uint64_t) printf; + cmd.n_argv = ARGC; + cmd.argv = args; + printf("Expected %d\n", strcmp(args[0]->v_str, args[1]->v_str)); + handle_call(1, &cmd); + + for (int i = 0; i < ARGC; i++) { + SAFE_FREE(args[i]); + } + exit(1); +#endif + printf("test_print : %p \n", test_print); while ((opt = getopt(argc, (char *const *) argv, "hp:o:w:d")) != -1) { switch (opt) { case 'p': {