mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-16 12:19:45 +00:00
parent
4949c00293
commit
01937fcaf9
@ -50,9 +50,11 @@ static const char *help_msg_p6[] = {
|
||||
};
|
||||
|
||||
static const char *help_msg_pF[] = {
|
||||
"Usage: pF[apd]", "[len]", "parse ASN1, PKCS, X509, DER",
|
||||
"Usage: pF[apdb]", "[len]", "parse ASN1, PKCS, X509, DER, protobuf",
|
||||
"pFa", "[len]", "decode ASN1 from current block",
|
||||
"pFaq", "[len]", "decode ASN1 from current block (quiet output)",
|
||||
"pFb", "[len]", "decode raw proto buffers.",
|
||||
"pFbv", "[len]", "decode raw proto buffers (verbose).",
|
||||
"pFo", "[len]", "decode ASN1 OID",
|
||||
"pFp", "[len]", "decode PKCS7",
|
||||
"pFx", "[len]", "Same with X509",
|
||||
@ -1199,6 +1201,11 @@ static void cmd_print_fromage(RCore *core, const char *input, const ut8* data, i
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'b': // "pFb"
|
||||
{
|
||||
r_protobuf_decode(data, size, input[1] == 'v');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case '?': // "pF?"
|
||||
r_core_cmd_help (core, help_msg_pF);
|
||||
|
@ -74,6 +74,7 @@ int gettimeofday (struct timeval* p, void* tz);
|
||||
#include "r_util/pj.h"
|
||||
#include "r_util/r_x509.h"
|
||||
#include "r_util/r_pkcs7.h"
|
||||
#include "r_util/r_protobuf.h"
|
||||
// requires io, core, ... #include "r_util/r_print.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
14
libr/include/r_util/r_protobuf.h
Normal file
14
libr/include/r_util/r_protobuf.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef R_PROTOBUF_H
|
||||
#define R_PROTOBUF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
R_API void r_protobuf_decode(const ut8* buffer, const ut64 size, bool debug);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* R_PROTOBUF_H */
|
@ -22,6 +22,7 @@ OBJS+=utf8.o utf16.o utf32.o strbuf.o lib.o name.o spaces.o signal.o syscmd.o
|
||||
OBJS+=diff.o bdiff.o stack.o queue.o tree.o idpool.o assert.o
|
||||
OBJS+=punycode.o pkcs7.o x509.o asn1.o astr.o json_indent.o skiplist.o pj.o
|
||||
OBJS+=rbtree.o qrcode.o vector.o str_constpool.o str_trim.o ascii_table.o
|
||||
OBJS+=protobuf.o
|
||||
|
||||
# DO NOT BUILD r_big api (not yet used and its buggy)
|
||||
ifeq (1,0)
|
||||
|
@ -77,6 +77,7 @@ r_util_sources = [
|
||||
'vector.c',
|
||||
'w32-sys.c',
|
||||
'zip.c',
|
||||
'protobuf.c',
|
||||
'regex/regcomp.c',
|
||||
'regex/regexec.c',
|
||||
'regex/regerror.c'
|
||||
|
165
libr/util/protobuf.c
Normal file
165
libr/util/protobuf.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* radare2 - LGPL - Copyright 2017-2019 - wargio */
|
||||
|
||||
#include <r_util.h>
|
||||
#include <r_cons.h>
|
||||
|
||||
typedef float ft32;
|
||||
typedef double ft64;
|
||||
|
||||
#define WIRE_VARINT 0 // int32, int64, uint32, uint64, sint32, sint64, bool, enum
|
||||
#define WIRE_64_BIT 1 // fixed64, sfixed64, double
|
||||
#define WIRE_LEN_DELIM 2 // string, bytes, embedded messages, packed repeated fields
|
||||
#define WIRE_START_GRP 3 // groups (deprecated)
|
||||
#define WIRE_END_GRP 4 // groups (deprecated)
|
||||
#define WIRE_32_BIT 5 // fixed32, sfixed32, float
|
||||
|
||||
typedef R_PACKED (struct _proto_head {
|
||||
ut8 wire : 3;
|
||||
ut8 number : 5;
|
||||
}) proto_head_t;
|
||||
|
||||
static const char* s_wire(const ut8 byte) {
|
||||
switch (byte) {
|
||||
case WIRE_VARINT:
|
||||
return "[VARINT]";
|
||||
case WIRE_64_BIT:
|
||||
return "[64_BIT]";
|
||||
case WIRE_LEN_DELIM:
|
||||
return "[LEN_DELIM]";
|
||||
case WIRE_START_GRP:
|
||||
return "[START_GROUP]";
|
||||
case WIRE_END_GRP:
|
||||
return "[END_GROUP]";
|
||||
case WIRE_32_BIT:
|
||||
return "[32_BIT]";
|
||||
default:
|
||||
return "[UNKN]";
|
||||
}
|
||||
}
|
||||
|
||||
static void pad(ut32 count) {
|
||||
ut32 i;
|
||||
for (i = 0; i < count; i++) {
|
||||
r_cons_printf (" ");
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_string(const ut8* start, const ut8* end) {
|
||||
while (start < end) {
|
||||
// TODO UTF-8 Support.
|
||||
if (!IS_PRINTABLE (*start)) {
|
||||
return false;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void decode_array(const ut8* start, const ut8* end) {
|
||||
while (start < end) {
|
||||
r_cons_printf ("%02x ", *start);
|
||||
start++;
|
||||
}
|
||||
r_cons_printf ("\n");
|
||||
}
|
||||
|
||||
static void decode_buffer(const ut8* start, const ut8* end, ut32 padcnt, bool debug) {
|
||||
size_t bytes_read = 0;
|
||||
ut32 var32 = 0;
|
||||
ut64 var64 = 0;
|
||||
const ut8* buffer = start;
|
||||
const proto_head_t *h = NULL;
|
||||
while(buffer >= start && buffer < end) {
|
||||
if (!*buffer) {
|
||||
return;
|
||||
}
|
||||
ut8 byte = *buffer;
|
||||
h = (proto_head_t*) buffer;
|
||||
buffer++;
|
||||
if (buffer < start || buffer >= end) {
|
||||
eprintf ("\ninvalid buffer pointer.\n");
|
||||
break;
|
||||
} else if (h->wire > WIRE_32_BIT) {
|
||||
eprintf ("\nunknown wire id (%u).\n", h->wire);
|
||||
return;
|
||||
}
|
||||
if (h->wire != WIRE_END_GRP) {
|
||||
pad (padcnt);
|
||||
if (debug) {
|
||||
r_cons_printf ("%u %-13s", h->number, s_wire(h->wire));
|
||||
} else {
|
||||
r_cons_printf ("%u", h->number);
|
||||
}
|
||||
}
|
||||
switch(h->wire) {
|
||||
case WIRE_VARINT:
|
||||
{
|
||||
st64* i = (st64*) &var64;
|
||||
bytes_read = read_u64_leb128 (buffer, end, &var64);
|
||||
r_cons_printf (": %"PFMT64u" | %"PFMT64d"\n", var64, *i);
|
||||
}
|
||||
break;
|
||||
case WIRE_64_BIT:
|
||||
{
|
||||
ft64* f = (ft64*) &var64;
|
||||
st64* i = (st64*) &var64;
|
||||
bytes_read = read_u64_leb128 (buffer, end, &var64);
|
||||
r_cons_printf (": %"PFMT64u" | %"PFMT64d" | %f\n", var64, *i, *f);
|
||||
}
|
||||
break;
|
||||
case WIRE_LEN_DELIM:
|
||||
{
|
||||
bytes_read = read_u64_leb128 (buffer, end, &var64);
|
||||
const ut8* ps = buffer + bytes_read;
|
||||
const ut8* pe = ps + var64;
|
||||
if (ps > buffer && pe <= end) {
|
||||
if (is_string (ps, pe)) {
|
||||
r_cons_printf (": \"%.*s\"\n", var64, (const char*) ps);
|
||||
} else {
|
||||
r_cons_printf (" {\n");
|
||||
decode_buffer (ps, pe, padcnt + 1, debug);
|
||||
pad (padcnt);
|
||||
r_cons_printf ("}\n");
|
||||
}
|
||||
bytes_read += var64;
|
||||
} else {
|
||||
eprintf ("\ninvalid delimited length (%"PFMT64u").\n", var64);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WIRE_START_GRP:
|
||||
r_cons_printf (" {\n");
|
||||
padcnt++;
|
||||
break;
|
||||
case WIRE_END_GRP:
|
||||
if (padcnt > 1) {
|
||||
padcnt--;
|
||||
}
|
||||
pad (padcnt);
|
||||
r_cons_printf ("}\n");
|
||||
break;
|
||||
case WIRE_32_BIT:
|
||||
{
|
||||
ft32* f = (ft32*) &var32;
|
||||
st32* i = (st32*) &var32;
|
||||
bytes_read = read_u32_leb128 (buffer, end, &var32);
|
||||
r_cons_printf (": %u | %d | %f\n", var32, *i, *f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
decode_array(buffer - 1, end);
|
||||
return;
|
||||
}
|
||||
buffer += bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
void r_protobuf_decode(const ut8* start, const ut64 size, bool debug) {
|
||||
if (!start || !size) {
|
||||
eprintf ("Invalid buffer pointer or size.\n");
|
||||
return;
|
||||
}
|
||||
const ut8* end = start + size;
|
||||
decode_buffer (start, end, 0u, debug);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user