Line data Source code
1 : /*
2 : * Gift Card Reading Application
3 : * Original Author: Shoddycorp's Cut-Rate Contracting
4 : * Comments added by: Justin Cappos (JAC) and Brendan Dolan-Gavitt (BDG)
5 : * Maintainer:
6 : * Date: 8 July 2020
7 : */
8 :
9 :
10 : #include "giftcard.h"
11 :
12 : #include <stdio.h>
13 : #include <strings.h>
14 : #include <limits.h>
15 : // .,~==== interpreter for THX-1138 assembly ====~,.
16 : //
17 : // This is an emulated version of a microcontroller with
18 : // 16 registers, one flag (the zero flag), and display
19 : // functionality. Programs can operate on the message
20 : // buffer and use opcode 0x07 to update the display, so
21 : // that animated greetings can be created.
22 :
23 0 : void animate(char *msg, unsigned char *program) {
24 : unsigned char regs[16];
25 0 : char *mptr = msg; // TODO: how big is this buffer?
26 0 : unsigned char *pc = program;
27 0 : int i = 0;
28 0 : int zf = 0;
29 0 : int count =0;
30 0 : int count2 =0;
31 0 : unsigned char lastpc =0;
32 0 : while (pc< program+256) {
33 : unsigned char op, arg1, arg2;
34 0 : op = *pc;
35 0 : arg1 = *(pc+1);
36 0 : arg2 = *(pc+2);
37 0 : switch (*pc) {
38 : case 0x00:
39 0 : break;
40 : case 0x01:
41 0 : regs[arg1] = *mptr;
42 0 : break;
43 : case 0x02:
44 0 : if(arg1<0 || arg1>15){
45 0 : exit(0);
46 : }
47 0 : *mptr = regs[arg1]; //crash here
48 0 : break;
49 : case 0x03:
50 0 : mptr += (char)arg1;
51 0 : break;
52 : case 0x04:
53 0 : regs[arg2] = arg1;
54 0 : break;
55 : case 0x05:
56 0 : regs[arg1] ^= regs[arg2];
57 0 : zf = !regs[arg1];
58 0 : break;
59 : case 0x06:
60 0 : regs[arg1] += regs[arg2];
61 0 : zf = !regs[arg1];
62 0 : break;
63 : case 0x07:
64 0 : puts(msg);
65 0 : break;
66 : case 0x08:
67 0 : goto done;
68 : case 0x09:
69 0 : if(pc< program+256+ (unsigned char)arg1){
70 0 : pc += (unsigned char)arg1;
71 0 : }
72 : else{
73 0 : goto done;
74 : }
75 0 : break;
76 : case 0x10:
77 0 : if(pc< program+256+ (unsigned char)arg1){
78 0 : if (zf) pc += (unsigned char)arg1;
79 0 : }
80 : else{
81 0 : goto done;
82 : }
83 0 : break;
84 : }
85 0 : pc+=3;
86 0 : count2++;
87 0 : if (count2 > 80)
88 : {
89 0 : goto done;
90 : }
91 :
92 : }
93 : done:
94 0 : pc =0;
95 0 : return;
96 : }
97 :
98 2 : int get_gift_card_value(struct this_gift_card *thisone) {
99 : struct gift_card_data *gcd_ptr;
100 : struct gift_card_record_data *gcrd_ptr;
101 : struct gift_card_amount_change *gcac_ptr;
102 2 : int ret_count = 0;
103 :
104 2 : gcd_ptr = thisone->gift_card_data;
105 4 : for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
106 2 : gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
107 2 : if (gcrd_ptr->type_of_record == 1) {
108 1 : gcac_ptr = gcrd_ptr->actual_record;
109 1 : ret_count += gcac_ptr->amount_added;
110 1 : }
111 2 : }
112 2 : return ret_count;
113 : }
114 :
115 2 : void print_gift_card_info(struct this_gift_card *thisone) {
116 : struct gift_card_data *gcd_ptr;
117 : struct gift_card_record_data *gcrd_ptr;
118 : struct gift_card_amount_change *gcac_ptr;
119 : struct gift_card_program *gcp_ptr;
120 :
121 2 : gcd_ptr = thisone->gift_card_data;
122 2 : printf(" Merchant ID: %32.32s\n",gcd_ptr->merchant_id);
123 2 : printf(" Customer ID: %32.32s\n",gcd_ptr->customer_id);
124 2 : printf(" Num records: %d\n",gcd_ptr->number_of_gift_card_records);
125 4 : for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
126 2 : gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
127 2 : if (gcrd_ptr->type_of_record == 1) {
128 1 : printf(" record_type: amount_change\n");
129 1 : gcac_ptr = gcrd_ptr->actual_record;
130 1 : printf(" amount_added: %d\n",gcac_ptr->amount_added);
131 1 : if (gcac_ptr->amount_added>0) {
132 1 : printf(" signature: %32.32s\n",gcac_ptr->actual_signature);
133 1 : }
134 1 : }
135 1 : else if (gcrd_ptr->type_of_record == 2) {
136 1 : printf(" record_type: message\n");
137 1 : printf(" message: %s\n",(char *)gcrd_ptr->actual_record);
138 1 : }
139 0 : else if (gcrd_ptr->type_of_record == 3) {
140 0 : gcp_ptr = gcrd_ptr->actual_record;
141 0 : printf(" record_type: animated message\n");
142 : // BDG: Hmm... is message guaranteed to be null-terminated?
143 0 : printf(" message: %s\n", gcp_ptr->message);
144 0 : printf(" [running embedded program] \n");
145 0 : animate(gcp_ptr->message, gcp_ptr->program);
146 0 : }
147 2 : }
148 2 : printf(" Total value: %d\n\n",get_gift_card_value(thisone));
149 2 : }
150 :
151 : // Added to support web functionalities
152 0 : void gift_card_json(struct this_gift_card *thisone) {
153 : struct gift_card_data *gcd_ptr;
154 : struct gift_card_record_data *gcrd_ptr;
155 : struct gift_card_amount_change *gcac_ptr;
156 0 : gcd_ptr = thisone->gift_card_data;
157 0 : printf("{\n");
158 0 : printf(" \"merchant_id\": \"%32.32s\",\n", gcd_ptr->merchant_id);
159 0 : printf(" \"customer_id\": \"%32.32s\",\n", gcd_ptr->customer_id);
160 0 : printf(" \"total_value\": %d,\n", get_gift_card_value(thisone));
161 0 : printf(" \"records\": [\n");
162 0 : for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
163 0 : gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
164 0 : printf(" {\n");
165 0 : if (gcrd_ptr->type_of_record == 1) {
166 0 : printf(" \"record_type\": \"amount_change\",\n");
167 0 : gcac_ptr = gcrd_ptr->actual_record;
168 0 : printf(" \"amount_added\": %d,\n",gcac_ptr->amount_added);
169 0 : if (gcac_ptr->amount_added>0) {
170 : // printf(" \"signature\": \"%32.32s\"\n",gcac_ptr->actual_signature);
171 0 : }
172 0 : }
173 0 : else if (gcrd_ptr->type_of_record == 2) {
174 0 : printf(" \"record_type\": \"message\",\n");
175 0 : printf(" \"message\": \"%s\"\n",(char *)gcrd_ptr->actual_record);
176 0 : }
177 0 : else if (gcrd_ptr->type_of_record == 3) {
178 0 : struct gift_card_program *gcp = gcrd_ptr->actual_record;
179 0 : printf(" \"record_type\": \"animated message\",\n");
180 0 : printf(" \"message\": \"%s\",\n",gcp->message);
181 : // programs are binary so we will hex for the json
182 0 : char *hexchars = "01234567890abcdef";
183 : char program_hex[512+1];
184 0 : program_hex[512] = '\0';
185 : int i;
186 0 : for(i = 0; i < 256; i++) {
187 0 : program_hex[i*2] = hexchars[((gcp->program[i] & 0xf0) >> 4)];
188 0 : program_hex[i*2+1] = hexchars[(gcp->program[i] & 0x0f)];
189 0 : }
190 0 : printf(" \"program\": \"%s\"\n",program_hex);
191 0 : }
192 0 : if (i < gcd_ptr->number_of_gift_card_records-1)
193 0 : printf(" },\n");
194 : else
195 0 : printf(" }\n");
196 0 : }
197 0 : printf(" ]\n");
198 0 : printf("}\n");
199 0 : }
200 :
201 :
202 2 : struct this_gift_card *gift_card_reader(FILE *input_fd) {
203 :
204 2 : struct this_gift_card *ret_val = malloc(sizeof(struct this_gift_card));
205 : void *optr;
206 : void *ptr;
207 :
208 : // Loop to do the whole file
209 4 : while (!feof(input_fd)) {
210 :
211 : struct gift_card_data *gcd_ptr;
212 : /* JAC: Why aren't return types checked? */
213 2 : fread(&ret_val->num_bytes, 4,1, input_fd);
214 2 : if ( ret_val->num_bytes < 0 || ret_val->num_bytes > 1024*1024*10)
215 : {
216 0 : exit(0);
217 : }
218 :
219 :
220 : // Make something the size of the rest and read it in
221 2 : ptr = malloc(ret_val->num_bytes);
222 2 : fread(ptr, ret_val->num_bytes, 1, input_fd);
223 :
224 2 : optr = ptr-4;
225 :
226 2 : gcd_ptr = ret_val->gift_card_data = malloc(sizeof(struct gift_card_data));
227 2 : gcd_ptr->merchant_id = ptr;
228 2 : ptr += 32;
229 : // printf("VD: %d\n",(int)ptr - (int) gcd_ptr->merchant_id);
230 2 : gcd_ptr->customer_id = ptr;
231 2 : ptr += 32;
232 : /* JAC: Something seems off here... */
233 2 : gcd_ptr->number_of_gift_card_records = *((char *)ptr);
234 2 : ptr += 4;
235 :
236 2 : gcd_ptr->gift_card_record_data = (void *)malloc(gcd_ptr->number_of_gift_card_records*sizeof(void*));
237 :
238 : // Now ptr points at the gift card recrod data
239 4 : for (int i=0; i < gcd_ptr->number_of_gift_card_records; i++){
240 : // printf("i: %d\n",i);
241 : struct gift_card_record_data *gcrd_ptr;
242 2 : gcrd_ptr = gcd_ptr->gift_card_record_data[i] = malloc(sizeof(struct gift_card_record_data));
243 : struct gift_card_amount_change *gcac_ptr;
244 2 : gcac_ptr = gcrd_ptr->actual_record = malloc(sizeof(struct gift_card_record_data));
245 : struct gift_card_program *gcp_ptr;
246 2 : gcp_ptr = malloc(sizeof(struct gift_card_program));
247 :
248 2 : gcrd_ptr->record_size_in_bytes = *((char *)ptr);
249 : //printf("rec at %x, %d bytes\n", ptr - optr, gcrd_ptr->record_size_in_bytes);
250 2 : ptr += 4;
251 : //printf("record_data: %d\n",gcrd_ptr->record_size_in_bytes);
252 2 : gcrd_ptr->type_of_record = *((char *)ptr);
253 2 : ptr += 4;
254 : //printf("type of rec: %d\n", gcrd_ptr->type_of_record);
255 :
256 : // amount change
257 2 : if (gcrd_ptr->type_of_record == 1) {
258 1 : gcac_ptr->amount_added = *((int*) ptr);
259 1 : ptr += 4;
260 :
261 : // don't need a sig if negative
262 : /* JAC: something seems off here */
263 1 : if (gcac_ptr < 0) break;
264 :
265 1 : gcac_ptr->actual_signature = ptr;
266 1 : ptr+=32;
267 1 : }
268 : // message
269 2 : if (gcrd_ptr->type_of_record == 2) {
270 1 : gcrd_ptr->actual_record = ptr;
271 : // printf("ptr: %d\n",ptr);
272 :
273 : // advance by the string size + 1 for nul
274 : // BDG: does not seem right
275 1 : ptr=ptr+strlen((char *)gcrd_ptr->actual_record)+1;
276 : // printf("ptr: %d\n",ptr);
277 :
278 1 : }
279 : // BDG: gift cards can run code?? Might want to check this one carefully...
280 : // text animatino (BETA)
281 2 : if (gcrd_ptr->type_of_record == 3) {
282 0 : gcp_ptr->message = malloc(32);
283 0 : gcp_ptr->program = malloc(256);
284 0 : memcpy(gcp_ptr->message, ptr, 32);
285 0 : ptr+=32;
286 0 : memcpy(gcp_ptr->program, ptr, 256);
287 0 : ptr+=256;
288 0 : gcrd_ptr->actual_record = gcp_ptr;
289 0 : }
290 2 : }
291 : }
292 2 : return ret_val;
293 : }
294 :
295 : struct this_gift_card *thisone;
296 :
297 2 : int main(int argc, char **argv) {
298 2 : if (argc != 3) {
299 0 : fprintf(stderr, "usage: %s <1|2> file.gft\n", argv[0]);
300 0 : fprintf(stderr, " - Use 1 for text output, 2 for JSON output\n");
301 0 : return 1;
302 : }
303 2 : FILE *input_fd = fopen(argv[2],"r");
304 2 : if (!input_fd) {
305 0 : fprintf(stderr, "error opening file\n");
306 0 : return 1;
307 : }
308 2 : thisone = gift_card_reader(input_fd);
309 2 : if (argv[1][0] == '1') print_gift_card_info(thisone);
310 0 : else if (argv[1][0] == '2') gift_card_json(thisone);
311 :
312 2 : return 0;
313 2 : }
|