Binary
bomb
Reversed source code
bomb.c
FILE *infile;
int num_input_strings = 0;
char input_strings[...][80];
void initialize_bomb(void)
{
signal(SIGINT, sig_handler);
}
void sig_handler(void)
{
printf("So you think you can stop the bomb with ctrl-c, do you?\n");
sleep(3);
printf("Well...");
fflush(stdout);
sleep(1);
print("OK. :-)\n");
exit(16);
}
// Returns whether a string has only space characters
int blank_line(char *input)
{
if (input[0] == '\0') {
return 1;
}
for (;;) {
int c = *input;
input++;
if (isspace(c)) {
if (*input == '\0') {
return 1;
}
} else {
return 0;
}
}
}
// Can return NULL
char *skip(void)
{
do {
char *input_string = input_strings[num_input_strings];
char *input = fgets(input_string, 80, infile);
if (input == NULL) {
break;
}
} while (blank_line(input));
return input;
}
void explode_bomb(void)
{
printf("\nBOOM!!!\n");
printf("The bomb has blown up.\n");
exit(8);
}
char *read_line(void)
{
char *line;
line = skip();
if (line == NULL) {
if (infile == stdin) {
printf("Error: Premature EOF on stdin\n");
explode_bomb();
}
char *env = getenv("GRADE_BOMB");
if (env != NULL) {
exit(0);
}
infile = stdin;
line = skip();
if (line == NULL) {
printf("Error: Premature EOF on stdin\n");
explode_bomb();
}
}
size_t len = strlen(line) + 1;
if (len >= 0x4f) {
printf("Error: Input line too long\n");
explode_bomb();
}
input_strings[num_input_strings][len] = '\0';
num_input_strings++;
}
// Equivalent to strlen()
size_t string_length(char *s)
{
if (*s == '\0') {
return 0;
}
size_t len = 0;
do {
s++;
len++;
} while (*s != '\0');
return len;
}
// Equivalent to strcmp()
bool strings_not_equal(char *s1, char *s2)
{
// STUB
}
// "Public speaking is very easy."
void phase_1(char *line)
{
if (strings_not_equal(line, "Public speaking is very easy.")) {
explode_bomb();
}
}
void read_six_numbers(char *line, int *nums)
{
int n_nums_read = sscanf(line, "%d %d %d %d %d %d", nums[0], nums[1],
nums[2], nums[3], nums[4], nums[5]);
if (n_nums_read != 6) {
explode_bomb();
}
}
// "1 2 6 24 120 720"
void phase_2(char *line)
{
int nums[6];
read_six_numbers(line, nums);
if (nums[0] != 1) {
explode_bomb();
}
int i = 1;
do {
int prod = i + 1;
prod *= nums[i - 1];
if (nums[i] != prod) {
explode_bomb();
}
i++;
} while (i <= 5);
}
// "0 q 777"
void phase_3(char *line)
{
int n1, c, n2, c_chk;
int nread = sscanf(line, "%d %c %d", n1, c, n2);
if (nread != 3) {
explode_bomb();
}
if (n1 > 7) {
explode_bomb();
}
switch (n1) {
case 0:
c_chk = 0x71;
if (n2 != 0x309) {
expolde_bomb();
}
break;
case 1:
c_chk = 0x62;
if (n2 != 0xd6) {
expolde_bomb();
}
break;
case 2:
c_chk = 0x62;
if (n2 != 0x2f3) {
expolde_bomb();
}
break;
case 3:
c_chk = 0x6b;
if (n2 != 0xfb) {
expolde_bomb();
}
break;
case 4:
c_chk = 0x6f;
if (n2 != 0xa0) {
expolde_bomb();
}
break;
case 5:
c_chk = 0x74;
if (n2 != 0x1ca) {
expolde_bomb();
}
break;
case 6:
c_chk = 0x76;
if (n2 != 0x30c) {
expolde_bomb();
}
break;
case 7:
c_chk = 0x62;
if (n2 != 0x20c) {
expolde_bomb();
}
break;
default:
explode_bomb();
}
if (c != c_chk) {
explode_bomb();
}
}
int fibo(int num)
{
if (num <= 1) {
return 1;
}
return fibo(num - 1) + fibo(num - 2);
}
// "9"
void phase_4(char *line)
{
int num;
int nread = sscanf(line, "%d", num);
if (nread != 1) {
explode_bomb();
}
if (num <= 0) {
explode_bomb();
}
if (fibo(num) != 55) {
explode_bomb();
}
}
// "? %+-!"
void phase_5(char *line)
{
char buf[7];
if (string_length(line) != 6) {
explode_bomb();
}
int i = 0;
do {
buf[i] = "isrveawhobpnutfg\xb0\x01"[line[i] & 0xf];
i++;
} while (i <= 5);
buf[6] = '\0';
if (strings_not_equal(buf, "giants")) {
explode_bomb();
}
}
struct list_node {
uint32_t data;
uint32_t list_node_num;
struct list_node *next;
};
struct list_node node6 = {
0x1b0,
6,
NULL
};
struct list_node node5 = {
0xd4,
5,
&node6
};
struct list_node node4 = {
0x3e5,
4,
&node5
};
struct list_node node3 = {
0x12d,
3,
&node4
};
struct list_node node2 = {
0x2d5,
2,
&node3
};
struct list_node node1 = {
0xfd,
1,
&node2
};
// "4 2 6 3 1 5"
void phase_6(char *line)
{
// [gb]
// Get 6 numbers, and check that they are unique and all 5 or less
int nums[6];
struct list_node *node = &node1;
// Input line is 6 numbers
read_six_numbers(line, nums);
int i = 0;
// [gd]
do {
// [gd]
// All numbers must be 5 or less
if (nums[i] > 6 && nums[i] <= 0) {
// [gf]
explode_bomb();
}
// [gc]
// All numbers unique
if (i <= 4) {
// [gh]
int j = i + 1;
// [gj]
do {
if (nums[i] == nums[j]) {
// [gk]
explode_bomb();
}
// [gi]
j++;
} while (j <= 5);
}
// [gg]
i++;
} while (i <= 5);
// [gl]
i = 0;
struct list_node *ptee;
struct list_node *nodes[6];
nodes[0] = &ptee;
// [gn]
// Order nodes in an array
do {
if (nums[i] > 1) {
// [go]
int j = i;
do {
node = node->next;
j++;
} while (j < num[j]);
}
// [gm]
nodes[i] = node;
i++;
} while (i <= 5);
// [gq]
node = ptee;
i = 1;
// [gr]
// Order list based on array of nodes
do {
node->next = ptee[i];
node = ptee[i];
i++;
} while (i <= 5);
// [gs]
node->next = NULL;
node = ptee;
i = 0;
// [gu]
// Ensure that data is in descending order
do {
// List must be in descending order?
if (node->data < node->next->data) {
// [gv]
explode_bomb();
}
// [gt]
node = node->next;
i++;
} while (i <= 4);
}
struct tree_node {
int val;
struct tree_node *next1;
struct tree_node *next2;
char pad[5 * 4];
};
struct tree_node n1 = {
0x24,
&n21,
&n22
};
struct tree_node n21 = {
0x8,
&n31,
&n32
};
struct tree_node n31 = {
0x6,
&n41,
&n42
};
struct tree_node n41 = {
0x1,
NULL,
NULL
};
struct tree_node n42 = {
0x7,
NULL,
NULL
};
struct tree_node n32 = {
0x16,
&n43,
&n44
};
struct tree_node n43 = {
0x14,
NULL,
NULL
};
struct tree_node n44 = {
0x23,
NULL,
NULL
};
struct tree_node n22 = {
0x32,
&n33,
&n34
};
struct tree_node n33 = {
0x2d,
&n45,
&n46
};
struct tree_node n45 = {
0x28,
NULL,
NULL
};
struct tree_node n46 = {
0x2f,
NULL,
NULL
};
struct tree_node n34 = {
0x6b,
&n47,
&n48
};
struct tree_node n47 = {
0x63,
NULL,
NULL
};
struct tree_node n48 = {
0x3e9,
NULL,
NULL
};
// 1st run: tree_node = &n1, return 7
// 2nd run: tree_node = &n22, return 3
// 3nd run: tree_node = &n34, return 1
// 4th run: tree_node = &n48, return 0
int fun7(struct tree_node *tree_node, int num)
{
// Shuould never be true
if (tree_node == NULL) {
return -1;
}
if (num >= tree_node->val) {
// [ge]
// 4th run num must be == 0x3e9
if (num == tree_node->val) {
return 0;
}
// [gh]
// 1st run num must be > 0x24
// 2nd run num must be > 0x32
// 3rd run num must be > 0x6b
return fun7(tree_node->next2, num) * 2 + 1;
} else {
// [gf]
return fun7(tree_node->next1, num) * 2;
}
}
void secret_phase(void)
{
char *line = read_line();
int num = strtol(line, NULL, 10);
// 0 <= num <= 0x3e9
if (num > 0x3e9 || num < 0) {
explode_bomb();
}
if (fun7(n1, num) != 7) {
// [gi]
explode_bomb();
}
printf("Wow! You've defused the secret stage!\n");
phase_defused();
}
void phase_defused(void)
{
if (num_input_strings != 6) {
return;
}
int num;
char *str;
if (sscanf((char *) 0x804b770, "%d %s", num, str) != 2) {
goto defused;
}
if (strings_not_equal(str, "austinpowers")) {
goto defused;
}
printf("Curses, you've found the secret phase!\n");
printf("But finding it and solving it are quite different...\n");
secret_phase();
defused:
printf("Congratulations! You've defused the bomb!\n");
}
int main(int argc, char *argv[])
{
char *line;
if (argc == 1) {
infile = stdin;
} else if (argc == 2) {
infile = fopen(argv[1], "r");
if (infile == NULL) {
printf("%s: Error: Couldn't open %s\n");
exit(8);
}
} else {
printf("Usage: %s [<input_file>]\n");
exit(8);
}
initialize_bomb();
printf("Welcome to my fiendish little bomb. You have 6 phases with\n");
printf("which to blow yourself up. Have a nice day!\n");
line = read_line();
phase_1(line);
phase_defused();
printf("Phase 1 defused. How about the next one?\n");
line = read_line();
phase_2(line);
phase_defused();
printf("That's number 2. Keep going!\n");
line = read_line();
phase_3(line);
phase_defused();
printf("Halfway there!\n");
line = read_line();
phase_4(line);
phase_defused();
printf("So you got that one. Try this one.\n");
line = read_line();
phase_5(line);
phase_defused();
printf("Good work! On to the next...\n");
line = read_line();
phase_6(line);
phase_defused(); // Secret phase
}
input.txt
Public speaking is very easy.
1 2 6 24 120 720
0 q 777
9 austinpowers
? %+-!
4 2 6 3 1 5
1001