radare2/libr/bin/p/bin_rar.c
Rakholiya Jenish 339a5b7b18 fix iZ and negative o for large files (#5242)
correct the add section check

keep commented part to it's original code

int to ut64

minor fix and limit buffer size in case file size cannot be allocted

remove section check

show size in readable format

minor changes
2016-07-05 12:46:28 +02:00

211 lines
5.0 KiB
C

/* radare - LGPL - Copyright 2012-2015 - pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>
#define RAR_CONST "\x00\x00\x00\x00\x20\x73\x74\x64\x6f\x75\x74\x20\x21\x55\x0c\xcd"
#define RARVMHDR "\x52\x61\x72\x21\x1a\x07\x00\xf9\x4e\x73\x00\x00\x0e\x00\x00\x00"
typedef struct r_bin_obj_rar_t {
RBuffer *buf;
ut64 loadaddr;
Sdb *kv;
} RRarBinObj;
static int check(RBinFile *arch);
static int check_bytes(const ut8 *buf, ut64 length);
static int check(RBinFile *arch) {
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
return check_bytes (bytes, sz);
}
static int check_bytes(const ut8 *buf, ut64 length) {
if (buf && length > 16)
if (!memcmp (buf, RARVMHDR, 16))
return true;
return false;
}
static Sdb* get_sdb (RBinObject *o) {
if (!o) return NULL;
struct r_bin_obj_rar_t *bin = (struct r_bin_obj_rar_t *) o->bin_obj;
if (bin->kv) return bin->kv;
return NULL;
}
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){
RBuffer *tbuf = NULL;
RRarBinObj *res = NULL;
if (!buf || sz == 0 || sz == UT64_MAX) {
return NULL;
}
res = R_NEW0 (RRarBinObj);
tbuf = r_buf_new ();
r_buf_set_bytes (tbuf, buf, sz);
res->buf = tbuf;
res->kv = sdb;
res->loadaddr = loadaddr;
return res;
}
static int load(RBinFile *arch) {
return check (arch);
}
static int destroy (RBinFile *arch) {
return true;
}
static ut64 baddr(RBinFile *arch) {
return 0;
}
static RList* entries(RBinFile *arch) {
RList* ret = r_list_new ();;
RBinAddr *ptr = NULL;
RRarBinObj *bin_obj = arch && arch->o ? arch->o->bin_obj : NULL;
const ut8 *buf = bin_obj ? r_buf_buffer (bin_obj->buf) : NULL;
ut64 sz = arch && bin_obj ? r_buf_size (bin_obj->buf) : 0;
if (!ret) return NULL;
ret->free = free;
if (bin_obj && sz > 0x30 && !memcmp (buf+0x30, RAR_CONST, 16)) {
if ((ptr = R_NEW (RBinAddr))) {
ptr->vaddr = ptr->paddr = 0x9a;
r_list_append (ret, ptr);
}
}
return ret;
}
static RList* sections(RBinFile *arch) {
RList *ret = NULL;
RBinSection *ptr = NULL;
RRarBinObj *bin_obj = arch && arch->o ? arch->o->bin_obj : NULL;
const ut8 *buf = bin_obj ? r_buf_buffer (bin_obj->buf) : NULL;
ut64 sz = 0;
if (bin_obj)
sz = r_buf_size (bin_obj->buf);
if (!(ret = r_list_new ()))
return NULL;
ret->free = free;
// TODO: return NULL here?
if (!buf || sz < 0x30 || memcmp (buf+0x30, RAR_CONST, 16))
return ret;
// add text segment
if (!(ptr = R_NEW0 (RBinSection)))
return ret;
strncpy (ptr->name, "header", R_BIN_SIZEOF_STRINGS);
ptr->size = ptr->vsize = 0x9a;
ptr->paddr = 0;
ptr->vaddr = ptr->paddr;
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_MAP; // r--
ptr->add = true;
r_list_append (ret, ptr);
/* rarvm code */
if (!(ptr = R_NEW0 (RBinSection)))
return ret;
strncpy (ptr->name, "rarvm", R_BIN_SIZEOF_STRINGS);
ptr->vsize = ptr->size = sz - 0x9a;
ptr->vaddr = ptr->paddr = 0x9a;
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x
ptr->add = true;
r_list_append (ret, ptr);
return ret;
}
static RList* symbols(RBinFile *arch) {
return NULL;
}
static RList* imports(RBinFile *arch) {
return NULL;
}
static RList* libs(RBinFile *arch) {
return NULL;
}
static RBinInfo* info(RBinFile *arch) {
RBinInfo *ret = R_NEW0 (RBinInfo);
RRarBinObj *bin_obj = arch && arch->o ? arch->o->bin_obj : NULL;
const ut8 *buf = bin_obj ? r_buf_buffer (bin_obj->buf) : NULL;
ut64 sz = arch && bin_obj ? r_buf_size (bin_obj->buf): 0;
int bits = 32; // Default value
if (!ret || !buf || sz < 0x30) {
free (ret);
return NULL;
}
ret->file = strdup (arch->file);
ret->rclass = strdup ("rar");
ret->os = strdup ("rar");
ret->arch = strdup ("rar");
ret->machine = strdup ("rarvm");
if (!memcmp (buf+0x30, RAR_CONST, 16)) {
ret->subsystem = strdup ("rarvm");
ret->bclass = strdup ("program");
ret->type = strdup ("EXEC (Compressed executable)");
} else {
ret->subsystem = strdup ("archive");
ret->bclass = strdup ("archive");
ret->type = strdup ("ARCHIVE (Compressed archive)");
}
// TODO: specify if its compressed or executable
ret->bits = bits;
ret->has_va = true;
ret->big_endian = true;
ret->dbg_info = 0;
ret->dbg_info = 0;
return ret;
}
static ut64 size(RBinFile *arch) {
// TODO: walk rar structures and guess size here...
return 0x9a+128; // XXX
}
/* inspired in http://www.phreedom.org/solar/code/tinype/tiny.97/tiny.asm */
static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen) {
RBuffer *buf = r_buf_new ();
return buf;
}
RBinPlugin r_bin_plugin_rar = {
.name = "rar",
.desc = "rarvm bin plugin",
.license = "LGPL3",
.get_sdb = &get_sdb,
.load = &load,
.load_bytes = &load_bytes,
.size = &size,
.destroy = &destroy,
.check = &check,
.check_bytes = &check_bytes,
.baddr = &baddr,
.entries = &entries,
.sections = &sections,
.symbols = &symbols,
.imports = &imports,
.info = &info,
.libs = &libs,
.create = &create,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_BIN,
.data = &r_bin_plugin_pe,
.version = R2_VERSION
};
#endif