1 /* radare2 - LGPL - Copyright 2016-2019 - pancake */
2
3 #include <r_types.h>
4 #include <r_util.h>
5 #include <r_lib.h>
6 #include <r_bin.h>
7
8 #define MENUET_VERSION(x) x[7]
9
10 #if 0
11 db 'MENUET00' ; 8 byte id
12 dd 38 ; required os
13 dd START ; program start
14 dd I_END ; image size
15 dd 0x100000 ; reguired amount of memory
16 dd 0x00000000 ; reserved=no extended header
17
18 org 0x0
19 db 'MENUET01' ; 8 byte id
20 dd 1 ; header version
21 dd START ; program start
22 dd I_END ; program image size
23 dd 0x1000 ; required amount of memory
24 dd 0x1000 ; esp
25 dd 0, 0 ; no parameters, no path
26
27 0 db 'MENUET02'
28 8 dd 0x01
29 12 dd __start
30 16 dd __iend
31 20 dd __bssend
32 24 dd __stack
33 28 dd __cmdline
34 32 dd __pgmname
35 36 dd 0x0; tls map
36 40 dd __idata_start; секция .import
37 44 dd __idata_end
38 48 dd main
39
40 db 'MENUET02'
41 dd 1
42 dd start
43 dd i_end
44 dd mem
45 dd mem
46 dd cmdline
47 dd path
48 dd 0
49
50 #endif
51
check_buffer(RBuffer * b)52 static bool check_buffer(RBuffer *b) {
53 ut8 buf[8];
54 if (r_buf_read_at (b, 0, buf, sizeof (buf)) != sizeof (buf)) {
55 return false;
56 }
57 if (r_buf_size (b) >= 32 && !memcmp (buf, "MENUET0", 7)) {
58 switch (buf[7]) {
59 case '0':
60 case '1':
61 case '2':
62 return true;
63 }
64 eprintf ("Unsupported MENUET version header\n");
65 }
66 return false;
67 }
68
load_buffer(RBinFile * bf,void ** bin_obj,RBuffer * b,ut64 loadaddr,Sdb * sdb)69 static bool load_buffer (RBinFile *bf, void **bin_obj, RBuffer *b, ut64 loadaddr, Sdb *sdb){
70 return check_buffer (b);
71 }
72
baddr(RBinFile * bf)73 static ut64 baddr(RBinFile *bf) {
74 return 0; // 0x800000;
75 }
76
menuetEntry(const ut8 * buf,int buf_size)77 static ut64 menuetEntry(const ut8 *buf, int buf_size) {
78 switch (MENUET_VERSION(buf)) {
79 case '0': return r_read_ble32 (buf + 12, false);
80 case '1': return r_read_ble32 (buf + 12, false);
81 case '2': return r_read_ble32 (buf + 44, false);
82 }
83 return UT64_MAX;
84 }
85
entries(RBinFile * bf)86 static RList* entries(RBinFile *bf) {
87 RList* ret;
88 ut8 buf[64] = {0};
89 RBinAddr *ptr = NULL;
90 const int buf_size = R_MIN (sizeof (buf), r_buf_size (bf->buf));
91
92 r_buf_read_at (bf->buf, 0, buf, buf_size);
93 ut64 entry = menuetEntry (buf, buf_size);
94 if (entry == UT64_MAX) {
95 return NULL;
96 }
97 if (!(ret = r_list_new ())) {
98 return NULL;
99 }
100 ret->free = free;
101 if ((ptr = R_NEW0 (RBinAddr))) {
102 ptr->paddr = r_read_ble32 (buf + 12, false);
103 ptr->vaddr = ptr->paddr + baddr (bf);
104 r_list_append (ret, ptr);
105 }
106 return ret;
107 }
108
sections(RBinFile * bf)109 static RList* sections(RBinFile *bf) {
110 RList *ret = NULL;
111 RBinSection *ptr = NULL;
112 ut8 buf[64] = {0};
113 const int buf_size = R_MIN (sizeof (buf), r_buf_size (bf->buf));
114
115 r_buf_read_at (bf->buf, 0, buf, buf_size);
116 if (!bf->o->info) {
117 return NULL;
118 }
119
120 if (!(ret = r_list_newf (free))) {
121 return NULL;
122 }
123 // add text segment
124 if (!(ptr = R_NEW0 (RBinSection))) {
125 return ret;
126 }
127 ptr->name = strdup ("text");
128 ptr->size = r_read_ble32 (buf + 16, false);
129 ptr->vsize = ptr->size + (ptr->size % 4096);
130 ptr->paddr = r_read_ble32 (buf + 12, false);
131 ptr->vaddr = ptr->paddr + baddr (bf);
132 ptr->perm = R_PERM_RX; // r-x
133 ptr->add = true;
134 r_list_append (ret, ptr);
135
136 if (MENUET_VERSION(buf)) {
137 /* add data section */
138 if (!(ptr = R_NEW0 (RBinSection))) {
139 return ret;
140 }
141 ptr->name = strdup ("idata");
142 const ut32 idata_start = r_read_ble32 (buf + 40, false);
143 const ut32 idata_end = r_read_ble32 (buf + 44, false);
144 ptr->size = idata_end - idata_start;
145 ptr->vsize = ptr->size + (ptr->size % 4096);
146 ptr->paddr = r_read_ble32 (buf + 40, false);
147 ptr->vaddr = ptr->paddr + baddr (bf);
148 ptr->perm = R_PERM_R; // r--
149 ptr->add = true;
150 r_list_append (ret, ptr);
151 }
152
153 return ret;
154 }
155
info(RBinFile * bf)156 static RBinInfo* info(RBinFile *bf) {
157 RBinInfo *ret = R_NEW0 (RBinInfo);
158 if (ret) {
159 ret->file = strdup (bf->file);
160 ret->bclass = strdup ("program");
161 ret->rclass = strdup ("menuet");
162 ret->os = strdup ("MenuetOS");
163 ret->arch = strdup ("x86");
164 ret->machine = strdup (ret->arch);
165 ret->subsystem = strdup ("kolibri");
166 ret->type = strdup ("EXEC");
167 ret->bits = 32;
168 ret->has_va = true;
169 ret->big_endian = 0;
170 ret->dbg_info = 0;
171 ret->dbg_info = 0;
172 }
173 return ret;
174 }
175
size(RBinFile * bf)176 static ut64 size(RBinFile *bf) {
177 ut8 buf[4] = {0};
178 if (!bf->o->info) {
179 bf->o->info = info (bf);
180 }
181 if (!bf->o->info) {
182 return 0;
183 }
184 r_buf_read_at (bf->buf, 16, buf, 4);
185 return (ut64)r_read_ble32 (buf, false);
186 }
187
188 #if !R_BIN_P9
189
190 /* inspired in http://www.phreedom.org/solar/code/tinype/tiny.97/tiny.asm */
create(RBin * bin,const ut8 * code,int codelen,const ut8 * data,int datalen,RBinArchOptions * opt)191 static RBuffer* create(RBin* bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RBinArchOptions *opt) {
192 RBuffer *buf = r_buf_new ();
193 #define B(x,y) r_buf_append_bytes(buf,(const ut8*)(x),y)
194 #define D(x) r_buf_append_ut32(buf,x)
195 B ("MENUET01", 8);
196 D (1); // header version
197 D (32); // program start
198 D (0x1000); // program image size
199 D (0x1000); // ESP
200 D (0); // no parameters
201 D (0); // no path
202 B (code, codelen);
203 return buf;
204 }
205
206 RBinPlugin r_bin_plugin_menuet = {
207 .name = "menuet",
208 .desc = "Menuet/KolibriOS bin plugin",
209 .license = "LGPL3",
210 .load_buffer = &load_buffer,
211 .size = &size,
212 .check_buffer = &check_buffer,
213 .baddr = &baddr,
214 .entries = &entries,
215 .sections = §ions,
216 .info = &info,
217 .create = &create,
218 };
219
220 #ifndef R2_PLUGIN_INCORE
221 R_API RLibStruct radare_plugin = {
222 .type = R_LIB_TYPE_BIN,
223 .data = &r_bin_plugin_menuet,
224 .version = R2_VERSION
225 };
226 #endif
227 #endif
228