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 = &sections,
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