rizin/librz/util/lang_byte_array.c
2024-04-18 00:04:38 +08:00

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 than 0\n");
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);
}