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 :
15 : // interpreter for THX-1138 assembly
16 0 : void animate(char *msg, unsigned char *program) {
17 : unsigned char regs[16];
18 0 : char *mptr = msg;
19 0 : unsigned char *pc = program;
20 0 : int i = 0;
21 0 : int zf = 0;
22 0 : while (1) {
23 : unsigned char op, arg1, arg2;
24 0 : op = *pc;
25 0 : arg1 = *(pc+1);
26 0 : arg2 = *(pc+2);
27 0 : switch (*pc) {
28 0 : case 0x00:
29 0 : break;
30 0 : case 0x01:
31 0 : regs[arg1] = *mptr;
32 0 : break;
33 0 : case 0x02:
34 0 : *mptr = regs[arg1];
35 0 : break;
36 0 : case 0x03:
37 0 : mptr += (char)arg1;
38 0 : break;
39 0 : case 0x04:
40 0 : regs[arg2] = arg1;
41 0 : break;
42 0 : case 0x05:
43 0 : regs[arg1] ^= regs[arg2];
44 0 : zf = !regs[arg1];
45 0 : break;
46 0 : case 0x06:
47 0 : regs[arg1] += regs[arg2];
48 0 : zf = !regs[arg1];
49 0 : break;
50 0 : case 0x07:
51 0 : puts(msg);
52 0 : break;
53 0 : case 0x08:
54 0 : goto done;
55 0 : case 0x09:
56 0 : pc += (char)arg1;
57 0 : break;
58 0 : case 0x10:
59 0 : if (zf) pc += (char)arg1;
60 0 : break;
61 : }
62 0 : pc+=3;
63 0 : if (pc > program+256) break;
64 : }
65 0 : done:
66 0 : return;
67 : }
68 :
69 1 : void print_gift_card_info(struct this_gift_card *thisone) {
70 : struct gift_card_data *gcd_ptr;
71 : struct gift_card_record_data *gcrd_ptr;
72 : struct gift_card_amount_change *gcac_ptr;
73 : struct gift_card_program *gcp_ptr;
74 :
75 1 : gcd_ptr = thisone->gift_card_data;
76 1 : printf(" Merchant ID: %32.32s\n",gcd_ptr->merchant_id);
77 1 : printf(" Customer ID: %32.32s\n",gcd_ptr->customer_id);
78 1 : printf(" Num records: %d\n",gcd_ptr->number_of_gift_card_records);
79 2 : for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
80 1 : gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
81 1 : if (gcrd_ptr->type_of_record == 1) {
82 1 : printf(" record_type: amount_change\n");
83 1 : gcac_ptr = gcrd_ptr->actual_record;
84 1 : printf(" amount_added: %d\n",gcac_ptr->amount_added);
85 1 : if (gcac_ptr->amount_added>0) {
86 1 : printf(" signature: %32.32s\n",gcac_ptr->actual_signature);
87 : }
88 : }
89 0 : else if (gcrd_ptr->type_of_record == 2) {
90 0 : printf(" record_type: message\n");
91 0 : printf(" message: %s\n",(char *)gcrd_ptr->actual_record);
92 : }
93 0 : else if (gcrd_ptr->type_of_record == 3) {
94 0 : gcp_ptr = gcrd_ptr->actual_record;
95 0 : printf(" record_type: animated message\n");
96 0 : printf(" message: %s\n", gcp_ptr->message);
97 0 : printf(" [running embedded program] \n");
98 0 : animate(gcp_ptr->message, gcp_ptr->program);
99 : }
100 : }
101 1 : printf(" Total value: %d\n\n",get_gift_card_value(thisone));
102 1 : }
103 :
104 : // Added to support web functionalities
105 0 : void gift_card_json(struct this_gift_card *thisone) {
106 : struct gift_card_data *gcd_ptr;
107 : struct gift_card_record_data *gcrd_ptr;
108 : struct gift_card_amount_change *gcac_ptr;
109 0 : gcd_ptr = thisone->gift_card_data;
110 0 : printf("{\n");
111 0 : printf(" \"merchant_id\": \"%32.32s\",\n", gcd_ptr->merchant_id);
112 0 : printf(" \"customer_id\": \"%32.32s\",\n", gcd_ptr->customer_id);
113 0 : printf(" \"total_value\": %d,\n", get_gift_card_value(thisone));
114 0 : printf(" \"records\": [\n");
115 0 : for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
116 0 : gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
117 0 : printf(" {\n");
118 0 : if (gcrd_ptr->type_of_record == 1) {
119 0 : printf(" \"record_type\": \"amount_change\",\n");
120 0 : gcac_ptr = gcrd_ptr->actual_record;
121 0 : printf(" \"amount_added\": %d,\n",gcac_ptr->amount_added);
122 0 : if (gcac_ptr->amount_added>0) {
123 0 : printf(" \"signature\": \"%32.32s\"\n",gcac_ptr->actual_signature);
124 : }
125 : }
126 0 : else if (gcrd_ptr->type_of_record == 2) {
127 0 : printf(" \"record_type\": \"message\",\n");
128 0 : printf(" \"message\": \"%s\"\n",(char *)gcrd_ptr->actual_record);
129 : }
130 0 : else if (gcrd_ptr->type_of_record == 3) {
131 0 : struct gift_card_program *gcp = gcrd_ptr->actual_record;
132 0 : printf(" \"record_type\": \"animated message\",\n");
133 0 : printf(" \"message\": \"%s\",\n",gcp->message);
134 : // programs are binary so we will hex for the json
135 0 : char *hexchars = "01234567890abcdef";
136 : char program_hex[512+1];
137 0 : program_hex[512] = '\0';
138 : int i;
139 0 : for(i = 0; i < 256; i++) {
140 0 : program_hex[i*2] = hexchars[((gcp->program[i] & 0xf0) >> 4)];
141 0 : program_hex[i*2+1] = hexchars[(gcp->program[i] & 0x0f)];
142 : }
143 0 : printf(" \"program\": \"%s\"\n",program_hex);
144 : }
145 0 : if (i < gcd_ptr->number_of_gift_card_records-1)
146 0 : printf(" },\n");
147 : else
148 0 : printf(" }\n");
149 : }
150 0 : printf(" ]\n");
151 0 : printf("}\n");
152 0 : }
153 :
154 1 : int get_gift_card_value(struct this_gift_card *thisone) {
155 : struct gift_card_data *gcd_ptr;
156 : struct gift_card_record_data *gcrd_ptr;
157 : struct gift_card_amount_change *gcac_ptr;
158 1 : int ret_count = 0;
159 :
160 1 : gcd_ptr = thisone->gift_card_data;
161 2 : for(int i=0;i<gcd_ptr->number_of_gift_card_records; i++) {
162 1 : gcrd_ptr = (struct gift_card_record_data *) gcd_ptr->gift_card_record_data[i];
163 1 : if (gcrd_ptr->type_of_record == 1) {
164 1 : gcac_ptr = gcrd_ptr->actual_record;
165 1 : ret_count += gcac_ptr->amount_added;
166 : }
167 : }
168 1 : return ret_count;
169 : }
170 :
171 :
172 :
173 : /* JAC: input_fd is misleading... It's a FILE type, not a fd */
174 1 : struct this_gift_card *gift_card_reader(FILE *input_fd) {
175 :
176 1 : struct this_gift_card *ret_val = malloc(sizeof(struct this_gift_card));
177 :
178 : void *optr;
179 : void *ptr;
180 :
181 : // Loop to do the whole file
182 3 : while (!feof(input_fd)) {
183 :
184 : struct gift_card_data *gcd_ptr;
185 : /* JAC: Why aren't return types checked? */
186 1 : fread(&ret_val->num_bytes, 4,1, input_fd);
187 :
188 : // Make something the size of the rest and read it in
189 1 : ptr = malloc(ret_val->num_bytes);
190 1 : fread(ptr, ret_val->num_bytes, 1, input_fd);
191 :
192 1 : optr = ptr-4;
193 :
194 1 : gcd_ptr = ret_val->gift_card_data = malloc(sizeof(struct gift_card_data));
195 1 : gcd_ptr->merchant_id = ptr;
196 1 : ptr += 32;
197 : // printf("VD: %d\n",(int)ptr - (int) gcd_ptr->merchant_id);
198 1 : gcd_ptr->customer_id = ptr;
199 1 : ptr += 32;
200 : /* JAC: Something seems off here... */
201 1 : gcd_ptr->number_of_gift_card_records = *((char *)ptr);
202 1 : ptr += 4;
203 :
204 1 : gcd_ptr->gift_card_record_data = (void *)malloc(gcd_ptr->number_of_gift_card_records*sizeof(void*));
205 :
206 : // Now ptr points at the gift card recrod data
207 3 : for (int i=0; i<=gcd_ptr->number_of_gift_card_records; i++){
208 : //printf("i: %d\n",i);
209 : struct gift_card_record_data *gcrd_ptr;
210 2 : gcrd_ptr = gcd_ptr->gift_card_record_data[i] = malloc(sizeof(struct gift_card_record_data));
211 : struct gift_card_amount_change *gcac_ptr;
212 2 : gcac_ptr = gcrd_ptr->actual_record = malloc(sizeof(struct gift_card_record_data));
213 : struct gift_card_program *gcp_ptr;
214 2 : gcp_ptr = malloc(sizeof(struct gift_card_program));
215 :
216 2 : gcrd_ptr->record_size_in_bytes = *((char *)ptr);
217 : //printf("rec at %x, %d bytes\n", ptr - optr, gcrd_ptr->record_size_in_bytes);
218 2 : ptr += 4;
219 : //printf("record_data: %d\n",gcrd_ptr->record_size_in_bytes);
220 2 : gcrd_ptr->type_of_record = *((char *)ptr);
221 2 : ptr += 4;
222 : //printf("type of rec: %d\n", gcrd_ptr->type_of_record);
223 :
224 : // amount change
225 2 : if (gcrd_ptr->type_of_record == 1) {
226 1 : gcac_ptr->amount_added = *((int*) ptr);
227 1 : ptr += 4;
228 :
229 : // don't need a sig if negative
230 : /* JAC: something seems off here */
231 : if (gcac_ptr < 0) break;
232 :
233 1 : gcac_ptr->actual_signature = ptr;
234 1 : ptr+=32;
235 : }
236 : // message
237 2 : if (gcrd_ptr->type_of_record == 2) {
238 0 : gcrd_ptr->actual_record = ptr;
239 : // advance by the string size + 1 for nul
240 : // BDG: does not seem right
241 0 : ptr=ptr+strlen((char *)gcrd_ptr->actual_record)+1;
242 : }
243 : // BDG: never seen one of these in the wild
244 : // text animatino (BETA)
245 2 : if (gcrd_ptr->type_of_record == 3) {
246 0 : gcp_ptr->message = malloc(32);
247 0 : gcp_ptr->program = malloc(256);
248 0 : memcpy(gcp_ptr->message, ptr, 32);
249 0 : ptr+=32;
250 0 : memcpy(gcp_ptr->program, ptr, 256);
251 0 : ptr+=256;
252 0 : gcrd_ptr->actual_record = gcp_ptr;
253 : }
254 : }
255 : }
256 1 : return ret_val;
257 : }
258 :
259 : // BDG: why not a local variable here?
260 : struct this_gift_card *thisone;
261 :
262 1 : int main(int argc, char **argv) {
263 : // BDG: no argument checking?
264 1 : FILE *input_fd = fopen(argv[2],"r");
265 1 : thisone = gift_card_reader(input_fd);
266 1 : if (argv[1][0] == '1') print_gift_card_info(thisone);
267 0 : else if (argv[1][0] == '2') gift_card_json(thisone);
268 :
269 1 : return 0;
270 : }
|