const char rodata[] = "abcd"; #include #include #define _GNU_SOURCE #include struct account { long money; const char *name; }; void retrieve_account(struct account *acc); void check_flag(const struct account *acc); int main(int argc, char **argv){ struct account acc; // current user and their money retrieve_account(&acc); /////////// INTERESTING CODE BELOW ////////////// // these are the interesting local variables, packed in a struct so the layout doesn't change struct { char buffer[16]; int nDucks; } order; const long price_per_duck = 20; setbuf(stdout, NULL); // turn off output buffering printf("Hi, %s! Welcome to *Acme Rubber Ducks, Inc.*! We sell rubber ducks for the low price of $%ld per duck. You have $%ld. How many rubber ducks would you like to order? ", acc.name, price_per_duck, acc.money); fgets(order.buffer, 512, stdin); order.nDucks = atoi(order.buffer); // atoi converts a string to an int if(order.nDucks < 1) { // we're certainly not going to get tricked by anyone ordering a negative amount of ducks! printf("Sorry, minimum order size is 1\n"); return 0; } printf("And what is your shipping address? "); fgets(order.buffer, 512, stdin); // read up to 512 bytes into our 16 byte buffer (what could possibly go wrong?) strchrnul(order.buffer, '\n')[0] = '\0'; // replace newline with end-of-string long total = order.nDucks*price_per_duck; if(total > acc.money) { // input validation is important. we're checking everything here! printf("Sorry! You don't have enough money!\n"); } else { acc.money -= total; printf("Thank you for your order of %d ducks!\nWe have charged your account $%ld, and you now have $%ld left.\n", order.nDucks, total, acc.money); check_flag(&acc); } return 0; } void retrieve_account(struct account *acc) { const char* m = getenv("MONEY"); if(m != NULL) acc->money = atol(m); else acc->money = 1000; acc->name = getenv("USER"); // ^^^ the arrow operator (->) gets a field value from a *pointer to a struct*; it is // equivalent to dereferencing the pointer (*acc) and then selecting the field: (*acc).name } // check if the flag was captured // ctf.py will check if money > 1000 and if so issue a success token void check_flag(const struct account *acc) { if(getenv("TASK_NAME")) { char cmdline[48]; snprintf(cmdline, 47, "python ctf.py check %ld", acc->money); system(cmdline); } else { printf("Success!"); } }