{
  "id": 351884,
  "title": "A Review of the CTF Competition",
  "url": "/competitions/ai-village-ctf/writeups/john-mitchell-a-review-of-the-ctf-competition",
  "author_name": "",
  "post_date": "2022-09-15T11:36:31.257Z",
  "votes": 6,
  "comment_count": 1,
  "views": 0,
  "content": "<p>Thanks to the organisers for a challenging and addictive competition that has occupied (far too) much of my time over the last few weeks. It adds a kind of immersive augmented reality to life to be doing this competition, but I’m expecting that I will need a little break from serious competitive Kaggling for a while  to recover. Thanks to everyone who contributed to the Discord forum; at least two challenges I only solved as a result of the discussions (OK, hints) there.</p>\n<p>I found this competition as a Kaggler, definitely not a hacker, and someone who has picked up only a little python through competing on Kaggle. Some of the challenges seemed beyond my limited coding expertise (I was taught to write FORTRAN77 in capitals with the six spaces that once had allowed for the margin of the punch card) or my essentially non-existent cybersecurity knowledge. I did manage to complete half of them and here I describe them briefly, listing them with those that I personally and subjectively found most intellectually satisfying at the top.</p>\n<p>Noted that many of my solutions are indirect, using targeted or exhaustive searches of the possible solution space to obtain the flag rather than intellectually defeating the problem. At least five of my solutions could be described as “brute force”, though for math1-3 the degree of force required is very gentle.</p>\n<p><strong>murderbots</strong><br>\nI had originally planned to try opening the cells one by one sending 49 zeros and a one, and hoping for a different message depending on whether a bot or a human was released. Unfortunately, all the failure messages were of the “Oh no murderbots” variety, indeed even if I sent 50 zeros. I left this challenge for a while, but came back to it upon seeing that someone had left a hint “Index” on the forum. I have no idea what this hint meant, but it sent me looking in detail at the training data, hoping that all the human-containing cells might have odd, even, or perhaps prime indices. I didn’t find anything that obvious, but what I did find was a strong association between humans in the cells and a high number of “movement events”. So, I tried the approach of identifying the 12 cells in the test data with the most movement events. I took the 55 different ways of choosing 10 out of 12 of these top-movement cells, and used the 55 corresponding bitstrings shown in this <a href=\"https://www.kaggle.com/jbomitchell/killer-droids\" target=\"_blank\">notebook</a> as my guesses. The first string, that is simply opening the ten cells with the most movement events, yielded the flag.</p>\n<p><strong>baseball</strong><br>\nI wondered initially, since both Sarah and Henry were five-letter names, if the patterns might be ciphers for the names, perhaps with three successive pitches as a codon for each of the five letters. Or perhaps Sarah’s pattern was an S and Henry’s an H? However, it quickly turned out that the problem could be taken at face value, with each set of pitches matched against the characteristic patterns of the different pitchers to produce a confidence score.  So, my approach here was to treat this as an optimisation problem, which as a computational chemist I had a reasonable familiarity with. Initially I tried some arbitrary patterns and quickly found one which was a weak match for Henry. Simply trying arbitrary moves and accepting improvements did increase my confidence score, but only very slowly; so I went for a more systematic method.  I set up a grid of 100 points covering the (0-29,0-29) space as a square grid with one point every three units in each direction.  At each step, I take the best solution so far, and consider one particular pitch (I loop through the 15 of them as needed), let’s call it pitch p. I cycle through all 100 points (with an arbitrary small adjustments for overlaps with existing pitches) and find the new scores. The best of the 101 options (original plus 100 grid points) is taken as the new position of pitch p. If we haven't got the flag, we move onto pitch p+1 (modulo 15). Once I’d set up the systematic approach, as roughly illustrated in this <a href=\"https://www.kaggle.com/jbomitchell/bazball\" target=\"_blank\">notebook</a>, the flag appeared on the second pitch I looked at.</p>\n<p><strong>math1-3</strong><br>\nThe answer key is a string consisting of three integers run together, and so it seemed easier to use a search of the possible strings than to solve the problems mathematically. The key will almost certainly be an integer of three or more digits, and for the first three maths challenges a search of the possible three-digit integers indeed yielded the flag. The notebooks are these: <a href=\"https://www.kaggle.com/jbomitchell/maths-1-looper\" target=\"_blank\">1</a>, <a href=\"https://www.kaggle.com/jbomitchell/maths-2-looper\" target=\"_blank\">2</a>, and <a href=\"https://www.kaggle.com/jbomitchell/maths-3-looper\" target=\"_blank\">3</a> </p>\n<p><strong>math4</strong><br>\nAs for math1-3, but for this <a href=\"https://www.kaggle.com/jbomitchell/maths-4-looper\" target=\"_blank\">notebook</a> I had to extend the search into five digits to find the flag. Noted that the possible answers to the mathematical problem have a many-to-one mapping onto the answer key (we could have one fewer cluster but with a double digit number of dimensions, for example), so I have the flag without knowing a unique answer to the underlying problem.</p>\n<p><strong>deepfake</strong><br>\nSomeone dropped the hint “re-enactment” on Discord and suggested that this was 800 points for 5 minutes’ work. I recorded my own version of the video with a more canine-friendly script, and obtained the flag easily enough in this <a href=\"https://www.kaggle.com/jbomitchell/canis-felix\" target=\"_blank\">notebook</a>. I did not attempt to edit the original .mp4 (I’ve had more than enough of editing lecture videos).</p>\n<p><strong>inference</strong><br>\nThe character-recognition model seemed to be little use, other than that its structure suggested that the answer might be a six-letter word or six-character string. I still don’t know what the model was supposed to output [EDIT now understood after reading solution codes], but two very strong hints on Discord suggested that the correct string was both guessable and related to DEFCON30. Searching the conference website for suitable six letter strings was more productive than throwing more images at the model.</p>\n<p><strong>token</strong><br>\nA nasty, brutish and long search over the two million or so unique pairs of integers from the range [1, 1973]. My code was poorly thought out, and I missed seeing the flag the first time around. I guess I learned to write better code, rationalising the amount of output produced and saving it to an easy-to-parse file. I still have no idea how a tokenizer works, nor why this game of Blankety Blank should confuse it. This <a href=\"https://www.kaggle.com/jbomitchell/token-350\" target=\"_blank\">notebook</a> got lucky, e pluribus unum.</p>\n<p><strong>hotdog</strong><br>\nWhile it seems from the discussion on the Kaggle &amp; Discord fora that many people found this easy, I'm afraid I struggled with it for too long. Everything non-canine was classified as a “window screen”, except for a window screen, which was classified as a “shower curtain”. I gave up. Weeks later, I came back to it, and found a <a href=\"https://www.kaggle.com/datasets/dansbecker/hot-dog-not-hot-dog\" target=\"_blank\">Hot Dog / Not Hot Dog dataset</a> on Kaggle. I threw Hot Dog training images at the model, and several of them tested positive for the flag, as shown in this <a href=\"https://www.kaggle.com/jbomitchell/sausage-sandwich-game\" target=\"_blank\">notebook</a>.</p>\n<p><strong>honorstudent</strong><br>\nSimilarly to hotdog, I spent far too long trying to do what the problem told me to do and use whiteout to morph the F into an A. What eventually worked was a <a href=\"https://www.kaggle.com/datasets/abx393/handwritten-characters\" target=\"_blank\">handwritten character recognition dataset</a> from Kaggle, with suitable decolourisation and resizing, as illustrated in this <a href=\"https://www.kaggle.com/jbomitchell/honor-est-a-henry\" target=\"_blank\">notebook</a>.</p>\n<p><strong>forensics</strong><br>\nI didn’t really see the point of having the model name hiding in such plain sight in the .h5 file that even the most cursory inspection of the problem would reveal the correct answer. We were told that there were no fake flags, so this is presumably the intended answer rather than a red herring.</p>\n<p><strong>bad2good</strong><br>\nI fondly imagined that this would be an optimisation problem akin to baseball. I turned out to be weirder and more frustrating. I learned that negative marks were acceptable, and that marks above 100% were not. However, setting Henry’s mark to 100% and everyone else’s to minus a million caused the score to stick at 18, and gave no flag. Empirically, integral values of the scoring function seemed to correspond to unproductive regions of the problem space. Eventually, I found a region where the score was non-integral and could be increased above 18 by the strange expedient of setting Henry’s number of absences to a negative value. Composing his 100% of a base mark of 1 and +99 in penalties for minus 33 absences [sic] was the rather improbable combination that brought me a flag. I think most people seeing this problem would naturally expect that the marks would be the most important variables, so this came across as very much a trick question. And took three days, on and off, to solve – see <a href=\"https://www.kaggle.com/jbomitchell/marx-class\" target=\"_blank\">notebook</a>.</p>\n<p>And to the other nine, WAF, WIFI, leakage, theft, salt, hotterdog, secret.sloth, crop1 and crop2. Well done, you were too good for me. </p>\n<p>I look forward, hopefully, to a similar competition next year.</p>",
  "messages": [
    {
      "id": "1935633",
      "postDate": "09/12/2022 08:49:27",
      "content": "<p>Thanks to the organisers for a challenging and addictive competition that has occupied (far too) much of my time over the last few weeks. It adds a kind of immersive augmented reality to life to be doing this competition, but I’m expecting that I will need a little break from serious competitive Kaggling for a while  to recover. Thanks to everyone who contributed to the Discord forum; at least two challenges I only solved as a result of the discussions (OK, hints) there.</p>\n<p>I found this competition as a Kaggler, definitely not a hacker, and someone who has picked up only a little python through competing on Kaggle. Some of the challenges seemed beyond my limited coding expertise (I was taught to write FORTRAN77 in capitals with the six spaces that once had allowed for the margin of the punch card) or my essentially non-existent cybersecurity knowledge. I did manage to complete half of them and here I describe them briefly, listing them with those that I personally and subjectively found most intellectually satisfying at the top.</p>\n<p>Noted that many of my solutions are indirect, using targeted or exhaustive searches of the possible solution space to obtain the flag rather than intellectually defeating the problem. At least five of my solutions could be described as “brute force”, though for math1-3 the degree of force required is very gentle.</p>\n<p><strong>murderbots</strong><br>\nI had originally planned to try opening the cells one by one sending 49 zeros and a one, and hoping for a different message depending on whether a bot or a human was released. Unfortunately, all the failure messages were of the “Oh no murderbots” variety, indeed even if I sent 50 zeros. I left this challenge for a while, but came back to it upon seeing that someone had left a hint “Index” on the forum. I have no idea what this hint meant, but it sent me looking in detail at the training data, hoping that all the human-containing cells might have odd, even, or perhaps prime indices. I didn’t find anything that obvious, but what I did find was a strong association between humans in the cells and a high number of “movement events”. So, I tried the approach of identifying the 12 cells in the test data with the most movement events. I took the 55 different ways of choosing 10 out of 12 of these top-movement cells, and used the 55 corresponding bitstrings shown in this <a href=\"https://www.kaggle.com/jbomitchell/killer-droids\" target=\"_blank\">notebook</a> as my guesses. The first string, that is simply opening the ten cells with the most movement events, yielded the flag.</p>\n<p><strong>baseball</strong><br>\nI wondered initially, since both Sarah and Henry were five-letter names, if the patterns might be ciphers for the names, perhaps with three successive pitches as a codon for each of the five letters. Or perhaps Sarah’s pattern was an S and Henry’s an H? However, it quickly turned out that the problem could be taken at face value, with each set of pitches matched against the characteristic patterns of the different pitchers to produce a confidence score.  So, my approach here was to treat this as an optimisation problem, which as a computational chemist I had a reasonable familiarity with. Initially I tried some arbitrary patterns and quickly found one which was a weak match for Henry. Simply trying arbitrary moves and accepting improvements did increase my confidence score, but only very slowly; so I went for a more systematic method.  I set up a grid of 100 points covering the (0-29,0-29) space as a square grid with one point every three units in each direction.  At each step, I take the best solution so far, and consider one particular pitch (I loop through the 15 of them as needed), let’s call it pitch p. I cycle through all 100 points (with an arbitrary small adjustments for overlaps with existing pitches) and find the new scores. The best of the 101 options (original plus 100 grid points) is taken as the new position of pitch p. If we haven't got the flag, we move onto pitch p+1 (modulo 15). Once I’d set up the systematic approach, as roughly illustrated in this <a href=\"https://www.kaggle.com/jbomitchell/bazball\" target=\"_blank\">notebook</a>, the flag appeared on the second pitch I looked at.</p>\n<p><strong>math1-3</strong><br>\nThe answer key is a string consisting of three integers run together, and so it seemed easier to use a search of the possible strings than to solve the problems mathematically. The key will almost certainly be an integer of three or more digits, and for the first three maths challenges a search of the possible three-digit integers indeed yielded the flag. The notebooks are these: <a href=\"https://www.kaggle.com/jbomitchell/maths-1-looper\" target=\"_blank\">1</a>, <a href=\"https://www.kaggle.com/jbomitchell/maths-2-looper\" target=\"_blank\">2</a>, and <a href=\"https://www.kaggle.com/jbomitchell/maths-3-looper\" target=\"_blank\">3</a> </p>\n<p><strong>math4</strong><br>\nAs for math1-3, but for this <a href=\"https://www.kaggle.com/jbomitchell/maths-4-looper\" target=\"_blank\">notebook</a> I had to extend the search into five digits to find the flag. Noted that the possible answers to the mathematical problem have a many-to-one mapping onto the answer key (we could have one fewer cluster but with a double digit number of dimensions, for example), so I have the flag without knowing a unique answer to the underlying problem.</p>\n<p><strong>deepfake</strong><br>\nSomeone dropped the hint “re-enactment” on Discord and suggested that this was 800 points for 5 minutes’ work. I recorded my own version of the video with a more canine-friendly script, and obtained the flag easily enough in this <a href=\"https://www.kaggle.com/jbomitchell/canis-felix\" target=\"_blank\">notebook</a>. I did not attempt to edit the original .mp4 (I’ve had more than enough of editing lecture videos).</p>\n<p><strong>inference</strong><br>\nThe character-recognition model seemed to be little use, other than that its structure suggested that the answer might be a six-letter word or six-character string. I still don’t know what the model was supposed to output [EDIT now understood after reading solution codes], but two very strong hints on Discord suggested that the correct string was both guessable and related to DEFCON30. Searching the conference website for suitable six letter strings was more productive than throwing more images at the model.</p>\n<p><strong>token</strong><br>\nA nasty, brutish and long search over the two million or so unique pairs of integers from the range [1, 1973]. My code was poorly thought out, and I missed seeing the flag the first time around. I guess I learned to write better code, rationalising the amount of output produced and saving it to an easy-to-parse file. I still have no idea how a tokenizer works, nor why this game of Blankety Blank should confuse it. This <a href=\"https://www.kaggle.com/jbomitchell/token-350\" target=\"_blank\">notebook</a> got lucky, e pluribus unum.</p>\n<p><strong>hotdog</strong><br>\nWhile it seems from the discussion on the Kaggle &amp; Discord fora that many people found this easy, I'm afraid I struggled with it for too long. Everything non-canine was classified as a “window screen”, except for a window screen, which was classified as a “shower curtain”. I gave up. Weeks later, I came back to it, and found a <a href=\"https://www.kaggle.com/datasets/dansbecker/hot-dog-not-hot-dog\" target=\"_blank\">Hot Dog / Not Hot Dog dataset</a> on Kaggle. I threw Hot Dog training images at the model, and several of them tested positive for the flag, as shown in this <a href=\"https://www.kaggle.com/jbomitchell/sausage-sandwich-game\" target=\"_blank\">notebook</a>.</p>\n<p><strong>honorstudent</strong><br>\nSimilarly to hotdog, I spent far too long trying to do what the problem told me to do and use whiteout to morph the F into an A. What eventually worked was a <a href=\"https://www.kaggle.com/datasets/abx393/handwritten-characters\" target=\"_blank\">handwritten character recognition dataset</a> from Kaggle, with suitable decolourisation and resizing, as illustrated in this <a href=\"https://www.kaggle.com/jbomitchell/honor-est-a-henry\" target=\"_blank\">notebook</a>.</p>\n<p><strong>forensics</strong><br>\nI didn’t really see the point of having the model name hiding in such plain sight in the .h5 file that even the most cursory inspection of the problem would reveal the correct answer. We were told that there were no fake flags, so this is presumably the intended answer rather than a red herring.</p>\n<p><strong>bad2good</strong><br>\nI fondly imagined that this would be an optimisation problem akin to baseball. I turned out to be weirder and more frustrating. I learned that negative marks were acceptable, and that marks above 100% were not. However, setting Henry’s mark to 100% and everyone else’s to minus a million caused the score to stick at 18, and gave no flag. Empirically, integral values of the scoring function seemed to correspond to unproductive regions of the problem space. Eventually, I found a region where the score was non-integral and could be increased above 18 by the strange expedient of setting Henry’s number of absences to a negative value. Composing his 100% of a base mark of 1 and +99 in penalties for minus 33 absences [sic] was the rather improbable combination that brought me a flag. I think most people seeing this problem would naturally expect that the marks would be the most important variables, so this came across as very much a trick question. And took three days, on and off, to solve – see <a href=\"https://www.kaggle.com/jbomitchell/marx-class\" target=\"_blank\">notebook</a>.</p>\n<p>And to the other nine, WAF, WIFI, leakage, theft, salt, hotterdog, secret.sloth, crop1 and crop2. Well done, you were too good for me. </p>\n<p>I look forward, hopefully, to a similar competition next year.</p>",
      "rawMarkdown": "Thanks to the organisers for a challenging and addictive competition that has occupied (far too) much of my time over the last few weeks. It adds a kind of immersive augmented reality to life to be doing this competition, but I’m expecting that I will need a little break from serious competitive Kaggling for a while  to recover. Thanks to everyone who contributed to the Discord forum; at least two challenges I only solved as a result of the discussions (OK, hints) there.\n\nI found this competition as a Kaggler, definitely not a hacker, and someone who has picked up only a little python through competing on Kaggle. Some of the challenges seemed beyond my limited coding expertise (I was taught to write FORTRAN77 in capitals with the six spaces that once had allowed for the margin of the punch card) or my essentially non-existent cybersecurity knowledge. I did manage to complete half of them and here I describe them briefly, listing them with those that I personally and subjectively found most intellectually satisfying at the top.\n\nNoted that many of my solutions are indirect, using targeted or exhaustive searches of the possible solution space to obtain the flag rather than intellectually defeating the problem. At least five of my solutions could be described as “brute force”, though for math1-3 the degree of force required is very gentle.\n\n**murderbots**\nI had originally planned to try opening the cells one by one sending 49 zeros and a one, and hoping for a different message depending on whether a bot or a human was released. Unfortunately, all the failure messages were of the “Oh no murderbots” variety, indeed even if I sent 50 zeros. I left this challenge for a while, but came back to it upon seeing that someone had left a hint “Index” on the forum. I have no idea what this hint meant, but it sent me looking in detail at the training data, hoping that all the human-containing cells might have odd, even, or perhaps prime indices. I didn’t find anything that obvious, but what I did find was a strong association between humans in the cells and a high number of “movement events”. So, I tried the approach of identifying the 12 cells in the test data with the most movement events. I took the 55 different ways of choosing 10 out of 12 of these top-movement cells, and used the 55 corresponding bitstrings shown in this [notebook]( https://www.kaggle.com/jbomitchell/killer-droids) as my guesses. The first string, that is simply opening the ten cells with the most movement events, yielded the flag.\n\n**baseball**\nI wondered initially, since both Sarah and Henry were five-letter names, if the patterns might be ciphers for the names, perhaps with three successive pitches as a codon for each of the five letters. Or perhaps Sarah’s pattern was an S and Henry’s an H? However, it quickly turned out that the problem could be taken at face value, with each set of pitches matched against the characteristic patterns of the different pitchers to produce a confidence score.  So, my approach here was to treat this as an optimisation problem, which as a computational chemist I had a reasonable familiarity with. Initially I tried some arbitrary patterns and quickly found one which was a weak match for Henry. Simply trying arbitrary moves and accepting improvements did increase my confidence score, but only very slowly; so I went for a more systematic method.  I set up a grid of 100 points covering the (0-29,0-29) space as a square grid with one point every three units in each direction.  At each step, I take the best solution so far, and consider one particular pitch (I loop through the 15 of them as needed), let’s call it pitch p. I cycle through all 100 points (with an arbitrary small adjustments for overlaps with existing pitches) and find the new scores. The best of the 101 options (original plus 100 grid points) is taken as the new position of pitch p. If we haven't got the flag, we move onto pitch p+1 (modulo 15). Once I’d set up the systematic approach, as roughly illustrated in this [notebook]( https://www.kaggle.com/jbomitchell/bazball), the flag appeared on the second pitch I looked at.\n\n**math1-3**\nThe answer key is a string consisting of three integers run together, and so it seemed easier to use a search of the possible strings than to solve the problems mathematically. The key will almost certainly be an integer of three or more digits, and for the first three maths challenges a search of the possible three-digit integers indeed yielded the flag. The notebooks are these: [1]( https://www.kaggle.com/jbomitchell/maths-1-looper), [2]( https://www.kaggle.com/jbomitchell/maths-2-looper), and [3]( https://www.kaggle.com/jbomitchell/maths-3-looper) \n\n**math4**\nAs for math1-3, but for this [notebook]( https://www.kaggle.com/jbomitchell/maths-4-looper) I had to extend the search into five digits to find the flag. Noted that the possible answers to the mathematical problem have a many-to-one mapping onto the answer key (we could have one fewer cluster but with a double digit number of dimensions, for example), so I have the flag without knowing a unique answer to the underlying problem.\n\n**deepfake**\nSomeone dropped the hint “re-enactment” on Discord and suggested that this was 800 points for 5 minutes’ work. I recorded my own version of the video with a more canine-friendly script, and obtained the flag easily enough in this [notebook]( https://www.kaggle.com/jbomitchell/canis-felix). I did not attempt to edit the original .mp4 (I’ve had more than enough of editing lecture videos).\n\n**inference**\nThe character-recognition model seemed to be little use, other than that its structure suggested that the answer might be a six-letter word or six-character string. I still don’t know what the model was supposed to output [EDIT now understood after reading solution codes], but two very strong hints on Discord suggested that the correct string was both guessable and related to DEFCON30. Searching the conference website for suitable six letter strings was more productive than throwing more images at the model.\n\n**token**\nA nasty, brutish and long search over the two million or so unique pairs of integers from the range [1, 1973]. My code was poorly thought out, and I missed seeing the flag the first time around. I guess I learned to write better code, rationalising the amount of output produced and saving it to an easy-to-parse file. I still have no idea how a tokenizer works, nor why this game of Blankety Blank should confuse it. This [notebook]( https://www.kaggle.com/jbomitchell/token-350) got lucky, e pluribus unum.\n\n**hotdog**\nWhile it seems from the discussion on the Kaggle & Discord fora that many people found this easy, I'm afraid I struggled with it for too long. Everything non-canine was classified as a “window screen”, except for a window screen, which was classified as a “shower curtain”. I gave up. Weeks later, I came back to it, and found a [Hot Dog / Not Hot Dog dataset]( https://www.kaggle.com/datasets/dansbecker/hot-dog-not-hot-dog) on Kaggle. I threw Hot Dog training images at the model, and several of them tested positive for the flag, as shown in this [notebook]( https://www.kaggle.com/jbomitchell/sausage-sandwich-game).\n\n**honorstudent**\nSimilarly to hotdog, I spent far too long trying to do what the problem told me to do and use whiteout to morph the F into an A. What eventually worked was a [handwritten character recognition dataset]( https://www.kaggle.com/datasets/abx393/handwritten-characters) from Kaggle, with suitable decolourisation and resizing, as illustrated in this [notebook]( https://www.kaggle.com/jbomitchell/honor-est-a-henry).\n\n**forensics**\nI didn’t really see the point of having the model name hiding in such plain sight in the .h5 file that even the most cursory inspection of the problem would reveal the correct answer. We were told that there were no fake flags, so this is presumably the intended answer rather than a red herring.\n\n**bad2good**\nI fondly imagined that this would be an optimisation problem akin to baseball. I turned out to be weirder and more frustrating. I learned that negative marks were acceptable, and that marks above 100% were not. However, setting Henry’s mark to 100% and everyone else’s to minus a million caused the score to stick at 18, and gave no flag. Empirically, integral values of the scoring function seemed to correspond to unproductive regions of the problem space. Eventually, I found a region where the score was non-integral and could be increased above 18 by the strange expedient of setting Henry’s number of absences to a negative value. Composing his 100% of a base mark of 1 and +99 in penalties for minus 33 absences [sic] was the rather improbable combination that brought me a flag. I think most people seeing this problem would naturally expect that the marks would be the most important variables, so this came across as very much a trick question. And took three days, on and off, to solve – see [notebook]( https://www.kaggle.com/jbomitchell/marx-class).\n\nAnd to the other nine, WAF, WIFI, leakage, theft, salt, hotterdog, secret.sloth, crop1 and crop2. Well done, you were too good for me. \n\nI look forward, hopefully, to a similar competition next year.",
      "votes": null
    },
    {
      "id": "1936585",
      "postDate": "09/12/2022 21:28:14",
      "content": "<p>Thanks for sharing your write-up. </p>\n<p>Yours MurderBots are to-the-point, precise snippets (Almost Sniper's snippets).  I \"bought\" one of yours Murderbots snippets.<br>\nBesides, thanks also for sharing your Dataset and many significant Kaggle Notebooks.  Great job J. Mitchell !</p>",
      "rawMarkdown": "Thanks for sharing your write-up. \n\nYours MurderBots are to-the-point, precise snippets (Almost Sniper's snippets).  I \"bought\" one of yours Murderbots snippets.\nBesides, thanks also for sharing your Dataset and many significant Kaggle Notebooks.  Great job J. Mitchell !",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1936585,
      "author_name": "mpwolke",
      "author_url": "",
      "post_date": "09/12/2022 21:28:14",
      "content": "<p>Thanks for sharing your write-up. </p>\n<p>Yours MurderBots are to-the-point, precise snippets (Almost Sniper's snippets).  I \"bought\" one of yours Murderbots snippets.<br>\nBesides, thanks also for sharing your Dataset and many significant Kaggle Notebooks.  Great job J. Mitchell !</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1935633": "Thanks to the organisers for a challenging and addictive competition that has occupied (far too) much of my time over the last few weeks. It adds a kind of immersive augmented reality to life to be doing this competition, but I’m expecting that I will need a little break from serious competitive Kaggling for a while  to recover. Thanks to everyone who contributed to the Discord forum; at least two challenges I only solved as a result of the discussions (OK, hints) there.\n\nI found this competition as a Kaggler, definitely not a hacker, and someone who has picked up only a little python through competing on Kaggle. Some of the challenges seemed beyond my limited coding expertise (I was taught to write FORTRAN77 in capitals with the six spaces that once had allowed for the margin of the punch card) or my essentially non-existent cybersecurity knowledge. I did manage to complete half of them and here I describe them briefly, listing them with those that I personally and subjectively found most intellectually satisfying at the top.\n\nNoted that many of my solutions are indirect, using targeted or exhaustive searches of the possible solution space to obtain the flag rather than intellectually defeating the problem. At least five of my solutions could be described as “brute force”, though for math1-3 the degree of force required is very gentle.\n\n**murderbots**\nI had originally planned to try opening the cells one by one sending 49 zeros and a one, and hoping for a different message depending on whether a bot or a human was released. Unfortunately, all the failure messages were of the “Oh no murderbots” variety, indeed even if I sent 50 zeros. I left this challenge for a while, but came back to it upon seeing that someone had left a hint “Index” on the forum. I have no idea what this hint meant, but it sent me looking in detail at the training data, hoping that all the human-containing cells might have odd, even, or perhaps prime indices. I didn’t find anything that obvious, but what I did find was a strong association between humans in the cells and a high number of “movement events”. So, I tried the approach of identifying the 12 cells in the test data with the most movement events. I took the 55 different ways of choosing 10 out of 12 of these top-movement cells, and used the 55 corresponding bitstrings shown in this [notebook]( https://www.kaggle.com/jbomitchell/killer-droids) as my guesses. The first string, that is simply opening the ten cells with the most movement events, yielded the flag.\n\n**baseball**\nI wondered initially, since both Sarah and Henry were five-letter names, if the patterns might be ciphers for the names, perhaps with three successive pitches as a codon for each of the five letters. Or perhaps Sarah’s pattern was an S and Henry’s an H? However, it quickly turned out that the problem could be taken at face value, with each set of pitches matched against the characteristic patterns of the different pitchers to produce a confidence score.  So, my approach here was to treat this as an optimisation problem, which as a computational chemist I had a reasonable familiarity with. Initially I tried some arbitrary patterns and quickly found one which was a weak match for Henry. Simply trying arbitrary moves and accepting improvements did increase my confidence score, but only very slowly; so I went for a more systematic method.  I set up a grid of 100 points covering the (0-29,0-29) space as a square grid with one point every three units in each direction.  At each step, I take the best solution so far, and consider one particular pitch (I loop through the 15 of them as needed), let’s call it pitch p. I cycle through all 100 points (with an arbitrary small adjustments for overlaps with existing pitches) and find the new scores. The best of the 101 options (original plus 100 grid points) is taken as the new position of pitch p. If we haven't got the flag, we move onto pitch p+1 (modulo 15). Once I’d set up the systematic approach, as roughly illustrated in this [notebook]( https://www.kaggle.com/jbomitchell/bazball), the flag appeared on the second pitch I looked at.\n\n**math1-3**\nThe answer key is a string consisting of three integers run together, and so it seemed easier to use a search of the possible strings than to solve the problems mathematically. The key will almost certainly be an integer of three or more digits, and for the first three maths challenges a search of the possible three-digit integers indeed yielded the flag. The notebooks are these: [1]( https://www.kaggle.com/jbomitchell/maths-1-looper), [2]( https://www.kaggle.com/jbomitchell/maths-2-looper), and [3]( https://www.kaggle.com/jbomitchell/maths-3-looper) \n\n**math4**\nAs for math1-3, but for this [notebook]( https://www.kaggle.com/jbomitchell/maths-4-looper) I had to extend the search into five digits to find the flag. Noted that the possible answers to the mathematical problem have a many-to-one mapping onto the answer key (we could have one fewer cluster but with a double digit number of dimensions, for example), so I have the flag without knowing a unique answer to the underlying problem.\n\n**deepfake**\nSomeone dropped the hint “re-enactment” on Discord and suggested that this was 800 points for 5 minutes’ work. I recorded my own version of the video with a more canine-friendly script, and obtained the flag easily enough in this [notebook]( https://www.kaggle.com/jbomitchell/canis-felix). I did not attempt to edit the original .mp4 (I’ve had more than enough of editing lecture videos).\n\n**inference**\nThe character-recognition model seemed to be little use, other than that its structure suggested that the answer might be a six-letter word or six-character string. I still don’t know what the model was supposed to output [EDIT now understood after reading solution codes], but two very strong hints on Discord suggested that the correct string was both guessable and related to DEFCON30. Searching the conference website for suitable six letter strings was more productive than throwing more images at the model.\n\n**token**\nA nasty, brutish and long search over the two million or so unique pairs of integers from the range [1, 1973]. My code was poorly thought out, and I missed seeing the flag the first time around. I guess I learned to write better code, rationalising the amount of output produced and saving it to an easy-to-parse file. I still have no idea how a tokenizer works, nor why this game of Blankety Blank should confuse it. This [notebook]( https://www.kaggle.com/jbomitchell/token-350) got lucky, e pluribus unum.\n\n**hotdog**\nWhile it seems from the discussion on the Kaggle & Discord fora that many people found this easy, I'm afraid I struggled with it for too long. Everything non-canine was classified as a “window screen”, except for a window screen, which was classified as a “shower curtain”. I gave up. Weeks later, I came back to it, and found a [Hot Dog / Not Hot Dog dataset]( https://www.kaggle.com/datasets/dansbecker/hot-dog-not-hot-dog) on Kaggle. I threw Hot Dog training images at the model, and several of them tested positive for the flag, as shown in this [notebook]( https://www.kaggle.com/jbomitchell/sausage-sandwich-game).\n\n**honorstudent**\nSimilarly to hotdog, I spent far too long trying to do what the problem told me to do and use whiteout to morph the F into an A. What eventually worked was a [handwritten character recognition dataset]( https://www.kaggle.com/datasets/abx393/handwritten-characters) from Kaggle, with suitable decolourisation and resizing, as illustrated in this [notebook]( https://www.kaggle.com/jbomitchell/honor-est-a-henry).\n\n**forensics**\nI didn’t really see the point of having the model name hiding in such plain sight in the .h5 file that even the most cursory inspection of the problem would reveal the correct answer. We were told that there were no fake flags, so this is presumably the intended answer rather than a red herring.\n\n**bad2good**\nI fondly imagined that this would be an optimisation problem akin to baseball. I turned out to be weirder and more frustrating. I learned that negative marks were acceptable, and that marks above 100% were not. However, setting Henry’s mark to 100% and everyone else’s to minus a million caused the score to stick at 18, and gave no flag. Empirically, integral values of the scoring function seemed to correspond to unproductive regions of the problem space. Eventually, I found a region where the score was non-integral and could be increased above 18 by the strange expedient of setting Henry’s number of absences to a negative value. Composing his 100% of a base mark of 1 and +99 in penalties for minus 33 absences [sic] was the rather improbable combination that brought me a flag. I think most people seeing this problem would naturally expect that the marks would be the most important variables, so this came across as very much a trick question. And took three days, on and off, to solve – see [notebook]( https://www.kaggle.com/jbomitchell/marx-class).\n\nAnd to the other nine, WAF, WIFI, leakage, theft, salt, hotterdog, secret.sloth, crop1 and crop2. Well done, you were too good for me. \n\nI look forward, hopefully, to a similar competition next year.",
    "1936585": "Thanks for sharing your write-up. \n\nYours MurderBots are to-the-point, precise snippets (Almost Sniper's snippets).  I \"bought\" one of yours Murderbots snippets.\nBesides, thanks also for sharing your Dataset and many significant Kaggle Notebooks.  Great job J. Mitchell !"
  },
  "source": "meta"
}