303 lines
9.1 KiB
C
303 lines
9.1 KiB
C
// SPDX-FileCopyrightText: 2022 RizinOrg <info@rizin.re>
|
|
// SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_util.h>
|
|
#define RZ_LANG_BYTE_ARRAY_TRUNK_SIZE 16
|
|
#define RZ_LANG_BYTE_ARRAY_TRUNK_SIZE_STR "16"
|
|
|
|
static void lang_byte_array_rizin(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
size_t pos = 0;
|
|
rz_strbuf_append(sb, "wx ");
|
|
for (pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % RZ_LANG_BYTE_ARRAY_TRUNK_SIZE)) {
|
|
rz_strbuf_append(sb, " ; sd +" RZ_LANG_BYTE_ARRAY_TRUNK_SIZE_STR "\nwx ");
|
|
}
|
|
rz_strbuf_appendf(sb, "%02x", buffer[pos]);
|
|
}
|
|
if (pos > RZ_LANG_BYTE_ARRAY_TRUNK_SIZE) {
|
|
rz_strbuf_appendf(sb, " ; sd -%" PFMTSZd, pos);
|
|
}
|
|
}
|
|
|
|
static void lang_byte_array_bash(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
bool append = false;
|
|
rz_strbuf_append(sb, "printf \"");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % RZ_LANG_BYTE_ARRAY_TRUNK_SIZE)) {
|
|
rz_strbuf_appendf(sb, "\" %s data.bin\nprintf \"", append ? ">>" : ">");
|
|
append = true;
|
|
}
|
|
rz_strbuf_appendf(sb, "\\%03o", buffer[pos]);
|
|
}
|
|
rz_strbuf_appendf(sb, "\" %s data.bin", append ? ">>" : ">");
|
|
}
|
|
|
|
static void lang_byte_array_c_cpp(RzStrBuf *sb, const ut8 *buffer, size_t size, size_t n_bytes, bool big_endian) {
|
|
const char *hex_c, *hex_e;
|
|
size_t n_bits = n_bytes * 8;
|
|
size_t max_print;
|
|
ut64 value;
|
|
|
|
switch (n_bytes) {
|
|
case 2:
|
|
hex_c = " 0x%04" PFMT64x ",";
|
|
hex_e = " 0x%04" PFMT64x "\n};";
|
|
// ensure that is always aligned
|
|
size -= (size % n_bytes);
|
|
break;
|
|
case 4:
|
|
hex_c = " 0x%08" PFMT64x "u,";
|
|
hex_e = " 0x%08" PFMT64x "u\n};";
|
|
// ensure that is always aligned
|
|
size -= (size % n_bytes);
|
|
break;
|
|
case 8:
|
|
hex_c = " 0x%016" PFMT64x "ull,";
|
|
hex_e = " 0x%016" PFMT64x "ull\n};";
|
|
// ensure that is always aligned
|
|
size -= (size % n_bytes);
|
|
break;
|
|
default:
|
|
hex_c = " 0x%02" PFMT64x ",";
|
|
hex_e = " 0x%02" PFMT64x "\n};";
|
|
break;
|
|
}
|
|
max_print = RZ_LANG_BYTE_ARRAY_TRUNK_SIZE / n_bytes;
|
|
|
|
if (size < 1 && n_bytes != 1) {
|
|
rz_strbuf_appendf(sb, "// Warning: the number of available bytes is less than %" PFMTSZd, n_bytes);
|
|
return;
|
|
}
|
|
rz_strbuf_appendf(sb, "#define ARRAY_SIZE %" PFMTSZd "\nconst uint%" PFMTSZd "_t array[ARRAY_SIZE] = {\n ", size / n_bytes, n_bits);
|
|
for (size_t pos = 0, n_print = 0; pos < size; pos += n_bytes, n_print++) {
|
|
if (n_print > 0 && !(n_print % max_print)) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
value = rz_read_ble(buffer + pos, big_endian, n_bits);
|
|
rz_strbuf_appendf(sb, (pos + n_bytes) < size ? hex_c : hex_e, value);
|
|
}
|
|
}
|
|
|
|
static void lang_byte_array_asm(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_append(sb, "byte_array:");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (!(pos % RZ_LANG_BYTE_ARRAY_TRUNK_SIZE)) {
|
|
rz_strbuf_appendf(sb, "\n.byte 0x%02x", buffer[pos]);
|
|
} else {
|
|
rz_strbuf_appendf(sb, ", 0x%02x", buffer[pos]);
|
|
}
|
|
}
|
|
rz_strbuf_appendf(sb, "\n.equ byte_array_len, %" PFMTSZd, size);
|
|
}
|
|
|
|
static void lang_byte_array_golang(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_append(sb, "byteArray := []byte{\n ");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
rz_strbuf_appendf(sb, " 0x%02x,", buffer[pos]);
|
|
}
|
|
rz_strbuf_append(sb, "\n}");
|
|
}
|
|
|
|
static void lang_byte_array_java(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
int value = 0;
|
|
rz_strbuf_append(sb, "byte[] byteArray = new byte[] {\n ");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
value = buffer[pos];
|
|
if (value > 127) {
|
|
value -= 256;
|
|
}
|
|
rz_strbuf_appendf(sb, " %4d,", value);
|
|
}
|
|
rz_strbuf_append(sb, "\n};");
|
|
}
|
|
|
|
static char *lang_byte_array_json(const ut8 *buffer, size_t size) {
|
|
PJ *pj = pj_new();
|
|
if (!pj) {
|
|
return NULL;
|
|
}
|
|
pj_a(pj);
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
pj_i(pj, buffer[pos]);
|
|
}
|
|
pj_end(pj);
|
|
return pj_drain(pj);
|
|
}
|
|
|
|
static void lang_byte_array_kotlin(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
int value = 0;
|
|
rz_strbuf_append(sb, "val byteArray = byteArrayOf(\n ");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
value = buffer[pos];
|
|
if (value > 127) {
|
|
value -= 256;
|
|
}
|
|
rz_strbuf_appendf(sb, " %4d,", value);
|
|
}
|
|
rz_strbuf_append(sb, "\n);");
|
|
}
|
|
|
|
static void lang_byte_array_nodejs(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
if (size == 0) {
|
|
rz_strbuf_append(sb, "var byteArray = new Buffer('', 'base64');");
|
|
return;
|
|
}
|
|
|
|
char *base64 = calloc(size, 3);
|
|
if (!base64) {
|
|
return;
|
|
}
|
|
rz_base64_encode(base64, buffer, size);
|
|
rz_strbuf_appendf(sb, "var byteArray = new Buffer('%s', 'base64');", base64);
|
|
free(base64);
|
|
}
|
|
|
|
static void lang_byte_array_objective_c_cpp(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_append(sb, "NSData *byteArray = [[NSData alloc] initWithBytes:{\n ");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
rz_strbuf_appendf(sb, (pos + 1) < size ? " 0x%02x," : " 0x%02x\n}];", buffer[pos]);
|
|
}
|
|
}
|
|
|
|
static void lang_byte_array_python(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_append(sb, "byteArray = b'");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "'\nbyteArray += b'");
|
|
}
|
|
rz_strbuf_appendf(sb, "\\x%02x", buffer[pos]);
|
|
}
|
|
rz_strbuf_append(sb, "'");
|
|
}
|
|
|
|
static void lang_byte_array_rust(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_appendf(sb, "let _: [u8; %" PFMTSZd "] = [\n ", size);
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
rz_strbuf_appendf(sb, (pos + 1) < size ? " 0x%02x," : " 0x%02x\n];", buffer[pos]);
|
|
}
|
|
}
|
|
|
|
static void lang_byte_array_swift(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_append(sb, "let byteArray : [UInt8] = [\n ");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
rz_strbuf_appendf(sb, (pos + 1) < size ? " 0x%02x," : " 0x%02x\n];", buffer[pos]);
|
|
}
|
|
}
|
|
|
|
static void lang_byte_array_yara(RzStrBuf *sb, const ut8 *buffer, size_t size) {
|
|
rz_strbuf_append(sb, "$byteArray = {\n ");
|
|
for (size_t pos = 0; pos < size; pos++) {
|
|
if (pos > 0 && !(pos % (RZ_LANG_BYTE_ARRAY_TRUNK_SIZE))) {
|
|
rz_strbuf_append(sb, "\n ");
|
|
}
|
|
rz_strbuf_appendf(sb, " %02x", buffer[pos]);
|
|
}
|
|
rz_strbuf_appendf(sb, "\n};");
|
|
}
|
|
|
|
/**
|
|
* \brief Generates a string containing a byte array in the specified language
|
|
*
|
|
* \param buffer The buffer to read
|
|
* \param size The buffer size
|
|
* \param type The RzLangByteArrayType type
|
|
*
|
|
* \return On success returns a string, otherwise NULL
|
|
*/
|
|
RZ_API RZ_OWN char *rz_lang_byte_array(RZ_NONNULL const ut8 *buffer, size_t size, RzLangByteArrayType type) {
|
|
rz_return_val_if_fail(buffer, NULL);
|
|
RzStrBuf sb;
|
|
rz_strbuf_init(&sb);
|
|
|
|
if (size <= 0) {
|
|
RZ_LOG_ERROR("Length must be greater 0");
|
|
return rz_strbuf_drain_nofree(&sb);
|
|
}
|
|
|
|
switch (type) {
|
|
case RZ_LANG_BYTE_ARRAY_RIZIN:
|
|
lang_byte_array_rizin(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_ASM:
|
|
lang_byte_array_asm(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_BASH:
|
|
lang_byte_array_bash(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_BYTES:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 1, false);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_HALFWORDS_BE:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 2, true);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_HALFWORDS_LE:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 2, false);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_WORDS_BE:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 4, true);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_WORDS_LE:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 4, false);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_DOUBLEWORDS_BE:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 8, true);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_C_CPP_DOUBLEWORDS_LE:
|
|
lang_byte_array_c_cpp(&sb, buffer, size, 8, false);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_GOLANG:
|
|
lang_byte_array_golang(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_JAVA:
|
|
lang_byte_array_java(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_JSON:
|
|
rz_strbuf_fini(&sb);
|
|
return lang_byte_array_json(buffer, size);
|
|
case RZ_LANG_BYTE_ARRAY_KOTLIN:
|
|
lang_byte_array_kotlin(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_NODEJS:
|
|
lang_byte_array_nodejs(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_OBJECTIVE_C:
|
|
lang_byte_array_objective_c_cpp(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_PYTHON:
|
|
lang_byte_array_python(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_RUST:
|
|
lang_byte_array_rust(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_SWIFT:
|
|
lang_byte_array_swift(&sb, buffer, size);
|
|
break;
|
|
case RZ_LANG_BYTE_ARRAY_YARA:
|
|
lang_byte_array_yara(&sb, buffer, size);
|
|
break;
|
|
default:
|
|
rz_strbuf_fini(&sb);
|
|
rz_warn_if_reached();
|
|
return NULL;
|
|
}
|
|
return rz_strbuf_drain_nofree(&sb);
|
|
}
|